net.alantea.swing.layout.percent.PercentLayout Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swingplus Show documentation
Show all versions of swingplus Show documentation
Addons over swing package.
The newest version!
package net.alantea.swing.layout.percent;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class PercentLayout implements LayoutManager2
{
/** Map of constraints for components. */
private Map map;
/** The layout done. */
private Map horizontalLayoutDone;
private Map verticalLayoutDone;
private List currently;
/**
* Constructor.
*/
public PercentLayout()
{
this(0, 0);
}
/**
* Constructor with info on full size.
*
* @param fullWidth full reference width
* @param fullHeight full reference height
*/
public PercentLayout(int fullWidth, int fullHeight)
{
map = new HashMap();
horizontalLayoutDone = new HashMap<>();
verticalLayoutDone = new HashMap<>();
currently = new LinkedList<>();
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
*/
@Override
public void addLayoutComponent(String name, Component comp)
{
// Not allowed
}
@Override
public void addLayoutComponent(Component component, Object constraints)
{
if (constraints instanceof PercentConstraints)
{
map.put(component, (PercentConstraints) constraints);
}
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
*/
@Override
public void removeLayoutComponent(Component comp)
{
map.remove(comp);
}
@Override
public Dimension minimumLayoutSize(Container parent)
{
// Container relativeSizeParent = parent;
// // keep size as it is.
// return relativeSizeParent.getSize();
return new Dimension(1, 1);
}
@Override
public Dimension preferredLayoutSize(Container parent)
{
int width = 1;
int height = 1;
for (Component component : parent.getComponents())
{
PercentConstraints constraints = map.get(component);
if (constraints != null)
{
double mpw = constraints.getWPercent();
double mph = constraints.getHPercent();
Dimension compDim = component.getPreferredSize();
int w = getSizeValue(mpw, width, compDim.width);
int h = getSizeValue(mph, height, compDim.height);
width = Math.max(width, w);
height = Math.max(height, h);
}
}
return new Dimension(width, height);
}
private int getSizeValue(double constr, int currentSize, int compDim)
{
int size = 0;
if (constr <= 1)
{
size = (int) ((constr > 0) ? compDim / constr : 1);
}
else
{
size = (int) (currentSize + constr);
}
return size;
}
@Override
public float getLayoutAlignmentX(Container parent)
{
return 0;
}
@Override
public float getLayoutAlignmentY(Container parent)
{
return 0;
}
@Override
public void invalidateLayout(Container parent)
{
// do nothing
}
@Override
public Dimension maximumLayoutSize(Container parent)
{
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
@Override
public void layoutContainer(Container parent)
{
horizontalLayoutDone.clear();
verticalLayoutDone.clear();
currently.clear();
Container relativeSizeParent = parent;
Insets insets = relativeSizeParent.getInsets();
int w = relativeSizeParent.getWidth() - (insets.left + insets.right);
int h = relativeSizeParent.getHeight() - (insets.top + insets.bottom);
// Do not manage if no constraints
for (Component component : parent.getComponents())
{
PercentConstraints constraints = map.get(component);
if (constraints == null)
{
Rectangle rect = component.getBounds();
horizontalLayoutDone.put(component, new PosAndSize(rect.x, rect.width));
verticalLayoutDone.put(component, new PosAndSize(rect.y, rect.height));
}
}
for (Component component : parent.getComponents())
{
doLayout(component, 0, 0, w, h);
}
}
/**
* Do layout.
*
* @param component the comp
* @param panelX the panel X
* @param panelY the panel Y
* @param panelW the w
* @param panelH the h
*/
private void doLayout(Component component, int panelX, int panelY, int panelW, int panelH)
{
PercentConstraints constraints = map.get(component);
if (!horizontalLayoutDone.keySet().contains(component))
{
doDirectionalLayout(component,
panelX,
getReferenceSize(constraints.getWReferent(), panelW, panelH, Direction.HORIZONTAL),
constraints.getXPercent(), constraints.getWPercent(),
constraints.getXReferent(), constraints.getWReferent(),
horizontalLayoutDone,
true
);
}
PosAndSize posAndSizeX = horizontalLayoutDone.get(component);
if (!verticalLayoutDone.keySet().contains(component))
{
doDirectionalLayout(component,
panelY,
getReferenceSize(constraints.getHReferent(), panelY, panelH, Direction.VERTICAL),
constraints.getYPercent(), constraints.getHPercent(),
constraints.getYReferent(), constraints.getHReferent(),
verticalLayoutDone,
false
);
}
PosAndSize posAndSizeY = verticalLayoutDone.get(component);
component.setBounds(posAndSizeX.position, posAndSizeY.position, posAndSizeX.size, posAndSizeY.size);
}
private int getReferenceSize(Referent referent, int panelW, int panelH, Direction defaultValue)
{
Direction how = (referent != null) ? referent.getHow() : defaultValue;
if (how == Direction.HORIZONTAL)
{
return panelW;
}
else
{
return panelH;
}
}
/**
* Do directional layout.
*
* @param component the component
* @param panelPos the panel usable position
* @param panelSize the panel usable size
*/
private void doDirectionalLayout(Component component, int panelPos, int panelSize,
double posConstraint, double sizeConstraint,
Referent posReferent, Referent sizeReferent,
Map doneMap,
boolean isHorizontal)
{
if (doneMap.keySet().contains(component))
{
return;
}
currently.add(component);
if ((posReferent != null) && ((posReferent.getWho() != null) && (!doneMap.keySet().contains(posReferent.getWho()))))
{
if (currently.contains(posReferent.getWho()))
{
// Abort : cycle detected
System.out.println("Abort : cycle detected");
return;
}
PercentConstraints refconstraints = map.get(posReferent.getWho());
if (refconstraints != null)
{
doDirectionalLayout(posReferent.getWho(), panelPos, panelSize,
refconstraints.getXPercent(), refconstraints.getWPercent(),
refconstraints.getXReferent(), refconstraints.getWReferent(),
doneMap,
isHorizontal
);
}
}
if ((sizeReferent != null) && ((sizeReferent.getWho() != null) && (!doneMap.keySet().contains(sizeReferent.getWho()))))
{
if (currently.contains(sizeReferent.getWho()))
{
// Abort : cycle detected
System.out.println("Abort : cycle detected");
return;
}
PercentConstraints refconstraints = map.get(sizeReferent.getWho());
if (refconstraints != null)
{
doDirectionalLayout(sizeReferent.getWho(), panelPos, panelSize,
refconstraints.getXPercent(), refconstraints.getWPercent(),
refconstraints.getXReferent(), refconstraints.getWReferent(),
doneMap,
isHorizontal
);
}
}
// Default values
int position = panelPos + (int) (panelSize * posConstraint);
int size = (int) (panelSize * sizeConstraint);
// Manage special cases
if ((sizeReferent != null) && (sizeReferent.getWho() != null))
{
PosAndSize posAndSize = doneMap.get(sizeReferent.getWho());
if (posAndSize == null)
{
posAndSize = new PosAndSize(0, 100);
}
switch (sizeReferent.getWhere())
{
// same size
case SAME :
size += posAndSize.size;
break;
// fill space after referent
case AFTER:
size = panelSize - posAndSize.position - posAndSize.size - size;
break;
// fill space before referent
case BEFORE:
size = posAndSize.position - position - size;
break;
case FAR:
// To be set after position is calculated
break;
case START:
// only for position
break;
case CENTER:
// only for position
break;
case END:
// only for position
break;
case ABSOLUTE:
size = (int)sizeConstraint;
break;
case PREFERRED:
size = isHorizontal ? component.getPreferredSize().width : component.getPreferredSize().height;
break;
default:
break;
}
}
else if ((sizeReferent != null) && (sizeReferent.getWhere() == Where.ABSOLUTE))
{
size = (int)sizeConstraint;
}
else if ((sizeReferent != null) && (sizeReferent.getWhere() == Where.PREFERRED))
{
size = isHorizontal ? component.getPreferredSize().width : component.getPreferredSize().height;
}
if ((posReferent != null) && (posReferent.getWho() != null))
{
PosAndSize posAndSize = doneMap.get(posReferent.getWho());
if (posAndSize == null)
{
posAndSize = new PosAndSize(0, 100);
}
switch (posReferent.getWhere())
{
case AFTER :
position += posAndSize.position + posAndSize.size;
break;
case SAME :
case START :
position += posAndSize.position;
break;
case BEFORE:
position += posAndSize.position - size;
break;
case CENTER:
position += posAndSize.position + (posAndSize.size - size) / 2;
break;
case END:
position += posAndSize.position + posAndSize.size - size;
break;
case FAR:
// only for size
break;
case ABSOLUTE:
position = (int)posConstraint;
break;
case PREFERRED:
break;
default:
break;
}
//
// if ((sizeReferent != null) && (sizeReferent.getWhere() != null))
// {
// }
}
else if ((posReferent != null) && (posReferent.getWhere() == Where.ABSOLUTE))
{
position = (int)posConstraint;
}
doneMap.put(component, new PosAndSize(position, size));
currently.remove(component);
return;
}
private class PosAndSize
{
int position;
int size;
PosAndSize(int position, int size)
{
this.position = position;
this.size = size;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy