View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.log4j.chainsaw;
18  
19  import java.awt.Component;
20  import java.awt.Dimension;
21  import java.awt.FlowLayout;
22  import java.awt.event.ActionEvent;
23  import java.awt.event.ActionListener;
24  import java.awt.event.InputEvent;
25  import java.awt.event.MouseAdapter;
26  import java.awt.event.MouseEvent;
27  import java.beans.PropertyChangeEvent;
28  import java.beans.PropertyChangeListener;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  import javax.swing.BorderFactory;
33  import javax.swing.Box;
34  import javax.swing.BoxLayout;
35  import javax.swing.ButtonGroup;
36  import javax.swing.JCheckBox;
37  import javax.swing.JFrame;
38  import javax.swing.JLabel;
39  import javax.swing.JList;
40  import javax.swing.JPanel;
41  import javax.swing.JRadioButton;
42  import javax.swing.JScrollPane;
43  import javax.swing.JTextField;
44  import javax.swing.table.TableColumn;
45  import javax.swing.tree.DefaultMutableTreeNode;
46  import javax.swing.tree.DefaultTreeModel;
47  import javax.swing.tree.TreeModel;
48  
49  import org.apache.log4j.LogManager;
50  import org.apache.log4j.Logger;
51  
52  
53  /***
54   * GUI panel used to manipulate the PreferenceModel for a Log Panel
55   *
56   * @author Paul Smith
57   */
58  public class LogPanelPreferencePanel extends AbstractPreferencePanel
59  {
60    //~ Instance fields =========================================================
61  
62    private final LogPanelPreferenceModel preferenceModel;
63    private final ModifiableListModel columnListModel = new ModifiableListModel();
64    private static final Logger logger = LogManager.getLogger(LogPanelPreferencePanel.class);
65  
66    //~ Constructors ============================================================
67  
68    public LogPanelPreferencePanel(LogPanelPreferenceModel model)
69    {
70      preferenceModel = model;
71      initComponents();
72  
73      getOkButton().addActionListener(new ActionListener()
74        {
75          public void actionPerformed(ActionEvent e)
76          {
77            hidePanel();
78          }
79        });
80  
81      getCancelButton().addActionListener(new ActionListener()
82        {
83          public void actionPerformed(ActionEvent e)
84          {
85            hidePanel();
86          }
87        });
88      }
89  
90    //~ Methods =================================================================
91  
92    /***
93     * DOCUMENT ME!
94     *
95     * @param args DOCUMENT ME!
96     */
97    public static void main(String[] args)
98    {
99      JFrame f = new JFrame("Preferences Panel Test Bed");
100     LogPanelPreferenceModel model = new LogPanelPreferenceModel();
101     LogPanelPreferencePanel panel = new LogPanelPreferencePanel(model);
102     f.getContentPane().add(panel);
103 
104     model.addPropertyChangeListener(new PropertyChangeListener()
105       {
106         public void propertyChange(PropertyChangeEvent evt)
107         {
108           logger.warn(evt.toString());
109         }
110       });
111     panel.setOkCancelActionListener(new ActionListener()
112       {
113         public void actionPerformed(ActionEvent e)
114         {
115           System.exit(1);
116         }
117       });
118 
119     f.setSize(640, 480);
120     f.setVisible(true);
121   }
122 
123   protected TreeModel createTreeModel()
124   {
125     final DefaultMutableTreeNode rootNode =
126       new DefaultMutableTreeNode("Preferences");
127     DefaultTreeModel model = new DefaultTreeModel(rootNode);
128 
129     DefaultMutableTreeNode visuals =
130       new DefaultMutableTreeNode(new VisualsPrefPanel());
131     DefaultMutableTreeNode formatting =
132       new DefaultMutableTreeNode(new FormattingPanel());
133     DefaultMutableTreeNode columns =
134       new DefaultMutableTreeNode(new ColumnSelectorPanel());
135 
136     rootNode.add(visuals);
137     rootNode.add(formatting);
138     rootNode.add(columns);
139 
140     return model;
141   }
142 
143   //~ Inner Classes ===========================================================
144 
145   /***
146    * Allows the user to choose which columns to display.
147    *
148    * @author Paul Smith
149    *
150    */
151   public class ColumnSelectorPanel extends BasicPrefPanel
152   {
153     //~ Constructors ==========================================================
154 
155     ColumnSelectorPanel()
156     {
157       super("Columns");
158       initComponents();
159     }
160 
161     //~ Methods ===============================================================
162 
163     private void initComponents()
164     {
165       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
166 
167       Box columnBox = new Box(BoxLayout.Y_AXIS);
168 
169       //		columnBox.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Displayed Columns"));
170       final JList columnList = new JList();
171       columnList.setVisibleRowCount(10);
172 
173       for (
174         Iterator iter = preferenceModel.getColumns().iterator();
175           iter.hasNext();)
176       {
177         columnListModel.addElement(iter.next());
178       }
179 
180       columnList.setModel(columnListModel);
181 
182       CheckListCellRenderer cellRenderer = new CheckListCellRenderer()
183         {
184           protected boolean isSelected(Object value)
185           {
186             return LogPanelPreferencePanel.this.preferenceModel.isColumnVisible((TableColumn)
187               value);
188           }
189         };
190 
191       columnList.addMouseListener(new MouseAdapter()
192         {
193           public void mouseClicked(MouseEvent e)
194           {
195             if (
196               (e.getClickCount() > 1)
197                 && ((e.getModifiers() & InputEvent.BUTTON1_MASK) > 0))
198             {
199               int i = columnList.locationToIndex(e.getPoint());
200 
201               if (i >= 0)
202               {
203                 Object column = columnListModel.get(i);
204                 preferenceModel.toggleColumn(((TableColumn)column));
205               }
206             }
207           }
208         });
209       columnList.setCellRenderer(cellRenderer);
210       columnBox.add(new JScrollPane(columnList));
211 
212       add(columnBox);
213       add(Box.createVerticalGlue());
214     }
215   }
216 
217   /***
218    * Provides preference gui's for all the Formatting options
219    * available for the columns etc.
220    */
221   private class FormattingPanel extends BasicPrefPanel
222   {
223     //~ Instance fields =======================================================
224 
225     private JTextField customFormatText = new JTextField("", 10);
226     private JTextField loggerPrecision = new JTextField(5);
227     private JRadioButton rdCustom = new JRadioButton("Custom Format");
228     private final JRadioButton rdISO =
229       new JRadioButton(
230         "<html><b>Fast</b> ISO 8601 format (yyyy-MM-dd HH:mm:ss)</html>");
231     private final JRadioButton rdLevelIcons = new JRadioButton("Icons");
232     private final JRadioButton rdLevelText = new JRadioButton("Text");
233     private JRadioButton rdLast;
234 
235     //~ Constructors ==========================================================
236 
237     private FormattingPanel()
238     {
239       super("Formatting");
240       this.initComponents();
241       setupListeners();
242     }
243 
244     //~ Methods ===============================================================
245 
246     private void initComponents()
247     {
248       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
249 
250       JPanel dateFormatPanel = new JPanel();
251       dateFormatPanel.setBorder(
252         BorderFactory.createTitledBorder(
253           BorderFactory.createEtchedBorder(), "Timestamp"));
254       dateFormatPanel.setLayout(
255         new BoxLayout(dateFormatPanel, BoxLayout.Y_AXIS));
256       dateFormatPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
257 
258       customFormatText.setPreferredSize(new Dimension(100, 20));
259       customFormatText.setMaximumSize(customFormatText.getPreferredSize());
260       customFormatText.setMinimumSize(customFormatText.getPreferredSize());
261       customFormatText.setEnabled(false);
262 
263       rdCustom.setSelected(preferenceModel.isCustomDateFormat());
264 
265       ButtonGroup bgDateFormat = new ButtonGroup();
266 
267       rdISO.setAlignmentX(0);
268       rdISO.setSelected(preferenceModel.isUseISO8601Format());
269 
270       bgDateFormat.add(rdISO);
271       dateFormatPanel.add(rdISO);
272 
273       for (
274         Iterator iter = LogPanelPreferenceModel.DATE_FORMATS.iterator();
275           iter.hasNext();)
276       {
277         final String format = (String) iter.next();
278         final JRadioButton rdFormat = new JRadioButton(format);
279         rdFormat.setAlignmentX(0);
280 
281         bgDateFormat.add(rdFormat);
282         rdFormat.addActionListener(new ActionListener()
283           {
284             public void actionPerformed(ActionEvent e)
285             {
286               preferenceModel.setDateFormatPattern(format);
287               customFormatText.setEnabled(rdCustom.isSelected());
288               rdLast = rdFormat;
289             }
290           });
291         //update based on external changes to dateformatpattern (column context
292         //menu)
293         preferenceModel.addPropertyChangeListener(
294           "dateFormatPattern", new PropertyChangeListener()
295           {
296             public void propertyChange(PropertyChangeEvent evt)
297             {
298               rdFormat.setSelected(
299                 preferenceModel.getDateFormatPattern().equals(format));
300               rdLast = rdFormat;
301             }
302           });
303 
304         dateFormatPanel.add(rdFormat);
305       }
306 
307       // add a custom date format
308       if (preferenceModel.isCustomDateFormat())
309       {
310         customFormatText.setText(preferenceModel.getDateFormatPattern());
311         customFormatText.setEnabled(true);
312       }
313 
314       rdCustom.setAlignmentX(0);
315       bgDateFormat.add(rdCustom);
316 
317       Box customBox = Box.createHorizontalBox();
318 
319       //      Following does not work in JDK 1.3.1
320       //      customBox.setAlignmentX(0);
321       customBox.add(rdCustom);
322       customBox.add(customFormatText);
323       customBox.add(Box.createHorizontalGlue());
324       dateFormatPanel.add(customBox);
325 
326       //      dateFormatPanel.add(Box.createVerticalGlue());
327       add(dateFormatPanel);
328 
329       JPanel levelFormatPanel = new JPanel();
330       levelFormatPanel.setLayout(
331         new BoxLayout(levelFormatPanel, BoxLayout.Y_AXIS));
332       levelFormatPanel.setBorder(
333         BorderFactory.createTitledBorder(
334           BorderFactory.createEtchedBorder(), "Level"));
335       levelFormatPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
336 
337       ButtonGroup bgLevel = new ButtonGroup();
338       bgLevel.add(rdLevelIcons);
339       bgLevel.add(rdLevelText);
340 
341       rdLevelIcons.setSelected(preferenceModel.isLevelIcons());
342 
343       levelFormatPanel.add(rdLevelIcons);
344       levelFormatPanel.add(rdLevelText);
345 
346       add(levelFormatPanel);
347 
348       JPanel loggerFormatPanel = new JPanel();
349       loggerFormatPanel.setLayout(
350         new BoxLayout(loggerFormatPanel, BoxLayout.Y_AXIS));
351       loggerFormatPanel.setBorder(
352         BorderFactory.createTitledBorder(
353           BorderFactory.createEtchedBorder(), "Logger"));
354       loggerFormatPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
355 
356       final JLabel precisionLabel =
357         new JLabel("Number of package levels to hide)");
358       final JLabel precisionLabel2 =
359         new JLabel("leave blank to display full logger");
360 
361       loggerFormatPanel.add(precisionLabel);
362       loggerFormatPanel.add(precisionLabel2);
363 
364       JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
365 
366       p.add(loggerPrecision);
367       loggerFormatPanel.add(p);
368 
369       add(loggerFormatPanel);
370 
371       add(Box.createVerticalGlue());
372     }
373 
374     /*
375      * Restore text fields to current model values
376      */
377     private void reset() {
378 
379     	if (preferenceModel.isCustomDateFormat()) {
380     		customFormatText.setText(preferenceModel.getDateFormatPattern());
381     	} else {
382     		if (rdLast != null) {
383     			rdLast.setSelected(true);
384     		}
385     		customFormatText.setEnabled(false);
386     	}
387     	
388     	loggerPrecision.setText(preferenceModel.getLoggerPrecision());
389     }
390 
391     /*
392      * Commit text fields to model
393      */
394     private void commit() {
395     	if (rdCustom.isSelected()) {
396     		preferenceModel.setDateFormatPattern(customFormatText.getText());
397     	}
398     	preferenceModel.setLoggerPrecision(loggerPrecision.getText());
399     }
400 
401     /***
402      * DOCUMENT ME!
403     */
404     private void setupListeners()
405     {
406       getOkButton().addActionListener(new ActionListener() {
407     	  public void actionPerformed(ActionEvent evt) {
408     		  commit();
409     	  }
410       });
411       
412       getCancelButton().addActionListener(new ActionListener() {
413     	  public void actionPerformed(ActionEvent evt) {
414     		  reset();
415     	  }
416       });
417     	  
418     	  rdCustom.addActionListener(new ActionListener()
419         {
420           public void actionPerformed(ActionEvent e)
421           {
422             customFormatText.setEnabled(rdCustom.isSelected());
423             customFormatText.grabFocus();
424           }
425         });
426 
427       //a second?? listener for dateformatpattern
428       preferenceModel.addPropertyChangeListener(
429         "dateFormatPattern", new PropertyChangeListener()
430         {
431           public void propertyChange(PropertyChangeEvent evt)
432           {
433             /***
434              * we need to make sure we are not reacting to the user typing, so only do this
435              * if the text box is not the same as the model
436              */
437             if (
438               preferenceModel.isCustomDateFormat()
439                 && !customFormatText.getText().equals(
440                   evt.getNewValue().toString()))
441             {
442               customFormatText.setText(preferenceModel.getDateFormatPattern());
443               rdCustom.setSelected(true);
444               customFormatText.setEnabled(true);
445             }
446             else
447             {
448               rdCustom.setSelected(false);
449             }
450           }
451         });
452 
453       rdISO.addActionListener(new ActionListener()
454         {
455           public void actionPerformed(ActionEvent e)
456           {
457             preferenceModel.setDateFormatPattern("ISO8601");
458             customFormatText.setEnabled(rdCustom.isSelected());
459             rdLast = rdISO;
460           }
461         });
462       preferenceModel.addPropertyChangeListener(
463         "dateFormatPattern", new PropertyChangeListener()
464         {
465           public void propertyChange(PropertyChangeEvent evt)
466           {
467             rdISO.setSelected(preferenceModel.isUseISO8601Format());
468             rdLast = rdISO;
469           }
470         });
471 
472       ActionListener levelIconListener = new ActionListener()
473         {
474           public void actionPerformed(ActionEvent e)
475           {
476             preferenceModel.setLevelIcons(rdLevelIcons.isSelected());
477           }
478         };
479 
480       rdLevelIcons.addActionListener(levelIconListener);
481       rdLevelText.addActionListener(levelIconListener);
482 
483       preferenceModel.addPropertyChangeListener(
484         "levelIcons", new PropertyChangeListener()
485         {
486           public void propertyChange(PropertyChangeEvent evt)
487           {
488             boolean value = ((Boolean) evt.getNewValue()).booleanValue();
489             rdLevelIcons.setSelected(value);
490             rdLevelText.setSelected(!value);
491           }
492         });
493     }
494   }
495 
496   /***
497    * DOCUMENT ME!
498    *
499    * @author $author$
500    * @version $Revision: 529672 $, $Date: 2007-04-17 11:59:53 -0500 (Tue, 17 Apr 2007) $
501    *
502    * @author psmith
503    *
504    */
505   private class VisualsPrefPanel extends BasicPrefPanel
506   {
507     //~ Instance fields =======================================================
508 
509     private final JCheckBox detailPanelVisible =
510       new JCheckBox("Show Event Detail panel");
511 
512     private final JCheckBox loggerTreePanel =
513       new JCheckBox("Show Logger Tree panel");
514     private final JCheckBox scrollToBottom =
515       new JCheckBox("Scroll to bottom (view tracks with new events)");
516     private final JCheckBox toolTips =
517       new JCheckBox("Show Event Detail Tooltips");
518 
519     //~ Constructors ==========================================================
520 
521     /***
522      * Creates a new VisualsPrefPanel object.
523     */
524     private VisualsPrefPanel()
525     {
526       super("Visuals");
527       initPanelComponents();
528       setupListeners();
529     }
530 
531     //~ Methods ===============================================================
532 
533     /***
534      * DOCUMENT ME!
535     */
536     private void initPanelComponents()
537     {
538       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
539 
540       add(toolTips);
541       add(detailPanelVisible);
542       add(loggerTreePanel);
543       add(scrollToBottom);
544 
545       toolTips.setSelected(preferenceModel.isToolTips());
546       detailPanelVisible.setSelected(preferenceModel.isDetailPaneVisible());
547       loggerTreePanel.setSelected(preferenceModel.isLogTreePanelVisible());
548     }
549 
550     /***
551      * DOCUMENT ME!
552     */
553     private void setupListeners()
554     {
555       toolTips.addActionListener(new ActionListener()
556         {
557           public void actionPerformed(ActionEvent e)
558           {
559             preferenceModel.setToolTips(toolTips.isSelected());
560           }
561         });
562       preferenceModel.addPropertyChangeListener(
563         "toolTips", new PropertyChangeListener()
564         {
565           public void propertyChange(PropertyChangeEvent evt)
566           {
567             boolean value = ((Boolean) evt.getNewValue()).booleanValue();
568             toolTips.setSelected(value);
569           }
570         });
571 
572       detailPanelVisible.addActionListener(new ActionListener()
573         {
574           public void actionPerformed(ActionEvent e)
575           {
576             preferenceModel.setDetailPaneVisible(detailPanelVisible.isSelected());
577           }
578         });
579 
580       preferenceModel.addPropertyChangeListener(
581         "detailPaneVisible", new PropertyChangeListener()
582         {
583           public void propertyChange(PropertyChangeEvent evt)
584           {
585             boolean value = ((Boolean) evt.getNewValue()).booleanValue();
586             detailPanelVisible.setSelected(value);
587           }
588         });
589 
590       scrollToBottom.addActionListener(new ActionListener()
591         {
592           public void actionPerformed(ActionEvent e)
593           {
594             preferenceModel.setScrollToBottom(scrollToBottom.isSelected());
595           }
596         });
597 
598       preferenceModel.addPropertyChangeListener(
599         "scrollToBottom", new PropertyChangeListener()
600         {
601           public void propertyChange(PropertyChangeEvent evt)
602           {
603             boolean value = ((Boolean) evt.getNewValue()).booleanValue();
604             scrollToBottom.setSelected(value);
605           }
606         });
607 
608       loggerTreePanel.addActionListener(new ActionListener()
609         {
610           public void actionPerformed(ActionEvent e)
611           {
612             preferenceModel.setLogTreePanelVisible(loggerTreePanel.isSelected());
613           }
614         });
615 
616       preferenceModel.addPropertyChangeListener(
617         "logTreePanelVisible", new PropertyChangeListener()
618         {
619           public void propertyChange(PropertyChangeEvent evt)
620           {
621             boolean value = ((Boolean) evt.getNewValue()).booleanValue();
622             loggerTreePanel.setSelected(value);
623           }
624         });
625 
626       preferenceModel.addPropertyChangeListener("columns", new PropertyChangeListener() {
627         	public void propertyChange(PropertyChangeEvent evt) {
628       	  List cols = (List)evt.getNewValue();
629             for (
630           	        Iterator iter = cols.iterator();
631           	          iter.hasNext();)
632           	      {
633           	        TableColumn col = (TableColumn) iter.next();
634           	        if (!columnListModel.contains(col)) {
635           	        	columnListModel.addElement(col);
636           	            columnListModel.fireContentsChanged();
637           	        }
638           	      }
639         }});
640 
641         preferenceModel.addPropertyChangeListener(
642                 "visibleColumns", new PropertyChangeListener()
643                 {
644                   public void propertyChange(PropertyChangeEvent evt)
645                   {
646                     columnListModel.fireContentsChanged();
647                   }
648                 });
649 
650     }
651   }
652 }