]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.message.ui/src/org/simantics/message/ui/EventDetailsDialog.java
7c3a330670a2bb1a5fb01881edc36045bc481eb5
[simantics/platform.git] / bundles / org.simantics.message.ui / src / org / simantics / message / ui / EventDetailsDialog.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.message.ui;
13
14 import java.io.IOException;
15 import java.io.PrintWriter;
16 import java.io.StringWriter;
17 import java.net.URI;
18 import java.net.URISyntaxException;
19 import java.text.Collator;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Comparator;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.StringTokenizer;
26
27 import org.eclipse.core.runtime.IAdaptable;
28 import org.eclipse.jface.dialogs.Dialog;
29 import org.eclipse.jface.dialogs.IDialogConstants;
30 import org.eclipse.jface.dialogs.IDialogSettings;
31 import org.eclipse.jface.dialogs.TrayDialog;
32 import org.eclipse.jface.resource.JFaceResources;
33 import org.eclipse.jface.resource.LocalResourceManager;
34 import org.eclipse.jface.viewers.ISelection;
35 import org.eclipse.jface.viewers.ISelectionProvider;
36 import org.eclipse.jface.viewers.ITreeContentProvider;
37 import org.eclipse.jface.viewers.StructuredSelection;
38 import org.eclipse.jface.viewers.TreeViewer;
39 import org.eclipse.jface.window.Window;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.browser.Browser;
42 import org.eclipse.swt.browser.LocationEvent;
43 import org.eclipse.swt.browser.LocationListener;
44 import org.eclipse.swt.custom.SashForm;
45 import org.eclipse.swt.dnd.Clipboard;
46 import org.eclipse.swt.dnd.TextTransfer;
47 import org.eclipse.swt.dnd.Transfer;
48 import org.eclipse.swt.events.SelectionAdapter;
49 import org.eclipse.swt.events.SelectionEvent;
50 import org.eclipse.swt.graphics.Point;
51 import org.eclipse.swt.layout.GridData;
52 import org.eclipse.swt.layout.GridLayout;
53 import org.eclipse.swt.widgets.Button;
54 import org.eclipse.swt.widgets.Composite;
55 import org.eclipse.swt.widgets.Control;
56 import org.eclipse.swt.widgets.Label;
57 import org.eclipse.swt.widgets.Shell;
58 import org.eclipse.swt.widgets.Text;
59 import org.eclipse.ui.IMemento;
60 import org.eclipse.ui.ISharedImages;
61 import org.eclipse.ui.PlatformUI;
62 import org.simantics.message.IMessageDataSchemeExtension;
63 import org.simantics.message.IMessageSchemeManager;
64 import org.simantics.message.MessageSchemeException;
65 import org.simantics.message.ReferenceSerializationException;
66 import org.simantics.utils.ui.ErrorLogger;
67
68 /**
69  * Displays details about Log Entry.
70  * Event information is split in three sections: details, stack trace and session. Details
71  * contain event date, message and severity. Stack trace is displayed if an exception is bound
72  * to event. Stack trace entries can be filtered.
73  */
74 public class EventDetailsDialog extends TrayDialog {
75
76         public static final String FILTER_ENABLED = "detailsStackFilterEnabled"; //$NON-NLS-1$
77         public static final String FILTER_LIST = "detailsStackFilterList"; //$NON-NLS-1$
78
79         private IMemento memento;
80
81         private AbstractEntry entry;
82         private AbstractEntry parentEntry; // parent of the entry
83         private AbstractEntry[] entryChildren; // children of the entry
84
85         private LogViewLabelProvider labelProvider;
86         private TreeViewer provider;
87
88         private static int COPY_ID = 22;
89
90         private int childIndex = 0;
91         private boolean isOpen;
92         private boolean isLastChild;
93         private boolean isAtEndOfLog;
94
95         private Label dateLabel;
96         private Label severityImageLabel;
97         private Label severityLabel;
98         private Text msgText;
99         //private Text stackTraceText;
100         private Text sessionDataText;
101         private Clipboard clipboard;
102         private Button copyButton;
103         private Button backButton;
104         private Button nextButton;
105         private SashForm sashForm;
106         private Label detailsTextDescription;
107     private Browser detailsText;
108
109         // sorting
110         private Comparator<Object> comparator = null;
111         Collator collator;
112
113         // patterns for filtering stack traces
114         private String[] stackFilterPatterns = null;
115
116         // location configuration
117         private Point dialogLocation;
118         private Point dialogSize;
119         private int[] sashWeights;
120     private LocalResourceManager resourceManager;
121
122         /**
123          * 
124          * @param parentShell shell in which dialog is displayed
125          * @param selection entry initially selected and to be displayed
126          * @param provider viewer
127          * @param comparator comparator used to order all entries
128          */
129         protected EventDetailsDialog(Shell parentShell, IAdaptable selection, ISelectionProvider provider, Comparator<Object> comparator, IMemento memento) {
130                 super(parentShell);
131             resourceManager = new LocalResourceManager(JFaceResources.getResources());
132                 this.provider = (TreeViewer) provider;
133                 labelProvider = (LogViewLabelProvider) this.provider.getLabelProvider();
134                 labelProvider.connect(this);
135                 this.entry = (AbstractEntry) selection;
136                 this.comparator = comparator;
137                 this.memento = memento;
138                 setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
139                 clipboard = new Clipboard(parentShell.getDisplay());
140                 initialize();
141                 collator = Collator.getInstance();
142                 readConfiguration();
143                 isLastChild = false;
144                 isAtEndOfLog = false;
145                 stackFilterPatterns = getFilters();
146         }
147
148         private void initialize() {
149                 parentEntry = (AbstractEntry) entry.getParent(entry);
150                 if (isChild(entry)) {
151                         setEntryChildren(parentEntry);
152                 } else {
153                         setEntryChildren();
154                 }
155                 resetChildIndex();
156                 isLastChild = false;
157                 isAtEndOfLog = false;
158         }
159
160         private void resetChildIndex() {
161                 if (entryChildren == null)
162                         return;
163
164                 LogEntry thisEntry = (LogEntry) entry;
165
166                 for (int i = 0; i < entryChildren.length; i++) {
167                         if (entryChildren[i] instanceof LogEntry) {
168
169                                 LogEntry logEntry = (LogEntry) entryChildren[i];
170
171                                 if (logEntry == thisEntry) {
172                                         childIndex = i;
173                                         return;
174                                 }
175                         }
176                 }
177
178                 childIndex = 0;
179         }
180
181         private boolean isChild(AbstractEntry entry) {
182                 return entry.getParent(entry) != null;
183         }
184
185         public boolean isOpen() {
186                 return isOpen;
187         }
188
189         public int open() {
190                 isOpen = true;
191                 /*if (sashWeights == null)*/ {
192                         int width = getSashForm().getClientArea().width;
193                         if (width - 100 > 0)
194                                 width -= 100;
195                         else
196                                 width = width / 3;
197                         sashWeights = new int[] {width, /*width/2,*/ getSashForm().getClientArea().width - width};
198                         //System.out.println("guessed new sashWeights: " + Arrays.toString(sashWeights));
199                 }               
200                 getSashForm().setWeights(sashWeights);
201                 return super.open();
202         }
203
204         public boolean close() {
205                 storeSettings();
206                 isOpen = false;
207                 labelProvider.disconnect(this);
208                 boolean result = super.close();
209                 resourceManager.dispose();
210                 return result;
211         }
212
213         public void create() {
214                 super.create();
215
216                 // dialog location 
217                 if (dialogLocation != null)
218                         getShell().setLocation(dialogLocation);
219
220                 // dialog size
221                 if (dialogSize != null)
222                         getShell().setSize(dialogSize);
223                 else
224                         getShell().setSize(500, 550);
225
226                 applyDialogFont(buttonBar);
227                 getButton(IDialogConstants.OK_ID).setFocus();
228         }
229
230         protected void buttonPressed(int buttonId) {
231                 if (IDialogConstants.OK_ID == buttonId)
232                         okPressed();
233                 else if (IDialogConstants.CANCEL_ID == buttonId)
234                         cancelPressed();
235                 else if (IDialogConstants.BACK_ID == buttonId)
236                         backPressed();
237                 else if (IDialogConstants.NEXT_ID == buttonId)
238                         nextPressed();
239                 else if (COPY_ID == buttonId)
240                         copyPressed();
241         }
242
243         protected void backPressed() {
244                 if (childIndex > 0) {
245                         if (isLastChild && (isChild(entry))) {
246                                 setEntryChildren(parentEntry);
247                                 isLastChild = false;
248                         }
249                         childIndex--;
250                         entry = entryChildren[childIndex];
251                 } else {
252                         if (parentEntry instanceof LogEntry) {
253                                 entry = parentEntry;
254                                 if (isChild(entry)) {
255                                         setEntryChildren((AbstractEntry) entry.getParent(entry));
256                                 } else {
257                                         setEntryChildren();
258                                 }
259                                 resetChildIndex();
260                         }
261                 }
262                 setEntrySelectionInTable();
263         }
264
265         protected void nextPressed() {
266                 if (childIndex < entryChildren.length - 1) {
267                         childIndex++;
268                         entry = entryChildren[childIndex];
269                         isLastChild = childIndex == entryChildren.length - 1;
270                 } else if (isChild(entry) && isLastChild && !isAtEndOfLog) {
271                         findNextSelectedChild(entry);
272                 } else { // at end of list but can branch into child elements - bug 58083
273                         setEntryChildren(entry);
274                         entry = entryChildren[0];
275                         isAtEndOfLog = entryChildren.length == 0;
276                         isLastChild = entryChildren.length == 0;
277                 }
278                 setEntrySelectionInTable();
279         }
280
281         protected void copyPressed() {
282                 StringWriter writer = new StringWriter();
283                 PrintWriter pwriter = new PrintWriter(writer);
284
285                 entry.write(pwriter);
286                 pwriter.flush();
287                 String textVersion = writer.toString();
288                 try {
289                         pwriter.close();
290                         writer.close();
291                 } catch (IOException e) { // do nothing
292                 }
293                 // set the clipboard contents
294                 clipboard.setContents(new Object[] {textVersion}, new Transfer[] {TextTransfer.getInstance()});
295         }
296
297         public void setComparator(Comparator<Object> comparator) {
298                 this.comparator = comparator;
299                 updateProperties();
300         }
301
302         private void setComparator(byte sortType, final int sortOrder) {
303                 if (sortType == LogView.DATE) {
304                         comparator = new Comparator<Object>() {
305                                 public int compare(Object e1, Object e2) {
306                                         Date date1 = ((LogEntry) e1).getDate();
307                                         Date date2 = ((LogEntry) e2).getDate();
308                                         if (sortOrder == LogView.ASCENDING)
309                                                 return date1.getTime() < date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
310                                         return date1.getTime() > date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
311                                 }
312                         };
313                 } else if (sortType == LogView.PLUGIN) {
314                         comparator = new Comparator<Object>() {
315                                 public int compare(Object e1, Object e2) {
316                                         LogEntry entry1 = (LogEntry) e1;
317                                         LogEntry entry2 = (LogEntry) e2;
318                                         return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * sortOrder;
319                                 }
320                         };
321                 } else {
322                         comparator = new Comparator<Object>() {
323                                 public int compare(Object e1, Object e2) {
324                                         LogEntry entry1 = (LogEntry) e1;
325                                         LogEntry entry2 = (LogEntry) e2;
326                                         return collator.compare(entry1.getMessage(), entry2.getMessage()) * sortOrder;
327                                 }
328                         };
329                 }
330         }
331
332         public void resetSelection(IAdaptable selectedEntry, byte sortType, int sortOrder) {
333                 setComparator(sortType, sortOrder);
334                 resetSelection(selectedEntry);
335         }
336
337         public void resetSelection(IAdaptable selectedEntry) {
338                 if (entry.equals(selectedEntry)) {
339                         updateProperties();
340                         return;
341                 }
342                 if (selectedEntry instanceof AbstractEntry) {
343                         entry = (AbstractEntry) selectedEntry;
344                         initialize();
345                         updateProperties();
346                 }
347         }
348
349         public void resetButtons() {
350                 backButton.setEnabled(false);
351                 nextButton.setEnabled(false);
352         }
353
354         private void setEntrySelectionInTable() {
355                 ISelection selection = new StructuredSelection(entry);
356                 provider.setSelection(selection);
357         }
358
359         public void updateProperties() {
360                 if (isChild(entry)) {
361                         parentEntry = (AbstractEntry) entry.getParent(entry);
362                         setEntryChildren(parentEntry);
363                         resetChildIndex();
364                         if (childIndex == entryChildren.length - 1)
365                                 isLastChild = true;
366                 }
367
368                 if (entry instanceof LogEntry) {
369                         LogEntry logEntry = (LogEntry) entry;
370
371                         String strDate = logEntry.getFormattedDate();
372                         dateLabel.setText(strDate);
373                         severityImageLabel.setImage(labelProvider.getColumnImage(entry, 0));
374                         severityLabel.setText(logEntry.getSeverityText());
375                         msgText.setText(logEntry.getMessage() != null ? logEntry.getMessage() : ""); //$NON-NLS-1$
376
377                         String detailedDescription= logEntry.getDetailedDescription();
378
379                         if (detailedDescription != null && !detailedDescription.trim().isEmpty()) {
380                                 detailsText.setText(detailedDescription);
381                                 detailsTextDescription.setText(Messages.EventDetailsDialog_detailedMessage);
382                         } else {
383                                 String stack = logEntry.getStack();
384
385                                 if (stack != null) {
386                                         stack = filterStack(stack);
387                                         detailsText.setText("<pre>" + stack + "</pre>");                
388                                         detailsTextDescription.setText(Messages.EventDetailsDialog_exception);
389                                 } else {
390                                         detailsText.setText("<pre>" + Messages.EventDetailsDialog_noDetailedMessage + "</pre>");
391                                 }                               
392                         }               
393
394                         LogSession logSession = logEntry.getSession();
395                         String session = logSession != null ? logSession.getSessionData() : null;
396                         if (session != null) {
397                                 sessionDataText.setText(session);
398                         }
399
400                 } else {
401                         dateLabel.setText(""); //$NON-NLS-1$
402                         severityImageLabel.setImage(null);
403                         severityLabel.setText(""); //$NON-NLS-1$
404                         msgText.setText(""); //$NON-NLS-1$
405                         //stackTraceText.setText(""); //$NON-NLS-1$
406                         sessionDataText.setText(""); //$NON-NLS-1$
407                 }
408
409                 updateButtons();
410                 //getSashForm().pack(true);
411         }
412
413         private void updateButtons() {
414                 boolean isAtEnd = childIndex == entryChildren.length - 1;
415                 if (isChild(entry)) {
416                         boolean canGoToParent = (entry.getParent(entry) instanceof LogEntry);
417                         backButton.setEnabled((childIndex > 0) || canGoToParent);
418                         nextButton.setEnabled(nextChildExists(entry, parentEntry, entryChildren) || entry.hasChildren() || !isLastChild || !isAtEnd);
419                 } else {
420                         backButton.setEnabled(childIndex != 0);
421                         nextButton.setEnabled(!isAtEnd || entry.hasChildren());
422                 }
423         }
424
425         private void findNextSelectedChild(AbstractEntry originalEntry) {
426                 if (isChild(parentEntry)) {
427                         // we're at the end of the child list; find next parent
428                         // to select.  If the parent is a child at the end of the child
429                         // list, find its next parent entry to select, etc.
430
431                         entry = parentEntry;
432                         setEntryChildren((AbstractEntry) parentEntry.getParent(parentEntry));
433                         parentEntry = (AbstractEntry) parentEntry.getParent(parentEntry);
434                         resetChildIndex();
435                         isLastChild = childIndex == entryChildren.length - 1;
436                         if (isLastChild) {
437                                 findNextSelectedChild(originalEntry);
438                         } else {
439                                 nextPressed();
440                         }
441                 } else if (parentEntry instanceof LogEntry) {
442                         entry = parentEntry;
443                         setEntryChildren();
444                         resetChildIndex();
445                         isLastChild = childIndex == entryChildren.length - 1;
446                         if (isLastChild) {
447                                 if (isChild(entry)) {
448                                         findNextSelectedChild(originalEntry);
449                                 } else {
450                                         entry = originalEntry;
451                                         isAtEndOfLog = true;
452                                         nextPressed();
453                                 }
454                         } else {
455                                 nextPressed();
456                         }
457                 } else {
458                         entry = originalEntry;
459                         isAtEndOfLog = true;
460                         nextPressed();
461                 }
462         }
463
464         private boolean nextChildExists(AbstractEntry originalEntry, AbstractEntry originalParent, AbstractEntry[] originalEntries) {
465                 if (isChild(parentEntry)) {
466                         // we're at the end of the child list; find next parent
467                         // to select.  If the parent is a child at the end of the child
468                         // list, find its next parent entry to select, etc.
469
470                         entry = parentEntry;
471                         parentEntry = (AbstractEntry) entry.getParent(entry);
472                         setEntryChildren(parentEntry);
473                         resetChildIndex();
474                         if (childIndex == entryChildren.length - 1) {
475                                 return nextChildExists(originalEntry, originalParent, originalEntries);
476                         }
477                         entry = originalEntry;
478                         parentEntry = originalParent;
479                         entryChildren = originalEntries;
480                         resetChildIndex();
481                         return true;
482                 } else if (parentEntry instanceof LogEntry) {
483                         entry = parentEntry;
484                         setEntryChildren();
485                         childIndex = -1;
486                         resetChildIndex();
487                         if ((childIndex != -1) && (childIndex < entryChildren.length - 1)) {
488                                 entry = originalEntry;
489                                 parentEntry = originalParent;
490                                 entryChildren = originalEntries;
491                                 resetChildIndex();
492                                 return true;
493                         }
494                 }
495                 entry = originalEntry;
496                 parentEntry = originalParent;
497                 entryChildren = originalEntries;
498                 resetChildIndex();
499                 return false;
500
501         }
502
503         /**
504          * Sets entry children (Prev-Next navigable) to top-level elements
505          */
506         private void setEntryChildren() {
507                 AbstractEntry[] children = getElements();
508
509                 if (comparator != null)
510                         Arrays.sort(children, comparator);
511                 entryChildren = new AbstractEntry[children.length];
512
513                 System.arraycopy(children, 0, entryChildren, 0, children.length);
514         }
515
516         /**
517          * Sets entry children (Prev-Next navigable) to children of given entry
518          */
519         private void setEntryChildren(AbstractEntry entry) {
520                 Object[] children = entry.getChildren(entry);
521
522                 if (comparator != null)
523                         Arrays.sort(children, comparator);
524
525                 List<Object> result = new ArrayList<Object>();
526                 for (int i = 0; i < children.length; i++) {
527                         if (children[i] instanceof AbstractEntry) {
528                                 result.add(children[i]);
529                         }
530                 }
531
532                 entryChildren = (AbstractEntry[]) result.toArray(new AbstractEntry[result.size()]);
533         }
534
535         public SashForm getSashForm() {
536                 return sashForm;
537         }
538
539         protected Control createDialogArea(Composite parent) {
540                 Composite container = new Composite(parent, SWT.NONE);
541                 GridLayout layout = new GridLayout();
542                 layout.numColumns = 1;
543                 container.setLayout(layout);
544                 GridData gd = new GridData(GridData.FILL_BOTH);
545                 container.setLayoutData(gd);
546
547                 createDetailsSection(container);
548                 createSashForm(container);
549                 createDetailedMessageSection(getSashForm());
550                 //createStackSection(getSashForm());
551                 createSessionSection(getSashForm());
552
553                 updateProperties();
554                 Dialog.applyDialogFont(container);
555                 return container;
556         }
557
558         private void createSashForm(Composite parent) {
559                 sashForm = new SashForm(parent, SWT.VERTICAL);
560                 GridLayout layout = new GridLayout();
561                 layout.marginHeight = layout.marginWidth = 0;
562                 sashForm.setLayout(layout);
563                 sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
564         }
565
566         private void createToolbarButtonBar(Composite parent) {
567                 Composite comp = new Composite(parent, SWT.NONE);
568                 GridLayout layout = new GridLayout();
569                 layout.marginWidth = layout.marginHeight = 0;
570                 //layout.numColumns = 1;
571                 comp.setLayout(layout);
572                 comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
573                 ((GridData) comp.getLayoutData()).verticalAlignment = SWT.BOTTOM;
574
575                 Composite container = new Composite(comp, SWT.NONE);
576                 layout = new GridLayout();
577                 layout.marginWidth = 0;
578                 layout.marginHeight = 0;
579                 container.setLayout(layout);
580                 container.setLayoutData(new GridData(GridData.FILL_BOTH));
581
582                 backButton = createButton(container, IDialogConstants.BACK_ID, "", false); //$NON-NLS-1$
583                 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
584                 backButton.setLayoutData(gd);
585                 backButton.setToolTipText(Messages.EventDetailsDialog_previous);
586                 backButton.setImage(SharedImages.getImage(SharedImages.DESC_PREV_EVENT));
587
588                 copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
589                 gd = new GridData();
590                 copyButton.setLayoutData(gd);
591                 copyButton.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_COPY));
592                 copyButton.setToolTipText(Messages.EventDetailsDialog_copy);
593
594                 nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
595                 gd = new GridData();
596                 nextButton.setLayoutData(gd);
597                 nextButton.setToolTipText(Messages.EventDetailsDialog_next);
598                 nextButton.setImage(SharedImages.getImage(SharedImages.DESC_NEXT_EVENT));
599
600                 Button button = new Button(container, SWT.NONE);
601                 button.setToolTipText(Messages.EventDetailsDialog_ShowFilterDialog);
602                 button.setImage(SharedImages.getImage(SharedImages.DESC_FILTER));
603                 gd = new GridData();
604                 gd.horizontalAlignment = SWT.RIGHT;
605                 button.setLayoutData(gd);
606                 button.addSelectionListener(new SelectionAdapter() {
607                         public void widgetSelected(SelectionEvent e) {
608                                 FilterDialog dialog = new FilterDialog(getShell(), memento);
609                                 dialog.create();
610                                 dialog.getShell().setText(Messages.EventDetailsDialog_FilterDialog);
611                                 if (dialog.open() == Window.OK)
612                                         // update filters and currently displayed stack trace
613                                         stackFilterPatterns = getFilters();
614                                 updateProperties();
615                         }
616                 });
617
618                 // set numColumns at the end, after all createButton() calls, which change this value
619                 layout.numColumns = 2;
620         }
621
622         protected void createButtonsForButtonBar(Composite parent) {
623                 // create OK button only by default
624                 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
625         }
626
627         private void createDetailsSection(Composite parent) {
628                 Composite container = new Composite(parent, SWT.NONE);
629                 GridLayout layout = new GridLayout();
630                 layout.marginWidth = layout.marginHeight = 0;
631                 layout.numColumns = 2;
632                 container.setLayout(layout);
633                 container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
634
635                 createTextSection(container);
636                 createToolbarButtonBar(container);
637         }
638
639         private void createTextSection(Composite parent) {
640                 Composite textContainer = new Composite(parent, SWT.NONE);
641                 GridLayout layout = new GridLayout();
642                 layout.numColumns = 3;
643                 layout.marginHeight = layout.marginWidth = 0;
644                 textContainer.setLayout(layout);
645                 textContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
646
647                 Label label = new Label(textContainer, SWT.NONE);
648                 label.setText(Messages.EventDetailsDialog_date);
649                 dateLabel = new Label(textContainer, SWT.NULL);
650                 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
651                 gd.horizontalSpan = 2;
652                 dateLabel.setLayoutData(gd);
653
654                 label = new Label(textContainer, SWT.NONE);
655                 label.setText(Messages.EventDetailsDialog_severity);
656                 severityImageLabel = new Label(textContainer, SWT.NULL);
657                 severityLabel = new Label(textContainer, SWT.NULL);
658                 gd = new GridData(GridData.FILL_HORIZONTAL);
659                 severityLabel.setLayoutData(gd);
660
661                 label = new Label(textContainer, SWT.NONE);
662                 label.setText(Messages.EventDetailsDialog_message);
663                 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
664                 label.setLayoutData(gd);
665                 msgText = new Text(textContainer, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
666                 msgText.setEditable(false);
667                 gd = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING | GridData.GRAB_VERTICAL);
668                 gd.horizontalSpan = 2;
669                 gd.heightHint = 44;
670                 gd.grabExcessVerticalSpace = true;
671                 msgText.setLayoutData(gd);
672         }
673
674         private void createDetailedMessageSection(Composite parent) {
675                 Composite container = new Composite(parent, SWT.NONE);
676                 GridLayout layout = new GridLayout(2, false);
677                 layout.marginHeight = 0;
678                 layout.marginWidth = 6;
679                 container.setLayout(layout);
680                 GridData gd = new GridData(GridData.FILL_BOTH);
681                 gd.heightHint = 100;
682                 container.setLayoutData(gd);
683
684                 detailsTextDescription = new Label(container, SWT.NONE);
685                 detailsTextDescription.setText(Messages.EventDetailsDialog_detailedMessage);
686                 gd = new GridData();
687                 gd.verticalAlignment = SWT.BOTTOM;
688                 gd.grabExcessHorizontalSpace = true;
689                 detailsTextDescription.setLayoutData(gd);
690
691                 /*final Composite messageDescriptorComposite = new Composite(container, SWT.BORDER);
692                 //GridDataFactory.fillDefaults().grab(true, false).applyTo(messageDescriptorComposite);
693                 TableWrapLayout layout2 = new TableWrapLayout();
694                 layout2.bottomMargin = 0;
695                 layout2.topMargin = 0;
696                 layout2.leftMargin = 0;
697                 layout2.rightMargin = 0;
698                 messageDescriptorComposite.setLayout(layout2);
699                 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
700                 gd.grabExcessHorizontalSpace = true;
701                 gd.horizontalSpan = 2;
702                 messageDescriptorComposite.setLayoutData(gd);*/
703
704                 detailsText = new Browser(container, SWT.BORDER);
705 //              detailsText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
706                 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
707                 gd.grabExcessHorizontalSpace = true;
708                 gd.grabExcessVerticalSpace = true;
709                 gd.horizontalSpan = 2;
710                 detailsText.setLayoutData(gd);
711                 /*TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB);
712                 detailsText.setLayoutData(data);*/
713                 //TextColors.bindTo(resourceManager, detailsText);
714                 /*detailsText.addHyperlinkListener(new IHyperlinkListener() {
715                     @Override
716                     public void linkActivated(HyperlinkEvent event) {
717                         String s = (String) event.data;
718                         //System.out.println("link activated: " + s);
719                         try {
720                             URI uri = new URI(s);
721                             String scheme = uri.getScheme();
722                             String schemeSpecificPart = uri.getSchemeSpecificPart();
723
724                             IMessageSchemeManager msm = org.simantics.message.internal.Activator.getDefault().getMessageSchemeManager();
725                             IMessageDataSchemeExtension[] exts = msm.getByScheme(scheme);
726
727                             for (IMessageDataSchemeExtension ext : exts) {
728                                 Object data = ext.getSerializer().deserialize(schemeSpecificPart);
729                                 ext.getHandler().perform(data);
730                                 return;
731                             }
732                         } catch (URISyntaxException e) {
733                             // TODO Auto-generated catch block
734                             e.printStackTrace();
735                         } catch (ReferenceSerializationException e) {
736                             // TODO Auto-generated catch block
737                             e.printStackTrace();
738                         }
739                     }
740                     @Override
741                     public void linkEntered(HyperlinkEvent e) {
742                         //System.out.println("link entered: " + e.data);
743                     }
744                     @Override
745                     public void linkExited(HyperlinkEvent e) {
746                         //System.out.println("link exited: " + e.data);
747                     }
748                 });*/
749                 
750                 /*messageDescriptorComposite.setContent(detailsText);
751                 messageDescriptorComposite.setExpandVertical(true);
752                 messageDescriptorComposite.setExpandHorizontal(true);
753                 messageDescriptorComposite.addControlListener(new ControlAdapter() {
754                     public void controlResized(ControlEvent e) {
755                         Rectangle r = messageDescriptorComposite.getClientArea();
756                         //System.out.println("scrolled composite resized: " + e + ", client area: " + r);
757                         Point contentSize = detailsText.computeSize(r.width, SWT.DEFAULT);
758                         //System.out.println("computed content size: " + contentSize);
759                         messageDescriptorComposite.setMinSize(contentSize);
760                     }
761                 });*/
762                 detailsText.addLocationListener(new LocationListener() {
763                     @Override
764                     public void changed(LocationEvent event) {
765                         //System.out.println("changed: " + event);
766                     }
767                     @Override
768                     public void changing(LocationEvent event) {
769                         //System.out.println("changing: " + event);
770                         String location = event.location;
771                         if ("about:blank".equals(location)) {
772                             event.doit = true;
773                         } else {
774                             event.doit = false;
775                             //System.out.println("link activated: " + location);
776                             try {
777                                 URI uri = new URI(location);
778                                 String scheme = uri.getScheme();
779                                 //String schemeSpecificPart = uri.getSchemeSpecificPart();
780
781                                 IMessageSchemeManager msm = org.simantics.message.internal.Activator.getDefault().getMessageSchemeManager();
782                                 IMessageDataSchemeExtension[] exts = msm.getByScheme(scheme);
783
784                                 for (IMessageDataSchemeExtension ext : exts) {
785                                     Object data = ext.getSerializer().deserialize(uri);
786                                     try {
787                                         ext.getHandler().perform(data);
788                                         return;
789                                     } catch (MessageSchemeException e) {
790                                         ErrorLogger.defaultLogError(e);
791                                     }
792                                 }
793                                 return;
794                             } catch (URISyntaxException e) {
795                                 // TODO Auto-generated catch block
796                                 e.printStackTrace();
797                             } catch (ReferenceSerializationException e) {
798                                 // TODO Auto-generated catch block
799                                 e.printStackTrace();
800                             }
801                         }
802                     }
803                 });
804         }
805
806         /*private void createStackSection(Composite parent) {
807                 Composite container = new Composite(parent, SWT.NONE);
808                 GridLayout layout = new GridLayout(2, false);
809                 layout.marginHeight = 0;
810                 layout.marginWidth = 6;
811                 container.setLayout(layout);
812                 GridData gd = new GridData(GridData.FILL_BOTH);
813                 gd.heightHint = 100;
814                 container.setLayoutData(gd);
815
816                 Label label = new Label(container, SWT.NONE);
817                 label.setText(Messages.EventDetailsDialog_exception);
818                 gd = new GridData();
819                 gd.verticalAlignment = SWT.BOTTOM;
820                 label.setLayoutData(gd);
821                 
822                 stackTraceText = new Text(container, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
823                 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
824                 gd.grabExcessHorizontalSpace = true;
825                 gd.horizontalSpan = 2;
826                 stackTraceText.setLayoutData(gd);
827                 stackTraceText.setEditable(false);
828         }*/
829
830         private void createSessionSection(Composite parent) {
831                 Composite container = new Composite(parent, SWT.NONE);
832                 GridLayout layout = new GridLayout();
833                 layout.marginHeight = 0;
834                 layout.marginWidth = 6;
835                 container.setLayout(layout);
836                 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
837                 gd.heightHint = 100;
838                 container.setLayoutData(gd);
839
840                 Label line = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
841                 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
842                 gd.widthHint = 1;
843                 line.setLayoutData(gd);
844
845                 Label label = new Label(container, SWT.NONE);
846                 label.setText(Messages.EventDetailsDialog_session);
847                 gd = new GridData(GridData.FILL_HORIZONTAL);
848                 label.setLayoutData(gd);
849                 sessionDataText = new Text(container, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
850                 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
851                 gd.grabExcessHorizontalSpace = true;
852                 sessionDataText.setLayoutData(gd);
853                 sessionDataText.setEditable(false);
854         }
855
856         /**
857          * Loads filters from preferences.
858          * @return filters from preferences or empty array
859          * 
860          * @since 3.4
861          */
862         private String[] getFilters() {
863
864                 Boolean filterEnabled = memento.getBoolean(FILTER_ENABLED);
865
866                 String filtersString = memento.getString(FILTER_LIST);
867
868                 if ((filterEnabled == null) || (filterEnabled.booleanValue() == false) || filtersString == null) {
869                         return new String[0];
870                 }
871
872                 StringTokenizer st = new StringTokenizer(filtersString, ";"); //$NON-NLS-1$
873                 List<Object> filters = new ArrayList<Object>();
874                 while (st.hasMoreElements()) {
875                         String filter = st.nextToken();
876                         filters.add(filter);
877                 }
878
879                 return (String[]) filters.toArray(new String[filters.size()]);
880         }
881
882         /**
883          * Filters stack trace.
884          * Every stack trace line is compared against all patterns.
885          * If line contains any of pattern strings, it's excluded from output.
886          * 
887          * @returns filtered stack trace
888          * @since 3.4
889          */
890         private String filterStack(String stack) {
891                 if (stackFilterPatterns.length == 0) {
892                         return stack;
893                 }
894
895                 StringTokenizer st = new StringTokenizer(stack, "\n"); //$NON-NLS-1$
896                 StringBuffer result = new StringBuffer();
897                 while (st.hasMoreTokens()) {
898                         String stackElement = st.nextToken();
899
900                         boolean filtered = false;
901                         int i = 0;
902                         while ((!filtered) && (i < stackFilterPatterns.length)) {
903                                 filtered = stackElement.indexOf(stackFilterPatterns[i]) >= 0;
904                                 i++;
905                         }
906
907                         if (!filtered) {
908                                 result.append(stackElement).append("\n"); //$NON-NLS-1$
909                         }
910                 }
911
912                 return result.toString();
913         }
914
915         //--------------- configuration handling --------------
916
917         /**
918          * Stores the current state in the dialog settings.
919          * @since 2.0
920          */
921         private void storeSettings() {
922                 writeConfiguration();
923         }
924
925         /**
926          * Returns the dialog settings object used to share state
927          * between several event detail dialogs.
928          * 
929          * @return the dialog settings to be used
930          */
931         private IDialogSettings getDialogSettings() {
932                 IDialogSettings settings = Activator.getDefault().getDialogSettings();
933                 IDialogSettings dialogSettings = settings.getSection(getClass().getName());
934                 if (dialogSettings == null)
935                         dialogSettings = settings.addNewSection(getClass().getName());
936                 return dialogSettings;
937         }
938
939         /**
940          * Initializes itself from the dialog settings with the same state
941          * as at the previous invocation.
942          */
943         private void readConfiguration() {
944                 IDialogSettings s = getDialogSettings();
945                 try { 
946                         int x = s.getInt("x"); //$NON-NLS-1$
947                         int y = s.getInt("y"); //$NON-NLS-1$
948                         dialogLocation = new Point(x, y);
949
950                         x = s.getInt("width"); //$NON-NLS-1$
951                         y = s.getInt("height"); //$NON-NLS-1$
952                         dialogSize = new Point(x, y);
953
954                         sashWeights = new int[3];
955                         sashWeights[0] = s.getInt("sashWidth0"); //$NON-NLS-1$
956                         sashWeights[1] = s.getInt("sashWidth1"); //$NON-NLS-1$
957                         sashWeights[2] = s.getInt("sashWidth2"); //$NON-NLS-1$
958
959                 } catch (NumberFormatException e) {
960                         dialogLocation = null;
961                         dialogSize = null;
962                         sashWeights = null;
963                 }
964         }
965
966         private void writeConfiguration() {
967                 IDialogSettings s = getDialogSettings();
968                 Point location = getShell().getLocation();
969                 s.put("x", location.x); //$NON-NLS-1$
970                 s.put("y", location.y); //$NON-NLS-1$
971
972                 Point size = getShell().getSize();
973                 s.put("width", size.x); //$NON-NLS-1$
974                 s.put("height", size.y); //$NON-NLS-1$
975
976                 sashWeights = getSashForm().getWeights();
977                 s.put("sashWidth0", sashWeights[0]); //$NON-NLS-1$
978                 s.put("sashWidth1", sashWeights[1]); //$NON-NLS-1$
979                 //s.put("sashWidth2", sashWeights[2]); //$NON-NLS-1$
980         }
981
982         /**
983          * Utility method to get all top level elements of the Log View
984          * @return top level elements of the Log View
985          */
986         private AbstractEntry[] getElements() {
987                 return (AbstractEntry[]) ((ITreeContentProvider) provider.getContentProvider()).getElements(null);
988         }
989 }