Java tutorial
/* * This file is part of the ZoRa project: http://www.photozora.org. * * ZoRa is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * ZoRa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZoRa; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * (c) 2009-2019 Berthold Daum */ package com.bdaum.zoom.ui.internal.views; import java.awt.Color; import java.awt.Font; import java.awt.Paint; import java.awt.event.InputEvent; import java.awt.geom.Point2D; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.AbstractOperation; import org.eclipse.core.commands.operations.IUndoableOperation; import org.eclipse.core.commands.operations.UndoContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressIndicator; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.IViewSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.piccolo2d.PNode; import org.piccolo2d.event.PBasicInputEventHandler; import org.piccolo2d.event.PInputEvent; import org.piccolo2d.extras.swt.PSWTCanvas; import org.piccolo2d.extras.swt.PSWTText; import org.piccolo2d.util.PBounds; import com.bdaum.aoModeling.runtime.IIdentifiableObject; import com.bdaum.aoModeling.runtime.IdentifiableObject; import com.bdaum.zoom.cat.model.asset.Asset; import com.bdaum.zoom.cat.model.asset.AssetImpl; import com.bdaum.zoom.cat.model.group.webGallery.Storyboard; import com.bdaum.zoom.cat.model.group.webGallery.StoryboardImpl; import com.bdaum.zoom.cat.model.group.webGallery.WebExhibit; import com.bdaum.zoom.cat.model.group.webGallery.WebExhibitImpl; import com.bdaum.zoom.cat.model.group.webGallery.WebGallery; import com.bdaum.zoom.cat.model.group.webGallery.WebGalleryImpl; import com.bdaum.zoom.core.Constants; import com.bdaum.zoom.core.Core; import com.bdaum.zoom.core.IGalleryGenerator; import com.bdaum.zoom.core.ISpellCheckingService; import com.bdaum.zoom.core.IVolumeManager; import com.bdaum.zoom.core.QueryField; import com.bdaum.zoom.core.db.IDbManager; import com.bdaum.zoom.core.internal.CoreActivator; import com.bdaum.zoom.core.internal.IMediaSupport; import com.bdaum.zoom.core.internal.Utilities; import com.bdaum.zoom.css.CSSProperties; import com.bdaum.zoom.css.ZColumnLabelProvider; import com.bdaum.zoom.css.internal.CssActivator; import com.bdaum.zoom.image.ImageUtilities; import com.bdaum.zoom.net.core.ftp.FtpAccount; import com.bdaum.zoom.net.core.job.TransferJob; import com.bdaum.zoom.operations.internal.gen.AbstractGalleryGenerator; import com.bdaum.zoom.operations.jobs.WebGalleryJob; import com.bdaum.zoom.ui.AssetSelection; import com.bdaum.zoom.ui.Ui; import com.bdaum.zoom.ui.dialogs.AcousticMessageDialog; import com.bdaum.zoom.ui.dialogs.ZTitleAreaDialog; import com.bdaum.zoom.ui.internal.HelpContextIds; import com.bdaum.zoom.ui.internal.Icons; import com.bdaum.zoom.ui.internal.UiActivator; import com.bdaum.zoom.ui.internal.UiUtilities; import com.bdaum.zoom.ui.internal.dialogs.EditStoryBoardDialog; import com.bdaum.zoom.ui.internal.dialogs.EditWebExibitDialog; import com.bdaum.zoom.ui.internal.dialogs.SaveTemplateDialog; import com.bdaum.zoom.ui.internal.dialogs.SelectWebExhibitDialog; import com.bdaum.zoom.ui.internal.dialogs.WebGalleryEditDialog; import com.bdaum.zoom.ui.internal.hover.IHoverContext; import com.bdaum.zoom.ui.internal.job.DecorateJob; import com.bdaum.zoom.ui.internal.operations.ExhibitionPropertiesOperation; import com.bdaum.zoom.ui.internal.operations.WebGalleryPropertiesOperation; import com.bdaum.zoom.ui.internal.views.SlideshowView.PSlide; import com.bdaum.zoom.ui.internal.widgets.GalleryPanEventHandler; import com.bdaum.zoom.ui.internal.widgets.GreekedPSWTText; import com.bdaum.zoom.ui.internal.widgets.IAugmentedTextField; import com.bdaum.zoom.ui.internal.widgets.PPanel; import com.bdaum.zoom.ui.internal.widgets.PSWTAssetThumbnail; import com.bdaum.zoom.ui.internal.widgets.PSWTButton; import com.bdaum.zoom.ui.internal.widgets.TextEventHandler; import com.bdaum.zoom.ui.internal.widgets.TextField; import com.bdaum.zoom.ui.internal.widgets.ZPSWTImage; @SuppressWarnings("restriction") public class WebGalleryView extends AbstractPresentationView implements IHoverContext { public class SelectStoryBoardDialog extends ZTitleAreaDialog { private String title; private String msg; private Collection<Storyboard> input; private TableViewer viewer; private Storyboard selected; public SelectStoryBoardDialog(Shell parentShell, String title, String msg, Collection<Storyboard> input) { super(parentShell); this.title = title; this.msg = msg; this.input = input; } @Override public void create() { super.create(); setTitle(title); setMessage(msg); updateButtons(); } @Override protected Control createDialogArea(Composite parent) { Composite area = (Composite) super.createDialogArea(parent); Composite composite = new Composite(area, SWT.NONE); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); composite.setLayout(new FillLayout()); viewer = new TableViewer(composite, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER); viewer.setContentProvider(ArrayContentProvider.getInstance()); viewer.setLabelProvider(new ZColumnLabelProvider() { @Override public String getText(Object element) { if (element instanceof Storyboard) return ((Storyboard) element).getTitle(); return super.getText(element); } }); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateButtons(); } }); viewer.setInput(input); return area; } private void updateButtons() { getButton(OK).setEnabled(!viewer.getSelection().isEmpty()); } @Override protected void okPressed() { selected = (Storyboard) viewer.getStructuredSelection().getFirstElement(); super.okPressed(); } public Storyboard getResult() { return selected; } } private static final Point DRAGTOLERANCE = new Point(25, 25); private static final java.awt.Rectangle RECT1 = new java.awt.Rectangle(0, 0, 1, 1); public class DeleteStoryboardOperation extends AbstractOperation { private PStoryboard pStoryboard; private Storyboard storyboard; private double y; private ArrayList<WebExhibitImpl> deletedExhibits; public DeleteStoryboardOperation(PStoryboard pStoryboard) { super(Messages.getString("WebGalleryView.delete_storyboard_undo")); //$NON-NLS-1$ this.pStoryboard = pStoryboard; this.y = pStoryboard.getOffset().getY(); this.storyboard = pStoryboard.getStoryboard(); } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl show = getGallery(); if (show != null) { show.removeStoryboard(storyboard); List<Object> toBeDeleted = new ArrayList<Object>(storyboard.getExhibit().size() + 1); List<String> assetIds = new ArrayList<String>(storyboard.getExhibit().size()); deletedExhibits = new ArrayList<WebExhibitImpl>(storyboard.getExhibit().size()); for (WebExhibitImpl obj : Core.getCore().getDbManager().obtainByIds(WebExhibitImpl.class, storyboard.getExhibit())) { toBeDeleted.add(obj); deletedExhibits.add(obj); assetIds.add(obj.getAsset()); } toBeDeleted.add(storyboard); storeSafelyAndUpdateIndex(toBeDeleted, show, assetIds); Point2D offset = pStoryboard.getOffset(); double ydiff = pStoryboard.getHeight() + 15; surface.removeChild(pStoryboard); ListIterator<?> it = surface.getChildrenIterator(); while (it.hasNext()) { Object obj = it.next(); if (obj instanceof PStoryboard) { PStoryboard w = (PStoryboard) obj; if (w.getOffset().getY() > offset.getY()) w.offset(0, -ydiff); } } storyMap.remove(storyboard.getStringId()); setPanAndZoomHandlers(); updateStatusLine(); } return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl show = getGallery(); if (show != null) { show.addStoryboard(storyboard); pStoryboard = addStoryboard(storyboard, y, null); setColor(canvas); List<Object> tobeStored = new ArrayList<Object>(deletedExhibits.size() + 2); List<String> assetIds = new ArrayList<String>(deletedExhibits.size()); for (WebExhibitImpl exhibit : deletedExhibits) { tobeStored.add(exhibit); assetIds.add(exhibit.getAsset()); } tobeStored.add(storyboard); tobeStored.add(show); storeSafelyAndUpdateIndex(null, tobeStored, assetIds); updateStatusLine(); } return Status.OK_STATUS; } } public class CreateStoryboardOperation extends AbstractOperation { private final Storyboard storyboard; private final int y; private PStoryboard added; public CreateStoryboardOperation(Storyboard storyboard, int y) { super(Messages.getString("WebGalleryView.create_storyboard_undo")); //$NON-NLS-1$ this.storyboard = storyboard; this.y = y; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl show = getGallery(); if (show != null) { show.addStoryboard(storyboard); added = addStoryboard(storyboard, y, null); setColor(canvas); List<Object> toBeStored = new ArrayList<Object>(2); toBeStored.add(storyboard); toBeStored.add(show); storeSafelyAndUpdateIndex(null, toBeStored, null); updateStatusLine(); return Status.OK_STATUS; } return Status.CANCEL_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl show = getGallery(); if (show != null) { show.removeStoryboard(storyboard); storeSafelyAndUpdateIndex(storyboard, show, null); Point2D offset = added.getOffset(); double ydiff = added.getHeight() + 15; surface.removeChild(added); for (ListIterator<?> it = surface.getChildrenIterator(); it.hasNext();) { Object obj = it.next(); if (obj instanceof PStoryboard) if (((PStoryboard) obj).getOffset().getY() > offset.getY()) ((PStoryboard) obj).offset(0, -ydiff); } storyMap.remove(storyboard.getStringId()); setPanAndZoomHandlers(); updateStatusLine(); } return Status.OK_STATUS; } } public static class EditStoryboardOperation extends AbstractOperation { private final StoryboardImpl storyboard; private final StoryboardImpl backup; private StoryboardImpl redo; private final PStoryboard pstoryboard; public EditStoryboardOperation(StoryboardImpl storyboard, StoryboardImpl backup, PStoryboard pstoryboard) { super(Messages.getString("WebGalleryView.edit_storyboard_undo")); //$NON-NLS-1$ this.storyboard = storyboard; this.backup = backup; this.pstoryboard = pstoryboard; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { Core.getCore().getDbManager().safeTransaction(null, storyboard); pstoryboard.setTitle(storyboard.getTitle()); return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { storyboard.setTitle(redo.getTitle()); storyboard.setSequenceNo(redo.getSequenceNo()); storyboard.setDescription(redo.getDescription()); storyboard.setImageSize(redo.getImageSize()); storyboard.setEnlargeSmall(redo.getEnlargeSmall()); storyboard.setShowCaptions(redo.getShowCaptions()); storyboard.setShowDescriptions(redo.getShowDescriptions()); storyboard.setShowExif(redo.getShowExif()); return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { redo = new StoryboardImpl(storyboard.getTitle(), storyboard.getSequenceNo(), storyboard.getHtmlDescription(), storyboard.getDescription(), storyboard.getImageSize(), storyboard.getEnlargeSmall(), storyboard.getShowCaptions(), storyboard.getShowDescriptions(), storyboard.getShowExif()); storyboard.setTitle(backup.getTitle()); storyboard.setSequenceNo(backup.getSequenceNo()); storyboard.setDescription(backup.getDescription()); storyboard.setImageSize(backup.getImageSize()); storyboard.setEnlargeSmall(backup.getEnlargeSmall()); storyboard.setShowCaptions(backup.getShowCaptions()); storyboard.setShowDescriptions(backup.getShowDescriptions()); storyboard.setShowExif(backup.getShowExif()); return execute(monitor, info); } } public static class EditStoryboardTextOperation extends AbstractOperation { public static final int CAPTION = 0; public static final int DESCRIPTION = 1; public static final int CREDITS = 2; public static final int DATE = 3; private final Storyboard storyboard; private final String text; private String oldtext; private final IAugmentedTextField textField; public EditStoryboardTextOperation(Storyboard storyboard, TextField textField) { super(Messages.getString("WebGalleryView.edit_storyboard_title_undo")); //$NON-NLS-1$ this.storyboard = storyboard; this.text = textField.getText(); this.textField = textField; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { oldtext = storyboard.getTitle(); doSetText(text); return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { doSetText(text); textField.setText(text); return Status.OK_STATUS; } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { doSetText(oldtext); textField.setText(oldtext); return Status.OK_STATUS; } private void doSetText(String t) { storyboard.setTitle(t); final IDbManager dbManager = Core.getCore().getDbManager(); dbManager.safeTransaction(() -> dbManager.store(storyboard)); } } public class EditTextOperation extends AbstractOperation { public static final int CAPTION = 0; public static final int DESCRIPTION = 1; private final WebExhibitImpl exhibit; private final String text; private String oldtext; private final IAugmentedTextField textField; private final int type; public EditTextOperation(WebExhibitImpl exhibit, String text, IAugmentedTextField textField, int type) { super(Messages.getString("WebGalleryView.edit_exh_undo")); //$NON-NLS-1$ this.exhibit = exhibit; this.text = text; this.textField = textField; this.type = type; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { switch (type) { case CAPTION: oldtext = exhibit.getCaption(); break; case DESCRIPTION: oldtext = exhibit.getDescription(); break; } doSetText(text); return Status.OK_STATUS; } private void doSetText(String t) { boolean changed = false; switch (type) { case CAPTION: changed = exhibit.getCaption() == null || !exhibit.getCaption().equals(t); exhibit.setCaption(t); break; case DESCRIPTION: changed = exhibit.getDescription() == null || !exhibit.getDescription().equals(t); exhibit.setDescription(t); break; } if (changed) storeSafelyAndUpdateIndex(null, exhibit, exhibit.getAsset()); } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { doSetText(text); doSetTextField(text); return Status.OK_STATUS; } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { doSetText(oldtext); doSetTextField(oldtext); return Status.OK_STATUS; } private void doSetTextField(String t) { textField.setText(t); } } public class EditExhibitOperation extends AbstractOperation { private final PWebExhibit pexhibit; private final WebExhibitImpl exhibit; private WebExhibitImpl redo; private WebExhibitImpl backup; private boolean indexChange; public EditExhibitOperation(PWebExhibit pexhibit, WebExhibitImpl backup, WebExhibitImpl exhibit) { super(Messages.getString("ExhibitionView.change_exh_size_pos_undo")); //$NON-NLS-1$ this.pexhibit = pexhibit; this.backup = backup; this.exhibit = exhibit; String backupDescription = Utilities.getPlainDescription(backup); indexChange = (backup.getCaption() == null || !backup.getCaption().equals(exhibit.getCaption()) || backupDescription == null || !backupDescription.equals(Utilities.getPlainDescription(exhibit)) || backup.getAltText() == null || !backup.getAltText().equals(exhibit.getAltText())); } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { pexhibit.invalidatePaint(); storeSafelyAndUpdateIndex(null, exhibit, indexChange ? exhibit.getAsset() : null); return Status.OK_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { exhibit.setCaption(redo.getCaption()); exhibit.setSequenceNo(redo.getSequenceNo()); exhibit.setDescription(redo.getDescription()); exhibit.setAltText(redo.getAltText()); exhibit.setDownloadable(redo.getDownloadable()); exhibit.setIncludeMetadata(redo.getIncludeMetadata()); exhibit.setAsset(redo.getAsset()); return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { redo = new WebExhibitImpl(exhibit.getCaption(), exhibit.getSequenceNo(), exhibit.getDescription(), exhibit.getHtmlDescription(), exhibit.getAltText(), exhibit.getDownloadable(), exhibit.getIncludeMetadata(), exhibit.getAsset()); exhibit.setCaption(backup.getCaption()); exhibit.setSequenceNo(backup.getSequenceNo()); exhibit.setDescription(backup.getDescription()); exhibit.setAltText(backup.getAltText()); exhibit.setDownloadable(backup.getDownloadable()); exhibit.setIncludeMetadata(backup.getIncludeMetadata()); exhibit.setAsset(backup.getAsset()); return Status.OK_STATUS; } } public class MoveExhibitOperation extends AbstractOperation { private final PWebExhibit moved; private final Point2D newOffset; private PStoryboard oldStoryboard; private int oldSeqno; public MoveExhibitOperation(PWebExhibit moved, Point2D newOffset) { super(Messages.getString("WebGalleryView.move_exh_undo")); //$NON-NLS-1$ this.moved = moved; this.newOffset = newOffset; this.oldSeqno = moved.exhibit.getSequenceNo(); } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { final WebGallery gal = getGallery(); if (gal != null) { PWebExhibit target = (PWebExhibit) findExhibit(newOffset); if (target != null) { List<Storyboard> storyboards = new ArrayList<>(2); String sbid = target.exhibit.getStoryboard_exhibit_parent(); PStoryboard targetpStoryboard = storyMap.get(sbid); int newSeqNo = target == null ? targetpStoryboard.getChildrenCount() + 1 : target.exhibit.getSequenceNo(); sbid = moved.exhibit.getStoryboard_exhibit_parent(); oldStoryboard = storyMap.get(sbid); storyboards.add(oldStoryboard.getStoryboard()); if (oldStoryboard != targetpStoryboard) storyboards.add(targetpStoryboard.getStoryboard()); oldSeqno = moved.exhibit.getSequenceNo(); if (oldSeqno != newSeqNo || targetpStoryboard != oldStoryboard) { if (oldSeqno > newSeqNo || targetpStoryboard != oldStoryboard) ++newSeqNo; removeExhibit(oldStoryboard.getStoryboard(), oldSeqno); moved.setSequenceNo(newSeqNo); insertExhibit(targetpStoryboard.getStoryboard(), moved); for (Storyboard sb : storyboards) updateSequenceNumbers(sb); newSeqNo = moved.exhibit.getSequenceNo(); Core.getCore().getDbManager().safeTransaction(null, storyboards); updateActions(false); return Status.OK_STATUS; } } } return Status.CANCEL_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { final WebGallery gal = getGallery(); if (gal != null) { List<Storyboard> storyboards = new ArrayList<>(2); String sbid = moved.exhibit.getStoryboard_exhibit_parent(); PStoryboard sourcepStoryboard = storyMap.get(sbid); removeExhibit(sourcepStoryboard.getStoryboard(), moved.exhibit.getSequenceNo()); moved.setSequenceNo(oldSeqno); insertExhibit(oldStoryboard.getStoryboard(), moved); storyboards.add(oldStoryboard.getStoryboard()); if (oldStoryboard != sourcepStoryboard) storyboards.add(sourcepStoryboard.getStoryboard()); for (Storyboard sb : storyboards) updateSequenceNumbers(sb); Core.getCore().getDbManager().safeTransaction(null, storyboards); updateActions(false); } return Status.OK_STATUS; } } public class DeleteExhibitOperation extends AbstractOperation { private List<PWebExhibit> deleted; private boolean cut; public DeleteExhibitOperation(List<PWebExhibit> deleted, boolean cut) { super(Messages.getString("WebGalleryView.delete_exh_undo")); //$NON-NLS-1$ this.deleted = deleted; this.cut = cut; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl gal = getGallery(); if (gal != null) { if (cut && !deleted.isEmpty()) clipboard.clear(); List<IIdentifiableObject> toBeDeleted = new ArrayList<>(deleted.size()); Set<IIdentifiableObject> storyboards = new HashSet<>(deleted.size()); List<String> toBeIndexed = new ArrayList<>(deleted.size()); List<WebExhibit> clipped = null; for (int i = deleted.size() - 1; i >= 0; i--) { WebExhibitImpl exhibit = deleted.get(i).exhibit; if (cut) { if (clipped == null) clipped = new ArrayList<>(deleted.size()); clipped.add(exhibit); } toBeDeleted.add(exhibit); String sbid = exhibit.getStoryboard_exhibit_parent(); Storyboard storyboard = storyMap.get(sbid).getStoryboard(); storyboards.add(storyboard); toBeIndexed.add(exhibit.getAsset()); removeExhibit(storyboard, exhibit.getSequenceNo()); } for (IIdentifiableObject storyboard : storyboards) updateSequenceNumbers((Storyboard) storyboard); updateSelectionMarkers(); storeSafelyAndUpdateIndex(toBeDeleted, storyboards, toBeIndexed); if (clipped != null) { clipboard.clear(); clipboard.addAll(clipped); } updateActions(false); updateStatusLine(); return Status.OK_STATUS; } return Status.CANCEL_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGalleryImpl gal = getGallery(); if (gal != null) { List<IIdentifiableObject> toBeStored = new ArrayList<>(deleted.size() + 10); Set<Storyboard> storyboards = new HashSet<Storyboard>(15); List<String> toBeIndexed = new ArrayList<>(deleted.size()); for (PWebExhibit pexhibit : deleted) { WebExhibit exhibit = pexhibit.exhibit; String sbid = exhibit.getStoryboard_exhibit_parent(); Storyboard storyboard = storyMap.get(sbid).getStoryboard(); insertExhibit(storyboard, pexhibit); toBeStored.add(exhibit); toBeIndexed.add(exhibit.getAsset()); storyboards.add(storyboard); } for (Storyboard sb : storyboards) { updateSequenceNumbers(sb); toBeStored.add(sb); } storeSafelyAndUpdateIndex(null, toBeStored, toBeIndexed); updateActions(false); updateStatusLine(); } return Status.OK_STATUS; } } public class DropAssetOperation extends AbstractOperation { private final AssetSelection selection; private final Point2D position; private List<PWebExhibit> added; private PStoryboard pstoryboard; private final boolean replace; private PWebExhibit deleted; public DropAssetOperation(AssetSelection selection, Point2D position, boolean replace) { super(Messages.getString("ExhibitionView.drop_images_undo")); //$NON-NLS-1$ this.selection = selection; this.position = position; this.replace = replace; added = new ArrayList<PWebExhibit>(selection.size()); pstoryboard = findStoryboard(position); } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGallery gal = getGallery(); if (gal != null && pstoryboard != null) { Storyboard storyboard = pstoryboard.getStoryboard(); PWebExhibit target = (PWebExhibit) findExhibit(position); List<String> assetIds = new ArrayList<String>(selection.size()); int seqNo = target == null ? pstoryboard.getChildrenCount() + 1 : target.exhibit.getSequenceNo(); WebExhibit replaced = null; if (replace && target != null) { replaced = target.exhibit; assetIds.add(replaced.getAsset()); deleted = removeExhibit(storyboard, seqNo); --seqNo; } boolean cleared = false; Set<IIdentifiableObject> toBeStored = new HashSet<>(selection.size() * 2); for (Asset asset : selection) { if (!accepts(asset)) continue; if (!cleared) { clearSelection(); cleared = true; } String assetId = asset.getStringId(); int rawIx = computeSequenceNumber(position.getX() - pstoryboard.getOffset().getX()); int ix = Math.max(1, Math.min(rawIx, storyboard.getExhibit().size() + 1)); WebExhibitImpl exhibit = replaced != null ? new WebExhibitImpl(UiUtilities.createSlideTitle(asset), ix, "", //$NON-NLS-1$ replaced.getHtmlDescription(), asset.getName(), replaced.getDownloadable(), replaced.getIncludeMetadata(), assetId) : new WebExhibitImpl(UiUtilities.createSlideTitle(asset), ix, "", false, //$NON-NLS-1$ asset.getName(), true, true, assetId); replaced = null; insertIntoStoryboard(storyboard, exhibit, ix - 1); PWebExhibit pexhibit = makeExhibit(pstoryboard, exhibit); pexhibit.setSelected(true); lastSelection = recentSelection = pexhibit; added.add(pexhibit); toBeStored.add(exhibit); assetIds.add(assetId); ix++; } toBeStored.add(storyboard); updateSequenceNumbers(storyboard); storeSafelyAndUpdateIndex(null, toBeStored, assetIds); updateActions(false); updateStatusLine(); return Status.OK_STATUS; } return Status.CANCEL_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { added.clear(); return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGallery gal = getGallery(); if (gal != null) { List<IIdentifiableObject> toBeDeleted = new ArrayList<>(added.size()); Set<IIdentifiableObject> toBeStored = new HashSet<>(5); List<String> assetIds = new ArrayList<>(added.size()); for (int i = added.size() - 1; i >= 0; i--) { PWebExhibit pexhibit = added.get(i); WebExhibitImpl exhibit = pexhibit.exhibit; String sbid = exhibit.getStoryboard_exhibit_parent(); Storyboard storyboard = storyMap.get(sbid).getStoryboard(); removeExhibit(storyboard, exhibit.getSequenceNo()); toBeDeleted.add(exhibit); toBeStored.add(storyboard); assetIds.add(exhibit.getAsset()); } if (deleted != null) { String sbid = deleted.exhibit.getStoryboard_exhibit_parent(); Storyboard storyboard = storyMap.get(sbid).getStoryboard(); insertExhibit(storyboard, deleted); } updateSequenceNumbers(pstoryboard.getStoryboard()); updateSelectionMarkers(); storeSafelyAndUpdateIndex(toBeDeleted, toBeStored, assetIds); updateActions(false); updateStatusLine(); } return Status.OK_STATUS; } } public class PasteExhibitsOperation extends AbstractOperation { private Point2D position; private List<PWebExhibit> added; private PStoryboard pstoryboard; public PasteExhibitsOperation(Point2D position) { super(Messages.getString("WebGalleryView.paste_exhibits")); //$NON-NLS-1$ this.position = position; added = new ArrayList<>(clipboard.size()); pstoryboard = findStoryboard(position); } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGallery gal = getGallery(); if (gal != null && !clipboard.isEmpty() && pstoryboard != null) { PWebExhibit target = (PWebExhibit) findExhibit(position); List<String> assetIds = new ArrayList<String>(clipboard.size()); int seqNo = target == null ? pstoryboard.getChildrenCount() + 1 : target.exhibit.getSequenceNo(); if (!clipboard.isEmpty()) clearSelection(); List<IIdentifiableObject> toBeStored = new ArrayList<>(clipboard.size() + 1); for (IIdentifiableObject exhibit : clipboard) { WebExhibitImpl copy = cloneExhibit((WebExhibitImpl) exhibit); insertIntoStoryboard(pstoryboard.getStoryboard(), copy, seqNo); PWebExhibit pexhibit = makeExhibit(pstoryboard, copy); pexhibit.setSelected(true); lastSelection = recentSelection = pexhibit; added.add(pexhibit); toBeStored.add(copy); assetIds.add(copy.getAsset()); ++seqNo; } updateSequenceNumbers(pstoryboard.getStoryboard()); toBeStored.add(pstoryboard.getStoryboard()); storeSafelyAndUpdateIndex(null, toBeStored, assetIds); updateActions(false); updateStatusLine(); return Status.OK_STATUS; } return Status.CANCEL_STATUS; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { added.clear(); return execute(monitor, info); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { WebGallery gal = getGallery(); if (gal != null && pstoryboard != null) { List<IIdentifiableObject> toBeDeleted = new ArrayList<>(added.size()); List<String> assetIds = new ArrayList<String>(added.size()); Storyboard storyboard = pstoryboard.getStoryboard(); for (int i = added.size() - 1; i >= 0; i--) { PWebExhibit pexhibit = added.get(i); WebExhibitImpl exhibit = pexhibit.exhibit; removeExhibit(storyboard, exhibit.getSequenceNo()); toBeDeleted.add(exhibit); assetIds.add(exhibit.getAsset()); } updateSequenceNumbers(pstoryboard.getStoryboard()); updateSelectionMarkers(); storeSafelyAndUpdateIndex(toBeDeleted, storyboard, assetIds); updateActions(false); updateStatusLine(); } return Status.OK_STATUS; } } public Set<String> offlineImages = null; public PWebExhibit exhibitAtFront; private class GalleryDecorateJob extends DecorateJob { private Set<String> offline = new HashSet<String>(); private Color penColor; public GalleryDecorateJob() { super(Messages.getString("WebGalleryView.decorate_storyboards")); //$NON-NLS-1$ } @Override protected boolean mayRun() { return !storyMap.isEmpty(); } @Override protected void doRun(IProgressMonitor monitor) { final Display display = canvas.getDisplay(); IDbManager dbManager = Core.getCore().getDbManager(); offline.clear(); for (PStoryboard storyboard : storyMap.values()) for (Object child : storyboard.getChildrenReference().toArray()) { if (child instanceof PWebExhibit && isVisible() && mayRun()) { final PWebExhibit pexhibit = (PWebExhibit) child; WebExhibit exhibit = pexhibit.exhibit; try { String assetId = exhibit.getAsset(); if (assetId != null) { AssetImpl asset = dbManager.obtainAsset(assetId); if (asset != null) { switch (volumeManager.determineFileState(asset)) { case IVolumeManager.PEER: case IVolumeManager.REMOTE: if (remoteColor != null) penColor = remoteColor; break; case IVolumeManager.OFFLINE: if (offlineColor != null) penColor = offlineColor; String volume = asset.getVolume(); offline.add((volume == null) ? "" : volume); //$NON-NLS-1$ break; default: penColor = titleForegroundColor; break; } if (penColor != null && !display.isDisposed() && !((PWebExhibit) child).caption.getPenColor().equals(penColor)) display.asyncExec(() -> { if (!canvas.isDisposed()) pexhibit.caption.setPenColor(penColor); }); } } } catch (Exception e) { // just ignore } } if (monitor.isCanceled()) break; } offlineImages = offline; } } @SuppressWarnings("serial") public class PWebExhibit extends PPresentationItem { private WebExhibitImpl exhibit; private TextField description; private PSWTButton propButton; private GreekedPSWTText seqNo; public PWebExhibit(final PSWTCanvas canvas, PStoryboard pstoryboard, WebExhibitImpl exhibit, int y) { this.exhibit = exhibit; setPickable(false); // Image pImage = new PSWTAssetThumbnail(canvas, WebGalleryView.this, Core.getCore().getDbManager().obtainAsset(exhibit.getAsset())); PBounds bounds = pImage.getBoundsReference(); addChild(pImage); configureImage(); setBounds(0, 0, CELLSIZE, STORYBOARDHEIGHT); // select frame pImage.addChild(createSelectionFrame(bounds)); // prop button Image propImage = Icons.smallProperties.getImage(); propButton = new PSWTButton(canvas, propImage, Messages.getString("WebGalleryView.slide_properties")); //$NON-NLS-1$ Rectangle propbounds = propImage.getBounds(); propButton.setOffset(STORYBOARDMARGINS, IMAGESIZE + CSIZE); addChild(propButton); // Seqno Color strokePaint = (Color) pstoryboard.getStrokePaint(); seqNo = new GreekedPSWTText(createSequenceNo(exhibit), new Font("Arial", //$NON-NLS-1$ Font.BOLD, 9)); seqNo.setGreekThreshold(5); seqNo.setTransparent(true); seqNo.setPenColor(strokePaint); int textHorMargins = 2 * STORYBOARDMARGINS + propbounds.width; int textYPos = IMAGESIZE + CSIZE; seqNo.setOffset(textHorMargins, textYPos); seqNo.setPickable(true); addChild(seqNo); // caption caption = createTextLine(this, exhibit.getCaption(), 5, (int) (IMAGESIZE - 2 * textHorMargins - seqNo.getWidth()), (int) (textHorMargins + seqNo.getWidth()), textYPos, titleForegroundColor, null, CAPTIONFONT, ISpellCheckingService.TITLEOPTIONS, SWT.SINGLE); // legend description = createTextLine(this, getDescription(exhibit), 5, IMAGESIZE - 2 * textHorMargins - 2 * CSIZE, textHorMargins + CSIZE, textYPos + 2 * CSIZE, foregroundColor, null, DESCRIPTIONFONT, ISpellCheckingService.DESCRIPTIONOPTIONS, SWT.SINGLE); // position and bounds setOffset(0, y); installHandleEventHandlers(pImage, false, false, this); addInputEventListener(new PBasicInputEventHandler() { @Override public void mousePressed(PInputEvent event) { setPickedNode(event.getPickedNode()); if (getAdapter(IPresentationItem.class) instanceof PSlide) event.getPickedNode().raiseToTop(); } @Override public void mouseReleased(PInputEvent event) { PNode pickedNode = getPickedNode(); if (pickedNode == propButton || pickedNode == seqNo || event.getClickCount() == 1) editExhibitProperties(); } }); pImage.addInputEventListener(new PBasicInputEventHandler() { @Override public void mousePressed(PInputEvent event) { PNode pickedNode = event.getPickedNode(); setPickedNode(pickedNode); if (event.isLeftMouseButton() && !event.isShiftDown() && !event.isAltDown() && (pickedNode instanceof PSWTAssetThumbnail)) selectExhibit((PWebExhibit) pickedNode.getParent(), event.getModifiers(), event.getClickCount()); } }); } @Override public void raiseToTop() { super.raiseToTop(); if (exhibitAtFront != null) exhibitAtFront.description.setPenColor(foregroundColor); exhibitAtFront = this; description.setPenColor(selectionForegroundColor); } @Override public void lowerToBottom() { super.lowerToBottom(); if (exhibitAtFront == this) exhibitAtFront = null; description.setPenColor(foregroundColor); } private void editExhibitProperties() { doEditExhibitProperties(PWebExhibit.this); } private void setCaptionAndDescription(WebExhibit exh) { caption.setText(exh.getCaption()); description.setText(getDescription(exh)); description.setSpellingOptions(10, exh.getHtmlDescription() ? ISpellCheckingService.NOSPELLING : ISpellCheckingService.DESCRIPTIONOPTIONS); } private String getDescription(WebExhibit exh) { String des = exh.getDescription(); if (des != null && !des.isEmpty()) return des; return Messages.getString("WebGalleryView.description"); //$NON-NLS-1$ } public void processTextEvent(TextField focus) { String text = focus.getText(); int type = -1; if (focus == caption) { if (!text.equals(exhibit.getCaption())) type = EditTextOperation.CAPTION; } else if (focus == description && !text.equals(exhibit.getDescription())) type = EditTextOperation.DESCRIPTION; if (type >= 0) performOperation(new EditTextOperation(exhibit, text, focus, type)); } public void update(WebExhibit exh, Asset asset) { removeChild(pImage); pImage.getImage().dispose(); Image image = ImageUtilities.loadThumbnail(canvas.getDisplay(), asset.getJpegThumbnail(), Ui.getUi().getDisplayCMS(), SWT.IMAGE_JPEG, true); images.add(image); pImage = new ZPSWTImage(canvas, image); addChild(0, pImage); configureImage(); pImage.lowerToBottom(); setCaptionAndDescription(exh); } private void configureImage() { pImage.setPickable(true); PBounds bounds = pImage.getBoundsReference(); double width = bounds.getWidth(); double height = bounds.getHeight(); double scale = Math.min(IMAGESIZE / width, IMAGESIZE / height); pImage.setOffset(STORYBOARDMARGINS + ((IMAGESIZE - width * scale) / 2), STORYBOARDMARGINS + ((IMAGESIZE - height * scale) / 2)); pImage.scale(scale); } public void setSequenceNo(int no) { exhibit.setSequenceNo(no); seqNo.setText(createSequenceNo(exhibit)); Rectangle propbounds = propButton.getImage().getBounds(); caption.setOffset(2 * STORYBOARDMARGINS + propbounds.width + seqNo.getWidth(), caption.getOffset().getY()); setOffset((no - 1) * CELLSIZE + 2 * LARGEBUTTONSIZE, 0); } private String createSequenceNo(WebExhibit exh) { return exh.getSequenceNo() + " - "; //$NON-NLS-1$ } public void setPenColor(Color color) { seqNo.setPenColor(color); description.setPenColor(color); description.setSelectedBgColor(selectionBackgroundColor); } public void setBackgroundColor(Color color) { description.setBackgroundColor(color); } public void setTitleColor(Color color) { caption.setPenColor(color); caption.setSelectedBgColor(selectionBackgroundColor); } public String getAssetId() { return exhibit.getAsset(); } } @SuppressWarnings("serial") public class PStoryboard extends PPanel { public PStoryboard(Storyboard storyboard) { super(storyboard, STORYBOARDWIDTH, STORYBOARDHEIGHT); // buttons deleteButton = createButton(canvas, Icons.largeDelete, Messages.getString("WebGalleryView.delete_storyboard")); //$NON-NLS-1$ Rectangle bounds = deleteButton.getImage().getBounds(); deleteButton.setOffset(STORYBOARDMARGINS, STORYBOARDHEIGHT - (bounds.height / 2 + STORYBOARDMARGINS)); propButton = createButton(canvas, Icons.largeProperties, Messages.getString("WebGalleryView.storyboard_properties")); //$NON-NLS-1$ bounds = propButton.getImage().getBounds(); propButton.setOffset(STORYBOARDMARGINS, STORYBOARDHEIGHT - 2 * (bounds.height / 2 + STORYBOARDMARGINS)); // Title createTitle(canvas, storyboard.getTitle(), STORYBOARDMARGINS, STORYBOARDMARGINS, titleForegroundColor, (Color) getPaint(), 18); setPickable(true); } public Storyboard getStoryboard() { return (Storyboard) data; } public void setStoryboard(StoryboardImpl storyboard) { this.data = storyboard; } @Override public void setPaint(Paint newPaint) { super.setPaint(newPaint); for (ListIterator<?> it = getChildrenIterator(); it.hasNext();) { Object child = it.next(); if (child instanceof TextField) ((TextField) child).setBackgroundColor((Color) newPaint); else if (child instanceof PWebExhibit) ((PWebExhibit) child).setBackgroundColor((Color) newPaint); } } @Override public void setStrokeColor(Paint strokeColor) { super.setStrokeColor(strokeColor); for (ListIterator<?> it = getChildrenIterator(); it.hasNext();) { Object child = it.next(); if (child instanceof PSWTText) ((PSWTText) child).setPenColor((Color) strokeColor); else if (child instanceof TextField) { ((TextField) child).setPenColor((Color) strokeColor); ((TextField) child).setSelectedBgColor(selectionBackgroundColor); } else if (child instanceof PWebExhibit) { ((PWebExhibit) child).setPenColor(foregroundColor); ((PWebExhibit) child).setTitleColor(titleForegroundColor); } } } /* * (non-Javadoc) * * @see com.bdaum.zoom.ui.views.PTextHandler#processTextEvent(com.bdaum.zoom * .ui.widgets.TextField) */ public void processTextEvent(TextField focus) { Storyboard storyboard = getStoryboard(); if (!focus.getText().equals(storyboard.getTitle())) performOperation(new EditStoryboardTextOperation(storyboard, focus)); } public void updateColors() { Color color = (Color) getPaint(); for (ListIterator<?> it = getChildrenIterator(); it.hasNext();) { PNode child = (PNode) it.next(); if (child instanceof PWebExhibit) ((PWebExhibit) child).updateColors(color); } } @Override protected void deletePressed() { setPickedNode(PStoryboard.this); deleteStoryboardAction.run(); } @Override protected void propertiesPressed() { setPickedNode(PStoryboard.this); editStoryboardAction.run(); } } public static final String ID = "com.bdaum.zoom.ui.WebGalleryView"; //$NON-NLS-1$ public static final String WEBGALLERY_PERSPECTIVE = "com.bdaum.zoom.PresentationPerspective"; //$NON-NLS-1$ private static final String LAST_GALLERY = "com.bdaum.zoom.lastGallery"; //$NON-NLS-1$ private static final int STORYBOARDWIDTH = 1500; private static final int CELLSIZE = 250; private static final int STORYBOARDMARGINS = 5; private static final int CSIZE = 12; private static final int STORYBOARDHEIGHT = CELLSIZE + 5 * CSIZE; private static final int IMAGESIZE = CELLSIZE - 2 * STORYBOARDMARGINS; protected static final int STORYBOARDDIST = STORYBOARDHEIGHT + CSIZE; private static final int LARGEBUTTONSIZE = 64; private Map<String, PStoryboard> storyMap = new HashMap<>(13); private Map<String, PWebExhibit> exhibitMap = new HashMap<>(521); protected Color wallPaint = new Color(255, 255, 250); protected static final Font CAPTIONFONT = new Font("Arial", Font.BOLD, 9); //$NON-NLS-1$ protected static final Font DESCRIPTIONFONT = new Font("Arial", Font.PLAIN, 9); //$NON-NLS-1$ private WebGalleryImpl gallery; private Action addStoryBoardAction; private Action generateAction; private Action saveAction; private Action deleteStoryboardAction; private Action editStoryboardAction; @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); if (memento != null) { WebGalleryImpl obj = Core.getCore().getDbManager().obtainById(WebGalleryImpl.class, memento.getString(LAST_GALLERY)); if (obj != null) setGallery(obj); } } public WebExhibitImpl cloneExhibit(WebExhibitImpl original) { return new WebExhibitImpl(original.getCaption(), original.getSequenceNo(), original.getDescription(), original.getHtmlDescription(), original.getAltText(), original.getDownloadable(), original.getDownloadable(), original.getAsset()); } @Override public void saveState(IMemento memento) { if (memento != null && gallery != null) memento.putString(LAST_GALLERY, gallery.getStringId()); super.saveState(memento); } private void setGallery(WebGalleryImpl gallery) { this.gallery = gallery; if (gallery.getStoryboard().isEmpty()) gallery.addStoryboard( new StoryboardImpl(Messages.getString("WebGalleryView.storyboard_1"), 1, false, "", //$NON-NLS-1$ //$NON-NLS-2$ 0, false, true, true, true)); } @Override protected String createHoverText(PNode thumbnail) { PNode parent = thumbnail.getParent(); if (parent instanceof PWebExhibit) return UiActivator.getDefault().getHoverManager().getHoverText( "com.bdaum.zoom.ui.hover.webexhibition.exhibit", ((PWebExhibit) parent).exhibit, this); //$NON-NLS-1$ return ""; //$NON-NLS-1$ } @Override protected String createHoverTitle(PNode thumbnail) { PNode parent = thumbnail.getParent(); if (parent instanceof PWebExhibit) return UiActivator.getDefault().getHoverManager().getHoverTitle( "com.bdaum.zoom.ui.hover.webexhibition.exhibit", ((PWebExhibit) parent).exhibit, this); //$NON-NLS-1$ return ""; //$NON-NLS-1$ } @Override public void createPartControl(Composite parent) { super.createPartControl(parent); canvas.setData(CSSProperties.ID, CSSProperties.WEBGALLERY); undoContext = new UndoContext() { @Override public String getLabel() { return Messages.getString("WebGalleryView.webgallery_undo_context"); //$NON-NLS-1$ } }; // Setup setupGallery(getViewSite(), gallery); setColor(canvas); addWheelListener(0.1d, 10d); textEventHandler = new TextEventHandler(selectionBackgroundColor); PBasicInputEventHandler eventHandler = new PBasicInputEventHandler() { private boolean dragged; @Override public void keyPressed(PInputEvent event) { if (textEventHandler.hasFocus()) textEventHandler.keyPressed(event); else pan(event); } @Override public void mouseMoved(PInputEvent event) { currentMousePosition = event.getPosition(); } @Override public void mousePressed(PInputEvent event) { dragged = false; setPickedNode(event.getPickedNode()); } @Override public void mouseDragged(PInputEvent event) { dragged = true; textEventHandler.mouseDragged(event); } @Override public void mouseReleased(PInputEvent event) { positionX = null; if (!dragged) { textEventHandler.mouseReleased(event); if (event.getClickCount() == 2) toggleTransform(event.getCamera()); else if (event.isRightMouseButton()) { positionX = event.getPosition(); positionRelativeToCamera = event.getPositionRelativeTo(canvas.getCamera()); } else if (event.isControlDown()) { PNode picked = getPickedNode(); if (picked == surface) propertiesAction.run(); else if (picked instanceof PStoryboard) editStoryboardAction.run(); } } } }; canvas.getRoot().getDefaultInputManager().setKeyboardFocus(eventHandler); canvas.addInputEventListener(eventHandler); setPanAndZoomHandlers(); // Create the help context id for the viewer's control PlatformUI.getWorkbench().getHelpSystem().setHelp(canvas, HelpContextIds.WEBGALLERY_VIEW); // Drop support addDropListener(canvas); // Hover installHoveringController(); // Actions makeActions(); installListeners(); hookContextMenu(); contributeToActionBars(); if (gallery != null) setInput(gallery); addCatalogListener(); setDecorator(canvas, new GalleryDecorateJob()); updateActions(false); } @Override protected void fillLocalToolBar(IToolBarManager manager) { super.fillLocalToolBar(manager); manager.add(addStoryBoardAction); manager.add(new Separator()); manager.add(generateAction); manager.add(saveAction); } @Override protected void fillLocalPullDown(IMenuManager manager) { manager.add(addStoryBoardAction); manager.add(new Separator()); manager.add(generateAction); manager.add(saveAction); super.fillLocalPullDown(manager); } @Override protected void fillContextMenu(IMenuManager manager) { updateActions(true); boolean writable = !dbIsReadonly(); PNode pickedNode = getPickedNode(); if (pickedNode != null && pickedNode.getParent() instanceof PWebExhibit) { if (writable) { manager.add(cutAction); manager.add(new Separator()); } addCommonContextActions(manager); } else { if (pickedNode != null && pickedNode.getParent() instanceof PStoryboard) pickedNode = pickedNode.getParent(); if (pickedNode instanceof PStoryboard) { if (writable) manager.add(pasteAction); manager.add(new Separator()); manager.add(editStoryboardAction); manager.add(deleteStoryboardAction); } } manager.add(new Separator()); manager.add(gotoExhibitAction); if (gotoLastSelectedAction.isEnabled()) manager.add(gotoLastSelectedAction); super.fillContextMenu(manager); } @Override protected void updatePresentation(Collection<? extends Asset> assets) { Map<String, Asset> amap = new HashMap<String, Asset>(assets.size()); for (Asset a : assets) amap.put(a.getStringId(), a); for (PStoryboard pstoryboard : storyMap.values()) for (ListIterator<?> it = pstoryboard.getChildrenIterator(); it.hasNext();) { Object next = it.next(); if (next instanceof PWebExhibit) { PWebExhibit pexhibit = (PWebExhibit) next; Asset asset = amap.get(pexhibit.getAssetId()); if (asset != null) { pexhibit.update(pexhibit.exhibit, asset); break; } } } } @Override public void updateActions(boolean force) { if (addStoryBoardAction != null && (isVisible() || force)) { boolean hasGallery = gallery != null; addStoryBoardAction.setEnabled(hasGallery && !dbIsReadonly()); propertiesAction.setEnabled(hasGallery); saveAction.setEnabled(hasGallery); generateAction.setEnabled(hasGallery); gotoExhibitAction.setEnabled(hasGallery); super.updateActions(force); } } private void setupGallery(IViewSite site, WebGalleryImpl gallery) { if (gallery != null) { int h = Math.max(2, gallery.getStoryboard().size()) * STORYBOARDDIST; surface.setBounds(-3000d, -3000d, (STORYBOARDWIDTH + 6000d), (h + 6000d)); surface.setScale(site.getShell().getDisplay().getPrimaryMonitor().getBounds().height / (2d * h)); } } @Override protected void cleanUp() { try { for (PStoryboard pstoryboard : storyMap.values()) { pstoryboard.removeAllChildren(); PNode parent = pstoryboard.getParent(); if (parent != null) parent.removeChild(pstoryboard); } } catch (SWTException e) { // do nothing } storyMap.clear(); super.cleanUp(); } @Override protected void setColor(Control control) { CssActivator.getDefault().applyExtendedStyle(control, this); surface.setPaint(wallPaint = UiUtilities.getAwtBackground(control, null)); for (PStoryboard pstoryboard : storyMap.values()) { pstoryboard.setPaint(wallPaint); pstoryboard.setStrokeColor(selectionBackgroundColor); } } @Override protected void makeActions() { super.makeActions(); propertiesAction = new Action(Messages.getString("WebGalleryView.gallery_properties"), //$NON-NLS-1$ Icons.webGallery.getDescriptor()) { @Override public void run() { WebGalleryImpl show = getGallery(); if (show == null) return; WebGalleryImpl backup = WebGalleryPropertiesOperation.cloneGallery(show); show = WebGalleryEditDialog.openWebGalleryEditDialog(getSite().getShell(), null, show, show.getName(), false, true, null); if (show != null) { performOperation(new WebGalleryPropertiesOperation(backup, gallery = show)); setInput(gallery); } } }; propertiesAction.setToolTipText(Messages.getString("WebGalleryView.gallery_properties_tooltip")); //$NON-NLS-1$ addStoryBoardAction = new Action(Messages.getString("WebGalleryView.add_storyboard"), //$NON-NLS-1$ Icons.add.getDescriptor()) { @Override public void run() { WebGalleryImpl show = getGallery(); if (show == null) return; int l = show.getStoryboard().size(); EditStoryBoardDialog dialog = new EditStoryBoardDialog(getSite().getShell(), show, null, NLS.bind("Storyboard {0}", l + 1)); //$NON-NLS-1$ if (dialog.open() == Window.OK) performOperation(new CreateStoryboardOperation(dialog.getResult(), 10 + l * STORYBOARDDIST)); } }; addStoryBoardAction.setToolTipText(Messages.getString("WebGalleryView.add_storyboard_tooltip")); //$NON-NLS-1$ generateAction = new Action(Messages.getString("WebGalleryView.generate"), Icons.play.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { generate(false); } }; generateAction.setToolTipText(Messages.getString("WebGalleryView.generate_tooltip")); //$NON-NLS-1$ saveAction = new Action(Messages.getString("WebGalleryView.save_design"), Icons.save.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { generate(true); } }; saveAction.setToolTipText(Messages.getString("WebGalleryView.generate_web_gallery")); //$NON-NLS-1$ gotoExhibitAction = new Action(Messages.getString("WebGalleryView.goto_exhibit")) { //$NON-NLS-1$ @Override public void run() { WebGallery gal = getGallery(); if (gal != null) { List<WebExhibitImpl> exhibits = getAllExhibits(gal); SelectWebExhibitDialog dialog = new SelectWebExhibitDialog(getSite().getShell(), exhibits); dialog.create(); org.eclipse.swt.graphics.Point pos = canvas.toDisplay((int) positionRelativeToCamera.getX(), (int) positionRelativeToCamera.getY()); pos.x += 10; pos.y += 10; dialog.getShell().setLocation(pos); if (dialog.open() == Window.OK) revealExhibit(dialog.getResult()); } } private List<WebExhibitImpl> getAllExhibits(WebGallery gal) { List<WebExhibitImpl> exhibits = new ArrayList<WebExhibitImpl>(300); for (Storyboard sb : gal.getStoryboard()) { for (String id : sb.getExhibit()) { PWebExhibit pexhibit = exhibitMap.get(id); exhibits.add(pexhibit.exhibit); } } return exhibits; } }; gotoExhibitAction.setToolTipText(Messages.getString("WebGalleryView.goto_exhibit_tooltip")); //$NON-NLS-1$ deleteStoryboardAction = new Action(Messages.getString("WebGalleryView.delete_storyboard"), //$NON-NLS-1$ Icons.delete.getDescriptor()) { @Override public void run() { if (getPickedNode() instanceof PStoryboard && AcousticMessageDialog.openQuestion( getSite().getShell(), Messages.getString("WebGalleryView.remove_storyboard"), //$NON-NLS-1$ Messages.getString("WebGalleryView.do_you_really_want_to_remove"))) //$NON-NLS-1$ performOperation(new DeleteStoryboardOperation((PStoryboard) getPickedNode())); } }; deleteStoryboardAction.setToolTipText(Messages.getString("WebGalleryView.delete_storyboard_tooltip")); //$NON-NLS-1$ editStoryboardAction = new Action(Messages.getString("WebGalleryView.edit_storyboard"), //$NON-NLS-1$ Icons.properties_blue.getDescriptor()) { @Override public void run() { if (getPickedNode() instanceof PStoryboard) { textEventHandler.commit(); editStoryboardLegend((PStoryboard) getPickedNode()); } } }; editStoryboardAction.setToolTipText(Messages.getString("WebGalleryView.edit_storyboard_tooltip")); //$NON-NLS-1$ exhibitPropertiesAction = new Action(Messages.getString("WebGalleryView.properties")) { //$NON-NLS-1$ @Override public void run() { doEditExhibitProperties((PWebExhibit) getAdapter(IPresentationItem.class)); } }; exhibitPropertiesAction.setToolTipText(Messages.getString("WebGalleryView.properties_tooltip")); //$NON-NLS-1$ } protected void doEditExhibitProperties(PWebExhibit pWebExhibit) { if (pWebExhibit != null) { textEventHandler.commit(); WebExhibitImpl exh = pWebExhibit.exhibit; WebExhibitImpl backup = new WebExhibitImpl(exh.getCaption(), exh.getSequenceNo(), exh.getDescription(), exh.getHtmlDescription(), exh.getAltText(), exh.getDownloadable(), exh.getIncludeMetadata(), exh.getAsset()); EditWebExibitDialog dialog = new EditWebExibitDialog(getSite().getShell(), exh, exh.getCaption(), gallery); if (dialog.open() == Window.OK) { performOperation(new EditExhibitOperation(pWebExhibit, backup, exh)); pWebExhibit.setCaptionAndDescription(exh); } } } protected PStoryboard addStoryboard(Storyboard storyboard, double y, ProgressIndicator progrBar) { IDbManager dbManager = Core.getCore().getDbManager(); PStoryboard pstoryboard = new PStoryboard(storyboard); storyMap.put(storyboard.getStringId(), pstoryboard); surface.addChild(pstoryboard); pstoryboard.setOffset(0, y); int i = 0; List<String> ids = new ArrayList<String>(storyboard.getExhibit().size()); for (String id : storyboard.getExhibit()) { WebExhibitImpl exhibit = dbManager.obtainById(WebExhibitImpl.class, id); if (exhibit != null) { ids.add(id); PWebExhibit pexhibit = makeExhibit(pstoryboard, exhibit); pexhibit.setSequenceNo(++i); if (progrBar != null) progrBar.worked(1); } } storyboard.setExhibit(ids); setColor(canvas); pstoryboard.updateColors(); setPanAndZoomHandlers(); return pstoryboard; } private void setPanAndZoomHandlers() { setPanAndZoomHandlers(-13, -17); } protected PWebExhibit makeExhibit(PStoryboard pstoryboard, WebExhibitImpl exhibit) { PWebExhibit pExhibit = new PWebExhibit(canvas, pstoryboard, exhibit, 0); PBounds bounds = pstoryboard.getBoundsReference(); int w = pstoryboard.getChildrenCount() * CELLSIZE; if (w > bounds.getWidth()) pstoryboard.setWidth(w); pstoryboard.addChild(pExhibit); exhibitMap.put(pExhibit.exhibit.getStringId(), pExhibit); return pExhibit; } private static int computeSequenceNumber(double x) { return Math.max(0, (int) ((x - 2 * LARGEBUTTONSIZE) / CELLSIZE + 1)); } protected void moveExhibit(PWebExhibit moved, Point2D newOffset) { performOperation(new MoveExhibitOperation(moved, newOffset)); } @Override protected void pastePresentationItems() { if (getGallery() != null) performOperation(new PasteExhibitsOperation(positionX)); } private PStoryboard findStoryboard(Point2D position) { RECT1.x = (int) position.getX(); RECT1.y = (int) position.getY(); for (PStoryboard w : storyMap.values()) if (w.fullIntersects(RECT1)) return w; return null; } @Override protected void deletePresentationItem(IPresentationItem picked, boolean cut, boolean multiple) { if (getGallery() != null) performOperation(new DeleteExhibitOperation(getSelectedExhibits((PWebExhibit) picked, multiple), cut)); } protected void selectExhibit(PWebExhibit pExhibit, int modifiers, int clicks) { if ((modifiers & InputEvent.CTRL_MASK) != 0) { pExhibit.setSelected(!pExhibit.isSelected()); if (pExhibit.isSelected()) recentSelection = pExhibit; else updateSelectionMarkers(); } else if ((modifiers & InputEvent.SHIFT_MASK) != 0) { PStoryboard pStory = (PStoryboard) pExhibit.getParent(); List<String> entries = pStory.getStoryboard().getExhibit(); int index = pExhibit.exhibit.getSequenceNo() - 1; if (pExhibit.isSelected()) { int lastIndex = -1; for (int i = 0; i < entries.size(); i++) if (exhibitMap.get(entries.get(i)) == lastSelection) { lastIndex = i; break; } if (lastIndex < 0) { int lower = 0; int upper = entries.size() - 1; for (int i = index - 1; i >= 0; i--) { if (!exhibitMap.get(entries.get(i)).isSelected()) break; lower = i; } for (int i = index + 1; i < entries.size(); i++) { if (!exhibitMap.get(entries.get(i)).isSelected()) break; upper = i; } if (index - lower < upper - index) lastIndex = lower; else lastIndex = upper; } if (lastIndex < index) for (int i = index - 1; i >= lastIndex; i--) exhibitMap.get(entries.get(i)).setSelected(false); else for (int i = index + 1; i <= lastIndex; i++) exhibitMap.get(entries.get(i)).setSelected(false); } else { recentSelection = pExhibit; for (int i = index - 1; i >= 0; i--) if (exhibitMap.get(entries.get(i)).isSelected()) { for (int j = i + 1; j <= index; j++) exhibitMap.get(entries.get(j)).setSelected(true); lastSelection = pExhibit; return; } for (int i = index + 1; i < entries.size(); i++) if (exhibitMap.get(entries.get(i)).isSelected()) { for (int j = i - 1; j >= index; j--) exhibitMap.get(entries.get(j)).setSelected(true); } } lastSelection = pExhibit; } else { clearSelection(); recentSelection = pExhibit; if (clicks == 2) { PStoryboard pStory = (PStoryboard) pExhibit.getParent(); for (ListIterator<?> iterator = pStory.getChildrenIterator(); iterator.hasNext();) { Object next = iterator.next(); if (next instanceof PWebExhibit) ((PWebExhibit) next).setSelected(true); } } else pExhibit.setSelected(true); } } private void clearSelection() { for (PStoryboard sb : storyMap.values()) for (ListIterator<?> childrenIterator = sb.getChildrenIterator(); childrenIterator.hasNext();) { Object next = childrenIterator.next(); if (next instanceof PWebExhibit) ((PWebExhibit) next).setSelected(false); } lastSelection = recentSelection = null; } public void updateSelectionMarkers() { for (PStoryboard sb : storyMap.values()) for (ListIterator<?> childrenIterator = sb.getChildrenIterator(); childrenIterator.hasNext();) { Object next = childrenIterator.next(); if (next instanceof PWebExhibit && ((PWebExhibit) next).isSelected()) return; } lastSelection = recentSelection = null; } protected List<PWebExhibit> getSelectedExhibits(PWebExhibit picked, boolean multiple) { boolean hit = false; List<PWebExhibit> selected = new ArrayList<>(); if (gallery != null) { if (multiple) for (Storyboard storyboard : gallery.getStoryboard()) { for (String id : storyboard.getExhibit()) { PWebExhibit pExhibit = exhibitMap.get(id); if (pExhibit.isSelected()) { selected.add(pExhibit); hit |= picked == pExhibit; } } } if (!hit) { selected.clear(); selected.add(picked); selectExhibit(picked, 0, 1); } } return selected; } protected PWebExhibit removeExhibit(Storyboard storyboard, int seqNo) { String id = storyboard.getExhibit().remove(seqNo - 1); PPresentationItem pexibit = exhibitMap.remove(id); PStoryboard pStoryboard = storyMap.get(storyboard.getStringId()); return (PWebExhibit) pStoryboard.removeChild(pexibit); } protected void insertExhibit(Storyboard storyboard, PWebExhibit pexhibit) { int seqNo = pexhibit.exhibit.getSequenceNo(); PStoryboard pStoryboard = storyMap.get(storyboard.getStringId()); pStoryboard.addChild(pexhibit); WebExhibitImpl exhibit = pexhibit.exhibit; exhibitMap.put(exhibit.getStringId(), pexhibit); insertIntoStoryboard(storyboard, exhibit, seqNo - 1); } private static void insertIntoStoryboard(Storyboard storyboard, WebExhibit exhibit, int index) { if (index >= storyboard.getExhibit().size()) storyboard.addExhibit(exhibit.getStringId()); else storyboard.getExhibit().add(index, exhibit.getStringId()); exhibit.setStoryboard_exhibit_parent(storyboard.getStringId()); } protected void updateSequenceNumbers(Storyboard storyboard) { int i = 1; for (String id : storyboard.getExhibit()) { PWebExhibit pexhibit = exhibitMap.get(id); if (pexhibit.exhibit.getSequenceNo() != i) pexhibit.setSequenceNo(i); ++i; } } protected WebGalleryImpl getGallery() { if (gallery == null && !dbIsReadonly()) gallery = WebGalleryEditDialog.openWebGalleryEditDialog(getSite().getShell(), null, null, Messages.getString("WebGalleryView.create_new_web_gallery"), false, false, null);//$NON-NLS-1$ return gallery; } @Override public void setInput(IdentifiableObject presentation) { super.setInput(presentation); if (presentation instanceof WebGalleryImpl) { WebGalleryImpl gal = (WebGalleryImpl) presentation; setGallery(gal); setupGallery(getViewSite(), gal); setPartName(gal.getName()); int n = 0; for (Storyboard sb : gal.getStoryboard()) n += sb.getExhibit().size(); beginTask(n); int y = 2 * STORYBOARDMARGINS; double w = STORYBOARDWIDTH; for (Storyboard sb : gal.getStoryboard()) w = Math.max(w, addStoryboard(sb, y += STORYBOARDDIST, progressBar).getBoundsReference().getWidth()); updateSurfaceBounds(w + 2 * STORYBOARDMARGINS, gal.getStoryboard().size() * (STORYBOARDHEIGHT + STORYBOARDDIST) + 2 * STORYBOARDMARGINS - STORYBOARDDIST); setColor(canvas); updateActions(false); updateStatusLine(); endTask(); } else setPartName(Messages.getString("WebGalleryView.web_gallery")); //$NON-NLS-1$ } private void generate(final boolean save) { WebGalleryImpl show = getGallery(); if (show != null) { if (offlineImages != null && !offlineImages.isEmpty()) { String[] volumes = offlineImages.toArray(new String[offlineImages.size()]); Arrays.sort(volumes); AcousticMessageDialog.openInformation(getSite().getShell(), Messages.getString("WebGalleryView.images_are_offline"), //$NON-NLS-1$ volumes.length > 1 ? NLS.bind(Messages.getString("WebGalleryView.some_image_on_volumes_are_offline"), //$NON-NLS-1$ Core.toStringList(volumes, ", ")) //$NON-NLS-1$ : NLS.bind(Messages.getString("WebGalleryView.some_images_on_volume_n_are_offline"), //$NON-NLS-1$ volumes[0])); } else { String selectedEngine = show.getSelectedEngine(); boolean isFtp = show.getIsFtp(); String outputFolder = (isFtp) ? show.getFtpDir() : show.getOutputFolder(); while (selectedEngine == null || outputFolder == null || selectedEngine.isEmpty() || outputFolder.isEmpty()) { show = WebGalleryEditDialog.openWebGalleryEditDialog(getSite().getShell(), null, show, show.getName(), true, false, Messages.getString("WebGalleryView.select_web_gallery")); //$NON-NLS-1$ if (show == null) return; selectedEngine = show.getSelectedEngine(); isFtp = show.getIsFtp(); outputFolder = (isFtp) ? show.getFtpDir() : show.getOutputFolder(); } for (IExtension ext : Platform.getExtensionRegistry() .getExtensionPoint(UiActivator.PLUGIN_ID, "galleryGenerator").getExtensions()) //$NON-NLS-1$ for (IConfigurationElement el : ext.getConfigurationElements()) if (el.getAttribute("id").equals(selectedEngine)) { //$NON-NLS-1$ if (createGenerator(show, el, outputFolder, isFtp, save)) return; break; } } } } private boolean createGenerator(WebGalleryImpl show, IConfigurationElement el, String outputFolder, boolean isFtp, final boolean save) { try { Storyboard selectedStoryboard = null; if (!Boolean.parseBoolean(el.getAttribute("sections")) && show.getStoryboard().size() > 1) { //$NON-NLS-1$ SelectStoryBoardDialog dialog = new SelectStoryBoardDialog(getSite().getShell(), Messages.getString("WebGalleryView.multiple_storyboards"), //$NON-NLS-1$ NLS.bind(Messages.getString("WebGalleryView.does_not_support_multiple_storyboards"), //$NON-NLS-1$ el.getAttribute("name")), //$NON-NLS-1$ show.getStoryboard()); if (dialog.open() != SelectStoryBoardDialog.OK) return true; selectedStoryboard = dialog.getResult(); } String maxImages = el.getAttribute("maxImages"); //$NON-NLS-1$ if (maxImages != null) { try { int max = Integer.parseInt(maxImages); int n = 0; for (Storyboard storyboard : show.getStoryboard()) max -= storyboard.getExhibit().size(); if (n > max && !AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("WebGalleryView.too_many"), //$NON-NLS-1$ NLS.bind(Messages.getString("WebGalleryView.n_exceeds_max"), //$NON-NLS-1$ new Object[] { n, max, el.getAttribute("name") }))) //$NON-NLS-1$ return true; } catch (NumberFormatException e) { // ignore } } String aspectRatio = el.getAttribute("aspectRatio"); //$NON-NLS-1$ if (aspectRatio != null) { aspectRatio.trim(); if (!aspectRatio.isEmpty()) { double sample = Double.NaN; double tolerance = 5; int p = aspectRatio.indexOf(' '); if (p > 0) { try { sample = Double.parseDouble(aspectRatio.substring(0, p)); } catch (NumberFormatException e) { // Leave at NaN } aspectRatio = aspectRatio.substring(p + 1); } if (aspectRatio.endsWith("%")) { //$NON-NLS-1$ try { tolerance = Double.parseDouble(aspectRatio.substring(0, aspectRatio.length() - 1)); } catch (NumberFormatException e) { // Leave at 5 } } List<String> errands = new ArrayList<>(); IDbManager dbManager = Core.getCore().getDbManager(); lp: for (Storyboard storyboard : show.getStoryboard()) { for (String exhibitId : storyboard.getExhibit()) { WebExhibitImpl exhibit = dbManager.obtainById(WebExhibitImpl.class, exhibitId); if (exhibit != null) { AssetImpl asset = dbManager.obtainAsset(exhibit.getAsset()); if (asset != null & asset.getHeight() > 0) { double prop = (double) asset.getWidth() / asset.getHeight(); if (Double.isNaN(sample)) sample = prop; else if (Math.abs(sample - prop) > sample * tolerance / 100d) { if (p > 0) errands.add((asset.getName())); else { if (!AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("WebGalleryView.unequal_proportions"), //$NON-NLS-1$ NLS.bind( Messages.getString( "WebGalleryView.unequal_proportions_msg"), //$NON-NLS-1$ el.getAttribute("name")))) //$NON-NLS-1$ return true; break lp; } } } } } } if (!errands.isEmpty() && !AcousticMessageDialog .openQuestion(getSite().getShell(), Messages.getString("WebGalleryView.unequal_proportions"), //$NON-NLS-1$ NLS.bind(Messages.getString("WebGalleryView.required_aspect_ratio"), //$NON-NLS-1$ new Object[] { el.getAttribute("name"), sample, //$NON-NLS-1$ Core.toStringList(errands.toArray(new String[errands.size()]), ", ") }))) //$NON-NLS-1$ return true; } } final IGalleryGenerator generator = (IGalleryGenerator) el.createExecutableExtension("class"); //$NON-NLS-1$ if (generator instanceof AbstractGalleryGenerator) { ((AbstractGalleryGenerator) generator).setConfigurationElement(el); ((AbstractGalleryGenerator) generator).setSelectedStoryBoard(selectedStoryboard); } final File file = new File(outputFolder); if (!isFtp && file.exists() && file.listFiles().length > 0) { AcousticMessageDialog dialog = new AcousticMessageDialog(getSite().getShell(), Messages.getString("WebGalleryView.overwrite"), //$NON-NLS-1$ null, NLS.bind(Messages.getString("WebGalleryView.output_folder_not_empty"), file), //$NON-NLS-1$ MessageDialog.QUESTION, new String[] { Messages.getString("WebGalleryView.overwrite_button"), //$NON-NLS-1$ Messages.getString("WebGalleryView.clear_folder"), //$NON-NLS-1$ IDialogConstants.CANCEL_LABEL }, 0); switch (dialog.open()) { case 2: return true; case 1: Core.deleteFolderExcluding(file, "themes"); //$NON-NLS-1$ break; } } String page = show.getPageName(); final boolean ftp = isFtp; final File start = new File(file, (page == null || page.isEmpty()) ? "index.html" //$NON-NLS-1$ : page); final WebGalleryImpl gal = show; final WebGalleryJob job = new WebGalleryJob(gal, generator, WebGalleryView.this); final FtpAccount account; if (ftp) { account = FtpAccount.findAccount(outputFolder); if (account == null) { AcousticMessageDialog.openError(getSite().getShell(), Messages.getString("WebGalleryView.account_does_not_exist"), //$NON-NLS-1$ NLS.bind(Messages.getString("WebGalleryView.ftp_account_not_defined"), //$NON-NLS-1$ outputFolder)); return true; } } else account = null; job.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { if (!job.wasAborted()) { if (ftp) new TransferJob(generator.getTargetFolder().listFiles(), account, true).schedule(0); else showWebGallery(save, start, gal); } } }); job.schedule(); } catch (CoreException e) { UiActivator.getDefault() .logError(NLS.bind(Messages.getString("WebGalleryView.error_when_instantiating_web_generator"), //$NON-NLS-1$ el.getAttribute("name")), e); //$NON-NLS-1$ } return false; } private void showWebGallery(final boolean save, final File start, final WebGalleryImpl show) { final Display display = getSite().getShell().getDisplay(); display.asyncExec(() -> { if (!display.isDisposed()) BusyIndicator.showWhile(display, () -> { try { URL url = start.toURI().toURL(); if (save) { SaveTemplateDialog dialog = new SaveTemplateDialog(getSite().getShell(), start, show); if (dialog.open() == Window.OK) { final WebGalleryImpl template = dialog.getResult(); final IDbManager dbManager = Core.getCore().getDbManager(); List<WebGalleryImpl> set = dbManager.obtainObjects(WebGalleryImpl.class, false, "name", //$NON-NLS-1$ template.getName(), QueryField.EQUALS, "template", true, //$NON-NLS-1$ QueryField.EQUALS); dbManager.safeTransaction(set, template); } } else { IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport() .getExternalBrowser(); if (browser != null) browser.openURL(url); } } catch (MalformedURLException e1) { // should not happen } catch (PartInitException e2) { // ignore } }); }); } @Override protected void dropAssets(ISelection selection, org.eclipse.swt.graphics.Point point, Point2D position, boolean replace) { performOperation(new DropAssetOperation((AssetSelection) selection, position, replace)); getSite().getPage().activate(this); } private void editStoryboardLegend(PStoryboard pStoryboard) { StoryboardImpl w = (StoryboardImpl) pStoryboard.getStoryboard(); StoryboardImpl backup = new StoryboardImpl(w.getTitle(), w.getSequenceNo(), w.getHtmlDescription(), w.getDescription(), w.getImageSize(), w.getEnlargeSmall(), w.getShowCaptions(), w.getShowDescriptions(), w.getShowExif()); EditStoryBoardDialog dialog = new EditStoryBoardDialog(getSite().getShell(), w.getWebGallery_storyboard_parent(), w, w.getTitle()); if (dialog.open() == Window.OK) performOperation(new EditStoryboardOperation(w, backup, pStoryboard)); } @Override protected PNode[] getWorkArea() { Collection<PStoryboard> values = storyMap.values(); return values.toArray(new PNode[values.size()]); } @Override protected int getPanDirection() { return GalleryPanEventHandler.BOTH; } @Override protected int getHoriztontalMargins() { return STORYBOARDMARGINS; } @Override public Object getContent() { return gallery; } @Override protected AbstractHandleDragSequenceEventHandler createDragSequenceEventHandler(PNode node, boolean relative, boolean restricted, PNode presentationObject) { return new AbstractPresentationView.AbstractHandleDragSequenceEventHandler(node, relative, restricted, presentationObject) { @Override protected void moveToFront(PNode object) { updateActions(false); } @Override protected void drop(PInputEvent event, PNode pnode) { PWebExhibit pexhibit = (PWebExhibit) pnode.getParent(); if (event.getCanvasPosition().getY() < 0) deletePresentationItem(pexhibit, false, false); else { Point2D newOffset = event.getPosition(); Point2D parentOffset = ((PStoryboard) pexhibit.getParent()).getOffset(); Point2D point = new Point2D.Double(newOffset.getX() + parentOffset.getX(), newOffset.getY()); surface.parentToLocal(point); for (PStoryboard pstoryboard : storyMap.values()) { double y = point.getY() - pstoryboard.getOffset().getY(); PBounds bounds = pstoryboard.getBoundsReference(); if (bounds.getY() <= y && bounds.getY() + bounds.getHeight() >= y) { moveExhibit(pexhibit, newOffset); return; } } pexhibit.setOffset(oldOffset); } } @Override public Point getDragTolerance() { return DRAGTOLERANCE; } }; } @Override protected PBounds getClientAreaReference() { PBounds bounds = new PBounds(0, 0, 0, 0); for (PStoryboard stb : storyMap.values()) { PBounds b1 = stb.getBoundsReference(); if (b1.getX() < bounds.x) bounds.x = b1.getX(); if (b1.getY() < bounds.y) bounds.y = b1.getY(); if (b1.getWidth() + b1.getX() > bounds.width + bounds.x) bounds.width = b1.getWidth() + b1.getX() - bounds.x; if (b1.getHeight() + b1.getY() > bounds.height + bounds.y) bounds.height = b1.getHeight() + b1.getY() - bounds.y; } return bounds; } public static boolean accepts(Asset asset) { if (asset == null) return false; IMediaSupport mediaSupport = CoreActivator.getDefault().getMediaSupport(asset.getFormat()); return mediaSupport == null || mediaSupport.testProperty(IMediaSupport.WEBGALLERY); } @Override protected void refreshAfterHistoryEvent(IUndoableOperation operation) { if (operation instanceof ExhibitionPropertiesOperation) setInput(gallery); } protected PNode findExhibit(Point2D position) { PStoryboard pstoryboard = null; RECT1.x = (int) position.getX(); RECT1.y = (int) position.getY(); for (PStoryboard w : storyMap.values()) if (w.fullIntersects(RECT1)) { pstoryboard = w; break; } if (pstoryboard != null) { int rawIx = computeSequenceNumber(position.getX() - pstoryboard.getOffset().getX()); String id = pstoryboard.getStoryboard().getExhibit(rawIx - 1); return exhibitMap.get(id); } return null; } protected void revealItem(PPresentationItem item) { if (item != null) { PBounds gfb = item.getGlobalFullBounds(); double w = gfb.getWidth(); double h = gfb.getHeight(); gfb.setRect(gfb.getX() - w * 0.4d, gfb.getY() - h * 0.4d, 1.8d * w, 1.8d * h); canvas.getCamera().setViewBounds(gfb); } } private void revealExhibit(WebExhibit selectedExhibit) { revealItem(exhibitMap.get(selectedExhibit.getStringId())); } @Override public String getId() { return ID; } @Override public String getValue(String key, Object object) { if (object instanceof WebExhibit) { if (Constants.HV_TOTAL.equals(key)) { int total = 0; for (PStoryboard sb : storyMap.values()) total += sb.getStoryboard().getExhibit().size(); return String.valueOf(total); } if (Constants.HV_STORYBOARD.equals(key)) { String sbId = ((WebExhibit) object).getStoryboard_exhibit_parent(); PStoryboard pstoryboard = storyMap.get(sbId); return pstoryboard.getStoryboard().getTitle(); } } return null; } @Override protected String getStatusMessage() { WebGalleryImpl gal = getGallery(); if (gal != null) return NLS.bind(storyMap.size() == 1 ? Messages.getString("WebGalleryView.n_exh_one_storyboard") //$NON-NLS-1$ : Messages.getString("WebGalleryView.n_exh_m_storyboards"), //$NON-NLS-1$ exhibitMap.size(), storyMap.size()); return null; } }