[Markups]
[aprog.git] / Markups / src / net / sourceforge / aprog / markups / MarkupsComponents.java
blobaa3ae71d355b9644d7dffb8b2d33a847ea3aa3bd
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.subtitlesadjuster.SubtitlesAdjusterTools.*;
32 import static net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterTools.menu;
33 import static net.sourceforge.aprog.swing.SwingTools.checkAWT;
34 import static net.sourceforge.aprog.swing.SwingTools.menuBar;
35 import static net.sourceforge.aprog.swing.SwingTools.packAndCenter;
36 import static net.sourceforge.aprog.swing.SwingTools.scrollable;
37 import static net.sourceforge.aprog.tools.Tools.*;
39 import java.awt.BorderLayout;
40 import java.awt.Color;
41 import java.awt.Component;
42 import java.awt.GridBagConstraints;
43 import java.awt.dnd.DropTarget;
44 import java.awt.dnd.DropTargetAdapter;
45 import java.awt.dnd.DropTargetDragEvent;
46 import java.awt.dnd.DropTargetDropEvent;
47 import java.awt.dnd.DropTargetEvent;
48 import java.awt.event.WindowListener;
49 import java.io.ByteArrayOutputStream;
50 import java.io.File;
51 import java.util.List;
53 import javax.swing.BorderFactory;
54 import javax.swing.Box;
55 import javax.swing.ButtonGroup;
56 import javax.swing.JButton;
57 import javax.swing.JFrame;
58 import javax.swing.JLabel;
59 import javax.swing.JList;
60 import javax.swing.JMenuBar;
61 import javax.swing.JMenuItem;
62 import javax.swing.JPanel;
63 import javax.swing.JSplitPane;
64 import javax.swing.JTabbedPane;
65 import javax.swing.JTextArea;
66 import javax.swing.JTextField;
67 import javax.swing.JTree;
68 import javax.swing.border.TitledBorder;
69 import javax.swing.tree.DefaultMutableTreeNode;
70 import javax.swing.tree.DefaultTreeModel;
72 import net.sourceforge.aprog.context.Context;
73 import net.sourceforge.aprog.events.Variable;
74 import net.sourceforge.aprog.events.Variable.ValueChangedEvent;
75 import net.sourceforge.aprog.i18n.Translator;
76 import net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterActions;
77 import net.sourceforge.aprog.subtitlesadjuster.SubtitlesAdjusterComponents;
78 import net.sourceforge.aprog.swing.SwingTools;
79 import net.sourceforge.aprog.tools.IllegalInstantiationException;
80 import net.sourceforge.aprog.xml.XMLTools;
81 import net.sourceforge.jmacadapter.MacAdapterTools;
83 import org.w3c.dom.NamedNodeMap;
84 import org.w3c.dom.Node;
86 /**
88 * @author codistmonk (creation 2010-07-03)
90 public final class MarkupsComponents {
92 /**
93 * @throws IllegalInstantiationException To prevent instantiation
95 private MarkupsComponents() {
96 throw new IllegalInstantiationException();
99 /**
101 * @param context
102 * <br>Not null
103 * <br>Input-output
104 * @return
105 * <br>Not null
106 * <br>New
108 public static final JFrame newMainFrame(final Context context) {
109 final JFrame result = new JFrame();
111 context.set(MAIN_FRAME, result);
113 result.setJMenuBar(newMenuBar(context));
114 result.add(newMainPanel(context));
116 result.addWindowListener(newListener(WindowListener.class, "windowClosing",
117 MarkupsActions.class, "quit", context));
119 invokeOnVariableChanged(context, FILE,
120 SubtitlesAdjusterActions.class, "updateMainFrameTitle", context);
121 invokeOnVariableChanged(context, FILE_MODIFIED,
122 SubtitlesAdjusterActions.class, "updateMainFrameTitle", context);
124 Translator.getDefaultTranslator().addListener(newListener(Translator.Listener.class, "localeChanged",
125 SwingTools.class, "packAndUpdateMinimumSize", result));
127 return packAndCenter(result);
132 * @param context
133 * <br>Not null
134 * <br>Shared
135 * @return
136 * <br>Not null
137 * <br>New
139 public static final JMenuBar newMenuBar(final Context context) {
140 checkAWT();
142 if (MacAdapterTools.isMacOSX()) {
143 MacAdapterTools.setUseScreenMenuBar(true);
146 return menuBar(
147 menu("Application",
148 newAboutMenuItem(context),
149 null,
150 newPreferencesMenuItem(context),
151 null,
152 newQuitMenuItem(context)
154 menu("File",
155 newNewMenuItem(context),
156 null,
157 newOpenMenuItem(context),
158 null,
159 newSaveMenuItem(context),
160 newSaveAsMenuItem(context)
162 menu("Edit",
163 newUndoMenuItem(context),
164 newRedoMenuItem(context),
165 null,
166 newCopyMenuItem(context),
167 newCutMenuItem(context),
168 newPasteMenuItem(context)
170 menu("Node",
171 newAppendNewNodeMenuItem(context),
172 null,
173 newMoveUpMenuItem(context),
174 newMoveDownMenuItem(context)
176 menu("Help",
177 newManualMenuItem(context)
183 * @param context
184 * <br>Not null
185 * <br>Shared
186 * @return
187 * <br>Not null
188 * <br>New
190 public static final JMenuItem newAboutMenuItem(final Context context) {
191 checkAWT();
193 return SubtitlesAdjusterComponents.newAboutMenuItem(context);
198 * @param context
199 * <br>Not null
200 * <br>Shared
201 * @return
202 * <br>Not null
203 * <br>New
205 public static final JMenuItem newPreferencesMenuItem(final Context context) {
206 checkAWT();
208 return SubtitlesAdjusterComponents.newPreferencesMenuItem(context);
213 * @param context
214 * <br>Not null
215 * <br>Shared
216 * @return
217 * <br>Not null
218 * <br>New
220 public static final JMenuItem newQuitMenuItem(final Context context) {
221 checkAWT();
223 if (MacAdapterTools.isMacOSX() && MacAdapterTools.getUseScreenMenuBar()) {
224 if (registerMacOSXApplicationListener("handleQuit",
225 MarkupsActions.class, "quit", context)) {
226 return null;
230 return item("Quit", getKeyStroke(META + " Q"),
231 MarkupsActions.class, "quit", context);
236 * @param context
237 * <br>Not null
238 * <br>Shared
239 * @return
240 * <br>Not null
241 * <br>New
243 public static final JMenuItem newNewMenuItem(final Context context) {
244 return item("New", getKeyStroke(META + " N"),
245 MarkupsActions.class, "newFile", context);
250 * @param context
251 * <br>Not null
252 * <br>Shared
253 * @return
254 * <br>Not null
255 * <br>New
257 public static final JMenuItem newOpenMenuItem(final Context context) {
258 return item("Open...", getKeyStroke(META + " O"),
259 MarkupsActions.class, "open", context);
264 * @param context
265 * <br>Not null
266 * <br>Shared
267 * @return
268 * <br>Not null
269 * <br>New
271 public static final JMenuItem newSaveMenuItem(final Context context) {
272 final JMenuItem result = item("Save", getKeyStroke(META + " S"),
273 MarkupsActions.class, "save", context);
274 final Variable<Boolean> fileModifiedVariable = context.getVariable(FILE_MODIFIED);
276 fileModifiedVariable.addListener(new Variable.Listener<Boolean>() {
278 @Override
279 public final void valueChanged(final ValueChangedEvent<Boolean, ?> event) {
280 result.setEnabled(event.getNewValue());
285 return result;
290 * @param context
291 * <br>Not null
292 * <br>Shared
293 * @return
294 * <br>Not null
295 * <br>New
297 public static final JMenuItem newSaveAsMenuItem(final Context context) {
298 final JMenuItem result = item("Save As...", getKeyStroke(META + " shift S"),
299 MarkupsActions.class, "saveAs", context);
301 return result;
306 * @param context
307 * <br>Not null
308 * <br>Shared
309 * @return
310 * <br>Not null
311 * <br>New
313 public static final JMenuItem newUndoMenuItem(final Context context) {
314 final JMenuItem result = item("Undo", getKeyStroke(META + " Z"),
315 MarkupsActions.class, "undo", context);
317 return result;
322 * @param context
323 * <br>Not null
324 * <br>Shared
325 * @return
326 * <br>Not null
327 * <br>New
329 public static final JMenuItem newRedoMenuItem(final Context context) {
330 final JMenuItem result = item("Redo", getKeyStroke(META + " Y"),
331 MarkupsActions.class, "redo", context);
333 return result;
338 * @param context
339 * <br>Not null
340 * <br>Shared
341 * @return
342 * <br>Not null
343 * <br>New
345 public static final JMenuItem newCopyMenuItem(final Context context) {
346 final JMenuItem result = item("Copy", getKeyStroke(META + " C"),
347 MarkupsActions.class, "copy", context);
349 return result;
354 * @param context
355 * <br>Not null
356 * <br>Shared
357 * @return
358 * <br>Not null
359 * <br>New
361 public static final JMenuItem newCutMenuItem(final Context context) {
362 final JMenuItem result = item("Cut", getKeyStroke(META + " X"),
363 MarkupsActions.class, "cut", context);
365 return result;
370 * @param context
371 * <br>Not null
372 * <br>Shared
373 * @return
374 * <br>Not null
375 * <br>New
377 public static final JMenuItem newPasteMenuItem(final Context context) {
378 final JMenuItem result = item("Paste", getKeyStroke(META + " V"),
379 MarkupsActions.class, "paste", context);
381 return result;
386 * @param context
387 * <br>Not null
388 * <br>Shared
389 * @return
390 * <br>Not null
391 * <br>New
393 public static final JMenuItem newAppendNewNodeMenuItem(final Context context) {
394 final JMenuItem result = item("Append New Node",
395 MarkupsActions.class, "appendNewNode", context);
397 return result;
402 * @param context
403 * <br>Not null
404 * <br>Shared
405 * @return
406 * <br>Not null
407 * <br>New
409 public static final JMenuItem newMoveUpMenuItem(final Context context) {
410 final JMenuItem result = item("Move Up",
411 MarkupsActions.class, "moveUp", context);
413 return result;
418 * @param context
419 * <br>Not null
420 * <br>Shared
421 * @return
422 * <br>Not null
423 * <br>New
425 public static final JMenuItem newMoveDownMenuItem(final Context context) {
426 final JMenuItem result = item("Move Down",
427 MarkupsActions.class, "moveDown", context);
429 return result;
434 * @param context
435 * <br>Not null
436 * <br>Shared
437 * @return
438 * <br>Not null
439 * <br>New
441 public static final JMenuItem newManualMenuItem(final Context context) {
442 return item(
443 "Manual", getKeyStroke("F1"),
444 SubtitlesAdjusterActions.class, "showManual", context);
449 * @param context
450 * <br>Not null
451 * @return
452 * <br>Not null
453 * <br>New
455 public static final JPanel newMainPanel(final Context context) {
456 final JPanel result = new JPanel(new BorderLayout());
458 result.add(newMainSplitPane(context));
460 new DropTarget(result, new DropTargetAdapter() {
462 @Override
463 public final void dragEnter(final DropTargetDragEvent event) {
464 result.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
467 @Override
468 public final void dragExit(final DropTargetEvent event) {
469 result.setBorder(null);
472 @Override
473 public final void drop(final DropTargetDropEvent event) {
474 result.setBorder(null);
476 final List<File> files = SwingTools.getFiles(event);
478 if (!files.isEmpty() && MarkupsActions.confirm(context)) {
479 context.set(FILE, files.get(0));
485 return result;
490 * @param context
491 * <br>Not null
492 * @return
493 * <br>Not null
494 * <br>New
496 public static final JSplitPane newMainSplitPane(final Context context) {
497 return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
498 scrollable(newDOMTreeView(context)),
499 newContextualSplitPane(context));
504 * @param context
505 * <br>Not null
506 * @return
507 * <br>Not null
508 * <br>New
510 public static final JSplitPane newContextualSplitPane(final Context context) {
511 return new JSplitPane(JSplitPane.VERTICAL_SPLIT,
512 newNodePanel(context),
513 newXPathPanel(context));
518 * @param context
519 * <br>Not null
520 * @return
521 * <br>Not null
522 * <br>New
524 public static final JPanel newNodePanel(final Context context) {
525 final JPanel result = new JPanel(new BorderLayout());
526 // final GridBagConstraints constraints = new GridBagConstraints();
528 // {
529 // constraints.gridx = 0;
530 // constraints.gridy = 0;
531 // constraints.fill = GridBagConstraints.HORIZONTAL;
532 // constraints.weightx = 1D;
533 // constraints.weighty = 0D;
535 // SwingTools.add(result, newNodeNamePanel(context), constraints);
536 // }
537 // {
538 // ++constraints.gridy;
539 // constraints.fill = GridBagConstraints.BOTH;
540 // constraints.weighty = 1D;
542 // SwingTools.add(result, newNodeValuePanel(context), constraints);
543 // }
545 result.add(newNodeNamePanel(context), BorderLayout.NORTH);
546 result.add(newNodeValuePanel(context), BorderLayout.CENTER);
548 return result;
553 * @param context
554 * <br>Not null
555 * @return
556 * <br>Not null
557 * <br>New
559 public static final JPanel newNodeNamePanel(final Context context) {
560 return newTitledPanel("Name", newNodeNameTextField(context));
565 * @param context
566 * <br>Not null
567 * @return
568 * <br>Not null
569 * <br>New
571 public static final JTextField newNodeNameTextField(final Context context) {
572 final JTextField result = new JTextField();
574 // TODO
576 return result;
581 * @param context
582 * <br>Not null
583 * @return
584 * <br>Not null
585 * <br>New
587 public static final JPanel newNodeValuePanel(final Context context) {
588 return newTitledPanel("Value", scrollable(newNodeValueTextArea(context)));
593 * @param context
594 * <br>Not null
595 * @return
596 * <br>Not null
597 * <br>New
599 public static final JTextArea newNodeValueTextArea(final Context context) {
600 final JTextArea result = new JTextArea();
602 // TODO
604 return result;
609 * @param context
610 * <br>Not null
611 * @return
612 * <br>Not null
613 * <br>New
615 public static final JPanel newXPathPanel(final Context context) {
616 final JPanel result = new JPanel(new BorderLayout());
618 result.setBorder(BorderFactory.createTitledBorder(
619 BorderFactory.createEtchedBorder(),
620 "XPath",
621 TitledBorder.CENTER,
622 TitledBorder.TOP));
624 result.add(newContextLabel(context), BorderLayout.NORTH);
625 result.add(newXPathTabbedPane(context), BorderLayout.CENTER);
627 return result;
632 * @param context
633 * <br>Not null
634 * @return
635 * <br>Not null
636 * <br>New
638 public static final JLabel newContextLabel(final Context context) {
639 final JLabel result = new JLabel();
641 return result;
646 * @param context
647 * <br>Not null
648 * @return
649 * <br>Not null
650 * <br>New
652 public static final JTabbedPane newXPathTabbedPane(final Context context) {
653 final JTabbedPane result = new JTabbedPane();
655 result.add("List", newXPathListSplitPane(context));
656 result.add("Create", newQuasiXPathPanel(context));
658 return result;
663 * @param context
664 * <br>Not null
665 * @return
666 * <br>Not null
667 * <br>New
669 public static final JSplitPane newXPathListSplitPane(final Context context) {
670 return new JSplitPane(JSplitPane.VERTICAL_SPLIT,
671 newTitledPanel("XPath Expression", scrollable(newXPathExpressionTextArea(context))),
672 newTitledPanel("Matches", scrollable(newXPathList(context))));
677 * @param context
678 * <br>Not null
679 * @return
680 * <br>Not null
681 * <br>New
683 public static final JTextArea newXPathExpressionTextArea(final Context context) {
684 final JTextArea result = new JTextArea();
686 // TODO
688 return result;
693 * @param context
694 * <br>Not null
695 * @return
696 * <br>Not null
697 * <br>New
699 public static final JList newXPathList(final Context context) {
700 final JList result = new JList();
702 // TODO
704 return result;
709 * @param context
710 * <br>Not null
711 * @return
712 * <br>Not null
713 * <br>New
715 public static final JPanel newQuasiXPathPanel(final Context context) {
716 final JPanel result = new JPanel(new BorderLayout());
718 result.add(newQuasiXPathExpressionTextArea(context), BorderLayout.CENTER);
719 result.add(newQuasiXPathCreateButton(context), BorderLayout.SOUTH);
721 return result;
726 * @param context
727 * <br>Not null
728 * @return
729 * <br>Not null
730 * <br>New
732 public static final JTextArea newQuasiXPathExpressionTextArea(final Context context) {
733 final JTextArea result = new JTextArea();
735 // TODO
737 return result;
742 * @param context
743 * <br>Not null
744 * @return
745 * <br>Not null
746 * <br>New
748 public static final JButton newQuasiXPathCreateButton(final Context context) {
749 final JButton result = translate(new JButton("Create Node"));
751 // TODO
753 return result;
758 * @param translationKey
759 * <br>Not null
760 * @param component
761 * <br>Not null
762 * <br>Input-output
763 * @return
764 * <br>Not null
765 * <br>New
767 public static final JPanel newTitledPanel(final String translationKey, final Component component) {
768 final JPanel result = new JPanel(new BorderLayout());
770 result.setBorder(translate(BorderFactory.createTitledBorder(translationKey)));
772 result.add(component);
774 return result;
779 * @param node
780 * <br>Not null
781 * @return
782 * <br>Not null
783 * <br>New
785 public static final String toXMLString(final Node node) {
786 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
788 XMLTools.write(node, buffer, 0);
790 return buffer.toString();
795 * @param context
796 * <br>Not null
797 * @return
798 * <br>Not null
799 * <br>New
801 public static final JTree newDOMTreeView(final Context context) {
802 final Variable<Node> domVariable = context.getVariable(DOM);
803 final JTree result = new JTree(new DOMTreeModel(domVariable.getValue()));
806 domVariable.addListener(new Variable.Listener<Node>() {
808 @Override
809 public final void valueChanged(final ValueChangedEvent<Node, ?> event) {
810 final DOMTreeModel treeModel = new DOMTreeModel(event.getNewValue());
812 result.setModel(treeModel);
814 context.set(TREE_MODEL, treeModel);
819 return result;
824 * @param context
825 * <br>Not null
826 * <br>Input-output
827 * @param variableName
828 * <br>Not null
829 * @return
830 * <br>Not null
831 * <br>Maybe new
833 public static final ButtonGroup getOrCreateButtonGroup(final Context context, final String variableName) {
834 ButtonGroup result = context.get(variableName);
836 if (result == null) {
837 context.set(variableName, result = new ButtonGroup());
840 return result;
845 * @param context
846 * <br>Not null
847 * <br>Input-output
848 * @return
849 * <br>Not null
850 * <br>Maybe new
852 public static final <T> Variable<T> getOrCreateVariable(final Context context, final String variableName, final T defaultValue) {
853 Variable<T> result = context.getVariable(variableName);
855 if (result == null) {
856 context.set(variableName, defaultValue);
857 result = context.getVariable(variableName);
860 return result;
865 * @author codistmonk (creation 2010-07-04)
867 public static final class DOMTreeModel extends DefaultTreeModel {
871 * @param domNode
872 * <br>Not null
873 * <br>Shared
875 public DOMTreeModel(final Node domNode) {
876 super(newTreeNode(domNode));
881 * @return
882 * <br>Not null
883 * <br>Shared
885 public final Node getDOMNode() {
886 return (Node) ((DefaultMutableTreeNode) this.getRoot()).getUserObject();
889 private static final long serialVersionUID = 4264388285566053331L;
893 * @param domNode
894 * <br>Not null
895 * <br>Shared
896 * @return
897 * <br>Not null
898 * <br>New
900 public static final DefaultMutableTreeNode newTreeNode(final Node domNode) {
901 final DefaultMutableTreeNode result = new DefaultMutableTreeNode(domNode) {
903 @Override
904 public final String toString() {
905 switch (domNode.getNodeType()) {
906 case Node.ATTRIBUTE_NODE:
907 return domNode.getNodeName() +
908 (domNode.getNodeValue() == null ? "" : "=\"" + domNode.getNodeValue() + "\"");
909 default:
910 return domNode.getNodeName() +
911 (domNode.getNodeValue() == null ? "" : "[" + domNode.getNodeValue() + "]");
915 private static final long serialVersionUID = 8090552131823122052L;
918 final NamedNodeMap attributes = domNode.getAttributes();
920 if (attributes != null) {
921 for (int i = 0; i < attributes.getLength(); ++i) {
922 result.add(newTreeNode(attributes.item(i)));
926 if (domNode.getNodeType() != Node.ATTRIBUTE_NODE) {
927 for (final Node domChild : XMLTools.toList(domNode.getChildNodes())) {
928 result.add(newTreeNode(domChild));
933 return result;