org.wings.plaf.css.AbstractLayoutCG Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/
package org.wings.plaf.css;
import org.wings.SComponent;
import org.wings.SContainer;
import org.wings.SGridBagLayout;
import org.wings.SLayoutManager;
import org.wings.io.Device;
import org.wings.plaf.LayoutCG;
import org.wings.style.CSSProperty;
import java.awt.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
/**
* Abstract super class for layout CGs using invisible tables to arrange their contained components.
*
* @author bschmid
*/
public abstract class AbstractLayoutCG implements LayoutCG {
/**
* Print HTML table element declaration of a typical invisible layouter table.
*/
protected static void openLayouterBody(Device d, SLayoutManager layout) throws IOException {
Utils.printDebugNewline(d, layout.getContainer());
Utils.printDebug(d, "");
d.print("");
}
private static String name(SLayoutManager layout) {
String name = layout.getClass().getName();
int pos = name.lastIndexOf('.');
if (pos != -1) {
name = name.substring(pos + 1);
}
return name;
}
/**
* Counterpart to {@link #openLayouterBody}
*/
protected static void closeLayouterBody(Device d, SLayoutManager layout) throws IOException {
d.print("");
Utils.printDebugNewline(d, layout.getContainer());
Utils.printDebug(d, "");
}
/**
* Render passed list of components to a table body.
* Use {@link #openLayouterBody(org.wings.io.Device,org.wings.SLayoutManager)} in front
* and {@link #closeLayouterBody(org.wings.io.Device,org.wings.SLayoutManager)} afterwards!
*
* @param d The device to write to
* @param renderedContainer The (container) component rendered
* @param cols Wrap after this amount of columns
* @param components The components to layout in this table
* @param cellStyle Style attributes for the table cells.
*/
protected void printLayouterTableBody(final Device d, final SContainer renderedContainer,
int cols, final List components, final TableCellStyle cellStyle)
throws IOException {
final int componentCount = components.size();
final TableCellStyle origCellStyle = cellStyle.makeACopy();
int col = 0;
int row = 0;
int idx = 0;
for (Iterator iter = components.iterator(); iter.hasNext();) {
final SComponent c = (SComponent) iter.next();
if (col == 0) {
Utils.printNewline(d, c.getParent());
d.print("");
} else if (col % cols == 0) {
row += 1;
col = 0;
d.print(" ");
Utils.printNewline(d, c.getParent());
d.print("");
}
cellStyle.renderAsTH = row == 0 && cellStyle.renderAsTH;
cellStyle.defaultLayoutCellHAlignment = getDefaultLayoutCellHAlignment();
cellStyle.defaultLayoutCellVAlignment = getDefaultLayoutCellVAlignment();
if (PaddingVoodoo.hasPaddingInsets(renderedContainer)) {
final Insets patchedInsets = (Insets) origCellStyle.getInsets().clone();
final boolean isFirstRow = row == 0;
final boolean isLastRow = ((componentCount - (idx+1))+col < cols);
final boolean isFirstCol = (col == 0);
final boolean isLastCol = ((col % cols) == 0);
PaddingVoodoo.doBorderPaddingsWorkaround(renderedContainer.getBorder(), patchedInsets,
isFirstRow, isFirstCol, isLastCol, isLastRow);
cellStyle.setInsets(patchedInsets);
}
openLayouterCell(d, c, cellStyle);
c.write(d); // Render component
closeLayouterCell(d, c, row == 0 && cellStyle.renderAsTH);
col++;
idx++;
if (!iter.hasNext()) {
d.print(" ");
Utils.printNewline(d, c.getParent());
}
}
}
/**
* The default horizontal alignment for components inside a layout cell.
*/
public abstract int getDefaultLayoutCellHAlignment();
/**
* The default vertical alignment for components inside a layout cell.
*/
public abstract int getDefaultLayoutCellVAlignment();
/**
* Converts a hgap/vgap in according inset declaration.
* If a gapp is odd, the overlapping additonal pixel is added to the right/bottom inset.
*
* @param hgap Horizontal gap between components in px
* @param vgap Vertical gap between components in px
* @return An inset equal to the gap declarations
*/
protected static Insets convertGapsToInset(int hgap, int vgap) {
Insets insets = null;
if (hgap > -1 || vgap > -1) {
final int paddingTop = (int) Math.round((vgap < 0 ? 0 : vgap) / 2.0);
final int paddingBottom = (int) Math.round((vgap < 0 ? 0 : vgap) / 2.0 + 0.1); // round up
final int paddingLeft = (int) Math.round((hgap < 0 ? 0 : hgap) / 2.0);
final int paddingRight = (int) Math.round((hgap < 0 ? 0 : hgap) / 2.0 + 0.1); // round up
insets = new Insets(paddingTop, paddingLeft, paddingBottom, paddingRight);
}
return insets;
}
public static void openLayouterRow(final Device d, String height) throws IOException {
d.print("");
}
/**
* Closes a TR.
*/
public static void closeLayouterRow(final Device d) throws IOException {
d.print(" ");
}
/**
* Opens a TD or TH cell of an invisible layouter table. This method also does component alignment.
* Attention: As you want to attach more attributes you need to close the tag with > on your own!
*/
public static void openLayouterCell(final Device d, final SComponent component, final TableCellStyle cellStyle)
throws IOException {
Utils.printNewline(d, component);
if (cellStyle.renderAsTH) {
d.print("");
}
/**
* Closes a TD or TH cell of an invisible layouter table.
*
* @param renderAsHeader Print TH instead of TD
*/
public static void closeLayouterCell(final Device d, final SComponent component, final boolean renderAsHeader) throws IOException {
Utils.printNewline(d, component);
d.print(renderAsHeader ? " " : "");
}
protected abstract int getLayoutHGap(SLayoutManager layout);
protected abstract int getLayoutVGap(SLayoutManager layout);
protected abstract int getLayoutBorder(SLayoutManager layout);
protected final TableCellStyle cellLayoutStyle(SLayoutManager layout) {
final Insets insets = convertGapsToInset(getLayoutHGap(layout), getLayoutVGap(layout));
final int layoutBorder = getLayoutBorder(layout);
final TableCellStyle cellStyle = new TableCellStyle();
cellStyle.setInsets(insets);
if (layoutBorder > 0) {
cellStyle.getAdditionalCellStyles().put(CSSProperty.BORDER, layoutBorder + "px solid black");
}
return cellStyle;
}
protected abstract int layoutOversize(SLayoutManager layout);
protected static int cellOversize(SGridBagLayout layout, Insets insets) {
return insets.top + insets.bottom + layout.getBorder();
}
}