/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.servoy.j2db.persistence.IAnchorConstants;
/**
* Handy Layout Manager keeps anchored sides of an component on the same distance to the border by resizing. (Used in combination with excact positioning,
* speedsup the development of dialogs with at least 20%)
*
* see main method as example
*
* Author jblok
*/
public class AnchorLayout implements LayoutManager2, IAnchorConstants
{
private Dimension initalSize;
private final Hashtable components;
private boolean enabled = true;
public AnchorLayout(int width, int height)
{
this(new Dimension(width, height));
}
public AnchorLayout(Dimension d)
{
components = new Hashtable();
setPreferredSize(d);
}
public AnchorLayout()
{
this(null);
}
public void addLayoutComponent(String s, Component c)
{
addLayoutComponent(c, new Integer(DEFAULT));
}
public void removeLayoutComponent(Component c)
{
components.remove(c);
}
public Dimension preferredLayoutSize(Container c)
{
return initalSize;
}
public Dimension minimumLayoutSize(Container c)
{
// return initalSize;
return new Dimension();
}
private Dimension lastSize;
public void layoutContainer(Container c)
{
if (enabled)
{
Dimension size = c.getSize();
if (lastSize != null && lastSize.equals(size)) return;
Insets insets = c.getInsets();
lastSize = size;
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
Enumeration e = components.keys();
while (e.hasMoreElements())
{
Component comp = (Component)e.nextElement();
Object[] constains = (Object[])components.get(comp);
Point orgLocation = (Point)constains[0];
Dimension orgSize = (Dimension)constains[1];
int anchors = ((Integer)constains[2]).intValue();
Point setLocation = (Point)constains[3];
Dimension setSize = (Dimension)constains[4];
if (!comp.getLocation().equals(setLocation))
{
Point pNow = comp.getLocation();
orgLocation.x = orgLocation.x + (pNow.x - setLocation.x);
orgLocation.y = orgLocation.y + (pNow.y - setLocation.y);
}
if (!comp.getSize().equals(setSize))
{
Dimension dimNow = comp.getSize();
orgSize.width = orgSize.width + (dimNow.width - setSize.width);
orgSize.height = orgSize.height + (dimNow.height - setSize.height);
}
top = orgLocation.y;
left = orgLocation.x;
right = initalSize.width - (orgLocation.x + orgSize.width);
bottom = initalSize.height - (orgLocation.y + orgSize.height);
//savety for bad placed elements(not entrily on the form) to make them resize within the view
if (right < 0) right = 0;
if (bottom < 0) bottom = 0;
if ((anchors & NORTH) != NORTH)
{
top = size.height - bottom - orgSize.height;
}
if ((anchors & WEST) != WEST)
{
left = size.width - right - orgSize.width;
}
if ((anchors & EAST) != EAST)
{
right = size.width - left - orgSize.width;
}
if ((anchors & SOUTH) != SOUTH)
{
bottom = size.height - top - orgSize.height;
}
//TODO: don't make the size smaller as the components min. size
comp.setBounds(left + insets.left, top + insets.top, size.width - (right + left), size.height - (top + bottom));
constains[3] = comp.getLocation();
constains[4] = comp.getSize();
}
}
}
public void addLayoutComponent(Component c, Object o)
{
if (c != null)
{
Integer anchors;
if (o != null && o instanceof Integer)
{
anchors = (Integer)o;
}
else
{
anchors = new Integer(DEFAULT);
}
if (anchors.intValue() == 0) anchors = new Integer(DEFAULT);
Object[] constaints = { c.getLocation(), c.getSize(), anchors, c.getLocation(), c.getSize() };
components.put(c, constaints);
}
else
{
throw new IllegalArgumentException();
}
}
public float getLayoutAlignmentX(Container c)
{
return 0;
}
public float getLayoutAlignmentY(Container c)
{
return 0;
}
public void invalidateLayout(Container c)
{
}
public Dimension maximumLayoutSize(Container c)
{
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public void setPreferredSize(Dimension d)
{
if (d != null)
{
initalSize = d;
}
else
{
initalSize = new Dimension(640, 480);
}
}
public void setEnabled(boolean b)
{
enabled = b;
}
public boolean getEnabled()
{
return enabled;
}
public static void main(String[] args)
{
JFrame f = new JFrame();
f.getContentPane().setLayout(new BorderLayout());
f.setSize(800, 600);
f.pack();
f.setVisible(true);
JPanel p = new JPanel();
p.setLayout(new AnchorLayout(300, 200));
JButton b = new JButton();
b.setLocation(10, 10);
b.setSize(40, 40);
p.add(b, new Integer(ALL));
f.getContentPane().add(p, BorderLayout.CENTER);
}
/**
*
*/
public void reset()
{
Enumeration e = components.keys();
while (e.hasMoreElements())
{
Component comp = (Component)e.nextElement();
Object[] constains = (Object[])components.get(comp);
constains[3] = comp.getLocation();
constains[4] = comp.getSize();
}
}
}