Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Equivalent of GWT-EXT Property Grid to SmartGWT (Listgrid?)

    Decided to start a new topic so I don't take over other thread as this is a very specific issue.

    I there a way to implement the property grid in http://www.gwt-ext.com/demo/#propertyGrid using ListGrid or any other similar component in SmartGWT?

    The problem that i'm facing right now using a ListGrid is that I can't set the field type by row, only bu column.

    How could I show a different editor for every row in the grid instead of every column in the grid (more like it's done in GWT-EXT sample).

    Any methods on the ListGrid that I could implement/overwrite to achieve a property grid?

    Thank you very much for your attention.


    P.S: (idea) should this be a widget in extensions project?

    #2
    In gwt-ext it is modeled as a grid with special configuration / editors but in SmartGWT all you need to do is create a DynamicForm and style it to appear like a grid / table as mentioned in the post above. The editor types are based on the FieldItem type (its a standard DynamicForm) and use all the layout features of DynamicForm allowing you complete control of layout / behavior.
    If you think about it, a property editor maps better to a form, than a grid.

    Have a look at the Properties Tab in the Visual Builder, you'll see that with the appropriate styling, you can get the desired result.

    Having said that, we plan on implementing a ListGrid.getEditorType(..) override method that will allow you to customize the editor used for a given row / column however using a DynamicForm with the appropriate styling is more appropriate for this usecase.

    Comment


      #3
      Thank you for the reply, after some investigation I extended the ListGrid and created a PropertyGrid that has exactly 2 columns (one for names, other for values)

      How it works:
      After you create the Property grid you make a map with a String that says what type of data you want ("text", "date", "myType", etc.) and an instance of the editor to use (a FormItem)

      Maybe an example would be better, so:


      The PropertyGrid.java class:
      Code:
      import java.util.Map;
      
      import com.smartgwt.client.data.Record;
      import com.smartgwt.client.widgets.form.fields.FormItem;
      import com.smartgwt.client.widgets.grid.ListGrid;
      import com.smartgwt.client.widgets.grid.ListGridField;
      import com.smartgwt.client.widgets.grid.events.EditorEnterEvent;
      import com.smartgwt.client.widgets.grid.events.EditorEnterHandler;
      import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
      import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
      
      /**
       * A PropertyGrid based on a {@link ListGrid} that automatically creates two
       * fields (one for name column and other for values column) and can display a
       * custom editor for every row
       * 
       * @author Dan Mihai Ile
       * 
       */
      public class PropertyGrid extends ListGrid {
      
      	/**
      	 * Map to hold the editors
      	 */
      	private Map<String, FormItem> editorsMap;
      
      	/**
      	 * Hold the name of the attribute on a {@link Record} which contains the
      	 * editorsMap key
      	 */
      	private String valueFieldAttribute;
      
      	/**
      	 * Create a new {@link PropertyGrid} with two column fields (first for
      	 * names, second for values)
      	 */
      	public PropertyGrid() {
      		
      		// create the 2 fields, one for names, other for values 
      		ListGridField nameField = new ListGridField();
      		nameField.setCanEdit(false);
      		ListGridField valueField = new ListGridField();
      		valueField.setCanEdit(true);
      		
      		setFields(nameField, valueField);
      		
      		// listeners to intercept when the user starts to edit data
      		addEditorEnterHandler(new EditorEnterHandler() {
      			public void onEditorEnter(EditorEnterEvent event) {
      				Record record = event.getRecord();
      				enableSpecificEditor(record);
      			}
      		});
      		addRecordClickHandler(new RecordClickHandler() {
      			public void onRecordClick(RecordClickEvent event) {
      				Record record = event.getRecord();
      				enableSpecificEditor(record);
      			}
      		});
      
      	}
      	
      	/**
      	 * The name column field
      	 * @return
      	 */
      	public ListGridField getNameField() {
      		return getField(0);
      	}
      
      	/**
      	 * The values column field
      	 * @return
      	 */
      	public ListGridField getValuesField() {
      		return getField(1);
      	}
      
      	/**
      	 * Set the name of the attribute from where the row will get the editor name
      	 * to be used on the {@link Map} from where the rows will get it's editors
      	 * <p>
      	 * When an edit starts the {@link PropertyGrid} will retrieve the key of the
      	 * editor form the row's attributes and use that key on the map to get the
      	 * editor to be used
      	 * 
      	 * @param attribute
      	 *            the name of the attribute on the rows that contains the key of
      	 *            the editor
      	 * @param map
      	 *            a map that contains the key of the editor and the editor
      	 */
      	public void setEditorsMap(String attribute, Map<String, FormItem> map) {
      		this.valueFieldAttribute = attribute;
      		this.editorsMap = map;
      	}
      
      	/**
      	 * Enable the specific editor for the given record
      	 * 
      	 * @param record
      	 *            the record
      	 */
      	private void enableSpecificEditor(Record record) {
      		if (editorsMap != null) {
      			String attribute = record.getAttribute(valueFieldAttribute);
      			if (editorsMap.containsKey(attribute)) {
      				FormItem formItem = editorsMap.get(attribute);
      				getField(1).setEditorType(formItem);
      			}
      		}
      	}
      
      }
      And a simple example:
      Code:
      	public void onModuleLoad() {
      		
      		// create the property grid
      		PropertyGrid propertyGrid = new PropertyGrid();
      		propertyGrid.getNameField().setName("Name");
      		propertyGrid.getValuesField().setName("Value");
      		
      		// create the editors
      		HashMap<String, FormItem> editorsMap = new HashMap<String, FormItem>();
      		SelectItem mapValuesEditor = new SelectItem();
      		mapValuesEditor.setValueMap("one", "two", "three");
      		editorsMap.put("myType", mapValuesEditor);
      		TextItem textEditor = new TextItem();
      		editorsMap.put("simpleText", textEditor);
      		DateItem dateEditor = new DateItem();
      		editorsMap.put("date", dateEditor);
      		ColorPickerItem colorEditor = new ColorPickerItem();
      		editorsMap.put("color", colorEditor);
      		
      		// set the editors and attribute name where to find the record type
      		propertyGrid.setEditorsMap("fieldType", editorsMap);
      		
      		// add some data
      		ListGridRecord[] listGridRecord = new ListGridRecord[4];
      		listGridRecord[0] = new ListGridRecord();
      		listGridRecord[0].setAttribute("Name", "Property1");
      		listGridRecord[0].setAttribute("Value", "Default Value");
      		listGridRecord[0].setAttribute("fieldType", "simpleText");
      		listGridRecord[1] = new ListGridRecord();
      		listGridRecord[1].setAttribute("Name", "Property2");
      		listGridRecord[1].setAttribute("fieldType", "myType");
      		listGridRecord[2] = new ListGridRecord();
      		listGridRecord[2].setAttribute("Name", "Property3");
      		listGridRecord[2].setAttribute("fieldType", "date");
      		listGridRecord[3] = new ListGridRecord();
      		listGridRecord[3].setAttribute("Name", "Property4");
      		listGridRecord[3].setAttribute("fieldType", "color");
      		
      		propertyGrid.setData(listGridRecord);
      		
      		propertyGrid.draw();
      		
      	}
      What do you think of the idea? is it worth to add this as a Showcase example or maybe in the smartgwt-extensions? (Maybe a showcase example would be better)

      Comment


        #4
        Mihai,
        The end result looks really good. The only issue is that I cant take a single Record and bind it to this widget like I would if I were using a DynamicForm but this might not be the only usecase and your solution looks good.


        The following settings in the PropertyGrid might also help :

        Code:
                setShowAllRecords(true);
                setBodyOverflow(Overflow.VISIBLE);
                setOverflow(Overflow.VISIBLE);
                setLeaveScrollbarGap(false);
                setEditEvent(ListGridEditEvent.CLICK);
                setShowHeaderContextMenu(false);
        
        ...
                valueField.setCanSort(false);
        The other nice addition would be for the right editor to be picked based on the type of the Record value, rather than always requiring a registered "fieldType". For example if type is Boolean, default to a certain editor etc.
        Users can still specify their own custom editorType if desired.

        Sanjiv
        Attached Files
        Last edited by sjivan; 3 Jun 2009, 05:05. Reason: attached screenshots

        Comment


          #5
          humm the problem is how could I find the type of the value?
          getAttributeAsObject is no good because the value could be boolean instead of Boolean for example...

          Anyway this is a improved version (better listener used to set up the right editor, works for example when using TAB to navigate through records)
          Code:
          import java.util.Map;
          
          import com.smartgwt.client.data.Record;
          import com.smartgwt.client.types.ListGridEditEvent;
          import com.smartgwt.client.types.Overflow;
          import com.smartgwt.client.types.SelectionStyle;
          import com.smartgwt.client.widgets.form.fields.FormItem;
          import com.smartgwt.client.widgets.grid.ListGrid;
          import com.smartgwt.client.widgets.grid.ListGridField;
          import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
          import com.smartgwt.client.widgets.grid.events.SelectionEvent;
          
          /**
           * A PropertyGrid based on a {@link ListGrid} that automatically creates two
           * fields (one for name column and other for values column) and can display a
           * custom editor for every row
           * 
           * @author Dan Mihai Ile
           * 
           */
          public class PropertyGrid extends ListGrid {
          
          	/**
          	 * Map to hold the editors
          	 */
          	private Map<String, FormItem> editorsMap;
          
          	/**
          	 * Hold the name of the attribute on a {@link Record} which contains the
          	 * editorsMap key
          	 */
          	private String valueFieldAttribute;
          
          	/**
          	 * addSelectionChangedHandler fires several times for the same record and we
          	 * don't want to set the editor repeatedly for the same record, this tracks
          	 * the last record that has the editor set up
          	 */
          	protected Record lastEditorChangedRecord;
          
          	/**
          	 * Create a new {@link PropertyGrid} with two column fields (first for
          	 * names, second for values)
          	 */
          	public PropertyGrid() {
          
          		// some property grid default values
          		setShowAllRecords(true);
          		setBodyOverflow(Overflow.VISIBLE);
          		setOverflow(Overflow.VISIBLE);
          		setLeaveScrollbarGap(false);
          		setSelectionType(SelectionStyle.SINGLE);
          		setEditEvent(ListGridEditEvent.CLICK);
          		setShowHeaderContextMenu(false);
          
          		// create the 2 fields, one for names, other for values
          		ListGridField nameField = new ListGridField();
          		nameField.setCanEdit(false);
          		ListGridField valueField = new ListGridField();
          		valueField.setCanEdit(true);
          
          		setFields(nameField, valueField);
          
          		// listener to set the right editor
          		addSelectionChangedHandler(new SelectionChangedHandler() {
          			public void onSelectionChanged(SelectionEvent event) {
          				Record record = event.getRecord();
          				if (event.getState() && !record.equals(lastEditorChangedRecord)) {
          					lastEditorChangedRecord = record;
          					enableSpecificEditor(record);
          				}
          			}
          		});
          
          	}
          
          	/**
          	 * The name column field
          	 * 
          	 * @return
          	 */
          	public ListGridField getNameField() {
          		return getField(0);
          	}
          
          	/**
          	 * The values column field
          	 * 
          	 * @return
          	 */
          	public ListGridField getValuesField() {
          		return getField(1);
          	}
          
          	/**
          	 * Set the name of the attribute from where the row will get the editor name
          	 * to be used on the {@link Map} from where the rows will get it's editors
          	 * <p>
          	 * When an edit starts the {@link PropertyGrid} will retrieve the key of the
          	 * editor form the row's attributes and use that key on the map to get the
          	 * editor to be used
          	 * 
          	 * @param attribute
          	 *            the name of the attribute on the rows that contains the key of
          	 *            the editor
          	 * @param map
          	 *            a map that contains the key of the editor and the editor
          	 */
          	public void setEditorsMap(String attribute, Map<String, FormItem> map) {
          		this.valueFieldAttribute = attribute;
          		this.editorsMap = map;
          	}
          
          	/**
          	 * Enable the specific editor for the given record
          	 * 
          	 * @param record
          	 *            the record
          	 */
          	private void enableSpecificEditor(Record record) {
          		String fieldType = null;
          		String attribute = record.getAttribute(valueFieldAttribute);
          		if (attribute != null) {
          			// direct hit, user has set the attribute for the field type
          			fieldType = attribute;
          		} else {
          			// user didn't setup the attribute for the field type, try to use a
          			// default editor by discovering the value type
          		}
          
          		if (fieldType != null) {
          			FormItem formItem = editorsMap.get(fieldType);
          			getField(1).setEditorType(formItem);
          		}
          	}
          
          }
          Last edited by mihai007; 4 Jun 2009, 01:09.

          Comment


            #6
            Awesome

            Landed on a awesome post. Really got what i searched. Thanks.

            Comment

            Working...
            X