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

File apply-page-template-dialog-impl.patch, 59.7 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.List; 
     5 
     6import org.sophie2.base.model.book.ElementH; 
     7import org.sophie2.core.prolib.impl.AutoListProperty; 
     8import org.sophie2.core.prolib.impl.BaseProObject; 
     9import org.sophie2.core.prolib.interfaces.ListProp; 
     10import org.sophie2.core.prolib.interfaces.Prop; 
     11import org.sophie2.core.prolib.interfaces.RwProp; 
     12import org.sophie2.core.prolib.list.ComposingProList; 
     13import org.sophie2.core.prolib.list.ProList; 
     14 
     15/** 
     16 * Holds the settings for applying a page template. 
     17 *  
     18 * @author deni 
     19 */ 
     20public class ApplyTemplateInfo extends BaseProObject { 
     21                 
     22        /** 
     23         * Creates a new object containing the default settings  
     24         * for applying the given template to the given element. 
     25         *  
     26         * @param template 
     27         *              The template that will be applied. 
     28         * @param target 
     29         *              The page to which the template will be applied. 
     30         */ 
     31        public ApplyTemplateInfo(ElementH template, ElementH target) { 
     32                getBean().init(template(), template); 
     33                getBean().init(target(), target); 
     34        } 
     35         
     36        /** 
     37         * Property holding the element (usually page) to which the template will be applied. 
     38         *  
     39         * @return 
     40         *              The property. 
     41         */ 
     42        public Prop<ElementH> target() { 
     43                return getBean().makeFinalProp("target", ElementH.class); 
     44        } 
     45         
     46        private Prop<ElementH> template() { 
     47                return getBean().makeFinalProp("template", ElementH.class); 
     48        } 
     49         
     50 
     51        /** 
     52         * Property holding the list of slots that associate each sub-element of the template 
     53         * with its target. 
     54         *  
     55         * @return 
     56         *              The property. 
     57         */ 
     58        public ListProp<Slot> slots() { 
     59                class slots extends AutoListProperty<Slot> { 
     60 
     61                        @Override 
     62                        protected ProList<Slot> constructList() { 
     63                                return new ComposingProList<Slot>() { 
     64 
     65                                        @SuppressWarnings("synthetic-access") 
     66                                        @Override 
     67                                        protected List<Slot> computeData() { 
     68                                                ArrayList<Slot> res = new ArrayList<Slot>(); 
     69                                                for(ElementH subElement : template().get().getSubElements()) { 
     70                                                        res.add(new Slot(subElement)); 
     71                                                } 
     72                                                 
     73                                                return res; 
     74                                        } 
     75                                         
     76                                }; 
     77                        } 
     78                         
     79                } 
     80                return getBean().makeProp(slots.class); 
     81        } 
     82         
     83        /** 
     84         * Property holding whether after applying the template, the existing elements  
     85         * that were unassigned to slots should be deleted. 
     86         *  
     87         * @return 
     88         *              The property. 
     89         */ 
     90        public RwProp<Boolean> deleteUnassigned() { 
     91                return getBean().makeValueProp("deleteUnassigned", Boolean.class, Boolean.FALSE); 
     92        } 
     93} 
  • 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 
     3import java.util.ArrayList; 
     4import java.util.HashMap; 
    35import java.util.List; 
     6import java.util.Map; 
    47 
    58import org.sophie2.base.commons.util.ImmList; 
    6 import org.sophie2.base.commons.util.ImmMap; 
    79import org.sophie2.base.commons.util.NaiveImmList; 
    8 import org.sophie2.base.dnd.DndTransferable; 
    910import org.sophie2.base.model.book.BookH; 
    1011import org.sophie2.base.model.book.ElementGroupH; 
    1112import org.sophie2.base.model.book.ElementH; 
     
    3334import org.sophie2.main.app.commons.element.ElementView; 
    3435import org.sophie2.main.app.commons.frame.FrameView; 
    3536import org.sophie2.main.app.commons.page.RootPageView; 
    36 import org.sophie2.main.dnd.TemplateRefData; 
    3737 
    3838/** 
    3939 * Utility class used to incorporate helper methods used in templating logic. 
     
    247247        } 
    248248 
    249249        /** 
    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         /** 
    274250         * Applies a template to a page. 
    275251         *  
    276252         * Frames and other page elements are templated by using the frames in the 
     
    286262         *      The page to apply the template to. 
    287263         * @param pageTemplateRef 
    288264         *              An absolute reference to the template to apply. 
    289          * @param templatesToExistingFrames 
     265         * @param existingMap 
    290266         *              A map from frames in the given page template to existing frames in the page 
    291267         *              to which the template will be applied. The frames from the template will be used 
    292268         *              as templates for the frames in the page. 
     
    295271         *              as templates. 
    296272         */ 
    297273        public static void applyPageTemplate(PageH page, ResourceRefR4 pageTemplateRef, 
    298                         ImmMap<ResourceRefR4, ResourceRefR4> templatesToExistingFrames, 
    299                         List<ElementH> list) { 
     274                        Map<ResourceRefR4, ResourceRefR4> existingMap, List<ResourceRefR4> list) { 
    300275                 
    301276                assert pageTemplateRef.isAbsolute(); 
    302277                final ResourceRefR4 pageToTemplateRef =  
     
    319294                                } 
    320295                        } 
    321296                }.register(page.getAccess()); 
    322                                  
    323                 // create new page elements (groups and frames) from the template 
    324                 for (ElementH subTemplate : list) { 
    325                         templatePageElement(subTemplate, page); 
     297                 
     298                // template page elements 
     299                List<ResourceRefR4> elementsToCreate = list != null ? list : new ArrayList<ResourceRefR4>(); 
     300                Map<ResourceRefR4, ResourceRefR4> existingElelements =  
     301                        existingMap != null ? existingMap : new HashMap<ResourceRefR4, ResourceRefR4>(); 
     302                for (ElementH subTemplate : templateH.getSubElements()) { 
     303                        templatePageElements(subTemplate, page, elementsToCreate, existingElelements); 
    326304                } 
    327305        } 
    328306         
    329         private static void templatePageElement(ElementH templateH, ElementH parent) {           
     307        private static void templatePageElements(ElementH templateH, ElementH parent,  
     308                        List<ResourceRefR4> newElements, Map<ResourceRefR4, ResourceRefR4> existing) { 
     309 
     310                if (!newElements.contains(templateH.getRef()) && !existing.containsKey(templateH.getRef())) { 
     311                        return; 
     312                } 
     313         
    330314                if (templateH instanceof ElementGroupH) { 
    331315                         
    332                         final ResourceRefR4 groupRef = ResourceRefR4.generateRandomSub(ElementGroupH.NAME_PREFIX); 
    333                         final String groupTitle = templateH.getTitle(); 
    334                         final ImmList<ActivationChannel> parentElements =  
    335                                 CompositeElement.KEY_SUB_ELEMENTS.get(parent.getAccess()); 
     316                        ResourceRefR4 nextParentRef; 
     317                        if (newElements.contains(templateH.getRef())) { 
     318                                assert !existing.containsKey(templateH.getRef()); 
     319                                nextParentRef = createNewEmptyGroup((ElementGroupH)templateH, parent); 
     320                        } else { 
     321                                nextParentRef = existing.get(templateH.getRef()); 
     322                        } 
    336323                         
    337                         new AutoAction("Create group for template", false) { 
    338                                  
    339                                 @Override 
    340                                 public void performAuto() { 
    341                                         ResourceChanger ch = getChanger(); 
    342                                         ch.makeResource(groupRef); 
    343                                         ch.setRaw(CompositeElement.KEY_SUB_ELEMENTS,  
    344                                                         parentElements.add(new ActivationChannel(groupRef))); 
    345                                          
    346                                         ResourceChanger groupCh = ch.getSub(groupRef); 
    347                                         groupCh.setRaw(ResourceR4.KEY_KIND, ElementGroupR4.KIND); 
    348                                         groupCh.setRaw(ResourceR4.KEY_TITLE, groupTitle); 
    349                                 } 
    350                                  
    351                         }.register(parent.getAccess()); 
    352                          
    353                         ResourceAccess groupAccess = parent.getAccess().open(groupRef, null); 
     324                        ResourceAccess groupAccess = parent.getAccess().open(nextParentRef, null); 
    354325                        ElementGroupH groupH = ResourceH.getHelper(groupAccess, ElementGroupH.class); 
    355326                         
    356327                        for (ElementH element : templateH.getSubElements()) { 
    357                                 templatePageElement(element, groupH); 
     328                                templatePageElements(element, groupH, newElements, existing); 
    358329                        } 
    359330                } 
    360                  
     331 
    361332                if (templateH instanceof FrameH) { 
    362                         final ResourceRefR4 templateRef = templateH.getRef(); 
    363                         final String frameKind = templateH.getKind(); 
    364                         final NaiveImmList<TemplatedKey<?>> immKeys = templateH.getApplicableTemplatedKeys(); 
     333                        if (newElements.contains(templateH.getRef())) { 
     334                                assert !existing.containsKey(templateH.getRef()); 
     335                                createFrameByTemplate((FrameH) templateH, parent); 
     336                        } else { 
     337                                ResourceRefR4 targetFrameRef = existing.get(templateH.getRef()); 
     338                                applyFrameTemplate((FrameH) templateH, parent, targetFrameRef); 
     339                        } 
     340                } 
     341        } 
    365342 
    366                         final ResourceRefR4 frameRef = ResourceRefR4.generateRandomSub(FrameH.NAME_PREFIX); 
    367                         final String frameTitle = templateH.getTitle(); 
     343        private static ResourceRefR4 createNewEmptyGroup(ElementGroupH templateH, ElementH parent) { 
     344                final ResourceRefR4 groupRef = ResourceRefR4.generateRandomSub(ElementGroupH.NAME_PREFIX); 
     345                final String groupTitle = templateH.getTitle(); 
     346                final ImmList<ActivationChannel> parentElements =  
     347                        CompositeElement.KEY_SUB_ELEMENTS.get(parent.getAccess()); 
    368348 
    369                         final ResourceRefR4 parentRef = parent.getRef(); 
    370                         final ImmList<ActivationChannel> elements =  
    371                                 CompositeElement.KEY_SUB_ELEMENTS.get(parent.getAccess()); 
     349                new AutoAction("Create group for template", false) { 
    372350 
    373                         new AutoAction("Create frame for template", false) { 
    374                                 @Override 
    375                                 public void performAuto() { 
    376                                         ResourceChanger ch = getChanger(); 
    377                                          
    378                                         FrameH.create(ch, frameRef, frameTitle, elements, frameKind, 
    379                                                         MemberElement.DEFAULT_LOCATION, FrameR4.DEFAULT_FRAME_SIZE); 
    380                                          
    381                                         ResourceRefR4 frameToTemplateRef = ResourceRefR4.getRelativeRef( 
    382                                                         parentRef.append(frameRef), templateRef);                                        
    383                                         TemplateUtil.applyFrameTemplate(ch.getSub(frameRef),  
    384                                                         immKeys.asList(), 
    385                                                         frameToTemplateRef, false, frameKind, false); 
    386                                         } 
    387                         }.register(parent.getAccess()); 
    388                 } 
    389                  
    390                 parent.getAccess().getHead().getModel().debugPrint(); 
     351                        @Override 
     352                        public void performAuto() { 
     353                                ResourceChanger ch = getChanger(); 
     354                                ch.makeResource(groupRef); 
     355                                ch.setRaw(CompositeElement.KEY_SUB_ELEMENTS,  
     356                                                parentElements.add(new ActivationChannel(groupRef))); 
     357 
     358                                ResourceChanger groupCh = ch.getSub(groupRef); 
     359                                groupCh.setRaw(ResourceR4.KEY_KIND, ElementGroupR4.KIND); 
     360                                groupCh.setRaw(ResourceR4.KEY_TITLE, groupTitle); 
     361                        } 
     362 
     363                }.register(parent.getAccess()); 
     364 
     365                return groupRef; 
    391366        } 
     367         
     368        private static void createFrameByTemplate(FrameH templateH, ElementH parent) { 
     369                final ResourceRefR4 templateRef = templateH.getRef(); 
     370                final String frameKind = templateH.getKind(); 
     371                final NaiveImmList<TemplatedKey<?>> immKeys = templateH.getApplicableTemplatedKeys(); 
    392372 
     373                final ResourceRefR4 frameRef = ResourceRefR4.generateRandomSub(FrameH.NAME_PREFIX); 
     374                final String frameTitle = templateH.getTitle(); 
     375 
     376                final ResourceRefR4 parentRef = parent.getRef(); 
     377                final ImmList<ActivationChannel> elements =  
     378                        CompositeElement.KEY_SUB_ELEMENTS.get(parent.getAccess()); 
     379 
     380                new AutoAction("Create frame for template", false) { 
     381                        @Override 
     382                        public void performAuto() { 
     383                                ResourceChanger ch = getChanger(); 
     384 
     385                                FrameH.create(ch, frameRef, frameTitle, elements, frameKind, 
     386                                                MemberElement.DEFAULT_LOCATION, FrameR4.DEFAULT_FRAME_SIZE); 
     387 
     388                                ResourceRefR4 frameToTemplateRef = ResourceRefR4.getRelativeRef( 
     389                                                parentRef.append(frameRef), templateRef);                                        
     390                                TemplateUtil.applyFrameTemplate(ch.getSub(frameRef),  
     391                                                immKeys.asList(), 
     392                                                frameToTemplateRef, false, frameKind, false); 
     393                        } 
     394                }.register(parent.getAccess()); 
     395        } 
     396         
     397        private static void applyFrameTemplate(FrameH templateH, ElementH parent, ResourceRefR4 frameRef) { 
     398                ResourceAccess frameAccess = parent.getAccess().open(frameRef, null); 
     399 
     400                final NaiveImmList<TemplatedKey<?>> templatedKeys =  
     401                        templateH.getApplicableTemplatedKeys(); 
     402                final String frameTemplateKind = templateH.getKind(); 
     403 
     404                final ResourceRefR4 targetToTemplateRef =  
     405                        ResourceRefR4.getRelativeRef(frameRef, templateH.getRef()); 
     406                new AutoAction("Applying frame template", false) { 
     407 
     408                        @Override 
     409                        public void performAuto() { 
     410                                TemplateUtil.applyFrameTemplate(getChanger(), templatedKeys.asList(),  
     411                                                targetToTemplateRef, false, frameTemplateKind, false); 
     412                        } 
     413 
     414                }.register(frameAccess); 
     415        } 
     416 
    393417} 
  • modules/org.sophie2.main.func.links/src/main/java/org/sophie2/main/func/links/LinksHud.java

     
    6161        /** 
    6262         * The {@link Skin} property id of the title of the {@link #EMPTY_RULE} item. 
    6363         */ 
    64         public static final String EMPTY_RULE_TITLE_PROP_ID = null; 
     64        public static final String EMPTY_RULE_TITLE_PROP_ID = "empty-rule-title"; 
    6565 
    6666        @SuppressWarnings("unused") 
    6767        @SkinPartDef 
  • 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.PageH; 
     11import org.sophie2.base.model.resources.r4.ResourceRefR4; 
     12import org.sophie2.base.model.resources.r4.access.ResourceAccess; 
     13import org.sophie2.base.model.resources.r4.changes.AutoAction; 
     14import org.sophie2.base.model.resources.r4.resources.ResourceH; 
    415import org.sophie2.main.app.commons.book.BookView; 
    516import org.sophie2.main.app.commons.element.ElementDropHandler; 
    617import org.sophie2.main.app.commons.page.MainPageView; 
    718import org.sophie2.main.app.commons.util.TemplateUtil; 
    819import org.sophie2.main.dnd.TemplateRefData; 
     20import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog; 
    921 
    1022/** 
    1123 * Handles dropping a page template over the {@link MainPageView}. 
     
    3951                TemplateRefData refData = transferable.getDndData(TemplateRefData.class); 
    4052                assert refData != null : "There is no template to apply"; 
    4153                 
    42                 TemplateUtil.applyPageTemplate(transferable,getView().model().get()); 
     54                PageH page = getView().model().get(); 
     55                ResourceRefR4 templateRef = refData.getTemplateRef(); 
     56                ResourceRefR4 pageToTemplateRef = ResourceRefR4.getRelativeRef(page.getRef(), templateRef); 
     57                ResourceAccess templateAccess = page.getAccess().open(pageToTemplateRef, null); 
     58                PageH templateH = ResourceH.getHelper(templateAccess, PageH.class); 
     59                 
     60                ApplyPageTemplateDialog.Input input = new ApplyPageTemplateDialog.Input(templateH, page); 
     61                ApplyTemplateInfo info = DialogManager.get().showDialog(input); 
     62                if (info != null) { 
     63                         
     64                        ArrayList<ResourceRefR4> newElements = new ArrayList<ResourceRefR4>(); 
     65                        Map<ResourceRefR4, ResourceRefR4> existingMap = new HashMap<ResourceRefR4, ResourceRefR4>(); 
     66                        parseInfo(info, newElements, existingMap); 
     67                         
     68                        // it is important first to delete the unassigned elements and then create new by templates 
     69                        if (info.deleteUnassigned().get()) { 
     70                                deleteUnassignedElements(page, existingMap); 
     71                        } 
     72                         
     73                        TemplateUtil.applyPageTemplate(page, refData.getTemplateRef(), 
     74                                        existingMap, newElements); 
     75 
     76                        AutoAction.registerEndChange(page.getAccess(), "Apply page template"); 
     77 
     78                        // go to the page that was changed 
     79                        BookView bookView = getView().getBookView();             
     80                        if (bookView.getCurrentPageView().mainPartView().get() != getView()) { 
     81                                bookView.goToPage(getView().model().get().getRef().getThisChildRef()); 
     82                        } 
     83                } 
     84        } 
    4385         
    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()); 
     86        private void deleteUnassignedElements(ElementH element, Map<ResourceRefR4, ResourceRefR4> existingMap) { 
     87                for (ElementH subelement : element.getSubElements()) { 
     88                        if (!existingMap.containsValue(subelement.getRef())) {                           
     89                                element.removeSubElement(subelement.getRef().getThisChildRef(), 
     90                                                "Remove unassigned subelement", false);                          
     91                        } else { 
     92                                deleteUnassignedElements(subelement, existingMap); 
     93                        } 
    4894                } 
    4995        } 
     96 
     97        private void parseInfo(ApplyTemplateInfo info, 
     98                        ArrayList<ResourceRefR4> newElements, Map<ResourceRefR4, ResourceRefR4> existingMap) { 
     99                for (Slot slot : info.slots().get()) { 
     100                        processSlot(slot, newElements, existingMap); 
     101                } 
     102        } 
     103 
     104        private void processSlot(Slot slot, ArrayList<ResourceRefR4> newElements, 
     105                        Map<ResourceRefR4, ResourceRefR4> existingMap) { 
     106                ResourceH target = slot.target().get(); 
     107                if (ApplyPageTemplateSwingDialog.NONE_ITEM.equals(target)) { 
     108                        return; 
     109                } 
     110                 
     111                if (ApplyPageTemplateSwingDialog.NEW_ITEM.equals(target)) { 
     112                        newElements.add(slot.template().get().getRef()); 
     113                } else { 
     114                        ResourceRefR4 templateRef = slot.template().get().getRef(); 
     115                        existingMap.put(templateRef, target.getRef()); 
     116                } 
     117                 
     118                for (Slot subSlot : slot.subSlots().get()) { 
     119                        processSlot(subSlot, newElements, existingMap); 
     120                } 
     121        } 
    50122} 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/book/BookView.java

     
    11package org.sophie2.main.app.commons.book; 
    22 
     3import java.util.ArrayList; 
    34import java.util.List; 
    45 
    56import org.sophie2.base.commons.util.ImmList; 
     
    1011import org.sophie2.base.media.MediaUtil; 
    1112import org.sophie2.base.media.TimePos; 
    1213import org.sophie2.base.model.book.BookH; 
     14import org.sophie2.base.model.book.ElementH; 
    1315import org.sophie2.base.model.book.PageH; 
    1416import org.sophie2.base.model.book.resource.AudioResourceH; 
    1517import org.sophie2.base.model.book.resource.MediaResourceR4; 
     
    519521                        ResourceAccess templateAccess = this.getAccess().open(absTemplateRef, null); 
    520522                        PageH templateH = ResourceH.getHelper(templateAccess, PageH.class); 
    521523 
    522                         TemplateUtil.applyPageTemplate(page, absTemplateRef, null, templateH.getSubElements()); 
     524                        TemplateUtil.applyPageTemplate(page, absTemplateRef, null, getAllSubelements(templateH)); 
     525                         
     526                        AutoAction.registerEndChange(getAccess(), "Add a new templated page"); 
    523527                } 
    524                  
    525                 AutoAction.registerEndChange(getAccess(), "Add a new templated page"); 
    526                  
     528                                 
    527529                goToPage(model().get().getPages().get(index)); 
    528530 
    529531                SophieLog.debugf("Went to page %d.", index + 1); 
    530532        } 
    531533         
     534        private List<ResourceRefR4> getAllSubelements(ElementH element) { 
     535                List<ResourceRefR4> res = new ArrayList<ResourceRefR4>(); 
     536                for (ElementH subelement : element.getSubElements()) { 
     537                        res.add(subelement.getRef()); 
     538                        res.addAll(getAllSubelements(subelement)); 
     539                }                
     540                return res; 
     541        } 
     542         
    532543        /** 
    533544         * Adds a new page to this book to the given index and sets it to be 
    534545         * current.  
  • 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; 
     28import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotTitleLable; 
     29import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotsPanel; 
     30import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.TargetComboBox; 
    2331 
    2432/** 
    2533 * Module class for template functionality. 
     
    3341                // no extension points 
    3442        } 
    3543 
     44        @SuppressWarnings("unchecked") 
    3645        @Override 
    3746        protected void defineExtensions(List<SophieExtension<?>> res) { 
    3847                res.add(SimpleVisualProvider.createExtension( 
     
    5261                 
    5362                SimpleOperation.fillExtensions(res, FrameTemplateLogic.class);           
    5463                SimpleOperation.fillExtensions(res, PageTemplateLogic.class);            
    55                 SimpleOperation.fillExtensions(res, BookTemplatesLogic.class);           
    56  
     64                SimpleOperation.fillExtensions(res, BookTemplatesLogic.class); 
     65                 
     66                res.add(new SimpleSophieExtension<Dialog>(Dialog.class, 
     67                                new ApplyPageTemplateDialog())); 
     68                AutoVisualProvider.fillExtensions(res, ApplyPageTemplateSwingDialog.class); 
     69                SimpleOperation.fillExtensions(res, ApplyPageTemplateDialog.DialogLogic.class); 
     70                res.add(SimpleVisualProvider.createExtension(TargetComboBox.class, 
     71                                SlotsPanel.class, "target-combo-box", "55-target-combo-box"));           
     72                res.add(SimpleVisualProvider.createExtension(SlotTitleLable.class, 
     73                                SlotsPanel.class, "slot-title-label", "44-slot-title-label")); 
     74                 
    5775                res.add(makeSkinPart()); 
    5876        } 
    5977         
  • modules/org.sophie2.base.dnd/src/main/java/org/sophie2/base/dnd/SophieDragDropHandler.java

     
    2020import javax.swing.TransferHandler; 
    2121 
    2222import org.sophie2.base.commons.util.position.ImmPoint; 
     23import org.sophie2.core.mvc.EventFilterBuilder; 
    2324import org.sophie2.core.mvc.EventParams; 
    2425import org.sophie2.core.mvc.LogicR3; 
     26import org.sophie2.core.mvc.OperationDef; 
    2527import org.sophie2.core.mvc.events.EventR3; 
    2628 
    2729/** 
     
    171173                 
    172174        } 
    173175 
    174         // TODO: delete 
    175176        /** 
    176177         * Class representing a transaction that is open when a transferable is to 
    177178         * be imported. 
    178179         *  
    179          * @author tanya 
     180         * @author tanya, deni 
    180181         */ 
    181182        public static class DndImport extends DndAction { 
    182183 
    183                 private boolean imported; 
     184                private DropHandler handler; 
    184185 
    185186                /** 
    186187                 * Constructs a transaction be given transferable. 
    187188                 *  
    188189                 * @param transferable 
     190                 *              The transferable that should be imported. 
     191                 * @param handler  
     192                 *              The handler responsible for importing the transferable 
    189193                 */ 
    190                 public DndImport(Transferable transferable) { 
    191                         this.imported = false; 
     194                public DndImport(Transferable transferable, DropHandler handler) { 
     195                        this.handler = handler; 
    192196                        setDndTransferable(new AwtTransferable(transferable)); 
    193197                } 
    194198 
    195199                /** 
    196                  * Sets if the transferable has been imported. 
     200                 * Gets the handler responsible for importing the transferable. 
    197201                 *  
    198                  * @param imported 
    199                  *            <b>true</b> if the transferable has been imported, and 
    200                  *            <b>false</b> otherwise. 
     202                 * @return 
     203                 *              The handler responsible for importing the transferable. 
    201204                 */ 
    202                 public void setImported(boolean imported) { 
    203                         this.imported = imported; 
     205                public DropHandler getHandler() { 
     206                        return this.handler; 
    204207                } 
    205  
    206                 /** 
    207                  * Returns whether the transferable has been imported. 
    208                  *  
    209                  * @return <b>true</b> if the transferable has been imported, and 
    210                  *         <b>false</b> otherwise. 
    211                  */ 
    212                 public boolean getImported() { 
    213                         return this.imported; 
    214                 } 
    215208        } 
    216209 
    217210        /** 
     
    342335        public void drop(DropTargetDropEvent dtde) { 
    343336                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 
    344337 
    345                 Transferable transferable = dtde.getTransferable(); 
    346          
    347338                if (this.handler != null) { 
    348                         try { 
    349                                 this.handler.handleDrop(new AwtTransferable(transferable)); 
    350                         } finally { 
    351                                 changeHandler(null); 
    352                         } 
     339                        Transferable transferable = dtde.getTransferable(); 
     340                        DndImport dndImport = new DndImport(transferable, this.handler); 
     341                        changeHandler(null); 
     342                         
     343                        LogicR3.fire(new EventR3(SophieDragDropHandler.this.source, 
     344                                        SophieDragDropHandler.this.context, 
     345                                        SophieDragDropHandler.this.tip, null, 
     346                                        SophieDragDropHandler.TransferEventIds.DND_IMPORT, 
     347                                        dndImport)); 
    353348                } 
    354349        } 
    355350 
     
    411406                DND_PRE_IMPORT, 
    412407                 
    413408                /** 
     409                 * Fired when a transferable is dropped over a component. 
     410                 */ 
     411                @EventParams( { DndImport.class,  }) 
     412                DND_IMPORT, 
     413                 
     414                /** 
    414415                 * Fired on exporting data - copy in copy/paste operation. 
    415416                 */ 
    416417                @EventParams( {}) 
     
    443444                 */ 
    444445                public static final int KEY_PARAM_INDEX = 2; 
    445446        } 
     447         
     448        /** 
     449         * DnD related logic. 
     450         *  
     451         * @author deni 
     452         */ 
     453        public enum DropHandlerLogic implements OperationDef { 
     454                 
     455                /** 
     456                 * Handles {@link TransferEventIds#DND_IMPORT} by executing the logic  
     457                 * in the {@link DropHandler}. 
     458                 */ 
     459                ON_DND_IMPORT { 
     460 
     461                        public void defineFilter(EventFilterBuilder filter) { 
     462                                filter.setEventId(TransferEventIds.DND_IMPORT);                          
     463                        } 
     464 
     465                        public boolean handle(EventR3 event) { 
     466                                DndImport preImport = event.getEventParam( 
     467                                                SophieDragDropHandler.TransferEventIds.TRANSACTION_PARAM_INDEX, 
     468                                                DndImport.class); 
     469                                DndTransferable transferable = preImport.getTransferable(); 
     470                                DropHandler handler = preImport.getHandler(); 
     471                                 
     472                                handler.handleDrop(transferable); 
     473                                 
     474                                return true; 
     475                        } 
     476                         
     477                } 
     478        } 
    446479} 
     480 No newline at end of file 
  • modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/dialogs/BaseCustomModalDialog.java

     
    66import java.awt.Frame; 
    77import java.awt.event.ActionEvent; 
    88import java.awt.event.KeyEvent; 
     9import java.awt.event.WindowAdapter; 
     10import java.awt.event.WindowEvent; 
    911 
    1012import javax.swing.AbstractAction; 
    1113import javax.swing.Action; 
     
    182184                        @Override 
    183185                        protected JDialog create() { 
    184186                                // Create the modal JDialog. 
    185                                 JDialog dialog = new JDialog((Frame)null, true); 
     187                                JDialog dialog = new JDialog((Frame)null, true);         
    186188                                JRootPane rootPane = dialog.getRootPane(); 
    187189                                 
     190                                // Map the Close button to Cancel action. 
     191                                dialog.addWindowListener(new WindowAdapter() { 
     192                                        @Override 
     193                                        public void windowClosing(final WindowEvent we) { 
     194                                                BaseCustomModalDialog.this.getCancelAction().actionPerformed(null); 
     195                                        }                                        
     196                                }); 
     197                                 
    188198                                // Map Esc to Cancel action. 
    189199                                KeyStroke stroke = KeyStroke 
    190200                                                .getKeyStroke(KeyEvent.VK_ESCAPE, 0); 
  • modules/org.sophie2.base.dnd/src/main/java/org/sophie2/base/dnd/BaseDndModule.java

     
    33import java.awt.datatransfer.DataFlavor; 
    44import java.util.List; 
    55 
     6import org.sophie2.base.dnd.SophieDragDropHandler.DropHandlerLogic; 
    67import org.sophie2.base.dnd.dnddata.ImageData; 
    78import org.sophie2.base.dnd.dnddata.RtfData; 
    89import org.sophie2.base.dnd.dnddata.StringData; 
     
    1011import org.sophie2.core.modularity.SophieExtension; 
    1112import org.sophie2.core.modularity.SophieExtensionPoint; 
    1213import org.sophie2.core.modularity.SophieModule; 
     14import org.sophie2.core.mvc.SimpleOperation; 
    1315 
    1416/** 
    1517 * A module class for the base dnd. 
     
    7173                 
    7274                res.add(new SimpleSophieExtension<DndProvider>(DndProvider.class, 
    7375                                new RtfData.RtfDndProvider())); 
     76                 
     77                SimpleOperation.fillExtensions(res, DropHandlerLogic.class);             
    7478        } 
    7579 
    7680        /** 
  • modules/org.sophie2.base.bound/src/main/java/org/sophie2/base/bound/BoundControl.java

     
    369369                                if (size().get() != null) { 
    370370                                        res.setSize(size().get().toDimension()); 
    371371                                        res.setPreferredSize(size().get().toDimension()); 
     372                                        res.setMinimumSize(size().get().toDimension()); 
     373                                        res.setMaximumSize(size().get().toDimension()); 
    372374                                } 
    373375                                if (controlSize().get() != null) { 
    374376                                        dataInputControl().get().setSize( 
  • 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.base.model.resources.r4.resources.ResourceH; 
     8import org.sophie2.core.prolib.annot.Own; 
     9import org.sophie2.core.prolib.impl.AutoListProperty; 
     10import org.sophie2.core.prolib.impl.BaseProObject; 
     11import org.sophie2.core.prolib.interfaces.ListProp; 
     12import org.sophie2.core.prolib.interfaces.Prop; 
     13import org.sophie2.core.prolib.interfaces.RwProp; 
     14import org.sophie2.core.prolib.list.ComposingProList; 
     15import org.sophie2.core.prolib.list.ProList; 
     16import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog; 
     17 
     18/** 
     19 * An association between a template element and its target. The target might be 
     20 * an existing element to which the template should be applied, the indication 
     21 * that a new element should be created by the template or the indication that 
     22 * the template should not be used. 
     23 *  
     24 * @author deni 
     25 */ 
     26public class Slot extends BaseProObject { 
     27         
     28        /** 
     29         * Creates a new slot by template element. 
     30         *  
     31         * @param template 
     32         *              The template for which this slot will be responsible. 
     33         */ 
     34        public Slot(ElementH template) { 
     35                getBean().init(template(), template); 
     36        } 
     37         
     38        /** 
     39         * The parent slot of this one. 
     40         *  
     41         * @return 
     42         *              The property.  
     43         */ 
     44        public Prop<? extends Slot> parent() { 
     45                return getBean().makeParentProp(Slot.class); 
     46        } 
     47         
     48        /** 
     49         * The template this slot is responsible for. 
     50         *  
     51         * @return 
     52         *              The property. 
     53         */ 
     54        public Prop<ElementH> template() { 
     55                return getBean().makeFinalProp("template", ElementH.class); 
     56        } 
     57         
     58        /** 
     59         * The resource this slot's template should be applied to. 
     60         * Can be an existing resource, {@link ApplyPageTemplateSwingDialog#NEW_ITEM} or  
     61         * {@link ApplyPageTemplateSwingDialog#NONE_ITEM}. 
     62         *  
     63         * @return 
     64         *              The property. 
     65         */ 
     66        public RwProp<ResourceH> target() { 
     67                return getBean().makeValueProp("target", ResourceH.class,  
     68                                ApplyPageTemplateSwingDialog.NEW_ITEM); 
     69        } 
     70         
     71        /** 
     72         * A list of slots for the sub-elements of this slot's template. 
     73         *  
     74         * @return 
     75         *              The property. 
     76         */ 
     77        @Own 
     78        public ListProp<Slot> subSlots() { 
     79                class subSlots extends AutoListProperty<Slot> { 
     80                        @Override 
     81                        protected ProList<Slot> constructList() { 
     82                                return new ComposingProList<Slot>() { 
     83                                         
     84                                        @Override 
     85                                        protected List<Slot> computeData() {     
     86                                                ArrayList<Slot> res = new ArrayList<Slot>(); 
     87                                                for(ElementH subTemplate : template().get().getSubElements()) { 
     88                                                        res.add(new Slot(subTemplate)); 
     89                                                } 
     90                                                return res; 
     91                                        } 
     92                                         
     93                                }; 
     94                        } 
     95                } 
     96                return getBean().makeProp(subSlots.class); 
     97        } 
     98 
     99} 
  • 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.BorderLayout; 
     4import java.awt.Dimension; 
     5import java.awt.FlowLayout; 
     6import java.util.ArrayList; 
     7import java.util.List; 
     8 
     9import javax.swing.Box; 
     10import javax.swing.BoxLayout; 
     11import javax.swing.JComponent; 
     12import javax.swing.JLabel; 
     13import javax.swing.JPanel; 
     14import javax.swing.JScrollPane; 
     15import javax.swing.ScrollPaneConstants; 
     16 
     17import org.sophie2.base.bound.BoundCheckBox; 
     18import org.sophie2.base.bound.BoundComboBox; 
     19import org.sophie2.base.bound.BoundControl; 
     20import org.sophie2.base.bound.BoundValidation; 
     21import org.sophie2.base.bound.ComboInput; 
     22import org.sophie2.base.bound.ComboState; 
     23import org.sophie2.base.bound.BoundControl.EventIds; 
     24import org.sophie2.base.commons.util.position.ImmSize; 
     25import org.sophie2.base.dialogs.Dialog; 
     26import org.sophie2.base.dialogs.DialogInput; 
     27import org.sophie2.base.layout.model.MainWindow; 
     28import org.sophie2.base.model.book.ElementGroupH; 
     29import org.sophie2.base.model.book.ElementH; 
     30import org.sophie2.base.model.book.FrameH; 
     31import org.sophie2.base.model.resources.r4.resources.ResourceH; 
     32import org.sophie2.base.skins.Skin; 
     33import org.sophie2.base.skins.SkinElementId; 
     34import org.sophie2.base.skins.SkinUtil; 
     35import org.sophie2.base.visual.BaseSwingVisualElement; 
     36import org.sophie2.base.visual.BaseVisualModule; 
     37import org.sophie2.base.visual.SwingVisualElement; 
     38import org.sophie2.base.visual.VisualProvider; 
     39import org.sophie2.base.visual.skins.ElementSkinPart; 
     40import org.sophie2.base.visual.skins.RelatedChildren; 
     41import org.sophie2.base.visual.skins.SkinPartDef; 
     42import org.sophie2.base.visual.skins.VisualElementDef; 
     43import org.sophie2.core.mvc.EventFilterBuilder; 
     44import org.sophie2.core.mvc.OperationDef; 
     45import org.sophie2.core.mvc.events.EventR3; 
     46import org.sophie2.core.prolib.annot.Own; 
     47import org.sophie2.core.prolib.impl.AutoListProperty; 
     48import org.sophie2.core.prolib.impl.AutoProperty; 
     49import org.sophie2.core.prolib.impl.ResourceProperty; 
     50import org.sophie2.core.prolib.interfaces.ListProp; 
     51import org.sophie2.core.prolib.interfaces.Prop; 
     52import org.sophie2.core.prolib.interfaces.RwProp; 
     53import org.sophie2.core.prolib.list.ComposingProList; 
     54import org.sophie2.core.prolib.list.ProList; 
     55import org.sophie2.main.app.commons.dialogs.BaseCustomModalDialog; 
     56import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.DeleteUnassignedElementsCheckBox; 
     57import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotsPanel; 
     58import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.TargetComboBox; 
     59 
     60/** 
     61 * A dialog shown when a page template is going to be applied. 
     62 *  
     63 * @author deni 
     64 */ 
     65public class ApplyPageTemplateDialog extends Dialog<ApplyPageTemplateDialog.Input, ApplyTemplateInfo> { 
     66 
     67        /** 
     68         * Input for {@link ApplyPageTemplateDialog}. 
     69         */ 
     70        public static class Input extends DialogInput<ApplyTemplateInfo> { 
     71 
     72                private ApplyTemplateInfo applyTemplateInfo; 
     73 
     74                /** 
     75                 * Constructs an input for the 'Apply page template' dialog.   
     76                 *  
     77                 * @param template 
     78                 *              The template that will be applied. 
     79                 * @param target 
     80                 *              The page to which the template will be applied. 
     81                 */ 
     82                public Input(ElementH template, ElementH target) { 
     83                        this.applyTemplateInfo = new ApplyTemplateInfo(template, target); 
     84                } 
     85 
     86                @Override 
     87                public Class<ApplyTemplateInfo> getResponseClass() { 
     88                        return ApplyTemplateInfo.class; 
     89                } 
     90 
     91                /** 
     92                 * Gets the default settings for applying the template to the page. 
     93                 *  
     94                 * @return 
     95                 *              The default ApplyTemplateInfo. 
     96                 */ 
     97                public ApplyTemplateInfo getApplyTemplateInfo() { 
     98                        return this.applyTemplateInfo; 
     99                } 
     100        } 
     101 
     102        /** 
     103         * The actual swing representation of the {@link ApplyPageTemplateDialog}. 
     104         *  
     105         * @author deni 
     106         */ 
     107        @VisualElementDef(parent=MainWindow.class, sortKey="apply-page-template-dialog") 
     108        @SkinElementId("apply-page-template-swing-dialog") 
     109        @RelatedChildren({ 
     110                ApplyPageTemplateSwingDialog.DeleteUnassignedElementsCheckBox.class, 
     111                ApplyPageTemplateSwingDialog.SlotsPanel.class 
     112        }) 
     113        public static class ApplyPageTemplateSwingDialog extends BaseCustomModalDialog { 
     114 
     115                /** 
     116                 * The height of the dialog. 
     117                 */ 
     118                public static final int DIALOG_HEIGHT = 240; 
     119 
     120                /** 
     121                 * The width of the dialog. 
     122                 */ 
     123                public static final int DIALOG_WIDTH = 300; 
     124 
     125                private static final String APPLY_PAGE_TEMPLATE_TITLE = "Apply Page Template"; 
     126 
     127                @SuppressWarnings("unused") 
     128                @SkinPartDef 
     129                private static void initSkin(ElementSkinPart part) { 
     130                        part.add(DIALOG_RESIZABLE_PROP_ID, false); 
     131                        part.add(TITLE_PROP_ID, APPLY_PAGE_TEMPLATE_TITLE); 
     132                        part.add(NEW_ITEM_TITLE_PROP_ID, "New"); 
     133                        part.add(NONE_ITEM_TITLE_PROP_ID, "None"); 
     134                } 
     135 
     136                /** 
     137                 * The {@link Skin} property id for the title of {@link #NEW_ITEM}. 
     138                 */ 
     139                public static final String NEW_ITEM_TITLE_PROP_ID = "new-item-title"; 
     140 
     141                /** 
     142                 * A special item used in {@link TargetComboBox} to mark that a new element 
     143                 * should be created by template.   
     144                 */ 
     145                public static final ResourceH NEW_ITEM = new ResourceH(null) { 
     146 
     147                        @Override 
     148                        public String toString() { 
     149                                return SkinUtil.getSkinValue(ApplyPageTemplateSwingDialog.class,  
     150                                                NEW_ITEM_TITLE_PROP_ID, String.class); 
     151                        } 
     152 
     153                }; 
     154 
     155                /** 
     156                 * The {@link Skin} property id for the title of {@link #NONE_ITEM}. 
     157                 */ 
     158                public static final String NONE_ITEM_TITLE_PROP_ID = "none-item-title"; 
     159 
     160                /** 
     161                 * A special item used in {@link TargetComboBox} to mark a template 
     162                 * should now be used at all. 
     163                 */ 
     164                public static final ResourceH NONE_ITEM = new ResourceH(null) { 
     165 
     166                        @Override 
     167                        public String toString() { 
     168                                return SkinUtil.getSkinValue(ApplyPageTemplateSwingDialog.class,  
     169                                                NONE_ITEM_TITLE_PROP_ID, String.class); 
     170                        } 
     171 
     172                }; 
     173 
     174                /** 
     175                 * Construct the swing representation of the {@link ApplyPageTemplateDialog}. 
     176                 *  
     177                 * @param input  
     178                 *  
     179                 */ 
     180                public ApplyPageTemplateSwingDialog(Input input) { 
     181                        applyTemplateInfo().set(input.getApplyTemplateInfo()); 
     182                } 
     183 
     184                /** 
     185                 * The {@link ApplyTemplateInfo} this dialog operates on. 
     186                 *  
     187                 * @return 
     188                 *              The property. 
     189                 */ 
     190                public RwProp<ApplyTemplateInfo> applyTemplateInfo() { 
     191                        return getBean().makeValueProp("applyTemplateInfo", ApplyTemplateInfo.class, null); 
     192                } 
     193 
     194                @Override 
     195                protected void dialogCanceled() { 
     196                        applyTemplateInfo().set(null); 
     197                } 
     198 
     199                @Override 
     200                protected JComponent initContent() { 
     201                        return contentPane().get(); 
     202                } 
     203 
     204                /** 
     205                 * The controls to display in this dialog. 
     206                 *  
     207                 * @return 
     208                 *              List property. 
     209                 */ 
     210                @Own 
     211                protected ListProp<SwingVisualElement> controls() { 
     212                        class controls extends AutoListProperty<SwingVisualElement> { 
     213 
     214                                @SuppressWarnings("synthetic-access") 
     215                                @Override 
     216                                protected ProList<SwingVisualElement> constructList() { 
     217                                        return createElementPropList(SwingVisualElement.class,  
     218                                                        ApplyPageTemplateSwingDialog.this.getClass(), null); 
     219                                } 
     220 
     221                        } 
     222                        return getBean().makeProp(controls.class); 
     223                } 
     224 
     225                /** 
     226                 * The content pane of this dialog. 
     227                 *  
     228                 * @return 
     229                 *              The property. 
     230                 */ 
     231                protected Prop<JPanel> contentPane() { 
     232                        class contentPane extends ResourceProperty<JPanel> { 
     233 
     234                                @Override 
     235                                protected JPanel create() { 
     236                                        JPanel res = new JPanel(); 
     237                                        res.setLayout(new BoxLayout(res, BoxLayout.Y_AXIS)); 
     238                                        res.setMinimumSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); 
     239                                        return res; 
     240                                } 
     241 
     242                                @Override 
     243                                protected void destroy(JPanel res) { 
     244                                        // Nothing... 
     245                                } 
     246 
     247                                @Override 
     248                                protected void setup(JPanel res) { 
     249                                        res.removeAll(); 
     250 
     251                                        for (SwingVisualElement control : controls().get()) { 
     252                                                res.add(control.swingComponent().get()); 
     253                                        } 
     254 
     255                                } 
     256 
     257                        } 
     258                        return getBean().makeProp(contentPane.class); 
     259                } 
     260 
     261                /** 
     262                 * A checkbox used to choose whether the existing elements that were left unassigned  
     263                 * should be deleted. 
     264                 *  
     265                 * @author deni 
     266                 */ 
     267                @VisualElementDef(parent=ApplyPageTemplateSwingDialog.class, sortKey="bbb-delete-other-check-box") 
     268                public static class DeleteUnassignedElementsCheckBox extends BoundCheckBox { 
     269 
     270                        @SuppressWarnings("unused") 
     271                        @SkinPartDef 
     272                        private static void initSkin(ElementSkinPart part) { 
     273                                part.add(TITLE_PROP_ID, "Delete unassigned elements"); 
     274                                part.add(TOOL_TIP_PROP_ID, "Select whether the groups and frames on the page"  
     275                                                + "that are not in this dialog should be deleted."); 
     276                                part.add(VALIDATION_VISIBLE_ID, false); 
     277                        } 
     278 
     279                        @Override 
     280                        protected Boolean computeModelData() { 
     281                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     282                                if (parentDialog != null && parentDialog.applyTemplateInfo().get() != null ) { 
     283                                        return parentDialog.applyTemplateInfo().get().deleteUnassigned().get(); 
     284                                } 
     285 
     286                                return false; 
     287                        } 
     288                } 
     289 
     290                /** 
     291                 * A panel with controls for associating the groups and frames from the template 
     292                 * to their targets. 
     293                 *  
     294                 * @author deni 
     295                 */ 
     296                @VisualElementDef(parent=ApplyPageTemplateSwingDialog.class, sortKey="aaa-slots-panel") 
     297                public static class SlotsPanel extends BaseSwingVisualElement { 
     298 
     299                        /** 
     300                         * The height of a single row (showing a single slot).  
     301                         */ 
     302                        public static final int ROW_HEIGHT = 25; 
     303 
     304                        /** 
     305                         * Property holding the page elements that are currently assigned to slots. 
     306                         *  
     307                         * @return 
     308                         *              The property. 
     309                         */ 
     310                        public ListProp<ResourceH> usedItems() { 
     311                                return getBean().makeListProp("usedItems", ResourceH.class); 
     312                        } 
     313 
     314                        private Prop<VisualProvider> targetComboboxProvider() { 
     315                                class targetComboboxProvider extends AutoProperty<VisualProvider> { 
     316 
     317                                        @Override 
     318                                        protected VisualProvider compute() { 
     319                                                return BaseVisualModule.get().findProvider(TargetComboBox.class, null, null); 
     320                                        } 
     321 
     322                                } 
     323                                return getBean().makeProp(targetComboboxProvider.class); 
     324                        } 
     325 
     326                        @Own 
     327                        private ListProp<TargetComboBox> targetComboBoxes() { 
     328                                class targetComboBoxes extends AutoListProperty<TargetComboBox> { 
     329                                        @Override 
     330                                        protected ProList<TargetComboBox> constructList() { 
     331                                                return new ComposingProList<TargetComboBox>() { 
     332 
     333                                                        @Override 
     334                                                        protected List<? extends TargetComboBox> computeData() { 
     335                                                                ArrayList<TargetComboBox> res = new ArrayList<TargetComboBox>(); 
     336                                                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     337                                                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     338                                                                        return res; 
     339                                                                } 
     340 
     341                                                                List<Slot> slots = parentDialog.applyTemplateInfo().get().slots().get(); 
     342                                                                for (Slot slot : slots) { 
     343                                                                        addSlot(slot, res); 
     344                                                                }                                                                
     345                                                                return res; 
     346                                                        } 
     347 
     348                                                        @SuppressWarnings("synthetic-access") 
     349                                                        private void addSlot(Slot slot, ArrayList<TargetComboBox> res) { 
     350                                                                VisualProvider provider = targetComboboxProvider().get(); 
     351                                                                if (provider == null) { 
     352                                                                        return; 
     353                                                                } 
     354                                                                TargetComboBox comboBox = provider.create(TargetComboBox.class); 
     355                                                                comboBox.initSlot(slot); 
     356                                                                res.add(comboBox); 
     357 
     358                                                                for (Slot subSlot : slot.subSlots().get()) { 
     359                                                                        addSlot(subSlot, res); 
     360                                                                }        
     361                                                        } 
     362 
     363                                                }; 
     364                                        } 
     365                                } 
     366                                return getBean().makeProp(targetComboBoxes.class); 
     367                        } 
     368 
     369                        private Prop<JPanel> comboboxesPanel() { 
     370                                class comboboxesPanel extends ResourceProperty<JPanel> { 
     371 
     372                                        @Override 
     373                                        protected JPanel create() { 
     374                                                JPanel res = new JPanel(); 
     375                                                res.setLayout(new BoxLayout(res, BoxLayout.Y_AXIS)); 
     376                                                return res; 
     377                                        } 
     378 
     379                                        @Override 
     380                                        protected void destroy(JPanel res) { 
     381                                                // nothing       
     382                                        } 
     383 
     384                                        @SuppressWarnings("synthetic-access") 
     385                                        @Override 
     386                                        protected void setup(JPanel res) { 
     387                                                res.removeAll(); 
     388                                                for (TargetComboBox combobox : targetComboBoxes().get()) { 
     389                                                        res.add(combobox.swingComponent().get()); 
     390                                                }                                                
     391                                        } 
     392 
     393                                } 
     394                                return getBean().makeProp(comboboxesPanel.class); 
     395                        } 
     396 
     397                        private Prop<VisualProvider> titleLabelProvider() { 
     398                                class titleLabelProvider extends AutoProperty<VisualProvider> { 
     399 
     400                                        @Override 
     401                                        protected VisualProvider compute() { 
     402                                                return BaseVisualModule.get().findProvider(SlotTitleLable.class, null, null); 
     403                                        } 
     404 
     405                                } 
     406                                return getBean().makeProp(titleLabelProvider.class); 
     407                        } 
     408 
     409                        private ListProp<SlotTitleLable> titleLabels() { 
     410                                class titleLabels extends AutoListProperty<SlotTitleLable> { 
     411                                        @Override 
     412                                        protected ProList<SlotTitleLable> constructList() { 
     413                                                return new ComposingProList<SlotTitleLable>() { 
     414 
     415                                                        @Override 
     416                                                        protected List<? extends SlotTitleLable> computeData() { 
     417                                                                ArrayList<SlotTitleLable> res = new ArrayList<SlotTitleLable>(); 
     418                                                                ApplyPageTemplateSwingDialog parentDialog = findParentElement(ApplyPageTemplateSwingDialog.class); 
     419                                                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     420                                                                        return res; 
     421                                                                } 
     422 
     423                                                                List<Slot> slots = parentDialog.applyTemplateInfo().get().slots().get(); 
     424                                                                for (Slot slot : slots) { 
     425                                                                        addSlot(slot, "", res); 
     426                                                                }                                                                
     427                                                                return res; 
     428                                                        } 
     429 
     430                                                        @SuppressWarnings("synthetic-access") 
     431                                                        private void addSlot(Slot slot, String indent, ArrayList<SlotTitleLable> res) { 
     432                                                                VisualProvider provider = titleLabelProvider().get(); 
     433                                                                if (provider == null) { 
     434                                                                        return; 
     435                                                                } 
     436                                                                SlotTitleLable label = provider.create(SlotTitleLable.class); 
     437                                                                label.initSlot(slot); 
     438                                                                label.initIndent(indent); 
     439                                                                res.add(label); 
     440 
     441                                                                for (Slot subSlot : slot.subSlots().get()) { 
     442                                                                        addSlot(subSlot, indent + "  ", res); 
     443                                                                }        
     444                                                        } 
     445 
     446                                                }; 
     447                                        } 
     448                                } 
     449                                return getBean().makeProp(titleLabels.class); 
     450                        } 
     451 
     452                        private Prop<JPanel> titlesPanel() { 
     453                                class titlesPanel extends ResourceProperty<JPanel> { 
     454 
     455                                        @Override 
     456                                        protected JPanel create() { 
     457                                                JPanel res = new JPanel(); 
     458                                                res.setLayout(new BoxLayout(res, BoxLayout.Y_AXIS)); 
     459                                                return res; 
     460                                        } 
     461 
     462                                        @Override 
     463                                        protected void destroy(JPanel res) { 
     464                                                // nothing       
     465                                        } 
     466 
     467                                        @SuppressWarnings("synthetic-access") 
     468                                        @Override 
     469                                        protected void setup(JPanel res) { 
     470                                                res.removeAll(); 
     471                                                for (SlotTitleLable label : titleLabels().get()) { 
     472                                                        res.add(label.swingComponent().get()); 
     473                                                }                                                
     474                                        } 
     475 
     476                                } 
     477                                return getBean().makeProp(titlesPanel.class); 
     478                        } 
     479 
     480                        private Prop<? extends JComponent> mainPanel() { 
     481                                class mainPanel extends ResourceProperty<JPanel> { 
     482 
     483                                        @Override 
     484                                        protected JPanel create() { 
     485                                                JPanel res = new JPanel(); 
     486                                                res.setLayout(new BorderLayout()); 
     487 
     488                                                return res; 
     489                                        } 
     490 
     491                                        @Override 
     492                                        protected void destroy(JPanel res) { 
     493                                                // do nothing 
     494                                        } 
     495 
     496                                        @SuppressWarnings("synthetic-access") 
     497                                        @Override 
     498                                        protected void setup(JPanel res) { 
     499                                                res.removeAll(); 
     500 
     501                                                res.add(Box.createRigidArea(new Dimension(280, 10)), BorderLayout.NORTH); 
     502                                                res.add(Box.createRigidArea(new Dimension(280, 10)), BorderLayout.SOUTH); 
     503 
     504                                                res.add(titlesPanel().get(), BorderLayout.WEST); 
     505                                                res.add(comboboxesPanel().get(), BorderLayout.EAST);     
     506 
     507                                        } 
     508                                } 
     509                                return getBean().makeProp(mainPanel.class); 
     510                        } 
     511 
     512                        public Prop<? extends JComponent> swingComponent() { 
     513                                class swingComponent extends ResourceProperty<JScrollPane> { 
     514 
     515                                        @Override 
     516                                        protected JScrollPane create() { 
     517                                                JScrollPane res = new JScrollPane(); 
     518                                                res.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
     519                                                res.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 
     520                                                return res; 
     521                                        } 
     522 
     523                                        @Override 
     524                                        protected void destroy(JScrollPane res) { 
     525                                                // nothing 
     526                                        } 
     527 
     528                                        @SuppressWarnings("synthetic-access") 
     529                                        @Override 
     530                                        protected void setup(JScrollPane res) { 
     531                                                res.setViewportView(mainPanel().get()); 
     532                                        } 
     533 
     534                                } 
     535                                return getBean().makeProp(swingComponent.class); 
     536                        } 
     537                } 
     538 
     539                /** 
     540                 * A combobox used to choose the target of a given slot, i.e. what to do 
     541                 * with its template. 
     542                 *  
     543                 * @author deni 
     544                 */ 
     545                public static class TargetComboBox extends BoundComboBox<ResourceH> { 
     546 
     547                        @SuppressWarnings("unused") 
     548                        @SkinPartDef 
     549                        private static void fillSkinParts(ElementSkinPart part) { 
     550                                part.add(TOOL_TIP_PROP_ID, "Target"); 
     551                                part.add(SIZE_PROP_ID, new ImmSize(140, SlotsPanel.ROW_HEIGHT)); 
     552                                part.add(FIELD_EDITABLE_PROP_ID, Boolean.FALSE); 
     553                                part.add(COMBO_SIZE_PROP_ID, new ImmSize(100, 20)); 
     554                                part.add(VALIDATION_VISIBLE_ID, false); 
     555                        } 
     556 
     557                        /** 
     558                         * The slot this combobox is associated with. 
     559                         *  
     560                         * @return 
     561                         *              The property. 
     562                         */ 
     563                        public Prop<Slot> slot() { 
     564                                return getBean().makeFinalProp("slot", Slot.class); 
     565                        } 
     566 
     567                        /** 
     568                         * Initializes the slot this combobox is associated with. 
     569                         *  
     570                         * @param slot 
     571                         *              The slot this combobox is associated with. 
     572                         */ 
     573                        public void initSlot(Slot slot) { 
     574                                getBean().init(slot(), slot); 
     575                        } 
     576 
     577                        @Override 
     578                        protected ComboState<ResourceH> computeModelData() {                             
     579                                Slot parentSlot = slot().get().parent().get(); 
     580                                Class<? extends ElementH> clazz = getTemplateClass(); 
     581 
     582                                ArrayList<ResourceH> targets = new ArrayList<ResourceH>();                               
     583                                if (parentSlot == null) {                                        
     584                                        targets.add(NEW_ITEM); 
     585                                        targets.add(NONE_ITEM); 
     586                                        ElementH topLevelTarget = getTopLevelTarget(); 
     587                                        if (topLevelTarget != null) { 
     588                                                targets.addAll(getUnassignedSubelements(getTopLevelTarget(), clazz)); 
     589                                        } 
     590                                } else {                                         
     591                                        ResourceH parentTarget = parentSlot.target().get(); 
     592                                        if (NONE_ITEM.equals(parentTarget)) { 
     593                                                targets.add(NONE_ITEM); 
     594                                        } else { 
     595                                                if (NEW_ITEM.equals(parentTarget)) { 
     596                                                        targets.add(NEW_ITEM); 
     597                                                        targets.add(NONE_ITEM); 
     598                                                } else { 
     599                                                        assert parentTarget instanceof ElementH; 
     600                                                        targets.add(NEW_ITEM); 
     601                                                        targets.add(NONE_ITEM); 
     602                                                        targets.addAll(getUnassignedSubelements(((ElementH)parentTarget), clazz)); 
     603                                                } 
     604                                        } 
     605                                } 
     606 
     607                                return new ComboState<ResourceH>("", targets, slot().get().target().get()); 
     608                        } 
     609 
     610                        private List<ElementH> getUnassignedSubelements(ElementH element, Class<? extends ElementH> clazz) { 
     611                                ArrayList<ElementH> res = new ArrayList<ElementH>(); 
     612 
     613                                SlotsPanel slotPanel = TargetComboBox.this.findParentElement(SlotsPanel.class);  
     614                                List<? extends ElementH> subelements = element.getSubElements(clazz); 
     615                                for (ElementH subelement : subelements) { 
     616                                        if (!slotPanel.usedItems().get().contains(subelement)) { 
     617                                                res.add(subelement); 
     618                                        } 
     619                                } 
     620 
     621                                return res; 
     622                        } 
     623 
     624                        private Class<? extends ElementH> getTemplateClass() { 
     625                                ElementH template = slot().get().template().get(); 
     626                                if (template instanceof FrameH) { 
     627                                        return FrameH.class; 
     628                                }                                
     629                                assert template instanceof ElementGroupH; 
     630                                return ElementGroupH.class; 
     631                        } 
     632 
     633                        private ElementH getTopLevelTarget() { 
     634                                ApplyPageTemplateSwingDialog parentDialog =  
     635                                        findParentElement(ApplyPageTemplateSwingDialog.class); 
     636                                if (parentDialog == null || parentDialog.applyTemplateInfo().get() == null) { 
     637                                        return null; 
     638                                } 
     639 
     640                                return parentDialog.applyTemplateInfo().get().target().get(); 
     641                        } 
     642 
     643                        @Override 
     644                        protected BoundValidation validate(ComboInput<ResourceH> inputData) { 
     645                                return BoundValidation.SUCCESS; 
     646                        } 
     647                } 
     648 
     649                /** 
     650                 * A label used to show the title of a given slot. 
     651                 *  
     652                 * @author deni 
     653                 */ 
     654                public static class SlotTitleLable extends BaseSwingVisualElement { 
     655 
     656                        /** 
     657                         * The slot this label is associated with. 
     658                         *  
     659                         * @return 
     660                         *              The property. 
     661                         */ 
     662                        public Prop<Slot> slot() { 
     663                                return getBean().makeFinalProp("slot", Slot.class); 
     664                        } 
     665 
     666                        /** 
     667                         * Initializes the slot this label is associated with. 
     668                         *  
     669                         * @param slot 
     670                         *              The slot this label is associated with. 
     671                         */ 
     672                        public void initSlot(Slot slot) { 
     673                                getBean().init(slot(), slot); 
     674                        } 
     675 
     676                        /** 
     677                         * The indentation before this label's title.  
     678                         *  
     679                         * @return 
     680                         *              The property. 
     681                         */ 
     682                        public Prop<String> indent() { 
     683                                return getBean().makeFinalProp("indent", String.class); 
     684                        } 
     685 
     686                        /** 
     687                         * Initializes indentation before this label's title. 
     688                         *  
     689                         * @param indent 
     690                         *              The indentation before this label's title. 
     691                         */ 
     692                        public void initIndent(String indent) { 
     693                                getBean().init(indent(), indent); 
     694                        } 
     695 
     696 
     697                        /** 
     698                         * The {@link JLabel} for the title of the slot. 
     699                         *  
     700                         * @return 
     701                         *              The property. 
     702                         */ 
     703                        public Prop<JLabel> label() { 
     704                                class label extends ResourceProperty<JLabel> { 
     705 
     706                                        @Override 
     707                                        protected JLabel create() { 
     708                                                return new JLabel(); 
     709                                        } 
     710 
     711                                        @Override 
     712                                        protected void destroy(JLabel res) { 
     713                                                // nothing 
     714                                        } 
     715 
     716                                        @Override 
     717                                        protected void setup(JLabel res) { 
     718                                                String title = indent().get() + slot().get().template().get().getTitle(); 
     719                                                res.setText(title); 
     720                                        } 
     721 
     722                                } 
     723                                return getBean().makeProp(label.class); 
     724                        } 
     725 
     726                        public Prop<JPanel> swingComponent() { 
     727                                class swingComponent extends ResourceProperty<JPanel> { 
     728 
     729                                        @Override 
     730                                        protected JPanel create() { 
     731                                                JPanel res = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
     732                                                res.setMinimumSize(new Dimension(0, SlotsPanel.ROW_HEIGHT)); 
     733                                                res.setMaximumSize(new Dimension(2000, SlotsPanel.ROW_HEIGHT)); 
     734                                                return res; 
     735                                        } 
     736 
     737                                        @Override 
     738                                        protected void destroy(JPanel res) { 
     739                                                // nothing 
     740                                        } 
     741 
     742                                        @Override 
     743                                        protected void setup(JPanel res) { 
     744                                                res.removeAll(); 
     745                                                res.add(label().get()); 
     746                                        } 
     747 
     748                                } 
     749                                return getBean().makeProp(swingComponent.class); 
     750                        }                        
     751                } 
     752        } 
     753 
     754        @Override 
     755        public Class<Input> getInputClass() { 
     756                return Input.class; 
     757        } 
     758 
     759        @Override 
     760        public Class<ApplyTemplateInfo> getOutputClass() { 
     761                return ApplyTemplateInfo.class; 
     762        } 
     763 
     764        @Override 
     765        protected ApplyTemplateInfo show(Input input) { 
     766                assert input != null; 
     767 
     768                ApplyPageTemplateSwingDialog dialog = new ApplyPageTemplateSwingDialog(input); 
     769                dialog.showDialog(); 
     770 
     771                return dialog.applyTemplateInfo().get(); 
     772        } 
     773 
     774        /** 
     775         * Controller for {@link ApplyPageTemplateDialog}. 
     776         *  
     777         * @author deni 
     778         */ 
     779        public enum DialogLogic implements OperationDef { 
     780 
     781                /** 
     782                 * Changes the target of a slot. 
     783                 * If necessary (for example when a group's slot is set to NONE), also changes the targets 
     784                 * of all sub-slots. 
     785                 */ 
     786                ON_TARGET_SUBMIT { 
     787 
     788                        public void defineFilter(EventFilterBuilder filter) { 
     789                                filter.setEventId(BoundControl.EventIds.SUBMIT); 
     790                                filter.setSourceClass(TargetComboBox.class); 
     791                        } 
     792 
     793                        @SuppressWarnings("unchecked") 
     794                        public boolean handle(EventR3 event) { 
     795                                TargetComboBox source = event.getSource(TargetComboBox.class); 
     796                                ComboInput<ResourceH> input = event.getEventParam( 
     797                                                EventIds.INPUT_PARAM_INDEX, ComboInput.class); 
     798                                SlotsPanel slotsPanel = source.findParentElement(SlotsPanel.class); 
     799                                changeTarget(source.slot().get(), input.getSelectedItem(), slotsPanel);                          
     800                                return true; 
     801                        } 
     802 
     803                        private void changeTarget(Slot slot, ResourceH target, SlotsPanel slotsPanel) { 
     804                                if (slot.target().get() == target) { 
     805                                        return; 
     806                                } 
     807 
     808                                slotsPanel.usedItems().get().remove(slot.target().get()); 
     809                                slotsPanel.usedItems().get().add(target); 
     810 
     811                                slot.target().set(target); 
     812                                for (Slot subSlot : slot.subSlots().get()) { 
     813                                        ResourceH subSlotTarget = (target == ApplyPageTemplateSwingDialog.NONE_ITEM) ?  
     814                                                        ApplyPageTemplateSwingDialog.NONE_ITEM : ApplyPageTemplateSwingDialog.NEW_ITEM; 
     815                                        changeTarget(subSlot, subSlotTarget, slotsPanel); 
     816                                } 
     817                        } 
     818 
     819                }, 
     820                 
     821                /** 
     822                 * Changes whether after applying the template, the existing elements 
     823                 * that were left unassigned to slots should be deleted. 
     824                 */ 
     825                ON_DELETE_UNASSIGNED_SUBMIT { 
     826 
     827                        public void defineFilter(EventFilterBuilder filter) { 
     828                                filter.setEventId(BoundControl.EventIds.SUBMIT); 
     829                                filter.setSourceClass(DeleteUnassignedElementsCheckBox.class); 
     830                        } 
     831 
     832                        public boolean handle(EventR3 event) { 
     833                                DeleteUnassignedElementsCheckBox source = event.getSource(DeleteUnassignedElementsCheckBox.class); 
     834                                boolean input = event.getEventParam(BoundControl.EventIds.INPUT_PARAM_INDEX, 
     835                                                Boolean.class); 
     836                                 
     837                                ApplyPageTemplateSwingDialog dialog =  
     838                                        source.findParentElement(ApplyPageTemplateSwingDialog.class); 
     839                                dialog.applyTemplateInfo().get().deleteUnassigned().set(input); 
     840                                 
     841                                return true; 
     842                        } 
     843                } 
     844 
     845        } 
     846}