Java tutorial
/* * Zettelkasten - nach Luhmann ** Copyright (C) 2001-2014 by Daniel Ldecke (http://www.danielluedecke.de) * * Homepage: http://zettelkasten.danielluedecke.de * * * 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 3 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, see <http://www.gnu.org/licenses/>. * * * Dieses Programm ist freie Software. Sie knnen es unter den Bedingungen der GNU * General Public License, wie von der Free Software Foundation verffentlicht, weitergeben * und/oder modifizieren, entweder gem Version 3 der Lizenz oder (wenn Sie mchten) * jeder spteren Version. * * Die Verffentlichung dieses Programms erfolgt in der Hoffnung, da es Ihnen von Nutzen sein * wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder * der VERWENDBARKEIT FR EINEN BESTIMMTEN ZWECK. Details finden Sie in der * GNU General Public License. * * Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm * erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>. */ package de.danielluedecke.zettelkasten; import com.explodingpixels.macwidgets.BottomBar; import de.danielluedecke.zettelkasten.util.Tools; import de.danielluedecke.zettelkasten.util.Constants; import de.danielluedecke.zettelkasten.util.HtmlUbbUtil; import de.danielluedecke.zettelkasten.util.classes.EntryStringTransferHandler; import com.explodingpixels.macwidgets.MacButtonFactory; import com.explodingpixels.macwidgets.MacUtils; import com.explodingpixels.macwidgets.MacWidgetFactory; import com.explodingpixels.macwidgets.UnifiedToolBar; import com.explodingpixels.macwidgets.WidgetFactory; import com.explodingpixels.widgets.WindowUtils; import de.danielluedecke.zettelkasten.database.AcceleratorKeys; import de.danielluedecke.zettelkasten.database.AutoKorrektur; import de.danielluedecke.zettelkasten.database.DesktopData; import de.danielluedecke.zettelkasten.util.classes.InitStatusbarForTasks; import de.danielluedecke.zettelkasten.database.Settings; import de.danielluedecke.zettelkasten.database.StenoData; import de.danielluedecke.zettelkasten.mac.MacSourceDesktopTree; import de.danielluedecke.zettelkasten.database.BibTex; import de.danielluedecke.zettelkasten.database.Bookmarks; import de.danielluedecke.zettelkasten.database.Daten; import de.danielluedecke.zettelkasten.database.TasksData; import de.danielluedecke.zettelkasten.tasks.TaskProgressDialog; import de.danielluedecke.zettelkasten.tasks.export.ExportTools; import de.danielluedecke.zettelkasten.util.ColorUtil; import de.danielluedecke.zettelkasten.util.FileOperationsUtil; import de.danielluedecke.zettelkasten.util.PlatformUtil; import de.danielluedecke.zettelkasten.util.TreeUtil; import de.danielluedecke.zettelkasten.util.classes.TreeUserObject; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FileDialog; import java.awt.Font; import java.awt.GraphicsDevice; import java.awt.IllegalComponentStateException; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.print.PrinterException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.logging.Level; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.border.MatteBorder; import javax.swing.event.HyperlinkEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.jdesktop.application.Action; import org.jdesktop.application.Application; import org.jdesktop.application.ApplicationContext; import org.jdesktop.application.Task; import org.jdesktop.application.TaskMonitor; import org.jdesktop.application.TaskService; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.jdom2.output.XMLOutputter; /** * * @author danielludecke */ public class DesktopFrame extends javax.swing.JFrame implements WindowListener { /** * Reference to the main data class. */ private final Daten dataObj; /** * */ private final TasksData taskdata; /** * Reference to the desktop data class. */ private final DesktopData desktopObj; /** * Reference to the bookmarks data class. */ private final Bookmarks bookmarksObj; /** * Reference to the settings class. */ private final Settings settingsObj; /** * */ private final BibTex bibtexObj; /** * */ private final AutoKorrektur spellObj; /** * */ private final StenoData stenoObj; /** * CAccelerator object, which contains the XML data of the accelerator table for the menus */ private final AcceleratorKeys accKeys; /** * */ private createDisplayTask cDisplayTask = null; /** * This variable indicates whether the task that updates the display is already * running or not... */ private boolean cDisplayTaskIsRunning = false; /** * Indicates whether the main entries' headings are visible or not. */ private boolean isHeadingVisible = true; /** * */ private boolean isEntryNumberVisible = true; /** * */ private boolean isEditModeActive = false; /** * Indicates the number of that entry that should be immediately selected * after the treeview is updated */ private int displayentrynr = -1; /** * Flag that indicates whether the message box warning when adding multiple entries * should only pop up once and not for each multiple entry */ private boolean showMultipleEntryMsg; /** * */ private String editModeTimeStamp = ""; /** * Used for the {@link #addLuhmann addLuhmann} Action. */ private StringBuilder luhmannnumbers; /** * This value stores entries that can be inserted using the {@link #pasteNode() pasteNode()}. */ public int[] clipEntries; /** * This variable indicates whether the entry in the clipboard is a bullet (true) or a child-entry (false) */ private boolean clipBullet = false; /** * This variable stores the name of the bullet that was copied or cut to the clipboard. we need * this information when inserting the bullet, so we can avoid double bullet-entries (double names). */ private String clipBulletName; /** * This variable stores modifications from entries that are cut or copied within the jTree. * Since cutting out an entry will delete it, the timestamp reference to possible modifications * is lost. To avoid this, we store the modifications in this variable. */ private String clipModifiedEntryContent = null; /** * This variable stores the treepath when a node was dragged&dropped within the jtreedesktop */ private DefaultMutableTreeNode movedNodeToRemove = null; /** * */ private final String lineseparator; /** * */ private String multipleOccurencesMessage; /** * Reference to the main frame. */ private final ZettelkastenView zknframe; /** * */ private int findlivepos; /** * */ private int findlivemax = 1; /** * create a new stringbuilder that will contain the plain text of * entries in the editorpane, so we can count the words */ private final StringBuilder sbWordCountDisplayTask = new StringBuilder(""); /** * */ private String completePage = ""; /** * This variable gets the graphic device and ist needed for full-screen-functionality. see * {@link #viewFullScreen() viewFullScreen()} for more details. */ private final GraphicsDevice graphicdevice = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice(); /** * */ private final JFrame mainframe; /** * get the strings for file descriptions from the resource map */ private final org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(DesktopFrame.class); /** * get the strings for file descriptions from the resource map */ private final org.jdesktop.application.ResourceMap toolbarResourceMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ToolbarIcons.class); /** * * @param zkn * @param td * @param d * @param bm * @param dk * @param s * @param ak * @param bt * @param st * @param auk */ @SuppressWarnings("LeakingThisInConstructor") public DesktopFrame(ZettelkastenView zkn, TasksData td, Daten d, Bookmarks bm, DesktopData dk, Settings s, AcceleratorKeys ak, BibTex bt, AutoKorrektur auk, StenoData st) { // reference needed for fullscreen mainframe = this; dataObj = d; taskdata = td; desktopObj = dk; settingsObj = s; accKeys = ak; bibtexObj = bt; zknframe = zkn; spellObj = auk; stenoObj = st; bookmarksObj = bm; // check whether memory usage is logged. if so, tell logger that new entry windows was opened if (settingsObj.isMemoryUsageLogged) { // log info Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window opened."); } // create brushed look for window, so toolbar and window-bar become a unit if (settingsObj.isMacAqua()) { MacUtils.makeWindowLeopardStyle(getRootPane()); // WindowUtils.createAndInstallRepaintWindowFocusListener(this); WindowUtils.installJComponentRepainterOnWindowFocusChanged(this.getRootPane()); } // init all components initComponents(); initListeners(); initBorders(settingsObj); headingsVisibleMenuItem.setSelected(isHeadingVisible); entryNumberVisibleMenuItem.setSelected(isEntryNumberVisible); // set application icon setIconImage(Constants.zknicon.getImage()); // if we have mac os x with aqua, make the window look like typical cocoa-applications if (settingsObj.isMacAqua()) { setupMacOSXLeopardStyle(); } if (settingsObj.isSeaGlass()) { setupSeaGlassStyle(); } // hide live-searchpanel on init. jPanelLiveSearch.setVisible(false); // retrieve system's line-separator lineseparator = System.getProperty("line.separator"); // init the progressbar and animated icon for background tasks InitStatusbarForTasks isb = new InitStatusbarForTasks(statusAnimationLabel, null, null); // set click to update-text jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText")); jButtonShowMultipleOccurencesDlg.setVisible(false); // init the accelerator keys initAcceleratorTable(); // This method initialises the toolbar buttons. depending on the user-setting, we either // display small, medium or large icons as toolbar-icons. initToolbarIcons(); // init jTree. we also initialise a DropTargetEvent here, so drag&drop-handling is // completeley initiated in this method initTree(); // init drag&drop-operations for editor-panes, so the user can drag&drop entries // from the jTree to the editorpanes... initDropPanes(jTextArea1); initDropPanes(jTextArea2); initDropPanes(jTextArea3); initComboBox(); initDefaultFontSize(); updateTitle(); } private void initBorders(Settings settingsObj) { /* * Constructor for Matte Border * public MatteBorder(int top, int left, int bottom, int right, Color matteColor) */ jPanelLiveSearch .setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); if (settingsObj.isSeaGlass()) { jSplitPaneDesktop2 .setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane1 .setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, ColorUtil.getBorderGray(settingsObj))); jTextArea1.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea1.border.title"), settingsObj)); jTextArea2.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea2.border.title"), settingsObj)); jTextArea3.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea3.border.title"), settingsObj)); } if (settingsObj.isMacAqua()) { WidgetFactory.updateSplitPane(jSplitPaneDesktop1); WidgetFactory.updateSplitPane(jSplitPaneDesktop2); jTextArea1.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea1.border.title"), settingsObj)); jTextArea2.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea2.border.title"), settingsObj)); jTextArea3.setBorder( WidgetFactory.getTitledBorder(resourceMap.getString("jTextArea3.border.title"), settingsObj)); } } /** * */ public final void updateTitle() { String currentTitle = getTitle(); // get filename and find out where extension begins, so we can just set the filename as title File f = settingsObj.getFilePath(); // check whether we have any valid filepath at all if (f != null && f.exists()) { String fname = f.getName(); // find file-extension int extpos = fname.lastIndexOf(Constants.ZKN_FILEEXTENSION); // set the filename as title if (extpos != -1) { // show proxy-icon, only applies to mac. getRootPane().putClientProperty("Window.documentFile", f); // set file-name and app-name in title-bar setTitle(currentTitle + " - [" + fname.substring(0, extpos) + "]"); } } } /** * */ private void initListeners() { // <editor-fold defaultstate="collapsed" desc="Here all relevant listeners are initiated."> // these codelines add an escape-listener to the dialog. so, when the user // presses the escape-key, the same action is performed as if the user // presses the cancel button... KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); ActionListener cancelAction = new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { quitFullScreen(); } }; getRootPane().registerKeyboardAction(cancelAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); addWindowListener(this); // these codelines add an escape-listener to the dialog. so, when the user // presses the escape-key, the same action is performed as if the user // presses the cancel button... stroke = KeyStroke .getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.MAINKEYS, "showSearchResultWindow")); ActionListener showSearchResultsAction = new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { zknframe.showSearchResultWindow(); } }; getRootPane().registerKeyboardAction(showSearchResultsAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); // these codelines add an escape-listener to the dialog. so, when the user // presses the escape-key, the same action is performed as if the user // presses the cancel button... stroke = KeyStroke.getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.MAINKEYS, "showNewEntryWindow")); ActionListener showNewEntryFrameAction = new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { zknframe.showNewEntryWindow(); } }; getRootPane().registerKeyboardAction(showNewEntryFrameAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); // these codelines add an escape-listener to the dialog. so, when the user // presses the escape-key, the same action is performed as if the user // presses the cancel button... stroke = KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0); ActionListener showMainFrameAction = new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { zknframe.bringToFront(); } }; getRootPane().registerKeyboardAction(showMainFrameAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); jTextArea1.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea1, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea1, evt.getPoint().x, evt.getPoint().y); } }); jTextArea2.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea2, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea2, evt.getPoint().x, evt.getPoint().y); } }); jTextArea3.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea3, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) jPopupMenuCutCopyPaste.show(jTextArea3, evt.getPoint().x, evt.getPoint().y); } }); jTreeDesktop.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuDesktop.isVisible()) jPopupMenuDesktop.show(jTreeDesktop, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { if (evt.isPopupTrigger() && !jPopupMenuDesktop.isVisible()) jPopupMenuDesktop.show(jTreeDesktop, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseClicked(java.awt.event.MouseEvent evt) { // this listener should only react on left-mouse-button-clicks... // if other button then left-button clicked, leeave... if (evt.getButton() == MouseEvent.BUTTON1 && 2 == evt.getClickCount()) modifiyEntry(); } }); jTreeDesktop.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() { @Override public void valueChanged(javax.swing.event.TreeSelectionEvent evt) { updateToolbarAndMenu(); scrollToEntry(); } }); jTreeDesktop.addTreeExpansionListener(new javax.swing.event.TreeExpansionListener() { @Override public void treeExpanded(javax.swing.event.TreeExpansionEvent evt) { changeBulletTreefold(evt, true); } @Override public void treeCollapsed(javax.swing.event.TreeExpansionEvent evt) { changeBulletTreefold(evt, false); } }); jEditorPaneMain.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mouseClicked(java.awt.event.MouseEvent evt) { updateView(); } }); jEditorPaneMain.addHyperlinkListener(new javax.swing.event.HyperlinkListener() { @Override public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { // retrieve the event type, e.g. if a link was clicked by the user HyperlinkEvent.EventType typ = evt.getEventType(); // get the description, to check whether we have a file or a hyperlink to a website String linktype = evt.getDescription(); // if the link was clicked, proceed if (typ == HyperlinkEvent.EventType.ACTIVATED) { // call method that handles the hyperlink-click String returnValue = Tools.openHyperlink(linktype, mainframe, Constants.FRAME_DESKTOP, dataObj, bibtexObj, settingsObj, jEditorPaneMain, -1); // check whether we have a return value. this might be the case either when the user clicked on // a footenote, or on the rating-stars if (returnValue != null && returnValue.startsWith("#z_")) { // show entry zknframe.showEntry(dataObj.getCurrentZettelPos()); } } } }); jTextFieldLiveSearch.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { // when the user presses the escape-key, hide panel if (KeyEvent.VK_ESCAPE == evt.getKeyCode()) { findCancel(); } // when up/down arrows are pressed, find next/previous occurence of search term else if (Tools.isNavigationKey(evt.getKeyCode())) { switch (evt.getKeyCode()) { // if user pressed arrow down key, find next occurence of live search case KeyEvent.VK_DOWN: findLiveNext(); break; // if user pressed arrow down key, find previous occurence of live search case KeyEvent.VK_UP: findLivePrev(); break; } } // when user presses enter key, retrieve new search term and highlight term else if (KeyEvent.VK_ENTER == evt.getKeyCode() && jTextFieldLiveSearch.getText().length() > 1) { updateLiveSearchDisplay(); } } }); // // init the menu-listeners... // desktopMenuFile.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { exportMultipleMenuItem.setEnabled(desktopObj.getCount() > 1); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); desktopMenuView.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // set selected state showDesktopTreeEntryNumberMenuItem.setSelected(settingsObj.getShowDesktopEntryNumber()); // check whether we have any comments at all if (!desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) { // if not, disable menu item jRadioButtonDesktopOnlyComments.setEnabled(false); // if view option was comments only, change this option if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions()) settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS); } else { jRadioButtonDesktopOnlyComments.setEnabled(true); } switch (settingsObj.getDesktopCommentDisplayOptions()) { case Constants.DESKTOP_WITH_COMMENTS: jRadioButtonDesktopWithComment.setSelected(true); break; case Constants.DESKTOP_WITHOUT_COMMENTS: jRadioButtonDesktopWithoutComments.setSelected(true); break; case Constants.DESKTOP_ONLY_COMMENTS: jRadioButtonDesktopOnlyComments.setSelected(true); break; default: jRadioButtonDesktopWithComment.setSelected(true); break; } } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); // </editor-fold> } /** * This method changes a bullet-point's treefold-state, so it's remembered when re-building * the treeview. * * @param evt the {@code TreeExpansionEvent} which holds information about the node that * was expanded or collapsed * @param isExpanded {@code true} if the node was expandend, {@code false} if it was collapsed. This * information is retrieved from the {@code addTreeExpansionListener}, see * {@link #initListeners() initListeners()}. */ private void changeBulletTreefold(javax.swing.event.TreeExpansionEvent evt, boolean isExpanded) { // retrieve path of value that was expanded TreePath tp = evt.getPath(); // check whether root was expanded or not. therefore, retrieve root-node // and the last node of the treepath, i.e. the node which was expanded TreeNode root = (TreeNode) jTreeDesktop.getModel().getRoot(); TreeNode expandednode = (TreeNode) tp.getLastPathComponent(); // if they equal, do nothing if (expandednode.equals(root) || TreeUtil.nodeIsRoot((DefaultMutableTreeNode) expandednode)) return; // else, retrieve node's timestamp String timestamp = TreeUtil.getNodeTimestamp((DefaultMutableTreeNode) tp.getLastPathComponent()); // and set new treefold-state desktopObj.setBulletTreefold(timestamp, isExpanded); } /** * This method initiates the drag&drop-hanlding for the jEditorPanes. By doing this, the user * can drag entries from the jTree to the editorpane(s), and the entry's content will be displayed * in that editorpane. it's just a more comfortable way to handle the notes a user can make when * working with the outliner-feature - in case the user wants to keep entries permanently visible, * this feature can be used. * * @param editorpane an existing jEditorPane, in this case we use the components * {@code jEditorPaneS1}, {@code jEditorPaneS2} and {@code jEditorPaneS3} */ private void initDropPanes(final javax.swing.JTextArea editorpane) { editorpane.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { return editorpane.getSelectedText(); } @Override protected boolean importString(JComponent c, String str) { // check for valid drop-string if (str != null) { // each received string consists of two lines. the first one with information // about the drag-source and the drag-operation, the second one with the data // by this we can see whether we have received entries (i.e. a valid drop) String[] dropinformation = str.split("\n"); // get source information String[] sourceinfo = dropinformation[0].split(","); // check out the source of the drag-operation. if we have a valid source, // retrieve entries than. if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_ENTRIES)) { // we only accept drop-data from tables, so we might have several // lines, separates by a new-line. thus, split all new lines into // a string array. String[] entries = dropinformation[1].split(","); // if we have any dropped data, go on... if (entries != null && entries.length > 0) { // get converted entry StringBuilder text = new StringBuilder(""); for (String entrie : entries) { try { text.append(dataObj.getZettelContentAsHtml(Integer.parseInt(entrie))); text.append(lineseparator); } catch (NumberFormatException ex) { } catch (IndexOutOfBoundsException ex) { } } // add content to editor pane editorpane.setText(text.toString()); } return true; } else { editorpane.append(str); } } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); } /** * This method initialises the toolbar buttons. depending on the user-setting, we either * display small, medium or large icons as toolbar-icons. */ public final void initToolbarIcons() { // check whether the toolbar should be displayed at all... if (!settingsObj.getShowIcons() && !settingsObj.getShowIconText()) { // if not, hide it and leave. jToolBarDesktop.setVisible(false); // and set a border to the main panel, because the toolbar's dark border is hidden // and remove border from the main panel jPanel1.setBorder(new MatteBorder(1, 0, 0, 0, ColorUtil.colorDarkLineGray)); return; } // set toolbar visible jToolBarDesktop.setVisible(true); // and remove border from the main panel jPanel1.setBorder(null); // init toolbar button array javax.swing.JButton toolbarButtons[] = new javax.swing.JButton[] { tb_newbullet, tb_newentry, tb_modifyentry, tb_cut, tb_copy, tb_paste, tb_rename, tb_comment, tb_delete, tb_refresh, tb_addluhmann, tb_moveup, tb_movedown }; String[] buttonNames = new String[] { "tb_newbulletText", "tb_newdesktopentryText", "tb_editText", "tb_cutText", "tb_copyText", "tb_pasteText", "tb_renameText", "tb_commentText", "tb_deleteText", "tb_refreshText", "tb_addluhmannText", "tb_moveupText", "tb_movedownText" }; String[] iconNames = new String[] { "newBulletIcon", "newDesktopEntryIcon", "editEntryIcon", "cutIcon", "copyIcon", "pasteIcon", "renameBulletIcon", "commentNodeIcon", "deleteIcon", "updateViewIcon", "addLuhmannIcon", "moveNodeUpIcon", "moveNodeDownIcon" }; // set toolbar-icons' text if (settingsObj.getShowIconText()) { for (int cnt = 0; cnt < toolbarButtons.length; cnt++) { toolbarButtons[cnt].setText(toolbarResourceMap.getString(buttonNames[cnt])); } } else { for (javax.swing.JButton tbb : toolbarButtons) { tbb.setText(""); } } // show icons, if requested if (settingsObj.getShowIcons()) { // retrieve icon theme path String icontheme = settingsObj.getIconThemePath(); for (int cnt = 0; cnt < toolbarButtons.length; cnt++) { toolbarButtons[cnt].setIcon(new ImageIcon(ZettelkastenView.class .getResource(icontheme + toolbarResourceMap.getString(iconNames[cnt])))); } } else { for (javax.swing.JButton tbb : toolbarButtons) { tbb.setIcon(null); } } if (!settingsObj.getShowAllIcons()) { tb_addluhmann.setVisible(false); tb_rename.setVisible(false); } if (settingsObj.isMacAqua()) makeMacToolbar(); if (settingsObj.isSeaGlass()) makeSeaGlassToolbar(); } private void setupSeaGlassStyle() { getRootPane().setBackground(ColorUtil.colorSeaGlassGray); jTextFieldLiveSearch.putClientProperty("JTextField.variant", "search"); jEditorPaneMain.setBackground(Color.white); } /** * This method applies some graphical stuff so the appearance of the program is even more * mac-like... */ private void setupMacOSXLeopardStyle() { // <editor-fold defaultstate="collapsed" desc="This method applies some UI-stuff particular for Mac OS X"> // now we have to change back the background-color of all components in the mainpart of the // frame, since the brush-metal-look applies to all components // // make searchfields look like mac jTextFieldLiveSearch.putClientProperty("JTextField.variant", "search"); // other components become normal gray - which is, however, a little bit // darker than the default gray Color backcol = ColorUtil.getMacBackgroundColor(); // on Leopard (OS X 10.5), we have different rendering, thus we need these lines if (PlatformUtil.isLeopard()) { mainframe.getContentPane().setBackground(backcol); jPanel1.setBackground(backcol); } jPanel3.setBackground(backcol); jPanel4.setBackground(backcol); jPanel5.setBackground(backcol); jPanel6.setBackground(backcol); jPanelLiveSearch.setBackground(backcol); jSplitPaneDesktop1.setBackground(backcol); jSplitPaneDesktop2.setBackground(backcol); MacWidgetFactory.makeEmphasizedLabel(jLabel1); // get the toolbar-action AbstractAction ac = (AbstractAction) org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(DesktopFrame.class, this).get("findCancel"); // and change the large-icon-property, which is applied to the toolbar-icons, // to the new icon ac.putValue(AbstractAction.LARGE_ICON_KEY, new ImageIcon(Toolkit.getDefaultToolkit().getImage("NSImage://NSStopProgressFreestandingTemplate") .getScaledInstance(16, 16, Image.SCALE_SMOOTH))); ac.putValue(AbstractAction.SMALL_ICON, new ImageIcon(Toolkit.getDefaultToolkit().getImage("NSImage://NSStopProgressFreestandingTemplate") .getScaledInstance(16, 16, Image.SCALE_SMOOTH))); // </editor-fold> } private void makeSeaGlassToolbar() { Tools.makeTexturedToolBarButton(tb_newbullet, Tools.SEGMENT_POSITION_FIRST); if (settingsObj.getShowAllIcons()) { Tools.makeTexturedToolBarButton(tb_newentry, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_addluhmann, Tools.SEGMENT_POSITION_LAST); } else { Tools.makeTexturedToolBarButton(tb_newentry, Tools.SEGMENT_POSITION_LAST); } Tools.makeTexturedToolBarButton(tb_modifyentry, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_cut, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_copy, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_paste, Tools.SEGMENT_POSITION_LAST); Tools.makeTexturedToolBarButton(tb_moveup, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_movedown, Tools.SEGMENT_POSITION_LAST); if (settingsObj.getShowAllIcons()) { Tools.makeTexturedToolBarButton(tb_rename, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_comment, Tools.SEGMENT_POSITION_MIDDLE); } else { Tools.makeTexturedToolBarButton(tb_comment, Tools.SEGMENT_POSITION_FIRST); } Tools.makeTexturedToolBarButton(tb_delete, Tools.SEGMENT_POSITION_LAST); Tools.makeTexturedToolBarButton(tb_refresh, Tools.SEGMENT_POSITION_ONLY); jToolBarDesktop.setPreferredSize( new java.awt.Dimension(jToolBarDesktop.getSize().width, Constants.seaGlassToolbarHeight)); jToolBarDesktop.add(new javax.swing.JToolBar.Separator(), 0); } private void makeMacToolbar() { // hide default toolbr jToolBarDesktop.setVisible(false); this.remove(jToolBarDesktop); // and create mac toolbar if (settingsObj.getShowIcons() || settingsObj.getShowIconText()) { UnifiedToolBar mactoolbar = new UnifiedToolBar(); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_newbullet, MacButtonFactory.SEGMENT_POSITION_FIRST)); if (settingsObj.getShowAllIcons()) { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_newentry, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addluhmann, MacButtonFactory.SEGMENT_POSITION_LAST)); } else { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_newentry, MacButtonFactory.SEGMENT_POSITION_LAST)); } mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_modifyentry, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_cut, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_copy, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_paste, MacButtonFactory.SEGMENT_POSITION_LAST)); mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_moveup, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_movedown, MacButtonFactory.SEGMENT_POSITION_LAST)); mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); if (settingsObj.getShowAllIcons()) { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_rename, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_comment, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); } else { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_comment, MacButtonFactory.SEGMENT_POSITION_FIRST)); } mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_delete, MacButtonFactory.SEGMENT_POSITION_LAST)); mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_refresh, MacButtonFactory.SEGMENT_POSITION_ONLY)); mactoolbar.installWindowDraggerOnWindow(this); jPanel1.add(mactoolbar.getComponent(), BorderLayout.PAGE_START); } makeMacBottomBar(); } private void makeMacBottomBar() { jPanel7.setVisible(false); BottomBar macbottombar = new BottomBar(); macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(jLabel1)); macbottombar.addComponentToLeft(jComboBoxDesktop); macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(jLabelWordCount)); macbottombar.addComponentToLeft(jButtonShowMultipleOccurencesDlg); macbottombar.addComponentToRight(statusAnimationLabel); jPanel2.remove(jPanel7); jPanel2.setBorder(null); jPanel2.setLayout(new BorderLayout()); jPanel2.add(macbottombar.getComponent(), BorderLayout.PAGE_START); } /** * This method sets the default font-size for tables, lists and treeviews. If the * user wants to have bigger font-sizes for better viewing, the new font-size will * be applied to the components here. */ private void initDefaultFontSize() { // get the default fontsize for tables and lists int defaultsize = settingsObj.getDesktopOutlineFontSize(); // get current font int fsize = jTreeDesktop.getFont().getSize(); // retrieve default listvewfont Font defaultfont = settingsObj.getDesktopOutlineFont(); // create new font, add fontsize-value Font f = new Font(defaultfont.getName(), defaultfont.getStyle(), fsize + defaultsize); // set new font jTreeDesktop.setFont(f); } /** * This method sets the accelerator table for all relevant actions which should have * accelerator keys. We don't use the GUI designer to set the values, because the user * should have the possibility to define own accelerator keys, which are managed * within the CAcceleratorKeys-class and loaed/saved via the CSettings-class */ private void initAcceleratorTable() { // setting up the accelerator table. we have two possibilities: either assigning // accelerator keys directly with an action like this: // // javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(zettelkasten.ZettelkastenApp.class).getContext().getActionMap(ZettelkastenView.class, this); // AbstractAction ac = (AbstractAction) actionMap.get("newEntry"); // KeyStroke controlN = KeyStroke.getKeyStroke("control N"); // ac.putValue(AbstractAction.ACCELERATOR_KEY, controlN); // // or setting the accelerator key directly to a menu-item like this: // // newEntryMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.META_MASK)); // // we choose the first option, because so we can easily iterate through the xml file // and retrieve action names as well as accelerator keys. this saves a lot of typing work here // // get the action map javax.swing.ActionMap actionMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(DesktopFrame.class, this); // iterate the xml file with the accelerator keys for the main window for (int cnt = 1; cnt <= accKeys.getCount(AcceleratorKeys.DESKTOPKEYS); cnt++) { // get the action's name String actionname = accKeys.getAcceleratorAction(AcceleratorKeys.DESKTOPKEYS, cnt); // check whether we have found any valid action name if (actionname != null && !actionname.isEmpty()) { // retrieve action AbstractAction ac = (AbstractAction) actionMap.get(actionname); // get the action's accelerator key String actionkey = accKeys.getAcceleratorKey(AcceleratorKeys.DESKTOPKEYS, cnt); // check whether we have any valid actionkey if (actionkey != null && !actionkey.isEmpty()) { // retrieve keystroke setting KeyStroke ks = KeyStroke.getKeyStroke(actionkey); // and put them together :-) ac.putValue(AbstractAction.ACCELERATOR_KEY, ks); } } } // now set the mnemonic keys of the menus (i.e. the accelerator keys, which give access // to the menu via "alt"+key). since the menus might have different texts, depending on // the programs language, we retrieve the menu text and simply set the first char // as mnemonic key // ATTENTION! Mnemonic keys are NOT applied on Mac OS, see Apple guidelines for // further details: // http://developer.apple.com/DOCUMENTATION/Java/Conceptual/Java14Development/07-NativePlatformIntegration/NativePlatformIntegration.html#//apple_ref/doc/uid/TP40001909-211867-BCIBDHFJ if (!settingsObj.isMacAqua()) { // init the variables String menutext; char mkey; // the mnemonic key for the file menu menutext = desktopMenuFile.getText(); mkey = menutext.charAt(0); desktopMenuFile.setMnemonic(mkey); // the mnemonic key for the edit menu menutext = desktopMenuEdit.getText(); mkey = menutext.charAt(0); desktopMenuEdit.setMnemonic(mkey); // the mnemonic key for the view menu menutext = desktopMenuView.getText(); mkey = menutext.charAt(0); desktopMenuView.setMnemonic(mkey); } // on Mac OS, at least for the German locale, the File menu is called different // compared to windows or linux. Furthermore, we don't need the about and preferences // menu items, since these are locates on the program's menu item in the apple-menu-bar if (PlatformUtil.isMacOS()) desktopMenuFile.setText(resourceMap.getString("macFileMenuText")); // en- or disable fullscreen icons setFullScreenSupp(graphicdevice.isFullScreenSupported()); // if fullscreen is not supportet, tell this in the tooltip if (!graphicdevice.isFullScreenSupported()) { AbstractAction ac = (AbstractAction) actionMap.get("viewFullScreen"); ac.putValue(AbstractAction.SHORT_DESCRIPTION, resourceMap.getString("fullScreenNotSupported")); } // jTrees have their own input-map, so we have to re-assign the standard-shortcuts for // the jTree here... otherwise, copying nodes would lead to copy just the node's text, // and not - as we are intending - the node itself... String[] treeactions = new String[] { "cutNode", "copyNode", "pasteNode", "renameBullet", "moveNodeUp", "moveNodeDown" }; // iterate the actions-array and change input-map for all relevant actions in the jTree for (String tac : treeactions) { // change tree's action-map for cut-action jTreeDesktop.getActionMap().put(tac + "KeyPressed", actionMap.get(tac)); // associate new keystroke with that action KeyStroke ks = KeyStroke.getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.DESKTOPKEYS, tac)); // and put the new keystroke-value to the tree's input-map jTreeDesktop.getInputMap().put(ks, tac + "KeyPressed"); } } /** * This method inits the combobox. First it clears all existing items, then it * adds all available desktop-data and finally an actionlistener is added to * the jcombobox, that updates the display each time another desktop is chosen. */ private void initComboBox() { // clear combobox jComboBoxDesktop.removeAllItems(); // fill combo box, if we have any items at all if (desktopObj.getCount() > 0) { // go through all desktops and add their names to the combobox for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) jComboBoxDesktop.addItem(desktopObj.getDesktopName(cnt)); // add action listener addCbActionListener(); // select first item jComboBoxDesktop.setSelectedIndex(settingsObj.getLastUsedDesktop(desktopObj.getCount())); } } /** * This method inits the action listener for the combo box. */ private void addCbActionListener() { // add action listener to combo box jComboBoxDesktop.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { // save current notes desktopObj.setDesktopNotes(1, jTextArea1.getText()); desktopObj.setDesktopNotes(2, jTextArea2.getText()); desktopObj.setDesktopNotes(3, jTextArea3.getText()); // after that, set the new selected index as current desktop index desktopObj.setCurrentDesktopNr(jComboBoxDesktop.getSelectedIndex()); // update the treeview, i.e. fill it with outline/structure from // the xml-document updateTreeView(); // if view option was comments only, change this option if we don't have any comments at all if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions() && !desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS); // tell the user that he should click to update... jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText")); // init notes, if any jTextArea1.setText(desktopObj.getDesktopNotes(1)); jTextArea2.setText(desktopObj.getDesktopNotes(2)); jTextArea3.setText(desktopObj.getDesktopNotes(3)); setNeedsUpdate(true); } }); } @Action public void printContent() { javax.swing.JEditorPane tmpPane = new javax.swing.JEditorPane(); tmpPane.setEditorKit(jEditorPaneMain.getEditorKit()); tmpPane.setContentType(jEditorPaneMain.getContentType()); StringBuilder sb = new StringBuilder(""); sb.append(completePage); // if we have any content, insert html-header at the beginning... if (sb.length() > 0) sb.insert(0, HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, true)); tmpPane.setText(sb.toString()); try { tmpPane.print(); } catch (PrinterException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } /** * Displays the selected entry in the main frame. */ @Action(enabledProperty = "entryNodeSelected") public void displayEntryInMainframe() { // retrieve selection from jtree int nr = getSelectedEntryNumber(); // when we have a valid selection, go on if (nr != -1) zknframe.showEntry(nr); } public void showEntryInDesktop(int entrynr) { // check for valid value if (-1 == entrynr) return; // itereate all desktops for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) { // check whether entry is in this desktop if (desktopObj.isEntryInDesktop(entrynr, cnt)) { // set entry number displayentrynr = entrynr; // selecte desktop jComboBoxDesktop.setSelectedIndex(cnt); // quit method return; } } } @Action public void showDesktopEntryNumber() { boolean val = settingsObj.getShowDesktopEntryNumber(); settingsObj.setShowDesktopEntryNumber(!val); val = isNeedsUpdate(); updateTreeView(); if (!val) setNeedsUpdate(false); } /** * Each time we add/delete a desktop, the combo box is being updated. First, * this method checks whether the current desktop was modified or not, and saves * the current desktop-data to xml-file, if necessary. * <br><br> * Then all action listeners are removed, so no actionevent is fired when we * add new items to the combobox. Then all available desktop-data is added. * Finally, an actionlistener is added to * the jcombobox, that updates the display each time another desktop is chosen. * * @param closing true when the window will be closed, false if the combobox should be updated * and the desktop-window will not be closed. */ private void updateComboBox(boolean closing) { // get all action listeners from the combo box ActionListener[] al = jComboBoxDesktop.getActionListeners(); // remove all action listeners so we don't fire several action-events // when we update the combo box. we can set the action listener later again for (ActionListener listener : al) jComboBoxDesktop.removeActionListener(listener); // clear combobox jComboBoxDesktop.removeAllItems(); // add all desktop-items to combo-box for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) jComboBoxDesktop.addItem(desktopObj.getDesktopName(cnt)); // add action listener to combo box addCbActionListener(); // enable multiple-export-menu-item exportMultipleMenuItem.setEnabled(desktopObj.getCount() > 1); // select last item if (!closing) try { jComboBoxDesktop.setSelectedIndex(jComboBoxDesktop.getItemCount() - 1); } catch (IllegalArgumentException e) { } } /** * A simple initialisation of the jTreeDesktop, i.e. the tree is cleared and * single-selection-mode is set. */ private void initTree() { // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel(); // and first of all, clear the jTree dtm.setRoot(null); // macstyle beim jTree setzen if (settingsObj.isMacAqua()) { jTreeDesktop.setUI(new MacSourceDesktopTree(desktopObj)); } else { // set cell renderer, for desktop icons jTreeDesktop.setCellRenderer( new MyCommentRenderer(Constants.iconDesktopComment, settingsObj.getUseMacBackgroundColor())); if (settingsObj.getUseMacBackgroundColor()) { jTreeDesktop.setBackground(ColorUtil.colorJTreeLighterBackground); jTreeDesktop.setForeground(ColorUtil.colorJTreeDarkText); } // set tree-selection-mode jTreeDesktop.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); } // enable drag&drop jTreeDesktop.setDragEnabled(true); // init transfer handler for tree jTreeDesktop.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { // retrieve tree-component javax.swing.JTree t = (javax.swing.JTree) c; // retrieve selected node that was dragged DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) t.getSelectionPath() .getLastPathComponent(); // prepare export-string, telling that the drag-source is the jTreeDesktop StringBuilder retval = new StringBuilder(Constants.DRAG_SOURCE_JTREEDESKTOP + ","); // and give information whether the dragged entry is a bullet or an entry retval.append((selectedNode.getAllowsChildren()) ? Constants.DRAG_SOURCE_TYPE_BULLET + "\n" : Constants.DRAG_SOURCE_TYPE_ENTRIES + "\n"); // next line contains the entry-number, or -1 if a bullet was selected retval.append(String.valueOf(getSelectedEntryNumber())).append("\n"); // retrieve treepath of dragged entry/bullet TreePath tp = t.getSelectionPath(); // add each single path component to return string, new-line-separated for (int cnt = 1; cnt < tp.getPathCount(); cnt++) { retval.append(tp.getPathComponent(cnt).toString()).append("\n"); } // finally, add node-ID to string-information retval.append(TreeUtil.getNodeTimestamp(selectedNode)); // remember selected node, which should be removed when dropping the node. movedNodeToRemove = selectedNode; // return information return retval.toString(); } @Override protected boolean importString(JComponent c, String str) { // get drop-component, i.e. the jTreeDesktop javax.swing.JTree t = (javax.swing.JTree) c; // retrieve selected node DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) t.getSelectionPath() .getLastPathComponent(); // check for valid drop-string if (str != null && selectedNode != null) { // retrieve nodetimestamp String nodets = TreeUtil.getNodeTimestamp(selectedNode); // each received string consists of two lines. the first one with information // about the drag-source and the drag-operation, the second one with the data // by this we can see whether we have received entries (i.e. a valid drop) String[] dropinformation = str.split("\n"); // get source information String[] sourceinfo = dropinformation[0].split(","); // in case an edited entry has been dragged, remember modifications String modifications = null; // check out the source of the drag-operation. if we have a valid source, // retrieve entries. // here we have // - entries as drop-elements // - and no root selected, i.e. a valid drop-location if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_ENTRIES) && !selectedNode.isRoot()) { // check for self-drop if (TreeUtil.getNodeTimestamp(movedNodeToRemove).equals(nodets)) return false; // here we have the jTreeDesktop as drag-source, i.e. a drag&drop from within // the jDesktopComponent. that means, we have to delete the drag-source, i.e. // the dragged node that was moved to the new location if (sourceinfo[0].equals(Constants.DRAG_SOURCE_JTREEDESKTOP)) { // retrieve node timestamp String ts = dropinformation[dropinformation.length - 1]; // save modifications modifications = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts); // delete entry desktopObj.deleteEntry(ts); // and remove node from original position movedNodeToRemove.removeFromParent(); } // retrieve dropped entries. double entries are removed. if an entry comes from within // the desktop, we have to check whether the dragged entry was just moved within a // bullet. if so, we don't have to consider it as "double" entry. String entries = retrieveDropEntries(dropinformation[1], selectedNode); // if we have any entries left, i.e. not only double entries, add them now if (entries != null && entries.length() > 0) { // add new entry addEntries(entries, modifications); // update toolbars // updateTreeView(); updateToolbarAndMenu(); return true; } } // here we have // - a bullet as drag-source // - and the root or a bullet (or: no entry) as drop-location else if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_BULLET) && selectedNode.getAllowsChildren()) { // check for self-drop if (TreeUtil.getNodeTimestamp(movedNodeToRemove).equals(nodets)) return false; // cut bullet from XML-data file desktopObj.cutBulletToClip(dropinformation[dropinformation.length - 1]); // and paste the bullet at the target-destination desktopObj.pasteBulletFromClip(TreeUtil.getNodeTimestamp(selectedNode), selectedNode.isRoot()); // update treeview and toolbars updateTreeView(); updateToolbarAndMenu(); return true; } // if we have no drag-information specified, check whether we have a table-drag // and can retrieve any entry-information else if (!selectedNode.isRoot()) { // try to extract entry-numbers from dropped string int[] entrynrs = Tools.retrieveEntryNumbersFromTransferHandler(str, dataObj.getCount(Daten.ZKNCOUNT)); // if we have any entries left, i.e. not only double entries, add them now if (entrynrs != null && entrynrs.length > 0) { // create new string builder StringBuilder sb = new StringBuilder(""); // iterate all moved/copied/pasted entrynumbers for (int cnt = 0; cnt < entrynrs.length; cnt++) { // check whether entrynumber already exists if (!entryExists(entrynrs[cnt], selectedNode)) { // if not, add it. sb.append(String.valueOf(entrynrs[cnt])).append(","); } } // delete last comma if (sb.length() > 1) { sb.setLength((sb.length() - 1)); // add new entry addEntries(sb.toString()); // update toolbars // updateTreeView(); updateToolbarAndMenu(); return true; } } } } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); } /** * This method retrieves all entry-numbers of entries that have been dropped (or dragged and dropped) * on the jTree. The method checks whether any of the dropped entries already exist as entry * of the parent-bullet, and if so, the related entry-number will be removed. * * @param entries the dropped entry-numbers as single string, comma separated. * @param targetNode the node where the entries have been dropped * @return a string with entry-numbers, comma separated, with double or multiple entries of * the {@code targetNode} (or its parent, if targetNode is no bullet) removed. */ private String retrieveDropEntries(String entries, DefaultMutableTreeNode targetNode) { // split entries into array String[] singleentry = entries.split(","); // now we have to check whether the dragged entry already exists as sub-entry of // the target's bullet-point. therefore, we have to retrieve the closest parent-bullet // to the drop-location DefaultMutableTreeNode parent = targetNode; // if the targetPath itself is not already a bullet, retrieve its parent. if (!targetNode.getAllowsChildren()) parent = (DefaultMutableTreeNode) parent.getParent(); //check for null if (null == parent) return null; // go through all entries and check, whether they exists. if so, remove them from the list, // so only valid entries are dropped... StringBuilder sb = new StringBuilder(""); for (String singleentry1 : singleentry) { if (!entryExists(Integer.parseInt(singleentry1), parent)) { sb.append(singleentry1).append(","); } } // delete last comma if (sb.length() > 1) sb.setLength((sb.length() - 1)); // if all elements have been removed, return null if (sb.length() < 1) return null; // return result return sb.toString(); } /** * This method checks whether an entry with the number {@code dropnr} already exists * as entry of the parent-bullet {@code parent}. * * @param dropnr the number of the dropped entry * @param parent the parent-bullet of the dropped entry * @return {@code true} if an entry with the same number as {@code dropnr} already exists as * entry of the parent-bullet {@code parent}, {@code false} otherwise. */ private boolean entryExists(int dropnr, DefaultMutableTreeNode parent) { // check for null if (null == parent) return false; // now go through all bullet's children for (int counter = 0; counter < parent.getChildCount(); counter++) { // get child DefaultMutableTreeNode doublechild = (DefaultMutableTreeNode) parent.getChildAt(counter); // retrieve the node's text and extract the entry-number int childnr = TreeUtil.extractEntryNumberFromNode(doublechild); // compare child's text with newBullet-text if (childnr == dropnr) return true; } return false; } @Override public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { closeWindow(); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } /** * */ private class MyCommentRenderer extends DefaultTreeCellRenderer { Icon commentIcon; boolean useMacBackgound; public MyCommentRenderer(Icon icon, boolean bg) { commentIcon = icon; useMacBackgound = bg; } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); setBackgroundNonSelectionColor(tree.getBackground()); if (!leaf && !sel && useMacBackgound) { setForeground(ColorUtil.colorJTreeDarkText); } setFont(getFont().deriveFont((leaf) ? Font.PLAIN : Font.BOLD)); if (isCommentNode(value)) { setIcon(commentIcon); } return this; } /** * This method checks whether a selected node has a comment or not. * * @param value the selected node * @return {@code true} if the selected node has a comment, {@code false} otherwise. */ protected boolean isCommentNode(Object value) { // if no value return if (null == value) return false; // retrieve node DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; // when root, return if (node.isRoot()) return false; return (!desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>").isEmpty()); } } /** * Updates/enables/disables the toolbar- and menu-buttons, depending on whether * the functions are available and executable or not. */ private void updateToolbarAndMenu() { // get selection DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // enable actions that require a selected bullet, but no root setBulletSelected((node != null) && (node.getAllowsChildren())); // enable actions that either require a selcted bullet or child-node, but no root setNodeSelected((node != null) && (!node.isRoot())); // enable actions that either require a selcted bullet or child-node, but no root setEntryNodeSelected((node != null) && (!node.isRoot()) && (!node.getAllowsChildren())); // enable actions that require any selection setAnyNodeSelected(node != null); setModifiedEntryNode(desktopObj.isModifiedEntry(getSelectedNodeTimestamp())); // enable paste-option setClipFilled(((clipBullet && isBulletSelected()) || (!clipBullet && clipEntries != null && clipEntries.length > 0))); // enable the move-actions, which let the user move an entry/bullet up and down setMoveUpEnabled(!isFirstNode() && node != null && !node.isRoot()); setMoveDownEnabled(!isLastNode() && node != null && !node.isRoot()); // create string that will hold the luhmann-numbers String luhmann = ""; // get selected entry-number int nr = getSelectedEntryNumber(); // if we have a valid entry, get luhmann-numbers if (nr != -1) luhmann = dataObj.getLuhmannNumbers(nr); // enable actions that require a selected child-node (entty), that has luhmann-numbers setLuhmannNodeSelected(isNodeSelected() && !luhmann.isEmpty()); } /** * This method retrieves the entry of the selected node and extracts its entry-number. * @return the number of the selected entry, or -1 if nothing was selected. */ private int getSelectedEntryNumber() { DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // if we have a valid node, go on... if (node != null) { // return TreeUtil.extractEntryNumberFromNodeText(node); return TreeUtil.extractEntryNumberFromNode(node); } return -1; } /** * This method updates the display, i.e. receiving the entry-structure from the jTree * and displays all those entries in html-formatting in the jEditorPane. */ private synchronized void updateDisplay() { // when the display is up to date, do nothing here... if (!isNeedsUpdate()) return; // cancel already running task if necessary, so we don't have more parallel tasks running if (cDisplayTask != null) cDisplayTask.cancel(true); // if task is already running, leave... if (cDisplayTaskIsRunning) return; Task cdT = displayTask(); // get the application's context... ApplicationContext appC = Application.getInstance().getContext(); // ...to get the TaskMonitor and TaskService TaskMonitor tM = appC.getTaskMonitor(); TaskService tS = appC.getTaskService(); // with these we can execute the task and bring it to the foreground // i.e. making the animated progressbar and busy icon visible tS.execute(cdT); tM.setForegroundTask(cdT); } /** * This method fills recursively all entries' contents to the jEditorPane. Therefore, * the jTreeDesktop is enumerated. Each element is then converted to a string, html-formatted, * and appended to a StringBuilder. At the end, the StringBuilder's content is set to the jEditorPane. * * @param node the root node, as starting point for the jTree-enumeration * @param sb the stringbuilder which finally will contain all content in html-format */ private void exportEntriesToEditorPane(DefaultMutableTreeNode node, StringBuilder sb, boolean showComments) { // get a list with all children of the node Enumeration en = node.children(); // go through all children while (en.hasMoreElements()) { // get the child node = (DefaultMutableTreeNode) en.nextElement(); // if the child is a bullet... if (node.getAllowsChildren()) { // retrieve bullet-level int lvl = node.getLevel(); String level = String.valueOf(lvl); // new table row sb.append("<tr>").append(lineseparator); // check whether comments should be displayed if (showComments) { // retieve and create comment String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>"); // insert comment as table-data sb.append("<td valign=\"top\" class=\"comment\">"); sb.append(com); sb.append("</td>").append(lineseparator); } // insert entry content sb.append("<td><h").append(level).append(">"); // now create the reference-ankh, so we can use the "scrollToReference" method // of the jEditorPane easily each time the user clicks on an entry in the jTree // to scroll to that entry in the text field. sb.append("<a name=\""); sb.append("entry").append(TreeUtil.getNodeTimestamp(node)); sb.append("\"> </a>"); // append a new headline with the bullet's name sb.append(TreeUtil.getNodeText(node)); // also add headline to wordcounter sbWordCountDisplayTask.append(TreeUtil.getNodeText(node)).append(" "); sb.append("</h").append(level).append("></td></tr>").append(lineseparator); } // now we know we have an entry. so get the entry number... else { // we now want to check whether the user has made modifications to the entry's // content, which are only made to the desktop (the content of the entry in the main database // is not changed, so you can edit the desktop-entry without changing the entry's original // content - this is useful when you want to add some words/phrases between entries etc., which // should be applied only to the final text on the desktop, but not to the original entries). // // in case we have modified an entry on the desktop, this entry has a "content" element. to // retrieve the correct entry, we need to look for the unique timestamp of that entry - since // an entry could appear multiple times on the desktop, thus the entry number itself is no // valid value for retrieving the right entry. Therefore, each treenode has a user-object // assigned, which holds the unique timestamp String text = desktopObj.retrieveModifiedEntryContentFromTimestamp(TreeUtil.getNodeTimestamp(node)); // retrieve entry-number int nr = TreeUtil.extractEntryNumberFromNode(node); // if nothing found, retrieve regular entry // that means, if the entry with the unique-timestamp has no or an empty content-element, the // entry was not modified - thus we retrieve the "original" entry. if (null == text || text.isEmpty()) { // also cleaned text for wordcounter sbWordCountDisplayTask.append(dataObj.getCleanZettelContent(nr)).append(" "); // get zettel-text text = HtmlUbbUtil.getHtmlContentForDesktop(dataObj, bibtexObj, settingsObj, nr, isHeadingVisible, isEntryNumberVisible, false, false); } // else if we have a modified entry-content, we still need to convert its // ubb-tags to HTML. this is done here... else { // also cleaned text for wordcounter sbWordCountDisplayTask.append(Tools.removeUbbFromString(text, true)).append(" "); // get the html-text for an entry which content is passed as parameter... text = HtmlUbbUtil.getHtmlContentForDesktop(dataObj, bibtexObj, settingsObj, text, nr, isHeadingVisible, isEntryNumberVisible, false, false); } // new table row sb.append("<tr>").append(lineseparator); // check whether comments should be displayed if (showComments) { // retieve and create comment String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>"); // insert comment as table-data sb.append("<td valign=\"top\" class=\"comment\">"); sb.append(com); sb.append("</td>"); } sb.append("<td class=\"content\">").append(lineseparator); // now create the reference-ankh, so we can use the "scrollToReference" method // of the jEditorPane easily each time the user clicks on an entry in the jTree // to scroll to that entry in the text field. sb.append("<a name=\""); sb.append("entry").append(TreeUtil.getNodeTimestamp(node)); sb.append("\"> </a>").append(lineseparator); // and append the html-text of the entry... sb.append(text); sb.append("</td></tr>").append(lineseparator); } // when the new node also has children, call this method again, // so we go through the strucuture recursively... if (node.getChildCount() > 0) exportEntriesToEditorPane(node, sb, showComments); } } /** * This method fills recursively all entries' contents to the jEditorPane. Therefore, * the jTreeDesktop is enumerated. Each element is then converted to a string, html-formatted, * and appended to a StringBuilder. At the end, the StringBuilder's content is set to the jEditorPane. * * @param node the root node, as starting point for the jTree-enumeration * @param sb the stringbuilder which finally will contain all content in html-format */ private void exportCommentsToEditorPane(DefaultMutableTreeNode node, StringBuilder sb) { // get a list with all children of the node Enumeration en = node.children(); // go through all children while (en.hasMoreElements()) { // get the child node = (DefaultMutableTreeNode) en.nextElement(); // if the child is a bullet... if (node.getAllowsChildren()) { // retrieve bullet-level int lvl = node.getLevel(); String level = String.valueOf(lvl); // retieve and create comment String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>"); // check whether comment is empty or not if (com != null && !com.isEmpty()) { // new table row sb.append("<tr>"); // insert paragraph heading sb.append("<td><h").append(level).append(">"); // now create the reference-ankh, so we can use the "scrollToReference" method // of the jEditorPane easily each time the user clicks on an entry in the jTree // to scroll to that entry in the text field. sb.append("<a name=\""); sb.append("entry").append(TreeUtil.getNodeTimestamp(node)); sb.append("\"> </a>"); // append a new headline with the bullet's name sb.append(TreeUtil.getNodeText(node)); sb.append("</h").append(level).append(">"); // insert comment as table-data sb.append("<p>").append(com).append("</p>"); sb.append("</td></tr>").append(lineseparator); // also add headline and comment to wordcounter sbWordCountDisplayTask.append(TreeUtil.getNodeText(node)).append(" ").append(com).append(" "); } } // now we know we have an entry. so get the entry number... else { // retieve and create comment String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>"); // check whether comment is empty or not if (com != null && !com.isEmpty()) { // new table row sb.append("<tr>"); sb.append("<td class=\"content\">"); // now create the reference-ankh, so we can use the "scrollToReference" method // of the jEditorPane easily each time the user clicks on an entry in the jTree // to scroll to that entry in the text field. sb.append("<a name=\""); sb.append("entry").append(TreeUtil.getNodeTimestamp(node)); sb.append("\"> </a>"); // and append the html-text of the entry... sb.append(HtmlUbbUtil.getZettelTitleForDesktop(dataObj, TreeUtil.extractEntryNumberFromNode(node), isEntryNumberVisible)); // insert comment as table-data sb.append("<p>").append(com).append("</p>"); sb.append("</td></tr>").append(lineseparator); // also cleaned text for wordcounter sbWordCountDisplayTask.append(com).append(" "); } } // when the new node also has children, call this method again, // so we go through the strucuture recursively... if (node.getChildCount() > 0) exportCommentsToEditorPane(node, sb); } } /** * This method scrolls to that entry in the jEditorPane, that is selected from the jTree. * This is achieved by simply activating a hyperlink (ankh), thus we can scroll to the * reference.<br><br> * A unique reference for each entry is set in the node's text in the jTree via the method * {@link #fillChildren(org.jdom.Element, javax.swing.tree.DefaultMutableTreeNode, javax.swing.tree.DefaultTreeModel) fillChildren} * and {@link #exportEntriesToEditorPane(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder) exportEntriesToEditorPane}. */ private void scrollToEntry() { // get selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); if (null == node || node.isRoot()) return; // get the node's text. this is what we want to search in the editor pane jEditorPaneMain.scrollToReference("entry" + getSelectedNodeTimestamp()); } @Action public void findLive() { // first, update the display, so we search in the current desktop updateDisplay(); // display the panel that contains the textfield for the search terms // and the find next/prev-buttons jPanelLiveSearch.setVisible(true); // set input-focus to textfield jTextFieldLiveSearch.requestFocusInWindow(); } @Action public void findLiveNext() { // first, we have to create a string that equals the ankh (reference) where // the editorpane should scroll to. each found search term has a link-tag with // a consecutive numbering (<a name="hl1">, <a name="hl2"> etc...) // the variable "findlivepos" contains the number of the current references ankh String ankh = "hl" + String.valueOf(findlivepos); // scroll the the reference jEditorPaneMain.scrollToReference(ankh); // increase findlivepos to refer to the next reference if (findlivepos < findlivemax) findlivepos++; // if we reach the last reference, start at first reference again else findlivepos = 1; } @Action public void findLivePrev() { // decrease findlivepos. if (findlivepos > 1) findlivepos--; // when we reached the first reference, set to last occurencs of search terms else findlivepos = findlivemax; // create reference string String ankh = "hl" + String.valueOf(findlivepos); // and scroll to reference jEditorPaneMain.scrollToReference(ankh); } @Action public void findCancel() { // restore complete page without highlighting jEditorPaneMain.setText(HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false) + completePage); // scroll to top jEditorPaneMain.setCaretPosition(0); // hide live-search-bar jPanelLiveSearch.setVisible(false); } private void updateLiveSearchDisplay() { // retrieve search term from textfield and set it as highlight-term for // the html-conversion HtmlUbbUtil.setHighlighTerms(new String[] { jTextFieldLiveSearch.getText() }, HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH, false); // init the counter for the references to the found search terms findlivepos = 1; // retrieve the desktop-content with highlighted search term StringBuilder newtext = new StringBuilder( HtmlUbbUtil.highlightSearchTerms(completePage, HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH)); // counter for bulding the HTML-link-tags, so we can scroll directly to each references // found search term, using the editor pane's scrollToReference()-method int counter = 1; int pos = 0; // while we find a highlighted search term, we want to insert an ankh (html-link-tag // including the reference-name) before that search term while (pos != -1) { // find occurence of highlighted text pos = newtext.toString().indexOf("<span class=\"hs_ls\"", pos); // if we found something... if (pos != -1) { // insert linktag before. newtext.insert(pos, "<a name=\"hl" + String.valueOf(counter++) + "\"></a>"); // and increase position-index, so we don't have an infinite loop that always finds // the same <span>-tag pos = pos + 40; } } // store the maximum amount of found/highlighted search terms, so we know when to // restart with our reference counter. see findLiveNext() and findLivePrev() for // more details findlivemax = counter - 1; // set new highlighted text to editor pane jEditorPaneMain.setText(HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false) + newtext.toString()); // set scroll-area to top jEditorPaneMain.setCaretPosition(0); // and scroll to first reference in the editor pane String ankh = "hl1"; jEditorPaneMain.scrollToReference(ankh); } @Action public void switchHeadingsVisibility() { isHeadingVisible = !isHeadingVisible; headingsVisibleMenuItem.setSelected(isHeadingVisible); setNeedsUpdate(true); } @Action public void switchEntryNumberVisibility() { isEntryNumberVisible = !isEntryNumberVisible; entryNumberVisibleMenuItem.setSelected(isEntryNumberVisible); setNeedsUpdate(true); } @Action public void menuDisplayDesktopWithComments() { settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS); setNeedsUpdate(true); } @Action public void menuDisplayDesktopWithoutComments() { settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITHOUT_COMMENTS); setNeedsUpdate(true); } @Action public void menuDisplayDesktopOnlyComments() { settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_ONLY_COMMENTS); setNeedsUpdate(true); } /** * This method is called whenever an entry that is also on the desktop was changed. In this case * we assume that the entry's content was changed, so we need an update to the treeview (in case * the entry has a new title, we need to display it in the treeview as well) and we need an * update to the html-content. */ public void updateEntriesAfterEditing() { updateTreeView(); } /** * This method updates the treeview after each change made to the desktop. The changes are only * applied to the desktop-data-file (the xml-file managed in the {@link #desktopObj CDesktop-Class}). * This method retrieves the structure from this xml-document and copies it to the treeview.<br><br> * Updating the treeview does <b>not</b> update the display of the entries as well, since many display-updates * take much time. Rather the action {@link #updateView() updateView} is enabled, which updates the display. */ private void updateTreeView() { // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel(); // and first of all, clear the jTree dtm.setRoot(null); // create a new root element from the current desktop name and set it as root DefaultMutableTreeNode root = new DefaultMutableTreeNode(new TreeUserObject( desktopObj.getDesktopName(jComboBoxDesktop.getSelectedIndex()), Constants.ROOT_ID_NAME, "")); dtm.setRoot(root); // get current desktop-element Element d = desktopObj.getCurrentDesktopElement(); // check whether the current desktop has any children at all if (desktopObj.hasChildren(d)) { // create treeview-content fillChildren(d, root, dtm); } // finally, expand the whole tree // expandAllTrees(true, jTreeDesktop); expandAllTrees(); // check whether a certain entry should be selected or not if (displayentrynr != -1) { // check whether entry exists in current desktop if (desktopObj.isEntryInCurrentDesktop(displayentrynr)) { // if yes, retrieve element Element en = desktopObj.getFoundDesktopElement(); // check for valid value if (en != null) { // get timestamp of entry String timestamp = en.getAttributeValue("timestamp"); // select entry in treeview selectTreePath(timestamp); } } // reset display entry nr displayentrynr = -1; } // display needs to be updated... setNeedsUpdate(true); } /** * This method updates the jTreeView. Each time an update for the treevuew is needed, this * method is called. It then recursevly traverses all XML-Elements of the currently activated * desktop-element, where the starting desktop-element is passed in the parameter {@code e}. * <br><br> * The method retrieves each element, checks whether the element is an entry- or a bullet-element, * than either, in case of a bullet point, uses the name-attribute as node-name and appends the * timestamp-attribute as ID; or it retrieves the entry's title from the entry-number that is stored * in each entry-element, and appends the entry's timestamp-attribute as ID. * <br><br> * After that, the node is inserted in the jTree. * * @param e * @param n * @param dtm */ private void fillChildren(Element e, DefaultMutableTreeNode n, DefaultTreeModel dtm) { // get a list with all children of the element List<Element> children = e.getChildren(); // create an iterator Iterator<Element> it = children.iterator(); // go through all children while (it.hasNext()) { // get the child e = it.next(); // create a new node DefaultMutableTreeNode node; // we have to ignore the comment-tags here. comments are no tags that will // be displayed in the jtree, but that store comments which will be displayed // in the jeditorpane (see "updateDisplay" method for further details) if (!e.getName().equals("comment")) { // if the child is a bullet... if (e.getName().equals("bullet")) { // create new stringbuilder StringBuilder sb = new StringBuilder(""); // append name of bullet point sb.append(e.getAttributeValue("name")); // // and append unique id, which is the element's timestamp // sb.append(" [id#").append(e.getAttributeValue("timestamp")).append("]"); // // create a node with the element's name-attribute // node = new DefaultMutableTreeNode(sb.toString()); // create a node with the element's name-attribute node = new DefaultMutableTreeNode( new TreeUserObject(sb.toString(), e.getAttributeValue("timestamp"), "")); // and tell node to have children node.setAllowsChildren(true); } else { // now we know we have an entry. so get the entry number... int nr = Integer.parseInt(e.getAttributeValue("id")); // get the zettel title String title = TreeUtil.retrieveNodeTitle(dataObj, settingsObj.getShowDesktopEntryNumber(), String.valueOf(nr)); // create a new node node = new DefaultMutableTreeNode( new TreeUserObject(title, e.getAttributeValue("timestamp"), String.valueOf(nr))); // and tell node not to have children node.setAllowsChildren(false); } // add new node to treeview dtm.insertNodeInto(node, n, n.getChildCount()); // when the new element also has children, call this method again, // so we go through the strucuture recursively... if (desktopObj.hasChildren(e)) { fillChildren(e, node, dtm); } } } } /** * This method retrieves all entries on the desktop and adds their number to the * list {@code liste}. This array of entry-numbers is needed in the export-dialog. * * @param e the starting point for the jTree-enumeration, either the root elementor a bullet (if only * a bullet should be exported, see {@link #exportDesktopBullet() exportDesktopBullet()}). * @param liste an array-object that will hold the found entry-nubers */ private void createExportEntries(Element e, ArrayList<Object> liste) { // if we have no element, return. if (null == e) return; // get a list with all children of the element List<Element> children = e.getChildren(); // create an iterator Iterator<Element> it = children.iterator(); // go through all children while (it.hasNext()) { // get the child e = it.next(); // we have to ignore the comment-tags here. comments are no tags that will // be displayed in the jtree, but that store comments which will be displayed // in the jeditorpane (see "updateDisplay" method for further details) if (!e.getName().equals("comment")) { // if the child is a bullet... if (e.getName().equals("bullet")) { // first, we want to retrieve the header-level int headerlevel = 1; // get bullet's parent Element f = e.getParentElement(); // as long as we have not reached the root, get further parent-elements // and increase counter for header-level while (!f.isRootElement()) { f = f.getParentElement(); headerlevel++; } // add the element's name-attribute. since headers might consist of only numbers, // we add a char here. this is necessary, since the export-methods distinguish // between headers and entry-numbers simply by parsing integer-values. if the parsing // succeeds, we have an entry, if a NumberFormatException is thrown, we have a headline. // to treat headline with numbers only as headlines, we add a char to be sure that every // headline will throw an exception when parsing the array's elements to integer. liste.add("h" + String.valueOf(headerlevel) + e.getAttributeValue("name")); } else { // now we know we have an entry. so get the entry number... int nr = Integer.parseInt(e.getAttributeValue("id")); liste.add(nr); } // when the new element also has children, call this method again, // so we go through the strucuture recursively... if (desktopObj.hasChildren(e)) { createExportEntries(e, liste); } } } } // /** // * If expand is true, expands all nodes in the tree. // * Otherwise, collapses all nodes in the tree. // */ // public void expandAllTrees(boolean expand, JTree tree) { // // get tree-root // TreeNode root = (TreeNode)tree.getModel().getRoot(); // // Traverse tree from root // expandAllTrees(new TreePath(root), expand, tree); // } // private void expandAllTrees(TreePath parent, boolean expand, JTree tree) { // // Traverse children // TreeNode node = (TreeNode)parent.getLastPathComponent(); // // if we have children, go on // if (node.getChildCount() >= 0) { // // itereate all children // for (Enumeration e=node.children(); e.hasMoreElements();) { // TreeNode n = (TreeNode)e.nextElement(); // TreePath path = parent.pathByAddingChild(n); // expandAllTrees(path, expand, tree); // } // } // // Expansion or collapse must be done bottom-up // if (expand) { // tree.expandPath(parent); // } else { // tree.collapsePath(parent); // } // } /** * If expand is true, expands all nodes in the tree. * Otherwise, collapses all nodes in the tree. */ public void expandAllTrees() { // get tree-root TreeNode root = (TreeNode) jTreeDesktop.getModel().getRoot(); // Traverse tree from root expandAllTrees(new TreePath(root)); } private void expandAllTrees(TreePath parent) { // Traverse children TreeNode node = (TreeNode) parent.getLastPathComponent(); // if we have children, go on if (node.getChildCount() >= 0) { // itereate all children for (Enumeration e = node.children(); e.hasMoreElements();) { DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); if (n.getAllowsChildren()) { // Expansion or collapse must be done bottom-up if (desktopObj.isBulletTreefoldExpanded(TreeUtil.getNodeTimestamp(n))) { jTreeDesktop.expandPath(path); expandAllTrees(path); } else { jTreeDesktop.collapsePath(path); } } } } // if (node.getAllowsChildren()) { // // Expansion or collapse must be done bottom-up // if (desktopObj.isBulletTreefoldExpanded(CCommonMethods.getNodeTimestamp((DefaultMutableTreeNode)node))) { // jTreeDesktop.expandPath(parent); // } else { // jTreeDesktop.collapsePath(parent); // } // } } /** * This method adds a new desktop to the desktop-data-file. The user can input a new * description (string-value). After that, the string is passed to the CDesktopData-class'es * method "addNewDesktop", where a new desktop-element is created */ @Action public void newDesktop() { // user-input for new desktop-description String newDesk = (String) JOptionPane.showInputDialog(null, resourceMap.getString("newDesktopMsg"), resourceMap.getString("newDesktopTitle"), JOptionPane.PLAIN_MESSAGE); // if we have any valdi input, go on... if ((newDesk != null) && (newDesk.length() > 0)) { // add the description as new element to the desktop-data-class if (desktopObj.addNewDesktop(newDesk)) { // save current notes desktopObj.setDesktopNotes(1, jTextArea1.getText()); desktopObj.setDesktopNotes(2, jTextArea2.getText()); desktopObj.setDesktopNotes(3, jTextArea3.getText()); // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel(); // set the desktop-description as root-element. DefaultMutableTreeNode root = new DefaultMutableTreeNode(newDesk); root.setAllowsChildren(true); dtm.setRoot(root); // and update combo box updateComboBox(false); } else { // desktop-name already existed, so desktop was not added... JOptionPane.showMessageDialog(this, resourceMap.getString("errDesktopExistsMsg"), resourceMap.getString("errDesktopExistsTitle"), JOptionPane.PLAIN_MESSAGE); } } // if new desktop action was cancelled, check whether we have any desktops at all... else if (desktopObj.getCount() < 1) { // if not, close window resetAndClose(); } } /** * This action renames a bullet point, including the root-bullet, i.e. * the name of the desktop. Entry-nodes cannot be renamed. */ @Action(enabledProperty = "bulletSelected") public void renameBullet() { // copy bullet's name into variable DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // open an input-dialog, setting the selected value as default-value String newBulletName = (String) JOptionPane.showInputDialog(this, resourceMap.getString("editBulletMsg"), resourceMap.getString("editBulletTitle"), JOptionPane.PLAIN_MESSAGE, null, null, node.toString()); // if we have a valid return-value, and this bulletname does not already exist... if ((newBulletName != null) && (newBulletName.length() > 0) && (!checkIfBulletExists(newBulletName))) { // ...either change desktop's name if the root is selected if (node.isRoot()) { // check whether renaming succeeded if (!desktopObj.setDesktopName(desktopObj.getCurrentDesktopNr(), newBulletName)) { // if not, tell user... JOptionPane.showMessageDialog(this, resourceMap.getString("errRenameDesktopMsg"), resourceMap.getString("errRenameDesktopTitle"), JOptionPane.PLAIN_MESSAGE); return; } // update the combobox updateComboBox(false); } // ...or change the name of the selected bullet else { if (!desktopObj.renameBullet(TreeUtil.getNodeTimestamp(node), newBulletName)) { // if not, tell user... JOptionPane.showMessageDialog(this, resourceMap.getString("errRenameBulletMsg"), resourceMap.getString("errRenameBulletTitle"), JOptionPane.PLAIN_MESSAGE); return; } // update treeview updateTreeView(); } } } /** * This method deletes the selected entry, bullet with child-entries or even the complete * desktop if the root is selected. */ @Action(enabledProperty = "anyNodeSelected") public void deleteNode() { // get selection DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // if we have a valid selection, go on if (node != null) { // variable that indicates what type of node we have to delete int delete_what; // check what we have to delete if (node.isRoot()) delete_what = Constants.DEL_DESKTOP; else if (node.getAllowsChildren()) delete_what = Constants.DEL_BULLET; else delete_what = Constants.DEL_ENTRY; // create empty string String msg = ""; // create message for confirm dialog, based on the type what we want to delete switch (delete_what) { case Constants.DEL_DESKTOP: msg = resourceMap.getString("askForDeleteDesktopMsg"); break; case Constants.DEL_BULLET: msg = resourceMap.getString("askForDeleteBulletMsg"); break; } int option = -1; // ask for delete only when the root or a bullet has to be deleted if (delete_what != Constants.DEL_ENTRY) { // ask user whether the node should be deleted option = JOptionPane.showConfirmDialog(null, msg, resourceMap.getString("askForDeleteTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); } // if yes, go on if ((JOptionPane.YES_OPTION == option) || (Constants.DEL_ENTRY == delete_what)) { // check which type of node was selected. either root, bullet or entry; and // delete the related entry/bullet with children/complete desktop switch (delete_what) { case Constants.DEL_DESKTOP: // delete desktop desktopObj.deleteDesktop(); // if we have any desktops left, update treeview if (desktopObj.getCount() > 0) updateComboBox(false); // else reset all fields and close window else { resetAndClose(); } break; case Constants.DEL_BULLET: // delete parent desktopObj.deleteBullet(TreeUtil.getNodeTimestamp(node)); // update view updateTreeView(); break; case Constants.DEL_ENTRY: // delete entry desktopObj.deleteEntry(TreeUtil.getNodeTimestamp(node)); // update view updateTreeView(); break; } } } } private void resetAndClose() { // set click to update-text jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText")); // reset tree initTree(); // reset combobox updateComboBox(true); // check whether memory usage is logged. if so, tell logger that new entry windows was opened if (settingsObj.isMemoryUsageLogged) { // log info Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window closed."); } // make window invisible setVisible(false); } /** * Opens a dialog where the user can choose which additional items for an entry (like * author, remarks etc.) should be displayed in the desktop. */ @Action public void displayItems() { if (null == desktopDisplayItemsDlg) { // create a new dialog with the desktop-dialog, passing some initial values desktopDisplayItemsDlg = new CDesktopDisplayItems(this, settingsObj); // center window desktopDisplayItemsDlg.setLocationRelativeTo(this); } // show window ZettelkastenApp.getApplication().show(desktopDisplayItemsDlg); // when the user made changes and applies them... if (desktopDisplayItemsDlg.isNeedsUpdate()) { // tell programm that we need an update to the display. setNeedsUpdate(true); } // delete the windows desktopDisplayItemsDlg.dispose(); desktopDisplayItemsDlg = null; } /** * This method adds a new header/bulletpoint to the desktop (and to the jtree). Bullets * differ from "usual" note in such case, that they are allowed to have children - in contrary * to nodes that refer to entries, which may not have children. * <br><br> * New bullet are always addes to the end of a selected node's children-list, while a new * "entry-node" should be added <b>before</b> bullets. Thus, in a children list, first come * all entry-nodes, than all bullet-nodes (always in this order). */ @Action(enabledProperty = "bulletSelected") public void addBullet() { // wait for user input String newBullet = (String) JOptionPane.showInputDialog(null, resourceMap.getString("newBulletMsg"), resourceMap.getString("newBulletTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid input and no cancel-operation, go on if (newBullet != null && newBullet.length() > 0) { // now we have to check whether the name of "newBullet" already exists as a bullet on this // level of the outline/structure. Therefor, check whether "insert" is a selected entry or a node. // if it's an entry, thus the new bullet is located on the same level, retrieve the parent. // then we go through all parent's children and check for the occurence of a bullet named // "newBullet". if (checkIfBulletExists(newBullet)) return; // retrieve selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // add bullet to xml-file. therefor, check whether selection is the root, then pass // "null" as parameter. in every other case, pass the bullet's timestamp as parameter String timestamp = desktopObj.addBullet((node.isRoot()) ? null : TreeUtil.getNodeTimestamp(node), newBullet); // update treeview updateTreeView(); // add new bullet to path and re-select new path... selectTreePath(timestamp); // update the menus/toolbar updateToolbarAndMenu(); } } /** * This method checks whether a new bullet {@code newBullet}, that should be added/inserted as sub-bullet * to an existing bullet {@code insert}, already exists as sub-element of the parent {@code insert} or not. * * @param newBullet the name of the new bullet that should be inserted as child of {@code insert} * @param insert the parent-bullet, where the bullet {@code newBullet} should be added to * @return {@code true} if a bullet which name equals {@code newBullet} already exists, false if {@code newBullet} * does not exist and can successfully be added/inserted. */ private boolean checkIfBulletExists(String newBullet) { // get the selected node, so we know where to insert the new bullet DefaultMutableTreeNode insert = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // now we have to check whether the name of "newBullet" already exists as a bullet on this // level of the outline/structure. Therefor, check whether "insert" is a selected entry or a node. // if it's an entry, thus the new bullet is located on the same level, retrieve the parent. // then we go through all parent's children and check for the occurence of a bullet named // "newBullet". DefaultMutableTreeNode parent = ((insert.getAllowsChildren()) ? insert : (DefaultMutableTreeNode) insert.getParent()); // got through all parent's children for (int cnt = 0; cnt < parent.getChildCount(); cnt++) { // get child DefaultMutableTreeNode child = (DefaultMutableTreeNode) parent.getChildAt(cnt); // since each bullet-point has a timestamp-id, we need to extract the bullet's name // only for comparison String text = child.toString(); int pos = text.indexOf("["); // only continue if we found something... if (pos != -1) { // compare child's text with newBullet-text if (newBullet.equalsIgnoreCase(text.substring(0, pos).trim())) { // if we found a match, tell user about cancelling JOptionPane.showMessageDialog(this, resourceMap.getString("errBulletExistsMsg"), resourceMap.getString("errBulletExistsTitle"), JOptionPane.PLAIN_MESSAGE); return true; } } } return false; } /** * This methods adds a new entry-node, i.e. a node that is not allowed to have children, to * the jTree. * <br><br> * First of all, an input-dialog is opened where the user can enter several entry-numbers, * separated by commas, including "from-to"-option (e.g.: "4,7,13-16,22"). Then each * entry is retrieved, setting entry-number and entry-title as node-text. * <br><br> * The nodes are added to the end of the selected node's children-list, but <b>before</b> the * first heading/bullet. so, a child-list always lists first the entry-nodes (that are not allowed * to have children), followed by header/bullet-nodes (that may have children). * <br><br> * An entry-node shall never be located <b>behind</b> a bullet/header node! * <br><br><i>This method is separated in two parts!</i> The main part can be found * in the {@link #addEntries addEntries} method. */ @Action(enabledProperty = "nodeSelected") public void addEntry() { // wait for user input String newEntries = (String) JOptionPane.showInputDialog(null, resourceMap.getString("newEntryMsg"), resourceMap.getString("newEntryTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid input and no cancel-operation, go on if (newEntries != null && newEntries.length() > 0) addEntries(newEntries); } @Action(enabledProperty = "entryNodeSelected") public void editEntry() { // get selected entry int nr = getSelectedEntryNumber(); // when we have a valid selection, go on if (nr != -1) zknframe.openEditWindow(true, nr, false, false, -1); } @Action(enabledProperty = "nodeSelected") public void insertEntry() { zknframe.editEntryFromDesktop = true; zknframe.openEditWindow(false, -1, false, false, getSelectedEntryNumber()); } /** * This methods adds a new entry-node, i.e. a node that is not allowed to have children, to * the jTree. * <br><br> * First of all, an input-dialog is opened where the user can enter several entry-numbers, * separated by commas, including "from-to"-option (e.g.: "4,7,13-16,22"). Then each * entry is retrieved, setting entry-number and entry-title as node-text. * <br><br> * The nodes are added to the end of the selected node's children-list, but <b>before</b> the * first heading/bullet. so, a child-list always lists first the entry-nodes (that are not allowed * to have children), followed by header/bullet-nodes (that may have children). * <br><br> * An entry-node shall never be located <b>behind</b> a bullet/header node! * <br><br><i>This method is separated in two parts!</i> The inital part can be found * in the {@link #addEntry addEntry} method. * * @param newEntries */ private void addEntries(String newEntries) { addEntries(newEntries, null); } /** * This methods adds a new entry-node, i.e. a node that is not allowed to have children, to * the jTree. * <br><br> * First of all, an input-dialog is opened where the user can enter several entry-numbers, * separated by commas, including "from-to"-option (e.g.: "4,7,13-16,22"). Then each * entry is retrieved, setting entry-number and entry-title as node-text. * <br><br> * The nodes are added to the end of the selected node's children-list, but <b>before</b> the * first heading/bullet. so, a child-list always lists first the entry-nodes (that are not allowed * to have children), followed by header/bullet-nodes (that may have children). * <br><br> * An entry-node shall never be located <b>behind</b> a bullet/header node! * <br><br><i>This method is separated in two parts!</i> The inital part can be found * in the {@link #addEntry addEntry} method. * * @param newEntries * @param modifications */ private void addEntries(String newEntries, String modifications) { // at the end we need this to check for changes boolean modified = false; // counter for inserting the new node, used below int childcount = 0; // remember the last added entry's timestamp String lastadded = null; // get the selected node, so we know where to insert the new entry DefaultMutableTreeNode insert = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // if we have selected an entry, make sure to get the parent as insert-point // else we have selected a parent (bullet/header). the entry should be inserted at // first posiion after the bullet. if (!insert.getAllowsChildren()) { DefaultMutableTreeNode parent = (DefaultMutableTreeNode) insert.getParent(); // get the index of the selected child (i.e. the selected entry) // and add one, so the entry is inserted *after* the current selected entry childcount = parent.getIndex(insert) + 1; // and set the insert-value to the parent insert = parent; } // retrieve arrays from the text-input int[] entries = Tools.retrieveEntryNumbersFromInput(newEntries, dataObj.getCount(Daten.ZKNCOUNT)); // here we store all found entries that have been added, so we can afterwards iterate // this array to find the multiple entries for the above linked-list // we do this in two steps, because we want to search all entries within one desktop, // that means: we want to go through all desktops (the outer loop), and inside this // loop we want to go through all entries (the inner loop). but below, we are iterating // all entries, so the desktop-iteration would be the inner-loop. this is not intended, // because we want to sort the multiple entries according to an ordered desktop-list, // which requires iterating the desktops as outer loop. LinkedList<Integer> multipleEntries = new LinkedList<Integer>(); // init multiple message flag showMultipleEntryMsg = true; // check for valid user-input if (entries != null) for (int cnt : entries) { // check whether entry already exists if (noDoubleEntries(insert, cnt)) { // go through all desktops and check whether the current entry already exists. // if yes, add added entry to our linked list. for (int me = 0; me < desktopObj.getCount(); me++) if (desktopObj.checkForDoubleEntry(me, cnt)) multipleEntries.add(cnt); // add entry to desktop (xml-file) lastadded = desktopObj.addEntry(TreeUtil.getNodeTimestamp(insert), String.valueOf(cnt), childcount); // check whether we also have modifications to add if (modifications != null && !modifications.isEmpty()) desktopObj.addModifiedEntry(lastadded, modifications); // remember that we have changes modified = true; // increase counter to indicate next entry childcount++; } } // update treeview if we have changes if (modified) { // update treeview updateTreeView(); // and re-select initial entry/bullet selectTreePath(lastadded); // show message box in case we have multiple occurences of entries... showMultipleOccurencesMessage(Tools.retrieveDoubleEntries(desktopObj, multipleEntries)); } } private void showMultipleOccurencesMessage(List<Object[]> list) { // if we have any multiple occurences, the stringbuilder must be longer than 0 multipleOccurencesMessage = Tools.prepareDoubleEntriesMessage(list); // check whether we have any multiple occurences... if (multipleOccurencesMessage != null) { // check whether this dialog should be displayed at all... if (!settingsObj.getHideMultipleDesktopOccurencesDlg()) { multipleOccurencesMessage = resourceMap.getString("showMultipleEntriesOnDesktop") + lineseparator + lineseparator + multipleOccurencesMessage; if (null == multipleOccurencesDlg) { // create a new dialog with the desktop-dialog, passing some initial values multipleOccurencesDlg = new CShowMultipleDesktopOccurences(this, settingsObj, false, multipleOccurencesMessage); // center window multipleOccurencesDlg.setLocationRelativeTo(null); } else multipleOccurencesDlg.setInfoMsg(multipleOccurencesMessage); // show window ZettelkastenApp.getApplication().show(multipleOccurencesDlg); } // if not, just display icon else { jButtonShowMultipleOccurencesDlg.setVisible(true); } } } @Action public void openMultipleOccurencesMessageDlg() { if (multipleOccurencesMessage != null) { multipleOccurencesMessage = resourceMap.getString("showMultipleEntriesOnDesktop") + lineseparator + lineseparator + multipleOccurencesMessage; if (null == multipleOccurencesDlg) { // create a new dialog with the desktop-dialog, passing some initial values multipleOccurencesDlg = new CShowMultipleDesktopOccurences(this, settingsObj, false, multipleOccurencesMessage); // center window multipleOccurencesDlg.setLocationRelativeTo(null); } else multipleOccurencesDlg.setInfoMsg(multipleOccurencesMessage); // show window ZettelkastenApp.getApplication().show(multipleOccurencesDlg); // hide button jButtonShowMultipleOccurencesDlg.setVisible(false); } } /** * This method adds entries, indicated by their index-numbers, to the desktop. this method * is usually used to add entries to the desktop from other windows, like main-window or * searchresults-window etc. * * @param entries the entry-numbers in an integer-array */ public void addEntries(int[] entries) { // when we have no entries, leave if ((null == entries) || (entries.length < 1)) return; // if we don't have any desktop created yet, tell the user to do so // before adding new entries... while (desktopObj.getCount() < 1) { // ask user whether a new desktop should be created... int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForNewDesktopMsg"), resourceMap.getString("askForNewDesktopTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if no, leave method... if (JOptionPane.NO_OPTION == option) return; // else create new desktop newDesktop(); // when the user added a new desktop, select it if (desktopObj.getCount() >= 1) { TreePath tp = new TreePath((TreeNode) jTreeDesktop.getModel().getRoot()); jTreeDesktop.setSelectionPath(tp); } } // if we don't have any bullets created yet, tell the user to do so // before adding new entries... while (!desktopObj.desktopHasBullets(desktopObj.getCurrentDesktopNr())) { // ask user whether a new bullet should be created... int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForNewBulletMsg"), resourceMap.getString("askForNewBulletTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if no, leave method if (JOptionPane.NO_OPTION == option) return; // else add bullet addBullet(); } // if a valid node is selected, add entries if (isNodeSelected()) { // create a new stringbuilder StringBuilder sb = new StringBuilder(""); // iterate the array with all entries for (int e : entries) { // append entry-number sb.append(String.valueOf(e)); // and a comma sb.append(","); } // delete last comma if (sb.length() > 1) sb.setLength(sb.length() - 1); // add entries addEntries(sb.toString()); } else { // copy entries to "clipboard", so the user can paste them after selecting a bullet or node. clipEntries = entries; // tell user that a selection has to be made... JOptionPane.showMessageDialog(this, resourceMap.getString("errSelectionNeededMsg"), resourceMap.getString("errSelectionNeededTitle"), JOptionPane.PLAIN_MESSAGE); } } /** * This action is enabled, when an entry has follower-entries (Luhmann-Numbers). If a user * performs this action, all entry's follower-entries (Luhmann-Numbers) are added behind this * entry. */ @Action(enabledProperty = "luhmannNodeSelected") public void addLuhmann() { // init string builder luhmannnumbers = new StringBuilder(""); // get recursive Luhmann-Numbers fillLuhmannNumbers(getSelectedEntryNumber()); // add them... if (luhmannnumbers.length() > 0) { // delete last comma luhmannnumbers.setLength(luhmannnumbers.length() - 1); // add entries to treeview addEntries(luhmannnumbers.toString()); } } /** * This method recursively retrieves all follower- and sub-follower-numbers * (Luhmann-Numbers) of an entry and adds them to a stringbuilder. This method * is needed for the {@link #addLuhmann addLuhmann}-Action that adds these * follower-numbers to the treeview, directly behind the selected entry. * * @param zettelpos the number of the selected entry */ private void fillLuhmannNumbers(int zettelpos) { // get the text from the luhmann-numbers String lnr = dataObj.getLuhmannNumbers(zettelpos); // if we have any luhmann-numbers, go on... if (!lnr.isEmpty()) { String[] lnrs = lnr.split(","); // go throughh array of current luhmann-numbers for (String exist : lnrs) { // copy all values to an array luhmannnumbers.append(exist); luhmannnumbers.append(","); // check whether luhmann-value exists, by re-calling this method // again and go through a recusrive loop fillLuhmannNumbers(Integer.parseInt(exist)); } } } /** * This method is called from "addEntry" and checks whether an entry-number already exists * as a child of that parent. * * @param parent the insert-parent, where the entry should be inserted as child * @param nr the number of the entry that should be inserted * @return {@code true} if the entry "nr" already exists as child of "parent". */ private boolean noDoubleEntries(DefaultMutableTreeNode parent, int nr) { // got through all parent's children for (int counter = 0; counter < parent.getChildCount(); counter++) { // get child DefaultMutableTreeNode doublechild = (DefaultMutableTreeNode) parent.getChildAt(counter); // retrieve the node's text and extract the entry-number int childnr = TreeUtil.extractEntryNumberFromNode(doublechild); // compare child's text with newBullet-text if (childnr == nr) { // if we found a match, tell user about cancelling if (showMultipleEntryMsg) { JOptionPane.showMessageDialog(this, resourceMap.getString("errEntryExistsMsg"), resourceMap.getString("errEntryExistsTitle"), JOptionPane.PLAIN_MESSAGE); showMultipleEntryMsg = false; } return false; } } return true; } /** * Exports the desktop-data to a file, i.e. the content will be written to a file "as it is" (wysiwyg). * unlink the typical export method, this export method also export bullet-point-headings, invisible * entry-titles, modified entries etc. some of these features are not supported by the usual export-method. */ @Action public void exportDesktop() { export(desktopObj.getCurrentDesktopElement(), (DefaultMutableTreeNode) jTreeDesktop.getModel().getRoot()); } @Action public void importArchivedDesktop() { // create document Document archive = new Document(); // retrieve last used importdirectory File importdir = settingsObj.getFilePath(); // let user choose filepath File filepath = FileOperationsUtil.chooseFile(this, (settingsObj.isMacAqua()) ? FileDialog.LOAD : JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY, (null == importdir) ? null : importdir.getPath(), (null == importdir) ? null : importdir.getName(), resourceMap.getString("openArchiveTitle"), new String[] { ".zip" }, "Zip", settingsObj); // if we have a valid file, go on if (filepath != null && filepath.exists()) { try { // open the zip-file ZipInputStream zip = new ZipInputStream(new FileInputStream(filepath)); ZipEntry entry; // now iterate the zip-file, searching for the requested file in it while ((entry = zip.getNextEntry()) != null) { // get filename of zip-entry String entryname = entry.getName(); // if the found file matches the requested one, start the SAXBuilder if (entryname.equals(Constants.archivedDesktopFileName)) { try { SAXBuilder builder = new SAXBuilder(); archive = builder.build(zip); break; } catch (JDOMException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } } } zip.close(); // tell about success Constants.zknlogger.log(Level.INFO, "Desktop archive successfully opened."); } catch (IOException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); // show error message dialog JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveDlgErr"), resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE); // and show error log zknframe.showErrorIcon(); return; } // init variables that indicate the success of the import-progress boolean finished = false; // we have a loop here, because the desktop-name of the imported archiv might already exist. // in this case, the user can retry with new names, until a new name was entered, or the // user cancels the action while (!finished) { // import archive int result = desktopObj.importArchivedDesktop(archive); // here we go on in case the desktop-name of the imported archive // already exists. in this case, the user shoould rename the archive if (DesktopData.IMPORT_ARCHIVE_ERR_DESKTOPNAME_EXISTS == result) { // desktop-name already existed, so desktop was not added... JOptionPane.showMessageDialog(this, resourceMap.getString("errDesktopNameExistsMsg", archive.getRootElement().getAttributeValue("name")), resourceMap.getString("errDesktopNameExistsTitle"), JOptionPane.PLAIN_MESSAGE); // user-input for new desktop-description String newDeskName = (String) JOptionPane.showInputDialog(this, resourceMap.getString("newDesktopMsg"), resourceMap.getString("newDesktopTitle"), JOptionPane.PLAIN_MESSAGE); // check for valid-return value, or if the user cancelled the action if (newDeskName != null && !newDeskName.isEmpty()) { // if everything was ok, set new name archive.getRootElement().setAttribute("name", newDeskName); } else { // else user has cancelled process JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveCancelled"), resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE); return; } } else if (DesktopData.IMPORT_ARCHIVE_ERR_OTHER == result) { // tell user about problem JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveError"), resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE); // and show error log zknframe.showErrorIcon(); return; } else if (DesktopData.IMPORT_ARCHIVE_OK == result) { // everything is ok, so quit while-loop finished = true; } } // show success JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveOK"), resourceMap.getString("openArchiveTitle"), JOptionPane.PLAIN_MESSAGE); // and update combo box updateComboBox(false); } } /** * This method archives the currently active desktop to a zipped xml-file. This method saves the * current desktop-data, the related notes for this desktop and possible modified entries.<br><br> * Archive files can be imported as well (see {@link #importArchivedDesktop() importArchivedDesktop()}). */ @Action public void archiveDesktop() { // retrieve data-filepath File datafp = settingsObj.getFilePath(); // convert to string, and cut off filename by creating a substring that cuts off // everything after the last separator char String datafilepath = (datafp != null) ? datafp.getPath().substring(0, datafp.toString().lastIndexOf(java.io.File.separator) + 1) : ""; // ... to cut off extension if (!datafilepath.isEmpty()) datafilepath = datafilepath + desktopObj.getCurrentDesktopName() + resourceMap.getString("archiveDesktopSuffix"); // create new path File exportdir = new File(datafilepath); // here we open a swing filechooser, in case the os ist no mac aqua File filepath = FileOperationsUtil.chooseFile(this, (settingsObj.isMacAqua()) ? FileDialog.SAVE : JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, exportdir.getPath(), exportdir.getName(), resourceMap.getString("fileDialogTitleSave"), new String[] { ".zip" }, "Zip", settingsObj); if (filepath != null) { // add fileextenstion, if necessay if (!filepath.getName().endsWith(".zip")) { filepath = new File(filepath.toString() + ".zip"); } // check whether file already exists if (filepath.exists()) { // file exists, ask user to overwrite it... int optionDocExists = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForOverwriteFileMsg", filepath.getName()), resourceMap.getString("askForOverwriteFileTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if the user does *not* choose to overwrite, quit... if (optionDocExists != JOptionPane.YES_OPTION) { // don't show "export was OK" message in main frame return; } } // create desktop-archive-XML-document Document archiveddesktop = desktopObj.archiveDesktop(desktopObj.getCurrentDesktopName()); // check whether an error occured if (null == archiveddesktop) { // tell user about error JOptionPane.showMessageDialog(this, resourceMap.getString("archiveErrMsg"), resourceMap.getString("archiveErrTitle"), JOptionPane.PLAIN_MESSAGE); zknframe.showErrorIcon(); return; } // export and zip file try { // open the outputstream ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(filepath)); // I first wanted to use a pretty output format, so advanced users who // extract the data file can better watch the xml-files. but somehow, this // lead to an error within the method "retrieveElement" in the class "CDaten.java", // saying the a org.jdom.text cannot be converted to org.jdom.element?!? // XMLOutputter out = new XMLOutputter(Format.getPrettyFormat()); XMLOutputter out = new XMLOutputter(); // save archived desktop zip.putNextEntry(new ZipEntry(Constants.archivedDesktopFileName)); out.output(archiveddesktop, zip); zip.close(); } catch (IOException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); JOptionPane.showMessageDialog(this, resourceMap.getString("archiveErrMsg"), resourceMap.getString("archiveErrTitle"), JOptionPane.PLAIN_MESSAGE); zknframe.showErrorIcon(); return; } catch (SecurityException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); JOptionPane.showMessageDialog(this, resourceMap.getString("archiveErrMsg"), resourceMap.getString("archiveErrTitle"), JOptionPane.PLAIN_MESSAGE); zknframe.showErrorIcon(); return; } JOptionPane.showMessageDialog(this, resourceMap.getString("archiveOkMsg"), resourceMap.getString("archiveOkTitle"), JOptionPane.PLAIN_MESSAGE); } } /** * Exports the desktop-data to a file, i.e. the content will be written to a file "as it is" (wysiwyg). * unlink the typical export method, this export method also export bullet-point-headings, invisible * entry-titles, modified entries etc. some of these features are not supported by the usual export-method. * * @param startelement the starting point for the jTree-enumeration, either the root element or a bullet (if only * a bullet should be exported, see {@link #exportDesktopBullet() exportDesktopBullet()}). * @param startnode the starting point for the jTree-enumeration, either the root node or a bullet (if only * a bullet should be exported, see {@link #exportDesktopBullet() exportDesktopBullet()}). */ private void export(Element startelement, DefaultMutableTreeNode startnode) { // opens the Export Dialog. This Class is responsible // for getting the relevant export data. the export task // itself (background task) will be started as another dialog, // when this one is closed // now open the export-dialog if (null == exportWindow) { // get parent und init window exportWindow = new CDesktopExport(this, settingsObj, bibtexObj); // center window exportWindow.setLocationRelativeTo(this); } ZettelkastenApp.getApplication().show(exportWindow); // Here the data (filepath, filetype) from the export window // will be passed to another dialog window, which starts the // background task. these dialogs are separated because it looks // better to have a background task with progress bar in an own, // smaller dialog // // first check for valid return value. export is only started, // when the previous dialog wasn't cancelled or simply closed if (Constants.RETURN_VALUE_CONFIRM == exportWindow.getReturnValue()) { // when the user wants to export into PDF or LaTex, open a new dialog where the user // can make some extra settings like page settings and font-sizes. if (ExportTools.isExportSettingsOk(this, settingsObj, exportWindow.getExportType())) { // if dialog window isn't already created, do this now if (null == taskDlg) { // create list that will contain all entries which should be exported ArrayList<Object> liste = new ArrayList<Object>(); // here we recursively create the list of headlines and entry-numbers // from the current desktop createExportEntries(startelement, liste); // open export dialog // get parent und init window taskDlg = new TaskProgressDialog(this, TaskProgressDialog.TASK_EXPORTDATA, taskdata, dataObj, bookmarksObj, desktopObj, settingsObj, bibtexObj, null, exportWindow.getFilePath(), liste, exportWindow.getExportType(), 0, ';', startnode, false, false, exportWindow.getExportBibTex(), false, exportWindow.getExportToc(), isHeadingVisible, isEntryNumberVisible); // center window taskDlg.setLocationRelativeTo(this); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // else tell user that everything went fine if (taskdata.showExportOkMessage()) JOptionPane.showMessageDialog(this, resourceMap.getString("exportOkMsg"), resourceMap.getString("exportOkTitle"), JOptionPane.PLAIN_MESSAGE); } } // we have to manually dispose the window and release the memory // because next time this method is called, the showKwlDlg is still not null, // i.e. the constructor is not called (because the if-statement above is not true) exportWindow.dispose(); exportWindow = null; // try to motivate garbage collector System.gc(); } /** * This method exports not a complete desktop, but the selected bullets with all its * sub-entries (child-nodes) to a file. */ @Action(enabledProperty = "bulletSelected") public void exportDesktopBullet() { // only export subentries, if a bullet-point is selected. if (!isBulletSelected()) return; // find starting-element (selected bullet) from timestamp String timestamp = getSelectedNodeTimestamp(); // and export data export(desktopObj.findEntryElementFromTimestamp(desktopObj.getCurrentDesktopElement(), timestamp), (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent()); } /** * This method exports all desktops to a file. Unlike the typical export-function for desktop-data * (see {@link #exportDesktop() exportDesktop()}, this method does not export the desktop-data "as it is" * (including modified entries, see {@link #modifiyEntry() modifiyEntry()}), but only the simple * entry-contents.<br><br> * While the typical desktop-export-functions call the {@link #export(org.jdom.Element, javax.swing.tree.DefaultMutableTreeNode) export()} * method, this method calls the export-method from the mainframe. */ @Action public void exportMultipleDesktop() { // check whether multiple desktops available if (desktopObj.getCount() < 2) return; if (null == desktopMultipleExportDlg) { // create a new dialog with the desktop-dialog, passing some initial values desktopMultipleExportDlg = new CDesktopMultipleExport(this, desktopObj, settingsObj); // center window desktopMultipleExportDlg.setLocationRelativeTo(this); } // show window ZettelkastenApp.getApplication().show(desktopMultipleExportDlg); // check for return-value if (desktopMultipleExportDlg.getChosenDesktops() != null && desktopMultipleExportDlg.getChosenDesktops().length > 0) { // create list that will contain all entries which should be exported ArrayList<Object> liste = new ArrayList<Object>(); // iterate all chosen desktop-names for (String desktopname : desktopMultipleExportDlg.getChosenDesktops()) { // here we recursively create the list of headlines and entry-numbers // from the current desktop createExportEntries(desktopObj.getDesktopElement(desktopname), liste); } // call export-method and export the entries. zknframe.exportEntries(liste); } // delete the windows desktopMultipleExportDlg.dispose(); desktopMultipleExportDlg = null; } /** * This method "exports" all entries of the current desktop as search results, i.e. all entry-numbers * are shown in the search results window.<br><br> * You can also export just the entries of a selected bullet and all its sub-entries (child-nodes) * as search result, see {@link #exportBulletToSearch() exportBulletToSearch()}. */ @Action public void exportToSearch() { zknframe.exportDesktopToSearch(desktopObj.retrieveDesktopEntries(desktopObj.getCurrentDesktopNr()), desktopObj.getCurrentDesktopName()); } /** * This method "exports" all entries of the currently selected bullet and all its sub-entries (child-nodes) * as search results, i.e. all related entry-numbers are shown in the search results window.<br><br> * You can also export the entries of the complete desktop as search result, see * {@link #exportToSearch() exportToSearch()}. */ @Action(enabledProperty = "bulletSelected") public void exportBulletToSearch() { if (isBulletSelected()) { // retrieve selected node and its timestamp String timestamp = getSelectedNodeTimestamp(); // here we recursively create the list of headlines and entry-numbers // from the current desktop zknframe.exportDesktopToSearch( desktopObj.retrieveBulletEntries(desktopObj .findEntryElementFromTimestamp(desktopObj.getCurrentDesktopElement(), timestamp)), desktopObj.getCurrentDesktopName()); } } /** * This method shows all entries that are <b>not</b> used in the current desktop as * search results, i.e. all entry-numbers that do not appear in the current desktop * are shown in the search results window. */ @Action public void exportMissingToSearch() { // retrieve all entry-numbers from current desktop int[] currentdesktopentries = desktopObj.retrieveDesktopEntries(desktopObj.getCurrentDesktopNr()); // check for valid return value if (currentdesktopentries != null && currentdesktopentries.length > 0) { // create new integer-array ArrayList<Integer> expvalues = new ArrayList<Integer>(); // go through all entry-numbers for (int cnt = 1; cnt <= dataObj.getCount(Daten.ZKNCOUNT); cnt++) { // if entry-number is *not* on the desktop... if (!isInArray(cnt, currentdesktopentries)) { // ... add it to our result-array expvalues.add(cnt); } } // if we have any results, go on... if (expvalues.size() > 0) { // create return value int[] retval = new int[expvalues.size()]; // and copy all integer-values from the list to that array for (int cnt = 0; cnt < retval.length; cnt++) { retval[cnt] = expvalues.get(cnt); } zknframe.exportDesktopToSearch(retval, desktopObj.getCurrentDesktopName()); } } } /** * This method checks for the occurence of the value {@code nr} inside the array * {@code arr}. * * @param nr the integer-value we are looking for * @param arr the integer-array, which mightt contain{@code nr} * @return {@code true} if {@code nr} was found inside {@code arr}, {@code false} otherwise. */ private boolean isInArray(int nr, int[] arr) { // check for valid array if (arr != null && arr.length > 0) { // go through whole array for (int cnt = 0; cnt < arr.length; cnt++) { // if we found the value "nr" inside the array "arr", return true if (arr[cnt] == nr) return true; } } return false; } /** * This methods checks whether a selected entry is the last entry in the list of a bullet's * child-nodes. * * @return {@code true} if the selected entry is the last entry in a list of child-nodes, false otherwise */ private boolean isLastNode() { // if no node selected, return... if (!isNodeSelected()) return false; // get the selected node, so we know where to insert the new bullet DefaultMutableTreeNode selection = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // enumerate all children of the node's parent's children... Enumeration<DefaultMutableTreeNode> children = node.getParent().children(); while (children.hasMoreElements()) { try { // get each child node = children.nextElement(); // if the child of the enumeration equals the selection... if (node.equals(selection)) { // get next node after selected entry node = children.nextElement(); // if the selected entry has another entry behind, return false // otherwise true return (!isBulletSelected()) ? (node.getAllowsChildren()) : false; } } catch (NoSuchElementException e) { // if there is no entry after the selected one, return true return true; } } return false; } /** * This methods checks whether a selected entry is the first entry in the list of a bullet's * child-nodes. * * @return {@code true} if the selected entry is the first entry in a list of child-nodes, false otherwise */ private boolean isFirstNode() { // if no node selected, return... if (!isNodeSelected()) return false; // get the selected node, so we know where to insert the new bullet DefaultMutableTreeNode selection = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // if the selection is a node-entry... // ...return true when selected entry equals the first child-node of the selected entry's parent if (!isBulletSelected()) { return (0 == selection.getParent().getIndex(selection)); // return (selection.equals(selection.getParent().getChildAt(0))); } // else if the selection is a bullet-point... else { // get the selected node's index int index = selection.getParent().getIndex(selection); // if index is 0, it is the first node. if (0 == index) return true; // else check whether the node before the selection is a bullet and return false, if it is... return !selection.getParent().getChildAt(index - 1).getAllowsChildren(); } } /** * Closes the window, i.e. makes it invisible */ @Action public void closeWindow() { // save current notes desktopObj.setDesktopNotes(1, jTextArea1.getText()); desktopObj.setDesktopNotes(2, jTextArea2.getText()); desktopObj.setDesktopNotes(3, jTextArea3.getText()); // save last used desktop nr settingsObj.setLastUsedDesktop(jComboBoxDesktop.getSelectedIndex()); // check whether memory usage is logged. if so, tell logger that new entry windows was opened if (settingsObj.isMemoryUsageLogged) { // log info Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window closed."); } // dispose window dispose(); setVisible(false); // try to motivate garbage collector System.gc(); } /** * This method modifies an entry, but these changes are only applied to the desktop-view. the * original entry's content in the main-database is not changed. * <br><br> * This is helpful when the user wants to "connect" entries by adding some words or paragraphs, * which is only necessary for a readable text on the desktop, while the original entries should * be left unmodified. */ @Action(enabledProperty = "entryNodeSelected") public void modifiyEntry() { // check whether a correct entry node was selected or not... if (!isEntryNodeSelected()) return; // check whether an entry is already being edited, i.e. the edit-window is already created if (isEditModeActive) { // if so, bring that window to the front modifyEntryDlg.toFront(); } // else create a new window and display it. else { // get the selected node, to tell the getComment method wether we have a bullet or an entry selected DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // retrieve and store edit-timestamp editModeTimeStamp = TreeUtil.getNodeTimestamp(node); // retrieve content from modified entry, if any... String oldcontent = desktopObj.retrieveModifiedEntryContentFromTimestamp(editModeTimeStamp); // check for any modified content. if we have no content, retrieve entry's original content instead if (null == oldcontent || oldcontent.isEmpty()) { // get original entry content oldcontent = dataObj.getZettelContent(TreeUtil.extractEntryNumberFromNode(node)); } // create a new dialog with the bigger edit-field, passing some initial values modifyEntryDlg = new CModifyDesktopEntry(this, settingsObj, spellObj, stenoObj, accKeys, oldcontent); // center window modifyEntryDlg.setLocationRelativeTo(this); ZettelkastenApp.getApplication().show(modifyEntryDlg); // edit window was initialized isEditModeActive = true; } } /** * This method replaces an original's entry's content with the modifications that have been made * for this entry on the desktop. */ @Action(enabledProperty = "modifiedEntryNode") public void applyModificationsToOriginalEntry() { // as whether original entry's content should really be replaced int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForApplyModificationsMsg"), resourceMap.getString("askForApplyModificationsTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // retrieve selected entry-number int nr = getSelectedEntryNumber(); // check for valid value if (nr != -1) { // retrieve timestamp of selected entry String timestamp = getSelectedNodeTimestamp(); // retrieve modified content String content = desktopObj.retrieveModifiedEntryContentFromTimestamp(timestamp); // and change entry dataObj.setZettelContent(nr, content, true); // remove modified entry from modification list desktopObj.deleteModifiedEntry(timestamp); // check whether modified entry is currently displayed. if so, // update view in mainframe... if (nr == zknframe.displayedZettel) zknframe.updateZettelContent(nr); } } } /** * This method replaces an original's entry's content with the modifications that have been made * for this entry on the desktop. */ @Action public void applyAllModificationsToOriginalEntries() { // as whether original entry's content should really be replaced int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForApplyModificationsMsg"), resourceMap.getString("askForApplyModificationsTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // retrieve all entry timestamps from desktop String[] alltimestamps = desktopObj.retrieveEntryTimestampsFromDesktop(); // check for valid value if (alltimestamps != null) { // iterate array for (String ats : alltimestamps) { // get entry number int enr = desktopObj.findEntryNrFromTimestamp(ats); // retrieve modified content String content = desktopObj.retrieveModifiedEntryContentFromTimestamp(ats); // check for valid values if (enr != -1 && content != null) { // and change entry dataObj.setZettelContent(enr, content, true); // remove modified entry from modification list desktopObj.deleteModifiedEntry(ats); // check whether modified entry is currently displayed. if so, // update view in mainframe... if (enr == zknframe.displayedZettel) zknframe.updateZettelContent(enr); } } } } } /** * This method is called after an entry was modified (see {@link #modifiyEntry() modifiyEntry()} * and {@link #modifyEntryDlg modifyEntryDlg} for more details). Since the edit-window is modal, * we need a message from that window when the editing is finished and when the changes can * be applied to the desktop data. the edit-window calls this method to indicate the finishing * of an edit-operation. */ public void finishedEditing() { // after closing the window, get the new value String newcontent = modifyEntryDlg.getModifiedEntry(); boolean newconmodified = modifyEntryDlg.isModified(); // delete the input-dialog modifyEntryDlg.dispose(); modifyEntryDlg = null; // reset flag isEditModeActive = false; // check for valid return value if (newconmodified && newcontent != null && !newcontent.isEmpty()) { // change modified entry if (desktopObj.changeEntry(editModeTimeStamp, newcontent)) { // update menu-items updateToolbarAndMenu(); // change updateflag setNeedsUpdate(true); } else { // if an error occured, tell user about it... JOptionPane.showMessageDialog(this, resourceMap.getString("errModifyEntryMsg"), resourceMap.getString("errModifyEntryTitle"), JOptionPane.PLAIN_MESSAGE); } } } // TODO kommentare von eintrgen mit kopieren/verschieben /** * Retrieves the entry-number of the selected entry and copies it to the * internal clipboard. after that, the selected node is deleted. */ @Action(enabledProperty = "nodeSelected") public void cutNode() { if (isBulletSelected()) { // store value, so we know the clipboard does contain bullets clipBullet = true; // copy bullet's name into variable DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); clipBulletName = node.toString(); // tell the desktop-data-class that the selected bullet has to be stored // for later use desktopObj.cutBulletToClip(TreeUtil.getNodeTimestamp(node)); // update view updateTreeView(); } else { // retrieve selected entry. int nr = getSelectedEntryNumber(); // if we have any entries, copy their numbers to the clipboard if (nr != -1) { // retrieve timestamp of selected node String ts = TreeUtil .getNodeTimestamp((DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent()); // retrieve modifications of that entry, if any modifications were made clipModifiedEntryContent = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts); // delete selected node deleteNode(); // and copy the entrynumber to the clipboard clipEntries = new int[] { nr }; // store value, so we know the clipboard does not contain bullets clipBullet = false; } } // update toolbars updateToolbarAndMenu(); } /** * Retrieves the entry-number of the selected entry and copies it to the * internal clipboard. */ @Action(enabledProperty = "nodeSelected") public void copyNode() { if (isBulletSelected()) { // store value, so we know the clipboard does contain bullets clipBullet = true; // copy bullet's name into variable DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); clipBulletName = node.toString(); // tell the desktop-data-class that the selected bullet has to be stored // for later use desktopObj.copyBulletToClip(TreeUtil.getNodeTimestamp(node)); } else { // retrieve selected entry. int nr = getSelectedEntryNumber(); // if we have any entries, copy their numbers to the clipboard if (nr != -1) { // retrieve timestamp of selected node String ts = TreeUtil .getNodeTimestamp((DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent()); // retrieve modifications of that entry, if any modifications were made clipModifiedEntryContent = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts); // and copy the entrynumber to the clipboard clipEntries = new int[] { nr }; // store value, so we know the clipboard does not contain bullets clipBullet = false; } } // update toolbars updateToolbarAndMenu(); } /** * This method pastes a node or bullet from the clipboard into the treeview. Relevant variables * for this operation are:<br><ul> * <li>{@code clipBullet}, a boolean variable that indicates whether the internal clipboard is filled * with entries (nodes) or a bullet</li> * <li>{@code clipBulletName}, a string variable containing the name of the cut or copied bullet-point, * in case we have a bullet-point in the clkipboard. this is need for checking if the bullet exists * at that point where it should be inserted (pasted)</li> * <li> {@code clipEntries}, an integer-array containing the entry-numbers of the entries that should * be pasted in case we have entries (nodes) in the clipboard.</li> * </ul> */ @Action(enabledProperty = "clipFilled") public void pasteNode() { // when we have a bullet-point in the clipboard, go on here... if (clipBullet) { // cut off id from clipbullet-timestamp-id int pos = clipBulletName.indexOf("["); // only continue if we found something... if (pos != -1) { // compare child's text with newBullet-text clipBulletName = clipBulletName.substring(0, pos).trim(); } // first check, whether the bullet-point already exists as child where the user // wants to pase the bullet if (!checkIfBulletExists(clipBulletName)) { // get selection DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); // if not, insert it. desktopObj.pasteBulletFromClip(getSelectedNodeTimestamp(), node.isRoot()); // update treeview updateTreeView(); } } // ...else if we have entries in the clipboard, add them now... else if ((clipEntries != null) && (clipEntries.length > 0)) { // check whether we have only one entry and modifications // this indicates a cut/copy and paste, so we use the other add-method // which also add modifications. if (1 == clipEntries.length) addEntries(String.valueOf(clipEntries[0]), clipModifiedEntryContent); else addEntries(clipEntries); } } /** * This method moves the selected node in the jTree upwards, if possible. */ @Action(enabledProperty = "moveUpEnabled") public void moveNodeUp() { moveNode(Constants.MOVE_UP); } /** * This method moves the selected node in the jTree downwards, if possible. */ @Action(enabledProperty = "moveDownEnabled") public void moveNodeDown() { moveNode(Constants.MOVE_DOWN); } /** * This method moves the selected node up- or downwards, if possible, depending * on the parameter {@code movement}. * * @param movement indicates whether the selected node in the jTree should be moved * up- or downwards. use following constants:<br> * - {@code CConstants.MOVE_UP}<br> * - {@code CConstants.MOVE_DOWN} */ private void moveNode(int movement) { // retrieve timestamp from selected node String timestamp = getSelectedNodeTimestamp(); // move element up desktopObj.moveElement(movement, timestamp); // update treeview updateTreeView(); // re-select the previous path selectTreePath(timestamp); // update toolbars updateToolbarAndMenu(); } /** * This method selects the node in the jTree that matches the timestamp-id {@code timestamp}. * * @param timestamp the timestamp of the entry which node should be selected in the jTree. */ private void selectTreePath(String timestamp) { // get the root DefaultMutableTreeNode node = findNodeFromTimestamp( (DefaultMutableTreeNode) jTreeDesktop.getModel().getRoot(), timestamp); // if we have a valid value... if (node != null) { // select node jTreeDesktop.setSelectionPath(new TreePath(node.getPath())); } // and bring focus back to window, if necessary this.toFront(); jTreeDesktop.requestFocusInWindow(); } /** * This method recursevily traverses the jTree, starting at the position {@code node}, and * tries to find an entry with the timestamp-id {@code timestamp}. * * @param node the starting-point in the jTree, where this method searches through all (child-)elements. * @param timestamp the timestamp-id of the requested entry * @return the found node that matches the entry with the timestamp-id {@code timestamp}, or {@code null} * if nothing was found. */ private DefaultMutableTreeNode findNodeFromTimestamp(DefaultMutableTreeNode node, String timestamp) { // check whether the element "e" passed as parameter already has a timestamp-attribute that // matches the parameter "t". if so, return that element. String ts = TreeUtil.getNodeTimestamp(node); if (ts != null && ts.equals(timestamp)) return node; // now go through all parts of the previously selected path Enumeration children = node.children(); // go through all children while (children.hasMoreElements()) { // get the child node = (DefaultMutableTreeNode) children.nextElement(); // check whether element has a timestamp value at all, and if it matches the parameter "t". ts = TreeUtil.getNodeTimestamp(node); if (ts != null && ts.equals(timestamp)) return node; // when the new element also has children, call this method again, // so we go through the strucuture recursively... if (node.getChildCount() > 0) { // if we have any child-elements, go into method again // to traverse recursevely all elements node = findNodeFromTimestamp(node, timestamp); // retrieve timestamp from returned node. ts = TreeUtil.getNodeTimestamp(node); // if we found a match, leave function and don't iterate any further elements if (ts != null && ts.equals(timestamp)) return node; /* else return null; */ } } // retrieve timestamp from returned node. ts = TreeUtil.getNodeTimestamp(node); // and return either the node if timestamp matches or null if not. if (ts != null && ts.equals(timestamp)) return node; else return null; } /** * This method updates the display, i.e. the whole page (the entries in html-formatting) is * new created and then set to the jEditorPane. This action is only enabled whenever changes * to the desktopstructure have been made, like inserting or renaming bullets, inserting or * removing entries and so on... */ @Action(enabledProperty = "needsUpdate") public void updateView() { updateDisplay(); } /** * Activates or deactivates the fullscreen-mode, thus switching between fullscreen and normal view. */ @Action(enabledProperty = "fullScreenSupp") public void viewFullScreen() { // check whether fullscreen is possible or not... if (graphicdevice.isFullScreenSupported()) { // if we already have a fullscreen window, quit fullscreen if (graphicdevice.getFullScreenWindow() != null) quitFullScreen(); // else show fullscreen window else showFullScreen(); } } /** * This method activates the fullscreen-mode, if it's not already activated yet. To have a * fullscreen-window without decoration, the frame is disposed first, then the decoration * will be removed and the window made visible again. */ private void showFullScreen() { // check whether fullscreen is supported, and if we currently have a fullscreen-window if (graphicdevice.isFullScreenSupported() && null == graphicdevice.getFullScreenWindow()) { // dispose frame, so we can remove the decoration when setting full screen mode mainframe.dispose(); // hide menubar jMenuBarDesktop.setVisible(false); // set frame non-resizable mainframe.setResizable(false); try { // remove decoration mainframe.setUndecorated(true); } catch (IllegalComponentStateException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } // show frame again mainframe.setVisible(true); // set fullscreen mode to this window graphicdevice.setFullScreenWindow(this); } } /** * This method <i>de</i>activates the fullscreen-mode, if it's not already deactivated yet. */ private void quitFullScreen() { // check whether fullscreen is supported, and if we currently have a fullscreen-window if (graphicdevice.isFullScreenSupported() && graphicdevice.getFullScreenWindow() != null) { // disable fullscreen-mode graphicdevice.setFullScreenWindow(null); // hide menubar jMenuBarDesktop.setVisible(true); // make frame resizable again mainframe.setResizable(true); // dispose frame, so we can restore the decoration mainframe.dispose(); try { // set decoration mainframe.setUndecorated(false); } catch (IllegalComponentStateException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } // show frame again mainframe.setVisible(true); } } /** * This method extracts the timestamp-id of the selected node's name. * * @return the timestamp-id of the node's name (userobject) as string, or {@code null} * if an error occured or nothing was found. */ private String getSelectedNodeTimestamp() { DefaultMutableTreeNode selectednode = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent(); return (TreeUtil.getNodeTimestamp(selectednode)); } /** * This actions opens an input-dialog where the user cann add comments to the * currently selected node or bullet-point.<br><br> * These comments are displayed in a grey area, just like it appears in typical * office-word-programs (word, writer, pages...).<br><br> * The comments are added to the xml-file that stores the desktop-data as well as * to a linked list which manages the comments. See {@link #exportEntriesToEditorPane exportEntriesToEditorPane} * for more details on how the display-page is created. */ @Action(enabledProperty = "nodeSelected") public void commentNode() { // get the comment of the selected entry String oldcomment = desktopObj.getComment(getSelectedNodeTimestamp(), lineseparator); // open an input-dialog, setting the selected value as default-value if (null == biggerEditDlg) { // create a new dialog with the bigger edit-field, passing some initial values biggerEditDlg = new CBiggerEditField(this, settingsObj, resourceMap.getString("newCommentTitle"), oldcomment, "", Constants.EDIT_DESKTOP_COMMENT); // center window biggerEditDlg.setLocationRelativeTo(this); } // show window ZettelkastenApp.getApplication().show(biggerEditDlg); // after closing the window, get the new value String newcomment = biggerEditDlg.getNewValue(); // delete the input-dialog biggerEditDlg.dispose(); biggerEditDlg = null; if (newcomment != null) { // and re-convert all new lines to br's. this is necessary for converting // them into <br>'s because the entry is displayed as html-content. simple // new lines without "<br>" command would not be shown as new lines // // but first, we habe to remove all carriage-returns (\r), which are part of the // line-seperator in windows. somehow, the replace-command does *not* work, when // we replace "System.getProperty("line.separator")" with "[br]", but only when // a "\n" is replaced by [br]. So, in case the system's line-separator also contains a // "\r", it is replaced by nothing, to clean the content. if (lineseparator.contains("\r")) newcomment = newcomment.replace("\r", ""); newcomment = newcomment.replace("\n", "[br]"); // set the comment to the selected entry if (desktopObj.setComment(getSelectedNodeTimestamp(), newcomment)) { // update treeview, so the new comment is also associated with the // correct node. we have to do this, because the comments are managed // via a linked list that is created in this method. otherwise the // comment would not appear... updateTreeView(); // display needs to be updated... setNeedsUpdate(true); } else { // in case the new comment could not be set, tell user about it... JOptionPane.showMessageDialog(this, resourceMap.getString("errSetCommentMsg"), resourceMap.getString("errSetCommentTitle"), JOptionPane.PLAIN_MESSAGE); } } // if view option was comments only, change this option if we don't have any comments at all if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions() && !desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS); } /** * @return the background task */ @Action public Task displayTask() { return new createDisplayTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } @SuppressWarnings("LeakingThisInConstructor") private class createDisplayTask extends org.jdesktop.application.Task<Object, Void> { // create a new stringbuilder that will contain the final string, i.e. // the html-page which we set to the jeditorpane StringBuilder sbDisplayTask = new StringBuilder(""); createDisplayTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to createLinksTask fields, here. super(app); cDisplayTask = this; } @Override protected Object doInBackground() { // Your Task's code here. This method runs // on a background thread, so don't reference // the Swing GUI from here. // tell programm that the task is running cDisplayTaskIsRunning = true; // clear content jEditorPaneMain.setText(resourceMap.getString("contentBeingUpdated")); // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel(); // create a new root element from the current desktop name and set it as root DefaultMutableTreeNode root = (DefaultMutableTreeNode) dtm.getRoot(); // check whether the current desktop has any children at all if (root.getChildCount() > 0) { // boolean showComments; // clean stringbuilder for word-count sbWordCountDisplayTask.setLength(0); // create the content for the html-page sbDisplayTask.append("<table "); if (PlatformUtil.isJava7OnMac() || PlatformUtil.isJava7OnWindows()) sbDisplayTask.append("cellspacing=\"0\" "); sbDisplayTask.append("class=\"maintable\">"); // check which display option is chosen switch (settingsObj.getDesktopCommentDisplayOptions()) { case Constants.DESKTOP_WITH_COMMENTS: showComments = desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement()); exportEntriesToEditorPane(root, sbDisplayTask, showComments); break; case Constants.DESKTOP_WITHOUT_COMMENTS: showComments = false; exportEntriesToEditorPane(root, sbDisplayTask, showComments); break; case Constants.DESKTOP_ONLY_COMMENTS: showComments = false; exportCommentsToEditorPane(root, sbDisplayTask); break; default: showComments = desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement()); exportEntriesToEditorPane(root, sbDisplayTask, showComments); break; } // retrieve all authors from desktop // therefor, we first need all entries int[] entries = desktopObj.retrieveDesktopEntries(); LinkedList<String> remainingAuthors = new LinkedList<String>(); // interate entries for (int e : entries) { // get authors String[] aus = dataObj.getAuthors(e); // iterate all authors if (aus != null && aus.length > 0) { for (String au : aus) { // check whether author exists in our array if (!remainingAuthors.contains(au)) { // if not, add it remainingAuthors.add(au); } } } } // extract footnotes. LinkedList<String> footnotes = Tools.extractFootnotesFromContent(sbDisplayTask.toString()); boolean hasAuthors = (footnotes.size() > 0 || remainingAuthors.size() > 0); // check whether we have any footnotes or authors if (hasAuthors) { // first, init the list in html... // create a separator line sbDisplayTask.append("<tr>"); if (showComments) sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>"); sbDisplayTask.append(lineseparator).append("<td><hr></td></tr>").append(lineseparator); // add title "references" sbDisplayTask.append("<tr>"); if (showComments) sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>"); sbDisplayTask.append(lineseparator).append("<td><h1>"); // append a new headline with the bullet's name sbDisplayTask.append(resourceMap.getString("referenceListHeading")); sbDisplayTask.append("</h1></td></tr>").append(lineseparator); // and add another table row for the unordered list... sbDisplayTask.append("<tr>"); if (showComments) sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>"); sbDisplayTask.append(lineseparator).append("<td>").append(lineseparator); } // now we have all footnotes, i.e. the author-index-numbers, in the linked // list. now we can create a reference list if (footnotes.size() > 0) { // iterator for the linked list Iterator<String> i = footnotes.iterator(); while (i.hasNext()) { String au = i.next(); try { int aunr = Integer.parseInt(au); String aus = dataObj.getAuthor(aunr); sbDisplayTask.append("<p class=\"reflist\"><b>[<a name=\"fn_").append(au).append("\">") .append(au).append("</a>]</b> "); sbDisplayTask.append(aus); sbDisplayTask.append("</p>").append(lineseparator); // remove author from remaining list remainingAuthors.remove(aus); } catch (NumberFormatException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } } // check whether we have any remaining authors that did not appear in footnotes if (remainingAuthors.size() > 0) { // sort array java.util.Collections.sort(remainingAuthors); // iterator for the linked list Iterator<String> ri = remainingAuthors.iterator(); while (ri.hasNext()) { String aus = ri.next(); sbDisplayTask.append("<p class=\"reflist\">"); sbDisplayTask.append(aus); sbDisplayTask.append("</p>").append(lineseparator); } } // close tags if (hasAuthors) sbDisplayTask.append("</td></tr>").append(lineseparator); // and close table tags... sbDisplayTask.append("</table>"); // get complete entry-content, i.e. title and content String wordcoutnstring = sbWordCountDisplayTask.toString(); // split complete content at each word String[] words = wordcoutnstring.toLowerCase().replace("", "ae").replace("", "oe") .replace("", "ue").replace("", "ss").split("\\W"); // init wordcounter int wordcount = 0; // iterate all words of the entry for (String word : words) { // remove all non-letter-chars word = word.replace("([^A-Za-z0-9]+)", ""); // trim spaces word = word.trim(); // if we have a "word" with more than one char, count it as word... if (!word.isEmpty() /* && word.length()>1 */) wordcount++; } // set count words to label jLabelWordCount.setText("(" + String.valueOf(wordcount) + " " + resourceMap.getString("WordCount") + ", " + String.valueOf(sbWordCountDisplayTask.length()) + " " + resourceMap.getString("CharCount") + ")"); } return null; } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). // // tell everbody that the display is up to date setNeedsUpdate(false); // store complete page. we need this string for the live-search, // since e.g. German umlauts will be escaped in the jEditorPane, so // we can't retrieve the page's content via jEditorPane.getText(). completePage = sbDisplayTask.toString(); // if we have any content, insert html-header at the beginning... if (sbDisplayTask.length() > 0) sbDisplayTask.insert(0, HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false)); // set the html-page to the editor pane jEditorPaneMain.setText(sbDisplayTask.toString()); // scroll to first entry jEditorPaneMain.setCaretPosition(0); } @Override protected void finished() { super.finished(); cDisplayTaskIsRunning = false; cDisplayTask = null; } } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jPopupMenuDesktop = new javax.swing.JPopupMenu(); popupNewBullet = new javax.swing.JMenuItem(); popupNewEntry = new javax.swing.JMenuItem(); popupNewLuhmann = new javax.swing.JMenuItem(); jSeparator23 = new javax.swing.JPopupMenu.Separator(); popupExportBullet = new javax.swing.JMenuItem(); popupExportBulletToSearch = new javax.swing.JMenuItem(); jSeparator11 = new javax.swing.JSeparator(); popupModifyEntry = new javax.swing.JMenuItem(); popupApplyModificationsEntry = new javax.swing.JMenuItem(); jSeparator25 = new javax.swing.JSeparator(); popupCut = new javax.swing.JMenuItem(); popupCopy = new javax.swing.JMenuItem(); popupPaste = new javax.swing.JMenuItem(); jSeparator12 = new javax.swing.JSeparator(); popupRename = new javax.swing.JMenuItem(); popupComment = new javax.swing.JMenuItem(); jSeparator13 = new javax.swing.JSeparator(); popupDelete = new javax.swing.JMenuItem(); jSeparator14 = new javax.swing.JSeparator(); popupShowEntryInMain = new javax.swing.JMenuItem(); popupRefreshView = new javax.swing.JMenuItem(); jPopupMenuCutCopyPaste = new javax.swing.JPopupMenu(); jMenuItemNotesCut = new javax.swing.JMenuItem(); jMenuItemNotesCopy = new javax.swing.JMenuItem(); jMenuItemNotesPaste = new javax.swing.JMenuItem(); buttonGroupDesktopView = new javax.swing.ButtonGroup(); jToolBarDesktop = new javax.swing.JToolBar(); tb_newbullet = new javax.swing.JButton(); tb_newentry = new javax.swing.JButton(); tb_addluhmann = new javax.swing.JButton(); jSeparator3 = new javax.swing.JToolBar.Separator(); tb_modifyentry = new javax.swing.JButton(); tb_cut = new javax.swing.JButton(); tb_copy = new javax.swing.JButton(); tb_paste = new javax.swing.JButton(); jSeparator4 = new javax.swing.JToolBar.Separator(); tb_moveup = new javax.swing.JButton(); tb_movedown = new javax.swing.JButton(); jSeparator29 = new javax.swing.JToolBar.Separator(); tb_rename = new javax.swing.JButton(); tb_comment = new javax.swing.JButton(); tb_delete = new javax.swing.JButton(); jSeparator7 = new javax.swing.JToolBar.Separator(); tb_refresh = new javax.swing.JButton(); jPanel1 = new javax.swing.JPanel(); jSplitPaneDesktop1 = new javax.swing.JSplitPane(); jPanel3 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); jTreeDesktop = new javax.swing.JTree(); jPanel4 = new javax.swing.JPanel(); jSplitPaneDesktop2 = new javax.swing.JSplitPane(); jPanel5 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); jEditorPaneMain = new javax.swing.JEditorPane(); jPanelLiveSearch = new javax.swing.JPanel(); jTextFieldLiveSearch = new javax.swing.JTextField(); jButtonLivePrev = new javax.swing.JButton(); jButtonLiveNext = new javax.swing.JButton(); jButtonLiveCancel = new javax.swing.JButton(); jPanel6 = new javax.swing.JPanel(); jScrollPane3 = new javax.swing.JScrollPane(); jTextArea1 = new javax.swing.JTextArea(); jScrollPane4 = new javax.swing.JScrollPane(); jTextArea2 = new javax.swing.JTextArea(); jScrollPane5 = new javax.swing.JScrollPane(); jTextArea3 = new javax.swing.JTextArea(); jPanel2 = new javax.swing.JPanel(); jPanel7 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); jComboBoxDesktop = new javax.swing.JComboBox(); statusAnimationLabel = new javax.swing.JLabel(); jButtonShowMultipleOccurencesDlg = new javax.swing.JButton(); jLabelWordCount = new javax.swing.JLabel(); jMenuBarDesktop = new javax.swing.JMenuBar(); desktopMenuFile = new javax.swing.JMenu(); newDesktopMenuItem = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JSeparator(); addBulletMenuItem = new javax.swing.JMenuItem(); insertNewEntryMenuItem = new javax.swing.JMenuItem(); addEntryMenuItem = new javax.swing.JMenuItem(); addLuhmannMenuItem = new javax.swing.JMenuItem(); jSeparator5 = new javax.swing.JSeparator(); exportSubMenu = new javax.swing.JMenu(); exportMenuItem = new javax.swing.JMenuItem(); jSeparator20 = new javax.swing.JSeparator(); exportMultipleMenuItem = new javax.swing.JMenuItem(); jSeparator21 = new javax.swing.JSeparator(); exportDeskToSearch = new javax.swing.JMenuItem(); jSeparator22 = new javax.swing.JSeparator(); exportMissingToSearch = new javax.swing.JMenuItem(); jSeparator28 = new javax.swing.JSeparator(); archiveDesktopMenuItem = new javax.swing.JMenuItem(); importArchivedDesktopMenuItem = new javax.swing.JMenuItem(); jSeparator15 = new javax.swing.JSeparator(); printMenuItem = new javax.swing.JMenuItem(); jSeparator16 = new javax.swing.JPopupMenu.Separator(); closeMenuItem = new javax.swing.JMenuItem(); desktopMenuEdit = new javax.swing.JMenu(); modifyEntryItem = new javax.swing.JMenuItem(); applyModificationsToOriginalMenuItem = new javax.swing.JMenuItem(); applyAllModificationsMenuItem = new javax.swing.JMenuItem(); jSeparator24 = new javax.swing.JSeparator(); cutMenuItem = new javax.swing.JMenuItem(); copyMenuItem = new javax.swing.JMenuItem(); pasteMenuItem = new javax.swing.JMenuItem(); jSeparator19 = new javax.swing.JSeparator(); editEntryMenuItem = new javax.swing.JMenuItem(); jSeparator17 = new javax.swing.JSeparator(); moveUpMenuItem = new javax.swing.JMenuItem(); moveDownMenuItem = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JSeparator(); renameBulletMenuItem = new javax.swing.JMenuItem(); commentMenuItem = new javax.swing.JMenuItem(); jSeparator6 = new javax.swing.JSeparator(); deleteMenuItem = new javax.swing.JMenuItem(); desktopMenuFind = new javax.swing.JMenu(); findMenuLiveSearch = new javax.swing.JMenuItem(); jSeparator18 = new javax.swing.JSeparator(); findMenuLiveNext = new javax.swing.JMenuItem(); findMenuLivePrev = new javax.swing.JMenuItem(); desktopMenuView = new javax.swing.JMenu(); updateViewMenuItem = new javax.swing.JMenuItem(); jSeparator9 = new javax.swing.JSeparator(); jRadioButtonDesktopWithComment = new javax.swing.JRadioButtonMenuItem(); jRadioButtonDesktopWithoutComments = new javax.swing.JRadioButtonMenuItem(); jRadioButtonDesktopOnlyComments = new javax.swing.JRadioButtonMenuItem(); jSeparator8 = new javax.swing.JPopupMenu.Separator(); headingsVisibleMenuItem = new javax.swing.JCheckBoxMenuItem(); entryNumberVisibleMenuItem = new javax.swing.JCheckBoxMenuItem(); jSeparator27 = new javax.swing.JSeparator(); displayItemsMenuItem = new javax.swing.JMenuItem(); jSeparator10 = new javax.swing.JSeparator(); viewFullScreenMenuItem = new javax.swing.JMenuItem(); jSeparator26 = new javax.swing.JPopupMenu.Separator(); showDesktopTreeEntryNumberMenuItem = new javax.swing.JCheckBoxMenuItem(); jPopupMenuDesktop.setName("jPopupMenuDesktop"); // NOI18N javax.swing.ActionMap actionMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(DesktopFrame.class, this); popupNewBullet.setAction(actionMap.get("addBullet")); // NOI18N popupNewBullet.setName("popupNewBullet"); // NOI18N jPopupMenuDesktop.add(popupNewBullet); popupNewEntry.setAction(actionMap.get("addEntry")); // NOI18N popupNewEntry.setName("popupNewEntry"); // NOI18N jPopupMenuDesktop.add(popupNewEntry); popupNewLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N popupNewLuhmann.setName("popupNewLuhmann"); // NOI18N jPopupMenuDesktop.add(popupNewLuhmann); jSeparator23.setName("jSeparator23"); // NOI18N jPopupMenuDesktop.add(jSeparator23); popupExportBullet.setAction(actionMap.get("exportDesktopBullet")); // NOI18N popupExportBullet.setName("popupExportBullet"); // NOI18N jPopupMenuDesktop.add(popupExportBullet); popupExportBulletToSearch.setAction(actionMap.get("exportBulletToSearch")); // NOI18N popupExportBulletToSearch.setName("popupExportBulletToSearch"); // NOI18N jPopupMenuDesktop.add(popupExportBulletToSearch); jSeparator11.setName("jSeparator11"); // NOI18N jPopupMenuDesktop.add(jSeparator11); popupModifyEntry.setAction(actionMap.get("modifiyEntry")); // NOI18N popupModifyEntry.setName("popupModifyEntry"); // NOI18N jPopupMenuDesktop.add(popupModifyEntry); popupApplyModificationsEntry.setAction(actionMap.get("applyModificationsToOriginalEntry")); // NOI18N popupApplyModificationsEntry.setName("popupApplyModificationsEntry"); // NOI18N jPopupMenuDesktop.add(popupApplyModificationsEntry); jSeparator25.setName("jSeparator25"); // NOI18N jPopupMenuDesktop.add(jSeparator25); popupCut.setAction(actionMap.get("cutNode")); // NOI18N popupCut.setName("popupCut"); // NOI18N jPopupMenuDesktop.add(popupCut); popupCopy.setAction(actionMap.get("copyNode")); // NOI18N popupCopy.setName("popupCopy"); // NOI18N jPopupMenuDesktop.add(popupCopy); popupPaste.setAction(actionMap.get("pasteNode")); // NOI18N popupPaste.setName("popupPaste"); // NOI18N jPopupMenuDesktop.add(popupPaste); jSeparator12.setName("jSeparator12"); // NOI18N jPopupMenuDesktop.add(jSeparator12); popupRename.setAction(actionMap.get("renameBullet")); // NOI18N popupRename.setName("popupRename"); // NOI18N jPopupMenuDesktop.add(popupRename); popupComment.setAction(actionMap.get("commentNode")); // NOI18N popupComment.setName("popupComment"); // NOI18N jPopupMenuDesktop.add(popupComment); jSeparator13.setName("jSeparator13"); // NOI18N jPopupMenuDesktop.add(jSeparator13); popupDelete.setAction(actionMap.get("deleteNode")); // NOI18N popupDelete.setName("popupDelete"); // NOI18N jPopupMenuDesktop.add(popupDelete); jSeparator14.setName("jSeparator14"); // NOI18N jPopupMenuDesktop.add(jSeparator14); popupShowEntryInMain.setAction(actionMap.get("displayEntryInMainframe")); // NOI18N popupShowEntryInMain.setName("popupShowEntryInMain"); // NOI18N jPopupMenuDesktop.add(popupShowEntryInMain); popupRefreshView.setAction(actionMap.get("updateView")); // NOI18N popupRefreshView.setName("popupRefreshView"); // NOI18N jPopupMenuDesktop.add(popupRefreshView); jPopupMenuCutCopyPaste.setName("jPopupMenuCutCopyPaste"); // NOI18N jMenuItemNotesCut.setAction(actionMap.get("cut")); jMenuItemNotesCut.setName("jMenuItemNotesCut"); // NOI18N jPopupMenuCutCopyPaste.add(jMenuItemNotesCut); jMenuItemNotesCopy.setAction(actionMap.get("copy")); jMenuItemNotesCopy.setName("jMenuItemNotesCopy"); // NOI18N jPopupMenuCutCopyPaste.add(jMenuItemNotesCopy); jMenuItemNotesPaste.setAction(actionMap.get("paste")); jMenuItemNotesPaste.setName("jMenuItemNotesPaste"); // NOI18N jPopupMenuCutCopyPaste.add(jMenuItemNotesPaste); setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(DesktopFrame.class); setTitle(resourceMap.getString("FormDesktop.title")); // NOI18N setMinimumSize(new java.awt.Dimension(350, 250)); setName("FormDesktop"); // NOI18N jToolBarDesktop.setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 0, resourceMap.getColor("jToolBarDesktop.border.matteColor"))); // NOI18N jToolBarDesktop.setFloatable(false); jToolBarDesktop.setRollover(true); jToolBarDesktop.setMinimumSize(new java.awt.Dimension(200, 10)); jToolBarDesktop.setName("jToolBarDesktop"); // NOI18N tb_newbullet.setAction(actionMap.get("addBullet")); // NOI18N tb_newbullet.setText(resourceMap.getString("tb_newbullet.text")); // NOI18N tb_newbullet.setBorderPainted(false); tb_newbullet.setFocusPainted(false); tb_newbullet.setFocusable(false); tb_newbullet.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_newbullet.setName("tb_newbullet"); // NOI18N tb_newbullet.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_newbullet); tb_newentry.setAction(actionMap.get("addEntry")); // NOI18N tb_newentry.setText(resourceMap.getString("tb_newentry.text")); // NOI18N tb_newentry.setBorderPainted(false); tb_newentry.setFocusPainted(false); tb_newentry.setFocusable(false); tb_newentry.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_newentry.setName("tb_newentry"); // NOI18N tb_newentry.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_newentry); tb_addluhmann.setAction(actionMap.get("addLuhmann")); // NOI18N tb_addluhmann.setText(resourceMap.getString("tb_addluhmann.text")); // NOI18N tb_addluhmann.setBorderPainted(false); tb_addluhmann.setFocusPainted(false); tb_addluhmann.setFocusable(false); tb_addluhmann.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_addluhmann.setName("tb_addluhmann"); // NOI18N tb_addluhmann.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_addluhmann); jSeparator3.setName("jSeparator3"); // NOI18N jToolBarDesktop.add(jSeparator3); tb_modifyentry.setAction(actionMap.get("modifiyEntry")); // NOI18N tb_modifyentry.setText(resourceMap.getString("tb_modifyentry.text")); // NOI18N tb_modifyentry.setBorderPainted(false); tb_modifyentry.setFocusPainted(false); tb_modifyentry.setFocusable(false); tb_modifyentry.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_modifyentry.setName("tb_modifyentry"); // NOI18N tb_modifyentry.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_modifyentry); tb_cut.setAction(actionMap.get("cutNode")); // NOI18N tb_cut.setText(resourceMap.getString("tb_cut.text")); // NOI18N tb_cut.setBorderPainted(false); tb_cut.setFocusPainted(false); tb_cut.setFocusable(false); tb_cut.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_cut.setName("tb_cut"); // NOI18N tb_cut.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_cut); tb_copy.setAction(actionMap.get("copyNode")); // NOI18N tb_copy.setText(resourceMap.getString("tb_copy.text")); // NOI18N tb_copy.setBorderPainted(false); tb_copy.setFocusPainted(false); tb_copy.setFocusable(false); tb_copy.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_copy.setName("tb_copy"); // NOI18N tb_copy.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_copy); tb_paste.setAction(actionMap.get("pasteNode")); // NOI18N tb_paste.setText(resourceMap.getString("tb_paste.text")); // NOI18N tb_paste.setBorderPainted(false); tb_paste.setFocusPainted(false); tb_paste.setFocusable(false); tb_paste.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_paste.setName("tb_paste"); // NOI18N tb_paste.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_paste); jSeparator4.setName("jSeparator4"); // NOI18N jToolBarDesktop.add(jSeparator4); tb_moveup.setAction(actionMap.get("moveNodeUp")); // NOI18N tb_moveup.setText(resourceMap.getString("tb_moveup.text")); // NOI18N tb_moveup.setBorderPainted(false); tb_moveup.setFocusPainted(false); tb_moveup.setFocusable(false); tb_moveup.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_moveup.setName("tb_moveup"); // NOI18N tb_moveup.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_moveup); tb_movedown.setAction(actionMap.get("moveNodeDown")); // NOI18N tb_movedown.setText(resourceMap.getString("tb_movedown.text")); // NOI18N tb_movedown.setBorderPainted(false); tb_movedown.setFocusPainted(false); tb_movedown.setFocusable(false); tb_movedown.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_movedown.setName("tb_movedown"); // NOI18N tb_movedown.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_movedown); jSeparator29.setName("jSeparator29"); // NOI18N jToolBarDesktop.add(jSeparator29); tb_rename.setAction(actionMap.get("renameBullet")); // NOI18N tb_rename.setText(resourceMap.getString("tb_rename.text")); // NOI18N tb_rename.setBorderPainted(false); tb_rename.setFocusPainted(false); tb_rename.setFocusable(false); tb_rename.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_rename.setName("tb_rename"); // NOI18N tb_rename.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_rename); tb_comment.setAction(actionMap.get("commentNode")); // NOI18N tb_comment.setText(resourceMap.getString("tb_comment.text")); // NOI18N tb_comment.setBorderPainted(false); tb_comment.setFocusPainted(false); tb_comment.setFocusable(false); tb_comment.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_comment.setName("tb_comment"); // NOI18N tb_comment.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_comment); tb_delete.setAction(actionMap.get("deleteNode")); // NOI18N tb_delete.setText(resourceMap.getString("tb_delete.text")); // NOI18N tb_delete.setBorderPainted(false); tb_delete.setFocusPainted(false); tb_delete.setFocusable(false); tb_delete.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_delete.setName("tb_delete"); // NOI18N tb_delete.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_delete); jSeparator7.setName("jSeparator7"); // NOI18N jToolBarDesktop.add(jSeparator7); tb_refresh.setAction(actionMap.get("updateView")); // NOI18N tb_refresh.setText(resourceMap.getString("tb_refresh.text")); // NOI18N tb_refresh.setBorderPainted(false); tb_refresh.setFocusPainted(false); tb_refresh.setFocusable(false); tb_refresh.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_refresh.setName("tb_refresh"); // NOI18N tb_refresh.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jToolBarDesktop.add(tb_refresh); jPanel1.setMinimumSize(new java.awt.Dimension(200, 150)); jPanel1.setName("jPanel1"); // NOI18N jPanel1.setLayout(new java.awt.BorderLayout()); jSplitPaneDesktop1.setBorder(null); jSplitPaneDesktop1.setDividerLocation(200); jSplitPaneDesktop1.setMinimumSize(new java.awt.Dimension(200, 200)); jSplitPaneDesktop1.setName("jSplitPaneDesktop1"); // NOI18N jSplitPaneDesktop1.setOneTouchExpandable(true); jPanel3.setMinimumSize(new java.awt.Dimension(50, 100)); jPanel3.setName("jPanel3"); // NOI18N jScrollPane1.setBorder(null); jScrollPane1.setMinimumSize(new java.awt.Dimension(20, 20)); jScrollPane1.setName("jScrollPane1"); // NOI18N jTreeDesktop.setName("jTreeDesktop"); // NOI18N jScrollPane1.setViewportView(jTreeDesktop); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout .setHorizontalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)); jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 451, Short.MAX_VALUE)); jSplitPaneDesktop1.setLeftComponent(jPanel3); jPanel4.setMinimumSize(new java.awt.Dimension(150, 100)); jPanel4.setName("jPanel4"); // NOI18N jSplitPaneDesktop2.setBorder(null); jSplitPaneDesktop2.setDividerLocation(400); jSplitPaneDesktop2.setMinimumSize(new java.awt.Dimension(150, 150)); jSplitPaneDesktop2.setName("jSplitPaneDesktop2"); // NOI18N jSplitPaneDesktop2.setOneTouchExpandable(true); jPanel5.setMinimumSize(new java.awt.Dimension(50, 50)); jPanel5.setName("jPanel5"); // NOI18N jScrollPane2.setBorder(null); jScrollPane2.setMinimumSize(new java.awt.Dimension(20, 20)); jScrollPane2.setName("jScrollPane2"); // NOI18N jEditorPaneMain.setEditable(false); jEditorPaneMain.setContentType(resourceMap.getString("jEditorPaneMain.contentType")); // NOI18N jEditorPaneMain.setText(resourceMap.getString("jEditorPaneMain.text")); // NOI18N jEditorPaneMain.setName("jEditorPaneMain"); // NOI18N jScrollPane2.setViewportView(jEditorPaneMain); jPanelLiveSearch.setMinimumSize(new java.awt.Dimension(20, 20)); jPanelLiveSearch.setName("jPanelLiveSearch"); // NOI18N jTextFieldLiveSearch.setToolTipText(resourceMap.getString("jTextFieldLiveSearch.toolTipText")); // NOI18N jTextFieldLiveSearch.setName("jTextFieldLiveSearch"); // NOI18N jButtonLivePrev.setAction(actionMap.get("findLivePrev")); // NOI18N jButtonLivePrev.setText(resourceMap.getString("jButtonLivePrev.text")); // NOI18N jButtonLivePrev.setBorderPainted(false); jButtonLivePrev.setContentAreaFilled(false); jButtonLivePrev.setFocusPainted(false); jButtonLivePrev.setName("jButtonLivePrev"); // NOI18N jButtonLiveNext.setAction(actionMap.get("findLiveNext")); // NOI18N jButtonLiveNext.setText(resourceMap.getString("jButtonLiveNext.text")); // NOI18N jButtonLiveNext.setBorderPainted(false); jButtonLiveNext.setContentAreaFilled(false); jButtonLiveNext.setFocusPainted(false); jButtonLiveNext.setName("jButtonLiveNext"); // NOI18N jButtonLiveCancel.setAction(actionMap.get("findCancel")); // NOI18N jButtonLiveCancel.setBorderPainted(false); jButtonLiveCancel.setContentAreaFilled(false); jButtonLiveCancel.setFocusPainted(false); jButtonLiveCancel.setName("jButtonLiveCancel"); // NOI18N javax.swing.GroupLayout jPanelLiveSearchLayout = new javax.swing.GroupLayout(jPanelLiveSearch); jPanelLiveSearch.setLayout(jPanelLiveSearchLayout); jPanelLiveSearchLayout.setHorizontalGroup( jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelLiveSearchLayout.createSequentialGroup().addContainerGap() .addComponent(jTextFieldLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, 318, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonLivePrev, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonLiveNext, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonLiveCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap())); jPanelLiveSearchLayout.setVerticalGroup( jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelLiveSearchLayout.createSequentialGroup().addGap(3, 3, 3) .addGroup(jPanelLiveSearchLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jButtonLiveCancel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButtonLiveNext, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButtonLivePrev, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jTextFieldLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(3, 3, 3))); javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); jPanel5.setLayout(jPanel5Layout); jPanel5Layout .setHorizontalGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanelLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)); jPanel5Layout.setVerticalGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup() .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE) .addGap(0, 0, 0).addComponent(jPanelLiveSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); jSplitPaneDesktop2.setLeftComponent(jPanel5); jPanel6.setMinimumSize(new java.awt.Dimension(50, 50)); jPanel6.setName("jPanel6"); // NOI18N jScrollPane3.setBorder(null); jScrollPane3.setName("jScrollPane3"); // NOI18N jTextArea1.setLineWrap(true); jTextArea1.setWrapStyleWord(true); jTextArea1.setBorder( javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea1.border.title"))); // NOI18N jTextArea1.setName("jTextArea1"); // NOI18N jScrollPane3.setViewportView(jTextArea1); jScrollPane4.setBorder(null); jScrollPane4.setName("jScrollPane4"); // NOI18N jTextArea2.setLineWrap(true); jTextArea2.setToolTipText(resourceMap.getString("jTextArea2.toolTipText")); // NOI18N jTextArea2.setWrapStyleWord(true); jTextArea2.setBorder( javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea2.border.title"))); // NOI18N jTextArea2.setName("jTextArea2"); // NOI18N jScrollPane4.setViewportView(jTextArea2); jScrollPane5.setBorder(null); jScrollPane5.setName("jScrollPane5"); // NOI18N jTextArea3.setLineWrap(true); jTextArea3.setWrapStyleWord(true); jTextArea3.setBorder( javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea3.border.title"))); // NOI18N jTextArea3.setName("jTextArea3"); // NOI18N jScrollPane5.setViewportView(jTextArea3); javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); jPanel6.setLayout(jPanel6Layout); jPanel6Layout .setHorizontalGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jScrollPane3).addComponent(jScrollPane5)); jPanel6Layout.setVerticalGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel6Layout.createSequentialGroup() .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 153, Short.MAX_VALUE))); jSplitPaneDesktop2.setRightComponent(jPanel6); javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout .setHorizontalGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPaneDesktop2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); jPanel4Layout.setVerticalGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPaneDesktop2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); jSplitPaneDesktop1.setRightComponent(jPanel4); jPanel1.add(jSplitPaneDesktop1, java.awt.BorderLayout.CENTER); jPanel2.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 0, 0, 0, resourceMap.getColor("jPanel2.border.matteColor"))); // NOI18N jPanel2.setMinimumSize(new java.awt.Dimension(200, 30)); jPanel2.setName("jPanel2"); // NOI18N jPanel7.setMinimumSize(new java.awt.Dimension(200, 20)); jPanel7.setName("jPanel7"); // NOI18N jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N jLabel1.setName("jLabel1"); // NOI18N jComboBoxDesktop.setModel( new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); jComboBoxDesktop.setName("jComboBoxDesktop"); // NOI18N statusAnimationLabel.setIcon(resourceMap.getIcon("statusAnimationLabel.icon")); // NOI18N statusAnimationLabel.setText(resourceMap.getString("statusAnimationLabel.text")); // NOI18N statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N jButtonShowMultipleOccurencesDlg.setAction(actionMap.get("openMultipleOccurencesMessageDlg")); // NOI18N jButtonShowMultipleOccurencesDlg.setIcon(resourceMap.getIcon("jButtonShowMultipleOccurencesDlg.icon")); // NOI18N jButtonShowMultipleOccurencesDlg .setToolTipText(resourceMap.getString("jButtonShowMultipleOccurencesDlg.toolTipText")); // NOI18N jButtonShowMultipleOccurencesDlg.setBorderPainted(false); jButtonShowMultipleOccurencesDlg.setContentAreaFilled(false); jButtonShowMultipleOccurencesDlg.setFocusPainted(false); jButtonShowMultipleOccurencesDlg.setIconTextGap(0); jButtonShowMultipleOccurencesDlg.setName("jButtonShowMultipleOccurencesDlg"); // NOI18N jLabelWordCount.setToolTipText(resourceMap.getString("jLabelWordCount.toolTipText")); // NOI18N jLabelWordCount.setName("jLabelWordCount"); // NOI18N javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); jPanel7.setLayout(jPanel7Layout); jPanel7Layout.setHorizontalGroup(jPanel7Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup().addContainerGap().addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jComboBoxDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabelWordCount).addGap(18, 18, 18) .addComponent(jButtonShowMultipleOccurencesDlg) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(statusAnimationLabel).addContainerGap())); jPanel7Layout.setVerticalGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup().addGap(3, 3, 3).addGroup(jPanel7Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(jPanel7Layout.createSequentialGroup().addGap(1, 1, 1).addGroup(jPanel7Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(jComboBoxDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabelWordCount))) .addComponent(jButtonShowMultipleOccurencesDlg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(statusAnimationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(3, 3, 3))); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout .setHorizontalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup().addContainerGap() .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap())); jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup().addGap(0, 0, 0) .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0))); jMenuBarDesktop.setMinimumSize(new java.awt.Dimension(100, 1)); jMenuBarDesktop.setName("jMenuBarDesktop"); // NOI18N desktopMenuFile.setText(resourceMap.getString("desktopMenuFile.text")); // NOI18N desktopMenuFile.setName("desktopMenuFile"); // NOI18N newDesktopMenuItem.setAction(actionMap.get("newDesktop")); // NOI18N newDesktopMenuItem.setName("newDesktopMenuItem"); // NOI18N desktopMenuFile.add(newDesktopMenuItem); jSeparator1.setName("jSeparator1"); // NOI18N desktopMenuFile.add(jSeparator1); addBulletMenuItem.setAction(actionMap.get("addBullet")); // NOI18N addBulletMenuItem.setName("addBulletMenuItem"); // NOI18N desktopMenuFile.add(addBulletMenuItem); insertNewEntryMenuItem.setAction(actionMap.get("insertEntry")); // NOI18N insertNewEntryMenuItem.setName("insertNewEntryMenuItem"); // NOI18N desktopMenuFile.add(insertNewEntryMenuItem); addEntryMenuItem.setAction(actionMap.get("addEntry")); // NOI18N addEntryMenuItem.setName("addEntryMenuItem"); // NOI18N desktopMenuFile.add(addEntryMenuItem); addLuhmannMenuItem.setAction(actionMap.get("addLuhmann")); // NOI18N addLuhmannMenuItem.setName("addLuhmannMenuItem"); // NOI18N desktopMenuFile.add(addLuhmannMenuItem); jSeparator5.setName("jSeparator5"); // NOI18N desktopMenuFile.add(jSeparator5); exportSubMenu.setText(resourceMap.getString("exportSubMenu.text")); // NOI18N exportSubMenu.setName("exportSubMenu"); // NOI18N exportMenuItem.setAction(actionMap.get("exportDesktop")); // NOI18N exportMenuItem.setName("exportMenuItem"); // NOI18N exportSubMenu.add(exportMenuItem); jSeparator20.setName("jSeparator20"); // NOI18N exportSubMenu.add(jSeparator20); exportMultipleMenuItem.setAction(actionMap.get("exportMultipleDesktop")); // NOI18N exportMultipleMenuItem.setName("exportMultipleMenuItem"); // NOI18N exportSubMenu.add(exportMultipleMenuItem); jSeparator21.setName("jSeparator21"); // NOI18N exportSubMenu.add(jSeparator21); exportDeskToSearch.setAction(actionMap.get("exportToSearch")); // NOI18N exportDeskToSearch.setName("exportDeskToSearch"); // NOI18N exportSubMenu.add(exportDeskToSearch); jSeparator22.setName("jSeparator22"); // NOI18N exportSubMenu.add(jSeparator22); exportMissingToSearch.setAction(actionMap.get("exportMissingToSearch")); // NOI18N exportMissingToSearch.setName("exportMissingToSearch"); // NOI18N exportSubMenu.add(exportMissingToSearch); desktopMenuFile.add(exportSubMenu); jSeparator28.setName("jSeparator28"); // NOI18N desktopMenuFile.add(jSeparator28); archiveDesktopMenuItem.setAction(actionMap.get("archiveDesktop")); // NOI18N archiveDesktopMenuItem.setName("archiveDesktopMenuItem"); // NOI18N desktopMenuFile.add(archiveDesktopMenuItem); importArchivedDesktopMenuItem.setAction(actionMap.get("importArchivedDesktop")); // NOI18N importArchivedDesktopMenuItem.setName("importArchivedDesktopMenuItem"); // NOI18N desktopMenuFile.add(importArchivedDesktopMenuItem); jSeparator15.setName("jSeparator15"); // NOI18N desktopMenuFile.add(jSeparator15); printMenuItem.setAction(actionMap.get("printContent")); // NOI18N printMenuItem.setName("printMenuItem"); // NOI18N desktopMenuFile.add(printMenuItem); jSeparator16.setName("jSeparator16"); // NOI18N desktopMenuFile.add(jSeparator16); closeMenuItem.setAction(actionMap.get("closeWindow")); // NOI18N closeMenuItem.setName("closeMenuItem"); // NOI18N desktopMenuFile.add(closeMenuItem); jMenuBarDesktop.add(desktopMenuFile); desktopMenuEdit.setText(resourceMap.getString("desktopMenuEdit.text")); // NOI18N desktopMenuEdit.setName("desktopMenuEdit"); // NOI18N modifyEntryItem.setAction(actionMap.get("modifiyEntry")); // NOI18N modifyEntryItem.setName("modifyEntryItem"); // NOI18N desktopMenuEdit.add(modifyEntryItem); applyModificationsToOriginalMenuItem.setAction(actionMap.get("applyModificationsToOriginalEntry")); // NOI18N applyModificationsToOriginalMenuItem.setName("applyModificationsToOriginalMenuItem"); // NOI18N desktopMenuEdit.add(applyModificationsToOriginalMenuItem); applyAllModificationsMenuItem.setAction(actionMap.get("applyAllModificationsToOriginalEntries")); // NOI18N applyAllModificationsMenuItem.setName("applyAllModificationsMenuItem"); // NOI18N desktopMenuEdit.add(applyAllModificationsMenuItem); jSeparator24.setName("jSeparator24"); // NOI18N desktopMenuEdit.add(jSeparator24); cutMenuItem.setAction(actionMap.get("cutNode")); // NOI18N cutMenuItem.setName("cutMenuItem"); // NOI18N desktopMenuEdit.add(cutMenuItem); copyMenuItem.setAction(actionMap.get("copyNode")); // NOI18N copyMenuItem.setName("copyMenuItem"); // NOI18N desktopMenuEdit.add(copyMenuItem); pasteMenuItem.setAction(actionMap.get("pasteNode")); // NOI18N pasteMenuItem.setName("pasteMenuItem"); // NOI18N desktopMenuEdit.add(pasteMenuItem); jSeparator19.setName("jSeparator19"); // NOI18N desktopMenuEdit.add(jSeparator19); editEntryMenuItem.setAction(actionMap.get("editEntry")); // NOI18N editEntryMenuItem.setName("editEntryMenuItem"); // NOI18N desktopMenuEdit.add(editEntryMenuItem); jSeparator17.setName("jSeparator17"); // NOI18N desktopMenuEdit.add(jSeparator17); moveUpMenuItem.setAction(actionMap.get("moveNodeUp")); // NOI18N moveUpMenuItem.setName("moveUpMenuItem"); // NOI18N desktopMenuEdit.add(moveUpMenuItem); moveDownMenuItem.setAction(actionMap.get("moveNodeDown")); // NOI18N moveDownMenuItem.setName("moveDownMenuItem"); // NOI18N desktopMenuEdit.add(moveDownMenuItem); jSeparator2.setName("jSeparator2"); // NOI18N desktopMenuEdit.add(jSeparator2); renameBulletMenuItem.setAction(actionMap.get("renameBullet")); // NOI18N renameBulletMenuItem.setName("renameBulletMenuItem"); // NOI18N desktopMenuEdit.add(renameBulletMenuItem); commentMenuItem.setAction(actionMap.get("commentNode")); // NOI18N commentMenuItem.setName("commentMenuItem"); // NOI18N desktopMenuEdit.add(commentMenuItem); jSeparator6.setName("jSeparator6"); // NOI18N desktopMenuEdit.add(jSeparator6); deleteMenuItem.setAction(actionMap.get("deleteNode")); // NOI18N deleteMenuItem.setName("deleteMenuItem"); // NOI18N desktopMenuEdit.add(deleteMenuItem); jMenuBarDesktop.add(desktopMenuEdit); desktopMenuFind.setText(resourceMap.getString("desktopMenuFind.text")); // NOI18N desktopMenuFind.setName("desktopMenuFind"); // NOI18N findMenuLiveSearch.setAction(actionMap.get("findLive")); // NOI18N findMenuLiveSearch.setName("findMenuLiveSearch"); // NOI18N desktopMenuFind.add(findMenuLiveSearch); jSeparator18.setName("jSeparator18"); // NOI18N desktopMenuFind.add(jSeparator18); findMenuLiveNext.setAction(actionMap.get("findLiveNext")); // NOI18N findMenuLiveNext.setName("findMenuLiveNext"); // NOI18N desktopMenuFind.add(findMenuLiveNext); findMenuLivePrev.setAction(actionMap.get("findLivePrev")); // NOI18N findMenuLivePrev.setName("findMenuLivePrev"); // NOI18N desktopMenuFind.add(findMenuLivePrev); jMenuBarDesktop.add(desktopMenuFind); desktopMenuView.setText(resourceMap.getString("desktopMenuView.text")); // NOI18N desktopMenuView.setName("desktopMenuView"); // NOI18N updateViewMenuItem.setAction(actionMap.get("updateView")); // NOI18N updateViewMenuItem.setName("updateViewMenuItem"); // NOI18N desktopMenuView.add(updateViewMenuItem); jSeparator9.setName("jSeparator9"); // NOI18N desktopMenuView.add(jSeparator9); jRadioButtonDesktopWithComment.setAction(actionMap.get("menuDisplayDesktopWithComments")); // NOI18N buttonGroupDesktopView.add(jRadioButtonDesktopWithComment); jRadioButtonDesktopWithComment.setName("jRadioButtonDesktopWithComment"); // NOI18N desktopMenuView.add(jRadioButtonDesktopWithComment); jRadioButtonDesktopWithoutComments.setAction(actionMap.get("menuDisplayDesktopWithoutComments")); // NOI18N buttonGroupDesktopView.add(jRadioButtonDesktopWithoutComments); jRadioButtonDesktopWithoutComments.setName("jRadioButtonDesktopWithoutComments"); // NOI18N desktopMenuView.add(jRadioButtonDesktopWithoutComments); jRadioButtonDesktopOnlyComments.setAction(actionMap.get("menuDisplayDesktopOnlyComments")); // NOI18N buttonGroupDesktopView.add(jRadioButtonDesktopOnlyComments); jRadioButtonDesktopOnlyComments.setName("jRadioButtonDesktopOnlyComments"); // NOI18N desktopMenuView.add(jRadioButtonDesktopOnlyComments); jSeparator8.setName("jSeparator8"); // NOI18N desktopMenuView.add(jSeparator8); headingsVisibleMenuItem.setAction(actionMap.get("switchHeadingsVisibility")); // NOI18N headingsVisibleMenuItem.setSelected(true); headingsVisibleMenuItem.setName("headingsVisibleMenuItem"); // NOI18N desktopMenuView.add(headingsVisibleMenuItem); entryNumberVisibleMenuItem.setAction(actionMap.get("switchEntryNumberVisibility")); // NOI18N entryNumberVisibleMenuItem.setSelected(true); entryNumberVisibleMenuItem.setName("entryNumberVisibleMenuItem"); // NOI18N desktopMenuView.add(entryNumberVisibleMenuItem); jSeparator27.setName("jSeparator27"); // NOI18N desktopMenuView.add(jSeparator27); displayItemsMenuItem.setAction(actionMap.get("displayItems")); // NOI18N displayItemsMenuItem.setName("displayItemsMenuItem"); // NOI18N desktopMenuView.add(displayItemsMenuItem); jSeparator10.setName("jSeparator10"); // NOI18N desktopMenuView.add(jSeparator10); viewFullScreenMenuItem.setAction(actionMap.get("viewFullScreen")); // NOI18N viewFullScreenMenuItem.setName("viewFullScreenMenuItem"); // NOI18N desktopMenuView.add(viewFullScreenMenuItem); jSeparator26.setName("jSeparator26"); // NOI18N desktopMenuView.add(jSeparator26); showDesktopTreeEntryNumberMenuItem.setAction(actionMap.get("showDesktopEntryNumber")); // NOI18N showDesktopTreeEntryNumberMenuItem.setSelected(true); showDesktopTreeEntryNumberMenuItem.setName("showDesktopTreeEntryNumberMenuItem"); // NOI18N desktopMenuView.add(showDesktopTreeEntryNumberMenuItem); jMenuBarDesktop.add(desktopMenuView); setJMenuBar(jMenuBarDesktop); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jToolBarDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jToolBarDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGap(0, 0, 0).addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); pack(); }// </editor-fold>//GEN-END:initComponents /** * This variable indicates whether the selection in the jtree is a bullet-point * or not, and no root-element */ private boolean bulletSelected = false; /** * This variable indicates whether the selection in the jtree is a bullet-point * or not, and no root-element * @return Returns true, if a bullet-point (except root element) is selected in the tree view. */ public boolean isBulletSelected() { return bulletSelected; } /** * This variable indicates whether the selection in the jtree is a bullet-point * or not, and no root-element. Triggers a property change to (de-)activate menu items. * @param b true, if a bullet point is selected. */ public void setBulletSelected(boolean b) { boolean old = isBulletSelected(); this.bulletSelected = b; firePropertyChange("bulletSelected", old, isBulletSelected()); } /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element */ private boolean entryNodeSelected = false; /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element * @return */ public boolean isEntryNodeSelected() { return entryNodeSelected; } /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element. * Triggers a property change to (de-)activate menu items. * @param b */ public void setEntryNodeSelected(boolean b) { boolean old = isEntryNodeSelected(); this.entryNodeSelected = b; firePropertyChange("entryNodeSelected", old, isEntryNodeSelected()); } /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element */ private boolean nodeSelected = false; /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element * @return */ public boolean isNodeSelected() { return nodeSelected; } /** * This variable indicates whether the selection in the jtree is a * child-note (entry), i.e. no bullet and no root-element * @param b */ public void setNodeSelected(boolean b) { boolean old = isNodeSelected(); this.nodeSelected = b; firePropertyChange("nodeSelected", old, isNodeSelected()); } /** * This variable indicates whether the we have any selection in the jtree, * i.e. a bullet, a child-node or a root-element */ private boolean anyNodeSelected = false; /** * This variable indicates whether the we have any selection in the jtree, * i.e. a bullet, a child-node or a root-element * @return */ public boolean isAnyNodeSelected() { return anyNodeSelected; } /** * This variable indicates whether the we have any selection in the jtree, * i.e. a bullet, a child-node or a root-element * @param b */ public void setAnyNodeSelected(boolean b) { boolean old = isAnyNodeSelected(); this.anyNodeSelected = b; firePropertyChange("anyNodeSelected", old, isAnyNodeSelected()); } /** * This variable indicates whether the selected entry was modified or not. */ private boolean modifiedEntryNode = false; /** * This variable indicates whether the selected entry was modified or not. * @return */ public boolean isModifiedEntryNode() { return modifiedEntryNode; } /** * This variable indicates whether the selected entry was modified or not. * @param b */ public void setModifiedEntryNode(boolean b) { boolean old = isModifiedEntryNode(); this.modifiedEntryNode = b; firePropertyChange("modifiedEntryNode", old, isModifiedEntryNode()); } /** * This variable indicates whether the selected node is a child-note (entry) * and also has luhmann-numbers (followers) */ private boolean luhmannNodeSelected = false; /** * This variable indicates whether the selected node is a child-note (entry) * and also has luhmann-numbers (followers) * @return */ public boolean isLuhmannNodeSelected() { return luhmannNodeSelected; } /** * This variable indicates whether the selected node is a child-note (entry) * and also has luhmann-numbers (followers) * @param b */ public void setLuhmannNodeSelected(boolean b) { boolean old = isLuhmannNodeSelected(); this.luhmannNodeSelected = b; firePropertyChange("luhmannNodeSelected", old, isLuhmannNodeSelected()); } /** * This variable indicates whether we have any entries or bullets in the clipboard */ private boolean clipFilled = false; /** * This variable indicates whether we have any entries or bullets in the clipboard * @return */ public boolean isClipFilled() { return clipFilled; } /** * This variable indicates whether we have any entries or bullets in the clipboard * @param b */ public void setClipFilled(boolean b) { boolean old = isClipFilled(); this.clipFilled = b; firePropertyChange("clipFilled", old, isClipFilled()); } /** * This variable indicates whether we have a non-updated display of the entries, where * the changes were made when this window was invisible. this for instance happen when initiating * the desktop after program-startup: the desktop is initiated, but the jEditorPane should not be * filled with entries at that moment, because it might take too long for the startup. instead, * we will do the update of the isplay later, when the window becomes visible. */ private boolean needsUpdate = false; /** * This variable indicates whether we have a non-updated display of the entries, where * the changes were made when this window was invisible. this for instance happen when initiating * the desktop after program-startup: the desktop is initiated, but the jEditorPane should not be * filled with entries at that moment, because it might take too long for the startup. instead, * we will do the update of the isplay later, when the window becomes visible. * @return */ public boolean isNeedsUpdate() { return needsUpdate; } /** * This variable indicates whether we have a non-updated display of the entries, where * the changes were made when this window was invisible. this for instance happen when initiating * the desktop after program-startup: the desktop is initiated, but the jEditorPane should not be * filled with entries at that moment, because it might take too long for the startup. instead, * we will do the update of the isplay later, when the window becomes visible. * @param b */ public void setNeedsUpdate(boolean b) { boolean old = isNeedsUpdate(); this.needsUpdate = b; firePropertyChange("needsUpdate", old, isNeedsUpdate()); } /** * This variable indicates whether or not the fullscreen mode is supportet * on the current system. if not, disable related icons... */ private boolean fullScreenSupp = false; /** * This variable indicates whether or not the fullscreen mode is supportet * on the current system. if not, disable related icons... * @return */ public boolean isFullScreenSupp() { return fullScreenSupp; } /** * This variable indicates whether or not the fullscreen mode is supportet * on the current system. if not, disable related icons... * @param b */ public void setFullScreenSupp(boolean b) { boolean old = isFullScreenSupp(); this.fullScreenSupp = b; firePropertyChange("fullScreenSupp", old, isFullScreenSupp()); } /** * This variable indicates whether the user has selected a node at the very first position. * depending on this, the action to move an entry/bullet up is en-/disabled. */ private boolean moveUpEnabled = false; /** * This variable indicates whether the user has selected a node at the very first position. * depending on this, the action to move an entry/bullet up is en-/disabled. * @return */ public boolean isMoveUpEnabled() { return moveUpEnabled; } /** * This variable indicates whether the user has selected a node at the very first position. * depending on this, the action to move an entry/bullet up is en-/disabled. * @param b */ public void setMoveUpEnabled(boolean b) { boolean old = isMoveUpEnabled(); this.moveUpEnabled = b; firePropertyChange("moveUpEnabled", old, isMoveUpEnabled()); } /** * This variable indicates whether the user has selected a node at the very last position. * depending on this, the action to move an entry/bullet down is en-/disabled. */ private boolean moveDownEnabled = false; /** * This variable indicates whether the user has selected a node at the very last position. * depending on this, the action to move an entry/bullet down is en-/disabled. * @return */ public boolean isMoveDownEnabled() { return moveDownEnabled; } /** * This variable indicates whether the user has selected a node at the very last position. * depending on this, the action to move an entry/bullet down is en-/disabled. * @param b */ public void setMoveDownEnabled(boolean b) { boolean old = isMoveDownEnabled(); this.moveDownEnabled = b; firePropertyChange("moveDownEnabled", old, isMoveDownEnabled()); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem addBulletMenuItem; private javax.swing.JMenuItem addEntryMenuItem; private javax.swing.JMenuItem addLuhmannMenuItem; private javax.swing.JMenuItem applyAllModificationsMenuItem; private javax.swing.JMenuItem applyModificationsToOriginalMenuItem; private javax.swing.JMenuItem archiveDesktopMenuItem; private javax.swing.ButtonGroup buttonGroupDesktopView; private javax.swing.JMenuItem closeMenuItem; private javax.swing.JMenuItem commentMenuItem; private javax.swing.JMenuItem copyMenuItem; private javax.swing.JMenuItem cutMenuItem; private javax.swing.JMenuItem deleteMenuItem; private javax.swing.JMenu desktopMenuEdit; private javax.swing.JMenu desktopMenuFile; private javax.swing.JMenu desktopMenuFind; private javax.swing.JMenu desktopMenuView; private javax.swing.JMenuItem displayItemsMenuItem; private javax.swing.JMenuItem editEntryMenuItem; private javax.swing.JCheckBoxMenuItem entryNumberVisibleMenuItem; private javax.swing.JMenuItem exportDeskToSearch; private javax.swing.JMenuItem exportMenuItem; private javax.swing.JMenuItem exportMissingToSearch; private javax.swing.JMenuItem exportMultipleMenuItem; private javax.swing.JMenu exportSubMenu; private javax.swing.JMenuItem findMenuLiveNext; private javax.swing.JMenuItem findMenuLivePrev; private javax.swing.JMenuItem findMenuLiveSearch; private javax.swing.JCheckBoxMenuItem headingsVisibleMenuItem; private javax.swing.JMenuItem importArchivedDesktopMenuItem; private javax.swing.JMenuItem insertNewEntryMenuItem; private javax.swing.JButton jButtonLiveCancel; private javax.swing.JButton jButtonLiveNext; private javax.swing.JButton jButtonLivePrev; private javax.swing.JButton jButtonShowMultipleOccurencesDlg; private javax.swing.JComboBox jComboBoxDesktop; private javax.swing.JEditorPane jEditorPaneMain; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabelWordCount; private javax.swing.JMenuBar jMenuBarDesktop; private javax.swing.JMenuItem jMenuItemNotesCopy; private javax.swing.JMenuItem jMenuItemNotesCut; private javax.swing.JMenuItem jMenuItemNotesPaste; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JPanel jPanel5; private javax.swing.JPanel jPanel6; private javax.swing.JPanel jPanel7; private javax.swing.JPanel jPanelLiveSearch; private javax.swing.JPopupMenu jPopupMenuCutCopyPaste; private javax.swing.JPopupMenu jPopupMenuDesktop; private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopOnlyComments; private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopWithComment; private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopWithoutComments; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JScrollPane jScrollPane5; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator10; private javax.swing.JSeparator jSeparator11; private javax.swing.JSeparator jSeparator12; private javax.swing.JSeparator jSeparator13; private javax.swing.JSeparator jSeparator14; private javax.swing.JSeparator jSeparator15; private javax.swing.JPopupMenu.Separator jSeparator16; private javax.swing.JSeparator jSeparator17; private javax.swing.JSeparator jSeparator18; private javax.swing.JSeparator jSeparator19; private javax.swing.JSeparator jSeparator2; private javax.swing.JSeparator jSeparator20; private javax.swing.JSeparator jSeparator21; private javax.swing.JSeparator jSeparator22; private javax.swing.JPopupMenu.Separator jSeparator23; private javax.swing.JSeparator jSeparator24; private javax.swing.JSeparator jSeparator25; private javax.swing.JPopupMenu.Separator jSeparator26; private javax.swing.JSeparator jSeparator27; private javax.swing.JSeparator jSeparator28; private javax.swing.JToolBar.Separator jSeparator29; private javax.swing.JToolBar.Separator jSeparator3; private javax.swing.JToolBar.Separator jSeparator4; private javax.swing.JSeparator jSeparator5; private javax.swing.JSeparator jSeparator6; private javax.swing.JToolBar.Separator jSeparator7; private javax.swing.JPopupMenu.Separator jSeparator8; private javax.swing.JSeparator jSeparator9; private javax.swing.JSplitPane jSplitPaneDesktop1; private javax.swing.JSplitPane jSplitPaneDesktop2; private javax.swing.JTextArea jTextArea1; private javax.swing.JTextArea jTextArea2; private javax.swing.JTextArea jTextArea3; private javax.swing.JTextField jTextFieldLiveSearch; private javax.swing.JToolBar jToolBarDesktop; private javax.swing.JTree jTreeDesktop; private javax.swing.JMenuItem modifyEntryItem; private javax.swing.JMenuItem moveDownMenuItem; private javax.swing.JMenuItem moveUpMenuItem; private javax.swing.JMenuItem newDesktopMenuItem; private javax.swing.JMenuItem pasteMenuItem; private javax.swing.JMenuItem popupApplyModificationsEntry; private javax.swing.JMenuItem popupComment; private javax.swing.JMenuItem popupCopy; private javax.swing.JMenuItem popupCut; private javax.swing.JMenuItem popupDelete; private javax.swing.JMenuItem popupExportBullet; private javax.swing.JMenuItem popupExportBulletToSearch; private javax.swing.JMenuItem popupModifyEntry; private javax.swing.JMenuItem popupNewBullet; private javax.swing.JMenuItem popupNewEntry; private javax.swing.JMenuItem popupNewLuhmann; private javax.swing.JMenuItem popupPaste; private javax.swing.JMenuItem popupRefreshView; private javax.swing.JMenuItem popupRename; private javax.swing.JMenuItem popupShowEntryInMain; private javax.swing.JMenuItem printMenuItem; private javax.swing.JMenuItem renameBulletMenuItem; private javax.swing.JCheckBoxMenuItem showDesktopTreeEntryNumberMenuItem; private javax.swing.JLabel statusAnimationLabel; private javax.swing.JButton tb_addluhmann; private javax.swing.JButton tb_comment; private javax.swing.JButton tb_copy; private javax.swing.JButton tb_cut; private javax.swing.JButton tb_delete; private javax.swing.JButton tb_modifyentry; private javax.swing.JButton tb_movedown; private javax.swing.JButton tb_moveup; private javax.swing.JButton tb_newbullet; private javax.swing.JButton tb_newentry; private javax.swing.JButton tb_paste; private javax.swing.JButton tb_refresh; private javax.swing.JButton tb_rename; private javax.swing.JMenuItem updateViewMenuItem; private javax.swing.JMenuItem viewFullScreenMenuItem; // End of variables declaration//GEN-END:variables private TaskProgressDialog taskDlg; private CModifyDesktopEntry modifyEntryDlg; private CDesktopExport exportWindow; private CBiggerEditField biggerEditDlg; private CDesktopDisplayItems desktopDisplayItemsDlg; private CDesktopMultipleExport desktopMultipleExportDlg; private CShowMultipleDesktopOccurences multipleOccurencesDlg; }