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