package net.sf.egonet.web.panel; import java.util.ArrayList; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxFallbackLink; import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton; import net.sf.egonet.web.component.TextField; import net.sf.egonet.model.AnswerListMgr; import net.sf.egonet.model.NameAndValue; public class OptionsListEditPanel extends Panel { private Long studyId; private Form outerForm; private Form titlesForm; private Form optionsForm; private Form editOptionForm; private WebMarkupContainer editOptionContainer; private ArrayList<String> listPresetTitles; private ArrayList<NameAndValue> listOptionNames; // for the Currently Selected preset private String strCurrentListTitle; private ListView lvPresetTitles; private ListView lvPresetOptionNames; private Label lblTitle; private String newTitle; private String newOptionName; private Integer newOptionValue; private String editOptionName; private String editOptionOldName; private Integer editOptionValue; private Integer editOptionOldValue; private TextField textNewTitle; private TextField textNewOptionName; private TextField textNewOptionValue; private TextField textEditOptionName; private TextField textEditOptionValue; /** * constructor * @param id string for wicket indentification * @param studyId the study we are dealing with, each study will have its * own set of sets of preset options */ public OptionsListEditPanel ( String id, Long studyId) { super(id); this.studyId = studyId; AnswerListMgr.loadAnswerListsForStudy(this.studyId); listPresetTitles = AnswerListMgr.getTitlesAsList(studyId); if ( !listPresetTitles.isEmpty() ) { strCurrentListTitle = listPresetTitles.get(0); setListOptionNames( AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); } setNewTitle("(new title)"); setNewOptionName("(new name)"); setNewOptionValue(0); build(); } /** * constructs the java objects and binds them to the associated * HTML file using the wicket ID strings */ private void build() { outerForm = new Form("outerForm"); titlesForm = new Form("titlesForm"); optionsForm = new Form("optionsForm"); editOptionForm = new Form("editOptionForm"); titlesForm.setOutputMarkupId(true); optionsForm.setOutputMarkupId(true); editOptionForm.setOutputMarkupId(true); this.setOutputMarkupId(true); //=========================================================== // Construct the form that fills the table on the left, // that will have the // names of the preset options lists lvPresetTitles = new ListView ("presetTitlesList", new PropertyModel(this,"listPresetTitles")) { protected void populateItem(final ListItem item) { final String strPresetName = item.getModelObjectAsString(); // add the link that will pull values for this list // up on the right side Link presetTitleLink = new AjaxFallbackLink("presetTitleLink") { public void onClick(AjaxRequestTarget target) { setStrCurrentListTitle(strPresetName); setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); target.addComponent(titlesForm); target.addComponent(optionsForm); editOptionForm.setVisible(false); } }; presetTitleLink.add(new Label("presetTitle", strPresetName)); item.add(presetTitleLink); // add the link that will delete this list Link deleteTitleLink = new AjaxFallbackLink("deleteTitleLink") { public void onClick(AjaxRequestTarget target) { if (deleteTitle(strPresetName)) { target.addComponent(titlesForm); target.addComponent(optionsForm); } editOptionForm.setVisible(false); } }; deleteTitleLink.add(new Label("deleteTitle", "delete")); item.add(deleteTitleLink); }; }; lvPresetTitles.setOutputMarkupId(true); titlesForm.add(lvPresetTitles); // add the text field users can enter the name of a new group textNewTitle = new TextField("newTitleEntry", new PropertyModel(this, "newTitle"), String.class); textNewTitle.setOutputMarkupId(true); titlesForm.add(textNewTitle); // add the button to add a new title - a new list AjaxFallbackButton btnAddTitle = new AjaxFallbackButton ("btnAddTitle",titlesForm) { protected void onSubmit ( AjaxRequestTarget target, Form f) { if ( addNewTitle()) { target.addComponent(titlesForm); target.addComponent(optionsForm); } editOptionForm.setVisible(false); } }; titlesForm.add(btnAddTitle); // ======================================================================= // now create the middle form that will have a table listing all the // option names for the selected group of presets // the 'title' over the middle lblTitle = new Label ("valuesTitle", new PropertyModel(this, "strCurrentListTitle")); lblTitle.setOutputMarkupId(true); optionsForm.add(lblTitle); // construct the table on the right, that will have the // values available for the currently selected preset list lvPresetOptionNames = new ListView ("presetNamesList", new PropertyModel(this, "listOptionNames")) { protected void populateItem(final ListItem item) { final NameAndValue nameAndValue = (NameAndValue)(item.getModelObject()); final String strName = nameAndValue.getName(); final String strValue = nameAndValue.getValue().toString(); item.add(new Label("presetName", strName)); item.add(new Label("presetValue", strValue)); // add the link that will delete this value Link deleteValueLink = new AjaxFallbackLink("deleteValueLink") { public void onClick(AjaxRequestTarget target) { if (deleteValue(strName,strValue)) target.addComponent(optionsForm); editOptionForm.setVisible(false); } }; deleteValueLink.add(new Label("deleteValue", "delete")); item.add(deleteValueLink); // add the link that will move this value up one // this will be used to reorganize value lists Link moveValueLink = new AjaxFallbackLink ("moveUpLink") { public void onClick(AjaxRequestTarget target) { if (moveUpValue(strName, strValue)) target.addComponent(optionsForm); editOptionForm.setVisible(false); } }; moveValueLink.add(new Label("moveUp", "Move Up")); item.add(moveValueLink); // this link will be used for editing, // it will make the edit form on the far right visible Link editOptionLink = new AjaxFallbackLink("editOptionLink") { public void onClick(AjaxRequestTarget target) { editOptionForm.setVisible(true); beginEdit(strName, strValue); target.addComponent(editOptionForm); target.addComponent(editOptionContainer); } }; editOptionLink.add(new Label("editOption","Edit")); item.add(editOptionLink); }; }; lvPresetOptionNames.setOutputMarkupId(true); optionsForm.add(lvPresetOptionNames); // now add the text edit field were // users can enter a new option name textNewOptionName = new TextField("textNewOptionName", new PropertyModel(this, "newOptionName"), String.class); textNewOptionName.setOutputMarkupId(true); optionsForm.add(textNewOptionName); textNewOptionValue = new TextField("textNewOptionValue", new PropertyModel(this, "newOptionValue"), Integer.class); textNewOptionValue.setOutputMarkupId(true); optionsForm.add(textNewOptionValue); // and the button that will take care of adding the // name entered in textNewOptionName to the current list AjaxFallbackButton btnAddOptionName = new AjaxFallbackButton("newValueButton",optionsForm) { protected void onSubmit ( AjaxRequestTarget target, Form f) { if ( addNewValue()) target.addComponent(optionsForm); editOptionForm.setVisible(false); } }; optionsForm.add(btnAddOptionName); // =================================================================== // construct the form on the far right side which will only // be visible when the user selects to edit an option name // the text edit box to edit an existing name editOptionContainer = new WebMarkupContainer("editOptionContainer"); editOptionContainer.setOutputMarkupId(true); textEditOptionName = new TextField("editOptionName", new PropertyModel(this, "editOptionName"), String.class); textEditOptionName.setOutputMarkupId(true); editOptionForm.add(textEditOptionName); textEditOptionValue = new TextField("editOptionValue", new PropertyModel(this, "editOptionValue"), Integer.class); textEditOptionValue.setOutputMarkupId(true); editOptionForm.add(textEditOptionValue); // and the button that will take care of adding the // name entered in textNewOptionName to the current list AjaxFallbackButton btnOkayEdit = new AjaxFallbackButton("btnOkayEdit",editOptionForm) { protected void onSubmit ( AjaxRequestTarget target, Form f) { endEdit(true); editOptionForm.setVisible(false); target.addComponent(optionsForm); target.addComponent(editOptionForm); target.addComponent(editOptionContainer); } }; btnOkayEdit.setOutputMarkupId(true); editOptionForm.add(btnOkayEdit); // and the button that will take care of adding the // name entered in textNewOptionName to the current list AjaxFallbackButton btnCancelEdit = new AjaxFallbackButton("btnCancelEdit",editOptionForm) { protected void onSubmit ( AjaxRequestTarget target, Form f) { endEdit(false); editOptionForm.setVisible(false); target.addComponent(optionsForm); target.addComponent(editOptionForm); target.addComponent(editOptionContainer); } }; btnCancelEdit.setOutputMarkupId(true); editOptionForm.add(btnCancelEdit); editOptionContainer.add(editOptionForm); editOptionForm.setVisible(false); // add the Save button below the table AjaxFallbackButton btnSave = new AjaxFallbackButton("saveButton",outerForm) { protected void onSubmit ( AjaxRequestTarget target, Form f) { saveAllEdits(); } }; btnSave.setOutputMarkupId(true); // add all three forms to the page outerForm.add(titlesForm); outerForm.add(optionsForm); outerForm.add(editOptionContainer); outerForm.add(btnSave); add(outerForm); } /** * reacts to 'add' in the title table getting clicked * to create a new list of words * @return true if newTitleEntry text box contains a non-empty * string that is not already in the list of titles */ private boolean addNewTitle() { if ( newTitle==null ) return(false); newTitle = newTitle.trim(); if ( newTitle.length()==0) return(false); if ( !AnswerListMgr.addTitle(newTitle, studyId)) { setNewTitle(""); return(false); } setStrCurrentListTitle(newTitle); listPresetTitles = AnswerListMgr.getTitlesAsList(studyId); setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); setNewTitle(""); return(true); } /** * deletes the list of presets specified by the name strTitle * @param strTitle the name of the list to delete * @return true if deletion takes place false otherwise */ private boolean deleteTitle(String strTitle) { int index; if ( strTitle==null || strTitle.length()==0) return(false); index = AnswerListMgr.removeTitle(strTitle, studyId); if ( index<0 ) return(false); listPresetTitles = AnswerListMgr.getTitlesAsList(studyId); // if the list we deleted is the currently display one // need to do extra work to display a different one... if (strCurrentListTitle.equals(strTitle)) { // System.out.println ( "strCurrentListTitle=" + strCurrentListTitle); // System.out.println ( "strTitle=" + strTitle); if (index<0 || index>listPresetTitles.size()) { index = listPresetTitles.size()-1; } if ( listPresetTitles.size()==0 ) { setStrCurrentListTitle(""); setListOptionNames(new ArrayList<NameAndValue>(0)); } else { setStrCurrentListTitle( listPresetTitles.get(index)); setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); } } return(true); } /** * reacts to 'add' in the values table getting clicked * to add a word to the current list of words * @return true if newValueEntry text box contains a non-empty * string that is not already in the list of values for the * current list */ private boolean addNewValue() { if ( newOptionName==null ) return(false); newOptionName = newOptionName.trim(); if ( newOptionName.length()==0) return(false); if ( newOptionValue==null ) newOptionValue = new Integer(0); if ( !AnswerListMgr.addOptionName(strCurrentListTitle, studyId, newOptionName, newOptionValue)) { setNewOptionName(""); return(false); } setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); setNewOptionName(""); return(true); } /** * deletes a value from the list of presets currently dealt with * @param strValue the value to delete * @return true if deletion takes place, false otherwise */ private boolean deleteValue(String strName, String strValue) { Integer value; if ( strName==null || strValue==null || strName.length()==0 || strValue.length()==0 ) return(false); try { value = Integer.parseInt(strValue); } catch ( NumberFormatException nfe) { System.out.println ( "OptionsListEditPanel.deleteValue " + strValue + " invalid integer"); value = 0; } if ( !AnswerListMgr.removeOptionName(strCurrentListTitle, studyId, strName, value)) return(false); setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); return(true); } /** * responds to the 'move up' link so users can rearrange * lists of option values * @param strValue the string values to move up in the list * @return true if the string is found and moved, false otherwise */ private boolean moveUpValue(String strName, String strValue) { Integer value; if ( strName==null || strValue==null || strName.length()==0 || strValue.length()==0 ) return(false); try { value = Integer.parseInt(strValue); } catch ( NumberFormatException nfe) { System.out.println ( "OptionsListEditPanel.moveUpValue " + strValue + " invalid integer"); value = 0; } if ( !AnswerListMgr.moveOptionNameUp(strCurrentListTitle, studyId, strName, value)) return(false); setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); return(true); } /** * responds to an edit link for an option name getting clicked, * brings the option name into the edit field as the edit panel * is made visible * @param strValue the option Name to edit * @return true */ private boolean beginEdit(String strName, String strValue) { editOptionOldName = strName; try { editOptionOldValue = Integer.parseInt(strValue); } catch ( NumberFormatException nfe ) { editOptionOldValue = 0; } setEditOptionName(strName); setEditOptionValue(editOptionOldValue); return(true); } /** * called when the edit panel is closed * @param save if true we want to use the new string value, * if false discard. * as this function is called the editOptionPanel will * be made invisible again. * @return true */ private boolean endEdit(boolean save) { if ( save ) { if ( AnswerListMgr.replaceOptionName(strCurrentListTitle, studyId, editOptionOldName, editOptionOldValue, editOptionName, editOptionValue )) setListOptionNames(AnswerListMgr.getOptionNamesAsList(strCurrentListTitle, studyId)); } return(true); } /** * save all the changes performed on this page * @return true */ private boolean saveAllEdits() { boolean bRetVal; bRetVal = AnswerListMgr.saveAllAnswerListsForStudy(studyId); return(bRetVal); } /** * getters/setters */ public void setStrCurrentListTitle( String strCurrentListTitle ) { this.strCurrentListTitle = strCurrentListTitle; } public String getStrCurrentListTitle() { return(strCurrentListTitle); } public void setEditOptionName ( String editOptionName ) { this.editOptionName = editOptionName; } public String getEditOptionName() { return(editOptionName); } public void setEditOptionValue ( Integer editOptionValue ) { this.editOptionValue = editOptionValue; } public Integer getEditOptionValue() { return(editOptionValue); } public void setListOptionNames ( ArrayList<NameAndValue> listOptionNames ) { this.listOptionNames = listOptionNames; } public ArrayList<NameAndValue> getListOptionNames() { return(listOptionNames); } public void setNewTitle ( String newTitle ) { this.newTitle = newTitle; } public String getNewTitle() { return(newTitle); } public void setNewOptionName ( String newOptionName ) { this.newOptionName = (newOptionName==null) ? "" : newOptionName; } public String getNewOptionName() { return(newOptionName); } public void setNewOptionValue ( Integer newOptionValue ) { this.newOptionValue = (newOptionValue==null) ? 0 : newOptionValue; } public Integer getNewOptionValue () { return(newOptionValue); } }