Differences
This shows you the differences between two versions of the page.
|
gallery [2012/03/31 21:46] srdjan.lukovic [Live example] |
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}}| | ||
| Line 11: | 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> | ||