/**
* 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.brixcms.web.picker.common;
import java.io.Serializable;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
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.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.brixcms.jcr.wrapper.BrixNode;
import org.brixcms.web.picker.node.NodePickerTreeModel;
import org.brixcms.web.tree.AbstractTreeModel;
import org.brixcms.web.tree.FilteredJcrTreeNode;
import org.brixcms.web.tree.JcrTreeNode;
import org.brixcms.web.tree.NodeFilter;
import org.brixcms.web.util.AbstractModel;
import com.inmethod.grid.IGridColumn;
import com.inmethod.grid.SizeUnit;
import com.inmethod.grid.column.CheckBoxColumn;
import com.inmethod.grid.column.PropertyColumn;
import com.inmethod.grid.column.tree.AbstractTreeColumn;
import com.inmethod.grid.treegrid.TreeGrid;
public abstract class NodePickerTreeGridPanel extends Panel {
private final static NodeFilter ALLOW_ALL_FILTER = new NodeFilter() {
public boolean isNodeAllowed(BrixNode node) {
return true;
}
};
private final NodeFilter visibilityFilter;
private final NodeFilter enabledFilter;
private TreeGrid<NodePickerTreeModel, JcrTreeNode, String> grid;
public NodePickerTreeGridPanel(String id, NodeFilter visibilityFilter, NodeFilter enabledFilter) {
super(id);
this.visibilityFilter = visibilityFilter;
this.enabledFilter = enabledFilter != null ? enabledFilter : ALLOW_ALL_FILTER;
}
public NodePickerTreeGridPanel(String id, IModel<?> model, NodeFilter visibilityFilter, NodeFilter enabledFilter) {
super(id, model);
this.visibilityFilter = visibilityFilter;
this.enabledFilter = enabledFilter != null ? enabledFilter : ALLOW_ALL_FILTER;
}
public TreeGrid<NodePickerTreeModel, JcrTreeNode, String> getGrid() {
return grid;
}
public NodeFilter getVisibilityFilter() {
return visibilityFilter;
}
@Override
protected void onBeforeRender() {
if (!hasBeenRendered()) {
initComponents();
}
expandToSelectedNodes();
super.onBeforeRender();
}
protected void initComponents() {
grid = new TreeGrid<NodePickerTreeModel, JcrTreeNode, String>("grid", new Model((Serializable) newTreeModel()), newGridColumns()) {
@Override
protected void onItemSelectionChanged(IModel<JcrTreeNode> rowModel, boolean newValue) {
BrixNode node = getNode(rowModel);
if (isNodeEnabled(rowModel.getObject()) && node != null) {
if (isItemSelected(rowModel)) {
onNodeSelected(node);
} else {
onNodeDeselected(node);
}
//update();
}
super.onItemSelectionChanged(rowModel, newValue);
}
@Override
protected void onRowClicked(AjaxRequestTarget target, IModel<JcrTreeNode> rowModel) {
BrixNode node = getNode(rowModel);
if (isNodeEnabled(rowModel.getObject()) && node != null) {
super.onRowClicked(target, rowModel);
}
}
@Override
protected void onRowPopulated(WebMarkupContainer rowComponent) {
super.onRowPopulated(rowComponent);
rowComponent.add(new Behavior() {
@Override
public void onComponentTag(Component component, ComponentTag tag) {
BrixNode node = getNode(component.getDefaultModel());
if (!isNodeEnabled((JcrTreeNode) component.getDefaultModelObject()) || node == null) {
tag.put("class", "disabled");
}
}
});
}
};
configureGrid(grid);
add(grid);
}
protected AbstractTreeModel newTreeModel() {
return new AbstractTreeModel() {
public JcrTreeNode getRoot() {
return new FilteredJcrTreeNode(getRootNode(), visibilityFilter);
}
};
}
protected abstract JcrTreeNode getRootNode();
protected List<IGridColumn<NodePickerTreeModel,JcrTreeNode, String>> newGridColumns() {
List<IGridColumn<NodePickerTreeModel,JcrTreeNode, String>> columns =
new ArrayList<IGridColumn<NodePickerTreeModel, JcrTreeNode, String>>();
columns.add(new NodePickerCheckBoxColumn("checkbox"));
columns.add(new TreeColumn("name", new ResourceModel("name")).setInitialSize(300));
columns.add(new NodePropertyColumn(new ResourceModel("type"), "userVisibleType"));
columns.add(new DatePropertyColumn(new ResourceModel("lastModified"), "lastModified"));
columns.add(new NodePropertyColumn(new ResourceModel("lastModifiedBy"), "lastModifiedBy"));
return columns;
}
protected void onNodeSelected(BrixNode node) {
}
protected void onNodeDeselected(BrixNode node) {
}
private BrixNode getNode(IModel<?> model) {
Object object = model.getObject();
if (object instanceof JcrTreeNode) {
IModel<BrixNode> nodeModel = ((JcrTreeNode) object).getNodeModel();
return nodeModel != null ? nodeModel.getObject() : null;
} else {
return null;
}
}
private boolean isNodeEnabled(JcrTreeNode node) {
BrixNode n = node.getNodeModel() != null ? node.getNodeModel().getObject() : null;
return enabledFilter.isNodeAllowed(n);
}
protected void configureGrid(TreeGrid<NodePickerTreeModel, JcrTreeNode, String> grid) {
grid.getTree().setRootLess(true);
grid.setClickRowToSelect(true);
grid.setContentHeight(18, SizeUnit.EM);
}
protected void expandToSelectedNodes() {
for (IModel<?> model : getGrid().getSelectedItems()) {
JcrTreeNode node = (JcrTreeNode) model.getObject();
expandToNode(node);
}
}
private void expandToNode(JcrTreeNode node) {
boolean first = true;
while (node != null && node.getNodeModel() != null && node.getNodeModel().getObject() != null) {
BrixNode n = node.getNodeModel().getObject();
if (!first) {
getGrid().getTreeState().expandNode(node);
} else {
first = false;
}
if (n.getDepth() > 0) {
node = TreeAwareNode.Util.getTreeNode((BrixNode) n.getParent(), visibilityFilter);
} else {
node = null;
}
}
}
private class TreeColumn extends AbstractTreeColumn {
public TreeColumn(String columnId, IModel headerModel) {
super(columnId, headerModel);
}
@Override
protected Component newNodeComponent(String id, final IModel model) {
IModel<String> labelModel = new AbstractModel<String>() {
@Override
public String getObject() {
BrixNode node = getNode(model);
if (node != null) {
return node.getUserVisibleName();
} else {
return model.getObject().toString();
}
}
};
return new Label(id, labelModel);
}
@Override
public int getColSpan(IModel rowModel) {
BrixNode node = getNode(rowModel);
return node != null ? 1 : 4;
}
}
private class NodePropertyColumn extends PropertyColumn {
public NodePropertyColumn(IModel headerModel, String propertyExpression) {
super(headerModel, propertyExpression);
}
@Override
protected Object getModelObject(IModel rowModel) {
return getNode(rowModel);
}
}
protected class NodePickerCheckBoxColumn extends CheckBoxColumn {
public NodePickerCheckBoxColumn(String columnId) {
super(columnId);
}
@Override
protected boolean isCheckBoxEnabled(IModel model) {
BrixNode node = getNode(model);
return isNodeEnabled((JcrTreeNode) model.getObject()) && node != null;
}
}
protected class DatePropertyColumn extends NodePropertyColumn {
public DatePropertyColumn(IModel<?> headerModel, String propertyExpression) {
super(headerModel, propertyExpression);
}
@Override
protected CharSequence convertToString(Object object) {
if (object instanceof Date) {
Date date = (Date) object;
return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date);
} else {
return null;
}
}
}
}