Sponsored link
BorderLayoutのCenterの伸びをカスタム(Draw2D/GEF - Java Eclipse)
単純に、LabelFigureを5箇所に追加してみました。
左が普通のBorderLayout
真ん中は、カスタムで元のFigureのサイズのまま
右は、カスタムでFigureのサイズを幅・高さ共に拡張したものです。
Draw2DのBorderLayoutは、なぜかCenterのWidthのみ、サイズは拡張されます。
両方するか、しないかの方が、わかりやすいと思いますが。
ラベルが挿入されることを意識したのだと思います。
しかし、CenterのFigureサイズをどうするか制御出来た方が便利だと思い
他の方法が見つからなかったので、わたしはこの方法を使っています。
あといくつか、動作のサンプル画像を載せておきます。
コード解説
StretchCenterHeightとStretchCenterWidth
ネーミングのセンスはさておき、以下のように、
stretchCenterWidthとstretchCenterHeightのboolean変数を作成しました。
一応、デフォルトで普通のBorderLayoutと同じ動きをするようにしてます。
private boolean stretchCenterWidth=true; private boolean stretchCenterHeight=false; public boolean isStretchCenterHeight() { return stretchCenterHeight; } public void setStretchCenterHeight(boolean stretchCenterHeight) { this.stretchCenterHeight = stretchCenterHeight; } public boolean isStretchCenterWidth() { return stretchCenterWidth; } public void setStretchCenterWidth(boolean stretchCenterWidth) { this.stretchCenterWidth = stretchCenterWidth; }
layout()
layoutでは元々、childFigureのHeightが、小さければ拡張するようになってました。
これを、制御できるようにと、Widthには適用してみました。
childSize = center.getPreferredSize( Math.max(0, area.width), Math.max(0, area.height)); if(!stretchCenterHeight){ if (childSize.height < area.height) { area.y += (area.height - childSize.height) / 2; area.height = childSize.height; } } if(!stretchCenterWidth){ if (childSize.width < area.width) { area.x += (area.width - childSize.width) / 2; area.width = childSize.width; } }
呼び出し
あとは、BorderLayoutの変わりに、CustomLayoutを作成して、
拡張するかどうかを指定します。
CustomBorderLayout layout=new CustomBorderLayout(); layout.setStretchCenterWidth(true); layout.setStretchCenterHeight(true);
コードフル
コードはCVSからダウンロードできます。
CustomBorderLayoutTest
以前、BorderLayoutの解説で使ったコードとほとんど同じです。
/* * Created on 2005/08/02 * Author aki@www.xucker.jpn.org * License Apache2.0 or Common Public License */ package example.draw2d; import org.eclipse.draw2d.BorderLayout; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.LineBorder; import org.eclipse.draw2d.Panel; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** * * */ public class CustomBorderLayoutTest { public CustomBorderLayoutTest(Shell shell) { shell.setBounds(0,0,150,150); shell.setLayout(new FillLayout(SWT.VERTICAL)); FigureCanvas canvas = new FigureCanvas(shell); Panel panel=new Panel(); panel.setBackgroundColor(ColorConstants.orange); canvas.setContents(panel); //BorderLayout layout=new BorderLayout(); CustomBorderLayout layout=new CustomBorderLayout(); layout.setStretchCenterWidth(true); layout.setStretchCenterHeight(true); //layout.setHorizontalSpacing(5); //layout.setVerticalSpacing(5); panel.setLayoutManager(layout); set(panel,"top",BorderLayout.TOP); set(panel,"bottom",BorderLayout.BOTTOM); set(panel,"center",BorderLayout.CENTER); set(panel,"left",BorderLayout.LEFT); set(panel,"right",BorderLayout.RIGHT); } public void set(Figure parent,String label,Object constants){ Label labelFigure=new Label(label); labelFigure.setBorder(new LineBorder()); parent.add(labelFigure,constants); } public static void main(String[] args) { Display display=new Display(); Shell shell=new Shell(display); CustomBorderLayoutTest app=new CustomBorderLayoutTest(shell); shell.open(); while(!shell.isDisposed()){ if (!display.readAndDispatch ()){ display.sleep (); } } display.dispose(); } }
CustomBorderLayout
ほとんど、BorderLayoutと同じです。
package example.draw2d; import org.eclipse.draw2d.AbstractLayout; import org.eclipse.draw2d.BorderLayout; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Rectangle; /******************************************************************************* * Copyright (c) 2000, 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 *******************************************************************************/ public class CustomBorderLayout extends BorderLayout{ /** * Constant to be used as a constraint for child figures */ public static final Integer CENTER = new Integer(PositionConstants.CENTER); /** * Constant to be used as a constraint for child figures */ public static final Integer TOP = new Integer(PositionConstants.TOP); /** * Constant to be used as a constraint for child figures */ public static final Integer BOTTOM = new Integer(PositionConstants.BOTTOM); /** * Constant to be used as a constraint for child figures */ public static final Integer LEFT = new Integer(PositionConstants.LEFT); /** * Constant to be used as a constraint for child figures */ public static final Integer RIGHT = new Integer(PositionConstants.RIGHT); private IFigure center, left, top, bottom, right; private int vGap = 0, hGap = 0; private boolean stretchCenterWidth=true; private boolean stretchCenterHeight=false; /** * @see org.eclipse.draw2d.AbstractHintLayout#calculateMinimumSize(IFigure, int, int) */ protected Dimension calculateMinimumSize(IFigure container, int wHint, int hHint) { int minWHint = 0, minHHint = 0; if (wHint < 0) { minWHint = -1; } if (hHint < 0) { minHHint = -1; } Insets border = container.getInsets(); wHint = Math.max(minWHint, wHint - border.getWidth()); hHint = Math.max(minHHint, hHint - border.getHeight()); Dimension minSize = new Dimension(); int middleRowWidth = 0, middleRowHeight = 0; int rows = 0, columns = 0; if (top != null && top.isVisible()) { Dimension childSize = top.getMinimumSize(wHint, hHint); hHint = Math.max(minHHint, hHint - (childSize.height + vGap)); minSize.setSize(childSize); rows += 1; } if (bottom != null && bottom.isVisible()) { Dimension childSize = bottom.getMinimumSize(wHint, hHint); hHint = Math.max(minHHint, hHint - (childSize.height + vGap)); minSize.width = Math.max(minSize.width, childSize.width); minSize.height += childSize.height; rows += 1; } if (left != null && left.isVisible()) { Dimension childSize = left.getMinimumSize(wHint, hHint); middleRowWidth = childSize.width; middleRowHeight = childSize.height; wHint = Math.max(minWHint, wHint - (childSize.width + hGap)); columns += 1; } if (right != null && right.isVisible()) { Dimension childSize = right.getMinimumSize(wHint, hHint); middleRowWidth += childSize.width; middleRowHeight = Math.max(childSize.height, middleRowHeight); wHint = Math.max(minWHint, wHint - (childSize.width + hGap)); columns += 1; } if (center != null && center.isVisible()) { Dimension childSize = center.getMinimumSize(wHint, hHint); middleRowWidth += childSize.width; middleRowHeight = Math.max(childSize.height, middleRowHeight); columns += 1; } rows += columns > 0 ? 1 : 0; // Add spacing, insets, and the size of the middle row minSize.height += middleRowHeight + border.getHeight() + ((rows - 1) * vGap); minSize.width = Math.max(minSize.width, middleRowWidth) + border.getWidth() + ((columns - 1) * hGap); return minSize; } /** * @see AbstractLayout#calculatePreferredSize(IFigure, int, int) */ protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) { int minWHint = 0, minHHint = 0; if (wHint < 0) minWHint = -1; if (hHint < 0) minHHint = -1; Insets border = container.getInsets(); wHint = Math.max(minWHint, wHint - border.getWidth()); hHint = Math.max(minHHint, hHint - border.getHeight()); Dimension prefSize = new Dimension(); int middleRowWidth = 0, middleRowHeight = 0; int rows = 0, columns = 0; if (top != null && top.isVisible()) { Dimension childSize = top.getPreferredSize(wHint, hHint); hHint = Math.max(minHHint, hHint - (childSize.height + vGap)); prefSize.setSize(childSize); rows += 1; } if (bottom != null && bottom.isVisible()) { Dimension childSize = bottom.getPreferredSize(wHint, hHint); hHint = Math.max(minHHint, hHint - (childSize.height + vGap)); prefSize.width = Math.max(prefSize.width, childSize.width); prefSize.height += childSize.height; rows += 1; } if (left != null && left.isVisible()) { Dimension childSize = left.getPreferredSize(wHint, hHint); middleRowWidth = childSize.width; middleRowHeight = childSize.height; wHint = Math.max(minWHint, wHint - (childSize.width + hGap)); columns += 1; } if (right != null && right.isVisible()) { Dimension childSize = right.getPreferredSize(wHint, hHint); middleRowWidth += childSize.width; middleRowHeight = Math.max(childSize.height, middleRowHeight); wHint = Math.max(minWHint, wHint - (childSize.width + hGap)); columns += 1; } if (center != null && center.isVisible()) { Dimension childSize = center.getPreferredSize(wHint, hHint); middleRowWidth += childSize.width; middleRowHeight = Math.max(childSize.height, middleRowHeight); columns += 1; } rows += columns > 0 ? 1 : 0; // Add spacing, insets, and the size of the middle row prefSize.height += middleRowHeight + border.getHeight() + ((rows - 1) * vGap); prefSize.width = Math.max(prefSize.width, middleRowWidth) + border.getWidth() + ((columns - 1) * hGap); return prefSize; } /** * @see org.eclipse.draw2d.LayoutManager#layout(IFigure) */ public void layout(IFigure container) { Rectangle area = container.getClientArea(); Rectangle rect = new Rectangle(); Dimension childSize; if (top != null && top.isVisible()) { childSize = top.getPreferredSize(area.width, -1); rect.setLocation(area.x, area.y); rect.setSize(childSize); rect.width = area.width; top.setBounds(rect); area.y += rect.height + vGap; area.height -= rect.height + vGap; } if (bottom != null && bottom.isVisible()) { childSize = bottom.getPreferredSize(Math.max(area.width, 0), -1); rect.setSize(childSize); rect.width = area.width; rect.setLocation(area.x, area.y + area.height - rect.height); bottom.setBounds(rect); area.height -= rect.height + vGap; } if (left != null && left.isVisible()) { childSize = left.getPreferredSize(-1, Math.max(0, area.height)); rect.setLocation(area.x, area.y); rect.width = childSize.width; rect.height = Math.max(0, area.height); left.setBounds(rect); area.x += rect.width + hGap; area.width -= rect.width + hGap; } if (right != null && right.isVisible()) { childSize = right.getPreferredSize(-1, Math.max(0, area.height)); rect.width = childSize.width; rect.height = Math.max(0, area.height); rect.setLocation(area.x + area.width - rect.width, area.y); right.setBounds(rect); area.width -= rect.width + hGap; } if (center != null && center.isVisible()) { childSize = center.getPreferredSize( Math.max(0, area.width), Math.max(0, area.height)); if(!stretchCenterHeight){ if (childSize.height < area.height) { area.y += (area.height - childSize.height) / 2; area.height = childSize.height; } } if(!stretchCenterWidth){ if (childSize.width < area.width) { area.x += (area.width - childSize.width) / 2; area.width = childSize.width; } } center.setBounds(area); } } /** * @see org.eclipse.draw2d.AbstractLayout#remove(IFigure) */ public void remove(IFigure child) { if (center == child) { center = null; } else if (top == child) { top = null; } else if (bottom == child) { bottom = null; } else if (right == child) { right = null; } else if (left == child) { left = null; } } /** * Sets the location of hte given child in this layout. Valid constraints: * <UL> * <LI>{@link #CENTER}</LI> * <LI>{@link #TOP}</LI> * <LI>{@link #BOTTOM}</LI> * <LI>{@link #LEFT}</LI> * <LI>{@link #RIGHT}</LI> * <LI><code>null</code> (to remove a child's constraint)</LI> * </UL> * * <p> * Ensure that the given Figure is indeed a child of the Figure on which this layout has * been set. Proper behaviour cannot be guaranteed if that is not the case. Also ensure * that every child has a valid constraint. * </p> * <p> * Passing a <code>null</code> constraint will invoke {@link #remove(IFigure)}. * </p> * <p> * If the given child was assigned another constraint earlier, it will be re-assigned to * the new constraint. If there is another child with the given constraint, it will be * over-ridden so that the given child now has that constraint. * </p> * * @see org.eclipse.draw2d.AbstractLayout#setConstraint(IFigure, Object) */ public void setConstraint(IFigure child, Object constraint) { remove(child); super.setConstraint(child, constraint); if (constraint == null) { return; } switch (((Integer) constraint).intValue()) { case PositionConstants.CENTER : center = child; break; case PositionConstants.TOP : top = child; break; case PositionConstants.BOTTOM : bottom = child; break; case PositionConstants.RIGHT : right = child; break; case PositionConstants.LEFT : left = child; break; default : break; } } /** * Sets the horizontal spacing to be used between the children. Default is 0. * * @param gap The horizonal spacing */ public void setHorizontalSpacing(int gap) { hGap = gap; } /** * Sets the vertical spacing ot be used between the children. Default is 0. * * @param gap The vertical spacing */ public void setVerticalSpacing(int gap) { vGap = gap; } public boolean isStretchCenterHeight() { return stretchCenterHeight; } public void setStretchCenterHeight(boolean stretchCenterHeight) { this.stretchCenterHeight = stretchCenterHeight; } public boolean isStretchCenterWidth() { return stretchCenterWidth; } public void setStretchCenterWidth(boolean stretchCenterWidth) { this.stretchCenterWidth = stretchCenterWidth; } }