001: /*******************************************************************************
002: * Copyright (c) 2004 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Common Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/cpl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.r21presentation.presentations;
011:
012: import java.util.ArrayList;
013:
014: import org.eclipse.jface.action.GroupMarker;
015: import org.eclipse.jface.action.IMenuManager;
016: import org.eclipse.jface.action.MenuManager;
017: import org.eclipse.jface.action.Separator;
018: import org.eclipse.jface.preference.IPreferenceStore;
019: import org.eclipse.jface.util.Geometry;
020: import org.eclipse.jface.util.IPropertyChangeListener;
021: import org.eclipse.jface.util.PropertyChangeEvent;
022: import org.eclipse.jface.window.Window;
023: import org.eclipse.swt.SWT;
024: import org.eclipse.swt.events.DisposeEvent;
025: import org.eclipse.swt.events.DisposeListener;
026: import org.eclipse.swt.events.MouseAdapter;
027: import org.eclipse.swt.events.MouseEvent;
028: import org.eclipse.swt.events.MouseListener;
029: import org.eclipse.swt.events.ShellAdapter;
030: import org.eclipse.swt.events.ShellEvent;
031: import org.eclipse.swt.graphics.Color;
032: import org.eclipse.swt.graphics.Image;
033: import org.eclipse.swt.graphics.Point;
034: import org.eclipse.swt.graphics.Rectangle;
035: import org.eclipse.swt.widgets.Composite;
036: import org.eclipse.swt.widgets.Control;
037: import org.eclipse.swt.widgets.Event;
038: import org.eclipse.swt.widgets.Listener;
039: import org.eclipse.swt.widgets.Menu;
040: import org.eclipse.ui.IPropertyListener;
041: import org.eclipse.ui.internal.IPreferenceConstants;
042: import org.eclipse.ui.internal.WorkbenchPlugin;
043: import org.eclipse.ui.internal.WorkbenchWindow;
044: import org.eclipse.ui.internal.dnd.DragUtil;
045: import org.eclipse.ui.internal.presentations.SystemMenuClose;
046: import org.eclipse.ui.internal.presentations.SystemMenuMaximize;
047: import org.eclipse.ui.internal.presentations.SystemMenuMove;
048: import org.eclipse.ui.internal.presentations.SystemMenuRestore;
049: import org.eclipse.ui.internal.presentations.UpdatingActionContributionItem;
050: import org.eclipse.ui.internal.r21presentation.R21Colors;
051: import org.eclipse.ui.internal.r21presentation.R21PresentationMessages;
052: import org.eclipse.ui.internal.r21presentation.widgets.CTabFolder;
053: import org.eclipse.ui.internal.r21presentation.widgets.CTabFolderEvent;
054: import org.eclipse.ui.internal.r21presentation.widgets.CTabFolderListener;
055: import org.eclipse.ui.internal.r21presentation.widgets.CTabItem;
056: import org.eclipse.ui.presentations.IPartMenu;
057: import org.eclipse.ui.presentations.IPresentablePart;
058: import org.eclipse.ui.presentations.IStackPresentationSite;
059: import org.eclipse.ui.presentations.PresentationUtil;
060: import org.eclipse.ui.presentations.StackDropResult;
061: import org.eclipse.ui.presentations.StackPresentation;
062:
063: /**
064: * A stack presentation for editors using a widget set that is close to what was
065: * provided in 2.1.
066: * <p>
067: * EXPERIMENTAL
068: * </p>
069: *
070: * @since 3.0
071: */
072: public class R21EditorStackPresentation extends StackPresentation {
073:
074: /** the tab folder */
075: private CTabFolder tabFolder;
076:
077: /** the drag listener */
078: private Listener dragListener = new Listener() {
079:
080: public void handleEvent(Event event) {
081: Point localPos = new Point(event.x, event.y);
082: CTabItem tabUnderPointer = tabFolder.getItem(localPos);
083:
084: if (tabUnderPointer == null) {
085: // drag the entire stack
086: if (getSite().isStackMoveable())
087: getSite().dragStart(tabFolder.toDisplay(localPos),
088: false);
089: return;
090: }
091:
092: IPresentablePart part = getPartForTab(tabUnderPointer);
093:
094: if (getSite().isPartMoveable(part)) {
095: // drag the part
096: getSite().dragStart(part,
097: tabFolder.toDisplay(localPos), false);
098: }
099: }
100: };
101:
102: /** the listener that will close the tab */
103: private CTabFolderListener closeListener = new CTabFolderListener() {
104:
105: public void itemClosed(CTabFolderEvent e) {
106: CTabItem item = (CTabItem) e.item;
107: if (null != item) {
108: e.doit = false; // otherwise tab is auto disposed on return
109: getSite().close(
110: new IPresentablePart[] { getPartForTab(item) });
111: }
112: }
113: };
114:
115: /** the current part */
116: private IPresentablePart current;
117:
118: /** the system menu */
119: private MenuManager systemMenuManager = new MenuManager();
120:
121: /** the shared preference store */
122: private IPreferenceStore preferenceStore = WorkbenchPlugin
123: .getDefault().getPreferenceStore();
124:
125: /** the tab item property holding the part */
126: private final static String TAB_DATA = R21EditorStackPresentation.class
127: .getName()
128: + ".partId"; //$NON-NLS-1$
129:
130: /** the mouse listener for setting focus */
131: private MouseListener mouseListener = new MouseAdapter() {
132:
133: /*
134: * (non-Javadoc)
135: *
136: * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
137: */
138: public void mouseDown(MouseEvent e) {
139: if (e.widget instanceof Control) {
140: Control ctrl = (Control) e.widget;
141:
142: Point globalPos = ctrl.toDisplay(new Point(e.x, e.y));
143:
144: CTabItem newItem = tabFolder.getItem(tabFolder
145: .toControl(globalPos));
146: if (newItem != null) {
147:
148: // show menu over icon
149: if ((e.button == 1) && overImage(newItem, e.x)) {
150: getSite().selectPart(getPartForTab(newItem));
151: showSystemMenu();
152: }
153:
154: // PR#1GDEZ25 - If selection will change in mouse up ignore
155: // mouse down.
156: CTabItem oldItem = tabFolder.getSelection();
157: if (newItem != oldItem)
158: return;
159: }
160:
161: // set focus
162: if (current != null) {
163: current.setFocus();
164: }
165: }
166: }
167:
168: /*
169: * (non-Javadoc)
170: *
171: * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
172: */
173: public void mouseDoubleClick(MouseEvent e) {
174: if (getSite().getState() == IStackPresentationSite.STATE_MAXIMIZED) {
175: getSite().setState(
176: IStackPresentationSite.STATE_RESTORED);
177: } else {
178: getSite().setState(
179: IStackPresentationSite.STATE_MAXIMIZED);
180: }
181: }
182: };
183:
184: /**
185: * Return true if <code>x</code> is over the tab item image.
186: *
187: * @return true if <code>x</code> is over the tab item image
188: */
189: static boolean overImage(CTabItem item, int x) {
190: Rectangle imageBounds = item.getImage().getBounds();
191: return x < (item.getBounds().x + imageBounds.x + imageBounds.width);
192: }
193:
194: /** the menu listener for showing the menu */
195: private Listener menuListener = new Listener() {
196:
197: /*
198: * (non-Javadoc)
199: *
200: * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
201: */
202: public void handleEvent(Event event) {
203: Point pos = new Point(event.x, event.y);
204: showSystemMenu(pos);
205: }
206: };
207:
208: /** the selection listener */
209: private Listener selectionListener = new Listener() {
210:
211: public void handleEvent(Event e) {
212: IPresentablePart item = getPartForTab((CTabItem) e.item);
213: if (item != null)
214: getSite().selectPart(item);
215: }
216: };
217:
218: private Listener resizeListener = new Listener() {
219:
220: public void handleEvent(Event e) {
221: setControlSize();
222: }
223: };
224:
225: /** a property change listener for the parts */
226: private IPropertyListener childPropertyChangeListener = new IPropertyListener() {
227:
228: public void propertyChanged(Object source, int property) {
229: if (source instanceof IPresentablePart) {
230: IPresentablePart part = (IPresentablePart) source;
231: childPropertyChanged(part, property);
232: }
233: }
234: };
235:
236: /** a dispose listener to do some cleanups when a tab is disposed */
237: private DisposeListener tabDisposeListener = new DisposeListener() {
238:
239: public void widgetDisposed(DisposeEvent e) {
240: if (e.widget instanceof CTabItem) {
241: CTabItem item = (CTabItem) e.widget;
242: IPresentablePart part = getPartForTab(item);
243: part
244: .removePropertyListener(childPropertyChangeListener);
245: }
246: }
247: };
248:
249: /** the shell listener for upgrading the gradient */
250: private ShellAdapter shellListener = new ShellAdapter() {
251:
252: public void shellActivated(ShellEvent event) {
253: updateGradient();
254: }
255:
256: public void shellDeactivated(ShellEvent event) {
257: updateGradient();
258: }
259: };
260:
261: /** the listener for preference changes */
262: private IPropertyChangeListener preferenceListener = new IPropertyChangeListener() {
263:
264: public void propertyChange(PropertyChangeEvent event) {
265: if (IPreferenceConstants.EDITOR_TAB_POSITION.equals(event
266: .getProperty())) {
267: int tabPos = preferenceStore
268: .getInt(IPreferenceConstants.EDITOR_TAB_POSITION);
269: getTabFolder().setTabPosition(tabPos);
270: }
271: }
272: };
273:
274: public R21EditorStackPresentation(Composite parent,
275: IStackPresentationSite stackSite) {
276: super (stackSite);
277:
278: // create the tab folder
279: int tabPos = preferenceStore
280: .getInt(IPreferenceConstants.EDITOR_TAB_POSITION);
281: tabFolder = new CTabFolder(parent, tabPos | SWT.BORDER);
282:
283: // add listener for preference changes
284: preferenceStore.addPropertyChangeListener(preferenceListener);
285:
286: // minimum tab width
287: tabFolder.MIN_TAB_WIDTH = preferenceStore
288: .getInt(IPreferenceConstants.EDITOR_TAB_WIDTH);
289:
290: // prevent close button and scroll buttons from taking focus
291: tabFolder.setTabList(new Control[0]);
292:
293: // enable close button in tab folder
294: tabFolder.addCTabFolderListener(closeListener);
295:
296: // listener to switch between visible tabItems
297: tabFolder.addListener(SWT.Selection, selectionListener);
298:
299: // listener to resize visible components
300: tabFolder.addListener(SWT.Resize, resizeListener);
301:
302: // listen for mouse down on tab to set focus, show system menu and
303: // maximize/restore.
304: tabFolder.addMouseListener(mouseListener);
305:
306: // the menu
307: tabFolder.addListener(SWT.MenuDetect, menuListener);
308:
309: // register drag listener
310: PresentationUtil.addDragListener(tabFolder, dragListener);
311:
312: // add the shell listener to track shell activations
313: // TODO: check if workaround can be removed (see bug 55458)
314: tabFolder.getShell().addShellListener(shellListener);
315:
316: // initialize system menu
317: populateSystemMenu(systemMenuManager);
318: }
319:
320: /**
321: * Initializes the specified menu manager.
322: *
323: * @param menuManager
324: */
325: private void populateSystemMenu(IMenuManager menuManager) {
326:
327: menuManager.add(new GroupMarker("misc")); //$NON-NLS-1$
328: menuManager.add(new GroupMarker("restore")); //$NON-NLS-1$
329: menuManager.add(new UpdatingActionContributionItem(
330: new SystemMenuRestore(getSite())));
331: menuManager.add(new SystemMenuMove(getSite(), getPaneName()));
332: menuManager.add(new GroupMarker("size")); //$NON-NLS-1$
333: menuManager.add(new GroupMarker("state")); //$NON-NLS-1$
334: //systemMenuManager.add(new UpdatingActionContributionItem(new
335: // SystemMenuMinimize(getSite())));
336: menuManager.add(new UpdatingActionContributionItem(
337: new SystemMenuMaximize(getSite())));
338: menuManager.add(new Separator("close")); //$NON-NLS-1$
339: menuManager.add(new UpdatingActionContributionItem(
340: new SystemMenuClose(getSite())));
341:
342: getSite().addSystemActions(menuManager);
343: }
344:
345: /**
346: * Returns the index of the tab for the given part, or returns
347: * tabFolder.getItemCount() if there is no such tab.
348: *
349: * @param part
350: * part being searched for
351: * @return the index of the tab for the given part, or the number of tabs if
352: * there is no such tab
353: */
354: private final int indexOf(IPresentablePart part) {
355: if (part == null)
356: return tabFolder.getItemCount();
357:
358: CTabItem[] items = tabFolder.getItems();
359: for (int idx = 0; idx < items.length; idx++)
360: if (part == getPartForTab(items[idx]))
361: return idx;
362:
363: return items.length;
364: }
365:
366: /**
367: * Returns the tab for the given part, or null if there is no such tab
368: *
369: * @param part
370: * the part being searched for
371: * @return the tab for the given part, or null if there is no such tab
372: */
373: protected final CTabItem getTab(IPresentablePart part) {
374: CTabItem[] items = tabFolder.getItems();
375: int idx = indexOf(part);
376: return idx < items.length ? items[idx] : null;
377: }
378:
379: /**
380: * @param part
381: * @param property
382: */
383: protected void childPropertyChanged(IPresentablePart part,
384: int property) {
385: initTab(getTab(part), part);
386: }
387:
388: protected final IPresentablePart getPartForTab(CTabItem item) {
389: return (IPresentablePart) item.getData(TAB_DATA);
390: }
391:
392: protected CTabFolder getTabFolder() {
393: return tabFolder;
394: }
395:
396: public boolean isDisposed() {
397: return tabFolder == null || tabFolder.isDisposed();
398: }
399:
400: /**
401: * Set the size of a page in the folder.
402: */
403: private void setControlSize() {
404: if (current != null && tabFolder != null)
405: current.setBounds(calculatePageBounds(tabFolder));
406: }
407:
408: public static Rectangle calculatePageBounds(CTabFolder folder) {
409: if (folder == null)
410: return new Rectangle(0, 0, 0, 0);
411:
412: Rectangle bounds = folder.getBounds();
413: Rectangle offset = folder.getClientArea();
414: bounds.x += offset.x;
415: bounds.y += offset.y;
416: bounds.width = offset.width;
417: bounds.height = offset.height;
418: return bounds;
419: }
420:
421: /*
422: * (non-Javadoc)
423: *
424: * @see org.eclipse.ui.internal.skins.Presentation#dispose()
425: */
426: public void dispose() {
427: if (isDisposed())
428: return;
429:
430: // remove shell listener
431: tabFolder.getShell().removeShellListener(shellListener);
432:
433: // remove close listener
434: tabFolder.removeCTabFolderListener(closeListener);
435:
436: // remove drag listener
437: PresentationUtil.removeDragListener(tabFolder, dragListener);
438:
439: // remove preference listener
440: preferenceStore
441: .removePropertyChangeListener(preferenceListener);
442:
443: // dispose system menu manager
444: systemMenuManager.dispose();
445: systemMenuManager.removeAll();
446:
447: // dispose tab folder
448: tabFolder.dispose();
449: tabFolder = null;
450: }
451:
452: /** the active state */
453: private int activeState = AS_INACTIVE;
454:
455: /**
456: * Update the tab folder's colours to match the current theme settings and
457: * active state
458: */
459: private void updateGradient() {
460:
461: if (isDisposed())
462: return;
463:
464: Color fgColor;
465: Color[] bgColors;
466: int[] bgPercents;
467: boolean vertical = false;
468: if (activeState == AS_ACTIVE_FOCUS) {
469: if (getShellActivated()) {
470: fgColor = R21Colors
471: .getSystemColor(SWT.COLOR_TITLE_FOREGROUND);
472: bgColors = R21Colors.getActiveEditorGradient();
473: bgPercents = R21Colors
474: .getActiveEditorGradientPercents();
475: } else {
476: fgColor = R21Colors
477: .getSystemColor(SWT.COLOR_TITLE_INACTIVE_FOREGROUND);
478: bgColors = R21Colors.getDeactivatedEditorGradient();
479: bgPercents = R21Colors
480: .getDeactivatedEditorGradientPercents();
481: }
482:
483: } else if (activeState == AS_ACTIVE_NOFOCUS) {
484: fgColor = R21Colors
485: .getSystemColor(SWT.COLOR_LIST_FOREGROUND);
486: bgColors = R21Colors.getActiveNoFocusEditorGradient();
487: bgPercents = R21Colors
488: .getActiveNoFocusEditorGradientPercents();
489: } else {
490: fgColor = null;
491: bgColors = null;
492: bgPercents = null;
493: }
494:
495: drawGradient(fgColor, bgColors, bgPercents, vertical);
496: }
497:
498: /**
499: * Sets the gradient for the selected tab
500: *
501: * @param fgColor
502: * @param bgColors
503: * @param percentages
504: * @param vertical
505: */
506: protected void drawGradient(Color fgColor, Color[] bgColors,
507: int[] percentages, boolean vertical) {
508: tabFolder.setSelectionForeground(fgColor);
509: tabFolder.setSelectionBackground(bgColors, percentages);
510: tabFolder.update();
511: }
512:
513: /**
514: * Return whether the window's shell is activated
515: */
516: /* package */boolean getShellActivated() {
517: Window window = getWindow();
518: if (window instanceof WorkbenchWindow)
519: return ((WorkbenchWindow) window).getShellActivated();
520: else
521: return false;
522: }
523:
524: /**
525: * Returns the top level window.
526: */
527: public Window getWindow() {
528: Control ctrl = getControl();
529: if (ctrl != null) {
530: Object data = ctrl.getShell().getData();
531: if (data instanceof Window)
532: return (Window) data;
533: }
534: return null;
535: }
536:
537: /**
538: * Creates the tab item for the specified part.
539: *
540: * @param part
541: * @param tabIndex
542: * @return the tab item for the part
543: */
544: private CTabItem createPartTab(IPresentablePart part, int tabIndex) {
545: CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE, tabIndex);
546: tabItem.setData(TAB_DATA, part);
547: part.addPropertyListener(childPropertyChangeListener);
548: tabItem.addDisposeListener(tabDisposeListener);
549: initTab(tabItem, part);
550: return tabItem;
551: }
552:
553: /**
554: * Initializes a tab for the given part. Sets the text, icon, tool tip, etc.
555: * This will also be called whenever a relevant property changes in the part
556: * to reflect those changes in the tab. Subclasses may override to change
557: * the appearance of tabs for a particular part.
558: *
559: * @param tabItem
560: * tab for the part
561: * @param part
562: * the part being displayed
563: */
564: protected void initTab(CTabItem tabItem, IPresentablePart part) {
565:
566: // set tab text and tooltip
567: tabItem.setText(getLabelText(part, true, false));
568: tabItem.setToolTipText(getLabelToolTipText(part));
569:
570: // set tab image
571: tabItem.setImage(getLabelImage(part));
572:
573: // following code allows a disabled image
574: // but the result was distracting: didn't see any disabled image
575:
576: //Image image = getLabelImage(part);
577: //boolean useColorIcons = false; // should we use a preference setting?
578: //
579: //if (image == null || image.isDisposed()) {
580: //// normal image
581: //tabItem.setImage(null);
582: //// disabled image
583: //if (!useColorIcons) {
584: //Image disableImage = tabItem.getDisabledImage();
585: //if (disableImage != null) {
586: //disableImage.dispose();
587: //tabItem.setDisabledImage(null);
588: //}
589: //}
590: //} else if (!image.equals(tabItem.getImage())) {
591: //// normal image
592: // tabItem.setImage(image);
593: //// disabled image
594: //if (!useColorIcons) {
595: //Image disableImage = tabItem.getDisabledImage();
596: //if (disableImage != null)
597: //disableImage.dispose();
598: //Display display = tabItem.getDisplay();
599: //disableImage = new Image(display, image, SWT.IMAGE_DISABLE);
600: //tabItem.setDisabledImage(disableImage);
601: //}
602: //}
603:
604: }
605:
606: /**
607: * Returns the label text that should be used for the tab item for the
608: * specified part
609: *
610: * @param presentablePart
611: * @param dirtyLeft
612: * @param includePath
613: * @return a formated label text
614: */
615: String getLabelText(IPresentablePart presentablePart,
616: boolean dirtyLeft, boolean includePath) {
617: String title = presentablePart.getName().trim();
618: String text = title;
619:
620: if (includePath) {
621: String titleTooltip = presentablePart.getTitleToolTip()
622: .trim();
623:
624: if (titleTooltip.endsWith(title))
625: titleTooltip = titleTooltip.substring(0,
626: titleTooltip.lastIndexOf(title)).trim();
627:
628: if (titleTooltip.endsWith("\\")) //$NON-NLS-1$
629: titleTooltip = titleTooltip.substring(0,
630: titleTooltip.lastIndexOf("\\")).trim(); //$NON-NLS-1$
631:
632: if (titleTooltip.endsWith("/")) //$NON-NLS-1$
633: titleTooltip = titleTooltip.substring(0,
634: titleTooltip.lastIndexOf("/")).trim(); //$NON-NLS-1$
635:
636: if (titleTooltip.length() >= 1)
637: text += " - " + titleTooltip; //$NON-NLS-1$
638: }
639:
640: if (presentablePart.isDirty()) {
641: if (dirtyLeft)
642: text = "* " + text; //$NON-NLS-1$
643: else
644: text = text + " *"; //$NON-NLS-1$
645: }
646:
647: return text;
648: }
649:
650: /**
651: * Returns the image used for the tab item
652: *
653: * @param presentablePart
654: * @return an image
655: */
656: Image getLabelImage(IPresentablePart presentablePart) {
657: return presentablePart.getTitleImage();
658: }
659:
660: /**
661: * Returns the tool tip text used for the tab item
662: *
663: * @param presentablePart
664: * @return a tool tip text
665: */
666: String getLabelToolTipText(IPresentablePart presentablePart) {
667: return presentablePart.getTitleToolTip();
668: }
669:
670: /* (non-Javadoc)
671: * @see org.eclipse.ui.internal.skins.StackPresentation#addPart(org.eclipse.ui.internal.skins.IPresentablePart, org.eclipse.ui.internal.skins.IPresentablePart)
672: */
673: public void addPart(IPresentablePart newPart, Object cookie) {
674:
675: int idx;
676:
677: if (cookie instanceof Integer) {
678: idx = ((Integer) cookie).intValue();
679: } else {
680: // Select a location for newly inserted parts
681: idx = tabFolder.getItemCount();
682: }
683:
684: if (getTab(newPart) != null) {
685: return;
686: }
687:
688: createPartTab(newPart, idx);
689: }
690:
691: /*
692: * (non-Javadoc)
693: *
694: * @see org.eclipse.ui.internal.skins.StackPresentation#removePart(org.eclipse.ui.internal.skins.IPresentablePart)
695: */
696: public void removePart(IPresentablePart oldPart) {
697: if (current == oldPart)
698: current = null;
699:
700: CTabItem item = getTab(oldPart);
701: if (item == null) {
702: return;
703: }
704: oldPart.setVisible(false);
705:
706: item.dispose();
707: }
708:
709: /*
710: * (non-Javadoc)
711: *
712: * @see org.eclipse.ui.internal.skins.StackPresentation#selectPart(org.eclipse.ui.internal.skins.IPresentablePart)
713: */
714: public void selectPart(IPresentablePart toSelect) {
715: if (toSelect == current) {
716: return;
717: }
718:
719: if (current != null) {
720: current.setVisible(false);
721: }
722:
723: current = toSelect;
724:
725: if (current != null) {
726: tabFolder.setSelection(indexOf(current));
727: current.setVisible(true);
728: setControlSize();
729:
730: }
731: }
732:
733: /*
734: * (non-Javadoc)
735: *
736: * @see org.eclipse.ui.internal.skins.Presentation#setBounds(org.eclipse.swt.graphics.Rectangle)
737: */
738: public void setBounds(Rectangle bounds) {
739: tabFolder.setBounds(bounds);
740: setControlSize();
741: }
742:
743: /*
744: * (non-Javadoc)
745: *
746: * @see org.eclipse.ui.internal.skins.Presentation#computeMinimumSize()
747: */
748: public Point computeMinimumSize() {
749: return Geometry.getSize(tabFolder.computeTrim(0, 0, 0, 0));
750: }
751:
752: /*
753: * (non-Javadoc)
754: *
755: * @see org.eclipse.ui.internal.skins.Presentation#setVisible(boolean)
756: */
757: public void setVisible(boolean isVisible) {
758: if (current != null)
759: current.setVisible(isVisible);
760:
761: getTabFolder().setVisible(isVisible);
762: }
763:
764: /*
765: * (non-Javadoc)
766: *
767: * @see org.eclipse.ui.internal.skins.Presentation#setState(int)
768: */
769: public void setState(int state) {
770: // tabFolder.setMinimized(state == IPresentationSite.STATE_MINIMIZED);
771: // tabFolder.setMaximized(state == IPresentationSite.STATE_MAXIMIZED);
772: }
773:
774: /**
775: * Returns the system menu manager.
776: *
777: * @return the system menu manager
778: */
779: public IMenuManager getSystemMenuManager() {
780: return systemMenuManager;
781: }
782:
783: /**
784: * Shows the system context menu at the specified location
785: *
786: * @param point
787: */
788: protected void showSystemMenu(Point point) {
789: Menu aMenu = systemMenuManager.createContextMenu(tabFolder
790: .getParent());
791: systemMenuManager.update(true);
792: aMenu.setLocation(point.x, point.y);
793: aMenu.setVisible(true);
794: }
795:
796: /*
797: * (non-Javadoc)
798: *
799: * @see org.eclipse.ui.internal.skins.Presentation#getControl()
800: */
801: public Control getControl() {
802: return tabFolder;
803: }
804:
805: /*
806: * (non-Javadoc)
807: *
808: * @see org.eclipse.ui.internal.skins.StackPresentation#dragOver(org.eclipse.swt.widgets.Control,
809: * org.eclipse.swt.graphics.Point)
810: */
811: public StackDropResult dragOver(Control currentControl,
812: Point location) {
813:
814: // Determine which tab we're currently dragging over
815: Point localPos = tabFolder.toControl(location);
816: final CTabItem tabUnderPointer = tabFolder.getItem(localPos);
817:
818: // This drop target only deals with tabs... if we're not dragging over
819: // a tab, exit.
820: if (tabUnderPointer == null)
821: return null;
822:
823: // workaround when left tab is dragged over next
824: int dragOverIndex = tabFolder.indexOf(tabUnderPointer);
825:
826: return new StackDropResult(Geometry.toDisplay(tabFolder,
827: tabUnderPointer.getBounds()),
828: new Integer(dragOverIndex));
829: }
830:
831: /*
832: * (non-Javadoc)
833: *
834: * @see org.eclipse.ui.presentations.StackPresentation#showSystemMenu()
835: */
836: public void showSystemMenu() {
837: if (null != current) {
838: // switch to the editor
839: CTabItem item = getTab(current);
840: getSite().selectPart(getCurrentPart());
841: Rectangle bounds = item.getBounds();
842: int y = bounds.height;
843: if (getTabFolder().getTabPosition() == SWT.BOTTOM)
844: y += bounds.y;
845: showSystemMenu(getTabFolder().toDisplay(bounds.x, y));
846: }
847: }
848:
849: /*
850: * (non-Javadoc)
851: *
852: * @see org.eclipse.ui.presentations.StackPresentation#showPaneMenu()
853: */
854: public void showPaneMenu() {
855: IPartMenu menu = getPartMenu();
856:
857: if (null != menu) {
858: CTabItem tab = getTab(getCurrentPart());
859:
860: if (null != tab && null != tab.getControl()) {
861: Rectangle bounds = DragUtil.getDisplayBounds(tab
862: .getControl());
863: menu.showMenu(new Point(bounds.x, bounds.y
864: + bounds.height));
865: }
866: }
867: }
868:
869: /**
870: * Returns the IPartMenu for the currently selected part, or null if the
871: * current part does not have a menu.
872: *
873: * @return the IPartMenu for the currently selected part or null if none
874: */
875: protected IPartMenu getPartMenu() {
876: IPresentablePart part = getCurrentPart();
877: if (part == null) {
878: return null;
879: }
880:
881: return part.getMenu();
882: }
883:
884: /*
885: * (non-Javadoc)
886: *
887: * @see org.eclipse.ui.presentations.StackPresentation#getTabList(IPresentablePart)
888: */
889: public Control[] getTabList(IPresentablePart part) {
890: ArrayList list = new ArrayList();
891: if (getControl() != null)
892: list.add(getControl());
893: if (part.getToolBar() != null)
894: list.add(part.getToolBar());
895: if (part.getControl() != null)
896: list.add(part.getControl());
897: return (Control[]) list.toArray(new Control[list.size()]);
898: }
899:
900: /*
901: * (non-Javadoc)
902: *
903: * @see org.eclipse.ui.presentations.StackPresentation#getCurrentPart()
904: */
905: public IPresentablePart getCurrentPart() {
906: return current;
907: }
908:
909: protected String getPaneName() {
910: return R21PresentationMessages
911: .getString("EditorPane.moveEditor"); //$NON-NLS-1$
912: }
913:
914: /* (non-Javadoc)
915: * @see org.eclipse.ui.presentations.StackPresentation#setActive(int)
916: */
917: public void setActive(int newState) {
918: activeState = newState;
919: updateGradient();
920: }
921: }
|