/*******************************************************************************
* Copyright (c) 2009 the CHISEL group and contributors.
* 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:
* Del Myers -- initial API and implementation
*******************************************************************************/
package org.eclipse.zest.custom.sequence.visuals;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.draw2d.AbstractConnectionAnchor;
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.ActionEvent;
import org.eclipse.draw2d.ActionListener;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.GridData;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.zest.custom.sequence.figures.LifeLineFigure;
import org.eclipse.zest.custom.sequence.figures.PlusMinusFigure;
import org.eclipse.zest.custom.sequence.figures.SequenceClassFigure;
import org.eclipse.zest.custom.sequence.figures.internal.ZoomListener;
import org.eclipse.zest.custom.sequence.figures.internal.ZoomManager;
import org.eclipse.zest.custom.sequence.widgets.Lifeline;
import org.eclipse.zest.custom.sequence.widgets.UMLItem;
import org.eclipse.zest.custom.sequence.widgets.internal.IWidgetProperties;
/**
* Visual representation of a life line.
* @author Del Myers
*/
public class LifelineVisual extends NodeVisualPart implements org.eclipse.zest.custom.sequence.widgets.PropertyChangeListener, ZoomListener {
private class InternalFigure extends Figure {
private SequenceClassFigure classFigure;
private LifeLineFigure lifeLineFigure;
InternalFigure(int type) {
classFigure = new SequenceClassFigure(type);
lifeLineFigure = new LifeLineFigure();
super.add(lifeLineFigure, null, -1);
super.add(classFigure, null, -1);
setLayoutManager(new AbstractLayout(){
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
Rectangle bounds = container.getBounds();
Rectangle parentB = container.getParent().getBounds();
Dimension classSize = classFigure.getPreferredSize(wHint, 0);
Dimension lifeSize = lifeLineFigure.getPreferredSize(wHint, hHint-classSize.height);
int width = classSize.width;
int height = Math.max(lifeSize.height + classSize.height, parentB.height-bounds.y);
return new Dimension(width,height);
}
public void layout(IFigure container) {
//stack one on top of the other
Rectangle bounds = container.getBounds();
Rectangle classBounds = new Rectangle(bounds.x, bounds.y, bounds.width, 0);
lifeLineFigure.setBounds(new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height));
classFigure.setBounds(classBounds);
}
});
}
public void add(IFigure figure, Object constraint, int index) {
lifeLineFigure.add(figure, constraint, index);
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#remove(org.eclipse.draw2d.IFigure)
*/
public void remove(IFigure figure) {
if (figure.getParent() == lifeLineFigure) {
lifeLineFigure.remove(figure);
} else {
super.remove(figure);
}
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
*/
public void setBounds(Rectangle rect) {
super.setBounds(rect);
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#getBounds()
*/
public Rectangle getBounds() {
return super.getBounds();
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#getClientArea(org.eclipse.draw2d.geometry.Rectangle)
*/
public Rectangle getClientArea(Rectangle rect) {
Rectangle area = classFigure.getBounds().getCopy();
area.union(lifeLineFigure.getBounds());
return area;
}
/* (non-Javadoc)
* @see org.eclipse.draw2d.Figure#containsPoint(int, int)
*/
public boolean containsPoint(int x, int y) {
return lifeLineFigure.containsPoint(x, y) || classFigure.containsPoint(x, y);
}
}
private ConnectionAnchor anchor;
private PlusMinusFigure expander;
private SequenceClassFigure classFigure;
private InternalFigure internalFigure;
/**
* @param item
* @param key
* @param parentFigure
*/
public LifelineVisual(UMLItem item, String key) {
super(item, key);
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.visuals.WidgetVisualPart#createFigure()
*/
@Override
public IFigure createFigures() {
int type = SequenceClassFigure.CLASS;
switch(getCastedModel().getTargetStyle()) {
case Lifeline.ACTOR:
type = SequenceClassFigure.ACTOR;
break;
case Lifeline.BOUNDARY:
type = SequenceClassFigure.BOUNDARY;
break;
case Lifeline.COLLECTION:
type = SequenceClassFigure.COLLECTION;
break;
case Lifeline.CONTROL:
type = SequenceClassFigure.CONTROL;
break;
case Lifeline.DATA_STORE:
type = SequenceClassFigure.DATA_STORE;
break;
case Lifeline.ENTITY:
type = SequenceClassFigure.ENTITY;
break;
case Lifeline.PACKAGE:
type = SequenceClassFigure.PACKAGE;
break;
}
classFigure = new SequenceClassFigure(type);
internalFigure = new InternalFigure(type);
internalFigure.setFont(Display.getCurrent().getSystemFont());
anchor = new AbstractConnectionAnchor(internalFigure.classFigure){
public Point getLocation(Point reference) {
Point point = getOwner().getBounds().getCenter();
point.y = getOwner().getBounds().y;
getOwner().translateToAbsolute(point);
return point;
}
};
classFigure.getLabel().setIcon(getWidget().getImage());
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = 1;
layout.marginWidth = 1;
classFigure.setLayoutManager(layout);
internalFigure.classFigure.getLabel().setIcon(getWidget().getImage());
internalFigure.lifeLineFigure.setFilled(false);
internalFigure.lifeLineFigure.setBackgroundColor(getWidget().getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
// feedbackFigure = new SequenceClassFigure(type);
// feedbackFigure.setEnabled(false);
Label toolTip = new Label();
toolTip.setText(getCastedModel().getText());
internalFigure.setToolTip(toolTip);
expander = new PlusMinusFigure(9);
expander.setSelected(false);
expander.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
getCastedModel().setExpanded(!getCastedModel().isExpanded());
}
});
return classFigure;
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.visuals.WidgetVisualPart#getFigures()
*/
@Override
public List<IFigure> getFigures() {
LinkedList<IFigure> figures = new LinkedList<IFigure>();
figures.add(getFigure());
figures.add(classFigure);
return figures;
}
private Lifeline getCastedModel() {
return (Lifeline)getWidget();
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.visuals.WidgetVisualPart#refreshVisuals()
*/
@Override
public void refreshVisuals() {
Lifeline model = getCastedModel();
String stereotype =
(String)model.getStereoType();
String text = model.getText();
internalFigure.classFigure.setClassName(text);
classFigure.setClassName(text);
internalFigure.classFigure.setStereoType(stereotype);
classFigure.setStereoType(stereotype);
classFigure.getLabel().setIcon(getWidget().getImage());
internalFigure.classFigure.getLabel().setIcon(getWidget().getImage());
Label tooltipFigure = (Label) internalFigure.getToolTip();
String tooltipText = getWidget().getTooltipText();
if (tooltipText == null) {
tooltipText = getWidget().getText();
}
tooltipFigure.setText(tooltipText);
if (model.getData("pin") != null) {
internalFigure.classFigure.setLineWidth(2);
classFigure.setLineWidth(2);
} else {
internalFigure.classFigure.setLineWidth(1);
internalFigure.lifeLineFigure.setFilled(false);
classFigure.setLineWidth(1);
}
internalFigure.lifeLineFigure.setFilled(model.isHighlighted());
if ((getWidget().getBackground()) != null) {
internalFigure.classFigure.setBackgroundColor(((getWidget()).getBackground()));
classFigure.setBackgroundColor(((getWidget()).getBackground()));
} else if (internalFigure.getParent() != null){
internalFigure.classFigure.setBackgroundColor(internalFigure.getParent().getBackgroundColor());
classFigure.setBackgroundColor(internalFigure.getParent().getBackgroundColor());
}
Label l = internalFigure.classFigure.getLabel();
Label cl = classFigure.getLabel();
if (getWidget().getForeground() != null) {
internalFigure.classFigure.setForegroundColor(((getWidget()).getForeground()));
classFigure.setForegroundColor(((getWidget()).getForeground()));
} else if (internalFigure.getParent() != null){
internalFigure.classFigure.setForegroundColor(internalFigure.getParent().getForegroundColor());
classFigure.setForegroundColor(internalFigure.getParent().getForegroundColor());
}
if (getCastedModel().getTextBackground() != null) {
l.setBackgroundColor(getCastedModel().getTextBackground());
l.setOpaque(true);
cl.setBackgroundColor(getCastedModel().getTextBackground());
cl.setOpaque(true);
} else {
l.setOpaque(false);
cl.setOpaque(false);
}
if (getCastedModel().getTextForeground() != null) {
l.setForegroundColor(getCastedModel().getTextForeground());
cl.setForegroundColor(getCastedModel().getTextForeground());
}
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.visuals.WidgetVisualPart#activate()
*/
@Override
public void activate() {
super.activate();
hookWidget();
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.visuals.WidgetVisualPart#getFigure()
*/
@Override
public IFigure getFigure() {
// TODO Auto-generated method stub
return super.getFigure();
}
/**
*
*/
private void hookWidget() {
getCastedModel().addPropertyChangeListener(this);
ZoomManager manager = (ZoomManager) getChartVisuals().getChart().getData("ZoomManager");
if (manager != null) {
manager.addZoomListener(this);
}
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.visuals.WidgetVisualPart#deactivate()
*/
@Override
public void deactivate() {
unhookWidget();
super.deactivate();
}
/**
*
*/
private void unhookWidget() {
ZoomManager manager = (ZoomManager) getChartVisuals().getChart().getData("ZoomManager");
if (manager != null) {
manager.removeZoomListener(this);
}
getCastedModel().removePropertyChangeListener(this);
if (!getWidget().isDisposed())
getCastedModel().setData(IWidgetProperties.LAYOUT, null);
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.widgets.PropertyChangeListener#propertyChanged(java.lang.Object, java.lang.String, java.lang.Object, java.lang.Object)
*/
public void propertyChanged(Object source, String property, Object oldValue, Object newValue) {
if (getChartVisuals().refreshing) return; //early return
if (IWidgetProperties.LAYOUT.equals(property)) {
if (newValue == null) return;
internalFigure.getParent().setConstraint(internalFigure, newValue);
internalFigure.invalidate();
classFigure.invalidateTree();
if (classFigure.getParent() != null) {
Rectangle r = (Rectangle) newValue;
r = r.getCopy().setSize(r.width, MessageBasedSequenceVisuals.OBJECT_HEIGHT);
r.y=0;
//scale the x position
ZoomManager manager = (ZoomManager) getChartVisuals().getChart().getData("ZoomManager");
if (manager != null) {
r.x *= manager.getZoom();
int zoomedWidth = (int) (r.width*manager.getZoom());
if (zoomedWidth > r.width) {
r.x += (zoomedWidth/2-r.width/2);
} else {
r.width = zoomedWidth;
}
}
classFigure.getParent().setConstraint(classFigure, r);
}
} else if (IWidgetProperties.HIGHLIGHT.equals(property)) {
internalFigure.lifeLineFigure.setFilled(getWidget().isHighlighted());
} else if ("pin".equals(property)) {
if (newValue != null) {
internalFigure.classFigure.setLineWidth(2);
classFigure.setLineWidth(2);
} else {
internalFigure.classFigure.setLineWidth(1);
classFigure.setLineWidth(1);
}
} else if (IWidgetProperties.BACKGROUND_COLOR.equals(property)) {
if ((getWidget().getBackground()) != null) {
internalFigure.classFigure.setBackgroundColor(((getWidget()).getBackground()));
classFigure.setBackgroundColor(((getWidget()).getBackground()));
} else if (internalFigure.getParent() != null){
internalFigure.classFigure.setBackgroundColor(internalFigure.getParent().getBackgroundColor());
classFigure.setBackgroundColor(internalFigure.getParent().getBackgroundColor());
}
} else if (IWidgetProperties.FOREGROUND_COLOR.equals(property)) {
if (getWidget().getForeground() != null) {
internalFigure.classFigure.setForegroundColor(((getWidget()).getForeground()));
classFigure.setForegroundColor(((getWidget()).getForeground()));
} else if (internalFigure.getParent() != null){
internalFigure.classFigure.setForegroundColor(internalFigure.getParent().getForegroundColor());
classFigure.setForegroundColor(internalFigure.getParent().getForegroundColor());
}
} else if (IWidgetProperties.TEXT_BACKGROUND.equals(property)) {
Label l = ((InternalFigure)internalFigure).classFigure.getLabel();
if (getCastedModel().getTextBackground() != null) {
l.setBackgroundColor(getCastedModel().getTextBackground());
l.setOpaque(true);
} else {
l.setOpaque(false);
}
l = classFigure.getLabel();
if (getCastedModel().getTextBackground() != null) {
l.setBackgroundColor(getCastedModel().getTextBackground());
l.setOpaque(true);
} else {
l.setOpaque(false);
}
} else if (IWidgetProperties.TEXT_FOREGROUND.equals(property)) {
Label l = internalFigure.classFigure.getLabel();
if (getCastedModel().getTextForeground() != null) {
l.setForegroundColor(getCastedModel().getTextForeground());
}
l = classFigure.getLabel();
if (getCastedModel().getTextForeground() != null) {
l.setForegroundColor(getCastedModel().getTextForeground());
}
} else if (IWidgetProperties.TOOLTIP.equals(property)) {
Label tooltipFigure = (Label) internalFigure.getToolTip();
String tooltipText = getWidget().getTooltipText();
if (tooltipText == null) {
tooltipText = getWidget().getText();
}
tooltipFigure.setText(tooltipText);
} else if (IWidgetProperties.CHILD.equals(property)) {
updateExpander();
} else if (IWidgetProperties.EXPANDED.equals(property)) {
updateExpander();
}
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.figures.internal.ZoomListener#zoomChanged(double)
*/
public void zoomChanged(double zoom) {
ZoomManager manager = (ZoomManager) getChartVisuals().getChart().getData("ZoomManager");
if (manager == null) return;
if (classFigure.getParent() != null) {
Rectangle r = (Rectangle) internalFigure.getBounds();
r = r.getCopy().setSize(r.width, MessageBasedSequenceVisuals.OBJECT_HEIGHT);
r.y=0;
//scale the x position
r.x *= manager.getZoom();
int zoomedWidth = (int) (r.width*manager.getZoom());
if (zoomedWidth > r.width) {
r.x += (zoomedWidth/2-r.width/2);
} else {
r.width = zoomedWidth;
}
classFigure.getParent().setConstraint(classFigure, r);
}
}
/**
*
*/
private void updateExpander() {
if (getCastedModel().getChildren().length > 0) {
if (expander.getParent() != classFigure) {
GridData data = new GridData(GridData.CENTER, GridData.BEGINNING, false, false);
data.widthHint = 9;
data.heightHint = 9;
classFigure.add(expander, data);
expander.setSelected(!getCastedModel().isExpanded());
}
} else {
if (expander.getParent() == classFigure) {
classFigure.remove(expander);
}
}
}
public IFigure getClassFigure() {
return classFigure;
}
/* (non-JavinternalFigure.getParent()rg.eclipse.mylar.zest.custom.sequence.visuals.NodeVisualPart#getSourceAnchor(org.eclipse.mylar.zest.custom.sequence.visuals.ConnectionVisualPart)
*/
@Override
public ConnectionAnchor getSourceAnchor(ConnectionVisualPart part) {
return anchor;
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.visuals.NodeVisualPart#getTargetAnchor(org.eclipse.mylar.zest.custom.sequence.visuals.ConnectionVisualPart)
*/
@Override
public ConnectionAnchor getTargetAnchor(ConnectionVisualPart part) {
return anchor;
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.visuals.WidgetVisualPart#installFigures()
*/
@Override
protected void installFigures() {
IFigure layer = getLayer(LayerConstants.LIFELINE_LAYER);
layer.add(internalFigure);
layer = getLayer(LayerConstants.OBJECT_LAYER);
if (layer != null) {
layer.add(classFigure);
}
updateExpander();
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.visuals.WidgetVisualPart#uninstallFigures()
*/
@Override
protected void uninstallFigures() {
super.uninstallFigures();
if (internalFigure != null && internalFigure.getParent() != null) {
internalFigure.getParent().remove(internalFigure);
}
}
}