package org.orienteer.core.component.structuretable;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.ILabelProvider;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import ru.ydn.wicket.wicketorientdb.behavior.SyncVisibilityBehaviour;
/**
* Panel which displays parameters of a specified object
*
* @param <T> the type of main object for this table
* @param <C> the type of criterias to be used for this table
*/
public abstract class StructureTable<T, C> extends GenericPanel<T>
{
private static final long serialVersionUID = 1L;
private static final String LABEL_CELL_ID = "label";
private static final String VALUE_CELL_ID = "value";
private final Caption caption;
private final ToolbarsContainer topToolbars;
private final ToolbarsContainer bottomToolbars;
private ListView<C> listView;
private long toolbarIdCounter;
private IModel<? extends List<? extends C>> criteriesModel;
public StructureTable(String id, IModel<T> model, List<C> list) {
this(id, model, Model.ofList(list));
}
public StructureTable(String id, IModel<T> model, IModel<? extends List<C>> criteriesModel) {
super(id, model);
this.criteriesModel = criteriesModel;
setOutputMarkupPlaceholderTag(true);
caption = new Caption("caption", Model.of(""));
topToolbars = new ToolbarsContainer("topToolbars");
bottomToolbars = new ToolbarsContainer("bottomToolbars");
add(caption, topToolbars, bottomToolbars);
this.listView = new ListView<C>("rows", criteriesModel) {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void populateItem(ListItem<C> item) {
IModel<C> rowModel = item.getModel();
Component value = getValueComponent(VALUE_CELL_ID, rowModel);
if(!VALUE_CELL_ID.equals(value.getId())) throw new WicketRuntimeException("Wrong component id '"+value.getId()+"'. Should be '"+VALUE_CELL_ID+"'.");
item.add(new SyncVisibilityBehaviour(value));
Component label = getLabelComponent(LABEL_CELL_ID, rowModel, getLabelModel(value, rowModel));
if(!LABEL_CELL_ID.equals(label.getId())) throw new WicketRuntimeException("Wrong component id '"+label.getId()+"'. Should be '"+LABEL_CELL_ID+"'.");
item.add(label, value);
}
};
listView.setReuseItems(true);
add(listView);
}
protected abstract Component getValueComponent(String id, IModel<C> rowModel);
protected Component getLabelComponent(String id, IModel<C> rowModel, IModel<?> labelModel)
{
return new Label(id, labelModel);
}
protected IModel<?> getLabelModel(Component resolvedComponent, IModel<C> rowModel)
{
if(resolvedComponent instanceof ILabelProvider<?>)
{
return ((ILabelProvider<?>)resolvedComponent).getLabel();
}
else
{
return rowModel;
}
}
public StructureTable<T, C> setReuseItems(boolean reuseItems)
{
listView.setReuseItems(reuseItems);
return this;
}
@SuppressWarnings("unchecked")
public IModel<String> getCaptionModel()
{
return (IModel<String>)caption.getDefaultModel();
}
public StructureTable<T, C> setCaptionModel(IModel<String> captionModel)
{
caption.setDefaultModel(captionModel);
return this;
}
public IModel<? extends List<? extends C>> getCriteriesModel() {
return criteriesModel;
}
public boolean getReuseItems()
{
return listView.getReuseItems();
}
String newToolbarId()
{
toolbarIdCounter++;
return String.valueOf(toolbarIdCounter).intern();
}
@Override
protected void onComponentTag(ComponentTag tag) {
checkComponentTag(tag, "table");
tag.append("class", "table table-condensed structure-table", " ");
super.onComponentTag(tag);
}
public void addBottomToolbar(final AbstractStructureTableToolbar<T> toolbar)
{
addToolbar(toolbar, bottomToolbars);
}
public void addTopToolbar(final AbstractStructureTableToolbar<T> toolbar)
{
addToolbar(toolbar, topToolbars);
}
private void addToolbar(final AbstractStructureTableToolbar<T> toolbar, final ToolbarsContainer container)
{
Args.notNull(toolbar, "toolbar");
container.getRepeatingView().add(toolbar);
}
@Override
public void detachModels() {
super.detachModels();
if(criteriesModel!=null) criteriesModel.detach();
}
private static class ToolbarsContainer extends WebMarkupContainer
{
private static final long serialVersionUID = 1L;
private final RepeatingView toolbars;
/**
* Constructor
*
* @param id
*/
private ToolbarsContainer(final String id)
{
super(id);
toolbars = new RepeatingView("toolbars");
add(toolbars);
}
public RepeatingView getRepeatingView()
{
return toolbars;
}
@Override
public void onConfigure()
{
super.onConfigure();
toolbars.configure();
Boolean visible = toolbars.visitChildren(new IVisitor<Component, Boolean>()
{
@Override
public void component(Component object, IVisit<Boolean> visit)
{
object.configure();
if (object.isVisible())
{
visit.stop(Boolean.TRUE);
}
else
{
visit.dontGoDeeper();
}
}
});
if (visible == null)
{
visible = false;
}
setVisible(visible);
}
}
/**
* A caption for the table. It renders itself only if {@link DataTable} caption has
* non-empty value.
*/
private static class Caption extends Label
{
/**
*/
private static final long serialVersionUID = 1L;
/**
* Construct.
*
* @param id
* the component id
* @param model
* the caption model
*/
public Caption(String id, IModel<String> model)
{
super(id, model);
}
@Override
protected void onConfigure()
{
setRenderBodyOnly(Strings.isEmpty(getDefaultModelObjectAsString()));
super.onConfigure();
}
@Override
protected IModel<String> initModel()
{
// don't try to find the model in the parent
return null;
}
}
}