package org.openrosa.client.view;
import java.util.ArrayList;
import java.util.List;
import org.openrosa.client.model.FormDef;
import org.openrosa.client.model.IFormElement;
import org.openrosa.client.model.QuestionDef;
import org.openrosa.client.model.SkipRule;
import org.openrosa.client.PurcConstants;
import org.openrosa.client.controller.QuestionSelectionListener;
import org.openrosa.client.locale.LocaleText;
import org.openrosa.client.util.FormUtil;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Handles selection of multiple questions as targets for a given skip rule.
*
* @author daniel
*
*/
public class SkipQtnsDialog extends DialogBox {
/** Widget displaying list of all questions on the form. */
private ListBox lbAllQtns = new ListBox(true);
/** Widget displaying list of selected questions. */
private ListBox lbSelQtns = new ListBox(true);
/** Widget to select one or more questions. */
private Button btnSelect = new Button(">>");
/** Widget to remove one or more selected questions. */
private Button btnDeselect = new Button("<<");
/** Button to commit changes and close this dialog box. */
private Button btnOk = new Button(LocaleText.get("ok"));
/** Button to cancel changes, if any, and close this dialog box. */
private Button btnCancel = new Button(LocaleText.get("cancel"));
/** Main or root widget for this dialog box. */
private VerticalPanel mainPanel = new VerticalPanel();
/** Call back for communicating to interested parties
* when user has finished selecting questions. */
private QuestionSelectionListener qtnSelListener;
/**
* Creates a new instance of skip questions dialog box.
*/
public SkipQtnsDialog(QuestionSelectionListener qtnSelListener){
this.qtnSelListener = qtnSelListener;
lbAllQtns.setWidth("250"+PurcConstants.UNITS);
lbSelQtns.setWidth("250"+PurcConstants.UNITS);
lbAllQtns.setHeight("200"+PurcConstants.UNITS);
lbSelQtns.setHeight("200"+PurcConstants.UNITS);
setWidget(mainPanel);
setupHeaderLabels();
HorizontalPanel horzPanel = new HorizontalPanel();
horzPanel.add(lbAllQtns);
lbAllQtns.addChangeHandler(new ChangeHandler(){
public void onChange(ChangeEvent event){
btnSelect.setEnabled(true);
}
});
lbSelQtns.addChangeHandler(new ChangeHandler(){
public void onChange(ChangeEvent event){
btnDeselect.setEnabled(true);
}
});
setupSelectionButtons(horzPanel);
horzPanel.add(lbSelQtns);
horzPanel.setSpacing(5);
mainPanel.add(horzPanel);
setupOkCancelButtons();
mainPanel.setSpacing(5);
setText(LocaleText.get("otherQuestions"));
}
/**
* Sets the form and currently selected question for the skip rule.
*
* @param formDef the form definition object.
* @param questionDef the question definition object to which the skip rule is being set.
* @param skipRule the current skip rule.
*/
public void setData(FormDef formDef, IFormElement questionDef, SkipRule skipRule){
lbAllQtns.clear();
lbSelQtns.clear();
//for(int index = 0; index < formDef.getPageCount(); index++)
// loadPageQnts(formDef.getPageAt(index),questionDef,skipRule);
loadPageQnts(formDef.getChildren(), questionDef,skipRule);
if(skipRule != null && skipRule.getActionTargets() != null)
loadSelQuestions(formDef, questionDef, skipRule.getActionTargets());
}
/**
* Loads a list of selected questions in the selected questions list box.
*
* @param formDef the form definition object.
* @param questionDef the question definition object to which the skip rule is being set.
* @param selQuestions the selected questions list.
*/
private void loadSelQuestions(FormDef formDef, IFormElement questionDef, List<Integer> selQuestions){
for(int index = 0; index < selQuestions.size(); index++){
Integer qtnId = selQuestions.get(index);
QuestionDef qtnDef = formDef.getQuestion(qtnId);
if(qtnDef == null)
continue;
if(qtnDef == questionDef)
continue;
lbSelQtns.addItem(qtnDef.getDisplayText(), qtnDef.getQuestionID());
}
}
/**
* Loads the all questions list box with questions from a given page.
*
* @param pageDef the page definition object.
* @param questionDef the question definition object.
* @param skipRule the current skip rule.
*/
private void loadPageQnts(List<IFormElement> elements, IFormElement questionDef, SkipRule skipRule){
for(int index = 0; index < elements.size(); index++){
IFormElement qtnDef = elements.get(index);
if(qtnDef == questionDef)
continue;
if(skipRule != null && skipRule.containsActionTarget(qtnDef.getId()))
continue;
lbAllQtns.addItem(qtnDef.getDisplayText(), qtnDef.getQuestionID());
}
}
/**
* Sets up the header labels for the all and selected questions list boxes.
*/
private void setupHeaderLabels(){
HorizontalPanel horzPanel = new HorizontalPanel();
Label lblAllQtns = new Label(LocaleText.get("allQuestions"));
Label lblSelQtns = new Label(LocaleText.get("selectedQuestions"));
horzPanel.add(lblAllQtns);
horzPanel.add(lblSelQtns);
horzPanel.setCellHorizontalAlignment(lblAllQtns, HasAlignment.ALIGN_CENTER);
horzPanel.setCellHorizontalAlignment(lblSelQtns, HasAlignment.ALIGN_CENTER);
FormUtil.maximizeWidget(horzPanel);
mainPanel.add(horzPanel);
}
/**
* Sets up the select and the remove selection buttons.
*
* @param parentPanel the panel to contain these buttons.
*/
private void setupSelectionButtons(HorizontalPanel parentPanel){
VerticalPanel vertPanel = new VerticalPanel();
vertPanel.add(btnSelect);
vertPanel.add(btnDeselect);
vertPanel.setCellVerticalAlignment(btnSelect, HasAlignment.ALIGN_MIDDLE);
vertPanel.setCellVerticalAlignment(btnDeselect, HasAlignment.ALIGN_MIDDLE);
vertPanel.setHeight("200"+PurcConstants.UNITS);
parentPanel.add(vertPanel);
btnSelect.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
selectQuestions();
}
});
btnDeselect.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
deselectQuestions();
}
});
btnSelect.setEnabled(false);
btnDeselect.setEnabled(false);
}
/**
* Sets up the Ok and Cancel buttons.
*/
private void setupOkCancelButtons(){
btnOk.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
hide();
qtnSelListener.onQuestionsSelected(getSelectedQtns());
}
});
btnCancel.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
hide();
}
});
HorizontalPanel horzPanel = new HorizontalPanel();
horzPanel.add(btnOk);
horzPanel.add(btnCancel);
horzPanel.setCellHorizontalAlignment(btnOk, HasAlignment.ALIGN_CENTER);
horzPanel.setCellHorizontalAlignment(btnCancel, HasAlignment.ALIGN_CENTER);
FormUtil.maximizeWidget(horzPanel);
btnOk.setEnabled(false);
mainPanel.add(horzPanel);
}
/**
* Removes selected questions from the all questions list box and puts them in the
* selected questions list box.
*/
private void selectQuestions(){
for(int index = 0; index < lbAllQtns.getItemCount(); index++){
if(lbAllQtns.isItemSelected(index)){
lbSelQtns.addItem(lbAllQtns.getItemText(index), lbAllQtns.getValue(index));
lbAllQtns.removeItem(index);
index--;
}
}
btnSelect.setEnabled(false);
btnOk.setEnabled(true/*lbSelQtns.getItemCount() > 0*/); //TODO need to be smarter than this
}
/**
* Removes selected questions from the selected questions list box and puts
* them in the all questions list box.
*/
private void deselectQuestions(){
for(int index = 0; index < lbSelQtns.getItemCount(); index++){
if(lbSelQtns.isItemSelected(index)){
lbAllQtns.addItem(lbSelQtns.getItemText(index), lbSelQtns.getValue(index));
lbSelQtns.removeItem(index);
index--;
}
}
btnDeselect.setEnabled(false);
btnOk.setEnabled(true /*lbSelQtns.getItemCount() > 0*/); //TODO Need to be smarter than this.
}
/**
* Gets a list of questions which have been selected.
*
* @return the questions list.
*/
private List<String> getSelectedQtns(){
List<String> selectedQtns = new ArrayList<String>();
for(int index = 0; index < lbSelQtns.getItemCount(); index++)
selectedQtns.add(lbSelQtns.getValue(index));
return selectedQtns;
}
}