package org.javabuilders.gtk.handler.type;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gnome.gtk.Alignment;
import org.gnome.gtk.AttachOptions;
import org.gnome.gtk.Container;
import org.gnome.gtk.HBox;
import org.gnome.gtk.SizeGroup;
import org.gnome.gtk.SizeGroupMode;
import org.gnome.gtk.Table;
import org.gnome.gtk.Widget;
import org.javabuilders.BuildException;
import org.javabuilders.BuildProcess;
import org.javabuilders.Builder;
import org.javabuilders.BuilderConfig;
import org.javabuilders.Node;
import org.javabuilders.TypeDefinition;
import org.javabuilders.gtk.GtkConstants;
import org.javabuilders.gtk.layout.RowColumnConstraint;
import org.javabuilders.handler.AbstractTypeHandler;
import org.javabuilders.handler.ITypeHandlerFinishProcessor;
import org.javabuilders.layout.ControlConstraint;
import org.javabuilders.layout.DefaultResize;
import org.javabuilders.layout.Flow;
import org.javabuilders.layout.HAlign;
import org.javabuilders.layout.LayoutCell;
import org.javabuilders.layout.LayoutConstraints;
import org.javabuilders.layout.VAlign;
import org.javabuilders.layout.mig.MigLayoutCommon;
/**
* Table type handler
* @author Jacek Furmankiewicz
*
*/
public class TableTypeHandler extends AbstractTypeHandler implements ITypeHandlerFinishProcessor {
private static final String ATTACH = "attach";
/**
* Constructor
*/
public TableTypeHandler() {
super(ATTACH);
}
/* (non-Javadoc)
* @see org.javabuilders.handler.ITypeHandler#createNewInstance(org.javabuilders.BuilderConfig, org.javabuilders.BuildProcess, org.javabuilders.Node, java.lang.String, java.util.Map)
*/
public Node createNewInstance(BuilderConfig config, BuildProcess process,
Node parent, String key, Map<String, Object> typeDefinition)
throws BuildException {
LayoutConstraints c = getLayoutConstraints(typeDefinition);
boolean homogenous = false;
if (typeDefinition.containsKey(GtkConstants.HOMOGENOUS)) {
homogenous = (Boolean) typeDefinition.get(GtkConstants.HOMOGENOUS);
}
Table instance = new Table(c.getRowCount(), c.getColumnCount(), homogenous);
return useExistingInstance(config, process, parent, key, typeDefinition, instance);
}
/* (non-Javadoc)
* @see org.javabuilders.handler.ITypeHandler#useExistingInstance(org.javabuilders.BuilderConfig, org.javabuilders.BuildProcess, org.javabuilders.Node, java.lang.String, java.util.Map, java.lang.Object)
*/
public Node useExistingInstance(BuilderConfig config, BuildProcess process,
Node parent, String key, Map<String, Object> typeDefinition,
Object instance) throws BuildException {
Node node = new Node(parent,key,typeDefinition, instance);
return node;
}
/* (non-Javadoc)
* @see org.javabuilders.handler.ITypeHandlerFinishProcessor#finish(org.javabuilders.BuilderConfig, org.javabuilders.BuildProcess, org.javabuilders.Node, java.lang.String, java.util.Map)
*/
public void finish(BuilderConfig config, BuildProcess process,
Node current, String key, Map<String, Object> typeDefinition)
throws BuildException {
LayoutConstraints c = getLayoutConstraints(typeDefinition);
Set<Node> widgets = current.getContentNodes(Widget.class);
Table table = (Table) current.getMainObject();
Map<String,Widget> widgetNames = new HashMap<String, Widget>();
for(Node node : widgets) {
Widget w = (Widget) node.getMainObject();
String name = node.getStringProperty(Builder.NAME);
if (name != null) {
widgetNames.put(name, w);
}
}
//parse the constraints
int rows = c.getRowCount();
int columns = c.getColumnCount();
List<RowColumnConstraint> rowConstraints = new LinkedList<RowColumnConstraint>();
if (c.getRowConstraints().size() > 0) {
for(int i = 0; i < c.getRowConstraints().size();i++) {
RowColumnConstraint con = new RowColumnConstraint(i, c.getRowConstraints().get(i));
rowConstraints.add(con);
if (con.getSpacerWidth() > 0) {
table.setRowSpacing(i, con.getSpacerWidth());
}
}
}
List<RowColumnConstraint> columnConstraints = new LinkedList<RowColumnConstraint>();
if (c.getColumnConstraints().size() > 0) {
for(int i = 0; i < c.getColumnConstraints().size();i++) {
RowColumnConstraint con = new RowColumnConstraint(i, c.getColumnConstraints().get(i));
columnConstraints.add(con);
if (con.getSpacerWidth() > 0) {
table.setColumnSpacing(i, con.getSpacerWidth());
}
}
}
Map<Integer,SizeGroup> sizeGroups = new HashMap<Integer, SizeGroup>();
for(int col = 0; col < columns; col++) {
for(int row = 0; row < rows; row++) {
LayoutCell cell = c.getCellAt(row,col);
if (cell != null && cell.getControls() != null && cell.getControls().size() > 0) {
//alignment on first control drive all of them
ControlConstraint first = cell.getControls().get(0);
Widget w = widgetNames.get(first.getControlName());
RowColumnConstraint columnConstraint = null;
AttachOptions colAttachOption = AttachOptions.FILL;
if (columnConstraints.size() > cell.getColumnIndex()) {
columnConstraint = columnConstraints.get(cell.getColumnIndex());
if (columnConstraint.isGrowing()) {
colAttachOption = AttachOptions.EXPAND;
}
}
RowColumnConstraint rowConstraint = null;
AttachOptions rowAttachOption = AttachOptions.FILL;
if (rowConstraints.size() > cell.getRowIndex()) {
rowConstraint = rowConstraints.get(cell.getRowIndex());
if (rowConstraint.isGrowing()) {
rowAttachOption = AttachOptions.EXPAND;
}
}
//handle multiple widgets defined
Widget widgetToAdd = w;
if (cell.getControls().size() > 1) {
Container box = null;
if (cell.getFlow() == Flow.HORIZONTAL) {
box = new HBox(false,4); //TODO: change 4
for(ControlConstraint cc : cell.getControls()) {
box.add(widgetNames.get(cc.getControlName()));
}
} else {
box = new HBox(false,4); //TODO: change 4
for(ControlConstraint cc : cell.getControls()) {
box.add(widgetNames.get(cc.getControlName()));
}
}
widgetToAdd = box;
}
//alignment
float xAlign = 0f;
if (columnConstraint != null) {
if (columnConstraint.getHAlign() == HAlign.RIGHT) {
xAlign = 1.0f;
} else if (columnConstraint.getHAlign() == HAlign.CENTER) {
xAlign = 0.5f;
}
}
if (first.getHAlign() == HAlign.RIGHT) {
xAlign = 1.0f;
} else if (first.getHAlign() == HAlign.CENTER) {
xAlign = 0.5f;
}
float yAlign = 0f;
if (rowConstraint != null) {
if (rowConstraint.getVAlign() == VAlign.BOTTOM) {
yAlign = 1.0f;
} else if (rowConstraint.getVAlign() == VAlign.MIDDLE || rowConstraint.getVAlign() == VAlign.DEFAULT) {
yAlign = 0.5f;
}
}
if (first.getVAlign() == VAlign.BOTTOM) {
yAlign = 1.0f;
} else if (first.getVAlign() == VAlign.MIDDLE || first.getVAlign() == VAlign.DEFAULT) {
yAlign = 0.5f;
}
float xScale = 0f, yScale = 0f;
TypeDefinition widgetTypeDef = process.getConfig().getTypeDefinition(widgetToAdd.getClass());
if (widgetTypeDef != null) {
if (widgetTypeDef.getDefaultResize() == DefaultResize.X_AXIS || widgetTypeDef.getDefaultResize() == DefaultResize.BOTH) {
xScale = 1f;
}
if (widgetTypeDef.getDefaultResize() == DefaultResize.Y_AXIS || widgetTypeDef.getDefaultResize() == DefaultResize.BOTH) {
yScale = 1f;
}
}
Alignment alignment = new Alignment(xAlign,yAlign,xScale,yScale,widgetToAdd);
if (columnConstraint != null && rowConstraint != null) {
alignment.setSizeRequest(columnConstraint.getWidth(), rowConstraint.getWidth());
}
table.attach(alignment, col, col + first.getHSpan(), row, row + first.getVSpan(), colAttachOption, rowAttachOption,0,0);
//size groups
for(ControlConstraint cc : cell.getControls()) {
Integer group = cc.getSizeGroup();
if (group != null) {
SizeGroup sg = sizeGroups.get(group);
if (sg == null) {
SizeGroupMode mode = SizeGroupMode.BOTH;
if (cc.isSizeGroupX() || !cc.isSizeGroupY()) {
mode = SizeGroupMode.HORIZONTAL;
} else if (!cc.isSizeGroupX() || cc.isSizeGroupY()) {
mode = SizeGroupMode.VERTICAL;
}
sg = new SizeGroup(mode);
sizeGroups.put(group,sg);
}
sg.add(widgetNames.get(cc.getControlName()));
}
}
}
}
}
current.getCustomProperties().put(GtkConstants.INTERNAL_LAYOUT_HANDLED, true); //tell the Container handler to skip its logic
}
//gets the layout constraints
@SuppressWarnings("unchecked")
private LayoutConstraints getLayoutConstraints(Map<String, Object> typeDefinition) {
LayoutConstraints c = null;
Object content = typeDefinition.get(Builder.CONTENT);
if (content instanceof List) {
List<Object> contents = (List<Object>) content;
for(Object value : contents) {
if (value instanceof Map) {
Map<String,Object> parts = (Map<String, Object>) value;
if (parts.containsKey(ATTACH)) {
String attach = (String) parts.get(ATTACH);
c = LayoutConstraints.getParsedLayoutConstraints(attach, MigLayoutCommon.DEFAULT_ROW_COLUMN_CONSTRAINT,
MigLayoutCommon.DEFAULT_ROW_COLUMN_CONSTRAINT);
}
}
}
}
//String attach = current.getContentNode().getStringProperty(ATTACH);
//c.setLayoutConstraints(attach);
return c;
}
/* (non-Javadoc)
* @see org.javabuilders.IApplicable#getApplicableClass()
*/
public Class<Table> getApplicableClass() {
return Table.class;
}
}