/**
*
*/
package net.frontlinesms.plugins.forms.ui;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import thinlet.Thinlet;
import net.frontlinesms.FrontlineSMSConstants;
import net.frontlinesms.csv.CsvExporter;
import net.frontlinesms.data.domain.Contact;
import net.frontlinesms.data.domain.Group;
import net.frontlinesms.data.repository.ContactDao;
import net.frontlinesms.data.repository.GroupMembershipDao;
import net.frontlinesms.events.EventObserver;
import net.frontlinesms.events.FrontlineEventNotification;
import net.frontlinesms.plugins.forms.FormsPluginController;
import net.frontlinesms.plugins.forms.csv.CsvFormExporter;
import net.frontlinesms.plugins.forms.data.domain.*;
import net.frontlinesms.plugins.forms.data.repository.*;
import net.frontlinesms.plugins.forms.ui.components.*;
import net.frontlinesms.plugins.BasePluginThinletTabController;
import net.frontlinesms.ui.FileChooser;
import net.frontlinesms.ui.Icon;
import net.frontlinesms.ui.UiGeneratorController;
import net.frontlinesms.ui.events.TabChangedNotification;
import net.frontlinesms.ui.handler.ComponentPagingHandler;
import net.frontlinesms.ui.handler.PagedComponentItemProvider;
import net.frontlinesms.ui.handler.PagedListDetails;
import net.frontlinesms.ui.handler.contacts.GroupSelecterDialog;
import net.frontlinesms.ui.handler.contacts.SingleGroupSelecterDialogOwner;
import net.frontlinesms.ui.i18n.InternationalisationUtils;
import net.frontlinesms.ui.i18n.TextResourceKeyOwner;
/**
* Thinlet controller class for the FrontlineSMS Forms plugin.
* @author Alex
*/
@TextResourceKeyOwner(prefix={"I18N_", "COMMON_", "SENTENCE_", "TOOLTIP_"})
public class FormsThinletTabController extends BasePluginThinletTabController<FormsPluginController> implements SingleGroupSelecterDialogOwner, PagedComponentItemProvider, EventObserver {
//> CONSTANTS
/** XML file containing forms pane for viewing results of a form */
protected static final String UI_FILE_RESULTS_VIEW = "/ui/plugins/forms/formsTab_resultsView.xml";
/** XML file containing dialog for exporting form data */
private static final String UI_FILE_FORM_EXPORT_DIALOG = "/ui/plugins/forms/formExportDialogForm.xml";
/** XML file containing dialog for choosing which contacts to send a form to */
private static final String XML_CHOOSE_CONTACTS = "/ui/plugins/forms/dgChooseContacts.xml";
/** Component name of the forms list */
private static final String FORMS_LIST_COMPONENT_NAME = "formsList";
//> I18N KEYS
/** i18n key: "Form Name" */
static final String I18N_KEY_FORM_NAME = "plugins.forms.editor.name.label";
/** i18n key: "Form Editor" */
static final String I18N_KEY_FORMS_EDITOR = "plugins.forms.editor.title";
/** i18n key: "You have not entered a name for this form" */
static final String I18N_KEY_MESSAGE_FORM_NAME_BLANK = "plugins.forms.name.blank";
/** i18n key: "You will not be able to edit this form again." */
private static final String I18N_KEY_CONFIRM_FINALISE = "plugins.forms.send.finalise.confirm";
/** i18n key: "There are no contacts to notify." */
private static final String I18N_KEY_NO_CONTACTS_TO_NOTIFY = "plugins.forms.send.nocontacts";
private static final String I18N_KEY_SET_GROUP_BEFORE = "plugins.forms.set.group.before";
/** i18n key: "Form submitter" */
public static final String I18N_FORM_SUBMITTER = "plugins.forms.submitter";
/** i18n key: "Your form 'formname' has been sent to N contacts." */
private static final String I18N_FORM_SENT_DIALOG_MESSAGE = "plugins.forms.message.form.sent";
/** i18n key: "Currency field" */
public static final String I18N_FCOMP_CURRENCY = "plugins.forms.field.currency";
public static final String I18N_FCOMP_DROP_DOWN_LIST = "plugins.forms.field.dropdownlist";
public static final String I18N_FCOMP_NUMBER = "plugins.forms.field.number";
public static final String I18N_FCOMP_PASSWORD = "plugins.forms.field.password";
public static final String I18N_FCOMP_PHONENUMBER = "plugins.forms.field.phonenumber";
public static final String I18N_FCOMP_TEXT_AREA = "plugins.forms.field.textarea";
public static final String I18N_FCOMP_TEXT_FIELD = "plugins.forms.field.textfield";
public static final String I18N_FCOMP_CHECKBOX = "plugins.forms.field.checkbox";
public static final String I18N_FCOMP_TIME = "common.time";
public static final String I18N_FCOMP_TRUNCATED_TEXT = "plugins.forms.field.truncatedtext";
public static final String I18N_FCOMP_WRAPPED_TEXT = "plugins.forms.field.wrappedtext";
private static final String I18N_PLUGINS_FORMS_NOT_SET = "plugins.forms.not.set";
private static final String I18N_PLUGINS_FORMS_GROUP = "plugins.forms.group";
private static final String I18N_PLUGINS_FORMS_CHOOSE_GROUP = "plugins.forms.choose.group";
public static final String COMMON_PALETTE = "plugins.forms.palette";
public static final String COMMON_PREVIEW = "plugins.forms.preview";
public static final String COMMON_PROPERTY = "plugins.forms.property";
public static final String COMMON_VALUE = "plugins.forms.value";
public static final String TOOLTIP_DRAG_TO_REMOVE = "plugins.forms.tooltip.drag.to.remove";
public static final String TOOLTIP_DRAG_TO_PREVIEW = "plugins.forms.tooltip.drag.to.preview";
public static final String SENTENCE_DELETE_KEY = "plugins.forms.sentence.delete.key";
public static final String SENTENCE_UP_KEY = "plugins.forms.sentence.up.key";
public static final String SENTENCE_DOWN_KEY = "plugins.forms.sentence.down.key";
private static final String MESSAGE_NO_FILENAME = "message.filename.blank";
private static final String MESSAGE_EXPORT_TASK_SUCCESSFUL = "message.export.successful";
private static final String MESSAGE_EXPORT_TASK_FAILED = "message.export.failed";
private static final String MESSAGE_BAD_DIRECTORY = "message.bad.directory";
private static final String MESSAGE_CONFIRM_FILE_OVERWRITE = "message.file.overwrite.confirm";
private static final Object UI_FORM_TAB_NAME = ":forms";
//> INSTANCE PROPERTIES
/** DAO for {@link Contact}s */
private ContactDao contactDao;
/** DAO for {@link Form}s */
private FormDao formsDao;
/** DAO for {@link FormResponse}s */
private FormResponseDao formResponseDao;
/** DAO for getting {@link Contact}s in {@link Group}s */
private GroupMembershipDao groupMembershipDao;
/** UI table displaying the results. */
private Object formResultsComponent;
/** Paging handler for the results component */
private ComponentPagingHandler formResponseTablePageControls;
private Object exportDialog;
//> CONSTRUCTORS
public FormsThinletTabController(FormsPluginController pluginController, UiGeneratorController ui) {
super(pluginController, ui);
this.ui.getFrontlineController().getEventBus().registerObserver(this);
}
//> INSTANCE METHODS
/** Refresh the tab's display. */
public void refresh() {
Object formList = getFormsList();
// If there was something selected previously, we will attempt to select it again after updating the list
Object previousSelectedItem = this.ui.getSelectedItem(formList);
Form previousSelectedForm = previousSelectedItem == null ? null : this.getForm(previousSelectedItem);
ui.removeAll(formList);
Object newSelectedItem = null;
for(Form f : formsDao.getAllForms()) {
Object formNode = getNode(f);
ui.add(formList, formNode);
if (previousSelectedForm != null && f.getFormMobileId() == previousSelectedForm.getFormMobileId()) {
newSelectedItem = formNode;
}
}
// Restore the selected item
if(newSelectedItem != null) {
this.ui.setSelectedItem(formList, newSelectedItem);
}
// We should enable or disable buttons as appropriate
formsList_selectionChanged();
}
//> THINLET EVENT METHODS
public void showFormsPluginInfo() {
FormsAboutDialogHandler.createAndShow(this.ui, this.getPluginController());
}
/** Show the dialog for exporting form results. */
public void showFormExportDialog() {
exportDialog = ui.loadComponentFromFile(UI_FILE_FORM_EXPORT_DIALOG, this);
ui.add(exportDialog);
}
public void showSaveModeFileChooser (Object textFieldToBeSet) {
this.ui.showFileChooser(textFieldToBeSet);
}
/** Show the AWT Forms Editor window */
public void showFormsEditor() {
VisualForm form = new VisualForm();
form = FormsUiController.getInstance().showFormsEditor(ui.getFrameLauncher(), form);
if (form != null) {
saveFormInformation(form);
}
}
public void removeSelected(Object component) {
Object[] selected = this.ui.getSelectedItems(component);
if(selected != null) {
for(Object selectedComponent : selected) {
this.ui.remove(selectedComponent);
}
}
}
/**
* Calls the export method according to the supplied information,
* and the user selection.
*
* @param aggregate
* @param dataPath
* @param exportDialog
*/
public void formsTab_exportResults(String dataPath) {
if (!dataPath.contains(File.separator) || !(new File(dataPath.substring(0, dataPath.lastIndexOf(File.separator))).isDirectory())) {
this.ui.alert(InternationalisationUtils.getI18NString(MESSAGE_BAD_DIRECTORY));
} else if (dataPath.substring(dataPath.lastIndexOf(File.separator), dataPath.length()).equals(File.separator)) {
this.ui.alert(InternationalisationUtils.getI18NString(MESSAGE_NO_FILENAME));
} else {
log.debug("Filename is [" + dataPath + "] before [" + CsvExporter.CSV_EXTENSION + "] check.");
if (!dataPath.endsWith(CsvExporter.CSV_EXTENSION)) {
dataPath += CsvExporter.CSV_EXTENSION;
}
log.debug("Filename is [" + dataPath + "] after [" + CsvExporter.CSV_EXTENSION + "] check.");
File csvFile = new File(dataPath);
if(csvFile.exists() && csvFile.isFile()) {
// Show confirmation dialog
ui.showConfirmationDialog("doExport('" + dataPath + "')", this, MESSAGE_CONFIRM_FILE_OVERWRITE);
} else {
doExport(dataPath);
}
}
}
public void doExport(String filename) {
Object formsList = find("formsList");
Form selectedForm = getForm(ui.getSelectedItem(formsList));
if (selectedForm == null) return;
File file = new File(filename);
try {
CsvFormExporter.exportForm(file, selectedForm, contactDao, formResponseDao);
this.ui.setStatus(InternationalisationUtils.getI18NString(MESSAGE_EXPORT_TASK_SUCCESSFUL));
}
catch (IOException e) {
log.debug(InternationalisationUtils.getI18NString(MESSAGE_EXPORT_TASK_FAILED), e);
this.ui.alert(InternationalisationUtils.getI18NString(MESSAGE_EXPORT_TASK_FAILED));
} finally {
removeDialog(exportDialog);
}
}
/**
* Called when the user has selected a different item on the forms tree.
* @param formsList
*/
public void formsList_selectionChanged() {
Form selectedForm = getForm(ui.getSelectedItem(getFormsList()));
if (selectedForm != null && selectedForm.isFinalised()) {
showResultsPanel(selectedForm);
} else {
//Nothing selected
Object pnRight = find("pnRight");
ui.removeAll(pnRight);
}
enableMenuOptions(find("formsList_toolbar"));
}
/**
* Show the GUI to edit a form.
* @param list Reference to the Forms tree object.
*/
public void formsList_editSelected() {
Form selectedForm = getSelectedForm();
if (selectedForm != null && !selectedForm.isFinalised()) {
VisualForm visualForm = VisualForm.getVisualForm(selectedForm);
List<PreviewComponent> old = new ArrayList<PreviewComponent>();
old.addAll(visualForm.getComponents());
visualForm = FormsUiController.getInstance().showFormsEditor(ui.getFrameLauncher(), visualForm);
if (visualForm != null) {
if (!visualForm.getName().equals(selectedForm.getName())) {
selectedForm.setName(visualForm.getName());
}
updateForm(old, visualForm.getComponents(), selectedForm);
formsList_selectionChanged();
}
}
}
/** Shows a selecter for assigning a {@link Group} to a {@link Form} */
public void formsList_showGroupSelecter() {
Form selectedForm = getSelectedForm();
log.info("FormsThinletTabController.showGroupSelecter() : " + selectedForm);
if(selectedForm != null) {
GroupSelecterDialog selecter = new GroupSelecterDialog(ui, this);
selecter.init(InternationalisationUtils.getI18NString(I18N_PLUGINS_FORMS_CHOOSE_GROUP), ui.getRootGroup());
selecter.show();
}
}
public void groupSelectionCompleted(Group group) {
// TODO Auto-generated method stub
Form form = getSelectedForm();
log.info("Form: " + form);
log.info("Group: " + group);
if(group != null) {
// Set the permitted group for this form, then save it
form.setPermittedGroup(group);
this.formsDao.updateForm(form);
this.refresh();
}
}
/**
* @param groupSelecter
* @param groupList
*/
public void setSelectedGroup(Object groupSelecter, Object groupList) {
Form form = getForm(groupSelecter);
log.info("Form: " + form);
Group group = ui.getGroup(ui.getSelectedItem(groupList));
log.info("Group: " + group);
if(group != null) {
// Set the permitted group for this form, then save it
form.setPermittedGroup(group);
this.formsDao.updateForm(form);
this.refresh();
removeDialog(groupSelecter);
}
}
/**
* Attempt to send the form selected in the forms list
* @param formsList the forms list component
*/
public void formsList_sendSelected() {
Form selectedForm = getSelectedForm();
if(selectedForm != null) {
// check the form has a group set
if(selectedForm.getPermittedGroup() == null) {
// The form has no group set, so we should explain that this needs to be done.
// FIXME i18n
ui.alert(InternationalisationUtils.getI18NString(I18N_KEY_SET_GROUP_BEFORE));
} else if(!selectedForm.isFinalised()) { // check the form is finalised.
// if form is not finalised, warn that it will be!
ui.showConfirmationDialog("showSendSelectionDialog", this, I18N_KEY_CONFIRM_FINALISE);
} else {
// show dialog for selecting group members to send the form to
showSendSelectionDialog();
}
}
}
/**
* Show dialog for selecting users to send a form to. If the form is not finalised, it will be
* finalised within this method.
*/
public void showSendSelectionDialog() {
ui.removeConfirmationDialog();
Form form = getSelectedForm();
if(form != null) {
// if form is not finalised, finalise it now
if(!form.isFinalised()) {
formsDao.finaliseForm(form);
this.refresh();
}
// show selection dialog for Contacts in the form's group
Object chooseContactsDialog = ui.loadComponentFromFile(XML_CHOOSE_CONTACTS, this);
ui.setAttachedObject(chooseContactsDialog, form);
// Add each contact in the group to the list. The user can then remove any contacts they don't
// want to be sent an SMS about the form at this time.
Object contactList = ui.find(chooseContactsDialog, "lsContacts");
for(Contact contact : this.groupMembershipDao.getActiveMembers(form.getPermittedGroup())) {
Object listItem = ui.createListItem(contact.getDisplayName(), contact);
ui.add(contactList, listItem);
}
ui.add(chooseContactsDialog);
}
}
/**
* Send a form to the contacts selected in the dialog.
* @param dgChooseContacts Dialog containing the contact selection
*/
public void sendForm(Object dgChooseContacts) {
// Work out which contacts we should be sending the form to
Object[] recipientItems = ui.getItems(ui.find(dgChooseContacts, "lsContacts"));
Form form = getForm(dgChooseContacts);
if(recipientItems.length == 0) {
// There are no contacts in the "send to" list. We should remove the dialog and inform the user
// of the problem.
ui.alert(InternationalisationUtils.getI18NString(I18N_KEY_NO_CONTACTS_TO_NOTIFY));
ui.removeDialog(dgChooseContacts);
} else {
HashSet<Contact> selectedContacts = new HashSet<Contact>();
for(Object o : recipientItems) {
Object attachment = ui.getAttachedObject(o);
if(attachment instanceof Contact) {
selectedContacts.add((Contact)attachment);
} else if(attachment instanceof Group) {
Group g = (Group)attachment;
selectedContacts.addAll(this.groupMembershipDao.getActiveMembers(g));
}
}
// Issue the send command to the plugin controller
this.getPluginController().sendForm(form, selectedContacts);
ui.alert(InternationalisationUtils.getI18NString(I18N_FORM_SENT_DIALOG_MESSAGE, form.getName(), Integer.toString(selectedContacts.size())));
ui.removeDialog(dgChooseContacts);
}
}
/** Finds the forms list and deletes the selected item. */
public void formsList_deleteSelected() {
Form selectedForm = getSelectedForm();
if(selectedForm != null) {
this.formsDao.deleteForm(selectedForm);
}
this.refresh();
// Now remove the confirmation dialog.
ui.removeConfirmationDialog();
}
/**
* Duplicates the selected form.
* @param formsList
*/
public void formsList_duplicateSelected() {
Form selected = getSelectedForm();
assert(selected != null) : "Duplicate Form button should not be enabled if there is no form selected!";
Form clone = new Form(selected.getName() + '*');
for (FormField oldField : selected.getFields()) {
FormField newField = new FormField(oldField.getType(), oldField.getLabel());
clone.addField(newField, oldField.getPositionIndex());
}
this.formsDao.saveForm(clone);
this.refresh();
}
/** Form selection has changed, so decide which toolbar and popup options should be available considering the current selection. */
public void formsTab_enabledFields(Object formsList_toolbar, Object formsList_popupMenu) {
enableMenuOptions(formsList_toolbar);
enableMenuOptions(formsList_popupMenu);
}
/**
* Enable menu options for the supplied menu component.
* @param menuComponent Menu component, a button bar or popup menu
* @param selectedComponent The selected object of the control that this menu applied to
*/
private void enableMenuOptions(Object menuComponent) {
Object selectedComponent = formsList_getSelected();
Form selectedForm = getForm(selectedComponent);
for (Object o : ui.getItems(menuComponent)) {
String name = ui.getName(o);
if(name != null) {
if (ui.getItems(getFormsList()).length == 0) {
ui.setVisible(o, (!name.startsWith("mi") && !name.startsWith("sp")) || name.endsWith("New"));
} else {
ui.setVisible(o, true);
if (name.contains("Delete")) {
// Tricky to remove the component for a form when the field is selected. If someone wants to
// solve that, they're welcome to enable delete here for FormFields
ui.setEnabled(o, ui.getAttachedObject(selectedComponent) instanceof Form);
} else if (name.contains("Edit")) {
ui.setEnabled(o, selectedForm != null && !selectedForm.isFinalised());
} else if (name.contains("New")) {
ui.setEnabled(o, true);
} else {
ui.setEnabled(o, selectedForm != null);
}
}
}
}
}
public PagedListDetails getListDetails(Object list, int startIndex, int limit) {
Form selectedForm = getSelectedForm();
int totalItemCount = this.formResponseDao.getFormResponseCount(selectedForm);
ArrayList<Object> responseRows = new ArrayList<Object>();
for (FormResponse response : formResponseDao.getFormResponses(selectedForm, startIndex, limit)) {
Object row = getRow(response);
responseRows.add(row);
}
return new PagedListDetails(totalItemCount, responseRows.toArray(new Object[0]));
}
/** Update the results for the selected form, taking into account the page number as well. */
public void formsTab_updateResults() {
this.formResponseTablePageControls.refresh();
}
/**
* Shows a confirmation dialog before calling a method. The method to be called
* is passed in as a string, and then called using reflection.
* @param methodToBeCalled
*/
public void showFormConfirmationDialog(String methodToBeCalled){
ui.showConfirmationDialog(methodToBeCalled, this);
}
//> THINLET EVENT HELPER METHODS
/** @return the {@link Form} selected in the {@link #getFormsList()}, or <code>null</code> if none is selected */
private Form getSelectedForm() {
Object selectedComponent = formsList_getSelected();
if(selectedComponent == null) return null;
else return getForm(selectedComponent);
}
/** @return gets the ui component selected in the forms list */
private Object formsList_getSelected() {
return this.ui.getSelectedItem(getFormsList());
}
/** @return the forms list component */
private Object getFormsList() {
return find(FormsThinletTabController.FORMS_LIST_COMPONENT_NAME);
}
/** Given a {@link VisualForm}, the form edit window, this saves its details. */
private void saveFormInformation(VisualForm visualForm) {
Form form = new Form(visualForm.getName());
for (PreviewComponent comp : visualForm.getComponents()) {
FormFieldType fieldType = FComponent.getFieldType(comp.getComponent().getClass());
FormField newField = new FormField(fieldType, comp.getComponent().getLabel());
form.addField(newField);
}
this.formsDao.saveForm(form);
this.refresh();
}
private void updateForm(List<PreviewComponent> old, List<PreviewComponent> newComp, Form form) {
//Let's remove from database the ones the user removed
List<PreviewComponent> toRemove = new ArrayList<PreviewComponent>();
for (PreviewComponent c : old) {
if (!newComp.contains(c)) {
form.removeField(c.getFormField());
toRemove.add(c);
}
}
// Compare the lists
for (PreviewComponent c : newComp) {
if (c.getFormField() != null) {
FormField ff = c.getFormField();
if (ff.getPositionIndex() != newComp.indexOf(c)) {
ff.setPositionIndex(newComp.indexOf(c));
}
ff.setLabel(c.getComponent().getLabel());
} else {
FormFieldType fieldType = FComponent.getFieldType(c.getComponent().getClass());
FormField newField = new FormField(fieldType, c.getComponent().getLabel());
form.addField(newField, newComp.indexOf(c));
}
}
this.formsDao.updateForm(form);
this.refresh();
}
/** Adds the result panel to the forms tab. */
private void addFormResultsPanel() {
Object pnRight = find("pnRight");
ui.removeAll(pnRight);
Object resultsView = ui.loadComponentFromFile(UI_FILE_RESULTS_VIEW, this);
formResultsComponent = ui.find(resultsView, "formResultsList");
this.formResponseTablePageControls = new ComponentPagingHandler(ui, this, this.formResultsComponent);
Object placeholder = ui.find(resultsView, "pageControlsPanel");
int index = ui.getIndex(ui.getParent(placeholder), placeholder);
ui.add(ui.getParent(placeholder), this.formResponseTablePageControls.getPanel(), index);
ui.remove(placeholder);
ui.add(pnRight, resultsView);
}
/**
* Adds the form results panel to the GUI, and refreshes it for the selected form.
* @param selected The form whose results should be displayed.
*/
private void showResultsPanel(Form selected) {
addFormResultsPanel();
Object pagePanel = find("pagePanel");
ui.setVisible(pagePanel, true);
Object pnResults = find("pnFormResults");
ui.setInteger(pnResults, "columns", 2);
form_createColumns(selected);
formsTab_updateResults();
ui.setEnabled(formResultsComponent, selected != null && ui.getItems(formResultsComponent).length > 0);
ui.setEnabled(find("btExportFormResults"), selected != null && ui.getItems(formResultsComponent).length > 0);
}
/**
* @param selectedComponent Screen component's selectedItem
* @return a {@link Form} if a form or formfield was selected, or <code>null</code> if none could be found
*/
private Form getForm(Object selectedComponent) {
Object selectedAttachment = ui.getAttachedObject(selectedComponent);
if (selectedAttachment == null
|| !(selectedAttachment instanceof Form)) {
// The selected item was not a form item, so probably was a child of that. Get it's parent, and check if that was a form instead
selectedAttachment = this.ui.getAttachedObject(this.ui.getParent(selectedComponent));
}
if (selectedAttachment == null
|| !(selectedAttachment instanceof Form)) {
// No form was found; return null
return null;
} else {
return (Form) selectedAttachment;
}
}
/**
* Gets {@link Thinlet} table row component for the supplied {@link FormResponse}
* @param response the {@link FormResponse} to represent as a table row
* @return row component to insert in a thinlet table
*/
private Object getRow(FormResponse response) {
Object row = ui.createTableRow(response);
Contact sender = contactDao.getFromMsisdn(response.getSubmitter());
String senderDisplayName = sender != null ? sender.getDisplayName() : response.getSubmitter();
ui.add(row, ui.createTableCell(senderDisplayName));
for (ResponseValue result : response.getResults()) {
ui.add(row, ui.createTableCell(result.toString()));
}
return row;
}
/**
* Creates a {@link Thinlet} tree node for the supplied form.
* @param form The form to represent as a node.
* @return node to insert in thinlet tree
*/
private Object getNode(Form form) {
log.trace("ENTER");
// Create the node for this form
log.debug("Form [" + form.getName() + "]");
Image icon = getIcon(form.isFinalised() ? FormIcon.FORM_FINALISED: FormIcon.FORM);
Object node = ui.createNode(form.getName(), form);
ui.setIcon(node, Thinlet.ICON, icon);
// Create a node showing the group for this form
Group g = form.getPermittedGroup();
String groupName = g == null ? InternationalisationUtils.getI18NString(I18N_PLUGINS_FORMS_NOT_SET) : g.getName();
Object groupNode = ui.createNode(InternationalisationUtils.getI18NString(I18N_PLUGINS_FORMS_GROUP, groupName), null);
ui.setIcon(groupNode, Icon.GROUP);
ui.add(node, groupNode);
for (FormField field : form.getFields()) {
Object child = ui.createNode(field.getLabel(), field);
ui.setIcon(child, Thinlet.ICON, getIcon(field.getType()));
ui.add(node, child);
}
log.trace("EXIT");
return node;
}
private void form_createColumns(Form selected) {
Object resultsTable = find("formResultsList");
Object header = Thinlet.get(resultsTable, Thinlet.HEADER);
ui.removeAll(header);
if (selected != null) {
// FIXME check if this constant can be removed from frontlinesmsconstants class
Object column = ui.createColumn(InternationalisationUtils.getI18NString(I18N_FORM_SUBMITTER), null);
ui.setWidth(column, 100);
ui.setIcon(column, Icon.PHONE_CONNECTED);
ui.add(header, column);
// For some reason we have a number column
int count = 0;
for (FormField field : selected.getFields()) {
if(field.getType().hasValue()) {
column = ui.createColumn(field.getLabel(), new Integer(++count));
ui.setInteger(column, "width", 100);
ui.setIcon(column, getIcon(field.getType()));
ui.add(header, column);
}
}
}
}
//> ACCESSORS
/**
* Set {@link FormDao}
* @param formsDao new value for {@link #formsDao}
*/
public void setFormsDao(FormDao formsDao) {
this.formsDao = formsDao;
}
/**
* Set {@link FormResponseDao}
* @param formResponseDao new value for {@link FormResponseDao}
*/
public void setFormResponseDao(FormResponseDao formResponseDao) {
this.formResponseDao = formResponseDao;
}
/**
* Set {@link #contactDao}
* @param contactDao new value for {@link #contactDao}
*/
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
//> TEMPORARY METHODS THAT NEED SORTING OUT
/**
* Gets an icon with the specified name.
* @param iconPath
* @return currently this returns <code>null</code> - needs to be implemented!
*/
private Image getIcon(String iconPath) {
return this.ui.getIcon(iconPath);
}
/**
* Gets the icon for a particular {@link FComponent}.
* @param fieldType
* @return icon to use for a particular {@link FComponent}.
*/
public Image getIcon(FormFieldType fieldType) {
if(fieldType == FormFieldType.CHECK_BOX) return getIcon(FormIcon.CHECKBOX);
if(fieldType == FormFieldType.CURRENCY_FIELD) return getIcon(FormIcon.CURRENCY_FIELD);
if(fieldType == FormFieldType.DATE_FIELD) return getIcon(FormIcon.DATE_FIELD);
if(fieldType == FormFieldType.EMAIL_FIELD) return getIcon(FormIcon.EMAIL_FIELD);
if(fieldType == FormFieldType.NUMERIC_TEXT_FIELD) return getIcon(FormIcon.NUMERIC_TEXT_FIELD);
if(fieldType == FormFieldType.PASSWORD_FIELD) return getIcon(FormIcon.PASSWORD_FIELD);
if(fieldType == FormFieldType.PHONE_NUMBER_FIELD) return getIcon(FormIcon.PHONE_NUMBER_FIELD);
if(fieldType == FormFieldType.TEXT_AREA) return getIcon(FormIcon.TEXT_AREA);
if(fieldType == FormFieldType.TEXT_FIELD) return getIcon(FormIcon.TEXT_FIELD);
if(fieldType == FormFieldType.TIME_FIELD) return getIcon(FormIcon.TIME_FIELD);
if(fieldType == FormFieldType.TRUNCATED_TEXT) return getIcon(FormIcon.TRUNCATED_TEXT);
if(fieldType == FormFieldType.WRAPPED_TEXT) return getIcon(FormIcon.WRAPPED_TEXT);
throw new IllegalStateException("No icon is mapped for field type: " + fieldType);
}
/**
* Set the DAO for this class
* @param groupMembershipDao
*/
public void setGroupMembershipDao(GroupMembershipDao groupMembershipDao) {
this.groupMembershipDao = groupMembershipDao;
}
/**
* Warn the user if he changes to another tab and has unsaved changes
*/
public void notify(FrontlineEventNotification notification) {
// This object is registered to the UIGeneratorController and get notified when the users changes tab
if(notification instanceof TabChangedNotification) {
String newTabName = ((TabChangedNotification) notification).getNewTabName();
if (newTabName.equals(UI_FORM_TAB_NAME)) {
this.refresh();
}
}
}
}