diff options
author | Tor Norbye <tnorbye@google.com> | 2012-04-19 15:05:27 -0700 |
---|---|---|
committer | android code review <noreply-gerritcodereview@google.com> | 2012-04-19 15:05:28 -0700 |
commit | 7d5e809721ca0f3460afcd8ae32fa366c86ec978 (patch) | |
tree | f456b9a3b7e64bee9a8f9980f58c641aa6dc3a7e /propertysheet/src/org/eclipse | |
parent | 710a161c9c528b5e5cb5cd6d0d41736881c9697f (diff) | |
parent | 4b1a9d7baa71df312585022c22e8025fafaba95a (diff) | |
download | eclipse-windowbuilder-7d5e809721ca0f3460afcd8ae32fa366c86ec978.tar.gz |
Merge "Add support for window docking in the property sheet code"android-cts-4.1_r4android-cts-4.1_r2android-cts-4.1_r1android-4.1.2_r2.1android-4.1.2_r2android-4.1.2_r1android-4.1.1_r6.1android-4.1.1_r6android-4.1.1_r5android-4.1.1_r4android-4.1.1_r3android-4.1.1_r2android-4.1.1_r1.1android-4.1.1_r1jb-releasejb-mr0-releasejb-dev
Diffstat (limited to 'propertysheet/src/org/eclipse')
19 files changed, 1677 insertions, 0 deletions
diff --git a/propertysheet/src/org/eclipse/wb/core/controls/Messages.java b/propertysheet/src/org/eclipse/wb/core/controls/Messages.java index 3d83ffc..d745db5 100644 --- a/propertysheet/src/org/eclipse/wb/core/controls/Messages.java +++ b/propertysheet/src/org/eclipse/wb/core/controls/Messages.java @@ -6,6 +6,12 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.wb.core.controls.messages"; //$NON-NLS-1$ public static String CSpinner_canNotParse; public static String CSpinner_outOfRange; + public static String FlyoutControlComposite_dockBottom; + public static String FlyoutControlComposite_dockLeft; + public static String FlyoutControlComposite_dockManager; + public static String FlyoutControlComposite_dockRight; + public static String FlyoutControlComposite_dockTop; + public static String FlyoutControlComposite_title; static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/propertysheet/src/org/eclipse/wb/core/controls/SelfOrientingSashForm.java b/propertysheet/src/org/eclipse/wb/core/controls/SelfOrientingSashForm.java new file mode 100644 index 0000000..ea94304 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/SelfOrientingSashForm.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; + +/** + * Instances of the class <code>SelfOrientingSashForm</code> implement a sash form that will + * automatically reset its orientation based on the relationship between the width and height of the + * client area. This is done so that the sash form can be placed in a view that will sometimes be + * tall and narrow and sometimes be short and wide and still lay out its children in a pleasing way. + * <p> + * + * @author unknown + * @author Brian Wilkerson + * @version $Revision: 1.2 $ + * @coverage core.control + */ +public class SelfOrientingSashForm extends SashForm { + //////////////////////////////////////////////////////////////////////////// + // + // Constructors + // + //////////////////////////////////////////////////////////////////////////// + /** + * Initialize a newly created control to have the given parent and style. The style describes the + * behavior and appearance of this control. + * <p> + * The style value is either one of the style constants defined in the class <code>SWT</code> + * which is applicable to instances of this class, or must be built by <em>bitwise OR</em>'ing + * together (that is, using the <code>int</code> "|" operator) two or more of those + * <code>SWT</code> style constants. The class description for all SWT widget classes should + * include a comment which describes the style constants which are applicable to the class. + * </p> + * + * @param parent + * a widget which will be the parent of the new instance (not null) + * @param style + * the style of widget to construct + * + * @exception IllegalArgumentException + * <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * </ul> + * @exception SWTException + * <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the + * parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + */ + public SelfOrientingSashForm(Composite parent, int style) { + super(parent, style); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Layout + // + //////////////////////////////////////////////////////////////////////////// + /** + * Returns SWT.HORIZONTAL if the controls in the SashForm are laid out side by side or + * SWT.VERTICAL if the controls in the SashForm are laid out top to bottom. + * + * @return SWT.HORIZONTAL or SWT.VERTICAL + */ + @Override + public int getOrientation() { + int currentOrientation = super.getOrientation(); + if (inSetOrientation) { + return currentOrientation; + } + int preferredOrientation = isDisposed() ? currentOrientation : getPreferredOrientation(); + if (currentOrientation != preferredOrientation) { + setOrientation(preferredOrientation); + } + return preferredOrientation; + } + + boolean inSetOrientation = false; + + @Override + public void setOrientation(int orientation) { + if (inSetOrientation) { + return; + } + inSetOrientation = true; + super.setOrientation(orientation); + inSetOrientation = false; + } + + /** + * If the receiver has a layout, ask the layout to <em>lay out</em> (that is, set the size and + * location of) the receiver's children. If the argument is <code>true</code> the layout must not + * rely on any cached information it is keeping about the children. If it is <code>false</code> + * the layout may (potentially) simplify the work it is doing by assuming that the state of the + * none of the receiver's children has changed since the last layout. If the receiver does not + * have a layout, do nothing. + * + * @param changed + * <code>true</code> if the layout must flush its caches, and <code>false</code> + * otherwise + * + * @exception SWTException + * <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the + * receiver</li> + * </ul> + */ + @Override + public void layout(boolean changed) { + Rectangle area; + int oldOrientation, newOrientation; + area = getClientArea(); + if (area.width > 0 && area.height > 0) { + oldOrientation = super.getOrientation(); + newOrientation = SWT.HORIZONTAL; + if (area.width < area.height) { + newOrientation = SWT.VERTICAL; + } + if (newOrientation != oldOrientation) { + setOrientation(newOrientation); + changed = true; + } + } + super.layout(changed); + } + + private int getPreferredOrientation() { + Rectangle area = getClientArea(); + if (area.width > 0 && area.height > 0 && area.width < area.height) { + return SWT.VERTICAL; + } + return SWT.HORIZONTAL; + } +}
\ No newline at end of file diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/FlyoutControlComposite.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/FlyoutControlComposite.java new file mode 100644 index 0000000..23d2f83 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/FlyoutControlComposite.java @@ -0,0 +1,1007 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +import org.eclipse.jface.action.Action; +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.swt.SWT; +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.MouseTrackAdapter; +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.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Sash; +import org.eclipse.swt.widgets.Tracker; +import org.eclipse.wb.core.controls.Messages; +import org.eclipse.wb.draw2d.IColorConstants; +import org.eclipse.wb.draw2d.ICursorConstants; +import org.eclipse.wb.internal.core.utils.ui.DrawUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link FlyoutControlComposite} is container for two {@link Control}'s. One (client control) is + * used to fill client area. Second (flyout control) can be docked to any enabled position or + * temporary hidden. + * + * @author scheglov_ke + * @coverage core.control + */ +public final class FlyoutControlComposite extends Composite { + private static final int RESIZE_WIDTH = 5; + private static final int TITLE_LINES = 30; + private static final int TITLE_MARGIN = 5; + private static final Font TITLE_FONT = JFaceResources.getFontRegistry().getBold( + JFaceResources.DEFAULT_FONT); + //////////////////////////////////////////////////////////////////////////// + // + // Images + // + //////////////////////////////////////////////////////////////////////////// + private static final Image PIN = loadImage("icons/pin.gif"); + private static final Image ARROW_LEFT = loadImage("icons/arrow_left.gif"); + private static final Image ARROW_RIGHT = loadImage("icons/arrow_right.gif"); + private static final Image ARROW_TOP = loadImage("icons/arrow_top.gif"); + private static final Image ARROW_BOTTOM = loadImage("icons/arrow_bottom.gif"); + + private static Image loadImage(String path) { + return DrawUtils.loadImage(FlyoutControlComposite.class, path); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Instance fields + // + //////////////////////////////////////////////////////////////////////////// + private final IFlyoutPreferences m_preferences; + private final FlyoutContainer m_flyoutContainer; + private int m_minWidth = 150; + private int m_validDockLocations = -1; + private final List<IFlyoutMenuContributor> m_menuContributors = + new ArrayList<IFlyoutMenuContributor>(); + + //////////////////////////////////////////////////////////////////////////// + // + // Constructor + // + //////////////////////////////////////////////////////////////////////////// + public FlyoutControlComposite(Composite parent, int style, IFlyoutPreferences preferences) { + super(parent, style); + m_preferences = preferences; + // add listeners + addListener(SWT.Resize, new Listener() { + @Override + public void handleEvent(Event event) { + if (getShell().getMinimized()) { + return; + } + layout(); + } + }); + // create container for flyout control + m_flyoutContainer = new FlyoutContainer(this, SWT.NO_BACKGROUND); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Parents + // + //////////////////////////////////////////////////////////////////////////// + /** + * @return the parent {@link Composite} for flyout {@link Control}. + */ + public Composite getFlyoutParent() { + return m_flyoutContainer; + } + + /** + * @return the parent {@link Composite} for client {@link Control}. + */ + public Composite getClientParent() { + return this; + } + + /** + * Sets the bit set with valid docking locations. + */ + public void setValidDockLocations(int validDockLocations) { + m_validDockLocations = validDockLocations; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Access + // + //////////////////////////////////////////////////////////////////////////// + /** + * Sets the minimal width of flyout. + */ + public void setMinWidth(int minWidth) { + m_minWidth = minWidth; + } + + /** + * Sets the text of title. + */ + public void setTitleText(String text) { + m_flyoutContainer.setTitleText(text); + } + + /** + * Adds new {@link IFlyoutMenuContributor}. + */ + public void addMenuContributor(IFlyoutMenuContributor contributor) { + if (!m_menuContributors.contains(contributor)) { + m_menuContributors.add(contributor); + } + } + + //////////////////////////////////////////////////////////////////////////// + // + // Layout + // + //////////////////////////////////////////////////////////////////////////// + @Override + public void layout() { + Rectangle clientArea = getClientArea(); + int state = m_preferences.getState(); + Control client = getChildren()[1]; + // check, may be "clientArea" is empty, for example because CTabFolder page is not visible + if (clientArea.width == 0 || clientArea.height == 0) { + return; + } + // check, maybe flyout has no Control, so "client" should fill client area + if (m_flyoutContainer.getControl() == null + // BEGIN ADT MODIFICATIONS + || !m_flyoutContainer.getControl().getVisible() + // END ADT MODIFICATIONS + ) { + m_flyoutContainer.setBounds(0, 0, 0, 0); + client.setBounds(clientArea); + return; + } + // prepare width to display + int width; + int offset; + if (state == IFlyoutPreferences.STATE_OPEN) { + width = m_preferences.getWidth(); + // limit maximum value + if (isHorizontal()) { + width = Math.min(clientArea.width / 2, width); + } else { + width = Math.min(clientArea.height / 2, width); + } + // limit minimum value + width = Math.max(width, m_minWidth); + width = Math.max(width, 2 * m_flyoutContainer.m_titleHeight + m_flyoutContainer.m_titleWidth); + // remember actual width + m_preferences.setWidth(width); + // + offset = width; + } else if (state == IFlyoutPreferences.STATE_EXPANDED) { + offset = m_flyoutContainer.m_titleHeight; + width = m_preferences.getWidth(); + } else { + width = m_flyoutContainer.m_titleHeight; + offset = width; + } + // change bounds for flyout container and client control + { + if (isWest()) { + m_flyoutContainer.setBounds(0, 0, width, clientArea.height); + client.setBounds(offset, 0, clientArea.width - offset, clientArea.height); + } else if (isEast()) { + m_flyoutContainer.setBounds(clientArea.width - width, 0, width, clientArea.height); + client.setBounds(0, 0, clientArea.width - offset, clientArea.height); + } else if (isNorth()) { + m_flyoutContainer.setBounds(0, 0, clientArea.width, width); + client.setBounds(0, offset, clientArea.width, clientArea.height - offset); + } else if (isSouth()) { + m_flyoutContainer.setBounds(0, clientArea.height - width, clientArea.width, width); + client.setBounds(0, 0, clientArea.width, clientArea.height - offset); + } + } + } + + //////////////////////////////////////////////////////////////////////////// + // + // Internal utils + // + //////////////////////////////////////////////////////////////////////////// + private boolean isHorizontal() { + return isWest() || isEast(); + } + + private boolean isWest() { + return getDockLocation() == IFlyoutPreferences.DOCK_WEST; + } + + private boolean isEast() { + return getDockLocation() == IFlyoutPreferences.DOCK_EAST; + } + + private boolean isNorth() { + return getDockLocation() == IFlyoutPreferences.DOCK_NORTH; + } + + private boolean isSouth() { + return getDockLocation() == IFlyoutPreferences.DOCK_SOUTH; + } + + /** + * @return <code>true</code> if given docking location is valid. + */ + private boolean isValidDockLocation(int location) { + return (location & m_validDockLocations) == location; + } + + /** + * @return current docking location. + */ + private int getDockLocation() { + return m_preferences.getDockLocation(); + } + + /** + * Sets new docking location. + */ + private void setDockLocation(int dockLocation) { + m_preferences.setDockLocation(dockLocation); + layout(); + } + + // BEGIN ADT MODIFICATIONS + /** If the flyout hover is showing, dismiss it */ + public void dismissHover() { + if (m_flyoutContainer != null) { + m_flyoutContainer.dismissHover(); + } + } + + /** Sets a listener to be modified when windows are opened, collapsed and expanded */ + public void setListener(IFlyoutListener listener) { + assert m_listener == null; // Only one listener supported + m_listener = listener; + } + private IFlyoutListener m_listener; + // END ADT MODIFICATIONS + + //////////////////////////////////////////////////////////////////////////// + // + // FlyoutContainer + // + //////////////////////////////////////////////////////////////////////////// + /** + * Container for flyout {@link Control}. + * + * @author scheglov_ke + */ + private final class FlyoutContainer extends Composite { + //////////////////////////////////////////////////////////////////////////// + // + // Container + // + //////////////////////////////////////////////////////////////////////////// + public FlyoutContainer(Composite parent, int style) { + super(parent, style); + configureMenu(); + updateTitleImage("Flyout"); + // add listeners + addListener(SWT.Dispose, new Listener() { + @Override + public void handleEvent(Event event) { + if (m_titleImage != null) { + m_titleImage.dispose(); + m_titleImageRotated.dispose(); + m_titleImage = null; + m_titleImageRotated = null; + } + if (m_backImage != null) { + m_backImage.dispose(); + m_backImage = null; + } + } + }); + { + Listener listener = new Listener() { + @Override + public void handleEvent(Event event) { + layout(); + } + }; + addListener(SWT.Move, listener); + addListener(SWT.Resize, listener); + } + addListener(SWT.Paint, new Listener() { + @Override + public void handleEvent(Event event) { + handlePaint(event.gc); + } + }); + // mouse listeners + addMouseListener(new MouseAdapter() { + @Override + public void mouseDown(MouseEvent event) { + if (event.button == 1) { + handle_mouseDown(event); + } + } + + @Override + public void mouseUp(MouseEvent event) { + if (event.button == 1) { + handle_mouseUp(event); + } + } + }); + addMouseTrackListener(new MouseTrackAdapter() { + @Override + public void mouseExit(MouseEvent e) { + m_stateHover = false; + redraw(); + setCursor(null); + } + + @Override + public void mouseHover(MouseEvent e) { + handle_mouseHover(); + } + }); + addMouseMoveListener(new MouseMoveListener() { + @Override + public void mouseMove(MouseEvent event) { + handle_mouseMove(event); + } + }); + } + + // BEGIN ADT MODIFICATIONS + private void dismissHover() { + int state = m_preferences.getState(); + if (state == IFlyoutPreferences.STATE_EXPANDED) { + state = IFlyoutPreferences.STATE_COLLAPSED; + m_preferences.setState(state); + redraw(); + FlyoutControlComposite.this.layout(); + if (m_listener != null) { + m_listener.stateChanged(IFlyoutPreferences.STATE_EXPANDED, state); + } + } + } + // END END MODIFICATIONS + + //////////////////////////////////////////////////////////////////////////// + // + // Events: mouse + // + //////////////////////////////////////////////////////////////////////////// + private boolean m_resize; + private boolean m_stateHover; + + /** + * Handler for {@link SWT#MouseDown} event. + */ + private void handle_mouseDown(MouseEvent event) { + if (m_stateHover) { + int state = m_preferences.getState(); + // BEGIN ADT MODIFICATIONS + int oldState = state; + // END ADT MODIFICATIONS + if (state == IFlyoutPreferences.STATE_OPEN) { + state = IFlyoutPreferences.STATE_COLLAPSED; + } else { + state = IFlyoutPreferences.STATE_OPEN; + } + m_preferences.setState(state); + redraw(); + FlyoutControlComposite.this.layout(); + // BEGIN ADT MODIFICATIONS + if (m_listener != null) { + m_listener.stateChanged(oldState, state); + } + // END ADT MODIFICATIONS + } else if (getCursor() == ICursorConstants.SIZEWE || getCursor() == ICursorConstants.SIZENS) { + m_resize = true; + } else if (getCursor() == ICursorConstants.SIZEALL) { + handleDocking(); + } + } + + /** + * Handler for {@link SWT#MouseUp} event. + */ + private void handle_mouseUp(MouseEvent event) { + if (m_resize) { + m_resize = false; + handle_mouseMove(event); + } + } + + /** + * Handler for {@link SWT#MouseMove} event. + */ + private void handle_mouseMove(MouseEvent event) { + final FlyoutControlComposite container = FlyoutControlComposite.this; + if (m_resize) { + // prepare width + int width; + if (isHorizontal()) { + width = getSize().x; + } else { + width = getSize().y; + } + // prepare new width + int newWidth = width; + if (isWest()) { + newWidth = event.x + RESIZE_WIDTH / 2; + } else if (isEast()) { + newWidth = width - event.x + RESIZE_WIDTH / 2; + } else if (isNorth()) { + newWidth = event.y + RESIZE_WIDTH / 2; + } else if (isSouth()) { + newWidth = width - event.y + RESIZE_WIDTH / 2; + } + // update width + if (newWidth != width) { + m_preferences.setWidth(newWidth); + redraw(); + container.layout(); + } + } else { + Rectangle clientArea = getClientArea(); + boolean inside = clientArea.contains(event.x, event.y); + int x = event.x; + int y = event.y; + if (inside) { + // check for state + { + boolean oldStateHover = m_stateHover; + if (isEast()) { + m_stateHover = x > clientArea.width - m_titleHeight && y < m_titleHeight; + } else { + m_stateHover = x < m_titleHeight && y < m_titleHeight; + } + if (m_stateHover != oldStateHover) { + redraw(); + } + if (m_stateHover) { + setCursor(null); + return; + } + } + // check for resize band + if (isOpenExpanded()) { + if (isWest() && x >= clientArea.width - RESIZE_WIDTH) { + setCursor(ICursorConstants.SIZEWE); + } else if (isEast() && x <= RESIZE_WIDTH) { + setCursor(ICursorConstants.SIZEWE); + } else if (isNorth() && y >= clientArea.height - RESIZE_WIDTH) { + setCursor(ICursorConstants.SIZENS); + } else if (isSouth() && y <= RESIZE_WIDTH) { + setCursor(ICursorConstants.SIZENS); + } else { + setCursor(null); + } + } + // check for docking + if (getCursor() == null) { + setCursor(ICursorConstants.SIZEALL); + } + } else { + setCursor(null); + } + } + } + + /** + * Handler for {@link SWT#MouseHover} event - temporary expands flyout and collapse again when + * mouse moves above client. + */ + private void handle_mouseHover() { + if (m_preferences.getState() == IFlyoutPreferences.STATE_COLLAPSED && !m_stateHover) { + m_preferences.setState(IFlyoutPreferences.STATE_EXPANDED); + // + final FlyoutControlComposite container = FlyoutControlComposite.this; + container.layout(); + // BEGIN ADT MODIFICATIONS + if (m_listener != null) { + m_listener.stateChanged(IFlyoutPreferences.STATE_COLLAPSED, + IFlyoutPreferences.STATE_EXPANDED); + } + // END ADT MODIFICATIONS + // add listeners + Listener listener = new Listener() { + @Override + public void handleEvent(Event event) { + if (event.type == SWT.Dispose) { + getDisplay().removeFilter(SWT.MouseMove, this); + } else { + Point p = ((Control) event.widget).toDisplay(event.x, event.y); + // during resize mouse can be temporary outside of flyout - ignore + if (m_resize) { + return; + } + // mouse in in flyout container - ignore + if (getClientArea().contains(toControl(p.x, p.y))) { + return; + } + // mouse is in full container - collapse + if (container.getClientArea().contains(container.toControl(p.x, p.y))) { + getDisplay().removeFilter(SWT.MouseMove, this); + // it is possible, that user restored (OPEN) flyout, so collapse only if we still in expand state + if (m_preferences.getState() == IFlyoutPreferences.STATE_EXPANDED) { + m_preferences.setState(IFlyoutPreferences.STATE_COLLAPSED); + container.layout(); + // BEGIN ADT MODIFICATIONS + if (m_listener != null) { + m_listener.stateChanged(IFlyoutPreferences.STATE_EXPANDED, + IFlyoutPreferences.STATE_COLLAPSED); + } + // END ADT MODIFICATIONS + } + } + } + } + }; + addListener(SWT.Dispose, listener); + getDisplay().addFilter(SWT.MouseMove, listener); + } + } + + /** + * Handler for docking. + */ + private void handleDocking() { + final FlyoutControlComposite container = FlyoutControlComposite.this; + final int width = m_preferences.getWidth(); + final int oldDockLocation = getDockLocation(); + final int[] newDockLocation = new int[]{oldDockLocation}; + final Tracker dockingTracker = new Tracker(container, SWT.NONE); + dockingTracker.setRectangles(new Rectangle[]{getBounds()}); + dockingTracker.setStippled(true); + dockingTracker.addListener(SWT.Move, new Listener() { + @Override + public void handleEvent(Event event2) { + Rectangle clientArea = container.getClientArea(); + Point location = container.toControl(event2.x, event2.y); + int h3 = clientArea.height / 3; + // check locations + if (location.y < h3 && isValidDockLocation(IFlyoutPreferences.DOCK_NORTH)) { + dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0, + 0, + clientArea.width, + width)}); + newDockLocation[0] = IFlyoutPreferences.DOCK_NORTH; + } else if (location.y > 2 * h3 && isValidDockLocation(IFlyoutPreferences.DOCK_SOUTH)) { + dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0, + clientArea.height - width, + clientArea.width, + width)}); + newDockLocation[0] = IFlyoutPreferences.DOCK_SOUTH; + } else if (location.x < clientArea.width / 2 + && isValidDockLocation(IFlyoutPreferences.DOCK_WEST)) { + dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0, + 0, + width, + clientArea.height)}); + newDockLocation[0] = IFlyoutPreferences.DOCK_WEST; + } else if (isValidDockLocation(IFlyoutPreferences.DOCK_EAST)) { + dockingTracker.setRectangles(new Rectangle[]{new Rectangle(clientArea.width - width, + 0, + width, + clientArea.height)}); + newDockLocation[0] = IFlyoutPreferences.DOCK_EAST; + } else { + dockingTracker.setRectangles(new Rectangle[]{getBounds()}); + newDockLocation[0] = oldDockLocation; + } + } + }); + // start tracking + if (dockingTracker.open()) { + setDockLocation(newDockLocation[0]); + } + // dispose tracker + dockingTracker.dispose(); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Access + // + //////////////////////////////////////////////////////////////////////////// + /** + * @return the {@link Control} installed on this {@link FlyoutControlComposite}, or + * <code>null</code> if there are no any {@link Control}. + */ + private Control getControl() { + Control[] children = getChildren(); + return children.length == 1 ? children[0] : null; + } + + /** + * Sets the text of title. + */ + public void setTitleText(String text) { + updateTitleImage(text); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Layout + // + //////////////////////////////////////////////////////////////////////////// + @Override + public void layout() { + Control control = getControl(); + if (control == null) { + return; + } + // OK, we have control, so can continue layout + Rectangle clientArea = getClientArea(); + if (isOpenExpanded()) { + if (isWest()) { + int y = m_titleHeight; + control.setBounds(0, y, clientArea.width - RESIZE_WIDTH, clientArea.height - y); + } else if (isEast()) { + int y = m_titleHeight; + control.setBounds(RESIZE_WIDTH, y, clientArea.width - RESIZE_WIDTH, clientArea.height - y); + } else if (isNorth()) { + int y = m_titleHeight; + control.setBounds(0, y, clientArea.width, clientArea.height - y - RESIZE_WIDTH); + } else if (isSouth()) { + int y = RESIZE_WIDTH + m_titleHeight; + control.setBounds(0, y, clientArea.width, clientArea.height - y); + } + } else { + control.setBounds(0, 0, 0, 0); + } + } + + //////////////////////////////////////////////////////////////////////////// + // + // Paint + // + //////////////////////////////////////////////////////////////////////////// + private Image m_backImage; + + /** + * Handler for {@link SWT#Paint} event. + */ + private void handlePaint(GC paintGC) { + Rectangle clientArea = getClientArea(); + // prepare back image + GC gc; + { + if (m_backImage == null || !m_backImage.getBounds().equals(clientArea)) { + if (m_backImage != null) { + m_backImage.dispose(); + } + m_backImage = new Image(getDisplay(), clientArea.width, clientArea.height); + } + // prepare GC + gc = new GC(m_backImage); + gc.setBackground(paintGC.getBackground()); + gc.setForeground(paintGC.getForeground()); + gc.fillRectangle(clientArea); + } + // + if (isOpenExpanded()) { + // draw header + { + // draw title + if (isWest()) { + drawStateImage(gc, 0, 0); + gc.drawImage(m_titleImage, m_titleHeight, 0); + } else if (isEast()) { + int x = clientArea.width - m_titleHeight; + drawStateImage(gc, x, 0); + gc.drawImage(m_titleImage, x - m_titleWidth, 0); + } else if (isNorth()) { + drawStateImage(gc, 0, 0); + gc.drawImage(m_titleImage, m_titleHeight, 0); + } else if (isSouth()) { + int y = RESIZE_WIDTH; + drawStateImage(gc, 0, y); + gc.drawImage(m_titleImage, m_titleHeight, y); + } + } + // draw resize band + drawResizeBand(gc); + } else { + if (isHorizontal()) { + drawStateImage(gc, 0, 0); + gc.drawImage(m_titleImageRotated, 0, m_titleHeight); + } else { + drawStateImage(gc, 0, 0); + gc.drawImage(m_titleImage, m_titleHeight, 0); + } + DrawUtils.drawHighlightRectangle(gc, 0, 0, clientArea.width, clientArea.height); + } + // flush back image + { + gc.dispose(); + paintGC.drawImage(m_backImage, 0, 0); + } + } + + /** + * Draws the state image (arrow) at given location. + */ + private void drawStateImage(GC gc, int x, int y) { + DrawUtils.drawImageCHCV(gc, getStateImage(), x, y, m_titleHeight, m_titleHeight); + if (m_stateHover) { + DrawUtils.drawHighlightRectangle(gc, x, y, m_titleHeight, m_titleHeight); + } + } + + /** + * @return the {@link Image} corresponding to current state (open or collapsed). + */ + private Image getStateImage() { + int location = getDockLocation(); + int state = m_preferences.getState(); + if (state == IFlyoutPreferences.STATE_OPEN) { + switch (location) { + case IFlyoutPreferences.DOCK_WEST : + return ARROW_LEFT; + case IFlyoutPreferences.DOCK_EAST : + return ARROW_RIGHT; + case IFlyoutPreferences.DOCK_NORTH : + return ARROW_TOP; + case IFlyoutPreferences.DOCK_SOUTH : + return ARROW_BOTTOM; + } + } else if (state == IFlyoutPreferences.STATE_EXPANDED) { + return PIN; + } else { + switch (location) { + case IFlyoutPreferences.DOCK_WEST : + return ARROW_RIGHT; + case IFlyoutPreferences.DOCK_EAST : + return ARROW_LEFT; + case IFlyoutPreferences.DOCK_NORTH : + return ARROW_BOTTOM; + case IFlyoutPreferences.DOCK_SOUTH : + return ARROW_TOP; + } + } + // + return null; + } + + /** + * Draws that resize band, {@link Sash} like. + */ + private void drawResizeBand(GC gc) { + Rectangle clientArea = getClientArea(); + // prepare locations + int x, y, width, height; + if (isHorizontal()) { + if (isWest()) { + x = clientArea.width - RESIZE_WIDTH; + } else { + x = 0; + } + y = 0; + width = RESIZE_WIDTH; + height = clientArea.height; + } else { + x = 0; + if (isNorth()) { + y = clientArea.height - RESIZE_WIDTH; + } else { + y = 0; + } + width = clientArea.width; + height = RESIZE_WIDTH; + } + // draw band + DrawUtils.drawHighlightRectangle(gc, x, y, width, height); + } + + /** + * @return <code>true</code> if flyout is open or expanded. + */ + private boolean isOpenExpanded() { + int state = m_preferences.getState(); + return state == IFlyoutPreferences.STATE_OPEN || state == IFlyoutPreferences.STATE_EXPANDED; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Title image + // + //////////////////////////////////////////////////////////////////////////// + private int m_titleWidth; + private int m_titleHeight; + private Image m_titleImage; + private Image m_titleImageRotated; + + /** + * Creates {@link Image} for given title text. + */ + private void updateTitleImage(String text) { + // prepare size of text + Point textSize; + { + GC gc = new GC(this); + gc.setFont(TITLE_FONT); + textSize = gc.textExtent(text); + gc.dispose(); + } + // dispose existing image + if (m_titleImage != null) { + m_titleImage.dispose(); + m_titleImageRotated.dispose(); + } + // prepare new image + { + m_titleWidth = textSize.x + 2 * TITLE_LINES + 4 * TITLE_MARGIN; + m_titleHeight = textSize.y; + m_titleImage = new Image(getDisplay(), m_titleWidth, m_titleHeight); + GC gc = new GC(m_titleImage); + try { + gc.setBackground(getBackground()); + gc.fillRectangle(0, 0, m_titleWidth, m_titleHeight); + int x = 0; + // draw left lines + { + x += TITLE_MARGIN; + drawTitleLines(gc, x, m_titleHeight, TITLE_LINES); + x += TITLE_LINES + TITLE_MARGIN; + } + // draw text + { + gc.setForeground(IColorConstants.black); + gc.setFont(TITLE_FONT); + gc.drawText(text, x, 0); + x += textSize.x; + } + // draw right lines + { + x += TITLE_MARGIN; + drawTitleLines(gc, x, m_titleHeight, TITLE_LINES); + } + } finally { + gc.dispose(); + } + } + // prepare rotated image + m_titleImageRotated = DrawUtils.createRotatedImage(m_titleImage); + } + + /** + * Draws two title lines. + */ + private void drawTitleLines(GC gc, int x, int height, int width) { + drawTitleLine(gc, x, height / 3, width); + drawTitleLine(gc, x, 2 * height / 3, width); + } + + /** + * Draws single title line. + */ + private void drawTitleLine(GC gc, int x, int y, int width) { + int right = x + TITLE_LINES; + // + gc.setForeground(IColorConstants.buttonLightest); + gc.drawLine(x, y, right - 2, y); + gc.drawLine(x, y + 1, right - 2, y + 1); + // + gc.setForeground(IColorConstants.buttonDarker); + gc.drawLine(right - 2, y, right - 1, y); + gc.drawLine(x + 2, y + 1, right - 2, y + 1); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Menu + // + //////////////////////////////////////////////////////////////////////////// + private void configureMenu() { + final MenuManager manager = new MenuManager(); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + @Override + public void menuAboutToShow(IMenuManager menuMgr) { + addDockActions(); + for (IFlyoutMenuContributor contributor : m_menuContributors) { + contributor.contribute(manager); + } + } + + private void addDockActions() { + MenuManager dockManager = new MenuManager(Messages.FlyoutControlComposite_dockManager); + addDockAction( + dockManager, + Messages.FlyoutControlComposite_dockLeft, + IFlyoutPreferences.DOCK_WEST); + addDockAction( + dockManager, + Messages.FlyoutControlComposite_dockRight, + IFlyoutPreferences.DOCK_EAST); + addDockAction( + dockManager, + Messages.FlyoutControlComposite_dockTop, + IFlyoutPreferences.DOCK_NORTH); + addDockAction( + dockManager, + Messages.FlyoutControlComposite_dockBottom, + IFlyoutPreferences.DOCK_SOUTH); + manager.add(dockManager); + } + + private void addDockAction(MenuManager dockManager, String text, int location) { + if ((m_validDockLocations & location) != 0) { + dockManager.add(new DockAction(text, location)); + } + } + }); + // set menu + setMenu(manager.createContextMenu(this)); + // dispose it later + addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + manager.dispose(); + } + }); + } + } + //////////////////////////////////////////////////////////////////////////// + // + // DockAction + // + //////////////////////////////////////////////////////////////////////////// + private class DockAction extends Action { + private final int m_location; + + //////////////////////////////////////////////////////////////////////////// + // + // Constructor + // + //////////////////////////////////////////////////////////////////////////// + public DockAction(String text, int location) { + super(text, AS_RADIO_BUTTON); + m_location = location; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Action + // + //////////////////////////////////////////////////////////////////////////// + @Override + public boolean isChecked() { + return getDockLocation() == m_location; + } + + @Override + public void run() { + setDockLocation(m_location); + } + } +} diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutListener.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutListener.java new file mode 100644 index 0000000..ed87bb8 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutListener.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +// BEGIN ADT MODIFICATIONS +/** Interface for listeners interested in window state transitions in flyout windows */ +public interface IFlyoutListener { + /** + * The flyout has changed state from the old state to the new state (see the + * state constants in {@link IFlyoutPreferences}) + * + * @param oldState the old state + * @param newState the new state + */ + void stateChanged(int oldState, int newState); +} +// END ADT MODIFICATIONS diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutMenuContributor.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutMenuContributor.java new file mode 100644 index 0000000..11a9b08 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutMenuContributor.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +import org.eclipse.jface.action.IMenuManager; + +/** + * Contributes items into {@link IMenuManager} or {@link FlyoutControlComposite}. + * + * @author scheglov_ke + * @coverage core.control + */ +public interface IFlyoutMenuContributor { + void contribute(IMenuManager manager); +} diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutPreferences.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutPreferences.java new file mode 100644 index 0000000..d24edb5 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/IFlyoutPreferences.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +/** + * Provider for preferences of flyout control of {@link FlyoutControlComposite}. + * + * @author scheglov_ke + * @coverage core.control + */ +public interface IFlyoutPreferences { + //////////////////////////////////////////////////////////////////////////// + // + // Docking constants + // + //////////////////////////////////////////////////////////////////////////// + int DOCK_WEST = 1; + int DOCK_EAST = 2; + int DOCK_NORTH = 4; + int DOCK_SOUTH = 8; + //////////////////////////////////////////////////////////////////////////// + // + // State constants + // + //////////////////////////////////////////////////////////////////////////// + int STATE_OPEN = 0; + int STATE_COLLAPSED = 1; + int STATE_EXPANDED = 2; + + //////////////////////////////////////////////////////////////////////////// + // + // Access + // + //////////////////////////////////////////////////////////////////////////// + /** + * @return the docking location - {@link #DOCK_WEST}, {@link #DOCK_EAST}, {@link #DOCK_NORTH} or + * {@link #DOCK_SOUTH}. + */ + int getDockLocation(); + + /** + * @return the state of flyout - {@link #STATE_OPEN} or {@link #STATE_COLLAPSED}. + */ + int getState(); + + /** + * @return the width of flyout. + */ + int getWidth(); + + //////////////////////////////////////////////////////////////////////////// + // + // Modification + // + //////////////////////////////////////////////////////////////////////////// + /** + * Sets the docking location. + */ + void setDockLocation(int location); + + /** + * Sets the state of flyout - {@link #STATE_OPEN} or {@link #STATE_COLLAPSED}. + */ + void setState(int state); + + /** + * Sets the width of flyout. + */ + void setWidth(int width); +} diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/MemoryFlyoutPreferences.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/MemoryFlyoutPreferences.java new file mode 100644 index 0000000..8591589 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/MemoryFlyoutPreferences.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +/** + * Implementation of {@link IFlyoutPreferences} for keeping settings in memory. + * + * @author scheglov_ke + * @coverage core.control + */ +public final class MemoryFlyoutPreferences implements IFlyoutPreferences { + private int m_dockLocation; + private int m_state; + private int m_width; + + //////////////////////////////////////////////////////////////////////////// + // + // Constructor + // + //////////////////////////////////////////////////////////////////////////// + public MemoryFlyoutPreferences(int dockLocation, int state, int width) { + m_dockLocation = dockLocation; + m_state = state; + m_width = width; + } + + //////////////////////////////////////////////////////////////////////////// + // + // IFlyoutPreferences + // + //////////////////////////////////////////////////////////////////////////// + public int getDockLocation() { + return m_dockLocation; + } + + public int getState() { + return m_state; + } + + public int getWidth() { + return m_width; + } + + public void setDockLocation(int location) { + m_dockLocation = location; + } + + public void setState(int state) { + m_state = state; + } + + public void setWidth(int width) { + m_width = width; + } +}
\ No newline at end of file diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/PluginFlyoutPreferences.java b/propertysheet/src/org/eclipse/wb/core/controls/flyout/PluginFlyoutPreferences.java new file mode 100644 index 0000000..270dba0 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/PluginFlyoutPreferences.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.core.controls.flyout; + +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * Implementation of {@link IFlyoutPreferences} for {@link IPreferenceStore}. + * + * @author scheglov_ke + * @coverage core.control + */ +public final class PluginFlyoutPreferences implements IFlyoutPreferences { + private final IPreferenceStore m_store; + private final String m_dockLocationKey; + private final String m_stateKey; + private final String m_widthKey; + + //////////////////////////////////////////////////////////////////////////// + // + // Constructor + // + //////////////////////////////////////////////////////////////////////////// + public PluginFlyoutPreferences(IPreferenceStore store, String prefix) { + m_store = store; + m_dockLocationKey = prefix + ".flyout.dockLocation"; + m_stateKey = prefix + ".flyout.state"; + m_widthKey = prefix + ".flyout.width"; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Access + // + //////////////////////////////////////////////////////////////////////////// + /** + * Initializes defaults using given values. + */ + public void initializeDefaults(int location, int state, int width) { + m_store.setDefault(m_dockLocationKey, location); + m_store.setDefault(m_stateKey, state); + m_store.setDefault(m_widthKey, width); + } + + //////////////////////////////////////////////////////////////////////////// + // + // IFlyoutPreferences + // + //////////////////////////////////////////////////////////////////////////// + public int getDockLocation() { + return m_store.getInt(m_dockLocationKey); + } + + public int getState() { + return m_store.getInt(m_stateKey); + } + + public int getWidth() { + return m_store.getInt(m_widthKey); + } + + public void setDockLocation(int location) { + m_store.setValue(m_dockLocationKey, location); + } + + public void setState(int state) { + m_store.setValue(m_stateKey, state); + } + + public void setWidth(int width) { + m_store.setValue(m_widthKey, width); + } +} diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_bottom.gif b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_bottom.gif Binary files differnew file mode 100644 index 0000000..4a2df3f --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_bottom.gif diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_left.gif b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_left.gif Binary files differnew file mode 100644 index 0000000..9f7018e --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_left.gif diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_right.gif b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_right.gif Binary files differnew file mode 100644 index 0000000..56fb7de --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_right.gif diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_top.gif b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_top.gif Binary files differnew file mode 100644 index 0000000..eb4e5c2 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/arrow_top.gif diff --git a/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/pin.gif b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/pin.gif Binary files differnew file mode 100644 index 0000000..61bb170 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/core/controls/flyout/icons/pin.gif diff --git a/propertysheet/src/org/eclipse/wb/core/controls/messages.properties b/propertysheet/src/org/eclipse/wb/core/controls/messages.properties index 75a1ca0..b2b833f 100644 --- a/propertysheet/src/org/eclipse/wb/core/controls/messages.properties +++ b/propertysheet/src/org/eclipse/wb/core/controls/messages.properties @@ -1,2 +1,8 @@ CSpinner_canNotParse=Text "{0}"does not satisfy pattern "{1}" CSpinner_outOfRange=Value {0} is out of range [{1}, {2}] +FlyoutControlComposite_dockBottom=&Bottom +FlyoutControlComposite_dockLeft=&Left +FlyoutControlComposite_dockManager=&Dock On +FlyoutControlComposite_dockRight=&Right +FlyoutControlComposite_dockTop=&Top +FlyoutControlComposite_title=Flyout
\ No newline at end of file diff --git a/propertysheet/src/org/eclipse/wb/draw2d/IColorConstants.java b/propertysheet/src/org/eclipse/wb/draw2d/IColorConstants.java index f12d94e..4246302 100644 --- a/propertysheet/src/org/eclipse/wb/draw2d/IColorConstants.java +++ b/propertysheet/src/org/eclipse/wb/draw2d/IColorConstants.java @@ -67,6 +67,7 @@ public interface IColorConstants { Color lightGray = new Color(null, 192, 192, 192); Color gray = new Color(null, 128, 128, 128); Color darkGray = new Color(null, 64, 64, 64); + Color black = new Color(null, 0, 0, 0); Color lightBlue = new Color(null, 127, 127, 255); Color darkBlue = new Color(null, 0, 0, 127); diff --git a/propertysheet/src/org/eclipse/wb/draw2d/ICursorConstants.java b/propertysheet/src/org/eclipse/wb/draw2d/ICursorConstants.java index b05035d..273cd46 100644 --- a/propertysheet/src/org/eclipse/wb/draw2d/ICursorConstants.java +++ b/propertysheet/src/org/eclipse/wb/draw2d/ICursorConstants.java @@ -24,4 +24,18 @@ public interface ICursorConstants { * System resize west-east cursor */ Cursor SIZEWE = new Cursor(null, SWT.CURSOR_SIZEWE); + /** + * System resize north-south cursor + */ + Cursor SIZENS = new Cursor(null, SWT.CURSOR_SIZENS); + /** + * System resize all directions cursor. + */ + // BEGIN ADT MODIFICATIONS + // The SWT CURSOR_SIZEALL cursor looks wrong; it's cross hairs. Use a hand for resizing + // instead. See the icons shown in + // http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html + //Cursor SIZEALL = new Cursor(null, SWT.CURSOR_SIZEALL); + Cursor SIZEALL = new Cursor(null, SWT.CURSOR_HAND); + // END ADT MODIFICATIONS }
\ No newline at end of file diff --git a/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/IPage.java b/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/IPage.java new file mode 100644 index 0000000..a86522d --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/IPage.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.internal.core.editor.structure; + +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** + * View-like page. + * + * @author scheglov_ke + * @coverage core.editor.structure + */ +public interface IPage { + /** + * Creates the {@link Control} for this page. + */ + void createControl(Composite parent); + + /** + * Disposes this page. + * <p> + * This is the last method called on the {@link IPage}. Implementors should clean up any resources + * associated with the page. + * <p> + * Note that there is no guarantee that {@link #createControl(Composite)} has been called, so the + * control may never have been created. + */ + void dispose(); + + /** + * @return the {@link Control} of this page, may be <code>null</code>. + */ + Control getControl(); + + /** + * Allows the page to make contributions to the given {@link IToolBarManager}. The contributions + * will be visible when the page is visible. This method is automatically called shortly after + * {@link #createControl(Composite)} is called. + */ + void setToolBar(IToolBarManager toolBarManager); + + /** + * Asks this page to take focus. + */ + void setFocus(); +} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/PageSiteComposite.java b/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/PageSiteComposite.java new file mode 100644 index 0000000..bc57360 --- /dev/null +++ b/propertysheet/src/org/eclipse/wb/internal/core/editor/structure/PageSiteComposite.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2011 Google, Inc. + * 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: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.internal.core.editor.structure; + +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.wb.core.controls.CImageLabel; +import org.eclipse.wb.internal.core.utils.check.Assert; +import org.eclipse.wb.internal.core.utils.ui.GridDataFactory; +import org.eclipse.wb.internal.core.utils.ui.GridLayoutFactory; + +/** + * The site {@link Composite} for {@link IPage}. + * + * @author scheglov_ke + * @coverage core.editor.structure + */ +public final class PageSiteComposite extends Composite { + private final CImageLabel m_title; + private final ToolBarManager m_toolBarManager; + private final ToolBar m_toolBar; + private IPage m_page; + + //////////////////////////////////////////////////////////////////////////// + // + // Constructor + // + //////////////////////////////////////////////////////////////////////////// + public PageSiteComposite(Composite parent, int style) { + super(parent, style); + GridLayoutFactory.create(this).noMargins().spacingV(0).columns(2); + // title + { + m_title = new CImageLabel(this, SWT.NONE); + GridDataFactory.create(m_title).grabH().fill(); + } + // toolbar + { + m_toolBar = new ToolBar(this, SWT.FLAT | SWT.RIGHT); + GridDataFactory.create(m_toolBar).fill(); + m_toolBarManager = new ToolBarManager(m_toolBar); + } + // separator + { + Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL); + GridDataFactory.create(separator).spanH(2).grabH().fillH(); + } + } + + //////////////////////////////////////////////////////////////////////////// + // + // Access + // + //////////////////////////////////////////////////////////////////////////// + /** + * Sets the {@link Image} for title; + */ + public void setTitleImage(Image image) { + m_title.setImage(image); + } + + /** + * Sets the text for title. + */ + public void setTitleText(String title) { + m_title.setText(title); + } + + /** + * Sets the {@link IPage} to display. + */ + public void setPage(IPage page) { + Assert.isNull(m_page); + Assert.isNotNull(page); + m_page = page; + // create Control + m_page.createControl(this); + GridDataFactory.create(m_page.getControl()).spanH(2).grab().fill(); + // set toolbar + m_page.setToolBar(m_toolBarManager); + } + + // BEGIN ADT MODIFICATIONS + public ToolBar getToolBar() { + return m_toolBar; + } + // END ADT MODIFICATIONS + +} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java b/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java index f7cc09d..c22256e 100644 --- a/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java +++ b/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java @@ -262,6 +262,73 @@ public class DrawUtils { //////////////////////////////////////////////////////////////////////////// // + // Rotated images + // + //////////////////////////////////////////////////////////////////////////// + /** + * Returns a new Image that is the given Image rotated left by 90 degrees. The client is + * responsible for disposing the returned Image. This method MUST be invoked from the + * user-interface (Display) thread. + * + * @param srcImage + * the Image that is to be rotated left + * @return the rotated Image (the client is responsible for disposing it) + */ + public static Image createRotatedImage(Image srcImage) { + // prepare Display + Display display = Display.getCurrent(); + if (display == null) { + SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS); + } + // rotate ImageData + ImageData destData; + { + ImageData srcData = srcImage.getImageData(); + if (srcData.depth < 8) { + destData = rotatePixelByPixel(srcData); + } else { + destData = rotateOptimized(srcData); + } + } + // create new image + return new Image(display, destData); + } + + private static ImageData rotatePixelByPixel(ImageData srcData) { + ImageData destData = + new ImageData(srcData.height, srcData.width, srcData.depth, srcData.palette); + for (int y = 0; y < srcData.height; y++) { + for (int x = 0; x < srcData.width; x++) { + destData.setPixel(y, srcData.width - x - 1, srcData.getPixel(x, y)); + } + } + return destData; + } + + private static ImageData rotateOptimized(ImageData srcData) { + int bytesPerPixel = Math.max(1, srcData.depth / 8); + int destBytesPerLine = + ((srcData.height * bytesPerPixel - 1) / srcData.scanlinePad + 1) * srcData.scanlinePad; + byte[] newData = new byte[destBytesPerLine * srcData.width]; + for (int srcY = 0; srcY < srcData.height; srcY++) { + for (int srcX = 0; srcX < srcData.width; srcX++) { + int destX = srcY; + int destY = srcData.width - srcX - 1; + int destIndex = destY * destBytesPerLine + destX * bytesPerPixel; + int srcIndex = srcY * srcData.bytesPerLine + srcX * bytesPerPixel; + System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel); + } + } + return new ImageData(srcData.height, + srcData.width, + srcData.depth, + srcData.palette, + srcData.scanlinePad, + newData); + } + + //////////////////////////////////////////////////////////////////////////// + // // Colors // //////////////////////////////////////////////////////////////////////////// |