/*
* Copyright 2011 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.formbuilder.client.form.items;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jbpm.formapi.client.CommonGlobals;
import org.jbpm.formapi.client.FormBuilderException;
import org.jbpm.formapi.client.bus.ui.NotificationEvent;
import org.jbpm.formapi.client.effect.FBFormEffect;
import org.jbpm.formapi.client.form.FBFormItem;
import org.jbpm.formapi.client.form.LayoutFormItem;
import org.jbpm.formapi.client.form.PhantomPanel;
import org.jbpm.formapi.shared.api.FormItemRepresentation;
import org.jbpm.formapi.shared.api.items.MIGPanelRepresentation;
import org.jbpm.formbuilder.client.FormBuilderGlobals;
import org.jbpm.formbuilder.client.effect.ChangeColspanFormEffect;
import org.jbpm.formbuilder.client.messages.I18NConstants;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.gwtent.reflection.client.Reflectable;
/**
* UI form item. Represents a flexible table (mig layout like)
*/
@Reflectable
public class MIGLayoutFormItem extends LayoutFormItem {
private final I18NConstants i18n = FormBuilderGlobals.getInstance().getI18n();
private final EventBus bus = CommonGlobals.getInstance().getEventBus();
private FlexTable table = new FlexTable() {
@Override
public boolean remove(Widget widget) {
if (widget instanceof FBFormItem) {
MIGLayoutFormItem.super.remove((FBFormItem) widget);
}
return super.remove(widget);
}
};
private Integer borderWidth = 1;
private Integer cellpadding = null;
private Integer cellspacing = null;
private Integer rows = 1;
private Integer columns = 1;
private String title = null;
public MIGLayoutFormItem() {
this(new ArrayList<FBFormEffect>());
}
public MIGLayoutFormItem(List<FBFormEffect> formEffects) {
super(formEffects);
table.setBorderWidth(this.borderWidth);
table.insertRow(table.getRowCount());
table.addCell(0);
add(table);
setSize("90px", "90px");
table.setSize(getWidth(), getHeight());
}
@Override
public void replacePhantom(FBFormItem item) {
if (!item.hasEffectOfType(ChangeColspanFormEffect.class)) {
item.addEffect(new ChangeColspanFormEffect());
}
boolean found = false;
int row = 0, column = 0;
while (row < table.getRowCount()) {
for (column = 0; column < table.getCellCount(row) && !found; column++) {
if (isPhantom(table.getWidget(row, column))) {
found= true;
break;
}
}
if (found) break; else row++;
}
if (found) {
int index = (row * table.getCellCount(row)) + column;
if (super.size() > index) {
super.insert(index, item);
} else {
super.add(item);
}
table.setWidget(row, column, null);
table.setWidget(row, column, item);
} else {
add(item);
}
}
@Override
public boolean add(FBFormItem child) {
if (!child.hasEffectOfType(ChangeColspanFormEffect.class)) {
child.addEffect(new ChangeColspanFormEffect());
}
boolean added = false;
for (int i = 0; i < table.getRowCount() && !added; i++) {
for (int j = 0; j < table.getCellCount(i) && !added; j++) {
if (table.getWidget(i, j) == null || isWhiteSpace(table.getWidget(i, j))) {
added = true;
int index = (i * table.getCellCount(i)) + j;
if (super.size() > index) {
super.insert(index-1, child);
} else {
super.add(child);
}
table.addCell(i);
table.setWidget(i, j, child);
break;
}
}
}
if (!added) {
bus.fireEvent(new NotificationEvent(NotificationEvent.Level.WARN, i18n.TableFull()));
return false;
}
return true;
}
@Override
public void add(PhantomPanel phantom, int x, int y) {
int row = 0, column = 0;
boolean found = false;
while (row < table.getRowCount() && !found) {
for (column = 0; column < table.getCellCount(row) && !found; column++) {
Element cellElement = table.getCellFormatter().getElement(row, column);
if (x > cellElement.getAbsoluteLeft() && x < cellElement.getAbsoluteRight() &&
y > cellElement.getAbsoluteTop() && y < cellElement.getAbsoluteBottom() &&
(table.getWidget(row, column) == null || isWhiteSpace(table.getWidget(row, column)) || isPhantom(table.getWidget(row, column)))) {
found = true;
break;
}
}
if (!found) {
row++;
}
}
if (found && !isPhantom(table.getWidget(row, column))) {
table.setWidget(row, column, phantom);
}
}
@Override
public HasWidgets getPanel() {
return table;
}
@Override
public Map<String, Object> getFormItemPropertiesMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("borderWidth", this.borderWidth);
map.put("cellpadding", this.cellpadding);
map.put("cellspacing", this.cellspacing);
map.put("height", getHeight());
map.put("width", getWidth());
map.put("title", this.title);
map.put("rows", this.rows);
map.put("columns", this.columns);
return map;
}
@Override
public void saveValues(Map<String, Object> asPropertiesMap) {
this.borderWidth = extractInt(asPropertiesMap.get("borderWidth"));
this.cellpadding = extractInt(asPropertiesMap.get("cellpadding"));
this.cellspacing = extractInt(asPropertiesMap.get("cellspacing"));
this.setHeight(extractString(asPropertiesMap.get("height")));
this.setWidth(extractString(asPropertiesMap.get("width")));
this.title = extractString(asPropertiesMap.get("title"));
this.rows = extractInt(asPropertiesMap.get("rows"));
this.columns = extractInt(asPropertiesMap.get("columns"));
populate(this.table);
}
@Override
public FormItemRepresentation getRepresentation() {
MIGPanelRepresentation rep = super.getRepresentation(new MIGPanelRepresentation());
rep.setRows(this.rows);
rep.setBorderWidth(this.borderWidth);
rep.setCellPadding(this.cellpadding);
rep.setCellSpacing(this.cellspacing);
rep.setTitle(this.title);
for (int r = 0; r < table.getRowCount(); r++) {
for (int c = 0; c < table.getCellCount(r); c++) {
Widget widget = table.getWidget(r, c);
int colspan = table.getFlexCellFormatter().getColSpan(r, c);
int rowspan = table.getFlexCellFormatter().getRowSpan(r, c);
if (widget != null && widget instanceof FBFormItem) {
FBFormItem item = (FBFormItem) widget;
FormItemRepresentation subRep = item.getRepresentation();
rep.setElement(r, c, subRep, colspan, rowspan);
}
}
}
return rep;
}
@Override
public void populate(FormItemRepresentation rep) throws FormBuilderException {
if (!(rep instanceof MIGPanelRepresentation)) {
throw new FormBuilderException(i18n.RepNotOfType(rep.getClass().getName(), "MIGPanelRepresentation"));
}
super.populate(rep);
MIGPanelRepresentation mprep = (MIGPanelRepresentation) rep;
this.rows = mprep.getRows();
this.borderWidth = mprep.getBorderWidth();
this.cellpadding = mprep.getCellPadding();
this.cellspacing = mprep.getCellSpacing();
populate(this.table);
this.table.clear();
super.getItems().clear();
if (mprep.getWidth() != null) {
setWidth(mprep.getWidth());
}
if (mprep.getHeight() != null) {
setHeight(mprep.getHeight());
}
if (mprep.getElements() != null) {
for (int rowindex = 0; rowindex < mprep.getElements().size(); rowindex++) {
List<FormItemRepresentation> row = mprep.getElements().get(rowindex);
if(row != null) {
for (int cellindex = 0; cellindex < row.size(); cellindex++) {
FormItemRepresentation cell = row.get(cellindex);
FBFormItem subItem = super.createItem(cell);
this.table.setWidget(rowindex, cellindex, subItem);
int colspan = mprep.getColspan(rowindex, cellindex);
int rowspan = mprep.getRowspan(rowindex, cellindex);
if (colspan > 1) {
this.table.getFlexCellFormatter().setColSpan(rowindex, cellindex, colspan);
}
if (rowspan > 1) {
this.table.getFlexCellFormatter().setRowSpan(rowindex, cellindex, rowspan);
}
super.add(subItem);
}
}
}
}
}
private void populate(FlexTable grid) {
if (this.borderWidth != null && this.borderWidth > 0) {
grid.setBorderWidth(this.borderWidth);
}
if (this.cellpadding != null && this.cellpadding >= 0) {
grid.setCellPadding(this.cellpadding);
}
if (this.cellspacing != null && this.cellspacing >= 0) {
grid.setCellSpacing(this.cellspacing);
}
if (getHeight() != null) {
grid.setHeight(getHeight());
}
if (getWidth() != null) {
grid.setWidth(getWidth());
}
if (this.title != null) {
grid.setTitle(this.title);
}
if (this.rows != null && this.rows > 0) {
while (this.rows > grid.getRowCount()) {
grid.insertRow(grid.getRowCount());
int columnCount = 0;
FlexCellFormatter formatter = grid.getFlexCellFormatter();
for (int cell = 0; cell < grid.getCellCount(grid.getRowCount() - 1); cell++) {
columnCount += formatter.getColSpan(grid.getRowCount() - 1, cell);
}
while (this.columns > columnCount) {
grid.addCell(grid.getRowCount() - 1); //at least one cell per column. Modified later by colspans
columnCount++;
}
}
while (this.rows < grid.getRowCount()) {
grid.removeRow(grid.getRowCount() - 1);
}
}
if (this.columns != null && this.columns > 0) {
for (int row = 0; row < grid.getRowCount(); row++) {
int columnCount = 0;
FlexCellFormatter formatter = grid.getFlexCellFormatter();
for (int cell = 0; cell < grid.getCellCount(row); cell++) {
columnCount += formatter.getColSpan(row, cell);
}
while (this.columns > columnCount) {
grid.addCell(row);
columnCount++;
}
while (this.columns < columnCount) {
int cellCount = grid.getCellCount(row);
if (cellCount > 0) {
int cellColumns = formatter.getColSpan(row, cellCount - 1);
if (cellColumns > 1 && columnCount - cellColumns >= this.columns) {
grid.removeCell(row, cellCount - 1);
} else {
grid.removeCell(row, cellCount - 1);
}
}
columnCount--;
}
}
}
}
@Override
public FBFormItem cloneItem() {
MIGLayoutFormItem clone = super.cloneItem(new MIGLayoutFormItem());
clone.borderWidth = this.borderWidth;
clone.cellpadding = this.cellpadding;
clone.cellspacing = this.cellspacing;
clone.rows = this.rows;
clone.title = this.title;
clone.populate(clone.table);
for (int row = 0; row < table.getRowCount(); row++) {
for (int column = 0; column < table.getCellCount(row); column++) {
FBFormItem item = (FBFormItem) this.table.getWidget(row, column);
if (item != null) {
clone.table.addCell(row);
int colspan = table.getFlexCellFormatter().getColSpan(row, column);
clone.table.getFlexCellFormatter().setColSpan(row, column, colspan);
clone.table.setWidget(row, column, item.cloneItem());
}
}
}
return clone;
}
@Override
public Widget cloneDisplay(Map<String, Object> data) {
FlexTable ft = new FlexTable();
populate(ft);
for (int row = 0; row < table.getRowCount(); row++) {
for (int column = 0; column < table.getCellCount(row); column++) {
FBFormItem item = (FBFormItem) this.table.getWidget(row, column);
if (item != null) {
ft.addCell(row);
int colspan = table.getFlexCellFormatter().getColSpan(row, column);
ft.getFlexCellFormatter().setColSpan(row, column, colspan);
ft.setWidget(row, column, item.cloneDisplay(data));
}
}
}
super.populateActions(ft.getElement());
return ft;
}
protected boolean isPhantom(Widget widget) {
return widget != null && widget instanceof PhantomPanel;
}
public void setSpan(FBFormItem item, Integer colspan, Integer rowspan) {
for (int row = 0; row < table.getRowCount(); row++) {
for (int col = 0; col < table.getCellCount(row); col++) {
Widget widget = table.getWidget(row, col);
if (widget != null && widget.equals(item)) {
if (colspan != null && colspan > 0) {
table.getFlexCellFormatter().setColSpan(row, col, colspan);
}
if (rowspan != null && rowspan > 0) {
table.getFlexCellFormatter().setRowSpan(row, col, rowspan);
}
break;
}
}
}
}
public int getColSpan(FBFormItem item) {
for (int row = 0; row < table.getRowCount(); row++) {
for (int col = 0; col < table.getCellCount(row); col++) {
Widget widget = table.getWidget(row, col);
if (widget != null && widget.equals(item)) {
int colSpan = table.getFlexCellFormatter().getColSpan(row, col);
if (colSpan <= 0) colSpan = 1;
return colSpan;
}
}
}
return 1;
}
public int getRowSpan(FBFormItem item) {
for (int row = 0; row < table.getRowCount(); row++) {
for (int col = 0; col < table.getCellCount(row); col++) {
Widget widget = table.getWidget(row, col);
if (widget != null && widget.equals(item)) {
int rowSpan = table.getFlexCellFormatter().getRowSpan(row, col);
if (rowSpan <= 0) rowSpan = 1;
return rowSpan;
}
}
}
return 1;
}
}