| /******************************************************************************* |
| * Copyright (c) 2004, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.presentations.util; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| 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.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.ui.presentations.IStackPresentationSite; |
| import org.eclipse.ui.presentations.PresentationUtil; |
| |
| /** |
| * @since 3.1 |
| */ |
| public abstract class AbstractTabFolder { |
| |
| private List listeners = new ArrayList(1); |
| |
| private Control toolbar; |
| private int state; |
| |
| public abstract Point computeSize(int widthHint, int heightHint); |
| |
| public abstract AbstractTabItem add(int index, int flags); |
| |
| public abstract Composite getContentParent(); |
| public abstract void setContent(Control newContent); |
| |
| public abstract AbstractTabItem[] getItems(); |
| |
| public abstract AbstractTabItem getSelection(); |
| public abstract void setSelection(AbstractTabItem toSelect); |
| public abstract void setSelectedInfo(PartInfo info); |
| public abstract void enablePaneMenu(boolean enabled); |
| private int activeState = IStackPresentationSite.STATE_RESTORED; |
| |
| 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 globalPos = new Point(event.x, event.y); |
| handleContextMenu(globalPos, event); |
| } |
| }; |
| |
| private Listener dragListener = new Listener() { |
| public void handleEvent(Event e) { |
| Point globalPos = ((Control)e.widget).toDisplay(e.x, e.y); |
| handleDragStarted(globalPos, e); |
| } |
| }; |
| |
| private MouseListener mouseListener = new MouseAdapter() { |
| |
| // If we single-click on an empty space on the toolbar, move focus to the |
| // active control |
| public void mouseDown(MouseEvent e) { |
| Point p = ((Control)e.widget).toDisplay(e.x, e.y); |
| |
| handleMouseDown(p, e); |
| } |
| |
| |
| // If we double-click on the toolbar, maximize the presentation |
| public void mouseDoubleClick(MouseEvent e) { |
| Point p = ((Control)e.widget).toDisplay(e.x, e.y); |
| |
| handleDoubleClick(p, e); |
| } |
| }; |
| |
| public void setActive(int activeState) { |
| this.activeState = activeState; |
| } |
| |
| public int getActive() { |
| return activeState; |
| } |
| |
| /** |
| * Returns the location where the pane menu should be opened when activated |
| * by a keyboard shortcut (display coordinates) |
| * |
| * @return the location for the pane menu (display coordinates) |
| * @since 3.1 |
| */ |
| public Point getPaneMenuLocation() { |
| return getControl().toDisplay(new Point(0,0)); |
| } |
| |
| /** |
| * Returns the location where the part list should be opened when activated |
| * by a keyboard shortcut (display coordinates) |
| * |
| * @return the location for the part list (display coordinates) |
| * @since 3.1 |
| */ |
| public Point getPartListLocation() { |
| return getSystemMenuLocation(); |
| } |
| |
| /** |
| * Returns the location where the pane menu should be opened when activated |
| * by a keyboard shortcut (display coordinates) |
| * |
| * @return the location for the pane menu (display coordinates) |
| * @since 3.1 |
| */ |
| public Point getSystemMenuLocation() { |
| return getControl().toDisplay(new Point(0,0)); |
| } |
| |
| /** |
| * Returns the parent composite that should be used for creating the toolbar. |
| * Any control passed into setToolbar must have this composite as its parent. |
| * |
| * @return the parent composite that should be used for creating the toolbar |
| * |
| * @since 3.1 |
| */ |
| public abstract Composite getToolbarParent(); |
| |
| /** |
| * Returns the main control for this folder. |
| * |
| * @return the main control for the folder |
| * @since 3.1 |
| */ |
| public abstract Control getControl(); |
| |
| public AbstractTabItem getItem(int idx) { |
| return getItems()[idx]; |
| } |
| |
| public AbstractTabItem getItem(Point toFind) { |
| AbstractTabItem[] items = getItems(); |
| |
| for (int i = 0; i < items.length; i++) { |
| AbstractTabItem item = items[i]; |
| |
| if (item.getBounds().contains(toFind)) { |
| return item; |
| } |
| } |
| |
| return null; |
| } |
| |
| public AbstractTabItem findItem(Object dataToFind) { |
| AbstractTabItem[] items = getItems(); |
| |
| for (int i = 0; i < items.length; i++) { |
| AbstractTabItem item = items[i]; |
| |
| if (item.getData() == dataToFind) { |
| return item; |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the index of the given item, or -1 if the given item is |
| * not found in this tab folder. Subclasses should override this if |
| * the underlying SWT widget has an equivalent method |
| * |
| * @param item item to find |
| * @return the index of the given item or -1 |
| */ |
| public int indexOf(AbstractTabItem item) { |
| AbstractTabItem[] items = getItems(); |
| |
| for (int idx = 0; idx < items.length; idx++) { |
| AbstractTabItem next = items[idx]; |
| |
| if (next == item) { |
| return idx; |
| } |
| } |
| |
| return -1; |
| } |
| |
| public int getItemCount() { |
| return getItems().length; |
| } |
| |
| public void setToolbar(Control toolbarControl) { |
| this.toolbar = toolbarControl; |
| } |
| |
| public final Control getToolbar() { |
| return toolbar; |
| } |
| |
| /** |
| * Sets the current state for the folder |
| * |
| * @param state one of the IStackPresentationSite.STATE_* constants |
| */ |
| public void setState(int state) { |
| this.state = state; |
| } |
| |
| /** |
| * Returns the title area for this control (in the control's coordinate system) |
| * |
| * @return |
| */ |
| public abstract Rectangle getTabArea(); |
| |
| /** |
| * Called when the tab folder's shell becomes active or inactive. Subclasses |
| * can override this to change the appearance of the tabs based on activation. |
| * |
| * @param isActive |
| */ |
| public void shellActive(boolean isActive) { |
| } |
| |
| /** |
| * Adds the given listener to this AbstractTabFolder |
| * |
| * @param newListener the listener to add |
| */ |
| public final void addListener(TabFolderListener newListener) { |
| listeners.add(newListener); |
| } |
| |
| /** |
| * Removes the given listener from this AbstractTabFolder |
| * |
| * @param toRemove the listener to remove |
| */ |
| public final void removeListener(TabFolderListener toRemove) { |
| listeners.remove(toRemove); |
| } |
| |
| public void flushToolbarSize() { |
| |
| } |
| |
| protected final void fireEvent(TabFolderEvent e) { |
| for (Iterator iter = listeners.iterator(); iter.hasNext();) { |
| TabFolderListener next = (TabFolderListener)iter.next(); |
| |
| next.handleEvent(e); |
| } |
| } |
| |
| protected final void fireEvent(int id) { |
| fireEvent(new TabFolderEvent(id)); |
| } |
| |
| protected final void fireEvent(int id, AbstractTabItem w) { |
| fireEvent(new TabFolderEvent(id, w, 0, 0)); |
| } |
| |
| protected final void fireEvent(int id, AbstractTabItem w, Point pos) { |
| fireEvent(new TabFolderEvent(id, w, pos)); |
| } |
| |
| public void layout(boolean flushCache) { |
| } |
| |
| public void setTabPosition(int tabPosition) { |
| } |
| |
| public int getTabPosition() { |
| return SWT.TOP; |
| } |
| |
| public int getState() { |
| return state; |
| } |
| |
| protected void attachListeners(Control theControl, boolean recursive) { |
| theControl.addListener(SWT.MenuDetect, menuListener); |
| theControl.addMouseListener(mouseListener); |
| PresentationUtil.addDragListener(theControl, dragListener); |
| |
| if (recursive && theControl instanceof Composite) { |
| Composite composite = (Composite) theControl; |
| Control[] children = composite.getChildren(); |
| |
| for (int i = 0; i < children.length; i++) { |
| Control control = children[i]; |
| |
| attachListeners(control, recursive); |
| } |
| } |
| } |
| |
| protected void detachListeners(Control theControl, boolean recursive) { |
| theControl.removeListener(SWT.MenuDetect, menuListener); |
| theControl.removeMouseListener(mouseListener); |
| PresentationUtil.removeDragListener(theControl, dragListener); |
| |
| if (recursive && theControl instanceof Composite) { |
| Composite composite = (Composite) theControl; |
| Control[] children = composite.getChildren(); |
| |
| for (int i = 0; i < children.length; i++) { |
| Control control = children[i]; |
| |
| detachListeners(control, recursive); |
| } |
| } |
| } |
| |
| protected void handleContextMenu(Point displayPos, Event e) { |
| if (isOnBorder(displayPos)) { |
| return; |
| } |
| |
| AbstractTabItem tab = getItem(displayPos); |
| |
| fireEvent(TabFolderEvent.EVENT_SYSTEM_MENU, tab, displayPos); |
| } |
| |
| protected void handleMouseDown(Point displayPos, MouseEvent e) { |
| fireEvent(TabFolderEvent.EVENT_GIVE_FOCUS_TO_PART); |
| } |
| |
| protected void handleDoubleClick(Point displayPos, MouseEvent e) { |
| if (isOnBorder(displayPos)) { |
| return; |
| } |
| |
| if (getState() == IStackPresentationSite.STATE_MAXIMIZED) { |
| fireEvent(TabFolderEvent.EVENT_RESTORE); |
| } else { |
| fireEvent(TabFolderEvent.EVENT_MAXIMIZE); |
| } |
| } |
| |
| protected void handleDragStarted(Point displayPos, Event e) { |
| |
| if (isOnBorder(displayPos)) { |
| return; |
| } |
| |
| AbstractTabItem tab = getItem(displayPos); |
| fireEvent(TabFolderEvent.EVENT_DRAG_START, tab, displayPos); |
| } |
| |
| /** |
| * Returns true iff the given point is on the border of the folder. |
| * By default, double-clicking, context menus, and drag/drop are disabled |
| * on the folder's border. |
| * |
| * @param toTest a point (display coordinates) |
| * @return true iff the point is on the presentation border |
| * @since 3.1 |
| */ |
| public boolean isOnBorder(Point toTest) { |
| return false; |
| } |
| |
| /** |
| * Set the folder to visible. This can be extended to propogate the |
| * visibility request to other components in the subclass. |
| * |
| * @param visible |
| * <code>true</code> - the folder is visible. |
| * @since 3.2 |
| */ |
| public void setVisible(boolean visible) { |
| getControl().setVisible(visible); |
| } |
| |
| /** |
| * Cause the folder to hide or show its |
| * Minimize and Maximize affordances. |
| * |
| * @param show |
| * <code>true</code> - the min/max buttons are visible. |
| * @since 3.3 |
| */ |
| public void showMinMax(boolean show) { |
| } |
| } |