]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.message.ui/src/org/simantics/message/ui/EventDetailsDialog.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.message.ui / src / org / simantics / message / ui / EventDetailsDialog.java
diff --git a/bundles/org.simantics.message.ui/src/org/simantics/message/ui/EventDetailsDialog.java b/bundles/org.simantics.message.ui/src/org/simantics/message/ui/EventDetailsDialog.java
new file mode 100644 (file)
index 0000000..8cff37a
--- /dev/null
@@ -0,0 +1,989 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.message.ui;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.simantics.message.IMessageDataSchemeExtension;
+import org.simantics.message.IMessageSchemeManager;
+import org.simantics.message.MessageSchemeException;
+import org.simantics.message.ReferenceSerializationException;
+import org.simantics.utils.ui.ErrorLogger;
+
+/**
+ * Displays details about Log Entry.
+ * Event information is split in three sections: details, stack trace and session. Details
+ * contain event date, message and severity. Stack trace is displayed if an exception is bound
+ * to event. Stack trace entries can be filtered.
+ */
+public class EventDetailsDialog extends TrayDialog {
+
+       public static final String FILTER_ENABLED = "detailsStackFilterEnabled"; //$NON-NLS-1$
+       public static final String FILTER_LIST = "detailsStackFilterList"; //$NON-NLS-1$
+
+       private IMemento memento;
+
+       private AbstractEntry entry;
+       private AbstractEntry parentEntry; // parent of the entry
+       private AbstractEntry[] entryChildren; // children of the entry
+
+       private LogViewLabelProvider labelProvider;
+       private TreeViewer provider;
+
+       private static int COPY_ID = 22;
+
+       private int childIndex = 0;
+       private boolean isOpen;
+       private boolean isLastChild;
+       private boolean isAtEndOfLog;
+
+       private Label dateLabel;
+       private Label severityImageLabel;
+       private Label severityLabel;
+       private Text msgText;
+       //private Text stackTraceText;
+       private Text sessionDataText;
+       private Clipboard clipboard;
+       private Button copyButton;
+       private Button backButton;
+       private Button nextButton;
+       private SashForm sashForm;
+       private Label detailsTextDescription;
+    private Browser detailsText;
+
+       // sorting
+       private Comparator<Object> comparator = null;
+       Collator collator;
+
+       // patterns for filtering stack traces
+       private String[] stackFilterPatterns = null;
+
+       // location configuration
+       private Point dialogLocation;
+       private Point dialogSize;
+       private int[] sashWeights;
+    private LocalResourceManager resourceManager;
+
+       /**
+        * 
+        * @param parentShell shell in which dialog is displayed
+        * @param selection entry initially selected and to be displayed
+        * @param provider viewer
+        * @param comparator comparator used to order all entries
+        */
+       protected EventDetailsDialog(Shell parentShell, IAdaptable selection, ISelectionProvider provider, Comparator<Object> comparator, IMemento memento) {
+               super(parentShell);
+           resourceManager = new LocalResourceManager(JFaceResources.getResources());
+               this.provider = (TreeViewer) provider;
+               labelProvider = (LogViewLabelProvider) this.provider.getLabelProvider();
+               labelProvider.connect(this);
+               this.entry = (AbstractEntry) selection;
+               this.comparator = comparator;
+               this.memento = memento;
+               setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
+               clipboard = new Clipboard(parentShell.getDisplay());
+               initialize();
+               collator = Collator.getInstance();
+               readConfiguration();
+               isLastChild = false;
+               isAtEndOfLog = false;
+               stackFilterPatterns = getFilters();
+       }
+
+       private void initialize() {
+               parentEntry = (AbstractEntry) entry.getParent(entry);
+               if (isChild(entry)) {
+                       setEntryChildren(parentEntry);
+               } else {
+                       setEntryChildren();
+               }
+               resetChildIndex();
+               isLastChild = false;
+               isAtEndOfLog = false;
+       }
+
+       private void resetChildIndex() {
+               if (entryChildren == null)
+                       return;
+
+               LogEntry thisEntry = (LogEntry) entry;
+
+               for (int i = 0; i < entryChildren.length; i++) {
+                       if (entryChildren[i] instanceof LogEntry) {
+
+                               LogEntry logEntry = (LogEntry) entryChildren[i];
+
+                               if (logEntry == thisEntry) {
+                                       childIndex = i;
+                                       return;
+                               }
+                       }
+               }
+
+               childIndex = 0;
+       }
+
+       private boolean isChild(AbstractEntry entry) {
+               return entry.getParent(entry) != null;
+       }
+
+       public boolean isOpen() {
+               return isOpen;
+       }
+
+       public int open() {
+               isOpen = true;
+               /*if (sashWeights == null)*/ {
+                       int width = getSashForm().getClientArea().width;
+                       if (width - 100 > 0)
+                               width -= 100;
+                       else
+                               width = width / 3;
+                       sashWeights = new int[] {width, /*width/2,*/ getSashForm().getClientArea().width - width};
+                       //System.out.println("guessed new sashWeights: " + Arrays.toString(sashWeights));
+               }               
+               getSashForm().setWeights(sashWeights);
+               return super.open();
+       }
+
+       public boolean close() {
+               storeSettings();
+               isOpen = false;
+               labelProvider.disconnect(this);
+               boolean result = super.close();
+               resourceManager.dispose();
+               return result;
+       }
+
+       public void create() {
+               super.create();
+
+               // dialog location 
+               if (dialogLocation != null)
+                       getShell().setLocation(dialogLocation);
+
+               // dialog size
+               if (dialogSize != null)
+                       getShell().setSize(dialogSize);
+               else
+                       getShell().setSize(500, 550);
+
+               applyDialogFont(buttonBar);
+               getButton(IDialogConstants.OK_ID).setFocus();
+       }
+
+       protected void buttonPressed(int buttonId) {
+               if (IDialogConstants.OK_ID == buttonId)
+                       okPressed();
+               else if (IDialogConstants.CANCEL_ID == buttonId)
+                       cancelPressed();
+               else if (IDialogConstants.BACK_ID == buttonId)
+                       backPressed();
+               else if (IDialogConstants.NEXT_ID == buttonId)
+                       nextPressed();
+               else if (COPY_ID == buttonId)
+                       copyPressed();
+       }
+
+       protected void backPressed() {
+               if (childIndex > 0) {
+                       if (isLastChild && (isChild(entry))) {
+                               setEntryChildren(parentEntry);
+                               isLastChild = false;
+                       }
+                       childIndex--;
+                       entry = entryChildren[childIndex];
+               } else {
+                       if (parentEntry instanceof LogEntry) {
+                               entry = parentEntry;
+                               if (isChild(entry)) {
+                                       setEntryChildren((AbstractEntry) entry.getParent(entry));
+                               } else {
+                                       setEntryChildren();
+                               }
+                               resetChildIndex();
+                       }
+               }
+               setEntrySelectionInTable();
+       }
+
+       protected void nextPressed() {
+               if (childIndex < entryChildren.length - 1) {
+                       childIndex++;
+                       entry = entryChildren[childIndex];
+                       isLastChild = childIndex == entryChildren.length - 1;
+               } else if (isChild(entry) && isLastChild && !isAtEndOfLog) {
+                       findNextSelectedChild(entry);
+               } else { // at end of list but can branch into child elements - bug 58083
+                       setEntryChildren(entry);
+                       entry = entryChildren[0];
+                       isAtEndOfLog = entryChildren.length == 0;
+                       isLastChild = entryChildren.length == 0;
+               }
+               setEntrySelectionInTable();
+       }
+
+       protected void copyPressed() {
+               StringWriter writer = new StringWriter();
+               PrintWriter pwriter = new PrintWriter(writer);
+
+               entry.write(pwriter);
+               pwriter.flush();
+               String textVersion = writer.toString();
+               try {
+                       pwriter.close();
+                       writer.close();
+               } catch (IOException e) { // do nothing
+               }
+               // set the clipboard contents
+               clipboard.setContents(new Object[] {textVersion}, new Transfer[] {TextTransfer.getInstance()});
+       }
+
+       public void setComparator(Comparator<Object> comparator) {
+               this.comparator = comparator;
+               updateProperties();
+       }
+
+       private void setComparator(byte sortType, final int sortOrder) {
+               if (sortType == LogView.DATE) {
+                       comparator = new Comparator<Object>() {
+                               public int compare(Object e1, Object e2) {
+                                       Date date1 = ((LogEntry) e1).getDate();
+                                       Date date2 = ((LogEntry) e2).getDate();
+                                       if (sortOrder == LogView.ASCENDING)
+                                               return date1.getTime() < date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
+                                       return date1.getTime() > date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
+                               }
+                       };
+               } else if (sortType == LogView.PLUGIN) {
+                       comparator = new Comparator<Object>() {
+                               public int compare(Object e1, Object e2) {
+                                       LogEntry entry1 = (LogEntry) e1;
+                                       LogEntry entry2 = (LogEntry) e2;
+                                       return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * sortOrder;
+                               }
+                       };
+               } else {
+                       comparator = new Comparator<Object>() {
+                               public int compare(Object e1, Object e2) {
+                                       LogEntry entry1 = (LogEntry) e1;
+                                       LogEntry entry2 = (LogEntry) e2;
+                                       return collator.compare(entry1.getMessage(), entry2.getMessage()) * sortOrder;
+                               }
+                       };
+               }
+       }
+
+       public void resetSelection(IAdaptable selectedEntry, byte sortType, int sortOrder) {
+               setComparator(sortType, sortOrder);
+               resetSelection(selectedEntry);
+       }
+
+       public void resetSelection(IAdaptable selectedEntry) {
+               if (entry.equals(selectedEntry)) {
+                       updateProperties();
+                       return;
+               }
+               if (selectedEntry instanceof AbstractEntry) {
+                       entry = (AbstractEntry) selectedEntry;
+                       initialize();
+                       updateProperties();
+               }
+       }
+
+       public void resetButtons() {
+               backButton.setEnabled(false);
+               nextButton.setEnabled(false);
+       }
+
+       private void setEntrySelectionInTable() {
+               ISelection selection = new StructuredSelection(entry);
+               provider.setSelection(selection);
+       }
+
+       public void updateProperties() {
+               if (isChild(entry)) {
+                       parentEntry = (AbstractEntry) entry.getParent(entry);
+                       setEntryChildren(parentEntry);
+                       resetChildIndex();
+                       if (childIndex == entryChildren.length - 1)
+                               isLastChild = true;
+               }
+
+               if (entry instanceof LogEntry) {
+                       LogEntry logEntry = (LogEntry) entry;
+
+                       String strDate = logEntry.getFormattedDate();
+                       dateLabel.setText(strDate);
+                       severityImageLabel.setImage(labelProvider.getColumnImage(entry, 0));
+                       severityLabel.setText(logEntry.getSeverityText());
+                       msgText.setText(logEntry.getMessage() != null ? logEntry.getMessage() : ""); //$NON-NLS-1$
+
+                       String detailedDescription= logEntry.getDetailedDescription();
+
+                       if (detailedDescription != null && !detailedDescription.trim().isEmpty()) {
+                               detailsText.setText(detailedDescription);
+                               detailsTextDescription.setText(Messages.EventDetailsDialog_detailedMessage);
+                       } else {
+                               String stack = logEntry.getStack();
+
+                               if (stack != null) {
+                                       stack = filterStack(stack);
+                                       detailsText.setText("<pre>" + stack + "</pre>");                
+                                       detailsTextDescription.setText(Messages.EventDetailsDialog_exception);
+                               } else {
+                                       detailsText.setText("<pre>" + Messages.EventDetailsDialog_noDetailedMessage + "</pre>");
+                               }                               
+                       }               
+
+                       LogSession logSession = logEntry.getSession();\r
+                       String session = logSession != null ? logSession.getSessionData() : null;
+                       if (session != null) {
+                               sessionDataText.setText(session);
+                       }
+
+               } else {
+                       dateLabel.setText(""); //$NON-NLS-1$
+                       severityImageLabel.setImage(null);
+                       severityLabel.setText(""); //$NON-NLS-1$
+                       msgText.setText(""); //$NON-NLS-1$
+                       //stackTraceText.setText(""); //$NON-NLS-1$
+                       sessionDataText.setText(""); //$NON-NLS-1$
+               }
+
+               updateButtons();
+               //getSashForm().pack(true);
+       }
+
+       private void updateButtons() {
+               boolean isAtEnd = childIndex == entryChildren.length - 1;
+               if (isChild(entry)) {
+                       boolean canGoToParent = (entry.getParent(entry) instanceof LogEntry);
+                       backButton.setEnabled((childIndex > 0) || canGoToParent);
+                       nextButton.setEnabled(nextChildExists(entry, parentEntry, entryChildren) || entry.hasChildren() || !isLastChild || !isAtEnd);
+               } else {
+                       backButton.setEnabled(childIndex != 0);
+                       nextButton.setEnabled(!isAtEnd || entry.hasChildren());
+               }
+       }
+
+       private void findNextSelectedChild(AbstractEntry originalEntry) {
+               if (isChild(parentEntry)) {
+                       // we're at the end of the child list; find next parent
+                       // to select.  If the parent is a child at the end of the child
+                       // list, find its next parent entry to select, etc.
+
+                       entry = parentEntry;
+                       setEntryChildren((AbstractEntry) parentEntry.getParent(parentEntry));
+                       parentEntry = (AbstractEntry) parentEntry.getParent(parentEntry);
+                       resetChildIndex();
+                       isLastChild = childIndex == entryChildren.length - 1;
+                       if (isLastChild) {
+                               findNextSelectedChild(originalEntry);
+                       } else {
+                               nextPressed();
+                       }
+               } else if (parentEntry instanceof LogEntry) {
+                       entry = parentEntry;
+                       setEntryChildren();
+                       resetChildIndex();
+                       isLastChild = childIndex == entryChildren.length - 1;
+                       if (isLastChild) {
+                               if (isChild(entry)) {
+                                       findNextSelectedChild(originalEntry);
+                               } else {
+                                       entry = originalEntry;
+                                       isAtEndOfLog = true;
+                                       nextPressed();
+                               }
+                       } else {
+                               nextPressed();
+                       }
+               } else {
+                       entry = originalEntry;
+                       isAtEndOfLog = true;
+                       nextPressed();
+               }
+       }
+
+       private boolean nextChildExists(AbstractEntry originalEntry, AbstractEntry originalParent, AbstractEntry[] originalEntries) {
+               if (isChild(parentEntry)) {
+                       // we're at the end of the child list; find next parent
+                       // to select.  If the parent is a child at the end of the child
+                       // list, find its next parent entry to select, etc.
+
+                       entry = parentEntry;
+                       parentEntry = (AbstractEntry) entry.getParent(entry);
+                       setEntryChildren(parentEntry);
+                       resetChildIndex();
+                       if (childIndex == entryChildren.length - 1) {
+                               return nextChildExists(originalEntry, originalParent, originalEntries);
+                       }
+                       entry = originalEntry;
+                       parentEntry = originalParent;
+                       entryChildren = originalEntries;
+                       resetChildIndex();
+                       return true;
+               } else if (parentEntry instanceof LogEntry) {
+                       entry = parentEntry;
+                       setEntryChildren();
+                       childIndex = -1;
+                       resetChildIndex();
+                       if ((childIndex != -1) && (childIndex < entryChildren.length - 1)) {
+                               entry = originalEntry;
+                               parentEntry = originalParent;
+                               entryChildren = originalEntries;
+                               resetChildIndex();
+                               return true;
+                       }
+               }
+               entry = originalEntry;
+               parentEntry = originalParent;
+               entryChildren = originalEntries;
+               resetChildIndex();
+               return false;
+
+       }
+
+       /**
+        * Sets entry children (Prev-Next navigable) to top-level elements
+        */
+       private void setEntryChildren() {
+               AbstractEntry[] children = getElements();
+
+               if (comparator != null)
+                       Arrays.sort(children, comparator);
+               entryChildren = new AbstractEntry[children.length];
+
+               System.arraycopy(children, 0, entryChildren, 0, children.length);
+       }
+
+       /**
+        * Sets entry children (Prev-Next navigable) to children of given entry
+        */
+       private void setEntryChildren(AbstractEntry entry) {
+               Object[] children = entry.getChildren(entry);
+
+               if (comparator != null)
+                       Arrays.sort(children, comparator);
+
+               List<Object> result = new ArrayList<Object>();
+               for (int i = 0; i < children.length; i++) {
+                       if (children[i] instanceof AbstractEntry) {
+                               result.add(children[i]);
+                       }
+               }
+
+               entryChildren = (AbstractEntry[]) result.toArray(new AbstractEntry[result.size()]);
+       }
+
+       public SashForm getSashForm() {
+               return sashForm;
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 1;
+               container.setLayout(layout);
+               GridData gd = new GridData(GridData.FILL_BOTH);
+               container.setLayoutData(gd);
+
+               createDetailsSection(container);
+               createSashForm(container);
+               createDetailedMessageSection(getSashForm());
+               //createStackSection(getSashForm());
+               createSessionSection(getSashForm());
+
+               updateProperties();
+               Dialog.applyDialogFont(container);
+               return container;
+       }
+
+       private void createSashForm(Composite parent) {
+               sashForm = new SashForm(parent, SWT.VERTICAL);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight = layout.marginWidth = 0;
+               sashForm.setLayout(layout);
+               sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
+       }
+
+       private void createToolbarButtonBar(Composite parent) {
+               Composite comp = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginWidth = layout.marginHeight = 0;
+               //layout.numColumns = 1;
+               comp.setLayout(layout);
+               comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+               ((GridData) comp.getLayoutData()).verticalAlignment = SWT.BOTTOM;
+
+               Composite container = new Composite(comp, SWT.NONE);
+               layout = new GridLayout();
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               container.setLayout(layout);
+               container.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+               backButton = createButton(container, IDialogConstants.BACK_ID, "", false); //$NON-NLS-1$
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               backButton.setLayoutData(gd);
+               backButton.setToolTipText(Messages.EventDetailsDialog_previous);
+               backButton.setImage(SharedImages.getImage(SharedImages.DESC_PREV_EVENT));
+
+               copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
+               gd = new GridData();
+               copyButton.setLayoutData(gd);
+               copyButton.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_COPY));
+               copyButton.setToolTipText(Messages.EventDetailsDialog_copy);
+
+               nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
+               gd = new GridData();
+               nextButton.setLayoutData(gd);
+               nextButton.setToolTipText(Messages.EventDetailsDialog_next);
+               nextButton.setImage(SharedImages.getImage(SharedImages.DESC_NEXT_EVENT));
+
+               Button button = new Button(container, SWT.NONE);
+               button.setToolTipText(Messages.EventDetailsDialog_ShowFilterDialog);
+               button.setImage(SharedImages.getImage(SharedImages.DESC_FILTER));
+               gd = new GridData();
+               gd.horizontalAlignment = SWT.RIGHT;
+               button.setLayoutData(gd);
+               button.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               FilterDialog dialog = new FilterDialog(getShell(), memento);
+                               dialog.create();
+                               dialog.getShell().setText(Messages.EventDetailsDialog_FilterDialog);
+                               if (dialog.open() == Window.OK)
+                                       // update filters and currently displayed stack trace
+                                       stackFilterPatterns = getFilters();
+                               updateProperties();
+                       }
+               });
+
+               // set numColumns at the end, after all createButton() calls, which change this value
+               layout.numColumns = 2;
+       }
+
+       protected void createButtonsForButtonBar(Composite parent) {
+               // create OK button only by default
+               createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+       }
+
+       private void createDetailsSection(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginWidth = layout.marginHeight = 0;
+               layout.numColumns = 2;
+               container.setLayout(layout);
+               container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+               createTextSection(container);
+               createToolbarButtonBar(container);
+       }
+
+       private void createTextSection(Composite parent) {
+               Composite textContainer = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 3;
+               layout.marginHeight = layout.marginWidth = 0;
+               textContainer.setLayout(layout);
+               textContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+               Label label = new Label(textContainer, SWT.NONE);
+               label.setText(Messages.EventDetailsDialog_date);
+               dateLabel = new Label(textContainer, SWT.NULL);
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               gd.horizontalSpan = 2;
+               dateLabel.setLayoutData(gd);
+
+               label = new Label(textContainer, SWT.NONE);
+               label.setText(Messages.EventDetailsDialog_severity);
+               severityImageLabel = new Label(textContainer, SWT.NULL);
+               severityLabel = new Label(textContainer, SWT.NULL);
+               gd = new GridData(GridData.FILL_HORIZONTAL);
+               severityLabel.setLayoutData(gd);
+
+               label = new Label(textContainer, SWT.NONE);
+               label.setText(Messages.EventDetailsDialog_message);
+               gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+               label.setLayoutData(gd);
+               msgText = new Text(textContainer, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
+               msgText.setEditable(false);
+               gd = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING | GridData.GRAB_VERTICAL);
+               gd.horizontalSpan = 2;
+               gd.heightHint = 44;
+               gd.grabExcessVerticalSpace = true;
+               msgText.setLayoutData(gd);
+       }
+
+       private void createDetailedMessageSection(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout(2, false);
+               layout.marginHeight = 0;
+               layout.marginWidth = 6;
+               container.setLayout(layout);
+               GridData gd = new GridData(GridData.FILL_BOTH);
+               gd.heightHint = 100;
+               container.setLayoutData(gd);
+
+               detailsTextDescription = new Label(container, SWT.NONE);
+               detailsTextDescription.setText(Messages.EventDetailsDialog_detailedMessage);
+               gd = new GridData();
+               gd.verticalAlignment = SWT.BOTTOM;
+               gd.grabExcessHorizontalSpace = true;
+               detailsTextDescription.setLayoutData(gd);
+
+               /*final Composite messageDescriptorComposite = new Composite(container, SWT.BORDER);
+               //GridDataFactory.fillDefaults().grab(true, false).applyTo(messageDescriptorComposite);
+               TableWrapLayout layout2 = new TableWrapLayout();
+               layout2.bottomMargin = 0;
+               layout2.topMargin = 0;
+               layout2.leftMargin = 0;
+               layout2.rightMargin = 0;
+               messageDescriptorComposite.setLayout(layout2);
+               gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+               gd.grabExcessHorizontalSpace = true;
+               gd.horizontalSpan = 2;
+               messageDescriptorComposite.setLayoutData(gd);*/
+
+               detailsText = new Browser(container, SWT.BORDER);
+//             detailsText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+               gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
+               gd.grabExcessHorizontalSpace = true;
+               gd.grabExcessVerticalSpace = true;
+               gd.horizontalSpan = 2;
+               detailsText.setLayoutData(gd);
+               /*TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB);
+               detailsText.setLayoutData(data);*/
+               //TextColors.bindTo(resourceManager, detailsText);
+               /*detailsText.addHyperlinkListener(new IHyperlinkListener() {
+                   @Override
+                   public void linkActivated(HyperlinkEvent event) {
+                       String s = (String) event.data;
+                       //System.out.println("link activated: " + s);
+                       try {
+                           URI uri = new URI(s);
+                           String scheme = uri.getScheme();
+                           String schemeSpecificPart = uri.getSchemeSpecificPart();
+
+                           IMessageSchemeManager msm = org.simantics.message.internal.Activator.getDefault().getMessageSchemeManager();
+                           IMessageDataSchemeExtension[] exts = msm.getByScheme(scheme);
+
+                           for (IMessageDataSchemeExtension ext : exts) {
+                               Object data = ext.getSerializer().deserialize(schemeSpecificPart);
+                               ext.getHandler().perform(data);
+                               return;
+                           }
+                       } catch (URISyntaxException e) {
+                           // TODO Auto-generated catch block
+                           e.printStackTrace();
+                       } catch (ReferenceSerializationException e) {
+                           // TODO Auto-generated catch block
+                           e.printStackTrace();
+                       }
+                   }
+                   @Override
+                   public void linkEntered(HyperlinkEvent e) {
+                       //System.out.println("link entered: " + e.data);
+                   }
+                   @Override
+                   public void linkExited(HyperlinkEvent e) {
+                       //System.out.println("link exited: " + e.data);
+                   }
+               });*/
+               
+               /*messageDescriptorComposite.setContent(detailsText);
+               messageDescriptorComposite.setExpandVertical(true);
+               messageDescriptorComposite.setExpandHorizontal(true);
+               messageDescriptorComposite.addControlListener(new ControlAdapter() {
+                   public void controlResized(ControlEvent e) {
+                       Rectangle r = messageDescriptorComposite.getClientArea();
+                       //System.out.println("scrolled composite resized: " + e + ", client area: " + r);
+                       Point contentSize = detailsText.computeSize(r.width, SWT.DEFAULT);
+                       //System.out.println("computed content size: " + contentSize);
+                       messageDescriptorComposite.setMinSize(contentSize);
+                   }
+               });*/
+               detailsText.addLocationListener(new LocationListener() {
+                   @Override
+                   public void changed(LocationEvent event) {
+                       //System.out.println("changed: " + event);
+                   }
+                   @Override
+                   public void changing(LocationEvent event) {
+                       //System.out.println("changing: " + event);
+                       String location = event.location;
+                       if ("about:blank".equals(location)) {
+                           event.doit = true;
+                       } else {
+                           event.doit = false;
+                           //System.out.println("link activated: " + location);
+                           try {
+                               URI uri = new URI(location);
+                               String scheme = uri.getScheme();
+                               //String schemeSpecificPart = uri.getSchemeSpecificPart();
+
+                               IMessageSchemeManager msm = org.simantics.message.internal.Activator.getDefault().getMessageSchemeManager();
+                               IMessageDataSchemeExtension[] exts = msm.getByScheme(scheme);
+
+                               for (IMessageDataSchemeExtension ext : exts) {
+                                   Object data = ext.getSerializer().deserialize(uri);
+                                   try {
+                                       ext.getHandler().perform(data);
+                                       return;
+                                   } catch (MessageSchemeException e) {
+                                       ErrorLogger.defaultLogError(e);
+                                   }
+                               }
+                               return;
+                           } catch (URISyntaxException e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                           } catch (ReferenceSerializationException e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                           }
+                       }
+                   }
+               });
+       }
+
+       /*private void createStackSection(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout(2, false);
+               layout.marginHeight = 0;
+               layout.marginWidth = 6;
+               container.setLayout(layout);
+               GridData gd = new GridData(GridData.FILL_BOTH);
+               gd.heightHint = 100;
+               container.setLayoutData(gd);
+
+               Label label = new Label(container, SWT.NONE);
+               label.setText(Messages.EventDetailsDialog_exception);
+               gd = new GridData();
+               gd.verticalAlignment = SWT.BOTTOM;
+               label.setLayoutData(gd);
+               
+               stackTraceText = new Text(container, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+               gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+               gd.grabExcessHorizontalSpace = true;
+               gd.horizontalSpan = 2;
+               stackTraceText.setLayoutData(gd);
+               stackTraceText.setEditable(false);
+       }*/
+
+       private void createSessionSection(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight = 0;
+               layout.marginWidth = 6;
+               container.setLayout(layout);
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               gd.heightHint = 100;
+               container.setLayoutData(gd);
+
+               Label line = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
+               gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+               gd.widthHint = 1;
+               line.setLayoutData(gd);
+
+               Label label = new Label(container, SWT.NONE);
+               label.setText(Messages.EventDetailsDialog_session);
+               gd = new GridData(GridData.FILL_HORIZONTAL);
+               label.setLayoutData(gd);
+               sessionDataText = new Text(container, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+               gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+               gd.grabExcessHorizontalSpace = true;
+               sessionDataText.setLayoutData(gd);
+               sessionDataText.setEditable(false);
+       }
+
+       /**
+        * Loads filters from preferences.
+        * @return filters from preferences or empty array
+        * 
+        * @since 3.4
+        */
+       private String[] getFilters() {
+
+               Boolean filterEnabled = memento.getBoolean(FILTER_ENABLED);
+
+               String filtersString = memento.getString(FILTER_LIST);
+
+               if ((filterEnabled == null) || (filterEnabled.booleanValue() == false) || filtersString == null) {
+                       return new String[0];
+               }
+
+               StringTokenizer st = new StringTokenizer(filtersString, ";"); //$NON-NLS-1$
+               List<Object> filters = new ArrayList<Object>();
+               while (st.hasMoreElements()) {
+                       String filter = st.nextToken();
+                       filters.add(filter);
+               }
+
+               return (String[]) filters.toArray(new String[filters.size()]);
+       }
+
+       /**
+        * Filters stack trace.
+        * Every stack trace line is compared against all patterns.
+        * If line contains any of pattern strings, it's excluded from output.
+        * 
+        * @returns filtered stack trace
+        * @since 3.4
+        */
+       private String filterStack(String stack) {
+               if (stackFilterPatterns.length == 0) {
+                       return stack;
+               }
+
+               StringTokenizer st = new StringTokenizer(stack, "\n"); //$NON-NLS-1$
+               StringBuffer result = new StringBuffer();
+               while (st.hasMoreTokens()) {
+                       String stackElement = st.nextToken();
+
+                       boolean filtered = false;
+                       int i = 0;
+                       while ((!filtered) && (i < stackFilterPatterns.length)) {
+                               filtered = stackElement.indexOf(stackFilterPatterns[i]) >= 0;
+                               i++;
+                       }
+
+                       if (!filtered) {
+                               result.append(stackElement).append("\n"); //$NON-NLS-1$
+                       }
+               }
+
+               return result.toString();
+       }
+
+       //--------------- configuration handling --------------
+
+       /**
+        * Stores the current state in the dialog settings.
+        * @since 2.0
+        */
+       private void storeSettings() {
+               writeConfiguration();
+       }
+
+       /**
+        * Returns the dialog settings object used to share state
+        * between several event detail dialogs.
+        * 
+        * @return the dialog settings to be used
+        */
+       private IDialogSettings getDialogSettings() {
+               IDialogSettings settings = Activator.getDefault().getDialogSettings();
+               IDialogSettings dialogSettings = settings.getSection(getClass().getName());
+               if (dialogSettings == null)
+                       dialogSettings = settings.addNewSection(getClass().getName());
+               return dialogSettings;
+       }
+
+       /**
+        * Initializes itself from the dialog settings with the same state
+        * as at the previous invocation.
+        */
+       private void readConfiguration() {
+               IDialogSettings s = getDialogSettings();
+               try { 
+                       int x = s.getInt("x"); //$NON-NLS-1$
+                       int y = s.getInt("y"); //$NON-NLS-1$
+                       dialogLocation = new Point(x, y);
+
+                       x = s.getInt("width"); //$NON-NLS-1$
+                       y = s.getInt("height"); //$NON-NLS-1$
+                       dialogSize = new Point(x, y);
+
+                       sashWeights = new int[3];
+                       sashWeights[0] = s.getInt("sashWidth0"); //$NON-NLS-1$
+                       sashWeights[1] = s.getInt("sashWidth1"); //$NON-NLS-1$
+                       sashWeights[2] = s.getInt("sashWidth2"); //$NON-NLS-1$
+
+               } catch (NumberFormatException e) {
+                       dialogLocation = null;
+                       dialogSize = null;
+                       sashWeights = null;
+               }
+       }
+
+       private void writeConfiguration() {
+               IDialogSettings s = getDialogSettings();
+               Point location = getShell().getLocation();
+               s.put("x", location.x); //$NON-NLS-1$
+               s.put("y", location.y); //$NON-NLS-1$
+
+               Point size = getShell().getSize();
+               s.put("width", size.x); //$NON-NLS-1$
+               s.put("height", size.y); //$NON-NLS-1$
+
+               sashWeights = getSashForm().getWeights();
+               s.put("sashWidth0", sashWeights[0]); //$NON-NLS-1$
+               s.put("sashWidth1", sashWeights[1]); //$NON-NLS-1$
+               //s.put("sashWidth2", sashWeights[2]); //$NON-NLS-1$
+       }
+
+       /**
+        * Utility method to get all top level elements of the Log View
+        * @return top level elements of the Log View
+        */
+       private AbstractEntry[] getElements() {
+               return (AbstractEntry[]) ((ITreeContentProvider) provider.getContentProvider()).getElements(null);
+       }
+}