package org.korsakow.ide.ui.factory;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.xml.xpath.XPathExpressionException;
import org.apache.log4j.Logger;
import org.korsakow.ide.DomHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class DomLayout implements LayoutManager
{
private final Document document;
private final DomHelper helper;
/**
* An absolute layout based on the dom.
* @param document
*/
public DomLayout(Document document)
{
this.document = document;
helper = new DomHelper(document);
}
/**
* Purely for debugging purposes
* @param comp
*/
private void defaultLayoutComponent(Component comp)
{
// comp.setLocation((int)(Math.random()*800), (int)(Math.random()*600));
// comp.setSize(comp.getPreferredSize());
}
private Rectangle getComponentBounds(String name, Rectangle rect) throws XPathExpressionException
{
Element element = helper.xpathAsElement("/layout/component[id=?]", name);
if (element == null) {
Logger.getLogger(DomLayout.class).debug("Layout not found for '" + name + "'");
// System.out.println(name);
return rect;
}
Integer x = getInt(element, "x", rect.x);
Integer y = getInt(element, "y", rect.y);
Integer width = getInt(element, "width", rect.width);
Integer height = getInt(element, "height", rect.height);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
return rect;
}
private void layoutComponent(Component comp) throws XPathExpressionException
{
String name = comp.getName();
if (name != null) {
Rectangle bounds = comp.getBounds();
Dimension d = comp.getPreferredSize();
bounds.width = d.width;
bounds.height = d.height;
if (name.equals("livesComboBox"))
name=name+"";
bounds = getComponentBounds(name, bounds);
comp.setBounds(bounds);
}
}
private Integer getInt(Element element, String name, Integer defaultValue)
{
Integer value = helper.getInt(element, name);
return value==null?defaultValue:value;
}
public void addLayoutComponent(String name, Component comp) {
}
public void layoutContainer(Container parent) {
for (int i = 0; i < parent.getComponentCount(); ++i)
{
Component comp = parent.getComponent(i);
try {
layoutComponent(comp);
} catch (XPathExpressionException e) {
Logger.getLogger(DomLayout.class).error("", e);
} catch (NumberFormatException e) {
Logger.getLogger(DomLayout.class).error("", e);
}
}
}
public Dimension minimumLayoutSize(Container parent) {
Dimension d = preferredLayoutSize(parent);
return d;
}
public Dimension preferredLayoutSize(Container parent) {
try {
int width = helper.xpathAsInt("/layout/attribute::width");
int height = helper.xpathAsInt("/layout/attribute::height");
return new Dimension(width, height);
} catch (Exception e) {
// just dont return
}
int paddingLeft = 0;
int paddingRight = 0;
int paddingBottom = 0;
int paddingTop = 0;
try { paddingLeft = helper.xpathAsInt("/layout/@paddingLeft"); } catch (Exception e) {}
try { paddingRight = helper.xpathAsInt("/layout/@paddingRight"); } catch (Exception e) {}
try { paddingTop = helper.xpathAsInt("/layout/@paddingTop"); } catch (Exception e) {}
try { paddingBottom = helper.xpathAsInt("/layout/@paddingBottom"); } catch (Exception e) {}
int left = Integer.MAX_VALUE;
int right = Integer.MIN_VALUE;
int top = Integer.MAX_VALUE;
int bottom = Integer.MIN_VALUE;
Rectangle bounds = new Rectangle();
for (int i = 0; i < parent.getComponentCount(); ++i)
{
Component comp = parent.getComponent(i);
String name = comp.getName();
if (name == null)
continue;
try {
bounds = getComponentBounds(name, comp.getBounds(bounds));
} catch (XPathExpressionException e) {
continue;
}
if (bounds.x < left)
left = bounds.x;
if (bounds.y < top)
top = bounds.y;
if (bounds.x + bounds.width > right)
right = bounds.x + bounds.width;
if (bounds.y + bounds.height > bottom)
bottom = bounds.y + bounds.height;
}
return new Dimension(right + paddingLeft+paddingRight, bottom + paddingTop+paddingBottom);
}
public void removeLayoutComponent(Component comp) {
}
}
/*
<layout>
<component>
<id />
<x />
<y />
<width />
<height />
</component>
</layout>
*/