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-2018 Berthold Daum */ package com.bdaum.zoom.ui.internal.views; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.eclipse.core.commands.operations.UndoContext; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.FileTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; 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.swt.widgets.Tree; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.operations.UndoRedoActionGroup; import org.eclipse.ui.part.DrillDownAdapter; 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.asset.Region; import com.bdaum.zoom.cat.model.asset.RegionImpl; import com.bdaum.zoom.cat.model.group.Criterion; import com.bdaum.zoom.cat.model.group.CriterionImpl; import com.bdaum.zoom.cat.model.group.Group; import com.bdaum.zoom.cat.model.group.GroupImpl; import com.bdaum.zoom.cat.model.group.SmartCollection; import com.bdaum.zoom.cat.model.group.SmartCollectionImpl; import com.bdaum.zoom.cat.model.group.SortCriterion; import com.bdaum.zoom.cat.model.group.SortCriterionImpl; import com.bdaum.zoom.cat.model.group.exhibition.ExhibitImpl; import com.bdaum.zoom.cat.model.group.exhibition.Exhibition; import com.bdaum.zoom.cat.model.group.exhibition.ExhibitionImpl; import com.bdaum.zoom.cat.model.group.exhibition.Wall; import com.bdaum.zoom.cat.model.group.slideShow.SlideImpl; import com.bdaum.zoom.cat.model.group.slideShow.SlideShow; import com.bdaum.zoom.cat.model.group.slideShow.SlideShowImpl; import com.bdaum.zoom.cat.model.group.webGallery.Storyboard; 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.cat.model.group.webGallery.WebParameter; import com.bdaum.zoom.cat.model.meta.Meta; import com.bdaum.zoom.core.BagChange; import com.bdaum.zoom.core.CatalogAdapter; import com.bdaum.zoom.core.CatalogListener; import com.bdaum.zoom.core.Constants; import com.bdaum.zoom.core.Core; import com.bdaum.zoom.core.QueryField; import com.bdaum.zoom.core.Range; import com.bdaum.zoom.core.db.IDbManager; import com.bdaum.zoom.core.internal.Utilities; import com.bdaum.zoom.job.OperationJob; import com.bdaum.zoom.mtp.ObjectFilter; import com.bdaum.zoom.operations.IProfiledOperation; import com.bdaum.zoom.operations.internal.AddAlbumOperation; import com.bdaum.zoom.operations.internal.AutoRuleOperation; import com.bdaum.zoom.operations.internal.MoveOperation; import com.bdaum.zoom.operations.internal.MultiModifyAssetOperation; import com.bdaum.zoom.operations.internal.RateOperation; import com.bdaum.zoom.operations.internal.RemoveAlbumOperation; import com.bdaum.zoom.operations.internal.SetLocationCreatedOperation; import com.bdaum.zoom.ui.AssetSelection; import com.bdaum.zoom.ui.IDropinHandler; import com.bdaum.zoom.ui.IZoomCommandIds; import com.bdaum.zoom.ui.dialogs.AcousticMessageDialog; import com.bdaum.zoom.ui.internal.HelpContextIds; import com.bdaum.zoom.ui.internal.Icons; import com.bdaum.zoom.ui.internal.Icons.Icon; import com.bdaum.zoom.ui.internal.UiActivator; import com.bdaum.zoom.ui.internal.UiUtilities; import com.bdaum.zoom.ui.internal.actions.DeleteAction; import com.bdaum.zoom.ui.internal.dialogs.CollectionEditDialog; import com.bdaum.zoom.ui.internal.dialogs.EditMetaDialog; import com.bdaum.zoom.ui.internal.dialogs.ExhibitionEditDialog; import com.bdaum.zoom.ui.internal.dialogs.FilterDialog; import com.bdaum.zoom.ui.internal.dialogs.GroupDialog; import com.bdaum.zoom.ui.internal.dialogs.PurgeEmptyDialog; import com.bdaum.zoom.ui.internal.dialogs.SlideshowEditDialog; import com.bdaum.zoom.ui.internal.dialogs.WebGalleryEditDialog; import com.bdaum.zoom.ui.internal.hover.IGalleryHover; import com.bdaum.zoom.ui.internal.operations.SlideshowPropertiesOperation; import com.bdaum.zoom.ui.internal.wizards.MergeCatWizard; @SuppressWarnings("restriction") public class CatalogView extends AbstractCatalogView implements IPerspectiveListener { public final class CatalogDragSourceListener implements DragSourceListener { public void dragStart(DragSourceEvent event) { Object firstElement = viewer.getStructuredSelection().getFirstElement(); if (firstElement != null && firstElement != WASTEBASKET) { boolean canDrag = false; IDbManager dbManager = Core.getCore().getDbManager(); if (firstElement instanceof SmartCollection) { SmartCollection parent = (SmartCollection) firstElement; while (parent.getSmartCollection_subSelection_parent() != null) parent = parent.getSmartCollection_subSelection_parent(); String groupId = parent.getGroup_rootCollection_parent(); if (groupId != null) { Group group = dbManager.obtainById(GroupImpl.class, groupId); if (group != null) { while (group.getGroup_subgroup_parent() != null) group = group.getGroup_subgroup_parent(); canDrag = (!group.getSystem() || group.getStringId().equals(Constants.GROUP_ID_PERSONS)); } } } else if (firstElement instanceof Group) canDrag = (((Group) firstElement).getGroup_subgroup_parent() != null); else if (firstElement instanceof Exhibition) canDrag = dbManager.exists(GroupImpl.class, ((Exhibition) firstElement).getGroup_exhibition_parent()); else if (firstElement instanceof SlideShow) canDrag = dbManager.exists(GroupImpl.class, ((SlideShow) firstElement).getGroup_slideshow_parent()); else if (firstElement instanceof WebGallery) canDrag = dbManager.exists(GroupImpl.class, ((WebGallery) firstElement).getGroup_webGallery_parent()); if (canDrag) { event.doit = true; selectionTransfer.setSelection(viewer.getSelection()); event.detail = DND.DROP_MOVE; return; } } event.doit = false; } public void dragSetData(DragSourceEvent event) { // do nothing } public void dragFinished(DragSourceEvent event) { selectionTransfer.setSelection(null); } } public final class CatalogDropTargetListener extends EffectDropTargetListener { public CatalogDropTargetListener(Control control) { super(control); } @Override public void dragEnter(DropTargetEvent event) { int detail = event.detail; event.detail = DND.DROP_NONE; if (!dbIsReadonly()) { boolean match = false; for (int i = 0; i < event.dataTypes.length; i++) { if (selectionTransfer.isSupportedType(event.dataTypes[i])) { event.currentDataType = event.dataTypes[i]; ISelection selection = selectionTransfer.getSelection(); if (selection instanceof TreeSelection) { if ((detail & DND.DROP_MOVE) != 0) event.detail = DND.DROP_MOVE; super.dragEnter(event); return; } AssetSelection selectedAssets = getNavigationHistory().getSelectedAssets(); if (!selectedAssets.isEmpty()) { selectionTransfer.setSelection(selectedAssets); match = true; break; } } } if (!match) for (int i = 0; i < event.dataTypes.length; i++) if (fileTransfer.isSupportedType(event.dataTypes[i])) { event.currentDataType = event.dataTypes[i]; match = true; break; } if (match && (detail & OPERATIONS) != 0) event.detail = DND.DROP_COPY; super.dragEnter(event); } } @Override public void dragOver(DropTargetEvent event) { int detail = event.detail; event.detail = DND.DROP_NONE; if (!dbIsReadonly()) { event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL; ISelection selection = selectionTransfer.getSelection(); if (selection instanceof TreeSelection) { if (canBeDroppedInGroup(event, (TreeSelection) selection)) event.detail = DND.DROP_MOVE; return; } if (selectionTransfer.isSupportedType(event.currentDataType) && canBeDropped(event)) { if ((detail & OPERATIONS) != 0 || detail == DND.DROP_NONE) event.detail = DND.DROP_COPY; } else if (fileTransfer.isSupportedType(event.currentDataType) && gpxCanBeDropped(event)) if ((detail & OPERATIONS) != 0 || detail == DND.DROP_NONE) event.detail = DND.DROP_COPY; } } private boolean canBeDroppedInGroup(DropTargetEvent event, TreeSelection selection) { Widget item = event.item; boolean canDrop = false; if (item != null) { Object data = item.getData(); if (data instanceof Group) { if (data == WASTEBASKET) return false; Group target = ((Group) data); Group targetRoot = getRoot(target); String targetRootId = targetRoot.getStringId(); boolean targetIsPersonGroup = Constants.GROUP_ID_PERSONS.equals(targetRootId); canDrop = !targetRoot.getSystem() || targetIsPersonGroup; if (canDrop) { Object firstElement = selection.getFirstElement(); if (firstElement instanceof Group) { Group group = (Group) firstElement; canDrop = group != target && group.getGroup_subgroup_parent() != target && isPersonGroup(group) == targetIsPersonGroup; } else { boolean exhibition = !target.getExhibition().isEmpty(); boolean slideshow = !target.getSlideshow().isEmpty(); boolean webgallery = target.getWebGallery() != null && !target.getWebGallery().isEmpty(); boolean collection = !target.getRootCollection().isEmpty(); if (!exhibition && !slideshow && !webgallery && !collection) { exhibition = Constants.GROUP_ID_EXHIBITION.equals(targetRootId); slideshow = Constants.GROUP_ID_SLIDESHOW.equals(targetRootId); webgallery = Constants.GROUP_ID_WEBGALLERY.equals(targetRootId); if (!exhibition && !slideshow && !webgallery) collection = exhibition = slideshow = webgallery = true; } if (firstElement instanceof Exhibition) canDrop &= exhibition; if (firstElement instanceof SlideShow) canDrop &= slideshow; if (firstElement instanceof WebGallery) canDrop &= webgallery; if (firstElement instanceof SmartCollection) canDrop &= collection && (!isPersonFolder((SmartCollection) firstElement) || targetIsPersonGroup); } } } } return canDrop; } private boolean gpxCanBeDropped(DropTargetEvent event) { return (event.item != null && (event.item.getData() instanceof SmartCollectionImpl)); } private boolean canBeDropped(DropTargetEvent event) { Widget item = event.item; boolean canDrop = false; if (item != null) { Object data = item.getData(); if (data instanceof SmartCollectionImpl) { SmartCollectionImpl coll = ((SmartCollectionImpl) data); if (coll.getAlbum()) canDrop = true; else { String collId = coll.getStringId(); int p = collId.indexOf('='); if (p > 0) { String key = collId.substring(0, p); canDrop = key.equals(QueryField.RATING.getKey()) || (key.equals(QueryField.URI.getKey()) && coll.getSmartCollection_subSelection_parent() != null) || key.equals(QueryField.IPTC_CATEGORY.getKey()) || key.equals(QueryField.IPTC_LOCATIONCREATED.getKey()); } } } else canDrop = data == WASTEBASKET && selectionTransfer.getSelection() instanceof AssetSelection; } return canDrop; } public void dragOperationChanged(DropTargetEvent event) { if (!dbIsReadonly()) { if (selectionTransfer.isSupportedType(event.currentDataType)) { if ((event.detail & OPERATIONS) == 0) event.detail = DND.DROP_NONE; return; } if (fileTransfer.isSupportedType(event.currentDataType)) { event.detail = ((event.detail & OPERATIONS) == 0) ? DND.DROP_NONE : DND.DROP_COPY; return; } } event.detail = DND.DROP_NONE; } public void drop(DropTargetEvent event) { if (dbIsReadonly()) return; ISelection selection = selectionTransfer.getSelection(); if (selection instanceof TreeSelection) { if (canBeDroppedInGroup(event, (TreeSelection) selection)) { IDbManager dbManager = Core.getCore().getDbManager(); List<Object> toBeStored = new ArrayList<Object>(3); Object movedElement = ((TreeSelection) selection).getFirstElement(); Widget item = event.item; Object data = item.getData(); Group target = ((Group) data); toBeStored.add(movedElement); toBeStored.add(target); if (movedElement instanceof Group) { Group group = (Group) movedElement; Group parent = group.getGroup_subgroup_parent(); if (parent != null && parent.getSubgroup() != null) { parent.removeSubgroup(group); toBeStored.add(parent); } group.setGroup_subgroup_parent(target); if (target.getSubgroup() == null) target.setSubgroup(Collections.singletonList(group)); else target.addSubgroup(group); } else if (movedElement instanceof SmartCollection) { SmartCollection sm = (SmartCollection) movedElement; SmartCollection parentSm = sm.getSmartCollection_subSelection_parent(); if (parentSm != null) { parentSm.removeSubSelection(sm); toBeStored.add(parentSm); sm.setSmartCollection_subSelection_parent(null); sm.setGroup_rootCollection_parent(target.getStringId()); target.addRootCollection(sm.getStringId()); } else { String parentId = sm.getGroup_rootCollection_parent(); if (parentId != null) { Group parent = dbManager.obtainById(Group.class, parentId); if (parent != null) { parent.removeRootCollection(sm.getStringId()); toBeStored.add(parent); } sm.setGroup_rootCollection_parent(target.getStringId()); target.addRootCollection(sm.getStringId()); } } } else if (movedElement instanceof Exhibition) { Exhibition exhibition = (Exhibition) movedElement; String parentId = exhibition.getGroup_exhibition_parent(); if (parentId != null) { Group parent = dbManager.obtainById(Group.class, parentId); if (parent != null) { parent.removeExhibition(exhibition.getStringId()); toBeStored.add(parent); } exhibition.setGroup_exhibition_parent(target.getStringId()); target.addExhibition(exhibition.getStringId()); } } else if (movedElement instanceof SlideShow) { SlideShow slideshow = (SlideShow) movedElement; String parentId = slideshow.getGroup_slideshow_parent(); if (parentId != null) { Group parent = dbManager.obtainById(Group.class, parentId); if (parent != null) { parent.removeSlideshow(slideshow.getStringId()); toBeStored.add(parent); } slideshow.setGroup_slideshow_parent(target.getStringId()); target.addSlideshow(slideshow.getStringId()); } } else if (movedElement instanceof WebGallery) { WebGallery gallery = (WebGallery) movedElement; String parentId = gallery.getGroup_webGallery_parent(); if (parentId != null) { Group parent = dbManager.obtainById(Group.class, parentId); if (parent != null) { parent.removeWebGallery(gallery.getStringId()); toBeStored.add(parent); } gallery.setGroup_webGallery_parent(target.getStringId()); target.addWebGallery(gallery.getStringId()); } } dbManager.safeTransaction(null, toBeStored); setInput(); setViewerSelection(new StructuredSelection(movedElement), true); } } if (selectionTransfer.isSupportedType(event.currentDataType)) { if (canBeDropped(event)) { Region region = null; List<Asset> assets; if (selection instanceof AssetSelection) { if (event.item.getData() == WASTEBASKET) { new DeleteAction("", "", null, CatalogView.this).run(); //$NON-NLS-1$//$NON-NLS-2$ return; } assets = ((AssetSelection) selection).getAssets(); } else { assets = new ArrayList<>(1); if (selection instanceof IStructuredSelection) { Object firstElement = ((IStructuredSelection) selection).getFirstElement(); if (firstElement instanceof ImageRegion) { ImageRegion imageRegion = (ImageRegion) firstElement; if (imageRegion != null) { assets.add(imageRegion.owner); List<RegionImpl> set = Core.getCore().getDbManager().obtainObjects( RegionImpl.class, false, "asset_person_parent", //$NON-NLS-1$ imageRegion.owner.getStringId(), QueryField.EQUALS, Constants.OID, imageRegion.regionId, QueryField.EQUALS); if (!set.isEmpty()) region = set.get(0); } } } } SmartCollectionImpl coll = (SmartCollectionImpl) event.item.getData(); Criterion criterion = coll.getCriterion(0); Object value = criterion.getValue(); IProfiledOperation op = null; if (coll.getAlbum()) { if (!assets.isEmpty()) op = new AddAlbumOperation(coll, assets, region); } else { String key = criterion.getField(); if (QueryField.RATING.getKey().equals(key)) op = new RateOperation(assets, ((Integer) value)); else if (QueryField.URI.getKey().equals(key)) try { File folder = new File(new URI((String) value)); folder.mkdirs(); // Just in case op = new MoveOperation(assets, folder); } catch (URISyntaxException e) { Core.getCore().logError(Messages.getString("CatalogView.bad_uri_for_target_folder"), //$NON-NLS-1$ e); } else if (QueryField.IPTC_CATEGORY.getKey().equals(key)) op = new MultiModifyAssetOperation(QueryField.IPTC_CATEGORY, value, null, assets); else if (QueryField.IPTC_LOCATIONCREATED.getKey().equals(key)) op = new SetLocationCreatedOperation(coll, assets); } if (op != null) OperationJob.executeOperation(op, CatalogView.this); } } else if (fileTransfer.isSupportedType(event.currentDataType)) { String[] filenames = (String[]) event.data; if (filenames.length == 1 && filenames[0].endsWith(Constants.CATALOGEXTENSION)) { MergeCatWizard wizard = new MergeCatWizard(); WizardDialog wizardDialog = new WizardDialog(getSite().getShell(), wizard); wizard.init(getSite().getWorkbenchWindow().getWorkbench(), new StructuredSelection(filenames[0])); wizardDialog.open(); return; } ObjectFilter filter = UiActivator.getDefault().createGpsFileFormatFilter(); List<File> gpx = new ArrayList<File>(); for (int j = 0; j < filenames.length; j++) { File file = new File(filenames[j]); if (filter.accept(file)) gpx.add(file); } if (!gpx.isEmpty() && gpxCanBeDropped(event)) { IDropinHandler handler = UiActivator.getDefault().getDropinHandler("gps"); //$NON-NLS-1$ if (handler != null) { final SmartCollectionImpl currentCollection = (SmartCollectionImpl) event.item.getData(); handler.handleDropin(gpx.toArray(new File[gpx.size()]), new IAdaptable() { @SuppressWarnings("unchecked") @Override public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { if (AssetSelection.class.equals(adapter)) return new AssetSelection(Core.getCore().getDbManager() .createCollectionProcessor(currentCollection).select(false)); return CatalogView.this.getAdapter(adapter); } }); } } } } } private static final int OPERATIONS = DND.DROP_MOVE | DND.DROP_COPY; public static class CatalogComparator extends ViewerComparator { @Override @SuppressWarnings("unchecked") public int compare(Viewer viewer, Object e1, Object e2) { if (e1 instanceof SmartCollection && e2 instanceof SmartCollection) { SmartCollection c1 = (SmartCollection) e1; SmartCollection c2 = (SmartCollection) e2; if (c1.getSystem() && c2.getSystem() && !c1.getAlbum() && !c2.getAlbum() && !c1.getCriterion().isEmpty() && !c2.getCriterion().isEmpty()) { Criterion crit1 = c1.getCriterion(0); Object value1 = crit1 == null ? null : crit1.getValue(); if (value1 instanceof Range) value1 = ((Range) value1).getFrom(); Criterion crit2 = c2.getCriterion(0); Object value2 = crit2 == null ? null : crit2.getValue(); if (value2 instanceof Range) value2 = ((Range) value2).getFrom(); if (value1 != null && value2 != null && value1.getClass().equals(value2.getClass())) return ((Comparable<Object>) value1).compareTo(value2); } else return (UiUtilities.isImport(c1)) ? c2.getName().compareTo(c1.getName()) : c1.getName().compareToIgnoreCase(c2.getName()); } else if (e1 instanceof Group && e2 instanceof Group) { Group c1 = (Group) e1; Group c2 = (Group) e2; if (c1 == CatalogView.WASTEBASKET) return 1; if (c2 == CatalogView.WASTEBASKET) return -1; return c1.getName().compareToIgnoreCase(c2.getName()); } else if (e1 instanceof Group && e2 instanceof SmartCollection) return ((SmartCollection) e2).getStringId().equals(Constants.LAST_IMPORT_ID) ? 1 : -1; else if (e1 instanceof SmartCollection && e2 instanceof Group) return ((SmartCollection) e1).getStringId().equals(Constants.LAST_IMPORT_ID) ? -1 : 1; return super.compare(viewer, e1, e2); } } public static final String ID = "com.bdaum.zoom.ui.views.CatalogView"; //$NON-NLS-1$ public static final GroupImpl WASTEBASKET = new GroupImpl(Messages.getString("CatalogView.wastebasket"), true, //$NON-NLS-1$ 1, null, -1, null); private static final FileTransfer fileTransfer = FileTransfer.getInstance(); private static final LocalSelectionTransfer selectionTransfer = LocalSelectionTransfer.getTransfer(); private static final Transfer[] allTypes = new Transfer[] { fileTransfer, selectionTransfer }; private static final Transfer[] selectionTypes = new Transfer[] { selectionTransfer }; private static final String CATFILTERS = "catFilters"; //$NON-NLS-1$ private static final String PERSONALBUMS = "persons"; //$NON-NLS-1$ private static final String EMPTYPERSONALBUMS = "emptyPersons"; //$NON-NLS-1$ private static final String RATINGS = "ratings"; //$NON-NLS-1$ private static final String CATEGORIES = "categories"; //$NON-NLS-1$ private static final String DIRECTORIES = "directories"; //$NON-NLS-1$ private static final String TIMELINE = "timeline"; //$NON-NLS-1$ private static final String LOCATIONS = "locations"; //$NON-NLS-1$ private static final String PASTIMPORTS = "pastImports"; //$NON-NLS-1$ private static final String[] ALLCATITEMS = new String[] { EMPTYPERSONALBUMS, PERSONALBUMS, CATEGORIES, RATINGS, DIRECTORIES, TIMELINE, LOCATIONS, PASTIMPORTS }; private static final String[] CATITEMLABELS = new String[] { Messages.getString("CatalogView.empty_person_albums"), //$NON-NLS-1$ Messages.getString("CatalogView.person_albums"), //$NON-NLS-1$ Messages.getString("CatalogView.categories"), Messages.getString("CatalogView.ratings"), //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("CatalogView.directories"), Messages.getString("CatalogView.timeline"), //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("CatalogView.locations"), Messages.getString("CatalogView.past_imports"), }; //$NON-NLS-1$ //$NON-NLS-2$ private DrillDownAdapter drillDownAdapter; private Action createCollectionAction, addSubCollectionAction, deleteAction, cutCollection, copyCollection, pasteCollection, createGroup, createSlideShowAction, collapseAction, propertiesAction, createExhibitionAction, createAlbumAction, createWebGalleryAction, filterAction, addSubAlbumAction, addSubGroupAction, expandAction, refreshAction; private Set<String> hiddenCatItems; private Clipboard clipboard; private boolean restoring; private Object[] expansions; private boolean settingSelection; private ISelection initialSelection; private boolean initialized; private int colorCode = -1; protected boolean catOpen; protected boolean selectionChanged; private Point findingPoint = new Point(0, 0); private ViewerFilter userFilter = new ViewerFilter() { @Override public boolean select(Viewer aViewer, Object parentElement, Object element) { if (element instanceof GroupImpl) { String groupId = ((GroupImpl) element).getStringId(); return !(Constants.GROUP_ID_CATEGORIES.equals(groupId) && hiddenCatItems.contains(CATEGORIES) || Constants.GROUP_ID_FOLDERSTRUCTURE.equals(groupId) && hiddenCatItems.contains(DIRECTORIES) || Constants.GROUP_ID_PERSONS.equals(groupId) && hiddenCatItems.contains(PERSONALBUMS) || Constants.GROUP_ID_RATING.equals(groupId) && hiddenCatItems.contains(RATINGS) || Constants.GROUP_ID_TIMELINE.equals(groupId) && hiddenCatItems.contains(TIMELINE) || Constants.GROUP_ID_LOCATIONS.equals(groupId) && hiddenCatItems.contains(LOCATIONS) || Constants.GROUP_ID_RECENTIMPORTS.equals(groupId) && hiddenCatItems.contains(PASTIMPORTS)); } else if (element instanceof SmartCollectionImpl) { SmartCollectionImpl coll = (SmartCollectionImpl) element; return !(hiddenCatItems.contains(EMPTYPERSONALBUMS) && coll.getAlbum() && coll.getSystem() && coll.getAsset().isEmpty() || hiddenCatItems.contains(PASTIMPORTS) && coll.getStringId().startsWith(IDbManager.IMPORTKEY)); } return true; } }; private ViewerFilter colorCodeFilter = new ViewerFilter() { @Override public boolean select(Viewer aViewer, Object parentElement, Object element) { if (colorCode > Constants.COLOR_UNDEFINED && element instanceof SmartCollection) { if (((SmartCollection) element).getColorCode() - 1 == colorCode) return true; for (SmartCollection sub : ((SmartCollection) element).getSubSelection()) if (select(aViewer, element, sub)) return true; return false; } return true; } }; @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); String textData = memento == null ? null : memento.getString(CATFILTERS); hiddenCatItems = new HashSet<String>(); if (textData != null) { StringTokenizer st = new StringTokenizer(textData); while (st.hasMoreTokens()) hiddenCatItems.add(st.nextToken()); } } @Override public void saveState(IMemento memento) { memento.putString(CATFILTERS, Core.toStringList(hiddenCatItems, ' ')); super.saveState(memento); } @Override public void createPartControl(final Composite parent) { undoContext = new UndoContext() { @Override public String getLabel() { return Messages.getString("CatalogView.catalog_undo_context"); //$NON-NLS-1$ } }; viewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); drillDownAdapter = new DrillDownAdapter((TreeViewer) viewer); viewer.setContentProvider(new CatalogContentProvider()); viewer.setLabelProvider(new CatalogLabelProvider(this)); viewer.setFilters(new ViewerFilter[] { colorCodeFilter, userFilter }); viewer.setComparator(new CatalogComparator()); viewer.setComparer(IdentifiedElementComparer.getInstance()); UiUtilities.installDoubleClickExpansion((TreeViewer) viewer); ZColumnViewerToolTipSupport.enableFor(viewer); PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), HelpContextIds.CATALOG_VIEW); viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(final SelectionChangedEvent event) { selectionChanged = true; if (viewer.getStructuredSelection().getFirstElement() == WASTEBASKET) { try { getSite().getPage().showView(TrashcanView.ID); } catch (PartInitException e) { // shouldn't happen } return; } if (!settingSelection) { cancelJobs(CatalogView.this); new SelectionJob(viewer, event).schedule(); } if (cntrlDwn && editItemAction.isEnabled()) { if (!settingSelection) editItemAction.run(); cntrlDwn = false; } } }); addCtrlKeyListener(); viewer.addDropSupport(OPERATIONS, allTypes, new CatalogDropTargetListener(viewer.getControl())); viewer.addDragSupport(DND.DROP_MOVE, new Transfer[] { selectionTransfer }, new CatalogDragSourceListener()); addKeyListener(); Tree tree = ((TreeViewer) viewer).getTree(); addGestureListener(tree); makeActions(); installListeners(); hookContextMenu(viewer); contributeToActionBars(); addDragDropClipboard(tree); getSite().getWorkbenchWindow().addPerspectiveListener(this); Core.getCore().addCatalogListener(new CatalogAdapter() { @Override public void structureModified() { Shell shell = getSite().getShell(); if (shell != null && !shell.isDisposed()) shell.getDisplay().asyncExec(() -> { if (!shell.isDisposed()) refresh(); }); } @Override public void assetsModified(BagChange<Asset> changes, QueryField node) { forceSelectionUpdate(); } @Override public void applyRules(Collection<? extends Asset> assets, QueryField node) { OperationJob.executeSlaveOperation( new AutoRuleOperation(UiActivator.getDefault().obtainAutoRules(), assets, node), CatalogView.this, false); } private void forceSelectionUpdate() { Shell shell = getSite().getShell(); if (shell != null && !shell.isDisposed()) shell.getDisplay().asyncExec(() -> { if (!shell.isDisposed()) { ISelection selection = viewer.getSelection(); viewer.setSelection(StructuredSelection.EMPTY); setViewerSelection(selection, true); fireSelection(new SelectionChangedEvent(CatalogView.this, selection)); } }); } @Override public void setCatalogSelection(final ISelection selection, final boolean forceUpdate) { try { Job.getJobManager().join(CatalogView.this, null); } catch (Exception e) { // do nothing } Shell shell = getSite().getShell(); if (shell != null && !shell.isDisposed()) shell.getDisplay().asyncExec(() -> { if (!shell.isDisposed()) setSelection(selection, forceUpdate); }); } @Override public void catalogOpened(boolean newDb) { Display display = getSite().getShell().getDisplay(); display.syncExec(() -> BusyIndicator.showWhile(display, () -> { structureModified(); restoreLastSelection(); catOpen = true; })); } @Override public void catalogClosed(int mode) { if (mode != CatalogListener.EMERGENCY) { saveLastSelection(); catOpen = false; } } }); updateActions(viewer.getStructuredSelection(), true); } public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) { // do nothing } public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) { IStructuredSelection selection = viewer.getStructuredSelection(); if (!selection.isEmpty()) { Object selected = selection.getFirstElement(); Object newSelection = null; for (IViewReference ref : page.getViewReferences()) { IViewPart view = ref.getView(false); if (view instanceof BasicView) { Object content = ((BasicView) view).getContent(); if (selected == content && !UiActivator.getDefault().isPresentationPerspective(perspective.getId())) return; if (content instanceof SmartCollection) newSelection = content; } } if (newSelection != null) setViewerSelection(new StructuredSelection(newSelection), true); } } private void setViewerSelection(ISelection selection, boolean reveal) { settingSelection = true; try { viewer.setSelection(selection, reveal); } finally { selectionChanged = false; settingSelection = false; } } private void saveLastSelection() { final IDbManager dbManager = Core.getCore().getDbManager(); if (!viewer.getControl().isDisposed()) { final Meta meta = dbManager.getMeta(true); if (meta != null) { if (meta.getLastExpansion() == null) meta.setLastExpansion(new ArrayList<String>()); else meta.clearLastExpansion(); Object[] expandedElements = ((TreeViewer) viewer).getExpandedElements(); for (Object element : expandedElements) if (element instanceof IdentifiableObject) meta.addLastExpansion(element.toString()); Object firstElement = viewer.getStructuredSelection().getFirstElement(); SmartCollectionImpl selectedCollection = null; String lastSelection = null; if (firstElement instanceof IdentifiableObject) { if (firstElement instanceof SmartCollection) { for (IViewReference ref : getSite().getPage().getViewReferences()) { IViewPart view = ref.getView(false); if (view instanceof AbstractPresentationView && ((AbstractPresentationView) view).isVisible()) { String currentPresentationId = ((AbstractPresentationView) view) .getCurrentPresentation(); if (currentPresentationId != null) { selectedCollection = (SmartCollectionImpl) firstElement; lastSelection = currentPresentationId; break; } } } if (selectedCollection == null) lastSelection = firstElement.toString(); } else { lastSelection = firstElement.toString(); selectedCollection = getNavigationHistory().getSelectedCollection(); } meta.setLastCollection(selectedCollection == null ? null : selectedCollection.getStringId()); meta.setLastSelection(lastSelection); } dbManager.safeTransaction(null, meta); } } } private void restoreLastSelection() { // long time = System.currentTimeMillis(); IDbManager dbManager = Core.getCore().getDbManager(); Meta meta = dbManager.getMeta(true); if (meta != null) { String lastCollection = meta.getLastCollection(); final SmartCollectionImpl sc = lastCollection != null ? dbManager.obtainById(SmartCollectionImpl.class, lastCollection) : null; if (sc != null) { restoring = true; try { getNavigationHistory().fireSelection(null, new StructuredSelection(sc)); } finally { restoring = false; } } String lastSelection = meta.getLastSelection(); final IdentifiableObject sm = lastSelection != null ? dbManager.obtainById(IdentifiableObject.class, lastSelection) : null; List<String> lastExpansion = meta.getLastExpansion(); if (sm != null || lastExpansion != null) { if (sm != null) { restoring = true; try { getNavigationHistory().postSelection(initialSelection = new StructuredSelection(sm)); if (initialized) super.selectionChanged(null, initialSelection); } finally { restoring = false; } } if (lastExpansion != null) expansions = lastExpansion.toArray(); } } // System.out.println("restore: " + (System.currentTimeMillis() - // time)); } @Override protected void updateActions(IStructuredSelection selection, boolean force) { if (deleteAction != null) { super.updateActions(selection, force); boolean writable = !dbIsReadonly(); createGroup.setEnabled(writable); if (selection.isEmpty()) { deleteAction.setEnabled(false); cutCollection.setEnabled(false); copyCollection.setEnabled(false); createSlideShowAction.setEnabled(false); createWebGalleryAction.setEnabled(false); createExhibitionAction.setEnabled(false); createCollectionAction.setEnabled(false); createAlbumAction.setEnabled(false); addSubAlbumAction.setEnabled(false); addSubCollectionAction.setEnabled(false); addSubGroupAction.setEnabled(false); playSlideshowAction.setEnabled(false); refreshAction.setEnabled(false); } else { Object obj = selection.getFirstElement(); if ((obj instanceof GroupImpl)) { GroupImpl group = (GroupImpl) obj; boolean exhibition = !group.getExhibition().isEmpty(); boolean slideshow = !group.getSlideshow().isEmpty(); boolean webgallery = group.getWebGallery() != null && !group.getWebGallery().isEmpty(); boolean collection = !group.getRootCollection().isEmpty(); String groupId = group.getStringId(); if (!exhibition && !slideshow && !webgallery && !collection) { exhibition = Constants.GROUP_ID_EXHIBITION.equals(groupId); slideshow = Constants.GROUP_ID_SLIDESHOW.equals(groupId); webgallery = Constants.GROUP_ID_WEBGALLERY.equals(groupId); if (!exhibition && !slideshow && !webgallery) collection = exhibition = slideshow = webgallery = true; } addSubGroupAction.setEnabled((!group.getSystem() || isPersonGroup(group)) && writable); createWebGalleryAction.setEnabled(webgallery && writable); createSlideShowAction.setEnabled(slideshow && writable); createExhibitionAction.setEnabled(exhibition && writable); createCollectionAction.setEnabled(collection && writable); createAlbumAction.setEnabled(collection && writable); deleteAction.setEnabled(!hasChildren(group) && !group.getSystem() && writable); cutCollection.setEnabled(false); copyCollection.setEnabled(false); addSubCollectionAction.setEnabled(false); addSubAlbumAction.setEnabled(false); refreshAction.setEnabled(true); } else { refreshAction.setEnabled(false); addSubGroupAction.setEnabled(false); createSlideShowAction.setEnabled(false); createExhibitionAction.setEnabled(false); createWebGalleryAction.setEnabled(false); createCollectionAction.setEnabled(false); createAlbumAction.setEnabled(false); if (obj instanceof SmartCollection) { SmartCollection coll = (SmartCollection) obj; boolean enabled = !coll.getSystem() && writable; boolean deleteEnabled = enabled; if (!enabled) { deleteEnabled = coll.getName() == null || coll.getName().isEmpty(); if (!deleteEnabled) { String collId = coll.getStringId(); String key = QueryField.URI.getKey() + '='; if (collId.startsWith(key)) try { deleteEnabled = !new File(new URI(collId.substring(key.length()))).exists(); } catch (URISyntaxException e) { deleteEnabled = true; } } } deleteAction.setEnabled(deleteEnabled); cutCollection.setEnabled(enabled); copyCollection.setEnabled(enabled); boolean isFinal = (coll.getCriterion().size() == 1 && coll.getCriterion(0).getField().startsWith("*")); //$NON-NLS-1$ addSubCollectionAction.setEnabled(!isFinal && writable); addSubAlbumAction.setEnabled(!coll.getSystem() && coll.getAlbum() && writable); } else { deleteAction.setEnabled(writable); cutCollection.setEnabled(writable); copyCollection.setEnabled(writable); addSubCollectionAction.setEnabled(false); } } } Object contents = clipboard.getContents(LocalSelectionTransfer.getTransfer()); pasteCollection.setEnabled((contents instanceof IStructuredSelection && ((IStructuredSelection) contents).getFirstElement() instanceof SmartCollectionImpl) && writable); } } private static boolean isPersonGroup(Group group) { Group root = getRoot(group); return root == null ? false : root.getStringId().equals(Constants.GROUP_ID_PERSONS); } private static Group getRoot(Group group) { if (group != null) while (group.getGroup_subgroup_parent() != null) group = group.getGroup_subgroup_parent(); return group; } private static boolean isPersonFolder(SmartCollection sm) { return sm.getSystem() && sm.getAlbum(); } @Override protected void setInput() { if (catOpen) { Shell shell = getSite().getWorkbenchWindow().getShell(); StringBuilder sb = new StringBuilder(shell.getText()); int p = sb.indexOf(" - "); //$NON-NLS-1$ if (p >= 0) sb.setLength(p); sb.append(" - ").append(Core.getCore().getDbManager().getFileName()); //$NON-NLS-1$ shell.setText(sb.toString()); super.setInput(); } } @Override public void refresh() { if (catOpen && isVisible()) { // long time = System.currentTimeMillis(); Object[] expandedElements = expansions != null ? expansions : ((TreeViewer) viewer).getExpandedElements(); expansions = null; viewer.setInput(GroupImpl.class); if (expandedElements != null && !restoring) { ((TreeViewer) viewer).setExpandedElements(expandedElements); setSelection(initialSelection == null ? viewer.getSelection() : initialSelection); initialSelection = null; } initialized = true; // System.out.println("cat:" + // (System.currentTimeMillis()-time)); } } @Override protected void setVisible(boolean visible) { if (isVisible() != visible) { super.setVisible(visible); if (visible && !initialized) refresh(); } } @Override public void dispose() { if (clipboard != null) clipboard.dispose(); super.dispose(); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); new UndoRedoActionGroup(getViewSite(), PlatformUI.getWorkbench().getOperationSupport().getUndoContext(), true).fillActionBars(bars); } private void fillLocalPullDown(IMenuManager manager) { manager.add(createGroup); manager.add(new Separator()); manager.add(editItemAction); manager.add(deleteAction); manager.add(new Separator()); manager.add(propertiesAction); manager.add(new Separator()); manager.add(filterAction); manager.add(expandAction); manager.add(collapseAction); } @Override protected void fillContextMenu(IMenuManager manager) { updateActions((IStructuredSelection) getSelection(), false); boolean readOnly = dbIsReadonly(); if (!readOnly) { addEnabled(manager, addSubGroupAction); addEnabled(manager, createCollectionAction); addEnabled(manager, addSubCollectionAction); addEnabled(manager, createAlbumAction); addEnabled(manager, addSubAlbumAction); if (createExhibitionAction.isEnabled() && createSlideShowAction.isEnabled() && createWebGalleryAction.isEnabled()) { MenuManager subMenu = new MenuManager(Messages.getString("CatalogView.create_new_presentation"), //$NON-NLS-1$ "new_presentation"); //$NON-NLS-1$ manager.add(subMenu); subMenu.add(createExhibitionAction); subMenu.add(createSlideShowAction); subMenu.add(createWebGalleryAction); } else { addEnabled(manager, createExhibitionAction); addEnabled(manager, createSlideShowAction); addEnabled(manager, createWebGalleryAction); } addEnabled(manager, refreshAction); } manager.add(new Separator()); super.fillContextMenu(manager); if (!readOnly) { manager.add(new Separator()); addEnabled(manager, cutCollection); addEnabled(manager, copyCollection); addEnabled(manager, pasteCollection); addEnabled(manager, deleteAction); } manager.add(new Separator()); drillDownAdapter.addNavigationActions(manager); // Other plug-ins can contribute there actions here manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } private void fillLocalToolBar(IToolBarManager manager) { manager.add(propertiesAction); manager.add(new Separator()); manager.add(createGroup); manager.add(editItemAction); manager.add(deleteAction); manager.add(new Separator()); manager.add(expandAction); manager.add(collapseAction); manager.add(filterAction); manager.add(new Separator()); drillDownAdapter.addNavigationActions(manager); } @Override protected void makeActions() { super.makeActions(); createGroup = new Action(Messages.getString("CatalogView.create_new_group"), //$NON-NLS-1$ Icons.newGroup.getDescriptor()) { @Override public void run() { GroupDialog dialog = new GroupDialog(getSite().getShell(), null, null); if (dialog.open() == Window.OK) { GroupImpl group = new GroupImpl(dialog.getName(), false, Constants.INHERIT_LABEL, null, 0, null); group.setAnnotations(dialog.getAnnotations()); group.setShowLabel(dialog.getShowLabel()); group.setLabelTemplate(dialog.getLabelTemplate()); Core.getCore().getDbManager().safeTransaction(null, group); setInput(); setViewerSelection(new StructuredSelection(group), true); } } }; createGroup.setToolTipText(Messages.getString("CatalogView.creates_a_group_for_collections")); //$NON-NLS-1$ createSlideShowAction = new Action(Messages.getString("CatalogView.create_new_slide_show"), //$NON-NLS-1$ Icons.newSlideshow.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { SlideshowEditDialog dialog = new SlideshowEditDialog(getSite().getShell(), (GroupImpl) obj, null, Messages.getString("CatalogView.create_slideshow"), //$NON-NLS-1$ false, false); if (dialog.open() == Window.OK) { SlideShowImpl result = dialog.getResult(); ((TreeViewer) viewer).add(obj, result); setViewerSelection(new StructuredSelection(result), true); openSlideShowEditor(result, true); } } } }; createSlideShowAction.setToolTipText(Messages.getString("CatalogView.creates_a_new_slideshow")); //$NON-NLS-1$ createExhibitionAction = new Action(Messages.getString("CatalogView.create_new_exhibition"), //$NON-NLS-1$ Icons.exhibition.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { ExhibitionImpl show = ExhibitionEditDialog.open(getSite().getShell(), (GroupImpl) obj, null, Messages.getString("CatalogView.create_exhibition"), false, null); //$NON-NLS-1$ if (show != null) { ((TreeViewer) viewer).add(obj, show); setViewerSelection(new StructuredSelection(show), true); openExhibitionEditor(show, true); } } } }; createExhibitionAction.setToolTipText(Messages.getString("CatalogView.creates_a_new_exhibition")); //$NON-NLS-1$ createWebGalleryAction = new Action(Messages.getString("CatalogView.create_web_gallery"), //$NON-NLS-1$ Icons.webGallery.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { WebGalleryImpl result = WebGalleryEditDialog.openWebGalleryEditDialog(getSite().getShell(), (GroupImpl) obj, null, Messages.getString("CatalogView.web_gallery"), false, false, //$NON-NLS-1$ null); if (result != null) { ((TreeViewer) viewer).add(obj, result); setViewerSelection(new StructuredSelection(result), true); openWebGalleryEditor(result, true); } } } }; createWebGalleryAction.setToolTipText(Messages.getString("CatalogView.creates_a_new_web_gallery")); //$NON-NLS-1$ createAlbumAction = new Action(Messages.getString("CatalogView.create_new_album"), //$NON-NLS-1$ Icons.addAlbum.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { CollectionEditDialog dialog = new CollectionEditDialog(getSite().getShell(), null, Messages.getString("CatalogView.create_album"), //$NON-NLS-1$ Messages.getString("CatalogView.albums_msg"), //$NON-NLS-1$ false, true, false, false); if (dialog.open() == Window.OK) insertCollection(dialog.getResult(), (GroupImpl) obj); } } }; createAlbumAction.setToolTipText(Messages.getString("CatalogView.create_album_tooltip")); //$NON-NLS-1$ addSubGroupAction = new Action(Messages.getString("CatalogView.add_subroup"), //$NON-NLS-1$ Icons.newGroup.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof Group) { Group parent = (Group) obj; if (!parent.getSystem() || isPersonGroup(parent)) { GroupDialog dialog = new GroupDialog(getSite().getShell(), null, parent); if (dialog.open() == Window.OK) { Group group = new GroupImpl(dialog.getName(), false, Constants.INHERIT_LABEL, null, 0, null); group.setAnnotations(dialog.getAnnotations()); group.setShowLabel(dialog.getShowLabel()); group.setLabelTemplate(dialog.getLabelTemplate()); group.setGroup_subgroup_parent(parent); List<Group> subgroups = parent.getSubgroup(); if (subgroups == null) parent.setSubgroup(Collections.singletonList(group)); else parent.addSubgroup(group); Core.getCore().getDbManager().safeTransaction(null, Utilities.storeGroup(parent, true, null)); setInput(); setViewerSelection(new StructuredSelection(group), true); } } } } }; addSubGroupAction.setToolTipText(Messages.getString("CatalogView.add_subgroup_tooltip")); //$NON-NLS-1$ addSubAlbumAction = new Action(Messages.getString("CatalogView.add_sub_album"), //$NON-NLS-1$ Icons.addAlbum.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof SmartCollection) { SmartCollection sm = (SmartCollection) obj; SmartCollection parent = sm.getSmartCollection_subSelection_parent(); if (sm.getAlbum() && !sm.getSystem()) { CollectionEditDialog dialog = new CollectionEditDialog(getSite().getShell(), null, NLS.bind(Messages.getString("CatalogView.add_sub_album"), parent.getName()), //$NON-NLS-1$ Messages.getString("CatalogView.albums_msg"), //$NON-NLS-1$ false, true, false, false); if (dialog.open() == Window.OK) addSubSelection((SmartCollection) obj, dialog.getResult()); } } } }; addSubAlbumAction.setToolTipText(Messages.getString("CatalogView.add_sub_album_tooltip")); //$NON-NLS-1$ createCollectionAction = new Action(Messages.getString("CatalogView.create_new_collection"), //$NON-NLS-1$ Icons.folder_add.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { CollectionEditDialog dialog = new CollectionEditDialog(getSite().getShell(), null, Messages.getString("CatalogView.create_collection"), //$NON-NLS-1$ Messages.getString("CatalogView.collection_msg"), //$NON-NLS-1$ false, false, false, Core.getCore().isNetworked()); if (dialog.open() == Window.OK) insertCollection(dialog.getResult(), (GroupImpl) obj); } } }; createCollectionAction.setToolTipText(Messages.getString("CatalogView.creates_a_new_root_collection")); //$NON-NLS-1$ addSubCollectionAction = new Action(Messages.getString("CatalogView.add_subselection"), //$NON-NLS-1$ Icons.addSubselection.getDescriptor()) { @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof SmartCollection) { SmartCollection parent = (SmartCollection) obj; CollectionEditDialog dialog = new CollectionEditDialog(getSite().getShell(), null, NLS.bind(Messages.getString("CatalogView.add_subselection"), parent.getName()), //$NON-NLS-1$ Messages.getString("CatalogView.collection_msg"), //$NON-NLS-1$ false, false, false, Core.getCore().isNetworked()); if (dialog.open() == Window.OK) addSubSelection(parent, dialog.getResult()); } } }; addSubCollectionAction.setToolTipText(Messages.getString("CatalogView.narrow_down_selection")); //$NON-NLS-1$ deleteAction = new Action(Messages.getString("CatalogView.delete"), Icons.folder_delete.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof SmartCollectionImpl) { SmartCollectionImpl current = (SmartCollectionImpl) obj; if (!current.getSystem()) { if (AcousticMessageDialog.openQuestion(getSite().getShell(), current.getAlbum() ? Messages.getString("CatalogView.delete_album") //$NON-NLS-1$ : Messages.getString("CatalogView.delete_collection"), //$NON-NLS-1$ current.getAlbum() ? Messages.getString("CatalogView.really_delete_album") //$NON-NLS-1$ : Messages.getString("CatalogView.really_delete_collection"))) //$NON-NLS-1$ deleteCollection(current); } else if (!current.getStringId().startsWith(IDbManager.URIKEY) && !current.getStringId().startsWith(IDbManager.VOLUMEKEY) || AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("CatalogView.delete_system_coll"), //$NON-NLS-1$ Messages.getString("CatalogView.delete_system_coll_msg"))) //$NON-NLS-1$ deleteCollection(current); } else if (obj instanceof SlideShowImpl) { SlideShowImpl current = (SlideShowImpl) obj; if (AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("CatalogView.delete_slideshow"), //$NON-NLS-1$ Messages.getString("CatalogView.really_delete_slideshow"))) //$NON-NLS-1$ deleteSlideshow(current); } else if (obj instanceof ExhibitionImpl) { ExhibitionImpl current = (ExhibitionImpl) obj; if (AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("CatalogView.delete_exhibition"), //$NON-NLS-1$ Messages.getString("CatalogView.really_delete_exhibition"))) //$NON-NLS-1$ deleteExhibition(current); } else if (obj instanceof WebGalleryImpl) { WebGalleryImpl current = (WebGalleryImpl) obj; if (AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("CatalogView.delete_web_gallery"), //$NON-NLS-1$ Messages.getString("CatalogView.do_you_really_want_to_delete"))) //$NON-NLS-1$ deleteWebGallery(current); } else if (obj instanceof GroupImpl) { final GroupImpl current = (GroupImpl) obj; if (!current.getSystem() && AcousticMessageDialog.openQuestion(getSite().getShell(), Messages.getString("CatalogView.delete_group"), //$NON-NLS-1$ hasChildren(current) ? Messages.getString("CatalogView.delete_group_with_contents") //$NON-NLS-1$ : Messages.getString("CatalogView.really_delete_group"))) //$NON-NLS-1$ deleteGroup(current); } } }; deleteAction.setToolTipText(Messages.getString("CatalogView.delete_selected_item")); //$NON-NLS-1$ cutCollection = new Action(Messages.getString("CatalogView.cut"), Icons.cut.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof SmartCollectionImpl) { copyCollection.run(); deleteCollection((SmartCollectionImpl) obj); } } }; cutCollection.setToolTipText(Messages.getString("CatalogView.cut_selected_item")); //$NON-NLS-1$ copyCollection = new Action(Messages.getString("CatalogView.copy"), Icons.copy.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { IStructuredSelection selection = viewer.getStructuredSelection(); Object obj = selection.getFirstElement(); if (obj instanceof SmartCollection) { selectionTransfer.setSelection(selection); clipboard.setContents(new Object[] { obj }, selectionTypes, DND.CLIPBOARD); pasteCollection.setEnabled(true); } } }; copyCollection.setToolTipText(Messages.getString("CatalogView.copy_selected_item")); //$NON-NLS-1$ pasteCollection = new Action(Messages.getString("CatalogView.paste"), Icons.paste.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { Object obj = viewer.getStructuredSelection().getFirstElement(); if (obj instanceof GroupImpl) { Object contents = clipboard.getContents(selectionTransfer); if (contents instanceof IStructuredSelection) { Object o = ((IStructuredSelection) contents).getFirstElement(); if (o instanceof SmartCollectionImpl) insertCollection(cloneCollection((SmartCollectionImpl) o), (GroupImpl) obj); else if (o instanceof SlideShowImpl) { SlideShowImpl newSm = SlideshowPropertiesOperation.cloneSlideshow((SlideShowImpl) o); final GroupImpl group = (GroupImpl) obj; group.addSlideshow(newSm.getStringId()); newSm.setGroup_slideshow_parent(group.getStringId()); Core.getCore().getDbManager().safeTransaction(null, group); ((TreeViewer) viewer).add(group, newSm); setViewerSelection(new StructuredSelection(newSm), true); openSlideShowEditor(newSm, true); } } } else if (obj instanceof SmartCollection) { SmartCollectionImpl parent = (SmartCollectionImpl) obj; Object contents = clipboard.getContents(selectionTransfer); if (contents instanceof IStructuredSelection) { Object o = ((IStructuredSelection) contents).getFirstElement(); if (o instanceof SmartCollectionImpl) addSubSelection(parent, cloneCollection((SmartCollectionImpl) o)); } } } private SmartCollectionImpl cloneCollection(SmartCollectionImpl oldSm) { SmartCollectionImpl newSm = new SmartCollectionImpl(oldSm.getName(), false, oldSm.getAlbum(), oldSm.getAdhoc(), oldSm.getNetwork(), null, oldSm.getColorCode(), oldSm.getLastAccessDate(), 0, oldSm.getPerspective(), oldSm.getShowLabel(), oldSm.getLabelTemplate(), oldSm.getFontSize(), null); for (Criterion oldCrit : oldSm.getCriterion()) newSm.addCriterion(new CriterionImpl(oldCrit.getField(), oldCrit.getSubfield(), oldCrit.getValue(), oldCrit.getRelation(), oldCrit.getAnd())); for (SortCriterion oldCrit : oldSm.getSortCriterion()) newSm.addSortCriterion(new SortCriterionImpl(oldCrit.getField(), oldCrit.getSubfield(), oldCrit.getDescending())); return newSm; } }; pasteCollection.setToolTipText(Messages.getString("CatalogView.paste_selected_item")); //$NON-NLS-1$ expandAction = new Action(Messages.getString("CatalogView.expand_all"), Icons.expandAll.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { ((TreeViewer) viewer).expandAll(); } }; expandAction.setToolTipText(Messages.getString("CatalogView.expand_all_tooltip")); //$NON-NLS-1$ collapseAction = new Action(Messages.getString("CatalogView.collapse_all"), //$NON-NLS-1$ Icons.collapseAll.getDescriptor()) { @Override public void run() { ((TreeViewer) viewer).collapseAll(); } }; collapseAction.setToolTipText(Messages.getString("CatalogView.collapse_all_tree_items")); //$NON-NLS-1$ propertiesAction = new Action(Messages.getString("CatalogView.properties"), //$NON-NLS-1$ Icons.properties.getDescriptor()) { @Override public void run() { IDbManager dbManager = Core.getCore().getDbManager(); if (dbManager.getFile() != null) BusyIndicator.showWhile(getSite().getShell().getDisplay(), () -> { new EditMetaDialog(getSite().getShell(), getSite().getPage(), dbManager, false, null) .open(); }); } }; propertiesAction.setToolTipText(Messages.getString("CatalogView.edit_catalog_properties")); //$NON-NLS-1$ filterAction = new Action(Messages.getString("CatalogView.filter"), Icons.catFilter.getDescriptor()) { //$NON-NLS-1$ @Override public void run() { FilterDialog filterDialog = new FilterDialog(getSite().getShell(), colorCode, ALLCATITEMS, hiddenCatItems, CATITEMLABELS); if (filterDialog.open() == Dialog.OK) { colorCode = filterDialog.getColorCode(); Icon icon = Icons.catFilter; Image image = (colorCode <= Constants.COLOR_UNDEFINED) ? icon.getImage() : icon.getColorOverlay(colorCode); filterAction.setImageDescriptor(ImageDescriptor.createFromImage(image)); viewer.refresh(); } } }; filterAction.setToolTipText(Messages.getString("CatalogView.filters_tooltip")); //$NON-NLS-1$ refreshAction = new Action(Messages.getString("CatalogView.remove_empty")) { //$NON-NLS-1$ @Override public void run() { Object firstElement = ((IStructuredSelection) getSelection()).getFirstElement(); if (firstElement instanceof Group) BusyIndicator.showWhile(getSite().getShell().getDisplay(), () -> new PurgeEmptyDialog(getSite().getShell(), (Group) firstElement).open()); } }; refreshAction.setToolTipText(Messages.getString("CatalogView.remove_empty_tooltip")); //$NON-NLS-1$ } @Override protected void registerCommands() { registerCommand(propertiesAction, IZoomCommandIds.PropertiesCommand); registerCommand(pasteCollection, IWorkbenchCommandConstants.EDIT_PASTE); registerCommand(copyCollection, IWorkbenchCommandConstants.EDIT_COPY); registerCommand(cutCollection, IWorkbenchCommandConstants.EDIT_CUT); registerCommand(deleteAction, IZoomCommandIds.DeleteCommand); registerCommand(refreshAction, IZoomCommandIds.RefreshCommand); super.registerCommands(); } private static boolean hasChildren(final GroupImpl group) { return group.getSubgroup() != null && !group.getSubgroup().isEmpty() || group.getExhibition() != null && !group.getExhibition().isEmpty() || group.getSlideshow() != null && !group.getSlideshow().isEmpty() || group.getWebGallery() != null && !group.getWebGallery().isEmpty() || group.getRootCollection() != null && !group.getRootCollection().isEmpty(); } protected void deleteGroup(Group current) { Set<Object> toBeStored = new HashSet<Object>(); Set<Object> toBeDeleted = new HashSet<Object>(); IDbManager dbManager = Core.getCore().getDbManager(); doDeleteGroup(current, toBeStored, toBeDeleted, dbManager); dbManager.safeTransaction(toBeDeleted, toBeStored); ((TreeViewer) viewer).remove(current); } private void doDeleteGroup(Group current, Set<Object> toBeStored, Set<Object> toBeDeleted, IDbManager dbManager) { List<String> exhibitions = current.getExhibition(); if (exhibitions != null) for (String id : exhibitions) { ExhibitionImpl exhibition = dbManager.obtainById(ExhibitionImpl.class, id); if (exhibition != null) doDeleteExhibition(exhibition, toBeStored, toBeDeleted, dbManager); } List<String> slideshows = current.getSlideshow(); if (slideshows != null) for (String id : slideshows) { SlideShowImpl slideshow = dbManager.obtainById(SlideShowImpl.class, id); if (slideshow != null) doDeleteSlideshow(slideshow, toBeStored, toBeDeleted, dbManager); } List<String> galleries = current.getWebGallery(); if (galleries != null) for (String id : galleries) { WebGalleryImpl gallery = dbManager.obtainById(WebGalleryImpl.class, id); if (gallery != null) doDeleteWebGallery(gallery, toBeStored, toBeDeleted, dbManager); } List<String> collections = current.getRootCollection(); if (collections != null) for (String id : collections) { SmartCollectionImpl sm = dbManager.obtainById(SmartCollectionImpl.class, id); if (sm != null) doDeleteCollection(sm, toBeStored, toBeDeleted, dbManager); } List<Group> subgroups = current.getSubgroup(); if (subgroups != null) for (Group subgroup : subgroups) doDeleteGroup(subgroup, toBeStored, toBeDeleted, dbManager); Group parent = current.getGroup_subgroup_parent(); if (parent != null && parent.getSubgroup() != null) parent.removeSubgroup(current); toBeDeleted.add(current); toBeStored.add(parent); } private void deleteWebGallery(final WebGalleryImpl gallery) { Set<Object> toBeStored = new HashSet<Object>(); Set<Object> toBeDeleted = new HashSet<Object>(); final IDbManager dbManager = Core.getCore().getDbManager(); Object sibling = doDeleteWebGallery(gallery, toBeStored, toBeDeleted, dbManager); dbManager.safeTransaction(toBeDeleted, toBeStored); refresh(); if (sibling != null) setViewerSelection(new StructuredSelection(sibling), true); tellHistoryView(gallery); } private Object doDeleteWebGallery(final WebGalleryImpl gallery, Set<Object> toBeStored, Set<Object> toBeDeleted, final IDbManager dbManager) { final Object parent = getParent(gallery); Object sibling = getSibling(parent, gallery); for (Storyboard storyboard : gallery.getStoryboard()) { toBeDeleted.addAll(dbManager.obtainByIds(WebExhibitImpl.class, storyboard.getExhibit())); toBeDeleted.add(storyboard); } for (WebParameter parameter : gallery.getParameter().values()) toBeDeleted.add(parameter); toBeDeleted.add(gallery); if (parent instanceof GroupImpl) { ((GroupImpl) parent).removeWebGallery(gallery.getStringId()); toBeStored.add(parent); } return sibling; } protected void addDragDropClipboard(Control control) { clipboard = new Clipboard(control.getDisplay()); } @Override public void setFocus() { getControl().setFocus(); } public ISelection getSelection() { return viewer.getSelection(); } public void setSelection(ISelection selection) { if (selection instanceof IStructuredSelection) { Object firstElement = ((IStructuredSelection) selection).getFirstElement(); if ((firstElement instanceof SlideShow && ((SlideShow) firstElement).getAdhoc()) || (firstElement instanceof SmartCollection && ((SmartCollection) firstElement).getAdhoc())) selection = StructuredSelection.EMPTY; setViewerSelection(selection, selectionChanged); updateActions((IStructuredSelection) selection, false); } } private void addSubSelection(final SmartCollection parent, SmartCollection subSelection) { parent.addSubSelection(subSelection); Core.getCore().getDbManager().safeTransaction(null, parent); ((TreeViewer) viewer).add(parent, subSelection); ((TreeViewer) viewer).expandToLevel(subSelection, 1); setViewerSelection(new StructuredSelection(subSelection), true); } private void deleteCollection(final SmartCollectionImpl collection) { Set<Object> toBeStored = new HashSet<Object>(); Set<Object> toBeDeleted = new HashSet<Object>(); final IDbManager dbManager = Core.getCore().getDbManager(); Object sibling = doDeleteCollection(collection, toBeDeleted, toBeStored, dbManager); dbManager.safeTransaction(toBeDeleted, toBeStored); refresh(); if (sibling != null) { StructuredSelection selection = new StructuredSelection(sibling); setViewerSelection(selection, true); cancelJobs(this); new SelectionJob(viewer, new SelectionChangedEvent(this, selection)).schedule(); } tellHistoryView(collection); } private void tellHistoryView(IdentifiableObject obj) { HistoryView historyView = (HistoryView) getSite().getPage().findView(HistoryView.ID); if (historyView != null) historyView.removeItem(obj); } private Object doDeleteCollection(final SmartCollectionImpl collection, Set<Object> toBeDeleted, Set<Object> toBeStored, final IDbManager dbManager) { if (collection.getAlbum()) { if (!collection.getCriterion().isEmpty()) { List<String> assetIds = collection.getAsset(); if (assetIds != null) { List<AssetImpl> set = dbManager.obtainByIds(AssetImpl.class, assetIds); if (!set.isEmpty()) OperationJob.executeOperation(new RemoveAlbumOperation(collection, set), this); } } } final Object parent = getParent(collection); Object sibling = getSibling(parent, collection); Utilities.deleteCollection(collection, true, toBeDeleted); if (parent instanceof SmartCollection) { ((SmartCollection) parent).removeSubSelection(collection); toBeStored.add(parent); } else if (parent instanceof GroupImpl) { ((GroupImpl) parent).removeRootCollection(collection.getStringId()); toBeStored.add(parent); } return sibling; } private Object getParent(Object obj) { return ((ITreeContentProvider) viewer.getContentProvider()).getParent(obj); } private Object getSibling(Object parent, Object obj) { if (parent != null) { Object[] children = ((ITreeContentProvider) viewer.getContentProvider()).getChildren(parent); for (int i = 0; i < children.length; i++) if (children[i] == obj) { if (i < children.length - 1) return children[i + 1]; if (i > 0) return children[i - 1]; } } return parent; } private void deleteSlideshow(final SlideShowImpl slideshow) { Set<Object> toBeStored = new HashSet<Object>(); Set<Object> toBeDeleted = new HashSet<Object>(); final IDbManager dbManager = Core.getCore().getDbManager(); Object sibling = doDeleteSlideshow(slideshow, toBeDeleted, toBeStored, dbManager); dbManager.safeTransaction(toBeDeleted, toBeStored); refresh(); if (sibling != null) setViewerSelection(new StructuredSelection(sibling), true); tellHistoryView(slideshow); } private Object doDeleteSlideshow(final SlideShowImpl slideshow, Set<Object> toBeDeleted, Set<Object> toBeStored, final IDbManager dbManager) { final Object parent = getParent(slideshow); Object sibling = getSibling(parent, slideshow); toBeDeleted.addAll(dbManager.obtainByIds(SlideImpl.class, slideshow.getEntry())); toBeDeleted.add(slideshow); if (parent instanceof GroupImpl) { ((GroupImpl) parent).removeSlideshow(slideshow.getStringId()); toBeStored.add(parent); } return sibling; } private void deleteExhibition(final ExhibitionImpl exhibition) { Set<Object> toBeStored = new HashSet<Object>(); Set<Object> toBeDeleted = new HashSet<Object>(); final IDbManager dbManager = Core.getCore().getDbManager(); Object sibling = doDeleteExhibition(exhibition, toBeStored, toBeDeleted, dbManager); dbManager.safeTransaction(toBeDeleted, toBeStored); refresh(); if (sibling != null) setViewerSelection(new StructuredSelection(sibling), true); tellHistoryView(exhibition); } private Object doDeleteExhibition(final ExhibitionImpl exhibition, Set<Object> toBeStored, Set<Object> toBeDeleted, final IDbManager dbManager) { final Object parent = getParent(exhibition); Object sibling = getSibling(parent, exhibition); for (Wall wall : exhibition.getWall()) { toBeDeleted.addAll(dbManager.obtainByIds(ExhibitImpl.class, wall.getExhibit())); toBeDeleted.add(wall); } toBeDeleted.add(exhibition); if (parent instanceof GroupImpl) { ((GroupImpl) parent).removeExhibition(exhibition.getStringId()); toBeStored.add(parent); } return sibling; } private void insertCollection(final SmartCollectionImpl result, final GroupImpl group) { final IDbManager dbManager = Core.getCore().getDbManager(); group.addRootCollection(result.getStringId()); result.setGroup_rootCollection_parent(group.getStringId()); dbManager.safeTransaction(() -> { dbManager.store(result); dbManager.store(group); }); ((TreeViewer) viewer).add(group, result); setViewerSelection(new StructuredSelection(result), true); } @Override public Object findObject(MouseEvent event) { findingPoint.x = event.x; findingPoint.y = event.y; ViewerCell cell = viewer.getCell(findingPoint); return cell == null ? null : cell.getElement(); } @Override public IGalleryHover getGalleryHover(MouseEvent event) { return null; } public Control getControl() { return viewer.getControl(); } @Override public boolean assetsChanged() { return false; } @Override public boolean collectionChanged() { return true; } @Override public boolean selectionChanged() { return true; } @Override public void collectionChanged(IWorkbenchPart part, IStructuredSelection selection) { if (part != this && selection != null && !selection.isEmpty()) setViewerSelection(selection, true); } }