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.phpeclipse.xdebug.ui.views.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.phpeclipse.xdebug.core.XDebugCorePlugin;
24 import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
25 import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPluginImages;
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.viewers.ISelection;
32 import org.eclipse.jface.viewers.ISelectionProvider;
33 import org.eclipse.jface.viewers.IStructuredSelection;
34 import org.eclipse.jface.viewers.StructuredSelection;
35 import org.eclipse.jface.viewers.TableTreeViewer;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.custom.SashForm;
38 import org.eclipse.swt.dnd.Clipboard;
39 import org.eclipse.swt.dnd.TextTransfer;
40 import org.eclipse.swt.dnd.Transfer;
41 import org.eclipse.swt.graphics.Image;
42 import org.eclipse.swt.graphics.Point;
43 import org.eclipse.swt.layout.GridData;
44 import org.eclipse.swt.layout.GridLayout;
45 import org.eclipse.swt.widgets.Button;
46 import org.eclipse.swt.widgets.Composite;
47 import org.eclipse.swt.widgets.Control;
48 import org.eclipse.swt.widgets.Label;
49 import org.eclipse.swt.widgets.Shell;
50 import org.eclipse.swt.widgets.Text;
51 import org.eclipse.ui.ISharedImages;
52 import org.eclipse.ui.PlatformUI;
54 public class EventDetailsDialog extends Dialog {
55 private LogEntry entry, parentEntry;
56 private LogViewLabelProvider labelProvider;
57 private static int COPY_ID = 22;
58 private TableTreeViewer provider;
59 private int elementNum, totalElementCount;
60 private LogEntry[] entryChildren;
61 private int childIndex = 0;
62 private boolean isOpen;
64 private Label dateLabel;
65 private Label severityImageLabel;
66 private Label severityLabel;
68 private Text stackTraceText;
69 private Text sessionDataText;
70 private Clipboard clipboard;
71 private Button copyButton;
72 private Button backButton;
73 private Button nextButton;
74 private Image imgNextEnabled;
75 private Image imgPrevEnabled;
76 private Image imgCopyEnabled;
77 private SashForm sashForm;
80 private static int ASCENDING = 1;
81 private Comparator comparator = null;
82 private Collator collator;
84 // location configuration
85 private IDialogSettings dialogSettings;
86 private Point dialogLocation;
87 private Point dialogSize;
88 private int[] sashWeights;
90 // externalize strings
91 private String EVENT_NO_STACK = "EventDetailsDialog.noStack"; //$NON-NLS-1$
92 private String EVENT_PREVIOUS = "EventDetailsDialog.previous"; //$NON-NLS-1$
93 private String EVENT_NEXT = "EventDetailsDialog.next"; //$NON-NLS-1$
94 private String EVENT_COPY = "EventDetailsDialog.copy"; //$NON-NLS-1$
98 * shell in which dialog is displayed
100 protected EventDetailsDialog(Shell parentShell, IAdaptable selection, ISelectionProvider provider) {
102 labelProvider = new LogViewLabelProvider();
103 this.provider = (TableTreeViewer) provider;
104 this.entry = (LogEntry)selection;
105 setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
106 clipboard = new Clipboard(parentShell.getDisplay());
109 collator = Collator.getInstance();
113 private void initialize() {
114 elementNum = getParentElementNum();
115 totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
116 parentEntry = (LogEntry) entry.getParent(entry);
118 setEntryChildren(parentEntry);
123 private void resetChildIndex(){
124 for (int i = 0; i<entryChildren.length; i++){
125 if (entryChildren[i].getMessage().equals(entry.getMessage())
126 && entryChildren[i].getDate().equals(entry.getDate())
127 && entryChildren[i].getPluginId().equals(entry.getPluginId())
128 && entryChildren[i].getSeverity() == entry.getSeverity()
129 && entryChildren[i].getSeverityText().equals(entry.getSeverityText())){
136 private void createImages(){
138 PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY).createImage(
140 //imgNextDisabled. = PHPDegugCorePluginImages.DESC_NEXT_EVENT_DISABLED.createImage(true);
141 //imgPrevDisabled = PHPDegugCorePluginImages.DESC_PREV_EVENT_DISABLED.createImage(true);
142 imgPrevEnabled = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_PREV_EVENT);
143 imgNextEnabled = XDebugUIPluginImages.get(XDebugUIPluginImages.DESC_NEXT_EVENT);
146 private boolean isChild(LogEntry entry) {
147 return entry.getParent(entry) != null;
150 public boolean isOpen(){
156 if (sashWeights == null){
157 int width = getSashForm().getClientArea().width;
162 sashWeights = new int[]{width, getSashForm().getClientArea().width-width};
164 getSashForm().setWeights(sashWeights);
168 public boolean close() {
171 imgCopyEnabled.dispose();
172 imgNextEnabled.dispose();
173 imgPrevEnabled.dispose();
174 return super.close();
177 public void create() {
181 if (dialogLocation != null)
182 getShell().setLocation(dialogLocation);
185 if (dialogSize != null)
186 getShell().setSize(dialogSize);
188 getShell().setSize(500,550);
191 applyDialogFont(buttonBar);
192 getButton(IDialogConstants.OK_ID).setFocus();
195 protected void buttonPressed(int buttonId) {
196 if (IDialogConstants.OK_ID == buttonId)
198 else if (IDialogConstants.CANCEL_ID == buttonId)
200 else if (IDialogConstants.BACK_ID == buttonId)
202 else if (IDialogConstants.NEXT_ID == buttonId)
204 else if (COPY_ID == buttonId)
208 protected void backPressed() {
209 if (isChild(entry)) {
210 if (childIndex > 0) {
212 entry = entryChildren[childIndex];
216 if (elementNum - 1 >= 0)
218 entry = (LogEntry) provider.getElementAt(elementNum);
220 setEntrySelectionInTable();
223 protected void nextPressed() {
224 if (isChild(entry) && childIndex < entryChildren.length-1) {
226 entry = entryChildren[childIndex];
227 } else if (elementNum + 1 < totalElementCount){
229 entry = (LogEntry) provider.getElementAt(elementNum);
230 } else { // at end of list but can branch into child elements - bug 58083
231 setEntryChildren(entry);
232 entry = entryChildren[0];
234 setEntrySelectionInTable();
237 protected void copyPressed() {
238 StringWriter writer = new StringWriter();
239 PrintWriter pwriter = new PrintWriter(writer);
241 entry.write(pwriter);
243 String textVersion = writer.toString();
247 } catch (IOException e) {
249 // set the clipboard contents
250 clipboard.setContents(new Object[] { textVersion }, new Transfer[] { TextTransfer.getInstance()});
253 public void setComparator(Comparator comparator){
254 this.comparator = comparator;
257 private void setComparator(byte sortType, final int sortOrder){
258 if (sortType == LogView.DATE){
259 comparator = new Comparator(){
260 public int compare(Object e1, Object e2) {
262 SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
263 Date date1 = formatter.parse(((LogEntry)e1).getDate());
264 Date date2 = formatter.parse(((LogEntry)e2).getDate());
265 if (sortOrder == ASCENDING)
266 return date1.before(date2) ? -1 : 1;
267 return date1.after(date2) ? -1 : 1;
268 } catch (ParseException e) {
273 } else if (sortType == LogView.PLUGIN){
274 comparator = new Comparator(){
275 public int compare(Object e1, Object e2) {
276 LogEntry entry1 = (LogEntry)e1;
277 LogEntry entry2 = (LogEntry)e2;
278 return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * sortOrder;
282 comparator = new Comparator(){
283 public int compare(Object e1, Object e2) {
284 LogEntry entry1 = (LogEntry)e1;
285 LogEntry entry2 = (LogEntry)e2;
286 return collator.compare(entry1.getMessage(), entry2.getMessage()) * sortOrder;
292 public void resetSelection(IAdaptable selectedEntry, byte sortType, int sortOrder){
293 setComparator(sortType, sortOrder);
294 resetSelection(selectedEntry);
297 public void resetSelection(IAdaptable selectedEntry){
298 if (entry.equals(selectedEntry) &&
299 elementNum == getParentElementNum()){
303 entry = (LogEntry)selectedEntry;
308 public void resetButtons(){
309 backButton.setEnabled(false);
310 nextButton.setEnabled(false);
313 private void setEntrySelectionInTable(){
314 ISelection selection = new StructuredSelection(entry);
315 provider.setSelection(selection);
318 public void updateProperties() {
320 parentEntry = (LogEntry) entry.getParent(entry);
321 setEntryChildren(parentEntry);
326 totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
327 dateLabel.setText(entry.getDate());
328 severityImageLabel.setImage(labelProvider.getColumnImage(entry, 1));
329 severityLabel.setText(entry.getSeverityText());
330 msgText.setText(entry.getMessage());
331 String stack = entry.getStack();
333 stackTraceText.setText(stack);
335 stackTraceText.setText(XDebugUIPlugin.getString(EVENT_NO_STACK));
337 LogSession session = entry.getSession();
338 if (session != null && session.getSessionData() != null)
339 sessionDataText.setText(session.getSessionData());
344 private void updateButtons(){
345 boolean isAtEnd = elementNum == totalElementCount - 1;
347 backButton.setEnabled(true);
348 boolean isLastChild = childIndex == entryChildren.length-1;
349 nextButton.setEnabled(!isLastChild || !isAtEnd || entry.hasChildren());
351 backButton.setEnabled(elementNum != 0);
352 nextButton.setEnabled(!isAtEnd || entry.hasChildren());
356 private void setEntryChildren(LogEntry parent){
357 Object[] children = parent.getChildren(parent);
358 if (comparator != null)
359 Arrays.sort(children, comparator);
360 entryChildren = new LogEntry[children.length];
362 System.arraycopy(children,0,entryChildren,0,children.length);
365 private int getParentElementNum(){
366 LogEntry itemEntry = (LogEntry)((IStructuredSelection)provider.getSelection()).getFirstElement();
367 itemEntry = getRootEntry(itemEntry);
369 for (int i = 0; i<provider.getTableTree().getItemCount(); i++){
371 LogEntry littleEntry = (LogEntry)provider.getElementAt(i);
372 if (itemEntry.equals(littleEntry)){
375 } catch (Exception e){
381 private LogEntry getRootEntry(LogEntry entry){
384 return getRootEntry((LogEntry)entry.getParent(entry));
386 public SashForm getSashForm(){
389 private int getVisibleChildrenCount(){
390 Object[] elements = provider.getVisibleExpandedElements();
391 LogEntry[] expandedElements = new LogEntry[elements.length];
392 System.arraycopy(elements, 0, expandedElements, 0, elements.length);
394 for (int i = 0; i<expandedElements.length; i++){
395 count += expandedElements[i].getChildren(expandedElements[i]).length;
400 protected Control createDialogArea(Composite parent) {
401 Composite container = new Composite(parent, SWT.NONE);
402 GridLayout layout = new GridLayout();
403 layout.numColumns = 1;
404 container.setLayout(layout);
405 GridData gd = new GridData(GridData.FILL_BOTH);
406 container.setLayoutData(gd);
408 createDetailsSection(container);
409 createSashForm(container);
410 createStackSection(getSashForm());
411 createSessionSection(getSashForm());
414 Dialog.applyDialogFont(container);
418 private void createSashForm(Composite parent){
419 sashForm = new SashForm(parent, SWT.VERTICAL);
420 GridLayout layout = new GridLayout();
421 layout.marginHeight = layout.marginWidth = 0;
422 sashForm.setLayout(layout);
423 sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
426 private void createToolbarButtonBar(Composite parent) {
427 Composite comp = new Composite(parent, SWT.NONE);
428 GridLayout layout = new GridLayout();
429 layout.marginWidth = layout.marginHeight = 0;
430 layout.numColumns = 1;
431 comp.setLayout(layout);
432 comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
434 Composite container = new Composite(comp, SWT.NONE);
435 layout = new GridLayout();
436 layout.marginWidth = 0;
437 layout.marginHeight = 10;
438 layout.numColumns = 1;
439 container.setLayout(layout);
440 container.setLayoutData(new GridData(GridData.FILL_BOTH));
442 backButton = createButton(container, IDialogConstants.BACK_ID, "", false); //$NON-NLS-1$
443 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
444 gd.horizontalSpan = 3;
446 backButton.setLayoutData(gd);
447 backButton.setToolTipText(XDebugUIPlugin.getString(EVENT_PREVIOUS));
448 backButton.setImage(imgPrevEnabled);
450 nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
452 gd.horizontalSpan = 3;
454 nextButton.setLayoutData(gd);
455 nextButton.setToolTipText(XDebugUIPlugin.getString(EVENT_NEXT));
456 nextButton.setImage(imgNextEnabled);
458 copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
460 gd.horizontalSpan = 3;
462 copyButton.setLayoutData(gd);
463 copyButton.setImage(imgCopyEnabled);
464 copyButton.setToolTipText(XDebugUIPlugin.getString(EVENT_COPY));
467 protected void createButtonsForButtonBar(Composite parent) {
468 // create OK button only by default
469 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
472 private void createDetailsSection(Composite parent) {
473 Composite container = new Composite(parent, SWT.NONE);
474 GridLayout layout = new GridLayout();
475 layout.numColumns = 2;
476 container.setLayout(layout);
477 container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
479 createTextSection(container);
480 createToolbarButtonBar(container);
483 private void createTextSection(Composite parent) {
484 Composite textContainer = new Composite(parent, SWT.NONE);
485 GridLayout layout = new GridLayout();
486 layout.numColumns = 3;
487 layout.marginHeight = layout.marginWidth = 0;
488 textContainer.setLayout(layout);
489 textContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
491 Label label = new Label(textContainer, SWT.NONE);
492 label.setText(XDebugUIPlugin.getString("EventDetailsDialog.date")); //$NON-NLS-1$
493 dateLabel = new Label(textContainer, SWT.NULL);
494 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
495 gd.horizontalSpan = 2;
496 dateLabel.setLayoutData(gd);
498 label = new Label(textContainer, SWT.NONE);
499 label.setText(XDebugUIPlugin.getString("EventDetailsDialog.severity")); //$NON-NLS-1$
500 severityImageLabel = new Label(textContainer, SWT.NULL);
501 severityLabel = new Label(textContainer, SWT.NULL);
502 gd = new GridData(GridData.FILL_HORIZONTAL);
503 severityLabel.setLayoutData(gd);
505 label = new Label(textContainer, SWT.NONE);
506 label.setText(XDebugUIPlugin.getString("EventDetailsDialog.message")); //$NON-NLS-1$
507 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
508 label.setLayoutData(gd);
509 msgText = new Text(textContainer, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
510 msgText.setEditable(false);
511 gd = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING | GridData.GRAB_VERTICAL);
512 gd.horizontalSpan = 2;
514 gd.grabExcessVerticalSpace = true;
515 msgText.setLayoutData(gd);
518 private void createStackSection(Composite parent) {
519 Composite container = new Composite(parent, SWT.NONE);
520 GridLayout layout = new GridLayout();
521 layout.marginHeight = 0;
522 layout.marginWidth = 6;
523 container.setLayout(layout);
524 GridData gd = new GridData(GridData.FILL_BOTH);
526 container.setLayoutData(gd);
528 Label label = new Label(container, SWT.NULL);
529 label.setText(XDebugUIPlugin.getString("EventDetailsDialog.exception")); //$NON-NLS-1$
530 gd = new GridData(GridData.FILL_HORIZONTAL);
531 gd.horizontalSpan = 3;
532 label.setLayoutData(gd);
534 stackTraceText = new Text(container, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
535 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
536 gd.grabExcessHorizontalSpace = true;
537 stackTraceText.setLayoutData(gd);
538 stackTraceText.setEditable(false);
541 private void createSessionSection(Composite parent) {
542 Composite container = new Composite(parent, SWT.NONE);
543 GridLayout layout = new GridLayout();
544 layout.marginHeight = 0;
545 layout.marginWidth = 6;
546 container.setLayout(layout);
547 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
549 container.setLayoutData(gd);
551 Label line = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
552 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
554 line.setLayoutData(gd);
556 Label label = new Label(container, SWT.NONE);
557 label.setText(XDebugUIPlugin.getString("EventDetailsDialog.session")); //$NON-NLS-1$
558 gd = new GridData(GridData.FILL_HORIZONTAL);
559 label.setLayoutData(gd);
560 sessionDataText = new Text(container, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL );
561 gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
562 gd.grabExcessHorizontalSpace = true;
563 sessionDataText.setLayoutData(gd);
564 sessionDataText.setEditable(false);
567 //--------------- configuration handling --------------
570 * Stores the current state in the dialog settings.
573 private void storeSettings() {
574 writeConfiguration();
577 * Returns the dialog settings object used to share state
578 * between several event detail dialogs.
580 * @return the dialog settings to be used
582 private IDialogSettings getDialogSettings() {
583 IDialogSettings settings= XDebugCorePlugin.getDefault().getDialogSettings();
584 dialogSettings= settings.getSection(getClass().getName());
585 if (dialogSettings == null)
586 dialogSettings= settings.addNewSection(getClass().getName());
587 return dialogSettings;
591 * Initializes itself from the dialog settings with the same state
592 * as at the previous invocation.
594 private void readConfiguration() {
595 IDialogSettings s= getDialogSettings();
597 int x= s.getInt("x"); //$NON-NLS-1$
598 int y= s.getInt("y"); //$NON-NLS-1$
599 dialogLocation= new Point(x, y);
601 x = s.getInt("width"); //$NON-NLS-1$
602 y = s.getInt("height"); //$NON-NLS-1$
603 dialogSize = new Point(x,y);
605 sashWeights = new int[2];
606 sashWeights[0] = s.getInt("sashWidth1"); //$NON-NLS-1$
607 sashWeights[1] = s.getInt("sashWidth2"); //$NON-NLS-1$
609 } catch (NumberFormatException e) {
610 dialogLocation= null;
616 private void writeConfiguration(){
617 IDialogSettings s = getDialogSettings();
618 Point location = getShell().getLocation();
619 s.put("x", location.x); //$NON-NLS-1$
620 s.put("y", location.y); //$NON-NLS-1$
622 Point size = getShell().getSize();
623 s.put("width", size.x); //$NON-NLS-1$
624 s.put("height", size.y); //$NON-NLS-1$
626 sashWeights = getSashForm().getWeights();
627 s.put("sashWidth1", sashWeights[0]); //$NON-NLS-1$
628 s.put("sashWidth2", sashWeights[1]); //$NON-NLS-1$