View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.support.shared.log.impl;
17  
18  import org.fourthline.cling.support.shared.CenterWindow;
19  import org.fourthline.cling.support.shared.log.LogView;
20  import org.seamless.swing.Application;
21  import org.seamless.swing.logging.LogCategorySelector;
22  import org.seamless.swing.logging.LogController;
23  import org.seamless.swing.logging.LogMessage;
24  import org.seamless.swing.logging.LogTableCellRenderer;
25  import org.seamless.swing.logging.LogTableModel;
26  
27  import javax.annotation.PostConstruct;
28  import javax.enterprise.event.Event;
29  import javax.inject.Inject;
30  import javax.inject.Singleton;
31  import javax.swing.BorderFactory;
32  import javax.swing.Box;
33  import javax.swing.ImageIcon;
34  import javax.swing.JButton;
35  import javax.swing.JComboBox;
36  import javax.swing.JLabel;
37  import javax.swing.JPanel;
38  import javax.swing.JScrollPane;
39  import javax.swing.JTable;
40  import javax.swing.JToolBar;
41  import javax.swing.event.ListSelectionEvent;
42  import javax.swing.event.ListSelectionListener;
43  import java.awt.BorderLayout;
44  import java.awt.Component;
45  import java.awt.Dimension;
46  import java.awt.event.ActionEvent;
47  import java.awt.event.ActionListener;
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  /**
52   * @author Christian Bauer
53   */
54  @Singleton
55  public class LogViewImpl extends JPanel implements LogView {
56  
57      @Inject
58      protected LogCategories logCategories;
59  
60      @Inject
61      protected Event<CenterWindow> centerWindowEvent;
62  
63      protected LogCategorySelector logCategorySelector;
64      protected JTable logTable;
65      protected LogTableModel logTableModel;
66  
67      final protected JToolBar toolBar = new JToolBar();
68  
69      final protected JButton configureButton =
70              new JButton("Options...", Application.createImageIcon(LogController.class, "img/configure.png"));
71  
72      final protected JButton clearButton =
73              new JButton("Clear Log", Application.createImageIcon(LogController.class, "img/removetext.png"));
74  
75      final protected JButton copyButton =
76              new JButton("Copy", Application.createImageIcon(LogController.class, "img/copyclipboard.png"));
77  
78      final protected JButton expandButton =
79              new JButton("Expand", Application.createImageIcon(LogController.class, "img/viewtext.png"));
80  
81      final protected JButton pauseButton =
82              new JButton("Pause/Continue Log", Application.createImageIcon(LogController.class, "img/pause.png"));
83  
84      final protected JLabel pauseLabel = new JLabel(" (Active)");
85  
86      final protected JComboBox expirationComboBox = new JComboBox(LogController.Expiration.values());
87  
88      protected Presenter presenter;
89  
90      @PostConstruct
91      public void init() {
92          setLayout(new BorderLayout());
93  
94          LogController.Expiration defaultExpiration = getDefaultExpiration();
95  
96          logCategorySelector = new LogCategorySelector(logCategories);
97  
98          logTableModel = new LogTableModel(defaultExpiration.getSeconds());
99          logTable = new JTable(logTableModel);
100 
101         logTable.setDefaultRenderer(
102                 LogMessage.class,
103                 new LogTableCellRenderer() {
104                     // TODO: These should be injected
105                     protected ImageIcon getWarnErrorIcon() {
106                         return LogViewImpl.this.getWarnErrorIcon();
107                     }
108 
109                     protected ImageIcon getDebugIcon() {
110                         return LogViewImpl.this.getDebugIcon();
111                     }
112 
113                     protected ImageIcon getTraceIcon() {
114                         return LogViewImpl.this.getTraceIcon();
115                     }
116 
117                     protected ImageIcon getInfoIcon() {
118                         return LogViewImpl.this.getInfoIcon();
119                     }
120                 });
121 
122         logTable.setCellSelectionEnabled(false);
123         logTable.setRowSelectionAllowed(true);
124         logTable.getSelectionModel().addListSelectionListener(
125                 new ListSelectionListener() {
126                     public void valueChanged(ListSelectionEvent e) {
127 
128                         if (e.getValueIsAdjusting()) return;
129 
130                         if (e.getSource() == logTable.getSelectionModel()) {
131                             int[] rows = logTable.getSelectedRows();
132 
133                             if (rows == null || rows.length == 0) {
134                                 copyButton.setEnabled(false);
135                                 expandButton.setEnabled(false);
136                             } else if (rows.length == 1) {
137                                 copyButton.setEnabled(true);
138                                 LogMessage msg = (LogMessage) logTableModel.getValueAt(rows[0], 0);
139                                 // TODO: This setting should be injected
140                                 if (msg.getMessage().length() > getExpandMessageCharacterLimit()) {
141                                     expandButton.setEnabled(true);
142                                 } else {
143                                     expandButton.setEnabled(false);
144                                 }
145                             } else {
146                                 copyButton.setEnabled(true);
147                                 expandButton.setEnabled(false);
148                             }
149                         }
150                     }
151                 }
152         );
153 
154         adjustTableUI();
155         initializeToolBar(defaultExpiration);
156 
157         setPreferredSize(new Dimension(250, 100));
158         setMinimumSize(new Dimension(250, 50));
159         add(new JScrollPane(logTable), BorderLayout.CENTER);
160         add(toolBar, BorderLayout.SOUTH);
161     }
162 
163     @Override
164     public Component asUIComponent() {
165         return this;
166     }
167 
168     @Override
169     public void setPresenter(Presenter presenter) {
170         this.presenter = presenter;
171     }
172 
173     @Override
174     public void pushMessage(LogMessage logMessage) {
175         logTableModel.pushMessage(logMessage);
176 
177         // Scroll to bottom if nothing is selected
178         if (!logTableModel.isPaused()) {
179             logTable.scrollRectToVisible(
180                     logTable.getCellRect(logTableModel.getRowCount() - 1, 0, true)
181             );
182         }
183     }
184 
185     @Override
186     public void dispose() {
187         logCategorySelector.dispose();
188     }
189 
190     protected void adjustTableUI() {
191         logTable.setFocusable(false);
192         logTable.setRowHeight(18);
193         logTable.getTableHeader().setReorderingAllowed(false);
194         logTable.setBorder(BorderFactory.createEmptyBorder());
195 
196         logTable.getColumnModel().getColumn(0).setMinWidth(30);
197         logTable.getColumnModel().getColumn(0).setMaxWidth(30);
198         logTable.getColumnModel().getColumn(0).setResizable(false);
199 
200 
201         logTable.getColumnModel().getColumn(1).setMinWidth(90);
202         logTable.getColumnModel().getColumn(1).setMaxWidth(90);
203         logTable.getColumnModel().getColumn(1).setResizable(false);
204 
205         logTable.getColumnModel().getColumn(2).setMinWidth(110);
206         logTable.getColumnModel().getColumn(2).setMaxWidth(250);
207 
208         logTable.getColumnModel().getColumn(3).setPreferredWidth(150);
209         logTable.getColumnModel().getColumn(3).setMaxWidth(400);
210 
211         logTable.getColumnModel().getColumn(4).setPreferredWidth(600);
212     }
213 
214     protected void initializeToolBar(LogController.Expiration expiration) {
215         configureButton.setFocusable(false);
216         configureButton.addActionListener(new ActionListener() {
217             public void actionPerformed(ActionEvent e) {
218                 centerWindowEvent.fire(new CenterWindow(logCategorySelector));
219                 logCategorySelector.setVisible(!logCategorySelector.isVisible());
220             }
221         });
222 
223         clearButton.setFocusable(false);
224         clearButton.addActionListener(new ActionListener() {
225             public void actionPerformed(ActionEvent e) {
226                 logTableModel.clearMessages();
227             }
228         });
229 
230         copyButton.setFocusable(false);
231         copyButton.setEnabled(false);
232         copyButton.addActionListener(new ActionListener() {
233             public void actionPerformed(ActionEvent e) {
234                 StringBuilder sb = new StringBuilder();
235                 List<LogMessage> messages = getSelectedMessages();
236                 for (LogMessage message : messages) {
237                     sb.append(message.toString()).append("\n");
238                 }
239                 Application.copyToClipboard(sb.toString());
240             }
241         });
242 
243         expandButton.setFocusable(false);
244         expandButton.setEnabled(false);
245         expandButton.addActionListener(new ActionListener() {
246             public void actionPerformed(ActionEvent e) {
247                 List<LogMessage> messages = getSelectedMessages();
248                 if (messages.size() != 1) return;
249                 presenter.onExpand(messages.get(0));
250             }
251         });
252 
253         pauseButton.setFocusable(false);
254         pauseButton.addActionListener(new ActionListener() {
255             public void actionPerformed(ActionEvent e) {
256                 logTableModel.setPaused(!logTableModel.isPaused());
257                 if (logTableModel.isPaused()) {
258                     pauseLabel.setText(" (Paused)");
259                 } else {
260                     pauseLabel.setText(" (Active)");
261                 }
262             }
263         });
264 
265         expirationComboBox.setSelectedItem(expiration);
266         expirationComboBox.setMaximumSize(new Dimension(100, 32));
267         expirationComboBox.addActionListener(new ActionListener() {
268             public void actionPerformed(ActionEvent e) {
269                 JComboBox cb = (JComboBox) e.getSource();
270                 LogController.Expiration expiration = (LogController.Expiration) cb.getSelectedItem();
271                 logTableModel.setMaxAgeSeconds(expiration.getSeconds());
272             }
273         });
274 
275         toolBar.setFloatable(false);
276         toolBar.add(copyButton);
277         toolBar.add(expandButton);
278         toolBar.add(Box.createHorizontalGlue());
279         toolBar.add(configureButton);
280         toolBar.add(clearButton);
281         toolBar.add(pauseButton);
282         toolBar.add(pauseLabel);
283         toolBar.add(Box.createHorizontalGlue());
284         toolBar.add(new JLabel("Clear after:"));
285         toolBar.add(expirationComboBox);
286     }
287 
288     protected LogController.Expiration getDefaultExpiration() {
289         return LogController.Expiration.SIXTY_SECONDS;
290     }
291 
292     protected ImageIcon getWarnErrorIcon() {
293         return Application.createImageIcon(LogController.class, "img/warn.png");
294     }
295 
296     protected ImageIcon getDebugIcon() {
297         return Application.createImageIcon(LogController.class, "img/debug.png");
298     }
299 
300     protected ImageIcon getTraceIcon() {
301         return Application.createImageIcon(LogController.class, "img/trace.png");
302     }
303 
304     protected ImageIcon getInfoIcon() {
305         return Application.createImageIcon(LogController.class, "img/info.png");
306     }
307 
308     protected int getExpandMessageCharacterLimit() {
309         return 100;
310     }
311 
312     protected List<LogMessage> getSelectedMessages() {
313         List<LogMessage> messages = new ArrayList<>();
314         for (int row : logTable.getSelectedRows()) {
315             messages.add((LogMessage) logTableModel.getValueAt(row, 0));
316         }
317         return messages;
318     }
319 }