package org.openrosa.client.view;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openrosa.client.Context;
import org.openrosa.client.dnd.JrTreePanelDropTarget;
import org.openrosa.client.model.FormDef;
import org.openrosa.client.model.GroupDef;
import org.openrosa.client.model.IFormElement;
import org.openrosa.client.model.OptionDef;
import org.openrosa.client.model.QuestionDef;
import org.openrosa.client.model.RepeatQtnsDef;
import org.openrosa.client.model.TreeModelItem;
import org.openrosa.client.controller.FormDesignerController;
import org.openrosa.client.controller.IFormActionListener;
import org.openrosa.client.controller.IFormChangeListener;
import org.openrosa.client.controller.IFormDesignerListener;
import org.openrosa.client.controller.IFormSelectionListener;
import org.openrosa.client.jr.xforms.util.XFormUtils;
import org.openrosa.client.locale.LocaleText;
import org.openrosa.client.model.ModelConstants;
import org.openrosa.client.util.FormDesignerUtil;
import org.openrosa.client.util.FormUtil;
import org.openrosa.client.util.Itext;
import org.openrosa.client.xforms.XformConstants;
import org.openrosa.client.xforms.XformUtil;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.dnd.TreePanelDragSource;
import com.extjs.gxt.ui.client.dnd.DND.Feedback;
import com.extjs.gxt.ui.client.event.DNDEvent;
import com.extjs.gxt.ui.client.event.DNDListener;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;
/**
* Displays questions in a tree view.
*
* @author daniel
*
*/
public class FormsTreeView extends com.extjs.gxt.ui.client.widget.Composite implements SelectionHandler<TreeItem>,IFormChangeListener,IFormActionListener, ModelIconProvider<TreeModelItem> {
/**
* Specifies the images that will be bundled for this Composite and specify
* that tree's images should also be included in the same bundle.
*/
public interface Images extends Toolbar.Images, Tree.Resources {
ImageResource drafts();
ImageResource markRead();
ImageResource templates();
ImageResource note();
ImageResource lookup();
}
public static final int DRAG_MOVE_UP = -1;
public static final int DRAG_NO_MOVE = 0;
public static final int DRAG_MOVE_DOWN = 1;
private static final int DATA_NODE = 0;
private static final int BIND_NODE = 1;
private static final int CONTROL_NODE = 2;
/** The main or root widget for displaying the list of forms and their contents
* in a tree view.
*/
//private Tree tree;
/** The tree images. */
private final Images images;
/** Pop up for displaying tree item context menu. */
private PopupPanel popup;
/** The item that has been copied to the clipboard. */
private Object clipboardItem;
private boolean inCutMode = false;
/** The currently selected tree item. */
private TreeItem item;
/** Flag determining whether to set the form node as the root tree node. */
private boolean showFormAsRoot;
/** The currently selected form. */
private FormDef formDef;
/** List of form item selection listeners. */
private List<IFormSelectionListener> formSelectionListeners = new ArrayList<IFormSelectionListener>();
/** The next available form id. We always have one form for OpenRosa form designer. */
private int nextFormId = 1;
public static final int INSERT_BEFORE = 0;
public static final int INSERT_AFTER = 1;
/** The listener to form designer global events. */
private IFormDesignerListener formDesignerListener;
private TreePanel treePanel;
/**
* Creates a new instance of the forms tree view widget.
*
* @param images the tree images.
* @param formSelectionListener the form item selection events listener.
*/
public FormsTreeView(IFormSelectionListener formSelectionListener) {
this.images = GWT.create(Images.class);
this.formSelectionListeners.add(formSelectionListener);
treePanel = new TreePanel(new TreeStore<TreeModelItem>());
treePanel.getStyle().setLeafIcon(AbstractImagePrototype.create(images.newform()));
//treePanel.getStyle().setJointExpandedIcon(jointExpandedIcon)
treePanel.setDisplayProperty("text");
treePanel.setAutoLoad(true);
//treePanel.setAutoHeight(true);
treePanel.setIconProvider(this);
initComponent(treePanel);
treePanel.getSelectionModel().addListener(Events.SelectionChange, new Listener<SelectionChangedEvent<TreeModelItem>>(){
public void handleEvent(SelectionChangedEvent<TreeModelItem> te) {
if(te.getSelectedItem() == null)
return;
Object selObject = te.getSelectedItem().getUserObject();
Context.setFormDef(FormDef.getFormDef((IFormElement)selObject));
formDef = Context.getFormDef();
fireFormItemSelected(selObject);
}
});
//add drag and drop
TreePanelDragSource source = new TreePanelDragSource(treePanel);
source.addDNDListener(new DNDListener() {
@Override
public void dragStart(DNDEvent e) {
ModelData sel = treePanel.getSelectionModel().getSelectedItem();
if (sel != null && sel == treePanel.getStore().getRootItems().get(0)) {
e.setCancelled(true);
e.getStatus().setStatus(false);
return;
}
super.dragStart(e);
}
/*@Override
public void dragDrop(DNDEvent e) {
super.dragDrop(e);
List<TreeStoreModel> models = e.getData();
TreeStoreModel storeModel = (TreeStoreModel) models.get(0);
final TreeModelItem data = (TreeModelItem) storeModel.getModel();
System.out.println(data.getText());
System.out.println(treePanel.getStore().indexOf(data));
System.out.println(data.getParent().indexOf(data));
treePanel.getStore().rejectChanges();
}*/
});
JrTreePanelDropTarget target = new JrTreePanelDropTarget(treePanel,this);
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.BOTH);
/*tree = new Tree(images);
//initWidget(tree);
FormUtil.maximizeWidget(tree);
tree.addSelectionHandler(this);
tree.ensureSelectedItemVisible();
//This is just for solving an abnormal behavior when one changes a node text
//and the click another node which gets the same text as the previously
//selected text. Just comment it out and you will see what happens.
tree.addMouseDownHandler(new MouseDownHandler(){
public void onMouseDown(MouseDownEvent event){
tree.setSelectedItem(tree.getSelectedItem());
scrollToLeft();
}
});
tree.addMouseUpHandler(new MouseUpHandler(){
public void onMouseUp(MouseUpEvent event){
scrollToLeft();
}
});*/
// initContextMenu();
}
private void scrollToLeft(){
DeferredCommand.addCommand(new Command(){
public void execute(){
Element element = (Element)getParent().getParent().getParent().getElement().getChildNodes().getItem(0).getChildNodes().getItem(0);
DOM.setElementPropertyInt(element, "scrollLeft", 0);
}
});
}
/**
* Sets the listener for form designer global events.
*
* @param formDesignerListener the listener.
*/
public void setFormDesignerListener(IFormDesignerListener formDesignerListener){
this.formDesignerListener = formDesignerListener;
}
/**
* Adds a listener to form item selection events.
*
* @param formSelectionListener the listener to add.
*/
public void addFormSelectionListener(IFormSelectionListener formSelectionListener){
this.formSelectionListeners.add(formSelectionListener);
}
public void showFormAsRoot(boolean showFormAsRoot){
this.showFormAsRoot = showFormAsRoot;
}
// /**
// * Prepares the tree item context menu.
// */
// private void initContextMenu(){
// popup = new PopupPanel(true,true);
//
// MenuBar menuBar = new MenuBar(true);
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.add(),LocaleText.get("addNew")),true, new Command(){
// public void execute() {popup.hide(); addNewItem();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.addchild(),LocaleText.get("addNewChild")),true, new Command(){
// public void execute() {popup.hide(); addNewChildItem();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.delete(),LocaleText.get("deleteItem")),true,new Command(){
// public void execute() {popup.hide(); deleteSelectedItem();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.moveup(),LocaleText.get("moveUp")),true, new Command(){
// public void execute() {popup.hide(); moveItemUp();}});
//
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.movedown(),LocaleText.get("moveDown")),true, new Command(){
// public void execute() {popup.hide(); moveItemDown();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.cut(),LocaleText.get("cut")),true,new Command(){
// public void execute() {popup.hide(); cutItem();}});
//
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.copy(),LocaleText.get("copy")),true,new Command(){
// public void execute() {popup.hide(); copyItem();}});
//
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.paste(),LocaleText.get("paste")),true,new Command(){
// public void execute() {popup.hide(); pasteItem();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.save(),LocaleText.get("save")),true,new Command(){
// public void execute() {popup.hide(); saveItem();}});
//
// menuBar.addSeparator();
// menuBar.addItem(FormDesignerUtil.createHeaderHTML(images.refresh(),LocaleText.get("refresh")),true,new Command(){
// public void execute() {popup.hide(); refreshItem();}});
//
// popup.setWidget(menuBar);
// }
/**
* A helper method to simplify adding tree items that have attached images.
* {@link #addImageItem(TreeItem, String) code}
*
* @param root the tree item to which the new item will be added.
* @param title the text associated with this item.
*/
/*private TreeItem addImageItem(TreeItem root, String title,ImageResource imageProto, Object userObj,String helpText) {
TreeItem item = new CompositeTreeItem(new TreeItemWidget(imageProto, title,popup,this));
item.setUserObject(userObj);
item.setTitle(helpText);
if(root != null)
root.addItem(item);
else
tree.addItem(item);
return item;
}*/
// public void moveItem()
/**
* @see com.google.gwt.event.logical.shared.SelectionHandler#onSelection(SelectionEvent)
*/
public void onSelection(SelectionEvent<TreeItem> event){
scrollToLeft();
TreeItem item = event.getSelectedItem();
//Should not call this more than once for the same selected item.
if(item != this.item){
Context.setFormDef(FormDef.getFormDef((IFormElement)item.getUserObject()));
formDef = Context.getFormDef();
fireFormItemSelected(item.getUserObject());
this.item = item;
//Expand if has kids such that users do not have to click the plus
//sign to expand. Besides, some are not even aware of that.
//if(item.getChildCount() > 0)
// item.setState(true);
}
}
/**
* Notifies all form item selection listeners about the currently
* selected form item.
*
* @param formItem the selected form item.
*/
private void fireFormItemSelected(Object formItem){
// for(int i=0; i<formSelectionListeners.size(); i++)
// formSelectionListeners.get(i).onFormItemSelected(formItem);
FormDesignerController.getFormDesignerController().changePropertiesViewSelection((IFormElement)formItem);
}
public void loadForm(FormDef formDef,boolean select, boolean langRefresh){
//We do not support loading of more than one form at the same time.
treePanel.getStore().removeAll();
if(formDef.getId() == ModelConstants.NULL_ID)
formDef.setId(nextFormId);
if(!langRefresh){
// int count = formDef.getQuestionCount();
// if(nextQuestionId <= count)
// nextQuestionId = count;
this.formDef = formDef;
if(formExists(formDef.getId()))
return;
//A temporary hack to ensure top level object is accessed.
//fireFormItemSelected(formDef);
}
TreeModelItem formRoot = null;
if(showFormAsRoot){
/*formRoot = new CompositeTreeItem(new TreeItemWidget(images.note(), formDef.getName(),popup,this));
formRoot.setUserObject(formDef);
tree.addItem(formRoot);*/
formRoot = new TreeModelItem(formDef.getName(),formDef,null);
treePanel.getStore().add(formRoot, true);
}
if(formDef.getChildren() != null){
for(int index = 0; index < formDef.getChildren().size(); index++){
IFormElement element = formDef.getChildAt(index);
TreeModelItem pageRoot = null;
if(element instanceof GroupDef){
loadGroup((GroupDef)element,formRoot);
}else{
this.loadQuestion((QuestionDef)element, formRoot);
}
//We expand only the first page.
if(index == 0)
treePanel.setExpanded(pageRoot, true);
//pageRoot.setState(true);
}
}
if(select && formRoot != null){
//tree.setSelectedItem(formRoot);
//formRoot.setState(true);
treePanel.setExpanded(formRoot, true);
treePanel.getSelectionModel().select(formRoot, true);
}
}
/**
* Check if a form with a given id is loaded.
*
* @param formId the form id.
* @return true if it exists, else false.
*/
public boolean formExists(int formId){
int count = treePanel.getStore().getChildCount(); //.getItemCount();
for(int index = 0; index < count; index++){
TreeModelItem item = (TreeModelItem)treePanel.getStore().getChild(index);
if(((FormDef)item.getUserObject()).getId() == formId){
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(item, false);
return true;
}
}
return false;
}
public void refreshForm(FormDef formDef){
//tree.clear();
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item != null){
TreeModelItem root = getSelectedItemRoot(item);
formDef.setId(((FormDef)root.getUserObject()).getId());
//tree.removeItem(root);
treePanel.getStore().remove(root);
}
loadForm(formDef,true,false);
}
/**
* Gets the list of forms that have been loaded.
*
* @return the form list.
*/
public List<FormDef> getForms(){
List<FormDef> forms = new ArrayList<FormDef>();
int count = treePanel.getStore().getChildCount(); //.getItemCount();
for(int index = 0; index < count; index++)
forms.add((FormDef)((TreeModelItem)treePanel.getStore().getChild(index)).getUserObject());
return forms;
}
/**
* Loads a list of forms and selects one of them.
*
* @param forms the form list to load.
* @param selFormId the id of the form to select.
*/
public void loadForms(List<FormDef> forms, int selFormId){
if(forms == null || forms.size() == 0)
return;
//tree.clear();
treePanel.getStore().removeAll();
this.formDef = null;
for(FormDef formDef : forms){
loadForm(formDef,formDef.getId() == selFormId,true);
if(formDef.getId() == selFormId){
this.formDef = formDef;
//A temporary hack to ensure top level object is accessed.
fireFormItemSelected(this.formDef);
}
}
}
private TreeModelItem loadGroup(GroupDef pageDef,TreeModelItem formRoot){
//TreeItem pageRoot = addImageItem(formRoot, pageDef.getName(), images.drafts(),pageDef,null);
TreeModelItem pageRoot = addImageItem(formRoot, Itext.getDisplayText(pageDef),pageDef);
loadQuestions(pageDef.getChildren(),pageRoot);
return pageRoot;
}
private void loadQuestions(List<IFormElement> questions,TreeModelItem root){
if(questions != null){
for(int currentQtnNo=0; currentQtnNo<questions.size(); currentQtnNo++){
IFormElement element = questions.get(currentQtnNo);
if(element instanceof GroupDef)
loadGroup((GroupDef)element,root);
else
loadQuestion((QuestionDef)element,root);
}
}
}
private TreeModelItem addImageItem(TreeModelItem root,String text, Object userObject){
TreeModelItem item = new TreeModelItem(text,userObject,root);
if(userObject instanceof IFormElement){
((FormDesignerController)formDesignerListener).alertToolbarQuestionAdded((IFormElement)userObject);
}
treePanel.getStore().add(root,item, true);
return item;
}
private TreeModelItem loadQuestion(QuestionDef questionDef,TreeModelItem root){
//TreeItem questionRoot = addImageItem(root, questionDef.getDisplayText(), images.lookup(),questionDef,questionDef.getHelpText());
TreeModelItem questionRoot = addImageItem(root, Itext.getDisplayText(questionDef), questionDef);
GWT.log("Loading Question in FormsTreeView, Name="+questionDef.getQuestionID()+", type="+questionDef.getDataType());
if(questionDef.getDataType() == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE ||
questionDef.getDataType() == QuestionDef.QTN_TYPE_LIST_MULTIPLE){
List options = questionDef.getOptions();
if(options == null){
return questionRoot;
}
for(int currentOptionNo=0; currentOptionNo < options.size(); currentOptionNo++){
GWT.log("FormsTreeView adding select option...");
OptionDef optionDef = (OptionDef)options.get(currentOptionNo);
//addImageItem(questionRoot, optionDef.getText(), images.markRead(),optionDef,null);
addImageItem(questionRoot, Itext.getDisplayText(optionDef), optionDef);
}
}
else if(questionDef.getDataType() == QuestionDef.QTN_TYPE_BOOLEAN){
//addImageItem(questionRoot, QuestionDef.TRUE_DISPLAY_VALUE, images.markRead(),null,null);
//addImageItem(questionRoot, QuestionDef.FALSE_DISPLAY_VALUE, images.markRead(),null,null);
OptionDef optionDef = new OptionDef(1, QuestionDef.TRUE_DISPLAY_VALUE, QuestionDef.TRUE_VALUE,questionDef);
addImageItem(questionRoot, QuestionDef.TRUE_DISPLAY_VALUE, optionDef);
optionDef = new OptionDef(2, QuestionDef.FALSE_DISPLAY_VALUE, QuestionDef.FALSE_VALUE,questionDef);
addImageItem(questionRoot, QuestionDef.FALSE_DISPLAY_VALUE, optionDef);
}
else if(questionDef.getDataType() == QuestionDef.QTN_TYPE_REPEAT){
loadQuestions(questionDef.getRepeatQtnsDef().getChildren(),questionRoot);
}
return questionRoot;
}
/**
* @see org.openrosa.client.controller.IFormActionListener#deleteSelectedItem()
*/
public void deleteSelectedItem(){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null){
Window.alert(LocaleText.get("selectDeleteItem"));
return;
}
if(inReadOnlyMode() && !(item.getUserObject() instanceof FormDef))
return;
if(!inCutMode && !Window.confirm(LocaleText.get("deleteTreeItemPrompt")))
return;
deleteItem(item);
}
/**
* Removes a given tree item from the tree widget.
*
* @param item the tree item to delete.
*/
private void deleteItem(TreeModelItem item){
TreeModelItem parent = (TreeModelItem)item.getParent();
int index;
if(parent != null){
index = parent.indexOf(item);
//If last item is the one selected, the select the previous, else the next.
if(index == parent.getChildCount()-1)
index -= 1;
removeFormDefItem(item,parent);
//Remove the selected item.
//item.remove();
parent.remove(item);
treePanel.getStore().remove(item);
//treePanel.getStore().update(parent);
//If no more kids, then select the parent.
if(parent.getChildCount() == 0)
treePanel.getSelectionModel().select(parent, false);
//tree.setSelectedItem(parent);
else
treePanel.getSelectionModel().select(parent.getChild(index), false);
//tree.setSelectedItem(parent.getChild(index));
}
else{ //Must be the form root
index = getRootItemIndex(item);
//item.remove();
treePanel.getStore().remove(item);
int count = treePanel.getStore().getChildCount(); //tree.getItemCount();
//If we have any items left, select the one which was after
//the one we have just removed.
if(count > 0){
//If we have deleted the last item, select the item which was before it.
if(index == count)
index--;
//tree.setSelectedItem(tree.getItem(index));
treePanel.getSelectionModel().select(treePanel.getStore().getChild(index), false);
}
}
//if(tree.getSelectedItem() == null){
if(treePanel.getSelectionModel().getSelectedItem() == null){
Context.setFormDef(null);
formDef = null;
fireFormItemSelected(null);
nextFormId = 1;
// nextQuestionId = 0;
// nextOptionId = 0;
}
}
/**
* Gets the index of the tree item which is at the root level.
*
* @param item the tree root item whose index we are to get.
* @return the index of the tree item.
*/
/*private int getRootItemIndex(TreeItem item){
int count = tree.getItemCount();
for(int index = 0; index < count; index++){
if(item == tree.getItem(index))
return index;
}
return 0;
}*/
/**
* Gets the index of the tree item which is at the root level.
*
* @param item the tree root item whose index we are to get.
* @return the index of the tree item.
*/
private int getRootItemIndex(TreeModelItem item){
int count = treePanel.getStore().getChildCount(); //getItemCount()
for(int index = 0; index < count; index++){
if(item == treePanel.getStore().getChild(index))
return index;
}
return 0;
}
private void removeFormDefItem(TreeModelItem item, TreeModelItem parent){
Object userObj = item.getUserObject();
Object parentUserObj = parent.getUserObject();
if(userObj instanceof QuestionDef){
if(parentUserObj instanceof QuestionDef){
((QuestionDef)parentUserObj).removeChild((IFormElement)userObj);
}
else{
((IFormElement)parentUserObj).removeChild((IFormElement)userObj);
}
}
else if(userObj instanceof OptionDef){
((QuestionDef)parentUserObj).removeOption((OptionDef)userObj);
}
else if(userObj instanceof GroupDef)
((IFormElement)parentUserObj).removeChild((IFormElement)userObj); //((FormDef)parentUserObj).removePage((PageDef)userObj);
}
/**
* @see org.openrosa.client.controller.IFormActionListener#addNewItem()
*/
public void addNewItem(){
if(inReadOnlyMode())
return;
/*TreeItem item = tree.getSelectedItem();
//Check if there is any selection.
if(item != null){
Object userObj = item.getUserObject();
if(userObj instanceof QuestionDef){
int id = ++nextQuestionId;
QuestionDef questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,item.getParentItem().getUserObject());
item = addImageItem(item.getParentItem(), questionDef.getText(), images.lookup(),questionDef,questionDef.getHelpText());
addFormDefItem(questionDef,item.getParentItem());
tree.setSelectedItem(item);
}
else if(userObj instanceof OptionDef){
int id = ++nextOptionId;
OptionDef optionDef = new OptionDef(id,LocaleText.get("option")+id,"option"+id,(QuestionDef)item.getParentItem().getUserObject());
item = addImageItem(item.getParentItem(), optionDef.getText(), images.markRead(),optionDef,null);
addFormDefItem(optionDef,item.getParentItem());
tree.setSelectedItem(item);
}
else if(userObj instanceof PageDef){
int id = ++nextPageId;
PageDef pageDef = new PageDef(LocaleText.get("page")+id,id,null,(FormDef)item.getParentItem().getUserObject());
item = addImageItem(item.getParentItem(), pageDef.getName(), images.drafts(),pageDef,null);
addFormDefItem(pageDef,item.getParentItem());
tree.setSelectedItem(item);
}
else if(userObj instanceof FormDef)
addNewForm();
}
else
addNewForm();*/
TreeModelItem selModelItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
//Check if there is any selection.
if(selModelItem != null){
Object userObj = selModelItem.getUserObject();
if(userObj instanceof QuestionDef){
int id = FormUtil.getNextNewQuestionID(formDef);
QuestionDef questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selModelItem.getParent()).getUserObject());
questionDef.setItextId(questionDef.getQuestionID());
TreeModelItem modelItem = new TreeModelItem(questionDef.getText(),questionDef,selModelItem.getParent());
addChildItemToParent(questionDef,(TreeModelItem)selModelItem.getParent());
treePanel.getStore().add(selModelItem.getParent(),modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
else if(userObj instanceof OptionDef){
int id = FormUtil.getNextNewOptionID(formDef);
OptionDef optionDef = new OptionDef(id,LocaleText.get("option")+id,"option"+id,(QuestionDef)((TreeModelItem)selModelItem.getParent()).getUserObject());
optionDef.setItextId(optionDef.getQuestionID());
TreeModelItem modelItem = new TreeModelItem(optionDef.getText(),optionDef,selModelItem.getParent());
addChildItemToParent(optionDef,(TreeModelItem)selModelItem.getParent());
treePanel.getStore().add(selModelItem.getParent(),modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
else if(userObj instanceof GroupDef){
int id = FormUtil.getNextNewQuestionID(formDef);
GroupDef pageDef = new GroupDef(LocaleText.get("page")+id,null,(FormDef)((TreeModelItem)selModelItem.getParent()).getUserObject());
pageDef.setItextId(FormDesignerUtil.getXmlTagName(pageDef.getQuestionID()));
TreeModelItem modelItem = new TreeModelItem(pageDef.getQuestionID(),pageDef,selModelItem.getParent());
addChildItemToParent(pageDef,(TreeModelItem)selModelItem.getParent());
treePanel.getStore().add(selModelItem.getParent(),modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
else if(userObj instanceof FormDef)
addNewForm();
}
else
addNewForm();
}
public void addYesNoQuestion(){
final String YES_ITEXT_ID = "answer_yes";
final String NO_ITEXT_ID = "answer_no";
final String EN_YES = "Yes";
final String EN_NO = "No";
final String DEFAULT_QUESTION_TEXT = "Yes/No Question";
addFormIfNew();
TreeModelItem listItem = addNewQuestionBare(QuestionDef.QTN_TYPE_LIST_EXCLUSIVE, (TreeModelItem)treePanel.getSelectionModel().getSelectedItem());
TreeModelItem yesItem = addNewQuestionBare(QuestionDef.QTN_TYPE_OPTION_ITEM, listItem);
TreeModelItem noItem = addNewQuestionBare(QuestionDef.QTN_TYPE_OPTION_ITEM, listItem);
QuestionDef listQuestionDef = (QuestionDef)listItem.getUserObject();
OptionDef yesOptionDef = (OptionDef)yesItem.getUserObject();
OptionDef noOptionDef = (OptionDef)noItem.getUserObject();
listQuestionDef.setText(DEFAULT_QUESTION_TEXT); //don't set ItextID like below since each yes/no question text will likely be unique
listItem.setText(DEFAULT_QUESTION_TEXT);
yesOptionDef.setItextId(YES_ITEXT_ID);
yesOptionDef.setText(EN_YES);
yesOptionDef.setDefaultValue(EN_YES);
yesItem.setText(EN_YES);
//don't set Itext since the user might want to specify which language to use, and they'll only have to do it once
noOptionDef.setItextId(NO_ITEXT_ID);
noOptionDef.setText(EN_NO);
noOptionDef.setDefaultValue(EN_NO);
noItem.setText(EN_NO);
treePanel.getStore().update(listItem);
treePanel.getStore().update(yesItem);
treePanel.getStore().update(noItem);
treePanel.setExpanded(listItem, true);
treePanel.getSelectionModel().select(false, listItem);
}
/**
* Creates a new FormDef in the FormTreeView if none is present (i.e. it's a blank new form)
*/
private void addFormIfNew(){
TreeModelItem selectedItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(selectedItem == null){
addNewQuestionBare(-1, null); //argument doesn't matter as it will trigger creation of a new FormDef
}else{
return; //something is already selected, implying that a form exists.
}
}
/**
* Creates a new Question in the FormsTreeView (and the internal data model) according
* to the dataType specified and the current item selected. Certain types of combinations
* of selected questions + specified dataTypes are invalid operations and will result in
* null being returned (for example, have a group selected and trying to create a new
* OptionDef). Ideally these combinations will be prevented further up stream, but the buck
* definitely stops here, regardless.
*
* The reason this method is called "Bare" is that it creates the new Question Type
* without any additional help (auto adding new options to (1)select questions, etc).
* That type of behavior is left up to functions calling this function, allowing one to get
* creative with interesting combo questions (such as setting up an auto Yes/No question generator)
* for common question combinations.
*
* @param dataType - The type of the new IFormElement which needs to be created
* @return TreeModelItem of the new IFormElement
*/
public TreeModelItem addNewQuestionBare(int dataType, TreeModelItem parentItem){
//Auto adding of children (for groups/repeats/(1)selects should not be done in this method
//this is for the bare addition of new IFormElements, allowing for flexibly making new
//combo question macros (like an auto Yes/No question generator) further upstream.
TreeModelItem selectedItem = parentItem;
if(selectedItem == null){
addNewForm("Form","data",1);
return (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
}
IFormElement selectedIFormElement = (IFormElement)selectedItem.getUserObject();
if(selectedIFormElement == null){ return null; }
TreeModelItem parentTreeItem = getCorrectParent(selectedItem,dataType);
if(parentTreeItem == null){ return null; }
IFormElement parentIFormElement = (IFormElement)parentTreeItem.getUserObject();
if(parentIFormElement == null){ return null; }
//create the IFormElement
if(dataType == QuestionDef.QTN_TYPE_OPTION_ITEM){
//TODO create a new OptionDef and return it as selected
int id = FormUtil.getNextNewOptionID(formDef);
String optionIDString = "option"+id;
OptionDef optionDef = new OptionDef(id,LocaleText.get("option")+id,optionIDString,(QuestionDef)parentIFormElement);
optionDef.setItextId(optionDef.getQuestionID());
TreeModelItem newTreeItem = new TreeModelItem(Itext.getDisplayText(optionDef),optionDef,parentTreeItem);
addChildItemToParent(optionDef,parentTreeItem);
treePanel.getStore().add(parentTreeItem,newTreeItem, true);
return newTreeItem;
}else if(dataType == QuestionDef.QTN_TYPE_GROUP){
//TODO create new group and return it as selected
//....
int id = FormUtil.getNextNewQuestionID(formDef);
String groupIDString = "Group"+id;
GroupDef groupDef = new GroupDef(groupIDString,null,parentIFormElement);
TreeModelItem newSelectedItem = addImageItem(parentTreeItem, Itext.getDisplayText(groupDef) ,groupDef);
addChildItemToParent(groupDef, parentTreeItem);
return newSelectedItem;
}else{
//add a new question and return it as selected
int id = FormUtil.getNextNewQuestionID(formDef);
String questionIDString = "question"+id;
QuestionDef questionDef = new QuestionDef(id,
LocaleText.get("question")+id,
QuestionDef.QTN_TYPE_TEXT,
questionIDString,
parentIFormElement);
questionDef.setDataType(dataType);
questionDef.setHasUINode(true);
questionDef.setItextId(questionDef.getQuestionID());
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
RepeatQtnsDef rptQtnsDef = new RepeatQtnsDef(questionDef);
questionDef.setRepeatQtnsDef(rptQtnsDef);
}
TreeModelItem newSelectedItem = addImageItem(parentTreeItem, Itext.getDisplayText(questionDef), questionDef);
addChildItemToParent(questionDef,parentTreeItem);
return newSelectedItem;
}
}
/**
* Looks for the correct parent of the new IFormElement to be created
* based on the datatype specified by newItemDataType and the currently
* selected item in the tree.
*
* For example, if a text question is currently selected and a new text question
* is to be created, the correct parent for the new question is the same as the parent for the existing text
* question.
* However, if a Select question was selected, with the new Item to be created being a select question OptionDef,
* the correct parent is the currently selected item (the Select question), as opposed to it's parent.
* @param selectedItem
* @param newItemDataType
* @return
*/
private TreeModelItem getCorrectParent(TreeModelItem selectedItem, int newItemDataType){
if(selectedItem == null){ return null; }
IFormElement selectedElement = (IFormElement)selectedItem.getUserObject();
if(selectedElement instanceof FormDef){
return selectedItem;
}
boolean isSelectedOptionDef = selectedElement instanceof OptionDef;
boolean isSelectedGroupOrRepeat = selectedElement instanceof GroupDef ||
(selectedElement instanceof QuestionDef &&
selectedElement.getDataType() == QuestionDef.QTN_TYPE_REPEAT);
boolean isSelectedListQuestion = selectedElement instanceof QuestionDef &&
(selectedElement.getDataType() == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE ||
selectedElement.getDataType() == QuestionDef.QTN_TYPE_LIST_MULTIPLE);
boolean isSelectedRegQuestion = selectedElement instanceof QuestionDef;
TreeModelItem parentOfSelectedItem = (TreeModelItem)selectedItem.getParent(); //should never be null (FormDef case taken care of above)
if(isSelectedOptionDef){
if(newItemDataType == QuestionDef.QTN_TYPE_OPTION_ITEM){
return parentOfSelectedItem;
}else{
return (TreeModelItem)parentOfSelectedItem.getParent();
}
}else if(isSelectedGroupOrRepeat){
if(newItemDataType == QuestionDef.QTN_TYPE_OPTION_ITEM){
return null;
}else{
return selectedItem;
}
}else if(isSelectedListQuestion){
if(newItemDataType == QuestionDef.QTN_TYPE_OPTION_ITEM){
return selectedItem;
}else{
return parentOfSelectedItem;
}
}else if(isSelectedRegQuestion){
if(newItemDataType == QuestionDef.QTN_TYPE_OPTION_ITEM){
return null;
}else{
return parentOfSelectedItem;
}
}else{
return null;
}
}
public void addNewQuestion(int dataType){
if(inReadOnlyMode())
return;
TreeModelItem selectedItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
//Check if there is any selection.
if(selectedItem != null){
Object selectedUserObj = selectedItem.getUserObject();
if(selectedUserObj instanceof QuestionDef){
int id = FormUtil.getNextNewQuestionID(formDef);
if(dataType == QuestionDef.QTN_TYPE_GROUP){
GroupDef pageDef = new GroupDef("Group"+id,null,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
selectedItem = addImageItem((TreeModelItem)selectedItem.getParent(), Itext.getDisplayText(pageDef) ,pageDef);
addChildItemToParent(pageDef, (TreeModelItem)selectedItem.getParent());
//if(dataType == QuestionDef.QTN_TYPE_GROUP)
// addNewQuestion(QuestionDef.QTN_TYPE_TEXT);
}
else{
QuestionDef questionDef = new QuestionDef(id,
LocaleText.get("question")+id,
QuestionDef.QTN_TYPE_TEXT,"question"+id,
(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
questionDef.setDataType(dataType);
// questionDef.setHasUINode(true); //when adding questions using the toolbar, it is implied that it contains a UI node.
questionDef.setItextId(questionDef.getQuestionID());
//item = addImageItem(item.getParent(), questionDef.getText(), images.lookup(),questionDef,questionDef.getHelpText());
selectedItem = addImageItem((TreeModelItem)selectedItem.getParent(), Itext.getDisplayText(questionDef), questionDef);
addChildItemToParent(questionDef,(TreeModelItem)selectedItem.getParent());
if(dataType == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE || dataType == QuestionDef.QTN_TYPE_LIST_MULTIPLE){
addNewOptionDef(questionDef, selectedItem);
}
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
treePanel.getSelectionModel().select(selectedItem, false);
// QuestionDef newChildQtn = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
// addFormDefItem(newChildQtn, selectedItem);
addNewChildItem(true, QuestionDef.QTN_TYPE_TEXT);
}
}
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(selectedItem, false);
}
else if(selectedUserObj instanceof OptionDef){
//addNewOptionDef();
int id = FormUtil.getNextNewQuestionID(formDef);
QuestionDef questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent().getParent()).getUserObject());
questionDef.setDataType(dataType);
questionDef.setItextId(questionDef.getQuestionID());
//item = addImageItem(item.getParent(), questionDef.getText(), images.lookup(),questionDef,questionDef.getHelpText());
selectedItem = addImageItem((TreeModelItem)selectedItem.getParent().getParent(), Itext.getDisplayText(questionDef), questionDef);
addChildItemToParent(questionDef,(TreeModelItem)selectedItem.getParent());
if(dataType == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE || dataType == QuestionDef.QTN_TYPE_LIST_MULTIPLE)
addNewOptionDef(questionDef, selectedItem);
else if(dataType == QuestionDef.QTN_TYPE_GROUP)
addNewQuestion(QuestionDef.QTN_TYPE_TEXT);
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(selectedItem, false);
}
else if(selectedUserObj instanceof GroupDef){
int id = FormUtil.getNextNewQuestionID(formDef);
QuestionDef questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
questionDef.setDataType(dataType);
questionDef.setItextId(questionDef.getQuestionID());
//item = addImageItem(item.getParent(), questionDef.getText(), images.lookup(),questionDef,questionDef.getHelpText());
selectedItem = addImageItem((TreeModelItem)selectedItem.getParent(), questionDef.getText(), questionDef);
addChildItemToParent(questionDef,(TreeModelItem)selectedItem.getParent());
if(dataType == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE || dataType == QuestionDef.QTN_TYPE_LIST_MULTIPLE)
addNewOptionDef(questionDef, selectedItem);
else if(dataType == QuestionDef.QTN_TYPE_GROUP)
addNewQuestion(QuestionDef.QTN_TYPE_TEXT);
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(selectedItem, false);
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
treePanel.getSelectionModel().select(selectedItem, false);
// QuestionDef newChildQtn = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
// addFormDefItem(newChildQtn, selectedItem);
addNewChildItem(true, QuestionDef.QTN_TYPE_TEXT);
}
}
else if(selectedUserObj instanceof FormDef){
//addNewForm();
TreeModelItem parentItem;
if(selectedItem.getChildCount() == 0){
parentItem = selectedItem;
}else{
parentItem = (TreeModelItem)selectedItem.getChild(0);
}
int id = FormUtil.getNextNewQuestionID(formDef);
QuestionDef questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)parentItem.getUserObject());
questionDef.setDataType(dataType);
questionDef.setItextId(questionDef.getQuestionID());
selectedItem = addImageItem(selectedItem, questionDef.getText(), questionDef);
addChildItemToParent(questionDef, (TreeModelItem)selectedItem.getParent());
if(dataType == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE || dataType == QuestionDef.QTN_TYPE_LIST_MULTIPLE){
addNewOptionDef(questionDef, selectedItem);
}else if(dataType == QuestionDef.QTN_TYPE_GROUP){
addNewQuestion(QuestionDef.QTN_TYPE_TEXT);
}
treePanel.getSelectionModel().select(selectedItem, false);
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
treePanel.getSelectionModel().select(selectedItem, false);
// QuestionDef newChildQtn = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
// addFormDefItem(newChildQtn, selectedItem);
addNewChildItem(true, QuestionDef.QTN_TYPE_TEXT);
}
}
}
else{
addNewForm(dataType);
//Get the newly added question and set its appropriate type.
selectedItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
IFormElement questionDef = (IFormElement)selectedItem.getUserObject();
questionDef.setDataType(dataType);
questionDef.setItextId(questionDef.getQuestionID());
if(dataType == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE || dataType == QuestionDef.QTN_TYPE_LIST_MULTIPLE){
addNewOptionDef((QuestionDef)questionDef, selectedItem);
}else if(dataType == QuestionDef.QTN_TYPE_GROUP){
;//addNewQuestion(QuestionDef.QTN_TYPE_TEXT);
}
treePanel.getSelectionModel().select(selectedItem, false);
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
treePanel.getSelectionModel().select(selectedItem, false);
// QuestionDef newChildQtn = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)((TreeModelItem)selectedItem.getParent()).getUserObject());
// addFormDefItem(newChildQtn, selectedItem);
addNewChildItem(true, QuestionDef.QTN_TYPE_TEXT);
}
}
}
private void addNewOptionDef(QuestionDef questionDef, TreeModelItem parentItem){
int id = FormUtil.getNextNewOptionID(formDef);
OptionDef optionDef = new OptionDef(id,LocaleText.get("option")+id,"option"+id,questionDef);
optionDef.setItextId(optionDef.getQuestionID());
//addImageItem(parentItem, optionDef.getText(), images.markRead(),optionDef,null);
addImageItem(parentItem, Itext.getDisplayText(optionDef),optionDef);
addChildItemToParent(optionDef,parentItem);
}
/**
* Adds the new IFormeElement as a child to its parent in the correct way
* @param newIFormeElement
* @param parentItem
*/
private void addChildItemToParent(Object newIFormeElement,TreeModelItem parentItem){
Object parentUserObj = parentItem.getUserObject();
if(parentUserObj instanceof QuestionDef){
if(newIFormeElement instanceof OptionDef){
((QuestionDef)parentUserObj).addOption((OptionDef)newIFormeElement);
}else if(newIFormeElement instanceof QuestionDef && ((IFormElement)parentUserObj).getDataType()==QuestionDef.QTN_TYPE_REPEAT){
((QuestionDef)parentUserObj).addRepeatChildDef((IFormElement)newIFormeElement);
}
// {
// ((IFormElement)parentUserObj).getParent().addChild((IFormElement)obj);
//// ((QuestionDef)parentUserObj).getRepeatQtnsDef().addQuestion((QuestionDef)obj);
// }
//((QuestionDef)parentUserObj).getRepeatQtnsDef().addQuestion((QuestionDef)obj);
}
else if(parentUserObj instanceof GroupDef || parentUserObj instanceof FormDef)
((IFormElement)parentUserObj).addChild((IFormElement)newIFormeElement);
}
public void addNewForm(){
addNewForm(QuestionDef.QTN_TYPE_TEXT);
}
public void addNewForm(int qtnDataType){
int id = nextFormId;
addNewForm(LocaleText.get("newForm")+id,"data",id);
//Automatically add a new question
addNewChildItem(false, qtnDataType);
}
public void addNewChildItem(boolean addNewIfNoKids){
addNewChildItem(addNewIfNoKids, QuestionDef.QTN_TYPE_TEXT);
}
public void addNewForm(String name, String varName, int formId){
if(inReadOnlyMode())
return;
if(formExists(formId))
return;
FormDef formDef = new FormDef(formId,name,varName, varName,null,null,null,null,null,null);
formDef.setItextId(formDef.getQuestionID());
/*TreeItem item = new CompositeTreeItem(new TreeItemWidget(images.note(), formDef.getName(),popup,this));
item.setUserObject(formDef);
tree.addItem(item);
tree.setSelectedItem(item);*/
TreeModelItem modelItem = new TreeModelItem(formDef.getName(),formDef,null);
treePanel.getStore().add(modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
/**
* @see org.openrosa.client.controller.IFormActionListener#addNewChildItem()
*/
public void addNewChildItem(){
addNewChildItem(true);
}
/**
* Adds a new child item.
*/
public void addNewChildItem(boolean addNewIfNoKids, int dataType){
if(inReadOnlyMode())
return;
TreeModelItem selModelItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
//Check if there is any selection.
if(selModelItem == null){
if(addNewIfNoKids)
addNewItem();
return;
}
Object userObj = selModelItem.getUserObject();
if(userObj instanceof GroupDef ||
userObj instanceof FormDef ||
(userObj instanceof QuestionDef &&
((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_REPEAT) ){
int id = FormUtil.getNextNewQuestionID(formDef);
IFormElement questionDef = new QuestionDef(id,LocaleText.get("question")+id,QuestionDef.QTN_TYPE_TEXT,"question"+id,(IFormElement)userObj);
if(dataType == QuestionDef.QTN_TYPE_REPEAT){
questionDef.setDataType(QuestionDef.QTN_TYPE_REPEAT);
questionDef.setHasUINode(true); //when adding questions using the toolbar, it is implied that it contains a UI node.
questionDef.setItextId(questionDef.getQuestionID());
}
questionDef.setItextId(questionDef.getQuestionID());
TreeModelItem modelItem = new TreeModelItem(questionDef.getText(),questionDef,selModelItem);
addChildItemToParent(questionDef,selModelItem);
treePanel.getStore().add(selModelItem,modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
else if(userObj instanceof QuestionDef &&
( ((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE ||
((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_LIST_MULTIPLE ) ){
int id = FormUtil.getNextNewOptionID(formDef);
OptionDef optionDef = new OptionDef(id,LocaleText.get("option")+id,"option"+id,(QuestionDef)userObj);
optionDef.setItextId(optionDef.getQuestionID());
TreeModelItem modelItem = new TreeModelItem(optionDef.getText(),optionDef,selModelItem);
addChildItemToParent(optionDef,selModelItem);
treePanel.getStore().add(selModelItem,modelItem, true);
treePanel.getSelectionModel().select(modelItem, false);
}
else if(addNewIfNoKids)
addNewItem();
}
/**
* @see org.openrosa.client.controller.IFormActionListener#moveItemUp()
*/
public void moveItemUp() {
// if(inReadOnlyMode())
// return;
//
// TreeModelItem selectedItem = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
//
// //Check if there is any selection.
// if(selectedItem == null){
// return;
// }
//
// TreeModelItem parentOfSelectedItem = (TreeModelItem)selectedItem.getParent();
//
// //We don't move root node (which has no parent, that is the form itself, since we design one form at a time)
// if(parentOfSelectedItem == null){
// return;
// }
//
// //One item can't move against itself.
// int count = parentOfSelectedItem.getChildCount();
// if(count == 1){
// return;
// }
//
// int selectedItemIndex = parentOfSelectedItem.indexOf(selectedItem);
// if(selectedItemIndex == 0){
// return; //Can't move any further upwards.
// }
//
// //move the item in the form object model.
// moveFormItemUp(selectedItem,parentOfSelectedItem);
//
// TreeModelItem currentItem; // = parent.getChild(index - 1);
// List list = new ArrayList();
//
// //item.remove();
// parentOfSelectedItem.remove(selectedItem);
// treePanel.getStore().remove(selectedItem);
//
// //parent.insert(item, index -1);
//
// while(parentOfSelectedItem.getChildCount() >= selectedItemIndex){
// currentItem = (TreeModelItem)parentOfSelectedItem.getChild(selectedItemIndex-1);
// list.add(currentItem);
// //currentItem.remove();
// currentItem.getParent().remove(currentItem);
// treePanel.getStore().remove(currentItem);
// }
//
// parentOfSelectedItem.add(selectedItem);
// treePanel.getStore().add(parentOfSelectedItem,selectedItem,true);
// for(int i=0; i<list.size(); i++){
// parentOfSelectedItem.add((TreeModelItem)list.get(i));
// treePanel.getStore().add(parentOfSelectedItem,(TreeModelItem)list.get(i),true);
// }
//
// //treePanel.getStore().update(parent);
//
// //tree.setSelectedItem(item);
// treePanel.getSelectionModel().select(selectedItem, false);
}
public void moveItem(IFormElement droppedDef, IFormElement neighborDef, int aboveOrBelow){
/////Start Init of easy to read variable names
com.google.gwt.xml.client.Element anchorBindNode, anchorDataNode, anchorControlNode,
droppedBindNode, droppedDataNode, droppedControlNode,
droppedBindParent, droppedDataParent, droppedControlParent;
anchorBindNode = (com.google.gwt.xml.client.Element)findNearestNeighborData(neighborDef, aboveOrBelow, FormsTreeView.BIND_NODE);
anchorDataNode = (com.google.gwt.xml.client.Element)findNearestNeighborData(neighborDef, aboveOrBelow, FormsTreeView.DATA_NODE);
anchorControlNode = (com.google.gwt.xml.client.Element)findNearestNeighborData(neighborDef, aboveOrBelow, FormsTreeView.CONTROL_NODE);
droppedBindNode = droppedDef.getBindNode();
droppedControlNode = droppedDef.getControlNode();
droppedDataNode = droppedDef.getDataNode();
droppedBindParent = null;
droppedDataParent = null;
droppedControlParent = null;
if(droppedBindNode != null){ droppedBindParent = (com.google.gwt.xml.client.Element)droppedBindNode.getParentNode();}
if(droppedControlNode != null){ droppedControlParent = (com.google.gwt.xml.client.Element)droppedControlNode.getParentNode();}
if(droppedDataNode != null){ droppedDataParent = (com.google.gwt.xml.client.Element)droppedDataNode.getParentNode();}
////////////End init
detachXformNodesFromParent(droppedDef); //detaches the data, bind and control nodes of the droppedDef from their respective parents
///////////Start the insertion of the dropped Question's data,bind and control node's in their new locations.
if(droppedDataNode != null){
if(anchorDataNode != null){
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
insertAfter(droppedDataNode,anchorDataNode);
}else{
anchorDataNode.getParentNode().insertBefore(droppedDataNode, anchorDataNode);
}
}else{
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
Node firstChild = droppedDataParent.getFirstChild();
if(firstChild != null){
droppedDataParent.insertBefore(droppedDataNode, firstChild);
}else{
droppedDataParent.appendChild(droppedDataNode);
}
}else{
droppedDataParent.appendChild(droppedDataNode);
}
}
}
if(droppedBindNode != null){
if(anchorBindNode != null){
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
insertAfter(droppedBindNode,anchorBindNode);
}else{
anchorBindNode.getParentNode().insertBefore(droppedBindNode, anchorBindNode);
}
}else{
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
Node firstChild = droppedBindParent.getFirstChild();
if(firstChild != null){
droppedBindParent.insertBefore(droppedBindNode, firstChild);
}else{
droppedBindParent.appendChild(droppedBindNode);
}
}else{
droppedBindParent.appendChild(droppedBindNode);
}
}
}
if(droppedControlNode != null){
if(anchorControlNode != null){
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
insertAfter(droppedControlNode,anchorControlNode);
}else{
anchorControlNode.getParentNode().insertBefore(droppedControlNode, anchorControlNode);
}
}else{
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
Node firstChild = droppedControlParent.getFirstChild();
if(firstChild != null){
droppedControlParent.insertBefore(droppedControlNode, firstChild);
}else{
droppedControlParent.appendChild(droppedControlNode);
}
}else{
droppedControlParent.appendChild(droppedControlNode);
}
}
}
/////////////end insertion
//Re-organize the internal data model...
if(aboveOrBelow == FormsTreeView.INSERT_AFTER){
neighborDef.getParent().insertChildAfter(droppedDef, neighborDef);
}else{
neighborDef.getParent().insertChildBefore(droppedDef, neighborDef);
}
}
/**
* Inserts the node newChild after the existing child node refChild. If
* refChild is <code>null</code>, insert newChild at the end of the list of children.
*
* @param newChild The node to insert
* @param refChild The reference node (that is, the node after which the new
* node must be inserted), or <code>null</code>
* @return The node being inserted
*/
public final Node insertAfter(Node newChild, Node refChild) {
assert (newChild != null) : "Cannot add a null child node";
assert (refChild != null) : "Cannot add After a null node";
Node next = refChild.getNextSibling();
if (next == null) {
return refChild.getParentNode().appendChild(newChild);
} else {
return refChild.getParentNode().insertBefore(newChild, next);
}
}
private static int nodeListIndexOf(NodeList list, Node node){
for(int i=0;i<list.getLength();i++){
if(list.item(i).equals(node)){
return i;
}
}
return -1;
}
/**
* In the event that a node (bind, data, control) is null, we need to find
* the nearest neighbor that does have a not null node.
* @param neighborDef
* @param aboveOrBelow
* @return
*/
private Node findNearestNeighborData(IFormElement originalNeighbour, int aboveOrBelow, int NodeTypeToGet){
List<IFormElement> siblings = originalNeighbour.getParent().getChildren();
int neighIndex = siblings.indexOf(originalNeighbour);
int curIndex = neighIndex;
com.google.gwt.xml.client.Element nNode;
boolean atEnd = curIndex < 0 || curIndex >= siblings.size();
while(!atEnd){
IFormElement newNeighbor;
//the below if/else is to prevent code duplication (it's a determines the direction we're going through the list
//from the starting point specified by originalNeighbour argument.
if(aboveOrBelow == FormsTreeView.INSERT_BEFORE){
newNeighbor = siblings.get(curIndex); //look progressively upwards in the siblings list
}else{
newNeighbor = siblings.get(curIndex); //look progressively downwards in the list
}
nNode = null;
switch (NodeTypeToGet) { //get the relevant XML Node of the new sibling
case DATA_NODE:
nNode = newNeighbor.getDataNode();
break;
case BIND_NODE:
nNode = newNeighbor.getBindNode();
break;
case CONTROL_NODE:
nNode = newNeighbor.getControlNode();
break;
default:
break;
}
if(nNode != null){ //if the XML Node exists return it otherwise continue going through the list.
return nNode;
}
if(aboveOrBelow == FormsTreeView.INSERT_BEFORE){
curIndex -= 1;
atEnd = curIndex < 0;
}else{
curIndex += 1;
atEnd = curIndex >= siblings.size();
}
}
return null;
}
/**
* Detaches the bind, data, and control nodes from their parent holders, in anticipation of moving them
* elsewhere in the form.
* @param droppedDef
*/
private void detachXformNodesFromParent(IFormElement droppedDef){
com.google.gwt.xml.client.Element bindNode = droppedDef.getBindNode(); //this extended name thing is real unfortunate
if(bindNode != null){
bindNode.getParentNode().removeChild(bindNode);
}
com.google.gwt.xml.client.Element dataNode = droppedDef.getDataNode();
if(dataNode != null){
dataNode.getParentNode().removeChild(dataNode);
}
com.google.gwt.xml.client.Element controlNode = droppedDef.getControlNode();
if(controlNode != null){
controlNode.getParentNode().removeChild(controlNode);
}
}
private void moveFormItemUp(TreeModelItem selectedItem,TreeModelItem parentSelectedItem){
IFormElement userObj = (IFormElement)selectedItem.getUserObject();
IFormElement parentObj = (IFormElement)parentSelectedItem.getUserObject();
//Normal question
if(parentObj instanceof GroupDef){
((GroupDef)parentObj).moveElementUp(userObj);
}else if(parentObj instanceof FormDef){
GroupDef.moveElementUp(((IFormElement)parentObj).getChildren(), userObj); //((FormDef)parentObj).movePageUp(userObj);
}else if(userObj instanceof OptionDef){
((QuestionDef)parentObj).moveOptionUp((OptionDef)userObj);
}
}
private void moveFormItemDown(TreeModelItem item,TreeModelItem parent){
IFormElement userObj = (IFormElement)item.getUserObject();
IFormElement parentObj = (IFormElement)parent.getUserObject();
//Normal question
if(parentObj instanceof GroupDef)
((GroupDef)parentObj).moveElementDown(userObj);
/*else if(userObj instanceof QuestionDef && parentObj instanceof QuestionDef)
((QuestionDef)parentObj).getRepeatQtnsDef().moveQuestionDown((QuestionDef)userObj);*/
else if(parentObj instanceof FormDef)
GroupDef.moveElementDown(((IFormElement)parentObj).getChildren(), userObj); //((FormDef)parentObj).movePageDown(userObj);
else if(userObj instanceof OptionDef)
((QuestionDef)parentObj).moveOptionDown((OptionDef)userObj);
}
/**
* @see org.openrosa.client.controller.IFormActionListener#moveItemDown()
*/
public void moveItemDown(){
if(inReadOnlyMode())
return;
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
//Check if there is any selection.
if(item == null)
return;
TreeModelItem parent = (TreeModelItem)item.getParent();
//We don't move root node (which has no parent, that is the form itself, since we design one form at a time)
if(parent == null)
return;
//One item can't move against itself.
int count = parent.getChildCount();
if(count == 1)
return;
int index = parent.indexOf(item);
if(index == count - 1)
return; //Can't move any further downwards.
//move the item in the form object model.
moveFormItemDown(item,parent);
TreeModelItem currentItem; // = parent.getChild(index - 1);
List list = new ArrayList();
//item.remove();
parent.remove(item);
treePanel.getStore().remove(item);
while(parent.getChildCount() > 0 && parent.getChildCount() > index){
currentItem = (TreeModelItem)parent.getChild(index);
list.add(currentItem);
//currentItem.remove();
currentItem.getParent().remove(currentItem);
treePanel.getStore().remove(currentItem);
}
for(int i=0; i<list.size(); i++){
if(i == 1){
parent.add(item); //Add after the first item.
treePanel.getStore().add(parent, item, true);
}
parent.add((TreeModelItem)list.get(i));
treePanel.getStore().add(parent, (TreeModelItem)list.get(i), true);
}
if(list.size() == 1){
parent.add(item);
treePanel.getStore().add(parent, item, true);
}
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(item, false);
}
/**
* @see org.openrosa.client.controller.IFormChangeListener#onFormItemChanged(java.lang.Object)
*/
public Object onFormItemChanged(Object formItem) {
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return formItem; //How can this happen?
if(item.getUserObject() != formItem){
return formItem;
}
if(formItem instanceof QuestionDef){
IFormElement element = (IFormElement)formItem;
//item.setWidget(new TreeItemWidget(images.lookup(), questionDef.getDisplayText(),popup,this));
//item.setTitle(questionDef.getHelpText());
if(element.getDataType() == QuestionDef.QTN_TYPE_GROUP){ // || element.getDataType() == QuestionDef.QTN_TYPE_REPEAT){
IFormElement newElement = new GroupDef(element.getText(), element.getChildren(), element.getParent());
copyElementValues(newElement, element);
item.setUserObject(newElement);
formItem = newElement;
}
item.setText(Itext.getDisplayText(element));
treePanel.getStore().update(item);
}
else if(formItem instanceof OptionDef){
OptionDef optionDef = (OptionDef)formItem;
//item.setWidget(new TreeItemWidget(images.markRead(), optionDef.getText(),popup,this));
item.setText(Itext.getDisplayText(optionDef));
treePanel.getStore().update(item);
}
else if(formItem instanceof GroupDef){
IFormElement element = (IFormElement)formItem;
//item.setWidget(new TreeItemWidget(images.drafts(), pageDef.getName(),popup,this));
if(!(element.getDataType() == QuestionDef.QTN_TYPE_GROUP || element.getDataType() == QuestionDef.QTN_TYPE_REPEAT)){
IFormElement newElement = new QuestionDef(element.getParent());
copyElementValues(newElement, element);
item.setUserObject(newElement);
formItem = newElement;
}
item.setText(Itext.getDisplayText(element));
treePanel.getStore().update(item);
}
else if(formItem instanceof FormDef){
FormDef formDef = (FormDef)formItem;
//item.setWidget(new TreeItemWidget(images.note(), formDef.getName(),popup,this));
item.setText(Itext.getDisplayText(formDef));
treePanel.getStore().update(item);
}
return formItem;
}
private void copyElementValues(IFormElement newElement, IFormElement element){
newElement.setId(element.getId());
newElement.setItextId(element.getItextId());
newElement.setQuestionID(element.getQuestionID());
newElement.setBindNode(element.getBindNode());
newElement.setDataNode(element.getDataNode());
newElement.setDataType(element.getDataType());
newElement.setHelpText(element.getHelpText());
newElement.setHintNode(element.getHintNode());
newElement.setLabelNode(element.getLabelNode());
newElement.setText(element.getText());
newElement.setControlNode(element.getControlNode());
newElement.setParent(element.getParent());
newElement.setChildren(element.getChildren());
IFormElement parent = element.getParent();
int index = parent.getChildren().indexOf(element);
parent.getChildren().remove(element);
parent.getChildren().add(index, newElement);
if(newElement.getControlNode() != null){
if(newElement instanceof GroupDef){
newElement.getControlNode().setAttribute(XformConstants.ATTRIBUTE_NAME_ID, newElement.getControlNode().getAttribute(XformConstants.ATTRIBUTE_NAME_BIND));
newElement.getControlNode().removeAttribute(XformConstants.ATTRIBUTE_NAME_BIND);
newElement.getControlNode().removeAttribute("mediatype");
}
else{
assert(newElement instanceof QuestionDef);
newElement.getControlNode().setAttribute(XformConstants.ATTRIBUTE_NAME_BIND, newElement.getControlNode().getAttribute(XformConstants.ATTRIBUTE_NAME_ID));
newElement.getControlNode().removeAttribute(XformConstants.ATTRIBUTE_NAME_ID);
newElement.getControlNode().removeAttribute("mediatype");
}
}
}
/**
* @see org.openrosa.client.controller.IFormChangeListener#onDeleteChildren(Object)
*/
public void onDeleteChildren(Object formItem){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return; //How can this happen?
if(formItem instanceof QuestionDef){
while(item.getChildCount() > 0){
deleteItem((TreeModelItem)item.getChild(0));
}
}else if (formItem instanceof GroupDef){
for(int i=0;i<((GroupDef)formItem).getChildCount();i++){
deleteItem((TreeModelItem)item.getChild(0));
}
treePanel.getSelectionModel().select(item, false);
}
}
/**
* @see org.openrosa.client.controller.IFormActionListener#cutItem()
*/
public void cutItem(){
if(inReadOnlyMode())
return;
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
clipboardItem = item.getUserObject();
inCutMode = true;
deleteSelectedItem();
inCutMode = false;
}
/**
* @see org.openrosa.client.controller.IFormActionListener#copyItem()
*/
public void copyItem() {
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
clipboardItem = item.getUserObject();
}
/**
* @see org.openrosa.client.controller.IFormActionListener#pasteItem()
*/
public void pasteItem(){
if(inReadOnlyMode())
return;
//Check if we have anything in the clipboard.
if(clipboardItem == null)
return;
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null){
if(clipboardItem instanceof FormDef)
this.loadForm((FormDef)clipboardItem, true, false);
return;
}
Object userObj = item.getUserObject();
String message = "The clipboard item cannot be pasted as a child of the selected item";
if(clipboardItem instanceof QuestionDef){
//Questions can be pasted only as kids of pages or repeat questions.
if(! ( (userObj instanceof GroupDef) || userObj instanceof FormDef ||
(userObj instanceof QuestionDef && ((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_REPEAT) )){
Window.alert(message);
return;
}
//create a copy of the clipboard question.
QuestionDef questionDef = new QuestionDef((QuestionDef)clipboardItem,(IFormElement)userObj);
//Repeat question can only be child of a page but not another question.
if(questionDef.getDataType() == QuestionDef.QTN_TYPE_REPEAT && userObj instanceof QuestionDef)
return;
questionDef.setId(item.getChildCount()+1);
/*if(userObj instanceof GroupDef)
((GroupDef)userObj).addChild(questionDef);
else
((QuestionDef)userObj).getRepeatQtnsDef().addQuestion(questionDef);*/
((IFormElement)userObj).addChild(questionDef);
item = loadQuestion(questionDef, item);
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(item, false);
//item.getParentItem().setState(true);
//item.setState(true);
}
else if(clipboardItem instanceof GroupDef){
//Pages can be pasted only as kids of forms.
if(!(userObj instanceof FormDef)){
Window.alert(message);
return;
}
//create a copy of the clipboard page.
GroupDef pageDef = new GroupDef((GroupDef)clipboardItem,(FormDef)userObj);
pageDef.setId(item.getChildCount()+1);
((IFormElement)userObj).addChild(pageDef);
item = loadGroup(pageDef, item);
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(item, false);
//item.getParentItem().setState(true);
//item.setState(true);
}
else if(clipboardItem instanceof OptionDef){
//Question options can be pasted only as kids of single and multi select questions.
if(!(userObj instanceof QuestionDef
&& (((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE)||
((QuestionDef)userObj).getDataType() == QuestionDef.QTN_TYPE_LIST_MULTIPLE)){
Window.alert(message);
return;
}
// create a copy of the clipboard page.
OptionDef optionDef = new OptionDef((OptionDef)clipboardItem,(QuestionDef)userObj);
optionDef.setId(item.getChildCount()+1);
((QuestionDef)userObj).addOption(optionDef);
//item = addImageItem(item, optionDef.getText(), images.markRead(),optionDef,null);
item = addImageItem(item, Itext.getDisplayText(optionDef),optionDef);
//tree.setSelectedItem(item);
treePanel.getSelectionModel().select(item, false);
//item.getParentItem().setState(true);
//item.setState(true);
}
else
Window.alert(message);
}
// public void refreshItem(){
// if(inReadOnlyMode())
// return;
//
// formDesignerListener.refresh(this);
// }
// /**
// * @see org.openrosa.client.controller.IFormDesignerListener#saveForm()
// */
// public void saveItem(){
// formDesignerListener.saveForm();
// }
/**
* Gets the selected form.
*
* @return the selected form.
*/
public FormDef getFormDef(){
return formDef; //we always have one form in openrosa form designer.
/*TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item != null)
return getSelectedForm(item);
return null;*/
}
/**
* Gets the form to which the selected tree item belongs.
*
* @param item the tree item.
* @return the form definition object.
*/
private FormDef getSelectedForm(TreeModelItem item){
Object obj = item.getUserObject();
if(obj instanceof FormDef)
return (FormDef)obj;
return getSelectedForm((TreeModelItem)item.getParent());
}
private TreeModelItem getSelectedItemRoot(TreeModelItem item){
if(item == null)
return null;
if(item.getParent() == null)
return item;
return getSelectedItemRoot((TreeModelItem)item.getParent());
}
/**
* Removes all forms.
*/
public void clear(){
//tree.clear();
treePanel.getStore().removeAll();
}
// /**
// * Checks if the selected form is valid for saving.
// *
// * @return true if valid, else false.
// */
// public boolean isValidForm(){
// TreeModelItem parent = getSelectedItemRoot((TreeModelItem)treePanel.getSelectionModel().getSelectedItem());
// if(parent == null)
// return true;
//
// Map<String,String> pageNos = new HashMap<String,String>();
// Map<String,QuestionDef> bindings = new HashMap<String,QuestionDef>();
// int count = parent.getChildCount();
// for(int index = 0; index < count; index++){
// /*TreeModelItem child = (TreeModelItem)parent.getChild(index);
// GroupDef pageDef = (GroupDef)child.getUserObject();
// String pageNo = String.valueOf(pageDef.getPageNo());
// if(pageNos.containsKey(pageNo)){
// //tree.setSelectedItem(child);
// //tree.ensureSelectedItemVisible();
// treePanel.getSelectionModel().select(child, false);
// Window.alert(LocaleText.get("selectedPage") + pageDef.getName() +LocaleText.get("shouldNotSharePageBinding") + pageNos.get(pageNo)+ "]");
// return false;
// }
// else
// pageNos.put(pageNo, pageDef.getName());
//
// if(!isValidQuestionList(child,bindings))
// return false;*/
// }
//
// return true;
// }
private boolean isValidQuestionList(TreeModelItem parent,Map<String,QuestionDef> bindings){
int count = parent.getChildCount();
for(int index = 0; index < count; index++){
TreeModelItem child = (TreeModelItem)parent.getChild(index);
QuestionDef questionDef = (QuestionDef)child.getUserObject();
String variableName = questionDef.getQuestionID();
if(bindings.containsKey(variableName) /*&& questionDef.getParent() == bindings.get(variableName).getParent()*/){
//tree.setSelectedItem(child);
//tree.ensureSelectedItemVisible();
treePanel.getSelectionModel().select(child, false);
Window.alert(LocaleText.get("selectedQuestion") + questionDef.getText()+LocaleText.get("shouldNotShareQuestionBinding") + bindings.get(variableName).getDisplayText()+ "]");
return false;
}
else
bindings.put(variableName, questionDef);
if(questionDef.getDataType() == QuestionDef.QTN_TYPE_REPEAT){
if(!isValidQuestionList(child,bindings))
return false;
}
else if(questionDef.getDataType() == QuestionDef.QTN_TYPE_LIST_EXCLUSIVE ||
questionDef.getDataType() == QuestionDef.QTN_TYPE_LIST_MULTIPLE){
if(!isValidOptionList(child))
return false;
}
}
return true;
}
private boolean isValidOptionList(TreeModelItem parent){
Map<String,String> bindings = new HashMap<String,String>();
int count = parent.getChildCount();
for(int index = 0; index < count; index++){
TreeModelItem child = (TreeModelItem)parent.getChild(index);
OptionDef optionDef = (OptionDef)child.getUserObject();
String variableName = optionDef.getQuestionID();
if(bindings.containsKey(variableName)){
//tree.setSelectedItem(child);
//tree.ensureSelectedItemVisible();
treePanel.getSelectionModel().select(child, false);
Window.alert(LocaleText.get("selectedOption") + optionDef.getText()+LocaleText.get("shouldNotShareOptionBinding") + bindings.get(variableName)+ "]");
return false;
}
else
bindings.put(variableName, optionDef.getText());
}
return true;
}
/**
* @see org.openrosa.client.controller.IFormActionListener#moveUp()
*/
public void moveUp(){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
int index;
TreeModelItem parent = (TreeModelItem)item.getParent();
if(parent == null){
index = getRootItemIndex(parent);
if(index == 0)
return;
//tree.setSelectedItem(tree.getItem(index - 1));
treePanel.getSelectionModel().select(treePanel.getStore().getChild(index - 1), false);
}
else{
index = parent.indexOf(item);
if(index == 0)
return;
//tree.setSelectedItem(parent.getChild(index - 1));
treePanel.getSelectionModel().select(parent.getChild(index - 1), false);
}
}
/**
* @see org.openrosa.client.controller.IFormActionListener#moveDown()
*/
public void moveDown(){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
int index;
TreeModelItem parent = (TreeModelItem)item.getParent();
if(parent == null){
index = getRootItemIndex(parent);
if(index == treePanel.getStore().getChildCount() - 1)
return;
//tree.setSelectedItem(tree.getItem(index + 1));
treePanel.getSelectionModel().select(treePanel.getStore().getChild(index + 1), false);
}
else{
index = parent.indexOf(item);
if(index == parent.getChildCount() - 1)
return;
//tree.setSelectedItem(parent.getChild(index + 1));
treePanel.getSelectionModel().select(parent.getChild(index + 1), false);
}
}
/**
* Selected the parent of the selected item.
*/
public void moveToParent(){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
TreeModelItem parent = (TreeModelItem)item.getParent();
if(parent == null)
return;
treePanel.getSelectionModel().select(parent, false);
//tree.ensureSelectedItemVisible();
}
/**
* Selects the child of the selected item.
*/
public void moveToChild(){
TreeModelItem item = (TreeModelItem)treePanel.getSelectionModel().getSelectedItem();
if(item == null)
return;
if(item.getChildCount() == 0){
addNewChildItem(false);
return;
}
TreeModelItem child = (TreeModelItem)item.getChild(0);
treePanel.getSelectionModel().select(child, false);
//tree.ensureSelectedItemVisible();
}
/**
* Checks if the selected form is in read only mode. In read only mode
* we can only change the text and help text of items.
*
* @return true if in read only mode, else false.
*/
private boolean inReadOnlyMode(){
return Context.isStructureReadOnly();
}
public void dragMove(TreeModelItem item, int direction){
if(inReadOnlyMode()){return;}
//Check if there is any selection.
if(item == null){return;}
TreeModelItem parent = (TreeModelItem)item.getParent();
//We don't move root node (which has no parent, that is the form itself, since we design one form at a time)
if(parent == null){return;}
//One item can't move against itself.
int count = parent.getChildCount();
if(count == 1){ return; }
int index = parent.indexOf(item);
if(direction == DRAG_MOVE_UP){
if(index == 0){ return; }//Can't move any further upwards.
moveFormItemUp(item,parent);
}else if(direction == DRAG_MOVE_DOWN){
if(index == count - 1){return;} //Can't move any further downwards.
moveFormItemDown(item,parent);
}
}
public AbstractImagePrototype getIcon(TreeModelItem model){
ImageResource imageResource = images.newform();
int type = ((IFormElement)model.getUserObject()).getDataType();
if(type == QuestionDef.QTN_TYPE_GROUP)
imageResource = images.note();
else if(type == QuestionDef.QTN_TYPE_REPEAT)
imageResource = images.drafts();
return AbstractImagePrototype.create(imageResource);
}
@Override
public void refreshItem() {
// TODO Auto-generated method stub
}
}