Java tutorial
/******************************************************************************* * Copyright (c) 2012 Rushan R. Gilmullin and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rushan R. Gilmullin - initial API and implementation *******************************************************************************/ package org.semanticsoft.vaaclipse.presentation.dnd; import javax.inject.Inject; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.advanced.MArea; import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer; import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; import org.eclipse.e4.ui.model.application.ui.basic.MStackElement; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.emf.ecore.EObject; import org.semanticsoft.commons.geom.GeomUtils; import org.semanticsoft.commons.geom.Side; import org.semanticsoft.commons.geom.Vector; import org.semanticsoft.vaaclipse.widgets.StackWidget; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptAll; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.shared.ui.dd.HorizontalDropLocation; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.TabSheet.Tab; import fi.jasoft.dragdroplayouts.DDTabSheet.TabSheetTargetDetails; import fi.jasoft.dragdroplayouts.events.LayoutBoundTransferable; /** * @author rushan * */ public class VaadinDropHandler implements DropHandler { private MPartStack targetPartStack; private StackWidget targetTabSheet; @Inject EModelService modelService; @Inject public VaadinDropHandler(MPartStack targetPartStack) { this.targetPartStack = targetPartStack; targetTabSheet = (StackWidget) targetPartStack.getWidget(); } public AcceptCriterion getAcceptCriterion() { // Only allow dropping between tabs //return new Not(HorizontalLocationIs.CENTER); return AcceptAll.get(); } public void drop(DragAndDropEvent event) { if (!(event.getTransferable() instanceof LayoutBoundTransferable)) return; LayoutBoundTransferable transferable = (LayoutBoundTransferable) event.getTransferable(); TabSheetTargetDetails details = (TabSheetTargetDetails) event.getTargetDetails(); if (transferable.getSourceComponent() instanceof StackWidget) { StackWidget sourceTabSheet = (StackWidget) transferable.getSourceComponent(); MPartStack targetFolder = targetPartStack; MPartStack sourceFolder = (MPartStack) sourceTabSheet.getData(); // this component is dragged by user AbstractComponent draggingComponent = (AbstractComponent) transferable.getComponent(); //This is model element that match to draggingComponent MStackElement draggingElement = (MStackElement) draggingComponent.getData(); //draggingElement must be in sourceFolder if (!sourceFolder.getChildren().contains(draggingElement)) return; String dropType = (String) details.getData("dropType"); if (dropType.equals("DropToTabsheetBar")) { int idx = details.getOverIndex(); HorizontalDropLocation location = details.getDropLocation(); if (draggingComponent == details.getOverComponent()) { // Dropped on itself return; } if (sourceTabSheet == targetTabSheet) {//reordering tabs if (sourceFolder != targetFolder) return; int modelOldPos = sourceFolder.getChildren().indexOf(draggingElement); Tab tabInNewPos = targetTabSheet.getTab(idx); if (tabInNewPos == null) return; MUIElement elementInInsertPos = (MUIElement) ((AbstractComponent) tabInNewPos.getComponent()) .getData(); int modelNewPos = targetPartStack.getChildren().indexOf(elementInInsertPos); targetPartStack.getChildren().remove(draggingElement); if (location == HorizontalDropLocation.RIGHT) { if (modelOldPos > modelNewPos) targetPartStack.getChildren().add(modelNewPos + 1, draggingElement); else targetPartStack.getChildren().add(modelNewPos, draggingElement); } else {//LEFT OR CENTER - processed as LEFT if (modelOldPos > modelNewPos) targetPartStack.getChildren().add(modelNewPos, draggingElement); else targetPartStack.getChildren().add(modelNewPos - 1, draggingElement); } } else {// Adding new tab sourceFolder.getChildren().remove(draggingElement); if (idx == -1) targetFolder.getChildren().add(draggingElement); else { Tab tabInNewPos = targetTabSheet.getTab(idx); MUIElement elementInNewPos = (MUIElement) ((AbstractComponent) tabInNewPos.getComponent()) .getData(); int modelNewPos = targetPartStack.getChildren().indexOf(elementInNewPos); int newPos = -1; if (location == HorizontalDropLocation.RIGHT) { targetFolder.getChildren().add(modelNewPos + 1, draggingElement); } else {//LEFT or CENTER - processed both as LEFT targetFolder.getChildren().add(modelNewPos, draggingElement); } } } targetFolder.setSelectedElement(draggingElement); } else if (dropType.equals("DropToTabsheetBody")) { //target widget coordinates: int x0 = (Integer) details.getData("targetWidgetAbsoluteLeft"); int y0 = (Integer) details.getData("targetWidgetAbsoluteTop"); int dx = (Integer) details.getData("targetWidgetOffsetWidth"); int dy = (Integer) details.getData("targetWidgetOffsetHeight"); int docPrcnt = 30; double docX = dx * docPrcnt / 100; double docY = dy * docPrcnt / 100; int mouseX = details.getMouseEvent().getClientX(); int mouseY = details.getMouseEvent().getClientY(); Vector mousePos = Vector.valueOf(mouseX, mouseY); Integer side = GeomUtils.findDockSide(x0, y0, dx, dy, docX, docY, mousePos); if (side != null) { targetPartStack.getChildren().remove(draggingElement); if (side == Side.CENTER) {//drop in center is equivalent tab adding at the end of target folder targetFolder.getChildren().add(draggingElement); targetFolder.setSelectedElement(draggingElement); } else {//if drop to sides, we must different what kind is target widget - tabsheet or area boolean onEdge = false; // Find the root of the targetFolder's sash structure //This root - is area, perspective or window MUIElement outerRelTo = targetFolder.getParent(); if (outerRelTo instanceof MPartSashContainer) { while (outerRelTo != null && !(outerRelTo instanceof MArea || outerRelTo instanceof MPerspective || outerRelTo instanceof MWindow)) outerRelTo = outerRelTo.getParent(); } //Outer element can not be null, becouse mpartstack or his sash structure must be located in one of place: area, perspective or window if (outerRelTo == null) return; if (outerRelTo.getParent() == null && outerRelTo.getCurSharedRef() != null) { outerRelTo = outerRelTo.getCurSharedRef(); } MPartSashContainerElement relTo = null; if (outerRelTo instanceof MArea || onEdge) relTo = (MPartSashContainerElement) outerRelTo; else relTo = targetFolder; //store original container data for using after model operations String containerDataBeforeModelOperations = targetFolder.getContainerData(); // wrap it in a stack if it's a part MPartStack toInsert; MStackElement stackElement = (MStackElement) draggingElement; toInsert = BasicFactoryImpl.eINSTANCE.createPartStack(); toInsert.getChildren().add(stackElement); toInsert.setSelectedElement(stackElement); float pct = (float) (onEdge ? 0.15 : 0.3); MUIElement relToParent = relTo.getParent(); modelService.insert(toInsert, relTo, convert(side), pct); // Force the new sash to have the same weight as the original element if (relTo.getParent() != relToParent && !onEdge) relTo.getParent().setContainerData(containerDataBeforeModelOperations); } } } } } private int convert(Integer side) { if (side == Side.LEFT) return EModelService.LEFT_OF; else if (side == Side.RIGHT) return EModelService.RIGHT_OF; else if (side == Side.BOTTOM) return EModelService.BELOW; else if (side == Side.TOP) return EModelService.ABOVE; else throw new IllegalArgumentException(); } }