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
;
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
;
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
;
88 * @author codistmonk (creation 2010-07-03)
90 public final class MarkupsComponents
{
93 * @throws IllegalInstantiationException To prevent instantiation
95 private MarkupsComponents() {
96 throw new IllegalInstantiationException();
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
);
139 public static final JMenuBar
newMenuBar(final Context context
) {
142 if (MacAdapterTools
.isMacOSX()) {
143 MacAdapterTools
.setUseScreenMenuBar(true);
148 newAboutMenuItem(context
),
150 newPreferencesMenuItem(context
),
152 newQuitMenuItem(context
)
155 newNewMenuItem(context
),
157 newOpenMenuItem(context
),
159 newSaveMenuItem(context
),
160 newSaveAsMenuItem(context
)
163 newUndoMenuItem(context
),
164 newRedoMenuItem(context
),
166 newCopyMenuItem(context
),
167 newCutMenuItem(context
),
168 newPasteMenuItem(context
)
171 newAppendNewNodeMenuItem(context
),
173 newMoveUpMenuItem(context
),
174 newMoveDownMenuItem(context
)
177 newManualMenuItem(context
)
190 public static final JMenuItem
newAboutMenuItem(final Context context
) {
193 return SubtitlesAdjusterComponents
.newAboutMenuItem(context
);
205 public static final JMenuItem
newPreferencesMenuItem(final Context context
) {
208 return SubtitlesAdjusterComponents
.newPreferencesMenuItem(context
);
220 public static final JMenuItem
newQuitMenuItem(final Context context
) {
223 if (MacAdapterTools
.isMacOSX() && MacAdapterTools
.getUseScreenMenuBar()) {
224 if (registerMacOSXApplicationListener("handleQuit",
225 MarkupsActions
.class, "quit", context
)) {
230 return item("Quit", getKeyStroke(META
+ " Q"),
231 MarkupsActions
.class, "quit", context
);
243 public static final JMenuItem
newNewMenuItem(final Context context
) {
244 return item("New", getKeyStroke(META
+ " N"),
245 MarkupsActions
.class, "newFile", context
);
257 public static final JMenuItem
newOpenMenuItem(final Context context
) {
258 return item("Open...", getKeyStroke(META
+ " O"),
259 MarkupsActions
.class, "open", context
);
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
>() {
279 public final void valueChanged(final ValueChangedEvent
<Boolean
, ?
> event
) {
280 result
.setEnabled(event
.getNewValue());
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
);
313 public static final JMenuItem
newUndoMenuItem(final Context context
) {
314 final JMenuItem result
= item("Undo", getKeyStroke(META
+ " Z"),
315 MarkupsActions
.class, "undo", context
);
329 public static final JMenuItem
newRedoMenuItem(final Context context
) {
330 final JMenuItem result
= item("Redo", getKeyStroke(META
+ " Y"),
331 MarkupsActions
.class, "redo", context
);
345 public static final JMenuItem
newCopyMenuItem(final Context context
) {
346 final JMenuItem result
= item("Copy", getKeyStroke(META
+ " C"),
347 MarkupsActions
.class, "copy", context
);
361 public static final JMenuItem
newCutMenuItem(final Context context
) {
362 final JMenuItem result
= item("Cut", getKeyStroke(META
+ " X"),
363 MarkupsActions
.class, "cut", context
);
377 public static final JMenuItem
newPasteMenuItem(final Context context
) {
378 final JMenuItem result
= item("Paste", getKeyStroke(META
+ " V"),
379 MarkupsActions
.class, "paste", context
);
393 public static final JMenuItem
newAppendNewNodeMenuItem(final Context context
) {
394 final JMenuItem result
= item("Append New Node",
395 MarkupsActions
.class, "appendNewNode", context
);
409 public static final JMenuItem
newMoveUpMenuItem(final Context context
) {
410 final JMenuItem result
= item("Move Up",
411 MarkupsActions
.class, "moveUp", context
);
425 public static final JMenuItem
newMoveDownMenuItem(final Context context
) {
426 final JMenuItem result
= item("Move Down",
427 MarkupsActions
.class, "moveDown", context
);
441 public static final JMenuItem
newManualMenuItem(final Context context
) {
443 "Manual", getKeyStroke("F1"),
444 SubtitlesAdjusterActions
.class, "showManual", context
);
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() {
463 public final void dragEnter(final DropTargetDragEvent event
) {
464 result
.setBorder(BorderFactory
.createLineBorder(Color
.GREEN
, 2));
468 public final void dragExit(final DropTargetEvent event
) {
469 result
.setBorder(null);
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));
496 public static final JSplitPane
newMainSplitPane(final Context context
) {
497 return new JSplitPane(JSplitPane
.HORIZONTAL_SPLIT
,
498 scrollable(newDOMTreeView(context
)),
499 newContextualSplitPane(context
));
510 public static final JSplitPane
newContextualSplitPane(final Context context
) {
511 return new JSplitPane(JSplitPane
.VERTICAL_SPLIT
,
512 newNodePanel(context
),
513 newXPathPanel(context
));
524 public static final JPanel
newNodePanel(final Context context
) {
525 final JPanel result
= new JPanel(new BorderLayout());
526 // final GridBagConstraints constraints = new GridBagConstraints();
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);
538 // ++constraints.gridy;
539 // constraints.fill = GridBagConstraints.BOTH;
540 // constraints.weighty = 1D;
542 // SwingTools.add(result, newNodeValuePanel(context), constraints);
545 result
.add(newNodeNamePanel(context
), BorderLayout
.NORTH
);
546 result
.add(newNodeValuePanel(context
), BorderLayout
.CENTER
);
559 public static final JPanel
newNodeNamePanel(final Context context
) {
560 return newTitledPanel("Name", newNodeNameTextField(context
));
571 public static final JTextField
newNodeNameTextField(final Context context
) {
572 final JTextField result
= new JTextField();
587 public static final JPanel
newNodeValuePanel(final Context context
) {
588 return newTitledPanel("Value", scrollable(newNodeValueTextArea(context
)));
599 public static final JTextArea
newNodeValueTextArea(final Context context
) {
600 final JTextArea result
= new JTextArea();
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(),
624 result
.add(newContextLabel(context
), BorderLayout
.NORTH
);
625 result
.add(newXPathTabbedPane(context
), BorderLayout
.CENTER
);
638 public static final JLabel
newContextLabel(final Context context
) {
639 final JLabel result
= new JLabel();
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
));
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
))));
683 public static final JTextArea
newXPathExpressionTextArea(final Context context
) {
684 final JTextArea result
= new JTextArea();
699 public static final JList
newXPathList(final Context context
) {
700 final JList result
= new JList();
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
);
732 public static final JTextArea
newQuasiXPathExpressionTextArea(final Context context
) {
733 final JTextArea result
= new JTextArea();
748 public static final JButton
newQuasiXPathCreateButton(final Context context
) {
749 final JButton result
= translate(new JButton("Create Node"));
758 * @param translationKey
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
);
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();
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
>() {
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
);
827 * @param variableName
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());
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
);
865 * @author codistmonk (creation 2010-07-04)
867 public static final class DOMTreeModel
extends DefaultTreeModel
{
875 public DOMTreeModel(final Node domNode
) {
876 super(newTreeNode(domNode
));
885 public final Node
getDOMNode() {
886 return (Node
) ((DefaultMutableTreeNode
) this.getRoot()).getUserObject();
889 private static final long serialVersionUID
= 4264388285566053331L;
900 public static final DefaultMutableTreeNode
newTreeNode(final Node domNode
) {
901 final DefaultMutableTreeNode result
= new DefaultMutableTreeNode(domNode
) {
904 public final String
toString() {
905 switch (domNode
.getNodeType()) {
906 case Node
.ATTRIBUTE_NODE
:
907 return domNode
.getNodeName() +
908 (domNode
.getNodeValue() == null ?
"" : "=\"" + domNode
.getNodeValue() + "\"");
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
));