Announcement

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

    CanvasItem in form and grid disappears

    Hi, I'm trying out the CanvasItem APIs:

    In code:
    1 DataSource created which is attached to a ValuesManager which holds a form and a grid.

    Issues:
    * When entering edit mode in the grid, the CanvasItem in the form suddenly disappears. I think I don't reuse the same instance, isn't that right?

    * Showcase sample says to do ((CanvasItem) item).setCanvas(innerPane), but item appears to be a TextItem instead of a CanvasItem.
    I tried to do the same myself (setCanvasWorkaround), but this gives a warning.


    Standalone test case:
    Code:
    public class CanvsTst implements EntryPoint {
    
    	public void onModuleLoad() {
    		RootPanel.get().add(getViewPanel());
    	}
    
    	private static final String FIELD1 = "field1";
    	private static final String FIELD2 = "field2";
    
    	public Canvas getViewPanel() {
    		MyRecord record1 = new MyRecord(1);
    		MyRecord record2 = new MyRecord(2);
    		MyRecord record3 = new MyRecord(3);
    
    		VLayout container = new VLayout();
    		container.setWidth("50%");
    		container.setHeight("50%");
    
    		DataSourceField field1 = new DataSourceField();
    		field1.setTitle(FIELD1);
    		field1.setName(FIELD1);
    		field1.setEditorType(new TextItem(FIELD1));
    
    		DataSourceField field2 = new DataSourceField();
    		field2.setName(FIELD2);
    		field2.setTitle(FIELD2);
    		field2.setEditorType(new ListGridItem(FIELD2));
    
    		DataSource dataSource = new DataSource();
    		dataSource.setClientOnly(true);
    		dataSource.setFields(field1, field2);
    
    		DynamicForm form = new DynamicForm();
    		form.setWidth(450);
    		form.setHeight(100);
    		form.setDataPath("/form");
    
    		ValuesManager vm = new ValuesManager();
    		vm.setDataSource(dataSource);
    		vm.setDisableValidation(true);
    		vm.addMember(form);
    		vm.setValue("/form", record1);
    		vm.setValue("/grid", new Record[] { record1, record2, record3 });
    
    		ListGrid grid = new ListGrid();
    		grid.setWidth100();
    		grid.setHeight(200);
    		grid.setCanEdit(true);
    		grid.setValuesManager(vm);
    		grid.setDataPath("/grid");
    
    		container.addMember(form);
    		container.addMember(grid);
    
    		return container;
    
    	}
    
    	public class ListGridItem extends CanvasItem {
    
    		ListGridItem(String name) {
    			super(name);
    			setShouldSaveValue(true);
    			setHeight("22px");
    
    			addShowValueHandler(new ShowValueHandler() {
    
    				public void onShowValue(ShowValueEvent event) {
    					Object value = event.getDataValue();
    					if (value != null) {
    						CanvasItem item = (CanvasItem) event.getSource();
    						HTMLPane innerPane = (HTMLPane) item.getCanvas();
    						innerPane.setContents("==> " + value);
    					}
    				}
    			});
    
    			setInitHandler(new FormItemInitHandler() {
    
    				public void onInit(FormItem item) {
    					HTMLPane innerPane = new HTMLPane();
    					innerPane.setContents("HTMLPane from onInit");
    
    					// 1.___
    					// ((CanvasItem) item).setCanvas(innerPane);
    					/*
    					 * Results in: java.lang.ClassCastException
    					 * com.smartgwt.client.widgets.form.fields.TextItem
    					 */
    
    					// 2.___
    					// CanvsTst.setCanvasWorkaround(item, innerPane);
    					/*
    					 * Workaround: set canvas attribute anyways Result in: [ERROR]
    					 * WARN:CanvasItem:isc_CanvasItem_1:Observer: [CanvasItem ID:isc_CanvasItem_1
    					 * name:field2] is already observing method '$lf' on object '[HTMLPane
    					 * ID:isc_HTMLPane_0]', ignoring
    					 * 
    					 * + value is not shown in the form and is only shown on the second edit of a
    					 * grid row
    					 */
    				}
    			});
    
    			HTMLPane innerPane = new HTMLPane();
    			innerPane.setBackgroundColor("green");
    			innerPane.setContents("HTMLPane from constructor");
    
    			setCanvas(innerPane);
    			/*
    			 * In no setCanvas is performed in the constructor: [ERROR]
    			 * WARN:CanvasItem:isc_CanvasItem_0:CanvasItem: field2 defined with no canvas property -
    			 * creating a default canvas for this item.
    			 */
    		}
    
    	};
    
    	public class MyRecord extends Record {
    
    		public MyRecord(int number) {
    			super();
    			setAttribute(FIELD1, FIELD1 + "_value_" + number);
    			setAttribute(FIELD2, FIELD2 + "_value_" + number);
    		}
    
    	}
    
    	public static void setCanvasWorkaround(FormItem item, Canvas canvas) {
    		item.setAttribute("canvas", canvas == null ? null : canvas.getOrCreateJsObj());
    	}
    
    }

    thanks,

    SmartGWT EE 26-07-2011

    #2
    Getting a generic type (TextItem instead of CanvasItem) is one of the consequences of using the DataSource-level setEditorType() API, similar to the other consequences of not being able to use instance variables normally because you're really generating a series of FormItems, not just one. You can "typecast" to ListGridItem via:

    Code:
    new ListGridItem(formItem.getJsObj());
    Last edited by Isomorphic; 29 Jul 2011, 07:24.

    Comment


      #3
      Thanks for that hint, JS is a puzzle somtimes :)


      This standalone case is based on the original sample:
      http://code.google.com/p/smartgwt/so...le.java?r=1672

      Difference is indeed that setEditorType and using a DataSource, but in this code:
      Code:
      setInitHandler: {
      	HTMLPane innerPane = new HTMLPane();
      	innerPane.setContents("HTMLPane from onInit");
      
      	CanvasItem canvasItem = new CanvasItem(item.getJsObj());
      	canvasItem.setCanvas(innerPane);
      }
      
      addShowValueHandler: {
      	CanvasItem item = (CanvasItem) event.getSource();
      	HTMLPane innerPane = (HTMLPane) item.getCanvas();
      	if (innerPane == null) return;
      	// innerPane is always null. The following code is never executed:
      	innerPane.setContents("==> " + value);
      }
      The innerPane is always null.
      When going into edit mode in the grid, I don't see the custom CanvasItem new content (which should be the "==> value")
      but always the text from during init: "HTMLPane from onInit"

      Comment


        #4
        This isn't real code, and shows access to a variable "item" that you don't show how you got. Get the item from the event, and it works.

        Comment


          #5
          It's pretty much the same code as in previous post, thought I'd shorten it. The item comes from the ShowValueEvent:

          I wanted to make clear that I see the value set in the initHandler, but I can't seem to do something with the ShowValueEvent.getSource().getCanvas() - it's always null.

          Code:
          addShowValueHandler(new ShowValueHandler() {
          
          public void onShowValue(ShowValueEvent event) {
          
          CanvasItem item = (CanvasItem) event.getSource();
          HTMLPane innerPane = (HTMLPane) item.getCanvas();
          
          //innerPane is always null

          Comment


            #6
            The problematic "item" reference is in the pseudo-code for your initHandler.

            Please just show a complete sample to prevent any further ambiguity.

            Comment


              #7
              'item' was about the problem you hinted to solve before: typecast it ourselves.

              Complete runnable code that shows the problem:

              Code:
              public Canvas getViewPanel() {
              	MyRecord record1 = new MyRecord(1);
              	MyRecord record2 = new MyRecord(2);
              	MyRecord record3 = new MyRecord(3);
              
              	VLayout container = new VLayout();
              	container.setWidth("50%");
              	container.setHeight("50%");
              
              	DataSourceField field1 = new DataSourceField();
              	field1.setTitle(FIELD1);
              	field1.setName(FIELD1);
              	field1.setEditorType(new TextItem(FIELD1));
              
              	DataSourceField field2 = new DataSourceField();
              	field2.setName(FIELD2);
              	field2.setTitle(FIELD2);
              	field2.setEditorType(new ListGridItem(FIELD2));
              
              	DataSource dataSource = new DataSource();
              	dataSource.setClientOnly(true);
              	dataSource.setFields(field1, field2);
              
              	DynamicForm form = new DynamicForm();
              	form.setWidth(450);
              	form.setHeight(100);
              	form.setDataPath("/form");
              
              	ValuesManager vm = new ValuesManager();
              	vm.setDataSource(dataSource);
              	vm.setDisableValidation(true);
              	vm.addMember(form);
              	vm.setValue("/form", record1);
              	vm.setValue("/grid", new Record[] { record1, record2, record3 });
              
              	ListGrid grid = new ListGrid();
              	grid.setWidth100();
              	grid.setHeight(200);
              	grid.setCanEdit(true);
              	grid.setValuesManager(vm);
              	grid.setDataPath("/grid");
              
              	container.addMember(form);
              	container.addMember(grid);
              
              	return container;
              
              }
              
              public class ListGridItem extends CanvasItem {
              
              	ListGridItem(String name) {
              		super(name);
              		setShouldSaveValue(true);
              		setHeight("22px");
              
              		addShowValueHandler(new ShowValueHandler() {
              
              			public void onShowValue(ShowValueEvent event) {
              				Object value = event.getDataValue();
              				if (value != null) {
              					CanvasItem item = (CanvasItem) event.getSource();
              					HTMLPane innerPane = (HTMLPane) item.getCanvas();
              					if (innerPane == null) return;
              					// innerPane is always null. The following code is never executed:
              					innerPane.setContents("==> " + value);
              				}
              			}
              		});
              
              		setInitHandler(new FormItemInitHandler() {
              
              			public void onInit(FormItem item) {
              				HTMLPane innerPane = new HTMLPane();
              				innerPane.setContents("HTMLPane from onInit");
              
              				CanvasItem canvasItem = new CanvasItem(item.getJsObj());
              				canvasItem.setCanvas(innerPane);
              			}
              		});
              	}
              
              };
              
              public class MyRecord extends Record {
              
              	public MyRecord(int number) {
              		super();
              		setAttribute(FIELD1, FIELD1 + "_value_" + number);
              		setAttribute(FIELD2, FIELD2 + "_value_" + number);
              	}
              
              }
              
              public static void setCanvasWorkaround(FormItem item, Canvas canvas) {
              	item.setAttribute("canvas", canvas == null ? null : canvas.getOrCreateJsObj());
              }

              Comment


                #8
                Thanks for the clear test case. We've investigated this and realized that event.getSource() refers to the template item rather than the live item, which leads to this behavior.

                The right way to fix this is with a framework change to ensure that a "getItem()" API is available on the event object, and returns the live item (this is already the case for most FormItem events but was not available in this case).
                We've made this change internally and will be posting a new nightly build under http://www.smartclient.com/builds/SmartGWT/2.x

                Note that this build will differ from the official 2.5 release only in that it contains a few bug fixes caught after the release went live, including this one. The build will be dated Aug 5th but will not be posted for several hours - we'd recommend checking tomorrow morning.

                Comment


                  #9
                  Thanks for fixing.
                  No problem for v2.5 for me, I'm already using the v3 nightlies anyway (which I assume will also have this fix ;).

                  Comment

                  Working...
                  X