/**
* Copyright (c) 2015-2016 Evolveum
*
* 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 com.evolveum.midpoint.web.page.admin.orgs;
import java.io.Serializable;
import java.util.*;
import com.evolveum.midpoint.web.page.admin.users.PageOrgTree;
import com.evolveum.midpoint.web.session.OrgTreeStateStorage;
import com.evolveum.midpoint.web.session.PageStorage;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.tree.ISortableTreeProvider;
import org.apache.wicket.extensions.markup.html.repeater.tree.TableTree;
import org.apache.wicket.extensions.markup.html.repeater.tree.table.TreeColumn;
import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.ReuseIfModelsEqualStrategy;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.web.component.TabbedPanel;
import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn;
import com.evolveum.midpoint.web.component.data.column.InlineMenuHeaderColumn;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenu;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction;
import com.evolveum.midpoint.web.component.util.SelectableBean;
import com.evolveum.midpoint.web.page.admin.users.component.AbstractTreeTablePanel;
import com.evolveum.midpoint.web.page.admin.users.component.OrgTreeProvider;
import com.evolveum.midpoint.web.page.admin.users.component.SelectableFolderContent;
import com.evolveum.midpoint.web.page.admin.users.dto.TreeStateSet;
import com.evolveum.midpoint.web.security.MidPointAuthWebSession;
import com.evolveum.midpoint.web.session.SessionStorage;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType;
public class OrgTreePanel extends AbstractTreeTablePanel {
private boolean selectable;
private String treeTitleKey = "";
SessionStorage storage;
public OrgTreePanel(String id, IModel<String> rootOid, boolean selectable) {
this(id, rootOid, selectable, "");
}
public OrgTreePanel(String id, IModel<String> rootOid, boolean selectable, String treeTitleKey) {
super(id, rootOid);
MidPointAuthWebSession session = OrgTreePanel.this.getSession();
storage = session.getSessionStorage();
this.treeTitleKey = treeTitleKey;
this.selectable = selectable;
selected = new LoadableModel<SelectableBean<OrgType>>() {
@Override
protected SelectableBean<OrgType> load() {
TabbedPanel currentTabbedPanel = null;
if (getTree().findParent(PageOrgTree.class) != null) {
currentTabbedPanel = getTree().findParent(PageOrgTree.class).getTabPanel().getTabbedPanel();
if (currentTabbedPanel != null) {
int tabId = currentTabbedPanel.getSelectedTab();
int storedTabId = OrgTreePanel.this.getSelectedTabId(getOrgTreeStateStorage());
if (storedTabId != -1
&& tabId != storedTabId) {
OrgTreePanel.this.setSelectedItem(null, getOrgTreeStateStorage());
}
}
}
if (OrgTreePanel.this.getSelectedItem(getOrgTreeStateStorage()) != null) {
return OrgTreePanel.this.getSelectedItem(getOrgTreeStateStorage());
} else {
return getRootFromProvider();
}
}
};
initLayout();
}
public SelectableBean<OrgType> getSelected() {
return selected.getObject();
}
public void setSelected(SelectableBean<OrgType> org) {
selected.setObject(org);
}
public List<OrgType> getSelectedOrgs() {
return ((OrgTreeProvider) getTree().getProvider()).getSelectedObjects();
}
private static final long serialVersionUID = 1L;
private void initLayout() {
WebMarkupContainer treeHeader = new WebMarkupContainer(ID_TREE_HEADER);
treeHeader.setOutputMarkupId(true);
add(treeHeader);
String title = StringUtils.isEmpty(treeTitleKey) ? "TreeTablePanel.hierarchy" : treeTitleKey;
Label treeTitle = new Label(ID_TREE_TITLE, createStringResource(title));
treeHeader.add(treeTitle);
InlineMenu treeMenu = new InlineMenu(ID_TREE_MENU,
new Model<>((Serializable) createTreeMenuInternal()));
treeHeader.add(treeMenu);
ISortableTreeProvider provider = new OrgTreeProvider(this, getModel()) {
@Override
protected List<InlineMenuItem> createInlineMenuItems() {
return createTreeChildrenMenu();
}
};
List<IColumn<SelectableBean<OrgType>, String>> columns = new ArrayList<>();
if (selectable) {
columns.add(new CheckBoxHeaderColumn<SelectableBean<OrgType>>());
}
columns.add(new TreeColumn<SelectableBean<OrgType>, String>(
createStringResource("TreeTablePanel.hierarchy")));
columns.add(new InlineMenuHeaderColumn(createTreeChildrenMenu()));
WebMarkupContainer treeContainer = new WebMarkupContainer(ID_TREE_CONTAINER) {
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
// method computes height based on document.innerHeight() -
// screen height;
Component form = OrgTreePanel.this.getParent().get("memberPanel");
if (form != null) {
response.render(OnDomReadyHeaderItem.forScript(
"updateHeight('" + getMarkupId() + "', ['#" + form.getMarkupId() + "'], ['#"
+ OrgTreePanel.this.get(ID_TREE_HEADER).getMarkupId() + "'])"));
}
}
};
add(treeContainer);
TableTree<SelectableBean<OrgType>, String> tree = new TableTree<SelectableBean<OrgType>, String>(
ID_TREE, columns, provider, Integer.MAX_VALUE, new TreeStateModel(this, provider){
@Override
public Set<SelectableBean<OrgType>> getExpandedItems(){
return OrgTreePanel.this.getExpandedItems(getOrgTreeStateStorage());
}
@Override
public SelectableBean<OrgType> getCollapsedItem(){
return OrgTreePanel.this.getCollapsedItem(getOrgTreeStateStorage());
}
@Override
public void setCollapsedItem(SelectableBean<OrgType> item){
OrgTreePanel.this.setCollapsedItem(null, getOrgTreeStateStorage());
}
}) {
@Override
protected Component newContentComponent(String id, IModel<SelectableBean<OrgType>> model) {
return new SelectableFolderContent(id, this, model, selected) {
@Override
protected void onClick(AjaxRequestTarget target) {
super.onClick(target);
OrgTreePanel.this.setSelectedItem(selected.getObject(), getOrgTreeStateStorage());
selectTreeItemPerformed(selected.getObject(), target);
}
};
}
@Override
protected Item<SelectableBean<OrgType>> newRowItem(String id, int index,
final IModel<SelectableBean<OrgType>> model) {
Item<SelectableBean<OrgType>> item = super.newRowItem(id, index, model);
item.add(AttributeModifier.append("class", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
SelectableBean<OrgType> itemObject = model.getObject();
if (itemObject != null && itemObject.equals(selected.getObject())) {
return "success";
}
return null;
}
}));
return item;
}
@Override
public void collapse(SelectableBean<OrgType> collapsedItem) {
super.collapse(collapsedItem);
Set<SelectableBean<OrgType>> items = OrgTreePanel.this.getExpandedItems(getOrgTreeStateStorage());
if (items != null && items.contains(collapsedItem)) {
items.remove(collapsedItem);
}
OrgTreePanel.this.setExpandedItems((TreeStateSet) items, getOrgTreeStateStorage());
OrgTreePanel.this.setCollapsedItem(collapsedItem, getOrgTreeStateStorage());
}
@Override
protected void onModelChanged() {
super.onModelChanged();
TreeStateSet<SelectableBean<OrgType>> items = (TreeStateSet) getModelObject();
if (!items.isInverse()) {
OrgTreePanel.this.setExpandedItems(items, getOrgTreeStateStorage());
}
}
};
tree.setItemReuseStrategy(new ReuseIfModelsEqualStrategy());
tree.getTable().add(AttributeModifier.replace("class", "table table-striped table-condensed"));
tree.add(new WindowsTheme());
// tree.add(AttributeModifier.replace("class", "tree-midpoint"));
treeContainer.add(tree);
}
private static class TreeStateModel extends AbstractReadOnlyModel<Set<SelectableBean<OrgType>>> {
private TreeStateSet<SelectableBean<OrgType>> set = new TreeStateSet<SelectableBean<OrgType>>();
private ISortableTreeProvider provider;
private OrgTreePanel panel;
TreeStateModel(OrgTreePanel panel, ISortableTreeProvider provider) {
this.panel = panel;
this.provider = provider;
}
@Override
public Set<SelectableBean<OrgType>> getObject() {
Set<SelectableBean<OrgType>> dtos = TreeStateModel.this.getExpandedItems();
SelectableBean<OrgType> collapsedItem = TreeStateModel.this.getCollapsedItem();
Iterator<SelectableBean<OrgType>> iterator = provider.getRoots();
if (collapsedItem != null) {
if (set.contains(collapsedItem)) {
set.remove(collapsedItem);
TreeStateModel.this.setCollapsedItem(null);
}
}
if (dtos != null && (dtos instanceof TreeStateSet)) {
for (SelectableBean<OrgType> orgTreeDto : dtos) {
if (!set.contains(orgTreeDto)) {
set.add(orgTreeDto);
}
}
}
// just to have root expanded at all time
if (iterator.hasNext()) {
SelectableBean<OrgType> root = iterator.next();
if (set.isEmpty() || !set.contains(root)) {
set.add(root);
}
}
return set;
}
public void expandAll() {
set.expandAll();
}
public void collapseAll() {
set.collapseAll();
}
public Set<SelectableBean<OrgType>> getExpandedItems(){
MidPointAuthWebSession session = panel.getSession();
SessionStorage storage = session.getSessionStorage();
return storage.getUsers().getExpandedItems();
}
public SelectableBean<OrgType> getCollapsedItem(){
MidPointAuthWebSession session = panel.getSession();
SessionStorage storage = session.getSessionStorage();
return storage.getUsers().getCollapsedItem();
}
public void setCollapsedItem(SelectableBean<OrgType> item){
MidPointAuthWebSession session = panel.getSession();
SessionStorage storage = session.getSessionStorage();
storage.getUsers().setCollapsedItem(item);
}
}
private List<InlineMenuItem> createTreeMenuInternal() {
List<InlineMenuItem> items = new ArrayList<>();
InlineMenuItem item = new InlineMenuItem(createStringResource("TreeTablePanel.collapseAll"),
new InlineMenuItemAction() {
@Override
public void onClick(AjaxRequestTarget target) {
collapseAllPerformed(target);
}
});
items.add(item);
item = new InlineMenuItem(createStringResource("TreeTablePanel.expandAll"),
new InlineMenuItemAction() {
@Override
public void onClick(AjaxRequestTarget target) {
expandAllPerformed(target);
}
});
items.add(item);
List<InlineMenuItem> additionalActions = createTreeMenu();
if (additionalActions != null) {
items.addAll(additionalActions);
}
return items;
}
protected List<InlineMenuItem> createTreeMenu() {
return null;
}
protected List<InlineMenuItem> createTreeChildrenMenu() {
return new ArrayList<>();
}
protected void selectTreeItemPerformed(SelectableBean<OrgType> selected, AjaxRequestTarget target) {
}
private void collapseAllPerformed(AjaxRequestTarget target) {
TableTree<SelectableBean<OrgType>, String> tree = getTree();
TreeStateModel model = (TreeStateModel) tree.getDefaultModel();
model.collapseAll();
target.add(tree);
}
private void expandAllPerformed(AjaxRequestTarget target) {
TableTree<SelectableBean<OrgType>, String> tree = getTree();
TreeStateModel model = (TreeStateModel) tree.getDefaultModel();
model.expandAll();
target.add(tree);
}
public Set<SelectableBean<OrgType>> getExpandedItems(OrgTreeStateStorage storage){
return storage.getExpandedItems();
}
public void setExpandedItems(TreeStateSet items, OrgTreeStateStorage storage){
storage.setExpandedItems(items);
}
public SelectableBean<OrgType> getCollapsedItem(OrgTreeStateStorage storage){
return storage.getCollapsedItem();
}
public void setCollapsedItem(SelectableBean<OrgType> item, OrgTreeStateStorage storage){
storage.setCollapsedItem(item);
}
public void setSelectedItem(SelectableBean<OrgType> item, OrgTreeStateStorage storage){
storage.setSelectedItem(item);
}
public SelectableBean<OrgType> getSelectedItem(OrgTreeStateStorage storage){
return storage.getSelectedItem();
}
protected OrgTreeStateStorage getOrgTreeStateStorage(){
return storage.getUsers();
}
public int getSelectedTabId(OrgTreeStateStorage storage){
return storage.getSelectedTabId();
}
}