org.nakedobjects.nos.client.dnd.table.TableCellBuilder Maven / Gradle / Ivy
package org.nakedobjects.nos.client.dnd.table;
import org.nakedobjects.noa.adapter.Naked;
import org.nakedobjects.noa.adapter.NakedObject;
import org.nakedobjects.noa.adapter.NakedValue;
import org.nakedobjects.noa.adapter.value.ImageValue;
import org.nakedobjects.noa.reflect.NakedObjectField;
import org.nakedobjects.noa.reflect.OneToManyAssociation;
import org.nakedobjects.noa.reflect.OneToOneAssociation;
import org.nakedobjects.noa.reflect.ValueAssociation;
import org.nakedobjects.noa.spec.NakedObjectSpecification;
import org.nakedobjects.nof.core.util.Assert;
import org.nakedobjects.nof.core.util.UnexpectedCallException;
import org.nakedobjects.nof.core.util.UnknownTypeException;
import org.nakedobjects.nos.client.dnd.CompositeViewSpecification;
import org.nakedobjects.nos.client.dnd.Content;
import org.nakedobjects.nos.client.dnd.ObjectContent;
import org.nakedobjects.nos.client.dnd.Toolkit;
import org.nakedobjects.nos.client.dnd.ValueContent;
import org.nakedobjects.nos.client.dnd.View;
import org.nakedobjects.nos.client.dnd.ViewAxis;
import org.nakedobjects.nos.client.dnd.ViewFactory;
import org.nakedobjects.nos.client.dnd.ViewSpecification;
import org.nakedobjects.nos.client.dnd.basic.UnlinedTextFieldSpecification;
import org.nakedobjects.nos.client.dnd.builder.AbstractViewBuilder;
import org.nakedobjects.nos.client.dnd.content.OneToOneFieldImpl;
import org.nakedobjects.nos.client.dnd.content.ValueFieldImpl;
import org.nakedobjects.nos.client.dnd.drawing.Location;
import org.nakedobjects.nos.client.dnd.drawing.Padding;
import org.nakedobjects.nos.client.dnd.drawing.Size;
import org.nakedobjects.nos.client.dnd.view.simple.BlankView;
import org.nakedobjects.nos.client.dnd.view.simple.CompositeView;
import org.nakedobjects.nos.client.dnd.view.simple.FieldErrorView;
import org.apache.log4j.Logger;
class TableCellBuilder extends AbstractViewBuilder {
private static final Logger LOG = Logger.getLogger(TableCellBuilder.class);
private void addField(final View view, final NakedObject object, final NakedObjectField field) {
Naked value = field.get(object);
View fieldView;
fieldView = createFieldView(view, object, field, value);
if (fieldView != null) {
view.addView(decorateSubview(fieldView));
} else {
view.addView(new FieldErrorView("No field for " + value));
}
}
public void build(final View view) {
Assert.assertEquals("ensure the view is complete decorated view", view.getView(), view);
Content content = view.getContent();
NakedObject object = ((ObjectContent) content).getObject();
TableAxis viewAxis = (TableAxis) view.getViewAxis();
if (view.getSubviews().length == 0) {
buildNew(object, view, viewAxis);
} else {
buildUpdate(object, view, viewAxis);
}
}
private void buildUpdate(final NakedObject object, final View view, final TableAxis viewAxis) {
LOG.debug("update view " + view + " for " + object);
View[] subviews = view.getSubviews();
NakedObjectSpecification spec = object.getSpecification();
for (int i = 0; i < subviews.length; i++) {
NakedObjectField field = fieldFromActualSpec(spec, viewAxis.getFieldForColumn(i));
View subview = subviews[i];
Naked value = field.get(object);
if (field.isValue()) {
boolean visiblityChange = !field.isVisible(object) ^ (subview instanceof BlankView);
Naked naked = subview.getContent().getNaked();
boolean valueChange = value != null && value.getObject() != null && !value.getObject().equals(naked.getObject());
if (visiblityChange || valueChange) {
View fieldView = createFieldView(view, object, field, value);
view.replaceView(subview, decorateSubview(fieldView));
}
subview.refresh();
} else if (field.isObject()) {
NakedObject existing = ((ObjectContent) subviews[i].getContent()).getObject();
boolean changedValue = value != existing;
if (changedValue) {
View fieldView;
fieldView = createFieldView(view, object, field, value);
if (fieldView != null) {
view.replaceView(subview, decorateSubview(fieldView));
} else {
view.addView(new FieldErrorView("No field for " + value));
}
}
}
}
}
private NakedObjectField fieldFromActualSpec(NakedObjectSpecification spec, NakedObjectField field) {
String fieldName = field.getId();
return spec.getField(fieldName);
}
private void buildNew(final NakedObject object, final View view, final TableAxis viewAxis) {
LOG.debug("build view " + view + " for " + object);
int len = viewAxis.getColumnCount();
NakedObjectSpecification spec = object.getSpecification();
for (int f = 0; f < len; f++) {
NakedObjectField field = fieldFromActualSpec(spec, viewAxis.getFieldForColumn(f));
addField(view, object, field);
}
}
public View createCompositeView(final Content content, final CompositeViewSpecification specification, final ViewAxis axis) {
return new CompositeView(content, specification, axis);
}
private View createFieldView(final View view, final NakedObject object, final NakedObjectField field, final Naked value) {
if (field == null) {
throw new NullPointerException();
}
ViewFactory factory = Toolkit.getViewFactory();
ViewSpecification cellSpec;
Content content;
if (field instanceof OneToManyAssociation) {
throw new UnexpectedCallException("no collections allowed");
} else if (field.isValue()) {
content = new ValueFieldImpl(object, (NakedValue) value, (ValueAssociation) field);
if (content.getNaked() instanceof ImageValue) {
return new BlankView(content);
}
if (!field.isVisible(object)) {
return new BlankView(content);
}
if (((ValueContent) content).getNoLines() > 0) {
/*
* TODO remove this after introducing constraints into view specs that allow the parent view
* to specify what kind of subviews it can deal
*/
cellSpec = new UnlinedTextFieldSpecification();
} else {
cellSpec = factory.getValueFieldSpecification((ValueContent) content);
}
} else if (field instanceof OneToOneAssociation) {
content = new OneToOneFieldImpl(object, (NakedObject) value, (OneToOneAssociation) field);
if (!field.isVisible(object)) {
return new BlankView(content);
}
cellSpec = factory.getIconizedSubViewSpecification((ObjectContent) content);
} else {
throw new UnknownTypeException(field);
}
ViewAxis axis = view.getViewAxis();
return cellSpec.createView(content, axis);
}
public Size getRequiredSize(final View row) {
int maxHeight = 0;
int totalWidth = 0;
TableAxis axis = ((TableAxis) row.getViewAxis());
View[] cells = row.getSubviews();
int maxBaseline = maxBaseline(cells);
for (int i = 0; i < cells.length; i++) {
totalWidth += axis.getColumnWidth(i);
Size s = cells[i].getRequiredSize(new Size());
int b = cells[i].getBaseline();
int baselineOffset = Math.max(0, maxBaseline - b);
maxHeight = Math.max(maxHeight, s.getHeight() + baselineOffset);
}
return new Size(totalWidth, maxHeight);
}
public void layout(final View row, final Size maximumSize) {
int x = 0;
// int rowHeight = row.getSize().getHeight();
TableAxis axis = ((TableAxis) row.getViewAxis());
View[] cells = row.getSubviews();
int maxBaseline = maxBaseline(cells);
for (int i = 0; i < cells.length; i++) {
View cell = cells[i];
Size s = cell.getRequiredSize(new Size(maximumSize));
s.setWidth(axis.getColumnWidth(i));
// s.setHeight(rowHeight);
cell.setSize(s);
int b = cell.getBaseline();
int baselineOffset = Math.max(0, maxBaseline - b);
cell.setLocation(new Location(x, baselineOffset));
x += s.getWidth();
}
Padding padding = row.getPadding();
Size size = new Size(padding.getLeftRight(), padding.getTopBottom());
row.setSize(size);
}
private int maxBaseline(final View[] cells) {
int maxBaseline = 0;
for (int i = 0; i < cells.length; i++) {
View cell = cells[i];
maxBaseline = Math.max(maxBaseline, cell.getBaseline());
}
return maxBaseline;
}
}
// Copyright (c) Naked Objects Group Ltd.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy