Java tutorial
/* =========================================================================== Copyright 2002-2010 Martin Dvorak 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 com.emental.mindraider.ui.outline; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.File; import java.net.URI; import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JToolBar; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import com.emental.mindraider.core.MindRaider; import com.emental.mindraider.core.rdf.MindRaiderVocabulary; import com.emental.mindraider.core.rest.properties.AttachmentProperty; import com.emental.mindraider.core.rest.resource.ConceptResource; import com.emental.mindraider.core.rest.resource.OutlineResource; import com.emental.mindraider.ui.dialogs.AttachmentJDialog; import com.emental.mindraider.ui.dialogs.NewNoteJDialog; import com.emental.mindraider.ui.dialogs.OpenOutlineJDialog; import com.emental.mindraider.ui.frames.MindRaiderMainWindow; import com.emental.mindraider.ui.gfx.IconsRegistry; import com.emental.mindraider.ui.outline.treetable.JTreeTable; import com.emental.mindraider.ui.outline.treetable.NotebookOutlineEntry; import com.emental.mindraider.ui.outline.treetable.NotebookOutlineModel; import com.emental.mindraider.ui.outline.treetable.OutlineTreeInstance; import com.mindcognition.mindraider.application.model.note.NoteCustodian; import com.mindcognition.mindraider.application.model.outline.OutlineCustodian; import com.mindcognition.mindraider.commons.MindRaiderConstants; import com.mindcognition.mindraider.commons.config.ConfigurationBean; import com.mindcognition.mindraider.commons.spring.MindRaiderSpringContext; import com.mindcognition.mindraider.integration.gnowsis.GnowsisClient; import com.mindcognition.mindraider.l10n.Messages; import com.mindcognition.mindraider.ui.swing.concept.ConceptJPanel; import com.mindcognition.mindraider.ui.swing.main.StatusBar; import com.mindcognition.mindraider.utils.Launcher; import com.mindcognition.mindraider.utils.Utils; /** * Panel holding notebook - * tree table (NotebookOutline), * mind map (RDF based graph, tag cloud) * and concept panel (active concept title/annotation) * <br> * <br> * Master is responsible for slots rendering. Knows slots offset, which slots * are shown, how is the tree folded, is able to crop the last slot on the page. */ public final class OutlineJPanel extends JPanel { private static final Logger logger = Logger.getLogger(OutlineJPanel.class); private static final int LABEL_COLUMN_PREFERRED_WIDTH = 200; private static final int LABEL_COLUMN_MAX_WIDTH = 300; private static final int DATE_COLUMN_PREFERRED_WIDTH = 50; private static final int DATE_COLUMN_MAX_WIDTH = 100; /* * Table tree classes: * o NotebookOutlineModel * ... table tree model * o NotebookOutlineTreeTable * ... just helper containing specialized table tree nodes + changes listener * o treeTable * ... basic widget behind the scene */ // object tree private OutlineTreeInstance outlineTableTree; // basic widget public JTreeTable treeTable; // class extending basic widget - notebook ouline table tree private NotebookOutlineModel outlineTableTreeModel; /* * UI */ public ConceptJPanel conceptJPanel; public ButtonGroup buttonGroup; public JRadioButton conceptRadio; public JComboBox searchTextCombo; public JSplitPane treeAndSpidersSplit; public JSplitPane rightSiderbarSplitPane; public JTabbedPane spidersAndTagsTabs; public JTabbedPane outlineAndTreeTabbedPane; private JButton newButton, attachButton; private JButton discardButton; private JButton refreshButton; private JButton refactorButton; private JButton promoteButton, demoteButton, upButton, downButton, firstButton, lastButton; private JButton onTheFlyExportButton, onTheFlyTWikiExportButton, expandTreeButton, collapseTreeButton, mindForgerUploadJButton; private JButton twikiExportJButton; private JButton gnowsisLinkButton; private OutlineArchiveJPanel outlineArchiveJPanel; private OutlineSorterJPanel outlineSorterJPanel; /** * singleton */ private static OutlineJPanel singleton; public static synchronized OutlineJPanel getInstance() { if (singleton == null) { singleton = new OutlineJPanel(); } return singleton; } /** * Creates notebook outline. */ private OutlineJPanel() { setDoubleBuffered(true); setLayout(new BorderLayout()); /* * toolbar */ JToolBar toolbar = createToolbar(); /* * tree */ // tree table itself outlineTableTree = OutlineTreeInstance.getInstance(); outlineTableTreeModel = new NotebookOutlineModel(outlineTableTree.getOutlineRoot()); treeTable = new JTreeTable(outlineTableTreeModel); treeTable.tree.addTreeSelectionListener(new TreeSelectionListenerImplementation()); // add key listener treeTable.addKeyListener(new KeyListenerImplementation()); // label column TableColumn tableColumn = treeTable .getColumn(NotebookOutlineModel.columnNames[NotebookOutlineModel.COLUMN_LABEL]); tableColumn.setMaxWidth(LABEL_COLUMN_MAX_WIDTH); tableColumn.setMinWidth(0); tableColumn.setPreferredWidth(LABEL_COLUMN_PREFERRED_WIDTH); // date column tableColumn = treeTable.getColumn(NotebookOutlineModel.columnNames[NotebookOutlineModel.COLUMN_CREATED]); tableColumn.setMaxWidth(DATE_COLUMN_MAX_WIDTH); tableColumn.setMinWidth(0); tableColumn.setPreferredWidth(DATE_COLUMN_PREFERRED_WIDTH); // and the rest will be annotation JScrollPane treeTableScrollPane = new JScrollPane(treeTable); // outline treetabble + toolbar panel JPanel treeAndToolbarPanel = new JPanel(new BorderLayout()); treeAndToolbarPanel.add(toolbar, BorderLayout.NORTH); treeAndToolbarPanel.add(treeTableScrollPane, BorderLayout.CENTER); /* * outline / list tabbed pane */ outlineAndTreeTabbedPane = new JTabbedPane(JTabbedPane.BOTTOM); outlineAndTreeTabbedPane.add(treeAndToolbarPanel, "Outline"); outlineSorterJPanel = new OutlineSorterJPanel(); outlineAndTreeTabbedPane.add(outlineSorterJPanel, "Sorter"); outlineArchiveJPanel = new OutlineArchiveJPanel(); outlineAndTreeTabbedPane.add(outlineArchiveJPanel, "Archive"); /* * concept sidebar */ conceptJPanel = (ConceptJPanel) MindRaiderSpringContext.getCtx().getBean("conceptPanel"); /* * vertical split of notebook outline and RDF graph */ treeAndSpidersSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); treeAndSpidersSplit.setContinuousLayout(true); treeAndSpidersSplit.setOneTouchExpandable(true); treeAndSpidersSplit.setDividerLocation(200); treeAndSpidersSplit.setLastDividerLocation(150); treeAndSpidersSplit.setDividerSize(6); treeAndSpidersSplit.add(outlineAndTreeTabbedPane); // spiders & tags visual navigation spidersAndTagsTabs = new JTabbedPane(JTabbedPane.BOTTOM); if (MindRaider.profile.isEnableSpiders()) { // notebook mind map spidersAndTagsTabs.addTab("Mind Map", MindRaider.spidersGraph.getPanel()); // TODO bundle } // global tags spidersAndTagsTabs.addTab("Tag Cloud", MindRaider.tagCustodian.getPanel()); // TODO bundle // global mind map //spidersAndTagsTabs.addTab("Global Mind Map",new JPanel()); // TODO bundle // lazy spiders rendering spidersAndTagsTabs.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent changeEvent) { JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource(); if (sourceTabbedPane.getSelectedIndex() == 0) { MindRaider.spidersGraph.renderModel(); } } }); if (!new ConfigurationBean().isDefaultTabMindMap()) { spidersAndTagsTabs.setSelectedIndex(1); } MindRaider.tagCustodian.redraw(); // add spiders panel treeAndSpidersSplit.add(spidersAndTagsTabs); /* * horizontal split of outline/graph slit and concept sidebar */ rightSiderbarSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeAndSpidersSplit, conceptJPanel); rightSiderbarSplitPane.setOneTouchExpandable(true); rightSiderbarSplitPane.setContinuousLayout(true); rightSiderbarSplitPane.setDividerLocation(500); rightSiderbarSplitPane.setLastDividerLocation(500); rightSiderbarSplitPane.setDividerSize(6); add(rightSiderbarSplitPane); } private JToolBar createToolbar() { JToolBar toolbar = new JToolBar(); newButton = new JButton("", IconsRegistry.getImageIcon("add.png")); newButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.newConcept")); newButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { newConcept(); } }); toolbar.add(newButton); attachButton = new JButton("", IconsRegistry.getImageIcon("attach.png")); attachButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.attachDragDropResourceToConcept")); attachButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptAttach(); } }); toolbar.add(attachButton); discardButton = new JButton("", IconsRegistry.getImageIcon("explorerDiscardSmall.png")); discardButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.discardConcept")); discardButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptDiscard(); } }); toolbar.add(discardButton); toolbar.addSeparator(); promoteButton = new JButton("", IconsRegistry.getImageIcon("back.png")); promoteButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.promoteConceptToParentLevel")); promoteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptPromote(); } }); toolbar.add(promoteButton); firstButton = new JButton("", IconsRegistry.getImageIcon("upup.png")); firstButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.moveConceptFirst")); firstButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { while (conceptUp()) ; } }); toolbar.add(firstButton); upButton = new JButton("", IconsRegistry.getImageIcon("up.png")); upButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.moveConceptUp")); upButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptUp(); } }); toolbar.add(upButton); downButton = new JButton("", IconsRegistry.getImageIcon("down.png")); downButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.moveConceptDown")); downButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptDown(); } }); toolbar.add(downButton); lastButton = new JButton("", IconsRegistry.getImageIcon("downdown.png")); lastButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.moveConceptLast")); lastButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { while (conceptDown()) ; } }); toolbar.add(lastButton); demoteButton = new JButton("", IconsRegistry.getImageIcon("forward.png")); demoteButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.demoteConceptToChildrenLevel")); demoteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { conceptDemote(); } }); toolbar.add(demoteButton); toolbar.addSeparator(); refactorButton = new JButton("", IconsRegistry.getImageIcon("refactorConcept.png")); refactorButton .setToolTipText(Messages.getString("NotebookOutlineJPanel.refactorConceptsToAnotherNotebook")); refactorButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { /* * in this case refactoring means: o discard of the concept in * this notebook o creation of the concept in the target * notebook concept is not deleted because URN should be never * deleted. this feature will be important for example for * vodyanoi. */ conceptRefactor(); treeTable.tree.updateUI(); } }); toolbar.add(refactorButton); refreshButton = new JButton("", IconsRegistry.getImageIcon("explorerReloadSmall.png")); refreshButton.setToolTipText(Messages.getString("NotebookOutlineJPanel.reloadNotebook")); refreshButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { refresh(); } }); toolbar.add(refreshButton); toolbar.addSeparator(); expandTreeButton = new JButton("", IconsRegistry.getImageIcon("expandTree.png")); expandTreeButton.setToolTipText("Expand Concept tree"); expandTreeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { expandAllTreeTableRows(); } }); toolbar.add(expandTreeButton); collapseTreeButton = new JButton("", IconsRegistry.getImageIcon("collapseTree.png")); collapseTreeButton.setToolTipText("Collapse Concept tree"); collapseTreeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { collapseAllTreeTableRows(); } }); toolbar.add(collapseTreeButton); toolbar.addSeparator(); // Gnowsis: link gnowsisLinkButton = new JButton("", IconsRegistry.getImageIcon("gnowsisLink.png")); gnowsisLinkButton.setToolTipText("Send Concept to Gnowsis to be linked"); gnowsisLinkButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To send URI to Gnowsis a notebook must be loaded!", "Gnowsis Error", JOptionPane.ERROR_MESSAGE); return; } // determine selected resource URI DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { String uri = ((OutlineNode) node).getUri(); logger.debug("Gnowsis hub: sending URI: '" + uri + "'"); GnowsisClient.linkResource(uri); } else { logger.debug("No node selected!"); } } }); if (MindRaider.profile.isEnableGnowsisSupport()) { toolbar.add(gnowsisLinkButton); } // Gnowsis: browse gnowsisBrowseButton = new JButton("", IconsRegistry.getImageIcon("gnowsisBrowse.png")); gnowsisBrowseButton.setToolTipText("Browse Concept in Gnowsis"); gnowsisBrowseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To browse URI in Gnowsis a notebook must be loaded!", "Gnowsis Error", JOptionPane.ERROR_MESSAGE); return; } // determine selected resource URI DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { String uri = ((OutlineNode) node).getUri(); logger.debug("Gnowsis hub: sending browse URI: '" + uri + "'"); GnowsisClient.browseResource(uri); } else { logger.debug("No node selected!"); } } }); if (MindRaider.profile.isEnableGnowsisSupport()) { toolbar.add(gnowsisBrowseButton); toolbar.addSeparator(); } // JButton button = new JButton("", IconsRegistry.getImageIcon("collapseTree.png")); // button.setToolTipText("Hide/Show annotation column"); // button.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) { // hideTreeTableAnnotationColumn(); // } // }); // mainPanelControls.add(button); // mainPanelControls.addSeparator(); onTheFlyTWikiExportButton = new JButton("", IconsRegistry.getImageIcon("mozillaTwiki.png")); onTheFlyTWikiExportButton.setToolTipText("'On the fly' TWiki Export 2 HTML"); onTheFlyTWikiExportButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To export a notebook it must be loaded!", "Export Error", JOptionPane.ERROR_MESSAGE); return; } // prepare directory String exportDirectory = MindRaider.profile.getHomeDirectory() + File.separator + "export" + File.separator + "twiki" + File.separator + "tmp"; Utils.createDirectory(exportDirectory); String dstFileName = exportDirectory + File.separator + "TWIKI-EXPORT-" + MindRaider.outlineCustodian.getActiveNotebookNcName() + ".html"; logger.debug("Exporting to file: " + dstFileName); MindRaider.outlineCustodian.exportOutline(OutlineCustodian.FORMAT_TWIKI_HTML, dstFileName); Launcher.launchInBrowser(dstFileName); } }); // TODO removed mainPanelControls.add(onTheFlyTWikiExportButton); twikiExportJButton = new JButton("", IconsRegistry.getImageIcon("twikiExport.png")); twikiExportJButton.setToolTipText("Export back to the imported TWiki file"); twikiExportJButton.setEnabled(false); twikiExportJButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To export a notebook it must be loaded!", "Export Error", JOptionPane.ERROR_MESSAGE); return; } // take the path from the notebook custodian String dstFileName; OutlineResource notebookResource = MindRaider.outlineCustodian.getActiveOutlineResource(); if (notebookResource != null && notebookResource.getSourceTWikiFileProperty() != null) { dstFileName = notebookResource.getSourceTWikiFileProperty().getPath(); StatusBar.show("Exporting Notebook to TWiki file: '" + dstFileName + "'..."); MindRaider.outlineCustodian.exportOutline(OutlineCustodian.FORMAT_TWIKI, dstFileName); } } }); toolbar.add(twikiExportJButton); // TODO removed mainPanelControls.addSeparator(); onTheFlyExportButton = new JButton("", IconsRegistry.getImageIcon("mozilla.png")); onTheFlyExportButton.setToolTipText("'On the fly' OPML Export 2 HTML"); onTheFlyExportButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To export a notebook it must be loaded!", "Export Error", JOptionPane.ERROR_MESSAGE); return; } // prepare directory String exportDirectory = MindRaider.profile.getHomeDirectory() + File.separator + "export" + File.separator + "opml" + File.separator + "tmp"; Utils.createDirectory(exportDirectory); String dstFileName = exportDirectory + File.separator + "OPML-EXPORT-" + MindRaider.outlineCustodian.getActiveNotebookNcName() + ".html"; logger.debug("Exporting to file: " + dstFileName); MindRaider.outlineCustodian.exportOutline(OutlineCustodian.FORMAT_OPML_HTML, dstFileName); Launcher.launchInBrowser(dstFileName); } }); // TODO removed mainPanelControls.add(onTheFlyExportButton); toolbar.addSeparator(); mindForgerUploadJButton = new JButton("", IconsRegistry.getImageIcon("tasks-internet.png")); mindForgerUploadJButton.setToolTipText("Upload this Outline to Online Edition"); mindForgerUploadJButton.setEnabled(false); mindForgerUploadJButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (MindRaider.profile.getActiveOutline() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, "To upload an Outline it must be loaded!", "Upload Error", JOptionPane.ERROR_MESSAGE); return; } // take the path from the notebook custodian MindRaiderMainWindow.getInstance().handleMindForgerActiveOutlineUpload(); } }); toolbar.add(mindForgerUploadJButton); return toolbar; } /** * Refresh. */ public void refresh() { logger.debug("Notebook Outline refresh..."); // refresh tree if (MindRaider.profile.getActiveOutlineUri() != null) { outlineTableTree.rebuildTree(); } else { outlineTableTree.clear(); } // sorter outlineSorterJPanel.updateUI(); outlineSorterJPanel.refresh(); // archive outlineArchiveJPanel.updateUI(); int archivedConcepts = outlineArchiveJPanel.refresh(); // archive tab if (outlineAndTreeTabbedPane != null) { outlineAndTreeTabbedPane.setTitleAt(2, "Archive (" + archivedConcepts + ")"); } // redraw widget treeTable.updateUI(); // select root treeTable.tree.setSelectionRow(0); // TODO make this optional (in profile) expandAllTreeTableRows(); // update buttons status enableDisableToolbarButtons(0); if (MindRaider.profile.getActiveOutlineUri() != null) { newButton.setEnabled(true); expandTreeButton.setEnabled(true); refreshButton.setEnabled(true); onTheFlyExportButton.setEnabled(true); onTheFlyTWikiExportButton.setEnabled(true); mindForgerUploadJButton.setEnabled(true); // TWiki import - determine whether active notebook has set twiki // import property OutlineResource notebookResource = MindRaider.outlineCustodian.getActiveOutlineResource(); if (notebookResource != null && notebookResource.getSourceTWikiFileProperty() != null) { twikiExportJButton.setEnabled(true); } else { twikiExportJButton.setEnabled(false); } // try to load concept (the first one) // @todo load it from the last clicked resource // ResourceDescriptor[] conceptDescriptors = MindRaider.notebookCustodian.getConceptDescriptors(); // if(conceptDescriptors!=null && conceptDescriptors.length>0) { // try { // conceptJPanel.refresh(MindRaider.conceptCustodian.get( // MindRaider.profile.getActiveNotebookUri().toString(), // conceptDescriptors[0].getUri())); // } catch (Exception e) { // logger.debug("Unable to load default concept!"); // } // } } else { newButton.setEnabled(false); expandTreeButton.setEnabled(false); refreshButton.setEnabled(false); onTheFlyExportButton.setEnabled(false); onTheFlyTWikiExportButton.setEnabled(false); twikiExportJButton.setEnabled(false); mindForgerUploadJButton.setEnabled(false); } treeTable.tree.updateUI(); } /** * Expand all tree table rows. */ public void expandAllTreeTableRows() { for (int i = 0; i < treeTable.tree.getRowCount(); i++) { treeTable.tree.expandRow(i); } } /** * Collapse all tree table rows. */ public void collapseAllTreeTableRows() { try { for (int i = 0; i < treeTable.tree.getRowCount(); i++) { if (i > 0) { treeTable.tree.collapseRow(i); } } } catch (Exception e) { // } } /** * Clear. */ public void clear() { outlineTableTree.clear(); conceptJPanel.clear(); treeTable.updateUI(); } /** * Redraw. */ public void redrawTreeTable() { if (MindRaider.profile.getActiveOutlineUri() != null) { treeTable.updateUI(); } } private final class KeyListenerImplementation implements KeyListener { public void keyPressed(KeyEvent keyEvent) { if (keyEvent.isControlDown()) { // if(keyEvent.getKeyCode() == KeyEvent.VK_N) { // NotebookOutlineJPanel.getInstance().conceptNew(); // return; // } if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) { OutlineJPanel.getInstance().conceptPromote(); return; } if (keyEvent.getKeyCode() == KeyEvent.VK_UP) { OutlineJPanel.getInstance().conceptUp(); return; } if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) { OutlineJPanel.getInstance().conceptDown(); return; } if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) { OutlineJPanel.getInstance().conceptDemote(); return; } } if (keyEvent.getKeyCode() == KeyEvent.VK_TAB) { OutlineJPanel.getInstance().conceptDemote(); return; } if (keyEvent.getKeyCode() == KeyEvent.VK_DELETE) { OutlineJPanel.getInstance().conceptDiscard(); return; } } public void keyReleased(KeyEvent keyEvent) { } public void keyTyped(KeyEvent keyEvent) { } } private final class TreeSelectionListenerImplementation implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) treeTable.tree .getLastSelectedPathComponent(); if (selectedNode != null) { logger.debug("OUTLINE: tree selection path: " + selectedNode.getPath()[selectedNode.getLevel()]); enableDisableToolbarButtons(selectedNode.getLevel()); // skip root from rendering if (selectedNode.getLevel() != 0) { String conceptUri = ((NotebookOutlineEntry) selectedNode).uri; try { // now refresh concept JPanel if (conceptUri != null) { conceptJPanel.open(MindRaider.noteCustodian .get(MindRaider.profile.getActiveOutlineUri().toString(), conceptUri)); // recent concepts MindRaider.recentConcepts.addRecentConcept( treeTable.tree.getSelectionModel().getSelectionPath().getLastPathComponent() .toString(), conceptUri, MindRaider.outlineCustodian.getActiveNotebookLabel(), MindRaider.outlineCustodian.getActiveOutlineResource().getUri()); // select concept in the graph MindRaider.spidersGraph.selectNodeByUri(conceptUri); } else { logger.debug("Concept URI is null - fallback to refresh..."); refresh(); } } catch (Exception e1) { logger.debug("Unable to select concept " + conceptUri, e1); } } } } } /** * The renderer used for String in the TreeTable. The only thing it does, is * to format a null String as '---'. */ static class BookmarksStringRenderer extends DefaultTableCellRenderer { /** * Serial version. */ private static final long serialVersionUID = 1L; /** * Constructor. */ public BookmarksStringRenderer() { super(); } /** * Set value. */ public void setValue(Object value) { setText((value == null) ? "---" : value.toString()); } } /** * Get notebook outline. * * @return */ public OutlineTreeInstance getOutlineTableTree() { return outlineTableTree; } /** * Get concept JPanel. * * @return */ public ConceptJPanel getConceptJPanel() { return conceptJPanel; } /* * UI */ /* * get selected... used for rendering */ /** * Get URI of the selected concept. */ public String getSelectedConceptUri() { TreePath treePath = treeTable.tree.getSelectionPath(); if (treePath != null) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent(); if (node != null) { return ((OutlineNode) node).getUri(); } } return null; } /** * Get selected tree node. * * @return */ public DefaultMutableTreeNode getSelectedTreeNode() { TreePath treePath = treeTable.tree.getSelectionPath(); if (treePath == null) { return null; } return (DefaultMutableTreeNode) treePath.getLastPathComponent(); } /** * Set selected tree node. * * @param conceptUri */ public void setSelectedTreeNodeConcept(String conceptUri) { logger.debug("=-> setSelectedTreeNodeConcept"); // try to load concept with this URI if (conceptUri != null && MindRaiderVocabulary.isConceptUri(conceptUri) && MindRaider.profile.getActiveOutlineUri() != null && !conceptUri.equals( NoteCustodian.getTrashConceptUri(MindRaider.profile.getActiveOutlineUri().toString()))) { try { // select particular concept in the table - find it yourself int rows = treeTable.tree.getRowCount(); TreePath treePath; OutlineNode node; for (int i = 0; i < rows; i++) { if (i > 0) { treePath = treeTable.tree.getPathForRow(i); // logger.debug("Tree path: "+treePath); node = (OutlineNode) treePath.getLastPathComponent(); if (conceptUri.equals(node.getUri())) { // logger.debug("Bingo: "+conceptUri); treeTable.tree.makeVisible(treePath); treeTable.tree.getSelectionModel().setSelectionPath(treePath); break; } } } } catch (Exception e) { logger.debug("Unable to load Concept for selected graph node: " + conceptUri, e); } } } /* * UI */ private boolean rightSidebarLatelyMaximized = true; public void toggleRightSidebar() { if (!rightSidebarLatelyMaximized) { rightSiderbarSplitPane.setDividerLocation(rightSiderbarSplitPane.getLastDividerLocation()); } else { rightSiderbarSplitPane.setDividerLocation(2000); } rightSiderbarSplitPane.updateUI(); rightSidebarLatelyMaximized = !rightSidebarLatelyMaximized; } public void hideRightSiderbar() { toggleRightSidebar(); if (rightSidebarLatelyMaximized) { toggleRightSidebar(); } } private boolean conceptTreeLatelyMaximized = true; private AbstractButton gnowsisBrowseButton; public void toggleConceptTree() { conceptTreeLatelyMaximized = !conceptTreeLatelyMaximized; if (conceptTreeLatelyMaximized) { treeAndSpidersSplit.setDividerLocation(treeAndSpidersSplit.getLastDividerLocation()); } else { treeAndSpidersSplit.setDividerLocation(2000); } treeAndSpidersSplit.updateUI(); } public void hideSpiders() { treeAndSpidersSplit.setDividerLocation(2000); treeAndSpidersSplit.updateUI(); } public void hideConceptTree() { // use divider location to determine current status if (treeAndSpidersSplit.getDividerLocation() != 0) { // maximize rdf navigator treeAndSpidersSplit.setDividerLocation(0); } treeAndSpidersSplit.updateUI(); } public void toggleRdfNavigator() { // use divider location to determine current status if (treeAndSpidersSplit.getDividerLocation() == 0) { // concept tree is minimized - rdf navigator maximized - get last // position treeAndSpidersSplit.setDividerLocation(treeAndSpidersSplit.getLastDividerLocation()); } else { // maximize rdf navigator treeAndSpidersSplit.setDividerLocation(0); } treeAndSpidersSplit.updateUI(); } /** * Enable/disable buttons. * * @param node */ protected void enableDisableToolbarButtons(int level) { // enable/disable buttons if (level == 0) { newButton.setEnabled(true); discardButton.setEnabled(false); promoteButton.setEnabled(false); demoteButton.setEnabled(false); upButton.setEnabled(false); firstButton.setEnabled(false); downButton.setEnabled(false); lastButton.setEnabled(false); gnowsisLinkButton.setEnabled(false); gnowsisBrowseButton.setEnabled(false); refactorButton.setEnabled(false); } else { newButton.setEnabled(true); discardButton.setEnabled(true); promoteButton.setEnabled(true); demoteButton.setEnabled(true); upButton.setEnabled(true); firstButton.setEnabled(true); downButton.setEnabled(true); lastButton.setEnabled(true); gnowsisLinkButton.setEnabled(true); gnowsisBrowseButton.setEnabled(true); refactorButton.setEnabled(true); } enableDisableAttachToolbarButton(); } public void disableAllToolbarButtons() { newButton.setEnabled(false); discardButton.setEnabled(false); promoteButton.setEnabled(false); demoteButton.setEnabled(false); upButton.setEnabled(false); firstButton.setEnabled(false); downButton.setEnabled(false); lastButton.setEnabled(false); gnowsisLinkButton.setEnabled(false); gnowsisBrowseButton.setEnabled(false); expandTreeButton.setEnabled(false); collapseTreeButton.setEnabled(false); refreshButton.setEnabled(false); onTheFlyExportButton.setEnabled(false); onTheFlyTWikiExportButton.setEnabled(false); twikiExportJButton.setEnabled(false); mindForgerUploadJButton.setEnabled(false); refactorButton.setEnabled(false); attachButton.setEnabled(false); } /** * Enable/disable attach toolbar button. */ public void enableDisableAttachToolbarButton() { if (MindRaider.mainJFrame != null && MindRaider.mainJFrame.dragAndDropReference != null) { attachButton.setEnabled(true); } else { attachButton.setEnabled(false); } } /** * New concept. */ public void newConcept() { if (MindRaider.profile.getActiveOutlineUri() != null) { new NewNoteJDialog(MindRaider.profile.getActiveOutlineUri().toString(), conceptJPanel.getAnnotationsCustodian()); } else { JOptionPane.showMessageDialog(OutlineJPanel.this, "To define the Concept a Notebook must be opened!", "Concept Creation Error", JOptionPane.ERROR_MESSAGE); } } /** * Attach resource dropped to the MR window to current concept. */ public void conceptAttach() { if (MindRaider.profile.getActiveOutlineUri() != null) { ConceptResource conceptResource = conceptJPanel.getConceptResource(); if (conceptResource != null) { new AttachmentJDialog(conceptResource, MindRaider.mainJFrame.dragAndDropReference); } else { JOptionPane.showMessageDialog(OutlineJPanel.this, "To attach reference to the active Concept a Concept must be selected!", "D&D Concept Attach Error", JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(OutlineJPanel.this, "To attach reference to the active Concept a Notebook must be opened!", "D&D Concept Attach Error", JOptionPane.ERROR_MESSAGE); } } /** * Discard concept. */ public void conceptDiscard() { if (MindRaider.profile.getActiveOutlineUri() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, Messages.getString("NotebookOutlineJPanel.toDiscardConceptTheNotebookMustBeOpened"), Messages.getString("NotebookOutlineJPanel.discardConceptError"), JOptionPane.ERROR_MESSAGE); return; } // move concept up in the tree DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { if (node.isLeaf() && node.getParent() != null) { try { if (JOptionPane.showConfirmDialog(MindRaider.mainJFrame, Messages.getString("NotebookOutlineJPanel.doYouWantToDiscardConcept", node.toString()), Messages.getString("NotebookOutlineJPanel.discardConcept"), JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { return; } DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); String notebookUri = MindRaider.outlineCustodian.getActiveOutlineResource().resource .getMetadata().getUri().toString(); MindRaider.noteCustodian.discard(notebookUri, ((OutlineNode) parent).getUri(), ((OutlineNode) node).getUri()); refresh(); MindRaider.spidersGraph.selectNodeByUri(notebookUri); MindRaider.spidersGraph.renderModel(); conceptJPanel.clear(); } catch (Exception e1) { logger.debug(Messages.getString("NotebookOutlineJPanel.unableToDiscardConcept"), e1); StatusBar.show(Messages.getString("NotebookOutlineJPanel.unableToDiscardConcept")); } } else { StatusBar.show(Messages.getString("NotebookOutlineJPanel.discardingOnlyLeafConcepts")); JOptionPane.showMessageDialog(OutlineJPanel.this, Messages.getString("NotebookOutlineJPanel.discardingOnlyLeafConcepts"), "Concept Discard Error", JOptionPane.ERROR_MESSAGE); return; } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected")); } } public void conceptRefactor() { String sourceOutlineUri; String sourceConceptUri; if (MindRaider.profile.getActiveOutlineUri() == null) { JOptionPane.showMessageDialog(OutlineJPanel.this, Messages.getString("NotebookOutlineJPanel.toRefactorConceptTheNotebookMustBeOpened"), Messages.getString("NotebookOutlineJPanel.refactoringError"), JOptionPane.ERROR_MESSAGE); return; } DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { if (node.isLeaf()) { try { if (JOptionPane.showConfirmDialog(MindRaider.mainJFrame, Messages.getString("NotebookOutlineJPanel.doYouWantToRefactorConcept", node.toString()), Messages.getString("NotebookOutlineJPanel.refactorConcept"), JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { return; } DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); sourceOutlineUri = MindRaider.outlineCustodian.getActiveOutlineResource().resource.getMetadata() .getUri().toString(); sourceConceptUri = ((OutlineNode) node).getUri(); MindRaider.noteCustodian.discard(sourceOutlineUri, ((OutlineNode) parent).getUri(), sourceConceptUri); ConceptResource conceptResource = MindRaider.noteCustodian.get(sourceOutlineUri, sourceConceptUri); // choose target outline and create new concept into this notebook new OpenOutlineJDialog(Messages.getString("NotebookOutlineJPanel.refactorConcept"), Messages.getString("NotebookOutlineJPanel.selectTargetNotebook"), Messages.getString("NotebookOutlineJPanel.refactor"), false); // create that concept in the target notebook (put it to the root) String targetConceptUri = conceptResource.resource.getMetadata().getUri().toString(); while (MindRaiderConstants.EXISTS.equals( MindRaider.noteCustodian.create(MindRaider.outlineCustodian.getActiveOutlineResource(), null, conceptResource.getLabel(), targetConceptUri, conceptResource.getAnnotation(), false))) { targetConceptUri += "_"; } // refactor also attachments AttachmentProperty[] attachments = conceptResource.getAttachments(); if (!ArrayUtils.isEmpty(attachments)) { ConceptResource newConceptResource = MindRaider.noteCustodian .get(MindRaider.outlineCustodian.getActiveOutlineResource().resource.getMetadata() .getUri().toString(), targetConceptUri); for (AttachmentProperty attachment : attachments) { newConceptResource.addAttachment(attachment.getDescription(), attachment.getUrl()); } newConceptResource.save(); } // delete discarded concept in the source outline MindRaider.noteCustodian.deleteConcept(sourceOutlineUri, sourceConceptUri); refresh(); MindRaider.spidersGraph.selectNodeByUri(sourceOutlineUri); MindRaider.spidersGraph.renderModel(); } catch (Exception e1) { logger.debug(Messages.getString("NotebookOutlineJPanel.unableToRefactorConcept"), e1); StatusBar.show(Messages.getString("NotebookOutlineJPanel.unableToRefactorConcept")); } } else { StatusBar.show(Messages.getString("NotebookOutlineJPanel.discardingingOnlyLeafConcepts")); JOptionPane.showMessageDialog(OutlineJPanel.this, Messages.getString("NotebookOutlineJPanel.refactoringOnlyLeafConcepts"), Messages.getString("NotebookOutlineJPanel.refactoringError"), JOptionPane.ERROR_MESSAGE); return; } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected")); } } /** * Promote concept. */ public void conceptPromote() { // imagine the row and move it to the level up (left) in this row // node must be stored as parent's parent DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); if (parent != null) { DefaultMutableTreeNode pparent = (DefaultMutableTreeNode) parent.getParent(); if (pparent != null) { // now put it right behind previous parent int parentIndex = pparent.getIndex(parent); parent.remove(node); pparent.insert(node, parentIndex + 1); treeTable.updateUI(); logger.debug(Messages.getString("NotebookOutlineJPanel.noNodePromoted")); MindRaider.noteCustodian.promote(MindRaider.outlineCustodian.getActiveOutlineResource(), ((OutlineNode) pparent).getUri(), ((OutlineNode) parent).getUri(), ((OutlineNode) node).getUri()); } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noParentsParent")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noParent")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected")); } } /** * Up concept. */ public boolean conceptUp() { // move concept up in the tree DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); if (parent != null) { DefaultMutableTreeNode previousSibling = node.getPreviousSibling(); if (previousSibling != null) { // move it up in the model if (MindRaider.noteCustodian.up(MindRaider.outlineCustodian.getActiveOutlineResource(), ((OutlineNode) parent).getUri(), ((OutlineNode) node).getUri())) { int siblingIndex = parent.getIndex(previousSibling); parent.remove(node); parent.insert(node, siblingIndex); treeTable.updateUI(); logger.debug(Messages.getString("NotebookOutlineJPanel.noMovedUp")); return true; } // else it is the first concept in the sequence } else { logger.debug("No sibling!"); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noParent")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected")); } return false; } /** * Down concept. */ public boolean conceptDown() { // move concept down in the tree DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); if (parent != null) { DefaultMutableTreeNode nextSibling = node.getNextSibling(); if (nextSibling != null) { if (MindRaider.noteCustodian.down(MindRaider.outlineCustodian.getActiveOutlineResource(), ((OutlineNode) parent).getUri(), ((OutlineNode) node).getUri())) { int siblingIndex = parent.getIndex(nextSibling); parent.remove(node); parent.insert(node, siblingIndex); treeTable.updateUI(); logger.debug("Node moved down!"); return true; } // else node the last in the sequence } else { logger.debug("No sibling!"); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noParent")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected")); } return false; } /** * Demote concept. */ public void conceptDemote() { // current node becomes the first child of the previous sibling, if node // has index 0, then do nothing DefaultMutableTreeNode node = getSelectedTreeNode(); if (node != null) { DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); if (parent != null) { DefaultMutableTreeNode previous = (DefaultMutableTreeNode) parent.getChildBefore(node); if (previous != null) { parent.remove(node); previous.insert(node, previous.getChildCount()); treeTable.updateUI(); logger.debug(Messages.getString("NotebookOutlineJPanel.conceptDemoted")); MindRaider.noteCustodian.demote(MindRaider.outlineCustodian.getActiveOutlineResource(), ((OutlineNode) parent).getUri(), ((OutlineNode) node).getUri()); setSelectedTreeNodeConcept(((OutlineNode) node).getUri()); } else { logger.debug(Messages.getString("NotebookOutlineJPanel.isTheFirstChild")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noParent")); } } else { logger.debug(Messages.getString("NotebookOutlineJPanel.noNodeSelected!")); } } public void loadConcept(String notebookUri, String conceptUri) { if (notebookUri != null && conceptUri != null) { try { MindRaider.outlineCustodian.loadOutline(new URI(notebookUri)); OutlineJPanel.getInstance().refresh(); OutlineJPanel.getInstance().conceptJPanel .open(MindRaider.noteCustodian.get(notebookUri, conceptUri)); MindRaider.spidersGraph.selectNodeByUri(conceptUri); } catch (Exception e) { logger.debug("Unable to load concept!", e); // {{debug}} } } } private static final long serialVersionUID = 5042795015913549213L; }