/* * 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 java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.io.File; import java.util.Vector; import javax.swing.Action; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JPopupMenu; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import tufts.Util; import tufts.vue.DataSource; import tufts.vue.ds.XmlDataSource; import tufts.vue.gui.DockWindow; import tufts.vue.gui.GUI; import tufts.vue.gui.Widget; import tufts.vue.gui.WidgetStack; public class DataSetViewer extends ContentViewer { public static final long serialVersionUID = 1; private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(DataSetViewer.class); protected DSBrowser DSB = null; protected static DataSourceList dataSourceList = null; private static Object activeDataSource = null; protected JPopupMenu contextMenu = null; public DataSetViewer(DSBrowser dsb) { DSB = dsb; dataSourceList = new DataSourceList(this); loadDataSets(); addListeners(); setLayout(new BorderLayout()); add(dataSourceList); if (editInfoDockWindow == null) { initUI(); } // editInfoDockWindow.setLocation(DSB.dockWindow.getX() + DSB.dockWindow.getWidth(), DSB.dockWindow.getY()); } public void finalize() { DSB = null; browserDS = null; dataSourceList = null; } protected void loadDataSets() { File file = new File(VueUtil.getDefaultUserFolder().getAbsolutePath()+File.separatorChar+VueResources.getString("save.datasources")); if (!file.exists()) { if (DEBUG.DR) System.out.println("Loading Datasets (does not exist: " + file + ")"); } else { try { SaveDataSourceViewer dataSourceViewer = unMarshallMap(file); Vector<BrowseDataSource> dataSources = dataSourceViewer.getSaveDataSources(); while (!dataSources.isEmpty()) { BrowseDataSource ds = (BrowseDataSource)dataSources.remove(0); // Only show XML data sources (this includes CSV files). if (ds.getTypeName().equals(XmlDataSource.TYPE_NAME)) { dataSourceList.addOrdered(ds); } } // select the first new data set, if any DefaultListModel model = dataSourceList.getModelContents(); // if (activeDataSource == null && model.size() > 0) // setActiveDataSource((DataSource)model.getElementAt(0)); } catch (Exception ex) { Log.error("Loading Datasets: ", ex); } } } private void addListeners() { dataSourceList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (DEBUG.KEYS || DEBUG.EVENTS) Log.debug("valueChanged: " + e); Object obj = ((JList)e.getSource()).getSelectedValue(); if (obj !=null) { if (obj instanceof tufts.vue.DataSource) { DataSource ds = (DataSource)obj; setActiveDataSource(ds); refreshEditInfo(ds); } else { obj = dataSourceList.getModelContents().getElementAt(((JList)e.getSource()).getSelectedIndex() - 1); if (obj instanceof tufts.vue.DataSource) { DataSource ds = (DataSource)obj; setActiveDataSource(ds); refreshEditInfo(ds); } } } DSB.refreshMenuActions(); } }); dataSourceList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent event) { int index = dataSourceList.locationToIndex(event.getPoint()); DataSource ds = (DataSource)dataSourceList.getModel().getElementAt(index); if (event.getClickCount() == 2) { displayEditOrInfo(ds); } else { if (event.getButton() == MouseEvent.BUTTON3) { // lastMouseClick = e.getPoint(); setActiveDataSource(ds); displayContextMenu(event); } } } }); } public void setActiveDataSource(final DataSource ds) { if (DEBUG.Enabled) Log.debug("setActiveDataSource: " + ds); if (activeDataSource != ds) { activeDataSource = ds; dataSourceList.setSelectedValue(ds, true); } browserDS = (tufts.vue.BrowseDataSource) ds; displayInBrowsePane(produceViewer(browserDS), true); } void refreshBrowser() { if (browserDS == null || browserDS.isLoading()) return; browserDS.unloadViewer(); dataSourceList.repaint(); // so change in loaded status will be visible displayInBrowsePane(produceViewer(browserDS), false); } protected void displayInBrowsePane(JComponent viewer, boolean priority) { if (DEBUG.Enabled) Log.debug("displayInBrowsePane: " + browserDS + "; " + GUI.name(viewer)); String title = VueResources.getString("button.browse.label")+": " + browserDS.getDisplayName(); if (browserDS.getCount() > 0) title += " (" + browserDS.getCount() + ")"; Widget.setTitle(DSB.browsePane, title); DSB.browsePane.removeAll(); DSB.browsePane.add(viewer); DSB.browsePane.revalidate(); DSB.browsePane.repaint(); Widget.setExpanded(DSB.browsePane, true); DSB.refreshMenuActions(); } protected void displayContextMenu(MouseEvent event) { getPopup(event).show(event.getComponent(), event.getX(), event.getY()); } protected JPopupMenu getPopup(MouseEvent e) { if (contextMenu == null) { contextMenu = new JPopupMenu(); contextMenu.add(DSB.editLibraryAction); contextMenu.add(DSB.reloadLibraryAction); contextMenu.addSeparator(); contextMenu.add(DSB.removeLibraryAction); } return contextMenu; } protected void repaintList() { dataSourceList.repaint(); // so change in loaded status will be visible } public static DataSourceList getDataSetList() { return dataSourceList; } public static void saveDataSetViewer() { if (dataSourceList == null) { System.err.println("DataSetViewer: No dataSourceList to save."); } else { int size = dataSourceList.getModel().getSize(); Vector dataSources = new Vector(); if (DEBUG.DR) Log.debug("saveDataSetViewer: found " + size + " dataSets: scanning for local's to save..."); for (int i = 0; i<size; i++) { Object item = dataSourceList.getModel().getElementAt(i); if (DEBUG.DR) System.err.print("\tsaveDataSetViewer: item " + i + " is " + tufts.Util.tag(item) + "[" + item + "]..."); if (item instanceof DataSource) { dataSources.add((DataSource)item); if (DEBUG.DR) System.err.println("saving"); } else { if (DEBUG.DR) System.err.println("skipping"); } } // For backwards compatability, "default" data source like My Computer and Saved Content are also saved to this XML file. // These data sources are displayed in DataSourceViewer, not DataSetViewer, so get them from there. if (DataSourceViewer.dataSourceList !=null) { size = DataSourceViewer.dataSourceList.getModel().getSize(); for (int i = 0; i<size; i++) { Object item = DataSourceViewer.dataSourceList.getModel().getElementAt(i); if (DEBUG.DR) System.err.print("\tsaveDataSetViewer: item " + i + " is " + tufts.Util.tag(item) + "[" + item + "]..."); if (item instanceof DataSource) { dataSources.add((DataSource)item); if (DEBUG.DR) System.err.println("saving"); } else { if (DEBUG.DR) System.err.println("skipping"); } } } try { if (DEBUG.DR) Log.debug("saveDataSetViewer: creating new SaveDataSourceViewer"); File file = new File(VueUtil.getDefaultUserFolder().getAbsolutePath() + File.separatorChar + VueResources.getString("save.datasources")); SaveDataSourceViewer sViewer= new SaveDataSourceViewer(dataSources); if (DEBUG.DR) Log.debug("saveDataSourceViewer: marshallMap: saving " + sViewer + " to " + file); marshallMap(file,sViewer); if (DEBUG.DR) Log.debug("saveDataSourceViewer: saved"); } catch (Throwable t) { t.printStackTrace(); } } } private static DockWindow editInfoDockWindow; // hack for now: need this set before DSV is created private static WidgetStack editInfoStack; // static hack: is needed before this class is constructed private Object loadedDataSource; public void displayEditOrInfo(DataSource ds) { if (DEBUG.DR) Log.debug("DISPLAY " + Util.tags(ds)); if (!editInfoDockWindow.isVisible()) positionEditInfoWindow(); refreshEditInfo(ds, true); editInfoDockWindow.setWidth(500); editInfoDockWindow.setVisible(true); editInfoDockWindow.raise(); } static void initUI() { editInfoDockWindow = buildConfigWindow(); } private void positionEditInfoWindow() { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); if ((DSB.dockWindow.getX() + DSB.dockWindow.getWidth() + editInfoDockWindow.getWidth()) < screenSize.getWidth()) editInfoDockWindow.setLocation(DSB.dockWindow.getX() + DSB.dockWindow.getWidth(), DSB.dockWindow.getY()); else editInfoDockWindow.setLocation(DSB.dockWindow.getX() - editInfoDockWindow.getWidth(), DSB.dockWindow.getY()); } private void refreshEditInfo(tufts.vue.DataSource ds) { refreshEditInfo(ds, false); } private void refreshEditInfo(tufts.vue.DataSource ds, boolean force) { if (ds == loadedDataSource) return; if (DEBUG.DR && DEBUG.META) Log.debug("refresh " + Util.tags(ds)); if (force || editInfoDockWindow.isVisible()) { if (DEBUG.DR) Log.debug("REFRESH " + Util.tags(ds)); editInfoStack.removeAll(); final String name; if (DEBUG.Enabled) name = VueResources.getString("optiondialog.configuration.message")+": " + ds.getClass().getName(); else name = VueResources.getString("optiondialog.configuration.message")+": " + ds.getTypeName(); editInfoStack.addPane(name, new EditLibraryPanel(this, ds), 1f); doLoad(ds, ds.getDisplayName()); } } private void doLoad(Object dataSource, String name) { editInfoStack.setTitleItem(name); //editInfoDockWindow.invalidate(); //editInfoDockWindow.repaint(); loadedDataSource = dataSource; } private static DockWindow buildConfigWindow() { try { return _buildWindow(); } catch (Throwable t) { Log.error("buildConfigWindow", t); } return null; } private static DockWindow _buildWindow() { final DockWindow dw = GUI.createDockWindow(VueResources.getString("dockWindow.dataset.title")); editInfoStack = new WidgetStack(); //editInfoStack.addPane("startup", new javax.swing.JLabel("config init")); editInfoStack.setMinimumSize(new Dimension(300,300)); dw.setContent(editInfoStack); if (DEBUG.Enabled) { //editInfoStack.setMinimumSize(new Dimension(400,600)); dw.setSize(500,800); } else { dw.setWidth(300); dw.setHeight(500); } // We don't have DSB yet to set location. return dw; } }