Results 1 to 2 of 2

Thread: [FNR] Null Pointer Exception from QuickTips

    You found a bug! We've classified it as a bug in our system. We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Ext User
    Join Date
    Sep 2009
    Location
    Firestone, CO
    Posts
    1

    Default [FNR] Null Pointer Exception from QuickTips

    There appears to be a related issue here: http://www.extjs.com/forum/showthread.php?t=71390 however I am not sure if the bug Sven reported fixed is in the Combobox or in BoxComponent/Layer.

    When using the QuickTips object with TreeGrid, any renderer's use of the qwidth attribute causes the following error to be thrown:
    Code:
    [java] 13:15:46,069 ERROR [uncaught] Uncaught exception: : java.lang.NullPointerException
    [java]     com.extjs.gxt.ui.client.widget.Layer.getShim(Layer.java:216)
    [java]     com.extjs.gxt.ui.client.widget.Layer.sync(Layer.java:446)
    [java]     com.extjs.gxt.ui.client.widget.Layer.setWidth(Layer.java:376)
    [java]     com.extjs.gxt.ui.client.widget.BoxComponent.setSize(BoxComponent.java:469)
    [java]     com.extjs.gxt.ui.client.widget.BoxComponent.setWidth(BoxComponent.java:581)
    [java]     com.extjs.gxt.ui.client.widget.tips.QuickTip.updateTargetElement(QuickTip.java:180)
    [java]     com.extjs.gxt.ui.client.widget.tips.QuickTip.onTargetOver(QuickTip.java:136)
    [java]     com.extjs.gxt.ui.client.widget.tips.QuickTip$1.handleEvent(QuickTip.java:68)
    [java]     com.extjs.gxt.ui.client.widget.tips.QuickTip$1.handleEvent(QuickTip.java:1)
    [java]     com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:176)
    [java]     com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:96)
    [java]     com.extjs.gxt.ui.client.widget.Component.fireEvent(Component.java:444)
    [java]     com.extjs.gxt.ui.client.widget.Component.onBrowserEvent(Component.java:762)
    [java]     com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1320)
    [java]     com.google.gwt.user.client.DOM.dispatchEventAndCatch(DOM.java:1299)
    [java]     com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1262)
    [java]     sun.reflect.GeneratedMethodAccessor19.invoke(Unknown Source)
    [java]     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    [java]     java.lang.reflect.Method.invoke(Method.java:597)
    [java]     com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    [java]     com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:126)
    [java]     com.google.gwt.dev.shell.ie.IDispatchProxy.invoke(IDispatchProxy.java:155)
    [java]     com.google.gwt.dev.shell.ie.IDispatchImpl.Invoke(IDispatchImpl.java:294)
    [java]     com.google.gwt.dev.shell.ie.IDispatchImpl.method6(IDispatchImpl.java:194)
    [java]     org.eclipse.swt.internal.ole.win32.COMObject.callback6(COMObject.java:117)
    [java]     org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
    [java]     org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1925)
    [java]     org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
    [java]     com.google.gwt.dev.SwtHostedModeBase.processEvents(SwtHostedModeBase.java:235)
    [java]     com.google.gwt.dev.HostedModeBase.pumpEventLoop(HostedModeBase.java:558)
    [java]     com.google.gwt.dev.HostedModeBase.run(HostedModeBase.java:405)
    [java]     com.google.gwt.dev.HostedMode.main(HostedMode.java:232)
    This appears in both hosted mode and web (output is from hosted mode) using GXT 2.0.1. Main platform is Windows (any browser).

    The following code reproduces this error:
    Code:
    package net.crystalfortress.gwt.gxt.test.client;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.extjs.gxt.ui.client.data.BaseTreeLoader;
    import com.extjs.gxt.ui.client.data.BeanModel;
    import com.extjs.gxt.ui.client.data.ChangeEvent;
    import com.extjs.gxt.ui.client.data.ChangeEventSource;
    import com.extjs.gxt.ui.client.data.DataProxy;
    import com.extjs.gxt.ui.client.data.DataReader;
    import com.extjs.gxt.ui.client.data.ModelData;
    import com.extjs.gxt.ui.client.data.TreeModel;
    import com.extjs.gxt.ui.client.store.ListStore;
    import com.extjs.gxt.ui.client.store.Store;
    import com.extjs.gxt.ui.client.store.StoreSorter;
    import com.extjs.gxt.ui.client.store.TreeStore;
    import com.extjs.gxt.ui.client.widget.ContentPanel;
    import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
    import com.extjs.gxt.ui.client.widget.grid.ColumnData;
    import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
    import com.extjs.gxt.ui.client.widget.grid.Grid;
    import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
    import com.extjs.gxt.ui.client.widget.tips.QuickTip;
    import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
    import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.user.client.rpc.AsyncCallback;
    import com.google.gwt.user.client.ui.RootPanel;
    
    /*
     * * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class Test implements EntryPoint
    {
        private BlindProxy<BeanTreeModel> proxy;
        private BaseTreeLoader<BeanTreeModel> loader;
        private TreeStore<BeanTreeModel> store;
        
        /**
         * This is the entry point method.
         */
        public void onModuleLoad()
        {
            BeanTreeModel root = new BeanTreeModel();
            TestModel group1 = new TestModel("Group 1", "F", "FLDR");
            group1.add(new TestModel("Group 1 Template A", "I", "TEMP"));
            group1.add(new TestModel("Group 1 Template B", "N", "TEMP"));
            TestModel group2 = new TestModel("Group 2", "F", "FLDR");
            group2.add(new TestModel("Group 2 Template A", "I", "TEMP"));
            group2.add(new TestModel("Group 2 Template B", "N", "TEMP"));
            group2.add(new TestModel("Group 2 Template C", "I", "OTHR"));
            root.add(group1);
            root.add(group2);
            
            proxy = new BlindProxy<BeanTreeModel>(root);
            
            List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
            
            ColumnConfig column = new ColumnConfig("abbrv", "Abbrv", 120);
            column.setSortable(true);
            column.setRenderer(new TooltipRenderer());
            columns.add(column);
            
            column = new ColumnConfig("icon", "Icon", 50);
            column.setSortable(true);
            column.setRenderer(new TooltipRenderer());
            columns.add(column);
            
            column = new ColumnConfig("name", "Name", 300);
            column.setSortable(true);
            column.setRenderer(new TooltipRenderer());
            columns.add(column);
            
            ColumnModel cm = new ColumnModel(columns);
            
            
            
            loader = new BaseTreeLoader<BeanTreeModel>(proxy);
            
            store = new TreeStore<BeanTreeModel>(loader);
            store.setStoreSorter(new StoreSorter<BeanTreeModel>()
            {
                @Override
                public int compare(Store<BeanTreeModel> store, BeanTreeModel m1,
                        BeanTreeModel m2, String property)
                {
                    boolean m1Folder = m1 instanceof BeanTreeModel;  
                    boolean m2Folder = m2 instanceof BeanTreeModel;  
               
                    if (m1Folder && !m2Folder) {  
                       return -1;  
                     } else if (!m1Folder && m2Folder) {  
                       return 1;  
                     }  
              
                     return super.compare(store, m1, m2, property);
                }  
              
            });
            
            loader.load(null);
            
            TreeGrid<BeanTreeModel> table = new TreeGrid<BeanTreeModel>(store, cm);
            table.setBorders(true);
            // table.getStyle().setLeafIconStyle("icon-page");
            
            QuickTip qt = new QuickTip(table);
            
            table.setStyleName("");
            table.setSize(700, 300);
            
            ContentPanel panel = new ContentPanel();
            panel.setLayout(new FlowLayout());
            panel.setSize(800, 400);
            panel.add(table);
            
            RootPanel.get().add(panel);
        }
        
        public class BlindProxy<C extends BeanTreeModel> implements DataProxy<List<C>>
        {
            private C model; 
    
            public BlindProxy()
            {
                
            }
            
            public BlindProxy(C model)
            {
                this.model = model;
            }
    
    
            @SuppressWarnings("unchecked")
            public void load(DataReader<List<C>> reader, Object loadConfig, AsyncCallback<List<C>> callback)
            {
                    try
                    {
                        List<C> d = null;
                        if (loadConfig != null && loadConfig instanceof BeanTreeModel)
                        {
                            BeanTreeModel item = (BeanTreeModel) loadConfig;
                            if (reader != null)
                            {
                                d = reader.read(loadConfig, model);
                            } 
                            else
                            {
                                d = (List<C>) item.getChildren();
                            }
                            callback.onSuccess(d);
                        }
                        else
                        {
                            if (loadConfig == null)
                            {
                                d = (List<C>) model.getChildren();
                                callback.onSuccess(d);
                            }
                            else
                            {
                                throw new Exception("Not a BeanTreeModel");
                            }
                        }
                    } catch (Exception e) 
                    {
                        callback.onFailure(e);
                    }
            }
            
            public C getModel()
            {
                return model;
            }
    
            public void setModel(C model)
            {
                this.model = model;
            }
        }
        
        @SuppressWarnings("serial")
        public class BeanTreeModel extends BeanModel implements TreeModel
        {
            /**
               * The model's parent.
               */
              protected TreeModel parent;
    
              /**
               * The model's children.
               */
              protected List<ModelData> children;
    
              /**
               * Creates a new model instance.
               */
              public BeanTreeModel() {
                children = new ArrayList<ModelData>();
              }
    
              /**
               * Creates a new model instance.
               * 
               * @param parent the parent
               */
              public BeanTreeModel(TreeModel parent) {
                this();
                parent.add(this);
              }
    
              /**
               * Adds a child to the model and fires an {@link ChangeEventSource#Add} event.
               * 
               * @param child the child to be added
               */
              public void add(ModelData child) {
                insert(child, getChildCount());
              }
    
              /**
               * Returns the child at the given index or <code>null</code> if the index is
               * out of range.
               * 
               * @param index the index to be retrieved
               * @return the model at the index
               */
              public ModelData getChild(int index) {
                if ((index < 0) || (index >= children.size())) return null;
                return children.get(index);
              }
    
              /**
               * Returns the number of children.
               * 
               * @return the number of children
               */
              public int getChildCount() {
                return children.size();
              }
    
              /**
               * Returns the model's children.
               * 
               * @return the children
               */
              public List<ModelData> getChildren() {
                return children;
              }
    
              /**
               * Returns the model's parent or <code>null</code> if no parent.
               * 
               * @return the parent
               */
              public TreeModel getParent() {
                return parent;
              }
    
              public int indexOf(ModelData child) {
                return children.indexOf(child);
              }
    
              /**
               * Inserts a child to the model and fires an {@link ChangeEventSource#Add}
               * event.
               * 
               * @param child the child to be inserted
               * @param index the location to insert the child
               */
              public void insert(ModelData child, int index) {
                adopt(child);
                children.add(index, child);
                ChangeEvent evt = new ChangeEvent(Add, this);
                evt.setParent(this);
                evt.setItem(child);
                evt.setIndex(index);
                notify(evt);
              }
    
              public boolean isLeaf() {
                return children.size() == 0;
              }
    
              @Override
              public void notify(ChangeEvent evt) {
                super.notify(evt);
                if (parent != null && parent instanceof ChangeEventSource) {
                  evt.setSource(parent);
                  ((ChangeEventSource) parent).notify(evt);
                }
              }
    
              /**
               * Removes the child at the given index.
               * 
               * @param index the child index
               */
              public void remove(int index) {
                if (index >= 0 && index < getChildCount()) {
                  remove(getChild(index));
                }
              }
    
              /**
               * Removes the child from the model and fires a
               * {@link ChangeEventSource#Remove} event.
               * 
               * @param child the child to be removed
               */
              public void remove(ModelData child) {
                orphan(child);
                children.remove(child);
                ChangeEvent evt = new ChangeEvent(Remove, this);
                evt.setParent(this);
                evt.setItem(child);
                notify(evt);
              }
    
              public void removeAll() {
                for (int i = children.size() - 1; i >= 0; i--) {
                  remove(getChild(i));
                }
              }
    
              /**
               * Sets the model's children. All existing children are first removed.
               * 
               * @param children the children to be set
               */
              public void setChildren(List<ModelData> children) {
                removeAll();
                if (children != null) {
                  for (ModelData child : children) {
                    add(child);
                  }
                }
              }
    
              public void setParent(TreeModel parent) {
                this.parent = parent;
              }
              
              
              
              private void setParentInternal(ModelData child) {
                if (child instanceof TreeModel) {
                  TreeModel treeChild = (TreeModel)child;
                  treeChild.setParent(this);
                } else {
                  child.set("gxt.parent", child);
                }
              }
              
              private TreeModel getParentInternal(ModelData child) {
                if (child instanceof TreeModel) {
                  TreeModel treeChild = (TreeModel)child;
                  return treeChild.getParent();
                } else {
                  return (TreeModel)child.get("gxt.parent");
                }
              }
    
              private void adopt(ModelData child) {
                TreeModel p = getParentInternal(child);
                if (p != null && p != this) {
                  p.remove(child);
                }
                setParentInternal(child);
              }
              
              private void orphan(ModelData child) {
                if (child instanceof TreeModel) {
                  TreeModel treeChild = (TreeModel)child;
                  treeChild.setParent(null);
                } else {
                  child.remove("gxt.parent");
                }
              }
        }
        
        public class TestModel extends BeanTreeModel implements Serializable
        {
            public TestModel() {
    
              }
    
              public TestModel(String name, String icon, String abbrv) {
                set("name", name);
                set("icon", icon);
                set("abbrv", abbrv);
              }
    
              public TestModel(String name, String icon, String abbrv, BeanTreeModel[] children) {
                this(name, icon, abbrv);
                for (int i = 0; i < children.length; i++) {
                  add(children[i]);
                }
              }
    
              public String getName() {
                return (String) get("name");
              }
              
              public String getAbbrv()
              {
                  return (String) get("abbrv");
              }
              
              public String getIcon()
              {
                  return (String) get("icon");
              }
    
              public String toString() {
                return getName();
              }
        }
        
        public class TooltipRenderer extends TreeGridCellRenderer<BeanModel>
        {
    
            /* (non-Javadoc)
             * @see com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer#render(com.extjs.gxt.ui.client.data.ModelData, java.lang.String, com.extjs.gxt.ui.client.widget.grid.ColumnData, int, int, com.extjs.gxt.ui.client.store.ListStore, com.extjs.gxt.ui.client.widget.grid.Grid)
             */
            @Override
            public Object render(BeanModel model, String property, ColumnData config,
                    int rowIndex, int colIndex, ListStore<BeanModel> store,
                    Grid<BeanModel> grid)
            {
                if (model instanceof TestModel && colIndex > 0)
                {
                    int tooltipWidth = (colIndex + 1) * 100;
                    
                    StringBuilder stringBuilder = new StringBuilder();
                    
                    stringBuilder.append("<span ");
                    stringBuilder.append("qtip='Tooltip Width " + tooltipWidth);
                    stringBuilder.append("' qwidth='" + tooltipWidth);
                    stringBuilder.append("' >");
                    switch(colIndex)
                    {
                        case 0:
                            stringBuilder.append(((TestModel) model).getName());
                            break;
                        case 1:
                            stringBuilder.append(((TestModel) model).getIcon());
                            break;
                        case 2:
                            stringBuilder.append(((TestModel) model).getAbbrv());
                            break;
                            
                    }
                    stringBuilder.append("</span>");
                    
                    return stringBuilder.toString();
                }
                else
                {
                    return super.render(model, property, config, rowIndex, colIndex, store, grid);
                }
            }
            
        }
    }

  2. #2
    Sencha Premium Member
    Join Date
    Sep 2007
    Posts
    13,976

    Default

    This is the same issue. Thanks for the detailed testcase. It works without any problems against the latest svn verison.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •