/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2007 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*
*/
package org.trianacode.gui.panels;
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;
/**
* this layout manager gets the size of the container parent and sets out digits according to that, as opposed to
* getting the preferred size of the components within the container. So you should set the preferred size of the
* container if using this class, otherwise it defaults to digit size of width 20, height 40. Allowed constraints are
* DIGIT and SEPARATOR. By default a separator is a quarter the width of a digit. Use the constructor that takes a float
* to change this. If no constraints are specified, then DIGIT is used.
*/
public class DigitalLayout implements LayoutManager, LayoutManager2, java.io.Serializable {
int hgap;
int vgap;
float sepFraction;
private ArrayList comps = new ArrayList();
private int digitCount = 0;
private int sepCount = 0;
private int defaultWidth = 20;
private int defaultHeight = 40;
private boolean triedParentPrefSize = false;
private boolean triedParentMinSize = false;
public static final String DIGIT = "digit";
public static final String SEPARATOR = "separator";
public DigitalLayout() {
this(0, 0, 0.25f);
}
public DigitalLayout(int hgap, int vgap) {
this(hgap, vgap, 0.25f);
}
/**
* @param hgap
* @param vgap
* @param separatorFraction a float specifying the fraction of the width of a digit that the separators should
* occupy. The default is .25
*/
public DigitalLayout(int hgap, int vgap, float separatorFraction) {
this.hgap = hgap;
this.vgap = vgap;
this.sepFraction = separatorFraction;
}
public int getHgap() {
return hgap;
}
public void setHgap(int hgap) {
this.hgap = hgap;
}
public int getVgap() {
return vgap;
}
public void setVgap(int vgap) {
this.vgap = vgap;
}
public void addLayoutComponent(String name, Component comp) {
if (name != DIGIT || name != SEPARATOR) {
throw new IllegalArgumentException("constraint must be either digit or separator");
}
comps.add(new Holder(comp, name));
if (name == DIGIT) {
digitCount++;
} else {
sepCount++;
}
}
public void removeLayoutComponent(Component comp) {
}
public Dimension preferredLayoutSize(Container parent) {
if (!triedParentPrefSize) {
triedParentPrefSize = true;
Dimension dim = parent.getPreferredSize();
return dim;
} else {
return defaultDimension(parent);
}
}
public Dimension minimumLayoutSize(Container parent) {
if (!triedParentMinSize) {
triedParentMinSize = true;
Dimension dim = parent.getMinimumSize();
return dim;
} else {
return defaultDimension(parent);
}
}
private Dimension defaultDimension(Container parent) {
Insets insets = parent.getInsets();
int digitsWidth = (defaultWidth + (hgap * 2)) * digitCount;
int sepsWidth = ((int) (defaultWidth * sepFraction) + (hgap * 2)) * digitCount;
int totalWidth = insets.left + insets.right + digitsWidth + sepsWidth;
int totalHeight = insets.top + insets.bottom + defaultHeight + (vgap * 2);
return new Dimension(totalWidth, totalHeight);
}
public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Dimension d = parent.getSize();
Insets insets = parent.getInsets();
int pwidth = d.width - insets.left - insets.right;
int pheight = d.height - insets.top - insets.bottom;
if (digitCount == 0) {
throw new IllegalArgumentException("at least one digit must be added to DigitalLayout.");
}
int digitWidth = (pwidth - ((hgap * 2)) * (digitCount + sepCount)) / digitCount;
int digitHeight = pheight - (vgap * 2);
int sepWidth = 0;
for (int i = 0; i < sepCount; i++) {
sepWidth = (int) (digitWidth * sepFraction);
digitWidth -= sepWidth / digitCount;
}
int currX = insets.left + hgap;
int currY = insets.top + vgap;
for (int i = 0; i < comps.size(); i++) {
Holder entry = (Holder) comps.get(i);
Component comp = entry.getComp();
String tag = entry.getTag();
if (tag == SEPARATOR) {
comp.setBounds(currX, currY, sepWidth, digitHeight);
currX += sepWidth + (hgap * 2);
} else if (tag == DIGIT) {
comp.setBounds(currX, currY, digitWidth, digitHeight);
currX += digitWidth + (hgap * 2);
}
}
}
}
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints == DIGIT || constraints == SEPARATOR) {
comps.add(new Holder(comp, (String) constraints));
if (constraints == DIGIT) {
digitCount++;
} else {
sepCount++;
}
} else {
comps.add(new Holder(comp, DIGIT));
digitCount++;
}
}
public Dimension maximumLayoutSize(Container target) {
return null;
}
public float getLayoutAlignmentX(Container target) {
return 0;
}
public float getLayoutAlignmentY(Container target) {
return 0;
}
public void invalidateLayout(Container target) {
}
class Holder {
private Component comp;
private String tag;
Holder(Component comp, String tag) {
this.comp = comp;
this.tag = tag;
}
public Component getComp() {
return comp;
}
public String getTag() {
return tag;
}
}
}