====== Gallery ====== **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 ==== [[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 ===== {{gallery.png}} ===== Business Logic Code ===== public void execute() // ------------- // ------------- { // --------- ObjectOfClass owner = galleryOwner.val(); IAssociationEndInstance gallery = ((House) owner).gallery; picture.val().addToGallery(gallery); // --------- } // ------------- @Override protected void doCheckPreconditions() throws CommandPreconditionsException { super.doCheckPreconditions(); if (galleryOwner.val() == null) { throw new CommandPreconditionsException("Please select the house."); } } // ------------- public void execute() // ------------- // ------------- { // --------- ObjectOfClass owner = galleryOwner.val(); IAssociationEndInstance gallery = ((House) owner).gallery; PictureFromGallery pfg = picture.val(); pfg.moveWithinGallery(gallery, position.val()); // --------- } public void execute() // ------------- // ------------- { // --------- ObjectOfClass owner = galleryOwner.val(); IAssociationEndInstance gallery = ((House) owner).gallery; picture.val().removeFromGallery(gallery); // --------- } /** * 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() // ------------- // ------------- { // --------- 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(); } // --------- } public void removeFromGallery(IAssociationEndInstance gallery) // ------------- // ------------- { // --------- gallery.remove(this); if (this.house.read().isEmpty()) this.destroy(); // --------- } public void addToGallery(IAssociationEndInstance gallery) // ------------- // ------------- { // --------- this.makeThumbnail(); this.submitted.set(Boolean.TRUE); gallery.addLast(this); // --------- } public void moveWithinGallery(IAssociationEndInstance gallery, Integer pos) // ------------- // ------------- { // --------- 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); } // --------- } ===== GUI Code ===== 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; } } 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()); } } function htmlComponentChanged(id) { if (id == "fancyGallery") { setTimeout(function() { $("a.fancy_group").fancybox({ 'titlePosition' : 'over' }); }, timeout); } }