| /******************************************************************************* |
| * Copyright (c) 2003, 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.internal.ui.rulers; |
| |
| import java.beans.PropertyChangeEvent; |
| |
| import org.eclipse.draw2d.ColorConstants; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.RangeModel; |
| import org.eclipse.draw2d.Viewport; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Insets; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| |
| import org.eclipse.gef.AutoexposeHelper; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.editparts.SimpleRootEditPart; |
| import org.eclipse.gef.editparts.ViewportAutoexposeHelper; |
| |
| /** |
| * RootEditPart for a ruler. |
| * |
| * @author Pratik Shah |
| * @since 3.0 |
| */ |
| public class RulerRootEditPart extends SimpleRootEditPart { |
| |
| private static final Insets VERTICAL_THRESHOLD = new Insets(18, 0, 18, 0); |
| private static final Insets HORIZONTAL_THRESHOLD = new Insets(0, 18, 0, 18); |
| |
| private boolean horizontal; |
| |
| /** |
| * Constructor |
| * |
| * @param isHorzontal |
| * whether or not the corresponding model ruler is horizontal |
| */ |
| public RulerRootEditPart(boolean isHorzontal) { |
| super(); |
| horizontal = isHorzontal; |
| } |
| |
| /** |
| * @see org.eclipse.gef.editparts.AbstractEditPart#addChildVisual(org.eclipse.gef.EditPart, |
| * int) |
| */ |
| protected void addChildVisual(EditPart childEditPart, int index) { |
| IFigure child = ((GraphicalEditPart) childEditPart).getFigure(); |
| getViewport().setContents(child); |
| } |
| |
| /** |
| * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() |
| */ |
| protected IFigure createFigure() { |
| return new RulerViewport(); |
| } |
| |
| /** |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) |
| */ |
| public Object getAdapter(Class adapter) { |
| if (adapter == AutoexposeHelper.class) { |
| if (((RulerEditPart) getContents()).isHorizontal()) |
| return new ViewportAutoexposeHelper(this, HORIZONTAL_THRESHOLD); |
| return new ViewportAutoexposeHelper(this, VERTICAL_THRESHOLD); |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * Convenience method to get to the viewport |
| * |
| * @return the figure cast as a viewport |
| */ |
| protected Viewport getViewport() { |
| return (Viewport) getFigure(); |
| } |
| |
| /** |
| * @see org.eclipse.gef.editparts.AbstractEditPart#removeChildVisual(org.eclipse.gef.EditPart) |
| */ |
| protected void removeChildVisual(EditPart childEditPart) { |
| getViewport().setContents(null); |
| } |
| |
| /** |
| * A RulerViewport shares a RangeModel with that of the primary |
| * GraphicalViewer. The shared RangeModel is set on this viewport externally |
| * by a client (in this case, RulerComposite). |
| * |
| * @author Pratik Shah |
| * @since 3.0 |
| */ |
| public class RulerViewport extends Viewport { |
| /** |
| * Constructor |
| */ |
| public RulerViewport() { |
| super(true); |
| setLayoutManager(null); |
| // The range model that's not shared is initialized such that it |
| // can't scroll |
| // anymore (otherwise, CTRL + SHIFT + ARROW scrolls it). |
| RangeModel bogusRangeModel; |
| if (horizontal) |
| bogusRangeModel = getVerticalRangeModel(); |
| else |
| bogusRangeModel = getHorizontalRangeModel(); |
| bogusRangeModel.setMinimum(0); |
| bogusRangeModel.setMaximum(100); |
| bogusRangeModel.setValue(0); |
| bogusRangeModel.setExtent(100); |
| } |
| |
| /** |
| * This is the method that does the actual layout. We don't want a |
| * layout to occur when layout() is invoked, rather when something |
| * changes in the shared RangeModel. |
| * |
| * @param force |
| * if <code>true</code>, the contents will be resized and |
| * revalidated; otherwise, just a repaint will occur. |
| */ |
| protected void doLayout(boolean force) { |
| repaint(); |
| /* |
| * @TODO:Pratik It seems you don't really need this force argument. |
| * Those that invoke doLayout(false) can invoke repaint() |
| * themselves. doLayout() should just layout. |
| */ |
| if (force) { |
| RangeModel rModel; |
| if (horizontal) |
| rModel = getHorizontalRangeModel(); |
| else |
| rModel = getVerticalRangeModel(); |
| Rectangle contentBounds = Rectangle.getSINGLETON(); |
| if (horizontal) { |
| contentBounds.y = 0; |
| contentBounds.x = rModel.getMinimum(); |
| contentBounds.height = this.getContents() |
| .getPreferredSize().height; |
| contentBounds.width = rModel.getMaximum() |
| - rModel.getMinimum(); |
| } else { |
| contentBounds.y = rModel.getMinimum(); |
| contentBounds.x = 0; |
| contentBounds.height = rModel.getMaximum() |
| - rModel.getMinimum(); |
| contentBounds.width = this.getContents().getPreferredSize().width; |
| } |
| if (!this.getContents().getBounds().equals(contentBounds)) { |
| this.getContents().setBounds(contentBounds); |
| this.getContents().revalidate(); |
| } |
| } |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.IFigure#getPreferredSize(int, int) |
| */ |
| public Dimension getPreferredSize(int wHint, int hHint) { |
| if (this.getContents() == null) |
| return new Dimension(); |
| Dimension pSize = this.getContents().getPreferredSize(wHint, hHint); |
| if (horizontal) { |
| RangeModel rModel = getHorizontalRangeModel(); |
| pSize.width = rModel.getMaximum() - rModel.getMinimum(); |
| } else { |
| RangeModel rModel = getVerticalRangeModel(); |
| pSize.height = rModel.getMaximum() - rModel.getMinimum(); |
| } |
| return pSize |
| .expand(getInsets().getWidth(), getInsets().getHeight()); |
| } |
| |
| /** |
| * Since the RangeModel is shared with that of the editor's, a |
| * RulerViewport should not adjust it. |
| * |
| * @see org.eclipse.draw2d.Viewport#readjustScrollBars() |
| */ |
| protected void readjustScrollBars() { |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.Figure#paintBorder(org.eclipse.draw2d.Graphics) |
| */ |
| protected void paintBorder(Graphics graphics) { |
| super.paintBorder(graphics); |
| if (this.getContents() != null |
| && ((RulerFigure) this.getContents()).getDrawFocus()) { |
| Rectangle focusBounds = getBounds().getCopy(); |
| if (((RulerFigure) this.getContents()).isHorizontal()) { |
| focusBounds.resize(-2, -4); |
| focusBounds.x++; |
| } else { |
| focusBounds.resize(-4, -2); |
| focusBounds.y++; |
| } |
| graphics.setForegroundColor(ColorConstants.black); |
| graphics.setBackgroundColor(ColorConstants.white); |
| graphics.drawFocus(focusBounds); |
| } |
| } |
| |
| /** |
| * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) |
| */ |
| public void propertyChange(PropertyChangeEvent event) { |
| if (this.getContents() != null |
| && event.getSource() instanceof RangeModel) { |
| String property = event.getPropertyName(); |
| doLayout(RangeModel.PROPERTY_MAXIMUM.equals(property) |
| || RangeModel.PROPERTY_MINIMUM.equals(property) |
| || RangeModel.PROPERTY_VALUE.equals(property)); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.Viewport#setContents(org.eclipse.draw2d.IFigure) |
| */ |
| public void setContents(IFigure figure) { |
| super.setContents(figure); |
| // Need to layout when contents change |
| if (this.getContents() != null) |
| doLayout(true); |
| } |
| |
| /** |
| * RulerViewport uses local coordinates. |
| * |
| * @see org.eclipse.draw2d.Figure#useLocalCoordinates() |
| */ |
| protected boolean useLocalCoordinates() { |
| return true; |
| } |
| } |
| |
| } |