/* * Zettelkasten - nach Luhmann * Copyright (C) 2001-2015 by Daniel Lüdecke (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 können es unter den Bedingungen der GNU * General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben * und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (wenn Sie möchten) * jeder späteren Version. * * Die Veröffentlichung 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 FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der * GNU General Public License. * * Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm * erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>. */ package de.danielluedecke.zettelkasten; import de.danielluedecke.zettelkasten.database.Bookmarks; import de.danielluedecke.zettelkasten.database.Settings; import de.danielluedecke.zettelkasten.util.ColorUtil; import de.danielluedecke.zettelkasten.util.Constants; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.jdesktop.application.Action; /** * * @author danielludecke */ public class CNewBookmark extends javax.swing.JDialog { /** * Reference to the bookmarks-class */ private final Bookmarks bookmarksObj; /** * Indicates whether the dialog was cancelled or not */ private boolean cancelled = false; private final int[] entrynumbers; private final boolean editbookmark; /** * get the strings for file descriptions from the resource map */ private final org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class). getContext().getResourceMap(CNewBookmark.class); /** * * @param parent * @param bm * @param nrs * @param edit * @param settingsObj */ public CNewBookmark(java.awt.Frame parent, Bookmarks bm, int[] nrs, boolean edit, Settings settingsObj) { super(parent); initComponents(); // set application icon setIconImage(Constants.zknicon.getImage()); bookmarksObj = bm; entrynumbers = nrs; editbookmark = edit; // init combobox with all existing categories initComboBox(); initListeners(); initBorders(settingsObj); if (settingsObj.isSeaGlass()) { setupSeaGlassStyle(); } // when the user wants to edit a bookmark, init fields if (editbookmark) { // get the bookmark // when changing a bookmark, we assume that we only have one bookmark int pos = bookmarksObj.getBookmarkPosition(entrynumbers[0]); // get category name String catname = bookmarksObj.getBookmarkCategoryAsString(pos); // and select it, if available if (catname != null) { jComboBoxCats.setSelectedItem(catname); } // get the comment String comment = bookmarksObj.getComment(pos); // replace br-tags with newlines comment = comment.replace("[br]", System.lineSeparator()); // and set text to textfield jTextAreaComment.setText(comment); // change title setTitle(resourceMap.getString("frametitleEdit")); // finally, reset modified state setModified(false); } } private void setupSeaGlassStyle() { jButtonApply.putClientProperty("JComponent.sizeVariant", "small"); jButtonCancel.putClientProperty("JComponent.sizeVariant", "small"); jButtonAddCat.putClientProperty("JComponent.sizeVariant", "small"); } private void initBorders(Settings settingsObj) { /* * Constructor for Matte Border * public MatteBorder(int top, int left, int bottom, int right, Color matteColor) */ jScrollPane1.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, ColorUtil.getBorderGray(settingsObj))); } private void initListeners() { // these codelines add an escape-listener to the dialog. so, when the user // presses the escape-key, the same action is performed as if the user // presses the cancel button... KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); ActionListener cancelAction = new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { cancelWindow(); } }; getRootPane().registerKeyboardAction(cancelAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); // if the document is ever edited, assume that it needs to be saved // so we add some document listeners here jTextFieldNewCat.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) { changeUpdateState(); } @Override public void insertUpdate(DocumentEvent e) { changeUpdateState(); } @Override public void removeUpdate(DocumentEvent e) { changeUpdateState(); } }); // if the document is ever edited, assume that it needs to be saved // so we add some document listeners here jTextAreaComment.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) { changeModifiedState(); } @Override public void insertUpdate(DocumentEvent e) { changeModifiedState(); } @Override public void removeUpdate(DocumentEvent e) { changeModifiedState(); } }); jTextFieldNewCat.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyReleased(java.awt.event.KeyEvent evt) { if (KeyEvent.VK_ENTER == evt.getKeyCode()) { addCat(); } } }); } /** * This method checks whether we have changes to the textfield. if so, and * we have text (i.e. textfield is not empty), enable the button (action). */ private void changeUpdateState() { setTextUpdated(!jTextFieldNewCat.getText().isEmpty()); } /** * This method indicates whether we have changes that the user can apply. * when no category is selected, the apply-button should not be * activated/enabled. */ private void changeModifiedState() { setModified(jComboBoxCats.getSelectedIndex() != -1); } /** * Inits or updates the combobox with all available bookmark-categories. * when a new category is added, it is selected and the modified state is * changed so the apply-button becomes enabled. */ private void initComboBox() { // clear combobox jComboBoxCats.removeAllItems(); // get sorted categories String[] cats = bookmarksObj.getSortedCategories(); // if we have any categories, go on... if ((cats != null) && (cats.length > 0)) { for (String cat : cats) { jComboBoxCats.addItem(cat); } } // add action listener to combo box jComboBoxCats.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(ActionEvent evt) { setModified(true); } }); // select first item if (jComboBoxCats.getItemCount() > 0) { jComboBoxCats.setSelectedIndex(0); } } /** * When the user presses the cancel button, no update needed, close window */ @Action public void cancelWindow() { cancelled = true; closeWindow(); } /** * Occurs when the user closes the window or presses the ok button. the * settings-file is then saved and the window disposed. */ private void closeWindow() { dispose(); setVisible(false); } /** * This method adds a new category to the bookmark-categories. the * category-description is retrieved from the textfield. */ @Action(enabledProperty = "textUpdated") public void addCat() { // get text String text = jTextFieldNewCat.getText(); // check whether category already exists if (-1 == bookmarksObj.getCategoryPosition(text)) { // if not, add it to bookmark-data bookmarksObj.addCategory(text); // and update combobox initComboBox(); // select the new created value jComboBoxCats.setSelectedItem(text); // reset textfield jTextFieldNewCat.setText(""); } else { // category-name already existed, so desktop was not added... JOptionPane.showMessageDialog(null, resourceMap.getString("errCatExistsMsg"), resourceMap.getString("errCatExistsTitle"), JOptionPane.PLAIN_MESSAGE); } } /** * This method applies the changes made from the user. then, if we have * edited a bookmark, its changes are saved. if we have a new bookmark, it * is added to the bookmark-data-file. */ @Action(enabledProperty = "modified") public void applyChanges() { // get the comment-text String comment = jTextAreaComment.getText(); // and re-convert all new lines to br's. this is necessary for converting // them into <br>'s because the entry is displayed as html-content. simple // new lines without "<br>" command would not be shown as new lines // // but first, we habe to remove all carriage-returns (\r), which are part of the // line-seperator in windows. somehow, the replace-command does *not* work, when // we replace "System.lineSeparator()" 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 (System.lineSeparator().contains("\r")) { comment = comment.replace("\r", ""); } comment = comment.replace("\n", "[br]"); // get the category String cat = jComboBoxCats.getSelectedItem().toString(); // add or change bookmark if (editbookmark) { // when changing a bookmark, we assume that we only have one bookmark bookmarksObj.changeBookmark(entrynumbers[0], cat, comment); } else { // whenn adding bookmarks, one or more bookmarks might be passed as parameter, // e.g. if we get several entries from the search results window... for (int bm : entrynumbers) { bookmarksObj.addBookmark(bm, cat, comment); } } // finally, close window closeWindow(); } /** * This variable indicates whether the displayed entry is already * bookmarked, so we can en- or disable the bookmark-action. */ private boolean textUpdated = false; public boolean isTextUpdated() { return textUpdated; } public void setTextUpdated(boolean b) { boolean old = isTextUpdated(); this.textUpdated = b; firePropertyChange("textUpdated", old, isTextUpdated()); } /** * This variable indicates whether changes have been made that should be * saved.... */ private boolean modified = false; public boolean isModified() { return modified; } public final void setModified(boolean b) { boolean old = isModified(); this.modified = b; firePropertyChange("modified", old, isModified()); } /** * * @return */ public boolean isCancelled() { return cancelled; } /** 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() { jLabel1 = new javax.swing.JLabel(); jComboBoxCats = new javax.swing.JComboBox(); jLabel2 = new javax.swing.JLabel(); jTextFieldNewCat = new javax.swing.JTextField(); jButtonAddCat = new javax.swing.JButton(); jLabel3 = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane(); jTextAreaComment = new javax.swing.JTextArea(); jButtonApply = new javax.swing.JButton(); jButtonCancel = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext().getResourceMap(CNewBookmark.class); setTitle(resourceMap.getString("FormNewBookmark.title")); // NOI18N setModal(true); setName("FormNewBookmark"); // NOI18N jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N jLabel1.setName("jLabel1"); // NOI18N jComboBoxCats.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); jComboBoxCats.setName("jComboBoxCats"); // NOI18N jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N jLabel2.setName("jLabel2"); // NOI18N jTextFieldNewCat.setText(resourceMap.getString("jTextFieldNewCat.text")); // NOI18N jTextFieldNewCat.setName("jTextFieldNewCat"); // NOI18N javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext().getActionMap(CNewBookmark.class, this); jButtonAddCat.setAction(actionMap.get("addCat")); // NOI18N jButtonAddCat.setName("jButtonAddCat"); // NOI18N jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N jLabel3.setName("jLabel3"); // NOI18N jScrollPane1.setName("jScrollPane1"); // NOI18N jTextAreaComment.setLineWrap(true); jTextAreaComment.setWrapStyleWord(true); jTextAreaComment.setName("jTextAreaComment"); // NOI18N jScrollPane1.setViewportView(jTextAreaComment); jButtonApply.setAction(actionMap.get("applyChanges")); // NOI18N jButtonApply.setName("jButtonApply"); // NOI18N jButtonCancel.setAction(actionMap.get("cancelWindow")); // NOI18N jButtonCancel.setName("jButtonCancel"); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTextFieldNewCat) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonAddCat)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jComboBoxCats, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jLabel3)) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(jButtonCancel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonApply))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(jComboBoxCats, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(jButtonAddCat) .addComponent(jTextFieldNewCat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jButtonApply) .addComponent(jButtonCancel)) .addGap(3, 3, 3)) ); pack(); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButtonAddCat; private javax.swing.JButton jButtonApply; private javax.swing.JButton jButtonCancel; private javax.swing.JComboBox jComboBoxCats; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTextArea jTextAreaComment; private javax.swing.JTextField jTextFieldNewCat; // End of variables declaration//GEN-END:variables }