1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.debug.core.logview;
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.io.StringWriter;
16 import java.text.Collator;
17 import java.text.ParseException;
18 import java.text.SimpleDateFormat;
19 import java.util.Arrays;
20 import java.util.Comparator;
21 import java.util.Date;
23 import net.sourceforge.phpdt.internal.debug.core.PHPDegugCorePluginImages;
24 import net.sourceforge.phpdt.internal.debug.core.PHPDebugCorePlugin;
26 import org.eclipse.core.runtime.IAdaptable;
27 import org.eclipse.jface.dialogs.Dialog;
28 import org.eclipse.jface.dialogs.IDialogConstants;
29 import org.eclipse.jface.dialogs.IDialogSettings;
30 import org.eclipse.jface.viewers.ISelection;
31 import org.eclipse.jface.viewers.ISelectionProvider;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.jface.viewers.StructuredSelection;
34 import org.eclipse.jface.viewers.TableTreeViewer;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.custom.SashForm;
37 import org.eclipse.swt.dnd.Clipboard;
38 import org.eclipse.swt.dnd.TextTransfer;
39 import org.eclipse.swt.dnd.Transfer;
40 import org.eclipse.swt.graphics.Image;
41 import org.eclipse.swt.graphics.Point;
42 import org.eclipse.swt.layout.GridData;
43 import org.eclipse.swt.layout.GridLayout;
44 import org.eclipse.swt.widgets.Button;
45 import org.eclipse.swt.widgets.Composite;
46 import org.eclipse.swt.widgets.Control;
47 import org.eclipse.swt.widgets.Label;
48 import org.eclipse.swt.widgets.Shell;
49 import org.eclipse.swt.widgets.Text;
50 import org.eclipse.ui.ISharedImages;
51 import org.eclipse.ui.PlatformUI;
53 public class EventDetailsDialog extends Dialog {
54 private LogEntry entry, parentEntry;
55 private LogViewLabelProvider labelProvider;
56 private static int COPY_ID = 22;
57 private TableTreeViewer provider;
58 private int elementNum, totalElementCount;
59 private LogEntry[] entryChildren;
60 private int childIndex = 0;
61 private boolean isOpen;
63 private Label dateLabel;
64 private Label severityImageLabel;
65 private Label severityLabel;
67 private Text stackTraceText;
68 private Text sessionDataText;
69 private Clipboard clipboard;
70 private Button copyButton;
71 private Button backButton;
72 private Button nextButton;
73 private Image imgNextEnabled;
74 private Image imgPrevEnabled;
75 private Image imgCopyEnabled;
76 private SashForm sashForm;
79 private static int ASCENDING = 1;
80 private Comparator comparator = null;
81 private Collator collator;
83 // location configuration
84 private IDialogSettings dialogSettings;
85 private Point dialogLocation;
86 private Point dialogSize;
87 private int[] sashWeights;
89 // externalize strings
90 private String EVENT_NO_STACK = "EventDetailsDialog.noStack"; //$NON-NLS-1$
91 private String EVENT_PREVIOUS = "EventDetailsDialog.previous"; //$NON-NLS-1$
92 private String EVENT_NEXT = "EventDetailsDialog.next"; //$NON-NLS-1$
93 private String EVENT_COPY = "EventDetailsDialog.copy"; //$NON-NLS-1$
97 * shell in which dialog is displayed
99 protected EventDetailsDialog(Shell parentShell, IAdaptable selection, ISelectionProvider provider) {
101 labelProvider = new LogViewLabelProvider();
102 this.provider = (TableTreeViewer) provider;
103 this.entry = (LogEntry)selection;
104 setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
105 clipboard = new Clipboard(parentShell.getDisplay());
108 collator = Collator.getInstance();
112 private void initialize() {
113 elementNum = getParentElementNum();
114 totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
115 parentEntry = (LogEntry) entry.getParent(entry);
117 setEntryChildren(parentEntry);
122 private void resetChildIndex(){
123 for (int i = 0; i<entryChildren.length; i++){
124 if (entryChildren[i].getMessage().equals(entry.getMessage())
125 && entryChildren[i].getDate().equals(entry.getDate())
126 && entryChildren[i].getPluginId().equals(entry.getPluginId())
127 && entryChildren[i].getSeverity() == entry.getSeverity()
128 && entryChildren[i].getSeverityText().equals(entry.getSeverityText())){
135 private void createImages(){
137 PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY).createImage(
139 //imgNextDisabled. = PHPDegugCorePluginImages.DESC_NEXT_EVENT_DISABLED.createImage(true);
140 //imgPrevDisabled = PHPDegugCorePluginImages.DESC_PREV_EVENT_DISABLED.createImage(true);
141 imgPrevEnabled = PHPDegugCorePluginImages.DESC_PREV_EVENT.createImage(true);
142 imgNextEnabled = PHPDegugCorePluginImages.DESC_NEXT_EVENT.createImage(true);
145 private boolean isChild(LogEntry entry) {
146 return entry.getParent(entry) != null;
149 public boolean isOpen(){
155 if (sashWeights == null){
156 int width = getSashForm().getClientArea().width;
161 sashWeights = new int[]{width, getSashForm().getClientArea().width-width};
163 getSashForm().setWeights(sashWeights);
167 public boolean close() {
170 imgCopyEnabled.dispose();
171 imgNextEnabled.dispose();
172 imgPrevEnabled.dispose();
173 return super.close();
176 public void create() {
180 if (dialogLocation != null)
181 getShell().setLocation(dialogLocation);
184 if (dialogSize != null)
185 getShell().setSize(dialogSize);
187 getShell().setSize(500,550);
190 applyDialogFont(buttonBar);
191 getButton(IDialogConstants.OK_ID).setFocus();
194 protected void buttonPressed(int buttonId) {
195 if (IDialogConstants.OK_ID == buttonId)
197 else if (IDialogConstants.CANCEL_ID == buttonId)
199 else if (IDialogConstants.BACK_ID == buttonId)
201 else if (IDialogConstants.NEXT_ID == buttonId)
203 else if (COPY_ID == buttonId)
207 protected void backPressed() {
208 if (isChild(entry)) {
209 if (childIndex > 0) {
211 entry = entryChildren[childIndex];
215 if (elementNum - 1 >= 0)
217 entry = (LogEntry) provider.getElementAt(elementNum);
219 setEntrySelectionInTable();
222 protected void nextPressed() {
223 if (isChild(entry) && childIndex < entryChildren.length-1) {
225 entry = entryChildren[childIndex];
226 } else if (elementNum + 1 < totalElementCount){
228 entry = (LogEntry) provider.getElementAt(elementNum);
229 } else { // at end of list but can branch into child elements - bug 58083
230 setEntryChildren(entry);
231 entry = entryChildren[0];
233 setEntrySelectionInTable();
236 protected void copyPressed() {
237 StringWriter writer = new StringWriter();
238 PrintWriter pwriter = new PrintWriter(writer);
240 entry.write(pwriter);
242 String textVersion = writer.toString();
246 } catch (IOException e) {
248 // set the clipboard contents
249 clipboard.setContents(new Object[] { textVersion }, new Transfer[] { TextTransfer.getInstance()});
252 public void setComparator(Comparator comparator){
253 this.comparator = comparator;
256 private void setComparator(byte sortType, final int sortOrder){
257 if (sortType == LogView.DATE){
258 comparator = new Comparator(){
259 public int compare(Object e1, Object e2) {
261 SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
262 Date date1 = formatter.parse(((LogEntry)e1).getDate());
263 Date date2 = formatter.parse(((LogEntry)e2).getDate());
264 if (sortOrder == ASCENDING)
265 return date1.before(date2) ? -1 : 1;
266 return date1.after(date2) ? -1 : 1;
267 } catch (ParseException e) {
272 } else if (sortType == LogView.PLUGIN){
273 comparator = new Comparator(){
274 public int compare(Object e1, Object e2) {
275 LogEntry entry1 = (LogEntry)e1;
276 LogEntry entry2 = (LogEntry)e2;
277 return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * sortOrder;
281 comparator = new Comparator(){
282 public int compare(Object e1, Object e2) {
283 LogEntry entry1 = (LogEntry)e1;
284 LogEntry entry2 = (LogEntry)e2;
285 return collator.compare(entry1.getMessage(), entry2.getMessage()) * sortOrder;
291 public void resetSelection(IAdaptable selectedEntry, byte sortType, int sortOrder){
292 setComparator(sortType, sortOrder);
293 resetSelection(selectedEntry);
296 public void resetSelection(IAdaptable selectedEntry){
297 if (entry.equals(selectedEntry) &&
298 elementNum == getParentElementNum()){
302 entry = (LogEntry)selectedEntry;
307 public void resetButtons(){
308 backButton.setEnabled(false);
309 nextButton.setEnabled(false);
312 private void setEntrySelectionInTable(){
313 ISelection selection = new StructuredSelection(entry);
314 provider.setSelection(selection);
317 public void updateProperties() {
319 parentEntry = (LogEntry) entry.getParent(entry);
320 setEntryChildren(parentEntry);
325 totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
326 dateLabel.setText(entry.getDate());
327 severityImageLabel.setImage(labelProvider.getColumnImage(entry, 1));
328 severityLabel.setText(entry.getSeverityText());
329 msgText.setText(entry.getMessage());
330 String stack = entry.getStack();
332 stackTraceText.setText(stack);
334 stackTraceText.setText(PHPDebugCorePlugin.getResourceString(EVENT_NO_STACK));
336 LogSession session = entry.getSession();
337 if (session != null && session.getSessionData() != null)
338 sessionDataText.setText(session.getSessionData());
343 private void updateButtons(){
344 boolean isAtEnd = elementNum == totalElementCount - 1;
346 backButton.setEnabled(true);
347 boolean isLastChild = childIndex == entryChildren.length-1;
348 nextButton.setEnabled(!isLastChild || !isAtEnd || entry.hasChildren());
350 backButton.setEnabled(elementNum != 0);
351 nextButton.setEnabled(!isAtEnd || entry.hasChildren());
355 private void setEntryChildren(LogEntry parent){
356 Object[] children = parent.getChildren(parent);
357 if (comparator != null)
358 Arrays.sort(children, comparator);
359 entryChildren = new LogEntry[children.length];
361 System.arraycopy(children,0,entryChildren,0,children.length);
364 private int getParentElementNum(){
365 LogEntry itemEntry = (LogEntry)((IStructuredSelection)provider.getSelection()).getFirstElement();
366 itemEntry = getRootEntry(itemEntry);
368 for (int i = 0; i<provider.getTableTree().getItemCount(); i++){
370 LogEntry littleEntry = (LogEntry)provider.getElementAt(i);
371 if (itemEntry.equals(littleEntry)){
374 } catch (Exception e){
380 private LogEntry getRootEntry(LogEntry entry){
383 return getRootEntry((LogEntry)entry.getParent(entry));
385 public SashForm getSashForm(){
388 private int getVisibleChildrenCount(){
389 Object[] elements = provider.getVisibleExpandedElements();
390 LogEntry[] expandedElements = new LogEntry[elements.length];
391 System.arraycopy(elements, 0, expandedElements, 0, elements.length);
393 for (int i = 0; i<expandedElements.length; i++){
394 count += expandedElements[i].getChildren(expandedElements[i]).length;
399 protected Control createDialogArea(Composite parent) {
400 Composite container = new Composite(parent, SWT.NONE);
401 GridLayout layout = new GridLayout();
402 layout.numColumns = 1;
403 container.setLayout(layout);
404 GridData gd = new GridData(GridData.FILL_BOTH);
405 container.setLayoutData(gd);
407 createDetailsSection(container);
408 createSashForm(container);
409 createStackSection(getSashForm());
410 createSessionSection(getSashForm());
413 Dialog.applyDialogFont(container);
417 private void createSashForm(Composite parent){
418 sashForm = new SashForm(parent, SWT.VERTICAL);
419 GridLayout layout = new GridLayout();
420 layout.marginHeight = layout.marginWidth = 0;
421 sashForm.setLayout(layout);
422 sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
425 private void createToolbarButtonBar(Composite parent) {
426 Composite comp = new Composite(parent, SWT.NONE);
427 GridLayout layout = new GridLayout();
428 layout.marginWidth = layout.marginHeight = 0;
429 layout.numColumns = 1;
430 comp.setLayout(layout);
431 comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
433 Composite container = new Composite(comp, SWT.NONE);
434 layout = new GridLayout();
435 layout.marginWidth = 0;
436 layout.marginHeight = 10;
437 layout.numColumns = 1;
438 container.setLayout(layout);
439 container.setLayoutData(new GridData(GridData.FILL_BOTH));
441 backButton = createButton(container, IDialogConstants.BACK_ID, "", false); //$NON-NLS-1$
442 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
443 gd.horizontalSpan = 3;
445 backButton.setLayoutData(gd);
446 backButton.setToolTipText(PHPDebugCorePlugin.getResourceString(EVENT_PREVIOUS));
447 backButton.setImage(imgPrevEnabled);
449 nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
451 gd.horizontalSpan = 3;
453 nextButton.setLayoutData(gd);
454 nextButton.setToolTipText(PHPDebugCorePlugin.getResourceString(EVENT_NEXT));
455 nextButton.setImage(imgNextEnabled);
457 copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
459 gd.horizontalSpan = 3;
461 copyButton.setLayoutData(gd);
462 copyButton.setImage(imgCopyEnabled);
463 copyButton.setToolTipText(PHPDebugCorePlugin.getResourceString(EVENT_COPY));
466 protected void createButtonsForButtonBar(Composite parent) {
467 // create OK button only by default
468 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
471 private void createDetailsSection(Composite parent) {
472 Composite container = new Composite(parent, SWT.NONE);
473 GridLayout layout = new GridLayout();
474 layout.numColumns = 2;
475 container.setLayout(layout);
476 container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
478 createTextSection(container);
479 createToolbarButtonBar(container);
482 private void createTextSection(Composite parent) {
483 Composite textContainer = new Composite(parent, SWT.NONE);
484 GridLayout layout = new GridLayout();
485 layout.numColumns = 3;
486 layout.marginHeight = layout.marginWidth = 0;
487 textContainer.setLayout(layout);
488 textContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
490 Label label = new Label(textContainer, SWT.NONE);
491 label.setText(PHPDebugCorePlugin.getResourceString("EventDetailsDialog.date")); //$NON-NLS-1$
492 dateLabel = new Label(textContainer, SWT.NULL);
493 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
494 gd.horizontalSpan = 2;
495 dateLabel.setLayoutData(gd);
497 label = new Label(textContainer, SWT.NONE);
498 label.setText(PHPDebugCorePlugin.getResourceString("EventDetailsDialog.severity")); //$NON-NLS-1$
499 severityImageLabel = new Label(textContainer, SWT.NULL);
500 severityLabel = new Label(textContainer, SWT.NULL);
501 gd = new GridData(GridData.FILL_HORIZONTAL);
502 severityLabel.setLayoutData(gd);
504 label = new Label(textContainer, SWT.NONE);
505 label.setText(PHPDebugCorePlugin.getResourceString("EventDetailsDialog.message")); //$NON-NLS-1$
506 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
507 label.setLayoutData(gd);
508 msgText = new Text(textContainer, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
509 msgText.setEditable(false);
510 gd = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING | GridData.GRAB_VERTICAL);
511 gd.horizontalSpan = 2;
513 gd.grabExcessVerticalSpace = true;
514 msgText.setLayoutData(gd);
517 private void createStackSection(Composite parent) {
518 Composite container = new Composite(parent, SWT.NONE);
519 GridLayout layout = new GridLayout();
520 layout.marginHeight = 0;
521 layout.marginWidth = 6;
522 container.setLayout(layout);
523 GridData gd = new GridData(GridData.FILL_BOTH);
525 container.setLayoutData(gd);
527 Label label = new Label(container, SWT.NULL);
528 label.setText(PHPDebugCorePlugin.getResourceString("EventDetailsDialog.exception")); //$NON-NLS-1$
529 gd = new GridData(GridData.FILL_HORIZONTAL);
530 gd.horizontalSpan = 3;
531 label.setLayoutData(gd);
533 stackTraceText = new Text(container, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
534 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
535 gd.grabExcessHorizontalSpace = true;
536 stackTraceText.setLayoutData(gd);
537 stackTraceText.setEditable(false);
540 private void createSessionSection(Composite parent) {
541 Composite container = new Composite(parent, SWT.NONE);
542 GridLayout layout = new GridLayout();
543 layout.marginHeight = 0;
544 layout.marginWidth = 6;
545 container.setLayout(layout);
546 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
548 container.setLayoutData(gd);
550 Label line = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
551 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
553 line.setLayoutData(gd);
555 Label label = new Label(container, SWT.NONE);
556 label.setText(PHPDebugCorePlugin.getResourceString("EventDetailsDialog.session")); //$NON-NLS-1$
557 gd = new GridData(GridData.FILL_HORIZONTAL);
558 label.setLayoutData(gd);
559 sessionDataText = new Text(container, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL );
560 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
561 gd.grabExcessHorizontalSpace = true;
562 sessionDataText.setLayoutData(gd);
563 sessionDataText.setEditable(false);
566 //--------------- configuration handling --------------
569 * Stores the current state in the dialog settings.
572 private void storeSettings() {
573 writeConfiguration();
576 * Returns the dialog settings object used to share state
577 * between several event detail dialogs.
579 * @return the dialog settings to be used
581 private IDialogSettings getDialogSettings() {
582 IDialogSettings settings= PHPDebugCorePlugin.getDefault().getDialogSettings();
583 dialogSettings= settings.getSection(getClass().getName());
584 if (dialogSettings == null)
585 dialogSettings= settings.addNewSection(getClass().getName());
586 return dialogSettings;
590 * Initializes itself from the dialog settings with the same state
591 * as at the previous invocation.
593 private void readConfiguration() {
594 IDialogSettings s= getDialogSettings();
596 int x= s.getInt("x"); //$NON-NLS-1$
597 int y= s.getInt("y"); //$NON-NLS-1$
598 dialogLocation= new Point(x, y);
600 x = s.getInt("width"); //$NON-NLS-1$
601 y = s.getInt("height"); //$NON-NLS-1$
602 dialogSize = new Point(x,y);
604 sashWeights = new int[2];
605 sashWeights[0] = s.getInt("sashWidth1"); //$NON-NLS-1$
606 sashWeights[1] = s.getInt("sashWidth2"); //$NON-NLS-1$
608 } catch (NumberFormatException e) {
609 dialogLocation= null;
615 private void writeConfiguration(){
616 IDialogSettings s = getDialogSettings();
617 Point location = getShell().getLocation();
618 s.put("x", location.x); //$NON-NLS-1$
619 s.put("y", location.y); //$NON-NLS-1$
621 Point size = getShell().getSize();
622 s.put("width", size.x); //$NON-NLS-1$
623 s.put("height", size.y); //$NON-NLS-1$
625 sashWeights = getSashForm().getWeights();
626 s.put("sashWidth1", sashWeights[0]); //$NON-NLS-1$
627 s.put("sashWidth2", sashWeights[1]); //$NON-NLS-1$