1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.ui.client.configurable.mvc;
17
18 import java.util.HashMap;
19 import java.util.LinkedHashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Map.Entry;
23
24 import org.kuali.student.common.assembly.data.QueryPath;
25 import org.kuali.student.common.ui.client.application.Application;
26 import org.kuali.student.common.ui.client.configurable.mvc.layouts.MenuSectionController;
27 import org.kuali.student.common.ui.client.configurable.mvc.layouts.TabMenuController;
28 import org.kuali.student.common.ui.client.configurable.mvc.layouts.ViewLayoutController;
29 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
30 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
31 import org.kuali.student.common.ui.client.event.ActionEvent;
32 import org.kuali.student.common.ui.client.event.SaveActionEvent;
33 import org.kuali.student.common.ui.client.event.SectionUpdateEvent;
34 import org.kuali.student.common.ui.client.event.SectionUpdateHandler;
35 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
36 import org.kuali.student.common.ui.client.event.ValidateRequestHandler;
37 import org.kuali.student.common.ui.client.mvc.ActionCompleteCallback;
38 import org.kuali.student.common.ui.client.mvc.Callback;
39 import org.kuali.student.common.ui.client.mvc.Controller;
40 import org.kuali.student.common.ui.client.mvc.DataModel;
41 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
42 import org.kuali.student.common.ui.client.mvc.View;
43 import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
44 import org.kuali.student.common.ui.client.widgets.KSButton;
45 import org.kuali.student.common.ui.client.widgets.KSLightBox;
46 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
47 import org.kuali.student.common.validation.dto.ValidationResultInfo;
48 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
49
50 import com.google.gwt.core.client.GWT;
51 import com.google.gwt.event.dom.client.ClickEvent;
52 import com.google.gwt.event.dom.client.ClickHandler;
53 import com.google.gwt.user.client.ui.FlowPanel;
54 import com.google.gwt.user.client.ui.Widget;
55
56
57
58
59
60
61
62
63
64 public abstract class LayoutController extends Controller implements ViewLayoutController, View {
65
66 protected Map<Enum<?>, View> viewMap = new LinkedHashMap<Enum<?>, View>();
67 protected Map<String, Enum<?>> viewEnumMap = new HashMap<String, Enum<?>>();
68 protected Enum<?> defaultView;
69
70 protected String name;
71 protected Enum<?> viewType;
72
73 protected View startPopupView;
74 protected KSLightBox startViewWindow;
75
76
77
78
79
80 public LayoutController(){
81 super();
82
83 addApplicationEventHandler(SectionUpdateEvent.TYPE, new SectionUpdateHandler(){
84
85 @Override
86 public void onSectionUpdate(final SectionUpdateEvent event) {
87 LayoutController.this.requestModel(new ModelRequestCallback<DataModel>(){
88
89 @Override
90 public void onRequestFail(Throwable cause) {
91 GWT.log("Unable to retrieve model for section update", cause);
92 }
93
94 @Override
95 public void onModelReady(DataModel model) {
96 event.getSection().updateModel(model);
97 event.getSection().updateWidgetData(model);
98
99 }
100 });
101
102 }
103 });
104
105 addApplicationEventHandler(ValidateRequestEvent.TYPE, new ValidateRequestHandler() {
106
107 @Override
108 public void onValidateRequest(final ValidateRequestEvent event) {
109 FieldDescriptor originatingField = event.getFieldDescriptor();
110 String modelId = null;
111 if (originatingField != null) {
112 modelId = originatingField.getModelId();
113 }
114 if (modelId == null) {
115 requestModel(new ModelRequestCallback<DataModel>() {
116 @Override
117 public void onModelReady(DataModel model) {
118 validate(model, event);
119 }
120
121 @Override
122 public void onRequestFail(Throwable cause) {
123 GWT.log("Unable to retrieve model for validation", cause);
124 }
125
126 });
127 } else {
128 requestModel(modelId, new ModelRequestCallback<DataModel>() {
129 @Override
130 public void onModelReady(DataModel model) {
131 validate(model, event);
132 }
133
134 @Override
135 public void onRequestFail(Throwable cause) {
136 GWT.log("Unable to retrieve model for validation", cause);
137 }
138
139 });
140 }
141 }
142
143 });
144 }
145
146 private void validate(DataModel model, final ValidateRequestEvent event) {
147 if(event.validateSingleField()){
148 model.validateField(event.getFieldDescriptor(), new Callback<List<ValidationResultInfo>>() {
149 @Override
150 public void exec(List<ValidationResultInfo> result) {
151 if(event.getFieldDescriptor() != null) {
152
153
154 FieldElement element = event.getFieldDescriptor().getFieldElement();
155 Widget w = event.getFieldDescriptor().getFieldWidget();
156 if(element != null) {
157 element.clearValidationErrors();
158
159 if ((w instanceof CanProcessValidationResults) && ((CanProcessValidationResults) w).doesOnTheFlyValidation()) {
160 ((CanProcessValidationResults) w).Validate(event, result);
161 } else {
162 for(int i = 0; i < result.size(); i++) {
163 ValidationResultInfo vr = result.get(i);
164 if (vr.getElement().equals(event.getFieldDescriptor().getFieldKey()) && event.getFieldDescriptor().hasHadFocus()) {
165 element.processValidationResult(vr);
166 }
167 }
168 }
169 }
170 }
171
172 }
173 });
174 } else {
175 model.validate(new Callback<List<ValidationResultInfo>>() {
176 @Override
177 public void exec(List<ValidationResultInfo> result) {
178 isValid(result, false, true);
179 }
180 });
181 }
182 }
183
184
185
186
187
188
189 public ErrorLevel checkForErrors(List<ValidationResultInfo> list){
190 ErrorLevel errorLevel = ErrorLevel.OK;
191
192 for(ValidationResultInfo vr: list){
193 if(vr.getErrorLevel().getLevel() > errorLevel.getLevel()){
194 errorLevel = vr.getErrorLevel();
195 }
196 if(errorLevel.equals(ErrorLevel.ERROR)){
197 break;
198 }
199 }
200
201 return errorLevel;
202
203 }
204
205
206
207
208
209
210
211 public static LayoutController findParentLayout(Widget w){
212 LayoutController result = null;
213 while (true) {
214 if (w == null) {
215 break;
216 } else if (w instanceof HasLayoutController) {
217 result = ((HasLayoutController)w).getLayoutController();
218 if (result != null) {
219 break;
220 }
221 } else if (w instanceof LayoutController) {
222 result = (LayoutController) w;
223 break;
224 }
225 w = w.getParent();
226
227 }
228 return result;
229 }
230
231
232
233
234 public void addStartViewPopup(final View view){
235 startPopupView = view;
236 if(startViewWindow == null){
237 startViewWindow = new KSLightBox();
238 }
239
240 FlowPanel panel = new FlowPanel();
241 panel.add(view.asWidget());
242 KSButton save = new KSButton("Save",new ClickHandler(){
243 public void onClick(ClickEvent event) {
244 view.updateModel();
245 SaveActionEvent saveActionEvent = new SaveActionEvent(true);
246
247 saveActionEvent.setActionCompleteCallback(new ActionCompleteCallback(){
248 public void onActionComplete(ActionEvent action) {
249 startViewWindow.hide();
250 }
251 });
252
253
254 fireApplicationEvent(saveActionEvent);
255 }
256 });
257 startViewWindow.addButton(save);
258
259 KSButton cancel = new KSButton("Cancel", new ClickHandler(){
260 public void onClick(ClickEvent event) {
261 startViewWindow.hide();
262 }
263 });
264 startViewWindow.addButton(cancel);
265
266 if(view instanceof SectionView){
267 ((SectionView) view).setController(this);
268 }
269 startViewWindow.setWidget(panel);
270 }
271
272
273
274
275 public boolean isStartViewShowing(){
276 if(startViewWindow == null){
277 return false;
278 }
279 return startViewWindow.isShowing();
280 }
281
282 public View getStartPopupView(){
283 return startPopupView;
284 }
285
286 public void showStartPopup(final Callback<Boolean> onReadyCallback){
287 startPopupView.beforeShow(new Callback<Boolean>() {
288 @Override
289 public void exec(Boolean result) {
290 if (result) {
291 startViewWindow.show();
292 }
293 onReadyCallback.exec(result);
294 }
295 });
296 }
297
298 public KSLightBox getStartPopup(){
299 return startViewWindow;
300 }
301
302
303
304
305
306
307
308 public void addView(View view){
309 viewMap.put(view.getViewEnum(), view);
310 viewEnumMap.put(view.getViewEnum().toString(), view.getViewEnum());
311 if(view instanceof SectionView){
312 ((SectionView) view).setController(this);
313 }
314 else if(view instanceof ToolView){
315 ((ToolView) view).setController(this);
316 }
317 }
318
319
320
321
322 public <V extends Enum<?>> void setDefaultView(V viewType){
323 this.defaultView = viewType;
324 }
325
326 public Enum<?> getDefaultView(){
327 return this.defaultView;
328 }
329
330
331
332
333 public abstract void updateModel();
334
335
336
337
338
339 public void updateModelFromView(Enum<?> viewType){
340 View v = viewMap.get(viewType);
341 if(v != null){
342 v.updateModel();
343 }
344 }
345
346
347
348
349 public void updateModelFromCurrentView(){
350 if(this.getCurrentView() != null){
351 this.getCurrentView().updateModel();
352 }
353 }
354
355 @Override
356 public <V extends Enum<?>> void getView(V viewType, Callback<View> callback) {
357 callback.exec(viewMap.get(viewType));
358 }
359
360 @Override
361 public Enum<?> getViewEnumValue(String enumValue) {
362 return viewEnumMap.get(enumValue);
363 }
364
365 @Override
366 public void showDefaultView(final Callback<Boolean> onReadyCallback) {
367 HistoryManager.setLogNavigationHistory(false);
368
369 if(defaultView != null){
370 showView(defaultView, onReadyCallback);
371 }
372 else if(!viewMap.isEmpty()){
373 if(defaultView == null){
374 showView(viewMap.entrySet().iterator().next().getKey(), onReadyCallback);
375 }
376 }
377
378 }
379
380
381
382
383
384
385
386 public void showFirstView(Callback<Boolean> onReadyCallback){
387 HistoryManager.setLogNavigationHistory(false);
388 if(!viewMap.isEmpty()){
389 showView(viewMap.entrySet().iterator().next().getKey(), onReadyCallback);
390 }
391 else{
392 showDefaultView(onReadyCallback);
393 }
394 }
395
396
397
398
399
400
401
402
403
404 public boolean isValid(List<ValidationResultInfo> validationResults, boolean checkCurrentSectionOnly){
405 return isValid(validationResults, checkCurrentSectionOnly, true);
406 }
407
408
409
410
411
412
413
414
415 public boolean isValid(List<ValidationResultInfo> validationResults, boolean checkCurrentSectionOnly, boolean allFields){
416
417 boolean isValid = true;
418
419 clearAllWarnings();
420
421 if (checkCurrentSectionOnly){
422
423 View v = getCurrentView();
424 if(v instanceof Section){
425 isValid = isValid(validationResults, (Section)v, allFields);
426 }
427 if(this.isStartViewShowing()){
428 if(startPopupView instanceof Section){
429 isValid = isValid(validationResults, ((Section) startPopupView), allFields) && isValid;
430 }
431 }
432 } else {
433
434 String errorSections = "";
435 StringBuilder errorSectionsbuffer = new StringBuilder();
436 errorSectionsbuffer.append(errorSections);
437 for (Entry<Enum<?>, View> entry:viewMap.entrySet()) {
438 View v = entry.getValue();
439 if (v instanceof Section){
440 if (!isValid(validationResults, (Section)v, allFields)){
441 isValid = false;
442 errorSectionsbuffer.append(((SectionView)v).getName() + ", ");
443 }
444 }
445 }
446 if(this.isStartViewShowing()){
447 if(startPopupView instanceof Section){
448 isValid = isValid(validationResults, ((Section) startPopupView), allFields) && isValid;
449 }
450 }
451 errorSections = errorSectionsbuffer.toString();
452 if (!errorSections.isEmpty()){
453 errorSections = errorSections.substring(0, errorSections.length()-2);
454
455 }
456 }
457
458 return isValid;
459 }
460
461 private boolean isValid(List<ValidationResultInfo> validationResults, Section section, boolean allFields){
462 ErrorLevel status;
463 if(allFields){
464 section.setFieldHasHadFocusFlags(true);
465 status = section.processValidationResults(validationResults);
466 }
467 else{
468 status = section.processValidationResults(validationResults, false);
469 }
470
471 return (status != ErrorLevel.ERROR);
472 }
473
474
475
476
477 protected void clearAllWarnings(){
478 for (Entry<Enum<?>, View> entry:viewMap.entrySet()) {
479 View v = entry.getValue();
480 if (v instanceof Section){
481 ((Section)v).clearValidationWarnings();
482 }
483 }
484 }
485
486
487
488
489
490
491
492
493
494
495 @Override
496 public void beforeViewChange(Enum<?> viewChangingTo, Callback<Boolean> okToChange) {
497
498 if(this.getCurrentView() instanceof Controller){
499 ((Controller)this.getCurrentView()).beforeViewChange(viewChangingTo, okToChange);
500 }
501 else{
502 okToChange.exec(true);
503 }
504
505 this.showExport(isExportButtonActive());
506 }
507
508
509
510
511
512 protected void showWarnings(){
513 if (!Application.getApplicationContext().getValidationWarnings().isEmpty()){
514 isValid(Application.getApplicationContext().getValidationWarnings(), true);
515 }
516 }
517
518 @Override
519 public Widget asWidget() {
520 return this;
521 }
522
523 @Override
524 public boolean beforeHide() {
525 return true;
526 }
527
528
529
530
531
532
533 @Override
534 public void beforeShow(Callback<Boolean> onReadyCallback) {
535 onReadyCallback.exec(true);
536 }
537
538 @Override
539 public Controller getController() {
540 return parentController;
541 }
542
543 @Override
544 public String getName() {
545 if(name == null && viewType != null){
546 return viewType.toString();
547 }
548 else{
549 return name;
550 }
551 }
552
553 @Override
554 public Enum<?> getViewEnum() {
555 return viewType;
556 }
557
558 public void setViewEnum(Enum<?> viewType){
559 this.viewType= viewType;
560 }
561
562
563
564
565
566
567 public void setName(String name){
568 this.name = name;
569 }
570
571 public void setController(Controller controller){
572 parentController = controller;
573 }
574
575 @Override
576 public void collectBreadcrumbNames(List<String> names) {
577 names.add(this.getName());
578 if(this.getCurrentView() != null){
579 this.getCurrentView().collectBreadcrumbNames(names);
580 }
581 }
582
583 @Override
584 public void clear() {
585
586 }
587
588 public boolean isExportButtonActive() {
589 return false;
590 }
591
592 @Override
593 public void showExport(boolean show) {
594
595
596 }
597 }