Ticket #2413: sync-template-subelements-impl.patch
File sync-template-subelements-impl.patch, 19.2 KB (added by deni, 15 years ago) |
---|
-
modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/util/TemplateUtil.java
### Eclipse Workspace Patch 1.0 #P sophie
109 109 final ResourceRefList newTemplates = 110 110 templates.contains(templateRef) ? templates : templates.add(templateRef); 111 111 112 //auto-action which changes the keys of the root element/its sub-elements 113 String changeKeysDescription = "Change the template's elements' keys"; 114 new AutoAction(changeKeysDescription, false) { 112 113 ImmList<ResourceRefR4> rootsToDelete = ImmTreeList.<ResourceRefR4>create(); 114 /* 115 * Adds the references to be removed. We're looking for references who should be deleted, 116 * but their parent shouldn't be (so when we remove them, we'll remove all their sub-elements as well, 117 * which is what we need). Note that iterRef.getParentRef() will never equal the ref of the element we're templating, 118 * because we pass the root as an absolute reference and the sub-elements as relative ones. 119 */ 120 for (ResourceRefR4 iterRef : toDelete) { 121 if (!toDelete.contains(iterRef.getParentRef()) && !iterRef.equals(ref) ) { 122 rootsToDelete = rootsToDelete.add(iterRef); 123 } 124 } 125 final ImmList<ResourceRefR4> finalRootsToDelete = rootsToDelete; 126 127 /* 128 * Copies the template as a child of the book, changes its keys and deletes 129 * the unneeded sub-elements (also removes their activation channels from the 130 * corresponding parent's KEY_SUB_ELEMENTS key). 131 */ 132 new AutoAction(description, true) { 115 133 @Override 116 134 public void performAuto() { 117 135 getChanger().copyResource(relativeRef, templateRef); … … 136 154 if(createDefaultTemplate) { 137 155 getChanger().setRaw(defaultTemplateKey, templateRef); 138 156 } 139 }140 141 }.register(bookAccess);142 143 ImmList<ResourceRefR4> rootsToDelete = ImmTreeList.<ResourceRefR4>create();144 145 /*146 * Adds the references to be removed. We're looking for references who should be deleted,147 * but their parent shouldn't be (so when we remove them, we'll remove all their sub-elements as well,148 * which is what we need). Note that iterRef.getParentRef() will never equal the ref of the element we're templating,149 * because we pass the root as an absolute reference and the sub-elements as relative ones.150 */151 for (ResourceRefR4 iterRef : toDelete) {152 if (!toDelete.contains(iterRef.getParentRef()) && !iterRef.equals(ref) ) {153 rootsToDelete = rootsToDelete.add(iterRef);154 }155 }156 157 final ImmList<ResourceRefR4> finalRootsToDelete = rootsToDelete;158 159 /*160 * Auto-action which deletes the unneeded sub-elements (also removes their activation channels from the161 * corresponding parent's KEY_SUB_ELEMENTS key).162 */163 new AutoAction (description, isSign) {164 @Override165 public void performAuto () {166 ResourceChanger subCh = getChanger().getSub(templateRef);167 157 168 158 for (ResourceRefR4 iterRef : finalRootsToDelete) { 169 159 ResourceRefR4 parent = iterRef.getParentRef(), parentToIterRef = ResourceRefR4.getRelativeRef(parent, iterRef); … … 184 174 subCh.removeResource(iterRef); 185 175 } 186 176 } 177 187 178 }.register(bookAccess); 188 179 } 189 180 … … 328 319 * @param pageTemplateRef 329 320 * An absolute reference to the template to apply. 330 321 * @param existingMap 331 * A map from frames in the given page template to existing frames in the page332 * to which the template will be applied. The frames from the template will be used333 * as templates for the frames in the page.322 * A map from elements in the given page template to existing frames in the page 323 * to which the template will be applied. The elements from the template will be used 324 * as templates for the elements in the page. 334 325 * @param list 335 * A list containing frames in the given page templatesthat should be instantiated326 * A list containing elements in the given page template that should be instantiated 336 327 * as templates. 337 328 */ 338 329 public static void applyPageTemplate(PageH page, ResourceRefR4 pageTemplateRef, … … 369 360 } 370 361 } 371 362 372 private static void templatePageElements(ElementH templateH, ElementH parent, 363 /** 364 * Templates a page element. 365 * 366 * @param templateH 367 * The template that should be applied. 368 * @param parent 369 * The parent of the element to which the template should be applied. 370 * @param newElements 371 * A list containing elements from the template that should be instantiated. 372 * @param existing 373 * A map from elements in the template to existing elements to which they should be applied. 374 */ 375 public static void templatePageElements(ElementH templateH, ElementH parent, 373 376 List<ResourceRefR4> newElements, Map<ResourceRefR4, ResourceRefR4> existing) { 374 377 375 378 if (!newElements.contains(templateH.getRef()) && !existing.containsKey(templateH.getRef())) { 376 379 return; 377 380 } … … 382 385 if (newElements.contains(templateH.getRef())) { 383 386 assert !existing.containsKey(templateH.getRef()); 384 387 nextParentRef = createNewEmptyGroup((ElementGroupH)templateH, parent); 385 } else { 388 } else { 386 389 nextParentRef = existing.get(templateH.getRef()); 390 ResourceAccess groupAccess = parent.getAccess().open(nextParentRef, null); 391 ElementGroupH groupH = ResourceH.getHelper(groupAccess, ElementGroupH.class); 392 final NaiveImmList<TemplatedKey<?>> keys = groupH.getApplicableTemplatedKeys(); 393 394 final ResourceRefR4 groupToTemplateRef = 395 ResourceRefR4.getRelativeRef(groupAccess.getRef(), templateH.getRef()); 396 397 new AutoAction("Template group", false) { 398 399 @Override 400 public void performAuto() { 401 ResourceChanger ch = getChanger(); 402 ch.setRaw(ResourceR4.KEY_TEMPLATE, groupToTemplateRef); 403 for (Key<?> key : keys) { 404 ch.setRaw(key, null); 405 } 406 } 407 408 }.register(groupAccess); 387 409 } 388 410 389 411 ResourceAccess groupAccess = parent.getAccess().open(nextParentRef, null); … … 410 432 final String groupTitle = templateH.getTitle(); 411 433 final ImmList<ActivationChannel> parentElements = 412 434 CompositeElement.KEY_SUB_ELEMENTS.get(parent.getAccess()); 413 435 final ResourceRefR4 groupToTemplateRef = ResourceRefR4.PARENT_REF.append( 436 ResourceRefR4.getRelativeRef(parent.getRef(), templateH.getRef())); 437 final NaiveImmList<TemplatedKey<?>> keys = templateH.getApplicableTemplatedKeys(); 438 414 439 new AutoAction("Create group for template", false) { 415 440 416 441 @Override … … 423 448 ResourceChanger groupCh = ch.getSub(groupRef); 424 449 groupCh.setRaw(ResourceR4.KEY_KIND, ElementGroupR4.KIND); 425 450 groupCh.setRaw(ResourceR4.KEY_TITLE, groupTitle); 451 452 groupCh.setRaw(ResourceR4.KEY_TEMPLATE, groupToTemplateRef); 453 for (Key<?> key : keys) { 454 groupCh.setRaw(key, null); 455 } 426 456 } 427 457 428 458 }.register(parent.getAccess()); … … 435 465 final String frameKind = templateH.getKind(); 436 466 final NaiveImmList<TemplatedKey<?>> immKeys = templateH.getApplicableTemplatedKeys(); 437 467 438 final ResourceRefR4 frameRef = ResourceRefR4.generateRandomSub(FrameH.NAME_PREFIX);468 final ResourceRefR4 frameRef = templateH.getRef().getThisChildRef(); 439 469 final String frameTitle = templateH.getTitle(); 440 470 441 471 final ResourceRefR4 parentRef = parent.getRef(); -
modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/FrameH.java
12 12 import org.sophie2.base.model.book.interfaces.CompositeElement; 13 13 import org.sophie2.base.model.book.interfaces.MemberElement; 14 14 import org.sophie2.base.model.book.interfaces.ResizableElement; 15 import org.sophie2.base.model.book.interfaces.ResourceFrame; 15 16 import org.sophie2.base.model.book.timelines.ActivationChannel; 16 17 import org.sophie2.base.model.book.timelines.LocationChannel; 17 18 import org.sophie2.base.model.resources.r4.ResourceRefR4; 18 19 import org.sophie2.base.model.resources.r4.access.ResourceAccess; 20 import org.sophie2.base.model.resources.r4.changes.AutoAction; 19 21 import org.sophie2.base.model.resources.r4.changes.ResourceChanger; 20 22 import org.sophie2.base.model.resources.r4.resources.ResourceR4; 21 23 import org.sophie2.core.prolib.impl.AutoProperty; … … 206 208 } 207 209 return super.getBoundArea(boundMode, elementTime, wrapMode); 208 210 } 211 212 /** 213 * Property synchronizing the kind of this frame with the kind of its template. 214 * 215 * @return 216 * The property. 217 */ 218 @SuppressWarnings("unused") 219 private Prop<String> templateKind() { 220 class templateKind extends AutoProperty<String> { 221 222 private String prevTemplateKind = ResourceR4.KIND; 223 private ResourceRefR4 prevTemplate = ResourceRefR4.NONE_REF; 224 225 @Override 226 protected String compute() { 227 ResourceRefR4 templateRef = getTemplate(); 228 ResourceAccess templateAccess = getAccess().open(templateRef, null); 229 final String templateKind = ResourceR4.KEY_KIND.get(templateAccess); 230 231 if (!templateKind.equals(this.prevTemplateKind)) { 232 233 if (templateRef.equals(this.prevTemplate) 234 && ResourceFrame.KEY_MAIN_RESOURCE.getApplyKey().get(templateAccess)) { 235 236 new AutoAction("Change kind", true) { 237 238 @Override 239 public void performAuto() { 240 getChanger().setRaw(ResourceR4.KEY_KIND, templateKind); 241 } 242 243 }.register(getAccess()); 244 } 245 246 this.prevTemplate = templateRef; 247 this.prevTemplateKind = templateKind; 248 } 249 250 return templateKind; 251 } 252 } 253 254 return getBean().makeProp(templateKind.class); 255 } 209 256 } -
modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/MainFuncTemplatesModule.java
19 19 import org.sophie2.main.app.menus.file.SaveBookAsTemplateItem; 20 20 import org.sophie2.main.func.templates.book.BookTemplatesLogic; 21 21 import org.sophie2.main.func.templates.book.BookTemplatesPalette; 22 import org.sophie2.main.func.templates.composite.CompositeTemplateLogic; 22 23 import org.sophie2.main.func.templates.frame.FrameTemplateLogic; 23 24 import org.sophie2.main.func.templates.frame.FrameTemplatesPalette; 24 25 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog; … … 62 63 SimpleOperation.fillExtensions(res, FrameTemplateLogic.class); 63 64 SimpleOperation.fillExtensions(res, PageTemplateLogic.class); 64 65 SimpleOperation.fillExtensions(res, BookTemplatesLogic.class); 65 66 SimpleOperation.fillExtensions(res, CompositeTemplateLogic.class); 67 66 68 res.add(new SimpleSophieExtension<Dialog>(Dialog.class, 67 69 new ApplyPageTemplateDialog())); 68 70 AutoVisualProvider.fillExtensions(res, ApplyPageTemplateSwingDialog.class); -
modules/org.sophie2.base.model.book/src/main/java/org/sophie2/base/model/book/ElementH.java
5 5 6 6 import org.sophie2.base.commons.structures.ImmTreeList; 7 7 import org.sophie2.base.commons.util.ImmList; 8 import org.sophie2.base.commons.util.NaiveImmList; 8 9 import org.sophie2.base.commons.util.position.ImmArea; 9 10 import org.sophie2.base.commons.util.position.ImmInsets; 10 11 import org.sophie2.base.commons.util.position.ImmMatrix; … … 33 34 import org.sophie2.base.model.resources.r4.resources.ResourceH; 34 35 import org.sophie2.base.model.resources.r4.resources.ResourceR4; 35 36 import org.sophie2.core.logging.SophieLog; 37 import org.sophie2.core.mvc.EventParams; 38 import org.sophie2.core.mvc.LogicR3; 36 39 import org.sophie2.core.prolib.impl.AutoProperty; 37 40 import org.sophie2.core.prolib.interfaces.Prop; 38 41 … … 567 570 } 568 571 return null; 569 572 } 573 574 /** 575 * Property synchronizing the sub-elements of this elements with those of its template. 576 * 577 * @return 578 * The property. 579 */ 580 @SuppressWarnings("unused") 581 private Prop<ImmList<ActivationChannel>> templateSubElements() { 582 class templateSubElements extends AutoProperty<ImmList<ActivationChannel>> { 570 583 584 private ImmList<ActivationChannel> prevTemplateElements = 585 NaiveImmList.<ActivationChannel>getEmpty(); 586 private ResourceRefR4 prevTemplate = ResourceRefR4.NONE_REF; 587 588 @Override 589 protected ImmList<ActivationChannel> compute() { 590 591 ResourceRefR4 templateRef = getTemplate(); 592 ResourceAccess templateAccess = getAccess().open(templateRef, null); 593 ImmList<ActivationChannel> subelements = 594 CompositeElement.KEY_SUB_ELEMENTS.get(templateAccess); 595 596 if (!this.prevTemplateElements.equals(subelements)) { 597 598 if (templateRef.equals(this.prevTemplate)) { 599 for (ActivationChannel channel : this.prevTemplateElements) { 600 if (!subelements.contains(channel)) { 601 LogicR3.fire(ElementH.this, null, null, null, 602 TemplateEventIds.TEMPLATE_ELEMENT_DELETED, 603 ResourceRefR4.PARENT_REF.append(templateRef.append(channel.getElementResource()))); 604 } 605 } 606 607 for (ActivationChannel channel : subelements) { 608 if (!this.prevTemplateElements.contains(channel)) { 609 LogicR3.fire(ElementH.this, null, null, null, 610 TemplateEventIds.TEMPLATE_ELEMENT_ADDED, 611 templateRef.append(channel.getElementResource())); 612 } 613 } 614 } else { 615 this.prevTemplate = templateRef; 616 } 617 618 this.prevTemplateElements = subelements; 619 } 620 621 return subelements; 622 } 623 624 } 625 return getBean().makeProp(templateSubElements.class); 626 } 627 628 /** 629 * Events related to changes in this element's template. 630 * 631 * @author deni 632 */ 633 public enum TemplateEventIds { 634 635 /** 636 * A new sub-element has been added to the template. 637 */ 638 @EventParams({ ResourceRefR4.class }) 639 TEMPLATE_ELEMENT_ADDED, 640 641 /** 642 * A sub-element has been deleted from the template. 643 */ 644 @EventParams({ ResourceRefR4.class }) 645 TEMPLATE_ELEMENT_DELETED; 646 647 /** 648 * The index of the ResourceRef parameter pointing to the sub-element 649 * that was added/removed. 650 */ 651 public static final int RESOURCE_REF_PARAM_INDEX = 0; 652 } 653 571 654 } -
modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/composite/CompositeTemplateLogic.java
1 package org.sophie2.main.func.templates.composite; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import org.sophie2.base.model.book.ElementH; 8 import org.sophie2.base.model.book.ElementH.TemplateEventIds; 9 import org.sophie2.base.model.resources.r4.ResourceRefR4; 10 import org.sophie2.base.model.resources.r4.access.ResourceAccess; 11 import org.sophie2.base.model.resources.r4.changes.AutoAction; 12 import org.sophie2.base.model.resources.r4.resources.ResourceH; 13 import org.sophie2.core.mvc.EventFilterBuilder; 14 import org.sophie2.core.mvc.OperationDef; 15 import org.sophie2.core.mvc.events.EventR3; 16 import org.sophie2.main.app.commons.util.TemplateUtil; 17 18 /** 19 * Logic for handling events related to changes in the template of an element. 20 * 21 * @author deni 22 */ 23 public enum CompositeTemplateLogic implements OperationDef { 24 25 /** 26 * Handles adding a new sub-element (sub-template) to the template of the source element. 27 * Creates a new sub-element by the sub-template. 28 */ 29 ON_TEMPLATE_SUBELEMENT_ADDED { 30 31 public void defineFilter(EventFilterBuilder filter) { 32 filter.setSourceClass(ElementH.class); 33 filter.setEventId(TemplateEventIds.TEMPLATE_ELEMENT_ADDED); 34 } 35 36 public boolean handle(EventR3 event) { 37 ElementH source = event.getSource(ElementH.class); 38 ResourceRefR4 templateRef = event.getEventParam(TemplateEventIds.RESOURCE_REF_PARAM_INDEX, 39 ResourceRefR4.class); 40 ResourceAccess templateAccess = source.getAccess().open(templateRef, null); 41 ElementH templateH = ResourceH.getHelper(templateAccess, ElementH.class); 42 43 ResourceRefR4 subelementToTemplate = ResourceRefR4.PARENT_REF.append(templateRef); 44 boolean templateUsed = false; 45 for (ElementH subelement : source.getSubElements()) { 46 if (subelement.getTemplate().equals(subelementToTemplate)) { 47 templateUsed = true; 48 break; 49 } 50 } 51 52 if (!templateUsed) { 53 TemplateUtil.templatePageElements(templateH, source, getAllSubelements(templateH), 54 new HashMap<ResourceRefR4, ResourceRefR4>()); 55 AutoAction.registerEndChange(source.getAccess(), "Add elements by template."); 56 } 57 58 return true; 59 } 60 61 private List<ResourceRefR4> getAllSubelements(ElementH element) { 62 List<ResourceRefR4> res = new ArrayList<ResourceRefR4>(); 63 res.add(element.getRef()); 64 for (ElementH subelement : element.getSubElements()) { 65 res.addAll(getAllSubelements(subelement)); 66 } 67 return res; 68 } 69 70 }, 71 72 /** 73 * Handles deleting a sub-element (sub-template) from the template of the source element. 74 * Deletes the element that was using the sub-template. 75 */ 76 ON_TEMPLATE_SUBELEMENT_DELETED { 77 78 public void defineFilter(EventFilterBuilder filter) { 79 filter.setSourceClass(ElementH.class); 80 filter.setEventId(TemplateEventIds.TEMPLATE_ELEMENT_DELETED); 81 } 82 83 public boolean handle(EventR3 event) { 84 ElementH source = event.getSource(ElementH.class); 85 ResourceRefR4 templateRef = event.getEventParam(TemplateEventIds.RESOURCE_REF_PARAM_INDEX, 86 ResourceRefR4.class); 87 88 for (ElementH subelement : source.getSubElements()) { 89 ResourceRefR4 subelementToTemplateRef = ResourceRefR4.getRelativeRef( 90 subelement.getRef(), templateRef); 91 if (subelementToTemplateRef.equals(subelement.getTemplate())) { 92 source.removeSubElement(subelement.getRef().getThisChildRef(), 93 "removing subelement", false); 94 } 95 } 96 AutoAction.registerEndChange(source.getAccess(), "Delete elements from template."); 97 98 return true; 99 } 100 101 } 102 103 }