diff options
| author | Patrik Suzzi | 2016-07-07 18:50:03 +0000 |
|---|---|---|
| committer | Patrik Suzzi | 2016-08-08 22:19:43 +0000 |
| commit | 00f6ec8ccbd5d17a1ddcc7015813487e643ce95f (patch) | |
| tree | bdc5d2f424ed7585f13b4212e4822ed131bd338e | |
| parent | 1b93472b81701d38ca2ddd374272f7d928c28eb8 (diff) | |
| download | eclipse.platform.ui-00f6ec8ccbd5d17a1ddcc7015813487e643ce95f.tar.gz eclipse.platform.ui-00f6ec8ccbd5d17a1ddcc7015813487e643ce95f.tar.xz eclipse.platform.ui-00f6ec8ccbd5d17a1ddcc7015813487e643ce95f.zip | |
Bug 497348 - Drag and drop of overflown editor tabs is broken I20160809-1100
Fixed D&D behavior when dropping a CTabItem in a stack with hidden tabs
Change-Id: Ic96c762d347e5ec979385f411dd24601239d0027
Signed-off-by: Patrik Suzzi <psuzzi@gmail.com>
| -rw-r--r-- | bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java | 146 |
1 files changed, 103 insertions, 43 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java index c30c5710769..f1a84310c52 100644 --- a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java +++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/StackDropAgent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2015 IBM Corporation and others. + * Copyright (c) 2010, 2016 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 @@ -7,12 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Patrik Suzzi <psuzzi@gmail.com> - Bug 497348 ******************************************************************************/ package org.eclipse.e4.ui.workbench.addons.dndaddon; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; @@ -28,16 +31,13 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; /** - * + * This agent manage drag and drop when dragging a Tab in Eclipse Part Stacks. */ public class StackDropAgent extends DropAgent { private Rectangle tabArea; private MPartStack dropStack; private CTabFolder dropCTF; - private ArrayList<Rectangle> itemRects; - private int curDropIndex = -2; - /** * @param manager */ @@ -85,7 +85,6 @@ public class StackDropAgent extends DropAgent { tabArea = areaRect; dropStack = (MPartStack) info.curElement; dropCTF = (CTabFolder) dropStack.getWidget(); - createInsertRects(); } return inArea; } @@ -98,13 +97,37 @@ public class StackDropAgent extends DropAgent { return displayBounds; } - private void createInsertRects() { - itemRects = new ArrayList<Rectangle>(); - if (dropCTF.getItems().length > 0) { - CTabItem[] items = dropCTF.getItems(); + /** + * Static helper to get visible items without using member variables in this + * stateful Agent. + * + * @param dropCTF + * @return + */ + private static List<CTabItem> getVisibleItems(CTabFolder dropCTF) { + return Stream.of(dropCTF.getItems()) + .filter(i -> i.isShowing()) + .collect(Collectors.toList()); + } + /** + * Static helper to compute the visual rectangles to drop, without using + * member variables in this stateful Agent. + * + * @param dropCTF + * @param visibleItems + * @param tabArea + * @return + */ + private static ArrayList<Rectangle> getItemRects(CTabFolder dropCTF, List<CTabItem> visibleItems, + Rectangle tabArea) { + // for dropping, we consider visible tab only + ArrayList<Rectangle> itemRects = new ArrayList<Rectangle>(); + CTabItem item; + if (visibleItems.size() > 0) { // First rect is from left to the center of the item - Rectangle itemRect = items[0].getBounds(); + item = visibleItems.get(0); + Rectangle itemRect = item.getBounds(); int centerX = itemRect.x + (itemRect.width / 2); itemRect.width /= 2; int curX = itemRect.x + itemRect.width; @@ -112,8 +135,9 @@ public class StackDropAgent extends DropAgent { itemRects.add(insertRect); // Process the other items - for (int i = 1; i < items.length; i++) { - itemRect = items[i].getBounds(); + for (int i = 1; i < visibleItems.size(); i++) { + item = visibleItems.get(i); + itemRect = item.getBounds(); centerX = itemRect.x + (itemRect.width / 2); itemRect.width = centerX - curX; itemRect.x = curX; @@ -121,8 +145,8 @@ public class StackDropAgent extends DropAgent { insertRect = dropCTF.getDisplay().map(dropCTF, null, itemRect); itemRects.add(insertRect); } - - // Finally, add a rectangle from the center of the last element to the end + // Finally, add rectangle from the center of the last element + // to the end itemRect.x = curX; itemRect.width = dropCTF.getBounds().width - curX; insertRect = dropCTF.getDisplay().map(dropCTF, null, itemRect); @@ -131,15 +155,24 @@ public class StackDropAgent extends DropAgent { // Empty stack, whole area is index == 0 itemRects.add(tabArea); } + // + return itemRects; + } + + private ArrayList<Rectangle> computeInsertRects() { + List<CTabItem> visibleItems = getVisibleItems(dropCTF); + return getItemRects(dropCTF, visibleItems, tabArea); } private int getDropIndex(DnDInfo info) { + ArrayList<Rectangle> itemRects = computeInsertRects(); if (itemRects == null) return -1; for (Rectangle itemRect : itemRects) { - if (itemRect.contains(info.cursorPos)) + if (itemRect.contains(info.cursorPos)) { return itemRects.indexOf(itemRect); + } } return -1; } @@ -156,38 +189,40 @@ public class StackDropAgent extends DropAgent { } tabArea = null; - curDropIndex = -2; super.dragLeave(dragElement, info); } + /** + * Tracks movements of mouse on the Stack where the user is dropping the element + */ @Override public boolean track(MUIElement dragElement, DnDInfo info) { if (!tabArea.contains(info.cursorPos) || dropStack == null || !dropStack.isToBeRendered()) return false; int dropIndex = getDropIndex(info); - if (curDropIndex == dropIndex || dropIndex == -1) + if (dropIndex == -1) return true; - curDropIndex = dropIndex; dndManager.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_HAND)); - if (dropStack.getChildren().indexOf(dragElement) == dropIndex) + if (dropStack.getChildren().indexOf(dragElement) == dropIndex){ return true; - + } if (dndManager.getFeedbackStyle() == DnDManager.HOSTED) { dock(dragElement, dropIndex); Display.getCurrent().update(); showFrame(dragElement); } else { - if (dropIndex < dropCTF.getItemCount()) { - Rectangle itemBounds = dropCTF.getItem(dropIndex).getBounds(); + List<CTabItem> visibleItems = getVisibleItems(dropCTF); + if (dropIndex < visibleItems.size()) { + Rectangle itemBounds = visibleItems.get(dropIndex).getBounds(); itemBounds.width = 2; itemBounds = Display.getCurrent().map(dropCTF, null, itemBounds); dndManager.frameRect(itemBounds); - } else if (dropCTF.getItemCount() > 0) { - Rectangle itemBounds = dropCTF.getItem(dropIndex - 1).getBounds(); + } else if (visibleItems.size() > 0) { + Rectangle itemBounds = visibleItems.get(dropIndex - 1).getBounds(); itemBounds.x = itemBounds.x + itemBounds.width; itemBounds.width = 2; itemBounds = Display.getCurrent().map(dropCTF, null, itemBounds); @@ -197,7 +232,6 @@ public class StackDropAgent extends DropAgent { fr.width = 2; dndManager.frameRect(fr); } - if (dndManager.getFeedbackStyle() == DnDManager.GHOSTED) { Rectangle ca = dropCTF.getClientArea(); ca = Display.getCurrent().map(dropCTF, null, ca); @@ -213,6 +247,10 @@ public class StackDropAgent extends DropAgent { * @param dropIndex */ private void dock(MUIElement dragElement, int dropIndex) { + + List<CTabItem> vItems = getVisibleItems(dropCTF); + boolean hiddenTabs = (vItems.size() < dropCTF.getChildren().length); + // Adjust the index if necessary int elementIndex = dropStack.getChildren().indexOf(dragElement); if (elementIndex != -1 && !(dragElement instanceof MPartStack)) { @@ -229,21 +267,44 @@ public class StackDropAgent extends DropAgent { // 'dropIndex' is now the index of the CTabItem to put ourselves before // we need to adjust this to be a model index - int ctfItemCount = dropCTF.getItemCount(); - if (dropIndex < ctfItemCount) { - CTabItem item = dropCTF.getItem(dropIndex); - MUIElement itemModel = (MUIElement) item.getData(AbstractPartRenderer.OWNING_ME); - - // if we're going before ourselves its a NO-OP - if (itemModel == dragElement) - return; - - dropIndex = itemModel.getParent().getChildren().indexOf(itemModel); - // if the item is dropped at the last position, there is - // no existing item to put ourselves before - // so we'll just go to the end. - } else if (dropIndex == ctfItemCount) { - dropIndex = dropStack.getChildren().size(); + + if (hiddenTabs) { + // some tabs are hidden + int nVisibleItems = vItems.size(); + if(dropIndex<nVisibleItems){ + CTabItem item = vItems.get(dropIndex); + MUIElement itemModel = (MUIElement) item.getData(AbstractPartRenderer.OWNING_ME); + + // if we're going before ourselves its a NO-OP + if (itemModel == dragElement) + return; + dropIndex = itemModel.getParent().getChildren().indexOf(itemModel); + // if the item is dropped at the last position, there is + // no existing item to put ourselves before + // so we'll just go to the end. + } else if (dropIndex == nVisibleItems) { + dropIndex = dropStack.getChildren().size(); + } + + + } else { + // all tabs are visible + int ctfItemCount = dropCTF.getItemCount(); + if (dropIndex < ctfItemCount) { + CTabItem item = dropCTF.getItem(dropIndex); + MUIElement itemModel = (MUIElement) item.getData(AbstractPartRenderer.OWNING_ME); + + // if we're going before ourselves its a NO-OP + if (itemModel == dragElement) + return; + + dropIndex = itemModel.getParent().getChildren().indexOf(itemModel); + // if the item is dropped at the last position, there is + // no existing item to put ourselves before + // so we'll just go to the end. + } else if (dropIndex == ctfItemCount) { + dropIndex = dropStack.getChildren().size(); + } } if (dragElement instanceof MStackElement) { @@ -267,8 +328,7 @@ public class StackDropAgent extends DropAgent { boolean curSelProcessed = false; while (kids.size() > 1) { // Offset the 'get' to account for skipping 'curSel' - MStackElement kid = curSelProcessed ? kids.get(kids.size() - 2) : kids.get(kids - .size() - 1); + MStackElement kid = curSelProcessed ? kids.get(kids.size() - 2) : kids.get(kids.size() - 1); if (kid == curSel) { curSelProcessed = true; continue; |
