Announcement

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

    menu and peer not destroyed

    Hi,

    is this a possible mem leak or do I need to manage destroy of a Menu myself?
    When I use the DEV CONSOLE tab watch (show hidden & undrawn & generated), the menu and its shadow are still there when clicking the destroy button here. I thought it was a problem with the peer, but menu1 which doesn't have shadow, also is still showing up.

    Code:
    Menu menu1 = new Menu();
    menu1.setID("myMenu1");
    menu1.setShowShadow(false);
    MenuItem item11 = new MenuItem("something");
    menu1.setItems(item11);
    
    Menu menu2 = new Menu();
    menu2.setID("myMenu2");
    menu2.setShowShadow(true);
    menu2.setShadowDepth(3);
    MenuItem item21 = new MenuItem("something else");
    menu2.setItems(item21);
    
    IconMenuButton choose1 = new IconMenuButton("One");
    choose1.setID("myButton1");
    choose1.setMenu(menu1);
    IconMenuButton choose2 = new IconMenuButton("Two");
    choose2.setID("myButton2");
    choose2.setMenu(menu2);
    
    final HLayout menuContainer = new HLayout();
    menuContainer.setMembers(choose1, choose2);
    
    Button d = new Button("destroy");
    d.addClickHandler(new ClickHandler() {
    	
    	public void onClick(ClickEvent event) {
    		menuContainer.destroy();
    	}
    });
    
    VLayout layout = new VLayout();
    layout.setWidth(300);
    layout.setHeight(300);
    layout.setMembers(menuContainer, d);
    
    return layout;
    in attachement screenshot:
    the watch tab after destroy


    FireFox 4 - dev mode
    SNAPSHOT_v8.3d_2012-04-04/Pro Deployment (built 2012-04-04)

    regards,
    Attached Files

    #2
    Menus aren't added as children of other objects - they are always pop-ups - so your addMember() call isn't valid below, and that also implies they have to be explicitly destroyed. The peer (menu shadow) will be destroyed with the menu automatically.

    Comment


      #3
      (I don't really do an addMember call)
      But I understand what you're saying:

      IconMenuButton.setMenu(menu)
      and when IconMenuButton is destroyed, it will not auto destroy that menu.
      I can do that myself indeed.

      Thanks for the verification.

      Comment


        #4
        Hi,

        I've got now almost the same problem with the Menu used in a ListGridField's context menu.

        Repro:
        Code:
        final ListGrid grid = new ListGrid(){
        	@Override
        	protected MenuItem[] getHeaderContextMenuItems(final Integer fieldNum) {
        		MenuItem [] defaults = super.getHeaderContextMenuItems(fieldNum);
        		
        		MenuItem [] mine = new MenuItem [defaults.length + 1];
        		for (int i=0; i<defaults.length; i++) mine[i] = defaults[i];
        		
        		MenuItem item1 = new MenuItem("item1");
        		MenuItem item2 = new MenuItem("item2");
        		
        		Menu submenu = new Menu();
        		submenu.setShowShadow(true);
        		submenu.setItems(item1, item2);
        		MenuItem entry = new MenuItem("I have a menu");
        		entry.setSubmenu(submenu);
        		
        		mine[mine.length - 1] = entry;
        		
        		return mine;
        	}
        };
        
        ListGridField field1 = new ListGridField("field1");
        grid.setFields(field1);
        
        Button d = new Button("destroy");
        d.addClickHandler(new ClickHandler() {
        	
        	public void onClick(ClickEvent event) {
        		grid.destroy();
        	}
        });
        
        VLayout layout = new VLayout();
        layout.setWidth(300);
        layout.setHeight(300);
        layout.setMembers(grid, d);
        SmartGWT v8.3d_2012-11-11/Pro Deployment (built 2012-11-11)

        1) if you run this sample and check with the Watch in the dev_console, there already is a _shadow element.
        2) open the the "I have a menu" menu item
        3) click destroy
        4) refresh the Watch tab
        lots of _shadow elements are not destroyed

        The previous problem (in the previous post) got solved by overwriting the destroy of the IconMenuButton, checking for the Menu and destroying that first.
        Since the MenuItem is actually a ListGridRecord, I'm not sure how or when I can access that Submenu property to destroy it when the grid(/field) is destroyed? Do you have some pointers in the right direction here?

        thanks

        Comment


          #5
          Firstly - you are going to need to track your explicitly created menus yourself, and destroy them.

          Secondly - as written, every time the getHeaderContextMenuItems method runs, the submenu is re-built.

          Basically you'll need your method to only create the menu once, and hold onto a reference to it, then clean that up at destroy.

          Something like this:

          Code:
                 final ListGrid grid = new ListGrid(){
                      private MenuItem[] headerContextMenuItems;
                      private Menu customHeaderMenu;
                      @Override
                      protected MenuItem[] getHeaderContextMenuItems(final Integer fieldNum) {
                          MenuItem [] defaults = super.getHeaderContextMenuItems(fieldNum);
                          if (headerContextMenuItems == null) {
                              MenuItem [] mine = new MenuItem [defaults.length + 1];
                              for (int i=0; i<defaults.length; i++) mine[i] = defaults[i];
                              
                              MenuItem item1 = new MenuItem("item1");
                              MenuItem item2 = new MenuItem("item2");
                              
                              Menu submenu = new Menu();
                              submenu.setShowShadow(true);
                              submenu.setItems(item1, item2);
                              MenuItem entry = new MenuItem("I have a menu");
                              entry.setSubmenu(submenu);
                              
                              customHeaderMenu = submenu;
                              
                              mine[mine.length - 1] = entry;
                              headerContextMenuItems = mine;
                          }
                          return headerContextMenuItems;
                      }
                      
                      @Override
                      public void destroy () {
                          if (customHeaderMenu != null) {
                              customHeaderMenu.destroy();
                              customHeaderMenu = null;
                          }
                          super.destroy();
                      }
                  };

          Comment


            #6
            Thanks, indeed I'm not keeping a menu item cache, as I don't notice it being slow to rebuild the menu each time. And I actually had given up in creating a context menu cache per field: when the user reorders the fields, the fieldNum changes with, so the wrong menu items would show up. I'll revisit that strategy - my field.name is also not unqiue, but field.dataPath should be.


            I tried out your solution and this is also interesting:
            I wanted to keep a reference to all Menus, including the built in one from the "column picker". However, when I try to destroy that one, I get a "self.__destroy is not a function". I'll see to it that I don't keep a reference to it then, but what could the reason for that be?

            Comment


              #7
              This is due to a rather complex interaction where you have a SmartClient component created automatically by the framework in JavaScript code being accessed by Java code (as a SmartGWT class instance). There are some extra initialization steps that occur on the javascript object when you create a SGWT Java widget instance - and it's possible there are cases where the system could get confused if the underlying javascript object never ran through that initialization.

              We would not expect this to be a problem in normal use cases. In this case it's probably safe to avoid and ignore since the (automatically generated) column picker menu is automatically destroyed along with the ListGrid -- it's only your custom menus that are not.

              If it seems there is more to this, or it's interfering with your app, please show us a runnable code snippet that causes this problem and we'll try it out and confirm / see if there's anything we need to address in the framework

              Thanks
              Isomorphic Software

              Comment

              Working...
              X