├── icons ├── hjt.icns ├── ico │ ├── hjt.ico │ └── jree.ico ├── jree.icns ├── png │ ├── 16x16.png │ ├── 24x24.hjt.png │ ├── 24x24.jree.png │ ├── 32x32.hjt.png │ ├── 32x32.jree.png │ ├── 48x48.hjt.png │ ├── 48x48.jree.png │ ├── 128x128.hjt.png │ └── 128x128.jree.png └── jreepadlogo-01.icns ├── images ├── Add16.gif ├── Back16.gif ├── Down16.gif ├── New16.gif ├── Open16.gif ├── Save16.gif ├── Up16.gif ├── Remove16.gif ├── Forward16.gif ├── InsertAfter16.gif ├── jreepad-icon.gif ├── InsertBefore16.gif └── jreepadlogo-01-iconsize.gif ├── src ├── images │ ├── Up16.gif │ ├── Add16.gif │ ├── Back16.gif │ ├── Down16.gif │ ├── New16.gif │ ├── Open16.gif │ ├── Save16.gif │ ├── Forward16.gif │ ├── Remove16.gif │ ├── jreepad-icon.gif │ ├── InsertAfter16.gif │ ├── InsertBefore16.gif │ └── jreepadlogo-01-iconsize.gif └── jreepad │ ├── jreepadmanifest │ ├── TreePathCollection.java │ ├── ui │ ├── FontHelper.java │ ├── ExtensionFileFilter.java │ ├── SaveFileChooser.java │ └── PasswordDialog.java │ ├── editor │ ├── HtmlViewer.java │ ├── ContentChangeListener.java │ ├── TextileViewer.java │ ├── AbstractArticleView.java │ ├── ArticleView.java │ ├── EditorPaneView.java │ ├── EditPopupHandler.java │ ├── TableViewer.java │ ├── TextTransferHandler.java │ └── PlainTextEditor.java │ ├── io │ ├── JreepadReader.java │ ├── JreepadWriter.java │ ├── TreepadWriter.java │ ├── EncryptedWriter.java │ ├── EncryptedReader.java │ ├── XmlWriter.java │ ├── XmlReader.java │ ├── TreepadReader.java │ ├── HtmlWriter.java │ └── AutoDetectReader.java │ ├── JreepadTreeModel.java │ ├── SoftLinkNode.java │ ├── JreepadSearcher.java │ ├── TreeView.java │ ├── lang │ ├── JreepadStrings_da.properties │ └── JreepadStrings.properties │ ├── JreepadNode.java │ ├── find.java │ └── SearchDialog.java ├── website ├── favicon.ico ├── jreepadlogo-01.icns ├── jreepadlogo-01.psd ├── images │ ├── jreepadlogo-01.icns │ ├── jreepadlogo-01.psd │ ├── sflogo-rotated.png │ ├── jreepad-icon-coen-32.gif │ ├── jreepadlogo-01-iconsize.gif │ └── jreepadlogo-01-logosize.gif ├── logo │ ├── vote.php │ └── index.php ├── jar │ └── index.html ├── formats │ └── index.htm ├── screenshots │ └── index.html ├── developers │ └── index.html └── index.html ├── lib ├── JTextile-1.2.jar ├── jarbundler-1.9.jar ├── gnu-regexp-1.1.4-lib.jar └── BrowserLauncher2-10rc4.jar ├── .project ├── .classpath ├── README.md └── manual └── osxreadme └── Read me first.rtf /icons/hjt.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/hjt.icns -------------------------------------------------------------------------------- /icons/ico/hjt.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/ico/hjt.ico -------------------------------------------------------------------------------- /icons/jree.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/jree.icns -------------------------------------------------------------------------------- /images/Add16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Add16.gif -------------------------------------------------------------------------------- /images/Back16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Back16.gif -------------------------------------------------------------------------------- /images/Down16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Down16.gif -------------------------------------------------------------------------------- /images/New16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/New16.gif -------------------------------------------------------------------------------- /images/Open16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Open16.gif -------------------------------------------------------------------------------- /images/Save16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Save16.gif -------------------------------------------------------------------------------- /images/Up16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Up16.gif -------------------------------------------------------------------------------- /icons/ico/jree.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/ico/jree.ico -------------------------------------------------------------------------------- /icons/png/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/16x16.png -------------------------------------------------------------------------------- /images/Remove16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Remove16.gif -------------------------------------------------------------------------------- /src/images/Up16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Up16.gif -------------------------------------------------------------------------------- /website/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/favicon.ico -------------------------------------------------------------------------------- /images/Forward16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/Forward16.gif -------------------------------------------------------------------------------- /lib/JTextile-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/lib/JTextile-1.2.jar -------------------------------------------------------------------------------- /lib/jarbundler-1.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/lib/jarbundler-1.9.jar -------------------------------------------------------------------------------- /src/images/Add16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Add16.gif -------------------------------------------------------------------------------- /src/images/Back16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Back16.gif -------------------------------------------------------------------------------- /src/images/Down16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Down16.gif -------------------------------------------------------------------------------- /src/images/New16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/New16.gif -------------------------------------------------------------------------------- /src/images/Open16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Open16.gif -------------------------------------------------------------------------------- /src/images/Save16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Save16.gif -------------------------------------------------------------------------------- /icons/png/24x24.hjt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/24x24.hjt.png -------------------------------------------------------------------------------- /icons/png/24x24.jree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/24x24.jree.png -------------------------------------------------------------------------------- /icons/png/32x32.hjt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/32x32.hjt.png -------------------------------------------------------------------------------- /icons/png/32x32.jree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/32x32.jree.png -------------------------------------------------------------------------------- /icons/png/48x48.hjt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/48x48.hjt.png -------------------------------------------------------------------------------- /icons/png/48x48.jree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/48x48.jree.png -------------------------------------------------------------------------------- /images/InsertAfter16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/InsertAfter16.gif -------------------------------------------------------------------------------- /images/jreepad-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/jreepad-icon.gif -------------------------------------------------------------------------------- /src/images/Forward16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Forward16.gif -------------------------------------------------------------------------------- /src/images/Remove16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/Remove16.gif -------------------------------------------------------------------------------- /icons/jreepadlogo-01.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/jreepadlogo-01.icns -------------------------------------------------------------------------------- /icons/png/128x128.hjt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/128x128.hjt.png -------------------------------------------------------------------------------- /icons/png/128x128.jree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/icons/png/128x128.jree.png -------------------------------------------------------------------------------- /images/InsertBefore16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/InsertBefore16.gif -------------------------------------------------------------------------------- /src/images/jreepad-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/jreepad-icon.gif -------------------------------------------------------------------------------- /website/jreepadlogo-01.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/jreepadlogo-01.icns -------------------------------------------------------------------------------- /website/jreepadlogo-01.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/jreepadlogo-01.psd -------------------------------------------------------------------------------- /lib/gnu-regexp-1.1.4-lib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/lib/gnu-regexp-1.1.4-lib.jar -------------------------------------------------------------------------------- /src/images/InsertAfter16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/InsertAfter16.gif -------------------------------------------------------------------------------- /src/images/InsertBefore16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/InsertBefore16.gif -------------------------------------------------------------------------------- /lib/BrowserLauncher2-10rc4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/lib/BrowserLauncher2-10rc4.jar -------------------------------------------------------------------------------- /images/jreepadlogo-01-iconsize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/images/jreepadlogo-01-iconsize.gif -------------------------------------------------------------------------------- /website/images/jreepadlogo-01.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/jreepadlogo-01.icns -------------------------------------------------------------------------------- /website/images/jreepadlogo-01.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/jreepadlogo-01.psd -------------------------------------------------------------------------------- /website/images/sflogo-rotated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/sflogo-rotated.png -------------------------------------------------------------------------------- /src/jreepad/jreepadmanifest: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Created-By: Dan Stowell 3 | Main-Class: jreepad.JreepadViewer 4 | 5 | -------------------------------------------------------------------------------- /src/images/jreepadlogo-01-iconsize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/src/images/jreepadlogo-01-iconsize.gif -------------------------------------------------------------------------------- /website/images/jreepad-icon-coen-32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/jreepad-icon-coen-32.gif -------------------------------------------------------------------------------- /website/images/jreepadlogo-01-iconsize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/jreepadlogo-01-iconsize.gif -------------------------------------------------------------------------------- /website/images/jreepadlogo-01-logosize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danstowell/jreepad/HEAD/website/images/jreepadlogo-01-logosize.gif -------------------------------------------------------------------------------- /src/jreepad/TreePathCollection.java: -------------------------------------------------------------------------------- 1 | package jreepad; 2 | 3 | import javax.swing.tree.TreePath; 4 | 5 | // A simple class to make it easy to serialize a list of TreePaths 6 | 7 | public class TreePathCollection implements java.io.Serializable 8 | { 9 | public TreePath[] paths; 10 | public TreePathCollection(TreePath[] coll) { paths = coll; } 11 | } 12 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | jreepad 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/jreepad/ui/FontHelper.java: -------------------------------------------------------------------------------- 1 | package jreepad.ui; 2 | 3 | import java.awt.Font; 4 | import javax.swing.JComponent; 5 | 6 | /** 7 | * 8 | * @author not attributable 9 | * @version 1.0 10 | */ 11 | public class FontHelper { 12 | public static final int FONT_DIR_UP = 1; 13 | public static final int FONT_DIR_DOWN = 2; 14 | 15 | private FontHelper() { 16 | super(); 17 | } 18 | 19 | public static void updateFont(JComponent comp, 20 | int direction) { 21 | Font font = comp.getFont(); 22 | float size = font.getSize2D(); 23 | Font newFont = null; 24 | switch (direction) { 25 | case FONT_DIR_UP: 26 | newFont = font.deriveFont(++size); 27 | break; 28 | case FONT_DIR_DOWN: 29 | newFont = font.deriveFont(--size); 30 | break; 31 | } 32 | if (newFont != null) { 33 | comp.setFont(newFont); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/jreepad/editor/HtmlViewer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import jreepad.JreepadArticle; 23 | 24 | /** 25 | * The plain HTML viewer pane. 26 | */ 27 | public class HtmlViewer extends EditorPaneView 28 | { 29 | public HtmlViewer(JreepadArticle article) 30 | { 31 | super("text/html", article); 32 | editorPane.setEditable(false); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/jreepad/editor/ContentChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | /** 23 | * Listener for changes in article content. 24 | * 25 | * @author Przemek Więch 26 | * @version $Id: ContentChangeListener.java,v 1.1 2007-02-05 10:56:43 pewu Exp $ 27 | */ 28 | public interface ContentChangeListener 29 | { 30 | public void contentChanged(); 31 | } 32 | -------------------------------------------------------------------------------- /src/jreepad/io/JreepadReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | import jreepad.JreepadTreeModel; 26 | 27 | /** 28 | * Interface for classes that read Jreepad trees. 29 | * 30 | * @author Przemek Więch 31 | * @version $Id$ 32 | */ 33 | public interface JreepadReader 34 | { 35 | public JreepadTreeModel read(InputStream in) throws IOException; 36 | } 37 | -------------------------------------------------------------------------------- /src/jreepad/io/JreepadWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | 25 | import jreepad.JreepadTreeModel; 26 | 27 | /** 28 | * Interface for classes that export Jreepad trees. 29 | * 30 | * @author Przemek Więch 31 | * @version $Id$ 32 | */ 33 | public interface JreepadWriter 34 | { 35 | public void write(OutputStream out, JreepadTreeModel document) throws IOException; 36 | } 37 | -------------------------------------------------------------------------------- /website/logo/vote.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vote on the choice of logo... 5 | 6 | 14 | 15 | 16 | 17 | 18 | No option detected! This might be a mistake. I hope not, though.

"); 33 | } 34 | 35 | mysql_query("DELETE FROM LOGOVOTES WHERE ip='$ip'", $dbcon); 36 | mysql_query("INSERT INTO LOGOVOTES SET ip='$ip', vote='$vote'", $dbcon); 37 | 38 | echo mysql_error(); 39 | 40 | ?> 41 |

Thanks - your vote has been recorded!

42 | 43 | -------------------------------------------------------------------------------- /src/jreepad/editor/TextileViewer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import org.philwilson.JTextile; 23 | 24 | import jreepad.JreepadArticle; 25 | 26 | /** 27 | * The Textile viewer pane. 28 | */ 29 | public class TextileViewer extends HtmlViewer 30 | { 31 | public TextileViewer(JreepadArticle article) 32 | { 33 | super(article); 34 | } 35 | 36 | public void reloadArticle() 37 | { 38 | try 39 | { 40 | editorPane.setText(JTextile.textile(article.getContent())); 41 | } 42 | catch (Exception e) 43 | { 44 | // Fallback to HTML if Textile failed 45 | e.printStackTrace(); 46 | super.reloadArticle(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jreepad 2 | 3 | Jreepad is an excellent free "personal database" program - it's a great way to organise all your personal notes, thoughts, tasks, recipes, memories... 4 | 5 | What's more, it's open-source and programmed in Java, so that all may benefit from it! Much used on Mac OSX, Linux, Unix, and even Windows! 6 | 7 | 8 | ## Main features: 9 | 10 | * A Jreepad file consists of a nice simple tree structure, and each "node" has an associated "article" - this can be plain text, HTML or tabular data. 11 | * Nodes can be rearranged very intuitively with drag-and-drop functionality (or by keyboard), so it's easy to arrange your thoughts. 12 | * There's a very powerful and intuitive search facility to locate a piece of text in a subtree 13 | * Hyperlink support: select a link and you can follow it - whether it's HTTP, FTP, mailto:, "node://" (as used in Treepad), or even WikiStyleLinks! 14 | * Integrated Google search 15 | * Load/save Treepad (.HJT) files, compatible with Treepad Lite (so you can share files with Windows users) 16 | * ...and much more, of course. 17 | 18 | ## Background 19 | 20 | Jreepad is originally based on [Treepad Lite](http://www.treepad.com/treepadfreeware/), an excellent free program which is only available for Windows and Linux. When I moved from Windows to Mac I needed Treepad's functionality so I created it myself. Jreepad has gradually grown to provide more functionality than Treepad Lite, but its files are still compatible with the original Windows software. 21 | 22 | Please note that Jreepad is not directly affiliated with Treepad - it's an independent project. 23 | 24 | ## How to compile Jreepad 25 | 26 | Clone/download the project, then run "ant" from the root folder. You'll need to have a Java JDK installed, as well as "Ant" the build tool. 27 | -------------------------------------------------------------------------------- /src/jreepad/ui/ExtensionFileFilter.java: -------------------------------------------------------------------------------- 1 | package jreepad.ui; 2 | 3 | import java.io.File; 4 | 5 | import javax.swing.filechooser.FileFilter; 6 | 7 | /** 8 | * File filter, which accepts only files with the given extension. 9 | */ 10 | public class ExtensionFileFilter extends FileFilter 11 | { 12 | /** 13 | * Description of this filter. 14 | */ 15 | private String description; 16 | 17 | /** 18 | * Allowed extension. 19 | */ 20 | private String extension; 21 | 22 | /** 23 | * Lowercase version of the extension. 24 | */ 25 | private String lowercaseExtension; 26 | 27 | public ExtensionFileFilter(String description, String extension) 28 | { 29 | this.description = description; 30 | this.extension = extension; 31 | this.lowercaseExtension = extension.toLowerCase(); 32 | } 33 | 34 | /** 35 | * Tests whether the given file has the appropriate extension. 36 | */ 37 | public boolean accept(File f) 38 | { 39 | if (f == null) 40 | return false; 41 | if (f.isDirectory()) 42 | return true; 43 | String fileName = f.getName(); 44 | int i = fileName.lastIndexOf('.'); 45 | if (i <= 0 || i >= fileName.length() - 1) 46 | return false; 47 | String fileExtension = fileName.substring(i + 1).toLowerCase(); 48 | if (fileExtension.equals(lowercaseExtension)) 49 | return true; 50 | return false; 51 | } 52 | 53 | /** 54 | * Returns the description of this filter. 55 | */ 56 | public String getDescription() 57 | { 58 | return description; 59 | } 60 | 61 | /** 62 | * Returns the filtered file extension. 63 | */ 64 | public String getExtension() 65 | { 66 | return extension; 67 | } 68 | } -------------------------------------------------------------------------------- /src/jreepad/editor/AbstractArticleView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import jreepad.JreepadArticle; 23 | 24 | /** 25 | * Abstract implementation of ArticleView. 26 | * Several basic methods are implemented. 27 | * 28 | * @author Przemek Więch 29 | * @version $Id: AbstractArticleView.java,v 1.2 2007-02-07 21:10:43 pewu Exp $ 30 | */ 31 | public abstract class AbstractArticleView implements ArticleView 32 | { 33 | protected JreepadArticle article; 34 | 35 | // The following boolean should be TRUE while we're changing from node to 36 | // node, and false otherwise 37 | protected boolean editLocked = false; 38 | 39 | public AbstractArticleView(JreepadArticle article) 40 | { 41 | this.article = article; 42 | } 43 | 44 | public void lockEdits() 45 | { 46 | editLocked = true; 47 | } 48 | 49 | public void unlockEdits() 50 | { 51 | editLocked = false; 52 | } 53 | 54 | public void saveArticle() 55 | { 56 | article.setContent(getText()); 57 | } 58 | 59 | public void setArticle(JreepadArticle article) 60 | { 61 | this.article = article; 62 | reloadArticle(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/jreepad/editor/ArticleView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import javax.swing.JComponent; 23 | 24 | import jreepad.JreepadArticle; 25 | 26 | /** 27 | * Interface for an article viewer or editor. 28 | * 29 | * @author Przemek Więch 30 | * @version $Id: ArticleView.java,v 1.3 2008-09-21 11:06:49 danstowell Exp $ 31 | */ 32 | public interface ArticleView 33 | { 34 | /** 35 | * Returns the GUI viewer/editor component. 36 | */ 37 | public JComponent getComponent(); 38 | 39 | /** 40 | * Returns selected text in view. 41 | */ 42 | public String getSelectedText(); 43 | 44 | /** 45 | * Reloads the article. 46 | * Transfers data from article to view. 47 | */ 48 | public void reloadArticle(); 49 | 50 | /** 51 | * Saves the current article. 52 | * Transfers data from view to article. 53 | */ 54 | public void saveArticle(); 55 | 56 | /** 57 | * Returns the content text. 58 | */ 59 | public String getText(); 60 | 61 | /** 62 | * Sets new article content. 63 | */ 64 | public void setArticle(JreepadArticle article); 65 | 66 | /** 67 | * Lock editor - no edits will be allowed. 68 | */ 69 | public void lockEdits(); 70 | 71 | /** 72 | * Unlock editor - edits will now be allowed. 73 | */ 74 | public void unlockEdits(); 75 | 76 | public void updateFont(int direction); 77 | } 78 | -------------------------------------------------------------------------------- /src/jreepad/io/TreepadWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.io.OutputStreamWriter; 25 | import java.io.Writer; 26 | import java.util.Enumeration; 27 | 28 | import jreepad.JreepadNode; 29 | import jreepad.JreepadTreeModel; 30 | 31 | /** 32 | * Writes the Jreepad tree as a Treepad file. 33 | * 34 | * @version $Id$ 35 | */ 36 | public class TreepadWriter 37 | implements JreepadWriter 38 | { 39 | 40 | private String encoding; 41 | 42 | public TreepadWriter(String encoding) 43 | { 44 | this.encoding = encoding; 45 | } 46 | 47 | public void write(OutputStream out, JreepadTreeModel document) 48 | throws IOException 49 | { 50 | Writer writer = new OutputStreamWriter(out, encoding); 51 | writer.write("\n"); 52 | writeNode(writer, document.getRootNode(), 0); 53 | writer.flush(); 54 | writer.close(); 55 | } 56 | 57 | private void writeNode(Writer writer, JreepadNode node, int depth) 58 | throws IOException 59 | { 60 | writer.write("dt=Text\n\n"); 61 | writer.write(node.getTitle()); 62 | writer.write("\n"); 63 | writer.write(depth + "\n"); 64 | writer.write(node.getContent()); 65 | writer.write("\n"); 66 | writer.write(" 5P9i0s8y19Z\n"); 67 | 68 | Enumeration kids = node.children(); 69 | while (kids.hasMoreElements()) 70 | writeNode(writer, (JreepadNode)kids.nextElement(), depth + 1); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /manual/osxreadme/Read me first.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf330 2 | {\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fswiss\fcharset77 Helvetica-Bold;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11899\paperh16839\margl1440\margr1440\vieww12020\viewh12700\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 6 | 7 | \f0\fs24 \cf0 \ 8 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural 9 | 10 | \f1\b\fs36 \cf0 Jreepad - designed for Mac OSX\ 11 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 12 | 13 | \f0\b0\fs24 \cf0 \ 14 | \ 15 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 16 | 17 | \f1\b\fs26 \cf0 Getting started 18 | \f0\b0\fs24 \ 19 | \ 20 | Just drag the "Jreepad" application into your "Applications" folder, and run it!\ 21 | \ 22 | In fact, Jreepad will run from anywhere (e.g. a portable memory stick, a CD). All you need is a computer with Java 1.4 or later installed (all Max OSX computers already have this).\ 23 | \ 24 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural 25 | \cf0 --\ 26 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 27 | \cf0 \ 28 | For a full introduction to Jreepad, it's a good idea to look at the manual "JreepadManual.jree", which is a manual written in Jreepad's own tree-like file format.\ 29 | \ 30 | Start Jreepad, then use the "File > Open" menu option to load "JreepadManual.jree". Or just double-click on the .jree file.\ 31 | \ 32 | \ 33 | \ 34 | \ 35 | \ 36 | \ 37 | \ 38 | \ 39 | Jreepad is free software made available under the terms of the GNU Public License.\ 40 | \ 41 | (c) Dan Stowell.\ 42 | \ 43 | \ 44 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural 45 | \cf0 All bugs, problems, suggestions, etc gratefully received at:\ 46 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural 47 | {\field{\*\fldinst{HYPERLINK "http://jreepad.sourceforge.net"}}{\fldrslt \cf0 http://jreepad.sourceforge.net}}\ 48 | } -------------------------------------------------------------------------------- /src/jreepad/io/EncryptedWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.security.GeneralSecurityException; 25 | import java.security.Key; 26 | 27 | import javax.crypto.Cipher; 28 | import javax.crypto.CipherOutputStream; 29 | import javax.crypto.spec.SecretKeySpec; 30 | 31 | import jreepad.JreepadTreeModel; 32 | 33 | /** 34 | * Writes an encrypted file. This writer is constructed with 35 | * any other writer as the actual file format which will be encrypted. 36 | * 37 | * @version $Id: EncryptedWriter.java,v 1.1 2007-09-28 14:29:22 pewu Exp $ 38 | */ 39 | public class EncryptedWriter 40 | implements JreepadWriter 41 | { 42 | static final String ALGORITHM = "Blowfish"; 43 | 44 | static final String HEADER = "JreepadEncrypted"; 45 | 46 | private JreepadWriter writer; 47 | 48 | private String password = ""; 49 | 50 | public EncryptedWriter(JreepadWriter writer) 51 | { 52 | this.writer = writer; 53 | } 54 | 55 | public void write(OutputStream out, JreepadTreeModel document) 56 | throws IOException 57 | { 58 | out.write(HEADER.getBytes()); 59 | out.write("\n".getBytes()); 60 | 61 | Cipher cipher = null; 62 | try 63 | { 64 | cipher = Cipher.getInstance(ALGORITHM); 65 | Key key = new SecretKeySpec(password.getBytes(), ALGORITHM); 66 | cipher.init(Cipher.ENCRYPT_MODE, key); 67 | } 68 | catch (GeneralSecurityException e) 69 | { 70 | throw new IOException(e.toString()); 71 | } 72 | OutputStream out2 = new CipherOutputStream(out, cipher); 73 | writer.write(out2, document); 74 | } 75 | 76 | public void setPassword(String password) 77 | { 78 | this.password = password; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/jreepad/editor/EditorPaneView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import java.awt.Font; 23 | import javax.swing.JComponent; 24 | import javax.swing.JEditorPane; 25 | import javax.swing.text.MutableAttributeSet; 26 | import javax.swing.text.StyleConstants; 27 | import javax.swing.text.StyledDocument; 28 | import javax.swing.text.StyledEditorKit; 29 | 30 | import jreepad.JreepadArticle; 31 | import jreepad.ui.FontHelper; 32 | /** 33 | * Abstract article view in the form of a JEditorPane. 34 | * 35 | * @author Przemek Więch 36 | * @version $Id: EditorPaneView.java,v 1.2 2008-09-21 11:06:50 danstowell Exp $ 37 | */ 38 | public abstract class EditorPaneView 39 | extends AbstractArticleView { 40 | 41 | protected JEditorPane editorPane; 42 | 43 | public EditorPaneView(String type, JreepadArticle article) { 44 | super(article); 45 | editorPane = new JEditorPane(type, ""); 46 | reloadArticle(); 47 | } 48 | 49 | public void reloadArticle() 50 | { 51 | editorPane.setText(article.getContent()); 52 | } 53 | 54 | public void updateFont(int direction) { 55 | StyledEditorKit kit = (StyledEditorKit) editorPane.getEditorKit(); 56 | MutableAttributeSet set = kit.getInputAttributes(); 57 | StyledDocument doc = (StyledDocument) editorPane.getDocument(); 58 | Font currentFont = doc.getFont(set); 59 | int currentFontSize = currentFont.getSize(); 60 | switch (direction) { 61 | case FontHelper.FONT_DIR_UP: 62 | currentFontSize++; 63 | break; 64 | case FontHelper.FONT_DIR_DOWN: 65 | currentFontSize--; 66 | break; 67 | } 68 | StyleConstants.setFontSize(set, currentFontSize); 69 | doc.setCharacterAttributes(0, doc.getLength(), set, false); 70 | } 71 | 72 | public JComponent getComponent() { 73 | return editorPane; 74 | } 75 | 76 | public String getText() 77 | { 78 | return editorPane.getText(); 79 | } 80 | 81 | public String getSelectedText() 82 | { 83 | return editorPane.getSelectedText(); 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /src/jreepad/io/EncryptedReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.security.GeneralSecurityException; 25 | import java.security.Key; 26 | 27 | import javax.crypto.Cipher; 28 | import javax.crypto.CipherInputStream; 29 | import javax.crypto.spec.SecretKeySpec; 30 | 31 | import jreepad.JreepadPrefs; 32 | import jreepad.JreepadTreeModel; 33 | 34 | /** 35 | * Reads encrypted input into Jreepad. This reader is constructed with 36 | * any other reader as the actual file format which will used when decrypted. 37 | * 38 | * @version $Id: EncryptedReader.java,v 1.2 2008-09-21 10:29:22 danstowell Exp $ 39 | */ 40 | public class EncryptedReader implements JreepadReader 41 | { 42 | private JreepadReader reader; 43 | 44 | private String password = ""; 45 | 46 | public EncryptedReader(JreepadReader reader) 47 | { 48 | this.reader = reader; 49 | } 50 | 51 | public JreepadTreeModel read(InputStream in) 52 | throws IOException 53 | { 54 | // Read header 55 | while (in.read() != '\n'); 56 | 57 | Cipher cipher = null; 58 | try 59 | { 60 | cipher = Cipher.getInstance(EncryptedWriter.ALGORITHM); 61 | Key key = new SecretKeySpec(password.getBytes(), EncryptedWriter.ALGORITHM); 62 | cipher.init(Cipher.DECRYPT_MODE, key); 63 | } 64 | catch (GeneralSecurityException e) 65 | { 66 | throw new IOException(e.toString()); 67 | } 68 | InputStream in2 = new CipherInputStream(in, cipher); 69 | 70 | JreepadTreeModel document; 71 | try 72 | { 73 | document = reader.read(in2); 74 | } 75 | catch (IOException e) 76 | { 77 | throw new IOException("Password incorrect or read problem occurred"); 78 | } 79 | document.setFileType(JreepadPrefs.FILETYPE_XML_ENCRYPTED); 80 | document.setPassword(password); 81 | return document; 82 | } 83 | 84 | public void setPassword(String password) 85 | { 86 | this.password = password; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/jreepad/JreepadTreeModel.java: -------------------------------------------------------------------------------- 1 | package jreepad; 2 | 3 | import java.io.File; 4 | 5 | import javax.swing.tree.DefaultTreeModel; 6 | import javax.swing.tree.TreePath; 7 | 8 | /** 9 | * The tree model. 10 | * 11 | * @version $Id: JreepadTreeModel.java,v 1.7 2007-09-28 14:29:22 pewu Exp $ 12 | */ 13 | public class JreepadTreeModel extends DefaultTreeModel 14 | { 15 | /** 16 | * The location, where the document was last saved. 17 | */ 18 | private File saveLocation = null; 19 | 20 | /** 21 | * Format of the loaded file. 22 | */ 23 | private int fileType = -1; 24 | 25 | /** 26 | * Encoding of the loaded file. 27 | */ 28 | private String encoding = null; 29 | 30 | /** 31 | * Password for saving encrypted files. 32 | */ 33 | private String password = null; 34 | 35 | /** 36 | * True if the current document content has been saved. 37 | */ 38 | private boolean contentSaved = false; 39 | 40 | public JreepadTreeModel() 41 | { 42 | this(new JreepadNode()); 43 | } 44 | 45 | /** 46 | * Creates the model. 47 | * 48 | * @param root root node of the tree 49 | */ 50 | public JreepadTreeModel(JreepadNode root) 51 | { 52 | super(root); 53 | } 54 | 55 | /** 56 | * Sets the title of the given node to the given value. 57 | */ 58 | public void valueForPathChanged(TreePath path, Object newValue) 59 | { 60 | JreepadNode node = (JreepadNode) path.getLastPathComponent(); 61 | node.setTitle((String) newValue); 62 | nodeChanged(node); 63 | } 64 | 65 | /** 66 | * Returns the root tree node. 67 | */ 68 | public JreepadNode getRootNode() 69 | { 70 | return (JreepadNode) getRoot(); 71 | } 72 | 73 | /** 74 | * Returns true if the current document content has been saved. 75 | */ 76 | public boolean isContentSaved() 77 | { 78 | return contentSaved; 79 | } 80 | 81 | /** 82 | * Sets the information whether the current document content has been saved 83 | * or not. 84 | * 85 | * @param contentSaved 86 | */ 87 | public void setContentSaved(boolean contentSaved) 88 | { 89 | this.contentSaved = contentSaved; 90 | } 91 | 92 | public void setSaveLocation(File saveLocation) 93 | { 94 | this.saveLocation = saveLocation; 95 | setContentSaved(true); 96 | } 97 | 98 | public void setFileType(int fileType) 99 | { 100 | this.fileType = fileType; 101 | } 102 | 103 | public File getSaveLocation() 104 | { 105 | return saveLocation; 106 | } 107 | 108 | public int getFileType() 109 | { 110 | return fileType; 111 | } 112 | 113 | public String getEncoding() 114 | { 115 | return encoding; 116 | } 117 | 118 | public void setEncoding(String encoding) 119 | { 120 | this.encoding = encoding; 121 | } 122 | 123 | public String getPassword() 124 | { 125 | return password; 126 | } 127 | 128 | public void setPassword(String password) 129 | { 130 | this.password = password; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/jreepad/SoftLinkNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad; 21 | 22 | import java.util.Enumeration; 23 | 24 | import javax.swing.tree.DefaultMutableTreeNode; 25 | import javax.swing.tree.MutableTreeNode; 26 | import javax.swing.tree.TreeNode; 27 | 28 | 29 | /** 30 | * Soft link tree node. Points to another node in the tree. 31 | * 32 | * @version $Id$ 33 | */ 34 | public class SoftLinkNode extends JreepadNode 35 | { 36 | private JreepadNode target; 37 | 38 | public SoftLinkNode(SoftLinkNode target) 39 | { 40 | super((JreepadArticle)null); 41 | this.target = target; 42 | } 43 | 44 | public JreepadArticle getArticle() 45 | { 46 | return target.getArticle(); 47 | } 48 | 49 | public void add(MutableTreeNode child) 50 | { 51 | target.add(child); 52 | } 53 | 54 | public JreepadNode removeChild(int child) // Can be used to delete, OR to 'get' one for moving 55 | { 56 | return target.removeChild(child); 57 | } 58 | 59 | public TreeNode getChildAt(int child) 60 | { 61 | return target.getChildAt(child); 62 | } 63 | 64 | public int getChildCount() 65 | { 66 | return target.getChildCount(); 67 | } 68 | 69 | public JreepadNode addChild() 70 | { 71 | return target.addChild(); 72 | } 73 | 74 | public JreepadNode addChild(int index) 75 | { 76 | return target.addChild(index); 77 | } 78 | 79 | public int getIndex(TreeNode child) 80 | { 81 | return target.getIndex(child); 82 | } 83 | 84 | public boolean isNodeDescendant(DefaultMutableTreeNode n) 85 | { 86 | return target.isNodeDescendant(n); 87 | } 88 | 89 | public void sortChildren() 90 | { 91 | target.sortChildren(); 92 | } 93 | 94 | public void sortChildrenRecursive() 95 | { 96 | target.sortChildrenRecursive(); 97 | } 98 | 99 | public Enumeration children() 100 | { 101 | return target.children(); 102 | } 103 | 104 | // MutableTreeNode functions 105 | public void remove(int child) 106 | { 107 | target.remove(child); 108 | } 109 | 110 | public void remove(MutableTreeNode node) 111 | { 112 | target.remove(node); 113 | } 114 | 115 | public void insert(MutableTreeNode child, int index) 116 | { 117 | target.insert(child, index); 118 | } 119 | 120 | public JreepadNode getSoftLinkTarget() 121 | { 122 | return target; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/jreepad/editor/EditPopupHandler.java: -------------------------------------------------------------------------------- 1 | package jreepad.editor; 2 | 3 | import java.awt.Toolkit; 4 | import java.awt.datatransfer.Clipboard; 5 | import java.awt.datatransfer.DataFlavor; 6 | import java.awt.datatransfer.Transferable; 7 | import java.awt.event.MouseAdapter; 8 | import java.awt.event.MouseEvent; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import javax.swing.JMenuItem; 13 | import javax.swing.JPopupMenu; 14 | import javax.swing.text.JTextComponent; 15 | import javax.swing.text.TextAction; 16 | 17 | /** 18 | * 19 | * @author not attributable 20 | * @version 1.1 21 | */ 22 | public class EditPopupHandler 23 | extends MouseAdapter { 24 | private JPopupMenu popupMenu = new JPopupMenu(); 25 | public static final String ITEM_CUT = "cut"; 26 | public static final String ITEM_COPY = "copy"; 27 | public static final String ITEM_PASTE = "paste"; 28 | public static final String ITEM_SELECTALL = "selectall"; 29 | private final Map itemMap = new HashMap(); 30 | 31 | public EditPopupHandler() { 32 | super(); 33 | itemMap.put(ITEM_COPY, null); 34 | itemMap.put(ITEM_CUT, null); 35 | itemMap.put(ITEM_PASTE, null); 36 | itemMap.put(ITEM_SELECTALL, null); 37 | } 38 | 39 | public void addActionItem(TextAction action, 40 | String menuLabel, 41 | String type) { 42 | JMenuItem item = new JMenuItem(action); 43 | item.setText(menuLabel); 44 | popupMenu.add(item); 45 | if (itemMap.containsKey(type)) { 46 | itemMap.put(type, item); 47 | } 48 | } 49 | 50 | private void enableMenuItems(MouseEvent e) { 51 | JTextComponent textComp = (JTextComponent) e.getComponent(); 52 | String selectedText = textComp.getSelectedText(); 53 | boolean textSelected = selectedText != null && 54 | selectedText.length() > 0; 55 | boolean isEditable = textComp.isEditable(); 56 | JMenuItem item = (JMenuItem) itemMap.get(ITEM_COPY); 57 | if (item != null) { 58 | item.setEnabled(textSelected); 59 | } 60 | item = (JMenuItem) itemMap.get(ITEM_CUT); 61 | if (item != null) { 62 | item.setEnabled(textSelected && isEditable); 63 | } 64 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 65 | Transferable contents = clipboard.getContents(null); 66 | boolean hasTransferableText = 67 | (contents != null) && 68 | contents.isDataFlavorSupported(DataFlavor.stringFlavor); 69 | item = (JMenuItem) itemMap.get(ITEM_PASTE); 70 | if (item != null) { 71 | item.setEnabled(hasTransferableText && isEditable); 72 | } 73 | item = (JMenuItem) itemMap.get(ITEM_SELECTALL); 74 | if (item != null) { 75 | item.setEnabled(true && isEditable); 76 | } 77 | } 78 | 79 | /* -------------- from MouseListener -------------- */ 80 | 81 | public void mouseClicked(MouseEvent e) { 82 | if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3) { 83 | enableMenuItems(e); 84 | popupMenu.show(e.getComponent(), 85 | e.getX(), 86 | e.getY()); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/jreepad/editor/TableViewer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import java.awt.Color; 23 | 24 | import javax.swing.JComponent; 25 | import javax.swing.JTable; 26 | import javax.swing.table.DefaultTableModel; 27 | import javax.swing.table.TableModel; 28 | 29 | import jreepad.JreepadArticle; 30 | import jreepad.JreepadPrefs; 31 | import jreepad.JreepadView; 32 | import jreepad.ui.FontHelper; 33 | 34 | /** 35 | * The table view pane. 36 | * Converts CSV content to table view. 37 | */ 38 | public class TableViewer extends AbstractArticleView 39 | { 40 | private JTable table; 41 | 42 | public TableViewer(JreepadArticle article) 43 | { 44 | super(article); 45 | table = new JTable(getTableModel(article)); 46 | table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 47 | table.setGridColor(Color.GRAY); 48 | table.setShowGrid(true); 49 | table.setShowVerticalLines(true); 50 | table.setShowHorizontalLines(true); 51 | } 52 | 53 | public void updateFont(int direction) { 54 | FontHelper.updateFont(getComponent(), direction); 55 | } 56 | 57 | public JComponent getComponent() 58 | { 59 | return table; 60 | } 61 | 62 | public void reloadArticle() 63 | { 64 | table.setModel(getTableModel(article)); 65 | } 66 | 67 | private static TableModel getTableModel(JreepadArticle a) 68 | { 69 | String[][] rowData = a.interpretContentAsCsv(); 70 | String[] columnNames = new String[rowData[0].length]; 71 | for (int i = 0; i < columnNames.length; i++) 72 | columnNames[i] = " "; 73 | return new ArticleTableModel(rowData, columnNames); 74 | } 75 | 76 | public String getText() 77 | { 78 | int w = table.getColumnCount(); 79 | int h = table.getRowCount(); 80 | StringBuffer csv = new StringBuffer(); 81 | String quoteMark = getPrefs().addQuotesToCsvOutput ? "\"" : ""; 82 | for (int i = 0; i < h; i++) 83 | { 84 | for (int j = 0; j < (w - 1); j++) 85 | csv.append(quoteMark + (String) table.getValueAt(i, j) + quoteMark + ","); 86 | csv.append(quoteMark + (String) table.getValueAt(i, w - 1) + quoteMark + "\n"); 87 | } 88 | return csv.toString(); 89 | } 90 | 91 | public String getSelectedText() 92 | { 93 | int x = table.getSelectedColumn(); 94 | int y = table.getSelectedRow(); 95 | if(x==-1 || y ==-1) 96 | return ""; 97 | return table.getValueAt(y,x).toString(); 98 | } 99 | 100 | public static JreepadPrefs getPrefs() 101 | { 102 | return JreepadView.getPrefs(); 103 | } 104 | 105 | private static class ArticleTableModel extends DefaultTableModel 106 | { 107 | public ArticleTableModel(Object[][] data, Object[] columnNames) 108 | { 109 | super(data, columnNames); 110 | } 111 | 112 | public ArticleTableModel() 113 | { 114 | super(); 115 | } 116 | 117 | public boolean isCellEditable(int row, int col) 118 | { 119 | return false; 120 | } 121 | } // End of: class ArticleTableModel 122 | } 123 | -------------------------------------------------------------------------------- /src/jreepad/ui/SaveFileChooser.java: -------------------------------------------------------------------------------- 1 | package jreepad.ui; 2 | 3 | import java.io.File; 4 | import java.util.ResourceBundle; 5 | 6 | import javax.swing.JFileChooser; 7 | import javax.swing.JOptionPane; 8 | import javax.swing.filechooser.FileFilter; 9 | 10 | import jreepad.JreepadPrefs; 11 | 12 | public class SaveFileChooser extends JFileChooser 13 | { 14 | protected static final ResourceBundle LANG = ResourceBundle.getBundle("jreepad.lang.JreepadStrings"); 15 | 16 | /** 17 | * File filter for Jreepad XML .jree files. 18 | */ 19 | public static final FileFilter JREEPAD_FILE_FILTER = new ExtensionFileFilter("Jreepad XML file (*.jree)", "jree"); 20 | 21 | /** 22 | * File filter for Treepad .hjt files. 23 | */ 24 | public static final FileFilter TREEPAD_FILE_FILTER = new ExtensionFileFilter("Treepad file (*.hjt)", "hjt"); 25 | 26 | /** 27 | * File filter for Jreepad Encrypted XML .jree files. 28 | */ 29 | public static final FileFilter JREEPAD_ENCRYPTED_FILE_FILTER = new ExtensionFileFilter("Jreepad Encrypted XML file (*.jree) [EXPERIMENTAL]", "jree"); 30 | 31 | private int defaultFileFormat; 32 | 33 | public SaveFileChooser(int defaultFileFormat) 34 | { 35 | this.defaultFileFormat = defaultFileFormat; 36 | 37 | addChoosableFileFilter(JREEPAD_FILE_FILTER); 38 | addChoosableFileFilter(JREEPAD_ENCRYPTED_FILE_FILTER); 39 | addChoosableFileFilter(TREEPAD_FILE_FILTER); 40 | 41 | switch (defaultFileFormat) 42 | { 43 | case JreepadPrefs.FILETYPE_HJT: 44 | setFileFilter(TREEPAD_FILE_FILTER); 45 | break; 46 | case JreepadPrefs.FILETYPE_XML_ENCRYPTED: 47 | setFileFilter(JREEPAD_ENCRYPTED_FILE_FILTER); 48 | break; 49 | case JreepadPrefs.FILETYPE_XML: // default 50 | default: 51 | setFileFilter(JREEPAD_FILE_FILTER); 52 | break; 53 | } 54 | } 55 | 56 | /** 57 | * Returns the selected file type or the default file type 58 | * if "All files" filter is selected. 59 | */ 60 | public int getFileType() 61 | { 62 | if (getFileFilter() == SaveFileChooser.JREEPAD_FILE_FILTER) 63 | return JreepadPrefs.FILETYPE_XML; 64 | if (getFileFilter() == SaveFileChooser.TREEPAD_FILE_FILTER) 65 | return JreepadPrefs.FILETYPE_HJT; 66 | if (getFileFilter() == SaveFileChooser.JREEPAD_ENCRYPTED_FILE_FILTER) 67 | return JreepadPrefs.FILETYPE_XML_ENCRYPTED; 68 | return defaultFileFormat; 69 | } 70 | 71 | public void approveSelection() 72 | { 73 | if (!checkOverwrite(getSelectedFile())) 74 | return; // User doesn't want to overwrite the file 75 | if (getSelectedFile().isFile() && !getSelectedFile().canWrite()) 76 | { 77 | JOptionPane.showMessageDialog(this, LANG.getString("MSG_FILE_NOT_WRITEABLE"), 78 | LANG.getString("TITLE_FILE_ERROR"), JOptionPane.ERROR_MESSAGE); 79 | return; // Can't write selected file 80 | } 81 | super.approveSelection(); 82 | } 83 | 84 | private boolean checkOverwrite(File theFile) 85 | { 86 | // If file doesn't already exist then fine 87 | if (theFile == null || !theFile.exists()) 88 | return true; 89 | 90 | // Else we need to confirm 91 | return (JOptionPane.showConfirmDialog(this, LANG.getString("PROMPT_CONFIRM_OVERWRITE1") 92 | + " " + theFile.getName() + " " 93 | + LANG.getString("PROMPT_CONFIRM_OVERWRITE2"), 94 | LANG.getString("TITLE_CONFIRM_OVERWRITE"), JOptionPane.YES_NO_OPTION) 95 | == JOptionPane.YES_OPTION); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/jreepad/ui/PasswordDialog.java: -------------------------------------------------------------------------------- 1 | package jreepad.ui; 2 | 3 | import java.awt.Frame; 4 | import java.awt.event.WindowAdapter; 5 | import java.awt.event.WindowEvent; 6 | import java.beans.PropertyChangeEvent; 7 | import java.beans.PropertyChangeListener; 8 | 9 | import javax.swing.JDialog; 10 | import javax.swing.JLabel; 11 | import javax.swing.JOptionPane; 12 | import javax.swing.JPasswordField; 13 | 14 | public class PasswordDialog extends JDialog implements PropertyChangeListener 15 | { 16 | private JOptionPane optionPane; 17 | private JPasswordField pwdField1; 18 | private JPasswordField pwdField2; 19 | 20 | private String password = null; 21 | 22 | public PasswordDialog(String message, boolean confirm) 23 | { 24 | super((Frame)null, "Enter password", true); 25 | 26 | pwdField1 = new JPasswordField(); 27 | Object[] array; 28 | if (confirm) 29 | { 30 | pwdField2 = new JPasswordField(); 31 | array = new Object[] { new JLabel(message), pwdField1, new JLabel("confirm:"), pwdField2 }; 32 | } 33 | else 34 | { 35 | array = new Object[] { new JLabel(message), pwdField1 }; 36 | } 37 | 38 | optionPane = new JOptionPane(array, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 39 | optionPane.addPropertyChangeListener(this); 40 | setContentPane(optionPane); 41 | pack(); 42 | setLocationRelativeTo(null); 43 | 44 | addWindowListener(new WindowAdapter() { 45 | public void windowClosing(WindowEvent we) { 46 | optionPane.setValue(new Integer(JOptionPane.CLOSED_OPTION)); 47 | } 48 | }); 49 | } 50 | 51 | /** 52 | * Dialog button was pressed. 53 | */ 54 | public void propertyChange(PropertyChangeEvent e) 55 | { 56 | String prop = e.getPropertyName(); 57 | 58 | if (isVisible() && JOptionPane.VALUE_PROPERTY.equals(prop)) 59 | { 60 | Object value = optionPane.getValue(); 61 | if (value == JOptionPane.UNINITIALIZED_VALUE) 62 | return; 63 | optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE); 64 | if (value.equals(Integer.valueOf(JOptionPane.OK_OPTION))) 65 | { 66 | String pwd1 = new String(pwdField1.getPassword()); 67 | if (pwdField2 != null) 68 | { 69 | String pwd2 = new String(pwdField2.getPassword()); 70 | if (!pwd1.equals(pwd2)) 71 | { 72 | JOptionPane.showMessageDialog(this, "The passwords do not match"); 73 | return; 74 | } 75 | } 76 | password = new String(pwdField1.getPassword()); 77 | } 78 | setVisible(false); 79 | } 80 | } 81 | 82 | /** 83 | * Returns entered password or null if Cancel was pressed. 84 | */ 85 | public String getPassword() 86 | { 87 | return password; 88 | } 89 | 90 | /** 91 | * Shows password dialog. 92 | * @param message message to show in the dialog (e.g. "Please enter password:") 93 | * @param confirm whether to show second confirmation password field 94 | * @return enetered password or null if Cancel was pressed 95 | */ 96 | public static String showPasswordDialog(String message, boolean confirm) 97 | { 98 | PasswordDialog dialog = new PasswordDialog(message, confirm); 99 | dialog.setVisible(true); 100 | dialog.dispose(); // We don't need the dialog anymore 101 | return dialog.getPassword(); 102 | } 103 | 104 | public static String showPasswordDialog(String message) 105 | { 106 | return showPasswordDialog(message, false); 107 | } 108 | 109 | public static String showPasswordDialog(boolean confirm) 110 | { 111 | return showPasswordDialog("Please enter password:", confirm); 112 | } 113 | 114 | public static String showPasswordDialog() 115 | { 116 | return showPasswordDialog(false); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/jreepad/editor/TextTransferHandler.java: -------------------------------------------------------------------------------- 1 | package jreepad.editor; 2 | 3 | /** 4 | * 5 | * @author not attributable 6 | * @version 1.0 7 | */ 8 | import java.awt.datatransfer.DataFlavor; 9 | import java.awt.datatransfer.StringSelection; 10 | import java.awt.datatransfer.Transferable; 11 | import java.awt.datatransfer.UnsupportedFlavorException; 12 | 13 | import javax.swing.JComponent; 14 | import javax.swing.TransferHandler; 15 | import javax.swing.text.BadLocationException; 16 | import javax.swing.text.Document; 17 | import javax.swing.text.JTextComponent; 18 | import javax.swing.text.Position; 19 | 20 | /** 21 | * An implementation of TransferHandler that adds support for the 22 | * import and export of text using drag and drop and cut/copy/paste. 23 | */ 24 | public class TextTransferHandler extends TransferHandler { 25 | //Start and end position in the source text. 26 | //We need this information when performing a MOVE 27 | //in order to remove the dragged text from the source. 28 | private Position p0 = null; 29 | private Position p1 = null; 30 | 31 | public boolean importData(JComponent comp, 32 | Transferable t) { 33 | boolean insertDone = false; 34 | if(comp instanceof JTextComponent) { 35 | if (!t.isDataFlavorSupported(DataFlavor.stringFlavor)) { 36 | return false; 37 | } 38 | String data; 39 | try { 40 | data = (String) t.getTransferData(DataFlavor.stringFlavor); 41 | } 42 | catch (UnsupportedFlavorException e) { 43 | return false; 44 | } 45 | catch (java.io.IOException e) { 46 | return false; 47 | } 48 | JTextComponent tc = (JTextComponent) comp; 49 | tc.replaceSelection(data); 50 | insertDone = true; 51 | } 52 | return insertDone; 53 | } 54 | 55 | /** 56 | * Bundle up the data for export. 57 | */ 58 | protected Transferable createTransferable(JComponent comp) { 59 | Transferable transferData = null; 60 | if(comp instanceof JTextComponent) { 61 | JTextComponent source = (JTextComponent) comp; 62 | int start = source.getSelectionStart(); 63 | int end = source.getSelectionEnd(); 64 | if (start == end) { 65 | return null; 66 | } 67 | Document doc = source.getDocument(); 68 | try { 69 | p0 = doc.createPosition(start); 70 | p1 = doc.createPosition(end); 71 | } 72 | catch (BadLocationException e) { 73 | // unable to do a drag 74 | // should log this 75 | p0 = p1 = null; 76 | } 77 | String data = source.getSelectedText(); 78 | transferData = new StringSelection(data); 79 | } 80 | return transferData; 81 | } 82 | 83 | /** 84 | * These text fields handle both copy and move actions. 85 | */ 86 | public int getSourceActions(JComponent c) { 87 | return COPY_OR_MOVE; 88 | } 89 | 90 | /** 91 | * When the export is complete, remove the old text if the action 92 | * was a move. 93 | */ 94 | protected void exportDone(JComponent c, Transferable data, int action) { 95 | if (action != MOVE) { 96 | return; 97 | } 98 | 99 | if ((p0 != null) && (p1 != null) && 100 | (p0.getOffset() != p1.getOffset())) { 101 | try { 102 | JTextComponent tc = (JTextComponent)c; 103 | tc.getDocument().remove(p0.getOffset(), 104 | p1.getOffset() - p0.getOffset()); 105 | } catch (BadLocationException e) { 106 | System.out.println("Can't remove text from source."); 107 | } 108 | } 109 | } 110 | 111 | public boolean canImport(JComponent comp, 112 | DataFlavor[] transferFlavors) { 113 | boolean supported = false; 114 | for(int idx = 0; idx < transferFlavors.length && !supported; idx++) { 115 | supported = DataFlavor.stringFlavor.equals(transferFlavors[idx]); 116 | } 117 | return supported; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/jreepad/io/XmlWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.util.Enumeration; 25 | 26 | import javax.xml.transform.TransformerConfigurationException; 27 | import javax.xml.transform.sax.SAXTransformerFactory; 28 | import javax.xml.transform.sax.TransformerHandler; 29 | import javax.xml.transform.stream.StreamResult; 30 | import javax.xml.transform.OutputKeys; 31 | 32 | import jreepad.JreepadArticle; 33 | import jreepad.JreepadNode; 34 | import jreepad.JreepadTreeModel; 35 | 36 | import org.xml.sax.ContentHandler; 37 | import org.xml.sax.SAXException; 38 | import org.xml.sax.helpers.AttributesImpl; 39 | 40 | /** 41 | * Writes the Jreepad tree as XML. 42 | * 43 | * @version $Id$ 44 | */ 45 | public class XmlWriter 46 | implements JreepadWriter 47 | { 48 | public static final String NODE_TAG = "node"; 49 | public static final String TITLE_ATTRIBUTE = "title"; 50 | public static final String TYPE_ATTRIBUTE = "type"; 51 | public static final String NSU = ""; 52 | private AttributesImpl attributes = new AttributesImpl(); 53 | 54 | public XmlWriter() 55 | { 56 | attributes.addAttribute("", "", TITLE_ATTRIBUTE, "", ""); 57 | attributes.addAttribute("", "", TYPE_ATTRIBUTE, "", ""); 58 | } 59 | 60 | public void write(OutputStream out, JreepadTreeModel document) 61 | throws IOException 62 | { 63 | StreamResult result = new StreamResult(out); 64 | SAXTransformerFactory factory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); 65 | TransformerHandler handler; 66 | try 67 | { 68 | handler = factory.newTransformerHandler(); 69 | handler.getTransformer().setOutputProperty(OutputKeys.INDENT,"yes"); 70 | handler.getTransformer().setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0"); 71 | } 72 | catch (TransformerConfigurationException e) 73 | { 74 | throw new IOException(e.toString()); 75 | } 76 | handler.setResult(result); 77 | 78 | try 79 | { 80 | write(handler, document); 81 | } 82 | catch (SAXException e) 83 | { 84 | throw new IOException(e.toString()); 85 | } 86 | } 87 | 88 | private void write(ContentHandler handler, JreepadTreeModel document) throws SAXException 89 | { 90 | handler.startDocument(); 91 | writeNode(handler, document.getRootNode()); 92 | handler.endDocument(); 93 | } 94 | 95 | private void writeNode(ContentHandler handler, JreepadNode node) throws SAXException 96 | { 97 | String type; 98 | switch (node.getArticle().getArticleMode()) 99 | { 100 | case JreepadArticle.ARTICLEMODE_HTML: 101 | type = "text/html"; 102 | break; 103 | case JreepadArticle.ARTICLEMODE_TEXTILEHTML: 104 | type = "text/textile"; 105 | break; 106 | case JreepadArticle.ARTICLEMODE_CSV: 107 | type = "text/csv"; 108 | break; 109 | default: 110 | type = "text/plain"; 111 | break; 112 | } 113 | 114 | attributes.setValue(0, node.getTitle()); 115 | attributes.setValue(1, type); 116 | 117 | handler.startElement(NSU, NODE_TAG, NODE_TAG, attributes); 118 | String content = node.getContent(); 119 | handler.characters(content.toCharArray(), 0, content.length()); 120 | 121 | Enumeration kids = node.children(); 122 | while (kids.hasMoreElements()) 123 | writeNode(handler, (JreepadNode)kids.nextElement()); 124 | 125 | handler.endElement(NSU, NODE_TAG, NODE_TAG); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/jreepad/io/XmlReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | import javax.xml.parsers.ParserConfigurationException; 26 | import javax.xml.parsers.SAXParser; 27 | import javax.xml.parsers.SAXParserFactory; 28 | 29 | import jreepad.JreepadArticle; 30 | import jreepad.JreepadNode; 31 | import jreepad.JreepadPrefs; 32 | import jreepad.JreepadTreeModel; 33 | 34 | import org.xml.sax.Attributes; 35 | import org.xml.sax.SAXException; 36 | import org.xml.sax.helpers.DefaultHandler; 37 | 38 | /** 39 | * Reads XML input into Jreepad. 40 | * 41 | * @version $Id$ 42 | */ 43 | public class XmlReader implements JreepadReader 44 | { 45 | public static final String NODE_TAG = "node"; 46 | public static final String TITLE_ATTRIBUTE = "title"; 47 | public static final String TYPE_ATTRIBUTE = "type"; 48 | 49 | public JreepadTreeModel read(InputStream in) 50 | throws IOException 51 | { 52 | SAXParserFactory factory = SAXParserFactory.newInstance(); 53 | Handler handler = null; 54 | try 55 | { 56 | SAXParser parser = factory.newSAXParser(); 57 | handler = new Handler(); 58 | parser.parse(in, handler); 59 | } 60 | catch (ParserConfigurationException e) 61 | { 62 | throw new IOException(e.toString()); 63 | } 64 | catch (SAXException e) 65 | { 66 | throw new IOException(e.toString()); 67 | } 68 | 69 | JreepadTreeModel document = new JreepadTreeModel(handler.getRoot()); 70 | document.setFileType(JreepadPrefs.FILETYPE_XML); 71 | return document; 72 | } 73 | 74 | private class Handler extends DefaultHandler 75 | { 76 | JreepadNode root = null; 77 | JreepadNode currentNode = null; 78 | StringBuffer content = null; 79 | int articleMode; 80 | 81 | public void characters(char[] ch, int start, int length) throws SAXException 82 | { 83 | if (content != null) 84 | content.append(ch, start, length); 85 | } 86 | 87 | public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException 88 | { 89 | if (!qName.equals(NODE_TAG)) 90 | throw new SAXException("Unknown tag " + qName); 91 | 92 | // Save node content 93 | if (currentNode != null && content != null) 94 | currentNode.getArticle().setContent(content.toString()); 95 | content = new StringBuffer(); 96 | 97 | String title = attributes.getValue(TITLE_ATTRIBUTE); 98 | String type = attributes.getValue(TYPE_ATTRIBUTE); 99 | 100 | JreepadNode newNode = new JreepadNode(title, ""); 101 | if (currentNode != null) 102 | currentNode.add(newNode); 103 | currentNode = newNode; 104 | if (root == null) 105 | root = currentNode; 106 | 107 | int articleMode = JreepadArticle.ARTICLEMODE_ORDINARY; 108 | if (type.equals("text/csv")) 109 | articleMode = JreepadArticle.ARTICLEMODE_CSV; 110 | else if (type.equals("text/html")) 111 | articleMode = JreepadArticle.ARTICLEMODE_HTML; 112 | else if (type.equals("text/textile")) 113 | articleMode = JreepadArticle.ARTICLEMODE_TEXTILEHTML; 114 | //else if (type.equals("application/x-jreepad-softlink")) 115 | // articleMode = JreepadArticle.ARTICLEMODE_SOFTLINK; 116 | currentNode.getArticle().setArticleMode(articleMode); 117 | } 118 | 119 | public void endElement(String uri, String localName, String qName) throws SAXException 120 | { 121 | if (content != null) 122 | currentNode.getArticle().setContent(content.toString()); 123 | currentNode = currentNode.getParentNode(); 124 | content = null; 125 | } 126 | 127 | public JreepadNode getRoot() 128 | { 129 | return root; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /website/logo/index.php: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Source code for Jreepad - Java Treepad Viewer/Editor 7 | 8 | 36 | 37 | 38 | 39 | 40 | 41 | 67 | 94 | 95 |
42 |
43 | Jreepad 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

 

65 | SourceForge.net Logo 66 |
68 |

The Jreepad icon/logo

69 |

Can be downloaded here:

70 | 75 | 86 |

 

87 | 88 |
89 |

The Jreepad project was started by Dan Stowell.

90 |

This page last updated 91 | 5 February, 2005.

92 |
93 |

SourceForge.net Logo

96 | 97 | -------------------------------------------------------------------------------- /website/jar/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jreepad - Java Treepad Viewer/Editor 7 | 8 | 34 | 35 | 36 | 37 | 61 | 62 | 63 | 64 | 65 | 66 | 89 | 126 | 127 |
67 |
68 | Jreepad 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |

 

87 | SourceForge.net Logo 88 |
90 |

Jreepad - Using the .JAR file

91 |

If you've never used a Java .JAR file before, here's what to do:

92 |
    93 |
  • On some systems (not many!) you can double-click the file and it'll run just like a program.
  • 94 |
95 |
    96 |
  • On other systems (e.g. Linux) you may need to run it from the command line - for example:
  • 97 |
98 |
99 |
java -jar Jreepad-1.0.jar
100 |
101 |

 

102 |

The "-jar" option tells Java that it's dealing with a JAR file, which is a zipped-up collection of Java classes and other resources.

103 |

 

104 |

Troubleshooting:

105 |
    106 |
  1. First, check that you have Java 1.4 or later, because it won't run otherwise.
  2. 107 |
  3. Some people don't have the path to Java set correctly: 108 |
      109 |
    • Explicitly set your path before typing the java command. Try something like
      110 | export PATH=/usr/java/j2re1.4.1/bin:$PATH
      (this syntax works on Redhat Linux)
    • 111 |
    • Or, call java with the full path. 112 | For example:
      113 | /usr/java/j2re1.4.1/bin/java -jar Jreepad-1.0.jar
    • 114 |
    115 |
  4. 116 |
117 |

 

118 |

 

119 | 120 |
121 |

The Jreepad project was started by Dan Stowell.

122 |

This page last updated 123 | 25 July, 2004.

124 |
125 |

SourceForge.net Logo

128 | 129 | -------------------------------------------------------------------------------- /website/formats/index.htm: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jreepad - Java Treepad Viewer/Editor 7 | 8 | 36 | 37 | 38 | 39 | 40 | 41 | 67 | 107 | 108 |
42 |
43 | Jreepad 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

 

65 | SourceForge.net Logo 66 |
68 |

Jreepad uses two main file formats.

69 |

The first (and original) format is the .HJT format as used in Henk Hagedoorn's Windows-based "Treepad" software. I won't go into detail since I'm not responsible for maintaining the file format.

70 |

The second format is an XML-based format. It's very, very simple - there's essentially just one type of element, the <node> element. Look at this simple example:

71 |
<?xml version="1.0" encoding="utf-8"?>
 72 | <node xmlns="http://jreepad.sourceforge.net/formats" type="text/plain" title="My notes">
 73 |   These are my notes. They're very interesting.
 74 |   <node type="text/csv" title="Things to do">Thing to do,Day
 75 |     Tidy house,Sunday
 76 |     Wash face,Monday
 77 |     Go to work,Monday
 78 |     Eat food,Wednesday
 79 |   </node>
 80 |   <node type="text/plain" title="Web address">
 81 |     http://www.flatfourradio.co.uk/
 82 |   </node>
 83 | </node>
 84 | 
85 |

This simple Jreepad file consists of three nodes - the root node, with two child nodes. Any node can contain text, optionally followed by further <node> elements representing that node's children. This nesting can go on indefinitely.

86 |

Node attributes:

87 |
    88 |
  • The title attribute simply stores the node's title. It's mandatory, but can be empty (not a good idea for it to be empty though!).
  • 89 |
  • The type attribute tells us what format the node content is. This attribute is optional. Choices: 90 |
      91 |
    • "text/plain" - the default, which Jreepad was originally designed for, is plain text;
    • 92 |
    • "text/csv" for comma-separated data which Jreepad interprets into a tabular format;
    • 93 |
    • "text/html" for HTML-formatted content which Jreepad will render using Java's built-in HTML rendering capability;
    • 94 |
    • "application/x-jreepad-softlink" designates a node which is merely a "soft-link" to another node.
    • 95 |
    96 |
  • 97 |
98 |

Character encodings: any character encoding should be OK in theory. Jreepad happily supports ISO-8859-1, UTF-8, UTF-16, and others.

99 |

 

100 | 101 |
102 |

The Jreepad project was started by Dan Stowell.

103 |

This page last updated 104 | 13 February, 2005.

105 |
106 |

SourceForge.net Logo

109 | 110 | -------------------------------------------------------------------------------- /src/jreepad/io/TreepadReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.InputStreamReader; 25 | import java.io.LineNumberReader; 26 | import java.util.Stack; 27 | 28 | import jreepad.JreepadArticle; 29 | import jreepad.JreepadNode; 30 | import jreepad.JreepadPrefs; 31 | import jreepad.JreepadTreeModel; 32 | 33 | /** 34 | * Reads a treepad file into Jreepad. 35 | * 36 | * @version $Id$ 37 | */ 38 | public class TreepadReader implements JreepadReader 39 | { 40 | 41 | private boolean autoDetectHtmlArticles; 42 | 43 | private String encoding; 44 | 45 | private int fileFormat; 46 | 47 | public TreepadReader(String encoding, boolean autoDetectHtmlArticles) 48 | { 49 | this.encoding = encoding; 50 | this.autoDetectHtmlArticles = autoDetectHtmlArticles; 51 | } 52 | 53 | public JreepadTreeModel read(InputStream in) 54 | throws IOException 55 | { 56 | LineNumberReader reader = new LineNumberReader(new InputStreamReader(in, encoding)); 57 | reader.readLine(); // skip first line // TODO check for treepadness 58 | 59 | Stack nodeStack = new Stack(); 60 | int depthMarker; 61 | JreepadNode newNode; 62 | JreepadNode rootNode = null; 63 | String dtLine, nodeLine, titleLine, depthLine; 64 | StringBuffer currentContent; 65 | String currentLine; 66 | dtLine = "dt=text"; 67 | 68 | while ((fileFormat == 2 || (dtLine = reader.readLine()) != null) 69 | && (nodeLine = reader.readLine()) != null && (titleLine = reader.readLine()) != null 70 | && (depthLine = reader.readLine()) != null) 71 | { 72 | // Read "dt=text" [or error] - NB THE OLDER FORMAT DOESN'T INCLUDE THIS LINE SO WE SKIP 73 | // IT 74 | if (dtLine.equals("") && nodeLine.startsWith("")) 75 | throw new IOException( 76 | "This is not a Treepad-Lite-compatible file!\n\nFiles created in more advanced versions of Treepad\ncontain features that are not available in Jreepad."); 77 | 78 | if (fileFormat != 2) 79 | if (!(dtLine.toLowerCase().startsWith("dt=text"))) 80 | throw new IOException("Unrecognised node dt format at line " + reader.getLineNumber() + ": " 81 | + dtLine); 82 | // Read "" [or error] 83 | if (!(nodeLine.toLowerCase().startsWith(""))) 84 | throw new IOException("Unrecognised node format at line " + (reader.getLineNumber() + 1) + ": " 85 | + nodeLine); 86 | 87 | // Read THE CONTENT! [loop until we find " 5P9i0s8y19Z"] 88 | currentContent = new StringBuffer(); 89 | while ((currentLine = reader.readLine()) != null 90 | && !currentLine.equals(" 5P9i0s8y19Z")) 91 | { 92 | currentContent.append(currentLine + "\n"); 93 | } 94 | 95 | // Now, having established the content and the title and the depth, we'll create the 96 | // child 97 | String content = currentContent.substring(0, Math.max(currentContent.length() - 1, 0)); 98 | newNode = new JreepadNode(titleLine, content); 99 | // babyNode = new JreepadNode(titleLine, currentContent.substring(0, 100 | // Math.max(currentContent.length()-2,0)), 101 | // (JreepadNode)(nodeStack.peek())); 102 | 103 | // Turn it into a HTML-mode node if it matches " ... " 104 | String compareContent = newNode.getContent().toLowerCase().trim(); 105 | int newArticleMode = (autoDetectHtmlArticles && compareContent.startsWith("") && compareContent 106 | .endsWith("")) ? JreepadArticle.ARTICLEMODE_HTML : JreepadArticle.ARTICLEMODE_ORDINARY; 107 | newNode.getArticle().setArticleMode(newArticleMode); 108 | 109 | if (depthLine.equals("0")) 110 | { 111 | rootNode = newNode; 112 | } 113 | else 114 | { 115 | depthMarker = Integer.parseInt(depthLine); 116 | while (nodeStack.size() > depthMarker) 117 | nodeStack.pop(); 118 | 119 | ((JreepadNode)(nodeStack.peek())).add(newNode); 120 | } 121 | nodeStack.push(newNode); 122 | } 123 | 124 | JreepadTreeModel document = new JreepadTreeModel(rootNode); 125 | document.setFileType(JreepadPrefs.FILETYPE_HJT); 126 | document.setEncoding(encoding); 127 | return document; 128 | } 129 | 130 | public boolean isAutoDetectHtmlArticles() 131 | { 132 | return autoDetectHtmlArticles; 133 | } 134 | 135 | public void setAutoDetectHtmlArticles(boolean autoDetectHtmlArticles) 136 | { 137 | this.autoDetectHtmlArticles = autoDetectHtmlArticles; 138 | } 139 | 140 | public String getEncoding() 141 | { 142 | return encoding; 143 | } 144 | 145 | public void setEncoding(String encoding) 146 | { 147 | this.encoding = encoding; 148 | } 149 | 150 | public int getFileFormat() 151 | { 152 | return fileFormat; 153 | } 154 | 155 | public void setFileFormat(int fileFormat) 156 | { 157 | this.fileFormat = fileFormat; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /website/screenshots/index.html: -------------------------------------------------------------------------------- 1 | Jreepad - Java Treepad Viewer/Editor
Jreepad

 

SourceForge.net Logo

Jreepad screenshots

Click on any screenshot to see a nice large version.

Mac OSX:
Click for screenshot of Jreepad on Mac OSX Click for screenshot of Jreepad on Mac OSX
Ubuntu 9.04:
Click for screenshot of Jreepad on Ubuntu
SuSE Linux 8.2 Pro:
Click for screenshot
Windows XP Pro:
Click for screenshot
Solaris 9:
Windows 98:
Click for screenshot of Jreepad on Windows 98

 

 

Send us your screenshots! If you are using Jreepad on an OS that isn't displayed here, it'd be nice for potential users to be able to see screenshots on their OS!

Email me at danstowell [to circumvent spam robots I'm not writing the email address normally] at users.sourceforge.net


The Jreepad project was started by Dan Stowell.

This page last updated 8 March, 2005.


SourceForge.net Logo

-------------------------------------------------------------------------------- /src/jreepad/JreepadSearcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad; 21 | 22 | /* 23 | import javax.swing.*; 24 | import javax.swing.event.*; 25 | import javax.swing.text.BadLocationException; 26 | import javax.swing.text.*; 27 | import java.awt.*; 28 | import java.awt.event.*; 29 | import java.io.*; 30 | import java.awt.print.*; 31 | */ 32 | import java.util.Vector; 33 | import javax.swing.tree.*; 34 | import java.util.Enumeration; 35 | 36 | /* 37 | 38 | This class provides the functionality to search a Jreepad tree. 39 | 40 | It's separate so that it can be used by the graphical Jreepad application as 41 | easily as by a command-line tool... 42 | 43 | */ 44 | public class JreepadSearcher 45 | { 46 | 47 | JreepadNode root; 48 | public JreepadSearcher(JreepadNode root) 49 | { 50 | this.root = root; 51 | } 52 | 53 | 54 | private JreepadSearchResult[] searchResults; 55 | private Vector searchResultsVec; 56 | private Object foundObject; 57 | public boolean performSearch(String inNodes, String inArticles, TreePath pathToSearchStart, 58 | boolean orNotAnd, boolean caseSensitive, int maxResults) 59 | { 60 | searchResults = null; 61 | searchResultsVec = new Vector(); 62 | 63 | // System.out.println("JreepadSearcher.performSearch: pathToSearchStart = " + pathToSearchStart); 64 | 65 | // recursiveSearchNode(inNodes, inArticles, root, pathToSearchStart, orNotAnd, caseSensitive, maxResults); 66 | recursiveSearchNode(inNodes, inArticles, (JreepadNode)pathToSearchStart.getLastPathComponent(), pathToSearchStart, orNotAnd, caseSensitive, maxResults); 67 | 68 | searchResults = new JreepadSearchResult[searchResultsVec.size()]; 69 | for(int i=0; i=maxResults) return; 81 | 82 | String quoteText; 83 | 84 | // These things ensure case-sensitivity behaves 85 | String casedInNodes = caseSensitive ? inNodes : inNodes.toUpperCase(); 86 | String casedInArticles = caseSensitive ? inArticles : inArticles.toUpperCase(); 87 | String casedNode = caseSensitive ? thisNode.getTitle() : thisNode.getTitle().toUpperCase(); 88 | String casedArticle = caseSensitive ? thisNode.getContent() : thisNode.getContent().toUpperCase(); 89 | 90 | // Look in current node. If it matches criteria, add "pathSoFar" to the Vector 91 | boolean itMatches; 92 | boolean nodeMatches = inNodes.equals("") || casedNode.indexOf(casedInNodes)!=-1; 93 | boolean articleMatches = inArticles.equals("") || casedArticle.indexOf(casedInArticles)!=-1; 94 | 95 | 96 | if(inNodes.equals("") && inArticles.equals("")) 97 | itMatches = false; 98 | else if(inNodes.equals("")) // Only looking in articles 99 | itMatches = articleMatches; 100 | else if(inArticles.equals("")) // Only looking in nodes 101 | itMatches = nodeMatches; 102 | else // Looking in both 103 | if(orNotAnd) // Use OR combinator 104 | itMatches = nodeMatches || articleMatches; 105 | else // Use AND combinator 106 | itMatches = nodeMatches && articleMatches; 107 | 108 | 109 | if(itMatches) 110 | { 111 | if(!articleMatches) 112 | { 113 | if(thisNode.getContent().length()>articleQuoteMaxLen) 114 | quoteText = thisNode.getContent().substring(0,articleQuoteMaxLen) + "..."; 115 | else 116 | quoteText = thisNode.getContent(); 117 | } 118 | else 119 | { 120 | quoteText = ""; 121 | int start = casedArticle.indexOf(casedInArticles); 122 | String substring; 123 | if(start>0) 124 | quoteText += "..."; 125 | else 126 | start = 0; 127 | substring = thisNode.getContent(); 128 | if(substring.length() > articleQuoteMaxLen) 129 | quoteText += substring.substring(0,articleQuoteMaxLen) + "..."; 130 | else 131 | quoteText += thisNode.getContent().substring(start); 132 | } 133 | searchResultsVec.add(new JreepadSearchResult(pathSoFar, quoteText, thisNode)); 134 | // System.out.println("Positive match: "+thisNode); 135 | } 136 | 137 | // Whether or not it matches, make the recursive call on the children 138 | Enumeration getKids = thisNode.children(); 139 | JreepadNode thisKid; 140 | while(getKids.hasMoreElements()) 141 | { 142 | thisKid = (JreepadNode)getKids.nextElement(); 143 | recursiveSearchNode(inNodes, inArticles, thisKid, pathSoFar.pathByAddingChild(thisKid), 144 | orNotAnd, caseSensitive, maxResults); 145 | } 146 | } 147 | public JreepadSearchResult[] getSearchResults() 148 | { 149 | return searchResults; 150 | } 151 | public class JreepadSearchResult 152 | { 153 | private TreePath treePath; 154 | private String articleQuote; 155 | private JreepadNode node; 156 | public JreepadSearchResult(TreePath treePath, String articleQuote, JreepadNode node) 157 | { 158 | this.treePath = treePath; 159 | this.articleQuote = articleQuote; 160 | this.node = node; 161 | } 162 | public String getArticleQuote() { return articleQuote; } 163 | public TreePath getTreePath() { return treePath; } 164 | public JreepadNode getNode() { return node; } 165 | } 166 | 167 | 168 | } -------------------------------------------------------------------------------- /website/developers/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Source code for Jreepad - Java Treepad Viewer/Editor 7 | 8 | 36 | 37 | 38 | 39 | 40 | 41 | 67 | 130 | 131 |
42 |
43 | Jreepad 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |

 

65 | SourceForge.net Logo 66 |
68 |

Developing/compiling Jreepad

69 |
70 |

Source code

71 |

Two ways to get the source code:

72 | 76 |

 

77 |
78 |
79 |

Compiling Jreepad

80 |

Compiling Jreepad is easy - from the command-line I just type

81 |
82 |

javac jreepad/JreepadViewer.java

83 |
84 |

Actually, that's not quite true, because now I use Apache Ant which is an excellent tool to help you compile projects and do various other things, nice and automatically. So instead, I type

85 |
86 |

ant

87 |
88 |

and that does everything for me (including moving files around, packaging up the source code for release, etc). Make sure you're in the directory which contains Jreepad's "build.xml" file when you do this. (Mac developers will also need the 'extra treat' mentioned below.)

89 |

Non-Mac developers

90 |

If you're compiling Jreepad on a non-Mac platform, you'll need to download a small JAR file from Apple and put it into your classpath:

91 |
92 |

AppleJavaExtensions (ZIP file, 3.6kB)

93 |
94 |

Why?

95 |

Jreepad is platform-neutral, but if you're on Mac OSX then a couple of little adjustments occur to make Jreepad fit more neatly into the OSX environment. If you're not on Mac then these adjustments simply don't happen - they should not cause any problems.

96 |

Jreepad users don't even need to have the "AppleJavaExtensions" in their systems, since if the extensions aren't found (by reflection) then Jreepad won't attempt to use them. But you do need those packages to exist if you're compiling.

97 |

An extra treat for Mac developers

98 |

The Jarbundler ant task makes it easy to create 99 | the Mac OSX application package, directly from the ant build. It even incorporates the icon files 100 | and document associations (if you're using v1.6.1 or later).

101 |

Thanks to Will Gilbert for maintaining and improving that tool.

102 |
103 |
104 |

Contributors

105 |

Jreepad was originated by Dan Stowell, and is maintained by:

106 | 107 |
    108 |
  • Dan Stowell
  • 109 |
  • Przemek Wiech
  • 110 |
111 | 112 |

Thanks to the following other people (in no particular order) for contributing or suggesting code improvements:

113 |
    114 |
  • Jason Lawrence Justice
  • 115 |
  • Coen Schalkwijk
  • 116 |
  • Mikhail Bakhtin
  • 117 |
  • "ExileInParadise"
  • 118 |
  • Phani Kandula
  • 119 |
  • Sander Oom
  • 120 |
  • Plus various anonymous people posting comments to the project page...
  • 121 |
122 |
123 | 124 |
125 |

The Jreepad project was started by Dan Stowell.

126 |

This page last updated 127 | February 2010.

128 |
129 |

SourceForge.net Logo

132 | 133 | 134 | -------------------------------------------------------------------------------- /src/jreepad/io/HtmlWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.io.OutputStreamWriter; 25 | import java.io.StringWriter; 26 | import java.io.Writer; 27 | import java.util.Enumeration; 28 | 29 | import jreepad.JreepadArticle; 30 | import jreepad.JreepadNode; 31 | import jreepad.JreepadTreeModel; 32 | 33 | /** 34 | * Writes the Jreepad tree as HTML. 35 | * 36 | * @version $Id$ 37 | */ 38 | public class HtmlWriter 39 | implements JreepadWriter 40 | { 41 | private String encoding; 42 | private int exportMode; 43 | private boolean urlsToLinks; 44 | private int anchorType; 45 | private boolean causeToPrint; 46 | 47 | /** 48 | * Constructs the writer. 49 | */ 50 | public HtmlWriter(String encoding, int exportMode, boolean urlsToLinks, int anchorType) 51 | { 52 | this(encoding, exportMode, urlsToLinks, anchorType, false); 53 | } 54 | 55 | /** 56 | * Constructs the writer. 57 | */ 58 | public HtmlWriter(String encoding, int exportMode, boolean urlsToLinks, int anchorType, boolean causeToPrint) 59 | { 60 | this.encoding = encoding; 61 | this.exportMode = exportMode; 62 | this.urlsToLinks = urlsToLinks; 63 | this.anchorType = anchorType; 64 | this.causeToPrint = causeToPrint; 65 | } 66 | 67 | /** 68 | * Writes the tree to the output stream starting from selected node. 69 | * @param out output stream 70 | * @param document document to export 71 | */ 72 | public void write(OutputStream out, JreepadTreeModel document) 73 | throws IOException 74 | { 75 | Writer writer = new OutputStreamWriter(out, encoding); 76 | write(writer, document.getRootNode()); 77 | out.flush(); 78 | out.close(); 79 | } 80 | 81 | /** 82 | * Writes the tree to a string starting from selected node. 83 | * @param node root node 84 | */ 85 | public String write(JreepadNode node) 86 | { 87 | Writer writer = new StringWriter(); 88 | try 89 | { 90 | write(writer, node); 91 | } 92 | catch (IOException e) 93 | { 94 | e.printStackTrace(); 95 | return ""; 96 | } 97 | return writer.toString(); 98 | } 99 | 100 | /** 101 | * Writes the tree to the given writer starting from selected node. 102 | * @param writer output writer 103 | * @param node root node 104 | */ 105 | public void write(Writer writer, JreepadNode node) throws IOException 106 | { 107 | writer.write("\n\n\n\n"); 108 | writer.write(htmlSpecialChars(node.getTitle())); 109 | writer.write("\n\n\n\n\n\n
"); 113 | writeNode(writer, node); 114 | writer.write("\n
\n\n"); 115 | } 116 | 117 | /** 118 | * Writes the node and its children to the writer. 119 | * @param writer output writer 120 | * @param node root node 121 | */ 122 | public void writeNode(Writer writer, JreepadNode node) throws IOException 123 | { 124 | writer.write("\n
"); 130 | writer.write(htmlSpecialChars(node.getTitle())); 131 | writer.write("
\n
"); 132 | 133 | // Write out the node's article content - using normal, preformatted, or HTML modes as 134 | // appropriate 135 | writer.write(node.getArticle().toHtml(exportMode, urlsToLinks, anchorType)); 136 | 137 | if (node.getChildCount() > 0) 138 | writer.write("\n
"); 139 | Enumeration kids = node.children(); 140 | while (kids.hasMoreElements()) 141 | writeNode(writer, (JreepadNode)kids.nextElement()); 142 | if (node.getChildCount() > 0) 143 | writer.write("\n
"); 144 | writer.write("
"); 145 | } 146 | 147 | /** 148 | * Replaces special characters to HTML entities. 149 | */ 150 | private static String htmlSpecialChars(String in) 151 | { 152 | char[] c = in.toCharArray(); 153 | StringBuffer ret = new StringBuffer(); 154 | for (int i = 0; i < c.length; i++) 155 | if (c[i] == '<') 156 | ret.append("<"); 157 | else if (c[i] == '>') 158 | ret.append(">"); 159 | else if (c[i] == '&') 160 | ret.append("&"); 161 | else if (c[i] == '\n') 162 | ret.append("
\n"); 163 | else if (c[i] == '"') 164 | ret.append("""); 165 | else 166 | ret.append(c[i]); 167 | return ret.toString(); 168 | } 169 | 170 | public int getAnchorType() 171 | { 172 | return anchorType; 173 | } 174 | 175 | public void setAnchorType(int anchorType) 176 | { 177 | this.anchorType = anchorType; 178 | } 179 | 180 | public boolean isCauseToPrint() 181 | { 182 | return causeToPrint; 183 | } 184 | 185 | public void setCauseToPrint(boolean causeToPrint) 186 | { 187 | this.causeToPrint = causeToPrint; 188 | } 189 | 190 | public String getEncoding() 191 | { 192 | return encoding; 193 | } 194 | 195 | public void setEncoding(String encoding) 196 | { 197 | this.encoding = encoding; 198 | } 199 | 200 | public int getExportMode() 201 | { 202 | return exportMode; 203 | } 204 | 205 | public void setExportMode(int exportMode) 206 | { 207 | this.exportMode = exportMode; 208 | } 209 | 210 | public boolean isUrlsToLinks() 211 | { 212 | return urlsToLinks; 213 | } 214 | 215 | public void setUrlsToLinks(boolean urlsToLinks) 216 | { 217 | this.urlsToLinks = urlsToLinks; 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /src/jreepad/editor/PlainTextEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.editor; 21 | 22 | import javax.swing.event.CaretEvent; 23 | import javax.swing.event.CaretListener; 24 | import javax.swing.event.UndoableEditEvent; 25 | import javax.swing.event.UndoableEditListener; 26 | import javax.swing.text.AbstractDocument; 27 | import javax.swing.text.BadLocationException; 28 | import javax.swing.text.BoxView; 29 | import javax.swing.text.ComponentView; 30 | import javax.swing.text.Document; 31 | import javax.swing.text.Element; 32 | import javax.swing.text.IconView; 33 | import javax.swing.text.LabelView; 34 | import javax.swing.text.StyleConstants; 35 | import javax.swing.text.StyledEditorKit; 36 | import javax.swing.text.View; 37 | import javax.swing.text.ViewFactory; 38 | 39 | import jreepad.JreepadArticle; 40 | import jreepad.JreepadPrefs; 41 | import jreepad.JreepadView; 42 | 43 | /** 44 | * The plain text editor pane. 45 | */ 46 | public class PlainTextEditor extends EditorPaneView implements CaretListener, UndoableEditListener 47 | { 48 | private ContentChangeListener contentChangeListener = null; 49 | 50 | public PlainTextEditor(JreepadArticle article) 51 | { 52 | super("text/plain", article); 53 | editorPane.setEditable(true); 54 | 55 | if (getPrefs().wrapToWindow) 56 | editorPane.setEditorKit(new JPEditorKit()); 57 | 58 | // Add a listener to make sure the editorpane's content is always stored 59 | // when it changes 60 | editorPane.addCaretListener(this); 61 | editorPane.getDocument().addUndoableEditListener(this); 62 | } 63 | 64 | public void insertText(String text) 65 | { 66 | Document doc = editorPane.getDocument(); 67 | int here = editorPane.getCaretPosition(); 68 | try 69 | { 70 | editorPane.setText(doc.getText(0, here) + text 71 | + doc.getText(here, doc.getLength() - here)); 72 | editorPane.setCaretPosition(here + text.length()); 73 | } 74 | catch (BadLocationException e) 75 | { 76 | // Simply ignore this 77 | } 78 | } 79 | 80 | public void setContentChangeListener(ContentChangeListener listener) 81 | { 82 | contentChangeListener = listener; 83 | } 84 | 85 | private void notifyContentChangeListener() 86 | { 87 | if (contentChangeListener != null) 88 | contentChangeListener.contentChanged(); 89 | } 90 | 91 | public String selectWordUnderCursor() 92 | { 93 | try 94 | { 95 | String text = editorPane.getText(); 96 | int startpos = editorPane.getCaretPosition(); 97 | int endpos = startpos; 98 | if (text.length() > 0) 99 | { 100 | // Select the character before/after the current position, and 101 | // grow it until we hit whitespace... 102 | while (startpos > 0 && !Character.isWhitespace(editorPane.getText(startpos - 1, 1).charAt(0))) 103 | startpos--; 104 | while (endpos < (text.length()) && !Character.isWhitespace(editorPane.getText(endpos, 1).charAt(0))) 105 | endpos++; 106 | if (endpos > startpos) 107 | { 108 | editorPane.setSelectionStart(startpos); 109 | editorPane.setSelectionEnd(endpos); 110 | return getSelectedText(); 111 | } 112 | } 113 | } 114 | catch (BadLocationException e) 115 | { 116 | } 117 | return ""; 118 | } 119 | 120 | public void caretUpdate(CaretEvent e) 121 | { 122 | if (editLocked) 123 | return; // i.e. we are deactivated while changing from node to node 124 | if (article.getArticleMode() != JreepadArticle.ARTICLEMODE_ORDINARY) 125 | return; // i.e. we are only relevant when in plain-text mode 126 | 127 | if (!editorPane.getText().equals(article.getContent())) 128 | { 129 | // System.out.println("UPDATE - I'd now overwrite node content with 130 | // editorpane content"); 131 | article.setContent(editorPane.getText()); 132 | notifyContentChangeListener(); 133 | } 134 | else 135 | { 136 | // System.out.println(" No need to update content."); 137 | } 138 | } 139 | 140 | public static JreepadPrefs getPrefs() 141 | { 142 | return JreepadView.getPrefs(); 143 | } 144 | 145 | // Code to ensure that the article word-wraps follows 146 | // - contributed by Michael Labhard based on code found on the web... 147 | private static class JPEditorKit extends StyledEditorKit 148 | { 149 | public ViewFactory getViewFactory() 150 | { 151 | return new JPRTFViewFactory(); 152 | } 153 | } 154 | 155 | private static class JPRTFViewFactory implements ViewFactory 156 | { 157 | public View create(Element elem) 158 | { 159 | String kind = elem.getName(); 160 | if (kind != null) 161 | if (kind.equals(AbstractDocument.ContentElementName)) 162 | { 163 | return new LabelView(elem); 164 | } 165 | else if (kind.equals(AbstractDocument.ParagraphElementName)) 166 | { 167 | return new JPParagraphView(elem); 168 | } 169 | else if (kind.equals(AbstractDocument.SectionElementName)) 170 | { 171 | return new BoxView(elem, View.Y_AXIS); 172 | } 173 | else if (kind.equals(StyleConstants.ComponentElementName)) 174 | { 175 | return new ComponentView(elem); 176 | } 177 | else if (kind.equals(StyleConstants.IconElementName)) 178 | { 179 | return new IconView(elem); 180 | } 181 | // default to text display 182 | return new LabelView(elem); 183 | } 184 | } 185 | 186 | private static short paraRightMargin = 0; 187 | 188 | static class JPParagraphView extends javax.swing.text.ParagraphView 189 | { 190 | public JPParagraphView(Element e) 191 | { 192 | super(e); 193 | this.setInsets((short) 0, (short) 0, (short) 0, paraRightMargin); 194 | } 195 | } 196 | // Code to ensure that the article word-wraps ends here 197 | // - contributed by Michael Labhard 198 | 199 | //This one listens for edits that can be undone. 200 | public void undoableEditHappened(UndoableEditEvent e) { 201 | 202 | // System.out.println("Undoable event is " + 203 | // (e.getEdit().isSignificant()?"":"NOT ") + "significant"); 204 | // System.out.println("Undoable event source: " + e.getEdit()); 205 | 206 | // Remember the edit and update the menus. 207 | 208 | if(!editLocked) { 209 | // System.out.println("Storing undoable event for node " + 210 | // getCurrentNode().getTitle()); 211 | // System.out.println(" Event is " + 212 | // e.getEdit().getPresentationName() ); 213 | // if(getCurrentNode().lastEditStyle != 214 | // e.getEdit().getPresentationName()){ 215 | // System.out.println(" This is a SIGNIFICANT change."); 216 | // } 217 | // System.out.println(" Content: " + getCurrentNode().getContent()); 218 | // System.out.println(" Node undoMgr: " + getCurrentNode().undoMgr); 219 | // Thread.currentThread().dumpStack(); 220 | article.getUndoMgr().addEdit(e.getEdit()); 221 | } 222 | // undoAction.updateUndoState(); 223 | // redoAction.updateRedoState(); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/jreepad/TreeView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad; 21 | 22 | import java.awt.Cursor; 23 | import java.awt.event.MouseAdapter; 24 | import java.awt.event.MouseEvent; 25 | import java.util.Enumeration; 26 | import java.util.Vector; 27 | 28 | import javax.swing.JTree; 29 | import javax.swing.tree.DefaultTreeCellRenderer; 30 | import javax.swing.tree.TreePath; 31 | import javax.swing.tree.TreeSelectionModel; 32 | 33 | 34 | 35 | /** 36 | * The GUI component that displays the tree. 37 | * 38 | * @version $Id$ 39 | */ 40 | public class TreeView extends JTree 41 | { 42 | private JreepadTreeModel treeModel; 43 | 44 | public TreeView(JreepadTreeModel treeModel) 45 | { 46 | super(treeModel); 47 | this.treeModel = treeModel; 48 | 49 | getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 50 | setExpandsSelectedPaths(true); 51 | setInvokesStopCellEditing(true); 52 | setEditable(true); 53 | 54 | DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); 55 | renderer.setOpenIcon(null); 56 | renderer.setClosedIcon(null); 57 | renderer.setLeafIcon(null); 58 | setCellRenderer(renderer); 59 | 60 | // Add mouse listener - this will be used to implement drag-and-drop, context menu (?), etc 61 | addMouseListener(new TreeViewMouseListener()); 62 | } 63 | 64 | public void moveNode(JreepadNode node, JreepadNode newParent) 65 | { 66 | // First we need to make sure that the node is not a parent of the new parent 67 | // - otherwise things would go really wonky! 68 | if (node.isNodeDescendant(newParent)) 69 | return; 70 | 71 | JreepadNode oldParent = node.getParentNode(); 72 | 73 | // Now make a note of the expanded/collapsed state of the subtree of the moving node 74 | boolean thisOnesExpanded = isExpanded(getSelectionPath()); 75 | Enumeration enumer; 76 | Vector expanded; 77 | if (thisOnesExpanded) 78 | { 79 | enumer = getExpandedDescendants(getSelectionPath()); 80 | expanded = new Vector(); 81 | while (enumer.hasMoreElements()) 82 | expanded.add(enumer.nextElement()); 83 | } 84 | 85 | newParent.add(node); // Also removes from old parent 86 | 87 | treeModel.reload(oldParent); 88 | treeModel.reload(newParent); 89 | 90 | // If the destination node didn't previously have any children, then we'll expand it 91 | // if(newParent.getChildCount()==1) 92 | 93 | // Reapply the expanded/collapsed states 94 | 95 | } 96 | 97 | public void expandAll(JreepadNode thisNode, TreePath tp) 98 | { 99 | // It's at this point that we expand the current element 100 | expandPath(tp); 101 | 102 | Enumeration getKids = thisNode.children(); 103 | JreepadNode thisKid; 104 | while (getKids.hasMoreElements()) 105 | { 106 | thisKid = (JreepadNode)getKids.nextElement(); 107 | expandAll(thisKid, tp.pathByAddingChild(thisKid)); 108 | } 109 | } 110 | 111 | public void collapseAll(JreepadNode thisNode, TreePath tp) 112 | { 113 | Enumeration getKids = thisNode.children(); 114 | JreepadNode thisKid; 115 | while (getKids.hasMoreElements()) 116 | { 117 | thisKid = (JreepadNode)getKids.nextElement(); 118 | collapseAll(thisKid, tp.pathByAddingChild(thisKid)); 119 | } 120 | // It's at this point that we collapse the current element 121 | collapsePath(tp); 122 | } 123 | 124 | public TreePath[] getAllExpandedPaths() 125 | { 126 | JreepadNode root = (JreepadNode)treeModel.getRoot(); 127 | if (root.getChildCount() == 0) 128 | return new TreePath[] { new TreePath(root) }; 129 | 130 | Enumeration getPaths = getExpandedDescendants(new TreePath(root)); 131 | TreePath thisKid; 132 | Vector allPaths = new Vector(); 133 | while (getPaths.hasMoreElements()) 134 | { 135 | thisKid = (TreePath)getPaths.nextElement(); 136 | allPaths.add(thisKid); 137 | } 138 | TreePath[] ret = new TreePath[allPaths.size()]; 139 | for (int i = 0; i < ret.length; i++) 140 | ret[i] = (TreePath)allPaths.get(i); 141 | return ret; 142 | } 143 | 144 | // THIS FUNCTION SEEMS TO HAVE NO EFFECT, ON MY MACHINE AT LEAST! WHAT'S GOING ON? 145 | public void expandPaths(TreePath[] paths) 146 | { 147 | for (int i = 0; i < paths.length; i++) 148 | { 149 | expandPath(paths[i]); 150 | } 151 | } 152 | 153 | /** 154 | * Mouse control for the Tree View. 155 | */ 156 | private class TreeViewMouseListener 157 | extends MouseAdapter 158 | { 159 | private JreepadNode currentDragDropNode; 160 | 161 | public void mousePressed(MouseEvent e) 162 | { 163 | TreePath selPath = getPathForLocation(e.getX(), e.getY()); 164 | if (selPath != null) 165 | { 166 | currentDragDropNode = (JreepadNode)selPath.getLastPathComponent(); 167 | setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 168 | } 169 | } 170 | 171 | public void mouseReleased(MouseEvent e) 172 | { 173 | TreePath selPath = getPathForLocation(e.getX(), e.getY()); 174 | // System.out.println("Mouse released: path = " + selPath); 175 | if (selPath != null) 176 | { 177 | if (currentDragDropNode != null 178 | && currentDragDropNode.getParentNode() != null 179 | && currentDragDropNode.getParentNode() != (JreepadNode)selPath 180 | .getLastPathComponent() 181 | && currentDragDropNode != (JreepadNode)selPath.getLastPathComponent()) 182 | { 183 | // Then we need to perform a drag-and-drop operation! 184 | moveNode(currentDragDropNode, (JreepadNode)selPath.getLastPathComponent()); 185 | 186 | // Ensure that the destination node is open 187 | setSelectionPath(selPath.pathByAddingChild(currentDragDropNode)); 188 | } 189 | } 190 | setCursor(Cursor.getDefaultCursor()); 191 | currentDragDropNode = null; 192 | } 193 | 194 | public void mouseClicked(MouseEvent e) 195 | { 196 | TreePath selPath = getPathForLocation(e.getX(), e.getY()); 197 | if (selPath != null) 198 | { 199 | if (e.isPopupTrigger()) 200 | { 201 | // Now we can implement the pop-up content menu 202 | System.out.println("Context menu would be launched here!"); 203 | } 204 | } 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /website/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Jreepad - Java Treepad Viewer/Editor 7 | 8 | 36 | 37 | 38 | 39 | 63 | 64 | 65 | 66 | 67 | 68 | 94 | 145 | 146 |
69 |
70 | Jreepad 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |

 

92 | SourceForge.net Logo 93 |
95 |

Jreepad

96 | Screenshot 97 |

Jreepad is an excellent free "personal database" program - it's a great way to organise all your personal notes, thoughts, tasks, recipes, memories...

98 |

What's more, it's open-source and programmed in Java, so that all may benefit from it! Much used on Mac OSX, Linux, Unix, and even Windows!

99 |

Main features:

100 |
    101 |
  • A Jreepad file consists of a nice simple tree structure, and each "node" has an associated "article" - this can be plain text, HTML or tabular data.
  • 102 |
  • Nodes can be rearranged very intuitively with drag-and-drop functionality (or by keyboard), so it's easy to arrange your thoughts.
  • 103 |
  • There's a very powerful and intuitive search facility to locate a piece of text in a subtree
  • 104 |
  • Hyperlink support: select a link and you can follow it - whether it's HTTP, FTP, mailto:, "node://" (as used in Treepad), or even WikiStyleLinks!
  • 105 |
  • Integrated Google search
  • 106 |
  • Load/save Treepad (.HJT) files, compatible with Treepad Lite (so you can share files with Windows users)
  • 107 |
  • ...and much more, of course.
  • 108 |
109 |
110 |

Download Jreepad 1.5:

111 | 122 |

System requirements: Any operating system, with Java 1.4 or later installed.

123 |

Download Jreepad 1.6 rc3:

124 | 130 |

This is a "release candidate" - the latest development 131 | version, published for public testing before it is confirmed as 132 | being stable for general use.

133 |
134 |

Jreepad is released under the terms of the GNU General Public License. If you want more features, then please visit the Jreepad project page and submit a feature request - or even better, download the source code and improve it yourself!

135 |

Background

136 |

Jreepad is originally based on Treepad Lite, an excellent free program which is only available for Windows and Linux. When I moved from Windows to Mac I needed Treepad's functionality so I created it myself. Jreepad has gradually grown to provide more functionality than Treepad Lite, but its files are still compatible with the original Windows software.

137 |

Please note that Jreepad is not directly affiliated with Treepad - it's an independent project.

138 | 139 |
140 |

The Jreepad project was started by Dan Stowell.

141 |

This page last updated 142 | February 2010.

143 |
144 |

SourceForge.net Logo

147 | 148 | -------------------------------------------------------------------------------- /src/jreepad/io/AutoDetectReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad.io; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | import jreepad.JreepadTreeModel; 26 | import jreepad.ui.PasswordDialog; 27 | 28 | /** 29 | * Reads a Jreepad file automatically detecting file type (XML or HJT). 30 | * 31 | * @version $Id$ 32 | */ 33 | public class AutoDetectReader 34 | implements JreepadReader 35 | { 36 | XmlReader xmlReader; 37 | 38 | TreepadReader treepadReader; 39 | 40 | EncryptedReader encryptedReader; 41 | 42 | public AutoDetectReader(String encoding, boolean autoDetectHtmlArticles) 43 | { 44 | xmlReader = new XmlReader(); 45 | treepadReader = new TreepadReader(encoding, autoDetectHtmlArticles); 46 | encryptedReader = new EncryptedReader(this); // Use this reader as the underlying reader 47 | } 48 | 49 | public JreepadTreeModel read(InputStream in) 50 | throws IOException 51 | { 52 | in = new RewindableInputStream(in); 53 | 54 | // Read first line 55 | String currentLine = ((RewindableInputStream)in).readLine(); 56 | in.reset(); // reset stream, so the specific readers read from the beginning 57 | 58 | if (currentLine.startsWith(""))) 63 | { 64 | treepadReader.setFileFormat(1); 65 | return treepadReader.read(in); 66 | } 67 | else if ((currentLine.toLowerCase().startsWith(""))) 68 | { 69 | treepadReader.setFileFormat(1); 70 | return treepadReader.read(in); 71 | } 72 | else if (currentLine.startsWith(EncryptedWriter.HEADER)) 73 | { 74 | String password = PasswordDialog.showPasswordDialog("This file is encrypted. Please enter password:"); 75 | if (password == null) 76 | throw new IOException("Could not decrypt. No password entered."); 77 | encryptedReader.setPassword(password); 78 | return encryptedReader.read(in); 79 | } 80 | else 81 | { 82 | System.out.println("First line of file does not indicate a recognised format:\n" 83 | + currentLine + "\n"); 84 | throw new IOException("First line of file does not indicate a recognised format:\n\n" 85 | + currentLine); 86 | } 87 | } 88 | 89 | public boolean isAutoDetectHtmlArticles() 90 | { 91 | return treepadReader.isAutoDetectHtmlArticles(); 92 | } 93 | 94 | public void setAutoDetectHtmlArticles(boolean autoDetectHtmlArticles) 95 | { 96 | treepadReader.setAutoDetectHtmlArticles(autoDetectHtmlArticles); 97 | } 98 | 99 | public String getEncoding() 100 | { 101 | return treepadReader.getEncoding(); 102 | } 103 | 104 | public void setEncoding(String encoding) 105 | { 106 | treepadReader.setEncoding(encoding); 107 | } 108 | 109 | /** 110 | * This class wraps the byte inputstreams we're presented with. We need it because 111 | * java.io.InputStreams don't provide functionality to reread processed bytes, and they have a 112 | * habit of reading more than one character when you call their read() methods. This means that, 113 | * once we discover the true (declared) encoding of a document, we can neither backtrack to read 114 | * the whole doc again nor start reading where we are with a new reader. This class allows 115 | * rewinding an inputStream by allowing a mark to be set, and the stream reset to that position. 116 | * The class assumes that it needs to read one character per invocation when it's read() 117 | * method is inovked, but uses the underlying InputStream's read(char[], offset length) 118 | * method--it won't buffer data read this way! 119 | * 120 | * @xerces.internal 121 | * @author Neil Graham, IBM 122 | * @author Glenn Marcy, IBM 123 | */ 124 | protected static class RewindableInputStream 125 | extends InputStream 126 | { 127 | private static int BUFFER_SIZE = 2048; 128 | 129 | private InputStream fInputStream; 130 | 131 | private byte[] fData; 132 | 133 | private int fStartOffset; 134 | 135 | private int fEndOffset; 136 | 137 | private int fOffset; 138 | 139 | private int fLength; 140 | 141 | private int fMark; 142 | 143 | public RewindableInputStream(InputStream is) 144 | { 145 | fData = new byte[BUFFER_SIZE]; 146 | fInputStream = is; 147 | fStartOffset = 0; 148 | fEndOffset = -1; 149 | fOffset = 0; 150 | fLength = 0; 151 | fMark = 0; 152 | } 153 | 154 | public void setStartOffset(int offset) 155 | { 156 | fStartOffset = offset; 157 | } 158 | 159 | public void rewind() 160 | { 161 | fOffset = fStartOffset; 162 | System.out.println("Rewinding " + fOffset + "/" + fLength + " -> " + fStartOffset 163 | + "(end=" + fEndOffset + ")"); 164 | } 165 | 166 | public int read() 167 | throws IOException 168 | { 169 | int b = 0; 170 | if (fOffset < fLength) 171 | { 172 | return fData[fOffset++] & 0xff; 173 | } 174 | if (fOffset == fEndOffset) 175 | { 176 | return -1; 177 | } 178 | if (fOffset == fData.length) 179 | { 180 | byte[] newData = new byte[fOffset << 1]; 181 | System.arraycopy(fData, 0, newData, 0, fOffset); 182 | fData = newData; 183 | } 184 | b = fInputStream.read(); 185 | if (b == -1) 186 | { 187 | fEndOffset = fOffset; 188 | return -1; 189 | } 190 | fData[fLength++] = (byte)b; 191 | fOffset++; 192 | return b & 0xff; 193 | } 194 | 195 | public int read(byte[] b, int off, int len) 196 | throws IOException 197 | { 198 | int bytesLeft = fLength - fOffset; 199 | if (bytesLeft == 0) 200 | { 201 | if (fOffset == fEndOffset) 202 | { 203 | return -1; 204 | } 205 | return fInputStream.read(b, off, len); 206 | } 207 | if (len < bytesLeft) 208 | { 209 | if (len <= 0) 210 | { 211 | return 0; 212 | } 213 | } 214 | else 215 | { 216 | len = bytesLeft; 217 | } 218 | if (b != null) 219 | { 220 | System.arraycopy(fData, fOffset, b, off, len); 221 | } 222 | fOffset += len; 223 | return len; 224 | } 225 | 226 | public long skip(long n) 227 | throws IOException 228 | { 229 | int bytesLeft; 230 | if (n <= 0) 231 | { 232 | return 0; 233 | } 234 | bytesLeft = fLength - fOffset; 235 | if (bytesLeft == 0) 236 | { 237 | if (fOffset == fEndOffset) 238 | { 239 | return 0; 240 | } 241 | return fInputStream.skip(n); 242 | } 243 | if (n <= bytesLeft) 244 | { 245 | fOffset += n; 246 | return n; 247 | } 248 | fOffset += bytesLeft; 249 | if (fOffset == fEndOffset) 250 | { 251 | return bytesLeft; 252 | } 253 | n -= bytesLeft; 254 | /* 255 | * In a manner of speaking, when this class isn't permitting more than one byte at a 256 | * time to be read, it is "blocking". The available() method should indicate how much 257 | * can be read without blocking, so while we're in this mode, it should only indicate 258 | * that bytes in its buffer are available; otherwise, the result of available() on the 259 | * underlying InputStream is appropriate. 260 | */ 261 | return fInputStream.skip(n) + bytesLeft; 262 | } 263 | 264 | public int available() 265 | throws IOException 266 | { 267 | int bytesLeft = fLength - fOffset; 268 | if (bytesLeft == 0) 269 | { 270 | if (fOffset == fEndOffset) 271 | { 272 | return -1; 273 | } 274 | return fInputStream.available(); 275 | } 276 | return bytesLeft; 277 | } 278 | 279 | public void mark(int howMuch) 280 | { 281 | fMark = fOffset; 282 | } 283 | 284 | public void reset() 285 | { 286 | fOffset = fMark; 287 | } 288 | 289 | public boolean markSupported() 290 | { 291 | return true; 292 | } 293 | 294 | public void close() 295 | throws IOException 296 | { 297 | if (fInputStream != null) 298 | { 299 | fInputStream.close(); 300 | fInputStream = null; 301 | } 302 | } 303 | 304 | public String readLine() 305 | throws IOException 306 | { 307 | byte[] bytes = new byte[BUFFER_SIZE]; 308 | int len = 0; 309 | while (len < BUFFER_SIZE) 310 | { 311 | int ret = read(); 312 | if (ret == -1 || ret == 0x0a || ret == 0x0d) 313 | break; 314 | bytes[len] = (byte)(ret & 0xff); 315 | len++; 316 | } 317 | return new String(bytes, 0, len); 318 | } 319 | 320 | } // end of RewindableInputStream class 321 | } 322 | -------------------------------------------------------------------------------- /src/jreepad/lang/JreepadStrings_da.properties: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | #Generic strings: 3 | #------------------------------------------------------------------------ 4 | 5 | OK=OK 6 | CANCEL=Afbryd 7 | 8 | #------------------------------------------------------------------------ 9 | #Menus: 10 | #------------------------------------------------------------------------ 11 | 12 | MENU_FILE=Arkiv 13 | MENUITEM_NEW=Ny 14 | MENUITEM_OPEN=\u00C5ben 15 | MENUITEM_OPENRECENT=\u00C5ben seneste 16 | MENUITEM_SAVE=Arkiver 17 | MENUITEM_SAVEAS=Arkiver som... 18 | MENUITEM_BACKUPTO=Backup til... 19 | MENUITEM_PRINTSUBTREE=Udskriv underemne 20 | MENUITEM_PRINTARTICLE=Udskriv artikel 21 | MENUITEM_IMPORT=Importer... 22 | MENUITEM_IMPORT_HJT=...Treepad fil som underemne 23 | MENUITEM_IMPORT_TEXTFILES=...tekstfil(er) som undernode(r) 24 | MENUITEM_IMPORT_TEXTLIST= tekst liste fil, \u00E9n-undernode-pr.-linie 25 | MENUITEM_EXPORT=Eksporter valgte... 26 | MENUITEM_EXPORT_HJT=...underemne til Treepad HJT fil 27 | MENUITEM_EXPORT_HTML=...underemne til HTML 28 | MENUITEM_EXPORT_XML=...underemne til XML 29 | MENUITEM_EXPORT_TEXTLIST=...underemne til tekstliste (kun node titler) 30 | MENUITEM_EXPORT_ARTICLE=...artikel til tekstfil 31 | MENUITEM_EXPORT_ARTICLES=...underemne artikler til tekstfil 32 | MENUITEM_QUIT=Afslut 33 | 34 | MENU_EDIT=Rediger 35 | MENUITEM_UNDO=Undo 36 | MENUITEM_ADDABOVE=Tilf\u00F8j s\u00F8skende over 37 | MENUITEM_ADDBELOW=Tilf\u00F8j s\u00F8skende under 38 | MENUITEM_ADDCHILD=Tilf\u00F8j underemne 39 | MENUITEM_NEWFROMCLIPBOARD=Ny node from clipboard 40 | MENUITEM_EDITNODETITLE=Rediger node navn 41 | MENUITEM_DELETENODE=Slet node 42 | MENUITEM_MOVEUP=Flyt node op 43 | MENUITEM_MOVEDOWN=Flyt node ned 44 | MENUITEM_MOVEIN=Indryk node (degrader) 45 | MENUITEM_MOVEOUT=Indryk ikke node (forfrem) 46 | 47 | MENU_ACTIONS=Aktioner 48 | MENUITEM_EXPAND=Udvid underemne 49 | MENUITEM_COLLAPSE=Sammenklap underemne 50 | MENUITEM_SEARCH=Find 51 | MENUITEM_FOLLOWLINK=F\u00F8lg markerede link 52 | MENUITEM_HARDWRAP1=Ombryd artikel til kolonner a 53 | MENUITEM_HARDWRAP2= tegn 54 | MENUITEM_STRIPTAGS=Fjern fra artiklen 55 | MENUITEM_INSERTDATE=Inds\u00E6t dato 56 | MENUITEM_SORTONELEVEL=Sorter underemner (et niveau) 57 | MENUITEM_SORTALLLEVELS=Sorter underemner (alle niveauer) 58 | 59 | MENU_VIEW=Se 60 | MENUITEM_VIEWBOTH=B\u00E5de emne og artikel 61 | MENUITEM_VIEWTREE=Emne 62 | MENUITEM_VIEWARTICLE=Artikel 63 | MENUITEM_TOOLBAR=V\u00E6rkt\u00F8jer 64 | MENUITEM_TOOLBAR_ICONS=Ikoner 65 | MENUITEM_TOOLBAR_TEXT=Tekst 66 | MENUITEM_TOOLBAR_OFF=Sl\u00E5et fra 67 | MENUITEM_ARTICLEFORMAT=Se denne artikel som... 68 | MENUITEM_ARTICLEFORMAT_TEXT=Tekst 69 | MENUITEM_ARTICLEFORMAT_HTML=HTML 70 | MENUITEM_ARTICLEFORMAT_CSV=Tabel (komma-adskilt data) 71 | MENUITEM_NODEADDRESS="node://" adresse for aktuelle node 72 | 73 | MENU_OPTIONS=Valg 74 | MENUITEM_AUTOSAVE_PREFS=Arkiver automatisk 75 | MENUITEM_PREFS=Indstillinger 76 | 77 | MENU_HELP=Hj\u00E6lp 78 | MENUITEM_KEYBOARDSHORTCUTS=Tastaturgenveje 79 | MENUITEM_LINKSHELP=Hj\u00E6lp til links 80 | MENUITEM_DRAGDROPHELP=Hj\u00E6lp til drag&drop 81 | MENUITEM_ABOUT=Om Jreepad 82 | MENUITEM_LICENSE=Licens 83 | 84 | #------------------------------------------------------------------------ 85 | #Text for toolbar buttons/widgets: 86 | #------------------------------------------------------------------------ 87 | TOOLBAR_NEW=Ny 88 | TOOLBAR_OPEN=\u00C5ben 89 | TOOLBAR_SAVE=Arkiver 90 | TOOLBAR_ADDABOVE=Tilf\u00F8j over 91 | TOOLBAR_ADDBELOW=Tilf\u00F8j under 92 | TOOLBAR_ADDCHILD=Tilf\u00F8j underemne 93 | TOOLBAR_DELETE=Slet 94 | TOOLBAR_UP=Flyt op 95 | TOOLBAR_DOWN=Flyt ned 96 | TOOLBAR_IN=Indryk node 97 | TOOLBAR_OUT=Indryk ikke node 98 | TOOLBAR_VIEWBOTH=Emne og artikel 99 | TOOLBAR_VIEWTREE=Emne 100 | TOOLBAR_VIEWARTICLE=Artikel 101 | 102 | 103 | #------------------------------------------------------------------------ 104 | #Text for preferences dialogue 105 | #------------------------------------------------------------------------ 106 | 107 | PREFS_WINDOWTITLE=Indstillinger 108 | PREFS_LOADLASTFILEONOPEN=Indl\u00E6s sidst arkivere fil, n\u00E5r Jreepad starter 109 | PREFS_AUTODATE_NODES=Autodater node: F\u00F8j altid datoen til nyoprettede nodes 110 | PREFS_AUTODETECT_HTML=Opspor HTML nodes og gengiv dem som formatteret HTML 111 | PREFS_CHAR_ENCODING=Tegnkode til indl\u00E6sning/arkivering: 112 | PREFS_SAVE_FILETYPE=Arkiver filer som: 113 | PREFS_QUOTE_CSV=Tilf\u00F8j anf\u00F8rselstegn, n\u00E5r der konverteres tabeller til CSV 114 | PREFS_GREEN_STRIP=Show funky green strip on window 115 | PREFS_GENERAL=Generelt 116 | PREFS_DEFAULT_LINK_ACTION=Standard aktiner med almindelige ord/udtryk 117 | PREFS_DEFAULT_LINK_ACTION_WEBSEARCH=Web s\u00F8gning 118 | PREFS_DEFAULT_LINK_ACTION_NODESEARCH=S\u00F8g efter node titler 119 | PREFS_LINK_ACTION_NAME="F\u00F8lg valgte link" aktion 120 | PREFS_HARDWRAP_WIDTH=Antal tegn i hver kolonne efter ombrydning: 121 | PREFS_HARDWRAP_NAME=Ombryde artiklens tekst 122 | PREFS_WEBSEARCH_LABEL1=Web s\u00F8gning er markeret " 123 | PREFS_WEBSEARCH_LABEL2=" og viser den f\u00F8lgende URL: 124 | PREFS_SELECTEDTEXT_PLACEHOLDER=[VALGTE TEKST] 125 | PREFS_WEBSEARCH_NAME=Web s\u00F8gning 126 | PREFS_HTML_NAME=HTML eksport indstillinger (bruges ogs\u00E5 til udskrivning) 127 | PREFS_HTML_TREATTEXTAS=Betragt tekst i almindelige tekstartikler som: 128 | PREFS_HTML_AUTOLINK=Konverter URL'er til link 129 | PREFS_HTML_INTERNALLINKS=Hvilken slags "interne" link der skal opspores: 130 | PREFS_DEFAULT_SEARCH_TEXT=Google s\u00F8gning efter markerede tekst 131 | PREFS_EXPORTTYPE_TEXT=Almindelig tekst 132 | PREFS_EXPORTTYPE_PREFORMATTED=Preformatteret tekst 133 | PREFS_EXPORTTYPE_HTML=HTML markup 134 | 135 | #------------------------------------------------------------------------ 136 | #Text for autosave dialogue 137 | #------------------------------------------------------------------------ 138 | 139 | AUTOSAVE=Arkiver automatisk 140 | AUTOSAVE_EVERY=Arkiver automatisk hvert 141 | AUTOSAVE_MINUTES=\ minut 142 | AUTOSAVE_ACTIVE=Autosave on 143 | AUTOSAVE_ACTIVE_LONG=Autosave turned on. It will stay on until you deactivate it (even if you quit and re-start Jreepad). 144 | 145 | 146 | #------------------------------------------------------------------------ 147 | #Text for search dialogue: 148 | #------------------------------------------------------------------------ 149 | SEARCH_WINDOWTITLE=Find i Jreepad 150 | SEARCH_SEARCHFOR=S\u00F8g efter: 151 | SEARCH_SEARCHWHERE=S\u00F8ge hvor: 152 | SEARCH_SELECTEDNODE=V\u00E6lg node og dets undernode 153 | SEARCH_WHOLETREE=Alle emner 154 | SEARCH_CASESENSITIVE=Versalf\u00F8lsom 155 | SEARCH_MAXRESULTS=Maks. antal resultater: 156 | SEARCH_TBL_COL_NODE=Node 157 | SEARCH_TBL_COL_ARTICLETEXT=Tekstartikel 158 | SEARCH_TBL_COL_FULLPATH=Hele stien 159 | SEARCH_TBL_BEFORERESULTS=Results will appear here... 160 | SEARCH_TBL_NORESULTS=Ingen matchede. 161 | SEARCH_RESULTS=S\u00F8geresultat: 162 | SEARCH_NODES_MATCHED= nodes passede. 163 | 164 | 165 | #------------------------------------------------------------------------ 166 | #Text for messages: 167 | #------------------------------------------------------------------------ 168 | 169 | TITLE_FILE_ERROR=File error 170 | TITLE_MISC_ERROR=Error 171 | MSG_LOAD_FILE_FAILED=Sorry, failed to load the requested file. 172 | MSG_FILE_NOT_WRITEABLE=The file is not writeable (e.g. marked as \"Read-only\"). Please choose another location for save. 173 | MSG_NOTHING_TO_UNDO=Nothing to undo! 174 | TITLE_SAVEPROMPT=Arkivere? 175 | PROMPT_SAVE_BEFORE_NEW=Vil du ikke arkivere denne fil, f\u00F8r du opretter en ny node? 176 | PROMPT_SAVE_BEFORE_OPEN=Save current file before opening a new one? 177 | PROMPT_SAVE_BEFORE_QUIT=Vil du arkivere denne fil, f\u00F8r den afsluttes? 178 | TITLE_INCLUDE_TITLES=Include titles? 179 | PROMPT_INCLUDE_TITLES=Include articles' titles in output? 180 | TITLE_CONFIRM_DELETE=Bekr\u00E6ft sletning 181 | PROMPT_CONFIRM_DELETE=Slet noden 182 | TITLE_CONFIRM_OVERWRITE=Overwrite file? 183 | PROMPT_CONFIRM_OVERWRITE1=The file 184 | PROMPT_CONFIRM_OVERWRITE2= already exists.\nAre you sure you want to overwrite it? 185 | TITLE_CONFIRM_STRIPTAGS=Strip all tags? 186 | PROMPT_CONFIRM_STRIPTAGS=Stripping tags will remove all the article content which\nis wrapped in HTML-style from\nthe current article. Are you sure this is what you want? 187 | TITLE_CLIPBOARD_EMPTY=No content 188 | MSG_CLIPBOARD_EMPTY=No content found in clipboard. 189 | TITLE_CLIPBOARD_ERROR=Clipboard error 190 | MSG_CLIPBOARD_TEXTERROR=Unable to interpret clipboard contents as text. 191 | TITLE_NODEURL=Node URL 192 | MSG_NODEURL1=Denne nodes adress: 193 | MSG_NODEURL2=(Du kan kopiere/inds\u00E6tte den til en artikel) 194 | TITLE_ONLY_ON_CHILDNODES=Root node is selected. 195 | MSG_ONLY_ON_CHILDNODES=You can only perform this operation on child nodes.\nPlease choose "Add child" to add nodes to the root node,\nand then this option will become more meaningful. 196 | TITLE_NODE_NOT_FOUND=Not found 197 | MSG_NODE_NOT_FOUND=No node found in the current file\nto match that path. 198 | MSG_NODE_NOT_FOUND_PROMPT_CREATE=No node with that name was found. Create it? 199 | 200 | 201 | #------------------------------------------------------------------------ 202 | #Text for help/information windows: 203 | #------------------------------------------------------------------------ 204 | 205 | HELP_KEYBOARD_TITLE=Jreepad tastaturgenveje 206 | HELP_KEYBOARD= 207 | HELP_DRAGDROP_TITLE=Drag&drop 208 | HELP_DRAGDROP=DRAG&DROP:\n\nDen nemmeste m\u00E5de at tilpasse strukturen i en Treepad fil, \ner at tr\u00E6kke nodes med musen.\n\nKlik p\u00E5 et nodenavn og hold musknappen nede, mens du flytter \nen node til den \u00F8nskede placering. \nSlip derefter musknappen igen. 209 | HELP_LINKS_TITLE=Link i Jreepad 210 | HELP_LINKS=Marker lidt tekst i en artikel,\nog g\u00E5 s\u00E5 til Aktion menuen og v\u00E6lg "F\u00F8lg link i artikel".\n\nLINK TYPER:\n\n"Normal link - Vi har testet disse former for link:\n Web: f.eks. http://jreepad.sourceforge.net\n E-mail: f.eks. mailto:billg@microsoft.com\n FTP: f.eks. ftp://.compaq.com/pub/\n Fil: (kan ikke f\u00E5 det til at virke p\u00E5 OS X)\n\nWiki link - Hvis den markerede tekst er et WikiOrd (f.eks. hvis DetSerS\u00E5danUd\nuden ordmellemrum og nogle store bogstaver imellem) \nELLER starter med "[[" og slutter med "]]" vil Jreepad \nlede efter en node med samme navn, og hoppe direkte til den. \nHvis det ikke bliver fundet en, vil det oprette en for dig. Pr\u00F8v det!\n\nTreepad link - Treepad Lite benytter link, som starter med "node://", \nog specificerer den n\u00F8jagtige sti til en anden node i samme fil. 211 | f.eks. "node://Treepad manual/Using Treepad" 212 | HELP_LICENSE=Jreepad - Et personligt informationsprogram\n\nEneret \u00A9 2004 Dan Stowell\n\nDette program er gratis. Man m\u00E5 gendistribuere det og/eller \u00E6ndre i det if\u00F8lge reglerne for \nGNU General Public License, publiseret via Free Software Foundation; \nenten version 2 eller (dit valg) enhver nyere version.\n\nDette program er distribueret i h\u00E5bet om, at det kan v\u00E6re til nytte, men der gives IKKE \nNOGEN SOM HELST GARANTI for programmets anvdenelse. \nSe GNU General Public License for flere detaljer.\n\nMan kan l\u00E6se om alle licens betingelserne her: 213 | HELP_ABOUT=Jreepad er et \u00E5ben-kilde Java program, \nsom giver samme muluigheder som \nWindows programmet Trepad Lite, der er en del af \nsoftwarepakken Treepad af Henk Hagedorn. 214 | -------------------------------------------------------------------------------- /src/jreepad/JreepadNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004-2006 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.IOException; 24 | import java.io.InputStreamReader; 25 | 26 | import javax.swing.tree.DefaultMutableTreeNode; 27 | import javax.swing.tree.MutableTreeNode; 28 | 29 | 30 | /** 31 | * The tree node. Contains an article. 32 | * 33 | * @version $Id: JreepadNode.java,v 1.27 2007-01-26 22:49:04 pewu Exp $ 34 | */ 35 | public class JreepadNode 36 | extends DefaultMutableTreeNode 37 | implements Comparable 38 | { 39 | public JreepadNode() 40 | { 41 | this(new JreepadArticle()); 42 | } 43 | 44 | public JreepadNode(String content) 45 | { 46 | this(new JreepadArticle(content)); 47 | } 48 | 49 | public JreepadNode(String title, String content) 50 | { 51 | this(new JreepadArticle(title, content)); 52 | } 53 | 54 | public JreepadNode(JreepadArticle article) 55 | { 56 | setUserObject(article); 57 | } 58 | 59 | public JreepadArticle getArticle() 60 | { 61 | return (JreepadArticle)getUserObject(); 62 | } 63 | 64 | public String toFullString() 65 | { 66 | String ret = "JreepadNode \"" + getTitle() + "\": " + getChildCount() 67 | + " direct child nodes in subtree"; 68 | ret += "\nDirect children:"; 69 | for (int i = 0; i < children.size(); i++) 70 | ret += "\n " + ((JreepadNode)getChildAt(i)).getTitle(); 71 | return ret; 72 | } 73 | 74 | public String getWikiAnchor() 75 | { 76 | if (getParent() == null) 77 | return htmlSpecialChars(getTitle()); 78 | return getParentNode().getWikiAnchor() + "/" + htmlSpecialChars(getTitle()); 79 | } 80 | 81 | private static String htmlSpecialChars(String in) 82 | { 83 | char[] c = in.toCharArray(); 84 | StringBuffer ret = new StringBuffer(); 85 | for (int i = 0; i < c.length; i++) 86 | if (c[i] == '<') 87 | ret.append("<"); 88 | else if (c[i] == '>') 89 | ret.append(">"); 90 | else if (c[i] == '&') 91 | ret.append("&"); 92 | else if (c[i] == '\n') 93 | ret.append("
\n"); 94 | else if (c[i] == '"') 95 | ret.append("""); 96 | else 97 | ret.append(c[i]); 98 | return ret.toString(); 99 | } 100 | 101 | public String exportTitlesAsList() 102 | { 103 | return exportTitlesAsList(0).toString(); 104 | } 105 | 106 | private StringBuffer exportTitlesAsList(int currentDepth) 107 | { 108 | StringBuffer ret = new StringBuffer(); 109 | for (int i = 0; i < currentDepth; i++) 110 | ret.append(" "); 111 | ret.append(getTitle() + "\n"); 112 | for (int i = 0; i < children.size(); i++) 113 | ret.append(((JreepadNode)getChildAt(i)).exportTitlesAsList(currentDepth + 1)); 114 | 115 | return ret; 116 | } 117 | 118 | public String exportArticlesToText(boolean titlesToo) 119 | { 120 | // System.out.println("Expooort beginning"); 121 | return exportArticlesToTextRecursive(titlesToo).toString(); 122 | } 123 | 124 | public StringBuffer exportArticlesToTextRecursive(boolean titlesToo) 125 | { 126 | // System.out.println("Expooort " + getTitle()); 127 | StringBuffer ret = new StringBuffer(); 128 | if (titlesToo) 129 | ret.append(getTitle() + "\n\n"); 130 | ret.append(getArticle().getContent() + "\n\n"); 131 | for (int i = 0; i < children.size(); i++) 132 | ret.append(((JreepadNode)getChildAt(i)).exportArticlesToTextRecursive(titlesToo)); 133 | 134 | return ret; 135 | } 136 | 137 | public JreepadNode removeChild(int child) // Can be used to delete, OR to 'get' one for moving 138 | { 139 | JreepadNode ret = (JreepadNode)getChildAt(child); 140 | remove(child); 141 | return ret; 142 | } 143 | 144 | public boolean indent() 145 | { 146 | // Get position in parent. If zero or -1 then return. 147 | int pos = getIndex(); 148 | if (pos < 1) 149 | return false; 150 | // Get sibling node just above, and move self to there. 151 | MutableTreeNode oldParent = (MutableTreeNode)getParent(); 152 | DefaultMutableTreeNode newParent = (DefaultMutableTreeNode)oldParent.getChildAt(pos - 1); 153 | newParent.add(this); 154 | return true; 155 | } 156 | 157 | public boolean outdent() 158 | { 159 | // Get parent's parent. If null then return. 160 | JreepadNode p = (JreepadNode)getParent(); 161 | if (p == null) 162 | return false; 163 | JreepadNode pp = (JreepadNode)p.getParent(); 164 | if (pp == null) 165 | return false; 166 | // Get parent's position in its parent. = ppos 167 | int ppos = p.getIndex(); 168 | // Move self to parent's parent, at (ppos+1) 169 | p.removeChild(getIndex()); 170 | pp.insert(this, ppos + 1); 171 | 172 | // Also (as in the original treepad) move all the later siblings so they're children of this 173 | // node 174 | 175 | // NOT DONE YET 176 | 177 | return true; 178 | } 179 | 180 | public void moveUp() 181 | { 182 | MutableTreeNode parent = (MutableTreeNode)getParent(); 183 | if (parent == null) 184 | return; 185 | int index = getIndex(); 186 | if (index < 1) 187 | return; 188 | 189 | parent.insert(this, index - 1); 190 | } 191 | 192 | public void moveDown() 193 | { 194 | MutableTreeNode parent = (MutableTreeNode)getParent(); 195 | if (parent == null) 196 | return; 197 | int index = getIndex(); 198 | if (index < 0 || index >= parent.getChildCount() - 1) 199 | return; 200 | 201 | parent.insert(this, index + 1); 202 | } 203 | 204 | public JreepadNode addChild() 205 | { 206 | JreepadNode theChild = new JreepadNode(); 207 | add(theChild); 208 | return theChild; 209 | } 210 | 211 | public JreepadNode addChild(int index) 212 | { 213 | JreepadNode theChild = new JreepadNode(); 214 | insert(theChild, index); 215 | return theChild; 216 | } 217 | 218 | public int getIndex() 219 | { 220 | if (getParent() == null) 221 | return -1; 222 | return getParent().getIndex(this); 223 | } 224 | 225 | public void sortChildrenRecursive() 226 | { 227 | sortChildren(); 228 | for (int i = 0; i < getChildCount(); i++) 229 | ((JreepadNode)getChildAt(i)).sortChildrenRecursive(); 230 | } 231 | 232 | // Function for using Java's built-in mergesort 233 | public void sortChildren() 234 | { 235 | Object[] childrenArray = children.toArray(); 236 | java.util.Arrays.sort(childrenArray); 237 | removeAllChildren(); 238 | for (int i = 0; i < childrenArray.length; i++) 239 | add((JreepadNode)childrenArray[i]); 240 | } 241 | 242 | // The following function is a halfway-house on the way to "natural numerical ordering" 243 | public int compareTo(Object o) 244 | { 245 | String a = getTitle(); 246 | String b = ((JreepadNode)o).getTitle(); 247 | if (a.length() != 0 && b.length() != 0 && Character.isDigit(a.charAt(0)) 248 | && Character.isDigit(b.charAt(0))) 249 | { 250 | // Both strings begin with digits - so implement natural numerical ordering here 251 | StringBuffer aBuf = new StringBuffer(""); 252 | StringBuffer bBuf = new StringBuffer(""); 253 | int i; 254 | for (i = 0; i < a.length(); i++) 255 | if (Character.isDigit(a.charAt(i))) 256 | aBuf.append(a.charAt(i)); 257 | else 258 | break; 259 | for (i = 0; i < b.length(); i++) 260 | if (Character.isDigit(b.charAt(i))) 261 | bBuf.append(b.charAt(i)); 262 | else 263 | break; 264 | return (new Integer(aBuf.toString())).compareTo(new Integer(bBuf.toString())); 265 | } 266 | return a.compareToIgnoreCase(b); 267 | } 268 | 269 | public boolean isLeaf() 270 | { 271 | return (getChildCount() == 0); 272 | } 273 | 274 | public JreepadNode getParentNode() 275 | { 276 | return (JreepadNode)getParent(); 277 | } 278 | 279 | public void addChildFromTextFile(InputStreamReader textFile, String nodeName) 280 | throws IOException 281 | { 282 | // Load the content as a string 283 | StringBuffer contentString = new StringBuffer(); 284 | String currentLine; 285 | BufferedReader bReader = new BufferedReader(textFile); 286 | while ((currentLine = bReader.readLine()) != null) 287 | contentString.append(currentLine + "\n"); 288 | // Then just create the node 289 | add(new JreepadNode(new JreepadArticle(nodeName, contentString.toString()))); 290 | } 291 | 292 | // This getCopy() function is intended to return a copy of the entire subtree, used for Undo 293 | public JreepadNode getCopy() 294 | { 295 | JreepadNode ret = new JreepadNode(getArticle()); 296 | for (int i = 0; i < getChildCount(); i++) 297 | { 298 | ret.add(((JreepadNode)getChildAt(i)).getCopy()); 299 | } 300 | return ret; 301 | } 302 | 303 | public JreepadNode getChildByTitle(String title) 304 | { 305 | for (int i = 0; i < getChildCount(); i++) 306 | if (((JreepadNode)getChildAt(i)).getTitle().equals(title)) 307 | return (JreepadNode)getChildAt(i); 308 | return null; 309 | } 310 | 311 | public String getTitle() 312 | { 313 | return getArticle().getTitle(); 314 | } 315 | 316 | public void setTitle(String title) 317 | { 318 | getArticle().setTitle(title); 319 | } 320 | 321 | public String getContent() 322 | { 323 | return getArticle().getContent(); 324 | } 325 | 326 | /* 327 | // Listens for edits that can be undone. 328 | protected class JreepadNodeUndoableEditListener 329 | implements UndoableEditListener { 330 | public void undoableEditHappened(UndoableEditEvent e) { 331 | 332 | //System.out.println("Undoable event is " + (e.getEdit().isSignificant()?"":"NOT ") + "significant"); 333 | //System.out.println("Undoable event source: " + e.getEdit()); 334 | 335 | //Remember the edit and update the menus. 336 | undoMgr.addEdit(e.getEdit()); 337 | //undoAction.updateUndoState(); 338 | //redoAction.updateRedoState(); 339 | } 340 | } 341 | */ 342 | } 343 | -------------------------------------------------------------------------------- /src/jreepad/find.java: -------------------------------------------------------------------------------- 1 | /* 2 | Jreepad - personal information manager. 3 | Copyright (C) 2004 Dan Stowell 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | The full license can be read online here: 16 | 17 | http://www.gnu.org/copyleft/gpl.html 18 | */ 19 | 20 | package jreepad; 21 | 22 | /* 23 | import javax.swing.*; 24 | import javax.swing.tree.*; 25 | import javax.swing.event.*; 26 | import javax.swing.text.BadLocationException; 27 | import javax.swing.text.*; 28 | import java.awt.*; 29 | import java.awt.event.*; 30 | import java.util.Enumeration; 31 | import java.awt.print.*; 32 | */ 33 | import java.io.File; 34 | import java.io.FileInputStream; 35 | import java.io.IOException; 36 | import java.io.InputStream; 37 | import java.io.ObjectInputStream; 38 | import java.util.Vector; 39 | 40 | import javax.swing.tree.TreePath; 41 | 42 | import jreepad.io.AutoDetectReader; 43 | import jreepad.io.JreepadReader; 44 | import jreepad.io.JreepadWriter; 45 | import jreepad.io.TreepadWriter; 46 | import jreepad.io.XmlWriter; 47 | 48 | /* 49 | 50 | The "Find" class is a command-line utility for searching a single HJT file. 51 | 52 | Examples of usage: 53 | 54 | java jreepad.find -f ../hjts/notes.hjt "Wood Green" 55 | java jreepad.find -f ../hjts/notes.hjt -t "Wood Green" 56 | java jreepad.find -f ../hjts/notes.hjt -t "Wood Green" -a "020" 57 | java jreepad.find -f ../hjts/notes.hjt "Wood Green" -a "020" 58 | 59 | The "-f" argument indicates the file to load. 60 | The remaining arguments are the search terms, 61 | which by default are found in EITHER the node title or the article. 62 | A "-t" indicates that what follows should only be in the title. 63 | A "-a" indicates that what follows should only be in the article. 64 | 65 | "-h" is for help, of course 66 | "-m" is for manual, i.e. more detailed than -h 67 | 68 | "-l 200" limit the results to a maximum of 200 69 | 70 | 71 | Output... hmm... 72 | 73 | Default format should be easy to read but should also be processible. 74 | 75 | Perhaps it should be plain old HJT format? 76 | 77 | Or perhaps it should be something like 78 | 79 | -- Node title: Wood Green stuff -- 80 | Blah blah blonky bloo isn't this a nice thing 81 | Don't forget to water the flowers by the way 82 | ---------------------------------- 83 | 84 | Perhaps output can be specified by 85 | -oh = Output should be .HJT format 86 | -on = Output should be simple texty format (default) 87 | -ot = Output should be just the node titles 88 | -ox = Simple XML format 89 | -ob = Brief texty format 90 | 91 | It needs to pick up the file format from the Jreepad prefs file (the encoding). 92 | It could also pick up the default file to search, i.e. the last one loaded. 93 | 94 | */ 95 | 96 | public class find 97 | { 98 | private static final int PARAMMODE_SEARCHANY = 1; 99 | private static final int PARAMMODE_FILENAME = 2; 100 | private static final int PARAMMODE_SEARCHTITLE = 3; 101 | private static final int PARAMMODE_SEARCHARTICLE = 4; 102 | private static final int PARAMMODE_SEARCHLIMIT = 5; 103 | 104 | private static final int OUTPUT_HJT = 1; 105 | private static final int OUTPUT_TEXT = 2; 106 | private static final int OUTPUT_TITLES = 3; 107 | private static final int OUTPUT_BRIEF = 4; 108 | private static final int OUTPUT_XML = 5; 109 | 110 | private static final File prefsFile = new File(System.getProperty("user.home"), ".jreepref"); 111 | 112 | public static void main(String[] args) throws IOException 113 | { 114 | int maxResults = 200; // A default which can be overridden 115 | boolean caseSensitive = false; 116 | boolean orNotAnd = true; 117 | File userFile = null; 118 | int outputFormat = OUTPUT_XML; 119 | 120 | Vector titleSearches = new Vector(); 121 | Vector articleSearches = new Vector(); 122 | 123 | // Load the arguments and check them out 124 | if(args.length==0 || (args.length==1 && (args[0].startsWith("-h") || args[0].startsWith("--h")) )) 125 | { 126 | printUsage(); 127 | System.exit(1); 128 | } 129 | int paramMode = PARAMMODE_SEARCHANY; 130 | for(int i=0; i1 || articleSearches.size()>1) 191 | { 192 | System.out.println("Warning: complicated searches (more than 1 item to find in article, or more than 1 article to find in title) don't currently work properly!"); 193 | } 194 | 195 | String encoding = "UTF-8"; 196 | File prefsLastFile = null; 197 | // Load the preferences file (if exists) 198 | if(prefsFile.exists()) 199 | { 200 | try 201 | { 202 | // De-serialize the prefs file (i.e. load it)... 203 | JreepadPrefs jreepref; 204 | ObjectInputStream prefsLoader = new ObjectInputStream(new FileInputStream(prefsFile)); 205 | jreepref = (JreepadPrefs)prefsLoader.readObject(); 206 | prefsLoader.close(); 207 | 208 | // ...and take some data from it 209 | encoding = jreepref.getEncoding(); 210 | prefsLastFile = jreepref.getMostRecentFile(); 211 | // then dump it! 212 | jreepref = null; 213 | } 214 | catch(Exception err){} // Exceptions are ignored - just ignore the prefs file if you get an error 215 | } 216 | else 217 | { 218 | } 219 | 220 | // If no file specified by user, attempt to take it from the preferences file 221 | if(userFile==null) 222 | userFile = prefsLastFile; 223 | 224 | // If file unspecified or not found, exit with error 225 | if(userFile==null) 226 | { 227 | System.out.println("No Treepad/Jreepad file specified, and none found in the recently-used files list!"); 228 | System.exit(1); 229 | } 230 | else if(!userFile.exists()) 231 | { 232 | System.out.println("File not found!"); 233 | System.exit(1); 234 | } 235 | 236 | // Load the file to be searched 237 | JreepadNode root = new JreepadNode(); 238 | try 239 | { 240 | InputStream in = new FileInputStream(userFile); 241 | JreepadReader reader = new AutoDetectReader(encoding, false); 242 | root = reader.read(in).getRootNode(); 243 | } 244 | catch(IOException err) 245 | { 246 | System.out.println("File input error: " + err); 247 | System.exit(1); 248 | } 249 | 250 | 251 | // Carry out the search 252 | JreepadSearcher searcher = new JreepadSearcher(root); 253 | searcher.performSearch(inNodes, inArticles, new TreePath(root), 254 | orNotAnd, caseSensitive, maxResults); 255 | JreepadSearcher.JreepadSearchResult[] res = searcher.getSearchResults(); 256 | 257 | if(res.length==0) 258 | { 259 | System.out.println("No matches."); 260 | System.exit(1); 261 | } 262 | 263 | // Output the results 264 | JreepadNode resultsParent; 265 | switch(outputFormat) 266 | { 267 | case OUTPUT_TEXT: 268 | for(int i=0; i" + n.getContent() + "
"; 313 | } 314 | */ 315 | 316 | private static void printUsage() 317 | { 318 | System.out.println("Usage: java jreepad.find -f mynotes.hjt \"Text to find\""); 319 | System.out.println("For more information use \"-m\" for a brief manual."); 320 | } 321 | 322 | private static void printManual() 323 | { 324 | System.out.println("Jreepad (c) Dan Stowell - open source under the Gnu Public Licence"); 325 | } 326 | 327 | } -------------------------------------------------------------------------------- /src/jreepad/lang/JreepadStrings.properties: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | #Generic strings: 3 | #------------------------------------------------------------------------ 4 | 5 | OK=OK 6 | CANCEL=Cancel 7 | 8 | #------------------------------------------------------------------------ 9 | #Menus: 10 | #------------------------------------------------------------------------ 11 | 12 | MENU_FILE=File 13 | MENUITEM_NEW=New 14 | MENUITEM_OPEN=Open 15 | MENUITEM_OPENRECENT=Open recent 16 | MENUITEM_SAVE=Save 17 | MENUITEM_SAVEAS=Save as... 18 | MENUITEM_BACKUPTO=Backup to... 19 | MENUITEM_PRINTSUBTREE=Print subtree 20 | MENUITEM_PRINTARTICLE=Print article 21 | MENUITEM_IMPORT=Import... 22 | MENUITEM_IMPORT_HJT=...Treepad file as subtree 23 | MENUITEM_IMPORT_TEXTFILES=...text file(s) as child node(s) 24 | MENUITEM_IMPORT_TEXTLIST=...text list file, one-child-per-line 25 | MENUITEM_EXPORT=Export selected... 26 | MENUITEM_EXPORT_HJT=...subtree to Treepad HJT file 27 | MENUITEM_EXPORT_HTML=...subtree to HTML 28 | MENUITEM_EXPORT_XML=...subtree to XML 29 | MENUITEM_EXPORT_TEXTLIST=...subtree to text list (node titles only) 30 | MENUITEM_EXPORT_ARTICLE=...article to text file 31 | MENUITEM_EXPORT_ARTICLES=...subtree articles to text file 32 | MENUITEM_QUIT=Quit 33 | 34 | MENU_EDIT=Edit 35 | MENUITEM_UNDO=Undo (in article text) 36 | MENUITEM_REDO=Redo (in article text) 37 | MENUITEM_ADDABOVE=Add sibling above 38 | MENUITEM_ADDBELOW=Add sibling below 39 | MENUITEM_ADDCHILD=Add child 40 | MENUITEM_NEWFROMCLIPBOARD=New node from clipboard 41 | MENUITEM_EDITNODETITLE=Edit node title 42 | MENUITEM_DELETENODE=Delete node 43 | MENUITEM_MOVEUP=Move node up 44 | MENUITEM_MOVEDOWN=Move node down 45 | MENUITEM_MOVEIN=Indent node (demote) 46 | MENUITEM_MOVEOUT=Outdent node (promote) 47 | 48 | MENU_ACTIONS=Actions 49 | MENUITEM_EXPAND=Expand subtree 50 | MENUITEM_COLLAPSE=Collapse subtree 51 | MENUITEM_SEARCH=Search 52 | MENUITEM_FOLLOWLINK=Follow highlighted link 53 | MENUITEM_HARDWRAP1=Hard-wrap current article to 54 | MENUITEM_HARDWRAP2= characters 55 | MENUITEM_STRIPTAGS=Strip from article 56 | MENUITEM_INSERTDATE=Insert date 57 | MENUITEM_SORTONELEVEL=Sort children (one level) 58 | MENUITEM_SORTALLLEVELS=Sort children (all levels) 59 | 60 | MENU_VIEW=View 61 | MENUITEM_VIEWBOTH=Both tree and article 62 | MENUITEM_VIEWTREE=Tree 63 | MENUITEM_VIEWARTICLE=Article 64 | MENUITEM_TOOLBAR=Toolbar 65 | MENUITEM_TOOLBAR_ICONS=Icons 66 | MENUITEM_TOOLBAR_TEXT=Text 67 | MENUITEM_TOOLBAR_OFF=Off 68 | MENUITEM_ARTICLEFORMAT=View this article as... 69 | MENUITEM_ARTICLEFORMAT_TEXT=Text 70 | MENUITEM_ARTICLEFORMAT_HTML=HTML 71 | MENUITEM_ARTICLEFORMAT_CSV=Table (comma-separated data) 72 | MENUITEM_ARTICLEFORMAT_TEXTILE=Textile-rendered text 73 | MENUITEM_NODEADDRESS="node://" address for current node 74 | MENUITEM_FONT_ARTICLE=Article Font 75 | MENUITEM_FONT_TREE=Tree Font 76 | MENUITEM_FONT_INCREASE=Increase 77 | MENUITEM_FONT_DECREASE=Decrease 78 | 79 | MENU_OPTIONS=Options 80 | MENUITEM_AUTOSAVE_PREFS=Autosave... 81 | MENUITEM_PREFS=Preferences 82 | 83 | MENU_HELP=Help 84 | MENUITEM_KEYBOARDSHORTCUTS=Keyboard shortcuts 85 | MENUITEM_LINKSHELP=Help with links 86 | MENUITEM_DRAGDROPHELP=Help with drag-and-drop 87 | MENUITEM_ABOUT=About Jreepad 88 | MENUITEM_LICENSE=License 89 | 90 | MENUITEM_COPY=Copy 91 | MENUITEM_CUT=Cut 92 | MENUITEM_PASTE=Paste 93 | MENUITEM_SELECTALL=Select all... 94 | 95 | #------------------------------------------------------------------------ 96 | #Text for toolbar buttons/widgets: 97 | #------------------------------------------------------------------------ 98 | TOOLBAR_NEW=New 99 | TOOLBAR_OPEN=Open 100 | TOOLBAR_SAVE=Save 101 | TOOLBAR_ADDABOVE=Add above 102 | TOOLBAR_ADDBELOW=Add below 103 | TOOLBAR_ADDCHILD=Add child 104 | TOOLBAR_DELETE=Del 105 | TOOLBAR_UP=Up 106 | TOOLBAR_DOWN=Down 107 | TOOLBAR_IN=In 108 | TOOLBAR_OUT=Out 109 | TOOLBAR_VIEWBOTH=Tree+Article 110 | TOOLBAR_VIEWTREE=Tree 111 | TOOLBAR_VIEWARTICLE=Article 112 | 113 | 114 | #------------------------------------------------------------------------ 115 | #Text for preferences dialogue 116 | #------------------------------------------------------------------------ 117 | 118 | PREFS_WINDOWTITLE=Preferences 119 | PREFS_LOADLASTFILEONOPEN=When Jreepad starts, automatically load the last-saved file 120 | PREFS_AUTODATE_NODES=Autodate nodes: whenever a new node is created, add the date into its article 121 | PREFS_AUTODETECT_HTML=Detect HTML nodes and render them as formatted HTML 122 | PREFS_CHAR_ENCODING=Character encoding for load and save: 123 | PREFS_SAVE_FILETYPE=Save files as: 124 | PREFS_QUOTE_CSV=Add quote marks when converting tables to CSV 125 | PREFS_GREEN_STRIP=Show funky green strip on window 126 | PREFS_DATEFORMAT_LABEL=Date format: 127 | PREFS_DATEFORMAT_LABEL2=leave blank for default 128 | PREFS_GENERAL=General 129 | PREFS_DEFAULT_LINK_ACTION=Default action to take with ordinary words/phrases: 130 | PREFS_DEFAULT_LINK_ACTION_WEBSEARCH=Web search 131 | PREFS_DEFAULT_LINK_ACTION_NODESEARCH=Search for node title 132 | PREFS_LINK_ACTION_NAME="Follow selected link" action 133 | PREFS_HARDWRAP_WIDTH=Column width to use for hard-wrap action: 134 | PREFS_HARDWRAP_NAME=Wrapping article text 135 | PREFS_WEBSEARCH_LABEL1=Web search is labelled " 136 | PREFS_WEBSEARCH_LABEL2=" and calls the following URL: 137 | PREFS_SELECTEDTEXT_PLACEHOLDER=[SELECTED TEXT] 138 | PREFS_WEBSEARCH_NAME=Web search 139 | PREFS_HTML_NAME=HTML export preferences (also used for printing) 140 | PREFS_HTML_TREATTEXTAS=Treat text in plain-text articles as: 141 | PREFS_HTML_AUTOLINK=Convert URLs to links 142 | PREFS_HTML_INTERNALLINKS=Which type of 'internal' link to detect: 143 | PREFS_DEFAULT_SEARCH_TEXT=Googlesearch for highlighted text 144 | PREFS_EXPORTTYPE_TEXT=Ordinary text 145 | PREFS_EXPORTTYPE_PREFORMATTED=Preformatted text 146 | PREFS_EXPORTTYPE_HTML=HTML markup 147 | PREFS_EXPORTTYPE_TEXTILEHTML=Textile format 148 | 149 | #------------------------------------------------------------------------ 150 | #Text for autosave dialogue 151 | #------------------------------------------------------------------------ 152 | 153 | AUTOSAVE=Autosave 154 | AUTOSAVE_EVERY=Autosave every 155 | AUTOSAVE_MINUTES=\ minutes 156 | AUTOSAVE_ACTIVE=Autosave on 157 | AUTOSAVE_ACTIVE_LONG=Autosave turned on. It will stay on until you deactivate it (even if you quit and re-start Jreepad). 158 | 159 | 160 | #------------------------------------------------------------------------ 161 | #Text for search dialogue: 162 | #------------------------------------------------------------------------ 163 | SEARCH_WINDOWTITLE=Search Jreepad 164 | SEARCH_SEARCHFOR=Search for: 165 | SEARCH_SEARCHWHERE=Search where: 166 | SEARCH_SELECTEDNODE=Selected node and its children 167 | SEARCH_WHOLETREE=Entire tree 168 | SEARCH_CASESENSITIVE=Case sensitive 169 | SEARCH_MAXRESULTS=Max number of results: 170 | SEARCH_TBL_COL_NODE=Node 171 | SEARCH_TBL_COL_ARTICLETEXT=Article text 172 | SEARCH_TBL_COL_FULLPATH=Full Path 173 | SEARCH_TBL_BEFORERESULTS=Results will appear here... 174 | SEARCH_TBL_NORESULTS=No matches. 175 | SEARCH_RESULTS=Search results: 176 | SEARCH_NODES_MATCHED= nodes matched. 177 | 178 | 179 | #------------------------------------------------------------------------ 180 | #Text for messages: 181 | #------------------------------------------------------------------------ 182 | 183 | TITLE_FILE_ERROR=File error 184 | TITLE_MISC_ERROR=Error 185 | MSG_LOAD_FILE_FAILED=Sorry, failed to load the requested file. 186 | MSG_FILE_NOT_WRITEABLE=The file is not writeable (e.g. marked as \"Read-only\"). Please choose another location for save. 187 | MSG_NOTHING_TO_UNDO=Nothing to undo! 188 | TITLE_SAVEPROMPT=Save? 189 | PROMPT_SAVE_BEFORE_NEW=Save current file before starting a new one? 190 | PROMPT_SAVE_BEFORE_OPEN=Save current file before opening a new one? 191 | PROMPT_SAVE_BEFORE_QUIT=Save current file before quitting? 192 | TITLE_INCLUDE_TITLES=Include titles? 193 | PROMPT_INCLUDE_TITLES=Include articles' titles in output? 194 | TITLE_CONFIRM_DELETE=Confirm delete 195 | PROMPT_CONFIRM_DELETE=Delete node 196 | TITLE_CONFIRM_OVERWRITE=Overwrite file? 197 | PROMPT_CONFIRM_OVERWRITE1=The file 198 | PROMPT_CONFIRM_OVERWRITE2= already exists.\nAre you sure you want to overwrite it? 199 | TITLE_CONFIRM_STRIPTAGS=Strip all tags? 200 | PROMPT_CONFIRM_STRIPTAGS=Stripping tags will remove all the article content which\nis wrapped in HTML-style from\nthe current article. Are you sure this is what you want? 201 | TITLE_CLIPBOARD_EMPTY=No content 202 | MSG_CLIPBOARD_EMPTY=No content found in clipboard. 203 | TITLE_CLIPBOARD_ERROR=Clipboard error 204 | MSG_CLIPBOARD_TEXTERROR=Unable to interpret clipboard contents as text. 205 | TITLE_NODEURL=Node URL 206 | MSG_NODEURL1=Current node's address: 207 | MSG_NODEURL2=(You can copy-and-paste this into an article) 208 | TITLE_ONLY_ON_CHILDNODES=Root node is selected. 209 | MSG_ONLY_ON_CHILDNODES=You can only perform this operation on child nodes.\nPlease choose \"Add child\" to add nodes to the root node,\nand then this option will become more meaningful. 210 | TITLE_NODE_NOT_FOUND=Not found 211 | MSG_NODE_NOT_FOUND=No node found in the current file\nto match that path. 212 | MSG_NODE_NOT_FOUND_PROMPT_CREATE=No node with that name was found. Create it? 213 | TITLE_INVALID_DATEFORMAT=Invalid date format 214 | MSG_INVALID_DATEFORMAT=The provided date format is invalid.\n See http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html for syntax. 215 | 216 | #------------------------------------------------------------------------ 217 | #Text for help/information windows: 218 | #------------------------------------------------------------------------ 219 | 220 | INFO=Info 221 | HELP_KEYBOARD_TITLE=Keyboard help 222 | HELP_KEYBOARD= 223 | HELP_DRAGDROP_TITLE=Drag-and-drop 224 | HELP_DRAGDROP=DRAG-AND-DROP:\n\nOne of the easiest ways to manage the structure\nof your Treepad file is to drag the nodes around\nusing the mouse.\n\nClick on a node's title, and, keeping the mouse\nbutton held down, move the mouse to where you\nwant the node to be moved to. Then release the\nmouse button, and the node will be moved to its\nnew position in the tree. 225 | HELP_DATEFORMAT_TITLE=Date formats 226 | HELP_DATEFORMAT=

Date formats

You can specify your preferred date format using standard Java date formatting commands.

Here are some examples:

CommandExample output
yyyy.MM.dd G 'at' HH:mm:ss z2001.07.04 AD at 12:08:56 PDT
EEE, MMM d, ''yyWed, Jul 4, '01
h:mm a12:08 PM
hh 'o''clock' a, zzzz12 o'clock PM, Pacific Daylight Time
K:mm a, z0:08 PM, PDT

A complete guide to the formatting is available online at: www.javadocs.org/SimpleDateFormat


Leave the box blank to use the system default formatting.

227 | HELP_LINKS_TITLE=Links in Jreepad 228 | HELP_LINKS=Select any piece of text in an article,\nthen choose "Actions > Follow link in article".\n\nTYPES OF LINK:\n\n"Normal" link - We've tested these types of link:\n Web: e.g. http://jreepad.sourceforge.net\n Email: e.g. mailto:billg@microsoft.com\n FTP: e.g. ftp://ftp.compaq.com/pub/\n File: e.g. file:///Users/harold/Documents/stripes.jpg\n\nWiki link - If the selected text is a WikiWord (i.e. if \n it LooksLikeThis with no spaces and some capital \n letters somewhere in the middle) OR begins \n with "[[" and ends with "]]" then \n Jreepad will search for a node of the same \n title, and jump directly to it. If one \n isn't found then it'll create one \n for you. Try it!\n\nTreepad link - Treepad Lite uses links which begin \n with \"node://\", and specify the exact path\n to a different node within the same file.\n e.g. \"node://TreePad manual/Using Treepad\" 229 | HELP_LICENSE= Jreepad - personal information manager.\n Copyright \u00A9 2004 Dan Stowell\n\nThis program is free software; you can redistribute it and/or\nmodify it under the terms of the GNU General Public License\nas published by the Free Software Foundation; either version 2\nof the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nThe full license can be read online here: 230 | HELP_ABOUT=Jreepad originally inspired by a\nWindows program called \"Treepad Lite\"\nwritten by Henk Hagedoorn. 231 | -------------------------------------------------------------------------------- /src/jreepad/SearchDialog.java: -------------------------------------------------------------------------------- 1 | package jreepad; 2 | 3 | import java.awt.Frame; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.awt.event.KeyAdapter; 7 | import java.awt.event.KeyEvent; 8 | import java.awt.event.MouseAdapter; 9 | import java.awt.event.MouseEvent; 10 | import java.awt.event.MouseListener; 11 | 12 | import javax.swing.Box; 13 | import javax.swing.JCheckBox; 14 | import javax.swing.JComboBox; 15 | import javax.swing.JDialog; 16 | import javax.swing.JLabel; 17 | import javax.swing.JScrollPane; 18 | import javax.swing.JSpinner; 19 | import javax.swing.JTable; 20 | import javax.swing.JTextField; 21 | import javax.swing.ListSelectionModel; 22 | import javax.swing.SpinnerNumberModel; 23 | import javax.swing.event.CaretEvent; 24 | import javax.swing.event.CaretListener; 25 | import javax.swing.event.ChangeEvent; 26 | import javax.swing.event.ChangeListener; 27 | import javax.swing.table.AbstractTableModel; 28 | 29 | /** 30 | * The search dialog. 31 | * 32 | * @version $Id: SearchDialog.java,v 1.1 2007-02-05 11:06:44 pewu Exp $ 33 | */ 34 | public class SearchDialog extends JDialog 35 | { 36 | private JTextField nodeSearchField; 37 | private JComboBox searchWhereSelector; 38 | private JSpinner searchMaxNumSpinner; 39 | private JCheckBox searchCaseCheckBox; 40 | private AbstractTableModel searchResultsTableModel; 41 | private JTable searchResultsTable; 42 | private JScrollPane searchResultsTableScrollPane; 43 | private JLabel searchResultsLabel; 44 | private JreepadView theJreepad; 45 | 46 | public SearchDialog(Frame owner, JreepadView theJreepad) 47 | { 48 | super(owner, JreepadViewer.lang.getString("SEARCH_WINDOWTITLE"), false); 49 | this.theJreepad = theJreepad; 50 | setVisible(false); 51 | Box vBox = Box.createVerticalBox(); 52 | // 53 | Box hBox = Box.createHorizontalBox(); 54 | nodeSearchField = new JTextField(""); 55 | vBox.add(new JLabel(JreepadViewer.lang.getString("SEARCH_SEARCHFOR"))); 56 | hBox.add(nodeSearchField); 57 | nodeSearchField.addActionListener(new ActionListener() 58 | { 59 | public void actionPerformed(ActionEvent e) 60 | { 61 | doTheSearch(); 62 | } 63 | }); 64 | nodeSearchField.addCaretListener(new CaretListener() 65 | { 66 | public void caretUpdate(CaretEvent e) 67 | { 68 | doTheSearch(); 69 | } 70 | }); 71 | vBox.add(hBox); 72 | // 73 | searchWhereSelector = new JComboBox(new String[] { 74 | JreepadViewer.lang.getString("SEARCH_SELECTEDNODE"), 75 | JreepadViewer.lang.getString("SEARCH_WHOLETREE") }); 76 | searchWhereSelector.setSelectedIndex(1); 77 | searchWhereSelector.setEditable(false); 78 | searchWhereSelector.addActionListener(new ActionListener() 79 | { 80 | public void actionPerformed(ActionEvent e) 81 | { 82 | doTheSearch(); 83 | } 84 | }); 85 | hBox = Box.createHorizontalBox(); 86 | hBox.add(Box.createGlue()); 87 | hBox.add(new JLabel(JreepadViewer.lang.getString("SEARCH_SEARCHWHERE"))); 88 | hBox.add(searchWhereSelector); 89 | hBox.add(Box.createGlue()); 90 | hBox.add(searchCaseCheckBox = new JCheckBox(JreepadViewer.lang 91 | .getString("SEARCH_CASESENSITIVE"), false)); 92 | searchCaseCheckBox.addActionListener(new ActionListener() 93 | { 94 | public void actionPerformed(ActionEvent e) 95 | { 96 | doTheSearch(); 97 | } 98 | }); 99 | hBox.add(Box.createGlue()); 100 | vBox.add(hBox); 101 | // 102 | // searchMaxNumSpinner = new DSpinner(1,1000,getPrefs().searchMaxNum); 103 | searchMaxNumSpinner = new JSpinner(new SpinnerNumberModel(getPrefs().searchMaxNum, 1, 1000, 104 | 1)); 105 | /* 106 | * searchMaxNumSpinner.addCaretListener(new CaretListener(){ public void 107 | * caretUpdate(CaretEvent e){ doTheSearch();}}); searchMaxNumSpinner.addActionListener(new 108 | * ActionListener(){ public void actionPerformed(ActionEvent e){ doTheSearch();}}); 109 | */ 110 | searchMaxNumSpinner.getModel().addChangeListener(new ChangeListener() 111 | { 112 | public void stateChanged(ChangeEvent e) 113 | { 114 | doTheSearch(); 115 | } 116 | }); 117 | hBox = Box.createHorizontalBox(); 118 | hBox.add(Box.createGlue()); 119 | hBox.add(new JLabel(JreepadViewer.lang.getString("SEARCH_MAXRESULTS"))); 120 | hBox.add(searchMaxNumSpinner); 121 | hBox.add(Box.createGlue()); 122 | vBox.add(hBox); 123 | // 124 | // NOW FOR THE SEARCH RESULTS TABLE - COULD BE TRICKY! 125 | searchResultsTableModel = new AbstractTableModel() 126 | { 127 | private final String[] columns = new String[] { 128 | JreepadViewer.lang.getString("SEARCH_TBL_COL_NODE"), 129 | JreepadViewer.lang.getString("SEARCH_TBL_COL_ARTICLETEXT"), 130 | JreepadViewer.lang.getString("SEARCH_TBL_COL_FULLPATH") }; 131 | 132 | public int getColumnCount() 133 | { 134 | return columns.length; 135 | } 136 | 137 | public String getColumnName(int index) 138 | { 139 | return columns[index]; 140 | } 141 | 142 | public int getRowCount() 143 | { 144 | JreepadSearcher.JreepadSearchResult[] results = SearchDialog.this.theJreepad 145 | .getSearchResults(); 146 | if (results == null || results.length == 0) 147 | return 1; 148 | else 149 | return results.length; 150 | } 151 | 152 | public Object getValueAt(int row, int col) 153 | { 154 | JreepadSearcher.JreepadSearchResult[] results = SearchDialog.this.theJreepad 155 | .getSearchResults(); 156 | if (results == null || results.length == 0) 157 | switch (col) 158 | { 159 | case 2: 160 | return ""; 161 | case 1: 162 | return (nodeSearchField.getText() == "" ? JreepadViewer.lang 163 | .getString("SEARCH_TBL_BEFORERESULTS") : JreepadViewer.lang 164 | .getString("SEARCH_TBL_NORESULTS")); 165 | default: 166 | return ""; 167 | } 168 | else 169 | switch (col) 170 | { 171 | case 2: 172 | return results[row].getTreePath(); 173 | case 1: 174 | return results[row].getArticleQuote(); 175 | default: 176 | return results[row].getNode().getTitle(); 177 | } 178 | } 179 | }; 180 | searchResultsTable = new JTable(searchResultsTableModel); 181 | searchResultsTable.setCellSelectionEnabled(false); 182 | searchResultsTable.setColumnSelectionAllowed(false); 183 | searchResultsTable.setRowSelectionAllowed(true); 184 | searchResultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 185 | searchResultsTableScrollPane = new JScrollPane(searchResultsTable); 186 | vBox.add(searchResultsLabel = new JLabel(JreepadViewer.lang.getString("SEARCH_RESULTS"))); 187 | vBox.add(searchResultsTableScrollPane); 188 | // 189 | // Add mouse listener 190 | MouseListener sml = new MouseAdapter() 191 | { 192 | public void mouseClicked(MouseEvent e) 193 | { 194 | mouseClickedOnSearchResultsTable(e); 195 | } 196 | }; 197 | searchResultsTable.addMouseListener(sml); 198 | // 199 | getContentPane().add(vBox); 200 | 201 | // Now we'll add some keyboard shortcuts 202 | KeyAdapter searchKeyListener = new KeyAdapter() 203 | { 204 | public void keyPressed(KeyEvent eek) 205 | { 206 | switch (eek.getKeyCode()) 207 | { 208 | case KeyEvent.VK_ESCAPE: 209 | setVisible(false); 210 | break; 211 | case KeyEvent.VK_W: 212 | if (eek.isControlDown() || eek.isMetaDown()) 213 | setVisible(false); 214 | break; 215 | } 216 | } 217 | }; 218 | addKeyListener(searchKeyListener); 219 | nodeSearchField.addKeyListener(searchKeyListener); 220 | searchCaseCheckBox.addKeyListener(searchKeyListener); 221 | searchWhereSelector.addKeyListener(searchKeyListener); 222 | searchResultsTable.addKeyListener(searchKeyListener); 223 | searchMaxNumSpinner.addKeyListener(searchKeyListener); 224 | searchResultsTable.addKeyListener(new KeyAdapter() 225 | { 226 | public void keyPressed(KeyEvent eek) 227 | { 228 | switch (eek.getKeyCode()) 229 | { 230 | case KeyEvent.VK_SPACE: 231 | case KeyEvent.VK_ENTER: 232 | mouseClickedOnSearchResultsTable(null); 233 | break; 234 | } 235 | } 236 | }); 237 | 238 | // Finished establishing the search dialogue box 239 | } 240 | 241 | private void doTheSearch() 242 | { 243 | getPrefs().searchMaxNum = ((Integer)searchMaxNumSpinner.getValue()).intValue(); 244 | // DSpinner version getPrefs().searchMaxNum = searchMaxNumSpinner.getValue(); 245 | 246 | performSearch(nodeSearchField.getText(), 247 | nodeSearchField.getText(), // articleSearchField.getText(), 248 | searchWhereSelector.getSelectedIndex(), 249 | true /* searchCombinatorSelector.getSelectedIndex()==0 */, searchCaseCheckBox 250 | .isSelected(), getPrefs().searchMaxNum); 251 | } 252 | 253 | private boolean performSearch(String inNodes, String inArticles, 254 | int searchWhat /* 0=selected, 1=all */, boolean orNotAnd, boolean caseSensitive, 255 | int maxResults) 256 | { 257 | // setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 258 | boolean ret = theJreepad.performSearch(inNodes, inArticles, searchWhat, orNotAnd, 259 | caseSensitive, maxResults); 260 | // setCursor(Cursor.getDefaultCursor()); 261 | if (!ret) 262 | { 263 | // JOptionPane.showMessageDialog(searchDialog, "Found nothing.", "Search result..." , 264 | // JOptionPane.INFORMATION_MESSAGE); 265 | searchResultsLabel.setText(JreepadViewer.lang.getString("SEARCH_RESULTS")); 266 | } 267 | else 268 | searchResultsLabel.setText(JreepadViewer.lang.getString("SEARCH_RESULTS") 269 | + theJreepad.getSearchResults().length 270 | + JreepadViewer.lang.getString("SEARCH_NODES_MATCHED")); 271 | searchResultsTableModel.fireTableStructureChanged(); 272 | // searchResultsTable.repaint(); 273 | return ret; 274 | } 275 | 276 | private void mouseClickedOnSearchResultsTable(MouseEvent e) 277 | { 278 | JreepadSearcher.JreepadSearchResult[] results = theJreepad.getSearchResults(); 279 | int selectedRow = searchResultsTable.getSelectedRow(); 280 | if (results == null || results.length == 0 || selectedRow == -1) 281 | return; 282 | 283 | // Select the node in the tree 284 | theJreepad.getTree().setSelectionPath(results[selectedRow].getTreePath()); 285 | theJreepad.getTree().scrollPathToVisible(results[selectedRow].getTreePath()); 286 | } 287 | 288 | private static JreepadPrefs getPrefs() 289 | { 290 | return JreepadView.getPrefs(); 291 | } 292 | 293 | public void setJreepad(JreepadView theJreepad) 294 | { 295 | this.theJreepad = theJreepad; 296 | } 297 | 298 | public void open() 299 | { 300 | setVisible(true); 301 | nodeSearchField.requestFocus(); 302 | nodeSearchField.setSelectionStart(0); 303 | } 304 | } 305 | --------------------------------------------------------------------------------