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 @Override
124 public boolean isBackground()
125 {
126 return true;
127 }
128
129
130
131
132
133
134
135
136
137 public static class ConsoleLogWriter implements Writer
138 {
139
140 @SuppressWarnings("checkstyle:visibilitymodifier")
141 JTextPane textPane;
142
143
144 @SuppressWarnings("checkstyle:visibilitymodifier")
145 StyledDocument doc;
146
147
148 @SuppressWarnings("checkstyle:visibilitymodifier")
149 Style style;
150
151
152 @SuppressWarnings("checkstyle:visibilitymodifier")
153 int nrLines = 0;
154
155
156 @SuppressWarnings("checkstyle:visibilitymodifier")
157 protected int maxLines = 20000;
158
159
160
161
162 public ConsoleLogWriter(final JTextPane textPane)
163 {
164 this.textPane = textPane;
165 this.doc = textPane.getStyledDocument();
166 this.style = textPane.addStyle("colorStyle", null);
167 }
168
169 @Override
170 public Set<LogEntryValue> getRequiredLogEntryValues()
171 {
172 return EnumSet.of(LogEntryValue.RENDERED_LOG_ENTRY);
173 }
174
175 @Override
176 public void init(final Configuration configuration) throws Exception
177 {
178
179 }
180
181 @Override
182 public synchronized void write(final LogEntry logEntry) throws Exception
183 {
184 Runnable runnable = new Runnable()
185 {
186 @Override
187 public void run()
188 {
189 String[] lines = logEntry.getRenderedLogEntry().split("\\r?\\n");
190
191 while (ConsoleLogWriter.this.nrLines > Math.max(0, ConsoleLogWriter.this.maxLines - lines.length))
192 {
193 Document document = ConsoleLogWriter.this.doc;
194 Element root = document.getDefaultRootElement();
195 Element line = root.getElement(0);
196 int end = line.getEndOffset();
197
198 try
199 {
200 document.remove(0, end);
201 ConsoleLogWriter.this.nrLines--;
202 }
203 catch (BadLocationException exception)
204 {
205 CategoryLogger.always().error(exception);
206 break;
207 }
208 }
209 switch (logEntry.getLevel())
210 {
211 case TRACE:
212 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.DARK_GRAY);
213 break;
214
215 case DEBUG:
216 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.BLUE);
217 break;
218
219 case INFO:
220 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.BLACK);
221 break;
222
223 case WARNING:
224 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.MAGENTA);
225 break;
226
227 case ERROR:
228 StyleConstants.setForeground(ConsoleLogWriter.this.style, Color.RED);
229 break;
230
231 default:
232 break;
233 }
234 try
235 {
236 for (String line : lines)
237 {
238 ConsoleLogWriter.this.doc.insertString(ConsoleLogWriter.this.doc.getLength(), line + "\n",
239 ConsoleLogWriter.this.style);
240 ConsoleLogWriter.this.nrLines++;
241 }
242 }
243 catch (Exception exception)
244 {
245
246 System.err.println("Was not able to insert text in the Console");
247 }
248 ConsoleLogWriter.this.textPane.setCaretPosition(ConsoleLogWriter.this.doc.getLength());
249 }
250 };
251 SwingUtilities.invokeLater(runnable);
252 }
253
254 @Override
255 public void flush() throws Exception
256 {
257
258 }
259
260 @Override
261 public void close() throws Exception
262 {
263
264 }
265
266 }
267 }