Ticket #2410: categories.patch

File categories.patch, 65.8 KB (added by boyanl, 15 years ago)
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/interfaces/ResourceFrame.java

    ### Eclipse Workspace Patch 1.0
    #P sophie
     
    77import org.sophie2.base.model.book.resource.ResourceFilesUtil; 
    88import org.sophie2.base.model.resources.r4.LocationPrefix; 
    99import org.sophie2.base.model.resources.r4.ResourceRefR4; 
     10import org.sophie2.base.model.resources.r4.keys.Category; 
    1011import org.sophie2.base.model.resources.r4.keys.DeeplyCopied; 
    1112import org.sophie2.base.model.resources.r4.keys.TemplatedResourceRefKey; 
     13import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    1214import org.sophie2.base.persistence.commons.PersistenceOptions; 
    1315import org.sophie2.base.persistence.commons.PersistenceUtil; 
    1416import org.sophie2.base.persistence.ref.ValueRef; 
     
    2628         * A key holding a reference to the main resource of the frame. 
    2729         */ 
    2830        @DeeplyCopied 
     31        @Category(Categories.CATEGORY_CONTENT) 
    2932        public static final TemplatedResourceRefKey KEY_MAIN_RESOURCE = 
    3033                new TemplatedResourceRefKey("main-resource", ResourceRefR4.class, 
    3134                                ResourceRefR4.NONE_REF){ 
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/interfaces/StyledElement.java

     
    1515import org.sophie2.base.persistence.commons.PersistenceOptions; 
    1616import org.sophie2.base.persistence.ref.ValueRef; 
    1717import org.sophie2.base.persistence.storage.Storage; 
     18import org.sophie2.base.model.resources.r4.keys.Category; 
     19import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    1820 
    1921/** 
    2022 * An element with a style. Provides keys for background and border. 
    2123 *  
    2224 * @author boyan 
    2325 */ 
     26@Category(Categories.CATEGORY_APPEARANCE) 
    2427public interface StyledElement { 
    2528 
    2629        // ---------- Default constants. ---------- // 
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/interfaces/MemberElement.java

     
    1010import org.sophie2.base.persistence.persister.MasterPersister; 
    1111import org.sophie2.base.persistence.ref.ValueRef; 
    1212import org.sophie2.base.persistence.storage.Storage; 
     13import org.sophie2.base.model.resources.r4.keys.Category; 
     14import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    1315 
    1416/** 
    1517 * An element that is contained in another element. Provides keys for location 
     
    3436         * The location of the element. Relative to the coordinate system of the 
    3537         * parent element. 
    3638         */ 
     39        @Category(Categories.CATEGORY_PROPERTIES) 
    3740        public static final TemplatedKey<LocationChannel> KEY_LOCATION = 
    3841                new TemplatedKey<LocationChannel>("location", LocationChannel.class, LocationChannel.DEFAULT) { 
    3942                private static final String STORAGE_NAME = "content-location"; 
     
    5154        /** 
    5255         * The angle at which the element is rotated. 
    5356         */ 
     57        @Category(Categories.CATEGORY_PROPERTIES) 
    5458        public static final TemplatedKey<Double> KEY_ROTATION_ANGLE = 
    5559                new TemplatedKey<Double>("rotation", Double.class, DEFAULT_ROTATION_ANGLE){ 
    5660                private static final String STORAGE_NAME = "rotation-angle"; 
  • modules/org.sophie2.main.app.halos/src/main/java/org/sophie2/main/app/halos/shared/AddTemplateHaloButton.java

     
    3636import org.sophie2.core.mvc.OperationDef; 
    3737import org.sophie2.core.mvc.events.EventR3; 
    3838import org.sophie2.main.app.commons.book.BookView; 
    39 import org.sophie2.main.app.commons.dialogs.TemplateDialog; 
     39import org.sophie2.main.app.commons.dialogs.CreateTemplateDialog; 
    4040import org.sophie2.main.app.commons.dialogs.TemplateInfo; 
    4141import org.sophie2.main.app.commons.element.ElementView; 
    4242import org.sophie2.main.app.commons.frame.FrameView; 
     
    153153                                } 
    154154 
    155155                                TemplateInfo info = new TemplateInfo(title, templateElemH, false); 
    156                                 TemplateDialog.Input input = new TemplateDialog.Input(pwa.swingComponent().get(), info); 
     156                                CreateTemplateDialog.Input input = new CreateTemplateDialog.Input(pwa.swingComponent().get(), info); 
    157157                                 
    158158 
    159159                                TemplateInfo res = DialogManager.get().showDialog(input); 
  • modules/org.sophie2.base.model.resources.r4/src/main/java/org/sophie2/base/model/resources/r4/resources/ResourceR4.java

     
    11package org.sophie2.base.model.resources.r4.resources; 
    22 
    33import java.io.IOException; 
     4import java.lang.reflect.Field; 
    45import java.net.URI; 
    56import java.util.ArrayList; 
    67import java.util.HashMap; 
     8import java.util.LinkedList; 
    79import java.util.List; 
    810import java.util.Map; 
     11import java.util.Queue; 
     12import java.util.Map.Entry; 
    913 
    1014import org.sophie2.base.model.resources.r4.BaseModelResourcesR4Module; 
    1115import org.sophie2.base.model.resources.r4.ResourceInfoProvider; 
     
    1317import org.sophie2.base.model.resources.r4.BaseModelResourcesR4Module.ResourceR4Point; 
    1418import org.sophie2.base.model.resources.r4.ResourceInfoProvider.KeyEntry; 
    1519import org.sophie2.base.model.resources.r4.access.ResourceAccess; 
     20import org.sophie2.base.model.resources.r4.keys.Category; 
    1621import org.sophie2.base.model.resources.r4.keys.ChildrenKey; 
    1722import org.sophie2.base.model.resources.r4.keys.Key; 
    1823import org.sophie2.base.model.resources.r4.keys.MetaKey; 
     
    231236        } 
    232237         
    233238        /** 
     239         * Gets the keys of a given resource class that are annotated with the {@link Category} as pairs of <category-name, list-of-keys>. 
     240         * @param <R> 
     241         *                      Type of the resource. 
     242         * @param resourceClass 
     243         *            The class of the resource. 
     244         * @return A map of the keys and their names. 
     245         */ 
     246        public static <R extends ResourceR4> Map<String, List<Key<?>>> getCategorizedKeys (Class<R> resourceClass) { 
     247                Map<String, List<Key<?>>> res = new HashMap<String, List<Key<?>>>(); 
     248                Map<Key<?>, String> keysCategories = new HashMap<Key<?>, String> (); 
     249                         
     250                /* 
     251                 * Perform a breadth-first search on the hierarchy and iterate the declared fields in each class/interface. We need to do this because  
     252                 * the annotation could be placed at class level too, and we need to consider its declared fields annotated accordingly. 
     253                 */ 
     254                Queue <Class <?>> parentsQueue = new LinkedList<Class<?>> (); 
     255                parentsQueue.add(resourceClass); 
     256                 
     257                while (!parentsQueue.isEmpty()) { 
     258                        Class<?> currentClass = parentsQueue.poll(); 
     259                         
     260                        Category classAnnotation = currentClass.getAnnotation (Category.class); 
     261                        for (Field field : currentClass.getDeclaredFields()) { 
     262                                try { 
     263                                        if (field.getName().startsWith("KEY_") )  { 
     264                                                Category fieldAnnotation = field.getAnnotation(Category.class), 
     265                                                                 annotationToPut = (fieldAnnotation == null ? classAnnotation : fieldAnnotation); 
     266                                                Key<?> key = (Key<?>) field.get (null); 
     267                                                 
     268                                                if (annotationToPut != null) 
     269                                                        keysCategories.put(key, annotationToPut.value()); 
     270                                        } 
     271                                } 
     272                                catch (IllegalAccessException e) { 
     273                                        throw new RuntimeException("Cannot access a KEY field (" 
     274                                                        + field.getName() + ") in the resource class " 
     275                                                        + resourceClass + "."); 
     276                                } 
     277                        } 
     278                         
     279                        for (Class<? extends ResourceR4> superInterface : currentClass.getInterfaces()) { 
     280                                parentsQueue.add(superInterface);                                                                
     281                        } 
     282                        Class<?> superClass = currentClass.getSuperclass(); 
     283                        if (superClass != null) { 
     284                                parentsQueue.add (superClass); 
     285                        } 
     286                } 
     287         
     288                for (Entry<Key<?>, String> entry : keysCategories.entrySet ()) { 
     289                        List<Key<?>> categoryKeys = res.get(entry.getValue()); 
     290                         
     291                        if (categoryKeys == null) { 
     292                                categoryKeys = new LinkedList <Key<?>> (); 
     293                        } 
     294                         
     295                        categoryKeys.add(entry.getKey ()); 
     296                        res.put(entry.getValue(), categoryKeys); 
     297                } 
     298                 
     299                return res; 
     300        } 
     301         
     302        /** 
    234303         * Gets the keys of a given resource class that should be deeply copied. 
    235304         * @param <R> Type of the resource. 
    236305         *  
  • modules/org.sophie2.extra.func.browser/src/main/java/org/sophie2/extra/func/browser/model/BrowserFrameR4.java

     
    11package org.sophie2.extra.func.browser.model; 
    22 
    33import org.sophie2.base.model.book.frame.FrameR4; 
    4 import org.sophie2.base.model.resources.r4.keys.Key; 
    5 import org.sophie2.base.model.resources.r4.keys.SimpleKey; 
     4import org.sophie2.base.model.resources.r4.keys.Category; 
     5import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
     6import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    67 
    78/** 
    89 * A frame with an embedded browser. 
     
    3334        /** 
    3435         * The url the browser frame shows. 
    3536         */ 
    36         public static final Key<String> KEY_URL = 
    37                 new SimpleKey<String>("url", String.class, DEFAULT_BROWSER_TARGET); 
     37        @Category(Categories.CATEGORY_CONTENT) 
     38        public static final TemplatedKey<String> KEY_URL = 
     39                new TemplatedKey<String>("url", String.class, DEFAULT_BROWSER_TARGET); 
    3840} 
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/frame/FrameR4.java

     
    1111import org.sophie2.base.model.book.interfaces.ResizableElement; 
    1212import org.sophie2.base.model.book.interfaces.StyledElement; 
    1313import org.sophie2.base.model.book.resource.r4.ElementR4; 
     14import org.sophie2.base.model.resources.r4.keys.Category; 
    1415import org.sophie2.base.model.resources.r4.keys.CompositeKey; 
    1516import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
     17import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    1618import org.sophie2.base.model.resources.r4.resources.ResourceR4; 
    1719import org.sophie2.base.persistence.commons.PersistenceOptions; 
    1820import org.sophie2.base.persistence.commons.PersistenceUtil; 
     
    2931 *  
    3032 * @author boyan 
    3133 */ 
     34@Category(Categories.CATEGORY_APPEARANCE) 
    3235public abstract class FrameR4 extends ElementR4 implements MemberElement, StyledElement, ResizableElement { 
    3336 
    3437        /** 
     
    131134        /** 
    132135         * The margins of the frame. 
    133136         */ 
     137        @Category(Categories.CATEGORY_PROPERTIES) 
    134138        public static final TemplatedKey<ImmInsets> KEY_MARGIN_INSETS = 
    135139                new TemplatedKey<ImmInsets>("margin-insets", ImmInsets.class, DEFAULT_MARGIN_INSETS) { 
    136140                @Override 
     
    146150        /** 
    147151         * The paddings of the frame.  
    148152         */ 
     153        @Category(Categories.CATEGORY_PROPERTIES) 
    149154        public static final TemplatedKey<ImmInsets> KEY_PADDING_INSETS = 
    150155                new TemplatedKey<ImmInsets>("padding-insets", ImmInsets.class, DEFAULT_PADDING_INSETS) { 
    151156 
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/interfaces/ResizableElement.java

     
    33import java.io.IOException; 
    44 
    55import org.sophie2.base.commons.util.position.ImmSize; 
     6import org.sophie2.base.model.resources.r4.keys.Category; 
    67import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
     8import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    79import org.sophie2.base.persistence.commons.PersistenceOptions; 
    810import org.sophie2.base.persistence.commons.PersistenceUtil; 
    911import org.sophie2.base.persistence.persister.MasterPersister; 
     
    2527        /** 
    2628         * The size (width and height in pixels) of the element. 
    2729         */ 
     30        @Category(Categories.CATEGORY_PROPERTIES) 
    2831        public static final TemplatedKey<ImmSize> KEY_SIZE = 
    2932                new TemplatedKey<ImmSize>("size", ImmSize.class, ResizableElement.DEFAULT_SIZE) { 
    3033                @Override 
  • modules/org.sophie2.main.func.media/src/main/java/org/sophie2/main/func/media/model/contents/MediaFrameR4.java

     
    44 
    55import org.sophie2.base.model.book.frame.FrameR4; 
    66import org.sophie2.base.model.book.interfaces.ResourceFrame; 
     7import org.sophie2.base.model.resources.r4.keys.Category; 
    78import org.sophie2.base.model.resources.r4.keys.CompositeKey; 
    89import org.sophie2.base.model.resources.r4.keys.Key; 
    910import org.sophie2.base.model.resources.r4.keys.SimpleKey; 
    1011import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
     12import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    1113import org.sophie2.base.persistence.commons.PersistenceOptions; 
    1214import org.sophie2.base.persistence.ref.ValueRef; 
    1315import org.sophie2.base.persistence.storage.Storage; 
     
    4244        /** 
    4345         * A key that holds informations whether the media clip is looped or not. 
    4446         */ 
    45         public static final Key<Boolean> KEY_LOOP = new SimpleKey<Boolean>("loop", Boolean.class, true); 
     47        @Category(Categories.CATEGORY_CONTENT) 
     48        public static final TemplatedKey<Boolean> KEY_LOOP = new TemplatedKey<Boolean>("loop", Boolean.class, true); 
    4649 
    4750        /** 
    4851         * A key that holds informations whether the media clip is clipped, and the 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/MainAppModule.java

     
    4444import org.sophie2.main.app.commons.dialogs.FontChooserDialog; 
    4545import org.sophie2.main.app.commons.dialogs.MessageDialog; 
    4646import org.sophie2.main.app.commons.dialogs.StringDialog; 
    47 import org.sophie2.main.app.commons.dialogs.TemplateDialog; 
     47import org.sophie2.main.app.commons.dialogs.CreateTemplateDialog; 
    4848import org.sophie2.main.app.commons.dialogs.BookPropertiesDialog.BookPropertiesSwingDialog; 
    4949import org.sophie2.main.app.commons.dialogs.BookPropertiesDialog.BookPropertiesSwingDialog.BookPropertiesDialogLogic; 
    5050import org.sophie2.main.app.commons.element.ElementLogic; 
     
    159159                        res.add(new SimpleSophieExtension<Dialog>(Dialog.class, 
    160160                                        new AudioCaptureDialog())); 
    161161                        res.add(new SimpleSophieExtension<Dialog>(Dialog.class, 
    162                                         new TemplateDialog())); 
     162                                        new CreateTemplateDialog())); 
    163163                         
    164164                        AutoVisualProvider.fillExtensions(res, BookPropertiesSwingDialog.class); 
    165165 
     
    204204                        SimpleOperation.fillExtensions(res, MainWindowLogic.class); 
    205205                        SimpleOperation.fillExtensions(res, BookPanelLogic.class); 
    206206                         
    207                         SimpleOperation.fillExtensions(res, TemplateDialog.DialogLogic.class); 
     207                        SimpleOperation.fillExtensions(res, CreateTemplateDialog.DialogLogic.class); 
    208208                                                 
    209209                        SimpleResourceViewProvider.register(res, AppMainWindow.class, 
    210210                                        BookDocView.class, BookR4.KIND, "kkk-book-doc-view"); 
  • modules/org.sophie2.base.model.resources.r4/src/main/java/org/sophie2/base/model/resources/r4/keys/Category.java

     
     1package org.sophie2.base.model.resources.r4.keys; 
     2 
     3import java.lang.annotation.Retention; 
     4import java.lang.annotation.RetentionPolicy; 
     5 
     6 
     7/** 
     8 * Annotation for declaring that a given keys belongs to a given category. Used for 
     9 * categorizing keys in the create template dialog.  
     10 *  
     11 * @author boyanl 
     12 */ 
     13@Retention(RetentionPolicy.RUNTIME) 
     14public @interface Category { 
     15        /**  
     16         * @return 
     17         *                      The value of the annotation 
     18         */ 
     19        String value(); 
     20         
     21         
     22        /** 
     23         * A class containing the names of the pre-defined categories. 
     24         * @author boyanl 
     25         */ 
     26        public static class Categories 
     27        { 
     28                /** 
     29                 * Name of the Appearance category. 
     30                 */ 
     31                public static final String CATEGORY_APPEARANCE = "Appearance"; 
     32                /** 
     33                 * Name of the Content category. 
     34                 */ 
     35                public static final String CATEGORY_CONTENT = "Content"; 
     36                /** 
     37                 * Name of the Properties category. 
     38                 */ 
     39                public static final String CATEGORY_PROPERTIES = "Properties"; 
     40                /** 
     41                 * Name of the Other category. 
     42                 */ 
     43                public static final String CATEGORY_OTHER = "Other"; 
     44        } 
     45} 
     46 No newline at end of file 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/dialogs/CreateTemplateDialog.java

     
    33import java.awt.BorderLayout; 
    44import java.awt.Component; 
    55import java.awt.Dimension; 
     6import java.awt.FlowLayout; 
    67import java.awt.Rectangle; 
    78import java.awt.event.ActionEvent; 
    89import java.awt.event.ActionListener; 
     
    1415import java.util.Collection; 
    1516import java.util.Enumeration; 
    1617import java.util.HashMap; 
     18import java.util.LinkedList; 
    1719import java.util.List; 
    1820import java.util.Map; 
    1921import java.util.Map.Entry; 
     
    3234import javax.swing.tree.TreeModel; 
    3335import javax.swing.tree.TreePath; 
    3436 
     37import org.sophie2.base.bound.BoundCheckBox; 
     38import org.sophie2.base.bound.BoundControl; 
     39import org.sophie2.base.bound.BoundControl.EventIds; 
    3540import org.sophie2.base.commons.gui.TriStateCheckBox; 
    3641import org.sophie2.base.commons.gui.TriStateCheckBox.State; 
    3742import org.sophie2.base.commons.util.ImmList; 
     
    4348import org.sophie2.base.model.resources.r4.keys.CompositeKey; 
    4449import org.sophie2.base.model.resources.r4.keys.Key; 
    4550import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
     51import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    4652import org.sophie2.base.model.resources.r4.resources.ResourceR4; 
    4753import org.sophie2.core.mvc.EventFilterBuilder; 
    4854import org.sophie2.core.mvc.OperationDef; 
    4955import org.sophie2.core.mvc.events.EventR3; 
    50 import org.sophie2.main.app.commons.dialogs.TemplateDialog.CheckBoxTree.CheckNode; 
     56import org.sophie2.core.prolib.interfaces.RwProp; 
     57import org.sophie2.main.app.commons.dialogs.CreateTemplateDialog.CheckBoxTree.CheckNode; 
    5158 
    5259/** 
    5360 * The dialog which is used to add a page or frame as a template. It generates a 
     
    5865 * @author boyanl 
    5966 */ 
    6067@SuppressWarnings("unchecked") 
    61 public class TemplateDialog extends Dialog<TemplateDialog.Input, TemplateInfo> { 
     68public class CreateTemplateDialog extends Dialog<CreateTemplateDialog.Input, TemplateInfo> { 
    6269 
    6370        /** 
    6471         * A check-box tree class which extends (and internally uses) JTree. 
     
    155162                                this.setState (this.state.getState()); 
    156163                        } 
    157164 
     165                        /* 
     166                         * Recalculates the state of the node based on its children. Called after removing a child for example. 
     167                         */ 
     168                        private void recalculateState () { 
     169                                 
     170                                /* 
     171                                 * If either all the nodes are selected or all are de-selected, change the state 
     172                                 * to selected/de-selected. Otherwise, partial 
     173                                 */ 
     174                                 
     175                                boolean allSelected = true, noneSelected = true;  
     176                                Enumeration<CheckNode> e = this.children.elements(); 
     177 
     178                                while (e.hasMoreElements()) { 
     179                                        CheckNode node = e.nextElement(); 
     180                                        if (node.getState () != TriStateCheckBox.State.CHECKED) { 
     181                                                allSelected = false; 
     182                                        } 
     183                                        if (node.getState () != TriStateCheckBox.State.UNCHECKED) { 
     184                                                noneSelected = false; 
     185                                        } 
     186                                        if (!allSelected && !noneSelected) { 
     187                                                break; 
     188                                        } 
     189                                } 
     190                                State newState; 
     191                                if (allSelected) { 
     192                                        newState = State.CHECKED; 
     193                                } else if (noneSelected) { 
     194                                        newState = State.UNCHECKED; 
     195                                } else { 
     196                                        newState = State.PARTIAL;                
     197                                } 
     198                                 
     199                                if (newState != this.state.getState()) { 
     200                                        this.setState(newState); 
     201                                        ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this); 
     202                                } 
     203                        } 
    158204                        /** 
    159205                         * Sets the state of the node. Propagates the changes to children/parent if necessary. 
    160206                         *  
     
    181227 
    182228                                //propagate to parent (if any) 
    183229                                if (this.getParent() != null) { 
    184  
    185                                         /* 
    186                                          * If either all the nodes are selected or all are de-selected, change the state 
    187                                          * to selected/de-selected. Otherwise, partial 
    188                                          */ 
    189                                         boolean allSelected = true, noneSelected = true;  
    190                                         Enumeration<CheckNode> e = this.parent.children(); 
    191  
    192                                         while (e.hasMoreElements()) { 
    193                                                 CheckNode node = e.nextElement(); 
    194                                                 if (node.getState () != TriStateCheckBox.State.CHECKED) { 
    195                                                         allSelected = false; 
    196                                                 } 
    197                                                 if (node.getState () != TriStateCheckBox.State.UNCHECKED) { 
    198                                                         noneSelected = false; 
    199                                                 } 
    200                                                 if (!allSelected && !noneSelected) { 
    201                                                         break; 
    202                                                 } 
    203                                         } 
    204  
    205                                         if (allSelected) { 
    206                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.CHECKED); 
    207                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent); 
    208                                         } else if (noneSelected) { 
    209                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.UNCHECKED); 
    210                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent); 
    211                                         } else { 
    212                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.PARTIAL); 
    213                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent);                                
    214                                         } 
     230                                        ((CheckNode)this.getParent()).recalculateState(); 
    215231                                }        
    216232                        } 
    217233                         
     234                        @Override 
     235                        public void removeFromParent () { 
     236                                CheckNode nodeParent = (CheckNode) this.parent; 
     237                                super.removeFromParent(); 
     238                                 
     239                                if(nodeParent != null) 
     240                                        nodeParent.recalculateState(); 
     241                        } 
     242                         
    218243                        /** 
    219244                         * Changes the node and updates children/parent accordingly. 
    220245                         *   
     
    406431                NaiveImmList.<TemplatedKey<?>>getEmpty(); 
    407432 
    408433        /** 
    409          * Input for {@link TemplateDialog}. 
     434         * Input for {@link CreateTemplateDialog}. 
    410435         */ 
    411436        public static class Input extends DialogInput<TemplateInfo> { 
    412437 
     
    457482        } 
    458483 
    459484        /** 
    460          * The swing representation of the {@link TemplateDialog}. Singleton. 
     485         * A {@link BoundCheckBox} with a simple model. 
     486         */ 
     487        static class StandardCheckBox extends BoundCheckBox { 
     488                /** 
     489                 * The model for the control. 
     490                 *  
     491                 * @return The property. 
     492                 */ 
     493                RwProp<Boolean> value() { 
     494                        return getBean().makeValueProp("value", Boolean.class, false); 
     495                } 
     496 
     497                 
     498                @Override 
     499                protected Boolean computeModelData() { 
     500                        return value().get(); 
     501                } 
     502                 
     503                @Override 
     504                public int computeAlignment() { 
     505                        return FlowLayout.LEFT; 
     506                } 
     507        } 
     508         
     509        /** 
     510         * The swing representation of the {@link CreateTemplateDialog}. Singleton. 
    461511         *  
    462512         * @author jani 
     513         * @author boyanl 
    463514         */ 
    464515        protected static class SwingDialog { 
    465516                 
    466517                /** 
    467                  * An inner class that serves as a key in the map that matches a given key from a given resource to a node in the tree.  
     518                 * An inner class that serves as a key in the map that matches a given key from a given resource to a node in the tree  
    468519                 */ 
    469520                private static class NodeCacheKey { 
    470                  
    471521                        private Key<?> key; 
    472522                        private ResourceRefR4 resourceRef; 
    473523                         
     
    483533                                result = prime * result + ((this.key == null) ? 0 : this.key.hashCode()); 
    484534                                result = prime * result 
    485535                                                + ((this.resourceRef == null) ? 0 : this.resourceRef.hashCode()); 
    486                                                  
    487536                                return result; 
    488537                        } 
    489538 
     
    501550                                 
    502551                                NodeCacheKey other = (NodeCacheKey) obj; 
    503552                                if (this.key == null) { 
    504                                         if (other.key != null) { 
     553                                        if (other.key != null) 
    505554                                                return false; 
    506                                         }        
    507                                 } else if (!this.key.equals(other.key)) { 
     555                                } else if (!this.key.equals(other.key)) 
    508556                                        return false; 
    509                                 } 
    510557                                if (this.resourceRef == null) { 
    511558                                        if (other.resourceRef != null) { 
    512559                                                return false; 
     
    514561                                } else if (!this.resourceRef.equals(other.resourceRef)) { 
    515562                                        return false; 
    516563                                } 
    517                                  
    518564                                return true; 
    519565                        } 
    520566                         
    521567                         
    522568                } 
    523569                 
    524                  
    525570                /** 
    526571                 * The instance of the book template helper. 
    527572                 */ 
     
    540585 
    541586                private JDialog dialog = null; 
    542587                private JPanel mainPanel; 
     588                private JPanel checkBoxPanel; 
    543589                private JLabel titleLabel = null; 
    544590                private JScrollPane treeScrollPane = null; 
    545591                private JTextField titleField = null; 
     
    548594                private JButton selectAllButton = null; 
    549595                private JButton selectNoneButton = null; 
    550596                private CheckBoxTree checkBoxTree = null; 
    551                  
    552597                private Map <NodeCacheKey, CheckNode> keyToNodeMap = null; 
    553598                private Map <ResourceRefR4, Map <Key<?>, Boolean>> keyStates = null; 
    554599                private Map <ResourceRefR4, CheckNode> resourcesCheckNodes; 
    555                 private CheckNode isDefaultTemplateNode = null; 
     600                private StandardCheckBox isDefaultTemplateCheckbox = null; 
    556601 
    557602                /** 
    558603                 * Holds the initial info for the dialog. 
     
    567612                private TemplateInfo resultInfo; 
    568613 
    569614                /** 
    570                  * Construct the swing representation of the {@link TemplateDialog}. 
     615                 * Construct the swing representation of the {@link CreateTemplateDialog}. 
    571616                 *  
    572617                 */ 
    573618                private SwingDialog() { 
     
    597642                        if (this.mainPanel == null) { 
    598643                                this.mainPanel = new JPanel(); 
    599644                                this.mainPanel.setLayout(new BorderLayout()); 
     645                                this.checkBoxPanel = new JPanel (); 
    600646 
    601647                                JPanel top = new JPanel(); 
    602648                                top.add(getTitleLabel()); 
    603649                                top.add(getTitleField()); 
    604                                 top.setPreferredSize(new Dimension(250, 60)); 
     650                                top.setPreferredSize(new Dimension(250, 85)); 
    605651                                top.add(getSelectAllButton()); 
    606652                                top.add(getSelectNoneButton()); 
     653                                top.add (this.checkBoxPanel); 
    607654 
    608655                                JPanel bottom = new JPanel(); 
    609656                                bottom.add(getOkButton()); 
    610657                                bottom.add(getCancelButton()); 
    611658         
    612                                 this.treeScrollPane = new JScrollPane(); 
    613  
     659                                this.treeScrollPane = new JScrollPane();         
     660                                                                 
    614661                                this.mainPanel.add(top, BorderLayout.NORTH); 
    615662                                this.mainPanel.add(this.treeScrollPane, BorderLayout.CENTER); 
    616663                                this.mainPanel.add(bottom, BorderLayout.SOUTH); 
     
    682729                                        @SuppressWarnings("synthetic-access") 
    683730                                        public void actionPerformed(final ActionEvent e) { 
    684731                                                String title = getTitleField().getText(); 
    685                                                 boolean isDefault = SwingDialog.this.isDefaultTemplateNode.isSelected(); 
     732                                                boolean isDefault = SwingDialog.this.isDefaultTemplateCheckbox.value().get(); 
    686733 
    687734                                                for (Entry<ResourceRefR4, Map<Key<?>, Boolean>> entry : SwingDialog.this.keyStates.entrySet()) { 
    688735                                                        for (Entry<Key<?>, Boolean> keyEntry : entry.getValue().entrySet()) { 
     
    694741                                                }                
    695742                                                 
    696743                                                List<ResourceRefR4> toDelete = new ArrayList<ResourceRefR4> (); 
    697                                                 for (Entry<ResourceRefR4, CheckNode> entry : SwingDialog.this.resourcesCheckNodes.entrySet()) { 
     744                                                for (Entry<ResourceRefR4, CheckNode> entry : SwingDialog.this.resourcesCheckNodes.entrySet ()) { 
    698745                                                        if (entry.getValue().getState() == State.UNCHECKED) { 
    699746                                                                toDelete.add(entry.getKey ()); 
    700747                                                        } 
     
    773820                        return this.selectNoneButton; 
    774821                } 
    775822 
     823                /* 
     824                 * Constructs the checkbox tree with a given element, its parent node (if it's null, the element is considered a root), 
     825                 * and a ResourceRef to the root element.  
     826                 */ 
    776827                private void constructTreeFromElement (ElementH element, CheckNode parentNode, ResourceRefR4 rootRef) { 
    777828                        ResourceRefR4 resourceRef = element.getRef(); 
    778829                         
    779830                        /* 
    780                          * Hold an absolute reference to the root element and relative references to the sub-elements. 
     831                         * Hold an absolute reference to the root element and relative references to the sub-elements 
    781832                         */ 
    782833                        if (!resourceRef.equals(rootRef)) { 
    783834                                resourceRef = ResourceRefR4.getRelativeRef (rootRef, resourceRef); 
    784835                        } 
    785                          
    786836                        String title = element.getTitle(); 
    787837                        CheckNode thisNode; 
    788838                         
    789839                        if (parentNode == null) {                       //if no parent node is given, create a new tree and set up its scroll pane 
    790                                 this.checkBoxTree = new CheckBoxTree (this.initialInfo.getTitle()); 
    791                                 this.isDefaultTemplateNode = this.checkBoxTree.addNode (DEFAULT_TEMPLATE_CHECK_BOX_LABEL); 
     840                                this.checkBoxTree = new CheckBoxTree (this.initialInfo.getTitle());                              
    792841                                this.treeScrollPane.setViewportView(this.checkBoxTree); 
    793                                  
    794842                                thisNode = this.checkBoxTree.getRootNode(); 
    795843                        } 
    796844                        else { 
    797845                                thisNode = this.checkBoxTree.addNode (title, parentNode); 
    798846                        } 
    799847                         
    800                         this.resourcesCheckNodes.put(resourceRef, thisNode);                     
     848                        this.resourcesCheckNodes.put(resourceRef, thisNode); 
     849                         
    801850                        Class <? extends ResourceR4> resourceClass = ResourceR4.getClassByKind( element.getKind() ); 
    802851                        Collection<Key<?>> elementKeys = ResourceR4.getKnownKeys(resourceClass).values(); 
    803852                         
     853                        Map<String, List<Key<?>>> annotatedKeys = ResourceR4.getCategorizedKeys(resourceClass); 
     854                        Map<Key<?>, String> keysCategory = new HashMap<Key<?>, String>(); 
    804855                        Map<Key<?>, Boolean> elementKeyMap = new HashMap <Key<?>, Boolean> (); 
     856                         
    805857                        this.keyStates.put(resourceRef, elementKeyMap); 
    806858                         
    807859                        boolean initialKeyState = true; 
     
    809861                                elementKeyMap.put(key, true); 
    810862                        } 
    811863                         
    812                         for (Key<?> key: elementKeys) { 
    813                                 addKey (thisNode, resourceRef, key, initialKeyState, this.keyToNodeMap, elementKeys, 1); 
     864                        String otherCategoryText = Categories.CATEGORY_OTHER, contentCategoryText = Categories.CATEGORY_CONTENT; 
     865                        CheckNode otherCategory = null, contentCategory = null; 
     866                         
     867                        // insert those special categories in the map beforehand so they can be added to the tree 
     868                        if (annotatedKeys.get(otherCategoryText) == null) { 
     869                                annotatedKeys.put (otherCategoryText, new LinkedList<Key<?>>()); 
    814870                        } 
    815871                         
    816                         List<ElementH> childElems = element.getSubElements (); 
    817                         for (ElementH child: childElems) 
    818                                 constructTreeFromElement(child, thisNode, rootRef); 
     872                        if (annotatedKeys.get(contentCategoryText) == null) { 
     873                                annotatedKeys.put (contentCategoryText, new LinkedList<Key<?>>()); 
     874                        } 
     875                         
     876                         
     877                        for (Entry<String, List<Key<?>>> categoryEntry : annotatedKeys.entrySet()) { 
     878                                String categoryName = categoryEntry.getKey(); 
     879                                CheckNode categoryNode = this.checkBoxTree.addNode (categoryName, thisNode); 
     880                                 
     881                                if (categoryName.equals(otherCategoryText)) { 
     882                                        otherCategory = categoryNode; 
     883                                } 
     884                                else if (categoryName.equals(contentCategoryText)) { 
     885                                        contentCategory = categoryNode; 
     886                                } 
     887                                 
     888                                for (Key<?> key : categoryEntry.getValue()) { 
     889                                        addKey (categoryNode, resourceRef, key, initialKeyState, this.keyToNodeMap, elementKeys, 1); 
     890                                        keysCategory.put(key, categoryName); 
     891                                } 
     892                                 
     893                                //delete leaf categories, but don't remove the ones that will be needed later 
     894                                if (categoryNode.isLeaf() && (categoryNode != otherCategory) && (categoryNode != contentCategory)) 
     895                                        categoryNode.removeFromParent(); 
     896                        } 
     897                         
     898                        for (Key<?> key : elementKeys) { 
     899                                if (keysCategory.get(key) == null) { 
     900                                        if (otherCategory == null) { 
     901                                                otherCategory = this.checkBoxTree.addNode(otherCategoryText, thisNode); 
     902                                        } 
     903                                         
     904                                        addKey (otherCategory, resourceRef, key, initialKeyState, this.keyToNodeMap, elementKeys, 1); 
     905                                } 
     906                        } 
     907                         
     908                        if (otherCategory != null && otherCategory.isLeaf()) { 
     909                                otherCategory.removeFromParent(); 
     910                        } 
     911                         
     912                        List<ElementH> children = element.getSubElements(); 
     913                        if (children.size() > 0) 
     914                        {                
     915                                for (ElementH child: children) { 
     916                                        constructTreeFromElement(child, contentCategory, rootRef); 
     917                                } 
     918                        } 
     919                         
     920                        if (contentCategory != null && contentCategory.isLeaf()) { 
     921                                contentCategory.removeFromParent(); 
     922                        } 
    819923                } 
    820                  
     924 
    821925                /** 
    822926                 * Performs setup of the dialog - sets up the title and the panel with 
    823927                 * the checkboxes. 
     
    830934                        this.resourcesCheckNodes = new HashMap<ResourceRefR4, CheckNode> (); 
    831935                         
    832936                        ElementH rootElement = this.initialInfo.getRootElement (); 
    833                         constructTreeFromElement (rootElement, null, rootElement.getRef());                      
     937                        constructTreeFromElement (rootElement, null, rootElement.getRef()); 
     938                         
     939                        this.isDefaultTemplateCheckbox = new StandardCheckBox() { 
     940                                @Override 
     941                                public String computeTitle() { 
     942                                        return DEFAULT_TEMPLATE_CHECK_BOX_LABEL; 
     943                                } 
     944                        }; 
     945                         
     946                        this.checkBoxPanel.removeAll(); 
     947                        this.checkBoxPanel.add(this.isDefaultTemplateCheckbox.swingComponent().get()); 
    834948                        this.checkBoxTree.expandPath(new TreePath (this.checkBoxTree.getRootNode())); 
    835949                } 
    836950 
     
    9171031                 */ 
    9181032                ON_SUBMIT { 
    9191033                        public void defineFilter(EventFilterBuilder filter) { 
    920                                 /*  
    921                                  * Don't define any filter 
    922                                  */ 
    923                         } 
     1034                                        filter.setEventId(BoundControl.EventIds.SUBMIT); 
     1035                                        filter.setSourceClass(StandardCheckBox.class); 
     1036                                } 
    9241037 
    925                         public boolean handle(EventR3 event) { 
    926                                 /* 
    927                                  * Do nothing in the handle method too 
    928                                  */ 
    929                                 return false; 
    930                         } 
     1038                                public boolean handle(EventR3 event) { 
     1039                                        StandardCheckBox source = event.getSource(StandardCheckBox.class); 
     1040                                        Boolean input = event.getEventParam(EventIds.INPUT_PARAM_INDEX, 
     1041                                                        Boolean.class); 
     1042                                        source.value().set(input); 
     1043                                        return true; 
     1044                                } 
    9311045                }; 
    9321046        } 
    9331047 
    9341048        @Override 
    9351049        public Class<Input> getInputClass() { 
    936                 return TemplateDialog.Input.class; 
     1050                return CreateTemplateDialog.Input.class; 
    9371051        } 
    9381052 
    9391053        @Override 
  • modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/resource/r4/ElementR4.java

     
    66import org.sophie2.base.model.book.timelines.VisibleChannel; 
    77import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
    88import org.sophie2.base.model.resources.r4.resources.ResourceR4; 
     9import org.sophie2.base.model.resources.r4.keys.Category; 
     10import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    911 
    1012/** 
    1113 * An element is defined as an entity that holds a timeline. Such entities are 
     
    1618 *  
    1719 * @author boyan 
    1820 */ 
     21@Category(Categories.CATEGORY_PROPERTIES) 
    1922public class ElementR4 extends ResourceR4 { 
    2023 
    2124        /** 
  • modules/org.sophie2.main.func.text/src/main/java/org/sophie2/main/func/text/model/TextTemplateR4.java

     
    44import org.sophie2.base.model.resources.r4.keys.Key; 
    55import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
    66import org.sophie2.main.func.text.chaining.ChainingMode; 
     7import org.sophie2.base.model.resources.r4.keys.Category; 
     8import org.sophie2.base.model.resources.r4.keys.Category.Categories; 
    79 
    810/** 
    911 * This is needed before implementation of the templating of sub-elements. 
     
    2123         * The chain mode of the chain this frame is head of. A string representing 
    2224         * whether chaining is automatic, manual or none. By default there is no chaining. 
    2325         */ 
     26        @Category(Categories.CATEGORY_CONTENT) 
    2427        public static final Key<ChainingMode> KEY_CHAIN_MODE = 
    2528                new TemplatedKey<ChainingMode>("chain-mode", ChainingMode.class, ChainingMode.NO_CHAINING); 
    2629 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/dialogs/TemplateDialog.java

     
    1 package org.sophie2.main.app.commons.dialogs; 
    2  
    3 import java.awt.BorderLayout; 
    4 import java.awt.Component; 
    5 import java.awt.Dimension; 
    6 import java.awt.Rectangle; 
    7 import java.awt.event.ActionEvent; 
    8 import java.awt.event.ActionListener; 
    9 import java.awt.event.FocusEvent; 
    10 import java.awt.event.FocusListener; 
    11 import java.awt.event.MouseAdapter; 
    12 import java.awt.event.MouseEvent; 
    13 import java.util.ArrayList; 
    14 import java.util.Collection; 
    15 import java.util.Enumeration; 
    16 import java.util.HashMap; 
    17 import java.util.List; 
    18 import java.util.Map; 
    19 import java.util.Map.Entry; 
    20  
    21 import javax.swing.JButton; 
    22 import javax.swing.JDialog; 
    23 import javax.swing.JFrame; 
    24 import javax.swing.JLabel; 
    25 import javax.swing.JPanel; 
    26 import javax.swing.JScrollPane; 
    27 import javax.swing.JTextField; 
    28 import javax.swing.JTree; 
    29 import javax.swing.tree.DefaultMutableTreeNode; 
    30 import javax.swing.tree.DefaultTreeModel; 
    31 import javax.swing.tree.TreeCellRenderer; 
    32 import javax.swing.tree.TreeModel; 
    33 import javax.swing.tree.TreePath; 
    34  
    35 import org.sophie2.base.commons.gui.TriStateCheckBox; 
    36 import org.sophie2.base.commons.gui.TriStateCheckBox.State; 
    37 import org.sophie2.base.commons.util.ImmList; 
    38 import org.sophie2.base.commons.util.NaiveImmList; 
    39 import org.sophie2.base.dialogs.Dialog; 
    40 import org.sophie2.base.dialogs.DialogInput; 
    41 import org.sophie2.base.model.book.ElementH; 
    42 import org.sophie2.base.model.resources.r4.ResourceRefR4; 
    43 import org.sophie2.base.model.resources.r4.keys.CompositeKey; 
    44 import org.sophie2.base.model.resources.r4.keys.Key; 
    45 import org.sophie2.base.model.resources.r4.keys.TemplatedKey; 
    46 import org.sophie2.base.model.resources.r4.resources.ResourceR4; 
    47 import org.sophie2.core.mvc.EventFilterBuilder; 
    48 import org.sophie2.core.mvc.OperationDef; 
    49 import org.sophie2.core.mvc.events.EventR3; 
    50 import org.sophie2.main.app.commons.dialogs.TemplateDialog.CheckBoxTree.CheckNode; 
    51  
    52 /** 
    53  * The dialog which is used to add a page or frame as a template. It generates a 
    54  * tree-like structure of checkboxes which represent the {@link Key}s of the 
    55  * object to create a template from. 
    56  *  
    57  * @author jani 
    58  * @author boyanl 
    59  */ 
    60 @SuppressWarnings("unchecked") 
    61 public class TemplateDialog extends Dialog<TemplateDialog.Input, TemplateInfo> { 
    62  
    63         /** 
    64          * A check-box tree class which extends (and internally uses) JTree. 
    65          *  
    66          * @author boyanl 
    67          */ 
    68         public final static class CheckBoxTree extends JTree { 
    69  
    70                 /** 
    71                  * Serial version ID for the class. 
    72                  */ 
    73                 private static final long serialVersionUID = -6024233811457619061L; 
    74  
    75                 /** 
    76                  * A node class for the tree. It contains just the logical data of a node (in this case, a tricheck model),  
    77                  * and a backlink to the container tree (needed for the update logic). 
    78                  *  
    79                  * @author boyanl 
    80                  */ 
    81                 public static class CheckNode extends DefaultMutableTreeNode { 
    82  
    83                         /** 
    84                          * Serial version ID for the class. 
    85                          */ 
    86                         private static final long serialVersionUID = 1701971996798985354L; 
    87  
    88                         /** 
    89                          * A backlink to the containing tree.  
    90                          * Needed for the visual update of items in setState 
    91                          */ 
    92                         private JTree backlink; 
    93  
    94                         private TriStateCheckBox.TriStateModel state; 
    95  
    96                         /** 
    97                          * Default constructor. 
    98                          */ 
    99                         public CheckNode() { 
    100                                 this(null); 
    101                         } 
    102  
    103                         /** 
    104                          * Setter of the backlink. 
    105                          *  
    106                          * @param link  
    107                          *                              The backlink value to set to. 
    108                          */ 
    109                         void setBacklink(JTree link) { 
    110                                 this.backlink = link; 
    111                         } 
    112  
    113                         /** 
    114                          * Constructs the node from a user-defined object (just String is used here, for the label text). 
    115                          *   
    116                          * @param userObject 
    117                          *                                 The user-defined object to construct from. 
    118                          */ 
    119                         public CheckNode(Object userObject) { 
    120                                 this(userObject, true, false); 
    121                         } 
    122  
    123                         /** 
    124                          * Constructs the node from a user-defined object and sets whether the node allows children and is selected. 
    125                          *   
    126                          * @param userObject 
    127                          *                                      The user-passed object. 
    128                          * @param allowsChildren 
    129                          *                                      A parameter indicating whether the node allows children. 
    130                          * @param isSelected 
    131                          *                                      A parameter indicating whether the node is selected. 
    132                          */ 
    133                         public CheckNode(Object userObject, boolean allowsChildren, 
    134                                         boolean isSelected) { 
    135                                 super(userObject, allowsChildren); 
    136                                 this.state = new TriStateCheckBox.TriStateModel(TriStateCheckBox.State.UNCHECKED); 
    137                                 this.state.setSelected(isSelected); 
    138                         } 
    139  
    140                         /** 
    141                          * Gets the state of the check node. 
    142                          *  
    143                          * @return  
    144                          *                      The state of the node 
    145                          */ 
    146                         public TriStateCheckBox.State getState () { 
    147                                 return this.state.getState(); 
    148                         } 
    149  
    150                         /** 
    151                          * Changes the state of the node to the "next" state. 
    152                          */ 
    153                         public void nextState () { 
    154                                 this.state.setPressed(true); 
    155                                 this.setState (this.state.getState()); 
    156                         } 
    157  
    158                         /** 
    159                          * Sets the state of the node. Propagates the changes to children/parent if necessary. 
    160                          *  
    161                          * @param newState 
    162                          *                                      The new state. 
    163                          */ 
    164                         public void setState (TriStateCheckBox.State newState) { 
    165                                 this.state.setState (newState); 
    166                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this); 
    167  
    168                                 // propagate changes to children (if any) 
    169                                 if (this.children != null && newState != TriStateCheckBox.State.PARTIAL) { 
    170                                         Enumeration<CheckNode> e = this.children.elements(); 
    171  
    172                                         while (e.hasMoreElements()) { 
    173                                                 CheckNode node = e.nextElement(); 
    174  
    175                                                 if (node.getState() != newState) { 
    176                                                         node.setState(newState); 
    177                                                         ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (node); 
    178                                                 } 
    179                                         } 
    180                                 } 
    181  
    182                                 //propagate to parent (if any) 
    183                                 if (this.getParent() != null) { 
    184  
    185                                         /* 
    186                                          * If either all the nodes are selected or all are de-selected, change the state 
    187                                          * to selected/de-selected. Otherwise, partial 
    188                                          */ 
    189                                         boolean allSelected = true, noneSelected = true;  
    190                                         Enumeration<CheckNode> e = this.parent.children(); 
    191  
    192                                         while (e.hasMoreElements()) { 
    193                                                 CheckNode node = e.nextElement(); 
    194                                                 if (node.getState () != TriStateCheckBox.State.CHECKED) { 
    195                                                         allSelected = false; 
    196                                                 } 
    197                                                 if (node.getState () != TriStateCheckBox.State.UNCHECKED) { 
    198                                                         noneSelected = false; 
    199                                                 } 
    200                                                 if (!allSelected && !noneSelected) { 
    201                                                         break; 
    202                                                 } 
    203                                         } 
    204  
    205                                         if (allSelected) { 
    206                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.CHECKED); 
    207                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent); 
    208                                         } else if (noneSelected) { 
    209                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.UNCHECKED); 
    210                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent); 
    211                                         } else { 
    212                                                 ((CheckNode) this.parent).setState (TriStateCheckBox.State.PARTIAL); 
    213                                                 ((DefaultTreeModel) this.backlink.getModel ()).nodeChanged (this.parent);                                
    214                                         } 
    215                                 }        
    216                         } 
    217                          
    218                         /** 
    219                          * Changes the node and updates children/parent accordingly. 
    220                          *   
    221                          * @param isSelected 
    222                          *                                 The new state of the node. 
    223                          */ 
    224                         public void setSelected(boolean isSelected) { 
    225                                 this.state.setSelected(isSelected); 
    226                                 setState (this.state.getState()); 
    227                         } 
    228  
    229                         /** 
    230                          * Getter for the isSelected field. 
    231                          *  
    232                          * @return  
    233                          *                      The field.                       
    234                          */ 
    235                         public boolean isSelected() { 
    236                                 return this.state.isSelected(); 
    237                         } 
    238                 } 
    239  
    240                 /** 
    241                  * A renderer class for the tree. Contains the checkbox  
    242                  * and the label used to visualize a node in the tree.  
    243                  *  
    244                  * @author boyanl 
    245                  */ 
    246                 class CheckRenderer extends JPanel implements TreeCellRenderer { 
    247  
    248                         /** 
    249                          * Serial Version ID for the class. 
    250                          */ 
    251                         private static final long serialVersionUID = 6223558893132192535L; 
    252                          
    253                         private TriStateCheckBox check; 
    254                         private JLabel label; 
    255  
    256                         /** 
    257                          * Default constructor, initializes the checkbox and the label. 
    258                          */ 
    259                         CheckRenderer() { 
    260                                 setLayout(null); 
    261                                 add(this.check = new TriStateCheckBox()); 
    262                                 add(this.label = new JLabel ()); 
    263                         } 
    264  
    265                         public Component getTreeCellRendererComponent( 
    266                                         JTree tree, Object value, 
    267                                         boolean isSelected, boolean expanded, boolean leaf, int row, 
    268                                         boolean hasFocus) { 
    269  
    270                                 String stringValue = tree.convertValueToText(value, isSelected,  
    271                                                 expanded, leaf, row, hasFocus); 
    272                                 setEnabled(tree.isEnabled()); 
    273                                 this.label.setText (stringValue); 
    274                                 this.check.setState(((CheckNode) value).getState()); 
    275                                  
    276                                 return this; 
    277                         } 
    278  
    279                         @Override 
    280                         public Dimension getPreferredSize() { 
    281                                 Dimension d_check = this.check.getPreferredSize(); 
    282                                 Dimension d_label = this.label.getPreferredSize(); 
    283                                  
    284                                 return new Dimension(d_check.width + d_label.width, 
    285                                                 (d_check.height < d_label.height ? d_label.height 
    286                                                                 : d_check.height)); 
    287                         } 
    288  
    289                         /** 
    290                          * Layouts the component, centering the label and the checkbox height-wise 
    291                          */ 
    292                         @Override 
    293                         public void doLayout() { 
    294                                 Dimension d_check = this.check.getPreferredSize(); 
    295                                 Dimension d_label = this.label.getPreferredSize(); 
    296  
    297                                 int y_check = 0; 
    298                                 int y_label = 0; 
    299                                 if (d_check.height < d_label.height) { 
    300                                         y_check = (d_label.height - d_check.height) / 2; 
    301                                 } else { 
    302                                         y_label = (d_check.height - d_label.height) / 2; 
    303                                 } 
    304                                  
    305                                 this.check.setLocation(0, y_check); 
    306                                 this.check.setBounds(0, y_check, d_check.width, d_check.height); 
    307                                 this.label.setLocation(d_check.width, y_label); 
    308                                 this.label.setBounds(d_check.width, y_label, d_label.width, d_label.height); 
    309                         }        
    310                 } 
    311  
    312                 private class NodeSelectionListener extends MouseAdapter { 
    313                         private JTree tree; 
    314  
    315                         NodeSelectionListener(final JTree tree) { 
    316                                 this.tree = tree;                        
    317                         } 
    318  
    319                         @Override 
    320                         public void mouseClicked (MouseEvent e) { 
    321                                 int x = e.getX (); 
    322                                 int y = e.getY (); 
    323                                 int row = this.tree.getRowForLocation(x, y); 
    324                                  
    325                                 TreePath path = this.tree.getPathForRow (row); 
    326  
    327                                 if (path != null) { 
    328                                         CheckNode node = (CheckNode) path.getLastPathComponent(); 
    329                                         node.nextState();                        
    330                                 }                        
    331                         }        
    332                 } 
    333  
    334                 /** 
    335                  * Adds a new node with a given text and parent node to the tree. 
    336                  *  
    337                  * @param nodeText 
    338                  *                              The text. 
    339                  * @param parent 
    340                  *                              The parent. 
    341                  * @return  
    342                  *                      The added node. 
    343                  */ 
    344                 public CheckNode addNode (String nodeText, CheckNode parent) { 
    345                         CheckNode node = new CheckNode (nodeText); 
    346                         if (parent != null){ 
    347                                 parent.add(node); 
    348                         } 
    349                         node.setBacklink(this); 
    350                          
    351                         return node; 
    352                 } 
    353                 /** 
    354                  * Adds a new node with a given text and parent node to the tree. 
    355                  *  
    356                  * @param nodeText 
    357                  *                      The text 
    358                  * @return 
    359                  *                      The added node 
    360                  */ 
    361                 public CheckNode addNode (String nodeText) { 
    362                         CheckNode node = new CheckNode (nodeText); 
    363                         CheckNode root = ((CheckNode) this.getModel ().getRoot ()); 
    364                         if (root!= null) { 
    365                                 root.add(node); 
    366                         } 
    367                          
    368                         node.setBacklink(this); 
    369                         return node; 
    370                 } 
    371  
    372                 /** 
    373                  * Getter of the root node. 
    374                  *  
    375                  * @return  
    376                  *                      The root node of the tree. 
    377                  */ 
    378                 public CheckNode getRootNode () { 
    379                         return (CheckNode) this.getModel().getRoot(); 
    380                 } 
    381  
    382                 /** 
    383                  * Constructs a tree with a given root name. 
    384                  *  
    385                  * @param rootName 
    386                  *                                The root name. 
    387                  */ 
    388                 public CheckBoxTree (final String rootName) { 
    389                         super(); 
    390                          
    391                         CheckNode root = new CheckNode (rootName); 
    392                         TreeModel model = new DefaultTreeModel (root); 
    393                         setModel (model); 
    394  
    395                         root.setBacklink (this); 
    396                         setCellRenderer (new CheckRenderer()); 
    397                         addMouseListener(new NodeSelectionListener(this)); 
    398                 } 
    399         } 
    400  
    401  
    402         /* 
    403          * Keys that will be omitted in the checkbox list. 
    404          */ 
    405         private final static ImmList<TemplatedKey<?>> HIDDEN_KEYS =  
    406                 NaiveImmList.<TemplatedKey<?>>getEmpty(); 
    407  
    408         /** 
    409          * Input for {@link TemplateDialog}. 
    410          */ 
    411         public static class Input extends DialogInput<TemplateInfo> { 
    412  
    413                 private Component parent; 
    414                 private TemplateInfo info; 
    415  
    416                 /** 
    417                  * Constructs an input for the book properties dialog. 
    418                  *  
    419                  * @param parent 
    420                  *            The parent which contains the dialog. 
    421                  * @param info 
    422                  *            The initial information for the dialog. Should not be 
    423                  *            null! 
    424                  */ 
    425                 public Input(Component parent, TemplateInfo info) { 
    426                         assert info != null; 
    427  
    428                         this.parent = parent; 
    429                         this.info = info;                
    430                 } 
    431  
    432                 @Override 
    433                 public Class<TemplateInfo> getResponseClass() { 
    434                         return TemplateInfo.class; 
    435                 } 
    436  
    437                 /** 
    438                  * Gets the {@link TemplateInfo} for the dialog. 
    439                  *  
    440                  * @return  
    441                  *                      The {@link TemplateInfo} for the dialog. 
    442                  */ 
    443                 public TemplateInfo getInfo() { 
    444                         return this.info; 
    445                 } 
    446  
    447                 /** 
    448                  * The parent of the dialog. 
    449                  *  
    450                  * @return  
    451                  *                      The parent {@link Component} of the dialog. 
    452                  */ 
    453                 public Component getParent() { 
    454                         return this.parent; 
    455                 } 
    456  
    457         } 
    458  
    459         /** 
    460          * The swing representation of the {@link TemplateDialog}. Singleton. 
    461          *  
    462          * @author jani 
    463          */ 
    464         protected static class SwingDialog { 
    465                  
    466                 /** 
    467                  * An inner class that serves as a key in the map that matches a given key from a given resource to a node in the tree.  
    468                  */ 
    469                 private static class NodeCacheKey { 
    470                  
    471                         private Key<?> key; 
    472                         private ResourceRefR4 resourceRef; 
    473                          
    474                         NodeCacheKey (Key<?> key, ResourceRefR4 resourceRef) { 
    475                                 this.key = key; 
    476                                 this.resourceRef = resourceRef; 
    477                         } 
    478  
    479                         @Override 
    480                         public int hashCode() { 
    481                                 final int prime = 31; 
    482                                 int result = 1; 
    483                                 result = prime * result + ((this.key == null) ? 0 : this.key.hashCode()); 
    484                                 result = prime * result 
    485                                                 + ((this.resourceRef == null) ? 0 : this.resourceRef.hashCode()); 
    486                                                  
    487                                 return result; 
    488                         } 
    489  
    490                         @Override 
    491                         public boolean equals(Object obj) { 
    492                                 if (this == obj) { 
    493                                         return true; 
    494                                 } 
    495                                 if (obj == null) { 
    496                                         return false; 
    497                                 } 
    498                                 if (this.getClass() != obj.getClass()) { 
    499                                         return false; 
    500                                 } 
    501                                  
    502                                 NodeCacheKey other = (NodeCacheKey) obj; 
    503                                 if (this.key == null) { 
    504                                         if (other.key != null) { 
    505                                                 return false; 
    506                                         }        
    507                                 } else if (!this.key.equals(other.key)) { 
    508                                         return false; 
    509                                 } 
    510                                 if (this.resourceRef == null) { 
    511                                         if (other.resourceRef != null) { 
    512                                                 return false; 
    513                                         } 
    514                                 } else if (!this.resourceRef.equals(other.resourceRef)) { 
    515                                         return false; 
    516                                 } 
    517                                  
    518                                 return true; 
    519                         } 
    520                          
    521                          
    522                 } 
    523                  
    524                  
    525                 /** 
    526                  * The instance of the book template helper. 
    527                  */ 
    528                  
    529                 private static SwingDialog instance; 
    530  
    531                 private static final int PANEL_HEIGHT = 300; 
    532                 private static final int PANEL_WIDTH = 300; 
    533                 private static final String DIALOG_TITLE = "Add template"; 
    534                 private static final String OK_BUTTON_LABEL = "Add"; 
    535                 private static final String CANCEL_BUTTON_LABEL = "Cancel"; 
    536                 private static final String SELECT_ALL_BUTTON_LABEL = "Select all"; 
    537                 private static final String SELECT_NONE_BUTTON_LABEL = "Select none"; 
    538                 private static final String TITLE_LABEL = "Template name: "; 
    539                 private static final String DEFAULT_TEMPLATE_CHECK_BOX_LABEL = "Use as a default template"; 
    540  
    541                 private JDialog dialog = null; 
    542                 private JPanel mainPanel; 
    543                 private JLabel titleLabel = null; 
    544                 private JScrollPane treeScrollPane = null; 
    545                 private JTextField titleField = null; 
    546                 private JButton okButton = null; 
    547                 private JButton cancelButton = null; 
    548                 private JButton selectAllButton = null; 
    549                 private JButton selectNoneButton = null; 
    550                 private CheckBoxTree checkBoxTree = null; 
    551                  
    552                 private Map <NodeCacheKey, CheckNode> keyToNodeMap = null; 
    553                 private Map <ResourceRefR4, Map <Key<?>, Boolean>> keyStates = null; 
    554                 private Map <ResourceRefR4, CheckNode> resourcesCheckNodes; 
    555                 private CheckNode isDefaultTemplateNode = null; 
    556  
    557                 /** 
    558                  * Holds the initial info for the dialog. 
    559                  */ 
    560                 private TemplateInfo initialInfo; 
    561  
    562                 /** 
    563                  * The result info for the dialog. 
    564                  *  
    565                  * Updated when the user clicks cancel or ok. 
    566                  */ 
    567                 private TemplateInfo resultInfo; 
    568  
    569                 /** 
    570                  * Construct the swing representation of the {@link TemplateDialog}. 
    571                  *  
    572                  */ 
    573                 private SwingDialog() { 
    574                         // nothing 
    575                 } 
    576  
    577                 /** 
    578                  * Gets the only instance of the swing dialog. 
    579                  *  
    580                  * @return  
    581                  *                      The instance. 
    582                  */ 
    583                 public static SwingDialog get() { 
    584                         if (instance == null) { 
    585                                 instance = new SwingDialog(); 
    586                         } 
    587                         return instance; 
    588                 } 
    589  
    590                 /** 
    591                  * Getter for the main panel. 
    592                  *  
    593                  * @return  
    594                  *                      The main JPanel. 
    595                  */ 
    596                 public JPanel getMainPanel() { 
    597                         if (this.mainPanel == null) { 
    598                                 this.mainPanel = new JPanel(); 
    599                                 this.mainPanel.setLayout(new BorderLayout()); 
    600  
    601                                 JPanel top = new JPanel(); 
    602                                 top.add(getTitleLabel()); 
    603                                 top.add(getTitleField()); 
    604                                 top.setPreferredSize(new Dimension(250, 60)); 
    605                                 top.add(getSelectAllButton()); 
    606                                 top.add(getSelectNoneButton()); 
    607  
    608                                 JPanel bottom = new JPanel(); 
    609                                 bottom.add(getOkButton()); 
    610                                 bottom.add(getCancelButton()); 
    611          
    612                                 this.treeScrollPane = new JScrollPane(); 
    613  
    614                                 this.mainPanel.add(top, BorderLayout.NORTH); 
    615                                 this.mainPanel.add(this.treeScrollPane, BorderLayout.CENTER); 
    616                                 this.mainPanel.add(bottom, BorderLayout.SOUTH); 
    617  
    618                                 this.mainPanel.setSize(PANEL_WIDTH, PANEL_HEIGHT); 
    619                         } 
    620                          
    621                         return this.mainPanel; 
    622                 } 
    623  
    624                 /** 
    625                  * Getter for the title field. 
    626                  *  
    627                  * @return  
    628                  *                      The title {@link JTextField}. 
    629                  */ 
    630                 public JTextField getTitleField() { 
    631                         if (this.titleField == null) { 
    632                                 this.titleField = new JTextField(); 
    633                                 this.titleField.setColumns(15); 
    634                                 this.titleField.setText(this.initialInfo.getTitle()); 
    635                                 this.titleField.addFocusListener(new FocusListener() { 
    636  
    637                                         @SuppressWarnings("synthetic-access") 
    638                                         public void focusLost(FocusEvent e) { 
    639                                                 SwingDialog.this.titleField.select(0, 0); 
    640  
    641                                         } 
    642  
    643                                         @SuppressWarnings("synthetic-access") 
    644                                         public void focusGained(FocusEvent e) { 
    645                                                 SwingDialog.this.titleField.select(0,  
    646                                                                 SwingDialog.this.titleField.getText().length()); 
    647  
    648                                         } 
    649                                 }); 
    650                         } 
    651                         return this.titleField; 
    652                 } 
    653  
    654                 /** 
    655                  * Getter for the title label. 
    656                  *  
    657                  * @return  
    658                  *                      The title {@link JLabel}.  
    659                  */ 
    660                 public JLabel getTitleLabel() { 
    661                         if (this.titleLabel == null) { 
    662                                 this.titleLabel = new JLabel(); 
    663                                 this.titleLabel.setText(TITLE_LABEL); 
    664                         } 
    665                          
    666                         return this.titleLabel; 
    667                 } 
    668  
    669                 /** 
    670                  * Getter for the ok button. 
    671                  *  
    672                  * @return  
    673                  *                      The "OK" {@link JButton}. 
    674                  */ 
    675                 public JButton getOkButton() { 
    676                         if (this.okButton == null) { 
    677  
    678                                 this.okButton = new JButton(); 
    679                                 this.okButton.setText(OK_BUTTON_LABEL); 
    680                                 this.okButton.addActionListener(new ActionListener() { 
    681  
    682                                         @SuppressWarnings("synthetic-access") 
    683                                         public void actionPerformed(final ActionEvent e) { 
    684                                                 String title = getTitleField().getText(); 
    685                                                 boolean isDefault = SwingDialog.this.isDefaultTemplateNode.isSelected(); 
    686  
    687                                                 for (Entry<ResourceRefR4, Map<Key<?>, Boolean>> entry : SwingDialog.this.keyStates.entrySet()) { 
    688                                                         for (Entry<Key<?>, Boolean> keyEntry : entry.getValue().entrySet()) { 
    689                                                                 CheckNode node = SwingDialog.this.keyToNodeMap.get (new NodeCacheKey (keyEntry.getKey(), entry.getKey()) ); 
    690                                                                 if (node != null) { 
    691                                                                         keyEntry.setValue(node.isSelected()); 
    692                                                                 } 
    693                                                         } 
    694                                                 }                
    695                                                  
    696                                                 List<ResourceRefR4> toDelete = new ArrayList<ResourceRefR4> (); 
    697                                                 for (Entry<ResourceRefR4, CheckNode> entry : SwingDialog.this.resourcesCheckNodes.entrySet()) { 
    698                                                         if (entry.getValue().getState() == State.UNCHECKED) { 
    699                                                                 toDelete.add(entry.getKey ()); 
    700                                                         } 
    701                                                 } 
    702                                                  
    703                                                 TemplateInfo res = new TemplateInfo(title, SwingDialog.this.keyStates, toDelete, isDefault);                                     
    704  
    705                                                 setResultInfo(res); 
    706                                                 SwingDialog.this.dialog.setVisible(false); 
    707                                         } 
    708  
    709                                 }); 
    710  
    711                         } 
    712                         return this.okButton; 
    713                 } 
    714  
    715                 /** 
    716                  * Getter for the cancel button. 
    717                  *  
    718                  * @return  
    719                  *                      The "Cancel" {@link JButton}. 
    720                  */ 
    721                 public JButton getCancelButton() { 
    722                         if (this.cancelButton == null) { 
    723                                 this.cancelButton = new JButton(); 
    724                                 this.cancelButton.setText(CANCEL_BUTTON_LABEL); 
    725                                 this.cancelButton.addActionListener(new ActionListener() { 
    726  
    727                                         @SuppressWarnings("synthetic-access") 
    728                                         public void actionPerformed(final ActionEvent e) { 
    729                                                 setResultInfo(null); 
    730                                                 SwingDialog.this.dialog.setVisible(false); 
    731                                         } 
    732                                 }); 
    733  
    734                         } 
    735                         return this.cancelButton; 
    736                 } 
    737  
    738                 /** 
    739                  * Getter for the "select all" button. 
    740                  *  
    741                  * @return  
    742                  *                      The "select all" {@link JButton}. 
    743                  */ 
    744                 public JButton getSelectAllButton() { 
    745                         if (this.selectAllButton == null) { 
    746                                 this.selectAllButton = new JButton(SELECT_ALL_BUTTON_LABEL); 
    747                                 this.selectAllButton.addActionListener(new ActionListener() { 
    748                                         @SuppressWarnings("synthetic-access") 
    749                                         public void actionPerformed(final ActionEvent e) { 
    750                                                 SwingDialog.this.checkBoxTree.getRootNode().setSelected(true); 
    751                                         } 
    752                                 }); 
    753                         } 
    754                         return this.selectAllButton; 
    755                 } 
    756  
    757                 /** 
    758                  * Getter for the "select none" button. 
    759                  *  
    760                  * @return  
    761                  *                      The "select none" {@link JButton}. 
    762                  */ 
    763                 public JButton getSelectNoneButton() { 
    764                         if (this.selectNoneButton == null) { 
    765                                 this.selectNoneButton = new JButton(SELECT_NONE_BUTTON_LABEL); 
    766                                 this.selectNoneButton.addActionListener(new ActionListener() { 
    767                                         @SuppressWarnings("synthetic-access") 
    768                                         public void actionPerformed(final ActionEvent e) { 
    769                                                 SwingDialog.this.checkBoxTree.getRootNode().setSelected(false); 
    770                                         } 
    771                                 }); 
    772                         } 
    773                         return this.selectNoneButton; 
    774                 } 
    775  
    776                 private void constructTreeFromElement (ElementH element, CheckNode parentNode, ResourceRefR4 rootRef) { 
    777                         ResourceRefR4 resourceRef = element.getRef(); 
    778                          
    779                         /* 
    780                          * Hold an absolute reference to the root element and relative references to the sub-elements. 
    781                          */ 
    782                         if (!resourceRef.equals(rootRef)) { 
    783                                 resourceRef = ResourceRefR4.getRelativeRef (rootRef, resourceRef); 
    784                         } 
    785                          
    786                         String title = element.getTitle(); 
    787                         CheckNode thisNode; 
    788                          
    789                         if (parentNode == null) {                       //if no parent node is given, create a new tree and set up its scroll pane 
    790                                 this.checkBoxTree = new CheckBoxTree (this.initialInfo.getTitle()); 
    791                                 this.isDefaultTemplateNode = this.checkBoxTree.addNode (DEFAULT_TEMPLATE_CHECK_BOX_LABEL); 
    792                                 this.treeScrollPane.setViewportView(this.checkBoxTree); 
    793                                  
    794                                 thisNode = this.checkBoxTree.getRootNode(); 
    795                         } 
    796                         else { 
    797                                 thisNode = this.checkBoxTree.addNode (title, parentNode); 
    798                         } 
    799                          
    800                         this.resourcesCheckNodes.put(resourceRef, thisNode);                     
    801                         Class <? extends ResourceR4> resourceClass = ResourceR4.getClassByKind( element.getKind() ); 
    802                         Collection<Key<?>> elementKeys = ResourceR4.getKnownKeys(resourceClass).values(); 
    803                          
    804                         Map<Key<?>, Boolean> elementKeyMap = new HashMap <Key<?>, Boolean> (); 
    805                         this.keyStates.put(resourceRef, elementKeyMap); 
    806                          
    807                         boolean initialKeyState = true; 
    808                         for (Key<?> key : elementKeys) {         
    809                                 elementKeyMap.put(key, true); 
    810                         } 
    811                          
    812                         for (Key<?> key: elementKeys) { 
    813                                 addKey (thisNode, resourceRef, key, initialKeyState, this.keyToNodeMap, elementKeys, 1); 
    814                         } 
    815                          
    816                         List<ElementH> childElems = element.getSubElements (); 
    817                         for (ElementH child: childElems) 
    818                                 constructTreeFromElement(child, thisNode, rootRef); 
    819                 } 
    820                  
    821                 /** 
    822                  * Performs setup of the dialog - sets up the title and the panel with 
    823                  * the checkboxes. 
    824                  */ 
    825                 private void setup() { 
    826                         getTitleField().setText(this.initialInfo.getTitle()); 
    827  
    828                         this.keyToNodeMap = new HashMap<NodeCacheKey, CheckNode>(); 
    829                         this.keyStates = new HashMap<ResourceRefR4, Map<Key<?>, Boolean>> (); 
    830                         this.resourcesCheckNodes = new HashMap<ResourceRefR4, CheckNode> (); 
    831                          
    832                         ElementH rootElement = this.initialInfo.getRootElement (); 
    833                         constructTreeFromElement (rootElement, null, rootElement.getRef());                      
    834                         this.checkBoxTree.expandPath(new TreePath (this.checkBoxTree.getRootNode())); 
    835                 } 
    836  
    837                 /* 
    838                  * Helper method to build the tree, 
    839                  * adds the key if he's at the appropriate level 
    840                  */ 
    841                 @SuppressWarnings("synthetic-access") 
    842  
    843                 private void addKey (CheckNode parent, final ResourceRefR4 resource, final Key<?> key, final Boolean state,  Map<NodeCacheKey, CheckNode> keyControlMap, Collection<Key<?>> keys, int level) { 
    844                         if (key instanceof TemplatedKey) { 
    845                                 if (!HIDDEN_KEYS.contains((TemplatedKey) key) && key.getParts().size() == level) { 
    846                                         ImmList<String> parts = key.getParts(); 
    847                                         String text = parts.get(parts.size() - 1); 
    848                                          
    849                                         CheckNode node = this.checkBoxTree.addNode(text, parent); 
    850                                         node.setSelected(state); 
    851                                         keyControlMap.put(new NodeCacheKey(key, resource), node); 
    852                                 } 
    853                         } 
    854                          
    855                         else if (key instanceof CompositeKey && key.getParts().size() == level) { 
    856                                 ImmList<String> parts = key.getParts(); 
    857                                 String text = parts.get(parts.size() - 1); 
    858                                  
    859                                 CheckNode node = this.checkBoxTree.addNode(text, parent); 
    860                                  
    861                                 String prefix = key.getId().concat(Key.SEPARATOR); 
    862                                 for (final Key<?> subKey : keys) { 
    863                                         String keyId = subKey.getId(); 
    864                                         if (keyId.startsWith(prefix)) { 
    865                                                 Boolean subState = this.keyStates.get(resource).get(subKey); 
    866                                                 addKey(node, resource, subKey, subState, this.keyToNodeMap, keys, level + 1);                                                    
    867                                         } 
    868                                 } 
    869                         } 
    870                 } 
    871  
    872                 /** 
    873                  * Gets the result info (after the user has clicked ok/cancel). 
    874                  *  
    875                  * @return  
    876                  *                      The result info or null if canceled. 
    877                  */ 
    878                 public TemplateInfo getResult() { 
    879                         return this.resultInfo; 
    880                 } 
    881  
    882                 private void setResultInfo(TemplateInfo resultInfo) { 
    883                         this.resultInfo = resultInfo; 
    884                 } 
    885  
    886                 /** 
    887                  * Shows this dialog as a modal to the user.  
    888                  *  
    889                  * @param input 
    890                  *            The initial values for the fields. 
    891                  * @param parentFrame 
    892                  *            The frame that this dialog corresponds to. 
    893                  */ 
    894                 public void show(TemplateInfo input, JFrame parentFrame) { 
    895                         this.initialInfo = input; 
    896                         if (this.dialog == null) { 
    897                                 this.dialog = new JDialog(parentFrame, true); 
    898                                 this.dialog.getContentPane().add(getMainPanel()); 
    899                                 this.dialog.setTitle(DIALOG_TITLE); 
    900                                 this.dialog.setBounds(new Rectangle(0, 0, PANEL_WIDTH, PANEL_HEIGHT)); 
    901                                 this.dialog.setLocationRelativeTo(parentFrame); 
    902                                 this.dialog.setResizable(false); 
    903                                 this.dialog.getRootPane().setDefaultButton(getOkButton()); 
    904                         } 
    905                         this.setup(); 
    906                         this.dialog.setVisible(true); 
    907                 } 
    908         } 
    909  
    910         /** 
    911          * Controller for dialog. 
    912          */ 
    913         public static enum DialogLogic implements OperationDef { 
    914  
    915                 /** 
    916                  * The submit action. 
    917                  */ 
    918                 ON_SUBMIT { 
    919                         public void defineFilter(EventFilterBuilder filter) { 
    920                                 /*  
    921                                  * Don't define any filter 
    922                                  */ 
    923                         } 
    924  
    925                         public boolean handle(EventR3 event) { 
    926                                 /* 
    927                                  * Do nothing in the handle method too 
    928                                  */ 
    929                                 return false; 
    930                         } 
    931                 }; 
    932         } 
    933  
    934         @Override 
    935         public Class<Input> getInputClass() { 
    936                 return TemplateDialog.Input.class; 
    937         } 
    938  
    939         @Override 
    940         public Class<TemplateInfo> getOutputClass() { 
    941                 return TemplateInfo.class; 
    942         } 
    943  
    944         @SuppressWarnings("synthetic-access") 
    945         @Override 
    946         protected TemplateInfo show(Input input) { 
    947                 assert input != null; 
    948  
    949                 SwingDialog.get().show(input.getInfo(), null); 
    950  
    951                 TemplateInfo result = SwingDialog.get().getResult(); 
    952  
    953                 SwingDialog.get().setResultInfo(null); 
    954  
    955                 return result; 
    956         } 
    957 } 
    958  No newline at end of file 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/dialogs/TemplateInfo.java

     
    1515 * the value of the key should be applied when the template itself is applied. 
    1616 *  
    1717 * @author jani 
     18 * @author boyanl 
    1819 */ 
    1920@Immutable 
    2021public class TemplateInfo {