/******************************************************************************* * Copyright (c) 2010, 2015 IBM Corporation 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: * IBM Corporation - initial API and implementation ******************************************************************************/ package org.eclipse.e4.ui.workbench.addons.dndaddon; import java.util.List; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedFactoryImpl; 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.MTrimElement; import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl; import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; /** * */ abstract class DragAgent { private static final String DRAG_PLACEHOLDER_ID = "Drag Placerholder"; protected MUIElement dragElement; protected DnDManager dndManager; private MUIElement dragPH = null; protected DropAgent dropAgent = null; /** * Return the element that your agent would start to drag given the current cursor info. * * @param info * Information about which model element the cursor is over * * @return The element that this agent would drag or null if the agent is not appropriate for * the given info */ public abstract MUIElement getElementToDrag(DnDInfo info); /** * */ public DragAgent(DnDManager manager) { dndManager = manager; } /** * @return the dragElement */ public MUIElement getDragElement() { return dragElement; } /** * Determine if a drag can be started on the given info. This allows a subclass to restrict the * ability of an agent to initiate a drag operation (i.e. in a 'fixed' perspective...). * * The default implementation is to allow dragging if the agent can determine an element to * drag. * * @param info * Information about which model element the cursor is over * * @return true iff there is an element to drag */ public boolean canDrag(DnDInfo info) { dragElement = getElementToDrag(info); return dragElement != null; } /** * Start a drag operation on the given element. * * @param element * The element to drag */ public void dragStart(DnDInfo info) { // cache a placeholder where the element started (NOTE: this also prevents the parent from // being auto-removed by going 'empty' if (dragElement.getParent() != null) { if (dragElement instanceof MStackElement) { dragPH = AdvancedFactoryImpl.eINSTANCE.createPlaceholder(); } else if (dragElement instanceof MPartStack) { dragPH = BasicFactoryImpl.eINSTANCE.createPartSashContainer(); } else if (dragElement instanceof MTrimElement) { dragPH = MenuFactoryImpl.eINSTANCE.createToolControl(); } dragPH.setElementId(DRAG_PLACEHOLDER_ID); dragPH.setToBeRendered(false); List<MUIElement> kids = dragElement.getParent().getChildren(); kids.add(kids.indexOf(dragElement), dragPH); } dropAgent = dndManager.getDropAgent(dragElement, info); if (dropAgent != null) { dropAgent.dragEnter(dragElement, info); } } public void track(DnDInfo info) { DropAgent newDropAgent = dndManager.getDropAgent(dragElement, info); if (newDropAgent == dropAgent) { if (dropAgent != null) { dropAgent.track(dragElement, info); } } else { if (dropAgent != null) { dropAgent.dragLeave(dragElement, info); } dropAgent = newDropAgent; if (dropAgent != null) { dropAgent.dragEnter(dragElement, info); } else { dndManager.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_NO)); } } } /** * Cancel the drag operation. The default implementation will return the dragElement to its * original location in the model. */ public void cancelDrag() { if (dragPH == null) { return; } // if the dragElement is *not* directly after the placeholder we have to return it there List<MUIElement> phParentsKids = dragPH.getParent().getChildren(); if (phParentsKids.indexOf(dragElement) != phParentsKids.indexOf(dragPH) + 1) { dragElement.setToBeRendered(false); if (dragElement.getParent() != null) { dragElement.getParent().getChildren().remove(dragElement); } phParentsKids.add(phParentsKids.indexOf(dragPH) + 1, dragElement); dragElement.setVisible(true); dragElement.setToBeRendered(true); } } /** * Restore the DragAgent to a state where it will be ready to start a new drag * * @param performDrop * determines if a drop operation should be performed if possible */ public void dragFinished(boolean performDrop, DnDInfo info) { boolean isNoDrop = dndManager.getDragShell().getCursor() == Display.getCurrent() .getSystemCursor(SWT.CURSOR_NO); if (performDrop && dropAgent != null && !isNoDrop) { dropAgent.drop(dragElement, info); } else { cancelDrag(); } if (dropAgent != null) { dropAgent.dragLeave(dragElement, info); } if (dragPH == null) { return; } if (dragPH != null) { dragPH.getParent().getChildren().remove(dragPH); dragPH = null; } dragElement = null; } /** * This agent is being disposed */ public void dispose() { } }