Ticket #2395: apply-page-template-dialog-design.patch

File apply-page-template-dialog-design.patch, 37.1 KB (added by deni, 15 years ago)
  • modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/ApplyTemplateInfo.java

    ### Eclipse Workspace Patch 1.0
    #P sophie
     
     1package org.sophie2.main.func.templates.page; 
     2 
     3import java.util.ArrayList; 
     4import java.util.Collections; 
     5import java.util.List; 
     6 
     7import org.sophie2.base.model.book.ElementH; 
     8 
     9/** 
     10 * Holds the settings for applying a page template. 
     11 *  
     12 * @author deni 
     13 */ 
     14public class ApplyTemplateInfo { 
     15         
     16        private List<Slot> slots; 
     17        private boolean deleteOther; 
     18        private ElementH target; 
     19         
     20        /** 
     21         * Creates a new object containing the default settings  
     22         * for applying the given template to the given element. 
     23         *  
     24         * @param templateH 
     25         *              The template that will be applied. 
     26         * @param target 
     27         *              The page to which the template will be applied. 
     28         */ 
     29        public ApplyTemplateInfo(ElementH templateH, ElementH target) { 
     30                this.deleteOther = false; 
     31                this.target = target; 
     32                 
     33                this.slots = new ArrayList<Slot>(); 
     34                for(ElementH subElement : templateH.getSubElements()) { 
     35                        this.slots.add(new Slot(subElement)); 
     36                } 
     37        } 
     38 
     39        /** 
     40         * Gets the element to which the template should be applied. 
     41         *  
     42         * @return 
     43         *              The element to which the template should be applied. 
     44         */ 
     45        public ElementH getTarget() { 
     46                return this.target; 
     47        } 
     48 
     49        /** 
     50         * Gets a list of slots that associate each sub-element of the template 
     51         * with its target. 
     52         *  
     53         * @return 
     54         *              A list of slots. 
     55         */ 
     56        public List<Slot> getSlots() { 
     57                return Collections.unmodifiableList(this.slots); 
     58        } 
     59 
     60        /** 
     61         * Checks whether after applying the template, the existing elements that were unassigned to slots 
     62         * should be deleted. 
     63         *  
     64         * @return 
     65         *              True if the unassigned elements should be deleted, false otherwise. 
     66         */ 
     67        public boolean shouldDeleteOther() { 
     68                return this.deleteOther; 
     69        }        
     70} 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/util/TemplateUtil.java

     
    11package org.sophie2.main.app.commons.util; 
    22 
    33import java.util.List; 
     4import java.util.Map; 
     5import java.util.Map.Entry; 
    46 
    57import org.sophie2.base.commons.util.ImmList; 
    6 import org.sophie2.base.commons.util.ImmMap; 
    78import org.sophie2.base.commons.util.NaiveImmList; 
    8 import org.sophie2.base.dnd.DndTransferable; 
    99import org.sophie2.base.model.book.BookH; 
    1010import org.sophie2.base.model.book.ElementGroupH; 
    1111import org.sophie2.base.model.book.ElementH; 
     
    3333import org.sophie2.main.app.commons.element.ElementView; 
    3434import org.sophie2.main.app.commons.frame.FrameView; 
    3535import org.sophie2.main.app.commons.page.RootPageView; 
    36 import org.sophie2.main.dnd.TemplateRefData; 
    3736 
    3837/** 
    3938 * Utility class used to incorporate helper methods used in templating logic. 
     
    247246        } 
    248247 
    249248        /** 
    250          * Extracts the template data from the given transferable and applies the template 
    251          * to the given page. 
    252          *  
    253          * @param transferable 
    254          *              A DndTransferable containing template data. 
    255          * @param page 
    256          *              The page to apply the template to. 
    257          */ 
    258         public static void applyPageTemplate(DndTransferable transferable, PageH page) { 
    259                 TemplateRefData refData = transferable.getDndData(TemplateRefData.class); 
    260                 assert refData != null : "There is no template to apply"; 
    261                  
    262                 ResourceRefR4 templateRef = refData.getTemplateRef(); 
    263                 ResourceRefR4 pageToTemplateRef = ResourceRefR4.getRelativeRef(page.getRef(), templateRef); 
    264                 ResourceAccess templateAccess = page.getAccess().open(pageToTemplateRef, null); 
    265                 PageH templateH = ResourceH.getHelper(templateAccess, PageH.class); 
    266                  
    267                 applyPageTemplate(page, refData.getTemplateRef(), 
    268                                 null, templateH.getSubElements()); 
    269                  
    270                 AutoAction.registerEndChange(page.getAccess(), "Apply page template"); 
    271         } 
    272  
    273         /** 
    274249         * Applies a template to a page. 
    275250         *  
    276251         * Frames and other page elements are templated by using the frames in the 
     
    285260         * @param page 
    286261         *      The page to apply the template to. 
    287262         * @param pageTemplateRef 
    288          *              A reference to the template to apply. 
    289          * @param templatesToExistingFrames 
     263         *              An absolute reference to the template to apply. 
     264         * @param existingMap 
    290265         *              A map from frames in the given page template to existing frames in the page 
    291266         *              to which the template will be applied. The frames from the template will be used 
    292267         *              as templates for the frames in the page. 
     
    295270         *              as templates. 
    296271         */ 
    297272        public static void applyPageTemplate(PageH page, ResourceRefR4 pageTemplateRef, 
    298                         ImmMap<ResourceRefR4, ResourceRefR4> templatesToExistingFrames, 
    299                         List<ElementH> list) { 
     273                        Map<ResourceRefR4, ResourceRefR4> existingMap, List<ElementH> list) { 
    300274                 
     275                assert pageTemplateRef.isAbsolute(); 
    301276                final ResourceRefR4 pageToTemplateRef =  
    302277                        ResourceRefR4.getRelativeRef(page.getRef(), pageTemplateRef); 
    303278                ResourceAccess templateAccess = page.getAccess().open(pageToTemplateRef, null); 
     
    318293                                } 
    319294                        } 
    320295                }.register(page.getAccess()); 
    321                                  
     296                 
     297                // apply frame templates to existing frames 
     298                if (existingMap != null) { 
     299                        for (Entry<ResourceRefR4, ResourceRefR4> entry : existingMap.entrySet()) { 
     300                                ResourceAccess frameTemplateAccess = page.getAccess().open(entry.getKey(), null); 
     301                                ResourceH frameTemplateH = ResourceH.getHelper(frameTemplateAccess); 
     302                                final NaiveImmList<TemplatedKey<?>> templatedKeys =  
     303                                        frameTemplateH.getApplicableTemplatedKeys(); 
     304                                final String frameTemplateKind = frameTemplateH.getKind(); 
     305 
     306                                ResourceAccess targetAccess = page.getAccess().open(entry.getValue(), null); 
     307                                final ResourceRefR4 targetToTemplateRef = ResourceRefR4.getRelativeRef(entry.getValue(), entry.getKey()); 
     308                                new AutoAction("Applying frame template", false) { 
     309 
     310                                        @Override 
     311                                        public void performAuto() { 
     312                                                TemplateUtil.applyFrameTemplate(getChanger(), templatedKeys.asList(), targetToTemplateRef, 
     313                                                                false, frameTemplateKind, false); 
     314 
     315                                        } 
     316 
     317                                }.register(targetAccess); 
     318                        } 
     319                } 
     320                 
    322321                // create new page elements (groups and frames) from the template 
    323322                for (ElementH subTemplate : list) { 
    324323                        templatePageElement(subTemplate, page); 
  • modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/ApplyPageTemplateHandler.java

     
    11package org.sophie2.main.func.templates.page; 
    22 
     3import java.util.ArrayList; 
     4import java.util.HashMap; 
     5import java.util.Map; 
     6 
     7import org.sophie2.base.dialogs.DialogManager; 
    38import org.sophie2.base.dnd.DndTransferable; 
     9import org.sophie2.base.model.book.ElementH; 
     10import org.sophie2.base.model.book.FrameH; 
     11import org.sophie2.base.model.book.PageH; 
     12import org.sophie2.base.model.resources.r4.ResourceRefR4; 
     13import org.sophie2.base.model.resources.r4.access.ResourceAccess; 
     14import org.sophie2.base.model.resources.r4.changes.AutoAction; 
     15import org.sophie2.base.model.resources.r4.resources.ResourceH; 
    416import org.sophie2.main.app.commons.book.BookView; 
    517import org.sophie2.main.app.commons.element.ElementDropHandler; 
    618import org.sophie2.main.app.commons.page.MainPageView; 
    719import org.sophie2.main.app.commons.util.TemplateUtil; 
    820import org.sophie2.main.dnd.TemplateRefData; 
     21import org.sophie2.main.func.templates.page.Slot.Target; 
    922 
    1023/** 
    1124 * Handles dropping a page template over the {@link MainPageView}. 
     
    3952                TemplateRefData refData = transferable.getDndData(TemplateRefData.class); 
    4053                assert refData != null : "There is no template to apply"; 
    4154                 
    42                 TemplateUtil.applyPageTemplate(transferable,getView().model().get()); 
    43          
    44                 // go to the page that was changed 
    45                 BookView bookView = getView().getBookView();             
    46                 if (bookView.getCurrentPageView().mainPartView().get() != getView()) { 
    47                         bookView.goToPage(getView().model().get().getRef().getThisChildRef()); 
     55                PageH page = getView().model().get(); 
     56                ResourceRefR4 templateRef = refData.getTemplateRef(); 
     57                ResourceRefR4 pageToTemplateRef = ResourceRefR4.getRelativeRef(page.getRef(), templateRef); 
     58                ResourceAccess templateAccess = page.getAccess().open(pageToTemplateRef, null); 
     59                PageH templateH = ResourceH.getHelper(templateAccess, PageH.class); 
     60                 
     61                ApplyPageTemplateDialog.Input input = new ApplyPageTemplateDialog.Input(templateH, page); 
     62                ApplyTemplateInfo info = DialogManager.get().showDialog(input); 
     63                if (info != null) { 
     64                         
     65                        ArrayList<ElementH> newElements = new ArrayList<ElementH>(); 
     66                        Map<ResourceRefR4, ResourceRefR4> existingMap = new HashMap<ResourceRefR4, ResourceRefR4>(); 
     67                        parseInfo(info, newElements, existingMap); 
     68                         
     69                        TemplateUtil.applyPageTemplate(page, refData.getTemplateRef(), 
     70                                        existingMap, newElements); 
     71                         
     72                        AutoAction.registerEndChange(page.getAccess(), "Apply page template"); 
     73 
     74                        // go to the page that was changed 
     75                        BookView bookView = getView().getBookView();             
     76                        if (bookView.getCurrentPageView().mainPartView().get() != getView()) { 
     77                                bookView.goToPage(getView().model().get().getRef().getThisChildRef()); 
     78                        } 
    4879                } 
    4980        } 
     81 
     82        private void parseInfo(ApplyTemplateInfo info, 
     83                        ArrayList<ElementH> newElements, Map<ResourceRefR4, ResourceRefR4> existingMap) { 
     84                for (Slot slot : info.getSlots()) { 
     85                        processSlot(slot, newElements, existingMap); 
     86                } 
     87        } 
     88 
     89        private void processSlot(Slot slot, ArrayList<ElementH> newElements, 
     90                        Map<ResourceRefR4, ResourceRefR4> existingMap) { 
     91                Target target = slot.target().get(); 
     92                if (Target.NONE_TARGET.equals(target)) { 
     93                        return; 
     94                } 
     95                 
     96                if (Target.NEW_TARGET.equals(target)) { 
     97                        newElements.add(slot.template().get()); 
     98                        return; 
     99                } 
     100                 
     101                ElementH template = slot.template().get(); 
     102                if (template instanceof FrameH) { 
     103                        existingMap.put(template.getRef(), target.getTargetResource().getRef()); 
     104                } 
     105        } 
    50106} 
  • modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/MainFuncTemplatesModule.java

     
    22 
    33import java.util.List; 
    44 
     5import org.sophie2.base.dialogs.Dialog; 
    56import org.sophie2.base.skins.BaseSkinPart; 
    67import org.sophie2.base.skins.SkinPart; 
    78import org.sophie2.base.skins.SkinUtil; 
     9import org.sophie2.base.visual.AutoVisualProvider; 
    810import org.sophie2.base.visual.BaseVisualElement; 
    911import org.sophie2.base.visual.SimpleVisualProvider; 
     12import org.sophie2.core.modularity.SimpleSophieExtension; 
    1013import org.sophie2.core.modularity.SophieExtension; 
    1114import org.sophie2.core.modularity.SophieExtensionPoint; 
    1215import org.sophie2.core.modularity.SophieModule; 
     
    1821import org.sophie2.main.func.templates.book.BookTemplatesPalette; 
    1922import org.sophie2.main.func.templates.frame.FrameTemplateLogic; 
    2023import org.sophie2.main.func.templates.frame.FrameTemplatesPalette; 
     24import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog; 
    2125import org.sophie2.main.func.templates.page.PageTemplateLogic; 
    2226import org.sophie2.main.func.templates.page.PageTemplatesPalette; 
     27import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog; 
    2328 
    2429/** 
    2530 * Module class for template functionality. 
     
    3338                // no extension points 
    3439        } 
    3540 
     41        @SuppressWarnings("unchecked") 
    3642        @Override 
    3743        protected void defineExtensions(List<SophieExtension<?>> res) { 
    3844                res.add(SimpleVisualProvider.createExtension( 
     
    5258                 
    5359                SimpleOperation.fillExtensions(res, FrameTemplateLogic.class);           
    5460                SimpleOperation.fillExtensions(res, PageTemplateLogic.class);            
    55                 SimpleOperation.fillExtensions(res, BookTemplatesLogic.class);           
     61                SimpleOperation.fillExtensions(res, BookTemplatesLogic.class); 
     62                 
     63                res.add(new SimpleSophieExtension<Dialog>(Dialog.class, 
     64                                new ApplyPageTemplateDialog())); 
     65                AutoVisualProvider.fillExtensions(res, ApplyPageTemplateSwingDialog.class); 
     66                SimpleOperation.fillExtensions(res, ApplyPageTemplateDialog.DialogLogic.class); 
    5667 
    5768                res.add(makeSkinPart()); 
    5869        } 
  • modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/Slot.java

     
     1package org.sophie2.main.func.templates.page; 
     2 
     3import java.util.ArrayList; 
     4import java.util.List; 
     5 
     6import org.sophie2.base.model.book.ElementH; 
     7import org.sophie2.core.prolib.annot.Own; 
     8import org.sophie2.core.prolib.impl.AutoListProperty; 
     9import org.sophie2.core.prolib.impl.BaseProObject; 
     10import org.sophie2.core.prolib.interfaces.ListProp; 
     11import org.sophie2.core.prolib.interfaces.Prop; 
     12import org.sophie2.core.prolib.interfaces.RwProp; 
     13import org.sophie2.core.prolib.list.ComposingProList; 
     14import org.sophie2.core.prolib.list.ProList; 
     15 
     16/** 
     17 * An association between a template element and its target. The target might be 
     18 * an existing element to which the template should be applied, the indication 
     19 * that a new element should be created by the template or the indication that 
     20 * the template should not be used. 
     21 *  
     22 * @author deni 
     23 */ 
     24public class Slot extends BaseProObject { 
     25         
     26        /** 
     27         * Creates a new slot by template element. 
     28         *  
     29         * @param template 
     30         *              The template for which this slot will be responsible. 
     31         */ 
     32        public Slot(ElementH template) { 
     33                getBean().init(template(), template); 
     34                target().set(Target.NEW_TARGET); 
     35        } 
     36         
     37        /** 
     38         * The parent slot of this one. 
     39         *  
     40         * @return 
     41         *              The property.  
     42         */ 
     43        public Prop<? extends Slot> parent() { 
     44                return getBean().makeParentProp(Slot.class); 
     45        } 
     46         
     47        /** 
     48         * The template this slot is responsible for. 
     49         *  
     50         * @return 
     51         *              The property. 
     52         */ 
     53        public Prop<ElementH> template() { 
     54                return getBean().makeFinalProp("template", ElementH.class); 
     55        } 
     56         
     57        /** 
     58         * The {@link Target} this slot is responsible for. 
     59         *  
     60         * @return 
     61         *              The property. 
     62         */ 
     63        public RwProp<Target> target() { 
     64                return getBean().makeValueProp("target", Target.class); 
     65        } 
     66         
     67        /** 
     68         * A list of slots for the sub-elements of this slot's template. 
     69         *  
     70         * @return 
     71         *              The property. 
     72         */ 
     73        @Own 
     74        public ListProp<Slot> subSlots() { 
     75                class subSlots extends AutoListProperty<Slot> { 
     76                        @Override 
     77                        protected ProList<Slot> constructList() { 
     78                                return new ComposingProList<Slot>() { 
     79                                         
     80                                        @Override 
     81                                        protected List<Slot> computeData() {     
     82                                                ArrayList<Slot> res = new ArrayList<Slot>(); 
     83                                                for(ElementH subTemplate : template().get().getSubElements()) { 
     84                                                        res.add(new Slot(subTemplate)); 
     85                                                } 
     86                                                return res; 
     87                                        } 
     88                                         
     89                                }; 
     90                        } 
     91                } 
     92                return getBean().makeProp(subSlots.class); 
     93        } 
     94         
     95        /** 
     96         * Objects from this class determine what to do with a template - whether to apply it to 
     97         * an existing element (and to which one exactly), to create a new element or do nothing. 
     98         *  
     99         * @author deni 
     100         */ 
     101        public static class Target { 
     102                 
     103                private ElementH targetResource; 
     104                private String name; 
     105                 
     106                private Target(ElementH targetResource, String name) { 
     107                        this.targetResource = targetResource; 
     108                        this.name = name; 
     109                } 
     110                 
     111                /** 
     112                 * The target that determines to create a new element from a template. 
     113                 */ 
     114                public static final Target NEW_TARGET = new Target(null, "New"); 
     115                 
     116                /** 
     117                 * The target that determines to do nothing with the template. 
     118                 */ 
     119                public static final Target NONE_TARGET = new Target(null, "None"); 
     120                 
     121                /** 
     122                 * Creates a new target by existing element. 
     123                 *  
     124                 * @param targetResource 
     125                 *              The element to apply the template to. 
     126                 * @param name 
     127                 *              The name of the target. 
     128                 * @return 
     129                 *              The created object. 
     130                 */ 
     131                public static Target createTarget(ElementH targetResource, String name) { 
     132                        assert targetResource != null : "Targets should be created by real resources"; 
     133                        return new Target(targetResource, name); 
     134                } 
     135                 
     136                /** 
     137                 * Creates a new target by existing element. The default target name is the title  
     138                 * of the element. 
     139                 *  
     140                 * @param targetResource 
     141                 *              The element to apply the template to. 
     142                 * @return 
     143                 *              The created object. 
     144                 */ 
     145                public static Target createTarget(ElementH targetResource) { 
     146                        assert targetResource != null : "Targets should be created by real resources"; 
     147                        return createTarget(targetResource, targetResource.getTitle()); 
     148                } 
     149 
     150                /** 
     151                 * Gets the element to which the template should be applied or null if there is no such 
     152                 * element. 
     153                 *  
     154                 * @return 
     155                 *              The element to which the template should be applied. 
     156                 */ 
     157                public ElementH getTargetResource() { 
     158                        return this.targetResource; 
     159                } 
     160 
     161                /** 
     162                 * Gets the name of the target. 
     163                 *  
     164                 * @return 
     165                 *              The name of the target. 
     166                 */ 
     167                public String getName() { 
     168                        return this.name; 
     169                } 
     170                 
     171                @Override 
     172                public int hashCode() { 
     173                        final int prime = 31; 
     174                        int result = 1; 
     175                        result = prime * result + ((this.name == null) ? 0 : this.name.hashCode()); 
     176                        result = prime * result 
     177                                        + ((this.targetResource == null) ? 0 : this.targetResource.hashCode()); 
     178                        return result; 
     179                } 
     180 
     181                @Override 
     182                public boolean equals(Object obj) { 
     183                        if (this == obj) { 
     184                                return true; 
     185                        } 
     186                        if (obj == null) { 
     187                                return false; 
     188                        } 
     189                        if (getClass() != obj.getClass()) { 
     190                                return false; 
     191                        } 
     192                        Target other = (Target) obj; 
     193                        if (this.name == null) { 
     194                                if (other.name != null) { 
     195                                        return false; 
     196                                } 
     197                        } else { 
     198                                if (!this.name.equals(other.name)) { 
     199                                        return false; 
     200                                } 
     201                        }                        
     202                        if (this.targetResource == null) { 
     203                                if (other.targetResource != null) { 
     204                                        return false; 
     205                                } 
     206                        } else { 
     207                                if (!this.targetResource.equals(other.targetResource)) { 
     208                                        return false; 
     209                                } 
     210                        } 
     211                         
     212                        return true; 
     213                } 
     214 
     215                @Override 
     216                public String toString() { 
     217                        return getName(); 
     218                } 
     219                 
     220        } 
     221} 
  • modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/ApplyPageTemplateDialog.java

     
     1package org.sophie2.main.func.templates.page; 
     2 
     3import java.awt.Dimension; 
     4import java.util.ArrayList; 
     5import java.util.List; 
     6 
     7import javax.swing.BoxLayout; 
     8import javax.swing.JComponent; 
     9import javax.swing.JLabel; 
     10import javax.swing.JPanel; 
     11 
     12import org.sophie2.base.bound.BoundCheckBox; 
     13import org.sophie2.base.bound.BoundComboBox; 
     14import org.sophie2.base.bound.BoundControl; 
     15import org.sophie2.base.bound.BoundValidation; 
     16import org.sophie2.base.bound.ComboInput; 
     17import org.sophie2.base.bound.ComboState; 
     18import org.sophie2.base.bound.BoundControl.EventIds; 
     19import org.sophie2.base.commons.util.position.ImmSize; 
     20import org.sophie2.base.dialogs.Dialog; 
     21import org.sophie2.base.dialogs.DialogInput; 
     22import org.sophie2.base.layout.model.MainWindow; 
     23import org.sophie2.base.model.book.ElementGroupH; 
     24import org.sophie2.base.model.book.ElementH; 
     25import org.sophie2.base.model.book.FrameH; 
     26import org.sophie2.base.model.book.frame.FrameR4; 
     27import org.sophie2.base.model.book.resource.r4.ElementGroupR4; 
     28import org.sophie2.base.model.resources.r4.resources.ResourceR4; 
     29import org.sophie2.base.skins.SkinElementId; 
     30import org.sophie2.base.visual.BaseSwingVisualElement; 
     31import org.sophie2.base.visual.SwingVisualElement; 
     32import org.sophie2.base.visual.skins.ElementSkinPart; 
     33import org.sophie2.base.visual.skins.RelatedChildren; 
     34import org.sophie2.base.visual.skins.SkinPartDef; 
     35import org.sophie2.base.visual.skins.VisualElementDef; 
     36import org.sophie2.core.mvc.EventFilterBuilder; 
     37import org.sophie2.core.mvc.OperationDef; 
     38import org.sophie2.core.mvc.events.EventR3; 
     39import org.sophie2.core.prolib.annot.Own; 
     40import org.sophie2.core.prolib.impl.AutoListProperty; 
     41import org.sophie2.core.prolib.impl.ResourceProperty; 
     42import org.sophie2.core.prolib.interfaces.ListProp; 
     43import org.sophie2.core.prolib.interfaces.Prop; 
     44import org.sophie2.core.prolib.interfaces.RwProp; 
     45import org.sophie2.core.prolib.list.ComposingProList; 
     46import org.sophie2.core.prolib.list.ProList; 
     47import org.sophie2.main.app.commons.dialogs.BaseCustomModalDialog; 
     48import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.TargetComboBox; 
     49import org.sophie2.main.func.templates.page.Slot.Target; 
     50 
     51/** 
     52 * A dialog shown when a page template is going to be applied. 
     53 *  
     54 * @author deni 
     55 */ 
     56public class ApplyPageTemplateDialog extends Dialog<ApplyPageTemplateDialog.Input, ApplyTemplateInfo> { 
     57 
     58        /** 
     59         * Input for {@link ApplyPageTemplateDialog}. 
     60         */ 
     61        public static class Input extends DialogInput<ApplyTemplateInfo> { 
     62                 
     63                private ApplyTemplateInfo applyTemplateInfo; 
     64                 
     65                /** 
     66                 * Constructs an input for the 'Apply page template' dialog.   
     67                 *  
     68                 * @param template 
     69                 *              The template that will be applied. 
     70                 * @param target 
     71                 *              The page to which the template will be applied. 
     72                 */ 
     73                public Input(ElementH template, ElementH target) { 
     74                        this.applyTemplateInfo = new ApplyTemplateInfo(template, target); 
     75                } 
     76                 
     77                @Override 
     78                public Class<ApplyTemplateInfo> getResponseClass() { 
     79                        return ApplyTemplateInfo.class; 
     80                } 
     81                 
     82                /** 
     83                 * Gets the default settings for applying the template to the page. 
     84                 *  
     85                 * @return 
     86                 *              The default ApplyTemplateInfo. 
     87                 */ 
     88                public ApplyTemplateInfo getApplyTemplateInfo() { 
     89                        return this.applyTemplateInfo; 
     90                } 
     91        } 
     92         
     93        /** 
     94         * The actual swing representation of the {@link ApplyPageTemplateDialog}. 
     95         *  
     96         * @author deni 
     97         */ 
     98        @VisualElementDef(parent=MainWindow.class, sortKey="apply-page-template-dialog") 
     99        @SkinElementId("apply-page-template-swing-dialog") 
     100        @RelatedChildren({ 
     101                ApplyPageTemplateSwingDialog.DeleteOtherCheckBox.class, 
     102                ApplyPageTemplateSwingDialog.SlotsPanel.class 
     103        }) 
     104        public static class ApplyPageTemplateSwingDialog extends BaseCustomModalDialog { 
     105                 
     106                /** 
     107                 * The height of the dialog. 
     108                 */ 
     109                public static final int DIALOG_HEIGHT = 240; 
     110 
     111                /** 
     112                 * The width of the dialog. 
     113                 */ 
     114                public static final int DIALOG_WIDTH = 300; 
     115                 
     116                private static final String APPLY_PAGE_TEMPLATE_TITLE = "Apply Page Template"; 
     117                 
     118                @SuppressWarnings("unused") 
     119                @SkinPartDef 
     120                private static void initSkin(ElementSkinPart part) { 
     121                        part.add(DIALOG_RESIZABLE_PROP_ID, false); 
     122                        part.add(TITLE_PROP_ID, APPLY_PAGE_TEMPLATE_TITLE); 
     123                } 
     124                 
     125                /** 
     126                 * Construct the swing representation of the {@link ApplyPageTemplateDialog}. 
     127                 *  
     128                 * @param input  
     129                 *  
     130                 */ 
     131                public ApplyPageTemplateSwingDialog(Input input) { 
     132                        applyTemplateInfo().set(input.getApplyTemplateInfo()); 
     133                } 
     134                 
     135                /** 
     136                 * The {@link ApplyTemplateInfo} this dialog operates on. 
     137                 *  
     138                 * @return 
     139                 *              The property. 
     140                 */ 
     141                public RwProp<ApplyTemplateInfo> applyTemplateInfo() { 
     142                        return getBean().makeValueProp("applyTemplateInfo", ApplyTemplateInfo.class, null); 
     143                } 
     144                 
     145                @Override 
     146                protected JComponent initContent() { 
     147                        return contentPane().get(); 
     148                } 
     149                 
     150                /** 
     151                 * The controls to display in this dialog. 
     152                 *  
     153                 * @return 
     154                 *              List property. 
     155                 */ 
     156                @Own 
     157                protected ListProp<SwingVisualElement> controls() { 
     158                        class controls extends AutoListProperty<SwingVisualElement> { 
     159 
     160                                @SuppressWarnings("synthetic-access") 
     161                                @Override 
     162                                protected ProList<SwingVisualElement> constructList() { 
     163                                        return  createElementPropList(SwingVisualElement.class,  
     164                                                        ApplyPageTemplateSwingDialog.this.getClass(), null); 
     165                                } 
     166                                 
     167                        } 
     168                        return getBean().makeProp(controls.class); 
     169                } 
     170 
     171                /** 
     172                 * The content pane of this dialog. 
     173                 *  
     174                 * @return 
     175                 *              The property. 
     176                 */ 
     177                protected Prop<JPanel> contentPane() { 
     178                        class contentPane extends ResourceProperty<JPanel> { 
     179 
     180                                @Override 
     181                                protected JPanel create() { 
     182                                        JPanel res = new JPanel(); 
     183                                        res.setLayout(new BoxLayout(res, BoxLayout.Y_AXIS));                                    res.setMinimumSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); 
     184                                        res.setMinimumSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); 
     185                                        return res; 
     186                                } 
     187 
     188                                @Override 
     189                                protected void destroy(JPanel res) { 
     190                                        // Nothing... 
     191                                } 
     192 
     193                                @Override 
     194                                protected void setup(JPanel res) { 
     195                                        res.removeAll(); 
     196                                         
     197                                        for (SwingVisualElement control : controls().get()) { 
     198                                                res.add(control.swingComponent().get()); 
     199                                        } 
     200                                         
     201                                } 
     202                                 
     203                        } 
     204                        return getBean().makeProp(contentPane.class); 
     205                } 
     206                 
     207                /** 
     208                 * A checkbox used to choose whether the existing elements that were left unassigned  
     209                 * should be deleted. 
     210                 *  
     211                 * @author deni 
     212                 */ 
     213                @VisualElementDef(parent=ApplyPageTemplateSwingDialog.class, sortKey="bbb-delete-other-check-box") 
     214                public static class DeleteOtherCheckBox extends BoundCheckBox { 
     215                         
     216                        @SuppressWarnings("unused") 
     217                        @SkinPartDef 
     218                        private static void initSkin(ElementSkinPart part) { 
     219                                part.add(TITLE_PROP_ID, "Delete other"); 
     220                                part.add(TOOL_TIP_PROP_ID, "Select whether the groups and frames on the page"  
     221                                                + "that are not in this dialog should be deleted."); 
     222                                part.add(VALIDATION_VISIBLE_ID, false); 
     223                        } 
     224 
     225                        @Override 
     226                        protected Boolean computeModelData() { 
     227                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     228                                if (parentDialog != null && parentDialog.applyTemplateInfo().get() != null ) { 
     229                                        return parentDialog.applyTemplateInfo().get().shouldDeleteOther(); 
     230                                } 
     231                                 
     232                                return false; 
     233                        } 
     234                } 
     235                 
     236                /** 
     237                 * A panel with controls for associating the groups and frames from the template 
     238                 * to their targets. 
     239                 *  
     240                 * @author deni 
     241                 */ 
     242                @VisualElementDef(parent=ApplyPageTemplateSwingDialog.class, sortKey="aaa-slots-panel") 
     243                public static class SlotsPanel extends BaseSwingVisualElement { 
     244 
     245                        /** 
     246                         * The height of a single row (showing a single slot).  
     247                         */ 
     248                        public static final int ROW_HEIGHT = 25; 
     249                         
     250                        @Own 
     251                        private ListProp<TargetComboBox> targetComboBoxes() { 
     252                                class targetComboBoxes extends AutoListProperty<TargetComboBox> { 
     253                                        @Override 
     254                                        protected ProList<TargetComboBox> constructList() { 
     255                                                return new ComposingProList<TargetComboBox>() { 
     256 
     257                                                        @Override 
     258                                                        protected List<? extends TargetComboBox> computeData() { 
     259                                                                ArrayList<TargetComboBox> res = new ArrayList<TargetComboBox>(); 
     260                                                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     261                                                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     262                                                                        return res; 
     263                                                                } 
     264                                                                 
     265                                                                List<Slot> slots = parentDialog.applyTemplateInfo().get().getSlots(); 
     266                                                                for (Slot slot : slots) { 
     267                                                                        addSlot(slot, res); 
     268                                                                }                                                                
     269                                                                return res; 
     270                                                        } 
     271 
     272                                                        private void addSlot(Slot slot, ArrayList<TargetComboBox> res) { 
     273                                                                res.add(new TargetComboBox(slot)); 
     274                                                                for (Slot subSlot : slot.subSlots().get()) { 
     275                                                                        addSlot(subSlot, res); 
     276                                                                }        
     277                                                        } 
     278                                                         
     279                                                }; 
     280                                        } 
     281                                } 
     282                                return getBean().makeProp(targetComboBoxes.class); 
     283                        } 
     284 
     285                        private ListProp<JLabel> titleLabels() { 
     286                                class titleLabels extends AutoListProperty<JLabel> { 
     287                                        @Override 
     288                                        protected ProList<JLabel> constructList() { 
     289                                                return new ComposingProList<JLabel>() { 
     290 
     291                                                        @Override 
     292                                                        protected List<? extends JLabel> computeData() { 
     293                                                                ArrayList<JLabel> res = new ArrayList<JLabel>(); 
     294                                                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     295                                                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     296                                                                        return res; 
     297                                                                } 
     298                                                                 
     299                                                                List<Slot> slots = parentDialog.applyTemplateInfo().get().getSlots(); 
     300                                                                for (Slot slot : slots) { 
     301                                                                        addSlot(slot, "", res); 
     302                                                                }                                                                
     303                                                                return res; 
     304                                                        } 
     305 
     306                                                        private void addSlot(Slot slot, String indent, ArrayList<JLabel> res) { 
     307                                                                JLabel label = new JLabel(indent + slot.template().get().getTitle()); 
     308                                                                label.setPreferredSize(new Dimension(100, ROW_HEIGHT)); 
     309                                                                res.add(label); 
     310                                                                 
     311                                                                for (Slot subSlot : slot.subSlots().get()) { 
     312                                                                        addSlot(subSlot, indent + "  ", res); 
     313                                                                }        
     314                                                        } 
     315                                                         
     316                                                }; 
     317                                        } 
     318                                } 
     319                                return getBean().makeProp(titleLabels.class); 
     320                        } 
     321                         
     322                        public Prop<? extends JComponent> swingComponent() { 
     323                                class swingComponent extends ResourceProperty<JPanel> { 
     324 
     325                                        @Override 
     326                                        protected JPanel create() { 
     327                                                JPanel res = new JPanel(); 
     328                                                 
     329                                                return res; 
     330                                        } 
     331 
     332                                        @Override 
     333                                        protected void destroy(JPanel res) { 
     334                                                // do nothing 
     335                                        } 
     336 
     337                                        @SuppressWarnings("synthetic-access") 
     338                                        @Override 
     339                                        protected void setup(JPanel res) { 
     340                                                res.removeAll(); 
     341                                                 
     342                                                JPanel titlesPanel = new JPanel(); 
     343                                                titlesPanel.setLayout(new BoxLayout(titlesPanel, BoxLayout.Y_AXIS)); 
     344                                                 
     345                                                JPanel comboBoxesPanel = new JPanel(); 
     346                                                comboBoxesPanel.setLayout(new BoxLayout(comboBoxesPanel, BoxLayout.Y_AXIS)); 
     347                                                 
     348                                                int rows = targetComboBoxes().get().size(); 
     349                                                if (rows != titleLabels().get().size()) { 
     350                                                        return; 
     351                                                } 
     352                                                 
     353                                                for (int i = 0; i < rows; i++) { 
     354                                                        titlesPanel.add(titleLabels().get(i)); 
     355                                                        comboBoxesPanel.add(targetComboBoxes().get(i).swingComponent().get()); 
     356                                                } 
     357                                                 
     358                                                res.add(titlesPanel); 
     359                                                res.add(comboBoxesPanel); 
     360                                                 
     361//                                              ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     362//                                              if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     363//                                                      return; 
     364//                                              } 
     365//                                              List<Slot> slots = parentDialog.applyTemplateInfo().get().getSlots(); 
     366//                                              for (Slot slot : slots) { 
     367//                                                      addSlot(slot, "", titlesPanel, comboBoxesPanel); 
     368//                                              } 
     369//                                               
     370//                                              res.add(titlesPanel); 
     371//                                              res.add(comboBoxesPanel); 
     372                                                 
     373                                        } 
     374 
     375                                        private void addSlot(Slot slot, String indent, JPanel titlesPanel,      JPanel comboBoxesPanel) { 
     376                                                JLabel label = new JLabel(indent + slot.template().get().getTitle()); 
     377                                                label.setPreferredSize(new Dimension(100, ROW_HEIGHT)); 
     378                                                titlesPanel.add(label); 
     379                                                TargetComboBox comboBox = new TargetComboBox(slot); 
     380                                                comboBoxesPanel.add(comboBox.swingComponent().get()); 
     381                                                 
     382                                                for (Slot subSlot : slot.subSlots().get()) { 
     383                                                        addSlot(subSlot, indent + "  ", titlesPanel, comboBoxesPanel); 
     384                                                }        
     385                                        } 
     386                                } 
     387                                return getBean().makeProp(swingComponent.class); 
     388                        } 
     389                } 
     390                 
     391                /** 
     392                 * A combobox used to choose the target of a given slot, i.e. what to do 
     393                 * with its template. 
     394                 *  
     395                 * @author deni 
     396                 */ 
     397                public static class TargetComboBox extends BoundComboBox<Target> { 
     398                         
     399                        /** 
     400                         * Creates a new TargetComboBox for choosing the target of a given slot. 
     401                         *  
     402                         * @param slot 
     403                         *              The slot this combobox is associated with. 
     404                         */ 
     405                        public TargetComboBox(Slot slot) { 
     406                                getBean().init(slot(), slot); 
     407                        } 
     408                         
     409                        @SuppressWarnings("unused") 
     410                        @SkinPartDef 
     411                        private static void fillSkinParts(ElementSkinPart part) { 
     412                                part.add(TOOL_TIP_PROP_ID, "Target"); 
     413                                part.add(SIZE_PROP_ID, new ImmSize(150, SlotsPanel.ROW_HEIGHT)); 
     414                                part.add(FIELD_EDITABLE_PROP_ID, Boolean.FALSE); 
     415                                part.add(COMBO_SIZE_PROP_ID, new ImmSize(100, 20)); 
     416                                part.add(VALIDATION_VISIBLE_ID, false); 
     417                        } 
     418                         
     419                        /** 
     420                         * The slot this combobox is associated with. 
     421                         *  
     422                         * @return 
     423                         *              The property. 
     424                         */ 
     425                        public Prop<Slot> slot() { 
     426                                return getBean().makeFinalProp("slot", Slot.class); 
     427                        } 
     428 
     429                        @Override 
     430                        protected ComboState<Target> computeModelData() {                                
     431                                Slot parentSlot = slot().get().parent().get(); 
     432                                String kind = getTemplateKind(); 
     433                                 
     434                                ArrayList<Target> targets = new ArrayList<Target>();                             
     435                                if (parentSlot == null) {                                        
     436                                        targets.add(Target.NEW_TARGET); 
     437                                        targets.add(Target.NONE_TARGET); 
     438                                        targets.addAll(getElementTargets(kind, getTopLevelTarget())); 
     439                                } else {                                         
     440                                        Target parentTarget = parentSlot.target().get(); 
     441                                        if (Target.NONE_TARGET.equals(parentTarget)) { 
     442                                                targets.add(Target.NONE_TARGET); 
     443                                        } else { 
     444                                                if (Target.NEW_TARGET.equals(parentTarget)) { 
     445                                                        targets.add(Target.NEW_TARGET); 
     446                                                        targets.add(Target.NONE_TARGET); 
     447                                                } else { 
     448                                                        assert parentTarget.getTargetResource() != null; 
     449                                                        targets.add(Target.NEW_TARGET); 
     450                                                        targets.add(Target.NONE_TARGET); 
     451                                                        targets.addAll(getElementTargets(kind, parentTarget.getTargetResource())); 
     452                                                } 
     453                                        } 
     454                                } 
     455                                 
     456                                if (!targets.contains(slot().get().target().get())) { 
     457                                        slot().get().target().set(targets.get(0)); 
     458                                } 
     459 
     460                                return new ComboState<Target>("", targets, slot().get().target().get()); 
     461                        } 
     462                         
     463                        private String getTemplateKind() { 
     464                                ElementH template = slot().get().template().get(); 
     465                                if (template instanceof FrameH) { 
     466                                        return FrameR4.KIND; 
     467                                }                                
     468                                assert template instanceof ElementGroupH; 
     469                                return ElementGroupR4.KIND; 
     470                        } 
     471 
     472                        private ElementH getTopLevelTarget() { 
     473                                ApplyPageTemplateSwingDialog parentDialog =  
     474                                        findParentElement(ApplyPageTemplateSwingDialog.class); 
     475                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     476                                        return null; 
     477                                } 
     478                                 
     479                                return parentDialog.applyTemplateInfo().get().getTarget(); 
     480                        } 
     481 
     482                        private ArrayList<Target> getElementTargets(String desiredKind, ElementH parent) { 
     483                                ArrayList<Target> res = new ArrayList<Target>(); 
     484                                if (parent == null) { 
     485                                        return res; 
     486                                } 
     487                                 
     488                                List<ElementH> elements = parent.getSubElements(); 
     489                                for (ElementH element : elements) { 
     490                                        if (ResourceR4.isSuperKind(desiredKind, element.getKind())) { 
     491                                                res.add(Target.createTarget(element)); 
     492                                        } 
     493                                } 
     494                                 
     495                                return res; 
     496                        } 
     497 
     498                        @Override 
     499                        protected BoundValidation validate(ComboInput<Target> inputData) { 
     500                                return BoundValidation.SUCCESS; 
     501                        } 
     502                } 
     503        } 
     504         
     505        @Override 
     506        public Class<Input> getInputClass() { 
     507                return Input.class; 
     508        } 
     509 
     510        @Override 
     511        public Class<ApplyTemplateInfo> getOutputClass() { 
     512                return ApplyTemplateInfo.class; 
     513        } 
     514 
     515        @Override 
     516        protected ApplyTemplateInfo show(Input input) { 
     517                assert input != null; 
     518 
     519                ApplyPageTemplateSwingDialog dialog = new ApplyPageTemplateSwingDialog(input); 
     520                dialog.showDialog(); 
     521 
     522                return dialog.applyTemplateInfo().get(); 
     523        } 
     524         
     525        /** 
     526         * Controller for {@link ApplyPageTemplateDialog}. 
     527         *  
     528         * @author deni 
     529         */ 
     530        public enum DialogLogic implements OperationDef { 
     531                 
     532                /** 
     533                 * Changes the target of a slot. 
     534                 */ 
     535                ON_TARGET_SUBMIT { 
     536 
     537                        public void defineFilter(EventFilterBuilder filter) { 
     538                                filter.setEventId(BoundControl.EventIds.SUBMIT); 
     539                                filter.setSourceClass(TargetComboBox.class); 
     540                        } 
     541 
     542                        @SuppressWarnings("unchecked") 
     543                        public boolean handle(EventR3 event) { 
     544                                TargetComboBox source = event.getSource(TargetComboBox.class); 
     545                                ComboInput<Target> input = event.getEventParam( 
     546                                                EventIds.INPUT_PARAM_INDEX, ComboInput.class); 
     547         
     548                                source.slot().get().target().set(input.getSelectedItem());                               
     549                                return true; 
     550                        } 
     551                         
     552                }; 
     553                 
     554        } 
     555}