1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw;
19
20 import org.apache.log4j.LogManager;
21 import org.apache.log4j.Logger;
22 import org.apache.log4j.chainsaw.helper.SwingHelper;
23 import org.apache.log4j.chainsaw.osx.OSXIntegration;
24
25 import javax.swing.*;
26 import javax.swing.tree.DefaultMutableTreeNode;
27 import javax.swing.tree.DefaultTreeModel;
28 import javax.swing.tree.TreeModel;
29 import java.awt.*;
30 import java.io.File;
31 import java.net.MalformedURLException;
32 import java.net.URL;
33 import java.util.Dictionary;
34 import java.util.Enumeration;
35 import java.util.Hashtable;
36 import java.util.Locale;
37
38
39
40
41
42
43
44 public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
45 private ApplicationPreferenceModel committedPreferenceModel;
46 private ApplicationPreferenceModel uncommittedPreferenceModel =
47 new ApplicationPreferenceModel();
48 private JTextField identifierExpression;
49 private JTextField toolTipDisplayMillis;
50 private JTextField cyclicBufferSize;
51 private JComboBox<String> configurationURL;
52 private final Logger logger;
53 private GeneralAllPrefPanel generalAllPrefPanel;
54
55 ApplicationPreferenceModelPanel(ApplicationPreferenceModel model) {
56 this.committedPreferenceModel = model;
57 logger = LogManager.getLogger(ApplicationPreferenceModelPanel.class);
58 initComponents();
59 getOkButton().addActionListener(
60 e -> {
61 uncommittedPreferenceModel.setConfigurationURL((String) configurationURL.getSelectedItem());
62 uncommittedPreferenceModel.setIdentifierExpression(
63 identifierExpression.getText());
64 try {
65 int millis = Integer.parseInt(toolTipDisplayMillis.getText());
66 if (millis >= 0) {
67 uncommittedPreferenceModel.setToolTipDisplayMillis(millis);
68 }
69 } catch (NumberFormatException nfe) {
70 }
71 try {
72 int bufferSize = Integer.parseInt(cyclicBufferSize.getText());
73 if (bufferSize >= 0) {
74 uncommittedPreferenceModel.setCyclicBufferSize(bufferSize);
75 }
76 } catch (NumberFormatException nfe) {
77 }
78 committedPreferenceModel.apply(uncommittedPreferenceModel);
79 hidePanel();
80 });
81
82 getCancelButton().addActionListener(
83 e -> {
84 uncommittedPreferenceModel.apply(committedPreferenceModel);
85 hidePanel();
86 });
87 }
88
89
90 public static void main(String[] args) {
91 JFrame f = new JFrame("App Preferences Panel Test Bed");
92 ApplicationPreferenceModel model = new ApplicationPreferenceModel();
93 ApplicationPreferenceModelPanel panel =
94 new ApplicationPreferenceModelPanel(model);
95 f.getContentPane().add(panel);
96
97 model.addPropertyChangeListener(System.out::println);
98 panel.setOkCancelActionListener(
99 e -> System.exit(1));
100
101 f.setSize(640, 480);
102 f.setVisible(true);
103 }
104
105
106
107
108
109 public void updateModel() {
110 this.uncommittedPreferenceModel.apply(committedPreferenceModel);
111 }
112
113
114
115
116 protected TreeModel createTreeModel() {
117 final DefaultMutableTreeNode rootNode =
118 new DefaultMutableTreeNode("Preferences");
119 DefaultTreeModel model = new DefaultTreeModel(rootNode);
120
121 generalAllPrefPanel = new GeneralAllPrefPanel();
122 DefaultMutableTreeNode general =
123 new DefaultMutableTreeNode(generalAllPrefPanel);
124
125 DefaultMutableTreeNode visuals =
126 new DefaultMutableTreeNode(new VisualsPrefPanel());
127
128 rootNode.add(general);
129 rootNode.add(visuals);
130
131 return model;
132 }
133
134 public class VisualsPrefPanel extends BasicPrefPanel {
135 private final JRadioButton topPlacement = new JRadioButton(" Top ");
136 private final JRadioButton bottomPlacement = new JRadioButton(" Bottom ");
137 private final JCheckBox statusBar = new JCheckBox(" Show Status bar ");
138 private final JCheckBox toolBar = new JCheckBox(" Show Toolbar ");
139 private final JCheckBox receivers = new JCheckBox(" Show Receivers ");
140 private UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
141 private final ButtonGroup lookAndFeelGroup = new ButtonGroup();
142
143 private VisualsPrefPanel() {
144 super("Visuals");
145
146
147
148 UIManager.LookAndFeelInfo[] newLookAndFeels = new UIManager.LookAndFeelInfo[lookAndFeels.length];
149 boolean useNewLookAndFeels = false;
150 int j = 0;
151 for (UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels) {
152 if (lookAndFeel.getClassName().toLowerCase(Locale.ENGLISH).contains("nimbus")) {
153 useNewLookAndFeels = true;
154 } else {
155 newLookAndFeels[j++] = lookAndFeel;
156 }
157 }
158 if (useNewLookAndFeels) {
159 UIManager.LookAndFeelInfo[] replacedLookAndFeels = new UIManager.LookAndFeelInfo[lookAndFeels.length - 1];
160 System.arraycopy(newLookAndFeels, 0, replacedLookAndFeels, 0, newLookAndFeels.length - 1);
161 lookAndFeels = replacedLookAndFeels;
162 }
163
164 setupComponents();
165 setupListeners();
166 setupInitialValues();
167 }
168
169
170
171
172 private void setupListeners() {
173 topPlacement.addActionListener(
174 e -> uncommittedPreferenceModel.setTabPlacement(SwingConstants.TOP));
175 bottomPlacement.addActionListener(
176 e -> uncommittedPreferenceModel.setTabPlacement(SwingConstants.BOTTOM));
177
178 statusBar.addActionListener(
179 e -> uncommittedPreferenceModel.setStatusBar(statusBar.isSelected()));
180
181 toolBar.addActionListener(
182 e -> uncommittedPreferenceModel.setToolbar(toolBar.isSelected()));
183
184 receivers.addActionListener(
185 e -> uncommittedPreferenceModel.setReceivers(receivers.isSelected()));
186
187 uncommittedPreferenceModel.addPropertyChangeListener(
188 "tabPlacement",
189 evt -> {
190 int value = (Integer) evt.getNewValue();
191
192 configureTabPlacement(value);
193 });
194
195 uncommittedPreferenceModel.addPropertyChangeListener(
196 "statusBar",
197 evt -> statusBar.setSelected(
198 (Boolean) evt.getNewValue()));
199
200 uncommittedPreferenceModel.addPropertyChangeListener(
201 "toolbar",
202 evt -> toolBar.setSelected((Boolean) evt.getNewValue()));
203
204 uncommittedPreferenceModel.addPropertyChangeListener(
205 "receivers",
206 evt -> receivers.setSelected(
207 (Boolean) evt.getNewValue()));
208
209 uncommittedPreferenceModel.addPropertyChangeListener(
210 "lookAndFeelClassName",
211 evt -> {
212 String lf = evt.getNewValue().toString();
213
214 Enumeration enumeration = lookAndFeelGroup.getElements();
215
216 while (enumeration.hasMoreElements()) {
217 JRadioButton button = (JRadioButton) enumeration.nextElement();
218
219 if (button.getName() != null && button.getName().equals(lf)) {
220 button.setSelected(true);
221
222 break;
223 }
224 }
225 });
226 }
227
228
229
230
231 private void setupComponents() {
232 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
233
234 JPanel tabPlacementBox = new JPanel();
235 tabPlacementBox.setLayout(new BoxLayout(tabPlacementBox, BoxLayout.Y_AXIS));
236
237 tabPlacementBox.setBorder(BorderFactory.createTitledBorder(" Tab Placement "));
238
239 ButtonGroup tabPlacementGroup = new ButtonGroup();
240
241 tabPlacementGroup.add(topPlacement);
242 tabPlacementGroup.add(bottomPlacement);
243
244 tabPlacementBox.add(topPlacement);
245 tabPlacementBox.add(bottomPlacement);
246
247
248
249
250 if (OSXIntegration.IS_OSX) {
251 tabPlacementBox.setEnabled(false);
252 topPlacement.setEnabled(false);
253 bottomPlacement.setEnabled(false);
254 }
255
256 add(tabPlacementBox);
257 add(statusBar);
258 add(receivers);
259 add(toolBar);
260
261 JPanel lfPanel = new JPanel();
262 lfPanel.setLayout(new BoxLayout(lfPanel, BoxLayout.Y_AXIS));
263 lfPanel.setBorder(BorderFactory.createTitledBorder(" Look & Feel "));
264
265 for (final UIManager.LookAndFeelInfo lfInfo : lookAndFeels) {
266 final JRadioButton lfItem = new JRadioButton(" " + lfInfo.getName() + " ");
267 lfItem.setName(lfInfo.getClassName());
268 lfItem.addActionListener(
269 e -> uncommittedPreferenceModel.setLookAndFeelClassName(
270 lfInfo.getClassName()));
271 lookAndFeelGroup.add(lfItem);
272 lfPanel.add(lfItem);
273 }
274
275 try {
276 final Class gtkLF =
277 Class.forName("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
278 final JRadioButton lfIGTK = new JRadioButton(" GTK+ 2.0 ");
279 lfIGTK.addActionListener(
280 e -> uncommittedPreferenceModel.setLookAndFeelClassName(
281 gtkLF.getName()));
282 lookAndFeelGroup.add(lfIGTK);
283 lfPanel.add(lfIGTK);
284 } catch (Exception e) {
285 logger.debug("Can't find new GTK L&F, might be Windows, or <JDK1.4.2");
286 }
287
288 add(lfPanel);
289
290 add(
291 new JLabel(
292 "<html>Look and Feel change will apply the next time you start Chainsaw.<br>" +
293 "If this value is not set, the default L&F of your system is used.</html>"));
294 }
295
296 private void configureTabPlacement(int value) {
297 switch (value) {
298 case SwingConstants.TOP:
299 topPlacement.setSelected(true);
300
301 break;
302
303 case SwingConstants.BOTTOM:
304 bottomPlacement.setSelected(true);
305
306 break;
307
308 default:
309 break;
310 }
311 }
312
313 private void setupInitialValues() {
314 statusBar.setSelected(uncommittedPreferenceModel.isStatusBar());
315 receivers.setSelected(uncommittedPreferenceModel.isReceivers());
316 toolBar.setSelected(uncommittedPreferenceModel.isToolbar());
317 configureTabPlacement(uncommittedPreferenceModel.getTabPlacement());
318 Enumeration e = lookAndFeelGroup.getElements();
319 while (e.hasMoreElements()) {
320 JRadioButton radioButton = (JRadioButton) e.nextElement();
321 if (radioButton.getText().equals(uncommittedPreferenceModel.getLookAndFeelClassName())) {
322 radioButton.setSelected(true);
323 break;
324 }
325 }
326 }
327 }
328
329
330
331
332 public class GeneralAllPrefPanel extends BasicPrefPanel {
333 private final JCheckBox showNoReceiverWarning =
334 new JCheckBox(" Prompt me on startup if there are no Receivers defined ");
335 private final JCheckBox showSplash = new JCheckBox(" Show Splash screen at startup ");
336 private final JSlider responsiveSlider =
337 new JSlider(SwingConstants.HORIZONTAL, 1, 4, 2);
338 private final JCheckBox confirmExit = new JCheckBox(" Confirm Exit ");
339 Dictionary<Integer, JLabel> sliderLabelMap = new Hashtable<>();
340
341 private final JCheckBox okToRemoveSecurityManager = new JCheckBox(" Ok to remove SecurityManager ");
342
343 public GeneralAllPrefPanel() {
344 super("General");
345
346 GeneralAllPrefPanel.this.initComponents();
347 }
348
349 private void initComponents() {
350 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
351
352 configurationURL = new JComboBox<>(new DefaultComboBoxModel<>(committedPreferenceModel.getConfigurationURLs()));
353 configurationURL.setEditable(true);
354 configurationURL.setPrototypeDisplayValue("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
355 configurationURL.setPreferredSize(new Dimension(375, 13));
356
357 identifierExpression = new JTextField(30);
358 toolTipDisplayMillis = new JTextField(8);
359 cyclicBufferSize = new JTextField(8);
360 Box p = new Box(BoxLayout.X_AXIS);
361
362 p.add(showNoReceiverWarning);
363 p.add(Box.createHorizontalGlue());
364
365 confirmExit.setToolTipText("If set, you prompt to confirm Chainsaw exit");
366 okToRemoveSecurityManager.setToolTipText("You will need to tick this to be able to load Receivers/Plugins that require external dependancies.");
367 setupInitialValues();
368 setupListeners();
369
370 initSliderComponent();
371 add(responsiveSlider);
372
373 JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
374
375 p1.add(new JLabel(" Tab name/event routing expression "));
376 p1.add(Box.createHorizontalStrut(5));
377 p1.add(identifierExpression);
378 add(p1);
379 add(p);
380
381 Box p2 = new Box(BoxLayout.X_AXIS);
382 p2.add(confirmExit);
383 p2.add(Box.createHorizontalGlue());
384
385 Box p3 = new Box(BoxLayout.X_AXIS);
386 p3.add(showSplash);
387 p3.add(Box.createHorizontalGlue());
388
389 Box ok4 = new Box(BoxLayout.X_AXIS);
390 ok4.add(okToRemoveSecurityManager);
391 ok4.add(Box.createHorizontalGlue());
392
393 add(p2);
394 add(p3);
395 add(ok4);
396
397 JPanel p4 = new JPanel(new FlowLayout(FlowLayout.LEFT));
398
399 p4.add(new JLabel(" ToolTip Display (millis) "));
400 p4.add(Box.createHorizontalStrut(5));
401 p4.add(toolTipDisplayMillis);
402 add(p4);
403
404 JPanel p5 = new JPanel(new FlowLayout(FlowLayout.LEFT));
405
406 p5.add(new JLabel(" Cyclic buffer size "));
407 p5.add(Box.createHorizontalStrut(5));
408 p5.add(cyclicBufferSize);
409 p5.add(Box.createHorizontalStrut(5));
410 p5.add(new JLabel(" (effective on restart) "));
411 add(p5);
412
413 Box p6 = new Box(BoxLayout.Y_AXIS);
414
415 Box configURLPanel = new Box(BoxLayout.X_AXIS);
416 JLabel configLabel = new JLabel(" Auto Config URL ");
417 configURLPanel.add(configLabel);
418 configURLPanel.add(Box.createHorizontalStrut(5));
419
420 configURLPanel.add(configurationURL);
421 configURLPanel.add(Box.createHorizontalGlue());
422
423 p6.add(configURLPanel);
424
425 JButton browseButton = new JButton(" Open File... ");
426 browseButton.addActionListener(e -> browseForConfiguration());
427 Box browsePanel = new Box(BoxLayout.X_AXIS);
428 browsePanel.add(Box.createHorizontalGlue());
429 browsePanel.add(browseButton);
430 p6.add(Box.createVerticalStrut(5));
431 p6.add(browsePanel);
432 p6.add(Box.createVerticalGlue());
433 add(p6);
434
435 configurationURL.setToolTipText("A complete and valid URL identifying the location of a valid log4 xml configuration file to auto-configure Receivers and other Plugins");
436 configurationURL.setInputVerifier(new InputVerifier() {
437
438 public boolean verify(JComponent input) {
439 try {
440 String selectedItem = (String) configurationURL.getSelectedItem();
441 if (selectedItem != null && !(selectedItem.trim().equals(""))) {
442 new URL(selectedItem);
443 }
444 } catch (Exception e) {
445 return false;
446 }
447 return true;
448 }
449 });
450 String configToDisplay = committedPreferenceModel.getBypassConfigurationURL() != null ? committedPreferenceModel.getBypassConfigurationURL() : committedPreferenceModel.getConfigurationURL();
451 configurationURL.setSelectedItem(configToDisplay);
452 }
453
454 public void browseForConfiguration() {
455 String defaultPath = ".";
456 if (configurationURL.getItemCount() > 0) {
457 Object selectedItem = configurationURL.getSelectedItem();
458 if (selectedItem != null) {
459 File currentConfigurationPath = new File(selectedItem.toString()).getParentFile();
460 if (currentConfigurationPath != null) {
461 defaultPath = currentConfigurationPath.getPath();
462
463
464 if (defaultPath.toLowerCase(Locale.ENGLISH).startsWith("file:\\")) {
465 defaultPath = defaultPath.substring("file:\\".length());
466 }
467 }
468 }
469 }
470 File selectedFile = SwingHelper.promptForFile(this, defaultPath, "Select a Chainsaw configuration file", true);
471 if (selectedFile != null) {
472 try {
473 String newConfigurationFile = selectedFile.toURI().toURL().toExternalForm();
474 if (!committedPreferenceModel.getConfigurationURLs().contains(newConfigurationFile)) {
475 configurationURL.addItem(newConfigurationFile);
476 }
477 configurationURL.setSelectedItem(newConfigurationFile);
478 } catch (MalformedURLException e1) {
479 e1.printStackTrace();
480 }
481 }
482 }
483
484 private void initSliderComponent() {
485 responsiveSlider.setToolTipText(
486 "Adjust to set the responsiveness of the app. How often the view is updated.");
487 responsiveSlider.setSnapToTicks(true);
488 responsiveSlider.setLabelTable(sliderLabelMap);
489 responsiveSlider.setPaintLabels(true);
490 responsiveSlider.setPaintTrack(true);
491
492 responsiveSlider.setBorder(BorderFactory.createTitledBorder(" Responsiveness "));
493
494
495
496 }
497
498 private void setupListeners() {
499 uncommittedPreferenceModel.addPropertyChangeListener(
500 "showNoReceiverWarning",
501 evt -> showNoReceiverWarning.setSelected(
502 (Boolean) evt.getNewValue()));
503
504 uncommittedPreferenceModel.addPropertyChangeListener("showSplash", evt -> {
505 boolean value = (Boolean) evt.getNewValue();
506 showSplash.setSelected(value);
507 });
508
509 uncommittedPreferenceModel.addPropertyChangeListener("okToRemoveSecurityManager", evt -> {
510 boolean newValue = (Boolean) evt.getNewValue();
511 if (newValue) {
512 okToRemoveSecurityManager.setSelected(newValue);
513 } else {
514 okToRemoveSecurityManager.setSelected(false);
515 }
516
517 });
518
519
520 uncommittedPreferenceModel.addPropertyChangeListener(
521 "identifierExpression",
522 evt -> identifierExpression.setText(evt.getNewValue().toString()));
523
524 uncommittedPreferenceModel.addPropertyChangeListener(
525 "responsiveness",
526 evt -> {
527 int value = (Integer) evt.getNewValue();
528
529 if (value >= 1000) {
530 int newValue = (value - 750) / 1000;
531 logger.debug(
532 "Adjusting old Responsiveness value from " + value + " to "
533 + newValue);
534 value = newValue;
535 }
536
537 responsiveSlider.setValue(value);
538 });
539
540 uncommittedPreferenceModel.addPropertyChangeListener(
541 "toolTipDisplayMillis",
542 evt -> toolTipDisplayMillis.setText(evt.getNewValue().toString()));
543
544 uncommittedPreferenceModel.addPropertyChangeListener(
545 "cyclicBufferSize",
546 evt -> cyclicBufferSize.setText(evt.getNewValue().toString()));
547
548 showNoReceiverWarning.addActionListener(
549 e -> uncommittedPreferenceModel.setShowNoReceiverWarning(
550 showNoReceiverWarning.isSelected()));
551
552 showSplash.addActionListener(e -> uncommittedPreferenceModel.setShowSplash(showSplash.isSelected()));
553
554 okToRemoveSecurityManager.addActionListener(e -> {
555
556 if (okToRemoveSecurityManager.isSelected() && JOptionPane.showConfirmDialog(okToRemoveSecurityManager, "By ticking this option, you are authorizing Chainsaw to remove Java's Security Manager.\n\n" +
557 "This is required under Java Web Start so that it can access Jars/classes locally. Without this, Receivers like JMSReceiver + DBReceiver that require" +
558 " specific driver jars will NOT be able to be run. \n\n" +
559 "By ticking this, you are saying that this is ok.", "Please Confirm", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
560 uncommittedPreferenceModel.setOkToRemoveSecurityManager(true);
561 } else {
562 uncommittedPreferenceModel.setOkToRemoveSecurityManager(false);
563 }
564
565 });
566
567
568 responsiveSlider.getModel().addChangeListener(
569 e -> {
570 if (responsiveSlider.getValueIsAdjusting()) {
571
572
573
574 } else {
575 int value = responsiveSlider.getValue();
576
577 if (value == 0) {
578 value = 1;
579 }
580
581 logger.debug("Adjust responsiveness to " + value);
582 uncommittedPreferenceModel.setResponsiveness(value);
583 }
584 });
585
586 uncommittedPreferenceModel.addPropertyChangeListener(
587 "confirmExit",
588 evt -> {
589 boolean value = (Boolean) evt.getNewValue();
590 confirmExit.setSelected(value);
591 });
592
593 uncommittedPreferenceModel.addPropertyChangeListener("configurationURL", evt -> {
594 String value = evt.getNewValue().toString();
595 configurationURL.setSelectedItem(value);
596 });
597 confirmExit.addActionListener(
598 e -> uncommittedPreferenceModel.setConfirmExit(
599 confirmExit.isSelected()));
600 }
601
602 private void setupInitialValues() {
603 sliderLabelMap.put(1, new JLabel(" Fastest "));
604 sliderLabelMap.put(2, new JLabel(" Fast "));
605 sliderLabelMap.put(3, new JLabel(" Medium "));
606 sliderLabelMap.put(4, new JLabel(" Slow "));
607
608
609 showNoReceiverWarning.setSelected(
610 uncommittedPreferenceModel.isShowNoReceiverWarning());
611 identifierExpression.setText(
612 uncommittedPreferenceModel.getIdentifierExpression());
613
614 confirmExit.setSelected(uncommittedPreferenceModel.isConfirmExit());
615 okToRemoveSecurityManager.setSelected(uncommittedPreferenceModel.isOkToRemoveSecurityManager());
616 showNoReceiverWarning.setSelected(uncommittedPreferenceModel.isShowNoReceiverWarning());
617 showSplash.setSelected(uncommittedPreferenceModel.isShowSplash());
618 identifierExpression.setText(uncommittedPreferenceModel.getIdentifierExpression());
619 toolTipDisplayMillis.setText(uncommittedPreferenceModel.getToolTipDisplayMillis() + "");
620 cyclicBufferSize.setText(uncommittedPreferenceModel.getCyclicBufferSize() + "");
621 configurationURL.setSelectedItem(uncommittedPreferenceModel.getConfigurationURL());
622 }
623 }
624 }