1. #1
    Ext User fulvius's Avatar
    Join Date
    Nov 2007
    Posts
    20
    Vote Rating
    0
    fulvius is on a distinguished road

      0  

    Question [FNR] gxt 2.0-m1 DragDrop tab support

    [FNR] gxt 2.0-m1 DragDrop tab support


    Hey guys... I think that I found a bug when put DD support in a tabPanel. To best understand, execute the code below and try do some moves with the tabs... you'll see some inconsistences in console: the tabs in the List<TabsItem> of tabPanel is another sequence in comparation with display in the browser.

    Thanks!




    Code:
    
    package main.client;
    
    import com.extjs.gxt.ui.client.dnd.DragSource;
    import com.extjs.gxt.ui.client.dnd.DropTarget;
    import com.extjs.gxt.ui.client.event.ButtonEvent;
    import com.extjs.gxt.ui.client.event.DNDEvent;
    import com.extjs.gxt.ui.client.event.Events;
    import com.extjs.gxt.ui.client.event.Listener;
    import com.extjs.gxt.ui.client.event.SelectionListener;
    import com.extjs.gxt.ui.client.widget.HorizontalPanel;
    import com.extjs.gxt.ui.client.widget.Info;
    import com.extjs.gxt.ui.client.widget.LayoutContainer;
    import com.extjs.gxt.ui.client.widget.TabItem;
    import com.extjs.gxt.ui.client.widget.TabPanel;
    import com.extjs.gxt.ui.client.widget.VerticalPanel;
    import com.extjs.gxt.ui.client.widget.TabItem.HeaderItem;
    import com.extjs.gxt.ui.client.widget.button.Button;
    import com.extjs.gxt.ui.client.widget.button.ToggleButton;
    import com.extjs.gxt.ui.client.widget.layout.FitLayout;
    
    public class AdvancedTabExample extends LayoutContainer {
    
    	private int index = 0;
    	private TabPanel advanced;
    
    	public AdvancedTabExample() {
    
    		setLayout(new FitLayout());
    
    		LayoutContainer wrap = new LayoutContainer();
    		wrap.setLayout(new FitLayout());
    
    		VerticalPanel vp = new VerticalPanel();
    		vp.setSpacing(10);
    
    		HorizontalPanel hp = new HorizontalPanel();
    		hp.setSpacing(5);
    
    		Button add = new Button("Add Tab");
    		add.addSelectionListener(new SelectionListener<ButtonEvent>() {
    			@Override
    			public void componentSelected(ButtonEvent ce) {
    				addTab();
    				advanced.setSelection(advanced.getItem(index - 1));
    			}
    		});
    		hp.add(add);
    
    		ToggleButton toggle = new ToggleButton("Enable Tab Context Menu");
    		toggle.addListener(Events.Toggle, new Listener<ButtonEvent>() {
    			public void handleEvent(ButtonEvent be) {
    				advanced.setCloseContextMenu(((ToggleButton) be.getButton())
    						.isPressed());
    			}
    		});
    		toggle.toggle(true);
    		hp.add(toggle);
    		vp.add(hp);
    
    		advanced = new TabPanel();
    		advanced.setMinTabWidth(115);
    		advanced.setResizeTabs(true);
    		advanced.setAnimScroll(true);
    		advanced.setTabScroll(true);
    		advanced.setCloseContextMenu(true);
    
    		while (index < 7) {
    			addTab();
    		}
    
    		addTabWithPortal();
    
    		vp.setStyleAttribute("border", "1px solid red");
    		wrap.setHeight("100%");
    		wrap.setStyleAttribute("border", "1px solid black");
    		wrap.add(advanced);
    		vp.add(wrap);
    		add(wrap);
    
    		advanced.setSelection(advanced.getItem(7));
    
    	}
    
    	private void addTab() {
    		final TabItem item = new TabItem();
    		item.setText("New Tab " + ++index);
    		item.setClosable(index != 1);
    		item.addText("Tab Body " + index);
    		item.addStyleName("pad-text");
    		item.setStyleAttribute("border", "1px solid green");
    		advanced.add(item);
    
    		addDragSupport(item);
    		addDropSupport(item);
    
    	}
    
    	
    
    	private void addDragSupport(final TabItem tabItem) {
    
    		final HeaderItem headerItem = tabItem.getHeader();
    		DragSource source = new DragSource(headerItem) {
    			@Override
    			protected void onDragStart(DNDEvent event) {
    
    				event.setData(tabItem);
    				event.getStatus().update(headerItem.getText());
    
    			}
    		};
    		source.setGroup("DDtabs");
    	}
    
    	private void addDropSupport(final TabItem tabItem) {
    
    		final HeaderItem headerItem = tabItem.getHeader();
    		DropTarget target = new DropTarget(headerItem) {
    			@Override
    			protected void onDragDrop(DNDEvent event) {
    				super.onDragDrop(event);
    
    				TabItem _draggedTabItem = event.getData();
    				TabPanel _tabPanel = tabItem.getTabPanel();
    				int indexSource = _tabPanel.indexOf(_draggedTabItem);
    				int indexTarget = _tabPanel.indexOf(tabItem);
    				Info.display("source:" + indexSource, "target:" + indexTarget);
    
    				_tabPanel.insert(_draggedTabItem, indexTarget);
    				showAllTabHeaders(_tabPanel);
    				advanced.setSelection(_draggedTabItem);
    			}
    		};
    		target.setGroup("DDtabs");
    		target.setOverStyle("drag-ok");
    
    	}
    
    	
    	
    	
    	
    	private void showAllTabHeaders(TabPanel tabPanel) {
    		String out = "";
    		for (TabItem _tb : tabPanel.getItems()) {
    			int index = tabPanel.indexOf(_tb);
    			out += index + " : " + _tb.getHeader().getText() + "\n";
    		}
    		System.out.println(out);
    	}
    
    
    }

  2. #2
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    I think I found the issue... I've been chasing this a while, and it looks like a bug to me in TabPanel.java:422 (code below is from trunk).
    Code:
    416:  public boolean insert(TabItem item, int index) {
    417:    boolean added = super.insert(item, index);
    418:    if (added) {
    419:      item.tabPanel = this;
    420:      item.setAutoHeight(isAutoHeight());
    421:      if (rendered) {
    422:        renderItem(item, index);
    At line 417, super.insert(T, int) has a routine called adjustIndex(T, int), which decrements the index by one if the item (TabItem in our case) is being inserted after itself, because by the time that happens, it will have been removed:

    [tab 0] [tab 1] [tab 2]
    TabPanel.add([tab 1], 2);
    index will be set to 1 instead.

    However, by the time we get back to TabPanel.insert(TabItem, int), we no longer have that corrected index, and the TabPanel mistakenly calls TabPanel.renderItem(TabItem, int) at 422 with the wrong index. There are a couple of fixes for this - either put the renderItem(TabItem, int) call in onInsert(T, int) where it can get the correct index, or call adjustIndex from within TabPanel.insert.

    Very annoying bug, but only presents itself when moving Tabs to a later position without removing them first, but then again, you aren't supposed to have to remove the object first...

    Can this be moved to the bug forum? Or should I cross post the issue and possible solutions?

  3. #3
    Sencha User
    Join Date
    Sep 2007
    Posts
    13,971
    Vote Rating
    132
    sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light

      0  

    Default


    I will move the part to onInsert where it gets the correct index. Will be part of the next release.

  4. #4
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    Thanks sven - I look forward to seeing it in svn.

  5. #5
    Sencha User
    Join Date
    Sep 2007
    Posts
    13,971
    Vote Rating
    132
    sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light sven is a glorious beacon of light

      0  

    Default


    Fixed in SVN.

Thread Participants: 2