/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.ui.gwt.desktop.client.widget.multi;
import java.util.ArrayList;
import java.util.List;
import org.onecmdb.ui.gwt.desktop.client.fixes.combo.AdaptableMenu;
import org.onecmdb.ui.gwt.desktop.client.mvc.CMDBEvents;
import org.onecmdb.ui.gwt.desktop.client.service.model.CIModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.CMDBPermissions;
import org.onecmdb.ui.gwt.desktop.client.service.model.ValueListModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.ValueModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.grid.AttributeColumnConfig;
import org.onecmdb.ui.gwt.desktop.client.service.model.grid.CIModelCollection;
import org.onecmdb.ui.gwt.desktop.client.utils.EditorFactory;
import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ComponentPlugin;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.Window.CloseAction;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.CheckColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.RowNumberer;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
public class MultiValueGrid extends LayoutContainer {
private ValueListModel values;
private ListStore<ValueModel> store;
private EditorGrid<ValueModel> grid;
private List<ValueModel> newValues;
private AttributeColumnConfig config;
private CMDBPermissions permissions;
private boolean cancel;
public MultiValueGrid(AttributeColumnConfig config) {
this.config = config;
setSize(340, 400);
}
public void setValue(ValueListModel model) {
if (model != null) {
this.values = model.copy();
} else {
this.values = new ValueListModel();
this.values.setIsComplex(config.isComplex());
}
updateStore();
}
public CMDBPermissions getPermissions() {
return permissions;
}
public void setPermissions(CMDBPermissions permissions) {
this.permissions = permissions;
}
protected void updateStore() {
if (store != null) {
store.commitChanges();
store.removeAll();
if (this.values != null) {
List<ValueModel> list = this.values.getValues();
for (ValueModel vModel : list) {
vModel.set("delete", false);
}
if (list.size() > 0) {
store.add(list);
}
}
}
if (grid != null) {
grid.getView().refresh(true);
}
}
public ValueListModel getValue() {
return(this.values);
}
@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
initUI();
}
private void initUI() {
setLayout(new FitLayout());
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
newValues = new ArrayList<ValueModel>();
/*
*/
configs.add(new RowNumberer());
if (!isReadonly()) {
CheckColumnConfig checkColumn = new CheckColumnConfig("delete", "Delete", 50);
configs.add(checkColumn);
}
ColumnConfig column = EditorFactory.getColumnConfig(config, true, permissions);
column.addListener(CMDBEvents.POPUP_HIDE_EVENT, new Listener<BaseEvent>() {
public void handleEvent(BaseEvent be) {
fireEvent(CMDBEvents.POPUP_HIDE_EVENT);
}
});
column.setId("this");
//column.setWidth(100);
//column.setEditor(new CellEditor());
/*
column.setRenderer(new GridCellRenderer<ValueModel>() {
public String render(ValueModel model, String property,
ColumnData config, int rowIndex, int colIndex,
ListStore<ValueModel> store) {
String text = model.getValue();
if (model.isComplex()) {
text = model.getValueDisplayName();
if (model.getValue() != null) {
String url = model.get(CIModel.CI_ICON_PATH);
if (url != null) {
url = CMDBSession.get().getContentRepositoryURL() + "/" + url;
text = "<a style='background-image:url(" + url + ");background-repeat: no-repeat; background-position: left center; font-size:16px;'>   </a>" + text;
}
}
}
return(text);
}
});
*/
//configs.add(new RowNumberer());
/*
valueColumn.setId("value");
valueColumn.setHeader("Value");
valueColumn.setWidth(200);
*/
configs.add(column);
ColumnModel cm = new ColumnModel(configs);
store = new ListStore<ValueModel>();
store.setMonitorChanges(true);
updateStore();
grid = new EditorGrid<ValueModel>(store, cm);
for (ColumnConfig cfg : configs) {
if (cfg instanceof ComponentPlugin) {
grid.addPlugin((ComponentPlugin)cfg);
}
}
grid.setBorders(true);
//grid.setAutoExpandColumn("this");
ContentPanel cp = new ContentPanel();
cp.setLayout(new FitLayout());
cp.setLayoutOnChange(true);
if (!isReadonly()) {
cp.setTopComponent(getTopToolBar());
}
cp.add(grid);
cp.setHeading("Select " + config.getType() + "s");
//cp.setHeaderVisible(false);
add(cp);
layout();
}
private boolean isReadonly() {
return(permissions.getCurrentState().equals(CMDBPermissions.PermissionState.READONLY));
}
private void addValues(List objects) throws Exception {
for (Object o : objects) {
CIModel ci = null;
ValueModel vModel = null;
if (o instanceof ValueModel) {
vModel = (ValueModel)o;
}
if (o instanceof CIModelCollection) {
CIModelCollection col = (CIModelCollection)o;
o = col.getCIModel("offspring");
}
if (o instanceof CIModel) {
ci = (CIModel)o;
// Check if existsing ...
boolean exists = false;
for (ValueModel availValue : store.getModels()) {
if (ci.getAlias().equals(availValue.getValue())) {
exists = true;
break;
}
}
if (exists) {
continue;
}
vModel = new ValueModel();
vModel.setAlias(values.getAlias());
vModel.setIsComplex(true);
vModel.setValue(ci.getAlias());
vModel.setValueDisplayName(ci.getDisplayName());
vModel.set(CIModel.CI_ICON_PATH, ci.get(CIModel.CI_ICON_PATH));
vModel.set("delete", false);
}
if (vModel == null) {
continue;
}
if (this.config.getMaxOccurs() > 0) {
if (store.getCount() >= this.config.getMaxOccurs()) {
throw new Exception("Attribute only allows " + this.config.getMaxOccurs() + " values");
}
}
newValues.add(vModel);
grid.stopEditing();
store.insert(vModel, 0);
}
grid.getView().refresh(false);
}
private ToolBar getTopToolBar() {
ToolBar bar = new ToolBar();
TextToolItem addAttribute = new TextToolItem("Add", "add-icon");
addAttribute.addSelectionListener(getAddValueSelection());
addAttribute.setToolTip("Add a new value");
bar.add(addAttribute);
if (this.config.isComplex()) {
TextToolItem selectValues = new TextToolItem("Select", "select-icon");
selectValues.setMenu(getSelectMenu());
//selectValues.addSelectionListener(getSelectValueSelection());
selectValues.setToolTip("Select multiple values");
bar.add(selectValues);
}
new SeparatorToolItem();
/*
TextToolItem removeAttribute = new TextToolItem("Remove", "delete-icon");
removeAttribute.addSelectionListener(getRemoveSelection());
removeAttribute.setToolTip("Remove checkd values.");
bar.add(removeAttribute);
new SeparatorToolItem();
*/
/*
TextToolItem restore = new TextToolItem("Undo", "restore-icon");
restore.addSelectionListener(getUndoSelection());
restore.setToolTip("Undo");
bar.add(restore);
*/
bar.add(new FillToolItem());
TextToolItem save = new TextToolItem("Ok", "commit-icon");
save.addSelectionListener(getOkSelection());
save.setToolTip("Ok");
bar.add(save);
TextToolItem cancel = new TextToolItem("Cancel", "cancel-icon");
cancel.addSelectionListener(getCancelSelection());
cancel.setToolTip("Close");
bar.add(cancel);
return(bar);
}
private SelectionListener getCancelSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
cancel = true;
fireEvent(Events.Select, new ComponentEvent(MultiValueGrid.this));
//fireEvent(Events.Hide, new ComponentEvent(MultiValueGrid.this));
}
});
}
private SelectionListener getOkSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
List<ValueModel> removeValues = store.findModels("delete", true);
for (ValueModel removeValue : removeValues) {
newValues.remove(removeValue);
if (config.isEditTemplate()) {
if (values.getValues().size() == 1) {
MessageBox.alert("Not allowed", "On template one attribute must exists!", new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
cancel = true;
fireEvent(Events.Select, new ComponentEvent(MultiValueGrid.this));
return;
}
});
return;
}
}
values.removeValue(removeValue);
}
store.commitChanges();
// Add all new values.
for (ValueModel vModel : newValues) {
values.addValue(vModel);
}
fireEvent(Events.Select, new ComponentEvent(MultiValueGrid.this));
}
});
}
private SelectionListener getSelectValueSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
final Window w = new Window();
w.setCloseAction(CloseAction.CLOSE);
w.setMinimizable(false);
w.setMaximizable(true);
w.setIconStyle("accordion");
//w.setHeading();
w.setWidth(600);
w.setHeight(400);
w.setLayout(new FitLayout());
SelectionMode selMod = SelectionMode.MULTI;
CIModel type = new CIModel();
type.setAlias(config.getType());
type.setTemplate(true);
final MultiSelectCI select = new MultiSelectCI(config.getMDR(), type, selMod, null, permissions);
ContentPanel cp = new ContentPanel();
cp.setLayout(new FillLayout());
cp.setHeading("Select " + config.getType() + "s");
cp.add(select);
Button cancelButton = new Button("Cancel");
cancelButton.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
w.setVisible(false);
}
});
Button selectButton = new Button("Select");
selectButton.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
w.setVisible(false);
List objects = select.getSelection();
try {
addValues(objects);
} catch (Exception e) {
MessageBox.alert("Can't add values", e.getMessage(), null);
}
}
});
cp.addButton(selectButton);
cp.addButton(cancelButton);
w.add(cp);
w.setVisible(true);
}
});
}
private Menu getSelectMenu() {
SelectionMode selMod = SelectionMode.MULTI;
CIModel type = new CIModel();
type.setAlias(config.getType());
type.setTemplate(true);
final MultiSelectCI select = new MultiSelectCI(config.getMDR(), type, selMod, getValue(), permissions);
ContentPanel cp = new ContentPanel();
cp.setLayout(new FillLayout());
cp.setHeading("Select 1.." + config.getMaxOccurs() + " " + config.getType() + "s");
cp.add(select);
final AdaptableMenu menu = new AdaptableMenu(cp, "select-icon");
TextToolItem cancelItem = new TextToolItem("Cancel", "cancel-icon");
cancelItem.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
menu.hide();
}
});
TextToolItem selectItem = new TextToolItem("Select", "select-icon");
selectItem.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
List objects = select.getSelection();
menu.hide();
try {
addValues(objects);
} catch (Exception e) {
MessageBox.alert("Can't add values", e.getMessage(), null);
}
}
});
ToolBar bar = new ToolBar();
bar.add(new FillToolItem());
bar.add(selectItem);
bar.add(cancelItem);
cp.setTopComponent(bar);
return(menu);
}
private SelectionListener getUndoSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
// Check all
for (ValueModel newValue : newValues) {
store.remove(newValue);
}
grid.getView().refresh(false);
store.rejectChanges();
}
});
}
private SelectionListener getRemoveSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
// Check all
List<ValueModel> values = store.findModels("delete", true);
for (ValueModel value : values) {
store.remove(value);
}
grid.getView().refresh(false);
}
});
}
private SelectionListener getAddValueSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
ValueModel newValue = new ValueModel();
newValue.setAlias(values.getAlias());
newValue.setIsComplex(values.isComplex());
newValue.setValueDisplayName("");
newValue.set("delete", false);
List<ValueModel> addValues = new ArrayList<ValueModel>();
addValues.add(newValue);
try {
addValues(addValues);
} catch (Exception e) {
e.printStackTrace();
Info.display("MaxOccurs Limit", "Attribute " + config.getName() + " max allows " + config.getMaxOccurs() + " values");
//MessageBox.alert("Can't add values", e.getMessage(), null);
}
/*
newValues.add(newValue);
grid.stopEditing();
store.insert(newValue, 0);
grid.getView().refresh(false);
grid.startEditing(0, 2);
*/
}
});
}
/**
* Called when opened.
*/
public void onOpen() {
if (newValues != null) {
newValues.clear();
}
this.values = null;
cancel = false;
}
public boolean isCancel() {
return(cancel);
}
}