/*
* 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.TableRepresentation;
import org.jbpm.formbuilder.client.FormBuilderGlobals;
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.Grid;
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 table
*/
@Reflectable
public class TableLayoutFormItem extends LayoutFormItem {
private final I18NConstants i18n = FormBuilderGlobals.getInstance().getI18n();
private Grid grid = new Grid(1, 1) {
@Override
public boolean remove(Widget widget) {
if (widget instanceof FBFormItem) {
boolean found = false;
int row = 0, column = 0;
while (row < super.getRowCount() && !found) {
for (column = 0; column < super.getColumnCount() && !found; ) {
Widget cellWidget = super.getWidget(row, column);
if (cellWidget != null && cellWidget.equals(widget)) {
found = true;
}
if (found) break; else column++;
}
if (found) break; else row++;
}
if (found) {
super.remove(widget);
getCellFormatter().getElement(row, column).setInnerHTML(" ");
}
return found;
} else if (widget instanceof PhantomPanel) {
boolean retval = false;
int row = 0, column = 0;
while (row < super.getRowCount() && !retval) {
for (column = 0; column < super.getColumnCount() && !retval; column++) {
if (super.getWidget(row, column) != null && isPhantom(super.getWidget(row, column))) {
getCellFormatter().getElement(row, column).setInnerHTML(" ");
break;
}
}
if (retval) break; else row++;
}
if (retval) {
super.remove(widget);
getCellFormatter().getElement(row, column).setInnerHTML(" ");
}
return retval;
} else {
return super.remove(widget);
}
}
};
private final EventBus bus = CommonGlobals.getInstance().getEventBus();
private Integer borderWidth = 1;
private Integer cellpadding = null;
private Integer cellspacing = null;
private Integer columns = 1;
private Integer rows = 1;
private String title = null;
public TableLayoutFormItem() {
this(new ArrayList<FBFormEffect>());
}
public TableLayoutFormItem(List<FBFormEffect> formEffects) {
super(formEffects);
grid.setBorderWidth(this.borderWidth);
add(grid);
setSize("90px", "90px");
grid.setSize(getWidth(), getHeight());
}
@Override
public HasWidgets getPanel() {
return grid;
}
@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.columns = extractInt(asPropertiesMap.get("columns"));
this.rows = extractInt(asPropertiesMap.get("rows"));
populate(this.grid);
}
private void populate(Grid 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.columns != null && this.columns > 0) {
grid.resizeColumns(this.columns);
}
if (this.rows != null && this.rows > 0) {
grid.resizeRows(this.rows);
}
}
@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("columns", this.columns);
map.put("rows", this.rows);
return map;
}
@Override
public boolean add(FBFormItem child) {
boolean added = false;
for (int i = 0; i < grid.getRowCount() && !added; i++) {
for (int j = 0; j < grid.getColumnCount() && !added; j++) {
if (grid.getWidget(i, j) == null || isWhiteSpace(grid.getWidget(i, j))) {
added = true;
int index = (i * grid.getColumnCount()) + j;
if (super.size() > index) {
super.insert(index-1, child);
} else {
super.add(child);
}
grid.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 < grid.getRowCount() && !found) {
for (column = 0; column < grid.getColumnCount() && !found; column++) {
Element cellElement = grid.getCellFormatter().getElement(row, column);
if (x > cellElement.getAbsoluteLeft() && x < cellElement.getAbsoluteRight() &&
y > cellElement.getAbsoluteTop() && y < cellElement.getAbsoluteBottom() &&
(grid.getWidget(row, column) == null ||
isWhiteSpace(grid.getWidget(row, column)) ||
isPhantom(grid.getWidget(row, column)))
) {
found = true;
break;
}
}
if (!found) {
row++;
}
}
if (found && !isPhantom(grid.getWidget(row, column))) {
grid.setWidget(row, column, phantom);
}
}
public int getRowForYCoordinate(int y) {
for (int row = 0; row < grid.getRowCount(); row++) {
Element rowElement = grid.getRowFormatter().getElement(row);
if (y > rowElement.getAbsoluteTop() && y < rowElement.getAbsoluteBottom()) {
return row;
}
}
return -1;
}
public List<FBFormItem> removeRow(int rowNumber) {
List<FBFormItem> retval = null;
if (rowNumber < grid.getRowCount()) {
retval = new ArrayList<FBFormItem>(grid.getColumnCount());
for (int column = 0; column < grid.getColumnCount(); column++) {
Widget widget = grid.getWidget(rowNumber, column);
if (widget instanceof FBFormItem) {
retval.add((FBFormItem) widget);
} else {
retval.add(null);
}
grid.remove(widget);
}
grid.removeRow(rowNumber);
this.rows--;
}
return retval;
}
public void addRow(int beforeRowNumber) {
grid.insertRow(beforeRowNumber);
this.rows++;
}
public void insertRowElements(int rowNumber, List<FBFormItem> rowItems) {
FBFormItem prevItem = null;
for (int i = rowNumber - 1; i > 0 && prevItem == null; i--) {
for (int j = grid.getColumnCount(); j > 0 && prevItem == null; j--) {
Widget widget = grid.getWidget(i, j);
if (widget != null && widget instanceof FBFormItem) {
prevItem = (FBFormItem) widget;
}
}
}
int index = prevItem == null ? -1 : super.getItems().indexOf(prevItem);
int colNumber = 0;
for (FBFormItem newItem : rowItems) {
if (newItem != null) {
if (index < 0) {
super.add(newItem);
} else {
super.insert(index, newItem);
}
index++;
grid.setWidget(rowNumber, colNumber, newItem);
}
colNumber++;
}
}
public void insertColumnElements(int colNumber, List<FBFormItem> columnItems) {
int rowNumber = 0;
for (FBFormItem newItem : columnItems) {
FBFormItem prevItem = null;
for (int i = grid.getRowCount(); i > 0 && prevItem == null; i--) {
for (int j = colNumber - 1; j > 0 && prevItem == null; j--) {
Widget widget = grid.getWidget(i, j);
if (widget != null && widget instanceof FBFormItem) {
prevItem = (FBFormItem) widget;
}
}
}
int index = prevItem == null ? -1 : super.getItems().indexOf(prevItem);
if (newItem != null) {
if (index < 0) {
super.add(newItem);
} else {
super.insert(index, newItem);
}
grid.setWidget(rowNumber, colNumber, newItem);
}
rowNumber++;
}
}
public int getColumnForXCoordinate(int x) {
if (grid.getRowCount() > 0) {
for (int column = 0; column < grid.getColumnCount(); column++) {
Element cellElement = grid.getCellFormatter().getElement(0, column);
if (x > cellElement.getAbsoluteLeft() && x < cellElement.getAbsoluteRight()) {
return column;
}
}
}
return -1;
}
public void addColumn(int beforeColumnNumber) {
if (beforeColumnNumber < grid.getColumnCount()) {
this.columns++;
grid.resizeColumns(grid.getColumnCount() + 1);
for (int row = 0; row < grid.getRowCount(); row++) {
for (int column = grid.getColumnCount() - 1; column > beforeColumnNumber && column < grid.getColumnCount(); column++) {
if (column > 0) {
Widget widget = grid.getWidget(row, column - 1);
if (widget != null) {
grid.setWidget(row, column, widget);
if (grid.getWidget(row, column - 1) != null) {
grid.getWidget(row, column - 1).getElement().getParentElement().setInnerHTML(" ");
}
}
}
}
}
}
}
public List<FBFormItem> removeColumn(int columnNumber) {
List<FBFormItem> retval = null;
if (columnNumber < grid.getColumnCount()) {
retval = new ArrayList<FBFormItem>(grid.getRowCount());
for (int row = 0; row < grid.getRowCount(); row++) {
for (int column = columnNumber + 1; column < grid.getColumnCount(); column++) {
Widget widget = grid.getWidget(row, column);
if (column == columnNumber + 1 && widget instanceof FBFormItem) {
retval.add((FBFormItem) widget);
} else if (column == columnNumber + 1) {
retval.add(null);
}
grid.setWidget(row, column - 1, widget);
remove(widget);
}
}
grid.resizeColumns(grid.getColumnCount() - 1);
this.columns--;
}
return retval;
}
protected boolean isPhantom(Widget widget) {
return widget != null && widget instanceof PhantomPanel;
}
@Override
public void replacePhantom(FBFormItem item) {
boolean found = false;
int row = 0, column = 0;
while (row < grid.getRowCount()) {
for (column = 0; column < grid.getColumnCount() && !found; column++) {
if (isPhantom(grid.getWidget(row, column))) {
found= true;
break;
}
}
if (found) break; else row++;
}
if (found) {
int index = (row * grid.getColumnCount()) + column;
if (super.size() > index) {
super.insert(index, item);
} else {
super.add(item);
}
grid.setWidget(row, column, null);
grid.setWidget(row, column, item);
} else {
add(item);
}
}
@Override
public boolean removeItem(FBFormItem item) {
return false;
}
@Override
public FormItemRepresentation getRepresentation() {
TableRepresentation rep = super.getRepresentation(new TableRepresentation());
rep.setRows(this.rows);
rep.setColumns(this.columns);
rep.setBorderWidth(this.borderWidth);
rep.setCellPadding(this.cellpadding);
rep.setCellSpacing(this.cellspacing);
for (int index = 0; index < this.columns * this.rows; index++) {
int column = index%this.columns;
int row = index/this.columns;
Widget widget = grid.getWidget(row, column);
if (widget != null && widget instanceof FBFormItem) {
FBFormItem item = (FBFormItem) widget;
FormItemRepresentation subRep = item.getRepresentation();
rep.setElement(row, column, subRep);
}
}
return rep;
}
@Override
public void populate(FormItemRepresentation rep) throws FormBuilderException {
if (!(rep instanceof TableRepresentation)) {
throw new FormBuilderException(i18n.RepNotOfType(rep.getClass().getName(), "TableRepresentation"));
}
super.populate(rep);
TableRepresentation trep = (TableRepresentation) rep;
this.rows = trep.getRows();
this.columns = trep.getColumns();
this.borderWidth = trep.getBorderWidth();
this.cellpadding = trep.getCellPadding();
this.cellspacing = trep.getCellSpacing();
populate(this.grid);
this.grid.clear();
super.getItems().clear();
if (trep.getWidth() != null) {
setWidth(trep.getWidth());
}
if (trep.getHeight() != null) {
setHeight(trep.getHeight());
}
if (trep.getElements() != null) {
for (int rowindex = 0; rowindex < trep.getElements().size(); rowindex++) {
List<FormItemRepresentation> row = trep.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.grid.setWidget(rowindex, cellindex, subItem);
super.add(subItem);
}
}
}
}
}
private void addItemToCollection(FBFormItem item) {
super.add(item);
}
@Override
public FBFormItem cloneItem() {
TableLayoutFormItem clone = new TableLayoutFormItem(getFormEffects());
clone.borderWidth = this.borderWidth;
clone.cellpadding = this.cellpadding;
clone.cellspacing = this.cellspacing;
clone.columns = this.columns;
clone.setHeight(getHeight());
clone.rows = this.rows;
clone.title = this.title;
clone.setWidth(getWidth());
clone.populate(clone.grid);
for (int index = 0; index < clone.columns * clone.rows; index++) {
int column = index%clone.columns;
int row = index/clone.columns;
FBFormItem item = (FBFormItem) this.grid.getWidget(row, column);
if (item != null) {
clone.grid.setWidget(row, column, item.cloneItem());
}
}
List<FBFormItem> items = this.getItems();
if (items != null) {
for (FBFormItem item : items) {
clone.addItemToCollection(item);
}
}
return clone;
}
@Override
public Widget cloneDisplay(Map<String, Object> data) {
Grid g = new Grid(this.rows, this.columns);
populate(g);
for (int index = 0; index < this.columns * this.rows; index++) {
int column = index%this.columns;
int row = index/this.columns;
FBFormItem item = (FBFormItem) this.grid.getWidget(row, column);
if (item != null) {
g.setWidget(row, column, item.cloneDisplay(data));
}
}
super.populateActions(g.getElement());
return g;
}
}