/* * Copyright 2003-2010 Tufts University Licensed under the * Educational Community License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ package tufts.vue; import tufts.Util; import tufts.vue.gui.*; import java.awt.*; import javax.swing.*; import javax.swing.border.*; /** * Digital Repository Browser * * This single panel abstracts the collective handling of a list of * selectable data sources, a search pane to be automatically * displayed and updated when searchable data sources are selected, * and a browse pane to be automatically populated and displayed when * browseable data sources are selected. * * This code, along with DataSourceViewer, DataSourceList, and * DataSourceListCellRenderer, are due for collective refactoring. It * would be best to do away with the JList / renderer impl, which adds * much complexity, and doesn't get us much: we're unlikely to ever * have so many data sources that the GUI performance gain of not * having full-time swing components present for each data source line * is worth it, and without having to go through a ListCellRenderer, * we'd have much more flexibility in layout out, drawing and * repainting the data sources (e.g., we could add spinners to loading * data sources -- that's wouldn't possible now without adding a * special timer thread to repaint the entire least each time the * spinner wanted to draw the next image.) * * Also, it would be very handy to have a single interface or class * that abstracts BOTH types of data-sources: OSID's (edu.tufts.vue.dsm.DataSource), * and browseable VUE ("old-style") data sources (tufts.vue.DataSource). * We'd probably need a delegating impl tho to handle that. * * @version $Revision: 1.88 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $ */ public class DRBrowser extends ContentBrowser { public static final long serialVersionUID = 1; private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(DRBrowser.class); public static final Object SEARCH_EDITOR = "search_editor_layout_constraint"; public static final Object SEARCH_RESULT = "search_result_layout_constraint"; final JComponent searchPane = new Widget(VueResources.getString("action.search")) { private Component editor, result; { setOpaque(false); // This is to keep the content window from coming to the front when the // data sources have loaded and the searchPane is expanded. Widget.setLoading(this, true); } protected void addImpl(Component c, Object constraints, int idx) { if (DEBUG.DR) out("SEARCH-WIDGET addImpl: " + GUI.name(c) + " " + constraints + " idx=" + idx); JComponent jc = null; if (c instanceof JComponent) jc = (JComponent) c; if (constraints == SEARCH_EDITOR) { if (editor != null) remove(editor); editor = c; constraints = BorderLayout.NORTH; if (jc != null) jc.setBorder(GUI.WidgetInsetBorder); } else if (constraints == SEARCH_RESULT) { // this method of setting this is a crazy hack for now, but // it's perfect for allowing us to try different layouts resultsPane.removeAll(); resultsPane.add(jc); resultsPane.setHidden(false); resultsPane.validate(); return; } else { tufts.Util.printStackTrace("illegal search pane constraints: " + constraints); } super.addImpl(c, constraints, idx); revalidate(); } }; final JPanel librariesPane = new Widget(VueResources.getString("drbrowser.resources")); final Widget browsePane = new Widget(VueResources.getString("button.browse.label")); final Widget resultsPane = new Widget(VueResources.getString("jlabel.searchresult")); final DockWindow dockWindow; private JComponent loadingComponent; private JLabel loadingLabel; private DataSourceViewer DSV; public DRBrowser(boolean delayedLoading, DockWindow resourceDock) { super("DRBrowser"); setName(VueResources.getString("dockWindow.contentPanel.resources.title")); if (DEBUG.DR || DEBUG.INIT) out("Creating DRBrowser"); dockWindow = resourceDock; //----------------------------------------------------------------------------- // Resources //----------------------------------------------------------------------------- if (delayedLoading) { final String LoadingMessage = VueResources.getString("dockWindow.Resources.loading.label"); if (Util.isMacLeopardOrLater()) { // todo: StatusLabel was made public just for us here: move to tufts.gui as a util class // (and make the params named via sub-constructors -- e.g., StatusLabel.Spin(msg) loadingComponent = new DataSourceViewer.StatusLabel(LoadingMessage, true, true); loadingComponent.setBorder(GUI.makeSpace(12,0,12,0)); } else { loadingLabel = new JLabel(LoadingMessage, SwingConstants.CENTER); loadingLabel.setMinimumSize(new Dimension(150, 80)); loadingLabel.setBorder(GUI.makeSpace(16,0,16,0)); GUI.apply(GUI.StatusFace, loadingLabel); loadingComponent = loadingLabel; } librariesPane.add(loadingComponent); } else { loadDataSourceViewer(); } //----------------------------------------------------------------------------- // Search //----------------------------------------------------------------------------- searchPane.setBackground(Color.white); JLabel please = new JLabel(VueResources.getString("jlabel.searchableresource"), JLabel.CENTER); GUI.apply(GUI.StatusFace, please); searchPane.add(please, SEARCH_EDITOR); //----------------------------------------------------------------------------- // Browse //----------------------------------------------------------------------------- browsePane.setBackground(Color.white); browsePane.setExpanded(false); browsePane.setLayout(new BorderLayout()); //----------------------------------------------------------------------------- // Results //----------------------------------------------------------------------------- resultsPane.setTitleHidden(true); resultsPane.setHidden(true); addPane(librariesPane, 0f); addPane(searchPane, 0f); addPane(browsePane, 1f); addPane(resultsPane, 0f); } public DataSourceViewer getDataSourceViewer() { return DSV; } public void loadDataSourceViewer() { Log.debug("loading the DataSourceViewer..."); try { DSV = new DataSourceViewer(this); DSV.setName("Data Source Viewer"); if (loadingComponent != null) librariesPane.remove(loadingComponent); librariesPane.add(DSV); // must do this to get re-laid out: apparently, the hierarchy // events from the add don't automatically do this! revalidate(); } catch (Throwable e) { Log.error(e); e.printStackTrace(); loadingLabel.setText(e.toString()); } // Done loading, so Content window should now come to front when searchPane is expanded. Widget.setLoading(searchPane, false); if (DEBUG.DR || DEBUG.Enabled) out("done loading DataSourceViewer"); } private static void out(String s) { //System.out.println("DRBrowser: " + s); Log.info(s); } }