/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.ui.figures; import java.util.List; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.LayoutAnimator; import org.eclipse.draw2d.LayoutManager; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Rectangle; import org.whole.lang.ui.layout.ColumnLayout; import org.whole.lang.ui.layout.ICompositeEntityLayout; import org.whole.lang.ui.layout.RowLayout; /** * @author Riccardo Solmi */ public class CompositeFigure extends EntityFigure { protected CompositeFigure() { } public CompositeFigure(boolean isHorizontal) { this(isHorizontal, true); } public CompositeFigure(boolean isHorizontal, boolean withPlaceholder) { setLayoutManager(createLayoutManager(isHorizontal)); setOpaque(false); if (withPlaceholder) setBorder(CompositePlaceHolderBorder.OPTIONAL_COMPOSITE); } public CompositeFigure(ICompositeEntityLayout layout) { this(layout, true); } public CompositeFigure(ICompositeEntityLayout layout, boolean withPlaceholder) { setLayoutManager(layout); setOpaque(false); if (withPlaceholder) setBorder(CompositePlaceHolderBorder.OPTIONAL_COMPOSITE); } protected ICompositeEntityLayout createLayoutManager(boolean isHorizontal) { return isHorizontal ? new RowLayout().withMarginLeft(4).withMarginRight(4).withSpacing(5) : new ColumnLayout().withMarginTop(5).withMarginBottom(5).withSpacing(5); } @Override public void setLayoutManager(LayoutManager manager) { super.setLayoutManager(manager); addLayoutListener(LayoutAnimator.getDefault()); } @Override public ICompositeEntityLayout getLayoutManager() { return (ICompositeEntityLayout) super.getLayoutManager(); } public boolean isHorizontal() { return getLayoutManager().isHorizontal(); } public void setHorizontal(boolean isHorizontal) { setLayoutManager(createLayoutManager(isHorizontal)); } private static final int MINIMUM_WIDTH = 4; private static final int MINIMUM_HEIGHT = 4; public Dimension getPreferredSize(int wHint, int hHint) { Dimension d = super.getPreferredSize(wHint, hHint); //FIXME move in the layout manager d.width = Math.max(d.width, MINIMUM_WIDTH); d.height = Math.max(d.height, MINIMUM_HEIGHT); return d; } public String toString() { return getChildren().toString()+"(visible="+isVisible()+")"; } @Override public void remove(IFigure figure) { invalidate(); //FIXME workaround to support Animation (initial state capture) super.remove(figure); } public void drawFixedSizeChildrenSeparators(Graphics g) { if (isHorizontal()) drawFixedSizeColumnSeparators(g); else drawFixedSizeRowSeparators(g); } public void drawVariableSizeChildrenSeparators(Graphics g) { if (isHorizontal()) drawVariableSizeColumnSeparators(g); else drawVariableSizeRowSeparators(g); } @SuppressWarnings("unchecked") public void drawFixedSizeRowSeparators(Graphics g) { List<IFigure> children = getChildren(); if (children.isEmpty()) return; int x0 = bounds.x; int x1 = bounds.right(); int spacing = getLayoutManager().getSpacing()/2; for (int i=0; i<children.size()-1; i++) { Rectangle boundsBefore = children.get(i).getBounds(); int y = boundsBefore.bottom() + spacing; g.drawLine(x0, y, x1, y); } } @SuppressWarnings("unchecked") public void drawFixedSizeColumnSeparators(Graphics g) { List<IFigure> children = getChildren(); if (children.isEmpty()) return; int y0 = bounds.y; int y1 = bounds.bottom(); int spacing = getLayoutManager().getSpacing()/2; for (int i=0; i<children.size()-1; i++) { Rectangle boundsBefore = children.get(i).getBounds(); int x = boundsBefore.right() + spacing; g.drawLine(x, y0, x, y1); } } @SuppressWarnings("unchecked") public void drawVariableSizeRowSeparators(Graphics g) { List<IFigure> children = getChildren(); if (children.isEmpty()) return; int spacing = getLayoutManager().getSpacing()/2; for (int i=0; i<children.size()-1; i++) { Rectangle boundsBefore = children.get(i).getBounds(); Rectangle boundsAfter = children.get(i+1).getBounds(); int x0 = Math.min(boundsBefore.x, boundsAfter.x); int x1 = boundsBefore.right() > boundsAfter.right() || boundsBefore.right() < boundsAfter.x ? boundsBefore.right() : boundsAfter.right(); int y = boundsBefore.bottom() + spacing; g.drawLine(x0, y, x1, y); } } @SuppressWarnings("unchecked") public void drawVariableSizeColumnSeparators(Graphics g) { List<IFigure> children = getChildren(); if (children.isEmpty()) return; int spacing = getLayoutManager().getSpacing()/2; for (int i=0; i<children.size()-1; i++) { Rectangle boundsBefore = children.get(i).getBounds(); Rectangle boundsAfter = children.get(i+1).getBounds(); int y0 = Math.min(boundsBefore.y, boundsAfter.y); int y1 = boundsBefore.bottom() > boundsAfter.bottom() || boundsBefore.bottom() < boundsAfter.y ? boundsBefore.bottom() : boundsAfter.bottom(); int x = boundsBefore.right() + spacing; g.drawLine(x, y0, x, y1); } } public void drawChildrenBorder(Graphics g) { if (isHorizontal()) drawColumnsBorder(g); else drawRowsBorder(g); } public void drawRowsBorder(Graphics g) { int lw = g.getLineWidth()/2; int y = bounds.y+lw; int x0 = bounds.x; int x1 = bounds.right(); g.drawLine(x0, y, x1, y); y = bounds.bottom()-lw; g.drawLine(x0, y, x1, y); } public void drawColumnsBorder(Graphics g) { int lw = g.getLineWidth()/2; int x = bounds.x+lw; int y0 = bounds.y; int y1 = bounds.bottom(); g.drawLine(x, y0, x, y0); x = bounds.right()-lw; g.drawLine(x, y0, x, y1); } }