Home | History | Annotate | Download | only in wizard
      1 package autotest.moblab.wizard;
      2 
      3 import com.google.gwt.event.dom.client.ClickEvent;
      4 import com.google.gwt.event.dom.client.ClickHandler;
      5 import com.google.gwt.json.client.JSONObject;
      6 import com.google.gwt.user.client.Window;
      7 import com.google.gwt.user.client.ui.Button;
      8 import com.google.gwt.user.client.ui.HorizontalPanel;
      9 import com.google.gwt.user.client.ui.Label;
     10 import com.google.gwt.user.client.ui.SimplePanel;
     11 import com.google.gwt.user.client.ui.VerticalPanel;
     12 import com.google.gwt.user.client.ui.Widget;
     13 
     14 import autotest.common.ui.NotifyManager;
     15 import autotest.moblab.rpc.MoblabRpcCallbacks;
     16 import autotest.moblab.rpc.MoblabRpcHelper;
     17 import autotest.moblab.rpc.OperationStatus;
     18 
     19 import java.util.HashMap;
     20 
     21 /**
     22  * A wizard editing mode widget contains a list of configuration steps.
     23  * Each step show a validation status, a title for current card, a wizard
     24  * card widget, and a set of navigation buttons are displayed.
     25  *
     26  * -------------------------------------------------------------------------
     27  * |Validation Error Message (optional)                                    |
     28  * -------------------------------------------------------------------------
     29  * | Title                                                                 |
     30  * -------------------------------------------------------------------------
     31  * |Card Configuration Widget                                              |
     32  * -------------------------------------------------------------------------
     33  * |          Back             Cancel            Next (Finish)             |
     34  * -------------------------------------------------------------------------
     35  */
     36 public class ConfigEditMode
     37     implements ConfigWizard.ConfigWizardMode, WizardCard.CardDataStatusListener {
     38   // Constants for invalid card index.
     39   private static final int INVALID_CARD_INDEX = -1;
     40 
     41   private ConfigWizard wizard;
     42 
     43   // Validation status
     44   private Label lblValidationStatus;
     45 
     46   // Title
     47   private Label lblCardTitle;
     48 
     49   // Wizard card widget container.
     50   private SimplePanel pnlCard;
     51 
     52   // Wizard navigation buttons.
     53   private Button btnBack;
     54   private Button btnNext;
     55   private Button btnCancel;
     56 
     57   // If the mode is visible.
     58   private boolean visible;
     59 
     60   // The current card index.
     61   private int currentCardIndex = INVALID_CARD_INDEX;
     62 
     63   public ConfigEditMode(ConfigWizard wizard) {
     64     this.wizard = wizard;
     65   }
     66 
     67   private Widget reloadModeWidget() {
     68     VerticalPanel pnlLayout = new VerticalPanel();
     69     pnlLayout.setStyleName("wizard-edit-panel");
     70     // status
     71     lblValidationStatus = new Label();
     72     lblValidationStatus.setStyleName("card-edit-status");
     73     pnlLayout.add(lblValidationStatus);
     74 
     75     // card title
     76     lblCardTitle = new Label();
     77     lblCardTitle.setStyleName("card-edit-title");
     78     pnlLayout.add(lblCardTitle);
     79 
     80     // card content
     81     pnlCard = new SimplePanel();
     82     pnlLayout.add(pnlCard);
     83 
     84     // navigation buttons
     85     HorizontalPanel pnlActions = new HorizontalPanel();
     86     btnBack = new Button("Back");
     87     btnNext = new Button("Next");
     88     btnCancel = new Button("Cancel");
     89     pnlActions.add(btnBack);
     90     pnlActions.add(btnCancel);
     91     pnlActions.add(btnNext);
     92     pnlLayout.add(pnlActions);
     93 
     94     btnBack.addClickHandler(new ClickHandler() {
     95       @Override
     96       public void onClick(ClickEvent event) {
     97         onGoBack();
     98       }
     99     });
    100 
    101     btnNext.addClickHandler(new ClickHandler() {
    102       @Override
    103       public void onClick(ClickEvent event) {
    104         onGoNext();
    105       }
    106     });
    107 
    108     btnCancel.addClickHandler(new ClickHandler() {
    109       @Override
    110       public void onClick(ClickEvent event) {
    111         onCancel();
    112       }
    113     });
    114 
    115     return pnlLayout;
    116   }
    117 
    118   private boolean isAtFirstCard() {
    119     return currentCardIndex == 0;
    120   }
    121 
    122   private boolean isAtLastCard() {
    123     return currentCardIndex == wizard.getCards().length - 1;
    124   }
    125 
    126   @Override
    127   public Widget display() {
    128     visible = true;
    129     Widget widget = reloadModeWidget();
    130     if (wizard.getCards().length == 0) {
    131       throw new RuntimeException("Empty wizard.");
    132     }
    133     currentCardIndex = 0;
    134 
    135     updateUIAtCurrentCard(null);
    136     return widget;
    137   }
    138 
    139   @Override
    140   public void hide() {
    141     visible = false;
    142   }
    143 
    144   private void updateUIAtCurrentCard(OperationStatus status) {
    145     // Updates the status panel.
    146     if (status != null && !status.isOk()) {
    147       if (status.getDetails() != null) {
    148         logError("Error:" + status.getDetails());
    149       } else {
    150         logError("Error: Unknown!");
    151       }
    152     } else {
    153       clearError();
    154     }
    155 
    156     // Update card title.
    157     int step = currentCardIndex + 1;
    158     WizardCard current = getCurrentCard();
    159     lblCardTitle.setText("Step " + step + " - " + current.getEditTitle());
    160 
    161     // Update the navigation buttons.
    162     if (isAtLastCard()) {
    163       btnNext.setText("Finish");
    164     } else {
    165       btnNext.setText("Next");
    166     }
    167     btnNext.setEnabled(current.canGoNext());
    168     btnBack.setEnabled(!isAtFirstCard());
    169 
    170     // Updates the card container with current card widget.
    171     pnlCard.setWidget(current.switchToMode(ConfigWizard.Mode.Edit));
    172   }
    173 
    174   /**
    175    * Clears the error message by hiding the widget.
    176    */
    177   protected void clearError() {
    178     lblValidationStatus.setVisible(false);
    179   }
    180 
    181   protected void logError(String message) {
    182     if (message != null) {
    183       lblValidationStatus.setText(message);
    184       lblValidationStatus.setVisible(true);
    185     }
    186   }
    187 
    188   protected void onGoNext() {
    189     clearError();
    190     getCurrentCard().validate(new WizardCard.CardValidationCallback() {
    191       @Override
    192       public void onValidationStatus(OperationStatus status) {
    193         if (status != null && status.isOk()) {
    194           if (!isAtLastCard()) {
    195             currentCardIndex++;
    196           } else {
    197             if (Window.confirm("Are you sure you want to commit the changes?")) {
    198               onFinish();
    199             }
    200           }
    201         }
    202         updateUIAtCurrentCard(status);
    203       }
    204     });
    205   }
    206 
    207   private WizardCard getCurrentCard() {
    208     return wizard.getCards()[currentCardIndex];
    209   }
    210 
    211   protected void onGoBack() {
    212     clearError();
    213     if (isAtFirstCard()) {
    214       throw new RuntimeException("Could not go back from the first card.");
    215     }
    216     currentCardIndex--;
    217     updateUIAtCurrentCard(null);
    218   }
    219 
    220   protected void onFinish() {
    221     HashMap<String, JSONObject> map = new HashMap<String, JSONObject>();
    222     for (WizardCard card : wizard.getCards()) {
    223       card.collectConfigData(map);
    224     }
    225     MoblabRpcHelper.submitWizardConfigData(map,
    226         new MoblabRpcCallbacks.SubmitWizardConfigInfoCallback() {
    227           @Override
    228           public void onWizardConfigInfoSubmitted(OperationStatus status) {
    229             if (status.isOk()) {
    230               reset();
    231               wizard.onFinishEdit();
    232               NotifyManager.getInstance().showMessage(
    233                   "Configuration is submitted. Some services are being restarted "
    234                   + "for new change to take effect.");
    235             } else {
    236               String details = status.getDetails();
    237               if (details == null) {
    238                 details = "Operation Failed: erver side error.";
    239               }
    240               NotifyManager.getInstance().showError(status.getDetails());
    241             }
    242           }
    243         });
    244   }
    245 
    246   protected void onCancel() {
    247     reset();
    248     wizard.onCancelEdit();
    249   }
    250 
    251   protected void reset() {
    252     clearError();
    253     for (WizardCard card : wizard.getCards()) {
    254       card.resetData();
    255     }
    256   }
    257 
    258   @Override
    259   public void onDataStatusChange() {
    260     if (visible) {
    261       updateUIAtCurrentCard(null);
    262     }
    263   }
    264 }
    265