Differences
This shows you the differences between two versions of the page.
gallery [2012/03/31 21:44] srdjan.lukovic |
gallery [2012/07/09 10:55] (current) srdjan.lukovic [GUI Code] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Gallery Sample ====== | + | ====== Gallery ====== |
- | This is standalone application showing one way of using [[Dynamic Panel]]. | + | |
+ | **Gallery** is a [[SOLoist Sample Applications|SOLoist sample application]] for a classical editable picture gallery. This is a simple, standalone application that demonstrates one way of using a [[Dynamic Panel]]. | ||
+ | |||
+ | By choosing an object of //House// from the suggest box, the gallery of pictures associated with that object is displayed. | ||
+ | |||
+ | A click on a thumbnail shows the full-sized picture. This functionality relies on an external JavaScript code, [[http://fancybox.net|FancyBox]], easily incorporated in the rest of the SOLoist code. | ||
+ | |||
+ | A click on the disclosure panel expands the form for adding new pictures to the gallery. | ||
+ | |||
+ | Pictures in the gallery can be reordered (by entering their order numbers in the boxes) and removed (by clicking on an X sign). | ||
==== Live example ==== | ==== Live example ==== | ||
- | [[http://soloistdemo.org/SampleApplications/gallery.html]] | + | [[http://soloistdemo.org/SampleApplications/gallery.html]]\\ |
+ | [[http://soloistdemo.org/SampleApplications/oql?q=SELECT+p%2C+p.title%2C+p.description%2C+p.isPublic%2C+p.submitted%2C+p.date%2C+p.superItem%2C+p.thumbnail%2C+p.picture%0AFROM+PictureFromGallery+p&hide=0 | OQL Query: Pictures]] | ||
+ | |{{screen:gallery.png?300}}| | ||
===== UML Model ===== | ===== UML Model ===== | ||
Line 10: | Line 22: | ||
===== Business Logic Code ===== | ===== Business Logic Code ===== | ||
- | <code java> | + | <code java AddToGallery.java> |
- | //... | + | public void execute() |
+ | // -------------<SOL id="e6326fe7-30c8-4f93-863a-2dc5825ac9aa:___throw__" /> | ||
+ | // -------------<LOS id="e6326fe7-30c8-4f93-863a-2dc5825ac9aa:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="e6326fe7-30c8-4f93-863a-2dc5825ac9aa:___body___" /> | ||
+ | ObjectOfClass owner = galleryOwner.val(); | ||
+ | IAssociationEndInstance<PictureFromGallery> gallery = ((House) owner).gallery; | ||
+ | picture.val().addToGallery(gallery); | ||
+ | // ---------<LOS id="e6326fe7-30c8-4f93-863a-2dc5825ac9aa:___body___" /> | ||
+ | } | ||
+ | |||
+ | // -------------<SOL id="519fec42-bffa-423b-997e-d6a6e567943e:___cend___" /> | ||
+ | @Override | ||
+ | protected void doCheckPreconditions() throws CommandPreconditionsException { | ||
+ | super.doCheckPreconditions(); | ||
+ | if (galleryOwner.val() == null) { | ||
+ | throw new CommandPreconditionsException("Please select the house."); | ||
+ | } | ||
+ | } | ||
+ | // -------------<LOS id="519fec42-bffa-423b-997e-d6a6e567943e:___cend___" /> | ||
+ | </code> | ||
+ | |||
+ | <code java MoveWithinGallery.java> | ||
+ | public void execute() | ||
+ | // -------------<SOL id="a7e66c29-b3b6-4471-8e5d-0f411c4c5a97:___throw__" /> | ||
+ | // -------------<LOS id="a7e66c29-b3b6-4471-8e5d-0f411c4c5a97:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="a7e66c29-b3b6-4471-8e5d-0f411c4c5a97:___body___" /> | ||
+ | ObjectOfClass owner = galleryOwner.val(); | ||
+ | IAssociationEndInstance<PictureFromGallery> gallery = ((House) owner).gallery; | ||
+ | PictureFromGallery pfg = picture.val(); | ||
+ | pfg.moveWithinGallery(gallery, position.val()); | ||
+ | // ---------<LOS id="a7e66c29-b3b6-4471-8e5d-0f411c4c5a97:___body___" /> | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code java RemoveFromGallery.java> | ||
+ | public void execute() | ||
+ | // -------------<SOL id="23580b3c-e2c5-4b16-894c-e3f4464f5a98:___throw__" /> | ||
+ | // -------------<LOS id="23580b3c-e2c5-4b16-894c-e3f4464f5a98:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="23580b3c-e2c5-4b16-894c-e3f4464f5a98:___body___" /> | ||
+ | ObjectOfClass owner = galleryOwner.val(); | ||
+ | IAssociationEndInstance<PictureFromGallery> gallery = ((House) owner).gallery; | ||
+ | picture.val().removeFromGallery(gallery); | ||
+ | // ---------<LOS id="23580b3c-e2c5-4b16-894c-e3f4464f5a98:___body___" /> | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code java PictureFromGallery.java> | ||
+ | /** | ||
+ | * Makes a thumbnail from the existing picture and sets it to the thumbnail slot. | ||
+ | * The size of the created thumbnail is 100 x 100px and the aspect ratio is | ||
+ | * preserved. | ||
+ | */ | ||
+ | public void makeThumbnail() | ||
+ | // -------------<SOL id="d1e4657a-b5a1-4c4c-9f4c-e0446b338e28:___throw__" /> | ||
+ | // -------------<LOS id="d1e4657a-b5a1-4c4c-9f4c-e0446b338e28:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="d1e4657a-b5a1-4c4c-9f4c-e0446b338e28:___body___" /> | ||
+ | if (picture.val() != null) | ||
+ | try { | ||
+ | thumbnail.set(Picture.fromBufferedImage(Thumbnails.of(picture.val().toBufferedImage()).size(150, 150).outputFormat("jpg").asBufferedImage())); | ||
+ | } catch (IOException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | // ---------<LOS id="d1e4657a-b5a1-4c4c-9f4c-e0446b338e28:___body___" /> | ||
+ | } | ||
+ | |||
+ | |||
+ | public void removeFromGallery(IAssociationEndInstance<PictureFromGallery> gallery) | ||
+ | // -------------<SOL id="0f0f610a-44b0-48dc-9a5d-2ed0887e62e3:___throw__" /> | ||
+ | // -------------<LOS id="0f0f610a-44b0-48dc-9a5d-2ed0887e62e3:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="0f0f610a-44b0-48dc-9a5d-2ed0887e62e3:___body___" /> | ||
+ | gallery.remove(this); | ||
+ | if (this.house.read().isEmpty()) | ||
+ | this.destroy(); | ||
+ | // ---------<LOS id="0f0f610a-44b0-48dc-9a5d-2ed0887e62e3:___body___" /> | ||
+ | } | ||
+ | |||
+ | |||
+ | public void addToGallery(IAssociationEndInstance<PictureFromGallery> gallery) | ||
+ | // -------------<SOL id="8cfd27a3-13bd-44e5-bb1b-b4681d1111e6:___throw__" /> | ||
+ | // -------------<LOS id="8cfd27a3-13bd-44e5-bb1b-b4681d1111e6:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="8cfd27a3-13bd-44e5-bb1b-b4681d1111e6:___body___" /> | ||
+ | this.makeThumbnail(); | ||
+ | this.submitted.set(Boolean.TRUE); | ||
+ | gallery.addLast(this); | ||
+ | // ---------<LOS id="8cfd27a3-13bd-44e5-bb1b-b4681d1111e6:___body___" /> | ||
+ | } | ||
+ | |||
+ | |||
+ | public void moveWithinGallery(IAssociationEndInstance<PictureFromGallery> gallery, Integer pos) | ||
+ | // -------------<SOL id="f77e5360-24d5-4e7c-ba30-4b91b2622f88:___throw__" /> | ||
+ | // -------------<LOS id="f77e5360-24d5-4e7c-ba30-4b91b2622f88:___throw__" /> | ||
+ | { | ||
+ | // ---------<SOL id="f77e5360-24d5-4e7c-ba30-4b91b2622f88:___body___" /> | ||
+ | int i = gallery.read().indexOf(this); | ||
+ | int position = pos.toInt() - 1; | ||
+ | if (position != -1) { | ||
+ | if (position >= gallery.size()) | ||
+ | position = (int) (gallery.size() - 1); | ||
+ | else if (position < 0) | ||
+ | position = 0; | ||
+ | gallery.reorder(i, position); | ||
+ | } | ||
+ | // ---------<LOS id="f77e5360-24d5-4e7c-ba30-4b91b2622f88:___body___" /> | ||
+ | } | ||
</code> | </code> | ||
===== GUI Code ===== | ===== GUI Code ===== | ||
<code java> | <code java> | ||
- | //... | + | package rs.sol.sampleapps.gallery; |
+ | |||
+ | import rs.sol.sampleapps.House; | ||
+ | import rs.sol.soloist.helpers.init.DefaultContextInit; | ||
+ | import rs.sol.soloist.helpers.init.Initializer; | ||
+ | import rs.sol.soloist.helpers.init.InitializerFailedException; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUIApplicationComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUIPanelComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.construction.GUIComponentBinding; | ||
+ | import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIInput; | ||
+ | import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIFindAllInstancesSAPComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.style.GUIContext; | ||
+ | import rs.sol.soloist.server.guiconfiguration.style.GUIObjectSetting; | ||
+ | import rs.sol.soloist.server.guiconfiguration.style.GUITextFeature; | ||
+ | import rs.sol.soloist.server.server.SoloistServiceServlet; | ||
+ | |||
+ | public enum Gallery implements Initializer { | ||
+ | |||
+ | INSTANCE; | ||
+ | |||
+ | @Override | ||
+ | public void init() throws InitializerFailedException { | ||
+ | GUIApplicationComponent application = new GUIApplicationComponent(); | ||
+ | application.setName("GallerySample"); | ||
+ | SoloistServiceServlet.registerApplication(application); | ||
+ | application.setContext(createContextAndStyles()); | ||
+ | |||
+ | GUIPanelComponent root = GUIPanelComponent.createFlow(application); | ||
+ | |||
+ | GUILabelComponent title = GUILabelComponent.create(root, "Gallery"); | ||
+ | title.setStyle("titleStyle"); | ||
+ | |||
+ | GUIPanelComponent topPanel = GUIPanelComponent.createFlow(root); | ||
+ | topPanel.setStyle("topPanel"); | ||
+ | |||
+ | GUILabelComponent.create(topPanel, "Choose house:").setStyle("formLabel"); | ||
+ | |||
+ | GUIFindAllInstancesSAPComponent allHouses = GUIFindAllInstancesSAPComponent.create(topPanel, House.CLASSIFIER); | ||
+ | GUIInput suggestBox = GUIInput.createSuggest(topPanel); | ||
+ | suggestBox.setLowerBound(1); | ||
+ | GUIComponentBinding.create(allHouses.opValue(), suggestBox.ipCollection()); | ||
+ | |||
+ | GalleryFragment gf = new GalleryFragment(topPanel); | ||
+ | GUIComponentBinding.create(suggestBox.opValue(), gf.ipOwner()); | ||
+ | } | ||
+ | |||
+ | private GUIContext createContextAndStyles() { | ||
+ | GUIContext context = new GUIContext(); | ||
+ | DefaultContextInit.getRoot().addContext(context); | ||
+ | GUIObjectSetting person = GUIObjectSetting.create(context, House.CLASSIFIER); | ||
+ | GUITextFeature.createName(person, House.PROPERTIES.code); | ||
+ | return context; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code java> | ||
+ | package rs.sol.sampleapps.gallery; | ||
+ | |||
+ | import rs.sol.sampleapps.Document; | ||
+ | import rs.sol.sampleapps.PictureFromGallery; | ||
+ | import rs.sol.sampleapps.commands.AddToGallery; | ||
+ | import rs.sol.sampleapps.commands.MoveWithinGallery; | ||
+ | import rs.sol.sampleapps.commands.RemoveFromGallery; | ||
+ | import rs.sol.sampleapps.gui.GUIGalleryPanel; | ||
+ | import rs.sol.soloist.server.builtindomains.builtincommands.CmdCreateObjectOfClass; | ||
+ | import rs.sol.soloist.server.builtindomains.builtindatatypes.Boolean; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUIButtonComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUICommandComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUIDisclosurePanel; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.GUIPanelComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.components.PerformImmediately; | ||
+ | import rs.sol.soloist.server.guiconfiguration.construction.GUIComponentBinding; | ||
+ | import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIEdit; | ||
+ | import rs.sol.soloist.server.guiconfiguration.layout.TableLayoutData; | ||
+ | import rs.sol.soloist.server.guiconfiguration.layout.VerticalAlignment; | ||
+ | import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIBooleanFilter; | ||
+ | import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIBufferComponent; | ||
+ | import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIRelayComponent; | ||
+ | import rs.sol.soloist.server.uml.concepts.runtime.ISlot; | ||
+ | |||
+ | public class GalleryFragment { | ||
+ | |||
+ | private ISlot<?> owner; | ||
+ | |||
+ | public ISlot<?> ipOwner(){ | ||
+ | return owner; | ||
+ | } | ||
+ | |||
+ | public static MoveWithinGallery cmdMoveWithinGallery = new MoveWithinGallery(); | ||
+ | public static RemoveFromGallery cmdRemoveFromGallery = new RemoveFromGallery(); | ||
+ | |||
+ | public GalleryFragment(GUIPanelComponent rootPanel) { | ||
+ | GUIRelayComponent ownerRelay = GUIRelayComponent.create(rootPanel); | ||
+ | owner = ownerRelay.ipRelay(); | ||
+ | |||
+ | GUIDisclosurePanel newPictureDisclosure = GUIDisclosurePanel.create(rootPanel, "Add picture to gallery"); | ||
+ | |||
+ | GUIPanelComponent subDisclosure = GUIPanelComponent.createFlow(newPictureDisclosure); | ||
+ | subDisclosure.setStyle("disclosureForm"); | ||
+ | GUIPanelComponent table = GUIPanelComponent.createTable(subDisclosure); | ||
+ | table.setStyle("table"); | ||
+ | |||
+ | CmdCreateObjectOfClass cmd = new CmdCreateObjectOfClass(); | ||
+ | cmd.setClass(PictureFromGallery.CLASSIFIER); | ||
+ | GUICommandComponent cmdNewBlank = GUICommandComponent.create(rootPanel, cmd, PerformImmediately.NOTHING); | ||
+ | GUIBooleanFilter gbf = GUIBooleanFilter.create(rootPanel); | ||
+ | GUIComponentBinding.create(newPictureDisclosure.opOpen(), gbf.ipInput()); | ||
+ | GUIComponentBinding.create(gbf.opYes(), cmdNewBlank.ipClick()); | ||
+ | |||
+ | int row = 0; | ||
+ | GUILabelComponent.create(table, "Title", row++, 0).setStyle("formLabel"); | ||
+ | GUILabelComponent.create(table, "Description", row++, 0).setStyle("formLabel"); | ||
+ | GUILabelComponent.create(table, "Picture", row++, 0).setStyle("formLabel"); | ||
+ | |||
+ | row = 0; | ||
+ | GUIEdit title = GUIEdit.createField(table, Document.PROPERTIES.title, row++, 1); | ||
+ | GUIEdit descrip = GUIEdit.createField(table, Document.PROPERTIES.description, row++, 1); | ||
+ | descrip.setMaxLength(2000); | ||
+ | descrip.setMultiline(true); | ||
+ | descrip.setSize("265px", "192px"); | ||
+ | GUIPanelComponent picUpload = GUIEdit.createPicture(table, PictureFromGallery.PROPERTIES.picture, true); | ||
+ | picUpload.setRowColumn(row++, 1); | ||
+ | |||
+ | GUIPanelComponent picture = GUIEdit.createPicture(table, PictureFromGallery.PROPERTIES.picture, false); | ||
+ | picture.setRowColumn(0, 2, 4, 1); | ||
+ | picture.setCellAlignment(null, VerticalAlignment.TOP); | ||
+ | |||
+ | GUIComponentBinding.create(cmdNewBlank, CmdCreateObjectOfClass.PROPERTIES.output, title.ipElement()); | ||
+ | GUIComponentBinding.create(cmdNewBlank, CmdCreateObjectOfClass.PROPERTIES.output, descrip.ipElement()); | ||
+ | GUIComponentBinding.create(cmdNewBlank, CmdCreateObjectOfClass.PROPERTIES.output, picUpload.ipRelay1()); | ||
+ | GUIComponentBinding.create(cmdNewBlank, CmdCreateObjectOfClass.PROPERTIES.output, picture.ipRelay1()); | ||
+ | |||
+ | GUIButtonComponent cmdAdd = GUIButtonComponent.create(table, "Add picture", new AddToGallery()); | ||
+ | cmdAdd.setLayoutData(TableLayoutData.create(row++, 0)); | ||
+ | GUIComponentBinding.create(ownerRelay.opRelay(), cmdAdd, AddToGallery.PROPERTIES.galleryOwner); | ||
+ | GUIComponentBinding.create(cmdNewBlank, CmdCreateObjectOfClass.PROPERTIES.output, cmdAdd, AddToGallery.PROPERTIES.picture); | ||
+ | |||
+ | GUIGalleryPanel galleryPanel = new GUIGalleryPanel(); | ||
+ | rootPanel.add(galleryPanel); | ||
+ | GUIComponentBinding.create(ownerRelay.opRelay(), galleryPanel.ipElement()); | ||
+ | GUIComponentBinding.create(cmdAdd.opCommandExecuted(), galleryPanel.ipRefreshContents()); | ||
+ | GUIBufferComponent gbc = GUIBufferComponent.create(rootPanel, false, Boolean.FALSE); | ||
+ | GUIComponentBinding.create(gbc.opOutput(), newPictureDisclosure.ipOpen()); | ||
+ | GUIComponentBinding.create(cmdAdd.opCommandExecuted(), gbc.ipSend()); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code javascript extension.js> | ||
+ | function htmlComponentChanged(id) { | ||
+ | |||
+ | if (id == "fancyGallery") { | ||
+ | setTimeout(function() { | ||
+ | $("a.fancy_group").fancybox({ | ||
+ | 'titlePosition' : 'over' | ||
+ | }); | ||
+ | }, timeout); | ||
+ | } | ||
+ | |||
+ | } | ||
</code> | </code> |