| /******************************************************************************* |
| * Copyright (c) 2005, 2012 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.bpel.ui.editparts.borders; |
| |
| import org.eclipse.bpel.ui.BPELUIPlugin; |
| import org.eclipse.bpel.ui.IBPELUIConstants; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.ImageFigure; |
| import org.eclipse.draw2d.Label; |
| import org.eclipse.draw2d.geometry.Insets; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.jface.resource.ColorRegistry; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.swt.graphics.Image; |
| |
| |
| /** |
| * This border knows about collapsability. Specifically, it has icons for expand |
| * and collapse, does hit testing for these icons, has an image and label to use |
| * when collapsed, and does complete rendering when collapsed to look similar to |
| * a leaf border (except with the addition of an expand icon). |
| * |
| * It does not do rendering for the expanded state. The rationale is that things |
| * should look similar when collapsed (like a leaf node) but may have different |
| * appearances when expanded. |
| */ |
| public abstract class CollapsableBorder extends GradientBorder { |
| |
| // Whether or not we are collapsed. |
| private boolean collapsed = false; |
| // The location of the collapsed image (+). |
| protected Rectangle rectCollapsed; |
| // The images for collapsed (+) and expanded (-). |
| protected Image collapsedImage, expandedImage; |
| // The width and height of the expanded image. Collapsed should be the same. |
| protected int expandedWidth, expandedHeight; |
| // The label to use when collapsed. Subclasses may also use it when expanded. |
| protected Label collapsedNameLabel = null; |
| // The image to use when collapsed. Subclasses may also use it when expanded. |
| protected Image image; |
| // The label containing the image. |
| protected ImageFigure imageLabel = null; |
| // Our parent figure. Used for relative location calculation. |
| protected IFigure parentFigure; |
| // The calculated rectangle for the collapsed border. This is null |
| // when not collapsed, so subclasses shouldn't assume it's there. |
| protected Rectangle collapsedBounds; |
| // The calculated location of the top and bottom drawer images as well as |
| // the top and bottom drawers themselves. |
| protected Point topImageLocation = new Point(), bottomImageLocation = new Point(); |
| protected Point topDrawerLocation = new Point(), bottomDrawerLocation = new Point(); |
| // The calculated bounds of the rectangle to draw when collapsed |
| protected Rectangle collapsedRectangle; |
| |
| public CollapsableBorder(boolean isVertical, int arcWidth, IFigure parentFigure, String labelText, Image image) { |
| super(isVertical, arcWidth); |
| this.parentFigure = parentFigure; |
| |
| this.image = image; |
| this.imageLabel = new ImageFigure(image); |
| |
| this.collapsedImage = BPELUIPlugin.INSTANCE.getImage(IBPELUIConstants.ICON_FIGURE_COLLAPSED); |
| this.expandedImage = BPELUIPlugin.INSTANCE.getImage(IBPELUIConstants.ICON_FIGURE_EXPANDED); |
| this.expandedHeight = expandedImage.getBounds().height; |
| this.expandedWidth = expandedImage.getBounds().width; |
| |
| this.collapsedNameLabel = new Label(labelText); |
| this.collapsedNameLabel.setFont(JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT)); |
| } |
| |
| /** |
| * Tests whether the given point is inside the collapsed image. |
| * The superclass only knows where the collapsed image is located; if subclasses |
| * want to do hit testing on the expanded image, they may override but may want |
| * to call super if we are collapsed. |
| */ |
| public boolean isPointInCollapseImage(int x, int y) { |
| if (!isCollapsed()) return false; |
| Point p = new Point(x,y); |
| parentFigure.translateToRelative(p); |
| Rectangle rect = rectCollapsed.getCopy(); |
| rect.expand(new Insets(1,1,1,1)); |
| return rect.contains(p); |
| } |
| |
| public boolean isCollapsed() { |
| return collapsed; |
| } |
| |
| public void setCollapsed(boolean showCollapse) { |
| this.collapsed = showCollapse; |
| } |
| |
| /** |
| * Throw away computed values that determine the layout |
| */ |
| public void invalidate() { |
| // rectCollapsed = null; |
| collapsedBounds = null; |
| } |
| |
| public Label getLabel() { |
| return collapsedNameLabel; |
| } |
| |
| public void setName(String name) { |
| collapsedNameLabel.setText(name); |
| } |
| |
| protected void calculate(IFigure figure) { |
| // Calculate the coordinates for collapsed state, even though |
| // we may currently be expanded. |
| if (collapsedBounds == null) { |
| collapsedBounds = figure.getBounds().getCopy(); |
| this.collapsedRectangle = collapsedBounds.getCopy(); |
| |
| // Leave room on the left and right for the drawer. |
| collapsedRectangle.x += DRAWER_WIDTH; |
| collapsedRectangle.width -= DRAWER_WIDTH * 2; |
| |
| // area for collapsed button |
| rectCollapsed = new Rectangle(collapsedBounds.x + collapsedBounds.width / 2 - expandedWidth/2, collapsedBounds.y + collapsedBounds.height - expandedHeight, expandedWidth, expandedHeight); |
| } |
| } |
| |
| /** |
| * This method first invalidates and recalculates any bounds, and then |
| * paints the top and bottom drawers, as well as any markers contained within them. |
| */ |
| @Override |
| public final void paint(IFigure figure, Graphics graphics, Insets insets) { |
| invalidate(); |
| calculate(figure); |
| doPaint(figure, graphics, insets); |
| } |
| |
| /** |
| * Subclasses should call this paint method unless there is a very good |
| * reason for overriding its behaviour. To affect where various things |
| * appear, override the calculate() method. |
| */ |
| protected void doPaint(IFigure figure, Graphics graphics, Insets insets) { |
| // Remember the clipping rectangle |
| Rectangle oldClip = new Rectangle(); |
| oldClip = graphics.getClip(oldClip); |
| |
| IMarker topMarker = getTopMarker(); |
| IMarker bottomMarker = getBottomMarker(); |
| if (topMarker != null || bottomMarker != null) { |
| ColorRegistry registry = BPELUIPlugin.INSTANCE.getColorRegistry(); |
| graphics.setForegroundColor(registry.get(IBPELUIConstants.COLOR_ACTIVITY_BORDER)); |
| Rectangle clippingRect; |
| if (bottomMarker == null) { |
| clippingRect = new Rectangle(topDrawerLocation.x, topDrawerLocation.y, DRAWER_WIDTH, DRAWER_HALF_HEIGHT + 1); |
| } else if (topMarker == null) { |
| clippingRect = new Rectangle(bottomDrawerLocation.x, bottomDrawerLocation.y, DRAWER_WIDTH, DRAWER_HALF_HEIGHT + 1); |
| } else { |
| clippingRect = new Rectangle(topDrawerLocation.x, topDrawerLocation.y, DRAWER_WIDTH, DRAWER_HEIGHT + 1); |
| } |
| graphics.setClip(clippingRect); |
| // -1 due to GEF |
| graphics.drawRoundRectangle(new Rectangle(topDrawerLocation.x + DRAWER_INSET, topDrawerLocation.y, DRAWER_WIDTH * 2, DRAWER_HEIGHT - 1), IBPELUIConstants.ARC_WIDTH, IBPELUIConstants.ARC_WIDTH); |
| graphics.setClip(oldClip); |
| if (bottomMarker == null || topMarker == null) { |
| graphics.drawLine(topDrawerLocation.x + DRAWER_INSET, topDrawerLocation.y + DRAWER_HALF_HEIGHT, topDrawerLocation.x + DRAWER_WIDTH, topDrawerLocation.y + DRAWER_HALF_HEIGHT); |
| } |
| |
| } |
| |
| // Draw the actual breakpoints |
| Image topImage = getTopImage(); |
| if (topImage != null) { |
| graphics.drawImage(topImage, topImageLocation); |
| } |
| Image bottomImage = getBottomImage(); |
| if (bottomImage != null) { |
| graphics.drawImage(bottomImage, bottomImageLocation); |
| } |
| } |
| |
| /** |
| * We only know about the gradient rectangle when we are collapsed. |
| * TODO: Do we need a gradient rectangle when collapsed? |
| */ |
| @Override |
| protected Rectangle getGradientRect() { |
| return new Rectangle(0,0,0,0); |
| } |
| |
| @Override |
| public boolean isPointInTopDrawer(int x, int y) { |
| if (getTopMarker() == null) return false; |
| Point p = new Point(x, y); |
| Image image = getTopImage(); |
| org.eclipse.swt.graphics.Rectangle imageSize = image.getBounds(); |
| Rectangle imageBounds = new Rectangle(topImageLocation.x, topImageLocation.y, imageSize.width, imageSize.height); |
| return imageBounds.contains(p); |
| } |
| |
| @Override |
| public boolean isPointInBottomDrawer(int x, int y) { |
| if (getBottomMarker() == null) return false; |
| Point p = new Point(x, y); |
| Image image = getBottomImage(); |
| org.eclipse.swt.graphics.Rectangle imageSize = image.getBounds(); |
| Rectangle imageBounds = new Rectangle(bottomImageLocation.x, bottomImageLocation.y, imageSize.width, imageSize.height); |
| return imageBounds.contains(p); |
| } |
| |
| /** |
| * Calculate the insets when in the collapsed state. In expanded state, we don't |
| * know how to answer. Insets don't matter in the collapsed state because there |
| * are no children. |
| */ |
| @Override |
| public Insets getInsets(IFigure figure) { |
| return new Insets(0, 0, 0, 0); |
| } |
| } |