/******************************************************************************* * Copyright (c) 2004, 2006 Sybase, Inc. 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: * Sybase, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.facesconfig.ui.preference; import java.util.Iterator; import org.eclipse.draw2d.ActionEvent; import org.eclipse.draw2d.ActionListener; import org.eclipse.draw2d.FreeformFigure; import org.eclipse.draw2d.FreeformListener; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.Layer; import org.eclipse.draw2d.LayoutManager; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.jst.jsf.facesconfig.ui.EditorPlugin; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; /** * The figure for Compound nodes */ /*package*/ class CompoundNodeFigure extends BaseNodeFigure implements FreeformFigure, IContainerFigure { private static final String RESTORE_HILITE_IMAGE_FILE = "restore_hilite.gif"; //$NON-NLS-1$ private static final String RESTORE_IMAGE_FILE = "restore.gif"; //$NON-NLS-1$ private static final String MAXIMIZE_HILITE_IMAGE_FILE = "maximize_hilite.gif"; //$NON-NLS-1$ private static final String MAXIMIZE_IMAGE_FILE = "maximize.gif"; //$NON-NLS-1$ private static final String MINIMIZE_HILITE_IMAGE_FILE = "minimize_hilite.gif"; //$NON-NLS-1$ private static final String MINIMIZE_IMAGE_FILE = "minimize.gif"; //$NON-NLS-1$ private final static int MINIMIZED = 1; final static int RESTORED = 2; private final static int MAXIMIZED = 3; private int state = RESTORED; private TitleBarButton minButton; private TitleBarButton maxButton; private IconFigure iconFigure; private WindowFigure windowFigure; private static String DEFAULT_NAME = "CompoundNode"; //$NON-NLS-1$ private static String DEFAULT_ICON = "editor/CompoundNode.gif"; //$NON-NLS-1$ private static Image minimizeImage = EditorPlugin.getDefault().getImage( MINIMIZE_IMAGE_FILE); private static Image minimizeHiliteImage = EditorPlugin.getDefault() .getImage(MINIMIZE_HILITE_IMAGE_FILE); private static Image maximizeImage = EditorPlugin.getDefault().getImage( MAXIMIZE_IMAGE_FILE); private static Image maximizeHiliteImage = EditorPlugin.getDefault() .getImage(MAXIMIZE_HILITE_IMAGE_FILE); private static Image restoreImage = EditorPlugin.getDefault().getImage( RESTORE_IMAGE_FILE); private static Image restoreHiliteImage = EditorPlugin.getDefault() .getImage(RESTORE_HILITE_IMAGE_FILE); /** * Default constructor */ public CompoundNodeFigure() { // create all of the figures and adornments: // the icon figure super(new IconFigure(DEFAULT_NAME, EditorPlugin.getDefault().getImage( DEFAULT_ICON))); iconFigure = (IconFigure) getBaseFigure(); // and the window figure windowFigure = new WindowFigure(); windowFigure.setForegroundColor(IconFigure.defaultForegroundColor); windowFigure.setFont(IconFigure.defaultFont); // then the minimize/maximize buttons. // Note that the maxButton is also used for the "Restore" action // TODO: // The reason for putting these buttons in CompoundNodeFigure instead of // WindowFigure where they really belong, is that the TitleBarButton is // a // draw2d Button (which subclasses Figure) and these must be placed in // the // titlebar (i.e. a SchemeBorder) because that's where they belong. The // problem // with this is that the Figure.paint() method first draws all of its // children // figures, then the border which means that the buttons would be // obscured. // This should be fixed as time allows and the WindowFigureListener // interface // should then also be modified to include a buttonPressed() // notification // for which CompoundNodeFigure can be a listener. minButton = new TitleBarButton(minimizeImage, minimizeHiliteImage, null, null); maxButton = new TitleBarButton(maximizeImage, maximizeHiliteImage, restoreImage, restoreHiliteImage); add(minButton); add(maxButton); minButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { setState(CompoundNodeFigure.MINIMIZED); } }); maxButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { setState(maxButton.getState() ? CompoundNodeFigure.MAXIMIZED : CompoundNodeFigure.RESTORED); } }); // show as a normal window initially showIcon(); // testing BaseFigureDecorators: // BaseFigureDecorator decorator; // decorator = new // BaseFigureDecorator(EditorPlugin.getDefault().getGEMImage("delete.gif"), // "top right", // PositionConstants.NORTH_EAST); // addDecorator(decorator); // decorator = new // BaseFigureDecorator(EditorPlugin.getDefault().getGEMImage("delete.gif"), // "top left", // PositionConstants.NORTH_WEST); // addDecorator(decorator); // decorator = new // BaseFigureDecorator(EditorPlugin.getDefault().getGEMImage("delete.gif"), // "bottom right", // PositionConstants.SOUTH_EAST); // addDecorator(decorator); // decorator = new // BaseFigureDecorator(EditorPlugin.getDefault().getGEMImage("delete.gif"), // "bottom left", // PositionConstants.SOUTH_WEST); // addDecorator(decorator); } public void setOpaque(boolean flag) { windowFigure.setOpaque(flag); } /* * Remove the window figure and its buttons and replace them with the icon * figure. */ private void showIcon() { // CR400779: GEM minimizing a complex activity sometimes leaves junk on // the screen setVisible(false); minButton.setVisible(false); maxButton.setVisible(false); super.setBaseFigure(iconFigure); setAnchorsVisible(true); // CR400779: GEM minimizing a complex activity sometimes leaves junk on // the screen setVisible(true); } /* * Remove the icon figure and replace with the window figure. Make sure the * buttons are reset to their correct states. */ private void showWindow() { // CR400779: GEM minimizing a complex activity sometimes leaves junk on // the screen setVisible(false); if (state == RESTORED) { super.setBaseFigure(windowFigure); minButton.setVisible(true); minButton.setState(false); minButton.setToolTip(new Label(PreferenceMessages.CompoundNodeFigure_MinimizeLabel)); maxButton.setVisible(true); maxButton.setState(false); maxButton.setToolTip(new Label(PreferenceMessages.CompoundNodeFigure_MaximizeLabel)); setAnchorsVisible(true); } else if (state == MAXIMIZED) { setAnchorsVisible(false); Rectangle constraint = new Rectangle(0, 0, -1, -1); IFigure parent = getParent(); if (parent != null) { constraint = parent.getBounds().getCopy(); constraint.width += constraint.x; constraint.height += constraint.y; constraint.x = 0; constraint.y = 0; } super.setBaseFigure(windowFigure, constraint); if (parent != null && parent.getLayoutManager() != null) { // System.out.println("CompoundNode.showWindow: maximize // "+constraint); parent.getLayoutManager().setConstraint(this, constraint); } // the maximize button is used for both Maximize and Restore actions minButton.setVisible(false); maxButton.setVisible(true); maxButton.setState(true); maxButton.setToolTip(new Label(PreferenceMessages.CompoundNodeFigure_RestoreLabel)); } // CR400779: GEM minimizing a complex activity sometimes leaves junk on // the screen setVisible(true); } public void addDecorator(BaseFigureDecorator decorator) { iconFigure.addDecorator(decorator); } public void removeDecorator() { iconFigure.removeDecorator(); } public void removeDecorator(int position) { iconFigure.removeDecorator(position); } /** * @param flag */ public void setHilight(boolean flag) { windowFigure.setHighlight(flag); if (flag) moveToTop(); } public void setText(String name) { iconFigure.setText(name); windowFigure.setText(name); } public void setIcon(Image image) { iconFigure.setIcon(image); } public void setToolTipText(String text) { iconFigure.setToolTipText(text); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.Figure#layout() */ public void validate() { LayoutManager layout = getLayoutManager(); if (state == MINIMIZED) { // iconFigure.validate(); } else if (state == RESTORED) { Rectangle r = windowFigure.getBounds().getCopy(); Insets i = windowFigure.getInsets(); Dimension dm = maxButton.getSize(); Insets p = windowFigure.getTabbedTitleBarBorder().getPadding(); layout.setConstraint(maxButton, new Rectangle(r.x + r.width - dm.width - p.right - i.right, r.y + p.top + i.top - dm.height - i.bottom, -1, -1)); layout.setConstraint(minButton, new Rectangle(r.x + r.width - 2 * dm.width - 2 * p.right - i.right, r.y + p.top + i.top - dm.height - i.bottom, -1, -1)); } else if (state == MAXIMIZED) { // CR387660: restore icon on complex activity bounces around // we need to use the parent's bounds when maximized instead of // current window bounds if (getParent() == null) return; Rectangle r = getParent().getBounds().getCopy(); Insets i = windowFigure.getInsets(); Dimension dm = maxButton.getSize(); Insets p = windowFigure.getTabbedTitleBarBorder().getPadding(); layout.setConstraint(maxButton, new Rectangle(r.x + r.width - dm.width - p.right - i.right, r.y + p.top, -1, -1)); } super.validate(); } /** * @return the window figure */ public WindowFigure getWindowFigure() { return windowFigure; } public void setFont(Font f) { iconFigure.setFont(f); windowFigure.setFont(f); } public void setForegroundColor(Color c) { iconFigure.setForegroundColor(c); windowFigure.setForegroundColor(c); } public void setBackgroundColor(Color c) { iconFigure.setBackgroundColor(c); windowFigure.setBackgroundColor(c); } /** * @return the state */ public int getState() { return state; } /** * @param newState */ public void setState(int newState) { int oldState = state; state = newState; if (state == CompoundNodeFigure.MINIMIZED) { if (getParent() != null && getParent().getLayoutManager() != null) { Rectangle constraint = (Rectangle) getParent() .getLayoutManager().getConstraint(this); constraint.width = -1; constraint.height = -1; } showIcon(); } else if (state == CompoundNodeFigure.MAXIMIZED) { if (getParent() != null && getParent().getLayoutManager() != null) { Rectangle constraint = (Rectangle) getParent() .getLayoutManager().getConstraint(this); constraint.x = 0; constraint.y = 0; constraint.width = -1; constraint.height = -1; } showWindow(); } else if (state == CompoundNodeFigure.RESTORED) { if (getParent() != null && getParent().getLayoutManager() != null) { Rectangle constraint = (Rectangle) getParent() .getLayoutManager().getConstraint(this); constraint.setSize(windowFigure.getBounds().getSize()); } showWindow(); } fireStateChanged(oldState, newState); } private void fireStateChanged(int oldState, int newState) { Object l[] = windowFigure.getTabbedTitleBarBorder().getListeners(); for (int i = 0; i < l.length; ++i) { if (l[i] instanceof CompoundFigureListener) ((CompoundFigureListener) l[i]) .stateChanged(oldState, newState); } } public Dimension getMinimumSize(int wHint, int hHint) { if (getState() == CompoundNodeFigure.RESTORED) { Dimension d = windowFigure.getMinimumSize(wHint, hHint); d.width += minButton.getSize().width + maxButton.getSize().width + 2 * windowFigure.getTabbedTitleBarBorder().getPadding() .getWidth(); return d; } if (getState() == CompoundNodeFigure.MINIMIZED) return iconFigure.getMinimumSize(wHint, hHint); return super.getMinimumSize(wHint, hHint); } // ////////////////////////////////////////////////////////////////////// // FreeformFigure methods // ////////////////////////////////////////////////////////////////////// private WindowFreeformHelper helper = new WindowFreeformHelper(this); /* * (non-Javadoc) * * @see org.eclipse.draw2d.FreeformFigure#addFreeformListener(org.eclipse.draw2d.FreeformListener) */ public void addFreeformListener(FreeformListener listener) { addListener(FreeformListener.class, listener); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.FreeformFigure#fireExtentChanged() */ public void fireExtentChanged() { // CR389495: Working with nested complex activities causes in the BP // editor causes lockup // not specifically related to this CR, but caused a problem when // compound node // was moved beyond viewport's client area and de-selected - this would // resize // the viewport so that compound node no longer participated in bounds // calculation. if (state == MAXIMIZED) { Iterator iter = getListeners(FreeformListener.class); while (iter.hasNext()) ((FreeformListener) iter.next()).notifyFreeformExtentChanged(); } } /* * (non-Javadoc) * * @see org.eclipse.draw2d.FreeformFigure#getFreeformExtent() */ public Rectangle getFreeformExtent() { // CR389495: Working with nested complex activities causes in the BP // editor causes lockup // same as above if (state == MAXIMIZED) return helper.getFreeformExtent(); return getBounds(); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.FreeformFigure#removeFreeformListener(org.eclipse.draw2d.FreeformListener) */ public void removeFreeformListener(FreeformListener listener) { removeListener(FreeformListener.class, listener); } /* * (non-Javadoc) * * @see org.eclipse.draw2d.FreeformFigure#setFreeformBounds(org.eclipse.draw2d.geometry.Rectangle) */ public void setFreeformBounds(Rectangle bounds) { if (getState() == MAXIMIZED) helper.setFreeformBounds(bounds); } /* * CR389070: Figures are abbreviating rule figures names and making them * unreadable New Method on IContainerFigure * * @see com.sybase.stf.gem.diagram.editor.figures.IContainerFigure#getLayer(java.lang.Object) */ public Layer getLayer(Object key) { if (windowFigure != null && windowFigure.isVisible()) return windowFigure.getLayer(key); return null; } }