/jEdit/branches/4.4.x-merge-request-for-r19197/org/gjt/sp/jedit/gui/LogViewer.java

# · Java · 541 lines · 438 code · 53 blank · 50 comment · 49 complexity · fff700738e29c6ecffcf2e178963cdad MD5 · raw file

  1. /*
  2. * LogViewer.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2004 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.gui;
  23. //{{{ Imports
  24. import java.awt.*;
  25. import java.awt.event.*;
  26. import javax.swing.*;
  27. import javax.swing.border.EmptyBorder;
  28. import javax.swing.event.*;
  29. import org.gjt.sp.jedit.*;
  30. import org.gjt.sp.jedit.EditBus.EBHandler;
  31. import org.gjt.sp.jedit.msg.PropertiesChanged;
  32. import org.gjt.sp.util.Log;
  33. //}}}
  34. /**
  35. * @version $Id: LogViewer.java 18221 2010-07-19 16:19:45Z daleanson $
  36. */
  37. public class LogViewer extends JPanel implements DefaultFocusComponent
  38. {
  39. //{{{ LogViewer constructor
  40. public LogViewer()
  41. {
  42. super(new BorderLayout());
  43. setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
  44. JPanel caption = new JPanel();
  45. caption.setLayout(new BoxLayout(caption,BoxLayout.X_AXIS));
  46. caption.setBorder(new EmptyBorder(6, 0, 6, 0));
  47. String settingsDirectory = jEdit.getSettingsDirectory();
  48. if(settingsDirectory != null)
  49. {
  50. String[] args = { MiscUtilities.constructPath(
  51. settingsDirectory, "activity.log") };
  52. JLabel label = new JLabel(jEdit.getProperty(
  53. "log-viewer.caption",args));
  54. caption.add(label);
  55. }
  56. caption.add(Box.createHorizontalGlue());
  57. tailIsOn = jEdit.getBooleanProperty("log-viewer.tail", false);
  58. tail = new JCheckBox(
  59. jEdit.getProperty("log-viewer.tail.label"),tailIsOn);
  60. tail.addActionListener(new ActionHandler());
  61. filter = new JTextField();
  62. filter.getDocument().addDocumentListener(new DocumentListener()
  63. {
  64. public void changedUpdate(DocumentEvent e)
  65. {
  66. setFilter();
  67. }
  68. public void insertUpdate(DocumentEvent e)
  69. {
  70. setFilter();
  71. }
  72. public void removeUpdate(DocumentEvent e)
  73. {
  74. setFilter();
  75. }
  76. });
  77. caption.add(filter);
  78. caption.add(tail);
  79. caption.add(Box.createHorizontalStrut(12));
  80. copy = new JButton(jEdit.getProperty("log-viewer.copy"));
  81. copy.addActionListener(new ActionHandler());
  82. caption.add(copy);
  83. caption.add(Box.createHorizontalStrut(6));
  84. JButton settings = new JButton(jEdit.getProperty("log-viewer.settings.label"));
  85. settings.addActionListener(
  86. new ActionListener(){
  87. public void actionPerformed(ActionEvent ae) {
  88. new LogSettings();
  89. }
  90. });
  91. caption.add(settings);
  92. ListModel model = Log.getLogListModel();
  93. listModel = new MyFilteredListModel(model);
  94. // without this, listModel is held permanently in model.
  95. // See addNotify() and removeNotify(), and constructor of
  96. // FilteredListModel.
  97. model.removeListDataListener(listModel);
  98. setFilter();
  99. list = new LogList(listModel);
  100. listModel.setList(list);
  101. add(BorderLayout.NORTH,caption);
  102. JScrollPane scroller = new JScrollPane(list);
  103. Dimension dim = scroller.getPreferredSize();
  104. dim.width = Math.min(600,dim.width);
  105. scroller.setPreferredSize(dim);
  106. add(BorderLayout.CENTER,scroller);
  107. propertiesChanged();
  108. } //}}}
  109. //{{{ setBounds() method
  110. @Override
  111. public void setBounds(int x, int y, int width, int height)
  112. {
  113. list.setCellRenderer( new ColorizerCellRenderer() );
  114. super.setBounds(x, y, width, height);
  115. scrollLaterIfRequired();
  116. } //}}}
  117. //{{{ handlePropertiesChanged() method
  118. @EBHandler
  119. public void handlePropertiesChanged(PropertiesChanged msg)
  120. {
  121. propertiesChanged();
  122. } //}}}
  123. //{{{ addNotify() method
  124. @Override
  125. public void addNotify()
  126. {
  127. super.addNotify();
  128. ListModel model = Log.getLogListModel();
  129. model.addListDataListener(listModel);
  130. model.addListDataListener(listHandler = new ListHandler());
  131. if(tailIsOn)
  132. scrollToTail();
  133. EditBus.addToBus(this);
  134. } //}}}
  135. //{{{ removeNotify() method
  136. @Override
  137. public void removeNotify()
  138. {
  139. super.removeNotify();
  140. ListModel model = Log.getLogListModel();
  141. model.removeListDataListener(listModel);
  142. model.removeListDataListener(listHandler);
  143. listHandler = null;
  144. EditBus.removeFromBus(this);
  145. } //}}}
  146. //{{{ focusOnDefaultComponent() method
  147. public void focusOnDefaultComponent()
  148. {
  149. list.requestFocus();
  150. } //}}}
  151. //{{{ Private members
  152. private ListHandler listHandler;
  153. private final FilteredListModel listModel;
  154. private final JList list;
  155. private final JButton copy;
  156. private final JCheckBox tail;
  157. private final JTextField filter;
  158. private boolean tailIsOn;
  159. private static boolean showDebug = jEdit.getBooleanProperty("log-viewer.message.debug", true);
  160. private static boolean showMessage = jEdit.getBooleanProperty("log-viewer.message.message", true);
  161. private static boolean showNotice = jEdit.getBooleanProperty("log-viewer.message.notice", true);
  162. private static boolean showWarning = jEdit.getBooleanProperty("log-viewer.message.warning", true);
  163. private static boolean showError = jEdit.getBooleanProperty("log-viewer.message.error", true);
  164. //{{{ setFilter() method
  165. private void setFilter()
  166. {
  167. String toFilter = filter.getText();
  168. listModel.setFilter(toFilter.length() == 0 ? " " : toFilter);
  169. scrollLaterIfRequired();
  170. } //}}}
  171. //{{{ propertiesChanged() method
  172. private void propertiesChanged()
  173. {
  174. list.setFont(jEdit.getFontProperty("view.font"));
  175. list.setFixedCellHeight(list.getFontMetrics(list.getFont())
  176. .getHeight());
  177. } //}}}
  178. //{{{ scrollToTail() method
  179. /** Scroll to the tail of the logs. */
  180. private void scrollToTail()
  181. {
  182. int index = list.getModel().getSize();
  183. if(index != 0)
  184. list.ensureIndexIsVisible(index - 1);
  185. } //}}}
  186. //{{{ scrollLaterIfRequired() method
  187. private void scrollLaterIfRequired()
  188. {
  189. if (tailIsOn)
  190. SwingUtilities.invokeLater(new Runnable()
  191. {
  192. public void run()
  193. {
  194. scrollToTail();
  195. }
  196. });
  197. } //}}}
  198. //}}}
  199. //{{{ ActionHandler class
  200. private class ActionHandler implements ActionListener
  201. {
  202. public void actionPerformed(ActionEvent e)
  203. {
  204. Object src = e.getSource();
  205. if(src == tail)
  206. {
  207. tailIsOn = !tailIsOn;
  208. jEdit.setBooleanProperty("log-viewer.tail",tailIsOn);
  209. if(tailIsOn)
  210. {
  211. scrollToTail();
  212. }
  213. }
  214. else if(src == copy)
  215. {
  216. StringBuilder buf = new StringBuilder();
  217. Object[] selected = list.getSelectedValues();
  218. if(selected != null && selected.length != 0)
  219. {
  220. for(int i = 0; i < selected.length; i++)
  221. {
  222. buf.append(selected[i]);
  223. buf.append('\n');
  224. }
  225. }
  226. else
  227. {
  228. ListModel model = list.getModel();
  229. for(int i = 0; i < model.getSize(); i++)
  230. {
  231. buf.append(model.getElementAt(i));
  232. buf.append('\n');
  233. }
  234. }
  235. Registers.setRegister('$',buf.toString());
  236. }
  237. }
  238. } //}}}
  239. //{{{ ListHandler class
  240. private class ListHandler implements ListDataListener
  241. {
  242. public void intervalAdded(ListDataEvent e)
  243. {
  244. contentsChanged(e);
  245. }
  246. public void intervalRemoved(ListDataEvent e)
  247. {
  248. contentsChanged(e);
  249. }
  250. public void contentsChanged(ListDataEvent e)
  251. {
  252. scrollLaterIfRequired();
  253. }
  254. } //}}}
  255. //{{{ LogList class
  256. private class LogList extends JList
  257. {
  258. LogList(ListModel model)
  259. {
  260. super(model);
  261. setVisibleRowCount(24);
  262. getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  263. setAutoscrolls(true);
  264. }
  265. @Override
  266. public void processMouseEvent(MouseEvent evt)
  267. {
  268. if(evt.getID() == MouseEvent.MOUSE_PRESSED)
  269. {
  270. startIndex = list.locationToIndex(
  271. evt.getPoint());
  272. }
  273. super.processMouseEvent(evt);
  274. }
  275. @Override
  276. public void processMouseMotionEvent(MouseEvent evt)
  277. {
  278. if(evt.getID() == MouseEvent.MOUSE_DRAGGED)
  279. {
  280. int row = list.locationToIndex(evt.getPoint());
  281. if(row != -1)
  282. {
  283. if(startIndex == -1)
  284. {
  285. list.setSelectionInterval(row,row);
  286. startIndex = row;
  287. }
  288. else
  289. list.setSelectionInterval(startIndex,row);
  290. list.ensureIndexIsVisible(row);
  291. evt.consume();
  292. }
  293. }
  294. else
  295. super.processMouseMotionEvent(evt);
  296. }
  297. private int startIndex;
  298. } //}}}
  299. //{{{ ColorizerCellRenderer class
  300. private static class ColorizerCellRenderer extends JLabel implements ListCellRenderer
  301. {
  302. // This is the only method defined by ListCellRenderer.
  303. // We just reconfigure the JLabel each time we're called.
  304. public Component getListCellRendererComponent(
  305. JList list,
  306. Object value, // value to display
  307. int index, // cell index
  308. boolean isSelected, // is the cell selected
  309. boolean cellHasFocus ) // the list and the cell have the focus
  310. {
  311. String s = value.toString();
  312. setText(s);
  313. if (isSelected)
  314. {
  315. setBackground(list.getSelectionBackground());
  316. setForeground(list.getSelectionForeground());
  317. }
  318. else
  319. {
  320. setBackground(list.getBackground());
  321. Color color = list.getForeground();
  322. if (s.contains("[debug]"))
  323. {
  324. color = jEdit.getColorProperty("log-viewer.message.debug.color", Color.BLUE);
  325. }
  326. else if (s.contains("[message]"))
  327. {
  328. color = jEdit.getColorProperty("log-viewer.message.message.color", Color.BLACK);
  329. }
  330. else if (s.contains("[notice]"))
  331. {
  332. color = jEdit.getColorProperty("log-viewer.message.notice.color", Color.GREEN);
  333. }
  334. else if (s.contains("[warning]"))
  335. {
  336. color = jEdit.getColorProperty("log-viewer.message.warning.color", Color.ORANGE);
  337. }
  338. else if (s.contains("[error]"))
  339. {
  340. color = jEdit.getColorProperty("log-viewer.message.error.color", Color.RED);
  341. }
  342. setForeground( color );
  343. }
  344. setEnabled( list.isEnabled() );
  345. setFont( list.getFont() );
  346. setOpaque( true );
  347. return this;
  348. }
  349. } //}}}
  350. //{{{ MyFilteredListModel
  351. private static class MyFilteredListModel extends FilteredListModel
  352. {
  353. MyFilteredListModel(ListModel model)
  354. {
  355. super(model);
  356. }
  357. @Override
  358. public String prepareFilter(String filter)
  359. {
  360. return filter.toLowerCase();
  361. }
  362. @Override
  363. public boolean passFilter(int row, String filter)
  364. {
  365. String text = delegated.getElementAt(row).toString().toLowerCase();
  366. if (text.contains("[debug]") && !showDebug)
  367. return false;
  368. if (text.contains("[message]") && !showMessage)
  369. return false;
  370. if (text.contains("[notice]") && !showNotice)
  371. return false;
  372. if (text.contains("[warning]") && !showWarning)
  373. return false;
  374. if (text.contains("[error]") && !showError)
  375. return false;
  376. return filter.length() == 0 || text.contains(filter);
  377. }
  378. } //}}}
  379. //{{{ LogSettings dialog
  380. private class LogSettings extends JDialog
  381. {
  382. LogSettings()
  383. {
  384. super(jEdit.getActiveView(), jEdit.getProperty("log-viewer.dialog.title"));
  385. AbstractOptionPane pane = new AbstractOptionPane(jEdit.getProperty("log-viewer.settings.label"))
  386. {
  387. protected void _init()
  388. {
  389. setBorder(BorderFactory.createEmptyBorder(11, 11, 12, 12));
  390. maxLines = new JSpinner(new SpinnerNumberModel(jEdit.getIntegerProperty("log-viewer.maxlines", 500), 500, Integer.MAX_VALUE, 1));
  391. addComponent(jEdit.getProperty("log-viewer.maxlines.label", "Max lines"),
  392. maxLines,
  393. GridBagConstraints.REMAINDER);
  394. addComponent(Box.createVerticalStrut(11));
  395. debug = new JCheckBox(jEdit.getProperty("log-viewer.message.debug.label", "Debug"),
  396. jEdit.getBooleanProperty("log-viewer.message.debug", true));
  397. message = new JCheckBox(jEdit.getProperty("log-viewer.message.message.label", "Message"),
  398. jEdit.getBooleanProperty("log-viewer.message.message", true));
  399. notice = new JCheckBox(jEdit.getProperty("log-viewer.message.notice.label", "Notice"),
  400. jEdit.getBooleanProperty("log-viewer.message.notice", true));
  401. warning = new JCheckBox(jEdit.getProperty("log-viewer.message.warning.label", "Warning"),
  402. jEdit.getBooleanProperty("log-viewer.message.warning", true));
  403. error = new JCheckBox(jEdit.getProperty("log-viewer.message.error.label", "Error"),
  404. jEdit.getBooleanProperty("log-viewer.message.error", true));
  405. addComponent(new JLabel(jEdit.getProperty("log-viewer.message.label", "Message Display:")));
  406. addComponent(debug,
  407. debugColor = new ColorWellButton(
  408. jEdit.getColorProperty("log-viewer.message.debug.color", Color.BLUE)),
  409. GridBagConstraints.REMAINDER);
  410. addComponent(message,
  411. messageColor = new ColorWellButton(
  412. jEdit.getColorProperty("log-viewer.message.message.color", Color.GREEN)),
  413. GridBagConstraints.REMAINDER);
  414. addComponent(notice,
  415. noticeColor = new ColorWellButton(
  416. jEdit.getColorProperty("log-viewer.message.notice.color", Color.GREEN)),
  417. GridBagConstraints.REMAINDER);
  418. addComponent(warning,
  419. warningColor = new ColorWellButton(
  420. jEdit.getColorProperty("log-viewer.message.warning.color", Color.ORANGE)),
  421. GridBagConstraints.REMAINDER);
  422. addComponent(error,
  423. errorColor = new ColorWellButton(
  424. jEdit.getColorProperty("log-viewer.message.error.color", Color.RED)),
  425. GridBagConstraints.REMAINDER);
  426. addComponent(Box.createVerticalStrut(11));
  427. JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
  428. JButton okButton = new JButton(jEdit.getProperty("common.ok"));
  429. okButton.addActionListener(
  430. new ActionListener() {
  431. public void actionPerformed(ActionEvent ae) {
  432. save();
  433. LogSettings.this.setVisible(false);
  434. LogSettings.this.dispose();
  435. }
  436. });
  437. JButton cancelButton = new JButton(jEdit.getProperty("common.cancel"));
  438. cancelButton.addActionListener(
  439. new ActionListener() {
  440. public void actionPerformed(ActionEvent ae) {
  441. LogSettings.this.setVisible(false);
  442. LogSettings.this.dispose();
  443. }
  444. });
  445. buttonPanel.add(okButton);
  446. buttonPanel.add(cancelButton);
  447. addComponent(buttonPanel, GridBagConstraints.HORIZONTAL);
  448. }
  449. protected void _save()
  450. {
  451. jEdit.setIntegerProperty("log-viewer.maxlines", ((SpinnerNumberModel)maxLines.getModel()).getNumber().intValue());
  452. showDebug = debug.isSelected();
  453. jEdit.setBooleanProperty("log-viewer.message.debug", showDebug);
  454. showMessage = message.isSelected();
  455. jEdit.setBooleanProperty("log-viewer.message.message", showMessage);
  456. showNotice = notice.isSelected();
  457. jEdit.setBooleanProperty("log-viewer.message.notice", showNotice);
  458. showWarning = warning.isSelected();
  459. jEdit.setBooleanProperty("log-viewer.message.warning", showWarning);
  460. showError = error.isSelected();
  461. jEdit.setBooleanProperty("log-viewer.message.error", showError);
  462. jEdit.setColorProperty("log-viewer.message.debug.color", debugColor.getSelectedColor());
  463. jEdit.setColorProperty("log-viewer.message.message.color", messageColor.getSelectedColor());
  464. jEdit.setColorProperty("log-viewer.message.notice.color", noticeColor.getSelectedColor());
  465. jEdit.setColorProperty("log-viewer.message.warning.color", warningColor.getSelectedColor());
  466. jEdit.setColorProperty("log-viewer.message.error.color", errorColor.getSelectedColor());
  467. setFilter();
  468. }
  469. };
  470. setContentPane(pane);
  471. pane.init();
  472. pack();
  473. setLocationRelativeTo(LogViewer.this);
  474. setVisible(true);
  475. }
  476. private JSpinner maxLines;
  477. private JCheckBox debug;
  478. private JCheckBox message;
  479. private JCheckBox notice;
  480. private JCheckBox warning;
  481. private JCheckBox error;
  482. private ColorWellButton debugColor;
  483. private ColorWellButton messageColor;
  484. private ColorWellButton noticeColor;
  485. private ColorWellButton warningColor;
  486. private ColorWellButton errorColor;
  487. } //}}}
  488. }