blob: 3fc5492df34e6f2e86d3902581638741fc770136 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2010 Technical University Berlin, Germany, 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
* $Id: ButtonListLayout.java 23502 2010-02-08 18:33:32Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.objectteams.samples.ordersystem.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
import java.util.ArrayList;
/**
*
* @author Dehla Sokenou
*
* Class for laying out are typical constellation: a button panel and a list (or a similar
* e.g. table) panel.
* <p>
*
* Buttons can be placed on top or below (vertical orientation) or on the left or right side
* (horizontal orientation) of the list.
* Standard orientation is horizontal.
* Standard placement of buttons is -depending on orientation- below or on the right side
* of the list panel (buttons after list).
*
*/
public class ButtonListLayout implements LayoutManager2 {
/**
* Enum for the orientation.
* Possibly values are
* <ul>
* <li> HORIZONTAL: button panel ist displayed at the left or the right side of list panel.
* <li> VERTICAL: button panel is dispayed on top or below list panel.
* </ul>
*
* Orientation and placement cannot be changed during lifecycle of this class' objects.
*/
public enum Orientation {
VERTICAL, HORIZONTAL;
}
public enum Placement {
BUTTONS_AFTER_LIST, BUTTONS_BEFORE_LIST;
}
public enum ComponentType {
BUTTON_PANEL, LIST_OR_TABLE_PANEL;
}
/**
* Orientation of the actual layout manager. Default is horizontal.
*/
protected final Orientation orientation;
/**
* Placement of the actual layout manager. Default is the placement of buttons after list.
*/
protected final Placement placement;
/**
* Reference to button panel that is managed by this layout manager.
*/
protected ArrayList<Component> buttons = new ArrayList<Component>();
/**
* Reference to list panel that is managed by this layout manager.
*/
protected Component listOrTablePanel = null;
/**
* The spacing between buttons. Default is 5.
*/
protected int buttonSpacing = 5;
/**
* The spacing between panels and panel to frame. Default is .
*/
protected int panelSpacing = 0;
/**
* Size of button panel depending from button panel's orientation.
* If orientation is horizontal, size means width.
* If orientation is vertical, size means height.
* Default is preferred size of included buttons (null).
*/
protected Dimension fixedButtonSize = null;
public ButtonListLayout() {
this(null, null);
}
public ButtonListLayout(Orientation anOrientation) {
this(anOrientation, null);
}
public ButtonListLayout(Placement aPlacement) {
this(null, aPlacement);
}
public ButtonListLayout(Orientation anOrientation, Placement aPlacement) {
orientation = anOrientation != null ? anOrientation : Orientation.HORIZONTAL;
placement = aPlacement != null ? aPlacement : Placement.BUTTONS_AFTER_LIST;
}
/**
* @param aPanelSpacing the panelSpacing to set
*/
public void setPanelSpacing(int aPanelSpacing) {
panelSpacing = aPanelSpacing;
}
/**
* @param aButtonSpacing the buttonSpacing to set
*/
public void setButtonSpacing(int aButtonSpacing) {
if (aButtonSpacing >= 0) {
buttonSpacing = aButtonSpacing;
}
}
/**
* @param aFixedButtonPanelSize the fixedButtonPanelSize to set
*/
public void setFixedButtonSize(Dimension aFixedButtonPanelSize) {
fixedButtonSize = aFixedButtonPanelSize;
}
/**
* @see LayoutManager2#addLayoutComponent(Component, Object)
*/
public void addLayoutComponent(Component aComponent, Object aConstraints) {
if (aConstraints instanceof ComponentType) {
switch ((ComponentType) aConstraints) {
case BUTTON_PANEL:
buttons.add(aComponent); break;
case LIST_OR_TABLE_PANEL:
listOrTablePanel = aComponent; break;
default:
throw new IllegalArgumentException("Unsupported layout constraint: " + aConstraints.toString());
}
}
else {
throw new IllegalArgumentException("Unsupported layout constraint: " + aConstraints.toString());
}
}
/**
* @see LayoutManager2#maximumLayoutSize(Container)
*/
public Dimension maximumLayoutSize(Container aTarget) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
* @see LayoutManager2#getLayoutAlignmentX(Container)
*/
public float getLayoutAlignmentX(Container aTarget) {
// do nothing
return 0;
}
/**
* @see LayoutManager2#getLayoutAlignmentY(Container)
*/
public float getLayoutAlignmentY(Container aTarget) {
// do nothing
return 0;
}
/**
* @see LayoutManager2#invalidateLayout(Container)
*/
public void invalidateLayout(Container aTarget) {
// do nothing
}
/**
* @see LayoutManager#addLayoutComponent(String, Component)
*/
public void addLayoutComponent(String aName, Component aComponent) {
throw new UnsupportedOperationException("Sdding layout components based on String constraints is not supported." +
"Use add(Component, Object) instead.");
}
/**
* @see LayoutManager#removeLayoutComponent(Component)
*/
public void removeLayoutComponent(Component aComponent) {
if (listOrTablePanel == aComponent) {
listOrTablePanel = null;
}
else if (buttons.contains(aComponent)) {
buttons.remove(aComponent);
}
// else do nothing
}
/**
* @see LayoutManager#preferredLayoutSize(Container)
*/
public Dimension preferredLayoutSize(Container aParent) {
return getLayoutSize(aParent, false);
}
/**
* @see LayoutManager#minimumLayoutSize(Container)
*/
public Dimension minimumLayoutSize(Container aParent) {
return getLayoutSize(aParent, true);
}
/**
* @see LayoutManager#layoutContainer(Container)
*/
public void layoutContainer(Container aParent) {
// beachten: insets, orientation, fixedbuttonsize, placement
// Note: we don't care about to small panel... if it doesn't fit, only a part is visible
// firstly, calculate button panel size
Insets tempInsets = aParent.getInsets();
int tempMaxWidth = aParent.getWidth() - (tempInsets.left + tempInsets.right)
- 2 * panelSpacing;
int tempMaxHeight = aParent.getHeight() - (tempInsets.top + tempInsets.bottom)
- 2 * panelSpacing;
Dimension tempPreferredButtonPanelSize = getButtonPanelLayoutSize(false);
double tempPreferredButtonPanelWidth = tempPreferredButtonPanelSize.getWidth();
double tempPreferredButtonPanelHeight = tempPreferredButtonPanelSize.getHeight();
// secondly, give remaining space to list
int tempListPanelX = tempInsets.left + panelSpacing;
if (orientation == Orientation.VERTICAL && placement == Placement.BUTTONS_BEFORE_LIST) {
tempListPanelX += panelSpacing + tempPreferredButtonPanelWidth;
}
int tempListPanelY = tempInsets.top + panelSpacing;
if (orientation == Orientation.HORIZONTAL && placement == Placement.BUTTONS_BEFORE_LIST) {
tempListPanelY += panelSpacing + tempPreferredButtonPanelHeight;
}
int tempListPanelWidth = tempMaxWidth;
if (orientation == Orientation.VERTICAL) {
tempListPanelWidth -= (int) tempPreferredButtonPanelWidth + panelSpacing;
}
int tempListPanelHeight = tempMaxHeight;
if (orientation == Orientation.HORIZONTAL) {
tempListPanelHeight -= (int) tempPreferredButtonPanelHeight + panelSpacing;
}
// check, if panel is unvisible
if (tempListPanelWidth < 0) {
tempListPanelWidth = 0;
}
if (tempListPanelHeight < 0) {
tempListPanelHeight = 0;
}
listOrTablePanel.setBounds(tempListPanelX, tempListPanelY, tempListPanelWidth, tempListPanelHeight);
// thirdly, layout buttons in button panel based on preferred size
int tempButtonX = tempInsets.left + panelSpacing;
if (orientation == Orientation.VERTICAL && placement == Placement.BUTTONS_AFTER_LIST) {
tempButtonX += panelSpacing + tempListPanelWidth;
}
int tempButtonY = tempInsets.top + panelSpacing;
if (orientation == Orientation.HORIZONTAL && placement == Placement.BUTTONS_AFTER_LIST) {
tempButtonY += panelSpacing + tempListPanelHeight;
}
for (Component tempButton : buttons) {
Dimension tempButtonSize = fixedButtonSize != null ? fixedButtonSize : tempButton.getPreferredSize();
int tempButtonWidth = tempButtonSize.width;
int tempButtonHeight = tempButtonSize.height;
tempButton.setBounds(tempButtonX, tempButtonY, tempButtonWidth, tempButtonHeight);
// calculate next button position
switch (orientation) {
case VERTICAL:
tempButtonY += tempButtonHeight + buttonSpacing;
break;
case HORIZONTAL:
tempButtonX += tempButtonWidth + buttonSpacing;
break;
}
}
}
/**
*
* @param aParent the container to manage
* @param minimum indicates whether minimum (true) or preferred (false) layout
* will be returned
* @return the preferred or (if minimum) minimum layout size
*/
protected Dimension getLayoutSize(Container aParent, boolean minimum) {
Dimension tempButtonPanelDimension = getButtonPanelLayoutSize(minimum);
Insets tempInsets = aParent.getInsets();
double tempLayoutWidth = 2 * panelSpacing + tempInsets.left + tempInsets.right;
double tempLayoutHeight = 2 * panelSpacing + tempInsets.top + tempInsets.bottom;
Dimension tempListDimension = minimum ? listOrTablePanel.getMinimumSize()
: listOrTablePanel.getPreferredSize();
switch (orientation) {
case HORIZONTAL:
tempLayoutWidth += tempListDimension.getWidth() + panelSpacing
+ tempButtonPanelDimension.getWidth();
tempLayoutHeight += Math.max(tempListDimension.getHeight(),
tempButtonPanelDimension.getHeight());
break;
case VERTICAL:
tempLayoutHeight += tempListDimension.getHeight() + panelSpacing
+ tempButtonPanelDimension.getHeight();
tempLayoutWidth += Math.max(tempListDimension.getWidth(),
tempButtonPanelDimension.getWidth());
break;
}
Dimension tempLayoutDimension = new Dimension();
tempLayoutDimension.setSize(tempLayoutWidth, tempLayoutHeight);
return tempLayoutDimension;
}
/**
* Returns the layout size of button panel.
*
* @param minimum indicates whether minimum (true) or preferred (false) layout
* will be returned
* @return the preferred or (if minimum) minimum layout size
*/
protected Dimension getButtonPanelLayoutSize(boolean minimum) {
// calculate sum of space between buttons dependent from orientation
double tempButtonsLayoutWidth = ((orientation == Orientation.HORIZONTAL) ?
(buttons.size() - 1) * buttonSpacing :
0);
double tempButtonsLayoutHeight = ((orientation == Orientation.VERTICAL) ?
(buttons.size() - 1) * buttonSpacing :
0);
if (fixedButtonSize != null) {
// if fixed button size, use fixed size instead of preferred or minimum size
switch (orientation) {
case VERTICAL:
tempButtonsLayoutWidth += fixedButtonSize.getWidth();
tempButtonsLayoutHeight += buttons.size() * fixedButtonSize.getHeight();
break;
case HORIZONTAL:
tempButtonsLayoutWidth += buttons.size() * fixedButtonSize.getWidth();
tempButtonsLayoutHeight += fixedButtonSize.getHeight();
break;
}
}
else {
// if not fixed size, use each buttons preferred resp. minimum size
for (Component tempComponent : buttons) {
Dimension tempButtonDimension = minimum ? tempComponent.getMinimumSize()
: tempComponent.getPreferredSize();
switch (orientation) {
case VERTICAL:
if (tempButtonsLayoutWidth < tempButtonDimension.getWidth()) {
tempButtonsLayoutWidth = tempButtonDimension.getWidth();
}
tempButtonsLayoutHeight += tempButtonDimension.getHeight();
break;
case HORIZONTAL:
tempButtonsLayoutWidth += tempButtonDimension.getWidth();
if (tempButtonsLayoutHeight < tempButtonDimension.getHeight()) {
tempButtonsLayoutHeight = tempButtonDimension.getHeight();
}
break;
}
}
}
Dimension tempButtonPanelDimension = new Dimension();
tempButtonPanelDimension.setSize(tempButtonsLayoutWidth, tempButtonsLayoutHeight);
return tempButtonPanelDimension;
}
}