1 package nl.tudelft.simulation.dsol.swing.gui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.util.EnumSet;
6 import java.util.Set;
7
8 import javax.swing.JPanel;
9 import javax.swing.JScrollPane;
10 import javax.swing.JTextPane;
11 import javax.swing.ScrollPaneConstants;
12 import javax.swing.SwingUtilities;
13 import javax.swing.text.BadLocationException;
14 import javax.swing.text.Document;
15 import javax.swing.text.Element;
16 import javax.swing.text.Style;
17 import javax.swing.text.StyleConstants;
18 import javax.swing.text.StyledDocument;
19
20 import org.djutils.logger.CategoryLogger;
21 import org.pmw.tinylog.Configuration;
22 import org.pmw.tinylog.Configurator;
23 import org.pmw.tinylog.Level;
24 import org.pmw.tinylog.LogEntry;
25 import org.pmw.tinylog.writers.LogEntryValue;
26 import org.pmw.tinylog.writers.Writer;
27
28 import nl.tudelft.simulation.dsol.swing.gui.appearance.AppearanceControl;
29
30
31
32
33
34
35
36
37
38
39
40 public class ConsoleLogger extends JPanel implements AppearanceControl
41 {
42
43 private static final long serialVersionUID = 1L;
44
45
46 @SuppressWarnings("checkstyle:visibilitymodifier")
47 protected ConsoleLogWriter consoleLogWriter;
48
49
50 private String messageFormat = CategoryLogger.DEFAULT_MESSAGE_FORMAT;
51
52
53 private Level level = Level.INFO;
54
55
56 private JTextPane textPane;
57
58
59
60
61
62 public ConsoleLogger(final Level logLevel)
63 {
64 this.level = logLevel;
65 setLayout(new BorderLayout());
66 this.textPane = new JTextPane();
67 this.textPane.setEditable(false);
68 this.textPane.setBackground(Color.WHITE);
69 this.textPane.setOpaque(true);
70 this.consoleLogWriter = new ConsoleLogWriter(this.textPane);
71 Configurator.currentConfig().addWriter(this.consoleLogWriter, this.level, this.messageFormat).activate();
72 JScrollPane scrollPane = new JScrollPane(this.textPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
73 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
74 scrollPane.setBackground(Color.WHITE);
75 scrollPane.setOpaque(true);
76 add(scrollPane, BorderLayout.CENTER);
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public void setLogMessageFormat(final String newMessageFormat)
96 {
97 Configurator.currentConfig().removeWriter(this.consoleLogWriter).activate();
98 this.messageFormat = newMessageFormat;
99 Configurator.currentConfig().addWriter(this.consoleLogWriter, this.level, this.messageFormat).activate();
100 }
101
102
103
104
105 public void setLogLevel(final Level newLevel)
106 {
107 Configurator.currentConfig().removeWriter(this.consoleLogWriter).activate();
108 this.level = newLevel;
109 Configurator.currentConfig().addWriter(this.consoleLogWriter, this.level, this.messageFormat).activate();
110 }
111
112
113
114
115
116
117 public void setMaxLines(final int maxLines)
118 {
119 this.consoleLogWriter.maxLines = Math.max(1, maxLines);
120 }
121
122
123
124 @Override
125 public boolean isBackground()
126 {
127 return true;
128 }
129
130
131
132
133
134
135
136
137
138 public static class ConsoleLogWriter implements Writer
139 {
140
141 @SuppressWarnings("checkstyle:visibilitymodifier")
142 JTextPane textPane;
143
144
145 @SuppressWarnings("checkstyle:visibilitymodifier")
146 StyledDocument doc;
147
148
149 @SuppressWarnings("checkstyle:visibilitymodifier")
150 Style style;
151
152
153 @SuppressWarnings("checkstyle:visibilitymodifier")
154 int nrLines = 0;
155
156
157 @SuppressWarnings("checkstyle:visibilitymodifier")
158 protected int maxLines = 20000;
159
160
161
162
163 public ConsoleLogWriter(final JTextPane textPane)
164 {
165 this.textPane = textPane;
166 this.doc = textPane.getStyledDocument();
167 this.style = textPane.addStyle("colorStyle", null);
168 }
169
170
171 @Override
172 public Set<LogEntryValue> getRequiredLogEntryValues()
173 {
174 return EnumSet.of(LogEntryValue.RENDERED_LOG_ENTRY);
175 }
176
177
178 @Override
179 public void init(final Configuration configuration) throws Exception
180 {
181
182 }
183
184
185 @Override
186 public synchronized void write(final LogEntry logEntry) throws Exception
187 {
188 Runnable runnable = new Runnable()
189 {
190 @Override
191 public void run()
192 {
193 String[] lines = logEntry.getRenderedLogEntry().split("\\r?\\n");
194
195 while (ConsoleLogWriter.this.nrLines > Math.max(0, ConsoleLogWriter.this.maxLines - lines.length))
196 {
197 Document document = ConsoleLogWriter.this.doc;
198 Element root = document.getDefaultRootElement();
199 Element line = root.getElement(0);
200 int end = line.getEndOffset();
201
202 try
203 {
204 document.remove(0, end);
205 ConsoleLogWriter.this.nrLines--;
206 }
207 catch (BadLocationException exception)
208 {
209 CategoryLogger.always().error(exception);
210 break;
211 }
212 }
213 switch (logEntry.getLevel())
214 {
215 case TRACE:
216 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.DARK_GRAY);
217 break;
218
219 case DEBUG:
220 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.BLUE);
221 break;
222
223 case INFO:
224 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.BLACK);
225 break;
226
227 case WARNING:
228 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.MAGENTA);
229 break;
230
231 case ERROR:
232 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.RED);
233 break;
234
235 default:
236 break;
237 }
238 try
239 {
240 for (String line : lines)
241 {
242 ConsoleLogWriter.this.doc.insertString(ConsoleLogWriter.this.doc.getLength(), line + "\n",
243 ConsoleLogWriter.this.style);
244 ConsoleLogWriter.this.nrLines++;
245 }
246 }
247 catch (Exception exception)
248 {
249
250 System.err.println("Was not able to insert text in the Console");
251 }
252 ConsoleLogWriter.this.textPane.setCaretPosition(ConsoleLogWriter.this.doc.getLength());
253 }
254 };
255 SwingUtilities.invokeLater(runnable);
256 }
257
258
259 @Override
260 public void flush() throws Exception
261 {
262
263 }
264
265
266 @Override
267 public void close() throws Exception
268 {
269
270 }
271
272 }
273 }