001 /* JAPI - (Yet another (hopefully) useful) Java API
002 *
003 * Copyright (C) 2004-2006 Christian Hujer
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but
011 * WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018 * 02111-1307, USA.
019 */
020
021 package net.sf.japi.swing.bookmarks;
022
023 import java.awt.BorderLayout;
024 import java.awt.dnd.DropTarget;
025 import java.awt.event.ActionEvent;
026 import java.io.File;
027 import java.io.IOException;
028 import java.util.ArrayList;
029 import java.util.Collections;
030 import java.util.Enumeration;
031 import java.util.Iterator;
032 import java.util.List;
033 import javax.swing.AbstractAction;
034 import javax.swing.Action;
035 import javax.swing.JComponent;
036 import javax.swing.JFrame;
037 import javax.swing.JMenu;
038 import javax.swing.JMenuBar;
039 import javax.swing.JMenuItem;
040 import static javax.swing.JOptionPane.ERROR_MESSAGE;
041 import static javax.swing.JOptionPane.QUESTION_MESSAGE;
042 import static javax.swing.JOptionPane.showInputDialog;
043 import static javax.swing.JOptionPane.showMessageDialog;
044 import javax.swing.JScrollPane;
045 import javax.swing.JToolBar;
046 import javax.swing.JTree;
047 import javax.swing.tree.MutableTreeNode;
048 import javax.swing.tree.TreeNode;
049 import javax.xml.parsers.DocumentBuilder;
050 import javax.xml.parsers.DocumentBuilderFactory;
051 import javax.xml.parsers.ParserConfigurationException;
052 import org.w3c.dom.DOMImplementation;
053 import org.w3c.dom.Document;
054 import org.w3c.dom.Element;
055 import org.w3c.dom.Node;
056 import org.w3c.dom.NodeList;
057 import org.w3c.dom.ls.DOMImplementationLS;
058 import org.xml.sax.SAXException;
059 import net.sf.japi.swing.ActionFactory;
060 import net.sf.japi.swing.IconManager;
061 import net.sf.japi.util.EmptyEnumeration;
062
063 /** Class for managing and displaying Bookmarks.
064 * Usage of this class works the following way:
065 * <ul>
066 * <li>implement the interface {@link Bookmarkable} and its methods</li>
067 * <li>instanciate this class once for each gruop / kind of bookmarks you want to manage. Normally, one instance is enough per application</li>
068 * <li>invoke {@link #createBookmarkMenu} to create your bookmarks menu</li>
069 * </ul>
070 * @author $Author: christianhujer $
071 * @todo documentation
072 * @todo fix bookmark drag and drop indices
073 * @todo think about serialization of Actions
074 */
075 public class BookmarkManager {
076
077 /** The Bookmarks. */
078 private BookmarkFolder bookmarks = new BookmarkFolder();
079
080 /** Action Factory. */
081 private static final ActionFactory ACTION_FACTORY = ActionFactory.getFactory("net.sf.japi.swing.bookmarks");
082
083 /** The ProgramFrame this BookmarkManager manages bookmarks for. */
084 private Bookmarkable bookmarkable;
085
086 /** Create a new BookmarkManager. */
087 public BookmarkManager(final Bookmarkable bookmarkable) {
088 this.bookmarkable = bookmarkable;
089 try {
090 load();
091 save();
092 } catch (final Exception e) {
093 e.printStackTrace();
094 // TODO: improve dialog
095 showMessageDialog(bookmarkable.getBookmarkBlocker(), ACTION_FACTORY.getString("bookmarksCreated.message"));
096 }
097 }
098
099 /** Create a Bookmark ToolBar.
100 * @return toolBar for Bookmarks
101 */
102 public JToolBar createBookmarkToolBar() {
103 // Variant 1: JToolBar with JMenuBar with one entry "Lesezeichen"
104 final JToolBar toolBar = new JToolBar(ACTION_FACTORY.getString("bookmarkToolBar.name"));
105 final JMenuBar mb = new JMenuBar();
106 mb.add(bookmarks.createMenu());
107 toolBar.add(mb);
108 return toolBar;
109
110 //// Variant 2: JToolBar with JMenus and JMenuItems (broken)
111 //JToolBar toolBar = new JToolBar(ACTION_FACTORY.getString("bookmarkToolBar.name"));
112 //for (Bookmark bookmark : bookmarks) {
113 // toolBar.add(bookmark.createMenu());
114 //}
115 //return toolBar;
116
117 //// Variant 3: JToolBar with JMenuBar with JMenus and JMenuItems (JMenuItems don't hover)
118 //JToolBar toolBar = new JToolBar(ACTION_FACTORY.getString("bookmarkToolBar.name"));
119 //JMenuBar mb = new JMenuBar();
120 //for (Bookmark bookmark : bookmarks) {
121 // mb.add(bookmark.createMenu());
122 //}
123 //toolBar.add(mb);
124 //return toolBar;
125
126 //// Variant 4: JToolBar with a button activating a PopupMenu.
127 //// Doesn't work either, the popup menu is not correctly usable.
128 //JToolBar toolBar = new JToolBar(ACTION_FACTORY.getString("bookmarkToolBar.name"));
129 //final JPopupMenu menu = new JPopupMenu(ACTION_FACTORY.getString("bookmark.text"));
130 //menu.add(bookmarks.createMenu());
131 //toolBar.add(
132 // new javax.swing.JButton(
133 // new AbstractAction() {
134 // public void actionPerformed(final ActionEvent e) {
135 // menu.setVisible(true);
136 // }
137 // }
138 // )
139 //);
140 //return toolBar;
141 }
142
143 /** Create a Bookmark Menu.
144 * @return JMenu for Bookmarks
145 */
146 public JMenu createBookmarkMenu() {
147 final JMenu menu = bookmarks.createMenu();
148 menu.add(new JMenuItem(manageBookmarks));
149 return menu;
150 }
151
152 /** Create a Bookmark ControlPanel.
153 * @return ControlPanel for Bookmarks
154 */
155 public JComponent createBookmarkControlPanel() {
156 return new ControlPanel();
157 }
158
159 /** Recursive attach method.
160 * @param menu JMenu to attach bookmarks to
161 * @param bookmarks Bookmarks to attach
162 */
163 private static void attach(final JMenu menu, final BookmarkFolder bookmarks) {
164 for (final Bookmark bookmark : bookmarks) {
165 if (bookmark instanceof BookmarkFolder) {
166 final JMenu newMenu = new JMenu(bookmark);
167 attach(newMenu, (BookmarkFolder) bookmark);
168 } else {
169 assert bookmark instanceof BookmarkItem;
170 menu.add(new JMenuItem(bookmark));
171 }
172 }
173 }
174
175 /** Action for managing the bookmarks.
176 * @serial include
177 */
178 private Action manageBookmarks = ACTION_FACTORY.createAction(true, "manageBookmarks", this);
179
180 /** Action for managing the bookmarks. */
181 public void manageBookmarks() {
182 final JFrame f = new JFrame(ACTION_FACTORY.getString("manageBookmarks_shortdescription"));
183 f.getContentPane().add(createBookmarkControlPanel());
184 //f.getContentPane().add(new JScrollPane(new JTree(bookmarks)));
185 f.pack();
186 f.setVisible(true);
187 }
188
189 /** Set the AddBookmark enabled state.
190 * @param enabled enabled state for AddBookmark action
191 */
192 public void setAddBookmarkEnabled(final boolean enabled) {
193 bookmarks.setAddBookmarkEnabled(enabled);
194 }
195
196 /** Load bookmarks from default file.
197 * @throws IOException in case of I/O problems
198 * @throws ParserConfigurationException in case of XML configuration problems
199 * @throws SAXException in case of XML document problems
200 */
201 public void load() throws IOException, ParserConfigurationException, SAXException {
202 load(new File(System.getProperty("user.home"), ".jeduca.bookmarks.xml").toURL().toString());
203 }
204
205 /** Save bookmarks to default file.
206 * @throws IOException in case of I/O problems
207 * @throws ParserConfigurationException in case of XML configuration problems
208 */
209 public void save() throws IOException, ParserConfigurationException {
210 save(new File(System.getProperty("user.home"), ".jeduca.bookmarks.xml").toURL().toString());
211 }
212
213 /** Save bookmarks to a file.
214 * @param uri URI of file to save
215 * @throws IOException in case of I/O problems
216 * @throws ParserConfigurationException in case of XML configuration problems
217 */
218 public void save(final String uri) throws IOException, ParserConfigurationException {
219 final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
220 final DocumentBuilder db = dbf.newDocumentBuilder();
221 final Document doc = db.newDocument();
222 bookmarks.store(doc);
223 final DOMImplementation impl = doc.getImplementation();
224 if (impl instanceof DOMImplementationLS) {
225 final DOMImplementationLS ls = (DOMImplementationLS) impl;
226 ls.createLSSerializer().writeToURI(doc, uri);
227 }
228 }
229
230 /** Load bookmarks from a file.
231 * @param uri URI of file to load
232 * @throws IOException in case of I/O problems
233 * @throws ParserConfigurationException in case of XML configuration problems
234 * @throws SAXException in case of XML document problems
235 */
236 public void load(final String uri) throws IOException, ParserConfigurationException, SAXException {
237 final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
238 final DocumentBuilder db = dbf.newDocumentBuilder();
239 final Document doc = db.parse(uri);
240 bookmarks = new BookmarkFolder(doc);
241 }
242
243
244 /** Class for a ControlPanel to manage the bookmarks.
245 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
246 * @version $Id: BookmarkManager.java,v 1.2 2006/03/26 15:22:16 christianhujer Exp $
247 */
248 private class ControlPanel extends JComponent {
249
250 /** Serial Version. */
251 private static final long serialVersionUID = 1L;
252
253 /** Create a new ControlPanel. */
254 ControlPanel() {
255 setLayout(new BorderLayout());
256 final JTree tree = new JTree(bookmarks, true);
257 tree.setRootVisible(false);
258 tree.setCellRenderer(new BookmarkTreeCellRenderer());
259 //tree.setEditable(true);
260 tree.setDragEnabled(true);
261 final DropTarget dt = new DropTarget(tree, new BookmarkDropTargetAdapter());
262 tree.setTransferHandler(new BookmarkTransferHandler());
263 add(new JScrollPane(tree));
264 }
265
266 } // class ControlPanel
267
268
269 /** Base class for bookmarks.
270 * There are two kinds of bookmarks:
271 * <ul>
272 * <li>{@link BookmarkItem}s for normal Bookmarks with title and url</li>
273 * <li>{@link BookmarkFolder}s for Folders within Bookmarks with a title and (possibly) contents</li>
274 * </ul>
275 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
276 * @version $Id: BookmarkManager.java,v 1.2 2006/03/26 15:22:16 christianhujer Exp $
277 */
278 public static abstract class Bookmark extends AbstractAction implements MutableTreeNode {
279
280 /** Title for Bookmark.
281 * @serial include
282 */
283 private String title;
284
285 /** The folder (parent) of this bookmark.
286 * @serial include
287 */
288 protected BookmarkFolder folder;
289
290 ///** Create a Bookmark without title.
291 // * Should only be used by {@link BookmarkFolder#BookmarkFolder()}.
292 // */
293 //protected Bookmark() {
294 //}
295
296 /** Create a Bookmark.
297 * You must not forget to invoke {@link #setFolder(BookmarkFolder)} in order to make {@link #getParent()} for JTrees working.
298 * @param title title for Bookmark
299 */
300 protected Bookmark(final String title) {
301 setTitle(title);
302 putValue(SMALL_ICON, IconManager.getDefaultIconManager().getIcon(ACTION_FACTORY.getString("bookmark.icon")));
303 }
304
305 /** {@inheritDoc}
306 * @return title of this Bookmark
307 */
308 public String toString() {
309 return title;
310 }
311
312 /** Get the folder (parent) of this bookmark.
313 * @return folder (parent) of this bookmark
314 */
315 public BookmarkFolder getFolder() {
316 return folder;
317 }
318
319 /** Set the folder (parent) of this bookmark.
320 * @param folder parent folder of this bookmark
321 */
322 public void setFolder(final BookmarkFolder folder) {
323 if (this.folder != null) {
324 this.folder.remove(this);
325 }
326 this.folder = folder;
327 }
328
329 /** Set this Bookmark's title.
330 * @param title new title for this Bookmark
331 */
332 public void setTitle(final String title) {
333 this.title = title;
334 putValue(NAME, title);
335 }
336
337 /** Create a MenuItem for this Bookmark
338 * @return MenuItem for this Bookmark
339 */
340 public abstract JMenuItem createMenu();
341
342 /** Get this Bookmark's title.
343 * @return Bookmark title
344 */
345 public String getTitle() {
346 return title;
347 }
348
349 /** Store bookmarks in an XML Document.
350 * @param n Node (Element or Document) to attach to
351 */
352 public abstract void store(final Node n);
353
354 /** {@inheritDoc} */
355 public Enumeration<Bookmark> children() {
356 return new EmptyEnumeration<Bookmark>();
357 }
358
359 /** {@inheritDoc} */
360 public boolean getAllowsChildren() {
361 return false;
362 }
363
364 /** {@inheritDoc} */
365 public Bookmark getChildAt(final int childIndex) {
366 throw new IndexOutOfBoundsException(Integer.toString(childIndex));
367 }
368
369 /** {@inheritDoc} */
370 public int getChildCount() {
371 return 0;
372 }
373
374 /** {@inheritDoc} */
375 public int getIndex(final TreeNode node) {
376 return 0;
377 }
378
379 /** {@inheritDoc} */
380 public BookmarkFolder getParent() {
381 return getFolder();
382 }
383
384 /** {@inheritDoc} */
385 public boolean isLeaf() {
386 return true;
387 }
388
389 /** {@inheritDoc} */
390 public void insert(final MutableTreeNode child, final int index) {
391 throw new IllegalStateException("A bookmark cannot have children");
392 }
393
394 /** {@inheritDoc} */
395 public void remove(final int index) {
396 throw new IllegalStateException("A bookmark has no children");
397 }
398
399 /** {@inheritDoc} */
400 public void remove(final MutableTreeNode child) {
401 throw new IllegalStateException("A bookmark has no children");
402 }
403
404 /** {@inheritDoc} */
405 public void removeFromParent() {
406 folder.remove(this);
407 }
408
409 /** {@inheritDoc} */
410 public void setParent(final MutableTreeNode newParent) {
411 if (newParent instanceof BookmarkFolder) {
412 setFolder((BookmarkFolder)newParent);
413 } else {
414 throw new IllegalArgumentException("Parent must be a BookmarkFolder, but was : " + newParent.getClass().getName());
415 }
416 }
417
418 /** {@inheritDoc} */
419 public void setUserObject(final Object object) {
420 System.err.println("setUserObject was called but does not know what to do. Supplied object: " + object);
421 }
422
423 } // class Bookmark
424
425
426 /** Class for Bookmark Separator.
427 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
428 * @version $Id: BookmarkManager.java,v 1.2 2006/03/26 15:22:16 christianhujer Exp $
429 */
430 public static class BookmarkSeparator extends Bookmark {
431
432 /** Serial Version. */
433 private static final long serialVersionUID = 1L;
434
435 /** Create a Bookmark Separator. */
436 BookmarkSeparator() {
437 super("--------------------------------");
438 }
439
440 /** {@inheritDoc}
441 * @return always <code>null</code>
442 */
443 @Override public JMenuItem createMenu() {
444 return null;
445 }
446
447 /** {@inheritDoc} */
448 @Override public void store(final Node n) {
449 final Element e = n.getOwnerDocument().createElement("separator");
450 n.appendChild(e);
451 }
452
453 /** {@inheritDoc} */
454 public void actionPerformed(final ActionEvent e) {
455 /* Do nothing */
456 }
457
458 } // class BookmarkSeparator
459
460
461 /** Class for Bookmark Items.
462 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
463 * @version $Id: BookmarkManager.java,v 1.2 2006/03/26 15:22:16 christianhujer Exp $
464 */
465 public class BookmarkItem extends Bookmark {
466
467 /** Serial Version. */
468 private static final long serialVersionUID = 1L;
469
470 /** URL of this Bookmark.
471 * @serial include
472 */
473 private String url;
474
475 /** Create a BookmarkItem.
476 * @param title title for this BookmarkItem
477 * @param url URL for this BookmarkItem
478 */
479 public BookmarkItem(final String title, final String url) {
480 super(title);
481 setURL(url);
482 }
483
484 /** Create a BookmarkItem from XML.
485 * @param el Element to create from
486 */
487 BookmarkItem(final Element el) {
488 this(el.getAttribute("title"), el.getAttribute("href"));
489 }
490
491 /** Set this BookmarkItem's url.
492 * @param url new url for this BookmarkItem
493 */
494 public void setURL(final String url) {
495 this.url = url;
496 putValue(SHORT_DESCRIPTION, url);
497 }
498
499 /** Get this BookmarkItem's url.
500 * @return BookmarkItem url
501 */
502 public String getURL() {
503 return url;
504 }
505
506 /** {@inheritDoc} */
507 @Override public JMenuItem createMenu() {
508 return new JMenuItem(this);
509 }
510
511 /** {@inheritDoc} */
512 public void actionPerformed(final ActionEvent e) {
513 bookmarkable.load(url);
514 }
515
516 /** {@inheritDoc} */
517 public void store(final Node n) {
518 final Element e = n.getOwnerDocument().createElement("bookmark");
519 e.setAttribute("title", getTitle());
520 e.setAttribute("href", getURL());
521 n.appendChild(e);
522 }
523
524 } // class BookmarkItem
525
526
527 /** Class for Bookmark folders.
528 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
529 * @version $Id: BookmarkManager.java,v 1.2 2006/03/26 15:22:16 christianhujer Exp $
530 */
531 public class BookmarkFolder extends Bookmark implements Iterable<Bookmark> {
532
533 /** Serial Version. */
534 private static final long serialVersionUID = 1L;
535
536 /** The bookmarks in this folder.
537 * @serial include
538 */
539 private List<Bookmark> bookmarks = new ArrayList<Bookmark>();
540
541 /** The Menus created for this folder.
542 * @serial include
543 */
544 private List<JMenu> menus = new ArrayList<JMenu>();
545
546 /** Create a BookmarkFolder without a title.
547 * This should only be used for the basic BookmarkFolder containing all other BookmarkItems and BookmarkFolders.
548 */
549 public BookmarkFolder() {
550 super(ACTION_FACTORY.getString("bookmark_text"));
551 }
552
553 /** Create a BookmarkFolder.
554 * @param title title for BookmarkFolder
555 */
556 public BookmarkFolder(final String title) {
557 super(title);
558 addBookmark.putValue(ACCELERATOR_KEY, null);
559 newBookmarkFolder.putValue(ACCELERATOR_KEY, null);
560 }
561
562 /** Create a BookmarkFolder from XML.
563 * @param doc Document to create from
564 */
565 BookmarkFolder(final Document doc) {
566 this();
567 readNodes(doc.getDocumentElement());
568 }
569
570 /** Create a BookmarkFolder from XML.
571 * @param el Element to create from
572 */
573 BookmarkFolder(final Element el) {
574 this(el.getAttribute("title"));
575 readNodes(el);
576 }
577
578 /** Read nodes from XML.
579 * @param el XML Element to read nodes from
580 */
581 private void readNodes(final Element el) {
582 final NodeList children = el.getChildNodes();
583 for (int i = 0; i < children.getLength(); i++) {
584 final Node n = children.item(i);
585 if (n instanceof Element) {
586 final Element e = (Element) n;
587 if ("bookmark".equals(e.getNodeName())) {
588 add(new BookmarkItem(e));
589 } else if ("bookmarks".equals(e.getNodeName())) {
590 add(new BookmarkFolder(e));
591 } else if ("separator".equals(e.getNodeName())) {
592 add(new BookmarkSeparator());
593 }
594 }
595 }
596 }
597
598 /** {@inheritDoc} */
599 public Iterator<Bookmark> iterator() {
600 return bookmarks.iterator();
601 }
602
603 /** Add a Bookmark to this BookmarkFolder.
604 * @param bookmark Bookmark to add
605 */
606 public void add(final Bookmark bookmark) {
607 final int pos = bookmarks.size();
608 bookmarks.add(bookmark);
609 bookmark.setFolder(this);
610 for (JMenu menu : menus) {
611 menu.insert(bookmark.createMenu(), pos);
612 }
613 try {
614 save();
615 } catch (final Exception e) {
616 showMessageDialog(bookmarkable.getBookmarkBlocker(), e, "Bookmarks-Fehler", ERROR_MESSAGE);
617 System.err.println(e);
618 e.printStackTrace();
619 }
620 }
621
622 /** Insert a Bookmark into this BookmarkFolder.
623 * @param bookmark Bookmark to add
624 * @param index desired index
625 */
626 public void insert(final Bookmark bookmark, final int index) {
627 if (index < 0 || index > bookmarks.size()) {
628 throw new IllegalArgumentException("Invalid index: " + index + " (size: " + bookmarks.size() + ")");
629 }
630 bookmark.setFolder(this);
631 bookmarks.add(index, bookmark);
632 for (JMenu menu : menus) {
633 menu.insert(bookmark.createMenu(), index);
634 }
635 try {
636 save();
637 } catch (final Exception e) {
638 showMessageDialog(bookmarkable.getBookmarkBlocker(), e, "Bookmarks-Fehler", ERROR_MESSAGE);
639 System.err.println(e);
640 e.printStackTrace();
641 }
642 }
643
644 /** Remove a Bookmark from this BookmarkFolder.
645 * @param bookmark Bookmark to remove
646 */
647 public void remove(final Bookmark bookmark) {
648 if (bookmarks.contains(bookmark)) {
649 remove(bookmarks.indexOf(bookmark));
650 } else {
651 for (final Bookmark folder : bookmarks) {
652 if (folder instanceof BookmarkFolder) {
653 ((BookmarkFolder)folder).remove(bookmark);
654 }
655 }
656 }
657 }
658
659 /** Remove a Bookmark from this BookmarkFolder.
660 * @param index Index of Bookmark to remove
661 */
662 @Override public void remove(final int index) {
663 final Bookmark bookmark = bookmarks.remove(index);
664 bookmark.folder = null;
665 for (JMenu menu : menus) {
666 menu.remove(index);
667 }
668 }
669
670 /** {@inheritDoc} */
671 @Override public JMenu createMenu() {
672 final JMenu menu = new JMenu(getTitle());
673 menu.setName(getTitle());
674 for (Bookmark bookmark : bookmarks) {
675 if (bookmark instanceof BookmarkSeparator) {
676 menu.addSeparator();
677 } else {
678 menu.add(bookmark.createMenu());
679 }
680 }
681 menu.addSeparator();
682 menu.add(new JMenuItem(addBookmark));
683 menu.add(new JMenuItem(newBookmarkFolder));
684 menus.add(menu);
685 return menu;
686 }
687
688 /** {@inheritDoc} */
689 public void actionPerformed(final ActionEvent e) {
690 /* Do nothing */
691 }
692
693 /** Action for adding a bookmark.
694 * @serial include
695 */
696 private Action addBookmark = ACTION_FACTORY.createAction(true, "addBookmark", this);
697
698 /** Action for creating a new bookmark folder.
699 * @serial include
700 */
701 private Action newBookmarkFolder = ACTION_FACTORY.createAction(true, "newBookmarkFolder", this);
702
703 /** Add a bookmark for the currently selected Question from the currently selected QuestionCollection . */
704 public void addBookmark() {
705 if (bookmarkable.isBookmarkPossible()) {
706 add(new BookmarkItem(bookmarkable.getBookmarkTitle(), bookmarkable.getBookmarkURL()));
707 }
708 }
709
710 /** Create a new BookmarkFolder. */
711 public void newBookmarkFolder() {
712 final String folderName = showInputDialog(bookmarkable.getBookmarkBlocker(), "Name für Lesezeichen", "Neuer Lesezeichen-Ordner", QUESTION_MESSAGE);
713 if (folderName == null) {
714 return;
715 }
716 add(new BookmarkFolder(folderName));
717 }
718
719 /** Set the AddBookmark enabled state.
720 * @param enabled enabled state for AddBookmark action
721 */
722 public void setAddBookmarkEnabled(final boolean enabled) {
723 addBookmark.setEnabled(enabled);
724 for (Bookmark folder : bookmarks) {
725 if (folder instanceof BookmarkFolder) {
726 ((BookmarkFolder)folder).setAddBookmarkEnabled(enabled);
727 }
728 }
729 }
730
731 /** {@inheritDoc} */
732 @Override public void store(final Node n) {
733 final Element e = (n instanceof Document ? (Document) n : n.getOwnerDocument()).createElement("bookmarks");
734 e.setAttribute("title", getTitle());
735 n.appendChild(e);
736 for (Bookmark bookmark : bookmarks) {
737 bookmark.store(e);
738 }
739 }
740
741 /** {@inheritDoc} */
742 public Enumeration<Bookmark> children() {
743 return Collections.enumeration(bookmarks);
744 }
745
746 /** {@inheritDoc} */
747 @Override public boolean getAllowsChildren() {
748 return true;
749 }
750
751 /** {@inheritDoc} */
752 @Override public Bookmark getChildAt(final int childIndex) {
753 return bookmarks.get(childIndex);
754 }
755
756 /** {@inheritDoc} */
757 @Override public int getChildCount() {
758 return bookmarks.size();
759 }
760
761 /** {@inheritDoc} */
762 @Override public int getIndex(final TreeNode node) {
763 return bookmarks.indexOf(node);
764 }
765
766 /** {@inheritDoc} */
767 @Override public boolean isLeaf() {
768 return false;
769 }
770
771 /** {@inheritDoc} */
772 @Override public void insert(final MutableTreeNode child, final int index) {
773 if (child instanceof Bookmark) {
774 insert((Bookmark)child, index);
775 } else {
776 throw new IllegalArgumentException("Children of BookmarkFolders must be instance of Bookmark but was " + child.getClass().getName());
777 }
778 }
779
780 ///** {@inheritDoc} */
781 //public void remove(final int index) {
782 // remove(index);
783 //}
784
785 /** {@inheritDoc} */
786 @Override public void remove(final MutableTreeNode child) {
787 if (child instanceof Bookmark) {
788 remove((Bookmark)child);
789 } else {
790 throw new IllegalArgumentException("Node " + child + " not child of this BookmarkFolder.");
791 }
792 }
793
794 } // class BookmarkFolder
795
796 } // class BookmarkManager