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/>. */ /** * Swing Application Framework PlugIn fr NetBeans 7.x * http://plugins.netbeans.org/plugin/43836/swing-application-framework-support */ package de.danielluedecke.zettelkasten; import com.explodingpixels.macwidgets.BottomBar; 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.TableUtils; import com.explodingpixels.widgets.WindowUtils; import de.danielluedecke.zettelkasten.database.AcceleratorKeys; import de.danielluedecke.zettelkasten.database.AutoKorrektur; import de.danielluedecke.zettelkasten.database.BibTex; import de.danielluedecke.zettelkasten.database.Bookmarks; import de.danielluedecke.zettelkasten.database.Daten; import de.danielluedecke.zettelkasten.database.DesktopData; import de.danielluedecke.zettelkasten.database.SearchRequests; import de.danielluedecke.zettelkasten.database.Settings; import de.danielluedecke.zettelkasten.database.StenoData; import de.danielluedecke.zettelkasten.database.Synonyms; import de.danielluedecke.zettelkasten.database.TasksData; import de.danielluedecke.zettelkasten.mac.MacSourceList; import de.danielluedecke.zettelkasten.mac.MacSourceTree; import de.danielluedecke.zettelkasten.tasks.FindDoubleEntriesTask; import de.danielluedecke.zettelkasten.tasks.TaskProgressDialog; import de.danielluedecke.zettelkasten.tasks.export.ExportTools; import de.danielluedecke.zettelkasten.util.ColorUtil; import de.danielluedecke.zettelkasten.util.classes.Comparer; import de.danielluedecke.zettelkasten.util.Constants; import de.danielluedecke.zettelkasten.util.classes.DateComparer; import de.danielluedecke.zettelkasten.util.classes.EntryStringTransferHandler; import de.danielluedecke.zettelkasten.util.HtmlUbbUtil; import de.danielluedecke.zettelkasten.util.classes.InitStatusbarForTasks; import de.danielluedecke.zettelkasten.util.Tools; import de.danielluedecke.zettelkasten.util.FileOperationsUtil; import de.danielluedecke.zettelkasten.util.PlatformUtil; import de.danielluedecke.zettelkasten.util.TreeUtil; import de.danielluedecke.zettelkasten.util.ZettelkastenViewUtil; import de.danielluedecke.zettelkasten.util.classes.TreeUserObject; import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Desktop; import java.awt.FileDialog; import java.awt.Font; import java.awt.Image; import java.awt.SystemTray; import java.awt.Toolkit; import java.awt.TrayIcon; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; 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.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.Date; import java.util.EventObject; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Timer; import java.util.TimerTask; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.SimpleFormatter; import java.util.logging.StreamHandler; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.MatteBorder; import javax.swing.event.HyperlinkEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; 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.FrameView; import org.jdesktop.application.SingleFrameApplication; 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.output.Format; import org.jdom2.output.XMLOutputter; /* * To-Do-Sammlung * */ // TODO beim majorbackup optional auch attachments/img? /** * The application's main frame. */ public class ZettelkastenView extends FrameView implements WindowListener, DropTargetListener { // <editor-fold defaultstate="collapsed" desc="Variablendeklaration"> /** * initiate the data class. this class stores and manages the main * data for this program. */ private final Daten data; /** * */ private final TasksData taskinfo; /** * initiate the search request class. this class stores and manages all * searches and searchresults for the loaded datafile. */ private final SearchRequests searchrequests = new SearchRequests(this); /** * initiate the bookmarks class. this class stores and manages the * bookmarks of entrys. */ private final Bookmarks bookmarks; /** * A reference to the bibtex-class. */ private final BibTex bibtex; /** * initiate the desktop class. this class stores and manages the * desktop data. */ private final DesktopData desktop = new DesktopData(this); /** * Initiate the settings-class. this class first of all loads some user settings * and e.g. the filepath of the currently used datafile, so it can be automatically opened */ private final Settings settings; /** * Initiate the synonyms-class. */ private final Synonyms synonyms; /** * Initiate the steno-class. */ private final StenoData steno; /** * Initiate the acceleratorkeys-class. */ private final AcceleratorKeys acceleratorKeys; /** * A reference to the auto-correction class */ private final AutoKorrektur autoKorrekt; /** * create a variable for a list model. this list model is used for * the JList-component which displays the keywords of the current * entry. */ private final DefaultListModel keywordListModel = new DefaultListModel(); /** * create a variable for a list model. this list model is used for * the JList-component which displays the found entries, which have relations * between certain keywords. see "showCluster()" for more details. */ private final List<String> clusterList = new ArrayList<String>(); /** * create a variable for a list model. this list model is used for * the JList-component which displays the is-follower-numbers. */ private final List<String> isFollowerList = new ArrayList<String>(); /** * This variable stores the table data of the keyword-list when this list is filtered. * All changes to a fitered table-list are also applied to this linked list. When * the table-list is being refreshed, we don't need to run the time-consuming task; instead * we simply iterate this list and set the values to the table */ private LinkedList<Object[]> linkedkeywordlist; /** * This variable stores the table data of the author-list when this list is filtered. * All changes to a fitered table-list are also applied to this linked list. When * the table-list is being refreshed, we don't need to run the time-consuming task; instead * we simply iterate this list and set the values to the table */ private LinkedList<Object[]> linkedauthorlist; /** * This variable stores the table data of the title-list when this list is filtered. * All changes to a fitered table-list are also applied to this linked list. When * the table-list is being refreshed, we don't need to run the time-consuming task; instead * we simply iterate this list and set the values to the table */ private LinkedList<Object[]> linkedtitlelist; /** * This variable stores the table data of the attachment-list. */ private LinkedList<Object[]> linkedattachmentlist; /** * This variable stores the state of the tree data of the cluster-list, * whether it is filtered (true) or not (false). we don't need to store the * initial elements, since we simply can iterate all keywords to restore that list */ private boolean linkedclusterlist; /** * This string builder contains all follower-(trailing)-numbers of an entry, prepared * for exporting these entries. */ private LinkedList<Integer> luhmannnumbersforexport; /** * This variable indicates whether the tabbed pane with the jTableLinks needs updates or not. * When selecting an entry, it is displayed, while the links in the table still belong/refer * to the activated entry. when re-activating the entry, the jTableLinks usually would be updated * (due to the {@link #updateDisplay() updateDisplay()} method). but this is not necessary, * when the list is already uptodate. see {@link #showRelatedKeywords() showRelatedKeywords()} for * and {@link #showLinks() showLinks()} for further details. */ private boolean needsLinkUpdate = true; /** * This variable indicates whether the data file is currently being saved. This * should prevent the automatic backup from starting while the data file is * saved. */ private boolean isSaving = false; /** * Indicates whether a system tray icon could be successfully installed or not. */ private boolean trayIconInstalled = false; /** * */ boolean isLiveSearchActive = false; /** * */ private boolean isbackupnecessary = false; /** * */ private boolean errorIconIsVisible = false; /** * */ boolean editEntryFromDesktop = false; /** * */ boolean editEntryFromSearchWindow = false; /** * */ private String updateURI = Constants.UPDATE_URI; /** * This string contains an added keyword that was added to the jTableKeywords, so the * new added value can be selected immediatley after adding in to the table. */ private String newAddedKeyword = null; /** * This string contains an added author that was added to the jTableAuthors, so the * new added value can be selected immediatley after adding in to the table. */ private String newAddedAuthor = null; /** * */ private String lastClusterRelationKeywords = ""; /** * This variable stores the treepath when a node was dragged&dropped within the jtreeluhmann */ private DefaultMutableTreeNode movedNodeToRemove = null; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_LINKS = 0; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_LUHMANN = 1; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_KEYWORDS = 2; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_AUTHORS = 3; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_TITLES = 4; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_CLUSTER = 5; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_BOOKMARKS = 6; /** * Constant for the selected tab of the tab pane. Since the order of the tabs * might change in the future, we declare constant here, so we just have to make * changes here instead of searching through the source code */ private final int TAB_ATTACHMENTS = 7; /** * indicates the currently selected tab, which will become the previously selected * tab when the tabbedpane state changed. */ private int previousSelectedTab = -1; /** * This variables stores the currently displayed zettel. the currently <i>displayed</i> * Zettel may differ from the currently <i>active</i> Zettel, if we e.g. select an entry * by single-clicking it from a jTable, but do not activate it by double-clicking it. */ public int displayedZettel = -1; /** * Indicates whether the thread "createLinksTask" is running or not... */ private boolean createLinksIsRunning = false; /** * Indicates whether the thread "createLinksFilterTask" is running or not... */ private boolean createFilterLinksIsRunning = false; /** * Indicates whether the thread "createLuhmannTask" is running or not... */ private boolean createClusterIsRunning = false; /** * Indicates whether the thread "createAutoBackupTask" is running or not... */ private boolean createAutoBackupIsRunning = false; /** * Since the window for editing new entries is a modeless frame, we need to have an indicator * which tells us whether the an entry is currently being edited or not. if yes, don't * open another window. */ private boolean isEditModeActive = false; /** * Indicated whether a table's content is changed, e.g. filtered. if so, we have to tell this * the selection listener which - otherwise - would be called several times... */ private boolean tableUpdateActive = false; /** * */ private Timer memoryDisplayTimer = null; /** * */ private Timer flashErrorIconTimer = null; /** * */ private int memoryLogCounter = 0; /** * */ private Timer makeAutoBackupTimer; /** * */ private TrayIcon trayIcon; private SystemTray tray = null; /** * */ public ByteArrayOutputStream baos_log = new ByteArrayOutputStream(1048576); /** * */ private createLinksTask cLinksTask; /** * String array that contain highlight terms. this is used when creating the html-entry in * the update display method. the {@link #findLive() live-search}-feature uses this to highlight * the terms, or e.g. highlighting the keywords in the text needs this array. */ static DataFlavor urlFlavor; static { try { urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL"); } catch (ClassNotFoundException cnfe) { Constants.zknlogger.log(Level.WARNING, "Could not create URL Data Flavor!"); } } /** * 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); // </editor-fold> /** * * @param app * @param st * @param ak * @param ac * @param sy * @param stn * @param td */ @SuppressWarnings("LeakingThisInConstructor") public ZettelkastenView(SingleFrameApplication app, Settings st, AcceleratorKeys ak, AutoKorrektur ac, Synonyms sy, StenoData stn, TasksData td) { super(app); taskinfo = td; // store reference to settings-class settings = st; // store reference to acceleratorKeys-class acceleratorKeys = ak; // store reference to auto-correction autoKorrekt = ac; // store reference to synonyms synonyms = sy; // store reference to steno data steno = stn; bookmarks = new Bookmarks(this, settings); bibtex = new BibTex(this, settings); // init all those classes that rely on parameters and could not be initialised // befor the constructor is called... data = new Daten(this, settings, synonyms, bibtex); // init stream-logger, so we have the logging both to a file and a byte-array StreamHandler sHandler = new StreamHandler(baos_log, new SimpleFormatter()); Constants.zknlogger.addHandler(sHandler); // tell logger to log everthing Constants.zknlogger.setLevel(Level.ALL); // init file-logger FileHandler fh; try { // set up a new file handler, using the settings-directory as log-file-directory fh = new FileHandler(FileOperationsUtil.getZettelkastenHomeDir() + "zknerror%g.log", // file limit of 100 kb 102400, // five log files 3, // and no appending... false); // add filehandler to our global logger Constants.zknlogger.addHandler(fh); // and use a simple formatting, so the log-file will be readable fh.setFormatter(new SimpleFormatter()); } catch (IOException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } catch (SecurityException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } // befor components are drawn, set the default look and feel for this application setDefaultLookAndFeel(); // setup the local for the default actions cut/copy/paste Tools.initLocaleForDefaultActions(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(ZettelkastenView.class, this)); // init all swing components initComponents(); // set application icon getFrame().setIconImage(Constants.zknicon.getImage()); // // Here we have some bug-fixes, which might occur due to os-bugs or NetBeans bugs... // initBorders(settings); // initially, hide the tree-view from keywords-tab // the user can switch between the hierarchic treeview of keywords // or the simple frequencies in a table. by default, the table-view is activated // since this is a new feature, so most people would use table-view in the beginning jScrollPane17.setVisible(false); jTreeKeywords.setVisible(false); // hide special menus. these will only be visible according to their // related displayed tab removeTabMenus(); // init the recent documents setRecentDocuments(); // attach bibtex-file // retrieve currently attached file File currentlyattachedfile = bibtex.getCurrentlyAttachedFile(); // retrieve bibtex-filepath File bibtexfilepath = bibtex.getFilePath(); // only attach bibtex file, if we have a specified filepath if (bibtexfilepath != null && bibtexfilepath.exists()) { // if we have no currently attached bibtex-file, or the currently attached bibtex-file // differs from the new selected file of the user, open the bibtex-file now if ((null == currentlyattachedfile) || (!currentlyattachedfile.toString().equals(bibtexfilepath.toString()))) { // open selected file, using the character encoding of the related reference-manager (i.e. // the programme that has exported the bib-tex-file). if (bibtex.openAttachedFile(Constants.BIBTEX_ENCODINGS[settings.getLastUsedBibtexFormat()], true)) { // tell about success Constants.zknlogger.log(Level.INFO, "BibTex-File was successfully attached."); } else { // tell about fail Constants.zknlogger.log(Level.INFO, "BibTex-File could not be found nor attached."); } } } else { // tell about fail Constants.zknlogger.log(Level.INFO, "No BibTex-File specified yet."); } // tick checbox-menuitem showHighlightKeywords.setSelected(settings.getHighlightKeywords()); // tick checkbox whether keyword-synonyms should also be displayed in the // jtableKeywords or not... jCheckBoxShowSynonyms.setSelected(settings.getShowSynonymsInTable()); // set background color jEditorPaneEntry.setBackground(new Color(Integer.parseInt(settings.getMainBackgroundColor(), 16))); // init action-, key- and mouse-listeners for all components. we do this after selecting // the two checkboxes above, to avoid triggering unnecessary actions. // furthermore, we init the selection listeners for the tables and lists here initListeners(); // init the searchbox for the toolbar createToolbarSearchbox(); // if we have mac osx aqua-look, apply leopard style if (settings.isMacAqua()) { setupMacOSXLeopardStyle(); } if (settings.isSeaGlass()) { setupSeaGlassStyle(); } // hide panels for live-search and is-follower-numbers jPanelLiveSearch.setVisible(false); // since we have a splitpane in this tab, we don't need auto-hiding anymore /* jPanelManLinks.setVisible(false); */ // setup the jtree-component initTrees(); // setup a table sorter and visible grids for the JTables initTables(); // init transferhandler for drag&drop operations initDragDropTransferHandler(); // init the default fontsizes for tables, lists and treeviews initDefaultFontSize(); // initialise the keystrokes for certain components initActionMaps(); // init accelerator table initAcceleratorTable(); // init the icons of the toolbar, whether they are small, medium or large initToolbarIcons(true); // when we have a mac, we need an extra quit-hanlder... if (PlatformUtil.isMacOS()) { setupMacOSXApplicationListener(); } // add an exit-listener, which offers saving etc. on // exit, when we have unaved changes to the data file getApplication().addExitListener(new ConfirmExit()); // add window-listener. somehow I lost the behaviour that clicking on the frame's // upper right cross on Windows OS, quits the application. Instead, it just makes // the frame disapear, but does not quit, so it looks like the application was quit // but asking for changes took place. So, we simply add a windows-listener additionally ZettelkastenView.super.getFrame().addWindowListener(this); ZettelkastenView.super.getFrame().setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // init the progress bar and status icon for // the swingworker background thread // creates a new class object. This variable is not used, it just associates task monitors to // the background tasks. furthermore, by doing this, this class object also animates the // busy icon and the progress bar of this frame. // // init the progressbar and animated icon for background tasks InitStatusbarForTasks isb = new InitStatusbarForTasks(statusAnimationLabel, null, null); // if the file exists, load it... if (!loadDocument()) { initVariables(); updateDisplay(); } // check for updates, if set if (settings.getAutoUpdate()) { Task cfuT = checkForUpdate(); // 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(cfuT); tM.setForegroundTask(cfuT); } // init autobackup-timer makeAutoBackupTimer = new Timer(); // this timer should start after 5 minutes and update every 5 minutes makeAutoBackupTimer.schedule(new AutoBackupTimer(), Constants.autobackupUpdateStart, Constants.autobackupUpdateInterval); } private void initBorders(Settings settingsObj) { /* * Constructor for Matte Border * public MatteBorder(int top, int left, int bottom, int right, Color matteColor) */ jScrollPane4.setBorder(null); jScrollPane3.setBorder(null); jScrollPane9.setBorder(null); jPanelLiveSearch .setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane5.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane6.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane7.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane8.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane10.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane11.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane13.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane14.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane16.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); if (settingsObj.getUseMacBackgroundColor() || settingsObj.isMacAqua()) { jListEntryKeywords.setBackground((settingsObj.isMacAqua()) ? ColorUtil.colorJTreeBackground : ColorUtil.colorJTreeLighterBackground); jListEntryKeywords.setForeground(ColorUtil.colorJTreeDarkText); } if (settingsObj.isSeaGlass()) { jScrollPane1 .setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, ColorUtil.getBorderGray(settingsObj))); jScrollPane2 .setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane3 .setBorder(BorderFactory.createMatteBorder(0, 1, 0, 1, ColorUtil.getBorderGray(settingsObj))); jScrollPane4 .setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane5 .setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane9 .setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane10 .setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane11 .setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane14 .setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); jScrollPane15 .setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj))); jTabbedPaneMain .setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, ColorUtil.getBorderGray(settingsObj))); jListEntryKeywords.setBorder(WidgetFactory .getTitledBorder(getResourceMap().getString("jListEntryKeywords.border.title"), settings)); jEditorPaneBookmarkComment.setBorder(WidgetFactory.getTitledBorder( getResourceMap().getString("jEditorPaneBookmarkComment.border.title"), settings)); } if (settingsObj.isMacAqua()) { WidgetFactory.updateSplitPane(jSplitPane1); WidgetFactory.updateSplitPane(jSplitPane2); WidgetFactory.updateSplitPane(jSplitPane3); WidgetFactory.updateSplitPane(jSplitPaneMain1); WidgetFactory.updateSplitPane(jSplitPaneMain2); WidgetFactory.updateSplitPane(jSplitPaneLinks); WidgetFactory.updateSplitPane(jSplitPaneAuthors); jListEntryKeywords.setBorder( WidgetFactory.getTitledBorder(getResourceMap().getString("jListEntryKeywords.border.title"), ColorUtil.colorJTreeText, settings)); jEditorPaneBookmarkComment.setBorder(WidgetFactory.getTitledBorder( getResourceMap().getString("jEditorPaneBookmarkComment.border.title"), settings)); } } /** * This method inits several listeners for our components. we do this manually instead of * letting the GUI-Builder create the event-methods, because this gives a better overview * and avoids having too many (event-)methods.<br><br> * Furthermore, selection listeners for the tables, trees and lists are initiated. Whenever a user makes * a selection in the components on the tabbed pane, we want to react to that, either by showing * the related entry or displaying other stuff. */ private void initListeners() { // <editor-fold defaultstate="collapsed" desc="Here all relevant listeners are initiated."> // // here we start with action listeners // // this actionn for the checkbox toggles the setting whether the synonyms // should be included in the keywordlist of the jtablekeywords or not jCheckBoxShowSynonyms.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { // change setting settings.setShowSynonymsInTable(jCheckBoxShowSynonyms.isSelected()); // tell that keywordlist is no longer up to date data.setKeywordlistUpToDate(false); // refresh keyword list showKeywords(); } }); // this settings toggles the setting whether the cluster-list in the jTreeCluster // should show *all* keywords or only those that are related to the current entry. // "related" means, that we retrieve the current entry's keywords and search through // all entries and retrieve those entries' keywords as well, if these entries' // keywords contain at least one keyword of the current entry's keywords. jCheckBoxCluster.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { // tell that clusterlist is no longer up to date data.setClusterlistUpToDate(false); // refresh cluster list showCluster(); } }); // clear combobox jComboBoxAuthorType.removeAllItems(); // add items to the combobox jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeAll")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeArticle")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeBook")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeBookArticle")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeChapter")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypePhD")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeThesis")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeUnpublished")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeConference")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeTechreport")); jComboBoxAuthorType.addItem(getResourceMap().getString("entryTypeNoBibKey")); // set rowcount jComboBoxAuthorType.setMaximumRowCount(jComboBoxAuthorType.getItemCount()); // select the last active look and feel jComboBoxAuthorType.setSelectedIndex(0); // init actionlistener jComboBoxAuthorType.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { // authorlist needs update data.setAuthorlistUpToDate(false); // show authors showAuthors(); } }); // // Now come the mouse-listeners // // here we set up a popup-trigger for the jListEntryKeywords and how this component // should react on mouse-clicks. a single click filters the jTableLinks, a double-click // starts a keyword-search jListEntryKeywords.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuKeywordList.isVisible()) { jPopupMenuKeywordList.show(jListEntryKeywords, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuKeywordList.isVisible()) { jPopupMenuKeywordList.show(jListEntryKeywords, 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) { return; } // on single click... if (1 == evt.getClickCount() && displayedZettel == data.getCurrentZettelPos()) { // filter links filterLinks(); highlightSegs(); } // or search keyword on double click else if (2 == evt.getClickCount()) { searchKeywordsFromListLogAnd(); } } }); jEditorPaneEntry.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuMain.isVisible()) { jPopupMenuMain.show(jEditorPaneEntry, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuMain.isVisible()) { jPopupMenuMain.show(jEditorPaneEntry, evt.getPoint().x, evt.getPoint().y); } } }); jTableLinks.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLinks.isVisible()) { jPopupMenuLinks.show(jTableLinks, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLinks.isVisible()) { jPopupMenuLinks.show(jTableLinks, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show cluster relations... if (2 == evt.getClickCount()) { showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableLinks, 0)); } } }); jTableManLinks.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLinks.isVisible()) { jPopupMenuLinks.show(jTableManLinks, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLinks.isVisible()) { jPopupMenuLinks.show(jTableManLinks, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show entry if (2 == evt.getClickCount()) { showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableManLinks, 0)); } } }); jTableKeywords.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuKeywords.isVisible()) { jPopupMenuKeywords.show(jTableKeywords, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuKeywords.isVisible()) { jPopupMenuKeywords.show(jTableKeywords, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show entry if (2 == evt.getClickCount()) { searchLogOr(); } } }); jTableAuthors.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuAuthors.isVisible()) { jPopupMenuAuthors.show(jTableAuthors, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuAuthors.isVisible()) { jPopupMenuAuthors.show(jTableAuthors, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show entry if (2 == evt.getClickCount()) { searchLogOr(); } } }); jTableTitles.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuTitles.isVisible()) { jPopupMenuTitles.show(jTableTitles, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuTitles.isVisible()) { jPopupMenuTitles.show(jTableTitles, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show entry if (2 == evt.getClickCount()) { showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableTitles, 0)); } } }); jTableBookmarks.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuBookmarks.isVisible()) { jPopupMenuBookmarks.show(jTableBookmarks, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuBookmarks.isVisible()) { jPopupMenuBookmarks.show(jTableBookmarks, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) { return; } // on double-click, show entry if (2 == evt.getClickCount()) { showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableBookmarks, 0)); } } }); jTableAttachments.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuAttachments.isVisible()) { jPopupMenuAttachments.show(jTableAttachments, evt.getPoint().x, evt.getPoint().y); } } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuAttachments.isVisible()) { jPopupMenuAttachments.show(jTableAttachments, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) return; // on double-click, open attachment if (2 == evt.getClickCount()) openAttachment(); } }); jTreeLuhmann.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mousePressed(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLuhmann.isVisible()) jPopupMenuLuhmann.show(jTreeLuhmann, evt.getPoint().x, evt.getPoint().y); } @Override public void mouseReleased(java.awt.event.MouseEvent evt) { // check whether the popup-trigger-mouse-key was pressed if (evt.isPopupTrigger() && !jPopupMenuLuhmann.isVisible()) jPopupMenuLuhmann.show(jTreeLuhmann, 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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) return; // on single-click, show entry if (2 == evt.getClickCount()) showEntry(retrieveEntryNrFromLuhmann()); } }); jTreeCluster.addMouseListener(new java.awt.event.MouseAdapter() { @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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) return; // on single-click, show cluster relations... if (1 == evt.getClickCount()) showClusterRelations(); } }); jLabelMemory.addMouseListener(new java.awt.event.MouseAdapter() { @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, don't count it. if (evt.getButton() != MouseEvent.BUTTON1) return; // when the memory label is clicked, call the garbage collector. if (1 == evt.getClickCount()) System.gc(); } }); // // here we start with key-listeners // jListEntryKeywords.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { // if a navigation-key (arrows, page-down/up, home etc.) is pressed, // we assume a new item-selection, so behave like on a mouse-click and // filter the links if (Tools.isNavigationKey(evt.getKeyCode())) { // filter links filterLinks(); highlightSegs(); } } }); 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()) { findLiveCancel(); } else { // get the text from the live-search-textbox String livetext = jTextFieldLiveSearch.getText(); // only highlight text, when we have more that two chars if (livetext.length() > 1) { // create array with search term // set highlightterms HtmlUbbUtil.setHighlighTerms(new String[] { livetext }, HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH, false); // update display and highlight text. updateDisplayParts(displayedZettel); } } } }); jTreeCluster.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { // if a navigation-key (arrows, page-down/up, home etc.) is pressed, // we assume a new item-selection, so behave like on a mouse-click and // show the cluster relations. if (Tools.isNavigationKey(evt.getKeyCode())) showClusterRelations(); } }); jTextFieldFilterKeywords.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { if (Tools.isNavigationKey(evt.getKeyCode())) { // if user pressed navigation key, select next table entry de.danielluedecke.zettelkasten.util.TableUtils.navigateThroughList(jTableKeywords, evt.getKeyCode()); } else { // select table-entry live, while the user is typing... de.danielluedecke.zettelkasten.util.TableUtils.selectByTyping(jTableKeywords, jTextFieldFilterKeywords, 0); } } }); jTextFieldFilterAuthors.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { if (Tools.isNavigationKey(evt.getKeyCode())) { // if user pressed navigation key, select next table entry de.danielluedecke.zettelkasten.util.TableUtils.navigateThroughList(jTableAuthors, evt.getKeyCode()); } else { // select table-entry live, while the user is typing... de.danielluedecke.zettelkasten.util.TableUtils.selectByTyping(jTableAuthors, jTextFieldFilterAuthors, 0); } } }); jTextFieldFilterTitles.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { if (Tools.isNavigationKey(evt.getKeyCode())) { // if user pressed navigation key, select next table entry de.danielluedecke.zettelkasten.util.TableUtils.navigateThroughList(jTableTitles, evt.getKeyCode()); } else { // select table-entry live, while the user is typing... de.danielluedecke.zettelkasten.util.TableUtils.selectByTyping(jTableTitles, jTextFieldFilterTitles, 1); } } }); jTextFieldFilterCluster.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { // select treenode live, while the user is typing... TreeUtil.selectByTyping(jTreeCluster, jTextFieldFilterCluster); } }); jTextFieldFilterAttachments.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { if (Tools.isNavigationKey(evt.getKeyCode())) { // if user pressed navigation key, select next table entry de.danielluedecke.zettelkasten.util.TableUtils.navigateThroughList(jTableAttachments, evt.getKeyCode()); } else { // select table-entry live, while the user is typing... de.danielluedecke.zettelkasten.util.TableUtils.selectByTyping(jTableAttachments, jTextFieldFilterAttachments, 0); } } }); // // the hyperlink-listeners // jEditorPaneEntry.addHyperlinkListener(new javax.swing.event.HyperlinkListener() { @Override public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { // if the link was clicked, proceed if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { // if (PlatformUtils.isJava7OnMac()) { // // get input event with additional modifiers // java.awt.event.InputEvent inev = evt.getInputEvent(); // // check whether shift key was pressed, and if so, remove manual link // if (inev.isControlDown() || inev.isMetaDown()) { // if (Tools.handleHyperlink(evt.getDescription(), data, displayedZettel)) { // updateZettelContent(displayedZettel); // updateTabbedPane(); // } // } // else { // openHyperlink(evt.getDescription()); // } // } openHyperlink(evt.getDescription()); } } }); // // the hyperlink-listeners // jEditorPaneIsFollower.addHyperlinkListener(new javax.swing.event.HyperlinkListener() { @Override public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { // if the link was clicked, proceed if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { openHyperlink(evt.getDescription()); } } }); // // the hyperlink-listeners // jEditorPaneClusterEntries.addHyperlinkListener(new javax.swing.event.HyperlinkListener() { @Override public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { // if the link was clicked, proceed if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { openHyperlink(evt.getDescription()); } } }); // // finally, init the selection listeners... // javax.swing.JTable[] tables = new javax.swing.JTable[] { jTableLinks, jTableManLinks, jTableAuthors, jTableTitles, jTableBookmarks, jTableAttachments }; for (javax.swing.JTable t : tables) { SelectionListener listener = new SelectionListener(t); t.getSelectionModel().addListSelectionListener(listener); t.getColumnModel().getSelectionModel().addListSelectionListener(listener); } jTreeLuhmann.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { showEntryFromLuhmann(); } }); jTreeLuhmann.addTreeExpansionListener(new javax.swing.event.TreeExpansionListener() { @Override public void treeExpanded(javax.swing.event.TreeExpansionEvent evt) { // retrieve path of value that was expanded TreePath tp = evt.getPath(); // check whether root was expanded or not. therefore, retrieve // last node of the treepath, i.e. the node which was expanded DefaultMutableTreeNode expandednode = (DefaultMutableTreeNode) tp.getLastPathComponent(); // if they equal, do nothing TreeUserObject userObject = (TreeUserObject) expandednode.getUserObject(); userObject.setCollapsed(false); } @Override public void treeCollapsed(javax.swing.event.TreeExpansionEvent evt) { // retrieve path of value that was expanded TreePath tp = evt.getPath(); // check whether root was expanded or not. therefore, retrieve // last node of the treepath, i.e. the node which was expanded DefaultMutableTreeNode expandednode = (DefaultMutableTreeNode) tp.getLastPathComponent(); // if they equal, do nothing TreeUserObject userObject = (TreeUserObject) expandednode.getUserObject(); userObject.setCollapsed(true); } }); // // init the menu-listeners... // recentDocsSubMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { updateRecentDocumentMenuIcon(recentDoc1, settings.getRecentDoc(1)); updateRecentDocumentMenuIcon(recentDoc2, settings.getRecentDoc(2)); updateRecentDocumentMenuIcon(recentDoc3, settings.getRecentDoc(3)); updateRecentDocumentMenuIcon(recentDoc4, settings.getRecentDoc(4)); updateRecentDocumentMenuIcon(recentDoc5, settings.getRecentDoc(5)); updateRecentDocumentMenuIcon(recentDoc6, settings.getRecentDoc(6)); updateRecentDocumentMenuIcon(recentDoc7, settings.getRecentDoc(7)); updateRecentDocumentMenuIcon(recentDoc8, settings.getRecentDoc(8)); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); recentDoc1.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(1); if (fp != null) openDocument(fp); } }); recentDoc2.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(2); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc3.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(3); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc4.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(4); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc5.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(5); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc6.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(6); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc7.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(7); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); recentDoc8.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { String fp = settings.getRecentDoc(8); if (fp != null && !fp.isEmpty()) openDocument(fp); } }); fileMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { menuFileInformation.setEnabled(settings.getFilePath() != null && settings.getFilePath().exists()); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { highlightSegmentsMenuItem.setSelected(settings.getHighlightSegments()); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); editMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // set indicator which show whether we have selections or not setListFilledWithEntry(jListEntryKeywords.getSelectedValues().length > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); windowsMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { showSearchResultsMenuItem.setEnabled(searchrequests.getCount() > 0); showDesktopMenuItem.setEnabled(desktop.getCount() > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); findEntryKeywordsMenu.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // set indicator which show whether we have selections or not setListFilledWithEntry(jListEntryKeywords.getSelectedValues().length > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuLinks.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { initViewMenuLinks(); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuAuthors.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // new keyword is always possible viewAuthorsNew.setEnabled(true); // at least one selection needed setTableEntriesSelected(jTableAuthors.getSelectedRowCount() > 0); setExportPossible(data.getCount(Daten.AUCOUNT) > 0); setBibtexFileLoaded(bibtex.getCurrentlyAttachedFile() != null); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuBookmarks.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // at least one selection needed setTableEntriesSelected(jTableBookmarks.getSelectedRowCount() > 0); setExportPossible(jTableBookmarks.getRowCount() > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuKeywords.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // new keyword is always possible viewKeywordsNew.setEnabled(true); // at least one selection needed setTableEntriesSelected(jTableKeywords.getSelectedRowCount() > 0); setExportPossible(data.getCount(Daten.KWCOUNT) > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuAttachments.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // get the amount of selected rows // at least one selection needed setTableEntriesSelected(jTableAttachments.getSelectedRowCount() > 0); setExportPossible(jTableAttachments.getRowCount() > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuTitles.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // get the amount of selected rows // at least one selection needed setTableEntriesSelected(jTableTitles.getSelectedRowCount() > 0); setExportPossible(data.getCount(Daten.ZKNCOUNT) > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuLuhmann.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { // set selected state viewMenuLuhmannShowNumbers.setSelected(settings.getShowLuhmannEntryNumber()); // retrieve selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeLuhmann.getLastSelectedPathComponent(); // check whether any selection made, that is not the root setLuhmannSelected((node != null) && (!node.isRoot())); setTableEntriesSelected((node != null) && (!node.isRoot())); setExportPossible(!data.getLuhmannNumbers(displayedZettel).isEmpty()); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); viewMenuCluster.addMenuListener(new javax.swing.event.MenuListener() { @Override public void menuSelected(javax.swing.event.MenuEvent evt) { setExportPossible(clusterList.size() > 0); } @Override public void menuDeselected(javax.swing.event.MenuEvent evt) { } @Override public void menuCanceled(javax.swing.event.MenuEvent evt) { } }); // // init the menu-listeners... // jPopupMenuKeywords.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // new keyword is always possible popupKeywordsNew.setEnabled(true); // at least one selection needed setTableEntriesSelected(jTableKeywords.getSelectedRowCount() > 0); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuKeywordList.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { initViewMenuLinks(); popupKwListHighlightSegments.setSelected(settings.getHighlightSegments()); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuAuthors.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // new keyword is always possible popupAuthorsNew.setEnabled(true); // at least one selection needed setTableEntriesSelected(jTableAuthors.getSelectedRowCount() > 0); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuLuhmann.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // retrieve selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeLuhmann.getLastSelectedPathComponent(); // check whether any selection made, that is not the root setLuhmannSelected((node != null) && (!node.isRoot())); setTableEntriesSelected((node != null) && (!node.isRoot())); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuTitles.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // at least one selection needed setTableEntriesSelected(jTableTitles.getSelectedRowCount() > 0); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuBookmarks.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // at least one selection needed setTableEntriesSelected(jTableBookmarks.getSelectedRowCount() > 0); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuLinks.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { initViewMenuLinks(); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuAttachments.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { // at least one selection needed setTableEntriesSelected(jTableAttachments.getSelectedRowCount() > 0); } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); jPopupMenuMain.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { try { // set copy/cut actions en- or disabled, depending on whether we have // selected text or not String selection = jEditorPaneEntry.getSelectedText(); // if we have selected text if (selection != null) { // enabled property setTextSelected(!selection.isEmpty()); } else { // else disable it setTextSelected(false); } } catch (IllegalArgumentException e) { // when the selection is deleted, this exception // occurs. so disable copy/cut setTextSelected(false); } } @Override public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } @Override public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } }); // // all other listeners that haven't been set up yet... // jTabbedPaneMain.addChangeListener(new javax.swing.event.ChangeListener() { @Override public void stateChanged(javax.swing.event.ChangeEvent evt) { updateTabbedPane(); } }); // </editor-fold> } private void highlightSegs() { // and highlight text segments if (settings.getHighlightSegments()) { // jEditorPaneEntry.setDocument(new HTMLDocument()); displayZettelContent(displayedZettel); } } private void createToolbarSearchbox() { // init a search textfield that is added to the toolbar tb_searchTextfield = new JTextField(15); // on mac, make textfield look like a search box if (settings.isMacAqua() || settings.isSeaGlass()) { tb_searchTextfield.putClientProperty("JTextField.variant", "search"); } else { tb_searchTextfield.setPreferredSize(new java.awt.Dimension(150, 26)); tb_searchTextfield.setMaximumSize(new java.awt.Dimension(200, 26)); tb_searchTextfield.setAlignmentY(java.awt.Component.CENTER_ALIGNMENT); } tb_searchTextfield.setToolTipText(getResourceMap().getString("searchfieldTooltip")); // put action to the tables' actionmaps tb_searchTextfield.getActionMap().put("EnterKeyPressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { JTextField tf = (JTextField) e.getSource(); // create a regular expression, that separates the input at each comma. // furthermore, commas within double-quotes ("") are not treated as separator-char, // so the user can search for sentences that include commas as well. and finally, the // quotes are removed, since we don't need them... Matcher mat = Pattern.compile("(\"(.*?)\"|([^,]+)),?").matcher(tf.getText()); // create a new list that will contain each found pattern (i.e. searchterm) List<String> result = new ArrayList<String>(); while (mat.find()) result.add(mat.group(2) == null ? mat.group(3) : mat.group(2)); // and copy the list to our array... String[] searchterms = result.toArray(new String[result.size()]); startSearch(searchterms, Constants.SEARCH_AUTHOR | Constants.SEARCH_CONTENT | Constants.SEARCH_TITLE | Constants.SEARCH_KEYWORDS | Constants.SEARCH_REMARKS, Constants.LOG_OR, false, false, true, false, false, "", "", 0, false, Constants.STARTSEARCH_USUAL, Constants.SEARCH_USUAL); } }); // associate enter-keystroke with that action KeyStroke ks = KeyStroke.getKeyStroke("ENTER"); tb_searchTextfield.getInputMap().put(ks, "EnterKeyPressed"); // add search box to toolbar jPanelSearchBox = new javax.swing.JPanel(); jLabelLupe = new javax.swing.JLabel(); jPanelSearchBox.setName("jPanelSearchBox"); jLabelLupe.setName("jLabelLupe"); jLabelLupe.setIcon(Constants.lupeIcon); javax.swing.GroupLayout jPanelSearchBoxLayout = new javax.swing.GroupLayout(jPanelSearchBox); jPanelSearchBox.setLayout(jPanelSearchBoxLayout); jPanelSearchBoxLayout.setHorizontalGroup(jPanelSearchBoxLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelSearchBoxLayout.createSequentialGroup().addContainerGap().addComponent(jLabelLupe) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tb_searchTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); jPanelSearchBoxLayout.setVerticalGroup( jPanelSearchBoxLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(jPanelSearchBoxLayout.createSequentialGroup().addContainerGap() .addGroup(jPanelSearchBoxLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabelLupe).addComponent(tb_searchTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(20, Short.MAX_VALUE))); toolBar.add(settings.isSeaGlass() ? tb_searchTextfield : jPanelSearchBox); // hide label on mac jLabelLupe.setVisible(!settings.isMacAqua() && !settings.isSeaGlass()); } /** * This method initialises the toolbar buttons. depending on the user-setting, we either * display small, medium or large icons as toolbar-icons. * @param bottomBarNeedsUdpate if {@code true}, the bottom bar on mac aqua style will also be * re-initialized. Use {@code true} only the first time the bottom bar is initialized. For further * GUI-updates, e.g. from settings window, use {@code false} as parameter. */ private void initToolbarIcons(boolean bottomBarNeedsUdpate) { statusErrorButton.setVisible(false); statusDesktopEntryButton.setVisible(false); // check whether the toolbar should be displayed at all... if (!settings.getShowIcons() && !settings.getShowIconText()) { // if not, hide it and leave. toolBar.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 mainPanel.setBorder(new MatteBorder(1, 0, 0, 0, ColorUtil.colorDarkLineGray)); return; } // set toolbar visible toolBar.setVisible(true); // and remove border from the main panel mainPanel.setBorder(null); // init toolbar button array javax.swing.JButton toolbarButtons[] = new javax.swing.JButton[] { tb_open, tb_save, tb_first, tb_next, tb_prev, tb_copy, tb_paste, tb_newEntry, tb_edit, tb_find, tb_addtodesktop, tb_addbookmark, tb_delete, tb_addluhmann, tb_addmanlinks, tb_selectall, tb_last }; String[] buttonNames = new String[] { "tb_openText", "tb_saveText", "tb_firstText", "tb_nextText", "tb_prevText", "tb_copyText", "tb_pasteText", "tb_newEntryText", "tb_editText", "tb_findText", "tb_addtodesktopText", "tb_addbookmarkText", "tb_deleteText", "tb_addluhmannText", "tb_addmanlinksText", "tb_selectallText", "tb_lastText" }; String[] iconNames = new String[] { "openIcon", "saveIcon", "showFirstEntryIcon", "showNextEntryIcon", "showPrevEntryIcon", "copyIcon", "pasteIcon", "newEntryIcon", "editEntryIcon", "findIcon", "addDesktopIcon", "addBookmarksIcon", "deleteIcon", "addLuhmannIcon", "addManLinksIcon", "selectAllIcon", "showLastEntryIcon" }; // set toolbar-icons' text if (settings.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 (settings.getShowIcons()) { // retrieve icon theme path String icontheme = settings.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); } } // check if all toolbar icons should be displayed or not if (settings.getShowIcons()) { tb_edit.setVisible(settings.getShowAllIcons()); tb_delete.setVisible(settings.getShowAllIcons()); tb_selectall.setVisible(settings.getShowAllIcons()); tb_addtodesktop.setVisible(settings.getShowAllIcons()); tb_find.setVisible(settings.getShowAllIcons()); } if (settings.isMacAqua() && bottomBarNeedsUdpate) makeMacToolbar(); if (settings.isSeaGlass()) makeSeaGlassToolbar(); } /** * 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(ZettelkastenView.class, this); // iterate the xml file with the accelerator keys for the main window for (int cnt = 1; cnt <= acceleratorKeys.getCount(AcceleratorKeys.MAINKEYS); cnt++) { // get the action's name String actionname = acceleratorKeys.getAcceleratorAction(AcceleratorKeys.MAINKEYS, 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 = acceleratorKeys.getAcceleratorKey(AcceleratorKeys.MAINKEYS, 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 // // when we have aqua look&feel, make some of the menu items invisivle, which already // appear in the Apple-Menu if (settings.isMacAqua()) { aboutMenu.setVisible(false); exitMenuItem.setVisible(false); jSeparatorExit.setVisible(false); } else { // init the variables String menutext; char mkey; // the mnemonic key for the file menu menutext = fileMenu.getText(); mkey = menutext.charAt(0); fileMenu.setMnemonic(mkey); // the mnemonic key for the edit menu menutext = editMenu.getText(); mkey = menutext.charAt(0); editMenu.setMnemonic(mkey); // the mnemonic key for the search menu menutext = findMenu.getText(); mkey = menutext.charAt(0); findMenu.setMnemonic(mkey); // the mnemonic key for the view menu menutext = viewMenu.getText(); mkey = menutext.charAt(0); viewMenu.setMnemonic(mkey); // the mnemonic key for the windows menu menutext = windowsMenu.getText(); mkey = menutext.charAt(0); windowsMenu.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()) fileMenu.setText(getResourceMap().getString("macFileMenuText")); } /** * This methods initiates table sorter for the jTables in the main window * we can now order the content of the keyword-lists, author-lists etc. in * the jTabbedPane by clicking on the table header. * <br><br> * Furthermore, visual settings like gridlines are set here. * <br><br> * Finally, we setup actionsmaps and associate them with the enter-key. by doing so, * we prevent the enter-key from selecting the next line. instead, a search request * is startetd. */ private void initTables() { // Create custom tablerow-sorter for sorting certain table rows that // might contain german umlauts setCustomTableRowSorter(jTableAuthors, 0); setCustomTableRowSorter(jTableKeywords, 0); setCustomTableRowSorter(jTableTitles, 1); setCustomTableRowSorter(jTableLinks, 1); setCustomTableRowSorter(jTableManLinks, 1); setCustomTableRowSorter(jTableBookmarks, 1); setCustomTableRowSorter(jTableAttachments, 0); javax.swing.JTable[] tables = new javax.swing.JTable[] { jTableLinks, jTableManLinks, jTableKeywords, jTableAuthors, jTableTitles, jTableBookmarks, jTableAttachments }; for (javax.swing.JTable t : tables) { t.getTableHeader().setReorderingAllowed(false); t.setGridColor(settings.getTableGridColor()); t.setShowHorizontalLines(settings.getShowGridHorizontal()); t.setShowVerticalLines(settings.getShowGridVertical()); t.setIntercellSpacing(settings.getCellSpacing()); // make extra table-sorter for itunes-tables if (settings.isMacStyle()) { TableUtils.SortDelegate sortDelegate = new TableUtils.SortDelegate() { @Override public void sort(int columnModelIndex, TableUtils.SortDirection sortDirection) { } }; TableUtils.makeSortable(t, sortDelegate); // change back default column-resize-behaviour when we have itunes-tables, // since the default for those is "auto resize off" t.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); } // if (settings.isMacAqua()) { // t.setDefaultRenderer(String.class, new MacSourceList.CustomTableCellRenderer()); // } } } /** * */ private void initDragDropTransferHandler() { jTableLinks.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { return de.danielluedecke.zettelkasten.util.TableUtils.prepareStringForTransferHandler(jTableLinks); } @Override protected boolean importString(JComponent c, String str) { int[] entries = Tools.retrieveEntryNumbersFromTransferHandler(str, data.getCount(Daten.ZKNCOUNT)); if (entries != null) { addToManLinks(entries); return true; } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jTableManLinks.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { return de.danielluedecke.zettelkasten.util.TableUtils .prepareStringForTransferHandler(jTableManLinks); } @Override protected boolean importString(JComponent c, String str) { int[] entries = Tools.retrieveEntryNumbersFromTransferHandler(str, data.getCount(Daten.ZKNCOUNT)); if (entries != null) { addToManLinks(entries); return true; } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jTableTitles.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { return de.danielluedecke.zettelkasten.util.TableUtils.prepareStringForTransferHandler(jTableTitles); } @Override protected boolean importString(JComponent c, String str) { // check whether a user drag'n'dropped entries within this table // if yes, sort them if (c.getName().equalsIgnoreCase("jTableTitles")) { // retrieve dropped entries int[] entries = Tools.retrieveEntryNumbersFromTransferHandler(str, data.getCount(Daten.ZKNCOUNT)); // retrieve drop index int droplocation = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableTitles, 0); // check for valid values if (droplocation != -1 && entries != null && entries.length > 0) { // sort entries data.moveEntries(entries, droplocation); // update display showTitles(); } } return false; } @Override protected void cleanup(JComponent c, boolean remove) { // clear selection jTableTitles.clearSelection(); } }); jTableBookmarks.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { return de.danielluedecke.zettelkasten.util.TableUtils .prepareStringForTransferHandler(jTableBookmarks); } @Override protected boolean importString(JComponent c, String str) { int[] entries = Tools.retrieveEntryNumbersFromTransferHandler(str, data.getCount(Daten.ZKNCOUNT)); if (entries != null) { addToBookmarks(entries, false); return true; } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); // enable drag&drop jTreeLuhmann.setDragEnabled(true); // init transfer handler for tree jTreeLuhmann.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_JTREELUHMANN + "\n"); // next line contains the entry-number, or -1 if a bullet was selected retval.append(String.valueOf(retrieveEntryNrFromLuhmann())).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("\t"); } // delete last, unnecessary new-line retval.setLength((retval.length() - 1)); // 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) { // 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]; // retrieve destination tree path of dragged node String[] nodepath = null; if (dropinformation.length >= 2) nodepath = dropinformation[2].split("\t"); // check out the source of the drag-operation. if we have a valid source, // retrieve entries. // here we have the jTreeLuhmannas drag-source, i.e. a drag&drop from within // this tree. that means, we have to delete the drag-source, i.e. // the dragged node that was moved to the new location if (nodepath != null && sourceinfo.equals(Constants.DRAG_SOURCE_JTREELUHMANN)) { // retrieve "depth" of treepathes of nodes int draglevel = nodepath.length; int droplevel = selectedNode.getLevel(); // retrieve parent of drop-location DefaultMutableTreeNode parent = (droplevel >= draglevel) ? (DefaultMutableTreeNode) selectedNode.getParent() : selectedNode; // check whether an entry was moved within the current entry's follower, // that means the entry was dragged & dropped within the same parent-level // or check whether the node was dropped onto its parent if ((draglevel == droplevel) || (draglevel == (droplevel + 1) && movedNodeToRemove.getParent().equals(parent))) { try { // cut of entry-number int dropentrynr = retrieveEntryNrFromLuhmann(parent); // retrieve entry-number of dragged entry. int draggedentrynr = Integer.parseInt(dropinformation[1]); // retrieve insert-index int insertIndex = (selectedNode.isRoot()) ? 0 : parent.getIndex(selectedNode) + 1; // delete moved entry from luhmann-numbers of source-entry data.deleteLuhmannNumber(dropentrynr, draggedentrynr); // insert entry at new index-position data.insertLuhmannNumber(dropentrynr, draggedentrynr, insertIndex); // update tabbed pane showLuhmann(); // return success value return true; } catch (NumberFormatException e) { } catch (IndexOutOfBoundsException ex) { } } } } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jListEntryKeywords.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { // retrieve selections Object[] kws = jListEntryKeywords.getSelectedValues(); // TODO ab Java 7 ersetzen durch getSelectedValuesList() // when we have no selection, return null if (kws.length < 1) return null; StringBuilder keywords = new StringBuilder(""); // iterate array and copy all selected keywords to clipboard for (Object o : kws) { keywords.append(o.toString()); keywords.append(System.getProperty("line.separator")); } return keywords.toString(); } @Override protected boolean importString(JComponent c, String str) { // check for valid drop-string if (str != null) { // remove carriage returns str = str.replace("\r", ""); // split at each new line addKeywords(str.split("\n"), true); return true; } return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jTableKeywords.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { // create string builder StringBuilder keywords = new StringBuilder(""); // retrieve selected valued that are being dragged String[] kws = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0); // create a comma-separated string from string array for (String k : kws) { keywords.append(k).append("\n"); } // return results return keywords.toString(); } @Override protected boolean importString(JComponent c, String str) { return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jTableAttachments.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { // create string builder StringBuilder attachments = new StringBuilder(""); // retrieve selected valued that are being dragged String[] atts = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAttachments, 0); // create a comma-separated string from string array for (String a : atts) { attachments.append(a).append("\n"); } // return results return attachments.toString(); } @Override protected boolean importString(JComponent c, String str) { return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jTableAuthors.setTransferHandler(new EntryStringTransferHandler() { @Override protected String exportString(JComponent c) { // create string builder StringBuilder authors = new StringBuilder(""); authors.append(Constants.DRAG_SOURCE_TYPE_AUTHORS).append("\n"); // retrieve selected values that are being dragged String[] aus = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0); // create a comma-separated string from string array for (String a : aus) { authors.append(a).append("\n"); } // return results return authors.toString(); } @Override protected boolean importString(JComponent c, String str) { return false; } @Override protected void cleanup(JComponent c, boolean remove) { } }); jEditorPaneEntry.setDragEnabled(true); DropTarget dropTarget = new DropTarget(jEditorPaneEntry, this); } /** * This method creates an own tablerow-sorter. this is necessary since we can use * own comparators here, so we can insert string with German umlauts at the correct * position - i.e. "" is inserted in "a", and not after "z". * * @param table the table that should get the custom tablerow-sorter * @param column the column where the sorter should be apllied to */ private void setCustomTableRowSorter(JTable table, int column) { // create new table sorter TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(); // tell tgis jtable that it has an own sorter table.setRowSorter(sorter); // and tell the sorter, which table model to sort. sorter.setModel((DefaultTableModel) table.getModel()); // in this table, the first column needs a custom comparator. try { sorter.setComparator(column, new Comparer()); // in case we have the table with titles, we make an exception, because // this table has two more columns that should be sorted, the columns with // the entries timestamps. if (table == jTableTitles) { sorter.setComparator(2, new DateComparer()); sorter.setComparator(3, new DateComparer()); } } catch (IndexOutOfBoundsException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } /** * 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 = settings.getTableFontSize(); // get current font int fsize = jTableLinks.getFont().getSize(); // retrieve default listvewfont Font defaultfont = settings.getTableFont(); // create new font, add fontsize-value Font f = new Font(defaultfont.getName(), defaultfont.getStyle(), fsize + defaultsize); // set new font jTableLinks.setFont(f); jTableManLinks.setFont(f); jTableAuthors.setFont(f); jTableKeywords.setFont(f); jTableTitles.setFont(f); jTableBookmarks.setFont(f); jTableAttachments.setFont(f); jListEntryKeywords.setFont(f); jTreeLuhmann.setFont(f); jTreeCluster.setFont(f); jTreeKeywords.setFont(f); } /** * This method inits the action map for several components like the tables, the treeviews * or the lists. here we can associate certain keystrokes with related methods. e.g. hitting * the enter-key in a table shows (activates) the related entry. * <br><br> * Setting up action maps gives a better overview and is shorter than adding key-release-events * to all components, although key-events would fulfill the same purpose. * <br><br> * The advantage of action maps is, that dependent from the operating system we need only * to associte a single action. with key-events, for each component we have to check * whether the operating system is mac os or windows, and then checking for different keys, * thus doubling each command: checking for F2 to edit, or checking for command+enter and also * call the edit-method. using action maps, we simply as for the os once, storing the related * keystroke-value as string, and than assign this string-value to the components. */ private void initActionMaps() { // <editor-fold defaultstate="collapsed" desc="Init of action-maps so we have shortcuts for the tables"> // create action which should be executed when the user presses // the enter-key AbstractAction a_enter = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTableAuthors == e.getSource()) searchLogOr(); else if (jTableKeywords == e.getSource()) searchLogOr(); else if (jTableLinks == e.getSource()) showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableLinks, 0)); else if (jTableManLinks == e.getSource()) showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableManLinks, 0)); else if (jTableTitles == e.getSource()) showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableTitles, 0)); else if (jTextFieldFilterKeywords == e.getSource()) filterKeywordList(false); else if (jTextFieldFilterAttachments == e.getSource()) filterAttachmentList(false); else if (jTextFieldFilterAuthors == e.getSource()) filterAuthorList(false); else if (jTextFieldFilterTitles == e.getSource()) filterTitleList(false); else if (jTextFieldFilterCluster == e.getSource()) filterClusterList(); else if (jTreeLuhmann == e.getSource()) showEntry(retrieveEntryNrFromLuhmann()); else if (jListEntryKeywords == e.getSource()) searchKeywordsFromListLogOr(); else if (jTableBookmarks == e.getSource()) showEntry(ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableBookmarks, 0)); else if (jTableAttachments == e.getSource()) openAttachment(); else if (jTextFieldEntryNumber == e.getSource()) ZettelkastenViewUtil.hiddenFeatures(ZettelkastenView.this, jTextFieldEntryNumber, data, searchrequests, desktop, settings, acceleratorKeys, bibtex, displayedZettel); } }; // put action to the tables' actionmaps jTableAuthors.getActionMap().put("EnterKeyPressed", a_enter); jTableKeywords.getActionMap().put("EnterKeyPressed", a_enter); jTableLinks.getActionMap().put("EnterKeyPressed", a_enter); jTableManLinks.getActionMap().put("EnterKeyPressed", a_enter); jTableTitles.getActionMap().put("EnterKeyPressed", a_enter); jTableBookmarks.getActionMap().put("EnterKeyPressed", a_enter); jTableAttachments.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldFilterKeywords.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldFilterAttachments.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldFilterAuthors.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldFilterTitles.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldFilterCluster.getActionMap().put("EnterKeyPressed", a_enter); jTextFieldEntryNumber.getActionMap().put("EnterKeyPressed", a_enter); jTreeLuhmann.getActionMap().put("EnterKeyPressed", a_enter); jListEntryKeywords.getActionMap().put("EnterKeyPressed", a_enter); // associate enter-keystroke with that action KeyStroke ks = KeyStroke.getKeyStroke("ENTER"); jTableAuthors.getInputMap().put(ks, "EnterKeyPressed"); jTableKeywords.getInputMap().put(ks, "EnterKeyPressed"); jTableLinks.getInputMap().put(ks, "EnterKeyPressed"); jTableManLinks.getInputMap().put(ks, "EnterKeyPressed"); jTableTitles.getInputMap().put(ks, "EnterKeyPressed"); jTableBookmarks.getInputMap().put(ks, "EnterKeyPressed"); jTableAttachments.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldFilterKeywords.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldFilterAttachments.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldFilterAuthors.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldFilterTitles.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldFilterCluster.getInputMap().put(ks, "EnterKeyPressed"); jTextFieldEntryNumber.getInputMap().put(ks, "EnterKeyPressed"); jTreeLuhmann.getInputMap().put(ks, "EnterKeyPressed"); jListEntryKeywords.getInputMap().put(ks, "EnterKeyPressed"); // create action which should be executed when the user presses // the delete/backspace-key AbstractAction a_delete = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTreeLuhmann == e.getSource()) deleteLuhmannFromEntry(); else if (jListEntryKeywords == e.getSource()) deleteKeywordFromEntry(); else if (jTableAuthors == e.getSource()) deleteAuthor(); else if (jTableKeywords == e.getSource()) deleteKeyword(); else if (jTableTitles == e.getSource()) deleteEntry(); else if (jTableBookmarks == e.getSource()) deleteBookmark(); else if (jTableManLinks == e.getSource()) deleteManualLink(); else if (jTableAttachments == e.getSource()) deleteAttachment(); } }; // put action to the tables' actionmaps jTreeLuhmann.getActionMap().put("DeleteKeyPressed", a_delete); jListEntryKeywords.getActionMap().put("DeleteKeyPressed", a_delete); jTableAuthors.getActionMap().put("DeleteKeyPressed", a_delete); jTableManLinks.getActionMap().put("DeleteKeyPressed", a_delete); jTableKeywords.getActionMap().put("DeleteKeyPressed", a_delete); jTableTitles.getActionMap().put("DeleteKeyPressed", a_delete); jTableBookmarks.getActionMap().put("DeleteKeyPressed", a_delete); jTableAttachments.getActionMap().put("DeleteKeyPressed", a_delete); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke((PlatformUtil.isMacOS()) ? "BACK_SPACE" : "DELETE"); jTreeLuhmann.getInputMap().put(ks, "DeleteKeyPressed"); jListEntryKeywords.getInputMap().put(ks, "DeleteKeyPressed"); jTableAuthors.getInputMap().put(ks, "DeleteKeyPressed"); jTableManLinks.getInputMap().put(ks, "DeleteKeyPressed"); jTableKeywords.getInputMap().put(ks, "DeleteKeyPressed"); jTableTitles.getInputMap().put(ks, "DeleteKeyPressed"); jTableBookmarks.getInputMap().put(ks, "DeleteKeyPressed"); jTableAttachments.getInputMap().put(ks, "DeleteKeyPressed"); // create action which should be executed when the user presses // the ctrl-F10/meta-F10-key AbstractAction a_add = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTableAuthors == e.getSource() || jTextFieldFilterAuthors == e.getSource()) addAuthorToList(); else if (jTableKeywords == e.getSource() || jTextFieldFilterKeywords == e.getSource()) addKeywordToList(); else if (jTableManLinks == e.getSource()) manualInsertLinks(); } }; // put action to the tables' actionmaps jTableAuthors.getActionMap().put("AddKeyPressed", a_add); jTableManLinks.getActionMap().put("AddKeyPressed", a_add); jTableKeywords.getActionMap().put("AddKeyPressed", a_add); jTextFieldFilterAuthors.getActionMap().put("AddKeyPressed", a_add); jTextFieldFilterKeywords.getActionMap().put("AddKeyPressed", a_add); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke((PlatformUtil.isMacOS()) ? "meta F10" : "ctrl F10"); jTableAuthors.getInputMap().put(ks, "AddKeyPressed"); jTableManLinks.getInputMap().put(ks, "AddKeyPressed"); jTableKeywords.getInputMap().put(ks, "AddKeyPressed"); jTextFieldFilterAuthors.getInputMap().put(ks, "AddKeyPressed"); jTextFieldFilterKeywords.getInputMap().put(ks, "AddKeyPressed"); // create action which should be executed when the user presses // the F2/meta-enter-key AbstractAction a_edit = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTableAuthors == e.getSource() || jTextFieldFilterAuthors == e.getSource()) editAuthor(); else if (jTableKeywords == e.getSource() || jTextFieldFilterKeywords == e.getSource()) editKeyword(); else if (jTableTitles == e.getSource() || jTextFieldFilterTitles == e.getSource()) editTitle(); else if (jTableBookmarks == e.getSource()) editBookmark(); else if (jTableAttachments == e.getSource() || jTextFieldFilterAttachments == e.getSource()) editAttachment(); } }; // put action to the tables' actionmaps jTableAuthors.getActionMap().put("EditKeyPressed", a_edit); jTableKeywords.getActionMap().put("EditKeyPressed", a_edit); jTableTitles.getActionMap().put("EditKeyPressed", a_edit); jTableBookmarks.getActionMap().put("EditKeyPressed", a_edit); jTableAttachments.getActionMap().put("EditKeyPressed", a_edit); jTextFieldFilterAuthors.getActionMap().put("EditKeyPressed", a_edit); jTextFieldFilterKeywords.getActionMap().put("EditKeyPressed", a_edit); jTextFieldFilterTitles.getActionMap().put("EditKeyPressed", a_edit); jTextFieldFilterAttachments.getActionMap().put("EditKeyPressed", a_edit); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke((PlatformUtil.isMacOS()) ? "meta ENTER" : "F2"); jTableAuthors.getInputMap().put(ks, "EditKeyPressed"); jTableKeywords.getInputMap().put(ks, "EditKeyPressed"); jTableTitles.getInputMap().put(ks, "EditKeyPressed"); jTableBookmarks.getInputMap().put(ks, "EditKeyPressed"); jTableAttachments.getInputMap().put(ks, "EditKeyPressed"); jTextFieldFilterAuthors.getInputMap().put(ks, "EditKeyPressed"); jTextFieldFilterKeywords.getInputMap().put(ks, "EditKeyPressed"); jTextFieldFilterTitles.getInputMap().put(ks, "EditKeyPressed"); jTextFieldFilterAttachments.getInputMap().put(ks, "EditKeyPressed"); // create action which should be executed when the user presses // the insert/Meta-Backspace-key AbstractAction a_new = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTableAuthors == e.getSource()) newAuthor(); else if (jTableKeywords == e.getSource()) newKeyword(); } }; // put action to the tables' actionmaps jTableAuthors.getActionMap().put("NewKeyPressed", a_new); jTableKeywords.getActionMap().put("NewKeyPressed", a_new); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke((PlatformUtil.isMacOS()) ? "meta BACK_SPACE" : "INSERT"); jTableAuthors.getInputMap().put(ks, "NewKeyPressed"); jTableKeywords.getInputMap().put(ks, "NewKeyPressed"); // create action which should be executed when the user presses // the insert/Meta-Backspace-key AbstractAction a_find = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { searchLogOr(); } }; // put action to the tables' actionmaps jTextFieldFilterKeywords.getActionMap().put("FindKeyPressed", a_find); jTextFieldFilterAuthors.getActionMap().put("FindKeyPressed", a_find); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke("shift ENTER"); jTextFieldFilterKeywords.getInputMap().put(ks, "FindKeyPressed"); jTextFieldFilterAuthors.getInputMap().put(ks, "FindKeyPressed"); // create action which should be executed when the user presses // the insert/Meta-Backspace-key AbstractAction a_findregex = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (jTextFieldFilterKeywords == e.getSource()) filterKeywordList(true); else if (jTextFieldFilterAttachments == e.getSource()) filterAttachmentList(true); else if (jTextFieldFilterAuthors == e.getSource()) filterAuthorList(true); else if (jTextFieldFilterTitles == e.getSource()) filterTitleList(true); } }; // put action to the tables' actionmaps jTextFieldFilterKeywords.getActionMap().put("FindRegExKeyPressed", a_findregex); jTextFieldFilterAuthors.getActionMap().put("FindRegExKeyPressed", a_findregex); jTextFieldFilterTitles.getActionMap().put("FindRegExKeyPressed", a_findregex); jTextFieldFilterAttachments.getActionMap().put("FindRegExKeyPressed", a_findregex); // check for os, and use appropriate controlKey ks = KeyStroke.getKeyStroke("alt ENTER"); jTextFieldFilterKeywords.getInputMap().put(ks, "FindRegExKeyPressed"); jTextFieldFilterAuthors.getInputMap().put(ks, "FindRegExKeyPressed"); jTextFieldFilterTitles.getInputMap().put(ks, "FindRegExKeyPressed"); jTextFieldFilterAttachments.getInputMap().put(ks, "FindRegExKeyPressed"); // </editor-fold> } /** * Method to init the jTrees components. Removes all elements, sets the root and * th selection-mode */ private void initTrees() { // in case we have mac os x with aqua look&feel, make JTrees look // mac-like if (settings.isMacAqua()) { // this tree has a root, so use "true" as parameter jTreeLuhmann.setUI(new MacSourceTree(true)); // this tree has no root, so use "false" as parameter jTreeCluster.setUI(new MacSourceTree(false)); // this tree has no root, so use "false" as parameter jTreeKeywords.setUI(new MacSourceTree(false)); } // on all other os / look&feels JTrees remain normal. else { // create array with all jTrees of mainframe javax.swing.JTree[] trees = new javax.swing.JTree[] { jTreeLuhmann, jTreeCluster, jTreeKeywords }; // and iterate that arrea for (javax.swing.JTree tree : trees) { // remove icons from jTree DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer(); // Remove the icons renderer.setLeafIcon(null); renderer.setClosedIcon(null); renderer.setOpenIcon(null); // set tree to single-selection-mode tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); } } } /** * Clears the trees and the related jlist on the tab with the tree. needed several times, * so we put these codelines into an own method. */ private void clearTreesAndTables() { // get the treemodel DefaultTreeModel dtrm = (DefaultTreeModel) jTreeLuhmann.getModel(); // and first of all, clear the jTree dtrm.setRoot(null); // get the treemodel dtrm = (DefaultTreeModel) jTreeCluster.getModel(); // and first of all, clear the jTree dtrm.setRoot(null); // get the treemodel dtrm = (DefaultTreeModel) jTreeKeywords.getModel(); // and first of all, clear the jTree dtrm.setRoot(null); // also clear the jListCluster on that tab clusterList.clear(); isFollowerList.clear(); DefaultTableModel dtm = (DefaultTableModel) jTableLinks.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableManLinks.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableKeywords.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableAuthors.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableTitles.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableBookmarks.getModel(); dtm.setRowCount(0); dtm = (DefaultTableModel) jTableAttachments.getModel(); dtm.setRowCount(0); } /** * This method is called at startup, or when a new data file is loaded * or created. used to reset all variable states that need to be resettet * at the beginning. */ private void initVariables() { // init the linked lists linkedkeywordlist = null; linkedauthorlist = null; linkedtitlelist = null; linkedattachmentlist = null; linkedclusterlist = false; // clear the jtress clearTreesAndTables(); displayedZettel = -1; // hide panels for live-search and is-follower-numbers jPanelLiveSearch.setVisible(false); /* jPanelManLinks.setVisible(false); */ } /** * This method sets the default look and feel before the components are drawn. This is needed * in case the user has changed the default look and feel and we need to set something different * than the usual default. */ private void setDefaultLookAndFeel() { try { // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); String laf = settings.getLookAndFeel(); if (laf.equals(Constants.seaGlassLookAndFeelClassName)) laf = "com.seaglasslookandfeel.SeaGlassLookAndFeel"; UIManager.setLookAndFeel(laf); // log info Constants.zknlogger.log(Level.INFO, "Using following LaF: {0}", settings.getLookAndFeel()); // when we have mac os with aqua look and feel, set menubar to main-menubar at top of screen if (settings.isMacAqua()) { System.setProperty("apple.laf.useScreenMenuBar", "true"); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Zettelkasten"); MacUtils.makeWindowLeopardStyle(ZettelkastenView.super.getFrame().getRootPane()); // WindowUtils.createAndInstallRepaintWindowFocusListener(ZettelkastenView.super.getFrame()); WindowUtils.installJComponentRepainterOnWindowFocusChanged( ZettelkastenView.super.getFrame().getRootPane()); } if (settings.isSeaGlass()) { // ZettelkastenView.super.getFrame().getRootPane().putClientProperty("SeaGlass.UnifiedToolbarLook", Boolean.TRUE); ZettelkastenView.super.getFrame().getRootPane().setBackground(ColorUtil.colorSeaGlassGray); } } catch (UnsupportedLookAndFeelException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } catch (ClassNotFoundException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } catch (InstantiationException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } catch (IllegalAccessException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } } /** * This methods updates the display, i.e. the content of the textfields, the availability * of toolbar icons and menu item */ @Action(enabledProperty = "currentEntryShown") public final void updateDisplay() { if (data.getCount(Daten.ZKNCOUNT) < 1) { // clear textfields jEditorPaneEntry.setText(""); // clear keyword-list keywordListModel.clear(); jTextFieldEntryNumber.setText(""); statusOfEntryLabel.setText(getResourceMap().getString("entryOfText")); // set new border text Color bcol = (settings.isMacAqua()) ? ColorUtil.colorJTreeText : null; jListEntryKeywords.setBorder(WidgetFactory.getTitledBorder( getResourceMap().getString("jListEntryKeywords.border.title"), bcol, settings)); // clear all table contents clearTreesAndTables(); } else { // Here we set up alle the textfields and lists updateDisplayParts(data.getCurrentZettelPos()); statusOfEntryLabel.setText(getResourceMap().getString("entryOfText") + " " + String.valueOf(data.getCount(Daten.ZKNCOUNT))); } // then update menu items and toolbar icons. updateToolbarAndMenu(); // Here we set up the jTabbedPane according to the page to be displayed // the keyword list e.g. is only to be displayed when selected - this is done // within the changelistener of the jTabbedPane. The connections of each entry to // other entries e.g. has to be updated each time updateTabbedPane(); } /** * Switches the logical filtering of the entry's keyword-list (jListEntryKeywords). * If the user selected keywords from the jListEntryKeywords, the link-list (jTableLinks) * is filtered. Here we switch whether the link-list is filtered in logical-or or logical-and * behaviour. after that, the link-list is being "re-filtered". */ @Action public void keywordListLogOr() { // switch checked items popupKwListLogOr.setSelected(true); popupKwListLogAnd.setSelected(false); viewMenuLinksKwListLogOr.setSelected(true); viewMenuLinksKwListLogAnd.setSelected(false); // save setting settings.setLogKeywordlist(Settings.SETTING_LOGKEYWORDLIST_OR); // and filter the list again filterLinks(); } /** * Switches the logical filtering of the entry's keyword-list (jListEntryKeywords). * If the user selected keywords from the jListEntryKeywords, the link-list (jTableLinks) * is filtered. Here we switch whether the link-list is filtered in logical-or or logical-and * behaviour. after that, the link-list is being "re-filtered". */ @Action public void keywordListLogAnd() { // switch checked items popupKwListLogOr.setSelected(false); popupKwListLogAnd.setSelected(true); viewMenuLinksKwListLogOr.setSelected(false); viewMenuLinksKwListLogAnd.setSelected(true); // save setting settings.setLogKeywordlist(Settings.SETTING_LOGKEYWORDLIST_AND); // and filter the list again filterLinks(); } /** * This method checks whether a certain menu has already been added to the menu bar. * We need this to avoid multiple occurences of same menus that are related to the * JTabbedPane. * * @param menu the menu that should be checked for existence * @return {@code true} if menu is already visible in the menu bar, {@code false} othwerwise. */ private boolean menuBarHasMenu(javax.swing.JMenu menu) { // iterate all menu items for (int cnt = 0; cnt < menuBar.getMenuCount(); cnt++) { // check whether requested menu is already added // if yes, return true if (menuBar.getMenu(cnt) == menu) return true; } // else return false return false; } /** * This method displays the menu that is related to the currently displayed * tab of the JTabbedPane.<br><br> * To avoid UI-bugs (which may occur in Snow Leopard 10.6), but * also to avoid multiple menu-handling for different operating systems, we now * <b>remove</b> <i>all</i> menus that are related to tabs of the JTabbedPane (formerly, * they were only set visible(true/false)). Thus, we have to check whether the to be * displayed menu is already "visible" (i.e. it already has been added to * the menu bar), so we don't have the same menu multiple times displayed in the menu bar. * This check is achived with the method {@link #menuBarHasMenu(javax.swing.JMenu) menuBarHasMenu(javax.swing.JMenu)}. * <br><br> * If the menu has not been added yet, it will be added then. And the menu bar is being validated and repainted. * * @param menu the menu that is related to the currently displayed tab in the JTabbedPane. */ private void showTabMenu(javax.swing.JMenu menu) { // check whether the menu already is visible (added) if (!menuBarHasMenu(menu)) { // if not, add it now menuBar.add(menu); // and validate and repaint menu bar // (we have to do this to avoid graphical bugs, for instance the menu text // will not be properly repainted when we do not call the repaint-method) menuBar.validate(); menuBar.repaint(); } } /** * This method updates the menu-items with the recent documents */ private void setRecentDocuments() { setRecentDocumentMenuItem(recentDoc1, 1); setRecentDocumentMenuItem(recentDoc2, 2); setRecentDocumentMenuItem(recentDoc3, 3); setRecentDocumentMenuItem(recentDoc4, 4); setRecentDocumentMenuItem(recentDoc5, 5); setRecentDocumentMenuItem(recentDoc6, 6); setRecentDocumentMenuItem(recentDoc7, 7); setRecentDocumentMenuItem(recentDoc8, 8); } private void setRecentDocumentMenuItem(javax.swing.JMenuItem menuItem, int recentDocNr) { // first, hide all menu-items menuItem.setVisible(false); // retrieve recent document String recDoc = settings.getRecentDoc(recentDocNr); // check whether we have any valid value if (recDoc != null && !recDoc.isEmpty()) { // make menu visible, if recent document is valid menuItem.setVisible(true); // set filename as text menuItem.setText(FileOperationsUtil.getFileName(recDoc)); // and set file-not-fouhd-icon updateRecentDocumentMenuIcon(menuItem, recDoc); } } private void updateRecentDocumentMenuIcon(javax.swing.JMenuItem menuItem, String recDoc) { // check whether we have any valid value if (recDoc != null && !recDoc.isEmpty()) { // create icon for file-not-found ImageIcon fileNotFoundIcon = Constants.errorIcon; // create zkn-icon for valid files ImageIcon zkn3Icon = Constants.zknicon; // create tooltip-text for file not found String fileNotFountText = getResourceMap().getString("recDocfileNotFoundTxt"); // check whether file exists File dummyfile = new File(recDoc); // set either filepath or file-not-found-text as tooltip menuItem.setToolTipText((dummyfile.exists() ? recDoc : fileNotFountText)); // set either file-not-found-icon or no icon menuItem.setIcon((dummyfile.exists()) ? zkn3Icon : fileNotFoundIcon); } } /** * This method removes all menus that are related to the JTabbedPane. After this method is * called, typically the method {@link #showTabMenu(javax.swing.JMenu) showTabMenu(javax.swing.JMenu)} * has to be called, to display the related menu of the currently displayed tab of the JTabbedPane. */ private void removeTabMenus() { // hide special menus. these will only be visible according to their // related displayed tab menuBar.remove(viewMenuLinks); menuBar.remove(viewMenuLuhmann); menuBar.remove(viewMenuKeywords); menuBar.remove(viewMenuAuthors); menuBar.remove(viewMenuTitles); menuBar.remove(viewMenuCluster); menuBar.remove(viewMenuBookmarks); menuBar.remove(viewMenuAttachments); menuBar.validate(); } /** * Here we set up the jTabbedPane according to the page to be displayed * the keyword list e.g. is only to be displayed when selected - this is done * within the changelistener of the jTabbedPane. The connections of each entry to * other entries e.g. has to be updated each time */ private void updateTabbedPane() { // enable refresh-button if we have a linked list jButtonRefreshKeywords.setEnabled(linkedkeywordlist != null); jButtonRefreshTitles.setEnabled(linkedtitlelist != null); jButtonRefreshAuthors.setEnabled(linkedauthorlist != null); jButtonRefreshCluster.setEnabled(linkedclusterlist); jButtonRefreshAttachments.setEnabled(linkedattachmentlist != null); // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterKeywords.setEnabled(jTableKeywords.getRowCount() > 0); jTextFieldFilterAuthors.setEnabled(jTableAuthors.getRowCount() > 0); jTextFieldFilterTitles.setEnabled(jTableTitles.getRowCount() > 0); jTextFieldFilterCluster.setEnabled(jTreeCluster.getRowCount() > 0); jTextFieldFilterAttachments.setEnabled(jTableAttachments.getRowCount() > 0); // hide special menus. these will only be visible according to their // related displayed tab removeTabMenus(); // reset status text statusMsgLabel.setText(""); // do nothing when we have no data if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // Get current tab int sel = jTabbedPaneMain.getSelectedIndex(); // if selected tab was different from the previous selection, update display if (sel != previousSelectedTab) { updateDisplayParts(data.getCurrentZettelPos()); } // we need always an update of the links needsLinkUpdate = true; // when the previous tab was the links-tab, stop the background-task... if ((TAB_LINKS == previousSelectedTab || TAB_LINKS != sel) && (cLinksTask != null) && !cLinksTask.isDone()) { cLinksTask.cancel(true); } // set new tab as current selection previousSelectedTab = sel; switch (sel) { case TAB_LINKS: showLinks(); break; case TAB_LUHMANN: showLuhmann(); break; case TAB_KEYWORDS: showKeywords(); break; case TAB_AUTHORS: showAuthors(); break; case TAB_TITLES: showTitles(); break; case TAB_CLUSTER: showCluster(); break; case TAB_BOOKMARKS: showBookmarks(); break; case TAB_ATTACHMENTS: showAttachments(); break; default: showLinks(); break; } } /** * This method is called from within the "updateDisplay" method. This method * enables or disables the toolbar icons and menubars, dependent on whether * their function is available or not. This depends on the amount of entries * in the program. */ public void updateToolbarAndMenu() { // store the amount of entries int count = data.getCount(Daten.ZKNCOUNT); // at least one entry necessary to enable following functions setEntriesAvailable(count > 0); // more than one entry necessary to enable following functions setMoreEntriesAvailable(count > 1); // check each selected entries for followers setMoreLuhmann(data.hasLuhmannNumbers(data.getCurrentZettelPos())); // check whether the current entry is bookmarked or not... setEntryBookmarked((-1 == bookmarks.getBookmarkPosition(displayedZettel)) && (count > 0)); // check whether current entry is on any desktop or not statusDesktopEntryButton.setVisible(desktop.isEntryInAnyDesktop(displayedZettel) && (count > 0)); statusDesktopEntryButton.setEnabled(desktop.isEntryInAnyDesktop(displayedZettel) && (count > 0)); // retrieve modified data-files setSaveEnabled(synonyms.isModified() | data.isMetaModified() | bibtex.isModified() | data.isModified() | bookmarks.isModified() | searchrequests.isModified() | desktop.isModified()); buttonHistoryBack.setEnabled(data.canHistoryBack()); buttonHistoryFore.setEnabled(data.canHistoryFore()); setHistoryBackAvailable(data.canHistoryBack()); setHistoryForAvailable(data.canHistoryFore()); // desktop and search results avaiable setDesktopAvailable(desktop.getCount() > 0); setSearchResultsAvailable(searchrequests.getCount() > 0); showSearchResultsMenuItem.setEnabled(searchrequests.getCount() > 0); showDesktopMenuItem.setEnabled(desktop.getCount() > 0); } /** * This method displays the information of an entry that is selected from the tree jTreeLuhmann, * i.e. displaying a follower- or sub-entry of the current entry. we use an extra display-method * here because we don't want to "lose" the current entry and we don't want updating the tabbed * pane with the jTree when the user selects an entry from that tree. */ private void showEntryFromLuhmann() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // retrieve number of selected entry int nr = retrieveEntryNrFromLuhmann(); // if we don't have a valid selection, use current entry as reference if (-1 == nr) nr = data.getCurrentZettelPos(); // now display only the relevant parts, no complete update of the display updateDisplayParts(nr); } /** * This method is used to update the content of the textfields/lists, but not the whole display * like tabbed pane as well. Usually this method is called when a link to another entry or a follower * entry or any entry in one of the tabbed pane's tables is selected. This selection does just show * the content of the related entry, which means the jEditorPanes and the jListKeywords are filled * with the entry's data. but: the data in the tabbed pane, like the entry's follower-numbers, * links and manual links etc. are <i>not</i> updated. this only occurs, when an entry is <i>activated</i>. * e.g. by double-clicking on an entry in on of the tabbed pane's tables. * * @param nr the number of the entry that should be displayed */ public void updateDisplayParts(int nr) { // if we have an invalid number, leave if (nr < 1) { return; } // set the number of the displayed zettel... // we need to do this so we can distinguish between the currently *displayed* entry // and the current *activated* or *active* entry (which can be retrieved via the // CDaten-class' getCurrentZettelPos. When an entry is displayed, the content of the // jEditorPane's is updated. However, when an entry is also *activated* the entry's related // content in the tabbed pane's tables is updated as well displayedZettel = nr; // if the user wants to add all displayed entries to the history, including those that are // not only activated, but also displayed, do this here... if (settings.getAddAllToHistory()) { // add displayed zettel to history data.addToHistory(nr); // update buttons for navigating through history buttonHistoryBack.setEnabled(data.canHistoryBack()); buttonHistoryFore.setEnabled(data.canHistoryFore()); } // update highlight-terms by either retrieving the keywords of the displayed entry // or setting it to null. // get the keywords which should be highlighted, if highlighting keywords is activated. // check whether keywords should be highlighted at all if (settings.getHighlightKeywords()) { // retrieve highlightterms String[] highlightterms = data.getSeparatedKeywords(displayedZettel); // create new linked list that will contain all highlight-terms, including // the related synonyms of the highlight-terms LinkedList<String> highlight = new LinkedList<String>(); // check whether we have any keywords to highlight if (highlightterms != null && highlightterms.length > 0) { highlight.addAll(Arrays.asList(highlightterms)); // check whether synonyms should be included as well if (settings.getSearchAlwaysSynonyms()) { // iterate all current highlight keywords // and add synonyms for (String kw : highlightterms) { // get the synonym-line for each search term String[] synline = synonyms.getSynonymLineFromAny(kw, false); // if we have synonyms... if (synline != null) { // iterate synonyms for (String sy : synline) { // add them to the linked list, if they are new if (!highlight.contains(sy)) { highlight.add(sy); } } } } } HtmlUbbUtil.setHighlighTerms(highlight.toArray(new String[highlight.size()]), HtmlUbbUtil.HIGHLIGHT_STYLE_KEYWORDS, settings.getHighlightWholeWord()); } else { HtmlUbbUtil.setHighlighTerms(null, HtmlUbbUtil.HIGHLIGHT_STYLE_KEYWORDS, settings.getHighlightWholeWord()); } } else { HtmlUbbUtil.setHighlighTerms(null, HtmlUbbUtil.HIGHLIGHT_STYLE_KEYWORDS, settings.getHighlightWholeWord()); } displayZettelContent(nr); // Here we set up the keywordlist for the JList // retrieve the current keywords String[] kws = data.getKeywords(nr); // prepare the JList which will display the keywords keywordListModel.clear(); // check whether any keywords have been found if (kws != null) { // sort the array if (kws.length > 0) { Arrays.sort(kws, new Comparer()); } // iterate the string array and add its content to the list model for (String kw : kws) { keywordListModel.addElement(kw); } } // create new stringbuilder for border-text. we set the amount of keywords // as new border-title StringBuilder bordertext = new StringBuilder(""); // get localalised description bordertext.append(getResourceMap().getString("jListEntryKeywords.border.title")); // if we have any keywords... // copy amount of keywords behind description if (!keywordListModel.isEmpty()) { bordertext.append(" (").append(String.valueOf(keywordListModel.size())).append(")"); } // set new border text Color bcol = (settings.isMacAqua()) ? ColorUtil.colorJTreeText : null; jListEntryKeywords.setBorder(WidgetFactory.getTitledBorder(bordertext.toString(), bcol, settings)); // en- or disable those actions which are related to the displaying of the current entry setCurrentEntryShown(displayedZettel != data.getCurrentZettelPos()); } /** * * @param nr * @return */ private void displayZettelContent(int nr) { // retrieve the string array of the first entry String disp = data.getEntryAsHtml(nr, (settings.getHighlightSegments()) ? retrieveSelectedKeywordsFromList() : null, Constants.FRAME_MAIN); // in case parsing was ok, display the entry if (Tools.isValidHTML(disp, nr)) { // set entry information in the main textfield jEditorPaneEntry.setText(disp); } // else show error message box to user and tell him what to do else { StringBuilder cleanedContent = new StringBuilder(""); cleanedContent .append("<body><div style=\"margin:5px;padding:5px;background-color:#dddddd;color:#800000;\">"); URL imgURL = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getClass() .getResource("/de/danielluedecke/zettelkasten/resources/icons/error.png"); cleanedContent.append("<img border=\"0\" src=\"").append(imgURL).append("\"> "); cleanedContent.append(getResourceMap().getString("incorrectNestedTagsText")); cleanedContent.append("</div>").append(data.getCleanZettelContent(nr)).append("</body>"); // and display clean content instead jEditorPaneEntry.setText(cleanedContent.toString()); } // place caret, so content scrolls to top jEditorPaneEntry.setCaretPosition(1); // set entry number tzo textfield jTextFieldEntryNumber.setText(String.valueOf(data.getCurrentZettelPos())); } /** * This method updates an entry's content only, and <i>not</i> all other fields like the tables in * the tabbed pane. * * @param zettelnummer the number of the entry which content should be updated. */ public void updateZettelContent(int zettelnummer) { displayZettelContent(zettelnummer); } /** * Action that deletes a selected Luhmann-number (i.e. a selection in the jTreeLuhmann, that * show follower- and sub-entries of an entry) from the selection's parent. Thus, we can not * only remove an sub-entry of the current entry, but also from other sub-entries. */ @Action(enabledProperty = "luhmannSelected") public void deleteLuhmannFromEntry() { // retrieve selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeLuhmann.getLastSelectedPathComponent(); // if we have a valid selection, go on... if (node != null) { // get the parent. the parent is the entry where the selected entry should be deleted // from the luhmann-element DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); // if the node has a parent (i.e. is not the root), we can go on if (parent != null) { // ask whether keyword really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("askForDeleteLuhmannMsg"), getResourceMap().getString("askForDeleteLuhmannTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // retrieve entry number of selected node int nodeNr = retrieveEntryNrFromLuhmann(); // retrieve entry number of parent node int parentNr = retrieveEntryNrFromLuhmann(parent); // check vor valid values if (nodeNr != -1 && parentNr != -1) { // and remove the nodeNr from the entry "parentNr" data.deleteLuhmannNumber(parentNr, nodeNr); // update the display updateDisplay(); } } } } } /** * This methods retrieves the number of a selected entry from the * jTreeLuhmann * * @return The number of the selected entry, or -1 if an error occured */ private int retrieveEntryNrFromLuhmann() { // retrieve selected node return retrieveEntryNrFromLuhmann((DefaultMutableTreeNode) jTreeLuhmann.getLastSelectedPathComponent()); } /** * This methods retrieves the number of the node {@code node} from the * jTreeLuhmann * * @param node * @return The number of the selected entry, or -1 if an error occured */ private int retrieveEntryNrFromLuhmann(DefaultMutableTreeNode node) { // if we have a valid selection, go on... if (node != null) { // get user data TreeUserObject userObject = (TreeUserObject) node.getUserObject(); // retrieve the node's id (i.e. entrynumber String text = userObject.getId(); // check for root if (text.equals(Constants.ROOT_ID_NAME)) { // if root is selected, return current acticated entry number return data.getCurrentZettelPos(); } try { int nr = Integer.parseInt(text); return nr; } catch (NumberFormatException e) { Constants.zknlogger.log(Level.WARNING, "Node was: {0}{1}Retrieved Number was: {2}{3}{4}", new Object[] { node.toString(), System.getProperty("line.separator"), text, System.getProperty("line.separator"), e.getLocalizedMessage() }); return -1; } } return -1; } @Action public void showLuhmannEntryNumber() { boolean val = settings.getShowLuhmannEntryNumber(); settings.setShowLuhmannEntryNumber(!val); showLuhmann(); } /** * This action shows the tab with the links to other entries, based on matching * keywords. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowLinks() { jTabbedPaneMain.setSelectedIndex(TAB_LINKS); } /** * This action shows the tab with the attachment of all entries. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowAttachments() { jTabbedPaneMain.setSelectedIndex(TAB_ATTACHMENTS); } /** * This method opens a modal dialog that starts a background-task. this background-task then * again creates the so-called luhmann-numbers. * <br><br> * The Luhmann-Numbers function is similar to a typical tree: we have one "parent"-entry * and several child-entries (sub-entries or followers). each of these child-elements can * have their own child-elements again (whereby the child-element itself is then again * understood as "parent"-entry). * <br><br> * So, the Luhmann-numbers of an entry only have one subordinated level of sub-entries. the tree- * structure comes from those sub-entries, that might have their own sub-entries again. */ private synchronized void showLuhmann() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // if the link-table is not shown, leave if (jTabbedPaneMain.getSelectedIndex() != TAB_LUHMANN) { return; } // show Luhmann numbers luhmannTask(); } /** * This method restores a filtered link-list. The list jTableLinks is filtered, when * a user selects an item from the jListEntryKeywords. To restore the list, we use * this method.<br><br> * When a filtered link-list (jTableLinks), which is filtered by selected keywords * from the keyword-list (jListEntryKeywords), we can reset the link-list, showing * not just the related keywords from the selected values, but all keywords again. */ @Action public void refreshFilteredLinks() { needsLinkUpdate = true; showLinks(); } /** * This method displays the links/connection of an entry by starting * a background task. after the task finishes, all links from this entry * to other entries are display in the JTable of the JTabbedPane */ private synchronized void showLinks() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // if the link-table is not shown, leave if (jTabbedPaneMain.getSelectedIndex() != TAB_LINKS) { return; } // when no update needed, show menu and leave method if (!needsLinkUpdate) { // update might be needed next time needsLinkUpdate = true; // show/enable viewmenu, if we have at least one entry... if ((jTableLinks.getRowCount() > 0) && (TAB_LINKS == jTabbedPaneMain.getSelectedIndex())) { showTabMenu(viewMenuLinks); } // we might have changes to the manual links, so update this here... displayManualLinks(); // and leave method return; } // when task is already running, quit... if (createLinksIsRunning) { return; } // clear selections jListEntryKeywords.clearSelection(); // clear table DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel(); // reset the table tm.setRowCount(0); // clear table with manual links tm = (DefaultTableModel) jTableManLinks.getModel(); // reset the table tm.setRowCount(0); // hide the panel with the table with manual links /* jPanelManLinks.setVisible(false); */ // tell user that we are doing something... statusMsgLabel.setText(getResourceMap().getString("createLinksMsg")); Task clT = createLinks(); // 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(clT); tM.setForegroundTask(clT); } private void displayManualLinks() { // get table model for manual links DefaultTableModel tm = (DefaultTableModel) jTableManLinks.getModel(); // reset the table tm.setRowCount(0); // get the current manual links int[] manlinks; manlinks = data.getCurrentManualLinks(); // if we have any manual links, fille the table and display the panel if ((manlinks != null) && (manlinks.length > 0)) { for (int cnt = 0; cnt < manlinks.length; cnt++) { // create a new object Object[] ob = new Object[3]; // store the information in that object ob[0] = manlinks[cnt]; ob[1] = data.getZettelTitle(manlinks[cnt]); ob[2] = data.getZettelRating(manlinks[cnt]); // add new table row tm.addRow(ob); } } // display panel /* jPanelManLinks.setVisible(jTableManLinks.getRowCount()>0); */ } /** * This action shows the tab with the keywords of the current data file. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowKeywords() { jTabbedPaneMain.setSelectedIndex(TAB_KEYWORDS); } /** * This method displays the all keywords in the keyword data file using * a background task. after the task finishes, all keywords and their useage frequency * in the main data file (zknfile) are displayed in the JTable of the JTabbedPane */ private void showKeywords() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableKeywords.getRowCount()) + " " + getResourceMap().getString("statusTextKeywords") + ")"); // show/enabke related menu showTabMenu(viewMenuKeywords); // if keywordlist is up to date, leave method if (data.isKeywordlistUpToDate()) { return; } // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SHOWKEYWORDS, data, synonyms, null /*only needed for authors*/, null /*only needed for attachments*/, settings.getShowSynonymsInTable(), 0 /*only need for authors*/, (DefaultTableModel) jTableKeywords.getModel()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have a new added keyword, and if so, select it if (newAddedKeyword != null) { // select recently added value de.danielluedecke.zettelkasten.util.TableUtils.selectValueInTable(jTableKeywords, newAddedKeyword, 0); // and clear strimg newAddedKeyword = null; } // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterKeywords.setEnabled(jTableKeywords.getRowCount() > 0); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableKeywords.getRowCount()) + " " + getResourceMap().getString("statusTextKeywords") + ")"); // try to motivate garbage collector System.gc(); } private void updateZettelkasten(String updateBuildNr) { // if dialog window isn't already created, do this now if (null == updateInfoDlg) { // get parent und init window updateInfoDlg = new CUpdateInfoBox(getFrame()); // center window updateInfoDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(updateInfoDlg); // check whether user wants to hide this msg box if (updateInfoDlg.getHideUpdateMsg()) { // set update build number to settings, so this update msg will not be displayed // for this update number again settings.setShowUpdateHintVersion(updateBuildNr); } // check whether user wants to update if (updateInfoDlg.isShowHomepage()) { // open homepage try { Desktop.getDesktop().browse(new URI(updateURI)); } catch (IOException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } catch (URISyntaxException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } // 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) updateInfoDlg.dispose(); updateInfoDlg = null; } /** * This methoid toggles the highlight-setting for the keywords. When activated, * the keywords of the current displayed entry are highlighted in the entry's * content-text. */ @Action(enabledProperty = "entriesAvailable") public void highlightKeywords() { // check whether highlighting is activated if (!settings.getHighlightKeywords()) { // if not, activate it settings.setHighlightKeyword(true); } else { // nex, if highlighting is activated, // check whether whole word highlighting is activated if (!settings.getHighlightWholeWord()) { // if not, activate whole-word-highlighting and do not // deactivate general highlighting settings.setHighlightWholeWord(true); } // else if both were activated, deactivate all else { settings.setHighlightKeyword(false); settings.setHighlightWholeWord(false); } } // no linkupdate needed needsLinkUpdate = false; // update the display updateDisplay(); } @Action(enabledProperty = "entriesAvailable") public void highlightSegments() { // toggle highlight setting for keywords settings.setHighlightSegments(!settings.getHighlightSegments()); // and update display displayZettelContent(displayedZettel); } /** * This method filters the keyword list from a given input of the user. the text entered into the * jTextFieldFilterKeywords is retrieved, and all keywords in the jTableKeywords, that do <b>not</b> * <i>contain</i> the entered text (case insensitive), are removed from the table.<br><br> * Thus, all remaining keywords in the table do start or at least contain the textinput from the * textfield. */ private void filterKeywordList(boolean forceRegEx) { LinkedList<Object[]> l = filterList(jTextFieldFilterKeywords, jTableKeywords, jButtonRefreshKeywords, linkedkeywordlist, "statusTextKeywords", 0, forceRegEx); if (l != null) { linkedkeywordlist = l; } } /** * When a keywordlist is filtered, the original table data is temporarily stored in a linked list. * when the user perfoms the refresh-method, the original table data is restored by clearing the * table's content and setting back all data from the linked list to the table. */ @Action public void refreshKeywordList() { refreshList(jTableKeywords, jButtonRefreshKeywords, jTextFieldFilterKeywords, linkedkeywordlist, "statusTextKeywords"); linkedkeywordlist = null; } @Action(enabledProperty = "exportPossible") public void exportTitles() { // retrieve amount of table rows int rowcount = jTableTitles.getRowCount(); // create array for entry-numbers int[] entries = new int[rowcount]; // iterate all table values and copy each enty-number to the array for (int cnt = 0; cnt < rowcount; cnt++) { entries[cnt] = Integer.parseInt(jTableTitles.getValueAt(cnt, 0).toString()); } // export entries from the jTableTitles in the according order... exportEntries(entries); } @Action(enabledProperty = "exportPossible") public void exportLuhmann() { // retrieve luhmann numbers int[] ent = prepareLuhmannNumbersForExport(); // check for valid values if (ent != null) { exportEntries(ent); } } @Action(enabledProperty = "exportPossible") public void exportLuhmannToSearch() { // retrieve luhmann numbers int[] ent = prepareLuhmannNumbersForExport(); // check for valid values if (ent != null) { // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch( new String[] { getResourceMap().getString("exportLuhmannSearch", String.valueOf(displayedZettel)) }, Constants.SEARCH_LUHMANN, Constants.LOG_OR, false, false, false, false, ent, getResourceMap().getString("exportLuhmannSearchDesc", String.valueOf(displayedZettel)) + " (" + df.format(new Date()) + ")", getResourceMap().getString("exportLuhmannSearchDesc", String.valueOf(displayedZettel))); // if dialog window isn't already created, do this now if (null == searchResultsDlg) { searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); } // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } } private int[] prepareLuhmannNumbersForExport() { // init linked list luhmannnumbersforexport = new LinkedList<Integer>(); // get recursive Luhmann-Numbers of current entry fillLuhmannNumbersForExport(displayedZettel); // add them... if (luhmannnumbersforexport.size() > 0) { // add initial entry luhmannnumbersforexport.add(0, displayedZettel); // convert to int array int[] ent = new int[luhmannnumbersforexport.size()]; try { // than the followers for (int cnt = 0; cnt < ent.length; cnt++) { ent[cnt] = luhmannnumbersforexport.get(cnt); } } catch (NumberFormatException e) { } return ent; } return null; } /** * 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 fillLuhmannNumbersForExport(int zettelpos) { // get the text from the luhmann-numbers String lnr = data.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) { // convert to int int e = Integer.parseInt(exist); // copy all values to an array if (!luhmannnumbersforexport.contains(e)) { luhmannnumbersforexport.add(e); } // check whether luhmann-value exists, by re-calling this method // again and go through a recusrive loop fillLuhmannNumbersForExport(e); } } } /** * This method exports the automatic links (referrers) of an entry. */ @Action(enabledProperty = "exportPossible") public void exportLinks() { // create linked list that will contain all attachments ArrayList<Object> explinks; explinks = new ArrayList<Object>(); // first, add original entry number explinks.add(String.valueOf(displayedZettel)); // get length of links-table int len = jTableLinks.getRowCount(); // copy all attachments to a linked list if (len > 0) { for (int cnt = 0; cnt < len; cnt++) { explinks.add(jTableLinks.getValueAt(cnt, 0)); } } // get length of manual-links-table len = jTableManLinks.getRowCount(); // if we also have manual links, add them if (len > 0) { // copy all attachments to a linked list for (int cnt = 0; cnt < len; cnt++) { explinks.add(jTableManLinks.getValueAt(cnt, 0)); } } // call export-method exportEntries(explinks); } /** * This method exports the automatic links (referrers) of an entry, but not to a file * but to the search results window instead. */ @Action(enabledProperty = "exportPossible") public void exportLinksToSearch() { // create linked list that will contain all attachments ArrayList<Object> explinks = new ArrayList<Object>(); // retrieve entry-numbers // first, add original entry number explinks.add(String.valueOf(displayedZettel)); // get length of links-table int len = jTableLinks.getRowCount(); // copy all attachments to a linked list if (len > 0) { for (int cnt = 0; cnt < len; cnt++) { explinks.add(jTableLinks.getValueAt(cnt, 0)); } } // get length of manual-links-table len = jTableManLinks.getRowCount(); // if we also have manual links, add them if (len > 0) { // copy all attachments to a linked list for (int cnt = 0; cnt < len; cnt++) { explinks.add(jTableManLinks.getValueAt(cnt, 0)); } } // create int-array with all entry-numbers int[] expvalues = new int[explinks.size()]; try { // copy all numbers from arraylist to int-array for (int cnt = 0; cnt < expvalues.length; cnt++) { expvalues[cnt] = Integer.parseInt(explinks.get(cnt).toString()); } // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch( new String[] { getResourceMap().getString("exportLinksSearch", String.valueOf(displayedZettel)) }, Constants.SEARCH_REFERRERS, Constants.LOG_OR, false, false, false, false, expvalues, getResourceMap().getString("exportLinksSearchDesc", String.valueOf(displayedZettel)) + " (" + df.format(new Date()) + ")", getResourceMap().getString("exportLinksSearchDesc", String.valueOf(displayedZettel))); // if dialog window isn't already created, do this now if (null == searchResultsDlg) { searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); } // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } catch (NumberFormatException e) { } } public void exportDesktopToSearch(int[] entries, String desktopname) { // check for valid search results if (entries != null && entries.length > 0) { // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch(new String[] { getResourceMap().getString("exportDesktopSearch") }, Constants.SEARCH_DESKTOP, Constants.LOG_OR, false, false, false, false, entries, getResourceMap().getString("exportDesktopSearchDesc", "\"" + desktopname + "\"" + " (" + df.format(new Date()) + ")"), getResourceMap().getString("exportDesktopSearchDesc", "\"" + desktopname + "\"")); // if dialog window isn't already created, do this now if (null == searchResultsDlg) { searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); } // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } } public void exportDesktopMissingToSearch(int[] entries, String desktopname) { // check for valid search results if (entries != null && entries.length > 0) { // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch(new String[] { getResourceMap().getString("exportMissingDesktopSearch") }, Constants.SEARCH_DESKTOP, Constants.LOG_OR, false, false, false, false, entries, getResourceMap().getString("exportMissingDesktopSearchDesc", "\"" + desktopname + "\"" + " (" + df.format(new Date()) + ")"), getResourceMap().getString("exportMissingDesktopSearchDesc", "\"" + desktopname + "\"")); // if dialog window isn't already created, do this now if (null == searchResultsDlg) { searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); } // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } } /** * This method exports the automatic links (referrers) of an entry. */ @Action(enabledProperty = "exportPossible") public void exportCluster() { // create linked list that will contain all attachments ArrayList<Object> expcluster = new ArrayList<Object>(); // get length of cluster-entry-list // call export-method exportEntries(expcluster); } /** * This method exports the automatic links (referrers) of an entry, but not to a file * but to the search results window instead. */ @Action(enabledProperty = "exportPossible") public void exportClusterToSearch() { // create int-array with all entry-numbers int[] expvalues = new int[clusterList.size()]; try { // copy all numbers from arraylist to int-array for (int cnt = 0; cnt < expvalues.length; cnt++) { expvalues[cnt] = Integer.parseInt(clusterList.get(cnt)); } // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch( new String[] { getResourceMap().getString("exportClusterSearch", lastClusterRelationKeywords) }, Constants.SEARCH_CLUSTER, Constants.LOG_OR, false, false, false, false, expvalues, getResourceMap().getString("exportClusterSearchDesc", lastClusterRelationKeywords) + " (" + df.format(new Date()) + ")", getResourceMap().getString("exportClusterSearchDesc", lastClusterRelationKeywords)); // if dialog window isn't already created, do this now if (null == searchResultsDlg) { searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); } // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } catch (NumberFormatException e) { } } /** * This action opens an input dialog and lets the user input a new keyword-value. * The currently selected keyword is then being changed and the modified state set. * In case the user chose a new keyword which already exists, the user is being * offered to "merge" the old keyword with the other existing one. */ @Action(enabledProperty = "tableEntriesSelected") public void editKeyword() { // get selected keywords String[] selectedkeywords = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0); // if now row is selected, leave... if (null == selectedkeywords) { return; } // get selected rows. we need this numbers for setting back the new values, see below int[] selectedrows = jTableKeywords.getSelectedRows(); // go through all selected keywords for (int cnt = selectedkeywords.length - 1; cnt >= 0; cnt--) { // save the old value String oldKw = selectedkeywords[cnt]; // now check whether the selected keyword is a keyword, or only a synonym // this may happen, when the user includes the synonyms in the keyword-list, // so in fact we have no "real" keyword. if (data.findKeywordInDatabase(oldKw) != -1) { // open an input-dialog, setting the selected value as default-value String newKw = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("editKeywordMsg"), getResourceMap().getString("editKeywordTitle"), JOptionPane.PLAIN_MESSAGE, null, null, oldKw); // ask the user if he wants to replace the new name of keywords, which appear as synonyms, but *not* // as index-word, with the related index-words... newKw = Tools.replaceSynonymsWithKeywords(synonyms, new String[] { newKw })[0]; // if we have a valid return-value that differs from the old value... if ((newKw != null) && (newKw.length() > 0) && (!oldKw.equalsIgnoreCase(newKw))) { // check whether the value already exists if (-1 == data.getKeywordPosition(newKw, false)) { // change the existing value in the table jTableKeywords.setValueAt(newKw, selectedrows[cnt], 0); // get the index-number of the old keyword-string int nr = data.getKeywordPosition(oldKw, false); // and change the entry to the new value data.setKeyword(nr, newKw); // now we want either to rename synonyms-index-words of the keyword // "oldKw", since this keyword has been renamed. or, if the new keyword // name "newKw" also has associated synonyms, we want to merge them. Tools.mergeSynonyms(synonyms, oldKw, newKw); // if we have a filtered list, remove the element also from // our refresh-list, so we don't show this item again when the list // is being refreshed if (linkedkeywordlist != null) { linkedkeywordlist = updateLinkedList(linkedkeywordlist, oldKw, newKw, 0); } // and update display updateDisplay(); } else { // the new name for keyword already exists, so we can offer to merge // the keywords here. in fact, this is an easy find/replace-routine, since the // old keyword is replaced by the existing one, when we merge them. // // create a JOptionPane with yes/no/cancel options int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("mergeKeywordMsg"), getResourceMap().getString("mergeKeywordTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if no merge is requested, leave method if (JOptionPane.NO_OPTION == option) { return; } // merge the keywords by opening a dialog with a background task // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_MERGEKEYWORDS, data, taskinfo, oldKw, newKw, null, jTableKeywords, selectedrows[cnt], linkedkeywordlist); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // update the merged linked list linkedkeywordlist = taskinfo.getLinkedValues(); // now we want either to rename synonyms-index-words of the keyword // "oldKw", since this keyword has been renamed. or, if the new keyword // name "newKw" also has associated synonyms, we want to merge them. Tools.mergeSynonyms(synonyms, oldKw, newKw); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableKeywords.getRowCount()) + " " + getResourceMap().getString("statusTextKeywords") + ")"); // finally, update display updateDisplay(); // try to motivate garbage collector System.gc(); } } } else { // display error message box JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("noKeywordSelectedMsg", oldKw, synonyms.getIndexWord(oldKw, true)), getResourceMap().getString("noKeywordSelectedTitle"), JOptionPane.PLAIN_MESSAGE); } } } /** * This action opens an input dialog and lets the user input a new title-value. * The currently selected title is then being changed and the modified state set. */ @Action(enabledProperty = "tableEntriesSelected") public void editTitle() { // get the selected row int row = jTableTitles.getSelectedRow(); // get entry number int entry = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableTitles, 0); // if now row is selected, leave... if ((-1 == row) || (-1 == entry)) return; // open an input-dialog, setting the selected value as default-value String newt = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("editTitleMsg"), getResourceMap().getString("editTitleTitle"), JOptionPane.PLAIN_MESSAGE, null, null, jTableTitles.getValueAt(row, 1)); // if we have a valid return-value... if ((newt != null) && (newt.length() > 0)) { // change the existing value in the table jTableTitles.setValueAt(newt, row, 1); // and change the title to the new value data.setZettelTitle(entry, newt); // change edited timestamp data.changeEditTimeStamp(entry); // and update display updateDisplayParts(entry); } } /** * This method deletes selected keywords in the jListEntryKeywords from * an entry. Therefore, the selected values are passed as parameter to a method * that identifies the index-numbers and removes them from the entry's keyword-index-numbers. * <br><br> * This method is called when the user presses the delete-key in the keywordlist or * activated the related popup-menu-item. */ @Action(enabledProperty = "listFilledWithEntry") public void deleteKeywordFromEntry() { // get the selected values of the keyword-list String[] kws = retrieveSelectedKeywordsFromList(); // if we have any selections, go on... if ((kws != null) && (kws.length > 0)) { // prepare the msg-string String msg; // if we have just a single selection, use phrasing for that message msg = (1 == kws.length) ? getResourceMap().getString("askForDeleteKeywordMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteKeywordMsgMultiple", String.valueOf(kws.length)); // ask whether keyword really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteKeywordTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // delete keywords from current entry data.deleteKeywordsFromEntry(kws, displayedZettel); // update the data (frequency of occurences of keywords) from the jTableKeywords and linked filter-list for (String k : kws) linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableKeywords, linkedkeywordlist, k, -1); // update display updateDisplayParts(displayedZettel); } } } @Action public void showInformationBox() { if (null == informationDlg) { informationDlg = new CInformation(getFrame(), data, settings); informationDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(informationDlg); // 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) informationDlg.dispose(); informationDlg = null; // try to motivate garbage collector System.gc(); } /** * This method deletes a keyword which is currently selected in the JTableKeywords. */ @Action(enabledProperty = "tableEntriesSelected") public void deleteKeyword() { // get the amount of selected keywords. int rowcount = jTableKeywords.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // prepare the msg-string String msg; // if we have just a single selection, use phrasing for that message msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteKeywordMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteKeywordMsgMultiple", String.valueOf(rowcount)); // ask whether keyword really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteKeywordTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // and delete the keywords by opening a dialog with a background task // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_DELETEKEYWORDS, data, ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0)); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // try to motivate garbage collector System.gc(); // remove entries also from table and linked list linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyRemove(jTableKeywords, linkedkeywordlist, this); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableKeywords.getRowCount()) + " " + getResourceMap().getString("statusTextKeywords") + ")"); // finally, update display updateDisplay(); } } /** * This action deletes one or more selected bookmarks from the jTabelBookmarks. */ @Action(enabledProperty = "tableEntriesSelected") public void deleteBookmark() { // get the amount of selected bookmarks. int rowcount = jTableBookmarks.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // if we have just a single selection, use phrasing for that message String msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteBookmarkMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteBookmarkMsgMultiple", String.valueOf(rowcount)); // ask whether author really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteBookmarkTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, do so if (JOptionPane.YES_OPTION == option) { // delete bookmarks bookmarks.deleteBookmarks( ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableBookmarks, 0)); // update display updateDisplay(); } } @Action(enabledProperty = "tableEntriesSelected") public void deleteAttachment() { // get the amount of selected keywords. int rowcount = jTableAttachments.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // prepare the msg-string String msg; // if we have just a single selection, use phrasing for that message msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteAttachmentMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteAttachmentMsgMultiple", String.valueOf(rowcount)); // ask whether keyword really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteAttachmentTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // get selected keywords String[] selectedattachments = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAttachments, 0); // if now row is selected, leave... if (null == selectedattachments) return; // retrieve the selected enty-numbers int[] entrynumbers = ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableAttachments, 2); // check for valid values if (entrynumbers != null && entrynumbers.length > 0) { // go through all selected keywords for (int cnt = 0; cnt < selectedattachments.length; cnt++) data.deleteAttachment(selectedattachments[cnt], entrynumbers[cnt]); } // update display updateDisplay(); } } /** * This action opens an attachment which was double-clicked within the jTableAttachments from the * tabbed pane. */ @Action public void openAttachment() { // get selected row int selectedrow = jTableAttachments.getSelectedRow(); // if we have no selection, leave... if (-1 == selectedrow) return; // get selected value String linktype = jTableAttachments.getValueAt(selectedrow, 0).toString(); // and open hyperlink openHyperlink(linktype); } /** * This method opens a file or URL either from within a clicked link inside the jEditorPane (see * {@link #eventHyperlinkActivated(javax.swing.event.HyperlinkEvent) eventHyperlinkActivated(javax.swing.event.HyperlinkEvent)} * or from the attachment-list (see {@link #openAttachment() openAttachment()}. * * @param linktype the clicked link as string */ private void openHyperlink(String linktype) { // call method that handles the hyperlink-click String returnValue = Tools.openHyperlink(linktype, getFrame(), Constants.FRAME_MAIN, data, bibtex, settings, jEditorPaneEntry, displayedZettel); // 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) { // here we have a reference to another entry if (returnValue.startsWith("#z_") || returnValue.equals("#activatedEntry") || returnValue.startsWith("#cr_")) { // show entry showEntry(data.getCurrentZettelPos()); } // edit cross references else if (returnValue.equalsIgnoreCase("#crt")) { editManualLinks(); } // check whether a rating was requested else if (returnValue.startsWith("#rateentry")) { try { // retrieve entry-number int entrynr = Integer.parseInt(linktype.substring(10)); // open rating-dialog if (null == rateEntryDlg) { rateEntryDlg = new CRateEntry(getFrame(), data, entrynr); rateEntryDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(rateEntryDlg); // check whether dialog was cancelled or not if (!rateEntryDlg.isCancelled()) { // update display updateZettelContent(entrynr); } rateEntryDlg.dispose(); rateEntryDlg = null; // try to motivate garbage collector System.gc(); } catch (NumberFormatException ex) { // log error Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); Constants.zknlogger.log(Level.WARNING, "Could not rate entry. Link-text was {0}", linktype); } } // the user clicked on the created or edited timestamp and wants to edit this timestamp else if (returnValue.startsWith("#tstampc") || returnValue.startsWith("#tstampe")) { // init value String defaulttimestamp = ""; // wait for valid input while (defaulttimestamp != null && defaulttimestamp.isEmpty()) { // get timestamp, either created or edited, depending on which timestamp was clicked String ts = Tools.getProperShortDate( (returnValue.startsWith("#tstampc")) ? data.getTimestampCreated(displayedZettel) : data.getTimestampEdited(displayedZettel)); // show input-dialog defaulttimestamp = (String) JOptionPane.showInputDialog(getFrame(), // parent window getResourceMap().getString("editTimeStampMsg"), // message text getResourceMap().getString("editTimeStampTitle"), // messagebox title JOptionPane.PLAIN_MESSAGE, // type of dialog null, // icon null, // array of selection values. // must be null to get an input-field. // providing an array here would create a dropdown-combobox ts); // initial value, date of importfile // now convert the user input into a timestamp // therefore, check whether we have any valid input at all, if we have the correct length (16 chars) // and if we have to "." at the right position. A valid input would be e.g. "31.12.08 05:46" (dd.mm.yy hh:mm) if (defaulttimestamp != null && 16 == defaulttimestamp.length() && defaulttimestamp.charAt(2) == '.' && defaulttimestamp.charAt(5) == '.' && defaulttimestamp.charAt(10) == ' ' && defaulttimestamp.charAt(13) == ':') { // check for number values try { defaulttimestamp = defaulttimestamp.substring(8, 10) + defaulttimestamp.substring(3, 5) + defaulttimestamp.substring(0, 2) + defaulttimestamp.substring(11, 13) + defaulttimestamp.substring(14); // is input valid? (i.e. only numbers) Integer.parseInt(defaulttimestamp); // set new timestamp if (returnValue.startsWith("#tstampc")) data.setTimestampCreated(displayedZettel, defaulttimestamp); else data.setTimestampEdited(displayedZettel, defaulttimestamp); // update display updateDisplayParts(displayedZettel); } // the user did not edit a valid date, and probably used chars instead of numbers catch (NumberFormatException ex) { // reset value, so the input can be done again defaulttimestamp = ""; } catch (IndexOutOfBoundsException ex) { // reset value, so the input can be done again defaulttimestamp = ""; } } else { if (defaulttimestamp != null) defaulttimestamp = ""; } } } // in case a footnote was clicked and the user wishes to display the author in the related // author table, do this now... else { // display tabbed pane with authors jTabbedPaneMain.setSelectedIndex(TAB_AUTHORS); // we now want to display the author in the jTable. Therefore, // we go through all entries of the table and search for the related string-vaule for (int cnt = 0; cnt < jTableAuthors.getRowCount(); cnt++) { // get each table-value String row = jTableAuthors.getValueAt(cnt, 0).toString(); // compare to requested author-string if (row.equals(returnValue)) { // if we found a match, select table row jTableAuthors.setRowSelectionInterval(cnt, cnt); // and make sure the selected row is visible... jTableAuthors.scrollRectToVisible(jTableAuthors.getCellRect(cnt, 0, false)); break; } } } } } @Action(enabledProperty = "tableEntriesSelected") public void openAttachmentDirectory() { // get selected row int selectedrow = jTableAttachments.getSelectedRow(); // if we have no selection, leave... if (-1 == selectedrow) return; // get selected value File filepath = FileOperationsUtil.getLinkFile(settings, data, jTableAttachments.getValueAt(selectedrow, 0).toString()); // check whether selected file exists if (filepath.exists()) { // if yes retrieve directory-path and open it. String path = filepath.toString().substring(0, filepath.toString().lastIndexOf(File.separatorChar)); // open path ZettelkastenViewUtil.openFilePath(path, settings); } } /** * This method deletes one or more manual links from the jTableManLinks */ @Action(enabledProperty = "tableEntriesSelected") public void deleteManualLink() { // get the amount of selected bookmarks. int rowcount = jTableManLinks.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // if we have just a single selection, use phrasing for that message String msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteManLinksMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteManLinksMsgMultiple", String.valueOf(rowcount)); // ask whether author really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteManLinksTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, do so if (JOptionPane.YES_OPTION == option) { // delete bookmarks data.deleteManualLinks(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableManLinks, 0)); // update display updateDisplay(); } } @Action(enabledProperty = "tableEntriesSelected") public void deleteBookmarkCategory() { // get the amount of selected bookmarks. int rowcount = jTableBookmarks.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // retrieve selected category Object selcat = jTableBookmarks.getValueAt(jTableBookmarks.getSelectedRow(), 1); // if we have just a single selection, use phrasing for that message String msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteBookmarkCategoryMsgSingle", (selcat != null) ? selcat.toString() : "") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteBookmarkCategoryMsgMultiple", String.valueOf(rowcount)); // ask whether author really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteBookmarkCategoryTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, do so if (JOptionPane.YES_OPTION == option) { // retrieve selected values String[] bmcats = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableBookmarks, 1); // if we have any selection, go on if (bmcats != null && bmcats.length > 0) { // iterate all selected values for (String bc : bmcats) { // get the table data at the selected row bookmarks.deleteCategory(bc); } // update display updateDisplay(); } } } /** * This method deletes the selected author(s), which is/are currently selected * in the JTableAuthors. */ @Action(enabledProperty = "tableEntriesSelected") public void deleteAuthor() { // get the amount of selected keywords. int rowcount = jTableAuthors.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // prepare the msg-string String msg; // if we have just a single selection, use phrasing for that message msg = (1 == rowcount) ? getResourceMap().getString("askForDeleteAuthorMsgSingle") // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteAuthorMsgMultiple", String.valueOf(rowcount)); // ask whether author really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteAuthorTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, do so if (JOptionPane.YES_OPTION == option) { // and delete the authors by opening a dialog with a background task // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_DELETEAUTHORS, data, ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0)); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // try to motivate garbage collector System.gc(); // update the tables and the possible linked lists linkedauthorlist = ZettelkastenViewUtil.updateTableFrequencyRemove(jTableAuthors, linkedauthorlist, this); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableAuthors.getRowCount()) + " " + getResourceMap().getString("statusTextAuthors") + ")"); // finally, update display updateDisplay(); } } @Action public void newKeyword() { // open an input-dialog String newKw = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("newKeywordMsg"), getResourceMap().getString("newKeywordTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid return-value... if ((newKw != null) && (newKw.length() > 0)) { // ask the user if he wants to replace possible keywords, which appear as synonyms, but *not* // as index-word, with the related index-words... newKw = Tools.replaceSynonymsWithKeywords(synonyms, new String[] { newKw })[0]; // check whether action was cancelled. if so, null is returned. if (newKw != null) { // check whether the value already exists if (-1 == data.getKeywordPosition(newKw, false)) { // add keyword to data file data.addKeyword(newKw, 0); // save new keyword value, so it can be selected in the table newAddedKeyword = newKw; // add keyword to table and linked filter-list linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyNew(jTableKeywords, linkedkeywordlist, newKw, 0); // update display updateDisplay(); } else { // display error message box JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errValueExistsMsg", newKw), getResourceMap().getString("errValueExistsTitle"), JOptionPane.PLAIN_MESSAGE); } } } } @Action public void newAuthor() { // 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(getFrame(), settings, getResourceMap().getString("newAuthorTitle"), "", "", Constants.EDIT_AUTHOR); // center window biggerEditDlg.setLocationRelativeTo(getFrame()); } // show window ZettelkastenApp.getApplication().show(biggerEditDlg); // after closing the window, get the new value String newAu = biggerEditDlg.getNewValue(); String newBibKey = biggerEditDlg.getNewBibKey(); // delete the input-dialog biggerEditDlg.dispose(); biggerEditDlg = null; // if we have a valid return-value... if ((newAu != null) && (newAu.length() > 0)) { // get system line separator String linesep = System.getProperty("line.separator"); // 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 (linesep.contains("\r")) newAu = newAu.replace("\r", ""); // ...parse them to an array String[] authors = newAu.split("\n"); for (String a : authors) { // if we have an empty string, do nothing... if (!a.isEmpty()) { // check whether the value already exists if (-1 == data.getAuthorPosition(a)) { // add author to data file data.addAuthor(a, 0); // change bibkey if (newBibKey != null) { data.setAuthorBibKey(a, newBibKey); // reset bibkey, so we only use it once in case we have multiple authors newBibKey = null; } // save author-value so it can be selected in the table newAddedAuthor = a; // add author to jTableAuthors and to the linked filtered list linkedauthorlist = ZettelkastenViewUtil.updateTableFrequencyNew(jTableAuthors, linkedauthorlist, a, 0); } else { // when we have a too long author-string, we truncate it so we can // display the complete error message. if (a.length() > 40) a = a.substring(0, 39) + "..."; // display error message box JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errValueExistsMsg", a), getResourceMap().getString("errValueExistsTitle"), JOptionPane.PLAIN_MESSAGE); } } } // update display updateDisplay(); } } /** * This method deletes entries which are selected in the titles-table (jTableTitles). The currently * displayed entry can also be deleted via toolbar or menu. see {@link #deleteCurrentEntry() deleteCurrentEntry()} * for more details. */ @Action(enabledProperty = "tableEntriesSelected") public void deleteEntry() { // get the amount of selected entries. int rowcount = jTableTitles.getSelectedRowCount(); // if nothing is selected, leave if (rowcount < 1) return; // get the selected rows int[] rows = jTableTitles.getSelectedRows(); // get the entrie-strings int[] nrs = new int[rows.length]; // copy all values into the integer array for (int cnt = 0; cnt < rows.length; cnt++) { try { // get the entry's number int nr = Integer.parseInt(jTableTitles.getValueAt(rows[cnt], 0).toString()); // save it to the array nrs[cnt] = nr; } catch (NumberFormatException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } } // try to delete entries. this method shows an option pane where the user can // confirm the delete-progress or cancel it. if cancelled, the method returns false if (deleteEntries(nrs)) { // set uptodate-state to false data.setTitlelistUpToDate(false); // update jTableTitles showTitles(); } } public void bringToFront() { super.getFrame().setAlwaysOnTop(true); super.getFrame().toFront(); super.getFrame().requestFocus(); super.getFrame().setAlwaysOnTop(false); } /** * Deletes one or more entries which entry-numbers are passed as int-array * @param nrs the index-numbers of the entries that should be deleted * @return {@code true} if entries were deleted, {@code false} is deletion was cancelled */ public boolean deleteEntries(int[] nrs) { // when we have no entries in the array, return if ((null == nrs) || (nrs.length < 1)) return false; // when we are editing an entry, check whether the to be deleted entry is currently edited. // if yes, cancel deletion if (isEditModeActive && newEntryDlg != null) { // go through all entries that should be deleted for (int n : nrs) { // if one of those to be deleted entries is currently being edited, cancel deletion if (n == newEntryDlg.entryNumber) { // show error message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("deleteNotPossibleMsg"), getResourceMap().getString("deleteNotPossibleTitle"), JOptionPane.PLAIN_MESSAGE); // display edit-dialog newEntryDlg.toFront(); // leave method return false; } } } // create a linked list that contains all entries, so we check whether one or more of // the to be deleted entries are also appearing in one or more desktop-files. // but first, check, whether we have any desktops at all... if (desktop.getCount() > 0) { // create linked list LinkedList<Integer> checkEntries = new LinkedList<Integer>(); // copy all to be deleted entries to the linked list for (int n : nrs) checkEntries.add(n); // now check whether one or more entries of the to be deleted entries appear in one or // more desktop-files and ask the user, whether the entries really should be deleted String multipleOccurencesMessage = Tools .prepareDoubleEntriesMessage(Tools.retrieveDoubleEntries(desktop, checkEntries)); // if we have any return-value, go on... if (multipleOccurencesMessage != null) { // get system line separator String linesep = System.getProperty("line.separator"); multipleOccurencesMessage = getResourceMap().getString("askForDeleteEntriesOnDesktop") + linesep + linesep + multipleOccurencesMessage; // create output window if (null == multipleOccurencesDlg) { // create a new dialog with the desktop-dialog, passing some initial values multipleOccurencesDlg = new CShowMultipleDesktopOccurences(getFrame(), settings, true, multipleOccurencesMessage); // center window multipleOccurencesDlg.setLocationRelativeTo(null); } else multipleOccurencesDlg.setInfoMsg(multipleOccurencesMessage); // show window ZettelkastenApp.getApplication().show(multipleOccurencesDlg); } } // if we have just a single selection, use phrasing for that message String msg = (1 == nrs.length) ? getResourceMap().getString("askForDeleteEntryMsgSingle", String.valueOf(nrs[0])) // else if we have multiple selectios, use phrasing with appropriate wording : getResourceMap().getString("askForDeleteEntryMsgMultiple", String.valueOf(nrs.length)); // ask whether entry really should be deleted int option = JOptionPane.showConfirmDialog(getFrame(), msg, getResourceMap().getString("askForDeleteEntryTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if yes, go on if (JOptionPane.YES_OPTION == option) { // delete entries for (int cnt = 0; cnt < nrs.length; cnt++) { // first, retrieve the entry's authors, so we can update the table jTableAuthors, // by decreasing the frequencies... String[] aus = data.getAuthors(nrs[cnt]); if (aus != null) for (String a : aus) linkedauthorlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableAuthors, linkedauthorlist, a, -1); // then, retrieve the entry's keywords, so we can update the table jTableKeywords, // by decreasing the frequencies... String[] kws = data.getKeywords(nrs[cnt]); if (kws != null) for (String k : kws) linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableKeywords, linkedkeywordlist, k, -1); // finally, we can remove that entry data.deleteZettel(nrs[cnt]); } // remove entries from desktop... if (desktop.deleteEntries(nrs) && desktopDlg != null) desktopDlg.updateEntriesAfterEditing(); // remove entries from bookmarks... bookmarks.deleteBookmarks(nrs); // manual links and the entry's content are deleted via the CDaten-class. // but it might be that deleting the entry from luhmann-numbers, desktop-data // and search results is quite time consuming. thus, we delete those parts // in an exra background-task // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_DELETEENTRY, data, searchrequests, nrs); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // when the search dialog is opened, remove entry from list... if (searchResultsDlg != null) searchResultsDlg.updateComboBox(-1, -1); // try to motivate garbage collector System.gc(); // finally, update display updateDisplay(); // entries deleted, so return true return true; } return false; } private void filterTitleList(boolean forceRegEx) { LinkedList<Object[]> l = filterList(jTextFieldFilterTitles, jTableTitles, jButtonRefreshTitles, linkedtitlelist, "statusTextTitles", 1, forceRegEx); if (l != null) linkedtitlelist = l; } private LinkedList<Object[]> filterList(JTextField filterfield, JTable table, JButton refreshbutton, LinkedList<Object[]> list, String resourcestring, int column, boolean forceRegEx) { // when we filter the table and want to restore it, we don't need to run the // time-consuming task that creates the author-list and related author-frequencies. // instead, we simply copy the values from the linkedlist to the table-model, which is // much faster. but therefore we have to apply all changes to the filtered-table // (like adding/changing values in a filtered list) to the linked list as well. // get text from the textfield containing the filter string // convert to lowercase, we don't want case-sensitive search String text = filterfield.getText(); // when we have no text, do nothing if (text.isEmpty()) return null; // tell table selection listener we are doing something, so don't react on value-changes tableUpdateActive = true; // get table model DefaultTableModel dtm = (DefaultTableModel) table.getModel(); // if we haven't already stored the current complete table data, do this now if (null == list) { // create new instance of list list = new LinkedList<Object[]>(); // go through all table-data for (int cnt = 0; cnt < dtm.getRowCount(); cnt++) { // init the object-variable Object[] o; // in case we have the table with titles, we make an exception, because // this table has two more columns that should be filtered, the columns with // the entries timestamps. if (table == jTableTitles) { o = new Object[5]; } // in case we have the table with attachments, we make an exception, because // this table has one more column that should be filtered else if (table == jTableAttachments) { o = new Object[3]; } // for each "typical" table, we have two columns else { o = new Object[2]; } // fill object with values for (int len = 0; len < o.length; len++) { o[len] = dtm.getValueAt(table.convertRowIndexToModel(cnt), len); } // add object to linked list list.add(o); } } int[] columns; if (table == jTableTitles) { columns = new int[] { column, 2, 3, 4 }; } else { columns = new int[] { column }; } de.danielluedecke.zettelkasten.util.TableUtils.filterTable(table, dtm, text, columns, forceRegEx); // reset textfield if (!forceRegEx) filterfield.setText(""); filterfield.requestFocusInWindow(); // enable textfield only if we have more than 1 element in the jtable filterfield.setEnabled(table.getRowCount() > 0); // enable refresh button refreshbutton.setEnabled(true); // show amount of entries statusMsgLabel.setText( "(" + String.valueOf(table.getRowCount()) + " " + getResourceMap().getString(resourcestring) + ")"); // all changes have been done... tableUpdateActive = false; // return list with new entries. return list; } @Action public void refreshTitleList() { refreshList(jTableTitles, jButtonRefreshTitles, jTextFieldFilterTitles, linkedtitlelist, "statusTextTitles"); linkedtitlelist = null; } @Action public void filterClusterList() { // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeCluster.getModel(); // and receive the root MutableTreeNode root = (MutableTreeNode) dtm.getRoot(); // get the filter text String text = jTextFieldFilterCluster.getText().toLowerCase(); // if we have any root and filter-text, go on if (root != null && !text.isEmpty()) { // go through all root's children for (int cnt = dtm.getChildCount(root) - 1; cnt >= 0; cnt--) { // get the child-node MutableTreeNode child = (MutableTreeNode) dtm.getChild(root, cnt); // get the node's text String childtext = child.toString().toLowerCase(); // if the child does *not* contains the filtertext, remove it if (!childtext.contains(text)) dtm.removeNodeFromParent(child); } // if the filtering removed a selected node, clear the jListCluster if (null == jTreeCluster.getSelectionPath()) { clusterList.clear(); // and show current entry again // TODO aktiuellen Zettel zeigen? } // indicate that we have filtered the list linkedclusterlist = true; // reset textfield jTextFieldFilterCluster.setText(""); jTextFieldFilterCluster.requestFocusInWindow(); // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterCluster.setEnabled(jTreeCluster.getRowCount() > 0); // enable refresh button jButtonRefreshCluster.setEnabled(true); } } @Action public void refreshClusterList() { // first check whether we have filtered the list if (linkedclusterlist) { // if yes, init the list initClusterList(); // enable filter field jTextFieldFilterCluster.setEnabled(true); // disable refresh button jButtonRefreshCluster.setEnabled(false); } } private void filterAuthorList(boolean forceRegEx) { LinkedList<Object[]> l = filterList(jTextFieldFilterAuthors, jTableAuthors, jButtonRefreshAuthors, linkedauthorlist, "statusTextAuthors", 0, forceRegEx); if (l != null) linkedauthorlist = l; } private void filterAttachmentList(boolean forceRegEx) { LinkedList<Object[]> l = filterList(jTextFieldFilterAttachments, jTableAttachments, jButtonRefreshAttachments, linkedattachmentlist, "statusTextAttachments", 0, forceRegEx); if (l != null) linkedattachmentlist = l; } @Action public void refreshAuthorList() { refreshList(jTableAuthors, jButtonRefreshAuthors, jTextFieldFilterAuthors, linkedauthorlist, "statusTextAuthors"); linkedauthorlist = null; } private void refreshList(JTable table, JButton refreshbutton, JTextField filterfield, LinkedList<Object[]> list, String resourcestring) { // first check whether we have any saved values at all if (list != null) { // table-values might be changed, so selection listener should not react tableUpdateActive = true; // get table model DefaultTableModel dtm = (DefaultTableModel) table.getModel(); // delete all data from the author-table dtm.setRowCount(0); // create an iterator for the linked list ListIterator<Object[]> iterator = list.listIterator(); // go through complete linked list and add each element to the table(model) while (iterator.hasNext()) dtm.addRow(iterator.next()); // enable filter field filterfield.setEnabled(true); // disable refresh button refreshbutton.setEnabled(false); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(table.getRowCount()) + " " + getResourceMap().getString(resourcestring) + ")"); // all changes have been made... tableUpdateActive = false; } } @Action public void refreshAttachmentList() { refreshList(jTableAttachments, jButtonRefreshAttachments, jTextFieldFilterAttachments, linkedattachmentlist, "statusTextAttachments"); linkedattachmentlist = null; } /** * This method opens a dialog with the data from the currently selected bookmarks. The user * can then make changes like changing the category, editing comments etc.<br><br> * Changes are immediatly applied to the jTableBookmarks. */ @Action(enabledProperty = "tableEntriesSelected") public void editBookmark() { // get the selected row int row = jTableBookmarks.getSelectedRow(); // if now row is selected, leave... if (-1 == row) return; // else change bookmark entry addToBookmarks(new int[] { ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableBookmarks, 0) }, true); } /** * This method opens an input-dialog where the user can edit a bookmark's category-name. * After that, all bookmarks with the old category-name get this new entered category-name. * <br><br> * If the new name already exists, the categories are merged. */ @Action(enabledProperty = "tableEntriesSelected") public void editBookmarkCategory() { // get the selected row int row = jTableBookmarks.getSelectedRow(); // if now row is selected, leave... if (-1 == row) return; // save the old value String oldbm = jTableBookmarks.getValueAt(row, 1).toString(); // open an input-dialog, setting the selected value as default-value String newbm = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("editBookmarkCategoryMsg"), getResourceMap().getString("editBookmarkCategoryTitle"), JOptionPane.PLAIN_MESSAGE, null, null, jTableBookmarks.getValueAt(row, 1)); // if we have a valid return-value that does not equal the old value... if ((newbm != null) && (newbm.length() > 0) && (!oldbm.equalsIgnoreCase(newbm))) { // check whether new category name already exists if (-1 == bookmarks.getCategoryPosition(newbm)) { // get index-number of old category int pos = bookmarks.getCategoryPosition(oldbm); // change category-name bookmarks.setCategory(pos, newbm); } // we know that the category already exists. here we cann offer merging... else { // get the position of old, previous category int oldpos = bookmarks.getCategoryPosition(oldbm); // get the position of the existing, new category int newpos = bookmarks.getCategoryPosition(newbm); // change category-index-numbers bookmarks.changeCategoryIndexOfBookmarks(oldpos, newpos); } // update the display showBookmarks(); } } @Action(enabledProperty = "tableEntriesSelected") public void editAttachment() { // get selected keywords String[] selectedattachments = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAttachments, 0); // if now row is selected, leave... if (null == selectedattachments) return; // get selected rows. we need this numbers for setting back the new values, see below int[] selectedrows = jTableAttachments.getSelectedRows(); // retrieve the selected enty-numbers int[] entrynumbers = ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableAttachments, 2); // check for valid values if (entrynumbers != null && entrynumbers.length > 0) { // go through all selected keywords for (int cnt = selectedattachments.length - 1; cnt >= 0; cnt--) { // save the old value String oldAt = selectedattachments[cnt]; // open an input-dialog, setting the selected value as default-value String newAt = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("editAttachmentMsg"), getResourceMap().getString("editAttachmentTitle"), JOptionPane.PLAIN_MESSAGE, null, null, oldAt); // if we have a valid return-value that differs from the old value... if ((newAt != null) && (newAt.length() > 0) && (!oldAt.equalsIgnoreCase(newAt))) { // change the existing value in the table jTableAttachments.setValueAt(newAt, selectedrows[cnt], 0); // update the possible file-extension jTableAttachments.setValueAt(FileOperationsUtil.getFileExtension(settings, data, newAt), selectedrows[cnt], 1); // also change the attachment in the data-file data.changeAttachment(oldAt, newAt, entrynumbers[cnt]); // if we have a filtered list, remove the element also from // our refresh-list, so we don't show this item again when the list // is being refreshed if (linkedattachmentlist != null) linkedattachmentlist = updateLinkedList(linkedattachmentlist, oldAt, newAt, 0); } // and update display updateDisplayParts(entrynumbers[0]); } } } private LinkedList<Object[]> updateLinkedList(LinkedList<Object[]> list, String oldvalue, String newvalue, int arrayindex) { // iterate list for (int pos = 0; pos < list.size(); pos++) { // get each element Object[] o = list.get(pos); // if element equals requested value, change frequency if (oldvalue.equals(o[arrayindex].toString())) { // change frequency valie o[arrayindex] = newvalue; // and set the element back to the list list.set(pos, o); break; } } return list; } @Action public void copyPlain() { Tools.copyPlain(data, displayedZettel, jEditorPaneEntry); } /** * This method opens a dialog to edit an author. When the edited author already exists, * the programm offers to "merge" the authors, and also all entries will be updated.<br><br> * Furthermore, when an edit-request was made while the author-list was filtered, the filtered * linkedlist is also being updated. */ @Action(enabledProperty = "tableEntriesSelected") public void editAuthor() { // get selected authors String[] selectedauthors = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0); // if now row is selected, leave... if (null == selectedauthors) return; // get selected rows. we need this numbers for setting back the new values, see below int[] selectedrows = jTableAuthors.getSelectedRows(); // go through all selected keywords for (int cnt = selectedauthors.length - 1; cnt >= 0; cnt--) { // save the old value String oldAu = selectedauthors[cnt]; // save old bibkey value String oldbibkey = data.getAuthorBibKey(oldAu); // 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(getFrame(), settings, getResourceMap().getString("editAuthorTitle"), oldAu, oldbibkey, Constants.EDIT_AUTHOR); // center window biggerEditDlg.setLocationRelativeTo(getFrame()); } // show window ZettelkastenApp.getApplication().show(biggerEditDlg); // after closing the window, get the new value String newAu = biggerEditDlg.getNewValue(); String newBibKey = biggerEditDlg.getNewBibKey(); // delete the input-dialog biggerEditDlg.dispose(); biggerEditDlg = null; // if we have a valid return-value that does not equal the old value... (so changed were made) if ((newAu != null) && (newAu.length() > 0) && (!oldAu.equalsIgnoreCase(newAu))) { // check whether the value already exists if (-1 == data.getAuthorPosition(newAu)) { // change the existing value in the table jTableAuthors.setValueAt(newAu, selectedrows[cnt], 0); // get the index-number of the old author-string int nr = data.getAuthorPosition(oldAu); // and change the entry to the new value data.setAuthor(nr, newAu, newBibKey); // if we have a filtered list, remove the element also from // our refresh-list, so we don't show this item again when the list // is being refreshed if (linkedauthorlist != null) linkedauthorlist = updateLinkedList(linkedauthorlist, oldAu, newAu, 0); } else { // the new name for author already exists, so we can offer to merge // the authors here. in fact, this is an easy find/replace-routine, since the // old author is replaced by the existing one, when we merge them. // create a JOptionPane with yes/no/cancel options int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("mergeAuthorMsg"), getResourceMap().getString("mergeAuthorTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if no merge is requested, leave method if (JOptionPane.NO_OPTION == option) return; // merge the authors by opening a dialog with a background task // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_MERGEAUTHORS, data, taskinfo, oldAu, newAu, newBibKey, jTableAuthors, selectedrows[cnt], linkedauthorlist); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // update the merged linked list linkedauthorlist = taskinfo.getLinkedValues(); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableAuthors.getRowCount()) + " " + getResourceMap().getString("statusTextAuthors") + ")"); // try to motivate garbage collector System.gc(); } // finally, update displayx updateDisplay(); // update authortext in textbox showAuthorText(); } } } @Action(enabledProperty = "tableEntriesSelected") public void changeBibkey() { if (setBibKeyDlg != null) { setBibKeyDlg.dispose(); setBibKeyDlg = null; System.gc(); } // open an input-dialog, setting the selected value as default-value if (null == setBibKeyDlg) { // create a new dialog with the bigger edit-field, passing some initial values setBibKeyDlg = new CSetBibKey(getFrame(), this, data, bibtex, settings); // center window setBibKeyDlg.setLocationRelativeTo(getFrame()); } // show window ZettelkastenApp.getApplication().show(setBibKeyDlg); } /** * @return The selected values from the jTableAuthors as String-ArrayList, or {@code null} * if no values have been selected */ public LinkedList<String> getSelectedAuthors() { String[] arr = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0); if (arr != null && arr.length > 0) { return new LinkedList(Arrays.asList(arr)); } return null; } /** * This method retrieves the selected keyword(s) from the jTableKeywords and adds * them to the keyword-list (jListKeywords). */ @Action(enabledProperty = "tableEntriesSelected") public void addKeywordToList() { // check for any selections. if nothing selected, leave if (jTableKeywords.getRowCount() < 1) return; // get selections if (!addKeywords(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), false)) JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("noNewKeywordsFoundMsg"), getResourceMap().getString("noNewKeywordsFoundTitle"), JOptionPane.PLAIN_MESSAGE); } private boolean addKeywords(String[] kws, boolean comesFromTextSelection) { // check for valid array if ((kws != null) && (kws.length > 0)) { // add keywords to entry... all relevant stuff like checking for multiple keywords, // synonyms or their related index-words etc. is done in this mehtod. an array of those // keywords that have been added is returned. kws = data.addKeywordsToEntry(kws, displayedZettel, 1); // iterate array and update table-frequencies. if (kws != null && kws.length > 0) { // update table with linked list. when "comesFromTextSelection" is true, we have // to check whether we have a completely new keyword, so we have to use the // updateTableFrequencyNew-method, or an existing one... if (comesFromTextSelection) { // we may have several keywords, since "comesFromTextSelection" is also true when // we have drag&drop from the jTableKeywords. In this case, we may have multiple keywords // dropped here for (String k : kws) { // when the added keyword was a textselection (see addToKeywordList()), the parameter // "comesFromTextSelection" is true. in this case, we check whether the keyword already // exists or not. if *not*, selectedKeywordExists is set to true - so we can use another // updateTable-Method below. in case we find the keyword, so it already exists, we leave // "selectedKeywordExists" to false, so below is a simple change-frequency update boolean selectedKeywordExists = (data.getKeywordPosition(k, false) != -1); // in this case we have an existing keyword from the text selection, so we need // to update the keyword-list if (selectedKeywordExists) { // to update the list, we have to select the added keyword in the // jTable. we do this here, and then we call the update method which // adds selected keywords as new keywords for (int cnt = 0; cnt < jTableKeywords.getRowCount(); cnt++) { // get each value String val = jTableKeywords.getValueAt(cnt, 0).toString(); // if table-value starts with the entered text in the textfield... if (val.equals(k)) { // ...select that value jTableKeywords.getSelectionModel().setSelectionInterval(cnt, cnt); // and make it visible jTableKeywords.scrollRectToVisible(jTableKeywords.getCellRect(cnt, 0, false)); } } linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableKeywords, linkedkeywordlist, k, 1); } // in this case we have a new keyword from the text selection, which is added // to the keyword-list else { linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyNew(jTableKeywords, linkedkeywordlist, k, 1); } } } // else when we have already existing keywords, update table with linked list using // the updateTableFrequencyChange-method. else { for (String k : kws) { if (!k.isEmpty()) linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableKeywords, linkedkeywordlist, k, 1); } } // update the display updateDisplay(); return true; } } return false; } /** * Adds the displayed entry to the bookmark list. */ @Action(enabledProperty = "entryBookmarked") public void addToBookmark() { addToBookmarks(new int[] { displayedZettel }, false); } /** * Adds one or more bookmarks to the bookmark-datafile. * * @param bms one or more bookmarks (entry-numbers) stored in an integer-array * @param edit true when existing bookmarks should be edited, false if new bookmarks * should be added. * @return {@code true} if bookmarks have been successfully added, false if an error occured */ public boolean addToBookmarks(int[] bms, boolean edit) { // return false on null or empty array if (null == bms || bms.length < 1) return false; // open the bookmark-dialog if (null == newBookmarkDlg) { // create a new dialog for editing new bookmarks newBookmarkDlg = new CNewBookmark(getFrame(), bookmarks, bms, edit, settings); // center window newBookmarkDlg.setLocationRelativeTo(getFrame()); } // show window ZettelkastenApp.getApplication().show(newBookmarkDlg); // when the dialog is not cancelled, update display if (!newBookmarkDlg.isCancelled()) { // update bookmarks-list if it is displayed if (TAB_BOOKMARKS == jTabbedPaneMain.getSelectedIndex()) showBookmarks(); // and toolbar updateToolbarAndMenu(); } // delete the input-dialog newBookmarkDlg.dispose(); newBookmarkDlg = null; // everything ok return true; } private void addAttachments(String[] att) { // add attachments data.addAttachments(displayedZettel, att); // update display displayZettelContent(displayedZettel); } /** * This method retrieves the selected authors(s) from the jTableAuthors and adds * them to the author-textfield of the entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addAuthorToList() { // check for any selections. if nothing selected, leave if (jTableAuthors.getRowCount() < 1) return; // get selections String[] aus = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0); addAuthorToList(aus); } private void addAuthorToList(String[] aus) { // check for valid array if ((aus != null) && (aus.length > 0)) { // iterate array for (String a : aus) { // if the author does not already exist in the current entry... if (!a.isEmpty() && !data.existsInAuthors(a, displayedZettel)) { // ...add it to that entry data.addAuthorToEntry(a, displayedZettel, 1); // and update table frequencies... linkedauthorlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableAuthors, linkedauthorlist, a, 1); } } // update the display updateZettelContent(displayedZettel); } } /** * This action shows the tab with the sub-entries of an entry. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowLuhmann() { jTabbedPaneMain.setSelectedIndex(TAB_LUHMANN); } /** * This action shows the tab with the authors of the main data. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowAuthors() { jTabbedPaneMain.setSelectedIndex(TAB_AUTHORS); } /** * This action shows the tab with the bookmarks. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowBookmarks() { jTabbedPaneMain.setSelectedIndex(TAB_BOOKMARKS); } private void showAttachments() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // reset status text, since the amount of titles is euqal to the amount of entries statusMsgLabel.setText(""); // show/enabke related menu showTabMenu(viewMenuAttachments); // if list is up to date, leave method if (data.isAttachmentlistUpToDate()) return; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SHOWATTACHMENTS, data, null /*only needed for authors*/, null /*only needed for authors*/, settings, false /*only need for keywords*/, 0 /*only need for authors*/, (DefaultTableModel) jTableAttachments.getModel()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterAttachments.setEnabled(jTableAttachments.getRowCount() > 0); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableAttachments.getRowCount()) + " " + getResourceMap().getString("statusTextAttachments") + ")"); // try to motivate garbage collector System.gc(); } /** * This method displays the all bookmarks in the jtable */ private void showBookmarks() { // fill bookmarked entries into table fillBookmarksToTables(bookmarks.getAllBookmarkedEntries()); // get all action listeners from the combo box ActionListener[] al = jComboBoxBookmarkCategory.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) jComboBoxBookmarkCategory.removeActionListener(listener); // clear combobox jComboBoxBookmarkCategory.removeAllItems(); // add first cat-description jComboBoxBookmarkCategory.addItem(getResourceMap().getString("bookmarkAllCategoriesText")); // retrieve bookmark-categories String[] bmcats = bookmarks.getCategoriesInSortedOrder(); // check if we have any categories if (bmcats != null && bmcats.length > 0) { // iterate array and add categories to combobox for (String bmc : bmcats) jComboBoxBookmarkCategory.addItem(bmc); } // add action listener to combo box jComboBoxBookmarkCategory.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { // get selection int selected = jComboBoxBookmarkCategory.getSelectedIndex(); // check for valid selection if (selected != -1) { // check whether first value was selected. if so, show all bookmarks if (0 == selected) { fillBookmarksToTables(bookmarks.getAllBookmarkedEntries()); } // else retrieve category and show only bookmarks of the selected category else { // retrieve selected category String cat = jComboBoxBookmarkCategory.getSelectedItem().toString(); // retrieve all bookmarks from that category fillBookmarksToTables(bookmarks.getBookmarkedEntriesFromCat(cat)); } // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableBookmarks.getRowCount()) + " " + getResourceMap().getString("statusTextBookmarks") + ")"); } } }); // show/enabke related menu showTabMenu(viewMenuBookmarks); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableBookmarks.getRowCount()) + " " + getResourceMap().getString("statusTextBookmarks") + ")"); } /** * This method fills all bookmarked entries, which are passed as parameter {@code bms}, * into the jTableBookmarks. * * @param bms an integer-array with all bookmarked entries. */ private void fillBookmarksToTables(int[] bms) { // get the table model DefaultTableModel tm = (DefaultTableModel) jTableBookmarks.getModel(); // reset the table tm.setRowCount(0); // check if we have any bookmarks at all if (bms != null && bms.length > 0) { // sort array Arrays.sort(bms); // go through all bookmark-entries for (int cnt = 0; cnt < bms.length; cnt++) { // get bookmark String[] bm = bookmarks.getCompleteBookmark(bookmarks.getBookmarkPosition(bms[cnt])); // check if bookmark exists if (bm != null) { // create a new object Object[] ob = new Object[2]; // store the information in that object ob[0] = Integer.parseInt(bm[0]); ob[1] = bm[1]; // and add that content as a new row to the table tm.addRow(ob); } } } } /** * This method displays the all authors in the author data file using * a background task. after the task finishes, all authors and their useage frequency * in the main data file (zknfile) are displayed in the JTable of the JTabbedPane */ private void showAuthors() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableAuthors.getRowCount()) + " " + getResourceMap().getString("statusTextAuthors") + ")"); // show/enable related menu showTabMenu(viewMenuAuthors); // if authorlist is up to date, leave method if (data.isAuthorlistUpToDate()) return; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SHOWAUTHORS, data, null /*only needed for keywords*/, bibtex, null /*only needed for attachments*/, false /*only needed for keywords*/, jComboBoxAuthorType.getSelectedIndex(), (DefaultTableModel) jTableAuthors.getModel()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have a new added author, and if so, select it if (newAddedAuthor != null) { // select recently added value de.danielluedecke.zettelkasten.util.TableUtils.selectValueInTable(jTableAuthors, newAddedAuthor, 0); // and clear strimg newAddedAuthor = null; } // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterAuthors.setEnabled(jTableAuthors.getRowCount() > 0); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableAuthors.getRowCount()) + " " + getResourceMap().getString("statusTextAuthors") + ")"); // try to motivate garbage collector System.gc(); } /** * This action shows the tab with the titles of the current data file. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowTitles() { jTabbedPaneMain.setSelectedIndex(TAB_TITLES); } /** * This action shows the tab with the titles of the current data file. * <br><br> * We need this action just for the menu command, so we can set keybindings * and resources to that menu item. it's better doing it like this rather * than having an actionPerformed-event. */ @Action public void menuShowCluster() { jTabbedPaneMain.setSelectedIndex(TAB_CLUSTER); } /** * This methods displays the entry which is selected in the titles-table * (jTableTitles). This method is especially called from the mouse-clicked * and key-released events from the jTableTitle. */ private void showEntryFromTitles() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // get the selected row int entry = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableTitles, 0); // if we don't have a valid selection, use current entry as reference if (-1 == entry) updateDisplayParts(data.getCurrentZettelPos()); // and if it was a avalid value, show entry else updateDisplayParts(entry); } /** * This methods displays the entry which is selected in the attachment-table * (jTableAttachment). This method is especially called from the mouse-clicked * and key-released events from the jTableTitle. */ private void showEntryFromAttachments() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // get the selected row int entry = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableAttachments, 2); // if we don't have a valid selection, use current entry as reference if (-1 == entry) updateDisplayParts(data.getCurrentZettelPos()); // and if it was a avalid value, show entry else updateDisplayParts(entry); } /** * This method retrieves the selected authors from the jTableAuthors and displays * in the text area on the author-tab, so the user can see the complete author-value. * the table-row usually is not wide enough to display the whole author-text */ public void showAuthorText() { // if no data available, leave method if (data.getCount(Daten.AUCOUNT) < 1) return; // get selected authors from table String[] aus = ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0); // if we have any selection, go on if (aus != null && aus.length > 0) { // string builder for output StringBuilder sb = new StringBuilder(""); // append style-definition String finalcontent = HtmlUbbUtil.getAuthorStyleDefinition(settings); // go through selected authors and add them to stringbuilder, // including possible bibkey-values. for (String a : aus) { // append author-value sb.append(a); // get author-bibkey String bibkey = data.getAuthorBibKey(a); // if bibkey available, add it as well if (bibkey != null && !bibkey.isEmpty()) sb.append(" <i>(Bibkey: ").append(bibkey).append(")</i>"); // add line-separators sb.append("<br><br>"); } // cut of last two line separators if (sb.length() > 0) sb.setLength(sb.length() - 8); finalcontent = finalcontent + "<body>" + sb.toString() + "</body>"; // show full author-text in text area jEditorPaneDispAuthor.setText(finalcontent); } else jEditorPaneDispAuthor.setText(""); } /** * This methods displays the entry which is selected in the bookmarks-table * (jTableBookmarks). This method is especially called from the mouse-clicked * and key-released events from the jTableBookmarks. */ private void showEntryFromBookmarks() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // get the entry number from selected bookmark int nr = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableBookmarks, 0); // if no entry is selected, show current entry if (-1 == nr) { // clear textfield content jEditorPaneBookmarkComment.setText(""); // and update display updateDisplayParts(data.getCurrentZettelPos()); } else { // get the selected row int row = jTableBookmarks.getSelectedRow(); // show comment of bookmark String comment = (row != -1) ? bookmarks.getCommentAsHtml(row) : ""; // show comment jEditorPaneBookmarkComment.setText(comment); // update displaypart updateDisplayParts(nr); } } private void showEntryFromManualLinks() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // get the selected row int entry = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableManLinks, 0); // if we don't have a valid selection, use current entry as reference if (-1 == entry) updateDisplayParts(data.getCurrentZettelPos()); // and if it was a avalid value, show entry else updateDisplayParts(entry); } /** * This method displays the the keyword-clusters, i.e. the relation between keywords and those * entries that contain all these related keywords. * <br><br> * Therefore, this method first displays all keywords as first-level-elements of the jTreeCluster. * Then, when a keyword is selected, this method searches for all entries that contain this * keyword and sets the related entry-numbers into the jListCluster. * <br><br> * After that, all keywords of those found entries are collected and displayed as children * of the selected keyword. This repeats for each selected keyword, i.e. if a children is selected, * the method searches for the selected keyword and all parent-keywords in the entries of the jList. * All entries, that contain each(!) keyword from the first-level-keyword to the selected child * will be displayed in the jList. */ private void showCluster() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // when a cluster-taks is already running, return if (createClusterIsRunning) return; // show/enabke related menu showTabMenu(viewMenuCluster); // if clusterlist is up to date, leave method if (data.isClusterlistUpToDate()) return; // reset status text, since the amount of titles is euqal to the amount of entries statusMsgLabel.setText(""); // init the cluster list. this method is separate, because we can // also use it for the "refreshClusterList()" method. initClusterList(); if (!jCheckBoxCluster.isSelected()) { // enable textfield only if we have more than 1 element in the jTree jTextFieldFilterCluster.setEnabled(jTreeCluster.getRowCount() > 1); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTreeCluster.getRowCount()) + " " + getResourceMap().getString("statusTextKeywords") + ")"); } } private synchronized void initClusterList() { // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeCluster.getModel(); // and first of all, clear the jTree dtm.setRoot(null); // get the amount of keywords int kwcount = data.getCount(Daten.KWCOUNT); // if we have no keywords, quit if (kwcount < 1) return; // if this checkbox is selected, we don't show the relations of *all* // keywords, but only of those keywords that appear in the current entry // and all related keywords of the current entry's keywords. if (jCheckBoxCluster.isSelected()) { // when a cluster-taks is already running, return if (createClusterIsRunning) return; // disable checkbox during task operation jCheckBoxCluster.setEnabled(false); // tell user that we are doing something... statusMsgLabel.setText(getResourceMap().getString("createLuhmannMsg")); Task ccT = clusterTask(); // 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(ccT); tM.setForegroundTask(ccT); } else { // else create a string array (for sorting the keywords) String[] kws = new String[kwcount]; // copy all keywords to that array for (int cnt = 1; cnt <= kwcount; cnt++) kws[cnt - 1] = data.getKeyword(cnt); // sort the array if (kws != null && kws.length > 0) Arrays.sort(kws, new Comparer()); // set this as root node. we don't need to care about this, since the // root is not visible. DefaultMutableTreeNode root = new DefaultMutableTreeNode("ZKN3-Cluster"); dtm.setRoot(root); // if we have any keywords, set them to the list if (kws != null) { // for each array in the keyword-array... for (String kw : kws) { // create a new node and add the keyword to the tree // remember that we might have empty keyword-entries in the array, which // have to be "removed" here if (!kw.isEmpty()) root.add(new DefaultMutableTreeNode(kw)); } // completely expand the jTree TreeUtil.expandAllTrees(true, jTreeCluster); } // we have no filtered list... linkedclusterlist = false; // indicate that the cluster list is up to date... data.setClusterlistUpToDate(true); } } /** * This method builds the cluster or keyword-relations. That means, all entries that contain * <b>all</b> keywords from the tree root through the selected path are extracted and displayed * in the related list. * <br><br> * After all Keywords from the selected path and their related entries are set to the list, * we get <b>all</b> keywords of the entries in that list. all new keywords, that do not * already appear in the tree-path, are added as new children to the last selected keyword * in the tree. Thus, by selecting a keyword, the related entries are shown and then the * remaining related keywords are addes as new children. */ private void showClusterRelations() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // if the link-table is not shown, leave if (jTabbedPaneMain.getSelectedIndex() != TAB_CLUSTER) return; // retrieve selected node DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeCluster.getLastSelectedPathComponent(); // if we have don't a valid selection, quit if (null == node) return; // get the treepath to the selection. this path contains all nodes from root // until to the selected child. we will set these nodes to the keywordlist TreePath tp = jTreeCluster.getLeadSelectionPath(); // disable tree, showing that the program works... jTreeCluster.setEnabled(false); // create a linked list. here we will add all keywords from the selection to the // first level paremt LinkedList<String> kws = new LinkedList<String>(); // start from the second element, since we don't want the root-element // and copy all nodes from this path to the linked list for (int cnt = 1; cnt < tp.getPathCount(); cnt++) kws.add(tp.getPathComponent(cnt).toString()); // now copy all related keywords into an array String[] keywords = kws.toArray(new String[kws.size()]); // copy all keywords to the string builder as well, so we can set the relations // as status msg label text StringBuilder sb = new StringBuilder(""); // and convert them to strings for (String kwsingle : keywords) sb.append(kwsingle).append(" + "); // trim string if (sb.length() > 3) sb.setLength(sb.length() - 3); // and set the relations as status message label if (!settings.isMacAqua()) statusMsgLabel.setText(sb.toString()); jTreeCluster.setToolTipText(sb.toString()); // remember this relation as "global variable" lastClusterRelationKeywords = sb.toString(); // clear list clusterList.clear(); // get count of entries int count = data.getCount(Daten.ZKNCOUNT); // go through all entries and get those entries // that contain *all* of the keywords in the array (true as parameter) for (int cnt = 1; cnt <= count; cnt++) if (data.existsInKeywords(keywords, cnt, true, false)) clusterList.add(String.valueOf(cnt)); // get selected node again node = (DefaultMutableTreeNode) jTreeCluster.getLastSelectedPathComponent(); // remove all children node.removeAllChildren(); // save the current size of the linked list. we will add all new keywords to this // list, but we may not set *all* keywords as children of "node", but only the // new ones - which start in this list at the index "previousSize". int previousSize = kws.size(); for (String clusterList1 : clusterList) { // get each entry-number of the list int nr = Integer.parseInt(clusterList1); // get the entry's keywords String[] entrykws = data.getKeywords(nr); // go through all keywords of this array // if the keyword does not already exist in the list, add it if (entrykws != null) for (String ek : entrykws) if (-1 == kws.indexOf(ek)) kws.add(ek); } // if we have any new keywords, i.e. children, go on if (kws.size() > previousSize) { // create string array with the size of the new children String[] children = new String[kws.size() - previousSize]; // receive all new element of that list // and copy them to the string array for (int cnt = 0; cnt < (kws.size() - previousSize); cnt++) children[cnt] = kws.get(cnt + previousSize); // sort the array if (children != null && children.length > 0) Arrays.sort(children, new Comparer()); // add each item as child of note // create and add a new child for (String c : children) node.add(new DefaultMutableTreeNode(c)); } // set cluster links jEditorPaneClusterEntries .setText(HtmlUbbUtil.getLinkedEntriesAsHtml(settings, clusterList, "clusterListText")); // enable tree, showing that the the method has finihsed jTreeCluster.setEnabled(true); jTreeCluster.requestFocusInWindow(); } /** * This action sorts follower entries in the jTreeLuhmann in the visible entry order. */ @Action(enabledProperty = "moreLuhmann") public void sortLuhmann() { // get current zettel int nr = data.getCurrentZettelPos(); // check whether it has followers if (data.hasLuhmannNumbers(nr)) { // get all follower entries int[] luhmanns = data.getAllLuhmannNumbers(nr); // and sort them data.moveEntries(luhmanns, nr); // update display updateDisplay(); } } /** * This method displays the all entries' titles using * a background task. after the task finishes, all titles and ther related entry number * in the main data file (zknfile) are displayed in the JTable of the JTabbedPane */ private void showTitles() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) return; // reset status text, since the amount of titles is euqal to the amount of entries statusMsgLabel.setText(""); // show/enabke related menu showTabMenu(viewMenuTitles); // if keywordlist is up to date, leave method if (data.isTitlelistUpToDate()) return; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SHOWTITLES, data, null /*only needed for keywords*/, null /*only needed for authors*/, null /*only needed for attachments*/, false /*only needed for keywords*/, 0 /*only needed for authors*/, (DefaultTableModel) jTableTitles.getModel()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // reset filtered list linkedtitlelist = null; // disable refresh button jButtonRefreshTitles.setEnabled(false); // enable textfield only if we have more than 1 element in the jtable jTextFieldFilterTitles.setEnabled(jTableTitles.getRowCount() > 0); // try to motivate garbage collector System.gc(); } /** * This Action creates the links between of the currently displayed entry with all other enries, * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane * * @return the background task */ @Action public Task createLinks() { return new createLinksTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } /** * This method adds the content of the clipboard as new entry. The new entry is created automatically, * where the clipboard content is used as entry content. No edit-window will be opened. */ @Action public void quickNewEntry() { // get the clipbaord Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); try { // retrieve clipboard content Transferable content = clipboard.getContents(null); // if we have any content, create new entry... if (content != null) { // first, copy clipboard to string String text = content.getTransferData(DataFlavor.stringFlavor).toString().trim(); // identify new-line/line-separator-char String sepval = (text.contains("\r\n")) ? "\r\n" : "\n"; // if we have any leading new lines, remove these // while (text.startsWith(System.getProperty("line.separator"))) { // text = text.substring(System.getProperty("line.separator").length()); // } while (text.startsWith(sepval)) { text = text.substring(sepval.length()); } // add text as new entry data.addEntry("", text, null, null, "", null, Tools.getTimeStamp(), -1, -1); // and titles might be out of date now as well... data.setTitlelistUpToDate(false); // tell about success Constants.zknlogger.log(Level.INFO, "Entry save finished."); // update the dislay... updateDisplay(); // tell about success Constants.zknlogger.log(Level.INFO, "Display updated."); // and create a backup... makeAutoBackup(); // tell about success Constants.zknlogger.log(Level.INFO, "Autobackup finished (if necessary)."); } } catch (IllegalStateException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } catch (IOException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } catch (UnsupportedFlavorException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } /** * This method adds the content of the clipboard as new entry. The first line of the clipboard content * will be automatically set as entry's title. The new entry is created automatically, * where the clipboard content is used as entry content. No edit-window will be opened. */ @Action public void quickNewEntryWithTitle() { // get the clipbaord Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); try { // retrieve clipboard content Transferable content = clipboard.getContents(null); // if we have any content, create new entry... if (content != null) { // first, copy clipboard to string String text = content.getTransferData(DataFlavor.stringFlavor).toString().trim(); // identify new-line/line-separator-char String sepval = (text.contains("\r\n")) ? "\r\n" : "\n"; String title = ""; // if we have any leading new lines, remove these while (text.startsWith(sepval)) { text = text.substring(sepval.length()); } // retrieve first line int pos = text.indexOf(sepval); // if we have more than one line, a first line is found if (pos != -1) { // cut first line and set it as title title = text.substring(0, pos).trim(); // remove first line from text text = text.substring(pos); // if we have any leading new lines, remove these while (text.startsWith(sepval)) { text = text.substring(sepval.length()); } } // // if we have any leading new lines, remove these // while (text.startsWith(System.getProperty("line.separator"))) { // text = text.substring(System.getProperty("line.separator").length()); // } // // retrieve first line // int pos = text.indexOf(System.getProperty("line.separator")); // // if we have more than one line, a first line is found // if (pos!=-1) { // // cut first line and set it as title // title = text.substring(0, pos).trim(); // // remove first line from text // text = text.substring(pos); // // if we have any leading new lines, remove these // while (text.startsWith(System.getProperty("line.separator"))) { // text = text.substring(System.getProperty("line.separator").length()); // } // } // add text as new entry data.addEntry(title, text, null, null, "", null, Tools.getTimeStamp(), -1, -1); // and titles might be out of date now as well... data.setTitlelistUpToDate(false); // tell about success Constants.zknlogger.log(Level.INFO, "Entry save finished."); // update the dislay... updateDisplay(); // tell about success Constants.zknlogger.log(Level.INFO, "Display updated."); // and create a backup... makeAutoBackup(); // tell about success Constants.zknlogger.log(Level.INFO, "Autobackup finished (if necessary)."); } } catch (IllegalStateException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } catch (IOException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } catch (UnsupportedFlavorException e) { Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage()); } } /** * This method inits the system tray. if supported, the program's window does not deiconfy/minimize * to the taskbar, but hides and displays an icon in the system tray instead. */ private void initSystemTray() { // if systemtray is not supported, leave method if (!SystemTray.isSupported()) return; // create tray-icon with tooltip trayIcon = new TrayIcon((new ImageIcon( org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getClass() .getResource("/de/danielluedecke/zettelkasten/resources/icons/zkn3_16x16.png"), "Zettelkasten")).getImage()); // retrieve system tray tray = SystemTray.getSystemTray(); // try to add the tray icon to the systray try { tray.add(trayIcon); } catch (AWTException e) { Constants.zknlogger.log(Level.WARNING, "Tray Icon could not be added."); return; } // if tray icon was successfully added, add tooltip trayIcon.setToolTip("Zettelkasten"); // and mouse listener, so the window will be restored when the user clicks on the tray icon trayIcon.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mouseClicked(java.awt.event.MouseEvent evt) { // set main frame visible getFrame().setVisible(true); // restore frame state to normal state getFrame().setExtendedState(java.awt.Frame.NORMAL); // if we have a tray icon, remove it if (tray != null) { // clear popup menu trayIcon.setPopupMenu(null); // remove tray icon tray.remove(trayIcon); } // and say that tray icon is currently not installed trayIconInstalled = false; } }); trayIconInstalled = true; } @Override public void windowOpened(WindowEvent arg0) { } @Override public void windowClosing(WindowEvent arg0) { // call the general exit-handler from the desktop-application-api // here we do all the stuff we need when exiting the application ZettelkastenApp.getApplication().exit(); } @Override public void windowClosed(WindowEvent arg0) { } @Override public void windowIconified(WindowEvent arg0) { // if minimizing to tray is activated, show tray icon if (settings.getMinimizeToTray()) { // when window is minimized to tray, init the system tray icon initSystemTray(); // and hide the window, when try icon was successfully installed if (trayIconInstalled) getFrame().setVisible(false); } } @Override public void windowDeiconified(WindowEvent arg0) { } @Override public void windowActivated(WindowEvent arg0) { } @Override public void windowDeactivated(WindowEvent arg0) { } @Override public void dragEnter(DropTargetDragEvent dtde) { } @Override public void dragOver(DropTargetDragEvent dtde) { } @Override public void dropActionChanged(DropTargetDragEvent dtde) { } @Override public void dragExit(DropTargetEvent dte) { } @Override public void drop(DropTargetDropEvent dtde) { // get transferable Transferable tr = dtde.getTransferable(); try { // check whether we have files dropped into textarea if (tr.isDataFlavorSupported(DataFlavor.stringFlavor) || tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor) || tr.isDataFlavorSupported(urlFlavor)) { // drag&drop was link action dtde.acceptDrop(DnDConstants.ACTION_LINK); // continue here if we have dropped an URLs from the webbrowser // in some cases, files are considered as URL. make sure that no // transfer data starting with "file" is accepted as URL if (tr.isDataFlavorSupported(urlFlavor) && !tr.getTransferData(urlFlavor).toString().startsWith("file:")) { // retrieve url URL url = (URL) tr.getTransferData(urlFlavor); // TODO abfrage, was kommen soll, ob import oder anhang // importWebPage(url); // else add the text to the keyword-list (JList) addAttachments(new String[] { url.toString() }); } else if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { // retrieve list of dropped files java.util.List files = (java.util.List) tr.getTransferData(DataFlavor.javaFileListFlavor); // check for valid values if (files != null && files.size() > 0) { // create array File[] atts = new File[files.size()]; // iterate drop files and convert to array for (int i = 0; i < files.size(); i++) { atts[i] = new File(files.get(i).toString()); } // insert attachments boolean added = FileOperationsUtil.insertAttachments(data, settings, getFrame(), atts, null); // add attachments if (added) { // retrieve final added attachments String[] finalatts = FileOperationsUtil.getAddedAttachments(); // checkfor valid values if (finalatts != null && finalatts.length > 0) { addAttachments(finalatts); } } } } else if (tr.isDataFlavorSupported(DataFlavor.stringFlavor)) { // get drop data String tfd = (String) tr.getTransferData(DataFlavor.stringFlavor); // check for valid values if (tfd != null && !tfd.isEmpty()) { // retrieve drag source info String[] sourceinformation = tfd.split("\\n"); // check if authors have been dropped if (sourceinformation[0].equals(Constants.DRAG_SOURCE_TYPE_AUTHORS)) { // new array String aus[] = new String[sourceinformation.length - 1]; // prepare new array without drag info for (int i = 1; i < sourceinformation.length; i++) { aus[i - 1] = sourceinformation[i]; } // add authors addAuthorToList(aus); } } } dtde.getDropTargetContext().dropComplete(true); } else { Constants.zknlogger.log(Level.WARNING, "DataFlavor is not supported, drop rejected!"); dtde.rejectDrop(); } } catch (IOException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); dtde.rejectDrop(); } catch (UnsupportedFlavorException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); dtde.rejectDrop(); } } /** * * @param url */ private void importWebPage(URL url) { // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_IMPORTDATA, taskinfo, data, bookmarks, desktop, searchrequests, settings, Constants.TYPE_URL, null, false, false, "", url); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // when an error occured, show errorlog if (!taskinfo.isImportOk()) { showErrorLog(); } else { openEditWindow(false, -1, false, false, -1, taskinfo.getWebContent()); } } /** * This Action creates the links between of the currently displayed entry with all other enries, * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane * * @return the background task */ private class createLinksTask extends org.jdesktop.application.Task<Object, Void> { /** * This variable stores the table data of the links-list. * We use this variable in the "createLinksTask", because when we add the values to the * tables directly (via tablemodel) and the user skips through the entries before the task * has finished, the table contains wrong values. so, within the task this list is filled, * and only when the task has finished, we copy this list to the table. */ private ArrayList<Object[]> linkedlinkslist; @SuppressWarnings("LeakingThisInConstructor") createLinksTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to createLinksTask fields, here. super(app); cLinksTask = 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 program that this thread is running... createLinksIsRunning = true; // variable that indicates whether a match of keywords was found boolean found; int cnt; // get the length of the data file, i.e. the amount of entrys final int len = data.getCount(Daten.ZKNCOUNT); // get the keyword index numbers of the current entry String[] kws = data.getCurrentKeywords(); // if we have any keywords, go on if (kws != null) { // create new instance of that variable linkedlinkslist = new ArrayList<Object[]>(); // iterate all entrys of the zettelkasten for (cnt = 1; cnt <= len; cnt++) { // leave out the comparison of the current entry with itself if (cnt == data.getCurrentZettelPos()) continue; // init the found indicator found = false; // iterate all keywords of current entry for (String k : kws) { // look for occurences of any of the current keywords if (data.existsInKeywords(k, cnt, false)) { // set found-indicator found = true; break; } } // if we have a match, connect entries, i.e. display the number and title of // the linked entries in the table of the tabbed pane if (found) { // create a new object Object[] ob = new Object[4]; // store the information in that object ob[0] = cnt; ob[1] = data.getZettelTitle(cnt); ob[2] = data.getLinkStrength(data.getCurrentZettelPos(), cnt); ob[3] = data.getZettelRating(cnt); // and add that content as a new row to the table linkedlinkslist.add(ob); } } } return null; } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel(); // reset the table tm.setRowCount(0); // check whether we have any entries at all... if (linkedlinkslist != null) { // create iterator for linked list Iterator<Object[]> i = linkedlinkslist.iterator(); // go through linked list and add all objects to the table model try { while (i.hasNext()) tm.addRow(i.next()); } catch (ConcurrentModificationException e) { // reset the table when we have overlappings threads tm.setRowCount(0); } } // display manual links now... displayManualLinks(); } @Override protected void finished() { super.finished(); cLinksTask = null; createLinksIsRunning = false; // show/enable viewmenu, if we have at least one entry... if ((jTableLinks.getRowCount() > 0) && (TAB_LINKS == jTabbedPaneMain.getSelectedIndex())) { showTabMenu(viewMenuLinks); } // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableLinks.getRowCount()) + " " + org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ZettelkastenView.class).getString("statusTextLinks") + ")"); } } private void fillLuhmannNumbers(MutableTreeNode node, int zettelpos) { // get the text from the luhmann-numbers String lnr = data.getLuhmannNumbers(zettelpos); // if we have any luhmann-numbers, go on... if (!lnr.isEmpty()) { // copy all values to an array String[] lnrs = lnr.split(","); // go throughh array of current luhmann-numbers for (String exist : lnrs) { // retrieve node title String title = TreeUtil.retrieveNodeTitle(data, settings.getShowLuhmannEntryNumber(), exist); // create a new node MutableTreeNode n = new DefaultMutableTreeNode(new TreeUserObject(title, exist, false)); // and add it node.insert(n, node.getChildCount()); // check whether luhmann-value exists, by re-calling this method // again and go through a recusrive loop fillLuhmannNumbers(n, Integer.parseInt(exist)); } } } /** * 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 * @param luhmannnumbers a StringBuilder that will contain the luhmann-numbers as comma-separated values */ private String fillLuhmannNumbers(int zettelpos, StringBuilder luhmannnumbers) { // get the text from the luhmann-numbers String lnr = data.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), luhmannnumbers); } } return luhmannnumbers.toString(); } /** * This method, called when the user enters "m" as input in the entry-textfield in the lower * statusbar, toggles a timer that display the current memory usage of the application. this * timer is executes every 5 seconds, so the memory-usage is updated each 5 seconds. * <br><br> * If the user types "m" for the second time, the timer is stopped. */ public void toggleMemoryTimer() { // check whether we have a already running timer... if (null == memoryDisplayTimer) { // if not, create new one memoryDisplayTimer = new Timer(); // this timer should start immediately and update every 5 seconds memoryDisplayTimer.schedule(new MemoryTimer(), 0, 5000); // show memory-usage-label jLabelMemory.setVisible(true); // display memory usage calculateMemoryUsage(); // switch on toggle settings.isMemoryUsageLogged = true; // log info Constants.zknlogger.log(Level.INFO, "Memory usage logging swicthed on."); } else { // if timer was running, cancel it memoryDisplayTimer.cancel(); // purge it from the task-list memoryDisplayTimer.purge(); // hide label jLabelMemory.setVisible(false); // free timer-object memoryDisplayTimer = null; // switch off toggle settings.isMemoryUsageLogged = false; // log info Constants.zknlogger.log(Level.INFO, "Memory usage logging swicthed off."); } // show current entry number again jTextFieldEntryNumber.setText(String.valueOf(data.getCurrentZettelPos())); } private void terminateTimers() { if (memoryDisplayTimer != null) { // if timer was running, cancel it memoryDisplayTimer.cancel(); // purge it from the task-list memoryDisplayTimer.purge(); // hide label jLabelMemory.setVisible(false); // free timer-object memoryDisplayTimer = null; } if (makeAutoBackupTimer != null) { // if timer was running, cancel it makeAutoBackupTimer.cancel(); // purge it from the task-list makeAutoBackupTimer.purge(); // free timer-object makeAutoBackupTimer = null; // reset counter memoryLogCounter = 0; } if (flashErrorIconTimer != null) { // if timer was running, cancel it flashErrorIconTimer.cancel(); // purge it from the task-list flashErrorIconTimer.purge(); // free timer-object flashErrorIconTimer = null; } } private void calculateMemoryUsage() { // calculate memory usage from the application long totalMem = Runtime.getRuntime().totalMemory(); // calculate the allocated memory from the jvm long freeMem = Runtime.getRuntime().freeMemory(); // calculate the maximum system memory long maxMem = Runtime.getRuntime().maxMemory(); // convert values to string String freeMemory = String.valueOf((totalMem - freeMem) / 1048576); String totalMemory = String.valueOf(totalMem / 1048576); String maximalMemory = String.valueOf(maxMem / 1048576); // display memory-usage jLabelMemory.setText(freeMemory + "MB / " + totalMemory + "MB (max. " + maximalMemory + "MB)"); // increase log-counter. we want to update the *display* of the memory-usage every // 5 seconds, but logging it to a file only each minute memoryLogCounter++; // when 12 ticks are over, we have one minute passed, so log info now... if (memoryLogCounter >= 12) { // log memory usage Constants.zknlogger.log(Level.INFO, "Memory-Usage: {0}MB / {1}MB (max. {2}MB)", new Object[] { freeMemory, totalMemory, maximalMemory }); // reset counter memoryLogCounter = 0; } } private void flashErrorIcon() { errorIconIsVisible = !errorIconIsVisible; if (errorIconIsVisible) { statusErrorButton.setIcon(Constants.errorIcon); } else { statusErrorButton.setIcon(Constants.errorIconFaded); } } /** * This class starts a timer that displays the memory-usage of the zettelkasten */ class MemoryTimer extends TimerTask { @Override public void run() { // display memory usage calculateMemoryUsage(); } } /** * This class starts a timer that displays the memory-usage of the zettelkasten */ class ErrorIconTimer extends TimerTask { @Override public void run() { // make update-icon flash flashErrorIcon(); } } /** * This class starts a timer that displays the memory-usage of the zettelkasten */ class AutoBackupTimer extends TimerTask { @Override public void run() { // create autobackup makeAutoBackup(); } } /** * This method creates the so-called Luhmann-numbers, i.e. follower-entries of the current * entry. Since follower-entries can have other followers itself (subentries), we iterate * all entries and subentries here, creating a jTreeView out of all entries and subentries. */ private void luhmannTask() { // retrieve collapsed status TreeUtil.retrieveCollapsedNodes(jTreeLuhmann); // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeLuhmann.getModel(); // and first of all, clear the jTree dtm.setRoot(null); // get current entry number int curzettel = data.getCurrentZettelPos(); // retrieve node title String title = TreeUtil.retrieveNodeTitle(data, settings.getShowLuhmannEntryNumber(), String.valueOf(curzettel)); // set this as root node MutableTreeNode root = new DefaultMutableTreeNode(new TreeUserObject(title, Constants.ROOT_ID_NAME, false)); dtm.setRoot(root); // now call a recursive method that fills the jTree with the luhmann-numbers, // i.e. with the follower- or sub-entries fillLuhmannNumbers(root, data.getCurrentZettelPos()); // completely expand the jTree TreeUtil.expandAllTrees(jTreeLuhmann); // now that we have created all luhmann-numbers, we want to retrieve all // entries, where the current entry itself is a follower-number. thus, we // both know which followers and sub-followers this entry has, and which entries // are follower-"parents" of this entry. // // clear list model isFollowerList.clear(); // get current entry number as string String currentEntry = String.valueOf(data.getCurrentZettelPos()); // go through complete data set for (int cnt = 1; cnt <= data.getCount(Daten.ZKNCOUNT); cnt++) { // get the luhmann-numbers of each entry String[] lnrs = data.getLuhmannNumbers(cnt).split(","); // now check each number for the occurence of the current entry number for (String l : lnrs) { // when one of the luhmann-numbers equals the current entry number... if (l.equals(currentEntry)) { try { // add that entry-number to the list. isFollowerList.add(String.valueOf(cnt)); break; } catch (ConcurrentModificationException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); System.out.println("Fehler Folgezettel UI!"); } } } } // when we found any entries, display jPanel jEditorPaneIsFollower .setText(HtmlUbbUtil.getLinkedEntriesAsHtml(settings, isFollowerList, "isFollowerText")); // show/enabke related menu showTabMenu(viewMenuLuhmann); } /** * Action with background task, which imorts the file * @return */ @Action public Task autoBackupTask() { return new createAutoBackupTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } private class createAutoBackupTask extends org.jdesktop.application.Task<Object, Void> { /** * Store old value of status-label, so we can restore it after task is finished */ String oldmsg; org.jdesktop.application.ResourceMap rm = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ZettelkastenView.class); createAutoBackupTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to ImportFileTask fields, here. super(app); } @Override protected Object doInBackground() throws IOException { // Your Task's code here. This method runs // on a background thread, so don't reference // the Swing GUI from here. // prevent task from processing when the file path is incorrect // get filepath File fp = settings.getFilePath(); // copy current filepath to string String newfp = fp.toString(); // look for last occurence of the extension-period. this // is needed to set another extension for the backup-file int lastDot = newfp.lastIndexOf("."); // if extension was found... if (-1 == lastDot) { // log error Constants.zknlogger.log(Level.WARNING, "Couldn't find file-extension! Auto-backup was not created!"); return null; } // create backup-file, with new extension File backup = new File(newfp.substring(0, lastDot) + ".zkb3"); // and copy original file to backupfile // if the user did not cancel and the destination file does not already exist, go on here // tell programm that task is running createAutoBackupIsRunning = true; // check whether file is write protected if (!backup.canWrite()) { // log error-message Constants.zknlogger.log(Level.WARNING, "Autobackup-file is write-protected. Removing write protection..."); try { // try to remove write protection backup.setWritable(true); } catch (SecurityException ex) { // log error-message Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); Constants.zknlogger.log(Level.SEVERE, "Autobackup-file is write-protected. Write protection could not be removed!"); } } try { // open the outputstream ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(backup)); // 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 old statustext oldmsg = statusMsgLabel.getText(); // show status text statusMsgLabel.setText(rm.getString("createAutoBackupMsg")); // save metainformation zip.putNextEntry(new ZipEntry(Constants.metainfFileName)); out.output(data.getMetaInformationData(), zip); // save main data. zip.putNextEntry(new ZipEntry(Constants.zknFileName)); out.output(data.getZknData(), zip); // save authors zip.putNextEntry(new ZipEntry(Constants.authorFileName)); out.output(data.getAuthorData(), zip); // save keywords zip.putNextEntry(new ZipEntry(Constants.keywordFileName)); out.output(data.getKeywordData(), zip); // save bookmarks zip.putNextEntry(new ZipEntry(Constants.bookmarksFileName)); out.output(bookmarks.getBookmarkData(), zip); // save searchrequests zip.putNextEntry(new ZipEntry(Constants.searchrequestsFileName)); out.output(searchrequests.getSearchData(), zip); // save synonyms zip.putNextEntry(new ZipEntry(Constants.synonymsFileName)); out.output(synonyms.getDocument(), zip); // save bibtex file zip.putNextEntry(new ZipEntry(Constants.bibTexFileName)); ByteArrayOutputStream bout = bibtex.saveFile(); bout.writeTo(zip); // save desktops zip.putNextEntry(new ZipEntry(Constants.desktopFileName)); out.output(desktop.getDesktopData(), zip); zip.putNextEntry(new ZipEntry(Constants.desktopModifiedEntriesFileName)); out.output(desktop.getDesktopModifiedEntriesData(), zip); zip.putNextEntry(new ZipEntry(Constants.desktopNotesFileName)); out.output(desktop.getDesktopNotesData(), zip); zip.close(); bout.close(); } catch (IOException e) { // log error message Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); // create a copy of the data file in case we have problems creating the auto-backup File datafiledummy = settings.getFilePath(); // check for valid value if (datafiledummy != null && datafiledummy.exists()) { try { // first, create basic backup-file File checkbackup = FileOperationsUtil.getBackupFilePath(datafiledummy); // copy data file as backup-file FileOperationsUtil.copyFile(datafiledummy, checkbackup, 1024); // log path. Constants.zknlogger.log(Level.INFO, "A backup of the data file was saved to {0}", checkbackup.toString()); // check whether file is write protected if (!backup.canWrite()) { // log error-message Constants.zknlogger.log(Level.SEVERE, "Autobackup failed. The file is write-protected."); // show error message JOptionPane.showMessageDialog(getFrame(), rm.getString("errorSavingWriteProtectedMsg"), rm.getString("autobackupSaveErrTitle"), JOptionPane.PLAIN_MESSAGE); } // tell user that an error occured JOptionPane.showMessageDialog(getFrame(), rm.getString("autobackupSaveErrMsg", "\"" + checkbackup.getName() + "\""), rm.getString("autobackupSaveErrTitle"), JOptionPane.PLAIN_MESSAGE); } catch (IOException e2) { Constants.zknlogger.log(Level.SEVERE, e2.getLocalizedMessage()); } } } catch (SecurityException e) { // log error message Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); // create a copy of the data file in case we have problems creating the auto-backup File datafiledummy = settings.getFilePath(); // check for valid value if (datafiledummy != null && datafiledummy.exists()) { try { // first, create basic backup-file File checkbackup = FileOperationsUtil.getBackupFilePath(datafiledummy); // copy data file as backup-file FileOperationsUtil.copyFile(datafiledummy, checkbackup, 1024); // log path. Constants.zknlogger.log(Level.INFO, "A backup of the data file was saved to {0}", checkbackup.toString()); // tell user that an error occured JOptionPane.showMessageDialog(getFrame(), rm.getString("autobackupSaveErrMsg", "\"" + checkbackup.getName() + "\""), rm.getString("autobackupSaveErrTitle"), JOptionPane.PLAIN_MESSAGE); } catch (IOException e2) { Constants.zknlogger.log(Level.SEVERE, e2.getLocalizedMessage()); } } } return null; // return your result } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). } @Override protected void finished() { super.finished(); // restore old status message statusMsgLabel.setText(oldmsg); // tell programm that task has finished createAutoBackupIsRunning = false; // no autoback necessary at the moment isbackupnecessary = false; // and log info message Constants.zknlogger.log(Level.INFO, "Automatic backup was successfully created."); } } /** * Action with background task, which imorts the file * @return */ @Action public final Task checkForUpdate() { return new checkForUpdateTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } private class checkForUpdateTask extends org.jdesktop.application.Task<Object, Void> { // indicates whether the zettelkasten has updates or not. boolean updateavailable = false; boolean showUpdateMsg = true; String updateBuildNr = "0"; checkForUpdateTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to ImportFileTask fields, here. super(app); } protected String accessUpdateFile(URL updatetext) { // input stream that will read the update text InputStream is; // stringbuilder that will contain the content of the update-file StringBuilder updateinfo = new StringBuilder(""); try { // open update-file on server is = updatetext.openStream(); // buffer for stream int buff = 0; // read update-file and copy content to string builder while (buff != -1) { buff = is.read(); if (buff != -1) updateinfo.append((char) buff); } } catch (IOException e) { // tell about fail Constants.zknlogger.log(Level.INFO, "No access to Zettelkasten-Website. Automatic update-check failed."); updateavailable = false; return null; } return updateinfo.toString(); } @Override protected Object doInBackground() throws IOException { // Your Task's code here. This method runs // on a background thread, so don't reference // the Swing GUI from here. String updateinfo = accessUpdateFile(new URL(Constants.UPDATE_INFO_URI)); // check for valid access if (null == updateinfo || updateinfo.isEmpty()) return null; // retrieve update info and split them into an array. this array will hold the latest // build-version-number in the first field, and the type of update in the 2. field. String[] updateversion = updateinfo.split("\n"); // check whether we have a valid array with content if (updateversion != null && updateversion.length > 0) { // retrieve start-index of the build-number within the version-string. int substringindex = Constants.BUILD_VERSION.indexOf("(Build") + 7; // only copy buildinfo into string, other information of version-info are not needed String curversion = Constants.BUILD_VERSION.substring(substringindex, substringindex + 8); // store build number of update updateBuildNr = updateversion[0]; // check whether there's a newer version online updateavailable = (curversion.compareTo(updateBuildNr) < 0); // check whether update hint should be shown for this version or not showUpdateMsg = (updateBuildNr.compareTo(settings.getShowUpdateHintVersion()) != 0); // if no update available and user wants to check for nightly versions, // check this now if (!updateavailable && settings.getAutoNightlyUpdate()) { updateinfo = accessUpdateFile(new URL(Constants.UPDATE_NIGHTLY_INFO_URI)); // check for valid access if (null == updateinfo || updateinfo.isEmpty()) return null; // retrieve update info and split them into an array. this array will hold the latest // build-version-number in the first field, and the type of update in the 2. field. updateversion = updateinfo.split("\n"); if (updateversion != null && updateversion.length > 0) { updateavailable = (curversion.compareTo(updateversion[0]) < 0); if (updateavailable) updateURI = Constants.UPDATE_NIGHTLY_URI; } } } return null; // return your result } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). } @Override protected void finished() { if (updateavailable) { //log info Constants.zknlogger.log(Level.INFO, "A new version of the Zettelkasten is available!"); if (showUpdateMsg) updateZettelkasten(updateBuildNr); } } } /** * This task creates the related (clustered) keywords from the current entry. Therefore, * the current entry's keywords are retrieved. Then, in each entry of the data-file * we look for occurences of the current entry's keywords. If we found any matches, the * related entry's other keywords are added to the final keyword-list. * * @return the background task */ @Action public Task clusterTask() { return new createClusterTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } /** * This task creates the related (clustered) keywords from the current entry. Therefore, * the current entry's keywords are retrieved. Then, in each entry of the data-file * we look for occurences of the current entry's keywords. If we found any matches, the * related entry's other keywords are added to the final keyword-list. * * @return the background task */ private class createClusterTask extends org.jdesktop.application.Task<Object, Void> { // create link list for the keywords and related keywords LinkedList<String> lwsClusterTask = new LinkedList<String>(); createClusterTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to createLinksTask fields, here. super(app); } @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 thread is running createClusterIsRunning = true; // get current entries keywords String[] cws = data.getCurrentKeywords(); // if we have any current keywords, go on if (cws != null) { // get amount of entries int count = data.getCount(Daten.ZKNCOUNT); // add all current keywords and their related keywords to // the linked list for (String c : cws) { // add each curent keyword to cluster list lwsClusterTask.add(c); // now go through all entries for (int cnt = 1; cnt <= count; cnt++) { // check whether current keywords exits in entry if (data.existsInKeywords(c, cnt, false)) { // if yes, retrieve entry's keywords String[] newkws = data.getKeywords(cnt); // check whether we have any keywords at all if (newkws != null) { // if so, iterate keywords for (String n : newkws) { // and add each keyword to the link list, if it's not // already in that list... if (!lwsClusterTask.contains(n)) lwsClusterTask.add(n); } } } } } // sort the array Collections.sort(lwsClusterTask, new Comparer()); } // we have no filtered list... linkedclusterlist = false; // indicate that the cluster list is up to date... data.setClusterlistUpToDate(true); return null; } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). // // get the treemodel DefaultTreeModel dtm = (DefaultTreeModel) jTreeCluster.getModel(); // set this as root node. we don't need to care about this, since the // root is not visible. DefaultMutableTreeNode root = new DefaultMutableTreeNode("ZKN3-Cluster"); dtm.setRoot(root); // if we have any keywords, set them to the list if (lwsClusterTask.size() > 0) { // create iterator Iterator<String> i = lwsClusterTask.iterator(); // and add all items to the list while (i.hasNext()) { root.add(new DefaultMutableTreeNode(i.next())); } // completely expand the jTree TreeUtil.expandAllTrees(true, jTreeCluster); } } @Override protected void finished() { super.finished(); createClusterIsRunning = false; jCheckBoxCluster.setEnabled(true); // enable textfield only if we have more than 1 element in the jTree jTextFieldFilterCluster.setEnabled(jTreeCluster.getRowCount() > 1); // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTreeCluster.getRowCount()) + " " + org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ZettelkastenView.class).getString("statusTextKeywords") + ")"); jTreeCluster.setToolTipText(null); } } /** * This Action creates the links between of the currently displayed entry with all other enries, * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane.<br><br> * Unlike the createLinks-task, this task does not look for any single occurences of keywords, * but of logical-combination of the selected keywords. I.e., whether <i>all</i> or <i>at least one</i> * of the selected keywords is/are part of another entry's keywords-list. * * @return the background task */ @Action public Task createFilterLinks() { return new createFilterLinksTask(org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class)); } /** * This Action creates the links between of the currently displayed entry with all other enries, * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane.<br><br> * Unlike the createLinks-task, this task does not look for any single occurences of keywords, * but of logical-combination of the selected keywords. I.e., whether <i>all</i> or <i>at least one</i> * of the selected keywords is/are part of another entry's keywords-list. * * @return the background task */ private class createFilterLinksTask extends org.jdesktop.application.Task<Object, Void> { /** * This variable stores the table data of the filtered links-list. * We use this variable in the "createLinksTask", because when we add the values to the * tables directly (via tablemodel) and the user skips through the entries before the task * has finished, the table contains wrong values. so, within the task this list is filled, * and only when the task has finished, we copy this list to the table. */ private ArrayList<Object[]> linkedfilteredlinkslist; createFilterLinksTask(org.jdesktop.application.Application app) { // Runs on the EDT. Copy GUI state that // doInBackground() depends on from parameters // to createLinksTask fields, here. super(app); } @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 program that this thread is running... createFilterLinksIsRunning = true; // variable that indicates whether a match of keywords was found boolean found; int cnt; // create string array for selected keyword-values String[] kws = retrieveSelectedKeywordsFromList(); // if we have no selection, return null. this happens, when the view is refreshed and a value // in the jListEntryKeywords is selected - the jList then loses somehow the selectiob, so this // task is startet, although no keyword is selected... if (null == kws) return null; // get the length of the data file, i.e. the amount of entrys final int len = data.getCount(Daten.ZKNCOUNT); // get setting, whether we have logical-and or logical-or-search boolean log_and = settings.getLogKeywordlist().equalsIgnoreCase(Settings.SETTING_LOGKEYWORDLIST_AND); // create new instance of that variable linkedfilteredlinkslist = new ArrayList<Object[]>(); // iterate all entrys of the zettelkasten for (cnt = 1; cnt <= len; cnt++) { // leave out the comparison of the current entry with itself if (cnt == data.getCurrentZettelPos()) continue; // init the found indicator found = false; // if we have logical-or, at least one of the keywords must exist. // so go through all selected keywords and look for occurences if (data.existsInKeywords(kws, cnt, log_and, false)) found = true; // if we have a match, connect entries, i.e. display the number and title of // the linked entries in the table of the tabbed pane if (found) { // create a new object Object[] ob = new Object[3]; // store the information in that object ob[0] = cnt; ob[1] = data.getZettelTitle(cnt); ob[2] = data.getLinkStrength(data.getCurrentZettelPos(), cnt); // and add that content to the linked list linkedfilteredlinkslist.add(ob); } } return null; } @Override protected void succeeded(Object result) { // Runs on the EDT. Update the GUI based on // the result computed by doInBackground(). DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel(); // reset the table tm.setRowCount(0); // check whether we have any entries at all... if (linkedfilteredlinkslist != null) { // create iterator for linked list Iterator<Object[]> i = linkedfilteredlinkslist.iterator(); // go through linked list and add all objects to the table model try { while (i.hasNext()) tm.addRow(i.next()); } catch (ConcurrentModificationException e) { // reset the table when we have overlappings threads tm.setRowCount(0); } } // show amount of entries statusMsgLabel.setText("(" + String.valueOf(jTableLinks.getRowCount()) + " " + org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ZettelkastenView.class).getString("statusTextLinks") + ")"); } @Override protected void finished() { super.finished(); createFilterLinksIsRunning = false; } } /** * This method opens the preferences-window (settings-window). */ @Action public void settingsWindow() { if (null == settingsDlg) { settingsDlg = new CSettingsDlg(getFrame(), settings, data, autoKorrekt, synonyms, steno); settingsDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(settingsDlg); // check for changes to synonyms if (settingsDlg.isSynModified()) { // update indicator for autobackup isbackupnecessary = true; setSaveEnabled(true); // check whether we have to update tabbed pane if (!data.isKeywordlistUpToDate()) updateTabbedPane(); } // check whether only entry display should be updated if (settingsDlg.getDisplayUpdate()) { updateZettelContent(displayedZettel); if (desktopDlg != null) desktopDlg.updateEntriesAfterEditing(); if (searchResultsDlg != null) searchResultsDlg.updateDisplayAfterEditing(); // set background color jEditorPaneEntry.setBackground(new Color(Integer.parseInt(settings.getMainBackgroundColor(), 16))); } // when we have any changes in visual settings, update display if (settingsDlg.getNeedsUpdate()) { // update tables, e.g. show new cellspacing or grids initTables(); // update toolbar, to show new icons if necessary initToolbarIcons(false); if (searchResultsDlg != null) searchResultsDlg.initToolbarIcons(); if (desktopDlg != null) desktopDlg.initToolbarIcons(); if (newEntryDlg != null) newEntryDlg.initToolbarIcons(); // set background color jEditorPaneEntry.setBackground(new Color(Integer.parseInt(settings.getMainBackgroundColor(), 16))); // update display, in case the user changed the font-settings updateDisplay(); } // when the user chose a new look and feel, or font-size for tables and lists, update ist if (settingsDlg.getNeedsLafUpdate()) JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("needsRestartMsg"), getResourceMap().getString("needsRestartTitle"), JOptionPane.PLAIN_MESSAGE); // when we have any changes in visual settings, tell desktop to update display if (desktopDlg != null) desktopDlg.setNeedsUpdate(true); // check for correct saving of settings if (!settingsDlg.isSaveSettingsOk()) { // show error log showErrorIcon(); } settingsDlg.dispose(); settingsDlg = null; // try to motivate garbage collector System.gc(); } /** * This method searches for entries that contain at least on of the selected * entries (log-or) from the jTableAuthors or jTableKewords, and adds those entries as manual * links to the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addManLinksLogOr() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addManLinksFromAuthors(Constants.LOG_OR); break; case TAB_KEYWORDS: addManLinksFromKeywords(Constants.LOG_OR); break; } } /** * This method searches for entries that contain <i>all</i> selected * entries (log-and) from the jTableAuthors or jTableKeywords, and adds those entries as manual * links to the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addManLinksLogAnd() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addManLinksFromAuthors(Constants.LOG_AND); break; case TAB_KEYWORDS: addManLinksFromKeywords(Constants.LOG_AND); break; } } /** * This method searches for entries that contain the selected * keywords from the jTableKeywords, and adds those entries as luhmann-numbers * (follower) to the current entry. * <br><br> * See {@link #addLuhmannLogOr() addLuhmannLogOr()} and * {@link #addLuhmannLogAnd() addLuhmannLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one keywords should exist * (log-or) or if only entries are added that contain all keywords (log-and) */ private void addLuhmannFromKeywords(int log) { // search for all entries that contain the selected keywords // and add them as luhmann-numbers startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_LUHMANN, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); // update display updateDisplay(); } /** * This method searches for entries that contain the selected * keywords from the jTableKeywords, and adds those entries as manual links * (follower) to the current entry. * <br><br> * See {@link #addManLinksLogOr() addManLinksLogOr()} and * {@link #addManLinksLogAnd() addManLinksLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one keywords should exist * (log-or) or if only entries are added that contain all keywords (log-and) */ private void addManLinksFromKeywords(int log) { // search for all entries that contain the selected keywords // and add them as manual links startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_MANLINK, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); // update display updateDisplay(); } /** * This method adds the selected entries from the the current activated tab in the tabbed pane, * and adds those entries to the desktop. */ @Action(enabledProperty = "tableEntriesSelected") public void addDesktop() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_TITLES: addToDesktop(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableTitles, 0)); break; case TAB_LINKS: addToDesktop(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableLinks, 0)); addToDesktop(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableManLinks, 0)); break; case TAB_LUHMANN: addToDesktop(new int[] { retrieveEntryNrFromLuhmann() }); break; case TAB_BOOKMARKS: addToDesktop(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableBookmarks, 0)); break; } } /** * This method searches for entries that contain the selected * keywords from the jTableKeywords, and adds those entries to the desktop. * <br><br> * See {@link #addDesktopLogOr() addDesktopLogOr()} and * {@link #addDesktopLogAnd() addDesktopLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one keywords should exist * (log-or) or if only entries are added that contain all keywords (log-and) */ private void addDesktopFromKeywords(int log) { // search for all entries that contain the selected keywords and add them to the desktop startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_DESKTOP, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); } /** * This method searches for entries that contain at least on of the selected * entries (log-or) from the jTableAuthors or jTableKeywords, and adds those entries to the desktop. */ @Action(enabledProperty = "tableEntriesSelected") public void addDesktopLogOr() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addDesktopFromAuthors(Constants.LOG_OR); break; case TAB_KEYWORDS: addDesktopFromKeywords(Constants.LOG_OR); break; } } /** * This method searches for entries that contain <i>all</i> selected * entries (log-and) from the jTableAuthors or jTableKeywords, and adds those entries to the desktop. */ @Action(enabledProperty = "tableEntriesSelected") public void addDesktopLogAnd() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addDesktopFromAuthors(Constants.LOG_AND); break; case TAB_KEYWORDS: addDesktopFromKeywords(Constants.LOG_AND); break; } } /** * This method searches for entries that contain the selected * authors from the jTableAuthors, and adds those entries to the desktop. * <br><br> * See {@link #addDesktopLogOr() addDesktopLogOr()} and * {@link #addDesktopLogAnd() addDesktopLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one author should exist * (log-or) or if only entries are added that contain all authors (log-and) */ private void addDesktopFromAuthors(int log) { // search for all entries that contain the selected authors and add them to the destzop startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_DESKTOP, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); } /** * This method rerieves the selected entries from the current activated tab in the tabbedpane * as manual links to the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addManLinks() { // retrieve activated entry. In case we have selected an entry from any table in the tabbed pane, // this entry is automatically displayed. Thus, this entry cannot be added as manual link to the // displayed entry (=itself), but instead it should be added to the activated entry. int activatedEntry = data.getCurrentZettelPos(); // retrieve selected tab switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_TITLES: addToManLinks(activatedEntry, ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableTitles, 0)); break; // in this single case, we have to update the tab with the links-table... case TAB_LINKS: needsLinkUpdate = true; addToManLinks(activatedEntry, ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableLinks, 0)); break; case TAB_BOOKMARKS: addToManLinks(activatedEntry, ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableBookmarks, 0)); break; case TAB_LUHMANN: addToManLinks(activatedEntry, new int[] { retrieveEntryNrFromLuhmann() }); break; } } /** * This method adds one or more entries as follower-numbers to the entry that is selected in * the jTreeLuhmann. The entry-numbers * of the to be added entries have to be passed as integer-array.<br><br> * This method needs to be public, since we want to access it from other frames, * like for instance {@link CSearchResults}. * * @param entries an int-array conatining the entry-numbers of those entries that should * be added as follower-entries * @return {@code true} if everything went ok, false if an error occured */ public boolean addToLuhmann(int[] entries) { if ((null == entries) || (entries.length < 1) || (-1 == entries[0])) return false; // if we have a selected entry, add numbers to that (sub-)entry int currentZettel = retrieveEntryNrFromLuhmann(); // if no valid selection made, get current entry number if (-1 == currentZettel) currentZettel = data.getCurrentZettelPos(); // init message-box indicator boolean error = false; // iterate array and add it to the current entry for (int nr : entries) if (!data.addLuhmannNumber(currentZettel, nr)) error = true; // display error message box, when any problems occured if (error) JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errLuhmannExistsMsg"), getResourceMap().getString("errLuhmannExistsTitle"), JOptionPane.PLAIN_MESSAGE); // update the display updateDisplay(); return true; } /** * This method rerieves the selected entries from the current activated tab in the tabbedpane * and adds them to the bookmarks of the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addBookmarks() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_TITLES: addToBookmarks(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableTitles, 0), false); break; case TAB_LUHMANN: addToBookmarks(new int[] { retrieveEntryNrFromLuhmann() }, false); break; } } /** * This method rerieves the selected entries from the current activated tab in the tabbedpane * and adds them as luhmann-numbers (follower) of the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addLuhmann() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_BOOKMARKS: addToLuhmann(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableBookmarks, 0)); break; case TAB_LINKS: addToLuhmann(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableLinks, 0)); addToLuhmann(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableManLinks, 0)); break; case TAB_TITLES: addToLuhmann(ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableTitles, 0)); break; } } /** * This method searches for entries that contain at least on of the selected * entries (log-or) from the jTableAuthors or jTableKeywords, and adds those entries as luhmann-numbers * (follower) to the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addLuhmannLogOr() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addLuhmannFromAuthors(Constants.LOG_OR); break; case TAB_KEYWORDS: addLuhmannFromKeywords(Constants.LOG_OR); break; } } /** * This method searches for entries that contain <i>all</i>of the selected * entries (log-and) from the jTableAuthors or jTableKeywords, and adds those entries as luhmann-numbers * (follower) to the current entry. */ @Action(enabledProperty = "tableEntriesSelected") public void addLuhmannLogAnd() { switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: addLuhmannFromAuthors(Constants.LOG_AND); break; case TAB_KEYWORDS: addLuhmannFromKeywords(Constants.LOG_AND); break; } } /** * This method searches for entries that contain the selected * authors from the jTableAuthors, and adds those entries as luhmann-numbers * (follower) to the current entry. * <br><br> * See {@link #addLuhmannLogOr() addLuhmannLogOr()} and * {@link #addLuhmannLogAnd() addLuhmannLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one author should exist * (log-or) or if only entries are added that contain all authors (log-and) */ private void addLuhmannFromAuthors(int log) { // search for all entries that contain at least on of the selected keywords // and add them as luhmann-numbers startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_LUHMANN, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); // update display updateDisplay(); } /** * This method searches for entries that contain the selected * authors from the jTableAuthors, and adds those entries as manual links * to the current entry. * <br><br> * See {@link #addManLinksFromAuthors() addManLinksFromAuthors()} and * {@link #addManLinksFromAuthorsLogAnd() addManLinksFromAuthorsLogAnd()} for more * details. * * @param log the logical combination of the search, whether at least one author should exist * (log-or) or if only entries are added that contain all authors (log-and) */ private void addManLinksFromAuthors(int log) { // search for all entries that contain at least on of the selected authors // and add them as manual links startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look log, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) true, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_MANLINK, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); // update display updateDisplay(); } /** * This action is triggered from the title view tabbed pane / menu. This method moves selected * entries behind another entry, which entry number is requested via option dialog. With this * method, entries can be reordered. */ @Action(enabledProperty = "tableEntriesSelected") public void moveEntry() { // retrieve selected entry numbers int[] moveentries = ZettelkastenViewUtil.retrieveSelectedEntriesFromTable(data, jTableTitles, 0); // check whether we have any entriews at all if (moveentries != null && moveentries.length > 0) { // ask user after which entry the selected entries should be inserted // open an input-dialog String insertAfter = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("moveEntryMsg"), getResourceMap().getString("moveEntryTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid return-value... if ((insertAfter != null) && (insertAfter.length() > 0)) { // convert the string-input into an int-array int[] selectedValues = Tools.retrieveEntryNumbersFromInput(insertAfter, data.getCount(Daten.ZKNCOUNT)); // and move selected entries behind the entered entry number if (selectedValues != null) { // move entries data.moveEntries(moveentries, selectedValues[0]); // update title list showTitles(); } } } } // TODO wenn import abbricht, werden nicht alle listen resettet, bspw. table enthalten noch alte daten /** * This method opens two dialogs: 1) the import dialog where the user can choose * which type of data to import and where the file is locates. and 2) the status * message window which does the import action in a background task */ @Action public void importWindow() { // opens the Import Dialog. This Class is responsible // for getting the relevant import data. the import task // itself (background task) will be started as another dialog, // when this one is closed // if dialog window isn't already created, do this now if (null == importWindow) { // when we have no data, there is no need for appending the data boolean isAppendPossible = data.getCount(Daten.ZKNCOUNT) > 0; // get parent und init window importWindow = new CImport(getFrame(), settings, bibtex, isAppendPossible); // center window importWindow.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(importWindow); // Here the data (filepath, filetype) from the import 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. import is only started, // when the previous dialog wasn't cancelled or simply closed if (Constants.RETURN_VALUE_CONFIRM == importWindow.getReturnValue()) { // check whether we want to import bibtex data if (Constants.TYPE_BIB == importWindow.getImportType()) { importAuthors(); } else { // first check whether we have unsaved changes, when the user wants // to create a new data-file - but only the import-type is a data-file! if (((Constants.TYPE_ZKN3 == importWindow.getImportType()) || (Constants.TYPE_ZKN == importWindow.getImportType()) || (Constants.TYPE_CSV == importWindow.getImportType())) && (!importWindow.getAppend() && !askForSaveChanges(getResourceMap().getString("msgSaveChangesTitle")))) { return; } // create default timestamp. this is only relevant for importing old data-files (.zkn), because // entries of old data-files may not always have timestamps. to ensure each entry has a time stamp // we offer the user to input a default date that is set for all entries that do not have any timestamp String defaulttimestamp = null; // if old data should be imported, ask for default timestamp if (Constants.TYPE_ZKN == importWindow.getImportType()) { // get current date as default or initial value SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yy"); // get mainfile that should be importet File f = importWindow.getFilePath(); // get last modification date from file long l = f.lastModified(); // wait for valid input while (null == defaulttimestamp) { // show input-dialog defaulttimestamp = (String) JOptionPane.showInputDialog(getFrame(), // parent window getResourceMap().getString("defaultTimeStampMsg"), // message text getResourceMap().getString("defaultTimeStampTitle"), // messagebox title JOptionPane.PLAIN_MESSAGE, // type of dialog null, // icon null, // array of selection values. // must be null to get an input-field. // providing an array here would create a dropdown-combobox sdf.format(l)); // initial value, date of importfile // now convert the timestamp into something // therefore, check whether we have any valid input at all, if we have the correct length (8 chars) // and if we have to "." at the right position. A valid input would be e.g. "31.12.08" (dd.mm.yy) if (defaulttimestamp != null && 8 == defaulttimestamp.length() && defaulttimestamp.charAt(2) == '.' && defaulttimestamp.charAt(5) == '.') { defaulttimestamp = defaulttimestamp.substring(6) + defaulttimestamp.substring(3, 5) + defaulttimestamp.substring(0, 2) + "0001"; } else { defaulttimestamp = null; } } } // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_IMPORTDATA, taskinfo, data, bookmarks, desktop, searchrequests, settings, importWindow.getImportType(), importWindow.getFilePath(), importWindow.getAsciiToUnicode(), importWindow.getAppend(), defaulttimestamp, null); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // when an error occured, show errorlog if (!taskinfo.isImportOk()) { showErrorLog(); } // this is the typical stuff we need to do when a file is opened // or imported, but only when we imported "real" data switch (importWindow.getImportType()) { case Constants.TYPE_ZKN3: case Constants.TYPE_ZKN: case Constants.TYPE_CSV: case Constants.TYPE_XML: updateAfterOpen(); break; } } } // 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) importWindow.dispose(); importWindow = null; // try to motivate garbage collector System.gc(); } /** * This method displays the log-file in a new window. */ @Action public void showErrorLog() { // terminate timer if (flashErrorIconTimer != null) { // if timer was running, cancel it flashErrorIconTimer.cancel(); // purge it from the task-list flashErrorIconTimer.purge(); // free timer-object flashErrorIconTimer = null; } // hide button statusErrorButton.setVisible(false); if (null == errorDlg) { errorDlg = new CErrorLog(getFrame(), this, settings); errorDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(errorDlg); // 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) errorDlg.dispose(); errorDlg = null; } public void showErrorIcon() { // show button statusErrorButton.setVisible(true); // check whether timer already exists if (flashErrorIconTimer != null) return; // create timer for flashing the update icon flashErrorIconTimer = new Timer(); // this timer should start immediately and update each second flashErrorIconTimer.schedule(new ErrorIconTimer(), 0, 1000); } /** * This method opens three dialogs: * <br><br>1) a dialog where the user can choose, which entries he wants to export. * <br><br>2) the export dialog where the user can choose * which type of format the data to be exported and where the file should be saved. * <br><br>and 3) the status message window which does the export action in a background task */ @Action(enabledProperty = "entriesAvailable") public void exportWindow() { // first, let the user choose, which entries to export - whether all entries // or just a selection... if (null == exportEntriesDlg) { // get parent und init window exportEntriesDlg = new CExportEntries(getFrame(), data.getCount(Daten.ZKNCOUNT), settings); // center window exportEntriesDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(exportEntriesDlg); // check for valid return-value if (!exportEntriesDlg.isCancelled()) { // now call the export-dialog with more options, so the chosen entries // will be exported exportEntries(exportEntriesDlg.getEntries()); // 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) } exportEntriesDlg.dispose(); exportEntriesDlg = null; } /** * This method opens the export-dialog where the user can choose which format to use when * exporting entries. This method is public, because it is also called from the CSearchResults-window * to export search results and from the Desktop/Outliner to export data. * * @param entries an array of entry-numbers that should be exported. use {@code null} to export * all entries. */ public void exportEntries(int[] entries) { // here we copy the integer-array to an object-array-list, // since our export-entries need to be in array-object-format ArrayList<Object> liste = new ArrayList<Object>(); if (null == entries || entries.length < 1) { liste = null; } else { for (int cnt = 0; cnt < entries.length; cnt++) liste.add(entries[cnt]); } exportEntries(liste); } /** * This method opens the export-dialog where the user can choose which format to use when * exporting entries. This method is public, because it is also called from the CSearchResults-window * to export search results and from the Desktop/Outliner to export data. * * @param entries an array of entry-numbers that should be exported. use {@code null} to export * all entries. */ public void exportEntries(ArrayList<Object> entries) { // 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 CExport(getFrame(), settings, bibtex); // center window exportWindow.setLocationRelativeTo(getFrame()); } 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(getFrame(), settings, exportWindow.getExportType())) { // if dialog window isn't already created, do this now if (null == taskDlg) { // open export dialog // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_EXPORTDATA, taskinfo, data, bookmarks, desktop, settings, bibtex, synonyms, exportWindow.getFilePath(), entries, exportWindow.getExportType(), exportWindow.getExportParts(), exportWindow.getCSVSeparator(), null, exportWindow.isAllInOneFile(), exportWindow.getFormatTagsRemoved(), exportWindow.getExportBibTex(), exportWindow.getKeywordsHighlighted(), false, false, exportWindow.hasTitlePrefix()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // if an error occured, show error-log if (!taskinfo.isExportOk()) showErrorIcon(); // else tell user that everything went fine else if (taskinfo.showExportOkMessage()) JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("exportOkMsg"), getResourceMap().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(); } /** * Shows the about box and gives information * about the programm and version */ @Action public void showAboutBox() { if (null == zknAboutBox) { zknAboutBox = new AboutBox(getFrame(), settings.isMacAqua() | settings.isMacStyle()); zknAboutBox.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(zknAboutBox); // clear memory allocation zknAboutBox.dispose(); zknAboutBox = null; // try to motivate garbage collector System.gc(); } /** * This method duplicates the currently displayed entry and adds it to the end * of the Zettelkasten database. */ @Action(enabledProperty = "entriesAvailable") public void duplicateEntry() { duplicateEntry(displayedZettel); } /** * This method duplicates the entry {@code nr} and adds it to the end of * the Zettelkasten database. * @param nr the entry-number of that entry that should be duplicated. */ public void duplicateEntry(int nr) { // first, retrieve the entry's authors, so we can update the table jTableAuthors, // by increasing the frequencies... String[] aus = data.getAuthors(nr); if (aus != null) for (String a : aus) linkedauthorlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableAuthors, linkedauthorlist, a, 1); // then, retrieve the entry's keywords, so we can update the table jTableKeywords, // by increasing the frequencies... String[] kws = data.getKeywords(nr); if (kws != null) for (String k : kws) linkedkeywordlist = ZettelkastenViewUtil.updateTableFrequencyChange(jTableKeywords, linkedkeywordlist, k, 1); // finally, duplicate entry if (!data.duplicateEntry(nr)) { // tell user about problem JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errDuplicateEntryMsg"), getResourceMap().getString("errDuplicateEntryTitle"), JOptionPane.PLAIN_MESSAGE); showErrorIcon(); } else { // update display if everything ok updateDisplay(); } } /** * This method opens the window for editing new entries. All the stuff like saving the * data to the main-data-object is done within the class "CNewEntry.java" */ @Action public void newEntry() { openEditWindow(false, -1, false, false, -1); } /** * This method opens the window for editing existing entries. All the stuff like saving the * data to the main-data-object is done within the class "CNewEntry.java" */ @Action(enabledProperty = "entriesAvailable") public void editEntry() { if (data.isDeleted(displayedZettel)) { openEditWindow(false, displayedZettel, false, true, -1); } else { openEditWindow(true, displayedZettel, false, false, -1); } } /** * This method opens the new-entry-window for editing new or existing entries. if an entry * is currently being edited, the {@code isEditModeActive} flag is set. In this case, the * edit-window is only brought to the front. Else, a new window is created. * * @param isEditing true if we want to edit an existing entry, false if a new entry is to be created * @param entrynumber the entrynumber. relevant for editing existing entries. * @param isLuhmann true if the new entry should be inserted as follower of the current entry. * @param isDeleted true if the user wants to edit a deleted entry, thus inserting a new entry * at an deleted entry's position * @param insertAfterEntry This variable stores the number of that entry after which the new entry should * be inserted. does only affect the prev/next attributes of an entry. Use {@code -1} to add entry * to the end of entry order. */ public void openEditWindow(boolean isEditing, int entrynumber, boolean isLuhmann, boolean isDeleted, int insertAfterEntry) { openEditWindow(isEditing, entrynumber, isLuhmann, isDeleted, insertAfterEntry, jEditorPaneEntry.getSelectedText()); } /** * This method opens the new-entry-window for editing new or existing entries. if an entry * is currently being edited, the {@code isEditModeActive} flag is set. In this case, the * edit-window is only brought to the front. Else, a new window is created. * * @param isEditing true if we want to edit an existing entry, false if a new entry is to be created * @param entrynumber the entrynumber. relevant for editing existing entries. * @param isLuhmann true if the new entry should be inserted as follower of the current entry. * @param isDeleted true if the user wants to edit a deleted entry, thus inserting a new entry * at an deleted entry's position * @param insertAfterEntry This variable stores the number of that entry after which the new entry should * be inserted. does only affect the prev/next attributes of an entry. Use {@code -1} to add entry * to the end of entry order. * @param String content */ private void openEditWindow(boolean isEditing, int entrynumber, boolean isLuhmann, boolean isDeleted, int insertAfterEntry, String content) { // 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 newEntryDlg.toFront(); } // else create a new window and display it. else { newEntryDlg = new NewEntryFrame(this, data, taskinfo, acceleratorKeys, settings, autoKorrekt, synonyms, steno, content, isEditing, entrynumber, isLuhmann, isDeleted, insertAfterEntry); newEntryDlg.setLocationRelativeTo(getFrame()); ZettelkastenApp.getApplication().show(newEntryDlg); // edit window was initialized isEditModeActive = true; // if so, bring that window to the front newEntryDlg.toFront(); } } /** * This method is called from the CNewEntry-frame to indicate when an edit.action has been finished. */ public void finishedEditing() { // edit window was closed isEditModeActive = false; // if the user made changes to the datafile, e.g. adding new entries // update the display if (newEntryDlg.isModified()) { // // here we update modified entries in the desktop window // // when we had an edit-option... if (newEntryDlg.isEditMode() && // and whether a current desktop-dialog is opened. desktopDlg != null && // check whether the changed entry was on the desktop... desktop.checkForDoubleEntry(desktop.getCurrentDesktopNr(), newEntryDlg.entryNumber)) // if yes, update desktop-view desktopDlg.updateEntriesAfterEditing(); // // here we update modified entries in the searchresults window // // when we had an edit-option and whether a current search-dialog is opened. if (newEntryDlg.isEditMode() && searchResultsDlg != null) { // if yes, update desktop-view searchResultsDlg.updateDisplayAfterEditing(); } // authorlist might be out of date now... data.setAuthorlistUpToDate(false); // and keywordlist might be out of date now as well... data.setKeywordlistUpToDate(false); // and titles might be out of date now as well... data.setTitlelistUpToDate(false); // and attachment-list might be out of date now as well... data.setAttachmentlistUpToDate(false); // tell about success Constants.zknlogger.log(Level.INFO, "Entry save finished."); // update the dislay... updateDisplay(); // tell about success Constants.zknlogger.log(Level.INFO, "Display updated."); // and create a backup... makeAutoBackup(); // tell about success Constants.zknlogger.log(Level.INFO, "Autobackup finished (if necessary)."); // check whether new entry was edited from search results window if (editEntryFromSearchWindow) { // bring window to front if (searchResultsDlg != null) searchResultsDlg.toFront(); } // check whether new entry was edited from desktop window if (editEntryFromDesktop) { // check whether window is opened if (desktopDlg != null) { // retrieve ID of latest added entry String id = data.getLastAddedZettelID(); // check for valid value if (id != null) { // find index number from ID int nr = data.getZettelNumberFromID(id); // if we found an entry, add it if (nr != -1) desktopDlg.addEntries(new int[] { nr }); } // bring window to front desktopDlg.toFront(); } } } // reset variable editEntryFromDesktop = false; editEntryFromSearchWindow = false; // try to motivate garbage collector System.gc(); } /** * This method starts a background thread that creates an automatic backup of the * current main data file. the file is saved to the same directory as the main data file, * just changing the extenstion to ".zkb3". * <br><br> * This method is called when we have changes that are not save, e.g. after the methods * {@link #newEntry() newEntry()} or {@link #editEntry() editEntry()}. */ private void makeAutoBackup() { // if // - task is already running, or // - no backup necessary // - or an save-operation is in progress... // ...then do nothing. if (createAutoBackupIsRunning || !isbackupnecessary || isSaving) return; // check for autobackup if (settings.getAutoBackup() && (settings.getFilePath() != null)) { Task cabT = autoBackupTask(); // 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(cabT); tM.setForegroundTask(cabT); } } /** * This mehtod creates an additional backup of<br> * - the data-file * - the meta-data ({@code zettelkasten-data.zkd3}) * when the user quits the application. These files are saved to a certain directory * that is specified by the user. */ private void makeExtraBackup() { // when no extrabackup is requested, leave method if (!settings.getExtraBackup()) return; // retrieve backup-directory File backuppath = settings.getExtraBackupPath(); // when the path does not exist, leave... if (null == backuppath) { // log error Constants.zknlogger.log(Level.WARNING, "The file path to the extra backup (which is created when closing the application) is null! Extra backup could not be created!"); return; } if (!backuppath.exists()) { // log error Constants.zknlogger.log(Level.WARNING, "Could not save extra backup to {0}. The file path to the extra backup (which is created when closing the application) does not exist! Extra backup could not be created!", backuppath.toString()); return; } // get filename and find out where extension begins, so we can retrieve the filename File datafile = settings.getFilePath(); // if we have a valid file-path, go on... if (datafile != null) { // create a backup-filename, that consists of the data-file's filename String backupfilename = datafile.getName(); // retrieve os-separator-char String sepchar = String.valueOf(File.separatorChar); // add additional separator-char if the file-path does not contain a trailing separator char if (!backuppath.toString().endsWith(sepchar)) backupfilename = sepchar + backupfilename; // create final backup-file-path File backupfile = new File(backuppath.toString() + backupfilename); // if backup-filepath is identical with the data-filepath, we don't create an extra backup // to prevent overwriting the file... if (backupfile.toString().equalsIgnoreCase(datafile.toString())) { // log error Constants.zknlogger.log(Level.WARNING, "The file path of the extra backup (which is created when closing the application) equals the main data file name! To prevent overwriting the data file, the extra backup was not created!"); return; } try { // copy data file FileOperationsUtil.copyFile(datafile, backupfile, 4096); // log file path and success Constants.zknlogger.log(Level.INFO, "Extra-backup was copied to {0}", backupfile.toString()); // retrieve filepath of meta-file, i.e. the file that stores spellchecking, synonyms etc. File metafile = settings.getMetaFilePath(); // check whether file exists if (metafile != null && metafile.exists()) { // get filename String metafilename = "zettelkasten-data.zkd3"; if (!backuppath.toString().endsWith(sepchar)) metafilename = sepchar + metafilename; // create backupfilepath File backupmetafile = new File(backuppath.toString() + metafilename); // copy meta-file FileOperationsUtil.copyFile(metafile, backupmetafile, 4096); // log file path and success Constants.zknlogger.log(Level.INFO, "Extra-backup meta-data was copied to {0}", backupmetafile.toString()); } else { // log error Constants.zknlogger.log(Level.WARNING, "Extra-backup meta-data does not exists and thus could not be created!"); } } catch (IOException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } } } /** * This method deletes the currently displayed zettel. usually this method is called from the * delete-action from the toolbbar or menu, in contrary to the delete-function from the jTableTitles * which deletes selected entries (see {@link #deleteEntry() deleteEntry()}).<br><br> * The entry is not being deleted completely. To keep the ordering and index-numbers of existing * entries, a deleted entry will just be cleared (all content set to empty string values), and if * a deleted entry is displayed, just a hint "deleted" is displayed in the main editor pane. */ @Action(enabledProperty = "entriesAvailable") public void deleteCurrentEntry() { // delete currently displayed zettel if (deleteEntries(new int[] { displayedZettel })) { // set uptodate-state to false data.setTitlelistUpToDate(false); // update tabbed pane updateTabbedPane(); } } /** * This method adds the currently displayed entry to the desktop-window. */ @Action(enabledProperty = "moreEntriesAvailable") public void addToDesktop() { // add entyry to desktop addToDesktop(new int[] { displayedZettel }); } /** * This method adds one or more entries to the desktop-window. The entry-numbers * of the to be added entries have to be passed as integer-array.<br><br> * This method needs to be public, since we want to access it from other frames, * like for instance {@link CSearchResults}. * * @param entries an int-array conatining the entry-numbers of those entries that should * be added to the desktop. */ public void addToDesktop(int[] entries) { // check for valid values if ((null == entries) || (entries.length < 1) || (-1 == entries[0])) return; // if dialog window isn't already created, do this now if (null == desktopDlg) desktopDlg = new DesktopFrame(this, taskinfo, data, bookmarks, desktop, settings, acceleratorKeys, bibtex, autoKorrekt, steno); // show desktop ZettelkastenApp.getApplication().show(desktopDlg); // add entyry to desktop desktopDlg.addEntries(entries); // enable window-menu-item, if we have loaded desktop data setDesktopAvailable(desktop.getCount() > 0); } @Action(enabledProperty = "entriesAvailable") public void newDesktop() { // if dialog window isn't already created, do this now if (null == desktopDlg) desktopDlg = new DesktopFrame(this, taskinfo, data, bookmarks, desktop, settings, acceleratorKeys, bibtex, autoKorrekt, steno); // show desktop ZettelkastenApp.getApplication().show(desktopDlg); // let user create new desktop desktopDlg.newDesktop(); // enable window-menu-item, if we have loaded desktop data setDesktopAvailable(desktop.getCount() > 0); } /** * This method opens the window for inserting new entries as "followers" or "sub-entries". * These entries are inserted at the end of the data set, but are indicated as "followers" * (i.e.: sub-entries) of the current visible entry. * All the stuff like saving the data to the main-data-object is done within the class "CNewEntry.java". * We than additionally set the "luhmann"-tag here (see CDaten.java for more detaiks), which is used * in the "showLuhmann" method here. */ @Action(enabledProperty = "entriesAvailable") public void insertEntry() { openEditWindow(false, displayedZettel, true, false, displayedZettel); } /** * This method opens the window for inserting new entries as "followers" or "sub-entries". * These entries are inserted at the end of the data set, but are indicated as "followers" * (i.e.: sub-entries) of the current visible entry. * All the stuff like saving the data to the main-data-object is done within the class "CNewEntry.java". * We than additionally set the "luhmann"-tag here (see CDaten.java for more detaiks), which is used * in the "showLuhmann" method here. */ @Action(enabledProperty = "entriesAvailable") public void insertEntryAt() { openEditWindow(false, displayedZettel, false, false, displayedZettel); } /** * This method opens the window for inserting new entries as "followers" or "sub-entries". * These entries are inserted at the end of the data set, but are indicated as "followers" * (i.e.: sub-entries) of the current visible entry, <b>or</b> of the currently selected entry * of the jTreeLuhmann - if there is any selection.<br><br> * All the stuff like saving the data to the main-data-object is done within the class "CNewEntry.java". * We than additionally set the "luhmann"-tag here (see CDaten.java for more detaiks), which is used * in the "showLuhmann" method here.<br><br> * Entries may be separated with commas, or also contain a "from-to" option. * example: "4,6,11-15,19" */ @Action(enabledProperty = "moreEntriesAvailable") public void manualInsertEntry() { // open an input-dialog String newLuhmann = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("newLuhmannMsg"), getResourceMap().getString("newLuhmannTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid return-value... if ((newLuhmann != null) && (newLuhmann.length() > 0)) { // convert the string-input into an int-array int[] selectedValues = Tools.retrieveEntryNumbersFromInput(newLuhmann, data.getCount(Daten.ZKNCOUNT)); // and add them as follower-entries if (selectedValues != null) addToLuhmann(selectedValues); } } /** * This method opens the window for inserting new entries as manual links. * Entries may be separated with commas, or also contain a "from-to" option. * example: "4,6,11-15,19" */ @Action(enabledProperty = "moreEntriesAvailable") public void manualInsertLinks() { // open an input-dialog String manLinks = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("newManLinksMsg"), getResourceMap().getString("newManLinksTitle"), JOptionPane.PLAIN_MESSAGE); // if we have a valid return-value... if ((manLinks != null) && (manLinks.length() > 0)) { // convert the string-input into an int-array int[] selectedValues = Tools.retrieveEntryNumbersFromInput(manLinks, data.getCount(Daten.ZKNCOUNT)); // and add them as follower-entries if (selectedValues != null) addToManLinks(selectedValues); } } public void editManualLinks() { // open an input-dialog String manLinks = (String) JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("newManLinksMsg"), data.getManualLinksAsSingleString(displayedZettel)); // if we have a valid return-value... if (manLinks != null) { if (!manLinks.isEmpty()) { // convert the string-input into an int-array int[] selectedValues = Tools.retrieveEntryNumbersFromInput(manLinks, data.getCount(Daten.ZKNCOUNT)); // and add them as crossreference-entries if (selectedValues != null) addToManLinks(selectedValues); } // if we have a valid empty return-value... else { // delete manual links data.setManualLinks(displayedZettel, ""); } // update display updateZettelContent(displayedZettel); updateTabbedPane(); } } /** * This method adds one or more entries as manual links to the current entry. The entry-numbers * of the to be added entries have to be passed as integer-array.<br><br> * This method needs to be public, since we want to access it from other frames, * like for instance {@link CSearchResults}. * * @param entries an int-array conatining the entry-numbers of those entries that should * be added as manual links * @return {@code true} if entries have been successfully added, false if an error occured */ public boolean addToManLinks(int[] entries) { return addToManLinks(displayedZettel, entries); } /** * This method adds one or more entries as manual links to the current entry. The entry-numbers * of the to be added entries have to be passed as integer-array.<br><br> * We have this method with additional parameter (in addition to * {@link #addToManLinks(int[]) addToManLinks(int[])}, in case we want to add manual * links from the jTableLinks to the current entry. Usually, manual links are added * to the displayed entry. Since the displayed entry is the entry that is selected in the * jTableLinks, we would add the selected entry as manual link to the selected entry - which * doesn't work. So, whenever an entry in the jTableLinks is selected, it will be added * as manual link to the <b>activated</b> entry.<br><br> * In all other cases, manual links are added to the displayed entry, thus calling * the {@link #addToManLinks(int[]) addToManLinks(int[])} method. * * @param activatedEntry the entry-number where the manual links should be added to... * @param entries an int-array conatining the entry-numbers of those entries that should * be added as manual links * @return {@code true} if entries have been successfully added, false if an error occured */ private boolean addToManLinks(int activatedEntry, int[] entries) { if ((null == entries) || (entries.length < 1) || (-1 == entries[0])) return false; // init message-box indicator boolean error = false; // iterate array // and add it to the current entry for (int nr : entries) { if (!data.addManualLink(activatedEntry, nr)) error = true; } // display error message box, when any problems occured if (error) { JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errManLinksExistsMsg"), getResourceMap().getString("errManLinksExistsTitle"), JOptionPane.PLAIN_MESSAGE); } // update the display updateDisplay(); // everything went ok return true; } /** * This method creates a new, empty zettelkasten. If there are unsaved changes, the user * can save them before. else, the currently opened datafile is immediately closed */ @Action public void newZettelkasten() { // first check whether we have unsaved changes, when the user wants // to open a new data-file if (askForSaveChanges(getResourceMap().getString("msgSaveChangesTitle"))) { // reset the data-file settings.setFilePath(new File("")); data.initZettelkasten(); desktop.clear(); bookmarks.clear(); searchrequests.clear(); synonyms.clear(); bibtex.clearEntries(); // set modified state to false data.setModified(false); searchrequests.setModified(false); desktop.setModified(false); bookmarks.setModified(false); synonyms.setModified(false); bibtex.setModified(false); // init some variables initVariables(); // update the new filename to the title updateTitle(); // and update the display. updateDisplay(); } } /** * Displays the first entry in the zettelkasten. */ @Action(enabledProperty = "moreEntriesAvailable") public void showFirstEntry() { // increase entry counter data.firstEntry(); // and update the whole content updateDisplay(); } /** * Displays the last entry in the zettelkasten. */ @Action(enabledProperty = "moreEntriesAvailable") public void showLastEntry() { // increase entry counter data.lastEntry(); // and update the whole content updateDisplay(); } /** * Displays the next entry in the zettelkasten. */ @Action(enabledProperty = "moreEntriesAvailable") public void showNextEntry() { // increase entry counter data.nextEntry(); // and update the whole content updateDisplay(); } /** * Sets the input focus to the textfield where the user can input an entry-number, * so the requested entry is displayed. */ @Action(enabledProperty = "moreEntriesAvailable") public void gotoEntry() { jTextFieldEntryNumber.requestFocusInWindow(); } /** * Displays the entry which is given via the parameter * @param nr (the entry number to display) */ public void showEntry(int nr) { // goto the requested entry and update the content, if the number-parameter // was within the right boundaries if (data.gotoEntry(nr)) updateDisplay(); } /** * This method displays a random entry, where deleted entries will not be shown. */ @Action public void showRandomEntry() { // check for available entries if (!data.hasEntriesExcludingDeleted()) return; // init variable int randomnumber = -1; // create randomnumber and check, whether the entry with the created random number // is deleted or not while (-1 == randomnumber || data.isDeleted(randomnumber)) { // create new random number until we have found a valid, non-deleted entry randomnumber = (int) (Math.random() * data.getCount(Daten.ZKNCOUNT)) + 1; } // show that entry showEntry(randomnumber); } /** * displays the first entry in the zettelkasten */ @Action(enabledProperty = "moreEntriesAvailable") public void showPrevEntry() { // increase entry counter data.prevEntry(); // and update the whole content updateDisplay(); } /** * Searches the database for multiple entries and displays them in a table. */ @Action(enabledProperty = "moreEntriesAvailable") public void findDoubleEntries() { // check whether dialog is already visible or was created if (null == doubleEntriesDlg || !doubleEntriesDlg.isVisible()) { // if not, create new dialog doubleEntriesDlg = new FindDoubleEntriesTask(getFrame(), this, data, settings); // center window doubleEntriesDlg.setLocationRelativeTo(getFrame()); } // display window ZettelkastenApp.getApplication().show(doubleEntriesDlg); // and start background task to search for double entries. doubleEntriesDlg.startTask(); } /** * Opens a file dialog and lets the user choose a zkn3-file. Then a method in the CLoadSave-class * is called to open the file and store the data in the CData-class. */ @Action public void openDocument() { // first check whether we have unsaved changes, when the user wants // to open a new data-file if (askForSaveChanges(getResourceMap().getString("msgSaveChangesTitle"))) { // retrieve current filepath File loadfile = settings.getFilePath(); // retrieve filename and extension String filedir = null; String filename = null; // check whether we have any valid filepath at all if (loadfile != null && loadfile.exists()) { filedir = loadfile.toString(); filename = loadfile.getName(); } // create a swing filechooser when we have no mac File filepath = FileOperationsUtil.chooseFile(getFrame(), (settings.isMacAqua()) ? FileDialog.LOAD : JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY, filedir, filename, getResourceMap().getString("fileDialogTitleOpen"), new String[] { Constants.ZKN_FILEEXTENSION, Constants.ZKN_BACKUPFILEEXTENSION }, getResourceMap().getString("fileDescription1"), settings); if ((filepath != null) && filepath.exists()) { // check whether opened file is a backup-file if (filepath.toString().toLowerCase().endsWith(Constants.ZKN_BACKUPFILEEXTENSION.toLowerCase())) { try { // create a dummy-file with the original file-extension, so we can backup that original file File fp = new File(filepath.toString().replace(Constants.ZKN_BACKUPFILEEXTENSION, Constants.ZKN_FILEEXTENSION)); // in case the user already created a backup, we concatenate a trainling // backup-counter-number to avoid overwriting existing backup-files File checkbackup = FileOperationsUtil.getBackupFilePath(fp); // rename original file and append ".backup" as extension fp.renameTo(checkbackup); // rename backup-file to original file-name... filepath.renameTo(fp); // and update variable filepath = fp; // tell user that the backup-file has been loaded and the old original file backuped JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("backupLoadedMsg", "\"" + checkbackup.getName() + "\"", System.getProperty("line.separator") + System.getProperty("line.separator") + "\"" + fp.toString().substring(0, fp.toString().lastIndexOf(File.separatorChar)) + "\"" + System.getProperty("line.separator") + System.getProperty("line.separator"), "\"" + fp.getName() + "\""), getResourceMap().getString("backupLoadedTitle"), JOptionPane.PLAIN_MESSAGE); } catch (SecurityException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } catch (NullPointerException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } } // save new filepath settings.setFilePath(filepath); // when all information are ready, load the document by opening //a modal dialog, which opens the data via a background task. the // dialog only displays a progressbar and an animated busyicon while // opening the file, no user-interaction possible.... loadDocument(); } } } /** * Opens the file {@code fp} and asks to save changes before opening the file * @param fp the data file to be opened */ public void openDocument(String fp) { // first check whether we have unsaved changes, when the user wants // to open a new data-file if (askForSaveChanges(getResourceMap().getString("msgSaveChangesTitle"))) { // create filepath from paramter File filepath = new File(fp); // if file exists, open it if (filepath.exists()) { // save new filepath settings.setFilePath(filepath); // when all information are ready, load the document by opening //a modal dialog, which opens the data via a background task. the // dialog only displays a progressbar and an animated busyicon while // opening the file, no user-interaction possible.... loadDocument(); } } } /** * load the document by opening * a modal dialog, which opens the data via a background task. the * dialog only displays a progressbar and an animated busyicon while * opening the file, no user-interaction possible.... * <br><br> * We have this part of code "outsourced" into an own method because we * need this more often, e.g. when automatically loading the data at * program start-up. * <br><br> * Furthermore, we have the method "updateAfterOpen". We need this additional * method because in that method we do all the stuff which e.g. has also to be * made after importing files... */ private boolean loadDocument() { // get the file path from the data file which has to be opened File fp = settings.getFilePath(); // if file is null, exit if (null == fp) { // log error Constants.zknlogger.log(Level.WARNING, "Could not open file! Filepath is null!"); return false; } // if no file exists, exit task if (!fp.exists()) { // log file path Constants.zknlogger.log(Level.WARNING, "Could not open file {0}!", fp.toString()); return false; } // check whether we have a backup-file that is newer than the original // data-file. if so, ask the user if he wants to open the backup // therefore, create a filename of the backup-file (which equals the // original filename, except the file-extension, which we replace // by the backup-extension here File backupfile = new File( fp.toString().replace(Constants.ZKN_FILEEXTENSION, Constants.ZKN_BACKUPFILEEXTENSION)); // if file exists, compare filedates... if (backupfile.exists()) { // get modified-dates of original- and backup-file long modifiedOriginal = fp.lastModified(); long modifiedBackup = backupfile.lastModified(); // if original-file is *older* than backup-file, ask // the user what to do... if (modifiedOriginal < modifiedBackup) { // ask the user whether he wants to load the original file, // the newer backup-file or cancel the complete load-operation... int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("newerBackupMsg"), getResourceMap().getString("newerBackupTitle"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); // the user chose to cancel the operation, so return "null" if (JOptionPane.CANCEL_OPTION == option || JOptionPane.CLOSED_OPTION == option /*User pressed cancel key*/) { // clear filepath, so the data-file won't be accidently overwritten... settings.setFilePath(null); // return result return false; } // here the user wants to open the backup-file instead of the older file... if (JOptionPane.NO_OPTION == option) { try { // in case the user already created a backup, we concatenate a trainling // backup-counter-number to avoid overwriting existing backup-files // we start with a "1" int backupcounter = 1; // the backup-extension String backupext = ".backup"; // first, create basic backup-file File checkbackup = new File(fp.toString() + backupext); // check whether backup-file already exists while (checkbackup.exists()) { // if yes, increase extension-counter backupcounter++; // append it to extension backupext = ".backup-" + String.valueOf(backupcounter); // and create new file-name which we want to check... checkbackup = new File(fp.toString() + backupext); } // rename original file and append ".backup" as extension fp.renameTo(checkbackup); // rename backup-file to original file-name... backupfile.renameTo(settings.getFilePath()); // tell user that the backup-file has been loaded and the old original file backuped JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("backupLoadedMsg", "\"" + checkbackup.getName() + "\"", System.getProperty("line.separator") + System.getProperty("line.separator") + "\"" + fp.toString().substring(0, fp.toString().lastIndexOf(File.separatorChar)) + "\"" + System.getProperty("line.separator") + System.getProperty("line.separator"), "\"" + fp.getName() + "\""), getResourceMap().getString("backupLoadedTitle"), JOptionPane.PLAIN_MESSAGE); } catch (SecurityException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } catch (NullPointerException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } } } } // add file path to recent documents history settings.addToRecentDocs(fp.toString()); // and update menus setRecentDocuments(); // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_LOAD, data, bookmarks, searchrequests, desktop, synonyms, settings, bibtex); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have a file-version which is newer than the current program-version, // e.g. if the user opens a newer data-file with an older program-version if (data.isIncompatibleFile()) { // tell user that the data file is too new to be opened... JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("incompatibleDataFileMsg"), getResourceMap().getString("incompatibleDataFileTitle"), JOptionPane.PLAIN_MESSAGE); return false; } // check whether we have a new file-version of the data-format. if yes, do conversion now... if (data.isNewVersion()) { // tell user that the data file is being updated... JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("updateDataMsg"), getResourceMap().getString("updateDataTitle"), JOptionPane.PLAIN_MESSAGE); // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_UPDATEFILE, settings, data, desktop, bibtex, false); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; } // which entry should be shown at startup? int shownr = 1; // get the setting what we want to show at startup int getstarttupvalue = settings.getShowAtStartup(); int paramentry = settings.getInitialParamZettel(); // and set the related entrynumber // in case we have retrieved an entry-number as parameter, set this entry number right now if (paramentry != -1 && paramentry <= data.getCount(Daten.ZKNCOUNT)) shownr = paramentry; else if (Settings.SHOWATSTARTUP_FIRST == getstarttupvalue) shownr = 1; else if (Settings.SHOWATSTARTUP_LAST == getstarttupvalue) shownr = settings.getStartupEntry(); else if (Settings.SHOWATSTARTUP_RANDOM == getstarttupvalue) shownr = (int) (Math.random() * data.getCount(Daten.ZKNCOUNT)) + 1; // set the first entry that should be displayed as current zettelpos and history-pos... data.setCurrentZettelPos(shownr); data.setInitialHistoryPos(shownr); // do the typical stuff like updating display, // setting toolbar etc. updateAfterOpen(); // try to motivate garbage collector System.gc(); // return success return true; } /** * Saves the document. Opens a file dialog and then calls a method the the CLoadSave-class * to save the data in the default file format (zkn3) * * @return {@code true} if save was successful, {@code false} otherwise */ @Action(enabledProperty = "saveEnabled") public boolean saveDocument() { // when autobackup is running, prevent saving and tell user to wait a moment... if (createAutoBackupIsRunning) { // show message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("waitForAutobackupMsg"), getResourceMap().getString("waitForAutobackupTitle"), JOptionPane.PLAIN_MESSAGE); return false; } // check for valid filepath File fp = settings.getFilePath(); // if no valid filepath exists, open the file-chooser to retrieve a new filepath if (null == fp || !fp.exists()) { // save the document under a new filepath // and leave this method, as all relevant saving was made in // the above called method return saveDocumentAs(); } // open the save dialog. this dialog is a modal dialog with // just some visible progress indicators, while a background task // is saving the data // tell everyone (especially autobackup-function) that we are saving data // now, so don't disturb us here! isSaving = true; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SAVE, data, bookmarks, searchrequests, desktop, synonyms, settings, bibtex); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // close dialog and clear variables taskDlg.dispose(); taskDlg = null; // saving done... isSaving = false; // update the display and toolbar icons updateDisplay(); // try to motivate garbage collector System.gc(); // check whether saving was successfull. // if not, show error-icon if (!data.isSaveOk()) { showErrorIcon(); return false; } return true; } /** * This method saves the data under a new filename. This method will always be * called when no filepath is set in the dataobject. * * @return {@code true}, when a valid filename was given. false otherwise, or when cancelled */ @Action(enabledProperty = "entriesAvailable") public boolean saveDocumentAs() { // when autobackup is running, prevent saving and tell user to wait a moment... if (createAutoBackupIsRunning) { // show message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("waitForAutobackupMsg"), getResourceMap().getString("waitForAutobackupTitle"), JOptionPane.PLAIN_MESSAGE); return false; } File filepath = FileOperationsUtil.chooseFile(getFrame(), (settings.isMacAqua()) ? FileDialog.SAVE : JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, null, null, getResourceMap().getString("fileDialogTitleSave"), new String[] { Constants.ZKN_FILEEXTENSION }, getResourceMap().getString("fileDescription1"), settings); if (filepath != null) { // check whether the user entered a file extension. if not, // add ".zkn3" as extension if (!filepath.getName().toLowerCase().endsWith(Constants.ZKN_FILEEXTENSION)) filepath = new File(filepath.getPath() + Constants.ZKN_FILEEXTENSION); // if file does not exist, create it - otherwise the getFilePath-method of // the settings-class would return "null" as filepath, if file doesn't exist if (!filepath.exists()) { try { filepath.createNewFile(); } catch (IOException ex) { Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); } } else { // file exists, ask user to overwrite it... int optionDocExists = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("askForOverwriteFileMsg"), getResourceMap().getString("askForOverwriteFileTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if the user does *not* choose to overwrite, quit... if (optionDocExists != JOptionPane.YES_OPTION) return false; } // store the filepath in the data class settings.setFilePath(filepath); // open the save dialog. this dialog is a modal dialog with // just some visible progress indicators, while a background task // is saving the data // tell everyone (especially autobackup-function) that we are saving data // now, so don't disturb us here! isSaving = true; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SAVE, data, bookmarks, searchrequests, desktop, synonyms, settings, bibtex); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // close dialog and clear variables taskDlg.dispose(); taskDlg = null; // saving done... isSaving = false; // update the title to the new filename updateTitle(); // update the display and toolbar icons updateDisplay(); // try to motivate garbage collector System.gc(); // check whether saving was successfull. // if not, show error-icon if (!data.isSaveOk()) { showErrorIcon(); return false; } return true; } return false; } /** * This method exports all bookmarks of the data-file to a file.<br><br> * This method fills a LinkedList with the export-data (i.e. the bookmarks).<br><br> * Then the method * {@link #exportList(java.util.LinkedList, java.lang.String) exportList(LinkedList,String)} * is called, which is responsible for saving the data of this linked list to a file. */ @Action(enabledProperty = "exportPossible") public void exportBookmarks() { exportEntries(createExportBookmarks()); } /** * This method opens the bookmarks as new "search-request" in the search-results-window. */ @Action(enabledProperty = "exportPossible") public void exportBookmarksToSearch() { // create array with export entries int[] entries = createExportBookmarks(); // copy all bookmarked entry-numbers to that array for (int cnt = 0; cnt < entries.length; cnt++) entries[cnt] = bookmarks.getBookmarkEntry(cnt); // append a time-string to description, so we always have a unique search-description, // even if the user searches twice for the same searchterms DateFormat df = new SimpleDateFormat("kkmmss"); // add search searchrequests.addSearch(new String[] { getResourceMap().getString("exportBookmarksSearch") }, Constants.SEARCH_BOOKMARKS, Constants.LOG_OR, false, false, false, false, entries, getResourceMap().getString("exportBookmarksSearchDesc") + " (" + df.format(new Date()) + ")", getResourceMap().getString("exportBookmarksSearchDesc")); // if dialog window isn't already created, do this now if (null == searchResultsDlg) searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } private int[] createExportBookmarks() { // create array with all bookmark-categories String[] bookmarkCategories = new String[bookmarks.getCategoryCount() + 1]; // first field is always "all" bookmarkCategories[0] = getResourceMap().getString("exportBookmarkCatAll"); // retrieve bookmark-categories for (int cnt = 0; cnt < bookmarks.getCategoryCount(); cnt++) { bookmarkCategories[cnt + 1] = bookmarks.getCategory(cnt); } Object expo = JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("exportBookmarkCatMsg"), getResourceMap().getString("exportBookmarkCatTitle"), JOptionPane.PLAIN_MESSAGE, null, bookmarkCategories, null); // init variable int[] entries = null; // check for valid return value if (expo != null) { // selection was: all categories should be exported if (expo.toString().equals(getResourceMap().getString("exportBookmarkCatAll"))) { // copy all bookmarked entry-numbers to that array entries = bookmarks.getAllBookmarkedEntries(); } // selection was a certain category else { entries = bookmarks.getBookmarkedEntriesFromCat(expo.toString()); } } return entries; } /** * This method exports all keywords of the data-file to a file.<br><br> * This method fills a LinkedList with the export-data (i.e. the keywords).<br><br> * Then the method * {@link #exportList(java.util.LinkedList, java.lang.String) exportList(LinkedList,String)} * is called, which is responsible for saving the data of this linked list to a file. */ @Action(enabledProperty = "exportPossible") public void exportKeywords() { // get length of keyword file int len = data.getCount(Daten.KWCOUNT); // create linked list that will contain all keywords LinkedList<String> keywords = new LinkedList<String>(); // copy all keywords to a linked list for (int cnt = 0; cnt < len; cnt++) keywords.add(data.getKeyword(cnt + 1)); // call export-method exportList(keywords, Daten.ELEMENT_KEYWORD); } /** * This method imports literatur-entries from a given bibtex-file and adds the * literatur as author-entries to the authorFile.xml-file of the data-file. * <br><br> * A new dialog is opened (see {@code CImportBibTex.java} fore more details) where * the user can choose a bibtex-file to open, and a file-format (which corresponds to * the literatur-program that is used, e.g. Citavi, JabRef, Zotero...) of that bibtex-file. * <br><br> * All bibtex-entries of that file are displayed in a table where the user can select those * entries that should be imported. Entries that have already previously beeing imported are * <i>not</i> listed in that tables (these entries are identified by their bibkeys, i.e. if an existing * author-value has the same bibkey like an entry of that bibtex-file). * <br><br> * Beside importing the author-values, the user can optionally choose to create an entry for each * imported bibtex-entry, in case the bibtex-entry has an abstract. */ @Action public void importAuthors() { // if dialog window isn't already created, do this now if (importBibTexDlg != null) { // free memory and release all allocated components importBibTexDlg.dispose(); importBibTexDlg = null; // try to motivate garbage collector System.gc(); } // if dialog window isn't already created, do this now if (null == importBibTexDlg) { // create a new dialog window importBibTexDlg = new CImportBibTex(getFrame(), this, data, bibtex, settings); // center window importBibTexDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(importBibTexDlg); } /** * This method exports all authors of the data-file to a file.<br><br> * This method fills a LinkedList with the export-data (i.e. the author-value).<br><br> * Then the method * {@link #exportList(java.util.LinkedList, java.lang.String) exportList(LinkedList,String)} * is called, which is responsible for saving the data of this linked list to a file. */ @Action(enabledProperty = "exportPossible") public void exportAuthors() { // get length of author file int len = data.getCount(Daten.AUCOUNT); // create linked list that will contain all authors LinkedList<String> authors = new LinkedList<String>(); // copy all authors to a linked list for (int cnt = 0; cnt < len; cnt++) authors.add(data.getAuthor(cnt + 1)); // call export-method exportList(authors, "authors"); } @Action public void attachBibtexFile() { // retrieve attached bibtex-file File selectedfile = bibtex.getCurrentlyAttachedFile(); // if we have no attached file, set last used file as filepath if (null == selectedfile || !selectedfile.exists()) selectedfile = bibtex.getFilePath(); selectedfile = FileOperationsUtil.chooseFile(getFrame(), (settings.isMacAqua()) ? FileDialog.LOAD : JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY, (null == selectedfile) ? null : selectedfile.toString(), (null == selectedfile) ? null : selectedfile.getName(), getResourceMap().getString("bibTextFileChooserTitle"), new String[] { ".bib", ".txt" }, getResourceMap().getString("bibTexDesc"), settings); if (selectedfile != null) { // set new bibtex-filepath bibtex.setFilePath(selectedfile); // detach current bibtex file bibtex.detachCurrentlyAttachedFile(); // show input-dialog offering the choice of bibtex-encoding Object encodingchoice = JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("bibtexEncodingsMsg"), getResourceMap().getString("bibtexEncodingsTitle"), JOptionPane.PLAIN_MESSAGE, null, Constants.BIBTEX_DESCRIPTIONS, Constants.BIBTEX_DESCRIPTIONS[settings.getLastUsedBibtexFormat()]); // if user did not cancel the operation, go on and open the bibtex-file if (encodingchoice != null) { // iterate all availabe bibtex-encodings. // if the appropriate encoding that matched the user's choice was found, // use that index-number to open the bibtex-file for (int enc = 0; enc < Constants.BIBTEX_DESCRIPTIONS.length; enc++) { if (encodingchoice.toString().equals(Constants.BIBTEX_DESCRIPTIONS[enc])) { settings.setLastUsedBibtexFormat(enc); break; } } // open selected file, using the character encoding of the related reference-manager (i.e. // the programme that has exported the bib-tex-file). if (bibtex.openAttachedFile(Constants.BIBTEX_ENCODINGS[settings.getLastUsedBibtexFormat()], false)) { // tell about success Constants.zknlogger.log(Level.INFO, "BibTex-File was successfully attached."); // tell user about success JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("bibtexAttachOkMsg"), getResourceMap().getString("bibtexAttachOkTitle"), JOptionPane.PLAIN_MESSAGE); } else { // tell about fail Constants.zknlogger.log(Level.INFO, "BibTex-File could not be found nor attached."); } } } } /** * */ @Action(enabledProperty = "bibtexFileLoaded") public void refreshBibTexFile() { // retrieve current filepath of bibtex file File bibfile = bibtex.getFilePath(); // check whether file already exists if (bibfile != null && bibfile.exists()) { // detach current bibtex file bibtex.detachCurrentlyAttachedFile(); // open selected file, using the character encoding of the related reference-manager (i.e. // the programme that has exported the bib-tex-file). if (bibtex.openAttachedFile(Constants.BIBTEX_ENCODINGS[settings.getLastUsedBibtexFormat()], false)) { // tell about success Constants.zknlogger.log(Level.INFO, "BibTex-File was successfully refreshed."); } else { // tell about fail Constants.zknlogger.log(Level.INFO, "BibTex-File could not be found nor refreshed."); } } } /** * This method exports all attachments of the data-file to a file.<br><br> * This method fills a LinkedList with the export-data (i.e. the attachment-values).<br><br> * Then the method * {@link #exportList(java.util.LinkedList, java.lang.String) exportList(LinkedList,String)} * is called, which is responsible for saving the data of this linked list to a file. */ @Action(enabledProperty = "exportPossible") public void exportAttachments() { refreshAttachmentList(); // get length of attachment-table int len = jTableAttachments.getRowCount(); // create linked list that will contain all attachments LinkedList<String> attachments = new LinkedList<String>(); // copy all attachments to a linked list for (int cnt = 0; cnt < len; cnt++) attachments.add(jTableAttachments.getValueAt(cnt, 0).toString()); // call export-method exportList(attachments, "attachments"); } /** * * @param exportlist * @param type */ private void exportList(LinkedList<String> exportlist, String type) { String formats = getResourceMap().getString("exportListFormat1") + "," + getResourceMap().getString("exportListFormat2") + "," + getResourceMap().getString("exportListFormat3"); if (type.equalsIgnoreCase("authors")) formats = formats + "," + getResourceMap().getString("exportListFormat4"); Object[] choice = formats.split(","); Object expo = JOptionPane.showInputDialog(getFrame(), getResourceMap().getString("exportListFormatMsg"), getResourceMap().getString("exportListFormatTitle"), JOptionPane.PLAIN_MESSAGE, null, choice, null); // check for valid return value or cancel-operation of user if (expo != null) { // convert object to string String exportformat = expo.toString(); // check for valid file extenstion if (exportformat.equalsIgnoreCase(getResourceMap().getString("exportListFormat4"))) exportformat = "bib"; // here we open a swing filechooser, in case the os ist no mac aqua File filepath = FileOperationsUtil.chooseFile(getFrame(), (settings.isMacAqua()) ? FileDialog.SAVE : JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, null, null, getResourceMap().getString("exportListFormatTitle"), new String[] { "." + exportformat.toLowerCase() }, expo.toString(), settings); // if we have any valid if (filepath != null) { // init extension-string String ext = null; // retrieve fileextension, in case the user does not enter a fileextension later... if (exportformat.equals(getResourceMap().getString("exportListFormat1"))) ext = "." + getResourceMap().getString("exportListFormat1").toLowerCase(); if (exportformat.equals(getResourceMap().getString("exportListFormat2"))) ext = "." + getResourceMap().getString("exportListFormat2").toLowerCase(); if (exportformat.equals(getResourceMap().getString("exportListFormat3"))) ext = "." + getResourceMap().getString("exportListFormat3").toLowerCase(); if (exportformat.equals("bib")) ext = ".bib"; // check whether the user entered a file extension. if not, add "ext" as extension if (!filepath.getName().toLowerCase().endsWith(ext)) filepath = new File(filepath.getPath() + ext); // if file does not exist, create it - otherwise the getFilePath-method of // the settings-class would return "null" as filepath, if file doesn't exist if (!filepath.exists()) { try { filepath.createNewFile(); } catch (IOException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } } else { // file exists, ask user to overwrite it... int optionDocExists = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("askForOverwriteFileMsg"), getResourceMap().getString("askForOverwriteFileTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); // if the user does *not* choose to overwrite, quit... if (optionDocExists != JOptionPane.YES_OPTION) return; } // create variable that indicates errors... boolean errorOccured = false; // sort list aphabetically before exporting it Collections.sort(exportlist, new Comparer()); // here startes the export of xml-data if (exportformat.equals(getResourceMap().getString("exportListFormat1"))) { // create new document Document exportfile = new Document(new Element(type)); // create list-iterator Iterator<String> i = exportlist.iterator(); // iterate exportlist while (i.hasNext()) { // create new element Element e = new Element(Daten.ELEMENT_ENTRY); // at element from the list e.setText(i.next()); // add element to the document exportfile.getRootElement().addContent(e); } // save the xml-file try { // open the outputstream FileOutputStream fos = new FileOutputStream(filepath); // create a new XML-outputter with the pretty output format, // so the xml-file looks nicer XMLOutputter out = new XMLOutputter(Format.getPrettyFormat()); try { // save the main-export-file out.output(exportfile, fos); // close the output stream fos.close(); } catch (IOException e) { // log error-message Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); errorOccured = true; // show error message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errorSavingMsg"), getResourceMap().getString("errorSavingTitle"), JOptionPane.PLAIN_MESSAGE); } } catch (FileNotFoundException ex) { // log error-message Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); errorOccured = true; // show error message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errorSavingMsg"), getResourceMap().getString("errorSavingTitle"), JOptionPane.PLAIN_MESSAGE); } } else if (exportformat.equals("bib")) { ByteArrayOutputStream bout = null; OutputStream exportfile = null; try { bout = bibtex.saveFile(); // create filewriter exportfile = new FileOutputStream(filepath); // retrieve string String bibdata = bout.toString("UTF-8"); // write content exportfile.write(bibdata.getBytes(Charset.forName("UTF-8"))); } catch (FileNotFoundException ex) { // log error-message Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); errorOccured = true; } catch (IOException ex) { // log error-message Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); errorOccured = true; } finally { try { if (bout != null) bout.close(); if (exportfile != null) exportfile.close(); } catch (IOException ex) { // log error-message Constants.zknlogger.log(Level.WARNING, ex.getLocalizedMessage()); errorOccured = true; } } } else { // create stringbuilder for the final content StringBuilder finalcontent = new StringBuilder(""); // create list-iterator Iterator<String> i = exportlist.iterator(); // here startes the export of txt-data if (exportformat.equals(getResourceMap().getString("exportListFormat2"))) { // iterate exportlist and copy each list-element to the string, separated by new lines while (i.hasNext()) finalcontent.append(i.next()).append(System.getProperty("line.separator")); } // here startes the export of html-data else if (exportformat.equals(getResourceMap().getString("exportListFormat3"))) { // init html-page finalcontent.append("<html><head></head><body><ol>") .append(System.getProperty("line.separator")); // iterate exportlist and copy each list-element to the string, separated by new lines while (i.hasNext()) { // create dummy string to convert German umlauts String dummy = i.next(); // convert special chars to html dummy = dummy.replace("&", "&"); dummy = dummy.replace("\"", """); dummy = dummy.replace("", "ä"); dummy = dummy.replace("", "Ä"); dummy = dummy.replace("", "ö"); dummy = dummy.replace("", "Ö"); dummy = dummy.replace("", "ü"); dummy = dummy.replace("", "Ü"); dummy = dummy.replace("", "ß"); // append converted author to stringbuilder finalcontent.append("<li>").append(dummy).append("</li>") .append(System.getProperty("line.separator")); } // close html-page finalcontent.append(System.getProperty("line.separator")).append("</ol></body></html>"); } // init output-filewriter Writer exportfile = null; try { // create filewriter exportfile = new FileWriter(filepath); // and save file to disk exportfile.write(finalcontent.toString()); } catch (IOException ex) { // log error-message Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); errorOccured = true; // show error message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errorSavingMsg"), getResourceMap().getString("errorSavingTitle"), JOptionPane.PLAIN_MESSAGE); } finally { try { // finally, close filewrite if (exportfile != null) { exportfile.close(); } } catch (IOException ex) { // log error-message Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); errorOccured = true; // show error message JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errorSavingMsg"), getResourceMap().getString("errorSavingTitle"), JOptionPane.PLAIN_MESSAGE); } } } // if an errors occured, show error-log if (errorOccured) { showErrorIcon(); } else { JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("exportOkMsg"), getResourceMap().getString("exportOkTitle"), JOptionPane.PLAIN_MESSAGE); } } } } /** * This methods goes back through the history and sets the current entry * to the related entry in the history... */ @Action(enabledProperty = "historyBackAvailable") public void historyBack() { // go back through history data.historyBack(); // and update the whole content updateDisplay(); } /** * This methods goes fore through the history and sets the current entry * to the related entry in the history... */ @Action(enabledProperty = "historyForAvailable") public void historyFor() { // go fore through history data.historyFore(); // and update the whole content updateDisplay(); } /** * Copies the current selection, or the whole text if no selection * is made, of the textfield which currently has the focus to the clipboard. * If no textfield is the focus owner, the selected values of the list or table * which has the focus is copied to the clipboard. */ @Action public void selectAllText() { // look for the component which has the focus and copy the (selected) text if (jEditorPaneEntry.isFocusOwner()) jEditorPaneEntry.selectAll(); if (jListEntryKeywords.isFocusOwner()) jListEntryKeywords.setSelectionInterval(0, keywordListModel.size() - 1); if (jTableKeywords.isFocusOwner()) jTableKeywords.selectAll(); if (jTableAuthors.isFocusOwner()) jTableAuthors.selectAll(); if (jTableTitles.isFocusOwner()) jTableTitles.selectAll(); if (jTableAttachments.isFocusOwner()) jTableAttachments.selectAll(); } /** * Shows the search results window. If it hasn't been created yet, a new instance will be created. * <br><br> * The window is modal, thus we don't wait for reactions here. */ @Action(enabledProperty = "searchResultsAvailable") public void showSearchResultWindow() { if (null == searchResultsDlg) searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); ZettelkastenApp.getApplication().show(searchResultsDlg); } @Action public void showNewEntryWindow() { if (newEntryDlg != null) { newEntryDlg.setAlwaysOnTop(true); newEntryDlg.toFront(); newEntryDlg.requestFocus(); newEntryDlg.setAlwaysOnTop(false); } } /** * Shows the desktop/outliner window. If it hasn't been created yet, a new instance will be created. * <br><br> * The window is modal, thus we don't wait for reactions here. */ @Action(enabledProperty = "desktopAvailable") public void showDesktopWindow() { if (null == desktopDlg) desktopDlg = new DesktopFrame(this, taskinfo, data, bookmarks, desktop, settings, acceleratorKeys, bibtex, autoKorrekt, steno); ZettelkastenApp.getApplication().show(desktopDlg); } /** * Shows the desktop/outliner window. If it hasn't been created yet, a new instance will be created. * <br><br> * The window is modal, thus we don't wait for reactions here. */ @Action public void showEntryInDesktopWindow() { showEntryInDesktopWindow(displayedZettel); } public void showEntryInDesktopWindow(int nr) { // check for valid value if (-1 == nr) return; // check whether desktop frame is already open. if not, create one if (null == desktopDlg) desktopDlg = new DesktopFrame(this, taskinfo, data, bookmarks, desktop, settings, acceleratorKeys, bibtex, autoKorrekt, steno); // show frame ZettelkastenApp.getApplication().show(desktopDlg); // show entry on desktop desktopDlg.showEntryInDesktop(nr); } /** * Retrieves the selected text and adds it as new keyword to the entry. */ @Action(enabledProperty = "entriesAvailable") public void addToKeywordList() { // retrieve selected text String selection = jEditorPaneEntry.getSelectedText(); // check whether we have any selection at all if (selection != null && !selection.isEmpty()) { // TODO zeilenumbrche auslesen // since new-lines are not recognized when selecting text (instead, new lines are // simple space-chars, thus multiple lines appear as one line with several space-separated word) // we need to check whether the selected text appears as whole phrase in the entry // ... // add it to keywords if (!addKeywords(new String[] { selection.trim() }, true)) JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("noNewKeywordsFoundMsg"), getResourceMap().getString("noNewKeywordsFoundTitle"), JOptionPane.PLAIN_MESSAGE); } } /** * Retrieves the selected text and sets it as entry's title. */ @Action(enabledProperty = "entriesAvailable") public void setSelectionAsTitle() { // retrieve selected text String selection = jEditorPaneEntry.getSelectedText(); // check whether we have any selection at all if (selection != null && !selection.isEmpty()) { // set new title data.setZettelTitle(displayedZettel, selection.trim()); // change edited timestamp data.changeEditTimeStamp(displayedZettel); // and update display updateDisplayParts(displayedZettel); // and tabbed pane updateTabbedPane(); } } /** * Retrieves the first text line and sets it as entry's title. */ @Action(enabledProperty = "entriesAvailable") public void setFirstLineAsTitle() { // retrieve selected text String title = data.getCleanZettelContent(displayedZettel); // check whether we have any selection at all if (title != null && !title.isEmpty()) { // remove carriage returns title = title.replace("\r", ""); // set new title data.setZettelTitle(displayedZettel, title.split("\n")[0].trim()); // change edited timestamp data.changeEditTimeStamp(displayedZettel); // and update display updateDisplayParts(displayedZettel); // and tabbed pane updateTabbedPane(); } } /** * Retrieves the first text line and sets it as entry's title. This method is called * from the titles-tab and used for automatically setting titles to all entries that * have no titles yet. */ @Action(enabledProperty = "entriesAvailable") public void automaticFirstLineAsTitle() { // ask user if he wants to remove the lines that have been set as title int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("removeTitleLineMsg"), getResourceMap().getString("removeTitleLineTitle"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); // if user cancelled or closed the dialog, leave method if (JOptionPane.CANCEL_OPTION == option || JOptionPane.CLOSED_OPTION == option) return; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SETFIRSTLINEASTITLE, data, option); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // reset title-list data.setTitlelistUpToDate(false); // and update display updateDisplayParts(displayedZettel); // and tabbed pane updateTabbedPane(); } /** * Opens the find dialog and sets the text selection as default search term. */ @Action(enabledProperty = "textSelected") public void findFromSelection() { // retrieve selected text String selection = jEditorPaneEntry.getSelectedText(); // check whether we have any selection at all if (selection != null && !selection.isEmpty()) { find(selection.trim()); } } /** * Opens the find dialog. */ @Action(enabledProperty = "moreEntriesAvailable") public void find() { find(null); } /** * Opens the replace dialog. */ @Action(enabledProperty = "moreEntriesAvailable") public void replace() { replace(getFrame(), null, null); } /** * Opens the find dialog. An optional initial value {@code initSearchTerm} can be supplied * as parameter. * @param initSearchTerm (optional) - can be used to set an initial search term. * can be {@code null} if not used. */ private void find(String initSearchTerm) { // if dialog window isn't already created, do this now if (null == searchDlg) { // create a new dialog window searchDlg = new CSearchDlg(getFrame(), searchrequests, settings, initSearchTerm); // center window searchDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(searchDlg); // open the search dialog // the parameters are as following: if (!searchDlg.isCancelled()) startSearch(searchDlg.getSearchTerms(), // - string-array with search results searchDlg.getWhereToSearch(), // - the type of search, i.e. where to look searchDlg.getLogical(), // - logical-and-combination searchDlg.isWholeWord(), // - whole words searchDlg.isMatchCase(), // - case-sensitive search searchDlg.isSynonymsIncluded(), // - whether synonyms are included in the search or not searchDlg.isRegExSearch(), // - whether the search term is a regular expression searchDlg.isTimestampSearch(), // - whether the search is limited to a certain period of time (creation or change date of entry) searchDlg.getDateFromValue(), // - the start of the time period searchDlg.getDateToValue(), // - the end of the time period searchDlg.getTimestampIndex(), // - whether the user wants to look for a time period of the *creation* or *edited* time stamp false, // - whether the search results are only needed for internal use (e.g. manual links, desktop etc.) or used as "real" search results Constants.STARTSEARCH_USUAL, // - the type of search (usual, within authors etc.) Constants.SEARCH_USUAL); // dispose window after closing searchDlg.dispose(); searchDlg = null; // try to motivate garbage collector System.gc(); } /** * Opens the replace-dialog and optionally sets the initial values {@code initSearchTerm} * and {@code replaceentries}. If not cancelled, the requestes serach term will be replaced * by its entered find term. applies to those domains (content, titles, keywords) which have * been checked in the replace dialog. * * @param frame * @param initSearchTerm optional. an initial search term that will be automatically set when * the dialog is opened. use {@code null} if not used. * @param replaceentries an integer-array that contains the entry-numbers where the replacements * should be applied to. use {@code null} to find and replace in <i>all</i> entries. else, if * replacements should only be done within certain entries (e.g. search results), simply pass * the entries' numbers as integer-array. * @return {@code true} if replacement was done, false if it was cancelled. */ public boolean replace(JFrame frame, String initSearchTerm, int[] replaceentries) { // if dialog window isn't already created, do this now if (null == replaceDlg) { // create a new dialog window replaceDlg = new CReplaceDialog(frame, settings, initSearchTerm, (replaceentries != null)); // center window replaceDlg.setLocationRelativeTo(frame); } ZettelkastenApp.getApplication().show(replaceDlg); // commented, since we want to allow empty find or replace terms // if (!replaceDlg.cancelled && (!replaceDlg.findTerm.isEmpty()&&!replaceDlg.replaceTerm.isEmpty()) ) { // when the user did not cancel, start replacement now. if (!replaceDlg.isCancelled()) { // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(frame, TaskProgressDialog.TASK_REPLACE, taskinfo, data, replaceDlg.getFindTerm(), // the find term replaceDlg.getReplaceTerm(), // the replace term replaceentries, // an array or entry numbers where the replacement should be applied to. Use null to find and replace in all entries replaceDlg.getWhereToSearch(), // where to replace, i.e. authors, keywords, content... replaceDlg.isWholeWord(), // whether only whole words should be found replaceDlg.isMatchCase(), // whether search is case sensitive replaceDlg.isRegEx()); // whether find/replace-terms are regular expressions // center window taskDlg.setLocationRelativeTo(frame); } ZettelkastenApp.getApplication().show(taskDlg); // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // show replace-results JOptionPane.showMessageDialog(frame, taskinfo.getReplaceMessage(), getResourceMap().getString("replace.Action.text"), JOptionPane.PLAIN_MESSAGE); // update the tabbed pane, in case we have to update a list/table-content updateTabbedPane(); } // if search was cancelled, return false else { // dispose dialogs replaceDlg.dispose(); replaceDlg = null; // try to motivate garbage collector System.gc(); return false; } // dispose dialogs replaceDlg.dispose(); replaceDlg = null; // try to motivate garbage collector System.gc(); // return true... return true; } /** * Starts a search request and finds entries that don't contain any keywords. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithoutKeywords() { findEntryWithout(Constants.SEARCH_NO_KEYWORDS); } /** * Starts a search request and finds entries that don't have any remarks. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithoutRemarks() { findEntryWithout(Constants.SEARCH_NO_REMARKS); } /** * Starts a search request and finds entries that have remarks. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithRemarks() { findEntryWithout(Constants.SEARCH_WITH_REMARKS); } /** * Starts a search request and finds entries that have attachments. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithAttachments() { findEntryWithout(Constants.SEARCH_WITH_ATTACHMENTS); } /** * Starts a search request and finds entries that don't contain any authors. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithoutAuthors() { findEntryWithout(Constants.SEARCH_NO_AUTHORS); } /** * Starts a search request and finds entries that have been rated. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithRating() { findEntryWithout(Constants.SEARCH_WITH_RATINGS); } /** * Starts a search request and finds entries that have <i>not</i>been rated. */ @Action(enabledProperty = "moreEntriesAvailable") public void findWithoutRating() { findEntryWithout(Constants.SEARCH_WITHOUT_RATINGS); } /** * Starts a search request and finds entries <i>not</i> according to a certain find term, * but according to missing or non-missing fields. With this function you can for instance * search for entries that don't have keyword-values yet, or that don't have any remarks yet. * * @param what a value that indicates in which domains the user wants to search. You can e.g. * find entries without keywords, without authors or with remarks etc.<br><br> * Use following constants:<br> * <ul> * <li>{@code CConstants.SEARCH_NO_AUTHORS} - finds entries with<i>out</i> author values</li> * <li>{@code CConstants.SEARCH_NO_KEYWORDS} - finds entries with<i>out</i> keyword values</li> * <li>{@code CConstants.SEARCH_NO_REMARKS} - finds entries with<i>out</i> remarks</li> * <li>{@code CConstants.SEARCH_WITH_REMARKS} - finds entries with remarks</li> * <li>{@code CConstants.SEARCH_WITH_ATTACHMENTS} - finds entries with attachments</li> * <li>{@code CConstants.SEARCH_WITH_RATINGS} - finds entries that have been rated</li> * </ul> */ private void findEntryWithout(int what) { // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SEARCH, data, searchrequests, synonyms, what, null, null, -1, Constants.LOG_OR, true, true, true, false, false, null, null, 0, false); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // 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) // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have any search results at all if (searchrequests.getCurrentSearchResults() != null) { // if dialog window isn't already created, do this now if (null == searchResultsDlg) searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); // show search results window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } else { // display error message box that nothing was found JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errNothingFoundMsg"), getResourceMap().getString("errNothingFoundTitle"), JOptionPane.PLAIN_MESSAGE); } // try to motivate garbage collector System.gc(); } @Action(enabledProperty = "moreEntriesAvailable") public void findEntriesWithTimeStampCreated() { findEntriesWithTimeStamp(Constants.SEARCH_WITH_CREATED_TIME, Constants.TIMESTAMP_CREATED, Constants.SEARCH_WITH_CREATED_TIME); } @Action(enabledProperty = "moreEntriesAvailable") public void findEntriesWithTimeStampEdited() { findEntriesWithTimeStamp(Constants.SEARCH_WITH_EDITED_TIME, Constants.TIMESTAMP_EDITED, Constants.SEARCH_WITH_EDITED_TIME); } /** * This method searches for entries that have been either created or edited during a certain time-period. * it is not necessary to provide a search term here.<br><br> * The user is being prompted to enter a startdate (start of search period) and end date. Depending on * which menu-items calls this method, either all entries that have been created or edited during that period * are shown in the search results window. * * @param wherestamp in which part of the entry should be searched, necessary for search description. use * {@code CConstants.SEARCH_WITH_CREATED_TIME} or {@code CConstants.SEARCH_WITH_EDITED_TIME} * @param whichstamp which timestamp is relevant use {@code CConstants.TIMESTAMP_CREATED} or * {@code CConstants.TIMESTAMP_EDITED} * @param whichsearch the type of search, relevant for the CStartSearch-class. use * {@code CConstants.SEARCH_WITH_CREATED_TIME} or {@code CConstants.SEARCH_WITH_EDITED_TIME} */ private void findEntriesWithTimeStamp(int wherestamp, int whichstamp, int whichsearch) { // create default timestamp. this is only relevant for importing old data-files (.zkn), because // entries of old data-files may not always have timestamps. to ensure each entry has a time stamp // we offer the user to input a default date that is set for all entries that do not have any timestamp String starttime = null; String stime = ""; boolean cancelled = false; boolean inputIsOk = false; // wait for valid input while (!cancelled && !inputIsOk) { // show input-dialog starttime = (String) JOptionPane.showInputDialog(getFrame(), // parent window getResourceMap().getString("startTimeStampMsg"), // message text getResourceMap().getString("startTimeStampTitle"), // messagebox title JOptionPane.PLAIN_MESSAGE); // type of dialog // now convert the timestamp into something // therefore, check whether we have any valid input at all, if we have the correct length (8 chars) // and if we have to "." at the right position. A valid input would be e.g. "31.12.08" (dd.mm.yy) if (starttime != null && 8 == starttime.length() && starttime.charAt(2) == '.' && starttime.charAt(5) == '.') { stime = starttime; starttime = starttime.substring(6) + starttime.substring(3, 5) + starttime.substring(0, 2); cancelled = false; inputIsOk = true; } else if (null == starttime || starttime.isEmpty()) { cancelled = true; inputIsOk = false; } } // check whether dialog was cancelled or not if (!inputIsOk && cancelled) return; // create default timestamp. this is only relevant for importing old data-files (.zkn), because // entries of old data-files may not always have timestamps. to ensure each entry has a time stamp // we offer the user to input a default date that is set for all entries that do not have any timestamp String endtime = null; String etime = ""; cancelled = false; inputIsOk = false; // wait for valid input while (!cancelled && !inputIsOk) { // show input-dialog endtime = (String) JOptionPane.showInputDialog(getFrame(), // parent window getResourceMap().getString("endTimeStampMsg"), // message text getResourceMap().getString("endTimeStampTitle"), // messagebox title JOptionPane.PLAIN_MESSAGE); // type of dialog // now convert the timestamp into something // therefore, check whether we have any valid input at all, if we have the correct length (8 chars) // and if we have to "." at the right position. A valid input would be e.g. "31.12.08" (dd.mm.yy) if (endtime != null && 8 == endtime.length() && endtime.charAt(2) == '.' && endtime.charAt(5) == '.') { etime = endtime; endtime = endtime.substring(6) + endtime.substring(3, 5) + endtime.substring(0, 2); cancelled = false; inputIsOk = true; } else if (null == endtime || endtime.isEmpty()) { cancelled = true; inputIsOk = false; } } // check whether dialog was cancelled or not if (!inputIsOk && cancelled) return; // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SEARCH, data, searchrequests, synonyms, whichsearch, new String[] { stime, etime }, null, -1, Constants.LOG_OR, true, true, true, false, true, starttime, endtime, whichstamp, false); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // 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) // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have any search results at all if (searchrequests.getCurrentSearchResults() != null) { // if dialog window isn't already created, do this now if (null == searchResultsDlg) searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); // show search window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); } // try to motivate garbage collector System.gc(); } /** * This method show the panel with the live-search text box, * where the user can find text in the current entry live by typing. */ @Action(enabledProperty = "entriesAvailable") public void findLive() { // show panel with live-search-textbox jPanelLiveSearch.setVisible(true); // set focus to textbox jTextFieldLiveSearch.requestFocusInWindow(); // indicate that live search is active isLiveSearchActive = true; } /** * Cancels the live-search by simply hiding the panel */ @Action public void findLiveCancel() { // hide live-search-bar jPanelLiveSearch.setVisible(false); // reset highlight terms HtmlUbbUtil.setHighlighTerms(null, HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH, false); // indicate that live search is over isLiveSearchActive = false; // update display, i.e. remove highlighted search terms updateDisplayParts(displayedZettel); } /** * Opens the search dialog. This method can deal several search requests.<br><br>For instance, we * can have a usual search where the user wants to have search results displayed in a new frame * (CSearchResults). This action is typically performed, when the user starts a search-request * from the find-dialog (see {@link #find() find()}) or when the user double-clicks on selected entries * in the jTableAuthors or jTableKeywords for example. * <br><br> * On the other hand, the search-algorithm is also used to retrieve entries for adding them to the * desktop, as manual links or as follower-numbers. In this case, the user chose to add - for instance - * all entries that match a certain keyword as manual links to the current entry (see {@link #addManLinksFromKeywords(int) addManlinks}) * or if the user wants to add all entries from a certain author to the desktop (see {@link #addDesktopFromAuthors(int) addDesktopFromAuthors}). * In this case, no searchresults-dialog (CSearchResults) is shown - instead, the "searchresults" are those entries * that have to be added as manual links or to the desktop. * <br><br> * The relevant parameters for indicating this are {@code displayonly} and {@code searchtype}, see below. * <br><br> * In case of keyword- and author-search <i>from the table</i> (lists), we can neglect the last * parameter, since keyword- and author-search simply functions by searching * for the index-numbers, that are always - or never - case sensitive relevant. * <br><br> * When we have searchterms from the search-dialog, the user also can search for <i>parts</i> inside * a keyword-string, so here the whole-word-parameter is relevant, since we then don't compare by index- * numbers, but by the string-value of the keywords/authors. * * @param searchterms string-array with search terms * @param where the type of search, i.e. where to look, e.g. searching for keywords, authors, text etc. * @param logical * @param wholeword whether we look for whole words or also parts of a word/phrase * @param matchcase whether the search should be case sensitive or not * @param syno * @param regex * @param timesearch whether the user requested a time-search, i.e. a search for entries that were created * or changed within a certain period * @param datefrom the start of the period, when a timesearch is requested. format: "yymmdd". * @param dateto the end of the period, when a timesearch is requested. format: "yymmdd". * @param timestampindex * @param displayonly true, if the search results are only needed for adding them to the entry as manual links, luhmann-numbers * or to the desktop. use false, if the search results should be displayed in the CSearchResults-dialog * @param startsearchtype if we just use the search to retrieve entries that should be added as luhmann-numbers, as manual links * or to the desktop, we can indicate this with this parameter. Also a usual search request is passed with this variable. * use <i>CConstants.STARTSEARCH_xxx</i> for the appropriate type. * @param searchtype */ public void startSearch(String[] searchterms, int where, int logical, boolean wholeword, boolean matchcase, boolean syno, boolean regex, boolean timesearch, String datefrom, String dateto, int timestampindex, boolean displayonly, int startsearchtype, int searchtype) { // check whether we have valid searchterms or not... if ((null == searchterms) || (searchterms.length < 1)) return; // in case we search for adding desktop-entries, we have to modify the search type here. // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_SEARCH, data, searchrequests, synonyms, searchtype, searchterms, null, where, logical, wholeword, matchcase, syno, regex, timesearch, datefrom, dateto, timestampindex, displayonly); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // 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) // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // check whether we have any search results at all if (searchrequests.getCurrentSearchResults() != null) { // check the search type, whether a usual search is requested or if we want to retrieve entries from // keywords or author-table. switch (startsearchtype) { // this is a usual search, that means the search results are added // to the CSearchResults-dialog-frame and displayed case Constants.STARTSEARCH_USUAL: // if dialog window isn't already created, do this now if (null == searchResultsDlg) searchResultsDlg = new SearchResultsFrame(this, data, searchrequests, desktop, settings, acceleratorKeys, synonyms, bibtex); // show search window ZettelkastenApp.getApplication().show(searchResultsDlg); // show latest search results by auto-selecting the last item in the combo-box searchResultsDlg.showLatestSearchResult(); // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); break; // this is a luhmann-search, that means the search results are *not* shown in // the searchresults-window. instead, they are added as follower-numbers to // the current entry. case Constants.STARTSEARCH_LUHMANN: // if dialog window isn't already created, do this now if (null == taskDlg) { // get parent und init window taskDlg = new TaskProgressDialog(getFrame(), TaskProgressDialog.TASK_ENTRIESTOLUHMANN, data, searchrequests.getCurrentSearchResults(), data.getCurrentZettelPos()); // center window taskDlg.setLocationRelativeTo(getFrame()); } ZettelkastenApp.getApplication().show(taskDlg); // 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) // dispose the window and clear the object taskDlg.dispose(); taskDlg = null; // try to motivate garbage collector System.gc(); break; // this is a desktop-search, that means the search results are *not* shown in // the searchresults-window. instead, they are added to the desktop case Constants.STARTSEARCH_DESKTOP: // if desktop window isn't already created, do this now if (null == desktopDlg) desktopDlg = new DesktopFrame(this, taskinfo, data, bookmarks, desktop, settings, acceleratorKeys, bibtex, autoKorrekt, steno); // show desktop window ZettelkastenApp.getApplication().show(desktopDlg); // add found entries to desktop desktopDlg.addEntries(searchrequests.getCurrentSearchResults()); // enable window-menu-item, if we have loaded desktop data setDesktopAvailable(desktop.getCount() > 0); break; // this is a manlink-search, that means the search results are *not* shown in // the searchresults-window. instead, they are added as manual links to // the current entry. case Constants.STARTSEARCH_MANLINK: addToManLinks(searchrequests.getCurrentSearchResults()); break; } } else { // display error message box that nothing was found JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("errNothingFoundMsg"), getResourceMap().getString("errNothingFoundTitle"), JOptionPane.PLAIN_MESSAGE); } // try to motivate garbage collector System.gc(); } /** * This method gets all selected elements of the jListEntryKeywords * and returns them in an array. * * @return a string-array containing all selected entries, or null if no selection made */ private String[] retrieveSelectedKeywordsFromList() { // get selected values Object[] values = jListEntryKeywords.getSelectedValues(); // if we have any selections, go on if (values != null && values.length > 0) { // create string array for selected values String[] keywords = new String[values.length]; // iterate array and copy value from list to array for (int cnt = 0; cnt < values.length; cnt++) keywords[cnt] = values[cnt].toString(); // return complete array return keywords; } // ...or null, if error occured. return null; } /** * Depending on the selected tabbed pane, this method retrieves the wither selected authors * from the jTableAuthors or the selected keywords from the jTableKeywords and starts a search * for those entries, that contain <i>all</i> selected entries. */ @Action(enabledProperty = "tableEntriesSelected") public void searchLogAnd() { // open the search dialog // the parameters are as following (see comments below): // however, in case of keyword- and author-search, we can neglect some // parameters, since keyword- and author-search simply functions by searching // for the index-numbers, that are e.g. always - or never - case sensitive relevant switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look Constants.LOG_AND, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); break; case TAB_KEYWORDS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), Constants.SEARCH_KEYWORDS, Constants.LOG_AND, true, true, settings.getSearchAlwaysSynonyms(), false, false, "", "", 0, false, Constants.STARTSEARCH_USUAL, Constants.SEARCH_USUAL); break; } } /** * Depending on the selected tabbed pane, this method retrieves the wither selected authors * from the jTableAuthors or the selected keywords from the jTableKeywords and starts a search * for those entries, that contain <i>all</i> selected entries. */ @Action(enabledProperty = "tableEntriesSelected") public void searchLogOr() { // open the search dialog // the parameters are as following: // however, in case of keyword- and author-search, we can neglect the last // parameter, since keyword- and author-search simply functions by searching // for the index-numbers, that are always - or never - case sensitive relevant switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look Constants.LOG_OR, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // time-period search false, // whether the search terms contain regular expressions or not "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); break; case TAB_KEYWORDS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), Constants.SEARCH_KEYWORDS, Constants.LOG_OR, true, true, settings.getSearchAlwaysSynonyms(), false, false, "", "", 0, false, Constants.STARTSEARCH_USUAL, Constants.SEARCH_USUAL); break; } } /** * Depending on the selected tabbed pane, this method retrieves the wither selected authors * from the jTableAuthors or the selected keywords from the jTableKeywords and starts a search * for those entries, that contain <i>all</i> selected entries. */ @Action(enabledProperty = "tableEntriesSelected") public void searchLogNot() { // open the search dialog // the parameters are as following: // however, in case of keyword- and author-search, we can neglect the last // parameter, since keyword- and author-search simply functions by searching // for the index-numbers, that are always - or never - case sensitive relevant switch (jTabbedPaneMain.getSelectedIndex()) { case TAB_AUTHORS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableAuthors, 0), // string-array with search terms Constants.SEARCH_AUTHOR, // the type of search, i.e. where to look Constants.LOG_NOT, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); break; case TAB_KEYWORDS: startSearch(ZettelkastenViewUtil.retrieveSelectedValuesFromTable(jTableKeywords, 0), Constants.SEARCH_KEYWORDS, Constants.LOG_NOT, true, true, settings.getSearchAlwaysSynonyms(), false, false, "", "", 0, false, Constants.STARTSEARCH_USUAL, Constants.SEARCH_USUAL); break; } } /** * Retrieves the selected keywords from the jListEntryKeywords and starts a search * for those entries, that contain <i>all</i> selected entries. */ @Action(enabledProperty = "listFilledWithEntry") public void searchKeywordsFromListLogAnd() { // open the search dialog // the parameters are as following: startSearch(retrieveSelectedKeywordsFromList(), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look Constants.LOG_AND, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); } /** * Retrieves the selected keywords from the jListEntryKeywords and starts a search * for those entries, that contain <i>none</i> of the selected entries. */ @Action(enabledProperty = "listFilledWithEntry") public void searchKeywordsFromListLogNot() { // open the search dialog // the parameters are as following: startSearch(retrieveSelectedKeywordsFromList(), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look Constants.LOG_NOT, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); } /** * Retrieves the selected keywords from the jTableKeywords and starts a search * for those entries, that contain <i>at least one</i> of the selected entries. */ @Action(enabledProperty = "listFilledWithEntry") public void searchKeywordsFromListLogOr() { // open the search dialog // the parameters are as following: startSearch(retrieveSelectedKeywordsFromList(), // string-array with search terms Constants.SEARCH_KEYWORDS, // the type of search, i.e. where to look Constants.LOG_OR, // the logical combination true, // whole-word-search true, // match-case-search settings.getSearchAlwaysSynonyms(), // whether synonyms should be included or not false, // whether the search terms contain regular expressions or not false, // time-period search "", // timestamp, date from (period start) "", // timestamp, date to (period end) 0, // timestampindex (whether the period should focus on creation or edited date, or both) false, // no display - whether the results should only be used for adding entries to the desktop or so (true), or if a searchresults-window shoud be opened (false) Constants.STARTSEARCH_USUAL, // whether we have a usual search, or a search for entries without remarks or keywords and so on - see related method findEntryWithout Constants.SEARCH_USUAL); } /** * Here we place the typical steps we have to do after a file was opened * or imported. typical tasks are for instance setting certain state-variables * to false or true, showing the first entry etc... */ private void updateAfterOpen() { // this is the typical stuff we need to do when a file is opened // or imported. first of all, all the views of the tabbed pane are not // uptodate, because we have new data. thus, we set all values to false, // indicating that all lists ar <b>not</b> up to date and all tables need // to be re-filled. data.setKeywordlistUpToDate(false); data.setAuthorlistUpToDate(false); data.setTitlelistUpToDate(false); data.setClusterlistUpToDate(false); data.setAttachmentlistUpToDate(false); // dispose and clear the window, if we have a created instance of it // (we need to do this e.g. if we have opened data, and load a new data-file) if (searchResultsDlg != null) { searchResultsDlg.dispose(); searchResultsDlg = null; // try to motivate garbage collector System.gc(); } // dispose and clear the window, if we have a created instance of it // (we need to do this e.g. if we have opened data, and load a new data-file) if (desktopDlg != null) { desktopDlg.dispose(); desktopDlg = null; // try to motivate garbage collector System.gc(); } // enable window-menu-item, if we have loaded search results setSearchResultsAvailable(searchrequests.getCount() > 0); // enable window-menu-item, if we have loaded desktop data setDesktopAvailable(desktop.getCount() > 0); // reset all necessary variables and clear all tables initVariables(); // update the new filename to the title updateTitle(); // update the display updateDisplay(); } /** * Changes the text in the application's titlebar, by adding the filename of the currently * opened file to it. */ private void updateTitle() { // get filename String fn = settings.getFileName(); // check whether we have any valid filepath at all if (fn != null) { // set file-name and app-name in title-bar getFrame().setTitle("[" + fn + "] - " + getResourceMap().getString("Application.title")); } // if we don't have any title from the file name, simply set the applications title else { getFrame().setTitle(getResourceMap().getString("Application.title")); } } /** * This method filters the entries in the jTableLinks depending on the selected keyword(s) * of the jListKeywords.<br><br> * This method is called when the user selects an entry from the list jListKeywords. * We then want to filter the list * with links/references to other entries (jTableLinks) to show only those links (entries) * that are related to the selected keywords.<br><br> * Futhermore, we want to offer logical-and and logical-or combination of the keywords, * i.e. showing either entries that contain ALL selected keywords or AT LEAST ONE of * the selected keywords. */ private synchronized void filterLinks() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // if the link-table is not shown, leave if (jTabbedPaneMain.getSelectedIndex() != TAB_LINKS) { return; } // if no selections made, or all values de-selected, leave method // and show all links instead if (jListEntryKeywords.getSelectedIndices().length < 1) { showLinks(); return; } // when thread is already running, do nothing... if (createFilterLinksIsRunning) { return; } // clear table DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel(); // reset the table tm.setRowCount(0); // tell user that we are doing something... statusMsgLabel.setText(getResourceMap().getString("createLinksMsg")); // create task Task cflT = createFilterLinks(); // 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(cflT); tM.setForegroundTask(cflT); } /** * Here we save the user- and programm settings. usually, this method is called from * within the exis listener */ private void saveSettings() { // save zettel-position settings.setStartupEntry(data.getCurrentZettelPos()); // save settings if (!settings.saveSettings()) { // if any problems occur, show error log showErrorIcon(); } } /** * This method is called when a user selects an entry from the jTableLinks. Whenever a * "linked" entry is selected in this table, we want to<br> * 1) display that entry and<br> * 2) highlight the keywords which are responsible for the relation between the activated entry * and the currently shown entry (i.e. the selectedone in the jTable).<br><br> * The highlighted keywords are shown in the jListEntryKeywords. */ private void showRelatedKeywords() { // if no data available, leave method if (data.getCount(Daten.ZKNCOUNT) < 1) { return; } // no update to linked list needed needsLinkUpdate = false; // get the selected row int entry = ZettelkastenViewUtil.retrieveSelectedEntryFromTable(data, jTableLinks, 0); // if we don't have a valid selection, use current entry as reference if (-1 == entry) { updateDisplayParts(data.getCurrentZettelPos()); } else { // and if it was a avalid value, show entry updateDisplayParts(entry); // get all keywords of the table's entry String[] kws_table = data.getKeywords(entry); // get keywords of current entry String[] kws_current = data.getCurrentKeywords(); // create new array int[] selections = {}; // if we have any keywords, go on... if ((kws_table != null) && (kws_current != null) && (kws_table.length > 0) && (kws_current.length > 0)) { // sort both array to keep the right order, which must be the same than the sorted // order in the jListEntryKewords... if (kws_table.length > 0) { Arrays.sort(kws_table, new Comparer()); } if (kws_current.length > 0) { Arrays.sort(kws_current, new Comparer()); } // go through both array and count the matches // after that, we can create an integer-array with the necessary amount of elements // init counter int count = 0; // go through outer array and compare for matching keywords for (String kw_outer : kws_table) { // iterate inner array for (String kw_inner : kws_current) { // compare valued of outer and inner loop-array if (kw_outer.equals(kw_inner)) { // incerease counter on macth count++; // and leave loop break; } } } // create new integer array with the size of the count of matching keywords selections = new int[count]; // create second counter for the above array int cnt = 0; // now iterate the array again. first the outer one for (int cnt_out = 0; cnt_out < kws_table.length; cnt_out++) { for (String kws_current1 : kws_current) { // compare for matching arrays if (kws_table[cnt_out].equals(kws_current1)) { // first, store the entry-index-number of the jList in the integer-array selections[cnt] = cnt_out; // increase the array counter cnt++; // and leave the inner loop to look for the next matching keyword break; } } } } // finally, show all selected keywords jListEntryKeywords.setSelectedIndices(selections); } } public void setBackupNecessary() { isbackupnecessary = bibtex.isModified() | synonyms.isModified() | data.isMetaModified() | data.isModified() | searchrequests.isModified() | bookmarks.isModified() | desktop.isModified(); // update mainframe's toolbar and enable save-function if (isbackupnecessary) { setSaveEnabled(true); } } public void resetBackupNecessary() { isbackupnecessary = false; } /** * This method checks whether there are unsaved changes in the data-files (maindata, bookmarks, * searchrequests, desktop-data...) and prepares a msg to save these changes. Usually, this * method is called when there are modifications in one of the above mentioned datafiles, and * a new data-file is to be imported or opened, or when the application * is about to quit. * * @param title the title of the message box, e.g. if the changes should be saved because the user * wants to quit the application of to open another data file * @return <i>true</i> if the changes have been successfully saved or if the user did not want to save anything, and * the program can go on. <i>false</i> if the user cancelled the dialog and the program should <i>not</i> go on * or not quit. */ private boolean askForSaveChanges(String title) { // first check whether we have unsaved changes StringBuilder confirmText = new StringBuilder(""); // check, which part of the data file has unsaved changes and set the related // warning message and title strings. // check whether we have any changes at all boolean anychanges = bibtex.isModified() | synonyms.isModified() | data.isMetaModified() | data.isModified() | searchrequests.isModified() | bookmarks.isModified() | desktop.isModified(); // and then check, which parts of the data-file have been changed... if (data.isMetaModified()) { confirmText.append(getResourceMap().getString("msgSaveMeta")); } if (data.isModified()) { confirmText.append(getResourceMap().getString("msgSaveData")); } if (searchrequests.isModified()) { confirmText.append(getResourceMap().getString("msgSaveSearches")); } if (bookmarks.isModified()) { confirmText.append(getResourceMap().getString("msgSaveBookmarks")); } if (desktop.isModified()) { confirmText.append(getResourceMap().getString("msgSaveDesktop")); } if (synonyms.isModified()) { confirmText.append(getResourceMap().getString("msgSaveSynonyms")); } if (bibtex.isModified()) { confirmText.append(getResourceMap().getString("msgSaveBibTex")); } // if we have any strings, we can assume we have to save changes if (anychanges) { // if so, open a confirm dialog int option = JOptionPane.showConfirmDialog(getFrame(), getResourceMap().getString("msgSaveChanges", confirmText.toString()), title, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); // if no save is requested, exit immediately if (JOptionPane.NO_OPTION == option) { return true; } // if action is cancelled, return to the program if (JOptionPane.CANCEL_OPTION == option || JOptionPane.CLOSED_OPTION == option /* User pressed cancel key */) { return false; } // else save the data // and exit return saveDocument(); } // no changes, so everything is ok return true; } /** * This is the Exit-Listener. Here we put in all the things which should be done * before closing the window and exiting the program */ private class ConfirmExit implements Application.ExitListener { @Override public boolean canExit(EventObject e) { // if we still have an active edit-progress, don't quit the apllication, but tell // the user to finish editing first... if (isEditModeActive) { // show message box JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("cannotExitActiveEditMsg"), getResourceMap().getString("cannotExitActiveEditTitle"), JOptionPane.PLAIN_MESSAGE); // bring edit window to front if (newEntryDlg != null) { newEntryDlg.toFront(); } // and don't exit... return false; } if (createAutoBackupIsRunning) { // show message box JOptionPane.showMessageDialog(getFrame(), getResourceMap().getString("cannotExitAutobackMsg"), getResourceMap().getString("cannotExitAutobackTitle"), JOptionPane.PLAIN_MESSAGE); // and don't exit... return false; } // return true to say "yes, we can", or false if exiting should cancelled return askForSaveChanges(getResourceMap().getString("msgSaveChangesOnExitTitle")); } @Override public void willExit(EventObject e) { // when exiting, kill all timers (auto-save, memory-logging...) terminateTimers(); // save the settings saveSettings(); // and create an additional backup, when option is activated. makeExtraBackup(); } } /** * This is an application listener that is initialised when running the program * on mac os x. by using this appListener, we can use the typical apple-menu bar * which provides own about, preferences and quit-menu-items. */ private void setupMacOSXApplicationListener() { // <editor-fold defaultstate="collapsed" desc="Application-listener initiating the stuff for the Apple-menu."> try { // get mac os-x application class Class appc = Class.forName("com.apple.eawt.Application"); // create a new instance for it. Object app = appc.newInstance(); // get the application-listener class. here we can set our action to the apple menu Class lc = Class.forName("com.apple.eawt.ApplicationListener"); Object listener = Proxy.newProxyInstance(lc.getClassLoader(), new Class[] { lc }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) { if (method.getName().equals("handleQuit")) { // call the general exit-handler from the desktop-application-api // here we do all the stuff we need when exiting the application ZettelkastenApp.getApplication().exit(); } if (method.getName().equals("handlePreferences")) { // show settings window settingsWindow(); } if (method.getName().equals("handleAbout")) { // show own aboutbox showAboutBox(); try { // set handled to true, so other actions won't take place any more. // if we leave this out, a second, system-own aboutbox would be displayed setHandled(args[0], Boolean.TRUE); } catch (NoSuchMethodException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } catch (IllegalAccessException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } catch (InvocationTargetException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } } return null; } private void setHandled(Object event, Boolean val) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method handleMethod = event.getClass().getMethod("setHandled", new Class[] { boolean.class }); handleMethod.invoke(event, new Object[] { val }); } }); // tell about success Constants.zknlogger.log(Level.INFO, "Apple Class Loader successfully initiated."); try { // add application listener that listens to actions on the apple menu items Method m = appc.getMethod("addApplicationListener", lc); m.invoke(app, listener); // register that we want that Preferences menu. by default, only the about box is shown // but no pref-menu-item Method enablePreferenceMethod = appc.getMethod("setEnabledPreferencesMenu", new Class[] { boolean.class }); enablePreferenceMethod.invoke(app, new Object[] { Boolean.TRUE }); // tell about success Constants.zknlogger.log(Level.INFO, "Apple Preference Menu successfully initiated."); } catch (NoSuchMethodException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } catch (SecurityException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } catch (InvocationTargetException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); } } catch (ClassNotFoundException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } catch (IllegalAccessException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } catch (InstantiationException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); } // </editor-fold> } /** * 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="Initiation of 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 // // other components become normal gray - which is, however, a little bit // darker than the default gray // // snow-leopard and java 6/7 have different color-rendering, we need a different // background-color for OS X 10.5 and above as well as java 6 and 7 Color backcol = ColorUtil.getMacBackgroundColor(); // on Leopard (OS X 10.5), we have different rendering, thus we need these lines if (PlatformUtil.isLeopard()) { mainPanel.setBackground(backcol); } jPanelMainRight.setBackground(backcol); jSplitPaneMain1.setBackground(backcol); jSplitPane1.setBackground(backcol); jSplitPaneMain2.setBackground(backcol); jSplitPaneLinks.setBackground(backcol); jSplitPaneAuthors.setBackground(backcol); jTabbedPaneMain.setBackground(backcol); jPanel1.setBackground(backcol); jPanel2.setBackground(backcol); jPanel7.setBackground(backcol); jPanel8.setBackground(backcol); jPanel9.setBackground(backcol); jPanel10.setBackground(backcol); jPanel11.setBackground(backcol); jPanel13.setBackground(backcol); jPanel14.setBackground(backcol); jPanel15.setBackground(backcol); jPanelLiveSearch.setBackground(backcol); jPanelManLinks.setBackground(backcol); jPanelDispAuthor.setBackground(backcol); // make searchfields look like mac searchTextFieldVariants(); // remove custim borders jScrollPane2.setBorder(null); jScrollPane5.setBorder(null); jScrollPane16.setBorder(null); // make refresh buttons look like mac // get the action map javax.swing.ActionMap actionMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(ZettelkastenView.class, this); // init variables AbstractAction ac; // get the toolbar-action ac = (AbstractAction) actionMap.get("findLiveCancel"); // 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 setupSeaGlassStyle() { // make searchfields look like mac searchTextFieldVariants(); jEditorPaneClusterEntries.setBackground(Color.white); jEditorPaneIsFollower.setBackground(Color.white); } private void searchTextFieldVariants() { if (settings.isMacAqua() || settings.isSeaGlass()) { jTextFieldLiveSearch.putClientProperty("JTextField.variant", "search"); jTextFieldFilterKeywords.putClientProperty("JTextField.variant", "search"); jTextFieldFilterAuthors.putClientProperty("JTextField.variant", "search"); jTextFieldFilterTitles.putClientProperty("JTextField.variant", "search"); jTextFieldFilterCluster.putClientProperty("JTextField.variant", "search"); jTextFieldFilterAttachments.putClientProperty("JTextField.variant", "search"); } } private void makeSeaGlassToolbar() { Tools.makeTexturedToolBarButton(tb_newEntry, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_open, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_save, Tools.SEGMENT_POSITION_LAST); if (settings.getShowAllIcons()) { Tools.makeTexturedToolBarButton(tb_edit, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_delete, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_copy, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_paste, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_selectall, Tools.SEGMENT_POSITION_LAST); } else { Tools.makeTexturedToolBarButton(tb_copy, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_paste, Tools.SEGMENT_POSITION_LAST); } Tools.makeTexturedToolBarButton(tb_addmanlinks, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_addluhmann, Tools.SEGMENT_POSITION_MIDDLE); if (settings.getShowAllIcons()) { Tools.makeTexturedToolBarButton(tb_addbookmark, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_addtodesktop, Tools.SEGMENT_POSITION_LAST); } else { Tools.makeTexturedToolBarButton(tb_addbookmark, Tools.SEGMENT_POSITION_LAST); } if (settings.getShowAllIcons()) { Tools.makeTexturedToolBarButton(tb_find, Tools.SEGMENT_POSITION_FIRST); Tools.makeTexturedToolBarButton(tb_first, Tools.SEGMENT_POSITION_MIDDLE); } else { Tools.makeTexturedToolBarButton(tb_first, Tools.SEGMENT_POSITION_FIRST); } Tools.makeTexturedToolBarButton(tb_prev, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_next, Tools.SEGMENT_POSITION_MIDDLE); Tools.makeTexturedToolBarButton(tb_last, Tools.SEGMENT_POSITION_LAST); toolBar.setPreferredSize(new java.awt.Dimension(toolBar.getSize().width, Constants.seaGlassToolbarHeight)); toolBar.add(new javax.swing.JToolBar.Separator(), 0); } /** * * @param bottomBarNeedsUdpate if {@code true}, the bottom bar on mac aqua style will also be * re-initialized. Use {@code true} only the first time the bottom bar is initialized. For further * GUI-updates, e.g. from settings window, use {@code false} as parameter. */ private void makeMacToolbar() { // hide default toolbr toolBar.setVisible(false); getFrame().remove(toolBar); // and create mac toolbar if (settings.getShowIcons() || settings.getShowIconText()) { UnifiedToolBar mactoolbar = new UnifiedToolBar(); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_newEntry, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_open, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_save, MacButtonFactory.SEGMENT_POSITION_LAST)); mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); if (settings.getShowAllIcons()) { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_edit, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_delete, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_copy, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_paste, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_selectall, MacButtonFactory.SEGMENT_POSITION_LAST)); } else { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_copy, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_paste, MacButtonFactory.SEGMENT_POSITION_LAST)); } mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addmanlinks, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addluhmann, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); if (settings.getShowAllIcons()) { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addbookmark, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addtodesktop, MacButtonFactory.SEGMENT_POSITION_LAST)); } else { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_addbookmark, MacButtonFactory.SEGMENT_POSITION_LAST)); } mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1)); if (settings.getShowAllIcons()) { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_find, MacButtonFactory.SEGMENT_POSITION_FIRST)); mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_first, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); } else { mactoolbar.addComponentToLeft(MacButtonFactory.makeTexturedToolBarButton(tb_first, MacButtonFactory.SEGMENT_POSITION_FIRST)); } mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_prev, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_next, MacButtonFactory.SEGMENT_POSITION_MIDDLE)); mactoolbar.addComponentToLeft( MacButtonFactory.makeTexturedToolBarButton(tb_last, MacButtonFactory.SEGMENT_POSITION_LAST)); mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(32, 1)); mactoolbar.addComponentToLeft(tb_searchTextfield); mactoolbar.installWindowDraggerOnWindow(ZettelkastenView.super.getFrame()); mainPanel.add(mactoolbar.getComponent(), BorderLayout.PAGE_START); } makeMacBottomBar(); } /** */ private void makeMacBottomBar() { jPanel12.setVisible(false); BottomBar macbottombar = new BottomBar(); // history buttons buttonHistoryBack.setBorderPainted(true); buttonHistoryFore.setBorderPainted(true); buttonHistoryBack.putClientProperty("JButton.buttonType", "segmentedTextured"); buttonHistoryFore.putClientProperty("JButton.buttonType", "segmentedTextured"); buttonHistoryBack.putClientProperty("JButton.segmentPosition", "first"); buttonHistoryFore.putClientProperty("JButton.segmentPosition", "last"); buttonHistoryBack.putClientProperty("JComponent.sizeVariant", "small"); buttonHistoryFore.putClientProperty("JComponent.sizeVariant", "small"); macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(statusEntryLabel), 5); macbottombar.addComponentToLeft(jTextFieldEntryNumber, 5); macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(statusOfEntryLabel), 10); macbottombar.addComponentToLeft(buttonHistoryBack); macbottombar.addComponentToLeft(buttonHistoryFore, 10); macbottombar.addComponentToLeft(MacButtonFactory.makeUnifiedToolBarButton(statusErrorButton), 5); macbottombar.addComponentToLeft(MacButtonFactory.makeUnifiedToolBarButton(statusDesktopEntryButton)); macbottombar.addComponentToCenter(MacWidgetFactory.makeEmphasizedLabel(jLabelMemory)); macbottombar.addComponentToRight(MacWidgetFactory.makeEmphasizedLabel(statusMsgLabel)); macbottombar.addComponentToRight(statusAnimationLabel, 4); statusPanel.remove(jPanel12); statusPanel.setBorder(null); statusPanel.setLayout(new BorderLayout()); statusPanel.add(macbottombar.getComponent(), BorderLayout.PAGE_START); } /** * This class sets up a selection listener for the tables. each table which shall react * on selections, e.g. by showing an entry, gets this selectionlistener in the method * {@link #initSelectionListeners() initSelectionListeners()}. */ private class SelectionListener implements ListSelectionListener { JTable table; // It is necessary to keep the table since it is not possible // to determine the table from the event's source SelectionListener(JTable table) { this.table = table; } @Override public void valueChanged(ListSelectionEvent e) { // when a tableupdate is being processed, to call the listener... if (tableUpdateActive) { return; } // get list selection model ListSelectionModel lsm = (ListSelectionModel) e.getSource(); // set value-adjusting to true, so we don't fire multiple value-changed events... lsm.setValueIsAdjusting(true); if (jTableAuthors == table) { showAuthorText(); if (setBibKeyDlg != null) { setBibKeyDlg.initTitleAndBibkey(); } } else if (jTableTitles == table) { showEntryFromTitles(); } else if (jTableAttachments == table) { showEntryFromAttachments(); } // if the user selects an entry from the table, i.e. a referred link to another entry, // highlight the jListEntryKeywors, which keywords are responsible for the links to // the other entry else if (jTableLinks == table) { showRelatedKeywords(); } else if (jTableManLinks == table) { showEntryFromManualLinks(); } else if (jTableBookmarks == table) { showEntryFromBookmarks(); } } } /** * This variable indicates whether we have any entries, so we can en- or disable * the all relevant actions that need at least one entry to be enabled. */ private boolean entriesAvailable = false; public boolean isEntriesAvailable() { return entriesAvailable; } public void setEntriesAvailable(boolean b) { boolean old = isEntriesAvailable(); this.entriesAvailable = b; firePropertyChange("entriesAvailable", old, isEntriesAvailable()); } /** * This variable indicates whether we have more than one entry, so we can en- or disable * the all relevant actions that need at least two entries to be enabled. */ private boolean moreEntriesAvailable = false; public boolean isMoreEntriesAvailable() { return moreEntriesAvailable; } public void setMoreEntriesAvailable(boolean b) { boolean old = isMoreEntriesAvailable(); this.moreEntriesAvailable = b; firePropertyChange("moreEntriesAvailable", old, isMoreEntriesAvailable()); } /** * This variable indicates whether we have entries in the tables, so we can en- or disable * the cut and copy actions and other actions that need at least one selection. */ private boolean tableEntriesSelected = false; public boolean isTableEntriesSelected() { return tableEntriesSelected; } public void setTableEntriesSelected(boolean b) { boolean old = isTableEntriesSelected(); this.tableEntriesSelected = b; firePropertyChange("tableEntriesSelected", old, isTableEntriesSelected()); } /** * This variable indicates whether we have entries in the tables, so we can en- or disable * the cut and copy actions and other actions that need at least one selection. */ private boolean exportPossible = false; public boolean isExportPossible() { return exportPossible; } public void setExportPossible(boolean b) { boolean old = isExportPossible(); this.exportPossible = b; firePropertyChange("exportPossible", old, isExportPossible()); } /** * This variable indicates whether we have search results or not. dependent on this setting, * the related menu-item in the windows-menu is en/disbaled */ private boolean searchResultsAvailable = false; public boolean isSearchResultsAvailable() { return searchResultsAvailable; } public void setSearchResultsAvailable(boolean b) { boolean old = isSearchResultsAvailable(); this.searchResultsAvailable = b; firePropertyChange("searchResultsAvailable", old, isSearchResultsAvailable()); } /** * This variable indicates whether we have desktop data or not. dependent on this setting, * the related menu-item in the windows-menu is en/disbaled */ private boolean desktopAvailable = false; public boolean isDesktopAvailable() { return desktopAvailable; } public void setDesktopAvailable(boolean b) { boolean old = isDesktopAvailable(); this.desktopAvailable = b; firePropertyChange("DesktopAvailable", old, isDesktopAvailable()); } /** * This variable indicates whether we have entries in the lists, so we can en- or disable * the cut and copy actions and other actions that need at least one selection. */ private boolean listFilledWithEntry = false; public boolean isListFilledWithEntry() { return listFilledWithEntry; } public void setListFilledWithEntry(boolean b) { boolean old = isListFilledWithEntry(); this.listFilledWithEntry = b; firePropertyChange("listFilledWithEntry", old, isListFilledWithEntry()); } /** * This variable indicates whether we have seleced text, so we can en- or disable * the related actions. */ private boolean textSelected = false; public boolean isTextSelected() { return textSelected; } public void setTextSelected(boolean b) { boolean old = isTextSelected(); this.textSelected = b; firePropertyChange("textSelected", old, isTextSelected()); } /** * This variable indicates whether we have seleced text, so we can en- or disable * the related actions. */ private boolean bibtexFileLoaded = false; public boolean isBibtexFileLoaded() { return bibtexFileLoaded; } public void setBibtexFileLoaded(boolean b) { boolean old = isBibtexFileLoaded(); this.bibtexFileLoaded = b; firePropertyChange("bibtexFileLoaded", old, isBibtexFileLoaded()); } /** * This variable indicates whether the displayed entry is already bookmarked, * so we can en- or disable the bookmark-action. */ private boolean entryBookmarked = false; public boolean isEntryBookmarked() { return entryBookmarked; } public void setEntryBookmarked(boolean b) { boolean old = isEntryBookmarked(); this.entryBookmarked = b; firePropertyChange("entryBookmarked", old, isEntryBookmarked()); } /** * This variable indicates whether the a luhmann-number (i.e. entry in the jTreeLuhmann) * is selected or not. * so we can en- or disable the bookmark-action. */ private boolean luhmannSelected = false; public boolean isLuhmannSelected() { return luhmannSelected; } public void setLuhmannSelected(boolean b) { boolean old = isLuhmannSelected(); this.luhmannSelected = b; firePropertyChange("luhmannSelected", old, isLuhmannSelected()); } /** * This variable indicates whether an entry has follower or not (i.e. elements in the jTreeLuhmann) */ private boolean moreLuhmann = false; public boolean isMoreLuhmann() { return moreLuhmann; } public void setMoreLuhmann(boolean b) { boolean old = isMoreLuhmann(); this.moreLuhmann = b; firePropertyChange("moreLuhmann", old, isMoreLuhmann()); } /** * This variable indicates whether the a luhmann-number (i.e. entry in the jTreeLuhmann) * is selected or not. * so we can en- or disable the bookmark-action. */ private boolean saveEnabled = false; public boolean isSaveEnabled() { return saveEnabled; } public void setSaveEnabled(boolean b) { boolean old = isSaveEnabled(); this.saveEnabled = b; firePropertyChange("saveEnabled", old, isSaveEnabled()); } /** * This variable indicates whether the current entry ist displayed, or if * e.g. a selected other entry is shown - so we can "reset" the display by * showing the current entry again */ private boolean currentEntryShown = false; public boolean isCurrentEntryShown() { return currentEntryShown; } public void setCurrentEntryShown(boolean b) { boolean old = isCurrentEntryShown(); this.currentEntryShown = b; firePropertyChange("currentEntryShown", old, isCurrentEntryShown()); } /** * This variable indicates whether the history-function is available or not. */ private boolean historyForAvailable = false; public boolean isHistoryForAvailable() { return historyForAvailable; } public void setHistoryForAvailable(boolean b) { boolean old = isHistoryForAvailable(); this.historyForAvailable = b; firePropertyChange("historyForAvailable", old, isHistoryForAvailable()); } /** * This variable indicates whether the history-function is available or not. */ private boolean historyBackAvailable = false; public boolean isHistoryBackAvailable() { return historyBackAvailable; } public void setHistoryBackAvailable(boolean b) { boolean old = isHistoryBackAvailable(); this.historyBackAvailable = b; firePropertyChange("historyBackAvailable", old, isHistoryBackAvailable()); } /** 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() { mainPanel = new javax.swing.JPanel(); jSplitPaneMain1 = new javax.swing.JSplitPane(); jSplitPaneMain2 = new javax.swing.JSplitPane(); jPanel17 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); jEditorPaneEntry = new javax.swing.JEditorPane(); jPanelLiveSearch = new javax.swing.JPanel(); jTextFieldLiveSearch = new javax.swing.JTextField(); jButton1 = new javax.swing.JButton(); jScrollPane3 = new javax.swing.JScrollPane(); jListEntryKeywords = MacSourceList.createMacSourceList(); jPanelMainRight = new javax.swing.JPanel(); jTabbedPaneMain = new javax.swing.JTabbedPane(); jPanel1 = new javax.swing.JPanel(); jSplitPaneLinks = new javax.swing.JSplitPane(); jPanel14 = new javax.swing.JPanel(); jScrollPane4 = new javax.swing.JScrollPane(); jTableLinks = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jPanelManLinks = new javax.swing.JPanel(); jScrollPane15 = new javax.swing.JScrollPane(); jTableManLinks = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jPanel10 = new javax.swing.JPanel(); jSplitPane2 = new javax.swing.JSplitPane(); jScrollPane10 = new javax.swing.JScrollPane(); jTreeLuhmann = new javax.swing.JTree(); jScrollPane2 = new javax.swing.JScrollPane(); jEditorPaneIsFollower = new javax.swing.JEditorPane(); jPanel2 = new javax.swing.JPanel(); jTextFieldFilterKeywords = new javax.swing.JTextField(); jButtonRefreshKeywords = new javax.swing.JButton(); jCheckBoxShowSynonyms = new javax.swing.JCheckBox(); jPanel16 = new javax.swing.JPanel(); jScrollPane17 = new javax.swing.JScrollPane(); jTreeKeywords = new javax.swing.JTree(); jScrollPane6 = new javax.swing.JScrollPane(); jTableKeywords = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jPanel7 = new javax.swing.JPanel(); jTextFieldFilterAuthors = new javax.swing.JTextField(); jSplitPaneAuthors = new javax.swing.JSplitPane(); jPanel15 = new javax.swing.JPanel(); jScrollPane7 = new javax.swing.JScrollPane(); jTableAuthors = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jComboBoxAuthorType = new javax.swing.JComboBox(); jPanelDispAuthor = new javax.swing.JPanel(); jScrollPane16 = new javax.swing.JScrollPane(); jEditorPaneDispAuthor = new javax.swing.JEditorPane(); jButtonRefreshAuthors = new javax.swing.JButton(); jPanel8 = new javax.swing.JPanel(); jScrollPane8 = new javax.swing.JScrollPane(); jTableTitles = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jTextFieldFilterTitles = new javax.swing.JTextField(); jButtonRefreshTitles = new javax.swing.JButton(); jPanel11 = new javax.swing.JPanel(); jTextFieldFilterCluster = new javax.swing.JTextField(); jButtonRefreshCluster = new javax.swing.JButton(); jCheckBoxCluster = new javax.swing.JCheckBox(); jPanel3 = new javax.swing.JPanel(); jSplitPane1 = new javax.swing.JSplitPane(); jScrollPane5 = new javax.swing.JScrollPane(); jEditorPaneClusterEntries = new javax.swing.JEditorPane(); jScrollPane11 = new javax.swing.JScrollPane(); jTreeCluster = new javax.swing.JTree(); jPanel9 = new javax.swing.JPanel(); jComboBoxBookmarkCategory = new javax.swing.JComboBox(); jSplitPane3 = new javax.swing.JSplitPane(); jScrollPane9 = new javax.swing.JScrollPane(); jTableBookmarks = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jScrollPane14 = new javax.swing.JScrollPane(); jEditorPaneBookmarkComment = new javax.swing.JEditorPane(); jPanel13 = new javax.swing.JPanel(); jScrollPane13 = new javax.swing.JScrollPane(); jTableAttachments = (settings.isMacStyle()) ? MacWidgetFactory.createITunesTable(null) : new javax.swing.JTable(); jTextFieldFilterAttachments = new javax.swing.JTextField(); jButtonRefreshAttachments = new javax.swing.JButton(); menuBar = new javax.swing.JMenuBar(); fileMenu = new javax.swing.JMenu(); newEntryMenuItem = new javax.swing.JMenuItem(); insertEntryMenuItem = new javax.swing.JMenuItem(); insertEntryAtMenuItem = new javax.swing.JMenuItem(); jSeparator104 = new javax.swing.JSeparator(); quickNewEntryMenuItem = new javax.swing.JMenuItem(); quickNewTitleEntryMenuItem = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JSeparator(); duplicateEntryMenuItem = new javax.swing.JMenuItem(); jSeparator79 = new javax.swing.JSeparator(); openMenuItem = new javax.swing.JMenuItem(); recentDocsSubMenu = new javax.swing.JMenu(); recentDoc1 = new javax.swing.JMenuItem(); recentDoc2 = new javax.swing.JMenuItem(); recentDoc3 = new javax.swing.JMenuItem(); recentDoc4 = new javax.swing.JMenuItem(); recentDoc5 = new javax.swing.JMenuItem(); recentDoc6 = new javax.swing.JMenuItem(); recentDoc7 = new javax.swing.JMenuItem(); recentDoc8 = new javax.swing.JMenuItem(); jSeparator107 = new javax.swing.JSeparator(); saveMenuItem = new javax.swing.JMenuItem(); saveAsMenuItem = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JSeparator(); newDesktopMenuItem = new javax.swing.JMenuItem(); newZettelkastenMenuItem = new javax.swing.JMenuItem(); jSeparator78 = new javax.swing.JSeparator(); importMenuItem = new javax.swing.JMenuItem(); exportMenuItem = new javax.swing.JMenuItem(); jSeparator77 = new javax.swing.JSeparator(); menuFileInformation = new javax.swing.JMenuItem(); jSeparatorExit = new javax.swing.JSeparator(); exitMenuItem = new javax.swing.JMenuItem(); editMenu = new javax.swing.JMenu(); editMenuItem = new javax.swing.JMenuItem(); jSeparator33 = new javax.swing.JSeparator(); deleteZettelMenuItem = new javax.swing.JMenuItem(); jSeparator6 = new javax.swing.JSeparator(); deleteKwFromListMenuItem = new javax.swing.JMenuItem(); jSeparator40 = new javax.swing.JSeparator(); copyMenuItem = new javax.swing.JMenuItem(); copyPlainMenuItem = new javax.swing.JMenuItem(); pasteMenuItem = new javax.swing.JMenuItem(); selectAllMenuItem = new javax.swing.JMenuItem(); jSeparator99 = new javax.swing.JSeparator(); addSelectionToKeywordMenuItem = new javax.swing.JMenuItem(); addFirstLineToTitleMenuItem = new javax.swing.JMenuItem(); addSelectionToTitleMenuItem = new javax.swing.JMenuItem(); jSeparator24 = new javax.swing.JSeparator(); manualInsertLinksMenuItem = new javax.swing.JMenuItem(); manualInsertMenuItem = new javax.swing.JMenuItem(); jSeparator41 = new javax.swing.JSeparator(); setBookmarkMenuItem = new javax.swing.JMenuItem(); addToDesktopMenuItem = new javax.swing.JMenuItem(); findMenu = new javax.swing.JMenu(); findMenuItem = new javax.swing.JMenuItem(); findReplaceMenuItem = new javax.swing.JMenuItem(); jSeparator31 = new javax.swing.JSeparator(); findEntryWithout = new javax.swing.JMenu(); findEntriesWithoutKeywords = new javax.swing.JMenuItem(); jSeparator69 = new javax.swing.JSeparator(); findEntriesWithoutAuthors = new javax.swing.JMenuItem(); jSeparator75 = new javax.swing.JSeparator(); findEntriesWithoutRemarks = new javax.swing.JMenuItem(); findEntriesWithRemarks = new javax.swing.JMenuItem(); jSeparator110 = new javax.swing.JSeparator(); findEntriesWithRatings = new javax.swing.JMenuItem(); findEntriesWithoutRatings = new javax.swing.JMenuItem(); jSeparator76 = new javax.swing.JSeparator(); findEntriesWithAttachments = new javax.swing.JMenuItem(); jSeparator83 = new javax.swing.JSeparator(); findEntriesFromCreatedTimestamp = new javax.swing.JMenuItem(); findEntriesFromEditedTimestamp = new javax.swing.JMenuItem(); jSeparator95 = new javax.swing.JSeparator(); findDoubleEntriesItem = new javax.swing.JMenuItem(); jSeparator68 = new javax.swing.JSeparator(); findEntryKeywordsMenu = new javax.swing.JMenu(); menuKwListSearchOr = new javax.swing.JMenuItem(); jSeparator19 = new javax.swing.JSeparator(); menuKwListSearchAnd = new javax.swing.JMenuItem(); jSeparator39 = new javax.swing.JSeparator(); menuKwListSearchNot = new javax.swing.JMenuItem(); jSeparator18 = new javax.swing.JSeparator(); liveSearchMenuItem = new javax.swing.JMenuItem(); jSeparator22 = new javax.swing.JSeparator(); homeMenuItem = new javax.swing.JMenuItem(); prevEntryMenuItem = new javax.swing.JMenuItem(); nextEntryMenuItem = new javax.swing.JMenuItem(); lastEntryMenuItem = new javax.swing.JMenuItem(); jSeparator72 = new javax.swing.JPopupMenu.Separator(); randomEntryMenuItem = new javax.swing.JMenuItem(); jSeparator111 = new javax.swing.JPopupMenu.Separator(); historyForMenuItem = new javax.swing.JMenuItem(); histroyBackMenuItem = new javax.swing.JMenuItem(); jSeparator112 = new javax.swing.JPopupMenu.Separator(); gotoEntryMenuItem = new javax.swing.JMenuItem(); viewMenu = new javax.swing.JMenu(); showLinksMenuItem = new javax.swing.JMenuItem(); showLuhmannMenuItem = new javax.swing.JMenuItem(); showKeywordsMenuItem = new javax.swing.JMenuItem(); showAuthorsMenuItem = new javax.swing.JMenuItem(); showTitlesMenuItem = new javax.swing.JMenuItem(); showClusterMenuItem = new javax.swing.JMenuItem(); showBookmarksMenuItem = new javax.swing.JMenuItem(); showAttachmentsMenuItem = new javax.swing.JMenuItem(); jSeparator23 = new javax.swing.JSeparator(); showCurrentEntryAgain = new javax.swing.JMenuItem(); jSeparator55 = new javax.swing.JSeparator(); showHighlightKeywords = new javax.swing.JCheckBoxMenuItem(); highlightSegmentsMenuItem = new javax.swing.JCheckBoxMenuItem(); viewMenuLinks = new javax.swing.JMenu(); viewMenuLinksKwListRefresh = new javax.swing.JMenuItem(); jSeparator116 = new javax.swing.JPopupMenu.Separator(); viewMenuLinksRemoveManLink = new javax.swing.JMenuItem(); jSeparator3 = new javax.swing.JSeparator(); viewMenuLinksKwListLogOr = new javax.swing.JCheckBoxMenuItem(); viewMenuLinksKwListLogAnd = new javax.swing.JCheckBoxMenuItem(); jSeparator53 = new javax.swing.JSeparator(); viewMenuLinksManLink = new javax.swing.JMenuItem(); viewMenuLinksLuhmann = new javax.swing.JMenuItem(); jSeparator58 = new javax.swing.JSeparator(); viewMenuLinksDesktop = new javax.swing.JMenuItem(); jSeparator100 = new javax.swing.JSeparator(); viewMenuLinksExport = new javax.swing.JMenuItem(); viewMenuExportToSearch = new javax.swing.JMenuItem(); viewMenuLuhmann = new javax.swing.JMenu(); viewMenuLuhmannDelete = new javax.swing.JMenuItem(); jSeparator61 = new javax.swing.JSeparator(); viewMenuLuhmannManLinks = new javax.swing.JMenuItem(); viewMenuLuhmannBookmarks = new javax.swing.JMenuItem(); jSeparator62 = new javax.swing.JSeparator(); viewMenuLuhmannDesktop = new javax.swing.JMenuItem(); jSeparator102 = new javax.swing.JSeparator(); viewMenuLuhmannExport = new javax.swing.JMenuItem(); viewMenuLuhmannExportSearch = new javax.swing.JMenuItem(); jSeparator117 = new javax.swing.JPopupMenu.Separator(); viewMenuLuhmannSortEntries = new javax.swing.JMenuItem(); jSeparator118 = new javax.swing.JPopupMenu.Separator(); viewMenuLuhmannShowNumbers = new javax.swing.JCheckBoxMenuItem(); viewMenuKeywords = new javax.swing.JMenu(); viewKeywordsCopy = new javax.swing.JMenuItem(); jSeparator25 = new javax.swing.JSeparator(); viewKeywordsSearchOr = new javax.swing.JMenuItem(); viewKeywordsSearchAnd = new javax.swing.JMenuItem(); viewKeywordsSearchNot = new javax.swing.JMenuItem(); jSeparator26 = new javax.swing.JSeparator(); viewKeywordsNew = new javax.swing.JMenuItem(); viewKeywordsEdit = new javax.swing.JMenuItem(); viewKeywordsDelete = new javax.swing.JMenuItem(); jSeparator27 = new javax.swing.JSeparator(); viewKeywordsAddToList = new javax.swing.JMenuItem(); jSeparator47 = new javax.swing.JSeparator(); viewKeywordsLuhmann = new javax.swing.JMenuItem(); viewKeywordsLuhmannAnd = new javax.swing.JMenuItem(); jSeparator67 = new javax.swing.JSeparator(); viewKeywordsManLinks = new javax.swing.JMenuItem(); viewKeywordsManLinksAnd = new javax.swing.JMenuItem(); jSeparator48 = new javax.swing.JSeparator(); viewKeywordsDesktop = new javax.swing.JMenuItem(); viewKeywordsDesktopAnd = new javax.swing.JMenuItem(); jSeparator80 = new javax.swing.JSeparator(); viewKeywordsExport = new javax.swing.JMenuItem(); viewMenuAuthors = new javax.swing.JMenu(); viewAuthorsCopy = new javax.swing.JMenuItem(); jSeparator28 = new javax.swing.JSeparator(); viewAuthorsSubFind = new javax.swing.JMenu(); viewAuthorsSearchOr = new javax.swing.JMenuItem(); viewAuthorsSearchAnd = new javax.swing.JMenuItem(); viewAuthorsSearchNot = new javax.swing.JMenuItem(); jSeparator29 = new javax.swing.JSeparator(); viewAuthorsSubEdit = new javax.swing.JMenu(); viewAuthorsNew = new javax.swing.JMenuItem(); viewAuthorsEdit = new javax.swing.JMenuItem(); viewAuthorsDelete = new javax.swing.JMenuItem(); jSeparator90 = new javax.swing.JSeparator(); viewAuthorsBibkey = new javax.swing.JMenuItem(); jSeparator30 = new javax.swing.JSeparator(); viewAuthorsSubAdd = new javax.swing.JMenu(); viewAuthorsAddToEntry = new javax.swing.JMenuItem(); jSeparator51 = new javax.swing.JSeparator(); viewAuthorsManLinks = new javax.swing.JMenuItem(); viewAuthorsManLinksAnd = new javax.swing.JMenuItem(); jSeparator71 = new javax.swing.JSeparator(); viewAuthorsAddLuhmann = new javax.swing.JMenuItem(); viewAuthorsAddLuhmannAnd = new javax.swing.JMenuItem(); jSeparator52 = new javax.swing.JSeparator(); viewAuthorsDesktop = new javax.swing.JMenuItem(); viewAuthorsDesktopAnd = new javax.swing.JMenuItem(); jSeparator81 = new javax.swing.JSeparator(); viewAuthorsImport = new javax.swing.JMenuItem(); viewAuthorsExport = new javax.swing.JMenuItem(); jSeparator92 = new javax.swing.JSeparator(); viewAuthorsAttachBibtexFile = new javax.swing.JMenuItem(); viewAuthorsRefreshBibtexFile = new javax.swing.JMenuItem(); viewMenuTitles = new javax.swing.JMenu(); viewTitlesCopy = new javax.swing.JMenuItem(); jSeparator43 = new javax.swing.JSeparator(); viewTitlesEdit = new javax.swing.JMenuItem(); viewTitlesDelete = new javax.swing.JMenuItem(); jSeparator65 = new javax.swing.JSeparator(); viewTitlesMoveEntry = new javax.swing.JMenuItem(); jSeparator105 = new javax.swing.JSeparator(); viewTitlesAutomaticFirstLine = new javax.swing.JMenuItem(); jSeparator42 = new javax.swing.JSeparator(); viewTitlesManLinks = new javax.swing.JMenuItem(); viewTitlesLuhmann = new javax.swing.JMenuItem(); viewTitlesBookmarks = new javax.swing.JMenuItem(); jSeparator113 = new javax.swing.JPopupMenu.Separator(); viewTitlesDesktop = new javax.swing.JMenuItem(); jSeparator108 = new javax.swing.JPopupMenu.Separator(); viewTitlesExport = new javax.swing.JMenuItem(); viewMenuCluster = new javax.swing.JMenu(); viewClusterExport = new javax.swing.JMenuItem(); viewClusterExportToSearch = new javax.swing.JMenuItem(); viewMenuBookmarks = new javax.swing.JMenu(); viewBookmarksEdit = new javax.swing.JMenuItem(); viewBookmarksDelete = new javax.swing.JMenuItem(); jSeparator35 = new javax.swing.JSeparator(); viewBookmarksEditCat = new javax.swing.JMenuItem(); viewBookmarksDeleteCat = new javax.swing.JMenuItem(); jSeparator37 = new javax.swing.JSeparator(); viewBookmarksManLink = new javax.swing.JMenuItem(); viewBookmarksAddLuhmann = new javax.swing.JMenuItem(); jSeparator59 = new javax.swing.JSeparator(); viewBookmarkDesktop = new javax.swing.JMenuItem(); jSeparator82 = new javax.swing.JSeparator(); viewBookmarksExport = new javax.swing.JMenuItem(); viewBookmarksExportSearch = new javax.swing.JMenuItem(); viewMenuAttachments = new javax.swing.JMenu(); viewAttachmentsCopy = new javax.swing.JMenuItem(); jSeparator84 = new javax.swing.JSeparator(); viewAttachmentEdit = new javax.swing.JMenuItem(); viewAttachmentsDelete = new javax.swing.JMenuItem(); jSeparator85 = new javax.swing.JSeparator(); viewMenuAttachmentGoto = new javax.swing.JMenuItem(); jSeparator93 = new javax.swing.JSeparator(); viewAttachmentsExport = new javax.swing.JMenuItem(); windowsMenu = new javax.swing.JMenu(); showSearchResultsMenuItem = new javax.swing.JMenuItem(); jSeparator44 = new javax.swing.JSeparator(); showDesktopMenuItem = new javax.swing.JMenuItem(); jSeparator109 = new javax.swing.JSeparator(); showNewEntryMenuItem = new javax.swing.JMenuItem(); jSeparator34 = new javax.swing.JPopupMenu.Separator(); showErrorLogMenuItem = new javax.swing.JMenuItem(); aboutMenu = new javax.swing.JMenu(); aboutMenuItem = new javax.swing.JMenuItem(); jSeparatorAbout1 = new javax.swing.JSeparator(); preferencesMenuItem = new javax.swing.JMenuItem(); statusPanel = new javax.swing.JPanel(); jPanel12 = new javax.swing.JPanel(); statusEntryLabel = new javax.swing.JLabel(); statusAnimationLabel = new javax.swing.JLabel(); jTextFieldEntryNumber = new javax.swing.JTextField(); statusOfEntryLabel = new javax.swing.JLabel(); buttonHistoryBack = new javax.swing.JButton(); buttonHistoryFore = new javax.swing.JButton(); statusMsgLabel = new javax.swing.JLabel(); statusErrorButton = new javax.swing.JButton(); statusDesktopEntryButton = new javax.swing.JButton(); toolBar = new javax.swing.JToolBar(); tb_newEntry = new javax.swing.JButton(); tb_open = new javax.swing.JButton(); tb_save = new javax.swing.JButton(); jSeparator4 = new javax.swing.JToolBar.Separator(); tb_edit = new javax.swing.JButton(); tb_delete = new javax.swing.JButton(); tb_copy = new javax.swing.JButton(); tb_paste = new javax.swing.JButton(); tb_selectall = new javax.swing.JButton(); jSeparator5 = new javax.swing.JToolBar.Separator(); tb_addmanlinks = new javax.swing.JButton(); tb_addluhmann = new javax.swing.JButton(); tb_addbookmark = new javax.swing.JButton(); tb_addtodesktop = new javax.swing.JButton(); jSeparator10 = new javax.swing.JToolBar.Separator(); tb_find = new javax.swing.JButton(); tb_first = new javax.swing.JButton(); tb_prev = new javax.swing.JButton(); tb_next = new javax.swing.JButton(); tb_last = new javax.swing.JButton(); jSeparator32 = new javax.swing.JToolBar.Separator(); jLabelMemory = new javax.swing.JLabel(); jPopupMenuKeywords = new javax.swing.JPopupMenu(); popupKeywordsCopy = new javax.swing.JMenuItem(); jSeparator8 = new javax.swing.JSeparator(); popupKeywordsSearchOr = new javax.swing.JMenuItem(); popupKeywordsSearchAnd = new javax.swing.JMenuItem(); popupKeywordsSearchNot = new javax.swing.JMenuItem(); jSeparator9 = new javax.swing.JSeparator(); popupKeywordsNew = new javax.swing.JMenuItem(); popupKeywordsEdit = new javax.swing.JMenuItem(); popupKeywordsDelete = new javax.swing.JMenuItem(); jSeparator7 = new javax.swing.JSeparator(); popupKeywordsAddToList = new javax.swing.JMenuItem(); jSeparator45 = new javax.swing.JSeparator(); popupKeywordsManLinks = new javax.swing.JMenuItem(); popupKeywordsManLinksAnd = new javax.swing.JMenuItem(); jSeparator66 = new javax.swing.JSeparator(); popupKeywordsLuhmann = new javax.swing.JMenuItem(); popupKeywordsLuhmannAnd = new javax.swing.JMenuItem(); jSeparator46 = new javax.swing.JSeparator(); popupKeywordsDesktop = new javax.swing.JMenuItem(); popupKeywordsDesktopAnd = new javax.swing.JMenuItem(); jPopupMenuKeywordList = new javax.swing.JPopupMenu(); popupKwListCopy = new javax.swing.JMenuItem(); jSeparator89 = new javax.swing.JSeparator(); popupKwListSearchOr = new javax.swing.JMenuItem(); popupKwListSearchAnd = new javax.swing.JMenuItem(); popupKwListSearchNot = new javax.swing.JMenuItem(); jSeparator13 = new javax.swing.JSeparator(); popupKwListHighlight = new javax.swing.JMenuItem(); popupKwListHighlightSegments = new javax.swing.JCheckBoxMenuItem(); popupKwListRefresh = new javax.swing.JMenuItem(); jSeparator11 = new javax.swing.JSeparator(); popupKwListLogOr = new javax.swing.JCheckBoxMenuItem(); popupKwListLogAnd = new javax.swing.JCheckBoxMenuItem(); jSeparator12 = new javax.swing.JSeparator(); popupKwListDelete = new javax.swing.JMenuItem(); jPopupMenuAuthors = new javax.swing.JPopupMenu(); popupAuthorsCopy = new javax.swing.JMenuItem(); jSeparator14 = new javax.swing.JSeparator(); popupAuthorsSearchLogOr = new javax.swing.JMenuItem(); popupAuthorsSearchLogAnd = new javax.swing.JMenuItem(); popupAuthorsSearchLogNot = new javax.swing.JMenuItem(); jSeparator15 = new javax.swing.JSeparator(); popupAuthorsNew = new javax.swing.JMenuItem(); popupAuthorsEdit = new javax.swing.JMenuItem(); popupAuthorsDelete = new javax.swing.JMenuItem(); jSeparator91 = new javax.swing.JSeparator(); popupAuthorsBibkey = new javax.swing.JMenuItem(); jSeparator16 = new javax.swing.JSeparator(); popupAuthorsAddToEntry = new javax.swing.JMenuItem(); jSeparator49 = new javax.swing.JSeparator(); popupAuthorsSubAdd = new javax.swing.JMenu(); popupAuthorsManLinks = new javax.swing.JMenuItem(); popupAuthorsManLinksAnd = new javax.swing.JMenuItem(); jSeparator70 = new javax.swing.JSeparator(); popupAuthorsLuhmann = new javax.swing.JMenuItem(); popupAuthorsLuhmannAnd = new javax.swing.JMenuItem(); jSeparator50 = new javax.swing.JSeparator(); popupAuthorsDesktop = new javax.swing.JMenuItem(); popupAuthorsDesktopAnd = new javax.swing.JMenuItem(); jSeparator96 = new javax.swing.JSeparator(); popupAuthorsImport = new javax.swing.JMenuItem(); jPopupMenuLuhmann = new javax.swing.JPopupMenu(); popupLuhmannAdd = new javax.swing.JMenuItem(); jSeparator17 = new javax.swing.JSeparator(); popupLuhmannDelete = new javax.swing.JMenuItem(); jSeparator60 = new javax.swing.JSeparator(); popupLuhmannManLinks = new javax.swing.JMenuItem(); popupLuhmannBookmarks = new javax.swing.JMenuItem(); jSeparator63 = new javax.swing.JSeparator(); popupLuhmannDesktop = new javax.swing.JMenuItem(); jPopupMenuTitles = new javax.swing.JPopupMenu(); popupTitlesCopy = new javax.swing.JMenuItem(); jSeparator20 = new javax.swing.JSeparator(); popupTitlesEdit = new javax.swing.JMenuItem(); popupTitlesEditEntry = new javax.swing.JMenuItem(); jSeparator103 = new javax.swing.JSeparator(); popupTitlesDelete = new javax.swing.JMenuItem(); jSeparator114 = new javax.swing.JPopupMenu.Separator(); popupTitleMoveEntry = new javax.swing.JMenuItem(); jSeparator106 = new javax.swing.JSeparator(); popupTitlesAutomaticTitle = new javax.swing.JMenuItem(); jSeparator21 = new javax.swing.JSeparator(); popupTitlesManLinks = new javax.swing.JMenuItem(); popupTitlesLuhmann = new javax.swing.JMenuItem(); popupTitlesBookmarks = new javax.swing.JMenuItem(); jSeparator64 = new javax.swing.JSeparator(); popupTitlesDesktop = new javax.swing.JMenuItem(); jPopupMenuBookmarks = new javax.swing.JPopupMenu(); popupBookmarksEdit = new javax.swing.JMenuItem(); popupBookmarksDelete = new javax.swing.JMenuItem(); jSeparator36 = new javax.swing.JSeparator(); popupBookmarksEditCat = new javax.swing.JMenuItem(); popupBookmarksDeleteCat = new javax.swing.JMenuItem(); jSeparator38 = new javax.swing.JSeparator(); popupBookmarksAddManLinks = new javax.swing.JMenuItem(); popupBookmarksAddLuhmann = new javax.swing.JMenuItem(); jSeparator56 = new javax.swing.JSeparator(); popupBookmarkAddDesktop = new javax.swing.JMenuItem(); jPopupMenuLinks = new javax.swing.JPopupMenu(); popupLinksRefresh = new javax.swing.JMenuItem(); jSeparator115 = new javax.swing.JPopupMenu.Separator(); popupLinkRemoveManLink = new javax.swing.JMenuItem(); jSeparator54 = new javax.swing.JSeparator(); popupLinksManLinks = new javax.swing.JMenuItem(); popupLinksLuhmann = new javax.swing.JMenuItem(); jSeparator57 = new javax.swing.JSeparator(); popupLinksDesktop = new javax.swing.JMenuItem(); jPopupMenuAttachments = new javax.swing.JPopupMenu(); popupAttachmentsCopy = new javax.swing.JMenuItem(); jSeparator87 = new javax.swing.JSeparator(); popupAttachmentsEdit = new javax.swing.JMenuItem(); popupAttachmentsDelete = new javax.swing.JMenuItem(); jSeparator94 = new javax.swing.JSeparator(); popupAttachmentsGoto = new javax.swing.JMenuItem(); jSeparator86 = new javax.swing.JSeparator(); popupAttachmentsExport = new javax.swing.JMenuItem(); jPopupMenuMain = new javax.swing.JPopupMenu(); popupMainCopy = new javax.swing.JMenuItem(); popupMainCopyPlain = new javax.swing.JMenuItem(); jSeparator88 = new javax.swing.JSeparator(); popupMainFind = new javax.swing.JMenuItem(); jSeparator97 = new javax.swing.JSeparator(); popupMainAddToKeyword = new javax.swing.JMenuItem(); jSeparator98 = new javax.swing.JSeparator(); popupMainSetFirstLineAsTitle = new javax.swing.JMenuItem(); popupMainSetSelectionAsTitle = new javax.swing.JMenuItem(); mainPanel.setName("mainPanel"); // NOI18N mainPanel.setLayout(new java.awt.BorderLayout()); jSplitPaneMain1.setBorder(null); jSplitPaneMain1.setDividerLocation(650); jSplitPaneMain1.setName("jSplitPaneMain1"); // NOI18N jSplitPaneMain1.setOneTouchExpandable(true); jSplitPaneMain2.setBorder(null); jSplitPaneMain2.setDividerLocation(440); jSplitPaneMain2.setName("jSplitPaneMain2"); // NOI18N jSplitPaneMain2.setOneTouchExpandable(true); jPanel17.setName("jPanel17"); // NOI18N jScrollPane1.setBorder(null); jScrollPane1.setName("jScrollPane1"); // NOI18N jEditorPaneEntry.setEditable(false); jEditorPaneEntry.setBorder(null); org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getResourceMap(ZettelkastenView.class); jEditorPaneEntry.setContentType(resourceMap.getString("jEditorPaneEntry.contentType")); // NOI18N jEditorPaneEntry.setName("jEditorPaneEntry"); // NOI18N jScrollPane1.setViewportView(jEditorPaneEntry); jPanelLiveSearch.setName("jPanelLiveSearch"); // NOI18N jTextFieldLiveSearch.setText(resourceMap.getString("jTextFieldLiveSearch.text")); // NOI18N jTextFieldLiveSearch.setToolTipText(resourceMap.getString("jTextFieldLiveSearch.toolTipText")); // NOI18N jTextFieldLiveSearch.setName("jTextFieldLiveSearch"); // NOI18N javax.swing.ActionMap actionMap = org.jdesktop.application.Application .getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext() .getActionMap(ZettelkastenView.class, this); jButton1.setAction(actionMap.get("findLiveCancel")); // NOI18N jButton1.setIcon(resourceMap.getIcon("jButton1.icon")); // NOI18N jButton1.setBorderPainted(false); jButton1.setContentAreaFilled(false); jButton1.setFocusPainted(false); jButton1.setName("jButton1"); // NOI18N javax.swing.GroupLayout jPanelLiveSearchLayout = new javax.swing.GroupLayout(jPanelLiveSearch); jPanelLiveSearch.setLayout(jPanelLiveSearchLayout); jPanelLiveSearchLayout.setHorizontalGroup( jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( javax.swing.GroupLayout.Alignment.TRAILING, jPanelLiveSearchLayout.createSequentialGroup().addContainerGap() .addComponent(jTextFieldLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, 406, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 16, 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.TRAILING, false) .addComponent(jButton1, 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 jPanel17Layout = new javax.swing.GroupLayout(jPanel17); jPanel17.setLayout(jPanel17Layout); jPanel17Layout .setHorizontalGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE) .addComponent(jPanelLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); jPanel17Layout.setVerticalGroup(jPanel17Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel17Layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 498, Short.MAX_VALUE) .addGap(0, 0, 0).addComponent(jPanelLiveSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); jSplitPaneMain2.setLeftComponent(jPanel17); jScrollPane3.setBorder(null); jScrollPane3.setName("jScrollPane3"); // NOI18N jListEntryKeywords.setBorder(javax.swing.BorderFactory .createTitledBorder(resourceMap.getString("jListEntryKeywords.border.title"))); // NOI18N jListEntryKeywords.setModel(keywordListModel); jListEntryKeywords.setName("jListEntryKeywords"); // NOI18N jListEntryKeywords.setVisibleRowCount(-1); jScrollPane3.setViewportView(jListEntryKeywords); jSplitPaneMain2.setRightComponent(jScrollPane3); jSplitPaneMain1.setLeftComponent(jSplitPaneMain2); jPanelMainRight.setName("jPanelMainRight"); // NOI18N jTabbedPaneMain.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT); jTabbedPaneMain.setName("jTabbedPaneMain"); // NOI18N jPanel1.setName("jPanel1"); // NOI18N jSplitPaneLinks.setBorder(null); jSplitPaneLinks.setDividerLocation(250); jSplitPaneLinks.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPaneLinks.setName("jSplitPaneLinks"); // NOI18N jSplitPaneLinks.setOneTouchExpandable(true); jPanel14.setName("jPanel14"); // NOI18N jScrollPane4.setName("jScrollPane4"); // NOI18N jTableLinks.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { "Zettel", "berschrift", "Relevanz", "Bewertung" }) { Class[] types = new Class[] { java.lang.Integer.class, java.lang.String.class, java.lang.Integer.class, java.lang.Float.class }; boolean[] canEdit = new boolean[] { false, false, false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableLinks.setDragEnabled(true); jTableLinks.setName("jTableLinks"); // NOI18N jTableLinks.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); jTableLinks.setShowVerticalLines(false); jTableLinks.getTableHeader().setReorderingAllowed(false); jScrollPane4.setViewportView(jTableLinks); jTableLinks.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableLinks.columnModel.title0")); // NOI18N jTableLinks.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableLinks.columnModel.title1")); // NOI18N jTableLinks.getColumnModel().getColumn(2) .setHeaderValue(resourceMap.getString("jTableLinks.columnModel.title2")); // NOI18N jTableLinks.getColumnModel().getColumn(3) .setHeaderValue(resourceMap.getString("jTableLinks.columnModel.title3")); // NOI18N javax.swing.GroupLayout jPanel14Layout = new javax.swing.GroupLayout(jPanel14); jPanel14.setLayout(jPanel14Layout); jPanel14Layout .setHorizontalGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel14Layout .setVerticalGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)); jSplitPaneLinks.setTopComponent(jPanel14); jPanelManLinks.setName("jPanelManLinks"); // NOI18N jScrollPane15.setBorder(null); jScrollPane15.setName("jScrollPane15"); // NOI18N jTableManLinks .setModel( new javax.swing.table.DefaultTableModel( new Object[][] { { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null } }, new String[] { "Eintrag", "berschrift", "Bewertung" }) { Class[] types = new Class[] { java.lang.Integer.class, java.lang.String.class, java.lang.Float.class }; boolean[] canEdit = new boolean[] { false, false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableManLinks.setToolTipText(resourceMap.getString("jTableManLinks.toolTipText")); // NOI18N jTableManLinks.setDragEnabled(true); jTableManLinks.setName("jTableManLinks"); // NOI18N jTableManLinks.getTableHeader().setReorderingAllowed(false); jScrollPane15.setViewportView(jTableManLinks); jTableManLinks.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableManLinks.columnModel.title0")); // NOI18N jTableManLinks.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableManLinks.columnModel.title1")); // NOI18N jTableManLinks.getColumnModel().getColumn(2) .setHeaderValue(resourceMap.getString("jTableManLinks.columnModel.title2")); // NOI18N javax.swing.GroupLayout jPanelManLinksLayout = new javax.swing.GroupLayout(jPanelManLinks); jPanelManLinks.setLayout(jPanelManLinksLayout); jPanelManLinksLayout.setHorizontalGroup( jPanelManLinksLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane15, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanelManLinksLayout.setVerticalGroup( jPanelManLinksLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent( jScrollPane15, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE)); jSplitPaneLinks.setRightComponent(jPanelManLinks); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup(jPanel1Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jSplitPaneLinks)); jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPaneLinks)); jTabbedPaneMain.addTab(resourceMap.getString("jPanel1.TabConstraints.tabTitle"), jPanel1); // NOI18N jPanel10.setName("jPanel10"); // NOI18N jSplitPane2.setBorder(null); jSplitPane2.setDividerLocation(420); jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane2.setName("jSplitPane2"); // NOI18N jScrollPane10.setBorder(null); jScrollPane10.setName("jScrollPane10"); // NOI18N jTreeLuhmann.setDragEnabled(true); jTreeLuhmann.setName("jTreeLuhmann"); // NOI18N jScrollPane10.setViewportView(jTreeLuhmann); jSplitPane2.setTopComponent(jScrollPane10); jScrollPane2.setBorder(null); jScrollPane2.setName("jScrollPane2"); // NOI18N jEditorPaneIsFollower.setEditable(false); jEditorPaneIsFollower.setBorder(null); jEditorPaneIsFollower.setContentType("text/html"); // NOI18N jEditorPaneIsFollower.setName("jEditorPaneIsFollower"); // NOI18N jScrollPane2.setViewportView(jEditorPaneIsFollower); jSplitPane2.setRightComponent(jScrollPane2); javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); jPanel10.setLayout(jPanel10Layout); jPanel10Layout .setHorizontalGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel10Layout .setVerticalGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 486, Short.MAX_VALUE)); jTabbedPaneMain.addTab(resourceMap.getString("jPanel10.TabConstraints.tabTitle"), jPanel10); // NOI18N jPanel2.setName("jPanel2"); // NOI18N jTextFieldFilterKeywords.setText(resourceMap.getString("jTextFieldFilterKeywords.text")); // NOI18N jTextFieldFilterKeywords.setToolTipText(resourceMap.getString("jTextFieldFilterKeywords.toolTipText")); // NOI18N jTextFieldFilterKeywords.setEnabled(false); jTextFieldFilterKeywords.setName("jTextFieldFilterKeywords"); // NOI18N jButtonRefreshKeywords.setAction(actionMap.get("refreshKeywordList")); // NOI18N jButtonRefreshKeywords.setIcon(resourceMap.getIcon("jButtonRefreshKeywords.icon")); // NOI18N jButtonRefreshKeywords.setBorderPainted(false); jButtonRefreshKeywords.setContentAreaFilled(false); jButtonRefreshKeywords.setFocusPainted(false); jButtonRefreshKeywords.setName("jButtonRefreshKeywords"); // NOI18N jCheckBoxShowSynonyms.setText(resourceMap.getString("jCheckBoxShowSynonyms.text")); // NOI18N jCheckBoxShowSynonyms.setToolTipText(resourceMap.getString("jCheckBoxShowSynonyms.toolTipText")); // NOI18N jCheckBoxShowSynonyms.setName("jCheckBoxShowSynonyms"); // NOI18N jPanel16.setName("jPanel16"); // NOI18N jScrollPane17.setBorder(null); jScrollPane17.setName("jScrollPane17"); // NOI18N jTreeKeywords.setName("jTreeKeywords"); // NOI18N jScrollPane17.setViewportView(jTreeKeywords); jScrollPane6.setBorder(null); jScrollPane6.setName("jScrollPane6"); // NOI18N jTableKeywords.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { "Schlagwrter", "Hufigkeit" }) { Class[] types = new Class[] { java.lang.String.class, java.lang.Integer.class }; boolean[] canEdit = new boolean[] { false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableKeywords.setDragEnabled(true); jTableKeywords.setName("jTableKeywords"); // NOI18N jTableKeywords.setShowVerticalLines(false); jTableKeywords.getTableHeader().setReorderingAllowed(false); jScrollPane6.setViewportView(jTableKeywords); jTableKeywords.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableKeywords.columnModel.title0")); // NOI18N jTableKeywords.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableKeywords.columnModel.title1")); // NOI18N javax.swing.GroupLayout jPanel16Layout = new javax.swing.GroupLayout(jPanel16); jPanel16.setLayout(jPanel16Layout); jPanel16Layout .setHorizontalGroup(jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane17, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE) .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel16Layout.setVerticalGroup(jPanel16Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel16Layout.createSequentialGroup() .addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane17, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE))); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel16, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap().addGroup(jPanel2Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addComponent(jTextFieldFilterKeywords, javax.swing.GroupLayout.DEFAULT_SIZE, 285, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonRefreshKeywords, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel2Layout.createSequentialGroup().addComponent(jCheckBoxShowSynonyms) .addGap(0, 161, Short.MAX_VALUE))) .addContainerGap())); jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addComponent(jPanel16, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(jPanel2Layout.createSequentialGroup().addComponent(jCheckBoxShowSynonyms) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTextFieldFilterKeywords, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jButtonRefreshKeywords)) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel2.TabConstraints.tabTitle"), jPanel2); // NOI18N jPanel7.setName("jPanel7"); // NOI18N jTextFieldFilterAuthors.setToolTipText(resourceMap.getString("jTextFieldFilterAuthors.toolTipText")); // NOI18N jTextFieldFilterAuthors.setEnabled(false); jTextFieldFilterAuthors.setName("jTextFieldFilterAuthors"); // NOI18N jSplitPaneAuthors.setBorder(null); jSplitPaneAuthors.setDividerLocation(270); jSplitPaneAuthors.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPaneAuthors.setName("jSplitPaneAuthors"); // NOI18N jSplitPaneAuthors.setOneTouchExpandable(true); jPanel15.setName("jPanel15"); // NOI18N jScrollPane7.setBorder(null); jScrollPane7.setName("jScrollPane7"); // NOI18N jTableAuthors.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { "Autoren", "Hufigkeit" }) { Class[] types = new Class[] { java.lang.String.class, java.lang.Integer.class }; boolean[] canEdit = new boolean[] { false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableAuthors.setDragEnabled(true); jTableAuthors.setName("jTableAuthors"); // NOI18N jTableAuthors.getTableHeader().setReorderingAllowed(false); jScrollPane7.setViewportView(jTableAuthors); jTableAuthors.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableAuthors.columnModel.title0")); // NOI18N jTableAuthors.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableAuthors.columnModel.title1")); // NOI18N jComboBoxAuthorType.setName("jComboBoxAuthorType"); // NOI18N javax.swing.GroupLayout jPanel15Layout = new javax.swing.GroupLayout(jPanel15); jPanel15.setLayout(jPanel15Layout); jPanel15Layout .setHorizontalGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jComboBoxAuthorType, 0, 329, Short.MAX_VALUE) .addComponent(jScrollPane7, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel15Layout.setVerticalGroup(jPanel15Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel15Layout.createSequentialGroup() .addComponent(jScrollPane7, javax.swing.GroupLayout.DEFAULT_SIZE, 234, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jComboBoxAuthorType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(3, 3, 3))); jSplitPaneAuthors.setTopComponent(jPanel15); jPanelDispAuthor.setName("jPanelDispAuthor"); // NOI18N jScrollPane16.setBorder(null); jScrollPane16.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane16.setName("jScrollPane16"); // NOI18N jEditorPaneDispAuthor.setEditable(false); jEditorPaneDispAuthor.setContentType(resourceMap.getString("jEditorPaneDispAuthor.contentType")); // NOI18N jEditorPaneDispAuthor.setName("jEditorPaneDispAuthor"); // NOI18N jScrollPane16.setViewportView(jEditorPaneDispAuthor); javax.swing.GroupLayout jPanelDispAuthorLayout = new javax.swing.GroupLayout(jPanelDispAuthor); jPanelDispAuthor.setLayout(jPanelDispAuthorLayout); jPanelDispAuthorLayout.setHorizontalGroup( jPanelDispAuthorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane16, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanelDispAuthorLayout.setVerticalGroup( jPanelDispAuthorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane16, javax.swing.GroupLayout.DEFAULT_SIZE, 167, Short.MAX_VALUE)); jSplitPaneAuthors.setRightComponent(jPanelDispAuthor); jButtonRefreshAuthors.setAction(actionMap.get("refreshAuthorList")); // NOI18N jButtonRefreshAuthors.setIcon(resourceMap.getIcon("jButtonRefreshAuthors.icon")); // NOI18N jButtonRefreshAuthors.setBorderPainted(false); jButtonRefreshAuthors.setContentAreaFilled(false); jButtonRefreshAuthors.setFocusPainted(false); jButtonRefreshAuthors.setName("jButtonRefreshAuthors"); // NOI18N javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); jPanel7.setLayout(jPanel7Layout); jPanel7Layout .setHorizontalGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPaneAuthors, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addGroup(jPanel7Layout.createSequentialGroup().addGap(6, 6, 6) .addComponent(jTextFieldFilterAuthors) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonRefreshAuthors, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap())); jPanel7Layout.setVerticalGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup() .addComponent(jSplitPaneAuthors) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jTextFieldFilterAuthors, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jButtonRefreshAuthors)) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel7.TabConstraints.tabTitle"), jPanel7); // NOI18N jPanel8.setName("jPanel8"); // NOI18N jScrollPane8.setBorder(null); jScrollPane8.setName("jScrollPane8"); // NOI18N jTableTitles.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { "Zettel", "berschrift", "Erstellt", "Gendert", "Bewertung" }) { Class[] types = new Class[] { java.lang.Integer.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.Float.class }; boolean[] canEdit = new boolean[] { false, false, false, false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableTitles.setDragEnabled(true); jTableTitles.setName("jTableTitles"); // NOI18N jTableTitles.getTableHeader().setReorderingAllowed(false); jScrollPane8.setViewportView(jTableTitles); jTableTitles.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableTitles.columnModel.title0")); // NOI18N jTableTitles.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableTitles.columnModel.title1")); // NOI18N jTableTitles.getColumnModel().getColumn(2) .setHeaderValue(resourceMap.getString("jTableTitles.columnModel.title2")); // NOI18N jTableTitles.getColumnModel().getColumn(3) .setHeaderValue(resourceMap.getString("jTableTitles.columnModel.title3")); // NOI18N jTableTitles.getColumnModel().getColumn(4) .setHeaderValue(resourceMap.getString("jTableTitles.columnModel.title4")); // NOI18N jTextFieldFilterTitles.setToolTipText(resourceMap.getString("jTextFieldFilterTitles.toolTipText")); // NOI18N jTextFieldFilterTitles.setEnabled(false); jTextFieldFilterTitles.setName("jTextFieldFilterTitles"); // NOI18N jButtonRefreshTitles.setAction(actionMap.get("refreshTitleList")); // NOI18N jButtonRefreshTitles.setIcon(resourceMap.getIcon("jButtonRefreshTitles.icon")); // NOI18N jButtonRefreshTitles.setBorderPainted(false); jButtonRefreshTitles.setContentAreaFilled(false); jButtonRefreshTitles.setFocusPainted(false); jButtonRefreshTitles.setName("jButtonRefreshTitles"); // NOI18N javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8); jPanel8.setLayout(jPanel8Layout); jPanel8Layout .setHorizontalGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel8Layout.createSequentialGroup().addContainerGap() .addComponent(jTextFieldFilterTitles, javax.swing.GroupLayout.DEFAULT_SIZE, 285, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonRefreshTitles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) .addComponent(jScrollPane8, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel8Layout.setVerticalGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel8Layout.createSequentialGroup() .addComponent(jScrollPane8, javax.swing.GroupLayout.DEFAULT_SIZE, 446, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jButtonRefreshTitles).addComponent(jTextFieldFilterTitles, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel8.TabConstraints.tabTitle"), jPanel8); // NOI18N jPanel11.setName("jPanel11"); // NOI18N jTextFieldFilterCluster.setToolTipText(resourceMap.getString("jTextFieldFilterCluster.toolTipText")); // NOI18N jTextFieldFilterCluster.setEnabled(false); jTextFieldFilterCluster.setName("jTextFieldFilterCluster"); // NOI18N jButtonRefreshCluster.setAction(actionMap.get("refreshClusterList")); // NOI18N jButtonRefreshCluster.setIcon(resourceMap.getIcon("jButtonRefreshCluster.icon")); // NOI18N jButtonRefreshCluster.setBorderPainted(false); jButtonRefreshCluster.setContentAreaFilled(false); jButtonRefreshCluster.setFocusPainted(false); jButtonRefreshCluster.setName("jButtonRefreshCluster"); // NOI18N jCheckBoxCluster.setText(resourceMap.getString("jCheckBoxCluster.text")); // NOI18N jCheckBoxCluster.setToolTipText(resourceMap.getString("jCheckBoxCluster.toolTipText")); // NOI18N jCheckBoxCluster.setName("jCheckBoxCluster"); // NOI18N jPanel3.setName("jPanel3"); // NOI18N jSplitPane1.setBorder(null); jSplitPane1.setDividerLocation(310); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setName("jSplitPane1"); // NOI18N jScrollPane5.setBorder(null); jScrollPane5.setName("jScrollPane5"); // NOI18N jEditorPaneClusterEntries.setEditable(false); jEditorPaneClusterEntries.setContentType("text/html"); // NOI18N jEditorPaneClusterEntries.setName("jEditorPaneClusterEntries"); // NOI18N jScrollPane5.setViewportView(jEditorPaneClusterEntries); jSplitPane1.setBottomComponent(jScrollPane5); jScrollPane11.setBorder(null); jScrollPane11.setName("jScrollPane11"); // NOI18N jTreeCluster.setName("jTreeCluster"); // NOI18N jTreeCluster.setRootVisible(false); jScrollPane11.setViewportView(jTreeCluster); jSplitPane1.setLeftComponent(jScrollPane11); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup(jPanel3Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jSplitPane1)); jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE)); javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11); jPanel11.setLayout(jPanel11Layout); jPanel11Layout.setHorizontalGroup(jPanel11Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel11Layout.createSequentialGroup() .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel11Layout.createSequentialGroup().addContainerGap() .addComponent(jTextFieldFilterCluster) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonRefreshCluster, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel11Layout.createSequentialGroup().addComponent(jCheckBoxCluster) .addGap(0, 91, Short.MAX_VALUE))) .addContainerGap()) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); jPanel11Layout.setVerticalGroup(jPanel11Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel11Layout.createSequentialGroup() .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jCheckBoxCluster) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jTextFieldFilterCluster, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jButtonRefreshCluster)) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel11.TabConstraints.tabTitle"), jPanel11); // NOI18N jPanel9.setName("jPanel9"); // NOI18N jComboBoxBookmarkCategory.setToolTipText(resourceMap.getString("jComboBoxBookmarkCategory.toolTipText")); // NOI18N jComboBoxBookmarkCategory.setName("jComboBoxBookmarkCategory"); // NOI18N jSplitPane3.setBorder(null); jSplitPane3.setDividerLocation(380); jSplitPane3.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane3.setName("jSplitPane3"); // NOI18N jScrollPane9.setBorder(null); jScrollPane9.setName("jScrollPane9"); // NOI18N jTableBookmarks.setModel(new javax.swing.table.DefaultTableModel( new Object[][] { { null, null }, { null, null }, { null, null }, { null, null } }, new String[] { "Eintrag", "Kategorie" }) { Class[] types = new Class[] { java.lang.Integer.class, java.lang.String.class }; boolean[] canEdit = new boolean[] { false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableBookmarks.setDragEnabled(true); jTableBookmarks.setName("jTableBookmarks"); // NOI18N jTableBookmarks.setShowVerticalLines(false); jTableBookmarks.getTableHeader().setReorderingAllowed(false); jScrollPane9.setViewportView(jTableBookmarks); jTableBookmarks.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableBookmarks.columnModel.title0")); // NOI18N jTableBookmarks.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableBookmarks.columnModel.title1")); // NOI18N jSplitPane3.setLeftComponent(jScrollPane9); jScrollPane14.setBorder(null); jScrollPane14.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane14.setName("jScrollPane14"); // NOI18N jEditorPaneBookmarkComment.setEditable(false); jEditorPaneBookmarkComment.setBorder(javax.swing.BorderFactory .createTitledBorder(resourceMap.getString("jEditorPaneBookmarkComment.border.title"))); // NOI18N jEditorPaneBookmarkComment.setContentType(resourceMap.getString("jEditorPaneBookmarkComment.contentType")); // NOI18N jEditorPaneBookmarkComment.setName("jEditorPaneBookmarkComment"); // NOI18N jScrollPane14.setViewportView(jEditorPaneBookmarkComment); jSplitPane3.setRightComponent(jScrollPane14); javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9); jPanel9.setLayout(jPanel9Layout); jPanel9Layout.setHorizontalGroup(jPanel9Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup().addContainerGap() .addComponent(jComboBoxBookmarkCategory, 0, 317, Short.MAX_VALUE).addContainerGap()) .addComponent(jSplitPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)); jPanel9Layout.setVerticalGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup() .addComponent(jSplitPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jComboBoxBookmarkCategory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel9.TabConstraints.tabTitle"), jPanel9); // NOI18N jPanel13.setName("jPanel13"); // NOI18N jScrollPane13.setBorder(null); jScrollPane13.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane13.setName("jScrollPane13"); // NOI18N jTableAttachments.setModel( new javax.swing.table.DefaultTableModel(new Object[][] { { null, null, null }, { null, null, null }, { null, null, null }, { null, null, null } }, new String[] { "Anhang", "Typ", "Zettel" }) { Class[] types = new Class[] { java.lang.String.class, java.lang.String.class, java.lang.Integer.class }; boolean[] canEdit = new boolean[] { false, false, false }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jTableAttachments.setDragEnabled(true); jTableAttachments.setName("jTableAttachments"); // NOI18N jScrollPane13.setViewportView(jTableAttachments); jTableAttachments.getColumnModel().getColumn(0) .setHeaderValue(resourceMap.getString("jTableAttachments.columnModel.title0")); // NOI18N jTableAttachments.getColumnModel().getColumn(1) .setHeaderValue(resourceMap.getString("jTableAttachments.columnModel.title1")); // NOI18N jTableAttachments.getColumnModel().getColumn(2) .setHeaderValue(resourceMap.getString("jTableAttachments.columnModel.title2")); // NOI18N jTextFieldFilterAttachments .setToolTipText(resourceMap.getString("jTextFieldFilterAttachments.toolTipText")); // NOI18N jTextFieldFilterAttachments.setEnabled(false); jTextFieldFilterAttachments.setName("jTextFieldFilterAttachments"); // NOI18N jButtonRefreshAttachments.setAction(actionMap.get("refreshAttachmentList")); // NOI18N jButtonRefreshAttachments.setIcon(resourceMap.getIcon("jButtonRefreshAttachments.icon")); // NOI18N jButtonRefreshAttachments.setBorderPainted(false); jButtonRefreshAttachments.setContentAreaFilled(false); jButtonRefreshAttachments.setFocusPainted(false); jButtonRefreshAttachments.setName("jButtonRefreshAttachments"); // NOI18N javax.swing.GroupLayout jPanel13Layout = new javax.swing.GroupLayout(jPanel13); jPanel13.setLayout(jPanel13Layout); jPanel13Layout.setHorizontalGroup(jPanel13Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel13Layout.createSequentialGroup().addContainerGap() .addComponent(jTextFieldFilterAttachments, javax.swing.GroupLayout.DEFAULT_SIZE, 285, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonRefreshAttachments, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) .addComponent(jScrollPane13, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE)); jPanel13Layout.setVerticalGroup(jPanel13Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel13Layout.createSequentialGroup() .addComponent(jScrollPane13, javax.swing.GroupLayout.DEFAULT_SIZE, 446, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jTextFieldFilterAttachments, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jButtonRefreshAttachments)) .addContainerGap())); jTabbedPaneMain.addTab(resourceMap.getString("jPanel13.TabConstraints.tabTitle"), jPanel13); // NOI18N javax.swing.GroupLayout jPanelMainRightLayout = new javax.swing.GroupLayout(jPanelMainRight); jPanelMainRight.setLayout(jPanelMainRightLayout); jPanelMainRightLayout.setHorizontalGroup(jPanelMainRightLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 350, Short.MAX_VALUE) .addGroup(jPanelMainRightLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedPaneMain))); jPanelMainRightLayout.setVerticalGroup(jPanelMainRightLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 532, Short.MAX_VALUE) .addGroup(jPanelMainRightLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedPaneMain, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 532, Short.MAX_VALUE))); jSplitPaneMain1.setRightComponent(jPanelMainRight); mainPanel.add(jSplitPaneMain1, java.awt.BorderLayout.CENTER); menuBar.setName("menuBar"); // NOI18N fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N fileMenu.setName("fileMenu"); // NOI18N newEntryMenuItem.setAction(actionMap.get("newEntry")); // NOI18N newEntryMenuItem.setName("newEntryMenuItem"); // NOI18N fileMenu.add(newEntryMenuItem); insertEntryMenuItem.setAction(actionMap.get("insertEntry")); // NOI18N insertEntryMenuItem.setName("insertEntryMenuItem"); // NOI18N fileMenu.add(insertEntryMenuItem); insertEntryAtMenuItem.setAction(actionMap.get("insertEntryAt")); // NOI18N insertEntryAtMenuItem.setName("insertEntryAtMenuItem"); // NOI18N fileMenu.add(insertEntryAtMenuItem); jSeparator104.setName("jSeparator104"); // NOI18N fileMenu.add(jSeparator104); quickNewEntryMenuItem.setAction(actionMap.get("quickNewEntry")); // NOI18N quickNewEntryMenuItem.setName("quickNewEntryMenuItem"); // NOI18N fileMenu.add(quickNewEntryMenuItem); quickNewTitleEntryMenuItem.setAction(actionMap.get("quickNewEntryWithTitle")); // NOI18N quickNewTitleEntryMenuItem.setName("quickNewTitleEntryMenuItem"); // NOI18N fileMenu.add(quickNewTitleEntryMenuItem); jSeparator1.setName("jSeparator1"); // NOI18N fileMenu.add(jSeparator1); duplicateEntryMenuItem.setAction(actionMap.get("duplicateEntry")); // NOI18N duplicateEntryMenuItem.setName("duplicateEntryMenuItem"); // NOI18N fileMenu.add(duplicateEntryMenuItem); jSeparator79.setName("jSeparator79"); // NOI18N fileMenu.add(jSeparator79); openMenuItem.setAction(actionMap.get("openDocument")); // NOI18N openMenuItem.setName("openMenuItem"); // NOI18N fileMenu.add(openMenuItem); recentDocsSubMenu.setText(resourceMap.getString("recentDocsSubMenu.text")); // NOI18N recentDocsSubMenu.setName("recentDocsSubMenu"); // NOI18N recentDoc1.setName("recentDoc1"); // NOI18N recentDocsSubMenu.add(recentDoc1); recentDoc2.setName("recentDoc2"); // NOI18N recentDocsSubMenu.add(recentDoc2); recentDoc3.setName("recentDoc3"); // NOI18N recentDocsSubMenu.add(recentDoc3); recentDoc4.setName("recentDoc4"); // NOI18N recentDocsSubMenu.add(recentDoc4); recentDoc5.setName("recentDoc5"); // NOI18N recentDocsSubMenu.add(recentDoc5); recentDoc6.setName("recentDoc6"); // NOI18N recentDocsSubMenu.add(recentDoc6); recentDoc7.setName("recentDoc7"); // NOI18N recentDocsSubMenu.add(recentDoc7); recentDoc8.setName("recentDoc8"); // NOI18N recentDocsSubMenu.add(recentDoc8); fileMenu.add(recentDocsSubMenu); jSeparator107.setName("jSeparator107"); // NOI18N fileMenu.add(jSeparator107); saveMenuItem.setAction(actionMap.get("saveDocument")); // NOI18N saveMenuItem.setName("saveMenuItem"); // NOI18N fileMenu.add(saveMenuItem); saveAsMenuItem.setAction(actionMap.get("saveDocumentAs")); // NOI18N saveAsMenuItem.setName("saveAsMenuItem"); // NOI18N fileMenu.add(saveAsMenuItem); jSeparator2.setName("jSeparator2"); // NOI18N fileMenu.add(jSeparator2); newDesktopMenuItem.setAction(actionMap.get("newDesktop")); // NOI18N newDesktopMenuItem.setName("newDesktopMenuItem"); // NOI18N fileMenu.add(newDesktopMenuItem); newZettelkastenMenuItem.setAction(actionMap.get("newZettelkasten")); // NOI18N newZettelkastenMenuItem.setName("newZettelkastenMenuItem"); // NOI18N fileMenu.add(newZettelkastenMenuItem); jSeparator78.setName("jSeparator78"); // NOI18N fileMenu.add(jSeparator78); importMenuItem.setAction(actionMap.get("importWindow")); // NOI18N importMenuItem.setName("importMenuItem"); // NOI18N fileMenu.add(importMenuItem); exportMenuItem.setAction(actionMap.get("exportWindow")); // NOI18N exportMenuItem.setName("exportMenuItem"); // NOI18N fileMenu.add(exportMenuItem); jSeparator77.setName("jSeparator77"); // NOI18N fileMenu.add(jSeparator77); menuFileInformation.setAction(actionMap.get("showInformationBox")); // NOI18N menuFileInformation.setName("menuFileInformation"); // NOI18N fileMenu.add(menuFileInformation); jSeparatorExit.setName("jSeparatorExit"); // NOI18N fileMenu.add(jSeparatorExit); exitMenuItem.setAction(actionMap.get("quit")); // NOI18N exitMenuItem.setName("exitMenuItem"); // NOI18N fileMenu.add(exitMenuItem); menuBar.add(fileMenu); editMenu.setText(resourceMap.getString("editMenu.text")); // NOI18N editMenu.setName("editMenu"); // NOI18N editMenuItem.setAction(actionMap.get("editEntry")); // NOI18N editMenuItem.setName("editMenuItem"); // NOI18N editMenu.add(editMenuItem); jSeparator33.setName("jSeparator33"); // NOI18N editMenu.add(jSeparator33); deleteZettelMenuItem.setAction(actionMap.get("deleteCurrentEntry")); // NOI18N deleteZettelMenuItem.setName("deleteZettelMenuItem"); // NOI18N editMenu.add(deleteZettelMenuItem); jSeparator6.setName("jSeparator6"); // NOI18N editMenu.add(jSeparator6); deleteKwFromListMenuItem.setAction(actionMap.get("deleteKeywordFromEntry")); // NOI18N deleteKwFromListMenuItem.setName("deleteKwFromListMenuItem"); // NOI18N editMenu.add(deleteKwFromListMenuItem); jSeparator40.setName("jSeparator40"); // NOI18N editMenu.add(jSeparator40); copyMenuItem.setAction(actionMap.get("copy")); copyMenuItem.setName("copyMenuItem"); // NOI18N editMenu.add(copyMenuItem); copyPlainMenuItem.setAction(actionMap.get("copyPlain")); // NOI18N copyPlainMenuItem.setName("copyPlainMenuItem"); // NOI18N editMenu.add(copyPlainMenuItem); pasteMenuItem.setAction(actionMap.get("paste")); pasteMenuItem.setName("pasteMenuItem"); // NOI18N editMenu.add(pasteMenuItem); selectAllMenuItem.setAction(actionMap.get("selectAllText")); // NOI18N selectAllMenuItem.setName("selectAllMenuItem"); // NOI18N editMenu.add(selectAllMenuItem); jSeparator99.setName("jSeparator99"); // NOI18N editMenu.add(jSeparator99); addSelectionToKeywordMenuItem.setAction(actionMap.get("addToKeywordList")); // NOI18N addSelectionToKeywordMenuItem.setName("addSelectionToKeywordMenuItem"); // NOI18N editMenu.add(addSelectionToKeywordMenuItem); addFirstLineToTitleMenuItem.setAction(actionMap.get("setFirstLineAsTitle")); // NOI18N addFirstLineToTitleMenuItem.setName("addFirstLineToTitleMenuItem"); // NOI18N editMenu.add(addFirstLineToTitleMenuItem); addSelectionToTitleMenuItem.setAction(actionMap.get("setSelectionAsTitle")); // NOI18N addSelectionToTitleMenuItem.setName("addSelectionToTitleMenuItem"); // NOI18N editMenu.add(addSelectionToTitleMenuItem); jSeparator24.setName("jSeparator24"); // NOI18N editMenu.add(jSeparator24); manualInsertLinksMenuItem.setAction(actionMap.get("manualInsertLinks")); // NOI18N manualInsertLinksMenuItem.setName("manualInsertLinksMenuItem"); // NOI18N editMenu.add(manualInsertLinksMenuItem); manualInsertMenuItem.setAction(actionMap.get("manualInsertEntry")); // NOI18N manualInsertMenuItem.setName("manualInsertMenuItem"); // NOI18N editMenu.add(manualInsertMenuItem); jSeparator41.setName("jSeparator41"); // NOI18N editMenu.add(jSeparator41); setBookmarkMenuItem.setAction(actionMap.get("addToBookmark")); // NOI18N setBookmarkMenuItem.setName("setBookmarkMenuItem"); // NOI18N editMenu.add(setBookmarkMenuItem); addToDesktopMenuItem.setAction(actionMap.get("addToDesktop")); // NOI18N addToDesktopMenuItem.setName("addToDesktopMenuItem"); // NOI18N editMenu.add(addToDesktopMenuItem); menuBar.add(editMenu); findMenu.setText(resourceMap.getString("findMenu.text")); // NOI18N findMenu.setName("findMenu"); // NOI18N findMenuItem.setAction(actionMap.get("find")); // NOI18N findMenuItem.setName("findMenuItem"); // NOI18N findMenu.add(findMenuItem); findReplaceMenuItem.setAction(actionMap.get("replace")); // NOI18N findReplaceMenuItem.setName("findReplaceMenuItem"); // NOI18N findMenu.add(findReplaceMenuItem); jSeparator31.setName("jSeparator31"); // NOI18N findMenu.add(jSeparator31); findEntryWithout.setText(resourceMap.getString("findEntryWithout.text")); // NOI18N findEntryWithout.setName("findEntryWithout"); // NOI18N findEntriesWithoutKeywords.setAction(actionMap.get("findWithoutKeywords")); // NOI18N findEntriesWithoutKeywords.setName("findEntriesWithoutKeywords"); // NOI18N findEntryWithout.add(findEntriesWithoutKeywords); jSeparator69.setName("jSeparator69"); // NOI18N findEntryWithout.add(jSeparator69); findEntriesWithoutAuthors.setAction(actionMap.get("findWithoutAuthors")); // NOI18N findEntriesWithoutAuthors.setName("findEntriesWithoutAuthors"); // NOI18N findEntryWithout.add(findEntriesWithoutAuthors); jSeparator75.setName("jSeparator75"); // NOI18N findEntryWithout.add(jSeparator75); findEntriesWithoutRemarks.setAction(actionMap.get("findWithoutRemarks")); // NOI18N findEntriesWithoutRemarks.setName("findEntriesWithoutRemarks"); // NOI18N findEntryWithout.add(findEntriesWithoutRemarks); findEntriesWithRemarks.setAction(actionMap.get("findWithRemarks")); // NOI18N findEntriesWithRemarks.setName("findEntriesWithRemarks"); // NOI18N findEntryWithout.add(findEntriesWithRemarks); jSeparator110.setName("jSeparator110"); // NOI18N findEntryWithout.add(jSeparator110); findEntriesWithRatings.setAction(actionMap.get("findWithRating")); // NOI18N findEntriesWithRatings.setName("findEntriesWithRatings"); // NOI18N findEntryWithout.add(findEntriesWithRatings); findEntriesWithoutRatings.setAction(actionMap.get("findWithoutRating")); // NOI18N findEntriesWithoutRatings.setName("findEntriesWithoutRatings"); // NOI18N findEntryWithout.add(findEntriesWithoutRatings); jSeparator76.setName("jSeparator76"); // NOI18N findEntryWithout.add(jSeparator76); findEntriesWithAttachments.setAction(actionMap.get("findWithAttachments")); // NOI18N findEntriesWithAttachments.setName("findEntriesWithAttachments"); // NOI18N findEntryWithout.add(findEntriesWithAttachments); jSeparator83.setName("jSeparator83"); // NOI18N findEntryWithout.add(jSeparator83); findEntriesFromCreatedTimestamp.setAction(actionMap.get("findEntriesWithTimeStampCreated")); // NOI18N findEntriesFromCreatedTimestamp.setName("findEntriesFromCreatedTimestamp"); // NOI18N findEntryWithout.add(findEntriesFromCreatedTimestamp); findEntriesFromEditedTimestamp.setAction(actionMap.get("findEntriesWithTimeStampEdited")); // NOI18N findEntriesFromEditedTimestamp.setName("findEntriesFromEditedTimestamp"); // NOI18N findEntryWithout.add(findEntriesFromEditedTimestamp); jSeparator95.setName("jSeparator95"); // NOI18N findEntryWithout.add(jSeparator95); findDoubleEntriesItem.setAction(actionMap.get("findDoubleEntries")); // NOI18N findDoubleEntriesItem.setName("findDoubleEntriesItem"); // NOI18N findEntryWithout.add(findDoubleEntriesItem); findMenu.add(findEntryWithout); jSeparator68.setName("jSeparator68"); // NOI18N findMenu.add(jSeparator68); findEntryKeywordsMenu.setText(resourceMap.getString("findEntryKeywordsMenu.text")); // NOI18N findEntryKeywordsMenu.setName("findEntryKeywordsMenu"); // NOI18N menuKwListSearchOr.setAction(actionMap.get("searchKeywordsFromListLogOr")); // NOI18N menuKwListSearchOr.setName("menuKwListSearchOr"); // NOI18N findEntryKeywordsMenu.add(menuKwListSearchOr); jSeparator19.setName("jSeparator19"); // NOI18N findEntryKeywordsMenu.add(jSeparator19); menuKwListSearchAnd.setAction(actionMap.get("searchKeywordsFromListLogAnd")); // NOI18N menuKwListSearchAnd.setName("menuKwListSearchAnd"); // NOI18N findEntryKeywordsMenu.add(menuKwListSearchAnd); jSeparator39.setName("jSeparator39"); // NOI18N findEntryKeywordsMenu.add(jSeparator39); menuKwListSearchNot.setAction(actionMap.get("searchKeywordsFromListLogNot")); // NOI18N menuKwListSearchNot.setName("menuKwListSearchNot"); // NOI18N findEntryKeywordsMenu.add(menuKwListSearchNot); findMenu.add(findEntryKeywordsMenu); jSeparator18.setName("jSeparator18"); // NOI18N findMenu.add(jSeparator18); liveSearchMenuItem.setAction(actionMap.get("findLive")); // NOI18N liveSearchMenuItem.setName("liveSearchMenuItem"); // NOI18N findMenu.add(liveSearchMenuItem); jSeparator22.setName("jSeparator22"); // NOI18N findMenu.add(jSeparator22); homeMenuItem.setAction(actionMap.get("showFirstEntry")); // NOI18N homeMenuItem.setName("homeMenuItem"); // NOI18N findMenu.add(homeMenuItem); prevEntryMenuItem.setAction(actionMap.get("showPrevEntry")); // NOI18N prevEntryMenuItem.setName("prevEntryMenuItem"); // NOI18N findMenu.add(prevEntryMenuItem); nextEntryMenuItem.setAction(actionMap.get("showNextEntry")); // NOI18N nextEntryMenuItem.setName("nextEntryMenuItem"); // NOI18N findMenu.add(nextEntryMenuItem); lastEntryMenuItem.setAction(actionMap.get("showLastEntry")); // NOI18N lastEntryMenuItem.setName("lastEntryMenuItem"); // NOI18N findMenu.add(lastEntryMenuItem); jSeparator72.setName("jSeparator72"); // NOI18N findMenu.add(jSeparator72); randomEntryMenuItem.setAction(actionMap.get("showRandomEntry")); // NOI18N randomEntryMenuItem.setName("randomEntryMenuItem"); // NOI18N findMenu.add(randomEntryMenuItem); jSeparator111.setName("jSeparator111"); // NOI18N findMenu.add(jSeparator111); historyForMenuItem.setAction(actionMap.get("historyBack")); // NOI18N historyForMenuItem.setText(resourceMap.getString("historyForMenuItem.text")); // NOI18N historyForMenuItem.setName("historyForMenuItem"); // NOI18N findMenu.add(historyForMenuItem); histroyBackMenuItem.setAction(actionMap.get("historyFor")); // NOI18N histroyBackMenuItem.setText(resourceMap.getString("histroyBackMenuItem.text")); // NOI18N histroyBackMenuItem.setName("histroyBackMenuItem"); // NOI18N findMenu.add(histroyBackMenuItem); jSeparator112.setName("jSeparator112"); // NOI18N findMenu.add(jSeparator112); gotoEntryMenuItem.setAction(actionMap.get("gotoEntry")); // NOI18N gotoEntryMenuItem.setName("gotoEntryMenuItem"); // NOI18N findMenu.add(gotoEntryMenuItem); menuBar.add(findMenu); viewMenu.setText(resourceMap.getString("viewMenu.text")); // NOI18N viewMenu.setName("viewMenu"); // NOI18N showLinksMenuItem.setAction(actionMap.get("menuShowLinks")); // NOI18N showLinksMenuItem.setName("showLinksMenuItem"); // NOI18N viewMenu.add(showLinksMenuItem); showLuhmannMenuItem.setAction(actionMap.get("menuShowLuhmann")); // NOI18N showLuhmannMenuItem.setName("showLuhmannMenuItem"); // NOI18N viewMenu.add(showLuhmannMenuItem); showKeywordsMenuItem.setAction(actionMap.get("menuShowKeywords")); // NOI18N showKeywordsMenuItem.setName("showKeywordsMenuItem"); // NOI18N viewMenu.add(showKeywordsMenuItem); showAuthorsMenuItem.setAction(actionMap.get("menuShowAuthors")); // NOI18N showAuthorsMenuItem.setName("showAuthorsMenuItem"); // NOI18N viewMenu.add(showAuthorsMenuItem); showTitlesMenuItem.setAction(actionMap.get("menuShowTitles")); // NOI18N showTitlesMenuItem.setName("showTitlesMenuItem"); // NOI18N viewMenu.add(showTitlesMenuItem); showClusterMenuItem.setAction(actionMap.get("menuShowCluster")); // NOI18N showClusterMenuItem.setName("showClusterMenuItem"); // NOI18N viewMenu.add(showClusterMenuItem); showBookmarksMenuItem.setAction(actionMap.get("menuShowBookmarks")); // NOI18N showBookmarksMenuItem.setName("showBookmarksMenuItem"); // NOI18N viewMenu.add(showBookmarksMenuItem); showAttachmentsMenuItem.setAction(actionMap.get("menuShowAttachments")); // NOI18N showAttachmentsMenuItem.setName("showAttachmentsMenuItem"); // NOI18N viewMenu.add(showAttachmentsMenuItem); jSeparator23.setName("jSeparator23"); // NOI18N viewMenu.add(jSeparator23); showCurrentEntryAgain.setAction(actionMap.get("updateDisplay")); // NOI18N showCurrentEntryAgain.setName("showCurrentEntryAgain"); // NOI18N viewMenu.add(showCurrentEntryAgain); jSeparator55.setName("jSeparator55"); // NOI18N viewMenu.add(jSeparator55); showHighlightKeywords.setAction(actionMap.get("highlightKeywords")); // NOI18N showHighlightKeywords.setSelected(true); showHighlightKeywords.setName("showHighlightKeywords"); // NOI18N viewMenu.add(showHighlightKeywords); highlightSegmentsMenuItem.setAction(actionMap.get("highlightSegments")); // NOI18N highlightSegmentsMenuItem.setName("highlightSegmentsMenuItem"); // NOI18N viewMenu.add(highlightSegmentsMenuItem); menuBar.add(viewMenu); viewMenuLinks.setText(resourceMap.getString("viewMenuLinks.text")); // NOI18N viewMenuLinks.setName("viewMenuLinks"); // NOI18N viewMenuLinksKwListRefresh.setAction(actionMap.get("refreshFilteredLinks")); // NOI18N viewMenuLinksKwListRefresh.setName("viewMenuLinksKwListRefresh"); // NOI18N viewMenuLinks.add(viewMenuLinksKwListRefresh); jSeparator116.setName("jSeparator116"); // NOI18N viewMenuLinks.add(jSeparator116); viewMenuLinksRemoveManLink.setAction(actionMap.get("deleteManualLink")); // NOI18N viewMenuLinksRemoveManLink.setName("viewMenuLinksRemoveManLink"); // NOI18N viewMenuLinks.add(viewMenuLinksRemoveManLink); jSeparator3.setName("jSeparator3"); // NOI18N viewMenuLinks.add(jSeparator3); viewMenuLinksKwListLogOr.setAction(actionMap.get("keywordListLogOr")); // NOI18N viewMenuLinksKwListLogOr.setSelected(true); viewMenuLinksKwListLogOr.setName("viewMenuLinksKwListLogOr"); // NOI18N viewMenuLinks.add(viewMenuLinksKwListLogOr); viewMenuLinksKwListLogAnd.setAction(actionMap.get("keywordListLogAnd")); // NOI18N viewMenuLinksKwListLogAnd.setSelected(true); viewMenuLinksKwListLogAnd.setName("viewMenuLinksKwListLogAnd"); // NOI18N viewMenuLinks.add(viewMenuLinksKwListLogAnd); jSeparator53.setName("jSeparator53"); // NOI18N viewMenuLinks.add(jSeparator53); viewMenuLinksManLink.setAction(actionMap.get("addManLinks")); // NOI18N viewMenuLinksManLink.setName("viewMenuLinksManLink"); // NOI18N viewMenuLinks.add(viewMenuLinksManLink); viewMenuLinksLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N viewMenuLinksLuhmann.setName("viewMenuLinksLuhmann"); // NOI18N viewMenuLinks.add(viewMenuLinksLuhmann); jSeparator58.setName("jSeparator58"); // NOI18N viewMenuLinks.add(jSeparator58); viewMenuLinksDesktop.setAction(actionMap.get("addDesktop")); // NOI18N viewMenuLinksDesktop.setName("viewMenuLinksDesktop"); // NOI18N viewMenuLinks.add(viewMenuLinksDesktop); jSeparator100.setName("jSeparator100"); // NOI18N viewMenuLinks.add(jSeparator100); viewMenuLinksExport.setAction(actionMap.get("exportLinks")); // NOI18N viewMenuLinksExport.setName("viewMenuLinksExport"); // NOI18N viewMenuLinks.add(viewMenuLinksExport); viewMenuExportToSearch.setAction(actionMap.get("exportLinksToSearch")); // NOI18N viewMenuExportToSearch.setName("viewMenuExportToSearch"); // NOI18N viewMenuLinks.add(viewMenuExportToSearch); menuBar.add(viewMenuLinks); viewMenuLuhmann.setText(resourceMap.getString("viewMenuLuhmann.text")); // NOI18N viewMenuLuhmann.setName("viewMenuLuhmann"); // NOI18N viewMenuLuhmannDelete.setAction(actionMap.get("deleteLuhmannFromEntry")); // NOI18N viewMenuLuhmannDelete.setName("viewMenuLuhmannDelete"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannDelete); jSeparator61.setName("jSeparator61"); // NOI18N viewMenuLuhmann.add(jSeparator61); viewMenuLuhmannManLinks.setAction(actionMap.get("addManLinks")); // NOI18N viewMenuLuhmannManLinks.setName("viewMenuLuhmannManLinks"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannManLinks); viewMenuLuhmannBookmarks.setAction(actionMap.get("addBookmarks")); // NOI18N viewMenuLuhmannBookmarks.setName("viewMenuLuhmannBookmarks"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannBookmarks); jSeparator62.setName("jSeparator62"); // NOI18N viewMenuLuhmann.add(jSeparator62); viewMenuLuhmannDesktop.setAction(actionMap.get("addDesktop")); // NOI18N viewMenuLuhmannDesktop.setName("viewMenuLuhmannDesktop"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannDesktop); jSeparator102.setName("jSeparator102"); // NOI18N viewMenuLuhmann.add(jSeparator102); viewMenuLuhmannExport.setAction(actionMap.get("exportLuhmann")); // NOI18N viewMenuLuhmannExport.setName("viewMenuLuhmannExport"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannExport); viewMenuLuhmannExportSearch.setAction(actionMap.get("exportLuhmannToSearch")); // NOI18N viewMenuLuhmannExportSearch.setName("viewMenuLuhmannExportSearch"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannExportSearch); jSeparator117.setName("jSeparator117"); // NOI18N viewMenuLuhmann.add(jSeparator117); viewMenuLuhmannSortEntries.setAction(actionMap.get("sortLuhmann")); // NOI18N viewMenuLuhmannSortEntries.setName("viewMenuLuhmannSortEntries"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannSortEntries); jSeparator118.setName("jSeparator118"); // NOI18N viewMenuLuhmann.add(jSeparator118); viewMenuLuhmannShowNumbers.setAction(actionMap.get("showLuhmannEntryNumber")); // NOI18N viewMenuLuhmannShowNumbers.setSelected(true); viewMenuLuhmannShowNumbers.setName("viewMenuLuhmannShowNumbers"); // NOI18N viewMenuLuhmann.add(viewMenuLuhmannShowNumbers); menuBar.add(viewMenuLuhmann); viewMenuKeywords.setText(resourceMap.getString("viewMenuKeywords.text")); // NOI18N viewMenuKeywords.setName("viewMenuKeywords"); // NOI18N viewKeywordsCopy.setAction(actionMap.get("copy")); viewKeywordsCopy.setName("viewKeywordsCopy"); // NOI18N viewMenuKeywords.add(viewKeywordsCopy); jSeparator25.setName("jSeparator25"); // NOI18N viewMenuKeywords.add(jSeparator25); viewKeywordsSearchOr.setAction(actionMap.get("searchLogOr")); // NOI18N viewKeywordsSearchOr.setName("viewKeywordsSearchOr"); // NOI18N viewMenuKeywords.add(viewKeywordsSearchOr); viewKeywordsSearchAnd.setAction(actionMap.get("searchLogAnd")); // NOI18N viewKeywordsSearchAnd.setName("viewKeywordsSearchAnd"); // NOI18N viewMenuKeywords.add(viewKeywordsSearchAnd); viewKeywordsSearchNot.setAction(actionMap.get("searchLogNot")); // NOI18N viewKeywordsSearchNot.setName("viewKeywordsSearchNot"); // NOI18N viewMenuKeywords.add(viewKeywordsSearchNot); jSeparator26.setName("jSeparator26"); // NOI18N viewMenuKeywords.add(jSeparator26); viewKeywordsNew.setAction(actionMap.get("newKeyword")); // NOI18N viewKeywordsNew.setName("viewKeywordsNew"); // NOI18N viewMenuKeywords.add(viewKeywordsNew); viewKeywordsEdit.setAction(actionMap.get("editKeyword")); // NOI18N viewKeywordsEdit.setName("viewKeywordsEdit"); // NOI18N viewMenuKeywords.add(viewKeywordsEdit); viewKeywordsDelete.setAction(actionMap.get("deleteKeyword")); // NOI18N viewKeywordsDelete.setName("viewKeywordsDelete"); // NOI18N viewMenuKeywords.add(viewKeywordsDelete); jSeparator27.setName("jSeparator27"); // NOI18N viewMenuKeywords.add(jSeparator27); viewKeywordsAddToList.setAction(actionMap.get("addKeywordToList")); // NOI18N viewKeywordsAddToList.setName("viewKeywordsAddToList"); // NOI18N viewMenuKeywords.add(viewKeywordsAddToList); jSeparator47.setName("jSeparator47"); // NOI18N viewMenuKeywords.add(jSeparator47); viewKeywordsLuhmann.setAction(actionMap.get("addLuhmannLogOr")); // NOI18N viewKeywordsLuhmann.setName("viewKeywordsLuhmann"); // NOI18N viewMenuKeywords.add(viewKeywordsLuhmann); viewKeywordsLuhmannAnd.setAction(actionMap.get("addLuhmannLogAnd")); // NOI18N viewKeywordsLuhmannAnd.setName("viewKeywordsLuhmannAnd"); // NOI18N viewMenuKeywords.add(viewKeywordsLuhmannAnd); jSeparator67.setName("jSeparator67"); // NOI18N viewMenuKeywords.add(jSeparator67); viewKeywordsManLinks.setAction(actionMap.get("addManLinksLogOr")); // NOI18N viewKeywordsManLinks.setName("viewKeywordsManLinks"); // NOI18N viewMenuKeywords.add(viewKeywordsManLinks); viewKeywordsManLinksAnd.setAction(actionMap.get("addManLinksLogAnd")); // NOI18N viewKeywordsManLinksAnd.setName("viewKeywordsManLinksAnd"); // NOI18N viewMenuKeywords.add(viewKeywordsManLinksAnd); jSeparator48.setName("jSeparator48"); // NOI18N viewMenuKeywords.add(jSeparator48); viewKeywordsDesktop.setAction(actionMap.get("addDesktopLogOr")); // NOI18N viewKeywordsDesktop.setName("viewKeywordsDesktop"); // NOI18N viewMenuKeywords.add(viewKeywordsDesktop); viewKeywordsDesktopAnd.setAction(actionMap.get("addDesktopLogAnd")); // NOI18N viewKeywordsDesktopAnd.setName("viewKeywordsDesktopAnd"); // NOI18N viewMenuKeywords.add(viewKeywordsDesktopAnd); jSeparator80.setName("jSeparator80"); // NOI18N viewMenuKeywords.add(jSeparator80); viewKeywordsExport.setAction(actionMap.get("exportKeywords")); // NOI18N viewKeywordsExport.setName("viewKeywordsExport"); // NOI18N viewMenuKeywords.add(viewKeywordsExport); menuBar.add(viewMenuKeywords); viewMenuAuthors.setText(resourceMap.getString("viewMenuAuthors.text")); // NOI18N viewMenuAuthors.setName("viewMenuAuthors"); // NOI18N viewAuthorsCopy.setAction(actionMap.get("copy")); viewAuthorsCopy.setName("viewAuthorsCopy"); // NOI18N viewMenuAuthors.add(viewAuthorsCopy); jSeparator28.setName("jSeparator28"); // NOI18N viewMenuAuthors.add(jSeparator28); viewAuthorsSubFind.setText(resourceMap.getString("viewAuthorsSubFind.text")); // NOI18N viewAuthorsSubFind.setName("viewAuthorsSubFind"); // NOI18N viewAuthorsSearchOr.setAction(actionMap.get("searchLogOr")); // NOI18N viewAuthorsSearchOr.setName("viewAuthorsSearchOr"); // NOI18N viewAuthorsSubFind.add(viewAuthorsSearchOr); viewAuthorsSearchAnd.setAction(actionMap.get("searchLogAnd")); // NOI18N viewAuthorsSearchAnd.setName("viewAuthorsSearchAnd"); // NOI18N viewAuthorsSubFind.add(viewAuthorsSearchAnd); viewAuthorsSearchNot.setAction(actionMap.get("searchLogNot")); // NOI18N viewAuthorsSearchNot.setName("viewAuthorsSearchNot"); // NOI18N viewAuthorsSubFind.add(viewAuthorsSearchNot); viewMenuAuthors.add(viewAuthorsSubFind); jSeparator29.setName("jSeparator29"); // NOI18N viewMenuAuthors.add(jSeparator29); viewAuthorsSubEdit.setText(resourceMap.getString("viewAuthorsSubEdit.text")); // NOI18N viewAuthorsSubEdit.setName("viewAuthorsSubEdit"); // NOI18N viewAuthorsNew.setAction(actionMap.get("newAuthor")); // NOI18N viewAuthorsNew.setName("viewAuthorsNew"); // NOI18N viewAuthorsSubEdit.add(viewAuthorsNew); viewAuthorsEdit.setAction(actionMap.get("editAuthor")); // NOI18N viewAuthorsEdit.setName("viewAuthorsEdit"); // NOI18N viewAuthorsSubEdit.add(viewAuthorsEdit); viewAuthorsDelete.setAction(actionMap.get("deleteAuthor")); // NOI18N viewAuthorsDelete.setName("viewAuthorsDelete"); // NOI18N viewAuthorsSubEdit.add(viewAuthorsDelete); jSeparator90.setName("jSeparator90"); // NOI18N viewAuthorsSubEdit.add(jSeparator90); viewAuthorsBibkey.setAction(actionMap.get("changeBibkey")); // NOI18N viewAuthorsBibkey.setName("viewAuthorsBibkey"); // NOI18N viewAuthorsSubEdit.add(viewAuthorsBibkey); viewMenuAuthors.add(viewAuthorsSubEdit); jSeparator30.setName("jSeparator30"); // NOI18N viewMenuAuthors.add(jSeparator30); viewAuthorsSubAdd.setText(resourceMap.getString("viewAuthorsSubAdd.text")); // NOI18N viewAuthorsSubAdd.setName("viewAuthorsSubAdd"); // NOI18N viewAuthorsAddToEntry.setAction(actionMap.get("addAuthorToList")); // NOI18N viewAuthorsAddToEntry.setName("viewAuthorsAddToEntry"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsAddToEntry); jSeparator51.setName("jSeparator51"); // NOI18N viewAuthorsSubAdd.add(jSeparator51); viewAuthorsManLinks.setAction(actionMap.get("addManLinksLogOr")); // NOI18N viewAuthorsManLinks.setName("viewAuthorsManLinks"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsManLinks); viewAuthorsManLinksAnd.setAction(actionMap.get("addManLinksLogAnd")); // NOI18N viewAuthorsManLinksAnd.setName("viewAuthorsManLinksAnd"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsManLinksAnd); jSeparator71.setName("jSeparator71"); // NOI18N viewAuthorsSubAdd.add(jSeparator71); viewAuthorsAddLuhmann.setAction(actionMap.get("addLuhmannLogOr")); // NOI18N viewAuthorsAddLuhmann.setName("viewAuthorsAddLuhmann"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsAddLuhmann); viewAuthorsAddLuhmannAnd.setAction(actionMap.get("addLuhmannLogAnd")); // NOI18N viewAuthorsAddLuhmannAnd.setName("viewAuthorsAddLuhmannAnd"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsAddLuhmannAnd); jSeparator52.setName("jSeparator52"); // NOI18N viewAuthorsSubAdd.add(jSeparator52); viewAuthorsDesktop.setAction(actionMap.get("addDesktopLogOr")); // NOI18N viewAuthorsDesktop.setName("viewAuthorsDesktop"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsDesktop); viewAuthorsDesktopAnd.setAction(actionMap.get("addDesktopLogAnd")); // NOI18N viewAuthorsDesktopAnd.setName("viewAuthorsDesktopAnd"); // NOI18N viewAuthorsSubAdd.add(viewAuthorsDesktopAnd); viewMenuAuthors.add(viewAuthorsSubAdd); jSeparator81.setName("jSeparator81"); // NOI18N viewMenuAuthors.add(jSeparator81); viewAuthorsImport.setAction(actionMap.get("importAuthors")); // NOI18N viewAuthorsImport.setName("viewAuthorsImport"); // NOI18N viewMenuAuthors.add(viewAuthorsImport); viewAuthorsExport.setAction(actionMap.get("exportAuthors")); // NOI18N viewAuthorsExport.setName("viewAuthorsExport"); // NOI18N viewMenuAuthors.add(viewAuthorsExport); jSeparator92.setName("jSeparator92"); // NOI18N viewMenuAuthors.add(jSeparator92); viewAuthorsAttachBibtexFile.setAction(actionMap.get("attachBibtexFile")); // NOI18N viewAuthorsAttachBibtexFile.setName("viewAuthorsAttachBibtexFile"); // NOI18N viewMenuAuthors.add(viewAuthorsAttachBibtexFile); viewAuthorsRefreshBibtexFile.setAction(actionMap.get("refreshBibTexFile")); // NOI18N viewAuthorsRefreshBibtexFile.setName("viewAuthorsRefreshBibtexFile"); // NOI18N viewMenuAuthors.add(viewAuthorsRefreshBibtexFile); menuBar.add(viewMenuAuthors); viewMenuTitles.setText(resourceMap.getString("viewMenuTitles.text")); // NOI18N viewMenuTitles.setName("viewMenuTitles"); // NOI18N viewTitlesCopy.setAction(actionMap.get("copy")); viewTitlesCopy.setName("viewTitlesCopy"); // NOI18N viewMenuTitles.add(viewTitlesCopy); jSeparator43.setName("jSeparator43"); // NOI18N viewMenuTitles.add(jSeparator43); viewTitlesEdit.setAction(actionMap.get("editTitle")); // NOI18N viewTitlesEdit.setName("viewTitlesEdit"); // NOI18N viewMenuTitles.add(viewTitlesEdit); viewTitlesDelete.setAction(actionMap.get("deleteEntry")); // NOI18N viewTitlesDelete.setName("viewTitlesDelete"); // NOI18N viewMenuTitles.add(viewTitlesDelete); jSeparator65.setName("jSeparator65"); // NOI18N viewMenuTitles.add(jSeparator65); viewTitlesMoveEntry.setAction(actionMap.get("moveEntry")); // NOI18N viewTitlesMoveEntry.setName("viewTitlesMoveEntry"); // NOI18N viewMenuTitles.add(viewTitlesMoveEntry); jSeparator105.setName("jSeparator105"); // NOI18N viewMenuTitles.add(jSeparator105); viewTitlesAutomaticFirstLine.setAction(actionMap.get("automaticFirstLineAsTitle")); // NOI18N viewTitlesAutomaticFirstLine.setName("viewTitlesAutomaticFirstLine"); // NOI18N viewMenuTitles.add(viewTitlesAutomaticFirstLine); jSeparator42.setName("jSeparator42"); // NOI18N viewMenuTitles.add(jSeparator42); viewTitlesManLinks.setAction(actionMap.get("addManLinks")); // NOI18N viewTitlesManLinks.setName("viewTitlesManLinks"); // NOI18N viewMenuTitles.add(viewTitlesManLinks); viewTitlesLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N viewTitlesLuhmann.setName("viewTitlesLuhmann"); // NOI18N viewMenuTitles.add(viewTitlesLuhmann); viewTitlesBookmarks.setAction(actionMap.get("addBookmarks")); // NOI18N viewTitlesBookmarks.setName("viewTitlesBookmarks"); // NOI18N viewMenuTitles.add(viewTitlesBookmarks); jSeparator113.setName("jSeparator113"); // NOI18N viewMenuTitles.add(jSeparator113); viewTitlesDesktop.setAction(actionMap.get("addDesktop")); // NOI18N viewTitlesDesktop.setName("viewTitlesDesktop"); // NOI18N viewMenuTitles.add(viewTitlesDesktop); jSeparator108.setName("jSeparator108"); // NOI18N viewMenuTitles.add(jSeparator108); viewTitlesExport.setAction(actionMap.get("exportTitles")); // NOI18N viewTitlesExport.setName("viewTitlesExport"); // NOI18N viewMenuTitles.add(viewTitlesExport); menuBar.add(viewMenuTitles); viewMenuCluster.setText(resourceMap.getString("viewMenuCluster.text")); // NOI18N viewMenuCluster.setName("viewMenuCluster"); // NOI18N viewClusterExport.setAction(actionMap.get("exportCluster")); // NOI18N viewClusterExport.setName("viewClusterExport"); // NOI18N viewMenuCluster.add(viewClusterExport); viewClusterExportToSearch.setAction(actionMap.get("exportClusterToSearch")); // NOI18N viewClusterExportToSearch.setName("viewClusterExportToSearch"); // NOI18N viewMenuCluster.add(viewClusterExportToSearch); menuBar.add(viewMenuCluster); viewMenuBookmarks.setText(resourceMap.getString("viewMenuBookmarks.text")); // NOI18N viewMenuBookmarks.setName("viewMenuBookmarks"); // NOI18N viewBookmarksEdit.setAction(actionMap.get("editBookmark")); // NOI18N viewBookmarksEdit.setName("viewBookmarksEdit"); // NOI18N viewMenuBookmarks.add(viewBookmarksEdit); viewBookmarksDelete.setAction(actionMap.get("deleteBookmark")); // NOI18N viewBookmarksDelete.setName("viewBookmarksDelete"); // NOI18N viewMenuBookmarks.add(viewBookmarksDelete); jSeparator35.setName("jSeparator35"); // NOI18N viewMenuBookmarks.add(jSeparator35); viewBookmarksEditCat.setAction(actionMap.get("editBookmarkCategory")); // NOI18N viewBookmarksEditCat.setName("viewBookmarksEditCat"); // NOI18N viewMenuBookmarks.add(viewBookmarksEditCat); viewBookmarksDeleteCat.setAction(actionMap.get("deleteBookmarkCategory")); // NOI18N viewBookmarksDeleteCat.setName("viewBookmarksDeleteCat"); // NOI18N viewMenuBookmarks.add(viewBookmarksDeleteCat); jSeparator37.setName("jSeparator37"); // NOI18N viewMenuBookmarks.add(jSeparator37); viewBookmarksManLink.setAction(actionMap.get("addManLinks")); // NOI18N viewBookmarksManLink.setName("viewBookmarksManLink"); // NOI18N viewMenuBookmarks.add(viewBookmarksManLink); viewBookmarksAddLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N viewBookmarksAddLuhmann.setName("viewBookmarksAddLuhmann"); // NOI18N viewMenuBookmarks.add(viewBookmarksAddLuhmann); jSeparator59.setName("jSeparator59"); // NOI18N viewMenuBookmarks.add(jSeparator59); viewBookmarkDesktop.setAction(actionMap.get("addDesktop")); // NOI18N viewBookmarkDesktop.setName("viewBookmarkDesktop"); // NOI18N viewMenuBookmarks.add(viewBookmarkDesktop); jSeparator82.setName("jSeparator82"); // NOI18N viewMenuBookmarks.add(jSeparator82); viewBookmarksExport.setAction(actionMap.get("exportBookmarks")); // NOI18N viewBookmarksExport.setName("viewBookmarksExport"); // NOI18N viewMenuBookmarks.add(viewBookmarksExport); viewBookmarksExportSearch.setAction(actionMap.get("exportBookmarksToSearch")); // NOI18N viewBookmarksExportSearch.setName("viewBookmarksExportSearch"); // NOI18N viewMenuBookmarks.add(viewBookmarksExportSearch); menuBar.add(viewMenuBookmarks); viewMenuAttachments.setText(resourceMap.getString("viewMenuAttachments.text")); // NOI18N viewMenuAttachments.setName("viewMenuAttachments"); // NOI18N viewAttachmentsCopy.setAction(actionMap.get("copy")); viewAttachmentsCopy.setName("viewAttachmentsCopy"); // NOI18N viewMenuAttachments.add(viewAttachmentsCopy); jSeparator84.setName("jSeparator84"); // NOI18N viewMenuAttachments.add(jSeparator84); viewAttachmentEdit.setAction(actionMap.get("editAttachment")); // NOI18N viewAttachmentEdit.setName("viewAttachmentEdit"); // NOI18N viewMenuAttachments.add(viewAttachmentEdit); viewAttachmentsDelete.setAction(actionMap.get("deleteAttachment")); // NOI18N viewAttachmentsDelete.setName("viewAttachmentsDelete"); // NOI18N viewMenuAttachments.add(viewAttachmentsDelete); jSeparator85.setName("jSeparator85"); // NOI18N viewMenuAttachments.add(jSeparator85); viewMenuAttachmentGoto.setAction(actionMap.get("openAttachmentDirectory")); // NOI18N viewMenuAttachmentGoto.setName("viewMenuAttachmentGoto"); // NOI18N viewMenuAttachments.add(viewMenuAttachmentGoto); jSeparator93.setName("jSeparator93"); // NOI18N viewMenuAttachments.add(jSeparator93); viewAttachmentsExport.setAction(actionMap.get("exportAttachments")); // NOI18N viewAttachmentsExport.setName("viewAttachmentsExport"); // NOI18N viewMenuAttachments.add(viewAttachmentsExport); menuBar.add(viewMenuAttachments); windowsMenu.setText(resourceMap.getString("windowsMenu.text")); // NOI18N windowsMenu.setName("windowsMenu"); // NOI18N showSearchResultsMenuItem.setAction(actionMap.get("showSearchResultWindow")); // NOI18N showSearchResultsMenuItem.setName("showSearchResultsMenuItem"); // NOI18N windowsMenu.add(showSearchResultsMenuItem); jSeparator44.setName("jSeparator44"); // NOI18N windowsMenu.add(jSeparator44); showDesktopMenuItem.setAction(actionMap.get("showDesktopWindow")); // NOI18N showDesktopMenuItem.setName("showDesktopMenuItem"); // NOI18N windowsMenu.add(showDesktopMenuItem); jSeparator109.setName("jSeparator109"); // NOI18N windowsMenu.add(jSeparator109); showNewEntryMenuItem.setAction(actionMap.get("showNewEntryWindow")); // NOI18N showNewEntryMenuItem.setName("showNewEntryMenuItem"); // NOI18N windowsMenu.add(showNewEntryMenuItem); jSeparator34.setName("jSeparator34"); // NOI18N windowsMenu.add(jSeparator34); showErrorLogMenuItem.setAction(actionMap.get("showErrorLog")); // NOI18N showErrorLogMenuItem.setName("showErrorLogMenuItem"); // NOI18N windowsMenu.add(showErrorLogMenuItem); menuBar.add(windowsMenu); aboutMenu.setText(resourceMap.getString("aboutMenu.text")); // NOI18N aboutMenu.setName("aboutMenu"); // NOI18N aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N aboutMenuItem.setName("aboutMenuItem"); // NOI18N aboutMenu.add(aboutMenuItem); jSeparatorAbout1.setName("jSeparatorAbout1"); // NOI18N aboutMenu.add(jSeparatorAbout1); preferencesMenuItem.setAction(actionMap.get("settingsWindow")); // NOI18N preferencesMenuItem.setName("preferencesMenuItem"); // NOI18N aboutMenu.add(preferencesMenuItem); menuBar.add(aboutMenu); statusPanel.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 0, 0, 0, resourceMap.getColor("statusPanel.border.matteColor"))); // NOI18N statusPanel.setMinimumSize(new java.awt.Dimension(200, 16)); statusPanel.setName("statusPanel"); // NOI18N jPanel12.setName("jPanel12"); // NOI18N statusEntryLabel.setText(resourceMap.getString("statusEntryLabel.text")); // NOI18N statusEntryLabel.setName("statusEntryLabel"); // NOI18N statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N jTextFieldEntryNumber.setColumns(4); jTextFieldEntryNumber.setText(resourceMap.getString("jTextFieldEntryNumber.text")); // NOI18N jTextFieldEntryNumber.setToolTipText(resourceMap.getString("jTextFieldEntryNumber.toolTipText")); // NOI18N jTextFieldEntryNumber.setName("jTextFieldEntryNumber"); // NOI18N statusOfEntryLabel.setText(resourceMap.getString("statusOfEntryLabel.text")); // NOI18N statusOfEntryLabel.setName("statusOfEntryLabel"); // NOI18N buttonHistoryBack.setAction(actionMap.get("historyBack")); // NOI18N buttonHistoryBack.setIcon(resourceMap.getIcon("buttonHistoryBack.icon")); // NOI18N buttonHistoryBack.setBorderPainted(false); buttonHistoryBack.setContentAreaFilled(false); buttonHistoryBack.setFocusPainted(false); buttonHistoryBack.setMargin(new java.awt.Insets(0, 0, 0, 0)); buttonHistoryBack.setName("buttonHistoryBack"); // NOI18N buttonHistoryFore.setAction(actionMap.get("historyFor")); // NOI18N buttonHistoryFore.setIcon(resourceMap.getIcon("buttonHistoryFore.icon")); // NOI18N buttonHistoryFore.setBorderPainted(false); buttonHistoryFore.setContentAreaFilled(false); buttonHistoryFore.setFocusPainted(false); buttonHistoryFore.setMargin(new java.awt.Insets(0, 0, 0, 0)); buttonHistoryFore.setName("buttonHistoryFore"); // NOI18N statusMsgLabel.setText(resourceMap.getString("statusMsgLabel.text")); // NOI18N statusMsgLabel.setName("statusMsgLabel"); // NOI18N statusErrorButton.setAction(actionMap.get("showErrorLog")); // NOI18N statusErrorButton.setIcon(resourceMap.getIcon("statusErrorButton.icon")); // NOI18N statusErrorButton.setText(resourceMap.getString("statusErrorButton.text")); // NOI18N statusErrorButton.setToolTipText(resourceMap.getString("statusErrorButton.toolTipText")); // NOI18N statusErrorButton.setBorderPainted(false); statusErrorButton.setContentAreaFilled(false); statusErrorButton.setFocusPainted(false); statusErrorButton.setName("statusErrorButton"); // NOI18N statusDesktopEntryButton.setAction(actionMap.get("showEntryInDesktopWindow")); // NOI18N statusDesktopEntryButton.setIcon(resourceMap.getIcon("statusDesktopEntryButton.icon")); // NOI18N statusDesktopEntryButton.setText(resourceMap.getString("statusDesktopEntryButton.text")); // NOI18N statusDesktopEntryButton.setToolTipText(resourceMap.getString("statusDesktopEntryButton.toolTipText")); // NOI18N statusDesktopEntryButton.setBorderPainted(false); statusDesktopEntryButton.setContentAreaFilled(false); statusDesktopEntryButton.setFocusPainted(false); statusDesktopEntryButton.setName("statusDesktopEntryButton"); // NOI18N javax.swing.GroupLayout jPanel12Layout = new javax.swing.GroupLayout(jPanel12); jPanel12.setLayout(jPanel12Layout); jPanel12Layout.setHorizontalGroup(jPanel12Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel12Layout.createSequentialGroup() .addComponent(statusEntryLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTextFieldEntryNumber, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(statusOfEntryLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonHistoryBack, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonHistoryFore, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel12Layout.createSequentialGroup() .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 743, Short.MAX_VALUE) .addComponent(statusMsgLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(statusAnimationLabel)) .addGroup(jPanel12Layout.createSequentialGroup().addGap(6, 6, 6) .addComponent(statusErrorButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(statusDesktopEntryButton).addContainerGap())))); jPanel12Layout.setVerticalGroup(jPanel12Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel12Layout.createSequentialGroup().addGap(3, 3, 3).addGroup(jPanel12Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(statusEntryLabel) .addComponent(jTextFieldEntryNumber, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(statusOfEntryLabel)) .addGroup(jPanel12Layout .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(buttonHistoryFore, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(buttonHistoryBack, javax.swing.GroupLayout.Alignment.LEADING)) .addComponent(statusAnimationLabel).addComponent(statusMsgLabel) .addComponent(statusErrorButton).addComponent(statusDesktopEntryButton)).addGap(3, 3, 3))); javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel); statusPanel.setLayout(statusPanelLayout); statusPanelLayout.setHorizontalGroup(statusPanelLayout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(statusPanelLayout.createSequentialGroup().addContainerGap().addComponent(jPanel12, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap())); statusPanelLayout.setVerticalGroup( statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( javax.swing.GroupLayout.Alignment.TRAILING, statusPanelLayout.createSequentialGroup().addGap(0, 0, Short.MAX_VALUE).addComponent( jPanel12, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); toolBar.setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 0, resourceMap.getColor("toolBar.border.matteColor"))); // NOI18N toolBar.setFloatable(false); toolBar.setMinimumSize(new java.awt.Dimension(300, 20)); toolBar.setName("toolBar"); // NOI18N tb_newEntry.setAction(actionMap.get("newEntry")); // 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); toolBar.add(tb_newEntry); tb_open.setAction(actionMap.get("openDocument")); // NOI18N tb_open.setText(resourceMap.getString("tb_open.text")); // NOI18N tb_open.setBorderPainted(false); tb_open.setFocusPainted(false); tb_open.setFocusable(false); tb_open.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_open.setName("tb_open"); // NOI18N tb_open.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_open); tb_save.setAction(actionMap.get("saveDocument")); // NOI18N tb_save.setText(resourceMap.getString("tb_save.text")); // NOI18N tb_save.setBorderPainted(false); tb_save.setFocusPainted(false); tb_save.setFocusable(false); tb_save.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_save.setName("tb_save"); // NOI18N tb_save.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_save); jSeparator4.setName("jSeparator4"); // NOI18N toolBar.add(jSeparator4); tb_edit.setAction(actionMap.get("editEntry")); // NOI18N tb_edit.setText(resourceMap.getString("tb_edit.text")); // NOI18N tb_edit.setBorderPainted(false); tb_edit.setFocusPainted(false); tb_edit.setFocusable(false); tb_edit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_edit.setName("tb_edit"); // NOI18N tb_edit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_edit); tb_delete.setAction(actionMap.get("deleteCurrentEntry")); // 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); toolBar.add(tb_delete); tb_copy.setAction(actionMap.get("copy")); 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); toolBar.add(tb_copy); tb_paste.setAction(actionMap.get("paste")); 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); toolBar.add(tb_paste); tb_selectall.setAction(actionMap.get("selectAllText")); // NOI18N tb_selectall.setText(resourceMap.getString("tb_selectall.text")); // NOI18N tb_selectall.setBorderPainted(false); tb_selectall.setFocusPainted(false); tb_selectall.setFocusable(false); tb_selectall.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_selectall.setName("tb_selectall"); // NOI18N tb_selectall.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_selectall); jSeparator5.setName("jSeparator5"); // NOI18N toolBar.add(jSeparator5); tb_addmanlinks.setAction(actionMap.get("manualInsertLinks")); // NOI18N tb_addmanlinks.setText(resourceMap.getString("tb_addmanlinks.text")); // NOI18N tb_addmanlinks.setBorderPainted(false); tb_addmanlinks.setFocusPainted(false); tb_addmanlinks.setFocusable(false); tb_addmanlinks.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_addmanlinks.setName("tb_addmanlinks"); // NOI18N tb_addmanlinks.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_addmanlinks); tb_addluhmann.setAction(actionMap.get("manualInsertEntry")); // 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); toolBar.add(tb_addluhmann); tb_addbookmark.setAction(actionMap.get("addToBookmark")); // NOI18N tb_addbookmark.setText(resourceMap.getString("tb_addbookmark.text")); // NOI18N tb_addbookmark.setBorderPainted(false); tb_addbookmark.setFocusPainted(false); tb_addbookmark.setFocusable(false); tb_addbookmark.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_addbookmark.setName("tb_addbookmark"); // NOI18N tb_addbookmark.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_addbookmark); tb_addtodesktop.setAction(actionMap.get("addToDesktop")); // NOI18N tb_addtodesktop.setText(resourceMap.getString("tb_addtodesktop.text")); // NOI18N tb_addtodesktop.setBorderPainted(false); tb_addtodesktop.setFocusPainted(false); tb_addtodesktop.setFocusable(false); tb_addtodesktop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_addtodesktop.setName("tb_addtodesktop"); // NOI18N tb_addtodesktop.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_addtodesktop); jSeparator10.setName("jSeparator10"); // NOI18N toolBar.add(jSeparator10); tb_find.setAction(actionMap.get("find")); // NOI18N tb_find.setText(resourceMap.getString("tb_find.text")); // NOI18N tb_find.setBorderPainted(false); tb_find.setFocusPainted(false); tb_find.setFocusable(false); tb_find.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_find.setName("tb_find"); // NOI18N tb_find.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_find); tb_first.setAction(actionMap.get("showFirstEntry")); // NOI18N tb_first.setText(resourceMap.getString("tb_first.text")); // NOI18N tb_first.setBorderPainted(false); tb_first.setFocusPainted(false); tb_first.setFocusable(false); tb_first.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_first.setName("tb_first"); // NOI18N tb_first.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_first); tb_prev.setAction(actionMap.get("showPrevEntry")); // NOI18N tb_prev.setText(resourceMap.getString("tb_prev.text")); // NOI18N tb_prev.setBorderPainted(false); tb_prev.setFocusPainted(false); tb_prev.setFocusable(false); tb_prev.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_prev.setName("tb_prev"); // NOI18N tb_prev.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_prev); tb_next.setAction(actionMap.get("showNextEntry")); // NOI18N tb_next.setText(resourceMap.getString("tb_next.text")); // NOI18N tb_next.setBorderPainted(false); tb_next.setFocusPainted(false); tb_next.setFocusable(false); tb_next.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_next.setName("tb_next"); // NOI18N tb_next.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_next); tb_last.setAction(actionMap.get("showLastEntry")); // NOI18N tb_last.setText(resourceMap.getString("tb_last.text")); // NOI18N tb_last.setBorderPainted(false); tb_last.setFocusPainted(false); tb_last.setFocusable(false); tb_last.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); tb_last.setName("tb_last"); // NOI18N tb_last.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); toolBar.add(tb_last); jSeparator32.setName("jSeparator32"); // NOI18N toolBar.add(jSeparator32); jLabelMemory.setName("jLabelMemory"); // NOI18N toolBar.add(jLabelMemory); jPopupMenuKeywords.setName("jPopupMenuKeywords"); // NOI18N popupKeywordsCopy.setAction(actionMap.get("copy")); popupKeywordsCopy.setName("popupKeywordsCopy"); // NOI18N jPopupMenuKeywords.add(popupKeywordsCopy); jSeparator8.setName("jSeparator8"); // NOI18N jPopupMenuKeywords.add(jSeparator8); popupKeywordsSearchOr.setAction(actionMap.get("searchLogOr")); // NOI18N popupKeywordsSearchOr.setName("popupKeywordsSearchOr"); // NOI18N jPopupMenuKeywords.add(popupKeywordsSearchOr); popupKeywordsSearchAnd.setAction(actionMap.get("searchLogAnd")); // NOI18N popupKeywordsSearchAnd.setName("popupKeywordsSearchAnd"); // NOI18N jPopupMenuKeywords.add(popupKeywordsSearchAnd); popupKeywordsSearchNot.setAction(actionMap.get("searchLogNot")); // NOI18N popupKeywordsSearchNot.setName("popupKeywordsSearchNot"); // NOI18N jPopupMenuKeywords.add(popupKeywordsSearchNot); jSeparator9.setName("jSeparator9"); // NOI18N jPopupMenuKeywords.add(jSeparator9); popupKeywordsNew.setAction(actionMap.get("newKeyword")); // NOI18N popupKeywordsNew.setName("popupKeywordsNew"); // NOI18N jPopupMenuKeywords.add(popupKeywordsNew); popupKeywordsEdit.setAction(actionMap.get("editKeyword")); // NOI18N popupKeywordsEdit.setName("popupKeywordsEdit"); // NOI18N jPopupMenuKeywords.add(popupKeywordsEdit); popupKeywordsDelete.setAction(actionMap.get("deleteKeyword")); // NOI18N popupKeywordsDelete.setName("popupKeywordsDelete"); // NOI18N jPopupMenuKeywords.add(popupKeywordsDelete); jSeparator7.setName("jSeparator7"); // NOI18N jPopupMenuKeywords.add(jSeparator7); popupKeywordsAddToList.setAction(actionMap.get("addKeywordToList")); // NOI18N popupKeywordsAddToList.setName("popupKeywordsAddToList"); // NOI18N jPopupMenuKeywords.add(popupKeywordsAddToList); jSeparator45.setName("jSeparator45"); // NOI18N jPopupMenuKeywords.add(jSeparator45); popupKeywordsManLinks.setAction(actionMap.get("addManLinksLogOr")); // NOI18N popupKeywordsManLinks.setName("popupKeywordsManLinks"); // NOI18N jPopupMenuKeywords.add(popupKeywordsManLinks); popupKeywordsManLinksAnd.setAction(actionMap.get("addManLinksLogAnd")); // NOI18N popupKeywordsManLinksAnd.setName("popupKeywordsManLinksAnd"); // NOI18N jPopupMenuKeywords.add(popupKeywordsManLinksAnd); jSeparator66.setName("jSeparator66"); // NOI18N jPopupMenuKeywords.add(jSeparator66); popupKeywordsLuhmann.setAction(actionMap.get("addLuhmannLogOr")); // NOI18N popupKeywordsLuhmann.setName("popupKeywordsLuhmann"); // NOI18N jPopupMenuKeywords.add(popupKeywordsLuhmann); popupKeywordsLuhmannAnd.setAction(actionMap.get("addLuhmannLogAnd")); // NOI18N popupKeywordsLuhmannAnd.setName("popupKeywordsLuhmannAnd"); // NOI18N jPopupMenuKeywords.add(popupKeywordsLuhmannAnd); jSeparator46.setName("jSeparator46"); // NOI18N jPopupMenuKeywords.add(jSeparator46); popupKeywordsDesktop.setAction(actionMap.get("addDesktopLogOr")); // NOI18N popupKeywordsDesktop.setName("popupKeywordsDesktop"); // NOI18N jPopupMenuKeywords.add(popupKeywordsDesktop); popupKeywordsDesktopAnd.setAction(actionMap.get("addDesktopLogAnd")); // NOI18N popupKeywordsDesktopAnd.setName("popupKeywordsDesktopAnd"); // NOI18N jPopupMenuKeywords.add(popupKeywordsDesktopAnd); jPopupMenuKeywordList.setName("jPopupMenuKeywordList"); // NOI18N popupKwListCopy.setAction(actionMap.get("copy")); popupKwListCopy.setName("popupKwListCopy"); // NOI18N jPopupMenuKeywordList.add(popupKwListCopy); jSeparator89.setName("jSeparator89"); // NOI18N jPopupMenuKeywordList.add(jSeparator89); popupKwListSearchOr.setAction(actionMap.get("searchKeywordsFromListLogOr")); // NOI18N popupKwListSearchOr.setName("popupKwListSearchOr"); // NOI18N jPopupMenuKeywordList.add(popupKwListSearchOr); popupKwListSearchAnd.setAction(actionMap.get("searchKeywordsFromListLogAnd")); // NOI18N popupKwListSearchAnd.setName("popupKwListSearchAnd"); // NOI18N jPopupMenuKeywordList.add(popupKwListSearchAnd); popupKwListSearchNot.setAction(actionMap.get("searchKeywordsFromListLogNot")); // NOI18N popupKwListSearchNot.setName("popupKwListSearchNot"); // NOI18N jPopupMenuKeywordList.add(popupKwListSearchNot); jSeparator13.setName("jSeparator13"); // NOI18N jPopupMenuKeywordList.add(jSeparator13); popupKwListHighlight.setAction(actionMap.get("highlightKeywords")); // NOI18N popupKwListHighlight.setName("popupKwListHighlight"); // NOI18N jPopupMenuKeywordList.add(popupKwListHighlight); popupKwListHighlightSegments.setAction(actionMap.get("highlightSegments")); // NOI18N popupKwListHighlightSegments.setName("popupKwListHighlightSegments"); // NOI18N jPopupMenuKeywordList.add(popupKwListHighlightSegments); popupKwListRefresh.setAction(actionMap.get("refreshFilteredLinks")); // NOI18N popupKwListRefresh.setName("popupKwListRefresh"); // NOI18N jPopupMenuKeywordList.add(popupKwListRefresh); jSeparator11.setName("jSeparator11"); // NOI18N jPopupMenuKeywordList.add(jSeparator11); popupKwListLogOr.setAction(actionMap.get("keywordListLogOr")); // NOI18N popupKwListLogOr.setSelected(true); popupKwListLogOr.setName("popupKwListLogOr"); // NOI18N jPopupMenuKeywordList.add(popupKwListLogOr); popupKwListLogAnd.setAction(actionMap.get("keywordListLogAnd")); // NOI18N popupKwListLogAnd.setSelected(true); popupKwListLogAnd.setName("popupKwListLogAnd"); // NOI18N jPopupMenuKeywordList.add(popupKwListLogAnd); jSeparator12.setName("jSeparator12"); // NOI18N jPopupMenuKeywordList.add(jSeparator12); popupKwListDelete.setAction(actionMap.get("deleteKeywordFromEntry")); // NOI18N popupKwListDelete.setName("popupKwListDelete"); // NOI18N jPopupMenuKeywordList.add(popupKwListDelete); jPopupMenuAuthors.setName("jPopupMenuAuthors"); // NOI18N popupAuthorsCopy.setAction(actionMap.get("copy")); popupAuthorsCopy.setName("popupAuthorsCopy"); // NOI18N jPopupMenuAuthors.add(popupAuthorsCopy); jSeparator14.setName("jSeparator14"); // NOI18N jPopupMenuAuthors.add(jSeparator14); popupAuthorsSearchLogOr.setAction(actionMap.get("searchLogOr")); // NOI18N popupAuthorsSearchLogOr.setName("popupAuthorsSearchLogOr"); // NOI18N jPopupMenuAuthors.add(popupAuthorsSearchLogOr); popupAuthorsSearchLogAnd.setAction(actionMap.get("searchLogAnd")); // NOI18N popupAuthorsSearchLogAnd.setName("popupAuthorsSearchLogAnd"); // NOI18N jPopupMenuAuthors.add(popupAuthorsSearchLogAnd); popupAuthorsSearchLogNot.setAction(actionMap.get("searchLogNot")); // NOI18N popupAuthorsSearchLogNot.setName("popupAuthorsSearchLogNot"); // NOI18N jPopupMenuAuthors.add(popupAuthorsSearchLogNot); jSeparator15.setName("jSeparator15"); // NOI18N jPopupMenuAuthors.add(jSeparator15); popupAuthorsNew.setAction(actionMap.get("newAuthor")); // NOI18N popupAuthorsNew.setName("popupAuthorsNew"); // NOI18N jPopupMenuAuthors.add(popupAuthorsNew); popupAuthorsEdit.setAction(actionMap.get("editAuthor")); // NOI18N popupAuthorsEdit.setName("popupAuthorsEdit"); // NOI18N jPopupMenuAuthors.add(popupAuthorsEdit); popupAuthorsDelete.setAction(actionMap.get("deleteAuthor")); // NOI18N popupAuthorsDelete.setName("popupAuthorsDelete"); // NOI18N jPopupMenuAuthors.add(popupAuthorsDelete); jSeparator91.setName("jSeparator91"); // NOI18N jPopupMenuAuthors.add(jSeparator91); popupAuthorsBibkey.setAction(actionMap.get("changeBibkey")); // NOI18N popupAuthorsBibkey.setName("popupAuthorsBibkey"); // NOI18N jPopupMenuAuthors.add(popupAuthorsBibkey); jSeparator16.setName("jSeparator16"); // NOI18N jPopupMenuAuthors.add(jSeparator16); popupAuthorsAddToEntry.setAction(actionMap.get("addAuthorToList")); // NOI18N popupAuthorsAddToEntry.setName("popupAuthorsAddToEntry"); // NOI18N jPopupMenuAuthors.add(popupAuthorsAddToEntry); jSeparator49.setName("jSeparator49"); // NOI18N jPopupMenuAuthors.add(jSeparator49); popupAuthorsSubAdd.setText(resourceMap.getString("popupAuthorsSubAdd.text")); // NOI18N popupAuthorsSubAdd.setName("popupAuthorsSubAdd"); // NOI18N popupAuthorsManLinks.setAction(actionMap.get("addManLinksLogOr")); // NOI18N popupAuthorsManLinks.setName("popupAuthorsManLinks"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsManLinks); popupAuthorsManLinksAnd.setAction(actionMap.get("addManLinksLogAnd")); // NOI18N popupAuthorsManLinksAnd.setName("popupAuthorsManLinksAnd"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsManLinksAnd); jSeparator70.setName("jSeparator70"); // NOI18N popupAuthorsSubAdd.add(jSeparator70); popupAuthorsLuhmann.setAction(actionMap.get("addLuhmannLogOr")); // NOI18N popupAuthorsLuhmann.setName("popupAuthorsLuhmann"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsLuhmann); popupAuthorsLuhmannAnd.setAction(actionMap.get("addLuhmannLogAnd")); // NOI18N popupAuthorsLuhmannAnd.setName("popupAuthorsLuhmannAnd"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsLuhmannAnd); jSeparator50.setName("jSeparator50"); // NOI18N popupAuthorsSubAdd.add(jSeparator50); popupAuthorsDesktop.setAction(actionMap.get("addDesktopLogOr")); // NOI18N popupAuthorsDesktop.setName("popupAuthorsDesktop"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsDesktop); popupAuthorsDesktopAnd.setAction(actionMap.get("addDesktopLogAnd")); // NOI18N popupAuthorsDesktopAnd.setName("popupAuthorsDesktopAnd"); // NOI18N popupAuthorsSubAdd.add(popupAuthorsDesktopAnd); jPopupMenuAuthors.add(popupAuthorsSubAdd); jSeparator96.setName("jSeparator96"); // NOI18N jPopupMenuAuthors.add(jSeparator96); popupAuthorsImport.setAction(actionMap.get("importAuthors")); // NOI18N popupAuthorsImport.setName("popupAuthorsImport"); // NOI18N jPopupMenuAuthors.add(popupAuthorsImport); jPopupMenuLuhmann.setName("jPopupMenuLuhmann"); // NOI18N popupLuhmannAdd.setAction(actionMap.get("manualInsertEntry")); // NOI18N popupLuhmannAdd.setName("popupLuhmannAdd"); // NOI18N jPopupMenuLuhmann.add(popupLuhmannAdd); jSeparator17.setName("jSeparator17"); // NOI18N jPopupMenuLuhmann.add(jSeparator17); popupLuhmannDelete.setAction(actionMap.get("deleteLuhmannFromEntry")); // NOI18N popupLuhmannDelete.setName("popupLuhmannDelete"); // NOI18N jPopupMenuLuhmann.add(popupLuhmannDelete); jSeparator60.setName("jSeparator60"); // NOI18N jPopupMenuLuhmann.add(jSeparator60); popupLuhmannManLinks.setAction(actionMap.get("addManLinks")); // NOI18N popupLuhmannManLinks.setName("popupLuhmannManLinks"); // NOI18N jPopupMenuLuhmann.add(popupLuhmannManLinks); popupLuhmannBookmarks.setAction(actionMap.get("addBookmarks")); // NOI18N popupLuhmannBookmarks.setName("popupLuhmannBookmarks"); // NOI18N jPopupMenuLuhmann.add(popupLuhmannBookmarks); jSeparator63.setName("jSeparator63"); // NOI18N jPopupMenuLuhmann.add(jSeparator63); popupLuhmannDesktop.setAction(actionMap.get("addDesktop")); // NOI18N popupLuhmannDesktop.setName("popupLuhmannDesktop"); // NOI18N jPopupMenuLuhmann.add(popupLuhmannDesktop); jPopupMenuTitles.setName("jPopupMenuTitles"); // NOI18N popupTitlesCopy.setAction(actionMap.get("copy")); popupTitlesCopy.setName("popupTitlesCopy"); // NOI18N jPopupMenuTitles.add(popupTitlesCopy); jSeparator20.setName("jSeparator20"); // NOI18N jPopupMenuTitles.add(jSeparator20); popupTitlesEdit.setAction(actionMap.get("editTitle")); // NOI18N popupTitlesEdit.setName("popupTitlesEdit"); // NOI18N jPopupMenuTitles.add(popupTitlesEdit); popupTitlesEditEntry.setAction(actionMap.get("editEntry")); // NOI18N popupTitlesEditEntry.setName("popupTitlesEditEntry"); // NOI18N jPopupMenuTitles.add(popupTitlesEditEntry); jSeparator103.setName("jSeparator103"); // NOI18N jPopupMenuTitles.add(jSeparator103); popupTitlesDelete.setAction(actionMap.get("deleteEntry")); // NOI18N popupTitlesDelete.setName("popupTitlesDelete"); // NOI18N jPopupMenuTitles.add(popupTitlesDelete); jSeparator114.setName("jSeparator114"); // NOI18N jPopupMenuTitles.add(jSeparator114); popupTitleMoveEntry.setAction(actionMap.get("moveEntry")); // NOI18N popupTitleMoveEntry.setName("popupTitleMoveEntry"); // NOI18N jPopupMenuTitles.add(popupTitleMoveEntry); jSeparator106.setName("jSeparator106"); // NOI18N jPopupMenuTitles.add(jSeparator106); popupTitlesAutomaticTitle.setAction(actionMap.get("automaticFirstLineAsTitle")); // NOI18N popupTitlesAutomaticTitle.setName("popupTitlesAutomaticTitle"); // NOI18N jPopupMenuTitles.add(popupTitlesAutomaticTitle); jSeparator21.setName("jSeparator21"); // NOI18N jPopupMenuTitles.add(jSeparator21); popupTitlesManLinks.setAction(actionMap.get("addManLinks")); // NOI18N popupTitlesManLinks.setName("popupTitlesManLinks"); // NOI18N jPopupMenuTitles.add(popupTitlesManLinks); popupTitlesLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N popupTitlesLuhmann.setName("popupTitlesLuhmann"); // NOI18N jPopupMenuTitles.add(popupTitlesLuhmann); popupTitlesBookmarks.setAction(actionMap.get("addBookmarks")); // NOI18N popupTitlesBookmarks.setName("popupTitlesBookmarks"); // NOI18N jPopupMenuTitles.add(popupTitlesBookmarks); jSeparator64.setName("jSeparator64"); // NOI18N jPopupMenuTitles.add(jSeparator64); popupTitlesDesktop.setAction(actionMap.get("addDesktop")); // NOI18N popupTitlesDesktop.setName("popupTitlesDesktop"); // NOI18N jPopupMenuTitles.add(popupTitlesDesktop); jPopupMenuBookmarks.setName("jPopupMenuBookmarks"); // NOI18N popupBookmarksEdit.setAction(actionMap.get("editBookmark")); // NOI18N popupBookmarksEdit.setName("popupBookmarksEdit"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksEdit); popupBookmarksDelete.setAction(actionMap.get("deleteBookmark")); // NOI18N popupBookmarksDelete.setName("popupBookmarksDelete"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksDelete); jSeparator36.setName("jSeparator36"); // NOI18N jPopupMenuBookmarks.add(jSeparator36); popupBookmarksEditCat.setAction(actionMap.get("editBookmarkCategory")); // NOI18N popupBookmarksEditCat.setName("popupBookmarksEditCat"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksEditCat); popupBookmarksDeleteCat.setAction(actionMap.get("deleteBookmarkCategory")); // NOI18N popupBookmarksDeleteCat.setName("popupBookmarksDeleteCat"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksDeleteCat); jSeparator38.setName("jSeparator38"); // NOI18N jPopupMenuBookmarks.add(jSeparator38); popupBookmarksAddManLinks.setAction(actionMap.get("addManLinks")); // NOI18N popupBookmarksAddManLinks.setName("popupBookmarksAddManLinks"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksAddManLinks); popupBookmarksAddLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N popupBookmarksAddLuhmann.setName("popupBookmarksAddLuhmann"); // NOI18N jPopupMenuBookmarks.add(popupBookmarksAddLuhmann); jSeparator56.setName("jSeparator56"); // NOI18N jPopupMenuBookmarks.add(jSeparator56); popupBookmarkAddDesktop.setAction(actionMap.get("addDesktop")); // NOI18N popupBookmarkAddDesktop.setName("popupBookmarkAddDesktop"); // NOI18N jPopupMenuBookmarks.add(popupBookmarkAddDesktop); jPopupMenuLinks.setName("jPopupMenuLinks"); // NOI18N popupLinksRefresh.setAction(actionMap.get("refreshFilteredLinks")); // NOI18N popupLinksRefresh.setName("popupLinksRefresh"); // NOI18N jPopupMenuLinks.add(popupLinksRefresh); jSeparator115.setName("jSeparator115"); // NOI18N jPopupMenuLinks.add(jSeparator115); popupLinkRemoveManLink.setAction(actionMap.get("deleteManualLink")); // NOI18N popupLinkRemoveManLink.setName("popupLinkRemoveManLink"); // NOI18N jPopupMenuLinks.add(popupLinkRemoveManLink); jSeparator54.setName("jSeparator54"); // NOI18N jPopupMenuLinks.add(jSeparator54); popupLinksManLinks.setAction(actionMap.get("addManLinks")); // NOI18N popupLinksManLinks.setName("popupLinksManLinks"); // NOI18N jPopupMenuLinks.add(popupLinksManLinks); popupLinksLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N popupLinksLuhmann.setName("popupLinksLuhmann"); // NOI18N jPopupMenuLinks.add(popupLinksLuhmann); jSeparator57.setName("jSeparator57"); // NOI18N jPopupMenuLinks.add(jSeparator57); popupLinksDesktop.setAction(actionMap.get("addDesktop")); // NOI18N popupLinksDesktop.setName("popupLinksDesktop"); // NOI18N jPopupMenuLinks.add(popupLinksDesktop); jPopupMenuAttachments.setName("jPopupMenuAttachments"); // NOI18N popupAttachmentsCopy.setAction(actionMap.get("copy")); popupAttachmentsCopy.setName("popupAttachmentsCopy"); // NOI18N jPopupMenuAttachments.add(popupAttachmentsCopy); jSeparator87.setName("jSeparator87"); // NOI18N jPopupMenuAttachments.add(jSeparator87); popupAttachmentsEdit.setAction(actionMap.get("editAttachment")); // NOI18N popupAttachmentsEdit.setName("popupAttachmentsEdit"); // NOI18N jPopupMenuAttachments.add(popupAttachmentsEdit); popupAttachmentsDelete.setAction(actionMap.get("deleteAttachment")); // NOI18N popupAttachmentsDelete.setName("popupAttachmentsDelete"); // NOI18N jPopupMenuAttachments.add(popupAttachmentsDelete); jSeparator94.setName("jSeparator94"); // NOI18N jPopupMenuAttachments.add(jSeparator94); popupAttachmentsGoto.setAction(actionMap.get("openAttachmentDirectory")); // NOI18N popupAttachmentsGoto.setName("popupAttachmentsGoto"); // NOI18N jPopupMenuAttachments.add(popupAttachmentsGoto); jSeparator86.setName("jSeparator86"); // NOI18N jPopupMenuAttachments.add(jSeparator86); popupAttachmentsExport.setAction(actionMap.get("exportAttachments")); // NOI18N popupAttachmentsExport.setName("popupAttachmentsExport"); // NOI18N jPopupMenuAttachments.add(popupAttachmentsExport); jPopupMenuMain.setName("jPopupMenuMain"); // NOI18N popupMainCopy.setAction(actionMap.get("copy")); popupMainCopy.setName("popupMainCopy"); // NOI18N jPopupMenuMain.add(popupMainCopy); popupMainCopyPlain.setAction(actionMap.get("copyPlain")); // NOI18N popupMainCopyPlain.setName("popupMainCopyPlain"); // NOI18N jPopupMenuMain.add(popupMainCopyPlain); jSeparator88.setName("jSeparator88"); // NOI18N jPopupMenuMain.add(jSeparator88); popupMainFind.setAction(actionMap.get("findFromSelection")); // NOI18N popupMainFind.setName("popupMainFind"); // NOI18N jPopupMenuMain.add(popupMainFind); jSeparator97.setName("jSeparator97"); // NOI18N jPopupMenuMain.add(jSeparator97); popupMainAddToKeyword.setAction(actionMap.get("addToKeywordList")); // NOI18N popupMainAddToKeyword.setName("popupMainAddToKeyword"); // NOI18N jPopupMenuMain.add(popupMainAddToKeyword); jSeparator98.setName("jSeparator98"); // NOI18N jPopupMenuMain.add(jSeparator98); popupMainSetFirstLineAsTitle.setAction(actionMap.get("setFirstLineAsTitle")); // NOI18N popupMainSetFirstLineAsTitle.setName("popupMainSetFirstLineAsTitle"); // NOI18N jPopupMenuMain.add(popupMainSetFirstLineAsTitle); popupMainSetSelectionAsTitle.setAction(actionMap.get("setSelectionAsTitle")); // NOI18N popupMainSetSelectionAsTitle.setName("popupMainSetSelectionAsTitle"); // NOI18N jPopupMenuMain.add(popupMainSetSelectionAsTitle); setComponent(mainPanel); setMenuBar(menuBar); setStatusBar(statusPanel); setToolBar(toolBar); }// </editor-fold>//GEN-END:initComponents /** * This event catches mouse-cicks which occur when the user clicks a hyperlink * in the main editor-pane. First has to be checked, wether the clicked hyperlink * was an web-url or links to a local file. Then the url or file will be opened * * @param evt */ /** * Enables and disables the menu items for the popupMenuKeywordList and viewMenuLinks */ private void initViewMenuLinks() { // check the user settings. when the filtering of links (jTableLinks) is set to logical-or, // select the appropriate item, else check the log-and-item if (settings.getLogKeywordlist().equalsIgnoreCase(Settings.SETTING_LOGKEYWORDLIST_OR)) { popupKwListLogOr.setSelected(true); popupKwListLogAnd.setSelected(false); viewMenuLinksKwListLogOr.setSelected(true); viewMenuLinksKwListLogAnd.setSelected(false); } else { popupKwListLogOr.setSelected(false); popupKwListLogAnd.setSelected(true); viewMenuLinksKwListLogOr.setSelected(false); viewMenuLinksKwListLogAnd.setSelected(true); } // set indicator which show whether we have selections or not setListFilledWithEntry(jListEntryKeywords.getSelectedValues().length > 0); setExportPossible(jTableLinks.getRowCount() > 0 || jTableManLinks.getRowCount() > 0); setTableEntriesSelected( (jTableLinks.getSelectedRowCount() > 0) || (jTableManLinks.getSelectedRowCount() > 0)); // show refresh links only when link-list (jTableLinks) are visible popupKwListRefresh.setEnabled(TAB_LINKS == jTabbedPaneMain.getSelectedIndex()); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenu aboutMenu; private javax.swing.JMenuItem aboutMenuItem; private javax.swing.JMenuItem addFirstLineToTitleMenuItem; private javax.swing.JMenuItem addSelectionToKeywordMenuItem; private javax.swing.JMenuItem addSelectionToTitleMenuItem; private javax.swing.JMenuItem addToDesktopMenuItem; private javax.swing.JButton buttonHistoryBack; private javax.swing.JButton buttonHistoryFore; private javax.swing.JMenuItem copyMenuItem; private javax.swing.JMenuItem copyPlainMenuItem; private javax.swing.JMenuItem deleteKwFromListMenuItem; private javax.swing.JMenuItem deleteZettelMenuItem; private javax.swing.JMenuItem duplicateEntryMenuItem; private javax.swing.JMenu editMenu; private javax.swing.JMenuItem editMenuItem; private javax.swing.JMenuItem exitMenuItem; private javax.swing.JMenuItem exportMenuItem; private javax.swing.JMenu fileMenu; private javax.swing.JMenuItem findDoubleEntriesItem; private javax.swing.JMenuItem findEntriesFromCreatedTimestamp; private javax.swing.JMenuItem findEntriesFromEditedTimestamp; private javax.swing.JMenuItem findEntriesWithAttachments; private javax.swing.JMenuItem findEntriesWithRatings; private javax.swing.JMenuItem findEntriesWithRemarks; private javax.swing.JMenuItem findEntriesWithoutAuthors; private javax.swing.JMenuItem findEntriesWithoutKeywords; private javax.swing.JMenuItem findEntriesWithoutRatings; private javax.swing.JMenuItem findEntriesWithoutRemarks; private javax.swing.JMenu findEntryKeywordsMenu; private javax.swing.JMenu findEntryWithout; private javax.swing.JMenu findMenu; private javax.swing.JMenuItem findMenuItem; private javax.swing.JMenuItem findReplaceMenuItem; private javax.swing.JMenuItem gotoEntryMenuItem; private javax.swing.JCheckBoxMenuItem highlightSegmentsMenuItem; private javax.swing.JMenuItem historyForMenuItem; private javax.swing.JMenuItem histroyBackMenuItem; private javax.swing.JMenuItem homeMenuItem; private javax.swing.JMenuItem importMenuItem; private javax.swing.JMenuItem insertEntryAtMenuItem; private javax.swing.JMenuItem insertEntryMenuItem; private javax.swing.JButton jButton1; private javax.swing.JButton jButtonRefreshAttachments; private javax.swing.JButton jButtonRefreshAuthors; private javax.swing.JButton jButtonRefreshCluster; private javax.swing.JButton jButtonRefreshKeywords; private javax.swing.JButton jButtonRefreshTitles; private javax.swing.JCheckBox jCheckBoxCluster; private javax.swing.JCheckBox jCheckBoxShowSynonyms; private javax.swing.JComboBox jComboBoxAuthorType; private javax.swing.JComboBox jComboBoxBookmarkCategory; private javax.swing.JEditorPane jEditorPaneBookmarkComment; private javax.swing.JEditorPane jEditorPaneClusterEntries; private javax.swing.JEditorPane jEditorPaneDispAuthor; private javax.swing.JEditorPane jEditorPaneEntry; private javax.swing.JEditorPane jEditorPaneIsFollower; private javax.swing.JLabel jLabelMemory; private javax.swing.JList jListEntryKeywords; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel10; private javax.swing.JPanel jPanel11; private javax.swing.JPanel jPanel12; private javax.swing.JPanel jPanel13; private javax.swing.JPanel jPanel14; private javax.swing.JPanel jPanel15; private javax.swing.JPanel jPanel16; private javax.swing.JPanel jPanel17; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel7; private javax.swing.JPanel jPanel8; private javax.swing.JPanel jPanel9; private javax.swing.JPanel jPanelDispAuthor; private javax.swing.JPanel jPanelLiveSearch; private javax.swing.JPanel jPanelMainRight; private javax.swing.JPanel jPanelManLinks; private javax.swing.JPopupMenu jPopupMenuAttachments; private javax.swing.JPopupMenu jPopupMenuAuthors; private javax.swing.JPopupMenu jPopupMenuBookmarks; private javax.swing.JPopupMenu jPopupMenuKeywordList; private javax.swing.JPopupMenu jPopupMenuKeywords; private javax.swing.JPopupMenu jPopupMenuLinks; private javax.swing.JPopupMenu jPopupMenuLuhmann; private javax.swing.JPopupMenu jPopupMenuMain; private javax.swing.JPopupMenu jPopupMenuTitles; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane10; private javax.swing.JScrollPane jScrollPane11; private javax.swing.JScrollPane jScrollPane13; private javax.swing.JScrollPane jScrollPane14; private javax.swing.JScrollPane jScrollPane15; private javax.swing.JScrollPane jScrollPane16; private javax.swing.JScrollPane jScrollPane17; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JScrollPane jScrollPane5; private javax.swing.JScrollPane jScrollPane6; private javax.swing.JScrollPane jScrollPane7; private javax.swing.JScrollPane jScrollPane8; private javax.swing.JScrollPane jScrollPane9; private javax.swing.JSeparator jSeparator1; private javax.swing.JToolBar.Separator jSeparator10; private javax.swing.JSeparator jSeparator100; private javax.swing.JSeparator jSeparator102; private javax.swing.JSeparator jSeparator103; private javax.swing.JSeparator jSeparator104; private javax.swing.JSeparator jSeparator105; private javax.swing.JSeparator jSeparator106; private javax.swing.JSeparator jSeparator107; private javax.swing.JPopupMenu.Separator jSeparator108; private javax.swing.JSeparator jSeparator109; private javax.swing.JSeparator jSeparator11; private javax.swing.JSeparator jSeparator110; private javax.swing.JPopupMenu.Separator jSeparator111; private javax.swing.JPopupMenu.Separator jSeparator112; private javax.swing.JPopupMenu.Separator jSeparator113; private javax.swing.JPopupMenu.Separator jSeparator114; private javax.swing.JPopupMenu.Separator jSeparator115; private javax.swing.JPopupMenu.Separator jSeparator116; private javax.swing.JPopupMenu.Separator jSeparator117; private javax.swing.JPopupMenu.Separator jSeparator118; private javax.swing.JSeparator jSeparator12; private javax.swing.JSeparator jSeparator13; private javax.swing.JSeparator jSeparator14; private javax.swing.JSeparator jSeparator15; private javax.swing.JSeparator 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.JSeparator jSeparator23; private javax.swing.JSeparator jSeparator24; private javax.swing.JSeparator jSeparator25; private javax.swing.JSeparator jSeparator26; private javax.swing.JSeparator jSeparator27; private javax.swing.JSeparator jSeparator28; private javax.swing.JSeparator jSeparator29; private javax.swing.JSeparator jSeparator3; private javax.swing.JSeparator jSeparator30; private javax.swing.JSeparator jSeparator31; private javax.swing.JToolBar.Separator jSeparator32; private javax.swing.JSeparator jSeparator33; private javax.swing.JPopupMenu.Separator jSeparator34; private javax.swing.JSeparator jSeparator35; private javax.swing.JSeparator jSeparator36; private javax.swing.JSeparator jSeparator37; private javax.swing.JSeparator jSeparator38; private javax.swing.JSeparator jSeparator39; private javax.swing.JToolBar.Separator jSeparator4; private javax.swing.JSeparator jSeparator40; private javax.swing.JSeparator jSeparator41; private javax.swing.JSeparator jSeparator42; private javax.swing.JSeparator jSeparator43; private javax.swing.JSeparator jSeparator44; private javax.swing.JSeparator jSeparator45; private javax.swing.JSeparator jSeparator46; private javax.swing.JSeparator jSeparator47; private javax.swing.JSeparator jSeparator48; private javax.swing.JSeparator jSeparator49; private javax.swing.JToolBar.Separator jSeparator5; private javax.swing.JSeparator jSeparator50; private javax.swing.JSeparator jSeparator51; private javax.swing.JSeparator jSeparator52; private javax.swing.JSeparator jSeparator53; private javax.swing.JSeparator jSeparator54; private javax.swing.JSeparator jSeparator55; private javax.swing.JSeparator jSeparator56; private javax.swing.JSeparator jSeparator57; private javax.swing.JSeparator jSeparator58; private javax.swing.JSeparator jSeparator59; private javax.swing.JSeparator jSeparator6; private javax.swing.JSeparator jSeparator60; private javax.swing.JSeparator jSeparator61; private javax.swing.JSeparator jSeparator62; private javax.swing.JSeparator jSeparator63; private javax.swing.JSeparator jSeparator64; private javax.swing.JSeparator jSeparator65; private javax.swing.JSeparator jSeparator66; private javax.swing.JSeparator jSeparator67; private javax.swing.JSeparator jSeparator68; private javax.swing.JSeparator jSeparator69; private javax.swing.JSeparator jSeparator7; private javax.swing.JSeparator jSeparator70; private javax.swing.JSeparator jSeparator71; private javax.swing.JPopupMenu.Separator jSeparator72; private javax.swing.JSeparator jSeparator75; private javax.swing.JSeparator jSeparator76; private javax.swing.JSeparator jSeparator77; private javax.swing.JSeparator jSeparator78; private javax.swing.JSeparator jSeparator79; private javax.swing.JSeparator jSeparator8; private javax.swing.JSeparator jSeparator80; private javax.swing.JSeparator jSeparator81; private javax.swing.JSeparator jSeparator82; private javax.swing.JSeparator jSeparator83; private javax.swing.JSeparator jSeparator84; private javax.swing.JSeparator jSeparator85; private javax.swing.JSeparator jSeparator86; private javax.swing.JSeparator jSeparator87; private javax.swing.JSeparator jSeparator88; private javax.swing.JSeparator jSeparator89; private javax.swing.JSeparator jSeparator9; private javax.swing.JSeparator jSeparator90; private javax.swing.JSeparator jSeparator91; private javax.swing.JSeparator jSeparator92; private javax.swing.JSeparator jSeparator93; private javax.swing.JSeparator jSeparator94; private javax.swing.JSeparator jSeparator95; private javax.swing.JSeparator jSeparator96; private javax.swing.JSeparator jSeparator97; private javax.swing.JSeparator jSeparator98; private javax.swing.JSeparator jSeparator99; private javax.swing.JSeparator jSeparatorAbout1; private javax.swing.JSeparator jSeparatorExit; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JSplitPane jSplitPane2; private javax.swing.JSplitPane jSplitPane3; private javax.swing.JSplitPane jSplitPaneAuthors; private javax.swing.JSplitPane jSplitPaneLinks; private javax.swing.JSplitPane jSplitPaneMain1; private javax.swing.JSplitPane jSplitPaneMain2; private javax.swing.JTabbedPane jTabbedPaneMain; private javax.swing.JTable jTableAttachments; private javax.swing.JTable jTableAuthors; private javax.swing.JTable jTableBookmarks; private javax.swing.JTable jTableKeywords; private javax.swing.JTable jTableLinks; private javax.swing.JTable jTableManLinks; private javax.swing.JTable jTableTitles; private javax.swing.JTextField jTextFieldEntryNumber; private javax.swing.JTextField jTextFieldFilterAttachments; private javax.swing.JTextField jTextFieldFilterAuthors; private javax.swing.JTextField jTextFieldFilterCluster; private javax.swing.JTextField jTextFieldFilterKeywords; private javax.swing.JTextField jTextFieldFilterTitles; private javax.swing.JTextField jTextFieldLiveSearch; private javax.swing.JTree jTreeCluster; private javax.swing.JTree jTreeKeywords; private javax.swing.JTree jTreeLuhmann; private javax.swing.JMenuItem lastEntryMenuItem; private javax.swing.JMenuItem liveSearchMenuItem; private javax.swing.JPanel mainPanel; private javax.swing.JMenuItem manualInsertLinksMenuItem; private javax.swing.JMenuItem manualInsertMenuItem; private javax.swing.JMenuBar menuBar; private javax.swing.JMenuItem menuFileInformation; private javax.swing.JMenuItem menuKwListSearchAnd; private javax.swing.JMenuItem menuKwListSearchNot; private javax.swing.JMenuItem menuKwListSearchOr; private javax.swing.JMenuItem newDesktopMenuItem; private javax.swing.JMenuItem newEntryMenuItem; private javax.swing.JMenuItem newZettelkastenMenuItem; private javax.swing.JMenuItem nextEntryMenuItem; private javax.swing.JMenuItem openMenuItem; private javax.swing.JMenuItem pasteMenuItem; private javax.swing.JMenuItem popupAttachmentsCopy; private javax.swing.JMenuItem popupAttachmentsDelete; private javax.swing.JMenuItem popupAttachmentsEdit; private javax.swing.JMenuItem popupAttachmentsExport; private javax.swing.JMenuItem popupAttachmentsGoto; private javax.swing.JMenuItem popupAuthorsAddToEntry; private javax.swing.JMenuItem popupAuthorsBibkey; private javax.swing.JMenuItem popupAuthorsCopy; private javax.swing.JMenuItem popupAuthorsDelete; private javax.swing.JMenuItem popupAuthorsDesktop; private javax.swing.JMenuItem popupAuthorsDesktopAnd; private javax.swing.JMenuItem popupAuthorsEdit; private javax.swing.JMenuItem popupAuthorsImport; private javax.swing.JMenuItem popupAuthorsLuhmann; private javax.swing.JMenuItem popupAuthorsLuhmannAnd; private javax.swing.JMenuItem popupAuthorsManLinks; private javax.swing.JMenuItem popupAuthorsManLinksAnd; private javax.swing.JMenuItem popupAuthorsNew; private javax.swing.JMenuItem popupAuthorsSearchLogAnd; private javax.swing.JMenuItem popupAuthorsSearchLogNot; private javax.swing.JMenuItem popupAuthorsSearchLogOr; private javax.swing.JMenu popupAuthorsSubAdd; private javax.swing.JMenuItem popupBookmarkAddDesktop; private javax.swing.JMenuItem popupBookmarksAddLuhmann; private javax.swing.JMenuItem popupBookmarksAddManLinks; private javax.swing.JMenuItem popupBookmarksDelete; private javax.swing.JMenuItem popupBookmarksDeleteCat; private javax.swing.JMenuItem popupBookmarksEdit; private javax.swing.JMenuItem popupBookmarksEditCat; private javax.swing.JMenuItem popupKeywordsAddToList; private javax.swing.JMenuItem popupKeywordsCopy; private javax.swing.JMenuItem popupKeywordsDelete; private javax.swing.JMenuItem popupKeywordsDesktop; private javax.swing.JMenuItem popupKeywordsDesktopAnd; private javax.swing.JMenuItem popupKeywordsEdit; private javax.swing.JMenuItem popupKeywordsLuhmann; private javax.swing.JMenuItem popupKeywordsLuhmannAnd; private javax.swing.JMenuItem popupKeywordsManLinks; private javax.swing.JMenuItem popupKeywordsManLinksAnd; private javax.swing.JMenuItem popupKeywordsNew; private javax.swing.JMenuItem popupKeywordsSearchAnd; private javax.swing.JMenuItem popupKeywordsSearchNot; private javax.swing.JMenuItem popupKeywordsSearchOr; private javax.swing.JMenuItem popupKwListCopy; private javax.swing.JMenuItem popupKwListDelete; private javax.swing.JMenuItem popupKwListHighlight; private javax.swing.JCheckBoxMenuItem popupKwListHighlightSegments; private javax.swing.JCheckBoxMenuItem popupKwListLogAnd; private javax.swing.JCheckBoxMenuItem popupKwListLogOr; private javax.swing.JMenuItem popupKwListRefresh; private javax.swing.JMenuItem popupKwListSearchAnd; private javax.swing.JMenuItem popupKwListSearchNot; private javax.swing.JMenuItem popupKwListSearchOr; private javax.swing.JMenuItem popupLinkRemoveManLink; private javax.swing.JMenuItem popupLinksDesktop; private javax.swing.JMenuItem popupLinksLuhmann; private javax.swing.JMenuItem popupLinksManLinks; private javax.swing.JMenuItem popupLinksRefresh; private javax.swing.JMenuItem popupLuhmannAdd; private javax.swing.JMenuItem popupLuhmannBookmarks; private javax.swing.JMenuItem popupLuhmannDelete; private javax.swing.JMenuItem popupLuhmannDesktop; private javax.swing.JMenuItem popupLuhmannManLinks; private javax.swing.JMenuItem popupMainAddToKeyword; private javax.swing.JMenuItem popupMainCopy; private javax.swing.JMenuItem popupMainCopyPlain; private javax.swing.JMenuItem popupMainFind; private javax.swing.JMenuItem popupMainSetFirstLineAsTitle; private javax.swing.JMenuItem popupMainSetSelectionAsTitle; private javax.swing.JMenuItem popupTitleMoveEntry; private javax.swing.JMenuItem popupTitlesAutomaticTitle; private javax.swing.JMenuItem popupTitlesBookmarks; private javax.swing.JMenuItem popupTitlesCopy; private javax.swing.JMenuItem popupTitlesDelete; private javax.swing.JMenuItem popupTitlesDesktop; private javax.swing.JMenuItem popupTitlesEdit; private javax.swing.JMenuItem popupTitlesEditEntry; private javax.swing.JMenuItem popupTitlesLuhmann; private javax.swing.JMenuItem popupTitlesManLinks; private javax.swing.JMenuItem preferencesMenuItem; private javax.swing.JMenuItem prevEntryMenuItem; private javax.swing.JMenuItem quickNewEntryMenuItem; private javax.swing.JMenuItem quickNewTitleEntryMenuItem; private javax.swing.JMenuItem randomEntryMenuItem; private javax.swing.JMenuItem recentDoc1; private javax.swing.JMenuItem recentDoc2; private javax.swing.JMenuItem recentDoc3; private javax.swing.JMenuItem recentDoc4; private javax.swing.JMenuItem recentDoc5; private javax.swing.JMenuItem recentDoc6; private javax.swing.JMenuItem recentDoc7; private javax.swing.JMenuItem recentDoc8; private javax.swing.JMenu recentDocsSubMenu; private javax.swing.JMenuItem saveAsMenuItem; private javax.swing.JMenuItem saveMenuItem; private javax.swing.JMenuItem selectAllMenuItem; private javax.swing.JMenuItem setBookmarkMenuItem; private javax.swing.JMenuItem showAttachmentsMenuItem; private javax.swing.JMenuItem showAuthorsMenuItem; private javax.swing.JMenuItem showBookmarksMenuItem; private javax.swing.JMenuItem showClusterMenuItem; private javax.swing.JMenuItem showCurrentEntryAgain; private javax.swing.JMenuItem showDesktopMenuItem; private javax.swing.JMenuItem showErrorLogMenuItem; private javax.swing.JCheckBoxMenuItem showHighlightKeywords; private javax.swing.JMenuItem showKeywordsMenuItem; private javax.swing.JMenuItem showLinksMenuItem; private javax.swing.JMenuItem showLuhmannMenuItem; private javax.swing.JMenuItem showNewEntryMenuItem; private javax.swing.JMenuItem showSearchResultsMenuItem; private javax.swing.JMenuItem showTitlesMenuItem; private javax.swing.JLabel statusAnimationLabel; private javax.swing.JButton statusDesktopEntryButton; private javax.swing.JLabel statusEntryLabel; private javax.swing.JButton statusErrorButton; private javax.swing.JLabel statusMsgLabel; private javax.swing.JLabel statusOfEntryLabel; private javax.swing.JPanel statusPanel; private javax.swing.JButton tb_addbookmark; private javax.swing.JButton tb_addluhmann; private javax.swing.JButton tb_addmanlinks; private javax.swing.JButton tb_addtodesktop; private javax.swing.JButton tb_copy; private javax.swing.JButton tb_delete; private javax.swing.JButton tb_edit; private javax.swing.JButton tb_find; private javax.swing.JButton tb_first; private javax.swing.JButton tb_last; private javax.swing.JButton tb_newEntry; private javax.swing.JButton tb_next; private javax.swing.JButton tb_open; private javax.swing.JButton tb_paste; private javax.swing.JButton tb_prev; private javax.swing.JButton tb_save; private javax.swing.JButton tb_selectall; private javax.swing.JToolBar toolBar; private javax.swing.JMenuItem viewAttachmentEdit; private javax.swing.JMenuItem viewAttachmentsCopy; private javax.swing.JMenuItem viewAttachmentsDelete; private javax.swing.JMenuItem viewAttachmentsExport; private javax.swing.JMenuItem viewAuthorsAddLuhmann; private javax.swing.JMenuItem viewAuthorsAddLuhmannAnd; private javax.swing.JMenuItem viewAuthorsAddToEntry; private javax.swing.JMenuItem viewAuthorsAttachBibtexFile; private javax.swing.JMenuItem viewAuthorsBibkey; private javax.swing.JMenuItem viewAuthorsCopy; private javax.swing.JMenuItem viewAuthorsDelete; private javax.swing.JMenuItem viewAuthorsDesktop; private javax.swing.JMenuItem viewAuthorsDesktopAnd; private javax.swing.JMenuItem viewAuthorsEdit; private javax.swing.JMenuItem viewAuthorsExport; private javax.swing.JMenuItem viewAuthorsImport; private javax.swing.JMenuItem viewAuthorsManLinks; private javax.swing.JMenuItem viewAuthorsManLinksAnd; private javax.swing.JMenuItem viewAuthorsNew; private javax.swing.JMenuItem viewAuthorsRefreshBibtexFile; private javax.swing.JMenuItem viewAuthorsSearchAnd; private javax.swing.JMenuItem viewAuthorsSearchNot; private javax.swing.JMenuItem viewAuthorsSearchOr; private javax.swing.JMenu viewAuthorsSubAdd; private javax.swing.JMenu viewAuthorsSubEdit; private javax.swing.JMenu viewAuthorsSubFind; private javax.swing.JMenuItem viewBookmarkDesktop; private javax.swing.JMenuItem viewBookmarksAddLuhmann; private javax.swing.JMenuItem viewBookmarksDelete; private javax.swing.JMenuItem viewBookmarksDeleteCat; private javax.swing.JMenuItem viewBookmarksEdit; private javax.swing.JMenuItem viewBookmarksEditCat; private javax.swing.JMenuItem viewBookmarksExport; private javax.swing.JMenuItem viewBookmarksExportSearch; private javax.swing.JMenuItem viewBookmarksManLink; private javax.swing.JMenuItem viewClusterExport; private javax.swing.JMenuItem viewClusterExportToSearch; private javax.swing.JMenuItem viewKeywordsAddToList; private javax.swing.JMenuItem viewKeywordsCopy; private javax.swing.JMenuItem viewKeywordsDelete; private javax.swing.JMenuItem viewKeywordsDesktop; private javax.swing.JMenuItem viewKeywordsDesktopAnd; private javax.swing.JMenuItem viewKeywordsEdit; private javax.swing.JMenuItem viewKeywordsExport; private javax.swing.JMenuItem viewKeywordsLuhmann; private javax.swing.JMenuItem viewKeywordsLuhmannAnd; private javax.swing.JMenuItem viewKeywordsManLinks; private javax.swing.JMenuItem viewKeywordsManLinksAnd; private javax.swing.JMenuItem viewKeywordsNew; private javax.swing.JMenuItem viewKeywordsSearchAnd; private javax.swing.JMenuItem viewKeywordsSearchNot; private javax.swing.JMenuItem viewKeywordsSearchOr; private javax.swing.JMenu viewMenu; private javax.swing.JMenuItem viewMenuAttachmentGoto; private javax.swing.JMenu viewMenuAttachments; private javax.swing.JMenu viewMenuAuthors; private javax.swing.JMenu viewMenuBookmarks; private javax.swing.JMenu viewMenuCluster; private javax.swing.JMenuItem viewMenuExportToSearch; private javax.swing.JMenu viewMenuKeywords; private javax.swing.JMenu viewMenuLinks; private javax.swing.JMenuItem viewMenuLinksDesktop; private javax.swing.JMenuItem viewMenuLinksExport; private javax.swing.JCheckBoxMenuItem viewMenuLinksKwListLogAnd; private javax.swing.JCheckBoxMenuItem viewMenuLinksKwListLogOr; private javax.swing.JMenuItem viewMenuLinksKwListRefresh; private javax.swing.JMenuItem viewMenuLinksLuhmann; private javax.swing.JMenuItem viewMenuLinksManLink; private javax.swing.JMenuItem viewMenuLinksRemoveManLink; private javax.swing.JMenu viewMenuLuhmann; private javax.swing.JMenuItem viewMenuLuhmannBookmarks; private javax.swing.JMenuItem viewMenuLuhmannDelete; private javax.swing.JMenuItem viewMenuLuhmannDesktop; private javax.swing.JMenuItem viewMenuLuhmannExport; private javax.swing.JMenuItem viewMenuLuhmannExportSearch; private javax.swing.JMenuItem viewMenuLuhmannManLinks; private javax.swing.JCheckBoxMenuItem viewMenuLuhmannShowNumbers; private javax.swing.JMenuItem viewMenuLuhmannSortEntries; private javax.swing.JMenu viewMenuTitles; private javax.swing.JMenuItem viewTitlesAutomaticFirstLine; private javax.swing.JMenuItem viewTitlesBookmarks; private javax.swing.JMenuItem viewTitlesCopy; private javax.swing.JMenuItem viewTitlesDelete; private javax.swing.JMenuItem viewTitlesDesktop; private javax.swing.JMenuItem viewTitlesEdit; private javax.swing.JMenuItem viewTitlesExport; private javax.swing.JMenuItem viewTitlesLuhmann; private javax.swing.JMenuItem viewTitlesManLinks; private javax.swing.JMenuItem viewTitlesMoveEntry; private javax.swing.JMenu windowsMenu; // End of variables declaration//GEN-END:variables private javax.swing.JTextField tb_searchTextfield; private javax.swing.JPanel jPanelSearchBox; private javax.swing.JLabel jLabelLupe; private TaskProgressDialog taskDlg; private NewEntryFrame newEntryDlg; private CImport importWindow; private CUpdateInfoBox updateInfoDlg; private CExport exportWindow; private CBiggerEditField biggerEditDlg; private SearchResultsFrame searchResultsDlg; private CSearchDlg searchDlg; private CReplaceDialog replaceDlg; private DesktopFrame desktopDlg; private CSettingsDlg settingsDlg; private CNewBookmark newBookmarkDlg; private CErrorLog errorDlg; private CInformation informationDlg; private CExportEntries exportEntriesDlg; private CImportBibTex importBibTexDlg; private CShowMultipleDesktopOccurences multipleOccurencesDlg; private CSetBibKey setBibKeyDlg; private AboutBox zknAboutBox; private FindDoubleEntriesTask doubleEntriesDlg; private CRateEntry rateEntryDlg; }