/*
* 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.tree;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.onecmdb.ui.gwt.desktop.client.WindowFactory;
import org.onecmdb.ui.gwt.desktop.client.fixes.combo.IValueComponent;
import org.onecmdb.ui.gwt.desktop.client.service.CMDBAsyncCallback;
import org.onecmdb.ui.gwt.desktop.client.service.content.Config;
import org.onecmdb.ui.gwt.desktop.client.service.content.ContentData;
import org.onecmdb.ui.gwt.desktop.client.service.model.CIModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.CMDBSession;
import org.onecmdb.ui.gwt.desktop.client.service.model.ModelItem;
import org.onecmdb.ui.gwt.desktop.client.service.model.ModelServiceFactory;
import org.onecmdb.ui.gwt.desktop.client.service.model.StoreResult;
import org.onecmdb.ui.gwt.desktop.client.service.model.TestModelData;
import org.onecmdb.ui.gwt.desktop.client.widget.ExceptionErrorDialog;
import org.onecmdb.ui.gwt.desktop.client.widget.grid.AttributeGrid;
import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.binder.TreeBinder;
import com.extjs.gxt.ui.client.data.BaseModelStringProvider;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelStringProvider;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.data.TreeLoader;
import com.extjs.gxt.ui.client.dnd.Insert;
import com.extjs.gxt.ui.client.dnd.TreeDropTarget;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.DNDEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.LoadListener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.TreeEvent;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.store.StoreEvent;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.Dialog;
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.button.Button;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.extjs.gxt.ui.client.widget.tree.Tree;
import com.extjs.gxt.ui.client.widget.tree.TreeItem;
import com.extjs.gxt.ui.client.widget.tree.TreeSelectionModel;
import com.extjs.gxt.ui.client.widget.tree.Tree.CheckCascade;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sun.tools.xjc.api.Reference;
public class CITemplateBrowser extends LayoutContainer implements IValueComponent<CIModel> {
private BaseTreeLoader loader;
private Listener<TreeEvent> selectionListener;
private Tree tree;
private boolean checkable;
private ContentData mdr;
private Listener<BaseEvent> checkListener;
private List<String> roots;
private boolean readonly;
protected HashMap<CIModel, List<ModelItem>> moveTable;
private TreeBinder<CIModel> binder;
private TreeSelectionModel selectionModel;
private TreeStore<CIModel> store;
public CITemplateBrowser(ContentData mdr, List<String> roots) {
this.mdr = mdr;
this.roots = roots;
}
/**
* Call this to enable move function.
*
* @param table
*/
public void setMoveTable(HashMap<CIModel, List<ModelItem>> table) {
this.moveTable = table;
}
public boolean isCheckable() {
return checkable;
}
public void setCheckable(boolean checkable, Listener<BaseEvent> listener) {
this.checkable = checkable;
this.checkListener = listener;
}
@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
init();
getLoader().load();
}
private BaseTreeLoader getLoader() {
return(loader);
}
public void init() {
setLayout(new FitLayout());
setLayoutOnChange(true);
setScrollMode(Scroll.AUTO);
// data proxy
RpcProxy<CIModel, List<CIModel>> proxy = new RpcProxy<CIModel, List<CIModel>>() {
@Override
protected void load(CIModel parent, final AsyncCallback<List<CIModel>> callback){// TODO Auto-generated method stub
ModelServiceFactory.get().getTemplateChildren(CMDBSession.get().getToken(), mdr, parent, roots, new CMDBAsyncCallback<List<CIModel>>() {
@Override
public void onSuccess(List<CIModel> arg0) {
// TODO Auto-generated method stub
callback.onSuccess(arg0);
}
});
}
};
// tree loader
loader = new BaseTreeLoader(proxy) {
@Override
public boolean hasChildren(ModelData parent) {
if (parent instanceof CIModel) {
int templateCount = (Integer)((CIModel)parent).get(CIModel.CI_TEMPLATE_CHILD_COUNT);
return(templateCount > 0);
}
return(true);
}
};
// trees store
store = new TreeStore<CIModel>(loader);
store.setMonitorChanges(true);
store.setStoreSorter(new StoreSorter<CIModel>() {
@Override
public int compare(Store<CIModel> store, CIModel m1,
CIModel m2, String property) {
// TODO Auto-generated method stub
return super.compare(store, m1, m2, property);
}
});
tree = new Tree();
if (checkable) {
tree.setCheckStyle(CheckCascade.NONE);
selectionModel = new TreeSelectionModel(SelectionMode.SINGLE);
tree.setSelectionModel(selectionModel);
tree.setCheckable(true);
if (checkListener != null) {
tree.addListener(Events.CheckChange, checkListener);
}
}
Menu contextMenu = getTemplateContextMenu(tree);
if (contextMenu != null) {
tree.setContextMenu(contextMenu);
}
binder = new TreeBinder<CIModel>(tree, store);
binder.setCaching(false);
//binder.setMask(true);
store.addListener(Store.Update, new Listener<StoreEvent>() {
public void handleEvent(StoreEvent be) {
ModelData data = be.model;
if (data instanceof CIModel) {
boolean update = ((CIModel)data).get("reloadFlag", false);
if (update) {
refreshTree();
/*
// Calculate items to reload...
for (CIModel m : moveTable.keySet()) {
loader.loadChildren(m);
}
*/
//moveTable.keySet();
}
}
}
});
binder.setStringProvider(new BaseModelStringProvider<CIModel>() {
@Override
public String getStringValue(CIModel model, String property) {
if (CIModel.CI_ALIAS.equals(property)) {
String text = model.getProperty(property);
Object decorate = CMDBSession.get().getConfig().get(Config.DECORATE_TEMPLATE_COUNT);
if (decorate != null && decorate.toString().equals("true")) {
int instanceCount = (Integer)model.getProperty(model.CI_INSTANCE_CHILD_COUNT);
int totalInstanceCount = (Integer)model.getProperty(model.CI_TOTAL_INSTANCE_COUNT);
text += "<a style='color:blue; font-size:smaller;'>[" + instanceCount + "/" + totalInstanceCount + "]</a>";
}
if (moveTable != null) {
List<ModelItem> items = moveTable.get(model);
if (items != null) {
text = text + "<a style='color:green; font-size:smaller;'>(" + items.size() + ")</a>";
}
}
return(text);
}
return((Object)model.getProperty(property) == null ? "" : ((Object)model.getProperty(property)).toString());
}
});
binder.setIconProvider(new ModelStringProvider<CIModel>() {
public String getStringValue(CIModel model, String property) {
String icon = model.get(model.CI_ICON_PATH);
if (icon != null) {
return(CMDBSession.get().getContentRepositoryURL() + "/" + icon);
}
return(null);
}
});
binder.setDisplayProperty(CIModel.CI_ALIAS);
if (getSelectionListener() != null) {
tree.addListener(Events.SelectionChange, getSelectionListener());
}
add(tree);
new TreeDropTarget(binder) {
TreeItem currentItem = null;
@Override
protected void showFeedback(DNDEvent event) {
final TreeItem item = tree.findItem(event.getTarget());
if (item == null || moveTable == null) {
event.status.setStatus(false);
return;
}
currentItem = item;
handleAppend(event, item);
}
@Override
protected void onDragLeave(DNDEvent e) {
super.onDragLeave(e);
currentItem = null;
}
@Override
protected void onDragDrop(DNDEvent event) {
component.enableEvents(true);
Insert.get().hide();
if (currentItem != null && moveTable != null) {
currentItem.el().firstChild().removeStyleName("my-tree-drop");
CIModel model = (CIModel) currentItem.getModel();
List<ModelItem> items = moveTable.get(model);
if (items == null) {
items = new ArrayList<ModelItem>();
moveTable.put(model, items);
}
if (event.data instanceof List) {
for (Object o : (List)event.data) {
if (o instanceof ModelItem) {
items.add((ModelItem)o);
}
}
} else if (event.data instanceof ModelData) {
items.add((ModelItem)event.data);
}
// Update Item....
boolean b = model.get("updateFlag", false);
model.set("updateFlag", !b);
//currentItem.recalculate()
}
}
};
layout();
}
protected void refreshTree() {
}
public void setSelected(CIModel model) {
if (model == null || binder == null || tree == null) {
return;
}
TreeItem item = (TreeItem) binder.findItem(model);
if (item != null) {
tree.setSelectedItem(item);
}
}
private Menu getTemplateContextMenu(final Tree tree) {
Menu contextMenu = new Menu();
contextMenu.setWidth(130);
/*
if (!this.readonly) {
MenuItem insert = new MenuItem();
insert.setText("New Template");
insert.setIconStyle("add-icon");
insert.addSelectionListener(new SelectionListener<MenuEvent>() {
public void componentSelected(MenuEvent ce) {
TreeItem item = (TreeItem)tree.getSelectionModel().getSelectedItem();
// Add new template dialog
final CIModel model = (CIModel) item.getModel();
// InputDialog for new AliasName.
final MessageBox box = MessageBox.prompt("Name", "Please enter template alias:");
box.addCallback(new Listener<MessageBoxEvent>() {
public void handleEvent(MessageBoxEvent be) {
//be.buttonClicked.
if (be.value == null || be.value.length() == 0) {
return;
}
// Create new template.
CIModel newTemplate = new CIModel();
newTemplate.setAlias(be.value);
newTemplate.setDerivedFrom(model.getAlias());
newTemplate.setTemplate(true);
List<CIModel> base = new ArrayList<CIModel>();
List<CIModel> local = new ArrayList<CIModel>();
local.add(newTemplate);
// Call create.
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
ExceptionErrorDialog.showError("Can't Create", caught);
//loader.load();
}
public void onSuccess(StoreResult result) {
if (result.isRejected()) {
MessageBox.alert("Create Failed", result.getRejectCause(), null);
return;
}
// TODO: Check errors on storeResult...
getLoader().loadChildren(model);
}
});
}
});
}
});
contextMenu.add(insert);
MenuItem delete = new MenuItem();
delete.setText("Delete Template");
delete.setIconStyle("delete-icon");
delete.addSelectionListener(new SelectionListener<MenuEvent>() {
public void componentSelected(MenuEvent ce) {
TreeItem item = (TreeItem)tree.getSelectionModel().getSelectedItem();
// Add new template dialog
final CIModel model = (CIModel) item.getModel();
final TreeItem parentItem = item.getParentItem();
if (parentItem == null || parentItem.getParentItem() == null) {
MessageBox.alert("Info", "Not allowed to delete Root CI's", null);
return;
}
final MessageBox box = MessageBox.confirm("Delete " + model.getNameAndIcon(), "Are you sure ?", new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
Dialog dialog = (Dialog) be.component;
Button btn = dialog.getButtonPressed();
if (!btn.getItemId().equals(Dialog.YES)) {
return;
}
List<CIModel> base = new ArrayList<CIModel>();
List<CIModel> local = new ArrayList<CIModel>();
base.add(model);
// Call create.
final MessageBox deleteInfo = MessageBox.wait("Progress",
"Delete, please wait...", "Deleting...");
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
deleteInfo.close();
ExceptionErrorDialog.showError("Can't Delete", caught);
//loader.load();
}
public void onSuccess(StoreResult result) {
deleteInfo.close();
if (result.isRejected()) {
MessageBox.alert("Delete Failed", result.getRejectCause(), null);
return;
}
// TODO: Check errors on storeResult...
getLoader().loadChildren(parentItem.getModel());
}
});
}
});
}
});
contextMenu.add(delete);
contextMenu.add(new SeparatorMenuItem());
}
*/
MenuItem refresh = new MenuItem();
refresh.setText("Refresh");
refresh.setIconStyle("refresh-icon");
refresh.addSelectionListener(new SelectionListener<MenuEvent>() {
public void componentSelected(MenuEvent ce) {
TreeItem item = (TreeItem)tree.getSelectionModel().getSelectedItem();
if (item != null) {
getLoader().loadChildren(item.getModel());
}
}
});
contextMenu.add(refresh);
return(contextMenu);
}
public void reload() {
TreeItem item = (TreeItem)tree.getSelectionModel().getSelectedItem();
if (item != null) {
TreeItem parent = item.getParentItem();
if (parent != null) {
getLoader().loadChildren(parent.getModel());
}
}
}
public TreeItem getSelected() {
if (tree == null) {
return(null);
}
return(tree.getSelectedItem());
}
private Listener<TreeEvent> getSelectionListener() {
return(this.selectionListener);
}
public void setSelectionListsner(Listener<TreeEvent> listener) {
this.selectionListener = listener;
}
public void setReadonly(boolean value) {
this.readonly = value;
}
public void reloadChildren(CIModel modelBase) {
getLoader().loadChildren(modelBase);
}
public void reloadChildren(CIModel modelBase, final CIModel newSelection) {
final LoadListener l = new LoadListener() {
@Override
public void loaderLoad(LoadEvent le) {
super.loaderLoad(le);
setSelected(newSelection);
getLoader().removeLoadListener(this);
}
};
getLoader().addLoadListener(l);
getLoader().loadChildren(modelBase);
}
public CIModel getValue() {
TreeItem item = getSelected();
if (item == null) {
return(null);
}
return((CIModel)item.getModel());
}
public void setValue(CIModel value) {
//setSelected(value);
}
public void updateStore(CIModel model) {
this.store.update(model);
}
}