/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2016 University of Dundee. All rights reserved. * * * This program 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. * This program 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 this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.dataBrowser.view; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Point; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.openmicroscopy.shoola.agents.dataBrowser.DataBrowserAgent; import org.openmicroscopy.shoola.agents.dataBrowser.browser.Browser; import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageDisplay; import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageDisplayVisitor; import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageNode; import org.openmicroscopy.shoola.agents.dataBrowser.browser.Thumbnail; import org.openmicroscopy.shoola.agents.dataBrowser.browser.WellSampleNode; import org.openmicroscopy.shoola.agents.dataBrowser.layout.Layout; import org.openmicroscopy.shoola.agents.dataBrowser.visitor.MagnificationVisitor; import org.openmicroscopy.shoola.agents.events.iviewer.ViewImage; import org.openmicroscopy.shoola.agents.events.iviewer.ViewImageObject; import org.openmicroscopy.shoola.env.config.Registry; import org.openmicroscopy.shoola.env.data.model.ApplicationData; import org.openmicroscopy.shoola.env.data.util.FilterContext; import org.openmicroscopy.shoola.env.event.EventBus; import org.openmicroscopy.shoola.util.ui.ScrollablePanel; import org.openmicroscopy.shoola.util.ui.UIUtilities; import org.openmicroscopy.shoola.util.ui.search.SearchObject; import omero.gateway.model.DataObject; import omero.gateway.model.ImageData; /** * The {@link DataBrowser}'s View. Embeds the <code>Browser</code>'s UI. * Also provides a menu bar and a status bar. * * @see Browser * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since OME3.0 */ class DataBrowserUI extends ScrollablePanel//JPanel { /** ID to select the thumbnail view. */ static final int THUMB_VIEW = 0; /** ID to select the columns view. */ static final int COLUMNS_VIEW = 1; /** ID to select the fields view. */ static final int FIELDS_VIEW = 2; /** ID to select the search view. */ static final int SEARCH_VIEW = 3; /** ID to sort the node alphabetically. */ static final int SORT_BY_NAME = 2; /** ID to sort the node by date. */ static final int SORT_BY_DATE = 3; /** Reference to the tool bar. */ private DataBrowserToolBar toolBar; /** Reference to the tool bar for Plates. */ private DataBrowserWellToolBar wellToolBar; /** Reference to the tool bar. */ private DataBrowserStatusBar statusBar; /** Reference to the tool bar. */ private PlateGridUI plateGridUI; /** Reference to the model. */ private DataBrowserModel model; /** Reference to the control. */ private DataBrowserControl controller; /** The slide show view. */ private SlideShowView slideShowView; /** The selected view. */ private int selectedView; /** The pop-up menu. */ private PopupMenu popupMenu; /** Component displaying the fields. */ private WellFieldsView fieldsView; /** The magnification factor. */ private double factor; /** Creates a new instance. */ DataBrowserUI() { super(true); } /** * Links the components composing the MVC triad. * * @param model Reference to the model. * Mustn't be <code>null</code>. * @param controller Reference to the control. * Mustn't be <code>null</code>. */ void initialize(DataBrowserModel model, DataBrowserControl controller) { if (model == null) throw new IllegalArgumentException("No model."); if (controller == null) throw new IllegalArgumentException("No control."); this.model = model; this.controller = controller; //if (model.getType() == DataBrowserModel.WELLS) wellToolBar = new DataBrowserWellToolBar(this, controller); toolBar = new DataBrowserToolBar(model, this, controller); if (model.getType() == DataBrowserModel.WELLS) plateGridUI = new PlateGridUI((WellsModel) model, controller); statusBar = new DataBrowserStatusBar(this); if (model.getType() == DataBrowserModel.SEARCH) { selectedView = SEARCH_VIEW; } else { selectedView = THUMB_VIEW; } factor = DataBrowserFactory.getThumbnailScaleFactor(); setNumberOfImages(-1); setLayout(new BorderLayout(0, 0)); buildGUI(true); } /** * Builds and lays out the UI. * * @param full Pass <code>true</code> to add all the components, * <code>false</code> otherwise. */ void buildGUI(boolean full) { removeAll(); if (full) { if (model.getType() == DataBrowserModel.WELLS) { add(wellToolBar, BorderLayout.NORTH); } else { add(toolBar, BorderLayout.NORTH); } add(statusBar, BorderLayout.SOUTH); statusBar.setVisible(model.getType() != DataBrowserModel.SEARCH); } add(model.getBrowser().getUI(), BorderLayout.CENTER); } /** * Returns the grid representing the plate. * * @return See above. */ PlateGridUI getGridUI() { return plateGridUI; } /** * Returns the selected object in order to filter the node. * * @return See above. */ SearchObject getSelectedFilter() { return toolBar.getSelectedFilter(); } /** * Returns the collection of existing tags. * * @return See above. */ Collection getExistingTags() { return model.getExistingTags(); } /** * Updates the UI elements when the tags are loaded. * * @param tags The collection of tags to display. */ void setTags(Collection tags) { toolBar.setTags(tags); } /** * Creates or deletes the slide show view. * * @param create Pass <code>true</code> to create a new dialog, * <code>false</code> to delete it. */ void slideShowView(boolean create) { toolBar.enableSlideShow(!create); if (!create) { if (slideShowView != null) { model.cancelSlideShow(); slideShowView.close(); } return; } //if (slideShowView != null) return; Browser browser = model.getBrowser(); List<ImageNode> nodes; Iterator i; Collection selected = browser.getSelectedDisplays(); if (selected != null && selected.size() > 0) { nodes = new ArrayList<ImageNode>(); i = selected.iterator(); Object n; while (i.hasNext()) { n = i.next(); if (n instanceof ImageNode) nodes.add((ImageNode) n); } } else { nodes = browser.getVisibleImageNodes(); } if (nodes == null || nodes.size() == 0) { toolBar.enableSlideShow(true); return; } List<ImageNode> selection = new ArrayList<ImageNode>(nodes.size()); ImageNode n; i = nodes.iterator(); while (i.hasNext()) { n = (ImageNode) i.next(); selection.add(n.copy()); } Registry reg = DataBrowserAgent.getRegistry(); slideShowView = new SlideShowView(reg.getTaskBar().getFrame(), selection); slideShowView.addPropertyChangeListener(controller); model.fireFullSizeLoading(selection); UIUtilities.centerAndShow(slideShowView); if (model.getState() != DataBrowser.LOADING_SLIDE_VIEW) setSlideViewStatus(true, -1); } /** * Adjusts the status bar according to the specified arguments. * * @param hideProgressBar Whether or not to hide the progress bar. * @param progressPerc The percentage value the progress bar should * display. If negative, it is interpreted as * not available and the progress bar will be * set to indeterminate mode. This argument is * only taken into consideration if the progress * bar shouldn't be hidden. */ void setSlideViewStatus(boolean hideProgressBar, int progressPerc) { if (slideShowView != null) slideShowView.setProgress(hideProgressBar, progressPerc); } /** * Returns <code>true</code> if the roll flag is on, <code>false</code> * otherwise. * * @return See above. */ boolean isRollOver() { return model.isRollOver(); } /** Lays out the selected component. */ void layoutUI() { switch (selectedView) { case THUMB_VIEW: Browser b = model.getBrowser(); model.layoutBrowser(); b.getUI().repaint(); break; case COLUMNS_VIEW: ImageTableView v = model.getTableView(); if (v != null) v.refreshTable(); break; case SEARCH_VIEW: SearchResultView sv = model.getSearchView(); if (sv != null) sv.refreshTable(); break; } } /** * Sets the selected view. * * @param index The value to set. */ void setSelectedView(int index) { removeAll(); double f = DataBrowserFactory.getThumbnailScaleFactor(); switch (index) { case THUMB_VIEW: selectedView = index; if (model.getType() == DataBrowserModel.WELLS) { add(wellToolBar, BorderLayout.NORTH); wellToolBar.displayFieldsOptions(false); } else { add(toolBar, BorderLayout.NORTH); layoutUI(); } add(model.getBrowser().getUI(), BorderLayout.CENTER); f = factor; break; case FIELDS_VIEW: selectedView = index; add(wellToolBar, BorderLayout.NORTH); if (fieldsView == null) { f = Thumbnail.MAX_SCALING_FACTOR; fieldsView = new WellFieldsView((WellsModel) model, controller, f);//statusBar.getMagnificationFactor()); } wellToolBar.displayFieldsOptions(true); add(fieldsView, BorderLayout.CENTER); f = fieldsView.getMagnification(); break; case COLUMNS_VIEW: selectedView = index; add(toolBar, BorderLayout.NORTH); ImageTableView existed = model.getTableView(); ImageTableView v = model.createImageTableView(); if (existed != null && v != null) v.refreshTable(); //if (existed == null) { Collection nodes = model.getBrowser().getSelectedDisplays(); if (nodes != null) { Iterator i = nodes.iterator(); List<DataObject> objects = new ArrayList<DataObject>(); ImageDisplay display; Object ho; while (i.hasNext()) { display = (ImageDisplay) i.next(); ho = display.getHierarchyObject(); if (ho instanceof DataObject) objects.add((DataObject) ho); } v.setSelectedNodes(objects); } //} if (existed == null) v.addPropertyChangeListener(controller); v.validate(); v.repaint(); add(v, BorderLayout.CENTER); break; case SEARCH_VIEW: selectedView = index; SearchResultView sv = model.createSearchResultView(); sv.addPropertyChangeListener(controller); add(sv, BorderLayout.CENTER); sv.refreshTable(); break; } add(statusBar, BorderLayout.SOUTH); toolBar.setSelectedViewIndex(selectedView); statusBar.setSelectedViewIndex(selectedView, f); revalidate(); repaint(); } /** * Returns the selected view index. * * @return See above. */ int getSelectedView() { return selectedView; } /** * Sets to <code>true</code> to zoom the image when the user * mouses over an {@link ImageNode}, to <code>false</code> otherwise. * * @param rollOver Pass <code>true</code> to zoom the image when the user * mouses over an {@link ImageNode}, * <code>false</code> otherwise. */ void setRollOver(boolean rollOver) { model.getBrowser().setRollOver(rollOver); } /** * Sets the number of images displayed in a row. * * @param number The number of images per row. */ void setItemsPerRow(int number) { Browser browser = model.getBrowser(); Layout layout = browser.getSelectedLayout(); if (layout != null) { layout.setImagesPerRow(number); browser.accept(layout, ImageDisplayVisitor.IMAGE_SET_ONLY); } } /** * Sets the number of images. * * @param value The number of images displayed. */ void setNumberOfImages(int value) { if (value < 0) value = model.getNumberOfImages(); toolBar.setNumberOfImages(value, model.getNumberOfImages()); } /** * Sorts the thumbnails either alphabetically or by date. * * @param index The sorting index. */ void sortBy(int index) { model.getSorter().setByDate(SORT_BY_DATE == index); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); Browser browser = model.getBrowser(); Layout layout = browser.getSelectedLayout(); if (layout != null) browser.accept(layout, ImageDisplayVisitor.IMAGE_SET_ONLY); ImageTableView v = model.getTableView(); if (v != null) v.refreshTable(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } /** * Magnifies the images nodes. * * @param factor The magnification factor. */ void setMagnificationFactor(double factor) { MagnificationVisitor visitor; Browser browser; switch (selectedView) { case THUMB_VIEW: visitor = new MagnificationVisitor(factor); browser = model.getBrowser(); browser.accept(visitor, ImageDisplayVisitor.IMAGE_NODE_ONLY); browser.accept(browser.getSelectedLayout(), ImageDisplayVisitor.IMAGE_SET_ONLY); break; case COLUMNS_VIEW: visitor = new MagnificationVisitor(factor); browser = model.getBrowser(); browser.accept(visitor, ImageDisplayVisitor.IMAGE_NODE_ONLY); ImageTableView v = model.getTableView(); if (v != null) { v.setMagnification(factor); v.refreshTable(); } break; case FIELDS_VIEW: if (fieldsView != null) fieldsView.setMagnificationFactor(factor); break; } //if (model.getType() == DataBrowserModel.WELLS); // browser.getSelectedLayout().doLayout(); } /** * Sets the magnification the <code>Fields View </code> is selected. * * @param factor The value to set. */ void setMagnificationUnscaled(double factor) { if (selectedView == FIELDS_VIEW && fieldsView != null) fieldsView.setMagnificationUnscaled(factor); } /** * Brings up the pop-up menu on top of the specified component at the * specified point. * * @param p The point at which to display the menu, relative to the * <code>component</code>'s coordinates. */ void showPopup(Point p) { if (popupMenu == null) popupMenu = new PopupMenu(controller, model); Component comp = null; switch (selectedView) { case THUMB_VIEW: if (model.getBrowser() != null) comp = model.getBrowser().getUI(); break; case COLUMNS_VIEW: comp = model.getTableView(); case SEARCH_VIEW: comp = model.getSearchView(); } if (comp != null) { popupMenu.populateOpenWith(); popupMenu.show(comp, p.x, p.y); } } /** * Returns the collections of applications. * * @return See above. */ List<ApplicationData> getApplications() { return model.getApplications(); } /** Views the selected node only if it is an image. */ void viewSelectedNode() { ImageDisplay node = model.getBrowser().getLastSelectedDisplay(); if (!(node instanceof ImageNode)) return; ImageData data = (ImageData) node.getHierarchyObject(); EventBus bus = DataBrowserAgent.getRegistry().getEventBus(); ViewImage evt = new ViewImage(model.getSecurityContext(), new ViewImageObject(data), null); evt.setPlugin(DataBrowserAgent.runAsPlugin()); bus.post(evt); } /** * Adjusts the status bar according to the specified arguments. * * @param status Textual description to display. * @param hideProgressBar Whether or not to hide the progress bar. * @param progressPerc The percentage value the progress bar should * display. If negative, it is interpreted as * not available and the progress bar will be * set to indeterminate mode. This argument is * only taken into consideration if the progress * bar shouldn't be hidden. */ void setStatus(String status, boolean hideProgressBar, int progressPerc) { statusBar.setStatus(status); statusBar.setProgress(hideProgressBar, progressPerc); } /** * Sets the filtering context. * * @param context The context to handle. */ void filterByContext(FilterContext context) { if (context == null) return; toolBar.filterByContext(context); } /** * Sets the filtering status. * * @param busy Pass <code>true</code> if filtering, <code>false</code> * otherwise. */ void setFilterStatus(boolean busy) { toolBar.setFilterStatus(busy); } /** * Sets the text of the filtered label. * * @param value The value to set. */ void setFilterLabel(String value) { toolBar.setFilterLabel(value); } /** * Returns the number of fields per well. * * @return See above. */ int getFieldsNumber() { if (model instanceof WellsModel) return ((WellsModel) model).getFieldsNumber(); return -1; } /** * Returns the selected field, the default value is <code>0</code>. * * @return See above. */ int getSelectedField() { if (model instanceof WellsModel) return ((WellsModel) model).getSelectedField(); return 0; } /** Updates the view when a new field is selected. */ void viewField() { setMagnificationFactor(statusBar.getMagnificationFactor()); } /** * Indicates the status of the fields loading. * * @param status Pass <code>true</code> while loading the fields, * <code>false</code> otherwise. */ void setFieldsStatus(boolean status) { wellToolBar.setStatus(status); } /** * Displays the passed fields. * * @param nodes The nodes hosting the fields. */ void displayFields(List<WellSampleNode> nodes) { if (fieldsView == null) return; setFieldsStatus(false); if (selectedView == FIELDS_VIEW) fieldsView.displayFields(nodes); } /** Invokes when a well is selected. */ void onSelectedWell() { if (!(model instanceof WellsModel)) return; plateGridUI.onSelectedWell(); } /** * Sets the layout used to display the fields. * * @param index The index of the layout. */ void setSelectedFieldLayout(int index) { if (fieldsView == null) return; fieldsView.setLayoutFields(index); if (selectedView == FIELDS_VIEW) fieldsView.displayFields(fieldsView.getNodes()); } /** Invokes when the parent has been set. */ void onExperimenterSet() { toolBar.onExperimenterSet(); } /** * Returns the parent of the nodes if any. * * @return See above. */ Object getParentOfNodes() { return model.getParent(); } /** * Returns the parent of the nodes if any. * * @return See above. */ Object getGrandParentOfNodes() { return model.getGrandParent(); } }