Tuesday, July 20, 2010

Customizing Which Form Fields Are Displayed: Part 6

Following on from parts 1, 2, 3, 4 and 5, I thought I'd blog some of the other field ordering preferences I've encountered.

This one is for those who want field ordering at the global (ie. application) level, but to exclude fields on a per-screen basis. Example implementation below. Some points to note:
  • It's in Swing so you can just cut and paste and run it

  • It defines an ExcludingInspectionResultProcessor that excludes the properties/actions

  • It uses this in a chain with the usual ComesAfterInspectonResultProcessor. Note that unlike Part 2 it adds to the chain after ComesAfterInspectonResultProcessor. This is so that excluding fields does not impact the UiComesAfter ordering. You may prefer this the other way around
package com.myapp;

import static org.metawidget.inspector.InspectionResultConstants.*;

import javax.swing.*;

import org.metawidget.inspectionresultprocessor.iface.*;
import org.metawidget.inspectionresultprocessor.sort.*;
import org.metawidget.inspector.annotation.*;
import org.metawidget.swing.*;
import org.metawidget.util.*;
import org.w3c.dom.*;

public class Main {

   public static void main( String[] args ) {

      Person person = new Person();

      SwingMetawidget metawidget = new SwingMetawidget();
      metawidget.addInspectionResultProcessor( new ComesAfterInspectionResultProcessor<SwingMetawidget>() );
      metawidget.addInspectionResultProcessor( new ExcludingInspectionResultProcessor() );
      metawidget.putClientProperty( "exclude", new String[] { "retired", "age" } );
      metawidget.setToInspect( person );

      JFrame frame = new JFrame( "Metawidget Tutorial" );
      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.getContentPane().add( metawidget );
      frame.setSize( 400, 250 );
      frame.setVisible( true );
   }

   static class Person {

      public String   name;

      @UiComesAfter( "name" )
      public int      age;

      @UiComesAfter( "age" )
      public boolean   retired;

      @UiComesAfter( "retired" )
      @UiLarge
      public String   notes;
   }

   static class ExcludingInspectionResultProcessor
      implements InspectionResultProcessor<SwingMetawidget> {

      public String processInspectionResult( String inspectionResult, SwingMetawidget metawidget, Object toInspect, String type, String... names ) {

         String[] excludes = (String[]) metawidget.getClientProperty( "exclude" );
         Document document = XmlUtils.documentFromString( inspectionResult );
         Element entity = (Element) document.getDocumentElement().getFirstChild();

         for ( int loop = 0; loop < entity.getChildNodes().getLength(); ) {

            Element trait = (Element) entity.getChildNodes().item( loop );

            if ( !ArrayUtils.contains( excludes, trait.getAttribute( NAME )))
            {
               loop++;
               continue;
            }

            entity.removeChild( trait );
         }

         return XmlUtils.documentToString( document, false );
      }
   }

}

2 comments:

liuk said...

Hi Richard,
I've read all six arguments "Customizing Which Form Fields Are Displayed" and I haven't seen any proposal to have an "natural" order for fields as are written in class file.
Perhaps it's already possible to do this setting something on InspectionResultProcessorConfig?
Thank You
Luca

Richard said...

Luca,

There are 9 parts (not 6) to 'Customizing Which Form Fields Are Displayed', and I think number 7 is the one you want:

http://kennardconsulting.blogspot.com/2010/08/customizing-which-form-fields-are_04.html

So you were nearly there!

Richard.