package org.sigmah.client.ui.widget.orgunit;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.client.ui.res.icon.orgunit.OrgUnitImageBundle;
import org.sigmah.client.ui.widget.HasTreeGrid;
import org.sigmah.client.ui.widget.form.Forms;
import org.sigmah.client.util.TreeGridCheckboxSelectionModel;
import org.sigmah.shared.dto.country.CountryDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.SortInfo;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters;
import com.extjs.gxt.ui.client.widget.grid.filters.StringFilter;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
/**
* <p>
* Widget representing the organizational chart (tree) of an org unit.
* </p>
* <p>
* To handle component events, see {@link #setTreeGridEventHandler(TreeGridEventHandler)}.
* </p>
*
* @author tmi
* @author Denis Colliot (dcolliot@ideia.fr)
*/
public class OrgUnitTreeGrid implements HasTreeGrid<OrgUnitDTO> {
// CSS style names.
private static final String STYLE_FLEXIBILITY_ACTION = "flexibility-action";
/**
* The tree grid.
*/
private final TreeGrid<OrgUnitDTO> tree;
/**
* The actions toolbar.
*/
private final ToolBar toolbar;
/**
* The grid events handler implementation.
*/
private HasTreeGrid.TreeGridEventHandler<OrgUnitDTO> eventsHandler;
/**
* The selection model (can be {@code null} if the tree doesn't manage a selection model).
*/
private TreeGridCheckboxSelectionModel<OrgUnitDTO> selectionModel;
private final CheckBox displayOnlyMainOrgUnitCheckbox;
/**
* Initializes a new {@code OrgUnitTreeGrid} widget.
*
* @param hasSelectionModel
* {@code true} if the tree grid widget manages a selection model, {@code false} if it does not.
*/
public OrgUnitTreeGrid(final boolean hasSelectionModel) {
// --
// Creates columns.
// --
final List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
// Name column.
final ColumnConfig nameColumn = new ColumnConfig();
nameColumn.setId(OrgUnitDTO.NAME);
nameColumn.setHeaderText(I18N.CONSTANTS.projectName());
nameColumn.setRenderer(new TreeGridCellRenderer<OrgUnitDTO>());
nameColumn.setWidth(150);
// Full Name column.
final ColumnConfig fullNameColumn = new ColumnConfig();
fullNameColumn.setId(OrgUnitDTO.FULL_NAME);
fullNameColumn.setHeaderText(I18N.CONSTANTS.projectFullName());
fullNameColumn.setWidth(250);
fullNameColumn.setRenderer(new GridCellRenderer<OrgUnitDTO>() {
@Override
public Object render(final OrgUnitDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<OrgUnitDTO> store, final Grid<OrgUnitDTO> grid) {
final com.google.gwt.user.client.ui.Label visitButton = new com.google.gwt.user.client.ui.Label((String) model.get(property));
visitButton.addStyleName(STYLE_FLEXIBILITY_ACTION);
visitButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
if (eventsHandler != null) {
eventsHandler.onRowClickEvent(model);
}
}
});
return visitButton;
}
});
// Country column.
final ColumnConfig countryColumn = new ColumnConfig();
countryColumn.setId(OrgUnitDTO.OFFICE_LOCATION_COUNTRY);
countryColumn.setHeaderText(I18N.CONSTANTS.projectCountry());
countryColumn.setWidth(100);
countryColumn.setRenderer(new GridCellRenderer<OrgUnitDTO>() {
@Override
public Object render(final OrgUnitDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<OrgUnitDTO> store, final Grid<OrgUnitDTO> grid) {
final CountryDTO country = (CountryDTO) model.get(property);
return CountryDTO.toString(country);
}
});
// Adds columns.
if (hasSelectionModel) {
// Tree selection model
selectionModel = new TreeGridCheckboxSelectionModel<OrgUnitDTO>();
columns.add(selectionModel.getColumn());
}
columns.add(nameColumn);
columns.add(fullNameColumn);
columns.add(countryColumn);
// --
// Tree store.
// --
final TreeStore<OrgUnitDTO> store = new TreeStore<OrgUnitDTO>();
store.setSortInfo(new SortInfo(OrgUnitDTO.NAME, SortDir.ASC));
store.setStoreSorter(new StoreSorter<OrgUnitDTO>() {
@Override
public int compare(final Store<OrgUnitDTO> store, final OrgUnitDTO m1, final OrgUnitDTO m2, final String property) {
if (OrgUnitDTO.OFFICE_LOCATION_COUNTRY.equals(property)) {
return ((CountryDTO) m1.get(property)).getName().compareToIgnoreCase(((CountryDTO) m2.get(property)).getName());
} else {
return super.compare(store, m1, m2, property);
}
}
});
// --
// Tree grid.
// --
tree = new TreeGrid<OrgUnitDTO>(store, new ColumnModel(columns));
tree.setBorders(true);
tree.getStyle().setLeafIcon(OrgUnitImageBundle.ICONS.orgUnitSmall());
tree.getStyle().setNodeCloseIcon(OrgUnitImageBundle.ICONS.orgUnitSmall());
tree.getStyle().setNodeOpenIcon(OrgUnitImageBundle.ICONS.orgUnitSmallTransparent());
tree.setTrackMouseOver(false);
tree.addPlugin(createOrgUnitFilters());
if (hasSelectionModel) {
tree.setSelectionModel(selectionModel);
tree.addPlugin(selectionModel);
}
// --
// Expand all button.
// --
final Button expandButton = new Button(I18N.CONSTANTS.expandAll(), IconImageBundle.ICONS.expand(), new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent ce) {
tree.expandAll();
}
});
// --
// Collapse all button.
// --
final Button collapseButton = new Button(I18N.CONSTANTS.collapseAll(), IconImageBundle.ICONS.collapse(), new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent ce) {
tree.collapseAll();
}
});
// --
// Toolbar.
// --
toolbar = new ToolBar();
toolbar.setAlignment(HorizontalAlignment.LEFT);
toolbar.add(expandButton);
toolbar.add(collapseButton);
displayOnlyMainOrgUnitCheckbox = Forms.checkbox(I18N.CONSTANTS.dashboardOnlyMainOrgUnitCheckboxLabel());
toolbar.add(displayOnlyMainOrgUnitCheckbox);
}
/**
* Creates filters for OrgUnits tree grid widget.
*
* @return The {@link GridFilters} instance.
*/
private static GridFilters createOrgUnitFilters() {
final GridFilters filters = new GridFilters();
filters.setLocal(true);
// Data index of each filter should be identical with column id in ColumnModel of TreeGrid
filters.addFilter(new StringFilter(OrgUnitDTO.NAME));
filters.addFilter(new StringFilter(OrgUnitDTO.FULL_NAME));
filters.addFilter(new StringFilter(OrgUnitDTO.OFFICE_LOCATION_COUNTRY) {
@Override
@SuppressWarnings("unchecked")
protected <X> X getModelValue(final ModelData model) {
final CountryDTO country = (CountryDTO) super.getModelValue(model);
return (X) CountryDTO.toString(country);
}
});
return filters;
}
/**
* {@inheritDoc}
*/
@Override
public TreeGrid<OrgUnitDTO> getTreeGrid() {
return tree;
}
/**
* {@inheritDoc}
*/
@Override
public TreeStore<OrgUnitDTO> getStore() {
return tree.getTreeStore();
}
/**
* {@inheritDoc}
*/
@Override
public void setTreeGridEventHandler(final HasTreeGrid.TreeGridEventHandler<OrgUnitDTO> handler) {
this.eventsHandler = handler;
}
public ToolBar getToolbar() {
return toolbar;
}
public void addToolbarButton(final Button button) {
if (button == null) {
return;
}
toolbar.add(new SeparatorToolItem());
toolbar.add(button);
}
public CheckBox getDisplayOnlyMainOrgUnitCheckbox() {
return displayOnlyMainOrgUnitCheckbox;
}
}