| /******************************************************************************* |
| * Copyright (c) 2005 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.common.ui.tray; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.bpel.common.ui.ICommonUIConstants; |
| import org.eclipse.bpel.common.ui.CommonUIPlugin; |
| import org.eclipse.bpel.common.ui.details.IDetailsColors; |
| import org.eclipse.bpel.common.ui.details.widgets.NoBorderButton; |
| import org.eclipse.draw2d.AbstractLayout; |
| import org.eclipse.draw2d.ActionEvent; |
| import org.eclipse.draw2d.ActionListener; |
| import org.eclipse.draw2d.Figure; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.ImageFigure; |
| import org.eclipse.draw2d.KeyEvent; |
| import org.eclipse.draw2d.Label; |
| import org.eclipse.draw2d.PositionConstants; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.gef.DragTracker; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.EditPolicy; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.Handle; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.RequestConstants; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.commands.CompoundCommand; |
| import org.eclipse.gef.requests.CreateRequest; |
| import org.eclipse.gef.requests.CreationFactory; |
| import org.eclipse.gef.requests.GroupRequest; |
| import org.eclipse.gef.tools.SelectEditPartTracker; |
| |
| |
| /** |
| * Represents a category in the Tray. |
| */ |
| public abstract class TrayCategoryEditPart extends TrayContainerEditPart { |
| protected SelectionBorderFigure titleFigure; |
| |
| protected class TrayCategoryEntrySelectionEditPolicy extends TraySelectionEditPolicy { |
| @Override |
| protected Handle createHandle(GraphicalEditPart owner) { |
| return new TraySelectionHandle(owner, titleFigure); |
| } |
| } |
| /** |
| * A layout for the title of this edit part: |
| * ICON LABEL ADD_BUTTON REMOVE_BUTTON |
| */ |
| protected class TitleLayout extends AbstractLayout { |
| private static final int SPACING = 2; |
| public void layout(IFigure container) { |
| List elements = container.getChildren(); |
| ImageFigure icon = (ImageFigure)elements.get(0); |
| Label text = (Label)elements.get(1); |
| Figure removeButton = (Figure)elements.get(2); |
| Figure addButton = (Figure)elements.get(3); |
| |
| Rectangle containerBounds = container.getBounds(); |
| int x = containerBounds.x + SPACING; |
| int y = containerBounds.y; |
| int height = containerBounds.height; |
| |
| Dimension size = icon.getPreferredSize(); |
| Rectangle bounds = new Rectangle(x, y, size.width, height); |
| icon.setBounds(bounds); |
| |
| size = removeButton.getPreferredSize(); |
| x = (containerBounds.x + containerBounds.width) - size.width; |
| bounds = new Rectangle(x, y, size.width, height); |
| removeButton.setBounds(bounds); |
| |
| size = addButton.getPreferredSize(); |
| x = x - size.width; |
| bounds = new Rectangle(x, y, size.width, height); |
| addButton.setBounds(bounds); |
| |
| x = icon.getBounds().x + icon.getBounds().width; |
| x = x + SPACING; |
| int width = containerBounds.width - (icon.getBounds().width + removeButton.getBounds().width + addButton.getBounds().width); |
| bounds = new Rectangle(x, y, width, height); |
| text.setBounds(bounds); |
| } |
| @Override |
| protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) { |
| Dimension result = new Dimension(0, hHint); |
| for (Iterator<IFigure> iter = container.getChildren().iterator(); iter.hasNext();) { |
| IFigure child = iter.next(); |
| Dimension size = (child instanceof Label) ? child.getMinimumSize() : child.getPreferredSize(); |
| result.height = Math.max(result.height, size.height); |
| result.width += size.width; |
| } |
| result.height += (SPACING*2); // give it some extra pixels |
| return result; |
| } |
| } |
| |
| /** |
| * The figure representing the title of this container. |
| */ |
| protected class TitleFigure extends SelectionBorderFigure { |
| protected Label textLabel; |
| protected NoBorderButton addButton; |
| protected NoBorderButton removeButton; |
| public TitleFigure() { |
| super(); |
| setLayoutManager(new TitleLayout()); |
| setOpaque(true); |
| setBackgroundColor(CommonUIPlugin.getDefault().getColorRegistry().get(IDetailsColors.COLOR_LIGHT_BACKGROUND)); |
| add(new ImageFigure(getLabelProvider().getImage(getModel()))); |
| textLabel = new Label(getLabelProvider().getText(getModel())); |
| textLabel.setLabelAlignment(PositionConstants.LEFT); |
| add(textLabel); |
| |
| removeButton = new NoBorderButton(CommonUIPlugin.getDefault().getImageRegistry().get(ICommonUIConstants.ICON_TRAY_CATEGORY_REMOVE_BUTTON)) { |
| @Override |
| public void handleKeyPressed(KeyEvent event) { |
| // Do nothing - the button can only be pressed with a mouse |
| } |
| @Override |
| public void handleKeyReleased(KeyEvent event) { |
| // Do nothing - the button can only be pressed with a mouse |
| } |
| }; |
| removeButton.setOpaque(false); |
| removeButton.setToolTip(getRemoveToolTip()); |
| removeButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent event) { |
| removeEntry(); |
| } |
| }); |
| |
| addButton = new NoBorderButton(CommonUIPlugin.getDefault().getImageRegistry().get(ICommonUIConstants.ICON_TRAY_CATEGORY_ADD_BUTTON)) { |
| @Override |
| public void handleKeyPressed(KeyEvent event) { |
| // Do nothing - the button can only be pressed with a mouse |
| } |
| @Override |
| public void handleKeyReleased(KeyEvent event) { |
| // Do nothing - the button can only be pressed with a mouse |
| } |
| }; |
| addButton.setOpaque(false); |
| addButton.setToolTip(getAddToolTip()); |
| addButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent event) { |
| addEntry(); |
| } |
| }); |
| |
| add(removeButton); |
| add(addButton); |
| } |
| public Label getTextLabel() { |
| return textLabel; |
| } |
| } |
| |
| /** |
| * Adds a new entry to the category. Returns the new model object. |
| */ |
| protected Object addEntry() { |
| CreateRequest request = new CreateRequest(); |
| request.setFactory(getCreationFactory()); |
| Command command = getCommand(request); |
| getCommandStack().execute(command); |
| Object newObject = request.getNewObject(); |
| // Select the new item after creation |
| selectEditPart(newObject); |
| return newObject; |
| } |
| |
| /** |
| * Adds a new entry to the category. Returns the new model object. |
| * Used by the AddChildInTrayAction. |
| */ |
| public Object publicAddEntry() { |
| return addEntry(); |
| } |
| |
| /** |
| * Called by the remove button to remove the currently selected entry. |
| */ |
| protected void removeEntry() { |
| List selectedParts = getViewer().getSelectedEditParts(); |
| if (selectedParts.size() == 0) return; // nothing to be done |
| |
| // we can only delete edit parts that are children of this edit part |
| List<EditPart> condemned = new ArrayList<EditPart>(); |
| for (Iterator<EditPart> iter = selectedParts.iterator(); iter.hasNext();) { |
| EditPart part = iter.next(); |
| if (part.getParent() == TrayCategoryEditPart.this) { |
| condemned.add(part); |
| } |
| } |
| if (condemned.isEmpty()) return; // nothing to be done |
| |
| // gets the index to be used in the post-deletion selection |
| EditPart indexPart = condemned.get(0); |
| int index = getModelChildren().indexOf(indexPart.getModel()); |
| |
| // remove all the valid selected edit parts |
| GroupRequest request = new GroupRequest(RequestConstants.REQ_DELETE); |
| CompoundCommand deletions = new CompoundCommand(); |
| for (Iterator<EditPart> iter = condemned.iterator(); iter.hasNext();) { |
| EditPart part = iter.next(); |
| deletions.add(part.getCommand(request)); |
| } |
| getCommandStack().execute(deletions); |
| |
| // Select the next edit part if one is available |
| int size = getModelChildren().size(); |
| if (size == 0) return; // nothing to be done |
| if (size > index) { |
| selectEditPart(getModelChildren().get(index)); |
| } else { |
| selectEditPart(getModelChildren().get(size-1)); |
| } |
| } |
| |
| public TrayCategoryEditPart() { |
| super(); |
| } |
| |
| @Override |
| protected TrayContainerFigure createMainFigure() { |
| return new TrayContainerFigure() { |
| @Override |
| protected void paintBorder(Graphics graphics) { |
| graphics.setForegroundColor(CommonUIPlugin.getDefault().getColorRegistry().get(IDetailsColors.COLOR_DARK_SHADOW)); |
| Rectangle area = getClientArea().getCopy(); |
| area.height--; |
| graphics.drawLine(area.getTopLeft(), area.getTopRight()); |
| } |
| }; |
| } |
| |
| @Override |
| protected IFigure createTitleFigure() { |
| return titleFigure = new TitleFigure(); |
| } |
| |
| /** |
| * As part of our layout, the entries and the category should have |
| * the same x-coordinate for their texts. This is the figure used |
| * by the entries to calculate the position of their text. |
| */ |
| public IFigure getLabelPositionReference() { |
| return ((TitleFigure)getTitleFigure()).getTextLabel(); |
| } |
| |
| @Override |
| protected void createEditPolicies() { |
| installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new TrayCategoryEntrySelectionEditPolicy()); |
| } |
| |
| /** |
| * Subclasses need to provide a creation factory for the category entry creation. |
| */ |
| protected abstract CreationFactory getCreationFactory(); |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.gef.EditPart#getDragTracker(org.eclipse.gef.Request) |
| */ |
| @Override |
| public DragTracker getDragTracker(Request request) { |
| return new SelectEditPartTracker(this); |
| } |
| |
| @Override |
| public Label getDirectEditLabel() { |
| return null; |
| } |
| |
| /** |
| * Return the label to be used as the tooltip for the Add button. |
| * Subclasses may override. |
| */ |
| protected IFigure getAddToolTip() { |
| return new Label("Add"); |
| } |
| |
| /** |
| * Return the label to be used as the tooltip for the Add button. |
| * Subclasses may override. |
| */ |
| protected IFigure getRemoveToolTip() { |
| return new Label("Remove"); |
| } |
| } |