Drag and drop tabs

Has anyone tried implementing drag and drop to tabs?

is it possible to reorder the position by user?

Hi,

You can probably use vaadin 14.1 drag and drop functionality. or try this addon: https://vaadin.com/directory/component/sortable-layout

I didn’t try it on tabs.

Hi Jean,

Need some help here if possible.


public class DNDTabs extends Tabs { 

	Map<Tab, Component> tabsToPages = new HashMap<>();
	@Getter
	private Div pages;
	
	public DNDTabs() {
		DNDTab tab1 = new DNDTab("Tab one", "Page 1", true);
		Div page1 = tab1.getPage();
		
		DNDTab tab2 = new DNDTab("Tab two", "Page#2", false);
		Div page2 = tab2.getPage();
 		
		DNDTab tab3 = new DNDTab("Tab three", "Page#3", false);
		Div page3 = tab3.getPage();

		tabsToPages.put(tab1, page1);
		tabsToPages.put(tab2, page2);
		tabsToPages.put(tab3, page3);
		add(tab1, tab2, tab3);
		pages = new Div(page1, page2, page3);
		Set<Component> pagesShown = Stream.of(page1).collect(Collectors.toSet());

		addSelectedChangeListener(event -> {
			pagesShown.forEach(page -> page.setVisible(false));
			pagesShown.clear();
			Component selectedPage = tabsToPages.get(getSelectedTab());
			selectedPage.setVisible(true);
			pagesShown.add(selectedPage);
		});
		setWidthFull();
		
		tab1.setSelected(true);
 	}
}



public class DNDTab extends Tab implements DragSource<DNDTab>, DropTarget<DNDTab> { 
	
	@Getter
	@Setter
	private Div page;
	
	public DNDTab(String string, String divText, boolean visible) {
        super(string);
		setDraggable(true); //(2)
		page = new Div();
		page.setText(divText);
		setDragData(page);
		page.setVisible(visible);
		
		setActive(true); // (2)
		 
		addDropListener(eventA -> { // (3)
//			eventA.getDragSourceComponent().ifPresent(this::add);
			eventA.getDragData().ifPresent(data -> page = data; ));
		
			System.out.println("Inside Dropping Event: " + page.getText());
        });
        
        addDragStartListener(event ->{
			System.out.println("Inside Drag Start Event: " + page.getText());      
        });
     }
 }

am i doing it correctly? cant seem to get it worked

Hi,

I think you are not changing the order on the component (drag and drop won’t change the order automatically ).
Here the tabs are swapped.


public class DNDTabs extends Tabs {

    Map<Tab, Component> tabsToPages = new HashMap<>();
    private Div pages;

    public DNDTabs() {
        DNDTab tab1 = new DNDTab("Tab one", "Page 1", true);
        Div page1 = tab1.getPage();

        DNDTab tab2 = new DNDTab("Tab two", "Page#2", false);
        Div page2 = tab2.getPage();

        DNDTab tab3 = new DNDTab("Tab three", "Page#3", false);
        Div page3 = tab3.getPage();

        tabsToPages.put(tab1, page1);
        tabsToPages.put(tab2, page2);
        tabsToPages.put(tab3, page3);

        add(tab1,tab2,tab3);
        pages = new Div(page1, page2, page3);
        Set<Component> pagesShown = Stream.of(page1).collect(Collectors.toSet());

        addSelectedChangeListener(event -> {
            pagesShown.forEach(page -> page.setVisible(false));
            pagesShown.clear();
            Component selectedPage = tabsToPages.get(getSelectedTab());
            selectedPage.setVisible(true);
            pagesShown.add(selectedPage);
        });
        setWidthFull();

        tab1.setSelected(true);
    }

    public Div getPages() {
        return pages;
    }


    public void swap(DNDTab sourceTab, DNDTab dndTab) {
        // should store selected tab and add it
        List<Component> components = getChildren().collect(Collectors.toList());
        int indexSource = components.indexOf(sourceTab);
        int indexDest = components.indexOf(dndTab);

        remove(sourceTab);
        remove(dndTab);
        if (indexDest > indexSource) {
            addComponentAtIndex(indexSource, dndTab);
            addComponentAtIndex(indexDest, sourceTab);
        } else {
            addComponentAtIndex(indexDest, sourceTab);
            addComponentAtIndex(indexSource, dndTab);
        }
    }
}


public class DNDTab extends Tab implements DragSource<DNDTab>, DropTarget<DNDTab> {

    private Div page;

    public DNDTab(String string, String divText, boolean visible) {
        super(string);
        setDraggable(true); //(2)
        page = new Div();
        page.setText(divText);
        setDragData(page);
        page.setVisible(visible);

        setActive(true); // (2)

        addDropListener(eventA -> { // (3)
//			eventA.getDragSourceComponent().ifPresent(this::add);
         //   eventA.getDragData().ifPresent(data -> page = data; ));
            eventA.getDragSourceComponent().ifPresent(component -> {
                if (component instanceof  DNDTab) {
                    DNDTab sourceTab = (DNDTab) component;
                    System.out.println("Source Dropping Event: " + sourceTab.getLabel());
                    // swap these two tabs
                    // check if parents are the same
                    DNDTabs tabs = (DNDTabs) sourceTab.getParent().get();
                    tabs.swap(sourceTab, this);
                }
            });
            System.out.println("Destination Dropping Event: " + getLabel());
        });

    }

    public Div getPage() {
        return page;
    }

    public void setPage(Div page) {
        this.page = page;
    }
}


Hi Jean,

thanks for helping. I created another version for drag and drop.

public void dragandDrop(DNDTab dragTab, DNDTab dropTab) {	
		int indexDest = indexOf(dropTab);
	 
		remove(dragTab);
		addComponentAtIndex(indexDest, dragTab);
 		setSelectedTab(dragTab);

}