/**************************************************************************** * Copyright (c) 2009 CEA LIST. * * 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: * Patrick Tessier (CEA LIST), Thibault Landre (Atos Origin) - Initial API and implementation * Vincent Lorenzo (CEA LIST), change layout(IFigure container) *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.figure.node; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.AbstractLayout; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure; import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel; /** * this is the layout manager in charge to place element in compartment element. * A modification of the code has been done in order to manage none visible * compartment. if a compartment becomes invisible, its size and its height are * equal to 1. * */ public class AutomaticCompartmentLayoutManager extends AbstractLayout { protected static final int MINIMUM_COMPARTMENT_HEIGHT = 15; // list of compartments protected ArrayList<IFigure> compartmentList = new ArrayList<IFigure>(); // list of none compartments ex wrapping label etc... protected ArrayList<IFigure> notCompartmentList = new ArrayList<IFigure>(); protected boolean addExtraHeight = true; /** * set the distance between compartments * @param addExtraHeight */ public void setAddExtraHeight(boolean addExtraHeight) { this.addExtraHeight = addExtraHeight; } /** * * {@inheritDoc} */ @Override protected Dimension calculatePreferredSize(IFigure container, int hint, int hint2) { collectInformationOnChildren(container); int minimumWith = 0; int minimumHeight = 0; if(container instanceof CompartmentFigure) { // display name if(((CompartmentFigure)container).getNameLabel() != null) { if(((CompartmentFigure)container).getNameLabel().getPreferredSize().width > minimumWith) { minimumWith = ((CompartmentFigure)container).getNameLabel().getPreferredSize().width; } } } if(compartmentList.size() != 0) { for(int i = 0; i < container.getChildren().size(); i++) { IFigure child = (IFigure)container.getChildren().get(i); minimumHeight += child.getPreferredSize().height; minimumWith = Math.max(minimumWith, child.getPreferredSize().width); } } else { for(int i = 0; i < notCompartmentList.size(); i++) { minimumHeight += notCompartmentList.get(i).getPreferredSize().height; } } if(addExtraHeight) minimumHeight += 7; return new Dimension(minimumWith, minimumHeight); } @Override public Dimension getMinimumSize(IFigure container, int wHint, int hHint) { return new Dimension(20,20); } /** * layout by putting label in the center of figure * * @param container */ protected void layoutCenterForLabel(IFigure container) { int labelheight = 0; for(int i = 0; i < notCompartmentList.size(); i++) { labelheight += notCompartmentList.get(i).getPreferredSize().height; } for(int i = 0; i < container.getChildren().size(); i++) { if(notCompartmentList.contains((container.getChildren().get(i)))) { Rectangle bound = new Rectangle(((IFigure)container.getChildren().get(i)).getBounds()); bound.setSize(getPreferedSize(((IFigure)container.getChildren().get(i)))); if(i > 0) { bound.y = ((IFigure)container.getChildren().get(i - 1)).getBounds().getBottomLeft().y + 1; bound.x = container.getBounds().x + 3; bound.width = container.getBounds().width; } else { bound.x = container.getBounds().x + 3; bound.y = container.getBounds().y + ((container.getBounds().height - labelheight) / 2); bound.width = container.getBounds().width; } ((IFigure)container.getChildren().get(i)).setBounds(bound); } else { Rectangle bound = new Rectangle(((IFigure)container.getChildren().get(i)).getBounds()); bound.y = container.getBounds().getBottomLeft().y + 1; bound.x = container.getBounds().x + 3; ((IFigure)container.getChildren().get(i)).setBounds(bound); } } } /** * * {@inheritDoc} */ public void layout(IFigure container) { collectInformationOnChildren(container); // this list contains the visible compartments (that is to say : // notCompartmentList + compartmentsList List<IFigure> visibleCompartments = new ArrayList<IFigure>(); visibleCompartments.addAll(notCompartmentList); visibleCompartments.addAll(compartmentList); // choose the good layout by taking in account if it exist GMF // compartment if(compartmentList.size() != 0) { // visit all compartment for(int i = 0; i < container.getChildren().size(); i++) { IFigure currentCompartment= (IFigure) container.getChildren().get(i); // this is a visible compartment if( visibleCompartments.contains(currentCompartment)){ Rectangle bound = new Rectangle(currentCompartment.getBounds()); currentCompartment.invalidate(); Dimension pref=currentCompartment.getPreferredSize(); currentCompartment.invalidate(); Dimension prefConstraint=currentCompartment.getPreferredSize(container.getBounds().width-40,-1); if( pref.width<prefConstraint.width){ bound.setSize(pref); } else{ bound.setSize(prefConstraint); } //bound.setSize(getPreferedSize(currentCompartment)); if(visibleCompartments.indexOf(currentCompartment) > 0) { bound.y = (visibleCompartments.get(visibleCompartments.indexOf(currentCompartment) - 1)).getBounds().getBottomLeft().y + 1; bound.x = container.getBounds().x + 3; bound.width = container.getBounds().width; } else { bound.x = container.getBounds().x + 3; bound.y = container.getBounds().y + 3; bound.width = container.getBounds().width; } currentCompartment.setBounds(bound); } else{ // this is a none visible compartment Rectangle bound = new Rectangle(currentCompartment.getBounds()); bound.setSize(1,1); currentCompartment.setBounds(bound); } } optimizeCompartmentSize(container); } else { layoutCenterForLabel(container); } } /** * Optimize the size of each compartment depending on the size of the * compartments container, and the size of each compartment. If a * compartment is empty, or not expanded, then a default size is applied to * this compartment * * @param compartmentsDimension * an hashmap containing each compartment dimension. */ protected void optimizeCompartmentSize(IFigure container) { int compartmentsHeight = 0; int notCompartmentsHeight = 0; for(int i = 0; i < notCompartmentList.size(); i++) { notCompartmentsHeight += notCompartmentList.get(i).getBounds().height; } for(int i = 0; i < compartmentList.size(); i++) { compartmentsHeight += compartmentList.get(i).getBounds().height; } int remainingspace = container.getBounds().height - notCompartmentsHeight; // ratio between the height of all compartments and the size of the // compartments container. double ratio = new Integer(compartmentsHeight).doubleValue() / new Integer(remainingspace).doubleValue(); for(int i = 0; i < compartmentList.size(); i++) { Rectangle bound = new Rectangle((compartmentList.get(i)).getBounds()); int value = (int)(bound.height / ratio); bound.height = value; bound.x = container.getBounds().x; if(i > 0) { bound.y = (compartmentList.get(i - 1)).getBounds().getBottomLeft().y + 1; } (compartmentList.get(i)).setBounds(bound); } } /** * use to know what kind of element we have in order to apply the good * policy for the disposition * @param container */ public void collectInformationOnChildren(IFigure container) { compartmentList = new ArrayList<IFigure>(); notCompartmentList = new ArrayList<IFigure>(); for(int i = 0; i < container.getChildren().size(); i++) { if(isAGMFContainer(((IFigure)container.getChildren().get(i)))||((container.getChildren().get(i)) instanceof StereotypePropertiesCompartment)) { compartmentList.add(((IFigure)container.getChildren().get(i))); } else { if((container.getChildren().get(i)) instanceof Label || (container.getChildren().get(i)) instanceof WrappingLabel) { notCompartmentList.add(((IFigure)container.getChildren().get(i))); } } } } /** * obtain a prefered size * * @param figure * that can contain a GMF compartment figure * @return a the size */ public Dimension getPreferedSize(IFigure figure) { Dimension dim = figure.getPreferredSize(); if(figure.getChildren().size() > 0) { Object compartment = figure.getChildren().get(0); if(compartment instanceof ResizableCompartmentFigure) { dim.height = ((ResizableCompartmentFigure)compartment).getPreferredSize().height + 10; if(dim.height == 0) { dim.height = MINIMUM_COMPARTMENT_HEIGHT; } } } return dim; } /** * tests is the figure contains a GMF compartment * * @param figure * @return true if this is the case */ public boolean isAGMFContainer(IFigure figure) { if (figure instanceof StereotypePropertiesCompartment){return false;} if(figure.getChildren().size() > 0) { if(figure.getChildren().get(0) instanceof ResizableCompartmentFigure) { return true; } } return false; } }