diff options
author | Quentin Le Menez | 2019-04-18 07:23:06 +0000 |
---|---|---|
committer | Quentin Le Menez | 2019-04-24 08:05:58 +0000 |
commit | a5a54e96a8005d091921a29f96b7b315726f6438 (patch) | |
tree | f460929818fbdb456a9655204a3e1aff9c9cc21d /plugins/infra/core | |
parent | f5e8e8d8d0f6deb02cf286b460bf8178a0411ca3 (diff) | |
download | org.eclipse.papyrus-a5a54e96a8005d091921a29f96b7b315726f6438.tar.gz org.eclipse.papyrus-a5a54e96a8005d091921a29f96b7b315726f6438.tar.xz org.eclipse.papyrus-a5a54e96a8005d091921a29f96b7b315726f6438.zip |
Bug 545631 - [Releng] 2019-06 traceability
- Update target platforms
- Copy removed internal classes from EclipsePlatformUI
Change-Id: Ib8ec1974b34c38b53a1ca547344077655147af67
Signed-off-by: Quentin Le Menez <quentin.lemenez@cea.fr>
Diffstat (limited to 'plugins/infra/core')
18 files changed, 1291 insertions, 59 deletions
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/AbstractPanelPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/AbstractPanelPart.java index 3409e6d0611..cc6d6010f9c 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/AbstractPanelPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/AbstractPanelPart.java @@ -16,9 +16,9 @@ package org.eclipse.papyrus.infra.core.sasheditor.internal; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.internal.dnd.IDropTarget; /** diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/ComponentPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/ComponentPart.java index f28435583c2..7f808dbeaf9 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/ComponentPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/ComponentPart.java @@ -23,7 +23,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.papyrus.infra.core.sasheditor.Activator; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IComponentModel; import org.eclipse.papyrus.infra.core.sasheditor.editor.IComponentPage; -import org.eclipse.papyrus.infra.core.sasheditor.internal.AbstractPart.GarbageState; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.papyrus.infra.tools.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; @@ -31,7 +31,6 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.PartInitException; -import org.eclipse.ui.internal.dnd.IDropTarget; /** @@ -41,7 +40,6 @@ import org.eclipse.ui.internal.dnd.IDropTarget; * @author dumoulin * */ -@SuppressWarnings("restriction") public class ComponentPart extends PagePart implements IComponentPage { /** @@ -112,7 +110,7 @@ public class ComponentPart extends PagePart implements IComponentPage { @Override public void dispose() { - if( !editorControl.isDisposed() ) { + if (!editorControl.isDisposed()) { // dispose the SWT root control editorControl.dispose(); } diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java index c5981a9cbd0..1ba765e1c6f 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java @@ -28,6 +28,7 @@ import org.eclipse.papyrus.infra.core.sasheditor.Activator; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.AbstractPageModel; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel; import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IMultiPageEditorSite; import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.MultiPageEditorSite; import org.eclipse.papyrus.infra.tools.util.PlatformHelper; @@ -49,7 +50,6 @@ import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.internal.ErrorEditorPart; -import org.eclipse.ui.internal.dnd.IDropTarget; import org.eclipse.ui.internal.misc.StatusUtil; import org.eclipse.ui.part.EditorActionBarContributor; import org.eclipse.ui.part.IWorkbenchPartOrientation; @@ -404,7 +404,7 @@ public class EditorPart extends PagePart implements IEditorPage { @Override public void dispose() { - if( !editorControl.isDisposed() ) { + if (!editorControl.isDisposed()) { detachListeners(editorControl, true); // dispose the SWT root control // This should also trigger the disposal of associated editor. @@ -412,7 +412,7 @@ public class EditorPart extends PagePart implements IEditorPage { // Dispose the editor. // disposeEditorPart(); } - + // clean up properties to help GC editorModel = null; rawModel = null; diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/PTabFolder.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/PTabFolder.java index 33e50c8e77e..07267653325 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/PTabFolder.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/PTabFolder.java @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Set; import org.eclipse.jface.util.Geometry; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.DragUtil; import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.PresentationUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; @@ -39,7 +40,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; -import org.eclipse.ui.internal.dnd.DragUtil; /** * Papyrus wrapper for CTabFolder. @@ -535,7 +535,7 @@ public class PTabFolder { /** * List of event listeners. */ - Set<IPTabFolderListener> listeners = new HashSet<IPTabFolderListener>(); + Set<IPTabFolderListener> listeners = new HashSet<>(); /** * Add a listener diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashPanelPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashPanelPart.java index 30c5a79a527..51c1fa9f751 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashPanelPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashPanelPart.java @@ -19,12 +19,12 @@ package org.eclipse.papyrus.infra.core.sasheditor.internal; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IAbstractPanelModel; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashPanelModel; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.DragUtil; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.internal.dnd.DragUtil; -import org.eclipse.ui.internal.dnd.IDropTarget; /** * Controller for a sash panel. diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java index da0ffc43fc7..84f49e1b370 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java @@ -37,6 +37,9 @@ import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageLifeCycleEventsList import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageVisitor; import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer; import org.eclipse.papyrus.infra.core.sasheditor.editor.ITabMouseEventsListener; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.DragUtil; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDragOverListener; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.papyrus.infra.core.sasheditor.utils.IObservableList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; @@ -49,9 +52,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.internal.DragCursors; -import org.eclipse.ui.internal.dnd.DragUtil; -import org.eclipse.ui.internal.dnd.IDragOverListener; -import org.eclipse.ui.internal.dnd.IDropTarget; /** @@ -82,10 +82,11 @@ public class SashWindowsContainer implements ISashWindowsContainer { /** * Tracker maintaining the history of the active pages. + * * @since 2.0.0 */ private ActivePageHistoryTracker activePageHistoryTracker; - + /** * Event provider firing Pages life cycle events to registered listeners. Inner parts call the fireXxxEvents * when appropriate. @@ -373,35 +374,36 @@ public class SashWindowsContainer implements ISashWindowsContainer { // } /** - * Method to request to change the currently active page. - * The currently active page is changed only if we are not currently synchronizing the tabs + * Method to request to change the currently active page. + * The currently active page is changed only if we are not currently synchronizing the tabs * (currently in a call to {@link #refreshTabsInternal()}. - * + * * This method is called by {@link TabFolderPart#pageChange(int)} when a UI change is detected. * Such UI change can happen: * <ul> - * <li>when a tab is removed. This usually happen inside the call of {@link #refreshTabsInternal()}</li> - * <li>when user select another tab in sashwindows</li> + * <li>when a tab is removed. This usually happen inside the call of {@link #refreshTabsInternal()}</li> + * <li>when user select another tab in sashwindows</li> * </ul> - * + * * If we are currently refreshing the tabs, we do nothing. The cactive page will be set at the end of {@link #refreshTabsInternal()}. - * + * * Otherwise, the page is changed by calling {@link #setActivePage(PagePart)} - * - * @param childPart The new page to set + * + * @param childPart + * The new page to set * @since 2.0.0 */ protected void setActivePageRequest(PagePart newChildPart) { - if( isRefreshing.get() ) { - // The page change comes from a PagePart removing. - // skip + if (isRefreshing.get()) { + // The page change comes from a PagePart removing. + // skip return; - } + } setActivePage(newChildPart); } - + /** * Set the active page. The current active page will be the specified page. Throw events indicating that * the current ActivePage has changed. <br> @@ -602,7 +604,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { } /** - * + * * @see org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer#getNextPage() * * @return @@ -614,7 +616,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { } /** - * + * * @see org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer#getNextPage() * * @return @@ -740,7 +742,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { // Get the currently selected page and folder PagePart oldActivePage = getActivePage(); - TabFolderPart oldActiveFolder = (oldActivePage!=null?oldActivePage.getParent():null); + TabFolderPart oldActiveFolder = (oldActivePage != null ? oldActivePage.getParent() : null); // Do refresh container.setRedraw(false); @@ -763,10 +765,10 @@ public class SashWindowsContainer implements ISashWindowsContainer { // Reenable SWT and force layout container.setRedraw(true); container.layout(true, true); - + // Check focus PagePart activePage = getActivePage(); - if( activePage != null && oldActiveFolder != activePage.getParent() ) { + if (activePage != null && oldActiveFolder != activePage.getParent()) { getActivePage().setFocus(); } // System.out.println("end synchronize2() ------------------------"); @@ -851,20 +853,23 @@ public class SashWindowsContainer implements ISashWindowsContainer { /** * Try to find the page that should now be set as active. - * + * * The next active page is: * <ul> - * <li>if a page has been created, set it as active</li> - * <li>otherwise, if the old active page still alive, set it as active</li> - * <li>otherwise, check if the last active tabfolder still alive, if yes, ask it for the currently selected tab, and set the corresponding page as active. </li> - * <li>If all of the previous fail, get a tabfolder, and set its active tabs as active page</li> + * <li>if a page has been created, set it as active</li> + * <li>otherwise, if the old active page still alive, set it as active</li> + * <li>otherwise, check if the last active tabfolder still alive, if yes, ask it for the currently selected tab, and set the corresponding page as active.</li> + * <li>If all of the previous fail, get a tabfolder, and set its active tabs as active page</li> * </ul> * - * @param oldActivePage The last active page (before refreshing) - * @param oldActiveFolder The last active tabFolder (before refreshing) - * @param partLists Lists of modified Parts + * @param oldActivePage + * The last active page (before refreshing) + * @param oldActiveFolder + * The last active tabFolder (before refreshing) + * @param partLists + * Lists of modified Parts * @return A valid active page or null if none exists. - * + * * @since 2.0.0 */ private PagePart checkAndGetActivePage(PagePart oldActivePage, TabFolderPart oldActiveFolder, PartLists partLists) { @@ -883,18 +888,18 @@ public class SashWindowsContainer implements ISashWindowsContainer { // Old active page nor more exists, and none is created. // Lookup in history - activePage = (PagePart)activePageHistoryTracker.lastActivePage(); + activePage = (PagePart) activePageHistoryTracker.lastActivePage(); if (activePage != null) { // There is a previous active page, use it return activePage; - } - + } + // No previous active page were found, try from tabfolder - if(oldActiveFolder==null || oldActiveFolder.isOrphaned() || oldActiveFolder.isUnchecked() ) { - // Last active folder is disabled. Search for a new active folder + if (oldActiveFolder == null || oldActiveFolder.isOrphaned() || oldActiveFolder.isUnchecked()) { + // Last active folder is disabled. Search for a new active folder oldActiveFolder = lookupFirstValidFolder(); } - + // Get an active page if any return oldActiveFolder.getVisiblePagePart(); } @@ -957,7 +962,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { * Visit the Part associated to the container. This method visibility is protected in order to be able to access it * from junit tests. * It is not intended to be used by public API or from outside. - * + * * @noreference This method is not intended to be referenced by clients. */ public void visit(IPartVisitor visitor) { @@ -1334,7 +1339,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { */ private class CollectVisiblePageVisitor extends PartVisitor { - private List<IPage> visiblePages = new ArrayList<IPage>(); + private List<IPage> visiblePages = new ArrayList<>(); private Class<? extends IPage> expectedClass; @@ -1396,7 +1401,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { */ private class CollectNextPageVisitor extends PartVisitor { - private List<IPage> nextPages = new ArrayList<IPage>(); + private List<IPage> nextPages = new ArrayList<>(); private final boolean isPrevious; @@ -1460,7 +1465,7 @@ public class SashWindowsContainer implements ISashWindowsContainer { */ private class AbstractCollectIEditorPart extends PartVisitor { - protected List<IEditorPart> editorParts = new ArrayList<IEditorPart>(); + protected List<IEditorPart> editorParts = new ArrayList<>(); /** * Constructor. diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/TabFolderPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/TabFolderPart.java index c42e9eddc5c..95f01aa50cb 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/TabFolderPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/TabFolderPart.java @@ -28,6 +28,9 @@ import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel import org.eclipse.papyrus.infra.core.sasheditor.editor.ICloseablePart; import org.eclipse.papyrus.infra.core.sasheditor.editor.IFolder; import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.AbstractTabFolderPart; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.DragUtil; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDragOverListener; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IDropTarget; import org.eclipse.papyrus.infra.tools.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; @@ -48,9 +51,6 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.internal.DragCursors; -import org.eclipse.ui.internal.dnd.DragUtil; -import org.eclipse.ui.internal.dnd.IDragOverListener; -import org.eclipse.ui.internal.dnd.IDropTarget; /** * Controller associated to a tabfolder. @@ -905,7 +905,7 @@ public class TabFolderPart extends AbstractTabFolderPart implements IFolder { } } else if (index < currentTabItems.size()) { // There is too much tabs, remove them - List<TabItemPart> toRemove = new ArrayList<TabItemPart>(); + List<TabItemPart> toRemove = new ArrayList<>(); // Collect tab to be removed for (int i = index; i < currentTabItems.size(); i++) { TabItemPart curTab = currentTabItems.get(i); diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/AbstractDropTarget.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/AbstractDropTarget.java new file mode 100755 index 00000000000..5b5157bb7f1 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/AbstractDropTarget.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Rectangle; + +/** + */ +public abstract class AbstractDropTarget implements IDropTarget { + @Override + public abstract void drop(); + + @Override + public abstract Cursor getCursor(); + + @Override + public Rectangle getSnapRectangle() { + return null; + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/CompatibilityDragTarget.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/CompatibilityDragTarget.java new file mode 100755 index 00000000000..0d2001062a2 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/CompatibilityDragTarget.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2004, 2017 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.jface.util.Geometry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; + +/** + * Compatibility layer for the old-style drag-and-drop. Adapts an old-style + * IPartDropListener into an IDragTarget. + * + */ +public class CompatibilityDragTarget { + + // Define width of part's "hot" border + private static final int MARGIN = 30; + + /** + * Returns the relative position of the given point (in display coordinates) + * with respect to the given control. Returns one of SWT.LEFT, SWT.RIGHT, SWT.CENTER, SWT.TOP, + * or SWT.BOTTOM if the point is on the control or SWT.DEFAULT if the point is not on the control. + * + * @param control + * control to perform hit detection on + * @param toTest + * point to test, in display coordinates + * @return + */ + public static int getRelativePosition(Control c, Point toTest) { + Point p = c.toControl(toTest); + Point e = c.getSize(); + + if (p.x > e.x || p.y > e.y || p.x < 0 || p.y < 0) { + return SWT.DEFAULT; + } + + // first determine whether mouse position is in center of part + int hmargin = Math.min(e.x / 3, MARGIN); + int vmargin = Math.min(e.y / 3, MARGIN); + + Rectangle inner = new Rectangle(hmargin, vmargin, e.x - (hmargin * 2), + e.y - (vmargin * 2)); + if (inner.contains(p)) { + return SWT.CENTER; + } + return Geometry.getClosestSide(inner, p); + } + +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragBorder.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragBorder.java new file mode 100755 index 00000000000..9640a2ab730 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragBorder.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2005, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.jface.util.Geometry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.themes.ColorUtil; + +/** + * Utility class that wraps a given control with a black 'border'. Moving the + * border control will cause the given control to move to stay within its bounds. + * + * @since 3.2 + * + */ +public class DragBorder { + // Controls + private Composite clientControl = null; + private Control dragControl = null; + private Canvas border = null; + + // Colors + private Color baseColor; + private Color hilightColor; + private boolean isHighlight; + + /** + * Construct a new DragBorder. + * + * @param client + * The client window that the border must stay within + * @param toDrag + * The control to be placed 'inside' the border + */ + public DragBorder(Composite client, Control toDrag, boolean provideFrame) { + clientControl = client; + dragControl = toDrag; + Point dragSize = toDrag.getSize(); + + // Create a control large enough to 'contain' the dragged control + border = new Canvas(dragControl.getParent(), SWT.NONE); + border.setSize(dragSize.x + 2, dragSize.y + 2); + + // Use the SWT 'title' colors since they should always have a proper contrast + // and are 'related' (i.e. should look good together) + baseColor = border.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); + RGB background = border.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB(); + RGB blended = ColorUtil.blend(baseColor.getRGB(), background); + hilightColor = new Color(border.getDisplay(), blended); + + // Ensure the border is visible and the control is 'above' it... + border.moveAbove(null); + dragControl.moveAbove(null); + + if (provideFrame) { + border.addPaintListener(e -> { + if (isHighlight) { + e.gc.setForeground(hilightColor); + } else { + e.gc.setForeground(baseColor); + } + + // Draw a rectangle as our 'border' + Rectangle bb = border.getBounds(); + e.gc.drawRectangle(0, 0, bb.width - 1, bb.height - 1); + }); + } + } + + + /** + * Move the border (and its 'contained' control to a new position. The new + * position will be adjusted to lie entirely within the client area of the + * <code>clientControl</code>. + * + * @param newPos + * The new position for the border + * @param alignment + * The location of the cursor relative to the border being dragged. + * Current implementation only recognizes SWT.TOP & SWT.BOTTOM (which implies SWT.LEFT) + * and SWT.CENTER (which centers teh dragged border on the cursor. + */ + public void setLocation(Point newPos, int alignment) { + // Move the border but ensure that it is still inside the Client area + if (alignment == SWT.CENTER) { + Point size = border.getSize(); + border.setLocation(newPos.x - (size.x / 2), newPos.y - (size.y / 2)); + } else if (alignment == SWT.TOP) { + border.setLocation(newPos.x, newPos.y); + } else { + border.setLocation(newPos.x, newPos.y - border.getSize().y); + } + + // Force the control to remain inside the shell + Rectangle bb = border.getBounds(); + Rectangle cr = clientControl.getClientArea(); + Geometry.moveInside(bb, cr); + + // Ensure that the controls are the 'topmost' controls + border.moveAbove(null); + dragControl.moveAbove(null); + + // OK, now move the drag control and the border to their new locations + dragControl.setLocation(bb.x + 1, bb.y + 1); + border.setBounds(bb); + } + + /** + * Sets the hilight 'mode' for the control. + * + * @param highlight + * true if the border should be drawn as 'hilighted' + */ + public void setHighlight(boolean highlight) { + isHighlight = highlight; + border.redraw(); + } + + /** + * Dispose the controls owned by the border. + */ + public void dispose() { + hilightColor.dispose(); + border.dispose(); + } + + + /** + * @return The bounds of the border's control. + */ + public Rectangle getBounds() { + return border.getBounds(); + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragUtil.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragUtil.java new file mode 100755 index 00000000000..68c01d478f4 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/DragUtil.java @@ -0,0 +1,417 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.util.Geometry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tracker; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.DragCursors; + +/** + * Provides the methods for attaching drag-and-drop listeners to SWT controls. + */ +public class DragUtil { + private static final String DROP_TARGET_ID = "org.eclipse.ui.internal.dnd.dropTarget"; //$NON-NLS-1$ + + /** + * The location where all drags will end. If this is non-null, then + * all user input is ignored in drag/drop. If null, we use user input + * to determine where objects should be dropped. + */ + private static TestDropLocation forcedDropTarget = null; + + /** + * List of IDragOverListener + */ + private static List defaultTargets = new ArrayList(); + + /** + * Sets the drop target for the given control. It is possible to add one or more + * targets for a "null" control. This becomes a default target that is used if no + * other targets are found (for example, when dragging objects off the application + * window). + * + * @param control + * the control that should be treated as a drag target, or null + * to indicate the default target + * @param target + * the drag target to handle the given control + */ + public static void addDragTarget(Control control, IDragOverListener target) { + if (control == null) { + defaultTargets.add(target); + } else { + List targetList = getTargetList(control); + + if (targetList == null) { + targetList = new ArrayList(1); + } + targetList.add(target); + control.setData(DROP_TARGET_ID, targetList); + } + } + + /** + * Return the list of 'IDragOverListener' elements associated with + * the given control. If there's a 'global' listener then always + * return it. + * + * @param control + * @return + */ + private static List getTargetList(Control control) { + List result = (List) control.getData(DROP_TARGET_ID); + return result; + } + + /** + * Removes a drop target from the given control. + * + * @param control + * @param target + */ + public static void removeDragTarget(Control control, + IDragOverListener target) { + if (control == null) { + defaultTargets.remove(target); + } else { + List targetList = getTargetList(control); + if (targetList != null) { + targetList.remove(target); + if (targetList.isEmpty()) { + control.setData(DROP_TARGET_ID, null); + } + } + } + } + + /** + * Shorthand method. Returns the bounding rectangle for the given control, in + * display coordinates. Note that all 'Shell' controls are expected to be 'top level' + * so DO NOT do the origin offset for them. + * + * @param draggedItem + * @param boundsControl + * @return + */ + public static Rectangle getDisplayBounds(Control boundsControl) { + Control parent = boundsControl.getParent(); + if (parent == null || boundsControl instanceof Shell) { + return boundsControl.getBounds(); + } + + return Geometry.toDisplay(parent, boundsControl.getBounds()); + } + + public static boolean performDrag(final Object draggedItem, + Rectangle sourceBounds, Point initialLocation, boolean allowSnapping) { + + IDropTarget target = dragToTarget(draggedItem, sourceBounds, + initialLocation, allowSnapping); + + if (target == null) { + return false; + } + + target.drop(); + + // If the target can handle a 'finished' notification then send one + if (target instanceof IDropTarget2) { + ((IDropTarget2) target).dragFinished(true); + } + + return true; + } + + /** + * Drags the given item to the given location (in display coordinates). This + * method is intended for use by test suites. + * + * @param draggedItem + * object being dragged + * @param finalLocation + * location being dragged to + * @return true iff the drop was accepted + */ + public static boolean dragTo(Display display, Object draggedItem, + Point finalLocation, Rectangle dragRectangle) { + Control currentControl = SwtUtil.findControl(display, finalLocation); + + IDropTarget target = getDropTarget(currentControl, draggedItem, + finalLocation, dragRectangle); + + if (target == null) { + return false; + } + + target.drop(); + + return true; + } + + /** + * Forces all drags to end at the given position (display coordinates). Intended + * for use by test suites. If this method is called, then all subsequent calls + * to performDrag will terminate immediately and behave as though the object were + * dragged to the given location. Calling this method with null cancels this + * behavior and causes performDrag to behave normally. + * + * @param forcedLocation + * location where objects will be dropped (or null to + * cause drag/drop to behave normally). + */ + public static void forceDropLocation(TestDropLocation forcedLocation) { + forcedDropTarget = forcedLocation; + } + + /** + * Drags the given item, given an initial bounding rectangle in display coordinates. + * Due to a quirk in the Tracker class, changing the tracking rectangle when using the + * keyboard will also cause the mouse cursor to move. Since "snapping" causes the tracking + * rectangle to change based on the position of the mouse cursor, it is impossible to do + * drag-and-drop with the keyboard when snapping is enabled. + * + * @param draggedItem + * object being dragged + * @param sourceBounds + * initial bounding rectangle for the dragged item + * @param initialLocation + * initial position of the mouse cursor + * @param allowSnapping + * true iff the rectangle should snap to the drop location. This must + * be false if the user might be doing drag-and-drop using the keyboard. + * + * @return + */ + static IDropTarget dragToTarget(final Object draggedItem, + final Rectangle sourceBounds, final Point initialLocation, + final boolean allowSnapping) { + final Display display = Display.getCurrent(); + + // Testing...immediately 'drop' onto the test target + if (forcedDropTarget != null) { + Point location = forcedDropTarget.getLocation(); + + Control currentControl = SwtUtil.findControl(forcedDropTarget.getShells(), location); + return getDropTarget(currentControl, draggedItem, location, + sourceBounds); + } + + // Create a tracker. This is just an XOR rect on the screen. + // As it moves we notify the drag listeners. + final Tracker tracker = new Tracker(display, SWT.NULL); + tracker.setStippled(true); + + tracker.addListener(SWT.Move, event -> display.syncExec(() -> { + // Get the curslor location as a point + Point location = new Point(event.x, event.y); + + // Select a drop target; use the global one by default + IDropTarget target = null; + + Control targetControl = display.getCursorControl(); + + // Get the drop target for this location + target = getDropTarget(targetControl, + draggedItem, location, + tracker.getRectangles()[0]); + + // Set up the tracker feedback based on the target + Rectangle snapTarget = null; + if (target != null) { + snapTarget = target.getSnapRectangle(); + + tracker.setCursor(target.getCursor()); + } else { + tracker.setCursor(DragCursors + .getCursor(DragCursors.INVALID)); + } + + // If snapping then reset the tracker's rectangle based on the current drop target + if (allowSnapping) { + if (snapTarget == null) { + snapTarget = new Rectangle(sourceBounds.x + + location.x - initialLocation.x, + sourceBounds.y + location.y + - initialLocation.y, + sourceBounds.width, sourceBounds.height); + } + + // Try to prevent flicker: don't change the rectangles if they're already in + // the right location + Rectangle[] currentRectangles = tracker.getRectangles(); + + if (!(currentRectangles.length == 1 && currentRectangles[0] + .equals(snapTarget))) { + tracker.setRectangles(new Rectangle[] { Geometry.copy(snapTarget) }); + } + } + })); + + // Setup...when the drag starts we might already be over a valid target, check this... + // If there is a 'global' target then skip the check + IDropTarget target = null; + Control startControl = display.getCursorControl(); + + if (startControl != null && allowSnapping) { + target = getDropTarget(startControl, + draggedItem, initialLocation, + sourceBounds); + } + + // Set up an initial tracker rectangle + Rectangle startRect = sourceBounds; + if (target != null) { + Rectangle rect = target.getSnapRectangle(); + + if (rect != null) { + startRect = rect; + } + + tracker.setCursor(target.getCursor()); + } + + if (startRect != null) { + tracker.setRectangles(new Rectangle[] { Geometry.copy(startRect) }); + } + + // Tracking Loop...tracking is preformed on the 'SWT.Move' listener registered + // against the tracker. + + // HACK: + // Some control needs to capture the mouse during the drag or other + // controls will interfere with the cursor + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + if (shell != null) { + shell.setCapture(true); + } + + // Run tracker until mouse up occurs or escape key pressed. + boolean trackingOk = tracker.open(); + + // HACK: + // Release the mouse now + if (shell != null) { + shell.setCapture(false); + } + + // Done tracking... + + // Get the current drop target + IDropTarget dropTarget = null; + Point finalLocation = display.getCursorLocation(); + Control targetControl = display.getCursorControl(); + dropTarget = getDropTarget(targetControl, draggedItem, + finalLocation, tracker.getRectangles()[0]); + + // Cleanup... + tracker.dispose(); + + // if we're going to perform a 'drop' then delay the issuing of the 'finished' + // callback until after it's done... + if (trackingOk) { + return dropTarget; + } else if (dropTarget != null && dropTarget instanceof IDropTarget2) { + // If the target can handle a 'finished' notification then send one + ((IDropTarget2) dropTarget).dragFinished(false); + } + + return null; + } + + /** + * Given a list of IDragOverListeners and a description of what is being dragged, it returns + * a IDropTarget for the current drop. + * + * @param toSearch + * @param mostSpecificControl + * @param draggedObject + * @param position + * @param dragRectangle + * @return + */ + private static IDropTarget getDropTarget(List toSearch, + Control mostSpecificControl, Object draggedObject, Point position, + Rectangle dragRectangle) { + if (toSearch == null) { + return null; + } + + Iterator iter = toSearch.iterator(); + while (iter.hasNext()) { + IDragOverListener next = (IDragOverListener) iter.next(); + + IDropTarget dropTarget = next.drag(mostSpecificControl, + draggedObject, position, dragRectangle); + + if (dropTarget != null) { + return dropTarget; + } + } + + return null; + } + + /** + * Returns the drag target for the given control or null if none. + * + * @param toSearch + * @param e + * @return + */ + public static IDropTarget getDropTarget(Control toSearch, + Object draggedObject, Point position, Rectangle dragRectangle) { + // Search for a listener by walking the control's parent hierarchy + for (Control current = toSearch; current != null; current = current + .getParent()) { + IDropTarget dropTarget = getDropTarget(getTargetList(current), + toSearch, draggedObject, position, dragRectangle); + + if (dropTarget != null) { + return dropTarget; + } + + // Don't look to parent shells for drop targets + if (current instanceof Shell) { + break; + } + } + + // No controls could handle this event -- check for default targets + return getDropTarget(defaultTargets, toSearch, draggedObject, position, + dragRectangle); + } + + /** + * Returns the location of the given event, in display coordinates + * + * @return + */ + public static Point getEventLoc(Event event) { + Control ctrl = (Control) event.widget; + return ctrl.toDisplay(new Point(event.x, event.y)); + } + +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDragOverListener.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDragOverListener.java new file mode 100755 index 00000000000..8d1a162182c --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDragOverListener.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; + +/** + * Implementers of this interface will receive notifications when objects are dragged over + * a particular SWT control. + */ +public interface IDragOverListener { + + /** + * Notifies the receiver that the given object has been dragged over + * the given position. Returns a drop target if the object may be + * dropped in this position. Returns null otherwise. + * + * @param draggedObject + * object being dragged over this location + * @param position + * location of the cursor + * @param dragRectangle + * current drag rectangle (may be an empty rectangle if none) + * @return a valid drop target or null if none + */ + IDropTarget drag(Control currentControl, Object draggedObject, + Point position, Rectangle dragRectangle); +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget.java new file mode 100755 index 00000000000..8c38ea939bd --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Rectangle; + +/** + * This interface is used to drop objects. It knows how to drop a particular object + * in a particular location. IDropTargets are typically created by IDragOverListeners, and + * it is the job of the IDragOverListener to supply the drop target with information about + * the object currently being dragged. + * + * @see org.eclipse.ui.internal.dnd.IDragOverListener + */ +public interface IDropTarget { + + /** + * Drops the object in this position + */ + void drop(); + + /** + * Returns a cursor describing this drop operation + * + * @return a cursor describing this drop operation + */ + Cursor getCursor(); + + /** + * Returns a rectangle (screen coordinates) describing the target location + * for this drop operation. + * + * @return a snap rectangle or null if this drop target does not have a specific snap + * location. + */ + Rectangle getSnapRectangle(); +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget2.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget2.java new file mode 100755 index 00000000000..7af99910c8d --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/IDropTarget2.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +/** + * This interface allows a particular drop target to be informed that + * the drag operation was cancelled. This allows the target to clean + * up any extended drag feedback. + * + * @since 3.2 + * + */ +public interface IDropTarget2 extends IDropTarget { + /** + * This is called whenever a drag operation is cancelled + */ + void dragFinished(boolean dropPerformed); +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/InsertCaret.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/InsertCaret.java new file mode 100755 index 00000000000..7ac821ce3b2 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/InsertCaret.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2005, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.themes.ColorUtil; + +/** + * This class provides 'insertion' feedback to the User. It can be used to draw a + * 'bracket' based on the trim area's rectangle. + * + * @since 3.2 + */ +public class InsertCaret { + // Constants + private static final int width = 6; // the handle's 'thickness' + private static final int pctInset = 10; // The percentage of the area left at each 'end' + + // Control info + private Canvas caretControl; + private Canvas end1; + private Canvas end2; + + // Colors + private Color baseColor; + private Color hilightColor; + private boolean isHighlight; + + /** + * Creates an affordance to indicate that the given trim area is a valid location for the + * trim being dragged. + * + * @param windowComposite + * The window to create the affordance as a child of + * @param trimRect + * The rectangle to show the affordance for + * @param swtSide + * The 'side' that the rectangle is on + * @param threshold + * The amount to offfset the affordance by + */ + public InsertCaret(Composite parent, Rectangle trimRect, int swtSide, int threshold) { + // Use the SWT 'title' colors since they should always have a proper contrast + // and are 'related' (i.e. should look good together) + baseColor = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); + RGB background = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB(); + RGB blended = ColorUtil.blend(baseColor.getRGB(), background); + hilightColor = new Color(parent.getDisplay(), blended); + + // Create the caret control + createControl(parent, trimRect, swtSide, threshold); + } + + /** + * Creates a control to show the 'area valid' affordance. The current implementation creates a + * simple rect half the length of the rect, centered and offset by the 'threshold' value. + * + * @param parent + * The control to used as the parent of the affordance control + * @param trimRect + * The trim rectangle + * @param swtSide + * The SWT side that the trim is on + * @param threshold + * The offset value + */ + private void createControl(Composite parent, Rectangle trimRect, int swtSide, int threshold) { + int hDelta = trimRect.width / pctInset; + int vDelta = trimRect.height / pctInset; + caretControl = new Canvas(parent.getShell(), SWT.BORDER); + + end1 = new Canvas(parent.getShell(), SWT.BORDER); + end1.setSize(width, width); + end2 = new Canvas(parent.getShell(), SWT.BORDER); + end2.setSize(width, width); + + Rectangle bb; + switch (swtSide) { + case SWT.TOP: + caretControl.setSize(trimRect.width - (2 * hDelta), width); + caretControl.setLocation(trimRect.x + hDelta, trimRect.y + trimRect.height + threshold); + bb = caretControl.getBounds(); + end1.setLocation(bb.x, bb.y - width); + end2.setLocation((bb.x + bb.width) - width, bb.y - width); + break; + case SWT.BOTTOM: + caretControl.setSize(trimRect.width - (2 * hDelta), width); + caretControl.setLocation(trimRect.x + hDelta, trimRect.y - threshold); + bb = caretControl.getBounds(); + end1.setLocation(bb.x, bb.y + width); + end2.setLocation((bb.x + bb.width) - width, bb.y + width); + break; + case SWT.LEFT: + caretControl.setSize(width, trimRect.height - (2 * vDelta)); + caretControl.setLocation(trimRect.x + trimRect.width + threshold, + trimRect.y + vDelta); + bb = caretControl.getBounds(); + end1.setLocation(bb.x - bb.width, bb.y); + end2.setLocation(bb.x - bb.width, (bb.y + bb.height) - width); + break; + case SWT.RIGHT: + caretControl.setSize(width, trimRect.height - (2 * vDelta)); + caretControl.setLocation(trimRect.x - threshold, + trimRect.y + vDelta); + bb = caretControl.getBounds(); + end1.setLocation(bb.x + bb.width, bb.y); + end2.setLocation(bb.x + bb.width, (bb.y + bb.height) - width); + break; + } + + // Initially create as not hilighted + setHighlight(false); + caretControl.moveAbove(null); + end1.moveAbove(null); + end2.moveAbove(null); + } + + /** + * Sets the hilight 'mode' for the control. + * + * @param highlight + * true if the caret should be drawn as 'hilighted' + */ + public void setHighlight(boolean highlight) { + isHighlight = highlight; + + // if we're displaying as a 'bar' then set the control's background to the + // appropriate value + if (isHighlight) { + caretControl.setBackground(hilightColor); + end1.setBackground(hilightColor); + end2.setBackground(hilightColor); + } else { + caretControl.setBackground(baseColor); + end1.setBackground(baseColor); + end2.setBackground(baseColor); + } + } + + public void dispose() { + // Dispose the control's resources (we don't have to dispose the + // 'bacseColor' because it's a system color + hilightColor.dispose(); + + caretControl.dispose(); + end1.dispose(); + end2.dispose(); + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/PresentationUtil.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/PresentationUtil.java index dec52a1c007..bcb7ec27c9a 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/PresentationUtil.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/PresentationUtil.java @@ -18,7 +18,6 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; -import org.eclipse.ui.internal.dnd.DragUtil; /** * FIXME : duplicate class from org.eclipse.ui.presentations. This class doesn't exist in Juno... diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/SwtUtil.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/SwtUtil.java new file mode 100755 index 00000000000..86dc802bd67 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/SwtUtil.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Monitor; +import org.eclipse.swt.widgets.Shell; + +/** + * Contains static methods for manipulating SWT controls + * + * @since 3.0 + */ +public class SwtUtil { + + private SwtUtil() { + + } + + /** + * Returns true if the given control is null or has been disposed + * + * @param toTest + * the control to test + * @return false if it is safe to invoke methods on the given control + */ + public static boolean isDisposed(Control toTest) { + return toTest == null || toTest.isDisposed(); + } + + /** + * Returns the control that is covering the given control, or null if none. + * + * @param toTest + * control to test + * @return a control that obscures the test control or null if none + */ + public static Control controlThatCovers(Control toTest) { + return controlThatCovers(toTest, DragUtil.getDisplayBounds(toTest)); + } + + private static Control controlThatCovers(Control toTest, Rectangle testRegion) { + Composite parent = toTest.getParent(); + + if (parent == null || toTest instanceof Shell) { + return null; + } + + for (Control element : parent.getChildren()) { + Control control = element; + + if (control == toTest) { + break; + } + + if (!control.isVisible()) { + continue; + } + + Rectangle nextBounds = DragUtil.getDisplayBounds(control); + + if (nextBounds.intersects(testRegion)) { + return control; + } + } + + return controlThatCovers(parent, testRegion); + } + + /** + * Determines if one control is a child of another. + * + * @param potentialParent + * @param childToTest + * @return <code>true</code> if the second argument is a child of the first + * or the same object, <code>false</code> otherwise + */ + public static boolean isChild(Control potentialParent, Control childToTest) { + if (childToTest == null) { + return false; + } + + if (childToTest == potentialParent) { + return true; + } + + return isChild(potentialParent, childToTest.getParent()); + } + + public static boolean isFocusAncestor(Control potentialParent) { + if (potentialParent == null) { + return false; + } + Control focusControl = Display.getCurrent().getFocusControl(); + if (focusControl == null) { + return false; + } + return isChild(potentialParent, focusControl); + } + + /** + * Finds and returns the most specific SWT control at the given location. + * (Note: this does a DFS on the SWT widget hierarchy, which is slow). + * + * @param displayToSearch + * @param locationToFind + * @return the most specific SWT control at the given location + */ + public static Control findControl(Display displayToSearch, + Point locationToFind) { + Shell[] shells = displayToSearch.getShells(); + + return findControl(shells, locationToFind); + } + + /** + * Searches the given list of controls for a control containing the given point. + * If the array contains any composites, those composites will be recursively + * searched to find the most specific child that contains the point. + * + * @param toSearch + * an array of composites + * @param locationToFind + * a point (in display coordinates) + * @return the most specific Control that overlaps the given point, or null if none + */ + public static Control findControl(Control[] toSearch, Point locationToFind) { + for (int idx = toSearch.length - 1; idx >= 0; idx--) { + Control next = toSearch[idx]; + + if (!next.isDisposed() && next.isVisible()) { + + Rectangle bounds = DragUtil.getDisplayBounds(next); + + if (bounds.contains(locationToFind)) { + if (next instanceof Composite) { + Control result = findControl((Composite) next, + locationToFind); + + if (result != null) { + return result; + } + } + + return next; + } + } + } + + return null; + } + + public static Control[] getAncestors(Control theControl) { + return getAncestors(theControl, 1); + } + + private static Control[] getAncestors(Control theControl, int children) { + Control[] result; + + if (theControl.getParent() == null) { + result = new Control[children]; + } else { + result = getAncestors(theControl.getParent(), children + 1); + } + + result[result.length - children] = theControl; + + return result; + } + + public static Control findCommonAncestor(Control control1, Control control2) { + Control[] control1Ancestors = getAncestors(control1); + Control[] control2Ancestors = getAncestors(control2); + + Control mostSpecific = null; + + for (int idx = 0; idx < Math.min(control1Ancestors.length, control2Ancestors.length); idx++) { + Control control1Ancestor = control1Ancestors[idx]; + if (control1Ancestor == control2Ancestors[idx]) { + mostSpecific = control1Ancestor; + } else { + break; + } + } + + return mostSpecific; + } + + /** + * Finds the control at the given location. + * + * @param toSearch + * @param locationToFind + * location (in display coordinates) + * @return the control at the given location + */ + public static Control findControl(Composite toSearch, Point locationToFind) { + Control[] children = toSearch.getChildren(); + + return findControl(children, locationToFind); + } + + /** + * + * Returns true iff the given rectangle is located in the client area of any + * monitor. + * + * @param display + * the display + * @param someRectangle + * a rectangle in display coordinates (not null) + * @return true iff the given point can be seen on any monitor + */ + public static boolean intersectsAnyMonitor(Display display, + Rectangle someRectangle) { + for (Monitor monitor : display.getMonitors()) { + if (monitor.getClientArea().intersects(someRectangle)) { + return true; + } + } + + return false; + } + +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/TestDropLocation.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/TestDropLocation.java new file mode 100755 index 00000000000..d8230b46f50 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/eclipsecopy/TestDropLocation.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +/** + * This is an interface intended for use in test suites. Objects can implement + * this interface to force any dragged object to be dropped at a particular + * location. + * + * @since 3.0 + */ +public interface TestDropLocation { + + /** + * Location where the object should be dropped, in display coordinates + * + * @return a location in display coordinates + */ + Point getLocation(); + + /** + * The drop code will pretend that only the given shells are open, + * and that they have the specified Z-order. + * + * @return the shells to check for drop targets, from bottom to top. + */ + Shell[] getShells(); +} |