/* * #! * Ontopia Vizigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache 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.apache.org/licenses/LICENSE-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 net.ontopia.topicmaps.viz; import java.awt.Color; import java.awt.Component; import java.awt.Frame; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import net.ontopia.Ontopia; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.core.index.ScopeIndexIF; import net.ontopia.topicmaps.entry.TopicMapReferenceIF; import net.ontopia.topicmaps.nav.utils.comparators.TopicComparator; import net.ontopia.utils.CmdlineOptions; import net.ontopia.utils.CmdlineUtils; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.SimpleFileFilter; import net.ontopia.utils.StringifierIF; import net.ontopia.utils.URIUtils; import com.touchgraph.graphlayout.Node; /** * INTERNAL: The top-level class for the VizDesktop. Can be run from the * command-line to produce the desktop UI. */ public class VizDesktop implements VizFrontEndIF { private static final String ONTOPIA_VIZDESKTOP_TITLE = "Ontopia VizDesktop"; /** * Simple main to allow stand-alone startup. Optionally can provide an initial * topicmap to load. */ public static void main(String[] argv) { // set up logging CmdlineUtils.initializeLogging(); CmdlineUtils.setLoggingPriority("ERROR"); // Initialize command line option parser and listeners CmdlineOptions options = new CmdlineOptions("VizDesktop", argv); OptionsListener ohandler = new OptionsListener(); options.addLong(ohandler, "lang", 'l', true); // Register logging options CmdlineUtils.registerLoggingOptions(options); // Parse command line options try { options.parse(); } catch (CmdlineOptions.OptionsException e) { System.err.println("Error: " + e.getMessage()); System.exit(1); } // Set user-interface language Messages.setLanguage(ohandler.lang); // Get command line arguments final String[] args = options.getArguments(); if (args.length > 1) { System.err.println(Messages.getString("Viz.InvalidParamNum")); usage(); System.exit(1); } // open main window SwingUtilities.invokeLater(new Runnable() { public void run() { new VizDesktop(args); } }); } protected static void usage() { System.out.println(Ontopia.getInfo()); System.out.println("java net.ontopia.topicmaps.viz.VizDesktop [options] " + "<file>"); System.out.println(""); System.out.println(" " + Messages.getString("Viz.cmdlineUsageTitle")); System.out.println(""); System.out.println(" Options:"); CmdlineUtils.printLoggingOptionsUsage(System.out); System.out.println(""); System.out.println(" <" + Messages.getString("Viz.cmdlineFile") + ">: " + Messages.getString("Viz.cmdLineFileDescription")); } private static class OptionsListener implements CmdlineOptions.ListenerIF { String lang = "en"; public void processOption(char option, String value) { if (option == 'l') lang = value; } } private VizPanel vPanel; private VizController controller; private JMenu recentTopicMapFilesMenu; private JMenu visibleAssocTypesMenu; private JMenu visibleTopicTypesMenu; private JMenuItem focusStartTopicItem; private TypesConfigFrame topicFrame; private TypesConfigFrame assocFrame; private TopicMapIF currentTopicMap; private HashMap topicTypeButtonMap; private HashMap associationTypeButtonMap; private JMenu styleMenu; private JMenu optionsMenu; private JMenu viewMenu; private GeneralConfigFrame generalFrame; private TypesPrecedenceFrame precedenceFrame; private JFrame frame; private JMenuItem mapViewMenu; private JMenuItem clearStartMenu; private JMenu scopingTopicsMenu; private StringifierIF stringifier; private TopicIF currentScope; private OpenRDBMSDialogBox openBox; private static final boolean enableRDBMSImport = true; private void disableMenuItems() { this.setEnableMenuItems(false); } public TypesConfigFrame getTopicFrame() { return topicFrame; } public TypesConfigFrame getAssocFrame() { return assocFrame; } private void setEnableMenuItems(boolean b) { visibleAssocTypesMenu.setEnabled(b); visibleTopicTypesMenu.setEnabled(b); viewMenu.setEnabled(b); styleMenu.setEnabled(b); optionsMenu.setEnabled(b); scopingTopicsMenu.setEnabled(b); AssociationScopeFilterMenu associationScopeFilterMenu = vPanel .getAssociationScopeFilterMenu(); associationScopeFilterMenu.setEnabled(b); } private void enableMenuItems() { setEnableMenuItems(true); } public VizDesktop(String args[]) { frame = new JFrame(ONTOPIA_VIZDESKTOP_TITLE); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { try { controller.saveGeneralConfiguration(); } catch (IOException ex) { ErrorDialog.showError(vPanel, ex); } System.exit(0); } }); try { getContext(); vPanel = new VizPanel(this); controller = vPanel.getController(); } catch (Exception e) { ErrorDialog.showError(vPanel, e); return; } frame.setJMenuBar(getMenuBar()); frame.getContentPane().add("Center", vPanel); frame.pack(); frame.setSize(800, 800); frame.setVisible(true); this.disableMenuItems(); if (args.length == 1) { // load topic map from file File f = new File(args[0]); if (!f.exists()) { ErrorDialog.showError(vPanel, Messages.getString( "Viz.FileDoesNotExist", args)); } else { setCurrentTopicMapDirectory(f.getParent()); try { loadTopicMap(f); } catch (IOException e) { ErrorDialog.showError(vPanel, Messages.getString("Viz.TMLoadError"), e); } } } } protected void resetMapViewMenu() { mapViewMenu.setEnabled(controller.getFocusNode() != null); } /** * Display recent file menu items. */ private void displayRecentFileMenuItems(JMenu parent) { Iterator fileIterator = controller.getRecentFiles().iterator(); boolean first = true; while (fileIterator.hasNext()) { File file = (File) fileIterator.next(); JMenuItem mItem = new JMenuItem(file.getAbsolutePath()); mItem.addActionListener(new FileOpenMenuListener()); if (first) mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0)); parent.add(mItem); first = false; } } /** * Returns a menu for controlling the application. Uses the isRemote flag for * deciding which menu items are displayed. */ private JMenuBar getMenuBar() { // FIXME: This whole menu sucks royally! We need to clean this // stuff up. It's 200 lines now, but should be about 20-50. JMenuBar mBar; JMenu men; JMenuItem mItem; mBar = new JMenuBar(); men = new JMenu(Messages.getString("Viz.File")); mBar.add(men); mItem = new JMenuItem(Messages.getString("Viz.MenuLoadTopicMap")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuLoadTopicMap(); } }); mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyInputManager.KEY_MASK)); men.add(mItem); if (enableRDBMSImport) addRDBMSImportMenuItem(men); men.addSeparator(); mItem = new JMenuItem(Messages.getString("Viz.MenuSaveConfiguration")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuSaveConfiguration(); } }); mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyInputManager.KEY_MASK)); men.add(mItem); men.addSeparator(); mItem = new JMenuItem(Messages.getString("Viz.SetRDFMappingFile")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuSetRdfMappingFile(); } }); mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyInputManager.KEY_MASK)); men.add(mItem); men.addSeparator(); recentTopicMapFilesMenu = new JMenu(Messages .getString("Viz.MenuRecentFiles")); men.add(recentTopicMapFilesMenu); displayRecentFileMenuItems(recentTopicMapFilesMenu); men.addSeparator(); mItem = new JMenuItem(Messages.getString("Viz.MenuExit")); mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyInputManager.KEY_MASK)); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { try { controller.saveGeneralConfiguration(); } catch (IOException e) { ErrorDialog.showError(vPanel, e); } System.exit(0); } }); men.add(mItem); viewMenu = new JMenu(Messages.getString("Viz.MenuView")); mBar.add(viewMenu); mapViewMenu = new JMenuItem(Messages.getString("Viz.MenuMapView")); mapViewMenu.setEnabled(false); mapViewMenu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { controller.goToMapView(); resetMapViewMenu(); resetStartTopicMenu(); } }); viewMenu.add(mapViewMenu); focusStartTopicItem = new JMenuItem(Messages .getString("Viz.MenuFocusStartNode")); focusStartTopicItem.setEnabled(false); focusStartTopicItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { controller.focusStartTopic(); } }); viewMenu.add(focusStartTopicItem); clearStartMenu = new JMenuItem(Messages .getString("Viz.MenuClearStartNode")); clearStartMenu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { controller.clearStartTopic(); resetClearStartMenu(); resetStartTopicMenu(); } }); viewMenu.add(clearStartMenu); visibleTopicTypesMenu = new JMenu(Messages .getString("Viz.TopicTypesTitle")); mBar.add(visibleTopicTypesMenu); visibleAssocTypesMenu = new JMenu(Messages .getString("Viz.AssociationTypesTitle")); mBar.add(visibleAssocTypesMenu); // Options for topic type visual appearance styleMenu = new JMenu(Messages.getString("Viz.StyleTitle")); mBar.add(styleMenu); mItem = new JMenuItem(Messages.getString("Viz.TopicTypeConfiguration")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenTopicConfig(); } }); styleMenu.add(mItem); // Options for association type visual appearance mItem = new JMenuItem(Messages.getString("Viz.AssociationTypeConfiguration")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenAssociationConfig(); } }); styleMenu.add(mItem); // General configuration options optionsMenu = new JMenu(Messages.getString("Viz.MenuOptions")); mBar.add(optionsMenu); mItem = new JMenuItem(Messages.getString("Viz.MenuGeneral")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenGeneralConfig(); } }); optionsMenu.add(mItem); mItem = new JMenuItem(Messages.getString("Viz.MenuPrecedence")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenPrecedenceConfig(); } }); optionsMenu.add(mItem); scopingTopicsMenu = new JMenu(Messages.getString("Viz.ScopingMenuTitle")); mBar.add(scopingTopicsMenu); AssociationScopeFilterMenu associationScopeFilterMenu = vPanel .getAssociationScopeFilterMenu(); mBar.add(associationScopeFilterMenu); JMenu helpMenu = new JMenu(Messages.getString("Viz.Help")); mBar.add(helpMenu); mItem = new JMenuItem(Messages.getString("Viz.About", "Ontopia Vizigator")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenAboutWindow(); } }); helpMenu.add(mItem); return mBar; } protected void addRDBMSImportMenuItem(JMenu containingMenu) { JMenuItem mItem = new JMenuItem(Messages .getString("Viz.MenuOpenRDBMSTopicMap")); mItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent anE) { menuOpenRDBMSTopicMap(); } }); mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyInputManager.KEY_MASK)); containingMenu.add(mItem); } protected void resetClearStartMenu() { clearStartMenu.setEnabled(controller.getStartTopic() != null); } private void menuSetRdfMappingFile() { setRdfMappingFile(getCurrentTopicMapDirectory()); } private void setRdfMappingFile(String suggestion) { File defaultFile = null; if (controller.getRdfMappingFile() != null) { defaultFile = new File(controller.getRdfMappingFile()); } if (defaultFile == null || !defaultFile.exists()) { // HACK - I don't like the following code String base = System.getProperty("user.dir"); base = base.substring(0, Math.max(0, base.length() - 4)); File preset = new File(base + "\\apache-tomcat\\webapps\\omnigator\\" + "WEB-INF\\topicmaps\\mapping.rdff"); if (preset.exists()) { defaultFile = preset; } else { if (suggestion != null) { File tmp = new File(suggestion); if (tmp.exists()) { defaultFile = tmp; } else { defaultFile = null; } } } } JFileChooser fc = new JFileChooser(defaultFile); fc.setSelectedFile(defaultFile); SimpleFileFilter def = new SimpleFileFilter(Messages .getString("Viz.RDFMappingFilesDescription"), "rdf", "rdff"); fc.addChoosableFileFilter(def); fc.setDialogTitle(Messages.getString("Viz.RfdMappingFileSelectionTitle")); int returnVal = fc.showDialog(vPanel, Messages.getString("Viz.FileSelect")); if (returnVal == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { controller.setRdfMappingFile(f); } catch (IOException e) { ErrorDialog.showError(vPanel, e); } } } /** * Invoked after a topic map and any configuration has been loaded so that the * user can configure the display. */ private void configureDynamicMenus() { configureFilterMenus(); configureScopeMenu(); vPanel.configureDynamicMenus(new DynamicMenuListener()); } private void configureScopeMenu() { if (currentTopicMap == null) return; ScopeIndexIF scopeix = (ScopeIndexIF) currentTopicMap.getIndex( "net.ontopia.topicmaps.core.index.ScopeIndexIF"); BasenameUserThemeFilter filter = new BasenameUserThemeFilter(currentTopicMap); HashMap map = new HashMap(); ArrayList untyped = new ArrayList(); for (Iterator iter = filter.filterThemes(scopeix.getTopicNameThemes()) .iterator(); iter.hasNext();) { TopicIF theme = (TopicIF) iter.next(); if (theme.getTypes().isEmpty()) untyped.add(theme); else { for (Iterator iterator = theme.getTypes().iterator(); iterator .hasNext();) { TopicIF type = (TopicIF) iterator.next(); List list = (List) map.get(type); if (list == null) { list = new ArrayList(); map.put(type, list); } list.add(theme); } } } scopingTopicsMenu.removeAll(); JMenuItem unconstrainedScopeMenu = new JMenuItem(Messages .getString("Viz.UnconstrainedScopeMenuTitle")); unconstrainedScopeMenu.addActionListener(new ScopeActionListener(null)); scopingTopicsMenu.add(unconstrainedScopeMenu); unconstrainedScopeMenu.setEnabled(currentScope != null); if (!untyped.isEmpty()) { scopingTopicsMenu.addSeparator(); Collections.sort(untyped, new TopicComparator()); for (Iterator iterator = untyped.iterator(); iterator.hasNext();) { TopicIF scope = (TopicIF) iterator.next(); JMenuItem scopeMenu = new JMenuItem(stringifier.toString(scope)); scopeMenu.addActionListener(new ScopeActionListener(scope)); scopingTopicsMenu.add(scopeMenu); scopeMenu.setEnabled(!scope.equals(currentScope)); } } if (!map.isEmpty()) { scopingTopicsMenu.addSeparator(); ArrayList grouping = new ArrayList(map.keySet()); Collections.sort(grouping, new TopicComparator()); for (Iterator iter = grouping.iterator(); iter.hasNext();) { TopicIF group = (TopicIF) iter.next(); JMenu groupMenu = new JMenu(stringifier.toString(group)); scopingTopicsMenu.add(groupMenu); List list = (List) map.get(group); Collections.sort(list, new TopicComparator()); for (Iterator iterator = list.iterator(); iterator.hasNext();) { TopicIF scope = (TopicIF) iterator.next(); JMenuItem scopeMenu = new JMenuItem(stringifier.toString(scope)); scopeMenu.addActionListener(new ScopeActionListener(scope)); groupMenu.add(scopeMenu); scopeMenu.setEnabled(!scope.equals(currentScope)); } } } } protected void scopingTopicChanged(TopicIF scope) { setScopingTopic(scope); controller.setScopingTopic(scope); configureDynamicMenus(); if (generalFrame != null) generalFrame.initializeTopicLists(); if (assocFrame != null) assocFrame.initializeTypeList(); if (topicFrame != null) topicFrame.initializeTypeList(); } public void setScopingTopic(TopicIF topic) { currentScope = topic; stringifier = VizUtils.stringifierFor(topic); } public void configureFilterMenus() { // clear any existing menu items visibleTopicTypesMenu.removeAll(); visibleAssocTypesMenu.removeAll(); // Create default association menu item. TopicIF defaultAssociationType = controller.getConfigurationManager() .defaultAssociationType; ColouredSquareMenuItem defaultAssociationMenuItem = setupAssociationMenuItem(defaultAssociationType); // Get and sort association types List types = new ArrayList(controller.getAssociationTypes()); Collections.sort(types, new TopicComparator()); associationTypeButtonMap = new HashMap(types.size()); // Iterate association types Iterator ttypes = types.iterator(); while (ttypes.hasNext()) { TopicIF type = (TopicIF) ttypes.next(); if (type == defaultAssociationType) continue; ColouredSquareMenuItem mItem = setupAssociationMenuItem(type); mItem.addActionListener(new AssocActionListener(type)); defaultAssociationMenuItem.addActionListener(new DefaultActionListener( mItem)); visibleAssocTypesMenu.add(mItem); associationTypeButtonMap.put(type, mItem); } defaultAssociationMenuItem.addActionListener( new AssocActionListener(defaultAssociationType)); visibleAssocTypesMenu.add(defaultAssociationMenuItem); associationTypeButtonMap.put(controller.getConfigurationManager() .defaultAssociationType, defaultAssociationMenuItem); // Create Default topic menu item. TopicIF defaultType = controller.getConfigurationManager().defaultType; ColouredSquareMenuItem defaultTopicMenuItem = setupTopicMenuItem(defaultType); // Get and sort topic types. types = new ArrayList(controller.getAllTopicTypesWithNull()); Collections.sort(types, new TopicComparator()); topicTypeButtonMap = new HashMap(types.size()); // Iterate topic types ttypes = types.iterator(); while (ttypes.hasNext()) { TopicIF type = (TopicIF) ttypes.next(); // Skip default type (treated separately. if (type == defaultType) continue; ColouredSquareMenuItem mItem = setupTopicMenuItem(type); mItem.addActionListener(new TopicActionListener(type)); defaultTopicMenuItem.addActionListener(new DefaultActionListener(mItem)); visibleTopicTypesMenu.add(mItem); topicTypeButtonMap.put(type, mItem); } defaultTopicMenuItem.addActionListener( new TopicActionListener(defaultType)); visibleTopicTypesMenu.add(defaultTopicMenuItem); topicTypeButtonMap.put(controller.getConfigurationManager().defaultType, defaultTopicMenuItem); } private ColouredSquareMenuItem setupAssociationMenuItem(TopicIF type) { String name = (type == controller.getConfigurationManager().defaultAssociationType) ? Messages.getString("Viz.DefaultType") : stringifier.toString(type); ColouredSquareMenuItem mItem = new ColouredSquareMenuItem(name, stateOf(type, false)); mItem.setSquareColor(controller.getAssociationTypeColor(type)); return mItem; } private ColouredSquareMenuItem setupTopicMenuItem(TopicIF type) { String name; if (type == null) name = Messages.getString("Viz.Untyped"); else if (type == controller.getConfigurationManager() .defaultType) name = Messages.getString("Viz.DefaultType"); else name = stringifier.toString(type); // add new ones based on topicmap ontology. ColouredSquareMenuItem mItem = new ColouredSquareMenuItem(name, stateOf(type, true)); mItem.setSquareColor(controller.getTopicTypeColor(type)); return mItem; } private byte stateOf(TopicIF type, boolean isTopicType) { VizTopicMapConfigurationManager confMan = controller .getConfigurationManager(); TopicIF visibleTopic = confMan.getTypeVisibleTopic(); if (confMan.hasOccurrence(type, visibleTopic)) { if (confMan.isAssociationTypeVisible(type)) return VisibleIndicator.CHECKED; return VisibleIndicator.UNCHECKED; } if (isTopicType && confMan.isTopicTypeVisible(type) || (!isTopicType) && confMan.isAssociationTypeVisible(type)) return VisibleIndicator.DEFAULT_CHECKED; return VisibleIndicator.DEFAULT_UNCHECKED; } private void loadTopicMap(File f) throws IOException { this.resetFrame(assocFrame); assocFrame = null; this.resetFrame(topicFrame); topicFrame = null; this.resetFrame(generalFrame); generalFrame = null; this.resetFrame(precedenceFrame); precedenceFrame = null; disableMenuItems(); if ("rdf".equals(getFileExtension(f)) || "n3".equals(getFileExtension(f))) { String mapping = controller.getRdfMappingFile(); if (mapping == null) this.setRdfMappingFile(f.getAbsolutePath()); } TopicMapIF newTopicMap; File defaultcfg = getConfigFileFor(f); if (defaultcfg.exists()) { newTopicMap = controller.loadTopicMap(f, defaultcfg); if (newTopicMap == null) { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE); } else { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE + " - " + f.getName() + " (" + defaultcfg.getName() + ")"); } } else { newTopicMap = controller.loadTopicMap(f); if (newTopicMap == null) { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE); } else { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE + " - " + f.getName()); } } if (newTopicMap != null) { currentTopicMap = newTopicMap; controller.setLocality(vPanel.getLocality()); controller.updateRecentFiles(f); recentTopicMapFilesMenu.removeAll(); displayRecentFileMenuItems(recentTopicMapFilesMenu); controller.saveGeneralConfiguration(); controller.undoManager.reset(); } if (vPanel != null) { configureDynamicMenus(); enableMenuItems(); } } public void loadTopicMap(TopicMapReferenceIF tmReference, String configFilePath) throws IOException { this.resetFrame(assocFrame); assocFrame = null; this.resetFrame(topicFrame); topicFrame = null; this.resetFrame(generalFrame); generalFrame = null; this.resetFrame(precedenceFrame); precedenceFrame = null; disableMenuItems(); TopicMapIF tm; try { tm = tmReference.createStore(false) .getTopicMap(); } catch (IOException e) { throw new OntopiaRuntimeException(e); } String tmString = OpenRDBMSDialogBox.createTMString(tmReference); File defaultcfg = new File(configFilePath); if (defaultcfg.exists()) { controller.loadTopicMap(tm, defaultcfg); if (tm == null) { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE); } else { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE + " - " + tmString + " (" + defaultcfg.getName() + ")"); } } else { tm = controller.loadTopicMap(tm); if (tm == null) { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE); } else { frame.setTitle(ONTOPIA_VIZDESKTOP_TITLE + " - " + tmString); } } if (tm != null) { currentTopicMap = tm; controller.setLocality(vPanel.getLocality()); recentTopicMapFilesMenu.removeAll(); displayRecentFileMenuItems(recentTopicMapFilesMenu); controller.saveGeneralConfiguration(); if (vPanel != null) { configureDynamicMenus(); enableMenuItems(); } } } private void resetFrame(JFrame frame) { if (frame != null) { frame.setVisible(false); frame.dispose(); } } /** * Called from the color configuration menu when the color for a topic or * association type is changed. */ public void setNewTypeColor(TopicIF type, Color c) { // Change in both topics and associations ColouredSquareMenuItem menuItem = (ColouredSquareMenuItem)topicTypeButtonMap .get(type); if (menuItem != null) menuItem.setSquareColor(c); menuItem = (ColouredSquareMenuItem) associationTypeButtonMap.get(type); if (menuItem != null) menuItem.setSquareColor(c); } private File getConfigFileFor(File tmfile) { tmfile = tmfile.getAbsoluteFile(); File cfg = new File(tmfile.getParentFile(), tmfile.getName() + ".viz"); return cfg; } // --- Internal classes class FileOpenMenuListener implements ActionListener { public void actionPerformed(ActionEvent ev) { JMenuItem source = (JMenuItem) ev.getSource(); File f = new File(source.getText()); try { loadTopicMap(f); } catch (Exception e) { // FIXME: Do we ever want this dialog? It was removed to fix bug // #2087, but are there any negative side effects? // Presumably, this error message always co-occurs with the error // message on (currently) line 546 in VizController (SwingWorker worker) //! ErrorDialog.showError(vPanel, Messages //! .getString("Viz.TMLoadError"), e); } } } abstract class TypeActionListener implements ActionListener { protected TopicIF type; protected TypeActionListener(TopicIF type) { this.type = type; } public TopicIF getType() { return type; } } /** * Class to handle menu events. */ class AssocActionListener extends TypeActionListener { protected AssocActionListener(TopicIF type) { super(type); } public void actionPerformed(ActionEvent ev) { ColouredSquareMenuItem source = (ColouredSquareMenuItem) ev.getSource(); VisibleIndicator indicator = source.getVisibleIndicator(); indicator.setSelected(indicator.isSelected() ? VisibleIndicator.UNCHECKED : VisibleIndicator.CHECKED); controller.setAssociationTypeVisible(type, indicator.isSelected()); if (assocFrame != null) assocFrame.updateSelectedFilter(); } } /** Class to handle menu events. */ class TopicActionListener extends TypeActionListener { protected TopicActionListener(TopicIF type) { super(type); } public void actionPerformed(ActionEvent ev) { ColouredSquareMenuItem source = (ColouredSquareMenuItem) ev.getSource(); VisibleIndicator indicator = source.getVisibleIndicator(); indicator.setSelected(indicator.isSelected() ? VisibleIndicator.UNCHECKED : VisibleIndicator.CHECKED); controller.setTopicTypeVisible(type, indicator.isSelected()); if (topicFrame != null) topicFrame.updateSelectedFilter(); } } /** * Class to handle menu events. */ class DefaultActionListener implements ActionListener { private ColouredSquareMenuItem mItem; protected DefaultActionListener(ColouredSquareMenuItem mItem) { this.mItem = mItem; } public void actionPerformed(ActionEvent ev) { ColouredSquareMenuItem source = (ColouredSquareMenuItem) ev.getSource(); byte selectedValue = source.getVisibleIndicator().getSelected(); mItem.getVisibleIndicator().setDefault(selectedValue); } } private void menuLoadTopicMap() { JFileChooser fc = new JFileChooser(getCurrentTopicMapDirectory()); SimpleFileFilter def = new SimpleFileFilter(Messages .getString("Viz.XTMfiles"), "xtm"); fc.addChoosableFileFilter(def); fc.addChoosableFileFilter(new SimpleFileFilter(Messages .getString("Viz.CTMfiles"), "ltm")); fc.addChoosableFileFilter(new SimpleFileFilter(Messages .getString("Viz.LTMfiles"), "ltm")); fc.addChoosableFileFilter(new SimpleFileFilter(Messages .getString("Viz.RDFfiles"), "rdf", "n3")); fc.addChoosableFileFilter(new SimpleFileFilter(Messages .getString("Viz.TMXMLfiles"), "tmx")); fc.setFileFilter(def); int returnVal = fc.showOpenDialog(vPanel); if (returnVal == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); setCurrentTopicMapDirectory(f.getParent()); try { loadTopicMap(f); } catch (Exception e) { // FIXME: Do we ever want this dialog? It was removed to fix bug // #2087, but are there any negative side effects? // Presumably, this error message always co-occurs with the error // message on (currently) line 546 in VizController (SwingWorker worker) //! ErrorDialog.showError(vPanel, Messages //! .getString("Viz.TMLoadError"), e); } } } private void menuOpenRDBMSTopicMap() { if (openBox == null) openBox = new OpenRDBMSDialogBox(this); openBox.show(); } private String getFileExtension(File file) { String name = file.getName(); int pos = name.lastIndexOf('.'); if (pos == -1) { return null; } return name.substring(pos + 1).toLowerCase(); } private void menuOpenAboutWindow() { Window parent = SwingUtilities.windowForComponent(vPanel); JDialog aboutframe = new AboutFrame((Frame) parent); aboutframe.show(); } protected void menuOpenAssociationConfig() { if (!controller.hasTopicMap()) return; if (assocFrame == null) { assocFrame = TypesConfigFrame.createAssociationTypeConfigFrame( controller, this); assocFrame.show(); } else { assocFrame.setVisible(true); assocFrame.toFront(); } } private void menuOpenGeneralConfig() { if (!controller.hasTopicMap()) return; if (generalFrame == null) { generalFrame = new GeneralConfigFrame(controller); generalFrame.show(); } else { generalFrame.setVisible(true); generalFrame.toFront(); } } private void menuOpenPrecedenceConfig() { if (!controller.hasTopicMap()) return; if (precedenceFrame == null) { precedenceFrame = new TypesPrecedenceFrame(controller); precedenceFrame.show(); } else { precedenceFrame.setVisible(true); precedenceFrame.toFront(); } } protected void menuOpenTopicConfig() { if (!controller.hasTopicMap()) return; if (topicFrame == null) { topicFrame = TypesConfigFrame.createTopicTypeConfigFrame(controller, this); topicFrame.show(); } else { topicFrame.setVisible(true); topicFrame.toFront(); } } private void menuSaveConfiguration() { if (!controller.hasTopicMap()) return; File existing = getFileFor(controller.getConfigurationManager() .getTopicMap()); if (existing == null) existing = getConfigFileFor(getFileFor(controller.getTopicMap())); JFileChooser fc = new JFileChooser(); fc.setSelectedFile(existing); SimpleFileFilter def = new SimpleFileFilter(Messages .getString("Viz.ConfigFilesDescription"), "viz"); fc.addChoosableFileFilter(def); int returnVal = fc.showSaveDialog(vPanel); if (returnVal == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { controller.saveTopicMapConfiguration(f); } catch (IOException e) { ErrorDialog.showError(vPanel, e); } } } private File getFileFor(TopicMapIF topicmap) { try { return URIUtils.getURIFile(topicmap.getStore().getBaseAddress()); } catch (MalformedURLException e) { return null; } } public String getCurrentTopicMapDirectory() { String configDir = controller.getCurrentTMDir(); if (configDir != null) return configDir; if (this.currentTopicMap == null) return null; // This seems like an overly convoluted way to get to the // (String)path of the currently loaded TM, but I have not // been able to find a simpler method. try { return new URL(this.currentTopicMap.getStore().getBaseAddress() .getAddress()).getPath(); } catch (MalformedURLException e) { throw new OntopiaRuntimeException(e); } } public void setCurrentTopicMapDirectory(String currentTMDir) { try { controller.setCurrentTMDir(currentTMDir); } catch (IOException e) { throw new OntopiaRuntimeException(e); } } public String getCurrentRDBMSDir() { return controller.getCurrentRDBMSDir(); } public void setCurrentRDBMSDir(String dir) { try { controller.setCurrentRDBMSDir(dir); } catch (IOException e) { ErrorDialog.showError(vPanel, Messages.getString("Viz.DirError"), e); } } public String getCurrentConfigDir() { return controller.getCurrentConfigDir(); } public void setCurrentConfigDir(String dir) { try { controller.setCurrentConfigDir(dir); } catch (IOException e) { ErrorDialog.showError(vPanel, Messages.getString("Viz.DirError"), e); } } public TopicMapIF getCurrentTopicMap() { return currentTopicMap; } protected void resetStartTopicMenu() { Node focusNode = controller.getFocusNode(); TopicIF startTopic = controller.getStartTopic(); // Not very pretty, but it does the job and I am a bit short of time focusStartTopicItem .setEnabled((startTopic != null && (focusNode == null || !(focusNode instanceof TMTopicNode))) || (startTopic != null && (focusNode != null) && !startTopic .equals(((TMTopicNode) focusNode).getTopic()))); } public Component getVpanel() { return vPanel; } /** * INTERNAL. */ protected class ScopeActionListener implements ActionListener { private TopicIF scope; protected ScopeActionListener(TopicIF topic) { scope = topic; } public void actionPerformed(ActionEvent aE) { scopingTopicChanged(scope); } } protected class DynamicMenuListener implements ActionListener { public void actionPerformed(ActionEvent aE) { configureDynamicMenus(); } } // --- VizFrontEndIF implementation public ApplicationContextIF getContext() { return new DesktopContext(this); } public boolean getDefaultControlsVisible() { return true; } public TypesConfigFrame getTypesConfigFrame(VizController controller, boolean isTopicConfig) { if(isTopicConfig) { return TypesConfigFrame.createTopicTypeConfigFrame(controller, this); } else { return TypesConfigFrame.createAssociationTypeConfigFrame(controller, this); } } public boolean mapPreLoaded() { return false; } public TopicMapIF getTopicMap() { return currentTopicMap; } public String getWallpaper() { return null; } public String getConfigURL() { return null; } public boolean useGeneralConfig() { return true; } }