Coverage Report - org.kuali.student.common.ui.client.configurable.mvc.sections.BaseSection
 
Classes in this File Line Coverage Branch Coverage Complexity
BaseSection
0%
0/244
0%
0/144
2.58
BaseSection$1
0%
0/16
0%
0/8
2.58
BaseSection$1$1
0%
0/9
0%
0/4
2.58
BaseSection$1$2
0%
0/5
N/A
2.58
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.common.ui.client.configurable.mvc.sections;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashSet;
 20  
 import java.util.List;
 21  
 
 22  
 import org.kuali.student.common.assembly.data.Data;
 23  
 import org.kuali.student.common.assembly.data.Data.Key;
 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.CanProcessValidationResults;
 27  
 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
 28  
 import org.kuali.student.common.ui.client.configurable.mvc.LayoutController;
 29  
 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBinding;
 30  
 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBindingImpl;
 31  
 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
 32  
 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
 33  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityComposite;
 34  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroup;
 35  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroupItem;
 36  
 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityItem;
 37  
 import org.kuali.student.common.ui.client.event.ContentDirtyEvent;
 38  
 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
 39  
 import org.kuali.student.common.ui.client.mvc.Callback;
 40  
 import org.kuali.student.common.ui.client.mvc.Controller;
 41  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 42  
 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
 43  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 44  
 import org.kuali.student.common.ui.client.mvc.View;
 45  
 import org.kuali.student.common.ui.client.widgets.KSDropDown;
 46  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.AbbrPanel;
 47  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
 48  
 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
 49  
 import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayout;
 50  
 import org.kuali.student.common.ui.client.widgets.search.KSPicker;
 51  
 import org.kuali.student.common.validation.dto.ValidationResultInfo;
 52  
 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
 53  
 
 54  
 import com.google.gwt.core.client.GWT;
 55  
 import com.google.gwt.user.client.ui.TextBoxBase;
 56  
 import com.google.gwt.user.client.ui.Widget;
 57  
 
 58  
 /**
 59  
  * The base section is the base implementation of the section interface.
 60  
  * @author Kuali Student
 61  
  *
 62  
  */
 63  0
 public abstract class BaseSection extends SpanPanel implements Section{
 64  
 
 65  
         protected FieldLayout layout;
 66  
 
 67  0
         protected ArrayList<Section> sections = new ArrayList<Section>();
 68  0
         protected ArrayList<FieldDescriptor> fields = new ArrayList<FieldDescriptor>();
 69  0
         protected LayoutController layoutController = null;
 70  0
         protected boolean isValidationEnabled = true;
 71  0
         protected boolean isDirty = false;
 72  
 
 73  
         /**
 74  
          * Adds a field to this section.  Adds the field to this section's layout.
 75  
          * Attaches an event handler for lost focus events on the field widget
 76  
          * to validate against the metadata defined in its FieldDescriptor as well as firing events for dirty
 77  
          * field handling.
 78  
          * 
 79  
          * Note if a field has been marked as hidden in the dictionary, this method will not add this field to the layout.
 80  
          * If it is not visible the key returned by making call to addField is null.
 81  
          * 
 82  
          * @param field
 83  
          * @return key/path of this field
 84  
          */
 85  
         @Override
 86  
         public String addField(final FieldDescriptor fieldDescriptor) {
 87  0
                 String key = null;
 88  
                 
 89  0
                 if (fieldDescriptor.isVisible()){
 90  0
                         fields.add(fieldDescriptor);
 91  0
                 key = layout.addField(fieldDescriptor.getFieldElement());
 92  
         
 93  0
                 ValidationEventBinding binding = new ValidationEventBindingImpl();
 94  0
                 if(fieldDescriptor.getValidationRequestCallback()== null){
 95  0
                     fieldDescriptor.setValidationCallBack(new Callback<Boolean>() {
 96  
                         @Override
 97  
                         public void exec(Boolean result) {
 98  0
                                 final ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
 99  0
                                 if (mwb != null) {
 100  0
                                     final Widget w = fieldDescriptor.getFieldWidget();
 101  0
                                     final String modelId = fieldDescriptor.getModelId();
 102  
                                     final Controller parent;
 103  0
                                 Controller findResult = LayoutController.findParentLayout(w);
 104  0
                                 if(BaseSection.this instanceof View){
 105  0
                                         findResult = ((View)BaseSection.this).getController();
 106  
                                 }
 107  0
                                 parent = findResult;
 108  0
                                 if(parent != null){
 109  0
                                         if (modelId == null) {
 110  0
                                                 parent.requestModel(new ModelRequestCallback<DataModel>() {
 111  
         
 112  
                                                         @Override
 113  
                                                         public void onModelReady(DataModel model) {
 114  0
                                                                 validateField(fieldDescriptor, model, parent);
 115  
                                                 
 116  
                                                                 //Cross referenced field update:
 117  0
                                                                 HashSet<HasCrossConstraints> fds = Application.getApplicationContext().getCrossConstraint(null, Application.getApplicationContext().getParentPath()+fieldDescriptor.getFieldKey());
 118  0
                                                                 if(fds!=null){
 119  0
                                                                         for(HasCrossConstraints fd:fds){
 120  0
                                                                                 fd.reprocessWithUpdatedConstraints();
 121  
                                                                         }
 122  
                                                                 }
 123  0
                                                         }
 124  
         
 125  
                                                         @Override
 126  
                                                         public void onRequestFail(Throwable cause) {
 127  0
                                                                 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
 128  0
                                                         }
 129  
         
 130  
                                                 });
 131  
                                         } else {
 132  0
                                                 parent.requestModel(modelId, new ModelRequestCallback<DataModel>() {
 133  
         
 134  
                                                         @Override
 135  
                                                         public void onModelReady(DataModel model) {
 136  0
                                                                 validateField(fieldDescriptor, model, parent);
 137  0
                                                         }
 138  
         
 139  
                                                         @Override
 140  
                                                         public void onRequestFail(Throwable cause) {
 141  0
                                                                 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
 142  0
                                                         }
 143  
         
 144  
                                                 });                                }
 145  
                                         }
 146  0
                             } else {
 147  0
                                 GWT.log(fieldDescriptor.getFieldKey() + " has no widget binding.", null);
 148  
                             }
 149  0
                         }
 150  
                     });
 151  
                 }
 152  0
                 binding.bind(fieldDescriptor);
 153  
                 }               
 154  
                 
 155  0
         return key;
 156  
         }
 157  
 
 158  
         private void validateField(
 159  
                         final FieldDescriptor fieldDescriptor, final DataModel model, Controller controller) {
 160  0
                 Widget w = fieldDescriptor.getFieldWidget();
 161  0
                 ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
 162  0
                 if(fieldDescriptor.getFieldKey() != null){
 163  0
                         mwb.setModelValue(w, model, fieldDescriptor.getFieldKey());
 164  0
                         dirtyCheckField(fieldDescriptor, model);
 165  0
                         ValidateRequestEvent e = new ValidateRequestEvent();
 166  0
                         e.setFieldDescriptor(fieldDescriptor);
 167  0
                         e.setValidateSingleField(true);
 168  0
                         controller.fireApplicationEvent(e);
 169  
                 }
 170  0
         }
 171  
 
 172  
         private void dirtyCheckField(FieldDescriptor fieldDescriptor, DataModel model){
 173  0
         QueryPath fieldPath = QueryPath.parse(fieldDescriptor.getFieldKey());
 174  0
                 QueryPath qPathDirty = fieldPath.subPath(0, fieldPath.size() - 1);
 175  0
             qPathDirty.add(ModelWidgetBindingSupport.RUNTIME_ROOT);
 176  0
             qPathDirty.add(ModelWidgetBindingSupport.DIRTY_PATH);
 177  0
             qPathDirty.add(fieldPath.get(fieldPath.size()-1));
 178  0
             Boolean dirty = false;
 179  
 
 180  0
             if(ensureDirtyFlagPath(model.getRoot(), qPathDirty)){
 181  0
                     dirty = model.get(qPathDirty);
 182  
             }
 183  0
             if(dirty){
 184  0
                     setIsDirty(true);
 185  0
                     fieldDescriptor.setDirty(true);
 186  
             }
 187  0
         }
 188  
 
 189  
     protected boolean ensureDirtyFlagPath(Data root, QueryPath path) {
 190  0
         Data current = root;
 191  0
         boolean containsFlag = false;
 192  0
         for (int i = 0; i < path.size(); i++) {
 193  0
             Key key = path.get(i);
 194  0
             if(i == path.size() - 1){
 195  0
                     containsFlag = current.containsKey(key);
 196  0
                     break;
 197  
             }
 198  0
             Data d = current.get(key);
 199  0
             if (d == null) {
 200  0
                 containsFlag = false;
 201  0
                 break;
 202  
             }
 203  0
             current = d;
 204  
         }
 205  0
         return containsFlag;
 206  
     }
 207  
 
 208  
         /** 
 209  
          * Adds a section to this section's layout.
 210  
          * 
 211  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addSection(org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 212  
          */
 213  
         @Override
 214  
         public String addSection(Section section) {
 215  
 
 216  0
         section.setLayoutController(layoutController);
 217  0
                 sections.add(section);
 218  0
         String key = layout.addLayout(section.getLayout());
 219  0
         return key;
 220  
         }
 221  
 
 222  
         /**
 223  
          * Removes a section from this section's layout.
 224  
          * 
 225  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#removeSection(org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 226  
          */
 227  
         @Override
 228  
         public void removeSection(Section section){
 229  0
                 sections.remove(section);
 230  0
                 layout.removeLayoutElement(section.getLayout());
 231  0
         }
 232  
 
 233  
         /**
 234  
          * Clear all validation errors from the layout (removes all red highlight and error text shown on the
 235  
          * screen)
 236  
          */
 237  
         protected void clearValidationErrors() {
 238  0
                 layout.clearValidationErrors();
 239  0
         }
 240  
 
 241  
         /**
 242  
          * Clear all validation warnings from the layout (removes all yellow highlight and warning text shown on the
 243  
          * screen)
 244  
          */
 245  
         public void clearValidationWarnings() {
 246  0
                 layout.clearValidationWarnings();
 247  0
         }
 248  
         
 249  
         /**
 250  
          * Gets all the fields in a section and its subsections.
 251  
          * 
 252  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getFields()
 253  
          */
 254  
         @Override
 255  
         public List<FieldDescriptor> getFields() {
 256  0
         List<FieldDescriptor> allFields = new ArrayList<FieldDescriptor>();
 257  0
         allFields.addAll(fields);
 258  
 
 259  0
         for(Section ns: sections){
 260  0
             allFields.addAll(ns.getFields());
 261  
         }
 262  0
         return allFields;
 263  
         }
 264  
 
 265  
         /**
 266  
          * Gets all the fields in this section, but does not include fields in its nested sections.
 267  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getUnnestedFields()
 268  
          */
 269  
         @Override
 270  
         public List<FieldDescriptor> getUnnestedFields() {
 271  0
         return fields;
 272  
         }
 273  
 
 274  
         /**
 275  
          * Gets all nested sections contained in this section
 276  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getSections()
 277  
          */
 278  
         @Override
 279  
         public List<Section> getSections() {
 280  0
                 return sections;
 281  
         }
 282  
 
 283  
         /**
 284  
          * Processes the validation results passed in and displays the appropriate message on the screen next
 285  
          * to the corresponding field or section.  If clearAllValidation is true, it will clear all validation before
 286  
          * displaying the errors (otherwise will append these errors to the ones already visible on the section).
 287  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#processValidationResults(java.util.List, boolean)
 288  
          */
 289  
         @Override
 290  
         public ErrorLevel processValidationResults(List<ValidationResultInfo> results, boolean clearErrors){
 291  0
                 if(clearErrors){
 292  0
                         this.clearValidationErrors();
 293  
                 }
 294  0
                 ErrorLevel status = ErrorLevel.OK;
 295  
 
 296  0
                 if (isValidationEnabled){
 297  
 
 298  0
                         for(FieldDescriptor f: this.fields){
 299  
 
 300  0
                                 if(f.hasHadFocus()){
 301  0
                                         for(ValidationResultInfo vr: results){
 302  0
                         String vrElement = vr.getElement();
 303  0
                         if(vrElement.startsWith("/")){
 304  0
                             vrElement = vrElement.substring(1);
 305  
                         }
 306  
                         //Strip out end indexes for collections of primitives to be handled by the element
 307  0
                         vrElement = vrElement.replaceFirst("^(\\S+)/[0-9]+$", "$1");
 308  
                         
 309  
                         //Check the parent path (mostly for mapping validation to specializations)
 310  0
                         String parentPath = Application.getApplicationContext().getParentPath();
 311  0
                         parentPath = parentPath==null?"":parentPath;
 312  
                         
 313  0
                                                 if((parentPath+vrElement).equals(parentPath+f.getFieldKey())){
 314  0
                                                         FieldElement element = f.getFieldElement();
 315  0
                                                         if (element != null){
 316  0
                                                                 ErrorLevel fieldStatus = element.processValidationResult(vr);
 317  0
                                                                 if(fieldStatus.getLevel() > status.getLevel()){
 318  0
                                                                         status = fieldStatus;
 319  
                                                                 }
 320  
                                                         }
 321  
                                                 }
 322  0
                                         }
 323  
                                 }
 324  
 
 325  0
                                 if(f.getFieldWidget() instanceof MultiplicityComposite ){
 326  0
                                         MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
 327  
 
 328  
                                         //possibly return error state from processValidationResults to give composite title bar a separate color
 329  0
                             for(MultiplicityItem item: mc.getItems()){
 330  0
                                     if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 331  0
                                             ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearErrors);
 332  0
                                                         if(fieldStatus.getLevel() > status.getLevel()){
 333  0
                                                                 status = fieldStatus;
 334  
                                                         }
 335  0
                                     }
 336  
                             }
 337  
                                 }
 338  
                                 // TODO Can we do this without checking for instanceof  MG??
 339  0
                                 if(f.getFieldWidget() instanceof MultiplicityGroup ){
 340  0
                                         MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
 341  
 
 342  
                                         //possibly return error state from processValidationResults to give composite title bar a separate color
 343  0
                             for(MultiplicityGroupItem item: mg.getItems()){
 344  0
                                     if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 345  0
                                             ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearErrors);
 346  0
                                                         if(fieldStatus.getLevel() > status.getLevel()){
 347  0
                                                                 status = fieldStatus;
 348  
                                                         }
 349  0
                                     }
 350  
                             }
 351  
                                 }
 352  0
                 if (f.getFieldWidget() instanceof CanProcessValidationResults) {
 353  0
                     ErrorLevel fieldStatus = ((CanProcessValidationResults) f.getFieldWidget()).processValidationResults(f, results, clearErrors);
 354  0
                     if (fieldStatus.getLevel() > status.getLevel()) {
 355  0
                         status = fieldStatus;
 356  
                     }
 357  0
                 }
 358  
                         }
 359  
 
 360  0
                 for(Section s: sections){
 361  0
                     ErrorLevel subsectionStatus = s.processValidationResults(results,clearErrors);
 362  0
                     if(subsectionStatus.getLevel() > status.getLevel()){
 363  0
                             status = subsectionStatus;
 364  
                     }
 365  0
                 }
 366  
                 }
 367  
 
 368  0
         return status;
 369  
         }
 370  
 
 371  
         /**
 372  
          * Same as processValidationResults(results, true)
 373  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#processValidationResults(java.util.List)
 374  
          */
 375  
         @Override
 376  
         public ErrorLevel processValidationResults(List<ValidationResultInfo> results) {
 377  0
                 return processValidationResults(results, true);
 378  
         }
 379  
 
 380  
         /**
 381  
          * Gets the defined controller for this section if one exists.
 382  
          * 
 383  
          * @see org.kuali.student.common.ui.client.configurable.mvc.HasLayoutController#getLayoutController()
 384  
          */
 385  
         @Override
 386  
         public LayoutController getLayoutController() {
 387  0
                 return this.layoutController;
 388  
         }
 389  
 
 390  
         @Override
 391  
         public void setLayoutController(LayoutController controller) {
 392  0
                 this.layoutController = controller;
 393  0
         }
 394  
 
 395  
 
 396  
         /**
 397  
          * Use this to add widgets to a sections layout.  DO NOT use the add(Widget widget) call.
 398  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addWidget(com.google.gwt.user.client.ui.Widget)
 399  
          */
 400  
         @Override
 401  
         public String addWidget(Widget w) {
 402  0
                 return layout.addWidget(w);
 403  
         }
 404  
 
 405  
     /**
 406  
      * Sets the fields has had focus flag.  This flag is used for determining if the user has interacted with
 407  
      * any fields on the page or if the fields need to be assumed to have been interacted with.  Used for determining
 408  
      * when validation is necessary on a particular section.
 409  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#setFieldHasHadFocusFlags(boolean)
 410  
      */
 411  
     public void setFieldHasHadFocusFlags(boolean hadFocus) {
 412  0
         for(FieldDescriptor f: fields){
 413  0
             f.setHasHadFocus(hadFocus);
 414  0
             if(f.getFieldWidget() instanceof MultiplicityComposite){
 415  0
                                 MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
 416  
 
 417  0
                     for(MultiplicityItem item: mc.getItems()){
 418  0
                             if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 419  0
                                     ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
 420  
                             }
 421  
                     }
 422  0
             }else if(f.getFieldWidget() instanceof MultiplicityGroup){
 423  0
                     MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
 424  
 
 425  0
                     for(MultiplicityGroupItem item: mg.getItems()){
 426  0
                             if(item.getItemWidget() instanceof Section && !item.isDeleted()){
 427  0
                                     ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
 428  
                             }
 429  
                     }
 430  0
             }
 431  
         }
 432  
 
 433  0
         for(Section s: sections){
 434  0
             s.setFieldHasHadFocusFlags(hadFocus);
 435  
         }
 436  
 
 437  0
     }
 438  
 
 439  
     /**
 440  
      * A section can turn off all validation by setting this flag
 441  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#enableValidation(boolean)
 442  
      */
 443  
     @Override
 444  
     public void enableValidation(boolean enableValidation) {
 445  0
             this.isValidationEnabled = enableValidation;
 446  0
     }
 447  
 
 448  
     @Override
 449  
     public boolean isValidationEnabled() {
 450  0
                 return isValidationEnabled;
 451  
         }
 452  
 
 453  
         /**
 454  
          * Update the model passed in with data from the fields on this section.  This method will use the 
 455  
          * modelWidgetBinding defined in each of this sections fields to determine how to add this data to the
 456  
          * model.
 457  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#updateModel(org.kuali.student.common.ui.client.mvc.DataModel)
 458  
          */
 459  
         @Override
 460  
     public void updateModel(DataModel model){
 461  0
         SectionBinding.INSTANCE.setModelValue(this, model, "");
 462  0
     }
 463  
 
 464  
     /**
 465  
      * Updates the section's fields with data from the model passed in.  This effects all the data input and
 466  
      * display widgets on the particular section.  This method will use the 
 467  
          * modelWidgetBinding defined in each of this sections fields to determine how to interpret data from the
 468  
          * model and display it on the fields corresponding widget.
 469  
          * 
 470  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#updateWidgetData(org.kuali.student.common.ui.client.mvc.DataModel)
 471  
      */
 472  
     @Override
 473  
     public void updateWidgetData(DataModel model) {
 474  0
         SectionBinding.INSTANCE.setWidgetValue(this, model, "");
 475  0
     }
 476  
 
 477  
     /**
 478  
      * Resets all the dirty and focus flags on fields.
 479  
      * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#resetFieldInteractionFlags()
 480  
      */
 481  
     @Override
 482  
     public void resetFieldInteractionFlags() {
 483  0
             this.isDirty = false;
 484  0
         for(FieldDescriptor f: fields){
 485  0
             f.setDirty(false);
 486  0
             f.setHasHadFocus(false);
 487  
         }
 488  
 
 489  0
         for(Section s: sections){
 490  0
             s.resetFieldInteractionFlags();
 491  
         }
 492  
 
 493  0
     }
 494  
 
 495  
     @Override
 496  
     public void resetDirtyFlags() {
 497  0
             this.isDirty = false;
 498  0
         for(FieldDescriptor f: fields){
 499  0
             f.setDirty(false);
 500  
         }
 501  
 
 502  0
         for(Section s: sections){
 503  0
             s.resetDirtyFlags();
 504  
         }
 505  0
     }
 506  
 
 507  
 
 508  
         /**
 509  
          * Same as addSection except with an option user defined key (for retrieval of the section if necessary).
 510  
          * 
 511  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#addSection(java.lang.String, org.kuali.student.common.ui.client.configurable.mvc.sections.Section)
 512  
          */
 513  
         @Override
 514  
         public String addSection(String key, Section section) {
 515  0
         sections.add(section);
 516  0
         section.getLayout().setKey(key);
 517  0
         String rkey = layout.addLayout(section.getLayout());
 518  0
         return rkey;
 519  
         }
 520  
 
 521  
         @Override
 522  
         public FieldDescriptor getField(String fieldKey) {
 523  0
                 for(FieldDescriptor f: fields){
 524  0
                         if(f.getFieldKey().equals(fieldKey)){
 525  0
                                 return f;
 526  
                         }
 527  
                 }
 528  0
                 return null;
 529  
         }
 530  
 
 531  
         /**
 532  
          * Gets this sections fieldLayout.  The fieldLayout is used to determine how sections will layout the
 533  
          * ui and contains things such as the title and validation panels.
 534  
          * 
 535  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#getLayout()
 536  
          */
 537  
         @Override
 538  
         public FieldLayout getLayout() {
 539  0
                 return layout;
 540  
         }
 541  
 
 542  
         @Override
 543  
         public Section getSection(String sectionKey) {
 544  0
                 for(Section s: sections){
 545  0
                         if(s.getLayout().getKey().equals(sectionKey)){
 546  0
                                 return s;
 547  
                         }
 548  
                 }
 549  0
                 return null;
 550  
         }
 551  
 
 552  
         @Override
 553  
         public void removeField(String fieldKey) {
 554  0
                 int index = 0;
 555  0
                 boolean found = false;
 556  0
                 for(FieldDescriptor f: fields){
 557  0
                         if(f.getFieldKey().equals(fieldKey)){
 558  0
                                 index = fields.indexOf(f);
 559  0
                                 found = true;
 560  0
                                 break;
 561  
                         }
 562  
                 }
 563  0
                 if(found){
 564  0
                         fields.remove(index);
 565  
                 }
 566  0
                 layout.removeLayoutElement(fieldKey);
 567  
 
 568  0
         }
 569  
 
 570  
         @Override
 571  
         public void removeField(FieldDescriptor field) {
 572  
 
 573  0
                 fields.remove(field);
 574  0
                 layout.removeLayoutElement(field.getFieldKey());
 575  
 
 576  0
         }
 577  
 
 578  
         @Override
 579  
         public void removeSection(String sectionKey) {
 580  0
                 int index = 0;
 581  0
                 boolean found = false;
 582  0
                 for(Section s: sections){
 583  0
                         if(s.getLayout().getKey().equals(sectionKey)){
 584  0
                                 index = sections.indexOf(s);
 585  0
                                 found = true;
 586  0
                                 break;
 587  
                         }
 588  
                 }
 589  0
                 if(found){
 590  0
                         sections.remove(index);
 591  
                 }
 592  0
                 layout.removeLayoutElement(sectionKey);
 593  
 
 594  0
         }
 595  
 
 596  
         @Override
 597  
         public void removeWidget(Widget widget) {
 598  0
                 layout.removeLayoutElement(widget);
 599  
 
 600  0
         }
 601  
 
 602  
         @Override
 603  
         public void removeWidget(String key) {
 604  0
                 layout.removeLayoutElement(key);
 605  
 
 606  0
         }
 607  
 
 608  
         /**
 609  
          * Returns true if this this section is considered dirty (the user may have entered data into this
 610  
          * section)
 611  
          * 
 612  
          * @see org.kuali.student.common.ui.client.configurable.mvc.sections.Section#isDirty()
 613  
          */
 614  
         public boolean isDirty(){
 615  0
                 if(!this.isDirty){
 616  
                         //Check child sections for dirtyness
 617  0
                         for(Section s: sections){
 618  0
                                 if(s.isDirty()){
 619  0
                                         setIsDirty(true);
 620  0
                                         break;
 621  
                                 }
 622  
                         }
 623  
                 }
 624  0
                 return isDirty;
 625  
         }
 626  
 
 627  
     public void setIsDirty(boolean state) {
 628  
                 //Should this trust layoutController to be already set?
 629  0
             if (layoutController == null){
 630  0
                     layoutController = LayoutController.findParentLayout(layout);
 631  
             }
 632  0
             if (isDirty != state){
 633  0
                 isDirty = state;
 634  0
                     if (layoutController != null && isDirty){
 635  0
                             layoutController.fireApplicationEvent(new ContentDirtyEvent());
 636  
                     }
 637  
             }
 638  0
     }
 639  
 
 640  
         /**
 641  
          * DO NOT use this method for adding sections, fields, or widgets to sections
 642  
          */
 643  
         @Override
 644  
         public void add(Widget w) {
 645  0
                 super.add(w);
 646  0
         }
 647  
 
 648  
         /**
 649  
          * Adds a style to this section's underlying layout.
 650  
          * @see com.google.gwt.user.client.ui.UIObject#addStyleName(java.lang.String)
 651  
          */
 652  
         @Override
 653  
         public void addStyleName(String style) {
 654  0
                 layout.addStyleName(style);
 655  0
         }
 656  
 
 657  
         @Override
 658  
         public void setStyleName(String style) {
 659  0
                 layout.setStyleName(style);
 660  0
         }
 661  
 
 662  
         /**
 663  
          * Sets instructions for this entire section (appears next to section title)
 664  
          * @param html
 665  
          */
 666  
         public void setInstructions(String html){
 667  0
                 layout.setInstructions(html);
 668  0
         }
 669  
 
 670  
         /**
 671  
          * Sets help for this entire section (appears next to section title)
 672  
          * @param html
 673  
          */
 674  
         public void setHelp(String html){
 675  0
                 layout.setHelp(html);
 676  0
         }
 677  
         
 678  
         /**
 679  
          * Sets required for this entire section (appears next to section title)
 680  
          * @param required
 681  
          */
 682  
         public void setRequired(AbbrPanel required){
 683  0
                 layout.setRequired(required);
 684  0
         }
 685  
         
 686  
         public void setSectionId(String id){
 687  0
                 ((Widget)layout).getElement().setId(id);                
 688  0
         }
 689  
 
 690  
 
 691  
         /* METHODS TO ENABLE/DISABLE FIELD */
 692  
         
 693  
         /**
 694  
      * This will progressively enable/disable a set of fields
 695  
      * 
 696  
      * @param isEnabled if the fields should be enabled or disabled
 697  
      * @param fieldDescriptor List of field descriptors to enable/disable
 698  
      */
 699  
         public static void progressiveEnableFields(Boolean isEnabled, FieldDescriptor ... fieldDescriptors){
 700  
                 
 701  0
                 for (FieldDescriptor fd : fieldDescriptors){
 702  0
                         enableField(isEnabled, fd);
 703  
                 } 
 704  0
         }
 705  
         
 706  
         /** 
 707  
          * This will progressively enable/disable and require/unrequire a set of fields
 708  
          * @param isEnabled
 709  
          * @param fieldDescriptors
 710  
          */
 711  
         public static void progressiveEnableAndRequireFields(Boolean isRequiredAndEnabled, FieldDescriptor ... fieldDescriptors){
 712  
 
 713  0
                 for (FieldDescriptor fd : fieldDescriptors){
 714  0
                         fd.setRequired(isRequiredAndEnabled);
 715  0
                         enableField(isRequiredAndEnabled, fd);
 716  
                 } 
 717  0
         }
 718  
         
 719  
          /** 
 720  
      * This will progressively require/unrequire a set of fields
 721  
      * @param isRequired
 722  
      * @param fieldDescriptors
 723  
      */
 724  
     public static void progressiveRequireFields(Boolean isRequired, FieldDescriptor ... fieldDescriptors){
 725  
 
 726  0
         for (FieldDescriptor fd : fieldDescriptors){
 727  0
             fd.setRequired(isRequired);
 728  
         } 
 729  0
     }        
 730  
     
 731  
         /**
 732  
          * Used to enable,disable widget defined in field descriptor 
 733  
          * 
 734  
          * @param isEnabled
 735  
          * @param fd
 736  
          */
 737  
         protected static void enableField(Boolean isEnabled, FieldDescriptor fd){
 738  
                 //TODO: May want to use different styles for field label if not enabled
 739  0
                 Widget widget = fd.getFieldWidget();
 740  
                 
 741  0
                 if (!isEnabled){
 742  0
                         fd.getFieldElement().clearValidationErrors();
 743  0
                         fd.getFieldElement().clearValidationWarnings();
 744  
                 }
 745  
 
 746  
                 //TODO: Make sure this works with all (most?) types of widgets
 747  0
                 if (widget instanceof KSPicker && ((KSPicker)widget).getInputWidget() instanceof KSDropDown){
 748  0
                         ((KSDropDown)((KSPicker)widget).getInputWidget()).setEnabled(isEnabled);                                
 749  0
                 } else if (widget instanceof TextBoxBase){
 750  0
                         ((TextBoxBase)widget).setReadOnly(!isEnabled);
 751  
                 }
 752  0
         }
 753  
         
 754  
         
 755  
 }