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