4 * Copyright 2010 Codist Monk.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 package net
.sourceforge
.aprog
.markups
;
27 import static javax
.swing
.KeyStroke
.getKeyStroke
;
28 import static net
.sourceforge
.aprog
.i18n
.Messages
.translate
;
29 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.DOM
;
30 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.FILE
;
31 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.FILE_MODIFIED
;
32 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.MAIN_FRAME
;
33 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.QUASI_XPATH_ERROR
;
34 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.QUASI_XPATH_EXPRESSION
;
35 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.SELECTED_NODE
;
36 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.XPATH_ERROR
;
37 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.XPATH_EXPRESSION
;
38 import static net
.sourceforge
.aprog
.markups
.MarkupsConstants
.Variables
.XPATH_RESULT
;
39 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.addListener
;
40 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.getChildren
;
41 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.getIdentifyingXPath
;
42 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.highlightBackgroundOnError
;
43 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.newTitledPanel
;
44 import static net
.sourceforge
.aprog
.markups
.MarkupsTools
.updateVariableOnTextChanged
;
45 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.META
;
46 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.invokeOnVariableChanged
;
47 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.item
;
48 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.menu
;
49 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.newListener
;
50 import static net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterTools
.registerMacOSXApplicationListener
;
51 import static net
.sourceforge
.aprog
.swing
.SwingTools
.checkAWT
;
52 import static net
.sourceforge
.aprog
.swing
.SwingTools
.menuBar
;
53 import static net
.sourceforge
.aprog
.swing
.SwingTools
.packAndCenter
;
54 import static net
.sourceforge
.aprog
.swing
.SwingTools
.scrollable
;
55 import static net
.sourceforge
.aprog
.tools
.Tools
.debugPrint
;
56 import static net
.sourceforge
.aprog
.tools
.Tools
.emptyIfNull
;
57 import static net
.sourceforge
.aprog
.tools
.Tools
.set
;
58 import static net
.sourceforge
.aprog
.xml
.XMLTools
.DOM_EVENT_NODE_INSERTED
;
59 import static net
.sourceforge
.aprog
.xml
.XMLTools
.DOM_EVENT_NODE_REMOVED
;
60 import static net
.sourceforge
.aprog
.xml
.XMLTools
.addDOMEventListener
;
61 import static net
.sourceforge
.aprog
.xml
.XMLTools
.getNode
;
62 import static net
.sourceforge
.aprog
.xml
.XMLTools
.removeDOMEventListener
;
63 import static net
.sourceforge
.aprog
.xml
.XMLTools
.rename
;
64 import static net
.sourceforge
.aprog
.xml
.XMLTools
.toList
;
66 import java
.awt
.BorderLayout
;
67 import java
.awt
.Color
;
68 import java
.awt
.dnd
.DropTarget
;
69 import java
.awt
.dnd
.DropTargetAdapter
;
70 import java
.awt
.dnd
.DropTargetDragEvent
;
71 import java
.awt
.dnd
.DropTargetDropEvent
;
72 import java
.awt
.dnd
.DropTargetEvent
;
73 import java
.awt
.event
.WindowListener
;
75 import java
.util
.List
;
76 import java
.util
.WeakHashMap
;
78 import javax
.swing
.BorderFactory
;
79 import javax
.swing
.DefaultListModel
;
80 import javax
.swing
.JButton
;
81 import javax
.swing
.JFrame
;
82 import javax
.swing
.JList
;
83 import javax
.swing
.JMenuBar
;
84 import javax
.swing
.JMenuItem
;
85 import javax
.swing
.JPanel
;
86 import javax
.swing
.JSplitPane
;
87 import javax
.swing
.JTabbedPane
;
88 import javax
.swing
.JTextArea
;
89 import javax
.swing
.JTextField
;
90 import javax
.swing
.JTree
;
91 import javax
.swing
.SwingUtilities
;
92 import javax
.swing
.WindowConstants
;
93 import javax
.swing
.border
.TitledBorder
;
94 import javax
.swing
.event
.DocumentEvent
;
95 import javax
.swing
.event
.DocumentListener
;
96 import javax
.swing
.event
.TreeSelectionEvent
;
97 import javax
.swing
.event
.TreeSelectionListener
;
98 import javax
.swing
.tree
.DefaultMutableTreeNode
;
99 import javax
.swing
.tree
.DefaultTreeModel
;
100 import javax
.swing
.tree
.TreePath
;
102 import net
.sourceforge
.aprog
.af
.MacOSXTools
;
103 import net
.sourceforge
.aprog
.context
.Context
;
104 import net
.sourceforge
.aprog
.events
.Variable
;
105 import net
.sourceforge
.aprog
.events
.Variable
.ValueChangedEvent
;
106 import net
.sourceforge
.aprog
.i18n
.Translator
;
107 import net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterActions
;
108 import net
.sourceforge
.aprog
.subtitlesadjuster
.SubtitlesAdjusterComponents
;
109 import net
.sourceforge
.aprog
.swing
.SwingTools
;
110 import net
.sourceforge
.aprog
.tools
.IllegalInstantiationException
;
112 import org
.w3c
.dom
.Node
;
113 import org
.w3c
.dom
.NodeList
;
114 import org
.w3c
.dom
.events
.Event
;
115 import org
.w3c
.dom
.events
.EventListener
;
119 * @author codistmonk (creation 2010-07-03)
121 public final class MarkupsComponents
{
124 * @throws IllegalInstantiationException To prevent instantiation
126 private MarkupsComponents() {
127 throw new IllegalInstantiationException();
139 public static final JFrame
newMainFrame(final Context context
) {
140 final JFrame result
= new JFrame();
142 context
.set(MAIN_FRAME
, result
);
144 result
.setJMenuBar(newMenuBar(context
));
145 result
.add(newMainPanel(context
));
146 result
.setDefaultCloseOperation(WindowConstants
.DO_NOTHING_ON_CLOSE
);
148 result
.addWindowListener(newListener(WindowListener
.class, "windowClosing",
149 MarkupsActions
.class, "quit", context
));
151 invokeOnVariableChanged(context
, FILE
,
152 SubtitlesAdjusterActions
.class, "updateMainFrameTitle", context
);
153 invokeOnVariableChanged(context
, FILE_MODIFIED
,
154 SubtitlesAdjusterActions
.class, "updateMainFrameTitle", context
);
156 Translator
.getDefaultTranslator().addListener(newListener(Translator
.Listener
.class, "localeChanged",
157 SwingTools
.class, "packAndUpdateMinimumSize", result
));
159 return packAndCenter(result
);
171 public static final JMenuBar
newMenuBar(final Context context
) {
174 if (MacOSXTools
.MAC_OS_X
) {
175 MacOSXTools
.setUseScreenMenuBar(true);
180 newAboutMenuItem(context
),
182 newPreferencesMenuItem(context
),
184 newQuitMenuItem(context
)
187 newNewMenuItem(context
),
189 newOpenMenuItem(context
),
191 newSaveMenuItem(context
),
192 newSaveAsMenuItem(context
)
195 newUndoMenuItem(context
),
196 newRedoMenuItem(context
),
198 newCopyMenuItem(context
),
199 newCutMenuItem(context
),
200 newPasteMenuItem(context
)
203 newAppendNewNodeMenuItem(context
),
205 newMoveUpMenuItem(context
),
206 newMoveDownMenuItem(context
)
209 newManualMenuItem(context
)
222 public static final JMenuItem
newAboutMenuItem(final Context context
) {
225 return SubtitlesAdjusterComponents
.newAboutMenuItem(context
);
237 public static final JMenuItem
newPreferencesMenuItem(final Context context
) {
240 return SubtitlesAdjusterComponents
.newPreferencesMenuItem(context
);
252 public static final JMenuItem
newQuitMenuItem(final Context context
) {
255 if (MacOSXTools
.MAC_OS_X
&& MacOSXTools
.getUseScreenMenuBar()) {
256 if (registerMacOSXApplicationListener("handleQuit",
257 MarkupsActions
.class, "quit", context
)) {
262 return item("Quit", getKeyStroke(META
+ " Q"),
263 MarkupsActions
.class, "quit", context
);
275 public static final JMenuItem
newNewMenuItem(final Context context
) {
276 return item("New", getKeyStroke(META
+ " N"),
277 MarkupsActions
.class, "newFile", context
);
289 public static final JMenuItem
newOpenMenuItem(final Context context
) {
290 return item("Open...", getKeyStroke(META
+ " O"),
291 MarkupsActions
.class, "open", context
);
303 public static final JMenuItem
newSaveMenuItem(final Context context
) {
304 final JMenuItem result
= item("Save", getKeyStroke(META
+ " S"),
305 MarkupsActions
.class, "save", context
);
306 final Variable
<Boolean
> fileModifiedVariable
= context
.getVariable(FILE_MODIFIED
);
308 fileModifiedVariable
.addListener(new Variable
.Listener
<Boolean
>() {
311 public final void valueChanged(final ValueChangedEvent
<Boolean
, ?
> event
) {
312 result
.setEnabled(event
.getNewValue());
329 public static final JMenuItem
newSaveAsMenuItem(final Context context
) {
330 final JMenuItem result
= item("Save As...", getKeyStroke(META
+ " shift S"),
331 MarkupsActions
.class, "saveAs", context
);
345 public static final JMenuItem
newUndoMenuItem(final Context context
) {
346 final JMenuItem result
= item("Undo", getKeyStroke(META
+ " Z"),
347 MarkupsActions
.class, "undo", context
);
361 public static final JMenuItem
newRedoMenuItem(final Context context
) {
362 final JMenuItem result
= item("Redo", getKeyStroke(META
+ " Y"),
363 MarkupsActions
.class, "redo", context
);
377 public static final JMenuItem
newCopyMenuItem(final Context context
) {
378 final JMenuItem result
= item("Copy", getKeyStroke(META
+ " C"),
379 MarkupsActions
.class, "copy", context
);
393 public static final JMenuItem
newCutMenuItem(final Context context
) {
394 final JMenuItem result
= item("Cut", getKeyStroke(META
+ " X"),
395 MarkupsActions
.class, "cut", context
);
409 public static final JMenuItem
newPasteMenuItem(final Context context
) {
410 final JMenuItem result
= item("Paste", getKeyStroke(META
+ " V"),
411 MarkupsActions
.class, "paste", context
);
425 public static final JMenuItem
newAppendNewNodeMenuItem(final Context context
) {
426 final JMenuItem result
= item("Append New Node",
427 MarkupsActions
.class, "appendNewNode", context
);
441 public static final JMenuItem
newMoveUpMenuItem(final Context context
) {
442 final JMenuItem result
= item("Move Up",
443 MarkupsActions
.class, "moveUp", context
);
457 public static final JMenuItem
newMoveDownMenuItem(final Context context
) {
458 final JMenuItem result
= item("Move Down",
459 MarkupsActions
.class, "moveDown", context
);
473 public static final JMenuItem
newManualMenuItem(final Context context
) {
475 "Manual", getKeyStroke("F1"),
476 SubtitlesAdjusterActions
.class, "showManual", context
);
487 public static final JPanel
newMainPanel(final Context context
) {
488 final JPanel result
= new JPanel(new BorderLayout());
490 result
.add(newMainSplitPane(context
));
492 new DropTarget(result
, new DropTargetAdapter() {
495 public final void dragEnter(final DropTargetDragEvent event
) {
496 result
.setBorder(BorderFactory
.createLineBorder(Color
.GREEN
, 2));
500 public final void dragExit(final DropTargetEvent event
) {
501 result
.setBorder(null);
505 public final void drop(final DropTargetDropEvent event
) {
506 result
.setBorder(null);
508 final List
<File
> files
= SwingTools
.getFiles(event
);
510 if (!files
.isEmpty() && MarkupsActions
.confirm(context
)) {
511 MarkupsActions
.open(context
, files
.get(0));
517 final EventListener domListener
= new EventListener() {
520 public final void handleEvent(final Event event
) {
526 addListener(context
, DOM
, new AbstractDOMListenerReattacher(domListener
) {
527 // Deliberately left empty
541 public static final JSplitPane
newMainSplitPane(final Context context
) {
542 return new JSplitPane(JSplitPane
.HORIZONTAL_SPLIT
,
543 scrollable(newDOMTreeView(context
)),
544 newContextualSplitPane(context
));
555 public static final JSplitPane
newContextualSplitPane(final Context context
) {
556 return new JSplitPane(JSplitPane
.VERTICAL_SPLIT
,
557 newNodePanel(context
),
558 newXPathPanel(context
));
569 public static final JPanel
newNodePanel(final Context context
) {
570 final JPanel result
= new JPanel(new BorderLayout());
572 result
.add(newNodeNamePanel(context
), BorderLayout
.NORTH
);
573 result
.add(newNodeValuePanel(context
), BorderLayout
.CENTER
);
586 public static final JPanel
newNodeNamePanel(final Context context
) {
587 return newTitledPanel("Name", newNodeNameTextField(context
));
598 public static final JTextField
newNodeNameTextField(final Context context
) {
599 final JTextField result
= new JTextField();
600 final Variable
<Node
> selectedNodeVariable
= context
.getVariable(SELECTED_NODE
);
601 final EventListener nodeListener
= new EventListener() {
604 public final void handleEvent(final Event event
) {
605 final Node node
= selectedNodeVariable
.getValue();
607 result
.setText(node
== null ?
"" : node
.getNodeName());
612 selectedNodeVariable
.addListener(new Variable
.Listener
<Node
>() {
615 public final void valueChanged(final ValueChangedEvent
<Node
, ?
> event
) {
616 if (event
.getOldValue() != null) {
617 removeDOMEventListener(event
.getOldValue(), nodeListener
);
620 final Node node
= event
.getNewValue();
623 addDOMEventListener(node
, nodeListener
);
626 result
.setEditable(node
!= null && set(Node
.ATTRIBUTE_NODE
,
627 Node
.ELEMENT_NODE
).contains(node
.getNodeType()));
629 result
.setText(node
== null ?
"" : node
.getNodeName());
634 result
.getDocument().addDocumentListener(new AbstractDocumentHandler() {
637 protected final void eventReceived(final DocumentEvent event
) {
638 SwingUtilities
.invokeLater(new Runnable() {
641 public final void run() {
642 final Node node
= selectedNodeVariable
.getValue();
643 final String text
= result
.getText();
645 if (node
== null || node
.getNodeName().equals(text
)) {
652 node
.getNamespaceURI(),
653 node
.getNamespaceURI() == null ? text
: node
.getPrefix() + ":" + text
);
654 } catch (final Exception exception
) {
655 exception
.printStackTrace();
656 result
.setText(node
.getNodeName());
676 public static final JPanel
newNodeValuePanel(final Context context
) {
677 return newTitledPanel("Value", scrollable(newNodeValueTextArea(context
)));
688 public static final JTextArea
newNodeValueTextArea(final Context context
) {
689 final Variable
<Node
> selectedNodeVariable
= context
.getVariable(SELECTED_NODE
);
690 final JTextArea result
= new JTextArea();
692 final EventListener nodeListener
= new EventListener() {
695 public final void handleEvent(final Event event
) {
696 final Node node
= selectedNodeVariable
.getValue();
698 if (event
.getTarget() == node
) {
699 result
.setText(node
== null ?
"" : node
.getNodeValue());
705 selectedNodeVariable
.addListener(new Variable
.Listener
<Node
>() {
708 public final void valueChanged(final ValueChangedEvent
<Node
, ?
> event
) {
709 if (event
.getOldValue() != null) {
710 removeDOMEventListener(event
.getOldValue(), nodeListener
);
713 final Node node
= event
.getNewValue();
716 addDOMEventListener(node
, nodeListener
);
719 result
.setEditable(node
!= null && set(Node
.ATTRIBUTE_NODE
, Node
.CDATA_SECTION_NODE
, Node
.COMMENT_NODE
,
720 Node
.PROCESSING_INSTRUCTION_NODE
, Node
.TEXT_NODE
).contains(node
.getNodeType()));
722 result
.setText(node
== null ?
"" : node
.getNodeValue());
727 result
.getDocument().addDocumentListener(new AbstractDocumentHandler() {
730 protected final void eventReceived(final DocumentEvent event
) {
731 SwingUtilities
.invokeLater(new Runnable() {
734 public final void run() {
735 final Node node
= selectedNodeVariable
.getValue();
736 final String text
= result
.getText();
738 if (node
== null || emptyIfNull(node
.getNodeValue()).equals(emptyIfNull(text
))) {
743 node
.setNodeValue(text
);
744 } catch (final Exception exception
) {
745 exception
.printStackTrace();
746 result
.setText(node
.getNodeValue());
766 public static final JPanel
newXPathPanel(final Context context
) {
767 final JPanel result
= new JPanel(new BorderLayout());
769 result
.setBorder(BorderFactory
.createTitledBorder(
770 BorderFactory
.createEtchedBorder(),
775 result
.add(newTitledPanel("Context", newContextTextField(context
)), BorderLayout
.NORTH
);
776 result
.add(newXPathTabbedPane(context
), BorderLayout
.CENTER
);
789 public static final JTextField
newContextTextField(final Context context
) {
790 final Variable
<Node
> selectedNodeVariable
= context
.getVariable(SELECTED_NODE
);
791 final JTextField result
= new JTextField();
793 final EventListener nodeListener
= new EventListener() {
796 public final void handleEvent(final Event event
) {
797 final Node node
= selectedNodeVariable
.getValue();
799 if (event
.getTarget() == node
) {
800 result
.setText(node
== null ?
"" : getIdentifyingXPath(node
));
806 selectedNodeVariable
.addListener(new Variable
.Listener
<Node
>() {
809 public final void valueChanged(final ValueChangedEvent
<Node
, ?
> event
) {
810 if (event
.getOldValue() != null) {
811 removeDOMEventListener(event
.getOldValue(), nodeListener
);
814 final Node node
= event
.getNewValue();
817 addDOMEventListener(node
, nodeListener
);
820 result
.setText(node
== null ?
"" : getIdentifyingXPath(node
));
825 result
.setEditable(false);
838 public static final JTabbedPane
newXPathTabbedPane(final Context context
) {
839 final JTabbedPane result
= new JTabbedPane();
841 result
.add("List", newXPathListSplitPane(context
));
842 result
.add("Create", newQuasiXPathPanel(context
));
855 public static final JSplitPane
newXPathListSplitPane(final Context context
) {
856 return new JSplitPane(JSplitPane
.VERTICAL_SPLIT
,
857 newTitledPanel("XPath Expression", scrollable(newXPathExpressionTextArea(context
))),
858 newTitledPanel("Matches", scrollable(newXPathList(context
))));
869 public static final JTextArea
newXPathExpressionTextArea(final Context context
) {
870 final JTextArea result
= new JTextArea();
872 updateVariableOnTextChanged(context
, XPATH_EXPRESSION
, result
);
874 highlightBackgroundOnError(context
, XPATH_ERROR
, result
);
887 public static final JList
newXPathList(final Context context
) {
888 final DefaultListModel model
= new DefaultListModel();
889 final JList result
= new JList(model
);
891 addListener(context
, XPATH_RESULT
, new Variable
.Listener
<NodeList
>() {
894 public final void valueChanged(final ValueChangedEvent
<NodeList
, ?
> event
) {
897 if (event
.getNewValue() != null) {
898 for (final Node node
: toList(event
.getNewValue())) {
899 model
.addElement(node
);
917 public static final JPanel
newQuasiXPathPanel(final Context context
) {
918 final JPanel result
= new JPanel(new BorderLayout());
920 result
.add(newTitledPanel("Quasi-XPath Expression", newQuasiXPathExpressionTextArea(context
)), BorderLayout
.CENTER
);
921 result
.add(newQuasiXPathCreateButton(context
), BorderLayout
.SOUTH
);
934 public static final JTextArea
newQuasiXPathExpressionTextArea(final Context context
) {
935 final JTextArea result
= new JTextArea();
937 updateVariableOnTextChanged(context
, QUASI_XPATH_EXPRESSION
, result
);
939 highlightBackgroundOnError(context
, QUASI_XPATH_ERROR
, result
);
952 public static final JButton
newQuasiXPathCreateButton(final Context context
) {
953 final JButton result
= translate(new JButton("Create Node"));
955 result
.addActionListener(SwingTools
.action(
956 MarkupsActions
.class, "evaluateQuasiXPathExpression", context
));
969 public static final JTree
newDOMTreeView(final Context context
) {
970 final Variable
<Node
> domVariable
= context
.getVariable(DOM
);
971 final JTree result
= new JTree(new DOMTreeModel(domVariable
.getValue()));
973 domVariable
.addListener(new Variable
.Listener
<Node
>() {
976 public final void valueChanged(final ValueChangedEvent
<Node
, ?
> event
) {
977 result
.setModel(new DOMTreeModel(event
.getNewValue()));
982 result
.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
985 public final void valueChanged(final TreeSelectionEvent event
) {
986 if (event
.getNewLeadSelectionPath() == null) {
987 context
.set(SELECTED_NODE
, null);
992 final DefaultMutableTreeNode selectedTreeNode
= (DefaultMutableTreeNode
) event
.getNewLeadSelectionPath().getLastPathComponent();
994 if (selectedTreeNode
!= null) {
995 context
.set(SELECTED_NODE
, (Node
) selectedTreeNode
.getUserObject());
1001 addListener(context
, SELECTED_NODE
, new Variable
.Listener
<Node
>() {
1004 public final void valueChanged(final ValueChangedEvent
<Node
, ?
> event
) {
1005 final DOMTreeModel treeModel
= (DOMTreeModel
) result
.getModel();
1006 final DOMTreeModel
.DOMTreeNode treeNode
= treeModel
.get(event
.getNewValue());
1008 if (treeNode
!= null) {
1009 result
.setSelectionPath(new TreePath(treeModel
.getPathToRoot(treeNode
)));
1011 result
.setSelectionPath(null);
1022 * @author codistmonk (creation 2010-07-04)
1024 public static final class DOMTreeModel
extends DefaultTreeModel
{
1026 private final WeakHashMap
<Node
, DOMTreeNode
> xmlTreeNodes
;
1034 public DOMTreeModel(final Node domNode
) {
1035 super(new DefaultMutableTreeNode());
1036 this.xmlTreeNodes
= new WeakHashMap
<Node
, DOMTreeNode
>();
1038 this.setRoot(this.new DOMTreeNode(domNode
));
1047 public final Node
getDOMNode() {
1048 return (Node
) ((DefaultMutableTreeNode
) this.getRoot()).getUserObject();
1056 * @param xmlTreeNode
1060 final void put(final Node domNode
, final DOMTreeNode xmlTreeNode
) {
1061 this.xmlTreeNodes
.put(domNode
, xmlTreeNode
);
1072 final DOMTreeNode
get(final Node domNode
) {
1073 return this.xmlTreeNodes
.get(domNode
);
1076 private static final long serialVersionUID
= 4264388285566053331L;
1080 * @author codistmonk (creation 2010-07-10)
1082 public final class DOMTreeNode
extends DefaultMutableTreeNode
{
1090 public DOMTreeNode(final Node domNode
) {
1093 this.getTreeModel().put(domNode
, this);
1095 addDOMEventListener(domNode
, new EventListener() {
1098 public final void handleEvent(final Event event
) {
1099 debugPrint("\ntype", event
.getType(), "\ntarget", event
.getTarget());
1100 if (event
.getTarget() == domNode
) {
1101 if (DOM_EVENT_NODE_REMOVED
.equals(event
.getType())) {
1102 DOMTreeNode
.this.getTreeModel().removeNodeFromParent(DOMTreeNode
.this);
1103 } else if (DOM_EVENT_NODE_INSERTED
.equals(event
.getType())) {
1104 final Node domParent
= getNode(domNode
, "..");
1105 final DOMTreeNode parent
= DOMTreeNode
.this.getTreeModel().get(domParent
);
1106 final List
<Node
> siblings
= getChildren(domParent
);
1108 DOMTreeNode
.this.getTreeModel().insertNodeInto(DOMTreeNode
.this, parent
, siblings
.indexOf(domNode
));
1110 DOMTreeNode
.this.refresh();
1117 for (final Node domChild
: getChildren(domNode
)) {
1118 this.add(new DOMTreeNode(domChild
));
1122 final void refresh() {
1125 for (final Node domChild
: getChildren(this.getDomNode())) {
1126 DOMTreeModel
.this.insertNodeInto(this.getOrCreate(domChild
), DOMTreeNode
.this, i
++);
1139 private final DOMTreeNode
getOrCreate(final Node domNode
) {
1140 DOMTreeNode result
= DOMTreeModel
.this.get(domNode
);
1142 if (result
== null) {
1143 result
= DOMTreeModel
.this.new DOMTreeNode(domNode
);
1155 public final Node
getDomNode() {
1156 return (Node
) this.getUserObject();
1165 public final DOMTreeModel
getTreeModel() {
1166 return DOMTreeModel
.this;
1170 public final String
toString() {
1171 switch (this.getDomNode().getNodeType()) {
1172 case Node
.ATTRIBUTE_NODE
:
1173 return this.getDomNode().getNodeName() +
1174 (this.getDomNode().getNodeValue() == null ?
"" : "=\"" + this.getDomNode().getNodeValue() + "\"");
1176 return this.getDomNode().getNodeName() +
1177 (this.getDomNode().getNodeValue() == null ?
"" : "[" + this.getDomNode().getNodeValue() + "]");
1181 private static final long serialVersionUID
= 8090552131823122052L;
1189 * @author codistmonk (creation 2010-07-07)
1191 public static abstract class AbstractDocumentHandler
implements DocumentListener
{
1194 public final void insertUpdate(final DocumentEvent event
) {
1195 this.doInsertUpdate(event
);
1199 public final void removeUpdate(final DocumentEvent event
) {
1200 this.doRemoveUpdate(event
);
1204 public final void changedUpdate(final DocumentEvent event
) {
1205 this.doChangedUpdate(event
);
1213 protected void doInsertUpdate(final DocumentEvent event
) {
1214 this.eventReceived(event
);
1222 protected void doRemoveUpdate(final DocumentEvent event
) {
1223 this.eventReceived(event
);
1231 protected void doChangedUpdate(final DocumentEvent event
) {
1232 this.eventReceived(event
);
1240 protected abstract void eventReceived(DocumentEvent event
);