All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.swm.commons.mobile.client.widgets.tree.TreePanel Maven / Gradle / Ivy

/*
 * Copyright 2011 SWM Services GmbH.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package de.swm.commons.mobile.client.widgets.tree;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import de.swm.commons.mobile.client.SWMMobile;
import de.swm.commons.mobile.client.base.PanelBase;
import de.swm.commons.mobile.client.event.*;
import de.swm.commons.mobile.client.theme.components.TreePanelCss;
import de.swm.commons.mobile.client.utils.Utils;
import de.swm.commons.mobile.client.widgets.*;
import de.swm.commons.mobile.client.widgets.scroll.ScrollPanelWithScrollbar;
import de.swm.commons.mobile.client.widgets.tree.TreeChangedEvent.EventType;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TreePanel extends PanelBase implements SwipeEventsHandler {
	
	private static final String BREADCRUMB_DELIMITER = ">";
	
	private final TreePanelCss css;
	
	private final boolean hasBreadcrumb;
	private Label breadcrumbLabel;

	private ScrollPanelWithScrollbar leftScrollPanel;
	private ScrollPanelWithScrollbar middleScrollPanel;
	private ScrollPanelWithScrollbar rightScrollPanel;
	
	private ITree selectedTree;
	private HandlerRegistration selectionHandlerRegistration;
	private final SelectionChangedHandler selectionHandler;
	private final Map itemMap = new HashMap();
	
	public TreePanel() {
		this(false);
	}

	@UiConstructor
	public TreePanel(boolean hasBreadcrumb) {
		this.hasBreadcrumb = hasBreadcrumb;
		css = SWMMobile.getTheme().getMGWTCssBundle().getTreePanelCss();
		addStyleName(css.getTreePanel());
		
		if (hasBreadcrumb) {
			HorizontalPanel breadcrumbPanel = new HorizontalPanel();
			breadcrumbPanel.addStyleName(css.getTreeBreadcrumbPanel());
			ImageHighlightButton backButton = new ImageHighlightButton(SWMMobile.getTheme().getMGWTImageBundle().arrowleft(), new ClickHandler() {

				@Override
				public void onClick(ClickEvent event) {
					navigateBack();
				}
			});
			backButton.addStyleName(css.getTreeBreadcrumbButton());
			breadcrumbPanel.add(backButton);
			breadcrumbLabel = new Label("-");
			breadcrumbLabel.addStyleName(css.getTreeBreadcrumbLabel());
			breadcrumbPanel.add(breadcrumbLabel);
			add(breadcrumbPanel);
		}

		HorizontalPanel container = new HorizontalPanel();
		container.addStyleName(css.getTreeContainer());
		add(container);
		
		leftScrollPanel = new ScrollPanelWithScrollbar();
		leftScrollPanel.addStyleName(css.getTreeList());
		leftScrollPanel.addStyleName(css.getTreeLeftList());		
		leftScrollPanel.add(new ListPanel());
		container.add(leftScrollPanel);
		
		rightScrollPanel = new ScrollPanelWithScrollbar();
		rightScrollPanel.addStyleName(css.getTreeList());
		rightScrollPanel.addStyleName(css.getTreeRightList());
		rightScrollPanel.add(new ListPanel());
		container.add(rightScrollPanel);
		
		middleScrollPanel = new ScrollPanelWithScrollbar();
		middleScrollPanel.addStyleName(css.getTreeList());
		middleScrollPanel.addStyleName(css.getTreeMiddleList());
		middleScrollPanel.add(new ListPanel());		
		container.add(middleScrollPanel);
		
		selectionHandler = new SelectionChangedHandler() {
			
			@Override
			public void onSelectionChanged(SelectionChangedEvent e) {
				int selectedIdex = e.getSelection();
				ListPanel list = (ListPanel) middleScrollPanel.getWidget();
				ListItem selectedItem = list.getItem(selectedIdex);
				ITree tree = itemMap.get(selectedItem);
				if (hasDetails(tree)) {
					shiftRight(tree);
					selectedTree = tree;
				}
				
				if (tree != null) {
					TreeChangedEvent event = new TreeChangedEvent(tree, EventType.CHILD_SELECTED);
					fireEvent(event);
				}
			}
		};
		ListPanel list = (ListPanel) middleScrollPanel.getWidget();
		selectionHandlerRegistration = list.addSelectionChangedHandler(selectionHandler);
	}
	
	private boolean hasDetails(ITree tree) {
		if (tree != null) {
			if (!tree.getChildren().isEmpty()) {
				return true;
			} else {
				ITreeNode node = tree.getNode();
				if (node != null && node.getDisplay() != null) {
					return true;
				}
			}
		}
		return false;
	}
	
	public void setTree(ITree tree) {
		ListPanel list = (ListPanel) middleScrollPanel.getWidget();
		populateList(list, tree);
		selectedTree = tree;
		if (hasBreadcrumb) {
			breadcrumbLabel.setText(tree.getNode().getHeader());
		}
		
		TreeChangedEvent event = new TreeChangedEvent(selectedTree, EventType.INIT_COMPLETE);
		this.fireEvent(event);
	}
	
	/**
	 * Adds a tree changed handler.
	 * 
	 * @param handler
	 *            tree changed handler
	 * @return handle to remove this handler.
	 */
	public HandlerRegistration addTreeChangedHandler(TreeChangedHandler handler) {
		return this.addHandler(handler, TreeChangedEvent.TYPE);
	}
	
	@Override
	public void onLoad() {
		super.onLoad();
		DragController.get().addSwipeEventsHandler(this);
	}

	@Override
	protected void onUnload() {
		DragController.get().removeSwipeEventHandler(this);
		super.onUnload();
	}

	@Override
	public void onSwipeHorizontal(SwipeEvent e) {
		e.stopPropagation();
		if (e.getSpeed() > 0) {
			navigateBack();
		}
	}

	@Override
	public void onSwipeVertical(SwipeEvent e) {
		// Do nothing.
	}
	
	private void shiftRight(ITree tree) {
		if (hasBreadcrumb) {
			breadcrumbLabel.setText(breadcrumbLabel.getText() + " " + BREADCRUMB_DELIMITER + " " + tree.getNode().getHeader());
		}
		
		if (tree.getChildren().isEmpty() && tree.getNode().getDisplay() != null) {
			// use custom display for leaf of tree
			rightScrollPanel.clear();
			rightScrollPanel.add(tree.getNode().getDisplay().asWidget());
			tree.getNode().getDisplay().setNode(tree.getNode());
		} else {
			// use standard list to display children of tree
			ListPanel list = (ListPanel) rightScrollPanel.getWidget();
			populateList(list, tree);
		}
		
		middleScrollPanel.addStyleName(css.getSlide());
		rightScrollPanel.addStyleName(css.getSlide());
		middleScrollPanel.addStyleName(css.getLeft());
		rightScrollPanel.addStyleName(css.getLeft());
		
		Utils.addEventListenerOnce(rightScrollPanel.getElement(), Utils.getTransitionEventName(rightScrollPanel.getElement()), false, new EventListener() {

			@Override
			public void onBrowserEvent(Event event) {
				selectionHandlerRegistration.removeHandler();
								
				middleScrollPanel.removeStyleName(css.getSlide());
				rightScrollPanel.removeStyleName(css.getSlide());
				middleScrollPanel.removeStyleName(css.getLeft());
				rightScrollPanel.removeStyleName(css.getLeft());

				leftScrollPanel.removeStyleName(css.getTreeLeftList());
				middleScrollPanel.removeStyleName(css.getTreeMiddleList());
				rightScrollPanel.removeStyleName(css.getTreeRightList());

				// shift panels
				ScrollPanelWithScrollbar tmp = leftScrollPanel;
				leftScrollPanel = middleScrollPanel;
				middleScrollPanel = rightScrollPanel;
				rightScrollPanel  = tmp;
				
				leftScrollPanel.addStyleName(css.getTreeLeftList());
				middleScrollPanel.addStyleName(css.getTreeMiddleList());
				rightScrollPanel.addStyleName(css.getTreeRightList());
				
				Widget content = middleScrollPanel.getWidget();
				if (content instanceof ListPanel) {
					ListPanel list = (ListPanel) content;
					selectionHandlerRegistration = list.addSelectionChangedHandler(selectionHandler);
				}
			}
			
		});
	}
	
	private void shiftLeft(final ITree tree) {
		if (hasBreadcrumb) {
			String breadcrumb = breadcrumbLabel.getText();
			int pos = breadcrumb.lastIndexOf(BREADCRUMB_DELIMITER);
			if (pos > 1) {
				breadcrumbLabel.setText(breadcrumb.substring(0, pos - 1));
			}
		}
		
		final ListPanel list = (ListPanel) leftScrollPanel.getWidget();
		populateList(list, tree.getParent());
		
		middleScrollPanel.addStyleName(css.getSlide());
		leftScrollPanel.addStyleName(css.getSlide());		
		middleScrollPanel.addStyleName(css.getRight());
		leftScrollPanel.addStyleName(css.getRight());		

		Utils.addEventListenerOnce(middleScrollPanel.getElement(), Utils.getTransitionEventName(middleScrollPanel.getElement()), false, new EventListener() {

			@Override
			public void onBrowserEvent(Event event) {
				if (!tree.getChildren().isEmpty() || (tree.getNode().getDisplay() == null)) {
					// current tree node is no leaf or has no custom display -> there was a standard selection listener which must be removed
					selectionHandlerRegistration.removeHandler();
				}
				
				middleScrollPanel.removeStyleName(css.getSlide());
				leftScrollPanel.removeStyleName(css.getSlide());		
				middleScrollPanel.removeStyleName(css.getRight());
				leftScrollPanel.removeStyleName(css.getRight());		

				leftScrollPanel.removeStyleName(css.getTreeLeftList());
				middleScrollPanel.removeStyleName(css.getTreeMiddleList());
				rightScrollPanel.removeStyleName(css.getTreeRightList());
				
				// shift panels
				ScrollPanelWithScrollbar tmp = rightScrollPanel;
				rightScrollPanel = middleScrollPanel;
				middleScrollPanel = leftScrollPanel;
				leftScrollPanel = tmp;
								
				leftScrollPanel.addStyleName(css.getTreeLeftList());
				middleScrollPanel.addStyleName(css.getTreeMiddleList());
				rightScrollPanel.addStyleName(css.getTreeRightList());
				
				if (tree.getChildren().isEmpty() && (tree.getNode().getDisplay() != null)) {
					// current tree node uses a custom display -> recreate list for new right scroll panel
					rightScrollPanel.clear();
					rightScrollPanel.add(new ListPanel());
				}

				selectionHandlerRegistration = list.addSelectionChangedHandler(selectionHandler);
			}
			
		});
	}
	
	private void populateList(ListPanel list, ITree tree) {
		itemMap.clear();
		list.clear();
		List children = tree.getChildren();
		for (ITree child : children) {
			ITreeNode node = child.getNode();
			ListItem item = null;
			if (node.getIcon() != null) {
				item = new DecoratedListItem(node.getIcon(), node.getHeader(), null);
			} else {
				item = new ListItem();
				item.add(new Label(node.getHeader()));
			}
			item.setShowArrow(!child.getChildren().isEmpty());
			if (node.getStyleName() != null) {
				item.addStyleName(node.getStyleName());
			}
			list.add(item);
			itemMap.put(item, child);
		}		
	}

	@Override
	public void setHeight(String height) {
		super.setHeight(height);
		leftScrollPanel.setHeight(height);
		rightScrollPanel.setHeight(height);
		middleScrollPanel.setHeight(height);
	}

	private void navigateBack() {
		if (selectedTree.getParent() != null) {
			shiftLeft(selectedTree);
			selectedTree = selectedTree.getParent();
			
			TreeChangedEvent backEvent = new TreeChangedEvent(selectedTree, EventType.BACK_EVENT);
			fireEvent(backEvent);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy