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
1 package org.sophie2.main.func.templates.page; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.sophie2.base.model.book.ElementH; 7 import org.sophie2.core.prolib.impl.AutoListProperty; 8 import org.sophie2.core.prolib.impl.BaseProObject; 9 import org.sophie2.core.prolib.interfaces.ListProp; 10 import org.sophie2.core.prolib.interfaces.Prop; 11 import org.sophie2.core.prolib.interfaces.RwProp; 12 import org.sophie2.core.prolib.list.ComposingProList; 13 import org.sophie2.core.prolib.list.ProList; 14 15 /** 16 * Holds the settings for applying a page template. 17 * 18 * @author deni 19 */ 20 public 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
1 1 package org.sophie2.main.app.commons.util; 2 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 3 5 import java.util.List; 6 import java.util.Map; 4 7 5 8 import org.sophie2.base.commons.util.ImmList; 6 import org.sophie2.base.commons.util.ImmMap;7 9 import org.sophie2.base.commons.util.NaiveImmList; 8 import org.sophie2.base.dnd.DndTransferable;9 10 import org.sophie2.base.model.book.BookH; 10 11 import org.sophie2.base.model.book.ElementGroupH; 11 12 import org.sophie2.base.model.book.ElementH; … … 33 34 import org.sophie2.main.app.commons.element.ElementView; 34 35 import org.sophie2.main.app.commons.frame.FrameView; 35 36 import org.sophie2.main.app.commons.page.RootPageView; 36 import org.sophie2.main.dnd.TemplateRefData;37 37 38 38 /** 39 39 * Utility class used to incorporate helper methods used in templating logic. … … 247 247 } 248 248 249 249 /** 250 * Extracts the template data from the given transferable and applies the template251 * to the given page.252 *253 * @param transferable254 * A DndTransferable containing template data.255 * @param page256 * 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 /**274 250 * Applies a template to a page. 275 251 * 276 252 * Frames and other page elements are templated by using the frames in the … … 286 262 * The page to apply the template to. 287 263 * @param pageTemplateRef 288 264 * An absolute reference to the template to apply. 289 * @param templatesToExistingFrames265 * @param existingMap 290 266 * A map from frames in the given page template to existing frames in the page 291 267 * to which the template will be applied. The frames from the template will be used 292 268 * as templates for the frames in the page. … … 295 271 * as templates. 296 272 */ 297 273 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) { 300 275 301 276 assert pageTemplateRef.isAbsolute(); 302 277 final ResourceRefR4 pageToTemplateRef = … … 319 294 } 320 295 } 321 296 }.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); 326 304 } 327 305 } 328 306 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 330 314 if (templateH instanceof ElementGroupH) { 331 315 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 } 336 323 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); 354 325 ElementGroupH groupH = ResourceH.getHelper(groupAccess, ElementGroupH.class); 355 326 356 327 for (ElementH element : templateH.getSubElements()) { 357 templatePageElement (element, groupH);328 templatePageElements(element, groupH, newElements, existing); 358 329 } 359 330 } 360 331 361 332 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 } 365 342 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()); 368 348 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) { 372 350 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; 391 366 } 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(); 392 372 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 393 417 } -
modules/org.sophie2.main.func.links/src/main/java/org/sophie2/main/func/links/LinksHud.java
61 61 /** 62 62 * The {@link Skin} property id of the title of the {@link #EMPTY_RULE} item. 63 63 */ 64 public static final String EMPTY_RULE_TITLE_PROP_ID = null;64 public static final String EMPTY_RULE_TITLE_PROP_ID = "empty-rule-title"; 65 65 66 66 @SuppressWarnings("unused") 67 67 @SkinPartDef -
modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/ApplyPageTemplateHandler.java
1 1 package org.sophie2.main.func.templates.page; 2 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import org.sophie2.base.dialogs.DialogManager; 3 8 import org.sophie2.base.dnd.DndTransferable; 9 import org.sophie2.base.model.book.ElementH; 10 import org.sophie2.base.model.book.PageH; 11 import org.sophie2.base.model.resources.r4.ResourceRefR4; 12 import org.sophie2.base.model.resources.r4.access.ResourceAccess; 13 import org.sophie2.base.model.resources.r4.changes.AutoAction; 14 import org.sophie2.base.model.resources.r4.resources.ResourceH; 4 15 import org.sophie2.main.app.commons.book.BookView; 5 16 import org.sophie2.main.app.commons.element.ElementDropHandler; 6 17 import org.sophie2.main.app.commons.page.MainPageView; 7 18 import org.sophie2.main.app.commons.util.TemplateUtil; 8 19 import org.sophie2.main.dnd.TemplateRefData; 20 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog; 9 21 10 22 /** 11 23 * Handles dropping a page template over the {@link MainPageView}. … … 39 51 TemplateRefData refData = transferable.getDndData(TemplateRefData.class); 40 52 assert refData != null : "There is no template to apply"; 41 53 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 } 43 85 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 } 48 94 } 49 95 } 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 } 50 122 } -
modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/book/BookView.java
1 1 package org.sophie2.main.app.commons.book; 2 2 3 import java.util.ArrayList; 3 4 import java.util.List; 4 5 5 6 import org.sophie2.base.commons.util.ImmList; … … 10 11 import org.sophie2.base.media.MediaUtil; 11 12 import org.sophie2.base.media.TimePos; 12 13 import org.sophie2.base.model.book.BookH; 14 import org.sophie2.base.model.book.ElementH; 13 15 import org.sophie2.base.model.book.PageH; 14 16 import org.sophie2.base.model.book.resource.AudioResourceH; 15 17 import org.sophie2.base.model.book.resource.MediaResourceR4; … … 519 521 ResourceAccess templateAccess = this.getAccess().open(absTemplateRef, null); 520 522 PageH templateH = ResourceH.getHelper(templateAccess, PageH.class); 521 523 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"); 523 527 } 524 525 AutoAction.registerEndChange(getAccess(), "Add a new templated page"); 526 528 527 529 goToPage(model().get().getPages().get(index)); 528 530 529 531 SophieLog.debugf("Went to page %d.", index + 1); 530 532 } 531 533 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 532 543 /** 533 544 * Adds a new page to this book to the given index and sets it to be 534 545 * current. -
modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/MainFuncTemplatesModule.java
2 2 3 3 import java.util.List; 4 4 5 import org.sophie2.base.dialogs.Dialog; 5 6 import org.sophie2.base.skins.BaseSkinPart; 6 7 import org.sophie2.base.skins.SkinPart; 7 8 import org.sophie2.base.skins.SkinUtil; 9 import org.sophie2.base.visual.AutoVisualProvider; 8 10 import org.sophie2.base.visual.BaseVisualElement; 9 11 import org.sophie2.base.visual.SimpleVisualProvider; 12 import org.sophie2.core.modularity.SimpleSophieExtension; 10 13 import org.sophie2.core.modularity.SophieExtension; 11 14 import org.sophie2.core.modularity.SophieExtensionPoint; 12 15 import org.sophie2.core.modularity.SophieModule; … … 18 21 import org.sophie2.main.func.templates.book.BookTemplatesPalette; 19 22 import org.sophie2.main.func.templates.frame.FrameTemplateLogic; 20 23 import org.sophie2.main.func.templates.frame.FrameTemplatesPalette; 24 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog; 21 25 import org.sophie2.main.func.templates.page.PageTemplateLogic; 22 26 import org.sophie2.main.func.templates.page.PageTemplatesPalette; 27 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog; 28 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotTitleLable; 29 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotsPanel; 30 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.TargetComboBox; 23 31 24 32 /** 25 33 * Module class for template functionality. … … 33 41 // no extension points 34 42 } 35 43 44 @SuppressWarnings("unchecked") 36 45 @Override 37 46 protected void defineExtensions(List<SophieExtension<?>> res) { 38 47 res.add(SimpleVisualProvider.createExtension( … … 52 61 53 62 SimpleOperation.fillExtensions(res, FrameTemplateLogic.class); 54 63 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 57 75 res.add(makeSkinPart()); 58 76 } 59 77 -
modules/org.sophie2.base.dnd/src/main/java/org/sophie2/base/dnd/SophieDragDropHandler.java
20 20 import javax.swing.TransferHandler; 21 21 22 22 import org.sophie2.base.commons.util.position.ImmPoint; 23 import org.sophie2.core.mvc.EventFilterBuilder; 23 24 import org.sophie2.core.mvc.EventParams; 24 25 import org.sophie2.core.mvc.LogicR3; 26 import org.sophie2.core.mvc.OperationDef; 25 27 import org.sophie2.core.mvc.events.EventR3; 26 28 27 29 /** … … 171 173 172 174 } 173 175 174 // TODO: delete175 176 /** 176 177 * Class representing a transaction that is open when a transferable is to 177 178 * be imported. 178 179 * 179 * @author tanya 180 * @author tanya, deni 180 181 */ 181 182 public static class DndImport extends DndAction { 182 183 183 private boolean imported;184 private DropHandler handler; 184 185 185 186 /** 186 187 * Constructs a transaction be given transferable. 187 188 * 188 189 * @param transferable 190 * The transferable that should be imported. 191 * @param handler 192 * The handler responsible for importing the transferable 189 193 */ 190 public DndImport(Transferable transferable ) {191 this. imported = false;194 public DndImport(Transferable transferable, DropHandler handler) { 195 this.handler = handler; 192 196 setDndTransferable(new AwtTransferable(transferable)); 193 197 } 194 198 195 199 /** 196 * Sets if the transferable has been imported.200 * Gets the handler responsible for importing the transferable. 197 201 * 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. 201 204 */ 202 public void setImported(boolean imported) {203 this.imported = imported;205 public DropHandler getHandler() { 206 return this.handler; 204 207 } 205 206 /**207 * Returns whether the transferable has been imported.208 *209 * @return <b>true</b> if the transferable has been imported, and210 * <b>false</b> otherwise.211 */212 public boolean getImported() {213 return this.imported;214 }215 208 } 216 209 217 210 /** … … 342 335 public void drop(DropTargetDropEvent dtde) { 343 336 dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 344 337 345 Transferable transferable = dtde.getTransferable();346 347 338 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)); 353 348 } 354 349 } 355 350 … … 411 406 DND_PRE_IMPORT, 412 407 413 408 /** 409 * Fired when a transferable is dropped over a component. 410 */ 411 @EventParams( { DndImport.class, }) 412 DND_IMPORT, 413 414 /** 414 415 * Fired on exporting data - copy in copy/paste operation. 415 416 */ 416 417 @EventParams( {}) … … 443 444 */ 444 445 public static final int KEY_PARAM_INDEX = 2; 445 446 } 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 } 446 479 } 480 No newline at end of file -
modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/dialogs/BaseCustomModalDialog.java
6 6 import java.awt.Frame; 7 7 import java.awt.event.ActionEvent; 8 8 import java.awt.event.KeyEvent; 9 import java.awt.event.WindowAdapter; 10 import java.awt.event.WindowEvent; 9 11 10 12 import javax.swing.AbstractAction; 11 13 import javax.swing.Action; … … 182 184 @Override 183 185 protected JDialog create() { 184 186 // Create the modal JDialog. 185 JDialog dialog = new JDialog((Frame)null, true); 187 JDialog dialog = new JDialog((Frame)null, true); 186 188 JRootPane rootPane = dialog.getRootPane(); 187 189 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 188 198 // Map Esc to Cancel action. 189 199 KeyStroke stroke = KeyStroke 190 200 .getKeyStroke(KeyEvent.VK_ESCAPE, 0); -
modules/org.sophie2.base.dnd/src/main/java/org/sophie2/base/dnd/BaseDndModule.java
3 3 import java.awt.datatransfer.DataFlavor; 4 4 import java.util.List; 5 5 6 import org.sophie2.base.dnd.SophieDragDropHandler.DropHandlerLogic; 6 7 import org.sophie2.base.dnd.dnddata.ImageData; 7 8 import org.sophie2.base.dnd.dnddata.RtfData; 8 9 import org.sophie2.base.dnd.dnddata.StringData; … … 10 11 import org.sophie2.core.modularity.SophieExtension; 11 12 import org.sophie2.core.modularity.SophieExtensionPoint; 12 13 import org.sophie2.core.modularity.SophieModule; 14 import org.sophie2.core.mvc.SimpleOperation; 13 15 14 16 /** 15 17 * A module class for the base dnd. … … 71 73 72 74 res.add(new SimpleSophieExtension<DndProvider>(DndProvider.class, 73 75 new RtfData.RtfDndProvider())); 76 77 SimpleOperation.fillExtensions(res, DropHandlerLogic.class); 74 78 } 75 79 76 80 /** -
modules/org.sophie2.base.bound/src/main/java/org/sophie2/base/bound/BoundControl.java
369 369 if (size().get() != null) { 370 370 res.setSize(size().get().toDimension()); 371 371 res.setPreferredSize(size().get().toDimension()); 372 res.setMinimumSize(size().get().toDimension()); 373 res.setMaximumSize(size().get().toDimension()); 372 374 } 373 375 if (controlSize().get() != null) { 374 376 dataInputControl().get().setSize( -
modules/org.sophie2.main.func.templates/src/main/java/org/sophie2/main/func/templates/page/Slot.java
1 package org.sophie2.main.func.templates.page; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.sophie2.base.model.book.ElementH; 7 import org.sophie2.base.model.resources.r4.resources.ResourceH; 8 import org.sophie2.core.prolib.annot.Own; 9 import org.sophie2.core.prolib.impl.AutoListProperty; 10 import org.sophie2.core.prolib.impl.BaseProObject; 11 import org.sophie2.core.prolib.interfaces.ListProp; 12 import org.sophie2.core.prolib.interfaces.Prop; 13 import org.sophie2.core.prolib.interfaces.RwProp; 14 import org.sophie2.core.prolib.list.ComposingProList; 15 import org.sophie2.core.prolib.list.ProList; 16 import 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 */ 26 public 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
1 package org.sophie2.main.func.templates.page; 2 3 import java.awt.BorderLayout; 4 import java.awt.Dimension; 5 import java.awt.FlowLayout; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 import javax.swing.Box; 10 import javax.swing.BoxLayout; 11 import javax.swing.JComponent; 12 import javax.swing.JLabel; 13 import javax.swing.JPanel; 14 import javax.swing.JScrollPane; 15 import javax.swing.ScrollPaneConstants; 16 17 import org.sophie2.base.bound.BoundCheckBox; 18 import org.sophie2.base.bound.BoundComboBox; 19 import org.sophie2.base.bound.BoundControl; 20 import org.sophie2.base.bound.BoundValidation; 21 import org.sophie2.base.bound.ComboInput; 22 import org.sophie2.base.bound.ComboState; 23 import org.sophie2.base.bound.BoundControl.EventIds; 24 import org.sophie2.base.commons.util.position.ImmSize; 25 import org.sophie2.base.dialogs.Dialog; 26 import org.sophie2.base.dialogs.DialogInput; 27 import org.sophie2.base.layout.model.MainWindow; 28 import org.sophie2.base.model.book.ElementGroupH; 29 import org.sophie2.base.model.book.ElementH; 30 import org.sophie2.base.model.book.FrameH; 31 import org.sophie2.base.model.resources.r4.resources.ResourceH; 32 import org.sophie2.base.skins.Skin; 33 import org.sophie2.base.skins.SkinElementId; 34 import org.sophie2.base.skins.SkinUtil; 35 import org.sophie2.base.visual.BaseSwingVisualElement; 36 import org.sophie2.base.visual.BaseVisualModule; 37 import org.sophie2.base.visual.SwingVisualElement; 38 import org.sophie2.base.visual.VisualProvider; 39 import org.sophie2.base.visual.skins.ElementSkinPart; 40 import org.sophie2.base.visual.skins.RelatedChildren; 41 import org.sophie2.base.visual.skins.SkinPartDef; 42 import org.sophie2.base.visual.skins.VisualElementDef; 43 import org.sophie2.core.mvc.EventFilterBuilder; 44 import org.sophie2.core.mvc.OperationDef; 45 import org.sophie2.core.mvc.events.EventR3; 46 import org.sophie2.core.prolib.annot.Own; 47 import org.sophie2.core.prolib.impl.AutoListProperty; 48 import org.sophie2.core.prolib.impl.AutoProperty; 49 import org.sophie2.core.prolib.impl.ResourceProperty; 50 import org.sophie2.core.prolib.interfaces.ListProp; 51 import org.sophie2.core.prolib.interfaces.Prop; 52 import org.sophie2.core.prolib.interfaces.RwProp; 53 import org.sophie2.core.prolib.list.ComposingProList; 54 import org.sophie2.core.prolib.list.ProList; 55 import org.sophie2.main.app.commons.dialogs.BaseCustomModalDialog; 56 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.DeleteUnassignedElementsCheckBox; 57 import org.sophie2.main.func.templates.page.ApplyPageTemplateDialog.ApplyPageTemplateSwingDialog.SlotsPanel; 58 import 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 */ 65 public 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 }