| /******************************************************************************* |
| * Copyright (c) 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.presentations; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.jface.action.GroupMarker; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.resource.ColorRegistry; |
| import org.eclipse.jface.resource.FontRegistry; |
| import org.eclipse.jface.util.Geometry; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CTabFolderEvent; |
| import org.eclipse.swt.custom.CTabItem; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.ShellAdapter; |
| import org.eclipse.swt.events.ShellEvent; |
| import org.eclipse.swt.events.ShellListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Monitor; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IPropertyListener; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.IWorkbenchConstants; |
| import org.eclipse.ui.internal.IWorkbenchGraphicConstants; |
| import org.eclipse.ui.internal.IWorkbenchThemeConstants; |
| import org.eclipse.ui.internal.WorkbenchImages; |
| import org.eclipse.ui.internal.WorkbenchMessages; |
| import org.eclipse.ui.internal.dnd.DragUtil; |
| import org.eclipse.ui.internal.util.Util; |
| import org.eclipse.ui.presentations.IPartMenu; |
| import org.eclipse.ui.presentations.IPresentablePart; |
| import org.eclipse.ui.presentations.IPresentationSerializer; |
| import org.eclipse.ui.presentations.IStackPresentationSite; |
| import org.eclipse.ui.presentations.PresentationUtil; |
| import org.eclipse.ui.presentations.StackDropResult; |
| import org.eclipse.ui.presentations.StackPresentation; |
| import org.eclipse.ui.themes.ITheme; |
| import org.eclipse.ui.themes.IThemeManager; |
| |
| /** |
| * Base class for StackPresentations that display IPresentableParts in a PaneFolder. |
| * |
| * @since 3.0 |
| */ |
| public class DefaultPartPresentation extends StackPresentation { |
| |
| private PaneFolder tabFolder; |
| private IPresentablePart current; |
| private int activeState = StackPresentation.AS_INACTIVE; |
| private MenuManager systemMenuManager = new MenuManager(); |
| private Label titleLabel; |
| private Listener dragListener; |
| |
| /** |
| * While we are dragging a tab from this folder, this holdes index of the tab |
| * being dragged. Set to -1 if we are not currently dragging a tab from this folder. |
| */ |
| private int dragStart = -1; |
| |
| private final static String TAB_DATA = DefaultPartPresentation.class.getName() + ".partId"; //$NON-NLS-1$ |
| |
| private PaneFolderButtonListener buttonListener = new PaneFolderButtonListener() { |
| public void stateButtonPressed(int buttonId) { |
| getSite().setState(buttonId); |
| } |
| |
| public void closeButtonPressed(CTabItem item) { |
| IPresentablePart part = getPartForTab(item); |
| |
| getSite().close(new IPresentablePart[]{part}); |
| } |
| |
| public void showList(CTabFolderEvent event) { |
| event.doit = false; |
| showPartList(); |
| } |
| }; |
| |
| private MouseListener mouseListener = new MouseAdapter() { |
| public void mouseDown(MouseEvent e) { |
| if (e.widget instanceof Control) { |
| Control ctrl = (Control)e.widget; |
| |
| Point globalPos = ctrl.toDisplay(new Point(e.x, e.y)); |
| |
| // PR#1GDEZ25 - If selection will change in mouse up ignore mouse down. |
| // Else, set focus. |
| CTabItem newItem = tabFolder.getItem(tabFolder.getControl().toControl(globalPos)); |
| if (newItem != null) { |
| CTabItem oldItem = tabFolder.getSelection(); |
| if (newItem != oldItem) |
| return; |
| } |
| if (current != null) { |
| current.setFocus(); |
| } |
| } |
| } |
| |
| public void mouseDoubleClick(MouseEvent e) { |
| if (getSite().getState() == IStackPresentationSite.STATE_MAXIMIZED) { |
| getSite().setState(IStackPresentationSite.STATE_RESTORED); |
| } else { |
| getSite().setState(IStackPresentationSite.STATE_MAXIMIZED); |
| } |
| } |
| }; |
| |
| private Listener menuListener = new Listener() { |
| /* (non-Javadoc) |
| * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) |
| */ |
| public void handleEvent(Event event) { |
| Point pos = new Point(event.x, event.y); |
| |
| showSystemMenu(pos); |
| } |
| }; |
| |
| private Listener selectionListener = new Listener() { |
| public void handleEvent(Event e) { |
| IPresentablePart item = getPartForTab((CTabItem)e.item); |
| |
| if (item != null) { |
| setSelection((CTabItem)e.item); |
| } |
| } |
| }; |
| |
| private IPropertyListener childPropertyChangeListener = new IPropertyListener() { |
| public void propertyChanged(Object source, int property) { |
| if (source instanceof IPresentablePart) { |
| IPresentablePart part = (IPresentablePart) source; |
| childPropertyChanged(part, property); |
| } |
| } |
| }; |
| |
| private DisposeListener tabDisposeListener = new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| if (e.widget instanceof CTabItem) { |
| CTabItem item = (CTabItem)e.widget; |
| |
| IPresentablePart part = getPartForTab(item); |
| |
| part.removePropertyListener(childPropertyChangeListener); |
| } |
| } |
| }; |
| private ToolBar viewToolBar; |
| |
| private boolean shellActive = true; |
| |
| private ShellListener shellListener = new ShellAdapter() { |
| |
| public void shellActivated(ShellEvent e) { |
| shellActive = true; |
| updateGradient(); |
| } |
| |
| |
| public void shellDeactivated(ShellEvent e) { |
| shellActive = false; |
| updateGradient(); |
| } |
| }; |
| |
| /** |
| * property listener that listens for theme events and updates the tab folder |
| * accordingly |
| */ |
| private IPropertyChangeListener themeListener = new IPropertyChangeListener() { |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) |
| */ |
| public void propertyChange(PropertyChangeEvent event) { |
| |
| String property = event.getProperty(); |
| if (property.equals(IThemeManager.CHANGE_CURRENT_THEME)) { |
| updateGradient(); |
| setTitleAttributes(); |
| } |
| else if (property.equals(IWorkbenchThemeConstants.INACTIVE_TAB_BG_START) |
| || property.equals(IWorkbenchThemeConstants.INACTIVE_TAB_BG_END) |
| || property.equals(IWorkbenchThemeConstants.INACTIVE_TAB_TEXT_COLOR) |
| || property.equals(IWorkbenchThemeConstants.ACTIVE_TAB_TEXT_COLOR) |
| || property.equals(IWorkbenchThemeConstants.ACTIVE_TAB_BG_START) |
| || property.equals(IWorkbenchThemeConstants.ACTIVE_TAB_BG_END) |
| || property.equals(IWorkbenchThemeConstants.TAB_TEXT_FONT)) { |
| updateGradient(); |
| } |
| else if (property.equals(IWorkbenchThemeConstants.VIEW_MESSAGE_TEXT_FONT)) { |
| setTitleAttributes(); |
| } |
| } |
| }; |
| |
| public DefaultPartPresentation(PaneFolder control, IStackPresentationSite stackSite) { |
| super(stackSite); |
| |
| shellActive = control.getControl().getShell().equals(control.getControl().getDisplay().getActiveShell()); |
| |
| tabFolder = control; |
| |
| tabFolder.setMinimizeVisible(stackSite.supportsState(IStackPresentationSite.STATE_MINIMIZED)); |
| tabFolder.setMaximizeVisible(stackSite.supportsState(IStackPresentationSite.STATE_MAXIMIZED)); |
| |
| tabFolder.getControl().getShell().addShellListener(shellListener); |
| |
| titleLabel = new Label(tabFolder.getControl(), SWT.NONE); |
| titleLabel.setVisible(false); |
| titleLabel.moveAbove(null); |
| |
| PlatformUI |
| .getWorkbench() |
| .getThemeManager() |
| .addPropertyChangeListener(themeListener); |
| |
| |
| viewToolBar = new ToolBar(control.getControl(), SWT.FLAT); |
| viewToolBar.moveAbove(null); |
| |
| ToolItem pullDownButton = new ToolItem(viewToolBar, SWT.PUSH); |
| // Image img = WorkbenchImages.getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU); |
| Image hoverImage = |
| WorkbenchImages.getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU_HOVER); |
| pullDownButton.setDisabledImage(hoverImage); // TODO: comment this out? |
| // PR#1GE56QT - Avoid creation of unnecessary image. |
| pullDownButton.setImage(hoverImage); |
| pullDownButton.setToolTipText(WorkbenchMessages.getString("Menu")); //$NON-NLS-1$ |
| pullDownButton.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| showPaneMenu(); |
| } |
| }); |
| |
| // listener to switch between visible tabItems |
| tabFolder.getControl().addListener(SWT.Selection, selectionListener); |
| |
| // listen for mouse down on tab to set focus. |
| tabFolder.getControl().addMouseListener(mouseListener); |
| |
| tabFolder.getControl().addListener(SWT.MenuDetect, menuListener); |
| |
| tabFolder.addButtonListener(buttonListener); |
| |
| dragListener = new Listener() { |
| public void handleEvent(Event event) { |
| |
| Point localPos = new Point(event.x, event.y); |
| // Ignore drags unless they are on the title area |
| if ((tabFolder.getControl().getStyle() & SWT.TOP) != 0) { |
| if (localPos.y > tabFolder.getTabHeight()) { |
| return; |
| } |
| } else { |
| if (localPos.y < tabFolder.getControl().getBounds().height - tabFolder.getTabHeight()) { |
| return; |
| } |
| } |
| |
| CTabItem tabUnderPointer = tabFolder.getItem(localPos); |
| |
| if (tabUnderPointer == null) { |
| getSite().dragStart(tabFolder.getControl().toDisplay(localPos), false); |
| return; |
| } |
| |
| IPresentablePart part = getPartForTab(tabUnderPointer); |
| |
| if (getSite().isPartMoveable(part)) { |
| dragStart = tabFolder.indexOf(tabUnderPointer); |
| getSite().dragStart(part, |
| tabFolder.getControl().toDisplay(localPos), false); |
| dragStart = -1; |
| } |
| } |
| }; |
| |
| PresentationUtil.addDragListener(tabFolder.getControl(), dragListener); |
| |
| titleLabel.addMouseListener(mouseListener); |
| |
| { // Initialize system menu |
| systemMenuManager.add(new GroupMarker("misc")); //$NON-NLS-1$ |
| systemMenuManager.add(new GroupMarker("restore")); //$NON-NLS-1$ |
| systemMenuManager.add(new UpdatingActionContributionItem(new SystemMenuRestore(getSite()))); |
| |
| systemMenuManager.add(new SystemMenuMove(getSite(), getPaneName())); |
| systemMenuManager.add(new GroupMarker("size")); //$NON-NLS-1$ |
| systemMenuManager.add(new GroupMarker("state")); //$NON-NLS-1$ |
| systemMenuManager.add(new UpdatingActionContributionItem(new SystemMenuMinimize(getSite()))); |
| |
| systemMenuManager.add(new UpdatingActionContributionItem(new SystemMenuMaximize(getSite()))); |
| systemMenuManager.add(new Separator("close")); //$NON-NLS-1$ |
| systemMenuManager.add(new UpdatingActionContributionItem(new SystemMenuClose(getSite()))); |
| |
| getSite().addSystemActions(systemMenuManager); |
| } // End of system menu initialization |
| } |
| |
| /** |
| * Restores a presentation from a previously stored state |
| * |
| * @param serializer (not null) |
| * @param savedState (not null) |
| */ |
| public void restoreState(IPresentationSerializer serializer, IMemento savedState) { |
| IMemento[] parts = savedState.getChildren(IWorkbenchConstants.TAG_PART); |
| |
| for (int idx = 0; idx < parts.length; idx++) { |
| String id = parts[idx].getString(IWorkbenchConstants.TAG_ID); |
| |
| if (id != null) { |
| IPresentablePart part = serializer.getPart(id); |
| |
| if (part != null) { |
| addPart(part, tabFolder.getItemCount()); |
| } |
| } |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.presentations.StackPresentation#saveState(org.eclipse.ui.presentations.IPresentationSerializer, org.eclipse.ui.IMemento) |
| */ |
| public void saveState(IPresentationSerializer context, IMemento memento) { |
| super.saveState(context, memento); |
| |
| List parts = getPresentableParts(); |
| |
| Iterator iter = parts.iterator(); |
| while (iter.hasNext()) { |
| IPresentablePart next = (IPresentablePart)iter.next(); |
| |
| IMemento childMem = memento.createChild(IWorkbenchConstants.TAG_PART); |
| childMem.putString(IWorkbenchConstants.TAG_ID, context.getId(next)); |
| } |
| } |
| |
| /** |
| * This method performs initialization that must be done after the object is created. Subclasses |
| * must call this method exactly once on the last line of any public constructor. |
| */ |
| public void init() { |
| updateGradient(); |
| setTitleAttributes(); |
| } |
| |
| /** |
| * Sets the font on the title of this stack. |
| */ |
| protected void setTitleAttributes() { |
| if (titleLabel == null || titleLabel.isDisposed()) |
| return; |
| ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); |
| Font messageFont = theme.getFontRegistry().get(IWorkbenchThemeConstants.VIEW_MESSAGE_TEXT_FONT); |
| if (!messageFont.equals(titleLabel.getFont())) { |
| titleLabel.setFont(messageFont); |
| setControlSize(); |
| } |
| } |
| |
| /** |
| * Sets the colors of the tab to the inactive tab colors. |
| */ |
| protected final void setInactiveTabColors() { |
| ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); |
| ColorRegistry colorRegistry = theme.getColorRegistry(); |
| |
| drawGradient( |
| colorRegistry.get(IWorkbenchThemeConstants.INACTIVE_TAB_TEXT_COLOR), |
| new Color [] { |
| colorRegistry.get(IWorkbenchThemeConstants.INACTIVE_TAB_BG_START), |
| colorRegistry.get(IWorkbenchThemeConstants.INACTIVE_TAB_BG_END) |
| }, |
| new int [] {theme.getInt(IWorkbenchThemeConstants.INACTIVE_TAB_PERCENT)}, |
| theme.getBoolean(IWorkbenchThemeConstants.INACTIVE_TAB_VERTICAL)); |
| } |
| |
| /** |
| * Sets the colors of the tab to the active tab colors, taking into account |
| * shell focus. |
| */ |
| protected final void setActiveTabColors() { |
| ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); |
| ColorRegistry colorRegistry = theme.getColorRegistry(); |
| |
| if (isShellActive()) { |
| drawGradient( |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_TAB_TEXT_COLOR), |
| new Color [] { |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_TAB_BG_START), |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_TAB_BG_END) |
| }, |
| new int [] {theme.getInt(IWorkbenchThemeConstants.ACTIVE_TAB_PERCENT)}, |
| theme.getBoolean(IWorkbenchThemeConstants.ACTIVE_TAB_VERTICAL)); |
| } |
| else { |
| drawGradient( |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_NOFOCUS_TAB_TEXT_COLOR), |
| new Color [] { |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_NOFOCUS_TAB_BG_START), |
| colorRegistry.get(IWorkbenchThemeConstants.ACTIVE_NOFOCUS_TAB_BG_END) |
| }, |
| new int [] {theme.getInt(IWorkbenchThemeConstants.ACTIVE_NOFOCUS_TAB_PERCENT)}, |
| theme.getBoolean(IWorkbenchThemeConstants.ACTIVE_NOFOCUS_TAB_VERTICAL)); |
| |
| } |
| } |
| |
| /** |
| * Update the folder colors and fonts based on the current active state. |
| * Subclasses should override, ensuring that they call |
| * super after all color/font changes. |
| */ |
| protected void updateGradient() { |
| // do nothing |
| } |
| |
| /** |
| * @return the required tab height for this folder. |
| */ |
| protected int computeTabHeight() { |
| GC gc = new GC(tabFolder.getControl()); |
| |
| // Compute the tab height |
| int tabHeight = Math.max( |
| viewToolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, |
| gc.getFontMetrics().getHeight()); |
| |
| gc.dispose(); |
| |
| return tabHeight; |
| } |
| |
| protected String getPaneName() { |
| return WorkbenchMessages.getString("DefaultPartPresentation.PaneName"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Displays the view menu as a popup |
| */ |
| public void showPaneMenu() { |
| IPartMenu menu = getPartMenu(); |
| |
| if (menu != null) { |
| Rectangle bounds = DragUtil.getDisplayBounds(viewToolBar); |
| menu.showMenu(new Point(bounds.x, bounds.y + bounds.height)); |
| } |
| } |
| |
| /** |
| * Returns the currently selected part, or <code>null</code>. |
| * |
| * @return the currently selected part, or <code>null</code> |
| */ |
| protected IPresentablePart getCurrent() { |
| return current; |
| } |
| |
| /** |
| * Returns the index of the tab for the given part, or returns tabFolder.getItemCount() |
| * if there is no such tab. |
| * |
| * @param part part being searched for |
| * @return the index of the tab for the given part, or the number of tabs |
| * if there is no such tab |
| */ |
| private final int indexOf(IPresentablePart part) { |
| if (part == null) { |
| return tabFolder.getItemCount(); |
| } |
| |
| CTabItem[] items = tabFolder.getItems(); |
| |
| for (int idx = 0; idx < items.length; idx++) { |
| IPresentablePart tabPart = getPartForTab(items[idx]); |
| |
| if (part == tabPart) { |
| return idx; |
| } |
| } |
| |
| return items.length; |
| } |
| |
| /** |
| * Returns the tab for the given part, or null if there is no such tab |
| * |
| * @param part the part being searched for |
| * @return the tab for the given part, or null if there is no such tab |
| */ |
| protected final CTabItem getTab(IPresentablePart part) { |
| CTabItem[] items = tabFolder.getItems(); |
| |
| int idx = indexOf(part); |
| |
| if (idx < items.length) { |
| return items[idx]; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * @param part |
| * @param property |
| */ |
| protected void childPropertyChanged(IPresentablePart part, int property) { |
| |
| CTabItem tab = getTab(part); |
| // If we're in the process of removing this part, it's possible that we might still receive |
| // some events for it. If everything is working perfectly, this should never happen... however, |
| // we check for this case just to be safe. |
| if (tab == null) { |
| return; |
| } |
| |
| initTab(tab, part); |
| |
| switch (property) { |
| case IPresentablePart.PROP_BUSY: |
| break; |
| case IPresentablePart.PROP_HIGHLIGHT_IF_BACK: |
| FontRegistry registry = |
| PlatformUI.getWorkbench(). |
| getThemeManager().getCurrentTheme(). |
| getFontRegistry(); |
| |
| if(!getCurrent().equals(part))//Set bold if it does currently have focus |
| tab.setFont(registry.getBold(IWorkbenchThemeConstants.TAB_TEXT_FONT)); |
| break; |
| case IPresentablePart.PROP_CONTENT_DESCRIPTION: |
| case IPresentablePart.PROP_TOOLBAR: |
| case IPresentablePart.PROP_PANE_MENU: |
| case IPresentablePart.PROP_TITLE: |
| setControlSize(); |
| break; |
| } |
| } |
| |
| protected final IPresentablePart getPartForTab(CTabItem item) { |
| IPresentablePart part = (IPresentablePart)item.getData(TAB_DATA); |
| |
| return part; |
| } |
| |
| /** |
| * Returns the underlying tab folder for this presentation. |
| * |
| * @return |
| */ |
| protected PaneFolder getTabFolder() { |
| return tabFolder; |
| } |
| |
| /** |
| * Returns true iff the underlying tab folder has been disposed. |
| * |
| * @return |
| */ |
| public boolean isDisposed() { |
| return tabFolder == null || tabFolder.isDisposed(); |
| } |
| |
| /** |
| * Sets the gradient for the selected tab |
| * |
| * @param fgColor |
| * @param bgColors |
| * @param percentages |
| * @param vertical |
| */ |
| public void drawGradient(Color fgColor, Color [] bgColors, int [] percentages, boolean vertical) { |
| tabFolder.setSelectionForeground(fgColor); |
| tabFolder.setSelectionBackground(bgColors, percentages, vertical); |
| } |
| |
| public boolean isActive() { |
| return activeState == StackPresentation.AS_ACTIVE_FOCUS; |
| } |
| |
| public int getActive() { |
| return activeState; |
| } |
| |
| protected String getCurrentTitle() { |
| if (current == null) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| String result = current.getTitleStatus(); |
| |
| return result; |
| } |
| |
| protected void layout(boolean changed) { |
| if (changed) { |
| String currentTitle = getCurrentTitle(); |
| |
| if (!currentTitle.equals(Util.ZERO_LENGTH_STRING)) { |
| tabFolder.setTopLeft(titleLabel); |
| titleLabel.setText(currentTitle); |
| titleLabel.setVisible(true); |
| } else { |
| tabFolder.setTopLeft(null); |
| titleLabel.setVisible(false); |
| } |
| |
| Control currentToolbar = getCurrentToolbar(); |
| tabFolder.setTopCenter(currentToolbar); |
| |
| IPartMenu partMenu = getPartMenu(); |
| |
| if (partMenu != null) { |
| tabFolder.setTopRight(viewToolBar); |
| viewToolBar.setVisible(true); |
| } else { |
| tabFolder.setTopRight(null); |
| viewToolBar.setVisible(false); |
| } |
| } |
| |
| tabFolder.layout(changed); |
| |
| if (current != null) { |
| Rectangle clientArea = tabFolder.getClientArea(); |
| Rectangle bounds = tabFolder.getControl().getBounds(); |
| clientArea.x += bounds.x; |
| clientArea.y += bounds.y; |
| |
| current.setBounds(clientArea); |
| } |
| } |
| |
| /** |
| * Set the size of a page in the folder. |
| */ |
| protected void setControlSize() { |
| layout(true); |
| } |
| |
| /** |
| * Returns the IPartMenu for the currently selected part, or null if the current |
| * part does not have a menu. |
| * |
| * @return the IPartMenu for the currently selected part or null if none |
| */ |
| protected IPartMenu getPartMenu() { |
| IPresentablePart part = getCurrentPart(); |
| if (part == null) { |
| return null; |
| } |
| |
| return part.getMenu(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#dispose() |
| */ |
| public void dispose() { |
| if (isDisposed()) { |
| return; |
| } |
| tabFolder.getControl().getShell().removeShellListener(shellListener); |
| PresentationUtil.removeDragListener(tabFolder.getControl(), dragListener); |
| |
| systemMenuManager.dispose(); |
| systemMenuManager.removeAll(); |
| tabFolder.getControl().dispose(); |
| tabFolder = null; |
| |
| titleLabel.dispose(); |
| titleLabel = null; |
| |
| viewToolBar.dispose(); |
| |
| PlatformUI |
| .getWorkbench() |
| .getThemeManager() |
| .removePropertyChangeListener(themeListener); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.presentations.StackPresentation#setActive(int) |
| */ |
| public void setActive(int newState) { |
| activeState = newState; |
| } |
| |
| private CTabItem createPartTab(IPresentablePart part, int tabIndex) { |
| CTabItem tabItem; |
| |
| int style = SWT.NONE; |
| |
| if (getSite().isCloseable(part)) { |
| style |= SWT.CLOSE; |
| } |
| |
| tabItem = tabFolder.createItem(style, tabIndex); |
| |
| tabItem.setData(TAB_DATA, part); |
| |
| part.addPropertyListener(childPropertyChangeListener); |
| tabItem.addDisposeListener(tabDisposeListener); |
| |
| initTab(tabItem, part); |
| |
| return tabItem; |
| } |
| |
| /** |
| * Initializes a tab for the given part. Sets the text, icon, tool tip, |
| * etc. This will also be called whenever a relevant property changes |
| * in the part to reflect those changes in the tab. Subclasses may override |
| * to change the appearance of tabs for a particular part. |
| * |
| * @param tabItem tab for the part |
| * @param part the part being displayed |
| */ |
| protected void initTab(CTabItem tabItem, IPresentablePart part) { |
| tabItem.setText(part.getName()); |
| |
| tabItem.setImage(part.getTitleImage()); |
| |
| String toolTipText = part.getTitleToolTip(); |
| if (!toolTipText.equals(Util.ZERO_LENGTH_STRING)) { |
| tabItem.setToolTipText(toolTipText); |
| } |
| |
| FontRegistry registry = |
| PlatformUI.getWorkbench(). |
| getThemeManager().getCurrentTheme(). |
| getFontRegistry(); |
| |
| if(part.isBusy()) |
| tabItem.setFont(registry.getItalic(IWorkbenchThemeConstants.TAB_TEXT_FONT)); |
| else{ |
| tabItem.setFont(null); |
| } |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.StackPresentation#addPart(org.eclipse.ui.internal.skins.IPresentablePart, org.eclipse.ui.internal.skins.IPresentablePart) |
| */ |
| public void addPart(IPresentablePart newPart, Object cookie) { |
| |
| int idx; |
| |
| if (cookie instanceof Integer) { |
| idx = ((Integer)cookie).intValue(); |
| } else { |
| // Select a location for newly inserted parts |
| // Insert at the begining |
| idx = 0; |
| } |
| |
| addPart(newPart, idx); |
| } |
| |
| /** |
| * Adds the given presentable part to this presentation at the given index. |
| * Does nothing if a tab already exists for the given part. |
| * |
| * @param newPart |
| * @param index |
| */ |
| public void addPart(IPresentablePart newPart, int index) { |
| // If we already have a tab for this part, do nothing |
| if (getTab(newPart) != null) { |
| return; |
| } |
| createPartTab(newPart, index); |
| |
| setControlSize(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.StackPresentation#removePart(org.eclipse.ui.internal.skins.IPresentablePart) |
| */ |
| public void removePart(IPresentablePart oldPart) { |
| if (current == oldPart) |
| current = null; |
| |
| CTabItem item = getTab(oldPart); |
| if (item == null) { |
| return; |
| } |
| oldPart.setVisible(false); |
| |
| item.dispose(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.StackPresentation#selectPart(org.eclipse.ui.internal.skins.IPresentablePart) |
| */ |
| public void selectPart(IPresentablePart toSelect) { |
| if (toSelect == current) { |
| return; |
| } |
| IPresentablePart oldPart = current; |
| |
| current = toSelect; |
| |
| if (current != null) { |
| CTabItem item = getTab(toSelect); |
| if (item != null) |
| // If the item is not currently visible, move it |
| // to the beginning |
| if (!item.isShowing() && tabFolder.getItemCount() > 1) |
| { |
| removePart(toSelect); |
| addPart(toSelect, 0); |
| current = toSelect; |
| } |
| tabFolder.setSelection(indexOf(current)); |
| current.setVisible(true); |
| setControlSize(); |
| } |
| if (oldPart != null) { |
| oldPart.setVisible(false); |
| } |
| } |
| |
| public IPresentablePart getCurrentPart() { |
| return current; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#setBounds(org.eclipse.swt.graphics.Rectangle) |
| */ |
| public void setBounds(Rectangle bounds) { |
| tabFolder.aboutToResize(); |
| tabFolder.getControl().setBounds(bounds); |
| layout(false); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#computeMinimumSize() |
| */ |
| public Point computeMinimumSize() { |
| return tabFolder.computeMinimumSize(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#setVisible(boolean) |
| */ |
| public void setVisible(boolean isVisible) { |
| if (current != null) { |
| current.setVisible(isVisible); |
| } |
| tabFolder.getControl().setVisible(isVisible); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#setState(int) |
| */ |
| public void setState(int state) { |
| tabFolder.setState(state); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#getSystemMenuManager() |
| */ |
| public IMenuManager getSystemMenuManager() { |
| return systemMenuManager; |
| } |
| |
| /** |
| * @param part |
| * @param point |
| */ |
| protected void showSystemMenu(Point point) { |
| Menu aMenu = systemMenuManager.createContextMenu(tabFolder.getControl().getParent()); |
| systemMenuManager.update(true); |
| aMenu.setLocation(point.x, point.y); |
| aMenu.setVisible(true); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.Presentation#getControl() |
| */ |
| public Control getControl() { |
| return tabFolder.getControl(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.internal.skins.StackPresentation#dragOver(org.eclipse.swt.widgets.Control, org.eclipse.swt.graphics.Point) |
| */ |
| public StackDropResult dragOver(Control currentControl, Point location) { |
| // Determine which tab we're currently dragging over |
| Point localPos = tabFolder.getControl().toControl(location); |
| |
| CTabItem tabUnderPointer = tabFolder.getItem(localPos); |
| |
| // This drop target only deals with tabs... if we're not dragging over |
| // a tab, exit. |
| if (tabUnderPointer == null) { |
| Rectangle titleArea = tabFolder.getTitleArea(); |
| |
| // If we're dragging over the title area, treat this as a drop in the last |
| // tab position. |
| if (titleArea.contains(localPos)) { |
| int dragOverIndex = tabFolder.getItemCount(); |
| CTabItem lastTab = tabFolder.getItem(dragOverIndex - 1); |
| |
| // Can't drag to end unless you can see the end |
| if (!lastTab.isShowing()) { |
| return null; |
| } |
| |
| if (dragStart >= 0) { |
| dragOverIndex--; |
| |
| return new StackDropResult(Geometry.toDisplay(tabFolder.getControl(), |
| lastTab.getBounds()), |
| new Integer(dragOverIndex)); |
| } |
| |
| // Make the drag-over rectangle look like a tab at the end of the tab region. |
| // We don't actually know how wide the tab will be when it's dropped, so just |
| // make it 3 times wider than it is tall. |
| Rectangle dropRectangle = Geometry.toDisplay(tabFolder.getControl(), titleArea); |
| |
| dropRectangle.width = 3 * dropRectangle.height; |
| return new StackDropResult(dropRectangle, new Integer(dragOverIndex)); |
| |
| } else { |
| return null; |
| } |
| } |
| |
| if (!tabUnderPointer.isShowing()) { |
| return null; |
| } |
| |
| return new StackDropResult(Geometry.toDisplay(tabFolder.getControl(), tabUnderPointer.getBounds()), |
| new Integer(tabFolder.indexOf(tabUnderPointer))); |
| } |
| |
| /** |
| * Returns the toolbar control for the currently selected part, or null if none (not |
| * all parts have a toolbar). |
| * |
| * @return the current toolbar or null if none |
| */ |
| protected Control getCurrentToolbar() { |
| IPresentablePart part = getCurrentPart(); |
| if (part == null) { |
| return null; |
| } |
| |
| return part.getToolBar(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.presentations.StackPresentation#showSystemMenu() |
| */ |
| public void showSystemMenu() { |
| IPresentablePart part = getCurrentPart(); |
| if (part != null) { |
| Rectangle bounds = DragUtil.getDisplayBounds(tabFolder.getControl()); |
| |
| int idx = tabFolder.getSelectionIndex(); |
| if (idx > -1) { |
| CTabItem item = tabFolder.getItem(idx); |
| Rectangle itemBounds = item.getBounds(); |
| |
| bounds.x += itemBounds.x; |
| bounds.y += itemBounds.y; |
| } |
| |
| Point location = new Point(bounds.x, bounds.y + tabFolder.getTabHeight()); |
| showSystemMenu(location); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.presentations.StackPresentation#getTabList(IPresentablePart) |
| */ |
| public Control[] getTabList(IPresentablePart part) { |
| ArrayList list = new ArrayList(); |
| if (tabFolder.getTabPosition() == SWT.BOTTOM) { |
| if (part.getToolBar() != null) list.add(part.getToolBar()); |
| if (part.getControl() != null) list.add(part.getControl()); |
| if (getTabFolder() != null) list.add(getTabFolder().getControl()); |
| } |
| else { |
| if (getTabFolder() != null) list.add(getTabFolder().getControl()); |
| if (part.getToolBar() != null) list.add(part.getToolBar()); |
| if (part.getControl() != null) list.add(part.getControl()); |
| } |
| return (Control[]) list.toArray(new Control[list.size()]); |
| } |
| |
| protected void showList(Shell parentShell, int x, int y) { |
| final PaneFolder tabFolder = getTabFolder(); |
| |
| int shellStyle = SWT.RESIZE | SWT.ON_TOP | SWT.NO_TRIM; |
| int tableStyle = SWT.V_SCROLL | SWT.H_SCROLL; |
| final BasicStackList editorList = new BasicStackList(tabFolder.getControl().getShell(), |
| shellStyle, tableStyle); |
| editorList.setInput(this); |
| Point size = editorList.computeSizeHint(); |
| |
| Monitor mon = getTabFolder().getControl().getMonitor(); |
| Rectangle bounds = mon.getClientArea(); |
| if (x + size.x > bounds.x + bounds.width) x = bounds.x + bounds.width - size.x; |
| if (y + size.y > bounds.y + bounds.height) y = bounds.y + bounds.height - size.y; |
| editorList.setLocation(new Point(x, y)); |
| editorList.setVisible(true); |
| editorList.setFocus(); |
| editorList.getTableViewer().getTable().getShell().addListener( |
| SWT.Deactivate, new Listener() { |
| |
| public void handleEvent(Event event) { |
| editorList.setVisible(false); |
| } |
| }); |
| } |
| |
| /* |
| * Shows the list of tabs at the top left corner of the editor |
| */ |
| public void showPartList() { |
| PaneFolder tabFolder = getTabFolder(); |
| Shell shell = tabFolder.getControl().getShell(); |
| |
| // get the last visible item |
| int numItems = tabFolder.getItemCount(); |
| CTabItem item = null, tempItem = null; |
| for (int i = 0; i < numItems; i++) { |
| tempItem = tabFolder.getItem(i); |
| if (tempItem.isShowing()) |
| item = tempItem; |
| } |
| |
| // if we have no visible tabs, abort. |
| if (item == null) |
| return; |
| |
| Rectangle itemBounds = item.getBounds(); |
| int x = itemBounds.x+itemBounds.width; |
| int y = itemBounds.y + itemBounds.height; |
| Point location = item.getDisplay().map(tabFolder.getControl(), null, x, y); |
| showList(shell, location.x, location.y); |
| } |
| |
| void setSelection(CTabItem tabItem) { |
| getSite().selectPart(getPartForTab(tabItem)); |
| } |
| |
| void close(IPresentablePart[] presentablePart) { |
| getSite().close(presentablePart); |
| } |
| |
| /** |
| * Returns the List of IPresentablePart currently in this presentation |
| */ |
| List getPresentableParts() { |
| CTabItem[] items = tabFolder.getItems(); |
| List result = new ArrayList(items.length); |
| |
| for (int idx = 0; idx < tabFolder.getItemCount(); idx++) { |
| result.add(getPartForTab(items[idx])); |
| } |
| |
| return result; |
| } |
| |
| Image getLabelImage(IPresentablePart presentablePart) { |
| return presentablePart.getTitleImage(); |
| } |
| |
| String getLabelText(IPresentablePart presentablePart, |
| boolean includePath) { |
| String title = presentablePart.getName(); |
| return title; |
| } |
| |
| /** |
| * Answers whether the shell containing this presentation is currently the active shell. |
| */ |
| protected boolean isShellActive() { |
| return shellActive; |
| } |
| } |