[Markups]
[aprog.git] / Markups / src / net / sourceforge / aprog / markups / MarkupsComponents.java
blobef43c1fef4db8983ca48f35d688c093d8ecb3eba
1 /*
2 * The MIT License
3 *
4 * Copyright 2010 Codist Monk.
5 *
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
22 * THE SOFTWARE.
25 package net.sourceforge.aprog.markups;
27 import static javax.swing.KeyStroke.getKeyStroke;
29 import static net.sourceforge.aprog.i18n.Messages.*;
30 import static net.sourceforge.aprog.markups.MarkupsConstants.Variables.*;
31 import static net.sourceforge.aprog.markups.MarkupsXMLTools.*;
32 import static net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterTools.*;
33 import static net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterTools.menu;
34 import static net.sourceforge.aprog.swing.SwingTools.checkAWT;
35 import static net.sourceforge.aprog.swing.SwingTools.menuBar;
36 import static net.sourceforge.aprog.swing.SwingTools.packAndCenter;
37 import static net.sourceforge.aprog.swing.SwingTools.scrollable;
38 import static net.sourceforge.aprog.tools.Tools.*;
39 import static net.sourceforge.aprog.xml.XMLTools.*;
41 import java.awt.BorderLayout;
42 import java.awt.Color;
43 import java.awt.Component;
44 import java.awt.dnd.DropTarget;
45 import java.awt.dnd.DropTargetAdapter;
46 import java.awt.dnd.DropTargetDragEvent;
47 import java.awt.dnd.DropTargetDropEvent;
48 import java.awt.dnd.DropTargetEvent;
49 import java.awt.event.ActionEvent;
50 import java.awt.event.ActionListener;
51 import java.awt.event.WindowListener;
52 import java.io.ByteArrayOutputStream;
53 import java.io.File;
54 import java.util.List;
56 import javax.swing.BorderFactory;
57 import javax.swing.DefaultListModel;
58 import javax.swing.JButton;
59 import javax.swing.JFrame;
60 import javax.swing.JList;
61 import javax.swing.JMenuBar;
62 import javax.swing.JMenuItem;
63 import javax.swing.JPanel;
64 import javax.swing.JSplitPane;
65 import javax.swing.JTabbedPane;
66 import javax.swing.JTextArea;
67 import javax.swing.JTextField;
68 import javax.swing.JTree;
69 import javax.swing.SwingUtilities;
70 import javax.swing.border.TitledBorder;
71 import javax.swing.event.DocumentEvent;
72 import javax.swing.event.DocumentListener;
73 import javax.swing.event.TreeSelectionEvent;
74 import javax.swing.event.TreeSelectionListener;
75 import javax.swing.tree.DefaultMutableTreeNode;
76 import javax.swing.tree.DefaultTreeModel;
78 import net.sourceforge.aprog.context.Context;
79 import net.sourceforge.aprog.events.Variable;
80 import net.sourceforge.aprog.events.Variable.ValueChangedEvent;
81 import net.sourceforge.aprog.i18n.Translator;
82 import net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterActions;
83 import net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterComponents;
84 import net.sourceforge.aprog.swing.SwingTools;
85 import net.sourceforge.aprog.tools.IllegalInstantiationException;
86 import net.sourceforge.aprog.xml.XMLTools;
87 import net.sourceforge.jmacadapter.MacAdapterTools;
89 import org.w3c.dom.NamedNodeMap;
90 import org.w3c.dom.Node;
91 import org.w3c.dom.events.Event;
92 import org.w3c.dom.events.EventListener;
94 /**
96 * @author codistmonk (creation 2010-07-03)
98 public final class MarkupsComponents {
101 * @throws IllegalInstantiationException To prevent instantiation
103 private MarkupsComponents() {
104 throw new IllegalInstantiationException();
109 * @param context
110 * <br>Not null
111 * <br>Input-output
112 * @return
113 * <br>Not null
114 * <br>New
116 public static final JFrame newMainFrame(final Context context) {
117 final JFrame result = new JFrame();
119 context.set(MAIN_FRAME, result);
121 result.setJMenuBar(newMenuBar(context));
122 result.add(newMainPanel(context));
124 result.addWindowListener(newListener(WindowListener.class, "windowClosing",
125 MarkupsActions.class, "quit", context));
127 invokeOnVariableChanged(context, FILE,
128 SubtitlesAdjusterActions.class, "updateMainFrameTitle", context);
129 invokeOnVariableChanged(context, FILE_MODIFIED,
130 SubtitlesAdjusterActions.class, "updateMainFrameTitle", context);
132 Translator.getDefaultTranslator().addListener(newListener(Translator.Listener.class, "localeChanged",
133 SwingTools.class, "packAndUpdateMinimumSize", result));
135 return packAndCenter(result);
140 * @param context
141 * <br>Not null
142 * <br>Shared
143 * @return
144 * <br>Not null
145 * <br>New
147 public static final JMenuBar newMenuBar(final Context context) {
148 checkAWT();
150 if (MacAdapterTools.isMacOSX()) {
151 MacAdapterTools.setUseScreenMenuBar(true);
154 return menuBar(
155 menu("Application",
156 newAboutMenuItem(context),
157 null,
158 newPreferencesMenuItem(context),
159 null,
160 newQuitMenuItem(context)
162 menu("File",
163 newNewMenuItem(context),
164 null,
165 newOpenMenuItem(context),
166 null,
167 newSaveMenuItem(context),
168 newSaveAsMenuItem(context)
170 menu("Edit",
171 newUndoMenuItem(context),
172 newRedoMenuItem(context),
173 null,
174 newCopyMenuItem(context),
175 newCutMenuItem(context),
176 newPasteMenuItem(context)
178 menu("Node",
179 newAppendNewNodeMenuItem(context),
180 null,
181 newMoveUpMenuItem(context),
182 newMoveDownMenuItem(context)
184 menu("Help",
185 newManualMenuItem(context)
191 * @param context
192 * <br>Not null
193 * <br>Shared
194 * @return
195 * <br>Not null
196 * <br>New
198 public static final JMenuItem newAboutMenuItem(final Context context) {
199 checkAWT();
201 return SubtitlesAdjusterComponents.newAboutMenuItem(context);
206 * @param context
207 * <br>Not null
208 * <br>Shared
209 * @return
210 * <br>Not null
211 * <br>New
213 public static final JMenuItem newPreferencesMenuItem(final Context context) {
214 checkAWT();
216 return SubtitlesAdjusterComponents.newPreferencesMenuItem(context);
221 * @param context
222 * <br>Not null
223 * <br>Shared
224 * @return
225 * <br>Not null
226 * <br>New
228 public static final JMenuItem newQuitMenuItem(final Context context) {
229 checkAWT();
231 if (MacAdapterTools.isMacOSX() && MacAdapterTools.getUseScreenMenuBar()) {
232 if (registerMacOSXApplicationListener("handleQuit",
233 MarkupsActions.class, "quit", context)) {
234 return null;
238 return item("Quit", getKeyStroke(META + " Q"),
239 MarkupsActions.class, "quit", context);
244 * @param context
245 * <br>Not null
246 * <br>Shared
247 * @return
248 * <br>Not null
249 * <br>New
251 public static final JMenuItem newNewMenuItem(final Context context) {
252 return item("New", getKeyStroke(META + " N"),
253 MarkupsActions.class, "newFile", context);
258 * @param context
259 * <br>Not null
260 * <br>Shared
261 * @return
262 * <br>Not null
263 * <br>New
265 public static final JMenuItem newOpenMenuItem(final Context context) {
266 return item("Open...", getKeyStroke(META + " O"),
267 MarkupsActions.class, "open", context);
272 * @param context
273 * <br>Not null
274 * <br>Shared
275 * @return
276 * <br>Not null
277 * <br>New
279 public static final JMenuItem newSaveMenuItem(final Context context) {
280 final JMenuItem result = item("Save", getKeyStroke(META + " S"),
281 MarkupsActions.class, "save", context);
282 final Variable<Boolean> fileModifiedVariable = context.getVariable(FILE_MODIFIED);
284 fileModifiedVariable.addListener(new Variable.Listener<Boolean>() {
286 @Override
287 public final void valueChanged(final ValueChangedEvent<Boolean, ?> event) {
288 result.setEnabled(event.getNewValue());
293 return result;
298 * @param context
299 * <br>Not null
300 * <br>Shared
301 * @return
302 * <br>Not null
303 * <br>New
305 public static final JMenuItem newSaveAsMenuItem(final Context context) {
306 final JMenuItem result = item("Save As...", getKeyStroke(META + " shift S"),
307 MarkupsActions.class, "saveAs", context);
309 return result;
314 * @param context
315 * <br>Not null
316 * <br>Shared
317 * @return
318 * <br>Not null
319 * <br>New
321 public static final JMenuItem newUndoMenuItem(final Context context) {
322 final JMenuItem result = item("Undo", getKeyStroke(META + " Z"),
323 MarkupsActions.class, "undo", context);
325 return result;
330 * @param context
331 * <br>Not null
332 * <br>Shared
333 * @return
334 * <br>Not null
335 * <br>New
337 public static final JMenuItem newRedoMenuItem(final Context context) {
338 final JMenuItem result = item("Redo", getKeyStroke(META + " Y"),
339 MarkupsActions.class, "redo", context);
341 return result;
346 * @param context
347 * <br>Not null
348 * <br>Shared
349 * @return
350 * <br>Not null
351 * <br>New
353 public static final JMenuItem newCopyMenuItem(final Context context) {
354 final JMenuItem result = item("Copy", getKeyStroke(META + " C"),
355 MarkupsActions.class, "copy", context);
357 return result;
362 * @param context
363 * <br>Not null
364 * <br>Shared
365 * @return
366 * <br>Not null
367 * <br>New
369 public static final JMenuItem newCutMenuItem(final Context context) {
370 final JMenuItem result = item("Cut", getKeyStroke(META + " X"),
371 MarkupsActions.class, "cut", context);
373 return result;
378 * @param context
379 * <br>Not null
380 * <br>Shared
381 * @return
382 * <br>Not null
383 * <br>New
385 public static final JMenuItem newPasteMenuItem(final Context context) {
386 final JMenuItem result = item("Paste", getKeyStroke(META + " V"),
387 MarkupsActions.class, "paste", context);
389 return result;
394 * @param context
395 * <br>Not null
396 * <br>Shared
397 * @return
398 * <br>Not null
399 * <br>New
401 public static final JMenuItem newAppendNewNodeMenuItem(final Context context) {
402 final JMenuItem result = item("Append New Node",
403 MarkupsActions.class, "appendNewNode", context);
405 return result;
410 * @param context
411 * <br>Not null
412 * <br>Shared
413 * @return
414 * <br>Not null
415 * <br>New
417 public static final JMenuItem newMoveUpMenuItem(final Context context) {
418 final JMenuItem result = item("Move Up",
419 MarkupsActions.class, "moveUp", context);
421 return result;
426 * @param context
427 * <br>Not null
428 * <br>Shared
429 * @return
430 * <br>Not null
431 * <br>New
433 public static final JMenuItem newMoveDownMenuItem(final Context context) {
434 final JMenuItem result = item("Move Down",
435 MarkupsActions.class, "moveDown", context);
437 return result;
442 * @param context
443 * <br>Not null
444 * <br>Shared
445 * @return
446 * <br>Not null
447 * <br>New
449 public static final JMenuItem newManualMenuItem(final Context context) {
450 return item(
451 "Manual", getKeyStroke("F1"),
452 SubtitlesAdjusterActions.class, "showManual", context);
457 * @param context
458 * <br>Not null
459 * @return
460 * <br>Not null
461 * <br>New
463 public static final JPanel newMainPanel(final Context context) {
464 final JPanel result = new JPanel(new BorderLayout());
466 result.add(newMainSplitPane(context));
468 new DropTarget(result, new DropTargetAdapter() {
470 @Override
471 public final void dragEnter(final DropTargetDragEvent event) {
472 result.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
475 @Override
476 public final void dragExit(final DropTargetEvent event) {
477 result.setBorder(null);
480 @Override
481 public final void drop(final DropTargetDropEvent event) {
482 result.setBorder(null);
484 final List<File> files = SwingTools.getFiles(event);
486 if (!files.isEmpty() && MarkupsActions.confirm(context)) {
487 MarkupsActions.open(context, files.get(0));
493 final Variable<Node> selectedNodeVariable = context.getVariable(DOM);
495 selectedNodeVariable.addListener(new Variable.Listener<Node>() {
497 @Override
498 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
499 final Node node = event.getNewValue();
501 debugPrint(node);
503 addDOMEventListener(node, new EventListener() {
505 @Override
506 public final void handleEvent(final Event event) {
507 result.repaint();
515 return result;
520 * @param context
521 * <br>Not null
522 * @return
523 * <br>Not null
524 * <br>New
526 public static final JSplitPane newMainSplitPane(final Context context) {
527 return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
528 scrollable(newDOMTreeView(context)),
529 newContextualSplitPane(context));
534 * @param context
535 * <br>Not null
536 * @return
537 * <br>Not null
538 * <br>New
540 public static final JSplitPane newContextualSplitPane(final Context context) {
541 return new JSplitPane(JSplitPane.VERTICAL_SPLIT,
542 newNodePanel(context),
543 newXPathPanel(context));
548 * @param context
549 * <br>Not null
550 * @return
551 * <br>Not null
552 * <br>New
554 public static final JPanel newNodePanel(final Context context) {
555 final JPanel result = new JPanel(new BorderLayout());
557 result.add(newNodeNamePanel(context), BorderLayout.NORTH);
558 result.add(newNodeValuePanel(context), BorderLayout.CENTER);
560 return result;
565 * @param context
566 * <br>Not null
567 * @return
568 * <br>Not null
569 * <br>New
571 public static final JPanel newNodeNamePanel(final Context context) {
572 return newTitledPanel("Name", newNodeNameTextField(context));
577 * @param context
578 * <br>Not null
579 * @return
580 * <br>Not null
581 * <br>New
583 public static final JTextField newNodeNameTextField(final Context context) {
584 final JTextField result = new JTextField();
585 final Variable<Node> selectedNodeVariable = context.getVariable(SELECTED_NODE);
586 final EventListener nodeListener = new EventListener() {
588 @Override
589 public final void handleEvent(final Event event) {
590 final Node node = selectedNodeVariable.getValue();
592 debugPrint(node);
594 result.setText(node == null ? "" : node.getNodeName());
599 selectedNodeVariable.addListener(new Variable.Listener<Node>() {
601 @Override
602 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
603 if (event.getOldValue() != null) {
604 removeDOMEventListener(event.getOldValue(), nodeListener);
607 final Node node = event.getNewValue();
609 debugPrint(node);
611 if (node != null) {
612 addDOMEventListener(node, nodeListener);
615 result.setEditable(node != null && set(Node.ATTRIBUTE_NODE,
616 Node.ELEMENT_NODE).contains(node.getNodeType()));
618 result.setText(node == null ? "" : node.getNodeName());
623 result.getDocument().addDocumentListener(new AbstractDocumentHandler() {
625 @Override
626 protected final void eventReceived(final DocumentEvent event) {
627 SwingUtilities.invokeLater(new Runnable() {
629 @Override
630 public final void run() {
631 final Node node = selectedNodeVariable.getValue();
632 final String text = result.getText();
634 debugPrint(node, text);
636 if (node == null || node.getNodeName().equals(text)) {
637 return;
640 try {
641 rename(
642 node,
643 node.getNamespaceURI(),
644 node.getNamespaceURI() == null ? text : node.getPrefix() + ":" + text);
645 } catch (final Exception exception) {
646 exception.printStackTrace();
647 result.setText(node.getNodeName());
656 return result;
661 * @param context
662 * <br>Not null
663 * @return
664 * <br>Not null
665 * <br>New
667 public static final JPanel newNodeValuePanel(final Context context) {
668 return newTitledPanel("Value", scrollable(newNodeValueTextArea(context)));
673 * @param context
674 * <br>Not null
675 * @return
676 * <br>Not null
677 * <br>New
679 public static final JTextArea newNodeValueTextArea(final Context context) {
680 final Variable<Node> selectedNodeVariable = context.getVariable(SELECTED_NODE);
681 final JTextArea result = new JTextArea();
683 final EventListener nodeListener = new EventListener() {
685 @Override
686 public final void handleEvent(final Event event) {
687 final Node node = selectedNodeVariable.getValue();
689 if (event.getTarget() == node) {
690 result.setText(node == null ? "" : node.getNodeValue());
696 selectedNodeVariable.addListener(new Variable.Listener<Node>() {
698 @Override
699 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
700 if (event.getOldValue() != null) {
701 removeDOMEventListener(event.getOldValue(), nodeListener);
704 final Node node = event.getNewValue();
706 if (node != null) {
707 addDOMEventListener(node, nodeListener);
710 result.setEditable(node != null && set(Node.ATTRIBUTE_NODE, Node.CDATA_SECTION_NODE, Node.COMMENT_NODE,
711 Node.PROCESSING_INSTRUCTION_NODE, Node.TEXT_NODE).contains(node.getNodeType()));
713 result.setText(node == null ? "" : node.getNodeValue());
718 result.getDocument().addDocumentListener(new AbstractDocumentHandler() {
720 @Override
721 protected final void eventReceived(final DocumentEvent event) {
722 SwingUtilities.invokeLater(new Runnable() {
724 @Override
725 public final void run() {
726 final Node node = selectedNodeVariable.getValue();
727 final String text = result.getText();
729 debugPrint(node, text);
731 if (node.getNodeValue().equals(text)) {
732 return;
735 try {
736 node.setNodeValue(text);
737 } catch (final Exception exception) {
738 exception.printStackTrace();
739 result.setText(node.getNodeName());
748 return result;
753 * @param context
754 * <br>Not null
755 * @return
756 * <br>Not null
757 * <br>New
759 public static final JPanel newXPathPanel(final Context context) {
760 final JPanel result = new JPanel(new BorderLayout());
762 result.setBorder(BorderFactory.createTitledBorder(
763 BorderFactory.createEtchedBorder(),
764 "XPath",
765 TitledBorder.CENTER,
766 TitledBorder.TOP));
768 result.add(newTitledPanel("Context", newContextTextField(context)), BorderLayout.NORTH);
769 result.add(newXPathTabbedPane(context), BorderLayout.CENTER);
771 return result;
776 * @param context
777 * <br>Not null
778 * @return
779 * <br>Not null
780 * <br>New
782 public static final JTextField newContextTextField(final Context context) {
783 final Variable<Node> selectedNodeVariable = context.getVariable(SELECTED_NODE);
784 final JTextField result = new JTextField();
786 final EventListener nodeListener = new EventListener() {
788 @Override
789 public final void handleEvent(final Event event) {
790 final Node node = selectedNodeVariable.getValue();
792 if (event.getTarget() == node) {
793 result.setText(node == null ? "" : getIdentifyingXPath(node));
799 selectedNodeVariable.addListener(new Variable.Listener<Node>() {
801 @Override
802 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
803 if (event.getOldValue() != null) {
804 removeDOMEventListener(event.getOldValue(), nodeListener);
807 final Node node = event.getNewValue();
809 if (node != null) {
810 addDOMEventListener(node, nodeListener);
813 result.setText(node == null ? "" : getIdentifyingXPath(node));
818 result.setEditable(false);
820 return result;
825 * @param context
826 * <br>Not null
827 * @return
828 * <br>Not null
829 * <br>New
831 public static final JTabbedPane newXPathTabbedPane(final Context context) {
832 final JTabbedPane result = new JTabbedPane();
834 result.add("List", newXPathListSplitPane(context));
835 result.add("Create", newQuasiXPathPanel(context));
837 return result;
842 * @param context
843 * <br>Not null
844 * @return
845 * <br>Not null
846 * <br>New
848 public static final JSplitPane newXPathListSplitPane(final Context context) {
849 return new JSplitPane(JSplitPane.VERTICAL_SPLIT,
850 newTitledPanel("XPath Expression", scrollable(newXPathExpressionTextArea(context))),
851 newTitledPanel("Matches", scrollable(newXPathList(context))));
856 * @param context
857 * <br>Not null
858 * @return
859 * <br>Not null
860 * <br>New
862 public static final JTextArea newXPathExpressionTextArea(final Context context) {
863 final JTextArea result = new JTextArea();
865 result.getDocument().addDocumentListener(new AbstractDocumentHandler() {
867 @Override
868 protected final void eventReceived(final DocumentEvent event) {
869 context.set(XPATH_EXPRESSION, result.getText());
874 final Variable<Exception> xPathErrorVariable = context.getVariable(XPATH_ERROR);
876 xPathErrorVariable.addListener(new Variable.Listener<Exception>() {
878 private Color defaultBackground;
880 @Override
881 public final void valueChanged(final ValueChangedEvent<Exception, ?> event) {
882 if (this.defaultBackground == null) {
883 this.defaultBackground = result.getBackground();
886 result.setBackground(event.getNewValue() == null ? this.defaultBackground : Color.RED);
891 return result;
896 * @param context
897 * <br>Not null
898 * @return
899 * <br>Not null
900 * <br>New
902 public static final JList newXPathList(final Context context) {
903 final DefaultListModel model = new DefaultListModel();
904 final JList result = new JList(model);
906 final Variable<String> xpathExpressionVariable = context.getVariable(XPATH_EXPRESSION);
908 xpathExpressionVariable.addListener(new Variable.Listener<String>() {
910 @Override
911 public final void valueChanged(final ValueChangedEvent<String, ?> event) {
912 model.clear();
914 final Node contextNode = context.get(SELECTED_NODE);
916 try {
917 for (final Node node : toList(getNodes(contextNode, event.getNewValue()))) {
918 model.addElement(node);
921 context.set(XPATH_ERROR, null);
922 } catch (final Exception exception) {
923 context.set(XPATH_ERROR, exception);
929 return result;
934 * @param context
935 * <br>Not null
936 * @return
937 * <br>Not null
938 * <br>New
940 public static final JPanel newQuasiXPathPanel(final Context context) {
941 final JPanel result = new JPanel(new BorderLayout());
943 result.add(newTitledPanel("Quasi-XPath Expression", newQuasiXPathExpressionTextArea(context)), BorderLayout.CENTER);
944 result.add(newQuasiXPathCreateButton(context), BorderLayout.SOUTH);
946 return result;
951 * @param context
952 * <br>Not null
953 * @return
954 * <br>Not null
955 * <br>New
957 public static final JTextArea newQuasiXPathExpressionTextArea(final Context context) {
958 final JTextArea result = new JTextArea();
960 result.getDocument().addDocumentListener(new AbstractDocumentHandler() {
962 @Override
963 protected final void eventReceived(final DocumentEvent event) {
964 context.set(QUASI_XPATH_EXPRESSION, result.getText());
969 final Variable<Exception> quasiXPathErrorVariable = context.getVariable(QUASI_XPATH_ERROR);
971 quasiXPathErrorVariable.addListener(new Variable.Listener<Exception>() {
973 private Color defaultBackground;
975 @Override
976 public final void valueChanged(final ValueChangedEvent<Exception, ?> event) {
977 if (this.defaultBackground == null) {
978 this.defaultBackground = result.getBackground();
981 result.setBackground(event.getNewValue() == null ? this.defaultBackground : Color.RED);
986 return result;
991 * @param context
992 * <br>Not null
993 * @return
994 * <br>Not null
995 * <br>New
997 public static final JButton newQuasiXPathCreateButton(final Context context) {
998 final JButton result = translate(new JButton("Create Node"));
1000 result.addActionListener(new ActionListener() {
1002 private Color defaultBackground;
1004 @Override
1005 public final void actionPerformed(final ActionEvent event) {
1006 if (this.defaultBackground == null) {
1007 this.defaultBackground = result.getParent().getBackground();
1010 try {
1011 getOrCreateNode((Node) context.get(SELECTED_NODE), (String) context.get(QUASI_XPATH_EXPRESSION));
1013 context.set(QUASI_XPATH_ERROR, null);
1014 } catch (final Exception exception) {
1015 context.set(QUASI_XPATH_ERROR, exception);
1021 return result;
1026 * @param translationKey
1027 * <br>Not null
1028 * @param component
1029 * <br>Not null
1030 * <br>Input-output
1031 * @return
1032 * <br>Not null
1033 * <br>New
1035 public static final JPanel newTitledPanel(final String translationKey, final Component component) {
1036 final JPanel result = new JPanel(new BorderLayout());
1038 result.setBorder(translate(BorderFactory.createTitledBorder(translationKey)));
1040 result.add(component);
1042 return result;
1047 * @param node
1048 * <br>Not null
1049 * @return
1050 * <br>Not null
1051 * <br>New
1053 public static final String toXMLString(final Node node) {
1054 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1056 XMLTools.write(node, buffer, 0);
1058 return buffer.toString();
1063 * @param context
1064 * <br>Not null
1065 * @return
1066 * <br>Not null
1067 * <br>New
1069 public static final JTree newDOMTreeView(final Context context) {
1070 final Variable<Node> domVariable = context.getVariable(DOM);
1071 final JTree result = new JTree(new DOMTreeModel(domVariable.getValue()));
1073 domVariable.addListener(new Variable.Listener<Node>() {
1075 @Override
1076 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
1077 final DOMTreeModel treeModel = new DOMTreeModel(event.getNewValue());
1079 result.setModel(treeModel);
1081 context.set(TREE_MODEL, treeModel);
1086 result.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
1088 @Override
1089 public final void valueChanged(final TreeSelectionEvent event) {
1090 if (event.getNewLeadSelectionPath() == null) {
1091 context.set(SELECTED_NODE, null);
1093 return;
1096 final DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) event.getNewLeadSelectionPath().getLastPathComponent();
1098 if (selectedTreeNode != null) {
1099 context.set(SELECTED_NODE, (Node) selectedTreeNode.getUserObject());
1105 return result;
1110 * @author codistmonk (creation 2010-07-04)
1112 public static final class DOMTreeModel extends DefaultTreeModel {
1116 * @param domNode
1117 * <br>Not null
1118 * <br>Shared
1120 public DOMTreeModel(final Node domNode) {
1121 super(newTreeNode(domNode));
1126 * @return
1127 * <br>Not null
1128 * <br>Shared
1130 public final Node getDOMNode() {
1131 return (Node) ((DefaultMutableTreeNode) this.getRoot()).getUserObject();
1134 private static final long serialVersionUID = 4264388285566053331L;
1138 * @param domNode
1139 * <br>Not null
1140 * <br>Shared
1141 * @return
1142 * <br>Not null
1143 * <br>New
1145 public static final DefaultMutableTreeNode newTreeNode(final Node domNode) {
1146 final DefaultMutableTreeNode result = new DefaultMutableTreeNode(domNode) {
1148 @Override
1149 public final String toString() {
1150 switch (domNode.getNodeType()) {
1151 case Node.ATTRIBUTE_NODE:
1152 return domNode.getNodeName() +
1153 (domNode.getNodeValue() == null ? "" : "=\"" + domNode.getNodeValue() + "\"");
1154 default:
1155 return domNode.getNodeName() +
1156 (domNode.getNodeValue() == null ? "" : "[" + domNode.getNodeValue() + "]");
1160 private static final long serialVersionUID = 8090552131823122052L;
1163 final NamedNodeMap attributes = domNode.getAttributes();
1165 if (attributes != null) {
1166 for (int i = 0; i < attributes.getLength(); ++i) {
1167 result.add(newTreeNode(attributes.item(i)));
1171 if (domNode.getNodeType() != Node.ATTRIBUTE_NODE) {
1172 for (final Node domChild : XMLTools.toList(domNode.getChildNodes())) {
1173 result.add(newTreeNode(domChild));
1178 return result;
1185 * @author codistmonk (ceration 2010-07-07)
1187 public static abstract class AbstractDocumentHandler implements DocumentListener {
1189 @Override
1190 public final void insertUpdate(final DocumentEvent event) {
1191 this.doInsertUpdate(event);
1194 @Override
1195 public final void removeUpdate(final DocumentEvent event) {
1196 this.doRemoveUpdate(event);
1199 @Override
1200 public final void changedUpdate(final DocumentEvent event) {
1201 this.doChangedUpdate(event);
1206 * @param event
1207 * <br>Not null
1209 protected void doInsertUpdate(final DocumentEvent event) {
1210 this.eventReceived(event);
1215 * @param event
1216 * <br>Not null
1218 protected void doRemoveUpdate(final DocumentEvent event) {
1219 this.eventReceived(event);
1224 * @param event
1225 * <br>Not null
1227 protected void doChangedUpdate(final DocumentEvent event) {
1228 this.eventReceived(event);
1233 * @param event
1234 * <br>Not null
1236 protected abstract void eventReceived(DocumentEvent event);