blob: d674e459e0fbf73e9499e9847a5e19af789ffb41 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2010 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.gef.ui.palette;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
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.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
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.swt.widgets.ControlPaintHandler;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tracker;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.dnd.IDropTarget;
import org.eclipse.draw2d.ActionEvent;
import org.eclipse.draw2d.ActionListener;
import org.eclipse.draw2d.Border;
import org.eclipse.draw2d.Button;
import org.eclipse.draw2d.ButtonBorder;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FocusEvent;
import org.eclipse.draw2d.FocusListener;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.Triangle;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.rap.swt.SWT;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.SharedCursors;
import org.eclipse.gef.dnd.TemplateTransfer;
import org.eclipse.gef.internal.GEFMessages;
import org.eclipse.gef.internal.InternalImages;
import org.eclipse.gef.internal.ui.palette.PaletteColorUtil;
import org.eclipse.gef.ui.views.palette.PaletteView;
/**
* The FlyoutPaletteComposite is used to show a flyout palette alongside another
* control. The flyout palette auto-hides (thus maximizing space) when not in
* use, but can also be pinned open if so desired. It will only be visible when
* the PaletteView is not.
*
* @author Pratik Shah
* @since 3.0
*/
public class FlyoutPaletteComposite extends Composite {
private static final FontManager FONT_MGR = new FontManager();
private static final String PROPERTY_PALETTE_WIDTH = "org.eclipse.gef.ui.palette.fpa.paletteWidth"; //$NON-NLS-1$
private static final String PROPERTY_STATE = "org.eclipse.gef.ui.palette.fpa.state"; //$NON-NLS-1$
private static final String PROPERTY_DOCK_LOCATION = "org.eclipse.gef.ui.palette.fpa.dock"; //$NON-NLS-1$
private static final int DEFAULT_PALETTE_SIZE = 125;
private static final int MIN_PALETTE_SIZE = 20;
private static final int MAX_PALETTE_SIZE = 500;
private static final int STATE_HIDDEN = 8;
private static final int STATE_EXPANDED = 1;
private static final Dimension ARROW_SIZE = new Dimension(6, 11);
private static final int SASH_BUTTON_WIDTH = 11;
/**
* One of the two possible initial states of the flyout palette. This is the
* default one. When in this state, only the flyout palette's sash is
* visible.
*/
public static final int STATE_COLLAPSED = 2;
/**
* One of the two possible initial states of the flyout palette. When in
* this state, the flyout palette is completely visible and pinned open so
* that it doesn't disappear when the user wanders away from the flyout.
*/
public static final int STATE_PINNED_OPEN = 4;
private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
private Composite paletteContainer;
private PaletteViewer pViewer, externalViewer;
private IMemento capturedPaletteState;
private Control graphicalControl;
private Composite sash;
private PaletteViewerProvider provider;
private FlyoutPreferences prefs;
private Point cachedBounds = new Point(0, 0);
/*
* Fix for Bug# 71525 transferFocus is used to transfer focus from the
* button in the vertical sash title to the button in the horizontal
* paletteComposite title. When either button is pressed it is set to true,
* and when either the sash or the paletteComposite gets notified of the
* change in state, they transfer the focus to their button if this flag is
* set to true and if that button is visible.
*/
private boolean transferFocus = false;
private int dock = PositionConstants.EAST;
private int paletteState = STATE_HIDDEN;
private int paletteWidth = DEFAULT_PALETTE_SIZE;
private int minWidth = MIN_PALETTE_SIZE;
private int cachedSize = -1, cachedState = -1, cachedLocation = -1;
private int cachedTitleHeight = 24; // give it a default value
private IPerspectiveListener perspectiveListener = new IPerspectiveListener() {
public void perspectiveActivated(IWorkbenchPage page,
IPerspectiveDescriptor perspective) {
handlePerspectiveActivated(page, perspective);
}
public void perspectiveChanged(IWorkbenchPage page,
IPerspectiveDescriptor perspective, String changeId) {
handlePerspectiveChanged(page, perspective, changeId);
}
};
/**
* Constructor
*
* @param parent
* The parent Composite
* @param style
* The style of the widget to construct; only SWT.BORDER is
* allowed
* @param page
* The current workbench page
* @param pvProvider
* The provider that is to be used to create the flyout palette
* @param preferences
* To save/retrieve the preferences for the flyout
*/
public FlyoutPaletteComposite(Composite parent, int style,
IWorkbenchPage page, PaletteViewerProvider pvProvider,
FlyoutPreferences preferences) {
super(parent, style & SWT.BORDER);
provider = pvProvider;
prefs = preferences;
sash = createSash();
paletteContainer = createPaletteContainer();
hookIntoWorkbench(page.getWorkbenchWindow());
// Initialize the state properly
if (prefs.getPaletteWidth() <= 0)
prefs.setPaletteWidth(DEFAULT_PALETTE_SIZE);
setPaletteWidth(prefs.getPaletteWidth());
setDockLocation(prefs.getDockLocation());
updateState(page);
addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
Rectangle area = getClientArea();
/*
* @TODO:Pratik Sometimes, the editor is resized to 1,1 or 0,0
* (depending on the platform) when the editor is closed or
* maximized. We have to ignore such resizes. See Bug# 62748
*/
if (area.width > minWidth)
layout(true);
}
});
listeners.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
if (property.equals(PROPERTY_PALETTE_WIDTH))
prefs.setPaletteWidth(paletteWidth);
else if (property.equals(PROPERTY_DOCK_LOCATION))
prefs.setDockLocation(dock);
else if (property.equals(PROPERTY_STATE))
if (paletteState == STATE_COLLAPSED
|| paletteState == STATE_PINNED_OPEN)
prefs.setPaletteState(paletteState);
}
});
}
private void addListenerToCtrlHierarchy(Control parent, int eventType,
Listener listener) {
parent.addListener(eventType, listener);
if (!(parent instanceof Composite))
return;
Control[] children = ((Composite) parent).getChildren();
for (int i = 0; i < children.length; i++) {
addListenerToCtrlHierarchy(children[i], eventType, listener);
}
}
private IMemento capturePaletteState(PaletteViewer viewer) {
IMemento memento = XMLMemento.createWriteRoot("paletteState"); //$NON-NLS-1$
try {
viewer.saveState(memento);
} catch (RuntimeException re) {
// Bug 74843 -- See comment #1
// If there's a problem with saving the palette's state, it simply
// won't be
// transferred to the new palette
memento = null;
/*
* @TODO:Pratik You should log this exception.
*/
}
return memento;
}
private Control createFlyoutControlButton(Composite parent) {
return new ButtonCanvas(parent);
}
/**
* This is a convenient method to get a default FlyoutPreferences object.
* The returned FlyoutPreferences does not save any changes made to the
* given {@link Preferences Preferences}. It's upto the owner plugin to
* {@link Plugin#savePluginPreferences() save} the changes before it
* {@link Plugin#stop(org.osgi.framework.BundleContext) stops}.
*
* @param prefs
* {@link Plugin#getPluginPreferences() a plugin's Preferences}
* @return a default implementation of FlyoutPreferences that stores the
* settings in the given Preferences
* @since 3.2
*/
public static FlyoutPreferences createFlyoutPreferences(Preferences prefs) {
return new DefaultFlyoutPreferences(prefs);
}
private Composite createPaletteContainer() {
return new PaletteComposite(this, SWT.NONE);
}
private Composite createSash() {
return new Sash(this, SWT.NONE);
}
private Control createTitle(Composite parent, boolean isHorizontal) {
return new TitleCanvas(parent, isHorizontal);
}
private Control getPaletteViewerControl() {
Control result = null;
if (pViewer != null)
result = pViewer.getControl();
// Fix for bug 101703 -- pViewer.getControl().getParent() might be
// parented
// by paletteContainer
if (result != null && !result.isDisposed()
&& result.getParent() != paletteContainer)
result = result.getParent();
return result;
}
private void handlePerspectiveActivated(IWorkbenchPage page,
IPerspectiveDescriptor perspective) {
updateState(page);
}
private void handlePerspectiveChanged(IWorkbenchPage page,
IPerspectiveDescriptor perspective, String changeId) {
if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_SHOW)
|| changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE))
updateState(page);
}
// Will return false if the ancestor or descendant is null
private boolean isDescendantOf(Control ancestor, Control descendant) {
if (ancestor == null || descendant == null)
return false;
while (descendant != null) {
if (ancestor == descendant)
return true;
descendant = descendant.getParent();
}
return false;
}
private boolean isInState(int state) {
return (paletteState & state) != 0;
}
private boolean isMirrored() {
return (getStyle() & SWT.MIRRORED) != 0;
}
/**
* @see Composite#layout(boolean)
*/
public void layout(boolean changed) {
if (graphicalControl == null || graphicalControl.isDisposed())
return;
Rectangle area = getClientArea();
if (area.width == 0 || area.height == 0)
return;
int sashWidth = sash.computeSize(-1, -1).x;
int pWidth = paletteWidth;
int maxWidth = Math.min(area.width / 2, MAX_PALETTE_SIZE);
maxWidth = Math.max(maxWidth, minWidth);
pWidth = Math.max(pWidth, minWidth);
pWidth = Math.min(pWidth, maxWidth);
/*
* Fix for Bug# 65892 Laying out only when necessary helps reduce
* flicker on GTK in the case where the flyout palette is being resized
* past its maximum size.
*/
if (paletteState == cachedState && pWidth == cachedSize
&& cachedLocation == dock && cachedBounds == getSize())
return;
cachedState = paletteState;
cachedSize = pWidth;
cachedLocation = dock;
cachedBounds = getSize();
setRedraw(false);
if (isInState(STATE_HIDDEN)) {
sash.setVisible(false);
paletteContainer.setVisible(false);
graphicalControl.setBounds(area);
} else if (dock == PositionConstants.EAST)
layoutComponentsEast(area, sashWidth, pWidth);
else
layoutComponentsWest(area, sashWidth, pWidth);
sash.layout();
setRedraw(true);
update();
}
private void layoutComponentsEast(Rectangle area, int sashWidth, int pWidth) {
if (isInState(STATE_COLLAPSED)) {
paletteContainer.setVisible(false);
sash.setBounds(area.x + area.width - sashWidth, area.y, sashWidth,
area.height);
graphicalControl.setBounds(area.x, area.y, area.width - sashWidth,
area.height);
sash.setVisible(true);
} else if (isInState(STATE_EXPANDED)) {
paletteContainer.moveAbove(graphicalControl);
sash.moveAbove(paletteContainer);
paletteContainer.setBounds(area.x + area.width - pWidth, area.y,
pWidth, area.height);
sash.setBounds(area.x + area.width - pWidth - sashWidth, area.y,
sashWidth, area.height);
graphicalControl.setBounds(area.x, area.y, area.width - sashWidth,
area.height);
sash.setVisible(true);
paletteContainer.setVisible(true);
} else if (isInState(STATE_PINNED_OPEN)) {
paletteContainer.setBounds(area.x + area.width - pWidth, area.y,
pWidth, area.height);
sash.setBounds(area.x + area.width - pWidth - sashWidth, area.y,
sashWidth, area.height);
graphicalControl.setBounds(area.x, area.y, area.width - sashWidth
- pWidth, area.height);
sash.setVisible(true);
paletteContainer.setVisible(true);
}
}
private void layoutComponentsWest(Rectangle area, int sashWidth, int pWidth) {
if (isInState(STATE_COLLAPSED)) {
sash.setVisible(true);
paletteContainer.setVisible(false);
sash.setBounds(area.x, area.y, sashWidth, area.height);
graphicalControl.setBounds(area.x + sashWidth, area.y, area.width
- sashWidth, area.height);
} else if (isInState(STATE_EXPANDED)) {
sash.setVisible(true);
paletteContainer.setVisible(true);
paletteContainer.moveAbove(graphicalControl);
sash.moveAbove(paletteContainer);
paletteContainer.setBounds(area.x, area.y, pWidth, area.height);
sash.setBounds(area.x + pWidth, area.y, sashWidth, area.height);
graphicalControl.setBounds(area.x + sashWidth, area.y, area.width
- sashWidth, area.height);
} else if (isInState(STATE_PINNED_OPEN)) {
sash.setVisible(true);
paletteContainer.setVisible(true);
paletteContainer.setBounds(area.x, area.y, pWidth, area.height);
sash.setBounds(area.x + pWidth, area.y, sashWidth, area.height);
graphicalControl.setBounds(area.x + pWidth + sashWidth, area.y,
area.width - sashWidth - pWidth, area.height);
}
}
private void hookIntoWorkbench(final IWorkbenchWindow window) {
window.addPerspectiveListener(perspectiveListener);
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
window.removePerspectiveListener(perspectiveListener);
perspectiveListener = null;
}
});
}
private boolean restorePaletteState(PaletteViewer newPalette, IMemento state) {
if (state != null) {
try {
return newPalette.restoreState(state);
} catch (RuntimeException re) {
/*
* @TODO:Pratik You should log this exception
*/
}
}
return false;
}
/**
* If an external palette viewer is provided, palette state (that is
* captured in {@link PaletteViewer#saveState(IMemento)} -- active tool,
* drawer expansion state, drawer pin state, etc.) will be maintained when
* switching between the two viewers. Providing an external viewer, although
* recommended, is optional.
*
* @param viewer
* The palette viewer used in the PaletteView
*/
public void setExternalViewer(PaletteViewer viewer) {
if (viewer == null && externalViewer != null)
capturedPaletteState = capturePaletteState(externalViewer);
externalViewer = viewer;
if (externalViewer != null && pViewer != null)
transferState(pViewer, externalViewer);
}
private void setDockLocation(int position) {
if (position != PositionConstants.EAST
&& position != PositionConstants.WEST)
return;
if (position != dock) {
int oldPosition = dock;
dock = position;
listeners.firePropertyChange(PROPERTY_DOCK_LOCATION, oldPosition,
dock);
if (pViewer != null)
layout(true);
}
}
private void setPaletteWidth(int newSize) {
if (paletteWidth != newSize) {
int oldValue = paletteWidth;
paletteWidth = newSize;
listeners.firePropertyChange(PROPERTY_PALETTE_WIDTH, oldValue,
paletteWidth);
if (pViewer != null)
layout(true);
}
}
/**
* Sets the control along the side of which the palette is to be displayed.
* The given Control should be a child of this Composite. This method should
* only be invoked once.
*
* @param graphicalViewer
* the control of the graphical viewer; cannot be
* <code>null</code>
*/
public void setGraphicalControl(Control graphicalViewer) {
Assert.isTrue(graphicalViewer != null);
Assert.isTrue(graphicalViewer.getParent() == this);
Assert.isTrue(graphicalControl == null);
graphicalControl = graphicalViewer;
// UNSUPPORTED - api not implemented in RAP
// addListenerToCtrlHierarchy(graphicalControl, SWT.MouseEnter, new
// Listener()
// {
// public void handleEvent(Event event)
// {
// if (!isInState(STATE_EXPANDED))
// return;
// Display.getCurrent().timerExec(250, new Runnable()
// {
// public void run()
// {
// if (isDescendantOf(graphicalControl,
// Display.getCurrent().getCursorControl()) &&
// isInState(STATE_EXPANDED))
// setState(STATE_COLLAPSED);
// }
// });
// }
// });
}
/*
* @TODO:Pratik For 4.0, change the parameter of this method to be
* EditpartViewer instead of GraphicalViewer.
*/
/**
* This method hooks a DropTargetListener that collapses the flyout patette
* when the user drags something from the palette and moves the cursor to
* the primary viewer's control. If the auto-hide feature of the palette is
* to work properly when dragging, this method should be called before any
* other drop target listeners are added to the primary viewer.
*
* @param viewer
* the primary viewer
*/
public void hookDropTargetListener(GraphicalViewer viewer) {
viewer.addDropTargetListener(new TransferDropTargetListener() {
public void dragEnter(DropTargetEvent event) {
}
public void dragLeave(DropTargetEvent event) {
}
public void dragOperationChanged(DropTargetEvent event) {
}
public void dragOver(DropTargetEvent event) {
}
public void drop(DropTargetEvent event) {
}
public void dropAccept(DropTargetEvent event) {
}
public Transfer getTransfer() {
return TemplateTransfer.getInstance();
}
public boolean isEnabled(DropTargetEvent event) {
if (isInState(STATE_EXPANDED))
setState(STATE_COLLAPSED);
return false;
}
});
}
/*
* If the given state is invalid (as could be the case when
* FlyoutPreferences.getPaletteState() is invoked for the first time), it
* will be defaulted to STATE_COLLAPSED.
*/
private void setState(int newState) {
/*
* Fix for Bug# 69617 and Bug# 81248 FlyoutPreferences.getPaletteState()
* could return an invalid state if none is stored. In that case, we use
* the default state: STATE_COLLAPSED.
*/
if (newState != STATE_HIDDEN && newState != STATE_PINNED_OPEN
&& newState != STATE_EXPANDED)
newState = STATE_COLLAPSED;
if (paletteState == newState)
return;
int oldState = paletteState;
paletteState = newState;
switch (paletteState) {
case STATE_EXPANDED:
case STATE_COLLAPSED:
case STATE_PINNED_OPEN:
if (pViewer == null) {
pViewer = provider.createPaletteViewer(paletteContainer);
if (externalViewer != null)
transferState(externalViewer, pViewer);
else
restorePaletteState(pViewer, capturedPaletteState);
capturedPaletteState = null;
minWidth = Math.max(pViewer.getControl().computeSize(0, 0).x,
MIN_PALETTE_SIZE);
}
break;
case STATE_HIDDEN:
if (pViewer == null)
break;
if (externalViewer != null) {
provider.getEditDomain().setPaletteViewer(externalViewer);
transferState(pViewer, externalViewer);
}
if (provider.getEditDomain().getPaletteViewer() == pViewer)
provider.getEditDomain().setPaletteViewer(null);
Control pViewerCtrl = getPaletteViewerControl();
if (pViewerCtrl != null && !pViewerCtrl.isDisposed())
pViewerCtrl.dispose();
pViewer = null;
}
/*
* Fix for Bug# 63901 When the flyout collapses, if the palette has
* focus, throw focus to the graphical control. That way, hitting ESC
* will still deactivate the current tool and load the default one. Note
* that focus is being set on RulerComposite and not GraphicalViewer's
* control. But this is okay since RulerComposite passes the focus on to
* its first child, which is the graphical viewer's control.
*/
if (paletteState == STATE_COLLAPSED
&& pViewer.getControl().isFocusControl())
graphicalControl.setFocus();
layout(true);
listeners.firePropertyChange(PROPERTY_STATE, oldState, newState);
}
private void transferState(PaletteViewer src, PaletteViewer dest) {
restorePaletteState(dest, capturePaletteState(src));
}
private void updateState(IWorkbenchPage page) {
IViewReference view = page.findViewReference(PaletteView.ID);
if (view == null && isInState(STATE_HIDDEN))
setState(prefs.getPaletteState());
if (view != null && !isInState(STATE_HIDDEN))
setState(STATE_HIDDEN);
}
/**
* FlyoutPreferences is used to save/load the preferences for the flyout
* palette.
*
* @author Pratik Shah
* @since 3.0
*/
public interface FlyoutPreferences {
/**
* Should return {@link PositionConstants#EAST} or
* {@link PositionConstants#WEST}. Any other int will be ignored and the
* default dock location (EAST) will be used instead.
*
* @return the saved dock location of the Palette
*/
int getDockLocation();
/**
* When there is no saved state, this method can return any non-positive
* int (which will result in the palette using the default state --
* collapsed), or {@link FlyoutPaletteComposite#STATE_COLLAPSED}, or
* {@link FlyoutPaletteComposite#STATE_PINNED_OPEN}
*
* @return the saved state of the palette
*/
int getPaletteState();
/**
* When there is no saved width, this method can return any int
* (preferrably a non-positive int). Returning a non-positive int will
* cause the palette to be sized to the default size, whereas returning
* a postive int will find the closest match in the valid range (>=
* minimum and <= maximum)
*
* @return the saved width of the flyout palette
*/
int getPaletteWidth();
/**
* This method is invoked when the flyout palette's dock location is
* changed. The provided dock location should be persisted and returned
* in {@link #getDockLocation()}.
*
* @param location
* {@link PositionConstants#EAST} or
* {@link PositionConstants#WEST}
*/
void setDockLocation(int location);
/**
* This method is invoked when the flyout palette's state is changed
* (the new state becomes the default). The provided state should be
* persisted and returned in {@link #getPaletteState()}.
*
* @param state
* {@link FlyoutPaletteComposite#STATE_COLLAPSED} or
* {@link FlyoutPaletteComposite#STATE_PINNED_OPEN}
*/
void setPaletteState(int state);
/**
* This method is invoked when the flyout palette is resized. The
* provided width should be persisted and returned in
* {@link #getPaletteWidth()}.
*
* @param width
* the new size of the flyout palette
*/
void setPaletteWidth(int width);
}
private class Sash extends Composite {
private Control button;
private ControlPaintHandler helper;
public Sash(Composite parent, int style) {
super(parent, style);
helper = new ControlPaintHandler(this);
button = createFlyoutControlButton(this);
new SashDragManager();
// UNSUPPORTED - api not implemented in RAP
// addMouseTrackListener(new MouseTrackAdapter()
// {
// public void mouseHover(MouseEvent e)
// {
// if (isInState(STATE_COLLAPSED))
// setState(STATE_EXPANDED);
// }
// });
helper.addPaintListener(new PaintListener() {
public void paintControl(org.eclipse.swt.events.PaintEvent event) {
paintSash(event.gc);
};
});
addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
layout(true);
}
});
listeners.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(PROPERTY_STATE))
updateState();
}
});
}
public Point computeSize(int wHint, int hHint, boolean changed) {
if (isInState(STATE_PINNED_OPEN))
return new Point(3, 3);
// button size plus two pixels for the two lines to be drawn
return new Point(SASH_BUTTON_WIDTH + 2, cachedTitleHeight);
}
private void handleSashDragged(int shiftAmount) {
int newSize = paletteContainer.getBounds().width
+ (dock == PositionConstants.EAST ? -shiftAmount
: shiftAmount);
setPaletteWidth(newSize);
}
public void layout(boolean changed) {
if (button == null)
return;
if (isInState(STATE_PINNED_OPEN)) {
button.setVisible(false);
return;
}
button.setVisible(true);
Rectangle area = getClientArea();
button.setBounds(area.x + 1, area.y + 1, SASH_BUTTON_WIDTH,
cachedTitleHeight - 1);
if (transferFocus) {
transferFocus = false;
button.setFocus();
}
}
private void paintSash(GC gc) {
Rectangle bounds = getBounds();
if (isInState(STATE_PINNED_OPEN)) {
gc.setBackground(PaletteColorUtil.WIDGET_BACKGROUND);
gc.fillRectangle(0, 0, bounds.width, bounds.height);
gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
gc.drawLine(0, 0, bounds.width, 0);
gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
gc.drawLine(0, bounds.height - 1, bounds.width - 1,
bounds.height - 1);
gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
gc.drawLine(0, 0, 0, bounds.height);
gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
gc.drawLine(bounds.width - 1, 0, bounds.width - 1,
bounds.height - 1);
} else {
gc.setForeground(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
gc.drawLine(0, 0, 0, bounds.height);
gc.drawLine(bounds.width - 1, 0, bounds.width - 1,
bounds.height);
gc.setForeground(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
gc.drawLine(1, 0, 1, bounds.height);
gc.setForeground(PaletteColorUtil.WIDGET_BACKGROUND_LIST_BACKGROUND_85);
gc.drawLine(2, 0, 2, bounds.height);
}
}
private void updateState() {
setCursor(isInState(STATE_EXPANDED | STATE_PINNED_OPEN) ? SharedCursors.SIZEWE
: null);
}
private class SashDragManager extends MouseAdapter implements
MouseMoveListener {
protected boolean dragging = false;
protected boolean correctState = false;
protected boolean mouseDown = false;
protected int origX;
protected Listener keyListener = new Listener() {
public void handleEvent(Event event) {
if (event.keyCode == SWT.ALT || event.keyCode == SWT.ESC) {
dragging = false;
Display.getCurrent().removeFilter(SWT.KeyDown, this);
}
event.doit = false;
event.type = SWT.None;
}
};
public SashDragManager() {
// UNSUPPORTED - api not implemented in RAP
// Sash.this.addMouseMoveListener(this);
Sash.this.addMouseListener(this);
}
public void mouseDown(MouseEvent me) {
if (me.button != 1)
return;
mouseDown = true;
correctState = isInState(STATE_EXPANDED | STATE_PINNED_OPEN);
origX = me.x;
Display.getCurrent().addFilter(SWT.KeyDown, keyListener);
}
public void mouseMove(MouseEvent me) {
if (mouseDown)
dragging = true;
if (dragging && correctState)
handleSashDragged(me.x - origX);
}
public void mouseUp(MouseEvent me) {
Display.getCurrent().removeFilter(SWT.KeyDown, keyListener);
if (!dragging && me.button == 1) {
if (isInState(STATE_COLLAPSED))
setState(STATE_EXPANDED);
else if (isInState(STATE_EXPANDED))
setState(STATE_COLLAPSED);
}
dragging = false;
correctState = false;
mouseDown = false;
}
}
}
private class ResizeAction extends Action {
public ResizeAction() {
super(PaletteMessages.RESIZE_LABEL);
}
public boolean isEnabled() {
return !isInState(STATE_COLLAPSED);
}
public void run() {
final Tracker tracker = new Tracker(FlyoutPaletteComposite.this,
SWT.RIGHT | SWT.LEFT);
Rectangle[] rects = new Rectangle[1];
rects[0] = sash.getBounds();
tracker.setCursor(SharedCursors.SIZEE);
tracker.setRectangles(rects);
if (tracker.open()) {
int deltaX = sash.getBounds().x - tracker.getRectangles()[0].x;
if (dock == PositionConstants.WEST)
deltaX = -deltaX;
setPaletteWidth(paletteContainer.getBounds().width + deltaX);
}
tracker.dispose();
}
}
private class TitleDragManager extends MouseAdapter implements Listener,
MouseTrackListener {
protected boolean switchDock = false;
protected boolean dragging = false;
protected int threshold;
public TitleDragManager(Control ctrl) {
ctrl.addListener(SWT.DragDetect, this);
ctrl.addMouseListener(this);
// UNSUPPORTED - api not implemented in RAP
// ctrl.addMouseTrackListener(this);
}
public void handleEvent(Event event) {
dragging = true;
switchDock = false;
threshold = dock == PositionConstants.EAST ? Integer.MAX_VALUE / 2
: -1;
final Composite flyout = FlyoutPaletteComposite.this;
final Rectangle flyoutBounds = flyout.getBounds();
final int switchThreshold = flyoutBounds.x
+ (flyoutBounds.width / 2);
Rectangle bounds = sash.getBounds();
if (paletteContainer.getVisible())
bounds = bounds.union(paletteContainer.getBounds());
final Rectangle origBounds = Display.getCurrent().map(flyout, null,
bounds);
final Tracker tracker = new Tracker(Display.getDefault(), SWT.NULL);
tracker.setRectangles(new Rectangle[] { origBounds });
final Display display = Display.getCurrent();
tracker.setStippled(true);
tracker.addListener(SWT.Move, new Listener() {
public void handleEvent(final Event evt) {
display.syncExec(new Runnable() {
public void run() {
Control ctrl = display.getCursorControl();
Point location = display.getCursorLocation(); // evt.x,
// evt.y
Point pt = flyout.toControl(location.x, location.y);
switchDock = isDescendantOf(graphicalControl, ctrl)
&& ((dock == PositionConstants.WEST && pt.x > threshold - 10) || (dock == PositionConstants.EAST && pt.x < threshold + 10));
boolean invalid = false;
if (!switchDock)
invalid = !isDescendantOf(
FlyoutPaletteComposite.this, ctrl);
if (switchDock) {
if (dock == PositionConstants.WEST) {
threshold = Math.max(threshold, pt.x);
threshold = Math.min(threshold,
switchThreshold);
} else {
threshold = Math.min(threshold, pt.x);
threshold = Math.max(threshold,
switchThreshold);
}
}
Rectangle placeHolder = origBounds;
if (switchDock) {
if (dock == PositionConstants.EAST)
placeHolder = new Rectangle(0, 0,
origBounds.width, origBounds.height);
else
placeHolder = new Rectangle(
flyoutBounds.width
- origBounds.width, 0,
origBounds.width, origBounds.height);
placeHolder = display.map(flyout, null,
placeHolder);
}
// update the cursor
int cursor;
if (invalid)
cursor = DragCursors.INVALID;
else if ((!switchDock && dock == PositionConstants.EAST)
|| (switchDock && dock == PositionConstants.WEST))
cursor = DragCursors.RIGHT;
else
cursor = DragCursors.LEFT;
if (isMirrored()) {
if (cursor == DragCursors.RIGHT)
cursor = DragCursors.LEFT;
else if (cursor == DragCursors.LEFT)
cursor = DragCursors.RIGHT;
}
tracker.setCursor(DragCursors.getCursor(cursor));
// update the rectangle only if it has changed
if (!tracker.getRectangles()[0].equals(placeHolder))
tracker.setRectangles(new Rectangle[] { placeHolder });
}
});
}
});
// HACK for DND in RAP
Job dragJob = new Job("Drag-Job") {
protected IStatus run(IProgressMonitor monitor) {
if (tracker.open()) {
display.asyncExec(new Runnable() {
public void run() {
IDropTarget dropTarget = null;
Point finalLocation = display
.getCursorLocation();
Control targetControl = display
.getCursorControl();
if (switchDock) {
setDockLocation(PositionConstants.EAST_WEST
& ~dock);
// mouse up is received by the tracker and
// by this listener, so
// we set dragging
// to be false
dragging = false;
}
// Cleanup...
tracker.dispose();
}
});
}
return Status.OK_STATUS;
}
};
dragJob.schedule();
}
public void mouseEnter(MouseEvent e) {
}
public void mouseExit(MouseEvent e) {
}
public void mouseHover(MouseEvent e) {
/*
* @TODO:Pratik Mouse hover events are received if the hover occurs
* just before you finish or cancel the drag. Open a bugzilla about
* it?
*/
if (isInState(STATE_COLLAPSED))
setState(STATE_EXPANDED);
}
public void mouseUp(MouseEvent me) {
if (me.button != 1)
return;
if (isInState(STATE_COLLAPSED))
setState(STATE_EXPANDED);
else if (isInState(STATE_EXPANDED))
setState(STATE_COLLAPSED);
}
}
private class PaletteComposite extends Composite {
protected Control button, title;
public PaletteComposite(Composite parent, int style) {
super(parent, style);
createComponents();
listeners.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(PROPERTY_STATE))
updateState();
else if (evt.getPropertyName().equals(
PROPERTY_DOCK_LOCATION))
if (getVisible())
layout(true);
}
});
addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
layout(true);
}
});
updateState();
}
protected void createComponents() {
title = createTitle(this, true);
button = createFlyoutControlButton(this);
}
public void layout(boolean changed) {
Control pCtrl = getPaletteViewerControl();
if (pCtrl == null || pCtrl.isDisposed())
return;
Rectangle area = getClientArea();
boolean buttonVisible = button.getVisible();
Point titleSize = title.computeSize(-1, -1);
Point buttonSize = buttonVisible ? button.computeSize(-1, -1)
: new Point(0, 0);
cachedTitleHeight = Math.max(titleSize.y, buttonSize.y);
if (buttonVisible) {
buttonSize.x = Math.max(cachedTitleHeight, buttonSize.x);
}
if (dock == PositionConstants.EAST) {
int buttonX = area.width - buttonSize.x;
button.setBounds(buttonX, 0, buttonSize.x, cachedTitleHeight);
title.setBounds(0, 0, buttonX, cachedTitleHeight);
} else {
int titleX = buttonSize.x;
button.setBounds(0, 0, buttonSize.x, cachedTitleHeight);
title.setBounds(titleX, 0, area.width - titleX,
cachedTitleHeight);
}
area.y += cachedTitleHeight;
area.height -= cachedTitleHeight;
pCtrl.setBounds(area);
}
protected void updateState() {
button.setVisible(isInState(STATE_PINNED_OPEN));
if (transferFocus && button.getVisible()) {
transferFocus = false;
button.setFocus();
}
layout(true);
}
}
private static class TitleLabel extends Label {
protected static final Border BORDER = new MarginBorder(4, 3, 4, 3);
protected static final Border TOOL_TIP_BORDER = new MarginBorder(0, 2,
0, 2);
public TitleLabel(boolean isHorizontal) {
super(GEFMessages.Palette_Label, InternalImages
.get(InternalImages.IMG_PALETTE));
setLabelAlignment(PositionConstants.LEFT);
setBorder(BORDER);
Label tooltip = new Label(getText());
tooltip.setBorder(TOOL_TIP_BORDER);
setToolTip(tooltip);
setForegroundColor(ColorConstants.listForeground);
}
public IFigure getToolTip() {
if (isTextTruncated())
return super.getToolTip();
return null;
}
protected void paintFigure(Graphics graphics) {
// paint the gradient
graphics.pushState();
org.eclipse.draw2d.geometry.Rectangle r = org.eclipse.draw2d.geometry.Rectangle.SINGLETON;
r.setBounds(getBounds());
graphics.setForegroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
graphics.setBackgroundColor(PaletteColorUtil.WIDGET_BACKGROUND);
graphics.fillGradient(r, true);
// draw bottom border
graphics.setForegroundColor(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
graphics.drawLine(r.getBottomLeft().getTranslated(0, -1), r
.getBottomRight().getTranslated(0, -1));
graphics.popState();
// paint the text and icon
super.paintFigure(graphics);
// paint the focus rectangle around the text
if (hasFocus()) {
org.eclipse.draw2d.geometry.Rectangle textBounds = getTextBounds();
// We reduce the width by 1 because FigureUtilities grows it by
// 1 unnecessarily
textBounds.width--;
graphics.drawFocus(bounds.getResized(-1, -1).intersect(
textBounds.getExpanded(getInsets())));
}
}
}
private class ButtonCanvas extends Canvas {
private LightweightSystem lws;
public ButtonCanvas(Composite parent) {
super(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
init();
provideAccSupport();
}
public Point computeSize(int wHint, int hHint, boolean changed) {
Dimension size = lws.getRootFigure().getPreferredSize(wHint, hHint);
size.union(new Dimension(wHint, hHint));
return new org.eclipse.swt.graphics.Point(size.width, size.height);
}
private int getArrowDirection() {
int direction = PositionConstants.EAST;
if (isInState(STATE_EXPANDED | STATE_PINNED_OPEN))
direction = dock == PositionConstants.WEST ? PositionConstants.WEST
: PositionConstants.EAST;
else
direction = dock == PositionConstants.WEST ? PositionConstants.EAST
: PositionConstants.WEST;
if (isMirrored()) {
if (direction == PositionConstants.WEST)
direction = PositionConstants.EAST;
else
direction = PositionConstants.WEST;
}
return direction;
}
private String getButtonTooltipText() {
if (isInState(STATE_COLLAPSED))
return PaletteMessages.PALETTE_SHOW;
return PaletteMessages.PALETTE_HIDE;
}
private void init() {
setCursor(SharedCursors.ARROW);
lws = new LightweightSystem();
lws.setControl(this);
final ArrowButton b = new ArrowButton(getArrowDirection());
b.setRolloverEnabled(true);
b.setBorder(new ButtonBorder(ButtonBorder.SCHEMES.TOOLBAR));
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
transferFocus = true;
if (isInState(STATE_COLLAPSED))
setState(STATE_PINNED_OPEN);
else
setState(STATE_COLLAPSED);
}
});
listeners.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(PROPERTY_STATE)) {
b.setDirection(getArrowDirection());
setToolTipText(getButtonTooltipText());
} else if (evt.getPropertyName().equals(
PROPERTY_DOCK_LOCATION))
b.setDirection(getArrowDirection());
}
});
lws.setContents(b);
}
private void provideAccSupport() {
getAccessible().addAccessibleListener(new AccessibleAdapter() {
public void getDescription(AccessibleEvent e) {
e.result = PaletteMessages.ACC_DESC_PALETTE_BUTTON;
}
public void getHelp(AccessibleEvent e) {
getDescription(e);
}
public void getName(AccessibleEvent e) {
e.result = getToolTipText();
}
});
getAccessible().addAccessibleControlListener(
new AccessibleControlAdapter() {
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_PUSHBUTTON;
}
});
}
private class ArrowButton extends Button {
private Triangle triangle;
/**
* Creates a new instance
*
* @param direction
* the direction the arrow should face
* (PositionConstants.RIGHT or PositionConstants.LEFT)
*/
public ArrowButton(int direction) {
super();
setDirection(direction);
triangle = new Triangle();
triangle.setOutline(true);
triangle.setBackgroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
triangle.setForegroundColor(PaletteColorUtil.WIDGET_DARK_SHADOW);
setContents(triangle);
}
public void setDirection(int direction) {
if (triangle != null) {
triangle.setDirection(direction);
}
}
protected void layout() {
org.eclipse.draw2d.geometry.Rectangle clientArea = getBounds();
triangle.setBounds(new org.eclipse.draw2d.geometry.Rectangle(
clientArea.getCenter().getTranslated(
-ARROW_SIZE.width / 2, -ARROW_SIZE.height / 2),
ARROW_SIZE));
}
protected void paintFigure(Graphics graphics) {
super.paintFigure(graphics);
// paint the gradient
graphics.pushState();
org.eclipse.draw2d.geometry.Rectangle r = org.eclipse.draw2d.geometry.Rectangle.SINGLETON;
r.setBounds(getBounds());
graphics.setForegroundColor(PaletteColorUtil.WIDGET_LIST_BACKGROUND);
graphics.setBackgroundColor(PaletteColorUtil.WIDGET_BACKGROUND);
graphics.fillGradient(r, true);
graphics.popState();
// draw bottom border
graphics.setForegroundColor(PaletteColorUtil.WIDGET_NORMAL_SHADOW);
graphics.drawLine(r.getBottomLeft().getTranslated(0, -1), r
.getBottomRight().getTranslated(0, -1));
}
}
}
private class TitleCanvas extends Canvas {
private LightweightSystem lws;
public TitleCanvas(Composite parent, boolean horizontal) {
super(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
init(horizontal);
provideAccSupport();
}
/**
* @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
*/
public Point computeSize(int wHint, int hHint, boolean changed) {
Dimension size = lws.getRootFigure().getPreferredSize(wHint, hHint);
size.union(new Dimension(wHint, hHint));
return new org.eclipse.swt.graphics.Point(size.width, size.height);
}
private void init(boolean isHorizontal) {
final IFigure contents = new TitleLabel(true);
contents.setRequestFocusEnabled(true);
contents.setFocusTraversable(true);
contents.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent fe) {
fe.gainer.repaint();
}
public void focusLost(FocusEvent fe) {
fe.loser.repaint();
}
});
lws = new LightweightSystem();
lws.setControl(this);
lws.setContents(contents);
setCursor(SharedCursors.SIZEALL);
FONT_MGR.register(this);
new TitleDragManager(this);
final MenuManager manager = new MenuManager();
MenuManager mgr = new MenuManager(PaletteMessages.DOCK_LABEL);
mgr.add(new ChangeDockAction(PaletteMessages.LEFT_LABEL,
PositionConstants.WEST));
mgr.add(new ChangeDockAction(PaletteMessages.RIGHT_LABEL,
PositionConstants.EAST));
manager.add(new ResizeAction());
manager.add(mgr);
setMenu(manager.createContextMenu(this));
mgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager menuMgr) {
IContributionItem[] items = menuMgr.getItems();
for (int i = 0; i < items.length; i++) {
((ActionContributionItem) items[i]).update();
}
}
});
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
FONT_MGR.unregister(TitleCanvas.this);
manager.dispose();
}
});
}
private void provideAccSupport() {
getAccessible().addAccessibleListener(new AccessibleAdapter() {
public void getDescription(AccessibleEvent e) {
e.result = PaletteMessages.ACC_DESC_PALETTE_TITLE;
}
public void getHelp(AccessibleEvent e) {
getDescription(e);
}
public void getName(AccessibleEvent e) {
e.result = GEFMessages.Palette_Label;
}
});
getAccessible().addAccessibleControlListener(
new AccessibleControlAdapter() {
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_LABEL;
}
});
}
public void setFont(Font font) {
((IFigure) lws.getRootFigure().getChildren().get(0)).setFont(font);
if (isVisible()) {
/*
* If this canvas is in the sash, we want the
* FlyoutPaletteComposite to layout (which will cause the sash
* to be resized and laid out). However, if this canvas is in
* the paletteContainer, the paletteContainer's bounds won't
* change, and hence it won't layout. Thus, we also invoke
* getParent().layout().
*/
FlyoutPaletteComposite.this.layout(true);
getParent().layout(true);
}
}
}
private class ChangeDockAction extends Action {
private int position;
/**
* Constructor
*
* @param text
* this action's text
* @param position
* the dock side that this action represents:
* PositionConstants.EAST or PositionConstants.WEST
*/
public ChangeDockAction(String text, int position) {
super(text, IAction.AS_RADIO_BUTTON);
this.position = position;
}
/**
* This Action is checked when the palette is docked on the side this
* action represents
*
* @see org.eclipse.jface.action.IAction#isChecked()
*/
public boolean isChecked() {
return dock == position;
}
/**
* Changes the palette's dock location to the side this action
* represents
*
* @see org.eclipse.jface.action.IAction#run()
*/
public void run() {
setDockLocation(position);
}
}
private static class FontManager {
private final String fontName = getFontType();
private List registrants = new ArrayList();
private Font titleFont;
private final IPropertyChangeListener fontListener = new IPropertyChangeListener() {
public void propertyChange(
org.eclipse.jface.util.PropertyChangeEvent event) {
if (fontName.equals(event.getProperty()))
handleFontChanged();
}
};
private FontManager() {
}
protected final Font createTitleFont() {
return JFaceResources.getFont(fontName);
}
protected void dispose() {
titleFont = null;
JFaceResources.getFontRegistry().removeListener(fontListener);
}
protected String getFontType() {
return JFaceResources.DIALOG_FONT;
}
protected void handleFontChanged() {
if (titleFont == null)
return;
Font oldFont = titleFont;
titleFont = createTitleFont();
for (Iterator iter = registrants.iterator(); iter.hasNext();)
((Control) iter.next()).setFont(titleFont);
oldFont.dispose();
}
protected void init() {
titleFont = createTitleFont();
JFaceResources.getFontRegistry().addListener(fontListener);
}
public void register(Control ctrl) {
if (titleFont == null)
init();
ctrl.setFont(titleFont);
registrants.add(ctrl);
}
public void unregister(Control ctrl) {
registrants.remove(ctrl);
if (registrants.isEmpty())
dispose();
}
}
/**
* Default implementation of FlyoutPreferences that stores the flyout
* palette settings in the given Preferences.
*
* @author Pratik Shah
* @since 3.2
*/
private static class DefaultFlyoutPreferences implements FlyoutPreferences {
/*
* There's no need to set the default for these properties since the
* default-default of 0 for ints will suffice.
*/
private static final String PALETTE_DOCK_LOCATION = "org.eclipse.gef.pdock"; //$NON-NLS-1$
private static final String PALETTE_SIZE = "org.eclipse.gef.psize"; //$NON-NLS-1$
private static final String PALETTE_STATE = "org.eclipse.gef.pstate"; //$NON-NLS-1$
private Preferences prefs;
private DefaultFlyoutPreferences(Preferences preferences) {
prefs = preferences;
}
public int getDockLocation() {
return prefs.getInt(PALETTE_DOCK_LOCATION);
}
public int getPaletteState() {
return prefs.getInt(PALETTE_STATE);
}
public int getPaletteWidth() {
return prefs.getInt(PALETTE_SIZE);
}
public void setDockLocation(int location) {
prefs.setValue(PALETTE_DOCK_LOCATION, location);
}
public void setPaletteState(int state) {
prefs.setValue(PALETTE_STATE, state);
}
public void setPaletteWidth(int width) {
prefs.setValue(PALETTE_SIZE, width);
}
}
private static class DragCursors {
public static final int INVALID = 0;
public static final int LEFT = 1;
public static final int RIGHT = 2;
private final static Cursor cursors[] = new Cursor[3];
/**
* Return the cursor for a drop scenario, as identified by code. Code
* must be one of INVALID, LEFT, RIGHT. If the code is not found default
* to INVALID. Note that since these three cursors are static, they will
* only be created once for the lifetime of the eclipse session and
* shared (i.e this is not an image leak).
*
* @param code
* the code
* @return the cursor
*/
public static Cursor getCursor(int code) {
Display display = Display.getCurrent();
// UNSUPPORTED - custom cursors not available in RAP
// if (cursors[code] == null) {
// ImageDescriptor source = null;
// ImageDescriptor mask = null;
// switch (code) {
// case LEFT:
// source = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_LEFT_SOURCE);
// mask = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_LEFT_MASK);
// cursors[LEFT] = new Cursor(display, source.getImageData(),
// mask.getImageData(), 16, 16);
// break;
// case RIGHT:
// source = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_RIGHT_SOURCE);
// mask = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_RIGHT_MASK);
// cursors[RIGHT] = new Cursor(display, source.getImageData(),
// mask.getImageData(), 16, 16);
// break;
// default:
// case INVALID:
// source = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_INVALID_SOURCE);
// mask = PlatformUI
// .getWorkbench()
// .getSharedImages()
// .getImageDescriptor(
// ISharedImages.IMG_OBJS_DND_INVALID_MASK);
// cursors[INVALID] = new Cursor(display,
// source.getImageData(), mask.getImageData(), 16, 16);
// break;
// }
// }
// return cursors[code];
return null;
}
}
}