2
2
3
3
package org .openlcb .swing ;
4
4
5
+ import java .awt .FlowLayout ;
6
+ import java .awt .Toolkit ;
7
+ import java .awt .datatransfer .Clipboard ;
8
+ import java .awt .datatransfer .ClipboardOwner ;
5
9
import java .awt .datatransfer .DataFlavor ;
6
10
import java .awt .datatransfer .StringSelection ;
7
11
import java .awt .datatransfer .Transferable ;
8
12
import java .awt .datatransfer .UnsupportedFlavorException ;
13
+ import java .awt .event .ActionEvent ;
14
+ import java .awt .event .ActionListener ;
15
+ import java .awt .event .InputEvent ;
16
+ import java .awt .event .MouseAdapter ;
17
+ import java .awt .event .MouseEvent ;
18
+ import java .awt .event .WindowAdapter ;
19
+ import java .awt .event .WindowEvent ;
20
+
9
21
import java .io .IOException ;
10
22
import java .util .logging .Level ;
11
23
import java .util .logging .Logger ;
12
24
25
+ import javax .swing .JButton ;
13
26
import javax .swing .JComponent ;
27
+ import javax .swing .JComboBox ;
28
+ import javax .swing .JDialog ;
14
29
import javax .swing .JFormattedTextField ;
30
+ import javax .swing .JFrame ;
31
+ import javax .swing .JMenu ;
32
+ import javax .swing .JMenuItem ;
33
+ import javax .swing .JOptionPane ;
34
+ import javax .swing .JPanel ;
35
+ import javax .swing .JPopupMenu ;
36
+ import javax .swing .JTextField ;
37
+ import javax .swing .SwingUtilities ;
15
38
import javax .swing .TransferHandler ;
39
+ import javax .swing .text .DefaultEditorKit ;
16
40
import javax .swing .text .JTextComponent ;
17
41
import javax .swing .text .MaskFormatter ;
18
42
43
+ import org .openlcb .EventID ;
44
+
19
45
/**
20
46
* Text field for entry of forced-valid EventID string.
21
47
*
@@ -39,14 +65,236 @@ public static JFormattedTextField getEventIdTextField() {
39
65
retval .setValue ("DD.DD.DD.DD.DD.DD.DD.DD" );
40
66
retval .setPreferredSize (retval .getPreferredSize ());
41
67
retval .setValue ("00.00.00.00.00.00.00.00" );
68
+
42
69
retval .setToolTipText ("EventID as eight-byte dotted-hex string, "
43
- + "e.g. 01.02.0A.AB.34.56.78.00" );
70
+ + "e.g. 01.02.0A.AB.34.56.78.00 "
71
+ + "You can drag&drop or ctrl-click for more options" );
72
+
44
73
retval .setDragEnabled (true );
45
74
retval .setTransferHandler (new CustomTransferHandler ());
46
75
76
+ configurePopUp (retval );
77
+
47
78
return retval ;
48
79
}
49
80
81
+ private static void configurePopUp (JFormattedTextField textfield ) {
82
+
83
+ // JMRI's apps.Apps.java line 330 adds cut/copy/paste to all JTextComponents
84
+ // (Also serves as example of cut/copy/paste code)
85
+
86
+ JPopupMenu popup = createPopupMenu (textfield );
87
+ //textfield.add(popup);
88
+ textfield .setComponentPopupMenu (popup );
89
+ textfield .setInheritsPopupMenu (false );
90
+ }
91
+
92
+ private static void checkAndShowPopup (JFormattedTextField textfield , MouseEvent event ) {
93
+ if ( event .isPopupTrigger () ) {
94
+ // user requested the popup menu
95
+ JPopupMenu popup = createPopupMenu (textfield );
96
+ popup .show (textfield , event .getX (), event .getY ());
97
+ }
98
+ }
99
+
100
+ private static JPopupMenu createPopupMenu (JFormattedTextField textfield ) {
101
+ JPopupMenu popup = new JPopupMenu ();
102
+
103
+ // add the usual copy and paste operators
104
+ JMenuItem menuItem = new JMenuItem ("Copy" );
105
+ popup .add (menuItem );
106
+ menuItem .addActionListener (new ActionListener () {
107
+ @ Override
108
+ public void actionPerformed (ActionEvent e ) {
109
+ String s = textfield .getText ();
110
+ SwingUtilities .invokeLater (new Runnable () {
111
+ @ Override
112
+ public void run () {
113
+ textfield .selectAll ();
114
+ }
115
+ });
116
+ StringSelection eventToCopy = new StringSelection (s );
117
+ Clipboard clipboard = Toolkit .getDefaultToolkit ().getSystemClipboard ();
118
+ clipboard .setContents (eventToCopy , new ClipboardOwner () {
119
+ @ Override
120
+ public void lostOwnership (Clipboard clipboard , Transferable transferable ) {
121
+ }
122
+ });
123
+ }
124
+ });
125
+
126
+ menuItem = new JMenuItem ("Paste" );
127
+ popup .add (menuItem );
128
+ menuItem .addActionListener (new ActionListener () {
129
+ @ Override
130
+ public void actionPerformed (ActionEvent e ) {
131
+ Clipboard systemClipboard = Toolkit .getDefaultToolkit ().getSystemClipboard ();
132
+ DataFlavor dataFlavor = DataFlavor .stringFlavor ;
133
+
134
+ Object text = null ;
135
+ try {
136
+ text = systemClipboard .getData (dataFlavor );
137
+ } catch (UnsupportedFlavorException | IOException e1 ) {
138
+ return ;
139
+ }
140
+ String pasteValue = (String ) text ;
141
+ if (pasteValue != null ) {
142
+ textfield .setText (pasteValue );
143
+ }
144
+ }
145
+ });
146
+
147
+ // create a submenu for well-known events
148
+ popup .add (makeWellKnownEventMenu (textfield ));
149
+
150
+ // Add the time events
151
+ popup .add ( makeClockEventMenuItem (textfield ));
152
+
153
+ // Add the accessory decoder events
154
+ popup .add (makeDccAccessoryEventMenuItem (textfield ));
155
+
156
+ // popup.add("Extended DCC accessory decoder events ...");
157
+ // popup.add("DCC turnout feedback events ...");
158
+ // popup.add("DCC system sensor feedback events ...");
159
+
160
+ return popup ;
161
+ }
162
+
163
+ public static JMenu makeWellKnownEventMenu (JFormattedTextField textfield ) {
164
+ JMenu wkeMenu = new JMenu ("Insert well-known event" );
165
+ wkeMenu .add (new EventIdInserter (
166
+ "Emergency off (de-energize)" , "01.00.00.00.05.00.FF.FF" , textfield ));
167
+ wkeMenu .add (new EventIdInserter (
168
+ "Clear emergency off (energize)" , "01.00.00.00.00.00.FF.FE" , textfield ));
169
+
170
+ wkeMenu .add (new EventIdInserter (
171
+ "Emergency stop of all operations" , "01.00.00.00.05.00.FF.FD" , textfield ));
172
+ wkeMenu .add (new EventIdInserter (
173
+ "Clear emergency stop of all operations" ,"01.00.00.00.00.00.FF.FC" , textfield ));
174
+
175
+ wkeMenu .add (new EventIdInserter (
176
+ "Start Default Fast Clock" , "01.01.00.00.01.00.F0.02" , textfield ));
177
+ wkeMenu .add (new EventIdInserter (
178
+ "Stop Default Fast Clock" , "01.01.00.00.01.00.F0.01" , textfield ));
179
+
180
+ return wkeMenu ;
181
+ }
182
+
183
+ public static JMenuItem makeClockEventMenuItem (JFormattedTextField textfield ) {
184
+ JMenuItem menuItem = new JMenuItem ("Insert Clock event..." );
185
+ menuItem .addActionListener (new ActionListener () {
186
+ @ Override
187
+ public void actionPerformed (ActionEvent e ) {
188
+ JDialog dialog = new JDialog ();
189
+ dialog .setTitle ("Select Clock Settings" );
190
+
191
+ JPanel innerPanel = new JPanel (new FlowLayout ());
192
+ JComboBox <String > clockBox = new JComboBox <String >(
193
+ new String []{
194
+ "Default Fast Clock" ,
195
+ "Default Real-Time Clock" ,
196
+ "Alternate Clock 1" ,
197
+ "Alternate Clock 2"
198
+ });
199
+ innerPanel .add (clockBox );
200
+ util .com .toedter .calendar .JHourMinuteChooser chooser = new util .com .toedter .calendar .JHourMinuteChooser ();
201
+ innerPanel .add (chooser );
202
+ JButton setButton = new JButton ("Set" );
203
+ innerPanel .add (setButton );
204
+ setButton .addActionListener (new ActionListener () {
205
+ @ Override
206
+ public void actionPerformed (ActionEvent e ) {
207
+ String prefix = "01.01.00.00.01.0" +clockBox .getSelectedIndex ();
208
+ int minute = Integer .parseInt (chooser .getMinute ());
209
+ int hour = Integer .parseInt (chooser .getHour ());
210
+ if (! chooser .getMeridian ().equals ("AM" )) hour = hour +12 ;
211
+ textfield .setText (prefix +String .format (".%02X.%02X" , hour , minute ));
212
+ dialog .dispatchEvent (new WindowEvent (dialog , WindowEvent .WINDOW_CLOSING ));
213
+ }
214
+ });
215
+
216
+ dialog .add (innerPanel );
217
+ dialog .setModal (true );
218
+ dialog .pack ();
219
+ dialog .setDefaultCloseOperation (JFrame .DISPOSE_ON_CLOSE );
220
+
221
+ dialog .setVisible (true );
222
+ }
223
+ });
224
+ return menuItem ;
225
+ }
226
+
227
+ public static JMenuItem makeDccAccessoryEventMenuItem (JFormattedTextField textfield ) {
228
+ JMenuItem menuItem = new JMenuItem ("Insert DCC accessory decoder events ..." );
229
+ menuItem .addActionListener (new ActionListener () {
230
+ @ Override
231
+ public void actionPerformed (ActionEvent e ) {
232
+ JDialog dialog = new JDialog ();
233
+ dialog .setTitle ("Select DCC Accessory Decoder" );
234
+
235
+ JPanel innerPanel = new JPanel (new FlowLayout ());
236
+
237
+ JTextField number = new JTextField (12 );
238
+ number .setText ("1" );
239
+ innerPanel .add (number );
240
+
241
+ JComboBox <String > onOffBox = new JComboBox <String >(
242
+ new String []{
243
+ "Reversed/Inactive/Off" ,
244
+ "Normal/Active/On"
245
+ });
246
+ innerPanel .add (onOffBox );
247
+
248
+ JButton setButton = new JButton ("Set" );
249
+ innerPanel .add (setButton );
250
+ setButton .addActionListener (new ActionListener () {
251
+ @ Override
252
+ public void actionPerformed (ActionEvent e ) {
253
+ int from = Integer .parseInt (number .getText ().trim ());
254
+
255
+ // See JMRI OlcnAddress line 89 for Event ID coding
256
+ int DD = (from -1 ) & 0x3 ;
257
+ int aaaaaa = (( (from -1 ) >> 2 )+1 ) & 0x3F ;
258
+ int AAA = ( (from ) >> 8 ) & 0x7 ;
259
+ long event = 0x0101020000FF0000L | (AAA << 9 ) | (aaaaaa << 3 ) | (DD << 1 );
260
+ event |= onOffBox .getSelectedIndex ();
261
+
262
+ EventID id = new EventID (String .format ("%016X" , event ));
263
+ textfield .setText (id .toShortString ());
264
+ dialog .dispatchEvent (new WindowEvent (dialog , WindowEvent .WINDOW_CLOSING ));
265
+ }
266
+ });
267
+
268
+ dialog .add (innerPanel );
269
+ dialog .setModal (true );
270
+ dialog .pack ();
271
+ dialog .setDefaultCloseOperation (JFrame .DISPOSE_ON_CLOSE );
272
+
273
+ dialog .setVisible (true );
274
+ }
275
+ });
276
+ return menuItem ;
277
+ }
278
+
279
+ private static class EventIdInserter extends JMenuItem {
280
+ public EventIdInserter (String name , String value , JFormattedTextField target ) {
281
+ super (name );
282
+ this .value = value ;
283
+ this .target = target ;
284
+
285
+ addActionListener (new ActionListener () {
286
+ @ Override
287
+ public void actionPerformed (ActionEvent e ) {
288
+ target .setText (value );
289
+ }
290
+ });
291
+ }
292
+ final String value ;
293
+ final JFormattedTextField target ;
294
+
295
+ }
296
+
297
+
50
298
private static MaskFormatter createFormatter (String s ) {
51
299
MaskFormatter formatter = null ;
52
300
try {
0 commit comments