Initial implementation of the new Debug Plugin
authorcperkonig <cperkonig>
Tue, 4 Oct 2005 11:01:58 +0000 (11:01 +0000)
committercperkonig <cperkonig>
Tue, 4 Oct 2005 11:01:58 +0000 (11:01 +0000)
24 files changed:
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/EnvironmentVariable.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/MultipleInputDialog.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIMessages.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPlugin.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPluginImages.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/BreakpointRulerActionDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/ToggleBreakpointRulerAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPDebugModelPresentation.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPEnvironmentTab.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPMainTab.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPTabGroup.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPBreakpointAdapterFactory.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPLineBreakpointAdapter.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/preference/XDebugPreferencePage.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialog.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialogAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/FilterDialog.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogEntry.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogReader.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogSession.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogView.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewContentProvider.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewLabelProvider.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/OpenLogDialog.java [new file with mode: 0644]

diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/EnvironmentVariable.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/EnvironmentVariable.java
new file mode 100644 (file)
index 0000000..f615429
--- /dev/null
@@ -0,0 +1,76 @@
+package net.sourceforge.phpeclipse.xdebug.ui;
+
+/**
+ * A key/value set whose data is passed into Runtime.exec(...)
+ */
+public class EnvironmentVariable
+{
+       // The name of the environment variable
+       private String name;
+       
+       // The value of the environment variable
+       private String value;
+       
+       public EnvironmentVariable(String name, String value)
+       {
+               this.name = name;
+               this.value = value;
+       }
+
+       /**
+        * Returns this variable's name, which serves as the key in the key/value
+        * pair this variable represents
+        * 
+        * @return this variable's name
+        */
+       public String getName()
+       {
+               return name;
+       }
+       
+       /**
+        * Returns this variables value.
+        * 
+        * @return this variable's value
+        */
+       public String getValue()
+       {
+               return value;
+       }
+               
+       /**
+        * Sets this variable's value
+        * @param value
+        */
+       public void setValue(String value)
+       {
+               this.value = value;
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return getName();
+       }
+       
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#equals(java.lang.Object)
+        */
+       public boolean equals(Object obj) {
+               boolean equal = false;
+               if (obj instanceof EnvironmentVariable) {
+                       EnvironmentVariable var = (EnvironmentVariable)obj;
+                       equal = var.getName().equals(name);
+               }
+               return equal;           
+       }
+       /* (non-Javadoc)
+        * @see java.lang.Object#hashCode()
+        */
+       public int hashCode() {
+               return name.hashCode();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/MultipleInputDialog.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/MultipleInputDialog.java
new file mode 100644 (file)
index 0000000..3af109a
--- /dev/null
@@ -0,0 +1,362 @@
+package net.sourceforge.phpeclipse.xdebug.ui;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.StringVariableSelectionDialog;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class MultipleInputDialog extends Dialog {
+       protected static final String FIELD_NAME = "FIELD_NAME"; //$NON-NLS-1$
+       protected static final int TEXT = 100;
+       protected static final int BROWSE = 101;
+       protected static final int VARIABLE = 102;
+       
+       protected Composite panel;
+       
+       protected List fieldList = new ArrayList();
+       protected List controlList = new ArrayList();
+       protected List validators = new ArrayList();
+       protected Map valueMap = new HashMap();
+
+       private String title;
+       
+       
+       
+       public MultipleInputDialog(Shell shell, String title) {
+               super(shell);
+               this.title = title;
+               setShellStyle(getShellStyle() | SWT.RESIZE);
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
+        */
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               if (title != null) {
+                       shell.setText(title);
+               }
+               
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite)
+        */
+       protected Control createButtonBar(Composite parent) {
+               Control bar = super.createButtonBar(parent);
+               validateFields();
+               return bar;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+        */
+       protected Control createDialogArea(Composite parent) {
+               Composite container = (Composite)super.createDialogArea(parent);
+               container.setLayout(new GridLayout(2, false));
+               container.setLayoutData(new GridData(GridData.FILL_BOTH));
+               
+               panel = new Composite(container, SWT.NONE);
+               GridLayout layout = new GridLayout(2, false);
+               panel.setLayout(layout);
+               panel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               
+               for (Iterator i = fieldList.iterator(); i.hasNext();) {
+                       FieldSummary field = (FieldSummary)i.next();
+                       switch(field.type) {
+                               case TEXT:
+                                       createTextField(field.name, field.initialValue, field.allowsEmpty);
+                                       break;
+                               case BROWSE:
+                                       createBrowseField(field.name, field.initialValue, field.allowsEmpty);
+                                       break;
+                               case VARIABLE:
+                                       createVariablesField(field.name, field.initialValue, field.allowsEmpty);
+                                       break;
+                       }
+               }
+               
+               fieldList = null; // allow it to be gc'd
+               Dialog.applyDialogFont(container);
+               return container;
+       }
+       
+       public void addBrowseField(String labelText, String initialValue, boolean allowsEmpty) {
+               fieldList.add(new FieldSummary(BROWSE, labelText, initialValue, allowsEmpty));
+       }
+       public void addTextField(String labelText, String initialValue, boolean allowsEmpty) {
+               fieldList.add(new FieldSummary(TEXT, labelText, initialValue, allowsEmpty));
+       }
+       public void addVariablesField(String labelText, String initialValue, boolean allowsEmpty) {
+               fieldList.add(new FieldSummary(VARIABLE, labelText, initialValue, allowsEmpty));
+       }
+
+       protected void createTextField(String labelText, String initialValue, boolean allowEmpty) { 
+               Label label = new Label(panel, SWT.NONE);
+               label.setText(labelText);
+               label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+               
+               final Text text = new Text(panel, SWT.SINGLE | SWT.BORDER);
+               text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               text.setData(FIELD_NAME, labelText);
+               
+               // make sure rows are the same height on both panels.
+               label.setSize(label.getSize().x, text.getSize().y); 
+               
+               if (initialValue != null) {
+                       text.setText(initialValue);
+               }
+               
+               if (!allowEmpty) {
+                       validators.add(new Validator() {
+                               public boolean validate() {
+                                       return !text.getText().equals(""); //$NON-NLS-1$
+                               }
+                       });
+                       text.addModifyListener(new ModifyListener() {
+                               public void modifyText(ModifyEvent e) {
+                                       validateFields();
+                               }
+                       });
+               }
+               
+               controlList.add(text);
+       }
+       
+       protected void createBrowseField(String labelText, String initialValue, boolean allowEmpty) {
+               Label label = new Label(panel, SWT.NONE);
+               label.setText(labelText);
+               label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+               
+               Composite comp = new Composite(panel, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight=0;
+               layout.marginWidth=0;
+               comp.setLayout(layout);
+               comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               
+               final Text text = new Text(comp, SWT.SINGLE | SWT.BORDER);
+               GridData data = new GridData(GridData.FILL_HORIZONTAL);
+               data.widthHint = 200;
+               text.setLayoutData(data);
+               text.setData(FIELD_NAME, labelText);
+
+               // make sure rows are the same height on both panels.
+               label.setSize(label.getSize().x, text.getSize().y); 
+               
+               if (initialValue != null) {
+                       text.setText(initialValue);
+               }
+
+               if (!allowEmpty) {
+                       validators.add(new Validator() {
+                               public boolean validate() {
+                                       return !text.getText().equals(""); //$NON-NLS-1$
+                               }
+                       });
+
+                       text.addModifyListener(new ModifyListener() {
+                               public void modifyText(ModifyEvent e) {
+                                       validateFields();
+                               }
+                       });
+               }
+               
+               Button button = createButton(comp, IDialogConstants.IGNORE_ID, "&Browse...", false); 
+               button.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               DirectoryDialog dialog = new DirectoryDialog(getShell());
+                               dialog.setMessage("Select a file:");  
+                               String currentWorkingDir = text.getText();
+                               if (!currentWorkingDir.trim().equals("")) { //$NON-NLS-1$
+                                       File path = new File(currentWorkingDir);
+                                       if (path.exists()) {
+                                               dialog.setFilterPath(currentWorkingDir);
+                                       }                       
+                               }
+                               
+                               String selectedDirectory = dialog.open();
+                               if (selectedDirectory != null) {
+                                       text.setText(selectedDirectory);
+                               }               
+                       }
+               });
+
+               controlList.add(text);
+               
+       }
+       
+       
+       public void createVariablesField(String labelText, String initialValue, boolean allowEmpty) {
+               Label label = new Label(panel, SWT.NONE);
+               label.setText(labelText);
+               label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+               
+               Composite comp = new Composite(panel, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight=0;
+               layout.marginWidth=0;
+               comp.setLayout(layout);
+               comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               
+               final Text text = new Text(comp, SWT.SINGLE | SWT.BORDER);
+               GridData data = new GridData(GridData.FILL_HORIZONTAL);
+               data.widthHint = 200;
+               text.setLayoutData(data);
+               text.setData(FIELD_NAME, labelText);
+
+               // make sure rows are the same height on both panels.
+               label.setSize(label.getSize().x, text.getSize().y); 
+               
+               if (initialValue != null) {
+                       text.setText(initialValue);
+               }
+
+               if (!allowEmpty) {
+                       validators.add(new Validator() {
+                               public boolean validate() {
+                                       return !text.getText().equals(""); //$NON-NLS-1$
+                               }
+                       });
+
+                       text.addModifyListener(new ModifyListener() {
+                               public void modifyText(ModifyEvent e) {
+                                       validateFields();
+                               }
+                       });
+               }
+               
+               Button button = createButton(comp, IDialogConstants.IGNORE_ID, "Varia&bles...", false); 
+               button.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell());
+                               int code = dialog.open();
+                               if (code == IDialogConstants.OK_ID) {
+                                       String variable = dialog.getVariableExpression();
+                                       if (variable != null) {
+                                               text.insert(variable);
+                                       }
+                               }
+                       }
+               });
+
+               controlList.add(text);
+                               
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.dialogs.Dialog#okPressed()
+        */
+       protected void okPressed() {
+               for (Iterator i = controlList.iterator(); i.hasNext(); ) {
+                       Control control = (Control)i.next();
+                       if (control instanceof Text) {
+                               valueMap.put(control.getData(FIELD_NAME), ((Text)control).getText());
+                       }
+               }
+               controlList = null;
+               super.okPressed();
+       }
+
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.window.Window#open()
+        */
+       public int open() {
+               applyDialogFont(panel);
+               return super.open();
+       }
+       
+       public Object getValue(String key) {
+               return valueMap.get(key);
+       }
+       
+       public String getStringValue(String key) {
+               return  (String) getValue(key);
+       }
+       
+       public void validateFields() {
+               for(Iterator i = validators.iterator(); i.hasNext(); ) {
+                       Validator validator = (Validator) i.next();
+                       if (!validator.validate()) {
+                               getButton(IDialogConstants.OK_ID).setEnabled(false);
+                               return;
+                       }
+               }
+               getButton(IDialogConstants.OK_ID).setEnabled(true);
+       }
+
+//     /* (non-Javadoc)
+//      * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
+//      */
+//     protected Point getInitialLocation(Point initialSize) {
+//             Point initialLocation= DialogSettingsHelper.getInitialLocation(getDialogSettingsSectionName());
+//             if (initialLocation != null) {
+//                     return initialLocation;
+//             }
+//             return super.getInitialLocation(initialSize);
+//     }
+
+       
+       protected String getDialogSettingsSectionName() {
+               return IDebugUIConstants.PLUGIN_ID + ".MULTIPLE_INPUT_DIALOG_2"; //$NON-NLS-1$
+       }
+       
+//     /* (non-Javadoc)
+//      * @see org.eclipse.jface.window.Window#getInitialSize()
+//      */
+//     protected Point getInitialSize() {
+//             Point size = super.getInitialSize();
+//             return DialogSettingsHelper.getInitialSize(getDialogSettingsSectionName(), size);
+//     }
+       
+//     /* (non-Javadoc)
+//      * @see org.eclipse.jface.window.Window#close()
+//      */
+//     public boolean close() {
+//             DialogSettingsHelper.persistShellGeometry(getShell(), getDialogSettingsSectionName());
+//             return super.close();
+//     }
+
+       protected class FieldSummary {
+               int type;
+               String name;
+               String initialValue;
+               boolean allowsEmpty;
+               
+               public FieldSummary(int type, String name, String initialValue, boolean allowsEmpty) {
+                       this.type = type;
+                       this.name = name;
+                       this.initialValue = initialValue;
+                       this.allowsEmpty = allowsEmpty;
+               }
+       }
+       
+       protected class Validator {
+               boolean validate() {
+                       return true;
+               }
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIMessages.properties b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIMessages.properties
new file mode 100644 (file)
index 0000000..711cbbd
--- /dev/null
@@ -0,0 +1,50 @@
+LogView.column.severity = !
+LogView.column.message = Message
+LogView.column.plugin = Plug-in
+LogView.column.date = Date
+LogView.clear = C&lear log viewer
+LogView.clear.tooltip = Clear log viewer
+LogView.copy = &Copy
+LogView.delete = &Delete log
+LogView.delete.tooltip = Delete log
+LogView.export = &Export log...
+LogView.export.tooltip = Export log
+LogView.import = &Import log...
+LogView.import.tooltip = Import log
+LogView.filter = &Filters...
+LogView.readLog.reload = Re&load this workspace's log
+LogView.readLog.restore = &Restore log
+LogView.readLog.restore.tooltip = Restore log
+LogView.severity.error = Error
+LogView.severity.warning = Warning
+LogView.severity.info = Info
+LogView.confirmDelete.title = Confirm Delete
+LogView.confirmDelete.message = Are you sure you want to permanently delete all logged events?
+LogView.confirmOverwrite.message = File " {0}" exists.  Would you like to overwrite it?
+LogView.operation.importing = Importing log...
+LogView.operation.reloading = Reloading...
+LogView.activate = &Activate on new events
+LogView.view.currentLog = &Open log
+LogView.view.currentLog.tooltip = Open log
+
+LogView.FilterDialog.title = Log Filters
+LogView.FilterDialog.eventTypes = Event Types
+LogView.FilterDialog.information = &Information
+LogView.FilterDialog.warning = &Warning
+LogView.FilterDialog.error = &Error
+LogView.FilterDialog.limitTo = &Limit visible events to:
+LogView.FilterDialog.eventsLogged = Show events logged during:
+LogView.FilterDialog.allSessions = &All sessions
+LogView.FilterDialog.recentSession = &Most recent session
+
+EventDetailsDialog.title= Event Details
+EventDetailsDialog.date=Date:
+EventDetailsDialog.severity=Severity:
+EventDetailsDialog.message=Message:
+EventDetailsDialog.exception=Exception Stack Trace:
+EventDetailsDialog.session=Session Data:
+EventDetailsDialog.noStack = An exception stack trace could not be found.
+EventDetailsDialog.previous=View details of previous event
+EventDetailsDialog.next=View details of next event
+EventDetailsDialog.copy=Copy event details to clipboard
+
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPlugin.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPlugin.java
new file mode 100644 (file)
index 0000000..03dc4a5
--- /dev/null
@@ -0,0 +1,150 @@
+package net.sourceforge.phpeclipse.xdebug.ui;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.plugin.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XDebugUIPlugin extends AbstractUIPlugin {
+
+       private static final String BUNDLE_NAME = "net.sourceforge.phpeclipse.xdebug.ui.XDebugUIMessages"; //$NON-NLS-1$
+
+       private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+                       .getBundle(BUNDLE_NAME);
+       
+       private static final String PLUGIN_ID ="net.sourceforge.phpeclipse.xdebug.ui"; 
+
+       
+       //The shared instance.
+       private static XDebugUIPlugin plugin;
+       
+       /**
+        * The constructor.
+        */
+       public XDebugUIPlugin() {
+               plugin = this;
+       }
+
+       /**
+        * This method is called upon plug-in activation
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+       }
+
+       /**
+        * This method is called when the plug-in is stopped
+        */
+       public void stop(BundleContext context) throws Exception {
+               super.stop(context);
+               plugin = null;
+       }
+
+       /**
+        * Returns the shared instance.
+        */
+       public static XDebugUIPlugin getDefault() {
+               return plugin;
+       }
+
+       /**
+        * Returns an image descriptor for the image file at the given
+        * plug-in relative path.
+        *
+        * @param path the path
+        * @return the image descriptor
+        */
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return AbstractUIPlugin.imageDescriptorFromPlugin("net.sourceforge.phpeclipse.xdebug.ui", path);
+       }
+       
+       /**
+        * Convenience method which returns the unique identifier of this plugin.
+        */
+       public static String getUniqueIdentifier() {
+               return PLUGIN_ID;
+       }
+       
+       /**
+        * Utility method with conventions
+        */
+       public static void errorDialog(Shell shell, String title, String message, IStatus s) {
+               // if the 'message' resource string and the IStatus' message are the same,
+               // don't show both in the dialog
+               if (s != null && message.equals(s.getMessage())) {
+                       message= null;
+               }
+               ErrorDialog.openError(shell, title, message, s);
+       }
+               
+
+       /**
+        * Utility method with conventions
+        */
+       public static void errorDialog(Shell shell, String title, String message, Throwable t) {
+               IStatus status;
+               if (t instanceof CoreException) {
+                       status= ((CoreException)t).getStatus();
+                       // if the 'message' resource string and the IStatus' message are the same,
+                       // don't show both in the dialog
+                       if (status != null && message.equals(status.getMessage())) {
+                               message= null;
+                       }
+               } else {
+                       status= new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, "Error within Debug UI: ", t); //$NON-NLS-1$
+                       log(status);    
+               }
+               ErrorDialog.openError(shell, title, message, status);
+       }
+
+       /**
+        * Logs the specified status with this plug-in's log.
+        * 
+        * @param status status to log
+        */
+       public static void log(IStatus status) {
+               getDefault().getLog().log(status);
+       }
+       
+       /**
+        * Logs an internal error with the specified throwable
+        * 
+        * @param e the exception to be logged
+        */     
+       public static void log(Throwable e) {
+               log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, "Internal Error", e));  
+       }
+       
+       /**
+        * Returns the standard display to be used. The method first checks, if
+        * the thread calling this method has an associated display. If so, this
+        * display is returned. Otherwise the method returns the default display.
+        */
+       public static Display getStandardDisplay() {
+               Display display;
+               display= Display.getCurrent();
+               if (display == null)
+                       display= Display.getDefault();
+               return display;         
+       }
+
+       public static String getString(String key) {
+               try {
+                       return RESOURCE_BUNDLE.getString(key);
+               } catch (MissingResourceException e) {
+                       return '!' + key + '!';
+               }
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPluginImages.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/XDebugUIPluginImages.java
new file mode 100644 (file)
index 0000000..69e49cc
--- /dev/null
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+
+public class XDebugUIPluginImages {
+
+
+       /* Declare Common paths */
+       private static URL ICON_BASE_URL= null;
+
+       static {
+               String pathSuffix = "icons/"; //$NON-NLS-1$
+               ICON_BASE_URL= XDebugUIPlugin.getDefault().getBundle().getEntry(pathSuffix);
+       }
+       
+       // The plugin registry
+       private static ImageRegistry fgImageRegistry = null;
+       
+       /*
+        * Set of predefined Image Descriptors.
+        */
+       private static final String T_OBJ= "obj16/";            //$NON-NLS-1$
+//     private static final String T_OVR= "ovr16/";            //$NON-NLS-1$
+       private static final String T_EVIEW= "eview16/";        //$NON-NLS-1$
+       private static final String T_LCL="elcl16/";
+
+       public static final String IMG_EVIEW_ARGUMENTS_TAB = "IMG_EVIEW_ARGUMENTS_TAB";
+       public static final String IMG_EVIEW_ENVIROMENT_TAB = "IMG_EVIEW_ENVIROMENT_TAB";
+
+       
+       public static final String IMG_PREV_EVENT="IMG_PREV_EVENT";
+       public static final String DESC_NEXT_EVENT="DESC_NEXT_EVENT";
+       public static final String IMG_ERROR_ST_OBJ="IMG_ERROR_ST_OBJ";
+       public static final String IMG_WARNING_ST_OBJ="IMG_WARNING_ST_OBJ";
+       public static final String IMG_INFO_ST_OBJ="IMG_INFO_ST_OBJ";
+       public static final String IMG_ERROR_STACK_OBJ="IMG_ERROR_STACK_OBJ";
+
+
+       public static final String IMG_PROPERTIES          = "IMG_PROPERTIES";
+//     public static final String IMG_PROPERTIES_DISABLED = "IMG_PROPERTIES_DISABLED";
+       public static final String IMG_CLEAR               = "IMG_CLEAR";
+//     public static final String IMG_CLEAR_DISABLED      = "IMG_CLEAR_DISABLED";
+       public static final String IMG_READ_LOG            = "IMG_READ_LOG";
+//     public static final String IMG_READ_LOG_DISABLED   = "IMG_READ_LOG_DISABLED";
+       public static final String IMG_REMOVE_LOG          = "IMG_REMOVE_LOG";
+//     public static final String IMG_REMOVE_LOG_DISABLED = "IMG_REMOVE_LOG_DISABLED";
+       public static final String IMG_FILTER              = "IMG_FILTER";
+//     public static final String IMG_FILTER_DISABLED     = "IMG_FILTER_DISABLED";
+       public static final String IMG_EXPORT              = "IMG_EXPORT";
+//     public static final String IMG_EXPORT_DISABLED     = "IMG_EXPORT_DISABLED";
+       public static final String IMG_IMPORT              = "IMG_IMPORT";
+//     public static final String IMG_IMPORT_DISABLED     = "IMG_IMPORT_DISABLED";
+       public static final String IMG_OPEN_LOG                    = "IMG_OPEN_LOG";
+
+
+
+
+
+       /**
+        * Returns the image managed under the given key in this registry.
+        * 
+        * @param key the image's key
+        * @return the image managed under the given key
+        */ 
+       public static Image get(String key) {
+               return getImageRegistry().get(key);
+       }
+       
+       /**
+        * Returns the <code>ImageDescriptor</code> identified by the given key,
+        * or <code>null</code> if it does not exist.
+        */
+       public static ImageDescriptor getImageDescriptor(String key) {
+               return getImageRegistry().getDescriptor(key);
+       }       
+       
+       /*
+        * Helper method to access the image registry from the XDebugUIPlugin class.
+        */
+       public  static ImageRegistry getImageRegistry() {
+               if (fgImageRegistry == null) {
+                       initializeImageRegistry();
+               }
+               return fgImageRegistry;
+       }
+       
+       public static void initializeImageRegistry() {
+               fgImageRegistry= new ImageRegistry(XDebugUIPlugin.getStandardDisplay());
+               declareImages();
+       }
+       
+       private static void declareImages() {
+               declareRegistryImage(IMG_EVIEW_ARGUMENTS_TAB, T_EVIEW + "arguments_tab.gif"); //$NON-NLS-1$
+               declareRegistryImage(IMG_EVIEW_ENVIROMENT_TAB, T_EVIEW + "environment_tab.gif"); //$NON-NLS-1$
+
+               declareRegistryImage(IMG_ERROR_ST_OBJ,T_OBJ+"error_st_obj.gif"); 
+               declareRegistryImage(IMG_WARNING_ST_OBJ,T_OBJ + "warning_st_obj.gif");
+               declareRegistryImage(IMG_INFO_ST_OBJ,T_OBJ +"info_st_obj.gif");
+               declareRegistryImage(IMG_ERROR_STACK_OBJ,T_OBJ +"error_stack.gif");
+
+               declareRegistryImage(IMG_PROPERTIES,T_LCL + "properties.gif");
+//             declareRegistryImage(IMG_PROPERTIES_DISABLED
+               declareRegistryImage(IMG_CLEAR,T_LCL + "clear_log.gif");
+//             declareRegistryImage(IMG_CLEAR_DISABLED
+               declareRegistryImage(IMG_READ_LOG ,T_LCL + "restore_log.gif");
+//             declareRegistryImage(IMG_READ_LOG_DISABLED
+               declareRegistryImage(IMG_REMOVE_LOG,T_LCL + "remove_log.gif");
+//             declareRegistryImage(IMG_REMOVE_LOG_DISABLED
+               declareRegistryImage(IMG_FILTER,T_LCL + "filter_log.gif");
+//             declareRegistryImage(IMG_FILTER_DISABLED
+               declareRegistryImage(IMG_EXPORT,T_LCL + "export_log.gif");
+//             declareRegistryImage(IMG_EXPORT_DISABLED
+               declareRegistryImage(IMG_IMPORT,T_LCL + "import_log.gif");
+//             declareRegistryImage(IMG_IMPORT_DISABLED
+               declareRegistryImage(IMG_OPEN_LOG,T_LCL + "open_log.gif");
+               
+       }       
+       
+       /**
+        * Declare an Image in the registry table.
+        * @param key   The key to use when registering the image
+        * @param path  The path where the image can be found. This path is relative to where
+        *                              this plugin class is found (i.e. typically the packages directory)
+        */
+       private final static void declareRegistryImage(String key, String path) {
+               ImageDescriptor desc= ImageDescriptor.getMissingImageDescriptor();
+               try {
+                       desc= ImageDescriptor.createFromURL(makeIconFileURL(path));
+               } catch (MalformedURLException me) {
+                       XDebugUIPlugin.log(me);
+               }
+               fgImageRegistry.put(key, desc);
+       }       
+       
+       private static URL makeIconFileURL(String iconPath) throws MalformedURLException {
+               if (ICON_BASE_URL == null) {
+                       throw new MalformedURLException();
+               }
+                       
+               return new URL(ICON_BASE_URL, iconPath);
+       }       
+
+
+
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/BreakpointRulerActionDelegate.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/BreakpointRulerActionDelegate.java
new file mode 100644 (file)
index 0000000..5f906be
--- /dev/null
@@ -0,0 +1,20 @@
+package net.sourceforge.phpeclipse.xdebug.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+
+
+public class BreakpointRulerActionDelegate extends AbstractRulerActionDelegate {
+
+       private ToggleBreakpointRulerAction fTargetAction;
+
+       protected IAction createAction(ITextEditor editor,
+                       IVerticalRulerInfo rulerInfo) {
+               fTargetAction = new ToggleBreakpointRulerAction( editor, rulerInfo );
+               return fTargetAction;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/ToggleBreakpointRulerAction.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/actions/ToggleBreakpointRulerAction.java
new file mode 100644 (file)
index 0000000..d6a03d2
--- /dev/null
@@ -0,0 +1,123 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+    IBM Corporation - Initial implementation
+    Vicente Fernando - www.alfersoft.com.ar
+**********************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.actions;
+
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.php.model.PHPLineBreakpointAdapter;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+public class ToggleBreakpointRulerAction extends Action {      
+       
+       static class EmptySelection implements ISelection {
+
+               public boolean isEmpty() {
+                       return true;
+               }               
+       }
+       
+       private IVerticalRulerInfo fRuler;
+       private IWorkbenchPart fTargetPart;
+       private PHPLineBreakpointAdapter fBreakpointAdapter;
+       private static final ISelection EMPTY_SELECTION = new EmptySelection();  
+       
+       public ToggleBreakpointRulerAction( IWorkbenchPart part, IVerticalRulerInfo ruler ) {
+               super( "Toggle Breakpoint" ); //$NON-NLS-1$
+
+               fRuler= ruler;
+               fRuler = ruler;
+               setTargetPart( part );
+               fBreakpointAdapter = new PHPLineBreakpointAdapter();
+//             part.getSite().getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp( this, ICDebugHelpContextIds.TOGGLE_BREAKPOINT_ACTION );
+//             setId( IInternalCDebugUIConstants.ACTION_TOGGLE_BREAKPOINT );
+       }
+       
+       
+       /**
+        * @see Action#run()
+        */
+       public void run() {
+               try {
+                               fBreakpointAdapter.toggleLineBreakpoints( getTargetPart(), getTargetSelection() );
+               }
+               catch( CoreException e ) {
+                       XDebugUIPlugin.errorDialog( getTargetPart().getSite().getShell(),"Error", "Operation failed" , e.getStatus() );
+               }
+       }
+       
+       /**
+        * Returns this action's vertical ruler info.
+        *
+        * @return this action's vertical ruler
+        */
+       protected IVerticalRulerInfo getVerticalRulerInfo() {
+               return fRuler;
+       }
+
+       private IWorkbenchPart getTargetPart() {
+               return this.fTargetPart;
+       }
+
+       private void setTargetPart( IWorkbenchPart targetPart ) {
+               this.fTargetPart = targetPart;
+       }
+
+       /**
+        * Returns the current selection in the active part, possibly
+        * and empty selection, but never <code>null</code>.
+        * 
+        * @return the selection in the active part, possibly empty
+        */
+       private ISelection getTargetSelection() {
+               IDocument doc = getDocument();
+               if ( doc != null ) {
+                       int line = getVerticalRulerInfo().getLineOfLastMouseButtonActivity();
+                       try {
+                               IRegion region = doc.getLineInformation( line );
+                               return new TextSelection( doc, region.getOffset(), region.getLength() );
+                       }
+                       catch( BadLocationException e ) {
+                               DebugPlugin.log( e );
+                       } 
+               }
+               return EMPTY_SELECTION;
+       }
+
+       private IDocument getDocument() {
+               IWorkbenchPart targetPart = getTargetPart();
+               if ( targetPart instanceof ITextEditor ) {
+                       ITextEditor textEditor = (ITextEditor)targetPart; 
+                       IDocumentProvider provider = textEditor.getDocumentProvider();
+                       if ( provider != null )
+                               return provider.getDocument( textEditor.getEditorInput() );
+               }
+//             else if ( targetPart instanceof DisassemblyView ) {
+//                     DisassemblyView dv = (DisassemblyView)targetPart;
+//                     IDocumentProvider provider = dv.getDocumentProvider();
+//                     if ( provider != null )
+//                             return provider.getDocument( dv.getInput() );
+//             }
+               return null;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPDebugModelPresentation.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPDebugModelPresentation.java
new file mode 100644 (file)
index 0000000..858937f
--- /dev/null
@@ -0,0 +1,121 @@
+package net.sourceforge.phpeclipse.xdebug.ui.php.launching;
+
+
+
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugLineBreakpoint;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugValue;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugVariable;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.IValueDetailListener;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+
+public class PHPDebugModelPresentation implements IDebugModelPresentation {
+
+       public void setAttribute(String attribute, Object value) {
+               // TODO Auto-generated method stub
+
+       }
+
+       /**
+        * @see IDebugModelPresentation#getImage(Object)
+        */
+       public Image getImage(Object element) {
+               if (element instanceof XDebugLineBreakpoint) {
+                       return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_BREAKPOINT);
+               } else if (element instanceof IMarker) {
+                       return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_BREAKPOINT);
+               } else if (element instanceof XDebugStackFrame || element instanceof XDebugThread || element instanceof XDebugTarget) {
+                       return null;
+               } else if (element instanceof XDebugVariable) {
+                       return getVariableImage((XDebugVariable)element);
+               } else if (element instanceof XDebugValue) {
+                       return getValueImage((XDebugValue)element);
+               }
+               return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_BREAKPOINT);
+       }
+       private Image getVariableImage(XDebugVariable phpVar) {
+               /*              if (phpVar != null) {
+                if (phpVar.isLocal())
+                return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_VARIABLE);
+                if (phpVar.isHashValue())
+                return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_VARIABLE);
+                }
+                */
+               return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_VARIABLE);
+       }
+       
+       private Image getValueImage(XDebugValue phpVar) {
+               if (phpVar != null) {
+                       return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_VARIABLE);
+               }
+               return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_VARIABLE);
+       }
+
+
+       public String getText(Object element) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       public void computeDetail(IValue value, IValueDetailListener listener) {
+               // TODO Auto-generated method stub
+
+       }
+
+       public void addListener(ILabelProviderListener listener) {
+               // TODO Auto-generated method stub
+
+       }
+
+       public void dispose() {
+               // TODO Auto-generated method stub
+
+       }
+
+       public boolean isLabelProperty(Object element, String property) {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public void removeListener(ILabelProviderListener listener) {
+               // TODO Auto-generated method stub
+
+       }
+
+       public IEditorInput getEditorInput(Object element) {
+
+               if (element instanceof IFile) {
+                       return new FileEditorInput((IFile)element);
+               }
+               if (element instanceof ILineBreakpoint) {
+                       return new FileEditorInput((IFile)((ILineBreakpoint)element).getMarker().getResource());
+               }
+               return null;
+       }
+
+       public String getEditorId(IEditorInput input, Object element) {
+               IEditorRegistry registry= PlatformUI.getWorkbench().getEditorRegistry();
+               IEditorDescriptor descriptor= registry.getDefaultEditor(input.getName());
+               if (descriptor != null)
+                       return descriptor.getId();
+               
+               return null;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPEnvironmentTab.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPEnvironmentTab.java
new file mode 100644 (file)
index 0000000..9133de0
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+ * Created on 14.07.2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sourceforge.phpeclipse.xdebug.ui.php.launching;
+
+import java.text.MessageFormat;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.EnvironmentVariable;
+import net.sourceforge.phpeclipse.xdebug.ui.MultipleInputDialog;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPluginImages;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ColumnLayoutData;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+/**
+ * @author Christian
+ * 
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class PHPEnvironmentTab extends AbstractLaunchConfigurationTab {
+
+       protected TableViewer environmentTable;
+
+       protected String[] envTableColumnHeaders = { "Variable", "Value" };
+
+       protected ColumnLayoutData[] envTableColumnLayouts = {
+                       new ColumnWeightData(50), new ColumnWeightData(50) };
+
+       private static final String NAME_LABEL = "Name";
+
+       private static final String VALUE_LABEL = "Value";
+
+       protected static final String P_VARIABLE = "variable"; //$NON-NLS-1$
+
+       protected static final String P_VALUE = "value"; //$NON-NLS-1$
+
+       protected static String[] envTableColumnProperties = { P_VARIABLE, P_VALUE };
+
+       protected Button envAddButton;
+
+       protected Button envAddCGIButton;
+
+       protected Button envEditButton;
+
+       protected Button envRemoveButton;
+
+       protected Button appendEnvironment;
+
+       protected Button replaceEnvironment;
+
+       protected Button envSelectButton;
+
+       /**
+        * Content provider for the environment table
+        */
+       protected class EnvironmentVariableContentProvider implements
+                       IStructuredContentProvider {
+               public Object[] getElements(Object inputElement) {
+                       EnvironmentVariable[] elements = new EnvironmentVariable[0];
+                       ILaunchConfiguration config = (ILaunchConfiguration) inputElement;
+                       Map m;
+                       try {
+                               m = config.getAttribute(
+                                               ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, (Map) null);
+                       } catch (CoreException e) {
+                               XDebugCorePlugin.log(new Status(IStatus.ERROR,
+                                               XDebugCorePlugin.PLUGIN_ID, IStatus.ERROR,
+                                               "Error reading configuration", e)); //$NON-NLS-1$
+                               return elements;
+                       }
+                       if (m != null && !m.isEmpty()) {
+                               elements = new EnvironmentVariable[m.size()];
+                               String[] varNames = new String[m.size()];
+                               m.keySet().toArray(varNames);
+                               for (int i = 0; i < m.size(); i++) {
+                                       elements[i] = new EnvironmentVariable(varNames[i],
+                                                       (String) m.get(varNames[i]));
+                               }
+                       }
+                       return elements;
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       if (newInput == null) {
+                               return;
+                       }
+                       if (viewer instanceof TableViewer) {
+                               TableViewer tableViewer = (TableViewer) viewer;
+                               if (tableViewer.getTable().isDisposed()) {
+                                       return;
+                               }
+                               tableViewer.setSorter(new ViewerSorter() {
+                                       public int compare(Viewer iviewer, Object e1, Object e2) {
+                                               if (e1 == null) {
+                                                       return -1;
+                                               } else if (e2 == null) {
+                                                       return 1;
+                                               } else {
+                                                       return ((EnvironmentVariable) e1).getName()
+                                                                       .compareToIgnoreCase(
+                                                                                       ((EnvironmentVariable) e2)
+                                                                                                       .getName());
+                                               }
+                                       }
+                               });
+                       }
+               }
+       }
+
+       /**
+        * Label provider for the environment table
+        */
+       public class EnvironmentVariableLabelProvider extends LabelProvider
+                       implements ITableLabelProvider {
+               public String getColumnText(Object element, int columnIndex) {
+                       String result = null;
+                       if (element != null) {
+                               EnvironmentVariable var = (EnvironmentVariable) element;
+                               switch (columnIndex) {
+                               case 0: // variable
+                                       result = var.getName();
+                                       break;
+                               case 1: // value
+                                       result = var.getValue();
+                                       break;
+                               }
+                       }
+                       return result;
+               }
+
+               public Image getColumnImage(Object element, int columnIndex) {
+                       return null;
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+        */
+       public void createControl(Composite parent) {
+               // Create main composite
+               Composite mainComposite = new Composite(parent, SWT.NONE);
+               setControl(mainComposite);
+               // WorkbenchHelp.setHelp(getControl(),
+               // IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_ENVIRONMENT_TAB);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+               mainComposite.setLayout(layout);
+               mainComposite.setLayoutData(gridData);
+               mainComposite.setFont(parent.getFont());
+
+               createEnvironmentTable(mainComposite);
+               createTableButtons(mainComposite);
+               createAppendReplace(mainComposite);
+
+               Dialog.applyDialogFont(mainComposite);
+       }
+
+       /**
+        * Creates and configures the widgets which allow the user to choose whether
+        * the specified environment should be appended to the native environment or
+        * if it should completely replace it.
+        * 
+        * @param parent
+        *            the composite in which the widgets should be created
+        */
+       protected void createAppendReplace(Composite parent) {
+               Composite appendReplaceComposite = new Composite(parent, SWT.NONE);
+               GridData gridData = new GridData();
+               gridData.horizontalSpan = 2;
+               GridLayout layout = new GridLayout();
+               appendReplaceComposite.setLayoutData(gridData);
+               appendReplaceComposite.setLayout(layout);
+               appendReplaceComposite.setFont(parent.getFont());
+
+               appendEnvironment = createRadioButton(appendReplaceComposite,
+                               "&Append environment to native environment");
+               appendEnvironment.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               updateLaunchConfigurationDialog();
+                       }
+               });
+               replaceEnvironment = createRadioButton(appendReplaceComposite,
+                               "Re&place native environment with specified environment");
+       }
+
+       /**
+        * Updates the enablement of the append/replace widgets. The widgets should
+        * disable when there are no environment variables specified.
+        */
+       protected void updateAppendReplace() {
+               boolean enable = environmentTable.getTable().getItemCount() > 0;
+               appendEnvironment.setEnabled(enable);
+               replaceEnvironment.setEnabled(enable);
+       }
+
+       /**
+        * Creates and configures the table that displayed the key/value pairs that
+        * comprise the environment.
+        * 
+        * @param parent
+        *            the composite in which the table should be created
+        */
+       protected void createEnvironmentTable(Composite parent) {
+               Font font = parent.getFont();
+               // Create table composite
+               Composite tableComposite = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.marginHeight = 0;
+               layout.marginWidth = 0;
+               layout.numColumns = 1;
+               GridData gridData = new GridData(GridData.FILL_BOTH);
+               gridData.heightHint = 150;
+               tableComposite.setLayout(layout);
+               tableComposite.setLayoutData(gridData);
+               tableComposite.setFont(font);
+               // Create label
+               Label label = new Label(tableComposite, SWT.NONE);
+               label.setFont(font);
+               label.setText("Environment variables to &set");
+               // Create table
+               environmentTable = new TableViewer(tableComposite, SWT.BORDER
+                               | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
+               Table table = environmentTable.getTable();
+               TableLayout tableLayout = new TableLayout();
+               table.setLayout(tableLayout);
+               table.setHeaderVisible(true);
+               table.setFont(font);
+               gridData = new GridData(GridData.FILL_BOTH);
+               environmentTable.getControl().setLayoutData(gridData);
+               environmentTable
+                               .setContentProvider(new EnvironmentVariableContentProvider());
+               environmentTable
+                               .setLabelProvider(new EnvironmentVariableLabelProvider());
+               environmentTable.setColumnProperties(envTableColumnProperties);
+               environmentTable
+                               .addSelectionChangedListener(new ISelectionChangedListener() {
+                                       public void selectionChanged(SelectionChangedEvent event) {
+                                               handleTableSelectionChanged(event);
+                                       }
+                               });
+               environmentTable.addDoubleClickListener(new IDoubleClickListener() {
+                       public void doubleClick(DoubleClickEvent event) {
+                               if (!environmentTable.getSelection().isEmpty()) {
+                                       handleEnvEditButtonSelected();
+                               }
+                       }
+               });
+               // Create columns
+               for (int i = 0; i < envTableColumnHeaders.length; i++) {
+                       tableLayout.addColumnData(envTableColumnLayouts[i]);
+                       TableColumn tc = new TableColumn(table, SWT.NONE, i);
+                       tc.setResizable(envTableColumnLayouts[i].resizable);
+                       tc.setText(envTableColumnHeaders[i]);
+               }
+       }
+
+       /**
+        * Responds to a selection changed event in the environment table
+        * 
+        * @param event
+        *            the selection change event
+        */
+       protected void handleTableSelectionChanged(SelectionChangedEvent event) {
+               int size = ((IStructuredSelection) event.getSelection()).size();
+               envEditButton.setEnabled(size == 1);
+               envRemoveButton.setEnabled(size > 0);
+       }
+
+       /**
+        * Creates the add/edit/remove buttons for the environment table
+        * 
+        * @param parent
+        *            the composite in which the buttons should be created
+        */
+       protected void createTableButtons(Composite parent) {
+               // Create button composite
+               Composite buttonComposite = new Composite(parent, SWT.NONE);
+               GridLayout glayout = new GridLayout();
+               glayout.marginHeight = 0;
+               glayout.marginWidth = 0;
+               glayout.numColumns = 1;
+               GridData gdata = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+                               | GridData.HORIZONTAL_ALIGN_END);
+               buttonComposite.setLayout(glayout);
+               buttonComposite.setLayoutData(gdata);
+               buttonComposite.setFont(parent.getFont());
+
+               createVerticalSpacer(buttonComposite, 1);
+               // Create buttons
+               envAddButton = createPushButton(buttonComposite, "New", null);
+               envAddButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleEnvAddButtonSelected();
+                       }
+               });
+               envAddCGIButton = createPushButton(buttonComposite, "CGIButton", null);
+               envAddCGIButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleEnvAddCGIButtonSelected();
+                       }
+               });
+
+               envSelectButton = createPushButton(buttonComposite, "Se&lect...", null);
+               envSelectButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleEnvSelectButtonSelected();
+                       }
+               });
+               envEditButton = createPushButton(buttonComposite, "Edit", null);
+               envEditButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleEnvEditButtonSelected();
+                       }
+               });
+               envEditButton.setEnabled(false);
+               envRemoveButton = createPushButton(buttonComposite, "Remove", null);
+               envRemoveButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleEnvRemoveButtonSelected();
+                       }
+               });
+               envRemoveButton.setEnabled(false);
+       }
+
+       /**
+        * Adds a new environment variable to the table.
+        */
+       protected void handleEnvAddButtonSelected() {
+               MultipleInputDialog dialog = new MultipleInputDialog(getShell(),
+                               "New Environment Variable");
+               dialog.addTextField(NAME_LABEL, null, false);
+               dialog.addVariablesField(VALUE_LABEL, null, true);
+
+               if (dialog.open() != Window.OK) {
+                       return;
+               }
+
+               String name = dialog.getStringValue(NAME_LABEL);
+               String value = dialog.getStringValue(VALUE_LABEL);
+
+               if (name != null && value != null && name.length() > 0
+                               && value.length() > 0) {
+                       addVariable(new EnvironmentVariable(name.trim(), value.trim()));
+                       updateAppendReplace();
+               }
+       }
+
+       /**
+        * Attempts to add the given variable. Returns whether the variable was
+        * added or not (as when the user answers not to overwrite an existing
+        * variable).
+        * 
+        * @param variable
+        *            the variable to add
+        * @return whether the variable was added
+        */
+       protected boolean addVariable(EnvironmentVariable variable) {
+               String name = variable.getName();
+               TableItem[] items = environmentTable.getTable().getItems();
+               for (int i = 0; i < items.length; i++) {
+                       EnvironmentVariable existingVariable = (EnvironmentVariable) items[i]
+                                       .getData();
+                       if (existingVariable.getName().equals(name)) {
+                               boolean overWrite = MessageDialog.openQuestion(getShell(),"Overwrite variable?",
+                                       MessageFormat.format("A variable named {0} already exists. Overwrite?",new String[] { name }));
+                               if (!overWrite) {
+                                       return false;
+                               }
+                               environmentTable.remove(existingVariable);
+                               break;
+                       }
+               }
+               environmentTable.add(variable);
+               updateLaunchConfigurationDialog();
+               return true;
+       }
+
+       /**
+        * Displays a dialog that allows user to select native environment variables
+        * to add to the table.
+        */
+       private void handleEnvSelectButtonSelected() {
+               // get Environment Variables from the OS
+               Map envVariables = getNativeEnvironment();
+
+               // get Environment Variables from the table
+               TableItem[] items = environmentTable.getTable().getItems();
+               for (int i = 0; i < items.length; i++) {
+                       EnvironmentVariable var = (EnvironmentVariable) items[i].getData();
+                       envVariables.remove(var.getName());
+               }
+
+               ListSelectionDialog dialog = new NativeEnvironmentDialog(getShell(),
+                               envVariables, createSelectionDialogContentProvider(),
+                               createSelectionDialogLabelProvider(),
+                               "Select &environment variables to add:");
+               dialog.setTitle("Select Environment Variables");
+
+               int button = dialog.open();
+               if (button == Window.OK) {
+                       Object[] selected = dialog.getResult();
+                       for (int i = 0; i < selected.length; i++) {
+                               environmentTable.add(selected[i]);
+                       }
+               }
+
+               updateAppendReplace();
+               updateLaunchConfigurationDialog();
+       }
+
+       /**
+        * Displays a dialog that allows user to select native environment variables
+        * to add to the table.
+        */
+       private void handleEnvAddCGIButtonSelected() {
+
+               Map envVariables = new HashMap();
+
+               envVariables.put("HTTP_COOKIE", new EnvironmentVariable("HTTP_COOKIE",
+                               "TestCookie=1"));
+               envVariables.put("REDIRECT_QUERY_STRING", new EnvironmentVariable(
+                               "REDIRECT_QUERY_STRING", ""));
+               envVariables.put("REDIRECT_STATUS", new EnvironmentVariable(
+                               "REDIRECT_STATUS", "200"));
+               envVariables.put("REDIRECT_URL", new EnvironmentVariable(
+                               "REDIRECT_URL", ""));
+               envVariables.put("SERVER_SOFTWARE", new EnvironmentVariable(
+                               "SERVER_SOFTWARE", "DBG / 2.1"));
+               envVariables.put("SERVER_NAME", new EnvironmentVariable("SERVER_NAME",
+                               "localhost"));
+               envVariables.put("SERVER_ADDR", new EnvironmentVariable("SERVER_ADDR",
+                               "127.0.0.1"));
+               envVariables.put("SERVER_PORT", new EnvironmentVariable("SERVER_PORT",
+                               "80"));
+               envVariables.put("REMOTE_ADDR", new EnvironmentVariable("REMOTE_ADDR",
+                               "127.0.0.1"));
+               envVariables.put("GATEWAY_INTERFACE", new EnvironmentVariable(
+                               "GATEWAY_INTERFACE", "CGI / 1.1"));
+               envVariables.put("SERVER_PROTOCOL", new EnvironmentVariable(
+                               "SERVER_PROTOCOL", "HTTP / 1.1"));
+               envVariables.put("REQUEST_METHOD", new EnvironmentVariable(
+                               "REQUEST_METHOD", "GET"));
+               envVariables.put("QUERY_STRING", new EnvironmentVariable(
+                               "QUERY_STRING", ""));
+               envVariables.put("REDIRECT_QUERY_STRING", new EnvironmentVariable(
+                               "REDIRECT_QUERY_STRING", ""));
+               // envVariables.put("REQUEST_URI" + OSFilePath;
+               // envVariables.put("PATH_INFO=" + OSFilePath;
+               // envVariables.put("PATH_TRANSLATED=" + OSFilePath;
+
+               // get Environment Variables from the table
+               TableItem[] items = environmentTable.getTable().getItems();
+               for (int i = 0; i < items.length; i++) {
+                       EnvironmentVariable var = (EnvironmentVariable) items[i].getData();
+                       envVariables.remove(var.getName());
+               }
+
+               ListSelectionDialog dialog = new NativeEnvironmentDialog(getShell(),
+                               envVariables, createSelectionDialogContentProvider(),
+                               createSelectionDialogLabelProvider(),
+                               "Select &environment variables to add:");
+               dialog.setTitle("Select Environment Variables");
+
+               int button = dialog.open();
+               if (button == Window.OK) {
+                       Object[] selected = dialog.getResult();
+                       for (int i = 0; i < selected.length; i++) {
+                               environmentTable.add(selected[i]);
+                       }
+               }
+
+               updateAppendReplace();
+               updateLaunchConfigurationDialog();
+       }
+
+       /**
+        * Creates a label provider for the native native environment variable
+        * selection dialog.
+        * 
+        * @return A label provider for the native native environment variable
+        *         selection dialog.
+        */
+       private ILabelProvider createSelectionDialogLabelProvider() {
+               return new ILabelProvider() {
+                       public Image getImage(Object element) {
+                               return null;
+                       }
+
+                       public String getText(Object element) {
+                               EnvironmentVariable var = (EnvironmentVariable) element;
+                               return var.getName() + " [" + var.getValue() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+
+                       public void addListener(ILabelProviderListener listener) {
+                       }
+
+                       public void dispose() {
+                       }
+
+                       public boolean isLabelProperty(Object element, String property) {
+                               return false;
+                       }
+
+                       public void removeListener(ILabelProviderListener listener) {
+                       }
+               };
+       }
+
+       /**
+        * Creates a content provider for the native native environment variable
+        * selection dialog.
+        * 
+        * @return A content provider for the native native environment variable
+        *         selection dialog.
+        */
+       private IStructuredContentProvider createSelectionDialogContentProvider() {
+               return new IStructuredContentProvider() {
+                       public Object[] getElements(Object inputElement) {
+                               EnvironmentVariable[] elements = null;
+                               if (inputElement instanceof HashMap) {
+                                       Comparator comparator = new Comparator() {
+                                               public int compare(Object o1, Object o2) {
+                                                       String s1 = (String) o1;
+                                                       String s2 = (String) o2;
+                                                       return s1.compareTo(s2);
+                                               }
+
+                                       };
+                                       TreeMap envVars = new TreeMap(comparator);
+                                       envVars.putAll((Map) inputElement);
+                                       elements = new EnvironmentVariable[envVars.size()];
+                                       int index = 0;
+                                       for (Iterator iterator = envVars.keySet().iterator(); iterator
+                                                       .hasNext(); index++) {
+                                               Object key = iterator.next();
+                                               elements[index] = (EnvironmentVariable) envVars
+                                                               .get(key);
+                                       }
+                               }
+                               return elements;
+                       }
+
+                       public void dispose() {
+                       }
+
+                       public void inputChanged(Viewer viewer, Object oldInput,
+                                       Object newInput) {
+                       }
+               };
+       }
+
+       /**
+        * Gets native environment variable from the LaunchManager. Creates
+        * EnvironmentVariable objects.
+        * 
+        * @return Map of name - EnvironmentVariable pairs based on native
+        *         environment.
+        */
+       private Map getNativeEnvironment() {
+               Map stringVars = DebugPlugin.getDefault().getLaunchManager()
+                               .getNativeEnvironment();
+               HashMap vars = new HashMap();
+               for (Iterator i = stringVars.keySet().iterator(); i.hasNext();) {
+                       String key = (String) i.next();
+                       String value = (String) stringVars.get(key);
+                       vars.put(key, new EnvironmentVariable(key, value));
+               }
+               return vars;
+       }
+
+       /**
+        * Creates an editor for the value of the selected environment variable.
+        */
+       private void handleEnvEditButtonSelected() {
+               IStructuredSelection sel = (IStructuredSelection) environmentTable
+                               .getSelection();
+               EnvironmentVariable var = (EnvironmentVariable) sel.getFirstElement();
+               if (var == null) {
+                       return;
+               }
+               String originalName = var.getName();
+               String value = var.getValue();
+               MultipleInputDialog dialog = new MultipleInputDialog(getShell(),
+                               "Edit Environment Variable");
+               dialog.addTextField(NAME_LABEL, originalName, false);
+               dialog.addVariablesField(VALUE_LABEL, value, true);
+
+               if (dialog.open() != Window.OK) {
+                       return;
+               }
+               String name = dialog.getStringValue(NAME_LABEL);
+               value = dialog.getStringValue(VALUE_LABEL);
+               if (!originalName.equals(name)) {
+                       if (addVariable(new EnvironmentVariable(name, value))) {
+                               environmentTable.remove(var);
+                       }
+               } else {
+                       var.setValue(value);
+                       environmentTable.update(var, null);
+                       updateLaunchConfigurationDialog();
+               }
+       }
+
+       /**
+        * Removes the selected environment variable from the table.
+        */
+       private void handleEnvRemoveButtonSelected() {
+               IStructuredSelection sel = (IStructuredSelection) environmentTable
+                               .getSelection();
+               environmentTable.getControl().setRedraw(false);
+               for (Iterator i = sel.iterator(); i.hasNext();) {
+                       EnvironmentVariable var = (EnvironmentVariable) i.next();
+                       environmentTable.remove(var);
+               }
+               environmentTable.getControl().setRedraw(true);
+               updateAppendReplace();
+               updateLaunchConfigurationDialog();
+       }
+
+       /**
+        * Updates the environment table for the given launch configuration
+        * 
+        * @param configuration
+        */
+       protected void updateEnvironment(ILaunchConfiguration configuration) {
+               environmentTable.setInput(configuration);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+        */
+       public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+        */
+       public void initializeFrom(ILaunchConfiguration configuration) {
+               boolean append = true;
+               try {
+                       append = configuration.getAttribute(
+                                       ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
+               } catch (CoreException e) {
+                       XDebugCorePlugin.log(e.getStatus());
+               }
+               if (append) {
+                       appendEnvironment.setSelection(true);
+                       replaceEnvironment.setSelection(false);
+               } else {
+                       replaceEnvironment.setSelection(true);
+                       appendEnvironment.setSelection(false);
+               }
+               updateEnvironment(configuration);
+               updateAppendReplace();
+       }
+
+       /**
+        * Stores the environment in the given configuration
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+        */
+       public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+               // Convert the table's items into a Map so that this can be saved in the
+               // configuration's attributes.
+               TableItem[] items = environmentTable.getTable().getItems();
+               Map map = new HashMap(items.length);
+               for (int i = 0; i < items.length; i++) {
+                       EnvironmentVariable var = (EnvironmentVariable) items[i].getData();
+                       map.put(var.getName(), var.getValue());
+               }
+               if (map.size() == 0) {
+                       configuration.setAttribute(
+                                       ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, (Map) null);
+               } else {
+                       configuration.setAttribute(
+                                       ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, map);
+               }
+               configuration.setAttribute(
+                               ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES,
+                               appendEnvironment.getSelection());
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+        */
+       public String getName() {
+               return "Environment";
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+        */
+       public Image getImage() {       
+               return XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_EVIEW_ENVIROMENT_TAB);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#activated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+        */
+       public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
+               // do nothing when activated
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#deactivated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+        */
+       public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) {
+               // do nothing when deactivated
+       }
+
+       private class NativeEnvironmentDialog extends ListSelectionDialog {
+               public NativeEnvironmentDialog(Shell parentShell, Object input,
+                               IStructuredContentProvider contentProvider,
+                               ILabelProvider labelProvider, String message) {
+                       super(parentShell, input, contentProvider, labelProvider, message);
+                       setShellStyle(getShellStyle() | SWT.RESIZE);
+               }
+
+               protected IDialogSettings getDialogSettings() {
+                       IDialogSettings settings = XDebugCorePlugin.getDefault()
+                                       .getDialogSettings();
+                       IDialogSettings section = settings
+                                       .getSection(getDialogSettingsSectionName());
+                       if (section == null) {
+                               section = settings
+                                               .addNewSection(getDialogSettingsSectionName());
+                       }
+                       return section;
+               }
+
+               /**
+                * Returns the name of the section that this dialog stores its settings
+                * in
+                * 
+                * @return String
+                */
+               protected String getDialogSettingsSectionName() {
+                       return IDebugUIConstants.PLUGIN_ID
+                                       + ".ENVIRONMENT_TAB.NATIVE_ENVIROMENT_DIALOG"; //$NON-NLS-1$
+               }
+
+               // /* (non-Javadoc)
+               // * @see
+               // org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
+               // */
+               // protected Point getInitialLocation(Point initialSize) {
+               // Point initialLocation=
+               // DialogSettingsHelper.getInitialLocation(getDialogSettingsSectionName());
+               // if (initialLocation != null) {
+               // return initialLocation;
+               // }
+               // return super.getInitialLocation(initialSize);
+               // }
+
+               // /* (non-Javadoc)
+               // * @see org.eclipse.jface.window.Window#getInitialSize()
+               // */
+               // protected Point getInitialSize() {
+               //              Point size = super.getInitialSize();
+               //              return DialogSettingsHelper.getInitialSize(getDialogSettingsSectionName(), size);
+               //              }
+
+               //              /* (non-Javadoc)
+               //              * @see org.eclipse.jface.window.Window#close()
+               //              */
+               //              public boolean close() {
+               //              DialogSettingsHelper.persistShellGeometry(getShell(), getDialogSettingsSectionName());
+               //              return super.close();
+               //              }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPMainTab.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPMainTab.java
new file mode 100644 (file)
index 0000000..03e5e3e
--- /dev/null
@@ -0,0 +1,323 @@
+package net.sourceforge.phpeclipse.xdebug.ui.php.launching;
+
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileSelector;
+import net.sourceforge.phpdt.internal.ui.util.PHPProjectSelector;
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+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.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+
+public class PHPMainTab extends AbstractLaunchConfigurationTab {
+
+       // Project UI widgets
+       protected Text fProjText;
+       protected Button fProjButton;
+
+       // Main class UI widgets
+       protected Text fMainText;
+       protected Button fSearchButton;
+       protected PHPProjectSelector projectSelector;
+       protected PHPFileSelector fileSelector;
+       private Button fUseDefaultInterpreterButton;
+       private Button fInterpreterButton;
+       private Text fInterpreterText;
+       private Label fInterpreterLabel;
+
+       public PHPMainTab() {
+               super();
+       }
+
+       public void createControl(Composite parent) {
+               Font font = parent.getFont();
+               
+               Composite comp = new Composite(parent, SWT.NONE);
+               setControl(comp);
+//             PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_MAIN_TAB);
+               GridLayout topLayout = new GridLayout();
+               topLayout.verticalSpacing = 0;
+               comp.setLayout(topLayout);
+               comp.setFont(font);
+               
+               createProjectEditor(comp);
+               createVerticalSpacer(comp, 1);
+               createMainTypeEditor(comp);
+               createVerticalSpacer(comp, 1);
+               createInterpreterEditor(comp);
+       }
+       
+       /**
+        * Creates the widgets for specifying a main type.
+        * 
+        * @param parent the parent composite
+        */
+       private void createProjectEditor(Composite parent) {
+               Font font= parent.getFont();
+               Group group= new Group(parent, SWT.NONE);
+               group.setText("Project:");
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               group.setLayoutData(gd);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               group.setLayout(layout);
+               group.setFont(font);
+
+               projectSelector = new PHPProjectSelector(group);
+               projectSelector.setBrowseDialogMessage("Choose the project containing the application entry point:");
+               projectSelector.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               projectSelector.addModifyListener(new ModifyListener() {
+                       public void modifyText(ModifyEvent evt) {
+                               updateLaunchConfigurationDialog();
+                       }
+               });
+       }       
+
+       
+       /**
+        * Creates the widgets for specifying a php file.
+        * 
+        * @param parent the parent composite
+        */
+       private void createMainTypeEditor(Composite parent) {
+               Font font= parent.getFont();
+               Group mainGroup= new Group(parent, SWT.NONE);
+               mainGroup.setText("File: "); 
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               mainGroup.setLayoutData(gd);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               mainGroup.setLayout(layout);
+               mainGroup.setFont(font);
+
+               fileSelector = new PHPFileSelector(mainGroup, projectSelector);
+               fileSelector.setBrowseDialogMessage("Choose the PHP file that represents the application entry point:");
+               fileSelector.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               fileSelector.addModifyListener(new ModifyListener() {
+                       public void modifyText(ModifyEvent evt) {
+                               updateLaunchConfigurationDialog();
+                       }
+               });
+       }
+       
+       /**
+        * Creates the widgets for specifying debug settings.
+        * 
+        * @param parent the parent composite
+        */
+       private void createInterpreterEditor(Composite parent) {
+               Font font= parent.getFont();
+               Group interpreterGroup= new Group(parent, SWT.NONE);
+               interpreterGroup.setText("Interpreter: "); 
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               interpreterGroup.setLayoutData(gd);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               interpreterGroup.setLayout(layout);
+               interpreterGroup.setFont(font);
+               
+//             fInterpreterLabel= new Label(interpreterGroup, SWT.NONE);
+//             fInterpreterLabel.setText("Interpreter: "); 
+//             gd= new GridData();
+//             gd.horizontalSpan = 2;
+//             fInterpreterLabel.setLayoutData(gd);
+//             fInterpreterLabel.setFont(font);
+               
+               fInterpreterText= new Text(interpreterGroup, SWT.SINGLE | SWT.BORDER);
+               gd= new GridData(GridData.FILL_HORIZONTAL);
+               fInterpreterText.setLayoutData(gd);
+               fInterpreterText.setFont(font);
+               fInterpreterText.addModifyListener(new ModifyListener() {
+                       public void modifyText(ModifyEvent evt) {
+                               updateLaunchConfigurationDialog();
+                       }
+               });
+
+               
+               fInterpreterButton= createPushButton(interpreterGroup,"Browse..", null);
+               fInterpreterButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleBrowseSellected(event);
+                       }
+               });
+               
+               fUseDefaultInterpreterButton = new Button(interpreterGroup,SWT.CHECK);
+               fUseDefaultInterpreterButton.setText("Use default interpreter");
+               gd = new GridData(GridData.FILL_HORIZONTAL);
+               fUseDefaultInterpreterButton.setLayoutData(gd);
+               fUseDefaultInterpreterButton.setFont(font);
+               fUseDefaultInterpreterButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent event) {
+                               handleDefaultSellected(event);
+                       }
+               });
+
+       }
+       
+       /**
+        * Set the appropriate enabled state for the appletviewqer text widget.
+        */
+       protected void setInterpreterTextEnabledState() {
+               if (isDefaultInterpreter()) {
+                       fInterpreterText.setEnabled(false);
+                       fInterpreterButton.setEnabled(false);
+               } else {
+                       fInterpreterText.setEnabled(true);
+                       fInterpreterButton.setEnabled(true);
+               }
+       }
+       
+       /**
+        * Returns whether the default appletviewer is to be used
+        */
+       protected boolean isDefaultInterpreter() {
+               return fUseDefaultInterpreterButton.getSelection();
+       }
+
+
+
+       protected void handleDefaultSellected(SelectionEvent event) {
+               setInterpreterTextEnabledState();
+               updateLaunchConfigurationDialog();
+//             if (isDefaultInterpreter()) {
+//                     fInterpreterText.setText("default Interpreter");
+//             }
+
+       }
+
+       protected void handleBrowseSellected(SelectionEvent event) {
+               FileDialog dlg=new FileDialog(getShell(),SWT.OPEN);
+               String fileName=dlg.open();
+               if (fileName!=null) {
+                       fInterpreterText.setText(fileName);
+                       updateLaunchConfigurationDialog();
+               }
+       }
+
+       protected IProject getContext() {
+               IWorkbenchPage page= XDebugCorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
+               if (page != null) {
+                       ISelection selection = page.getSelection();
+                       if (selection instanceof IStructuredSelection) {
+                               IStructuredSelection ss = (IStructuredSelection) selection;
+                               if (!ss.isEmpty()) {
+                                       Object obj = ss.getFirstElement();
+                                       if (obj instanceof IResource)
+                                               return ((IResource) obj).getProject();
+                               }
+                       }
+                       IEditorPart part = page.getActiveEditor();
+                       if (part != null) {
+                               IEditorInput input = part.getEditorInput();
+                               IResource file = (IResource) input.getAdapter(IResource.class);
+                               if (file != null) {
+                                       return file.getProject();
+                               }
+                       }
+               }
+               return null;
+       }
+
+       public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+               IProject project = getContext();
+               if (project != null)
+                       configuration.setAttribute(IXDebugConstants.ATTR_PHP_PROJECT, project.getName());
+       }
+
+
+       public void initializeFrom(ILaunchConfiguration configuration) {
+               try {
+                       String project = configuration.getAttribute(IXDebugConstants.ATTR_PHP_PROJECT, (String)null);
+                       if (project != null) {
+                       projectSelector.setSelectionText(project);
+                       }
+                       String file = configuration.getAttribute(IXDebugConstants.ATTR_PHP_FILE, (String)null);
+                       if (file != null) {
+                               fileSelector.setSelectionText(file);
+                       }
+                       
+                       String interpreterFile=configuration.getAttribute(IXDebugConstants.ATTR_PHP_INTERPRETER, (String) null);
+                       if(interpreterFile!=null)
+                               fInterpreterText.setText(interpreterFile);
+                       boolean selection=configuration.getAttribute(IXDebugConstants.ATTR_PHP_DEFAULT_INTERPRETER, true);
+                       fUseDefaultInterpreterButton.setSelection(selection);
+                       setInterpreterTextEnabledState();
+
+               } catch (CoreException e) {
+                       setErrorMessage(e.getMessage());
+               }
+       }
+
+       public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+               String project = projectSelector.getSelectionText().trim();
+               if (project.length() == 0) {
+                       project = null;
+               }
+               configuration.setAttribute(IXDebugConstants.ATTR_PHP_PROJECT, project);
+
+               IFile file = fileSelector.getSelection();
+               configuration.setAttribute(IXDebugConstants.ATTR_PHP_FILE, file == null ? "" : file.getProjectRelativePath()
+                               .toString());
+               configuration.setAttribute(IXDebugConstants.ATTR_PHP_DEFAULT_INTERPRETER, this.fUseDefaultInterpreterButton.getSelection());
+               configuration.setAttribute(IXDebugConstants.ATTR_PHP_INTERPRETER, this.fInterpreterText.getText());
+
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+        */
+       public boolean isValid(ILaunchConfiguration launchConfig) {
+               try {
+
+                       String projectName = launchConfig.getAttribute(IXDebugConstants.ATTR_PHP_PROJECT, "");
+                       if (projectName.length() == 0) {
+                               setErrorMessage("Iinvalid Project");
+                               return false;
+                       }
+
+                       String fileName = launchConfig.getAttribute(IXDebugConstants.ATTR_PHP_FILE, "");
+                       if (fileName.length() == 0) {
+                               setErrorMessage("Invalid File");
+                               return false;
+                       }
+               } catch (CoreException e) {
+//                     XDebugCorePlugin.log(e);
+               }
+
+               setErrorMessage(null);
+               return super.isValid(launchConfig);
+       }
+       public Image getImage() {
+               return PHPUiImages.get(PHPUiImages.IMG_CTOOLS_PHP_PAGE);
+       }
+       
+       public String getName() {
+               return "Main";
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPTabGroup.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/launching/PHPTabGroup.java
new file mode 100644 (file)
index 0000000..772df58
--- /dev/null
@@ -0,0 +1,20 @@
+package net.sourceforge.phpeclipse.xdebug.ui.php.launching;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
+
+public class PHPTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+
+       public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+               setTabs(new ILaunchConfigurationTab[] {
+                               new PHPMainTab(),
+                               new SourceLookupTab(),
+                               new PHPEnvironmentTab(),
+                               new CommonTab()
+               });
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPBreakpointAdapterFactory.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPBreakpointAdapterFactory.java
new file mode 100644 (file)
index 0000000..1124273
--- /dev/null
@@ -0,0 +1,19 @@
+package net.sourceforge.phpeclipse.xdebug.ui.php.model;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
+
+public class PHPBreakpointAdapterFactory implements IAdapterFactory {
+
+       public Object getAdapter(Object adaptableObject, Class adapterType) {
+               if (adapterType == IToggleBreakpointsTarget.class) {
+                       return new PHPLineBreakpointAdapter();
+               }
+               return null;
+       }
+
+       public Class[] getAdapterList() {
+               return new Class[]{IToggleBreakpointsTarget.class};
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPLineBreakpointAdapter.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/php/model/PHPLineBreakpointAdapter.java
new file mode 100644 (file)
index 0000000..e2a5415
--- /dev/null
@@ -0,0 +1,73 @@
+package net.sourceforge.phpeclipse.xdebug.ui.php.model;
+
+import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugLineBreakpoint;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class PHPLineBreakpointAdapter implements IToggleBreakpointsTarget {
+
+       public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection)
+                       throws CoreException {
+               IEditorPart editorPart = (IEditorPart)part;
+
+               IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class);
+               ITextSelection textSelection = (ITextSelection) selection;
+               int lineNumber = textSelection.getStartLine()+1;
+               IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(IXDebugConstants.ID_PHP_DEBUG_MODEL);
+               for (int i = 0; i < breakpoints.length; i++) {
+                       IBreakpoint breakpoint = breakpoints[i];
+                       if (resource.equals(breakpoint.getMarker().getResource())) {
+                               if (((ILineBreakpoint)breakpoint).getLineNumber() == (lineNumber )) {
+                                               // remove
+                                       breakpoint.delete();
+                                       return;
+                               }
+                       }
+               }
+                       // create line breakpoint (doc line numbers start at 0)
+               XDebugLineBreakpoint lineBreakpoint = new XDebugLineBreakpoint(resource, lineNumber);
+//             DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(lineBreakpoint);
+               
+       }
+
+       public boolean canToggleLineBreakpoints(IWorkbenchPart part,
+                       ISelection selection) {
+               // TODO Auto-generated method stub
+               return true;
+       }
+
+       public void toggleMethodBreakpoints(IWorkbenchPart part,
+                       ISelection selection) throws CoreException {
+               // TODO Auto-generated method stub
+
+       }
+
+       public boolean canToggleMethodBreakpoints(IWorkbenchPart part,
+                       ISelection selection) {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public void toggleWatchpoints(IWorkbenchPart part, ISelection selection)
+                       throws CoreException {
+               // TODO Auto-generated method stub
+
+       }
+
+       public boolean canToggleWatchpoints(IWorkbenchPart part,
+                       ISelection selection) {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/preference/XDebugPreferencePage.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/preference/XDebugPreferencePage.java
new file mode 100644 (file)
index 0000000..58580b8
--- /dev/null
@@ -0,0 +1,52 @@
+package net.sourceforge.phpeclipse.xdebug.ui.preference;
+
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.FileFieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.IntegerFieldEditor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class XDebugPreferencePage extends FieldEditorPreferencePage implements
+               IWorkbenchPreferencePage {
+
+       /* Preference page for the default XDebug-Settings */
+       
+       public XDebugPreferencePage() {
+               super(FieldEditorPreferencePage.GRID);
+
+               // Set the preference store for the preference page.
+               IPreferenceStore store =
+                       XDebugCorePlugin.getDefault().getPreferenceStore();
+               store.setDefault(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE,IXDebugPreferenceConstants.DEFAULT_DEBUGPORT);
+               // get the default form the externalToolsPlugin 
+               String interpreter=ExternalToolsPlugin.getDefault().getPreferenceStore().getString(ExternalToolsPlugin.PHP_RUN_PREF);
+               store.setDefault(IXDebugPreferenceConstants.PHP_INTERPRETER_PREFERENCE,interpreter);
+               setPreferenceStore(store);
+       }
+
+       public void init(IWorkbench workbench) {
+               setDescription("Default Entries for XDebug:");
+       }
+
+       protected void createFieldEditors() {
+               IntegerFieldEditor debugPort = new IntegerFieldEditor(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE, "&Debugport:", getFieldEditorParent(),5);
+               debugPort.setValidRange(1025,65535);
+               debugPort.setErrorMessage("Debugport must be between 1024 and 65536");
+               addField(debugPort);
+               
+               FileFieldEditor phpInterpreter = new FileFieldEditor(IXDebugPreferenceConstants.PHP_INTERPRETER_PREFERENCE, "PHP &Interpreter:",true,getFieldEditorParent());
+           phpInterpreter.setErrorMessage("File not found");
+               addField(phpInterpreter);
+               
+       }
+
+
+
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialog.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialog.java
new file mode 100644 (file)
index 0000000..afd7581
--- /dev/null
@@ -0,0 +1,630 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.Collator;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPluginImages;
+
+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.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableTreeViewer;
+import org.eclipse.swt.SWT;
+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.graphics.Image;
+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.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+public class EventDetailsDialog extends Dialog {
+       private LogEntry entry, parentEntry;
+       private LogViewLabelProvider labelProvider;
+       private static int COPY_ID = 22;
+       private TableTreeViewer provider;
+       private int elementNum, totalElementCount;
+       private LogEntry[] entryChildren;
+       private int childIndex = 0;
+       private boolean isOpen;
+       
+       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 Image imgNextEnabled;
+       private Image imgPrevEnabled;
+       private Image imgCopyEnabled;
+       private SashForm sashForm;
+       
+       // sorting
+       private static int ASCENDING = 1;
+       private Comparator comparator = null;
+       private Collator collator;
+       
+       // location configuration
+       private IDialogSettings dialogSettings;
+       private Point dialogLocation;
+       private Point dialogSize;
+       private int[] sashWeights;
+       
+       // externalize strings
+       private String EVENT_NO_STACK = "EventDetailsDialog.noStack"; //$NON-NLS-1$
+       private String EVENT_PREVIOUS = "EventDetailsDialog.previous"; //$NON-NLS-1$
+       private String EVENT_NEXT = "EventDetailsDialog.next"; //$NON-NLS-1$
+       private String EVENT_COPY = "EventDetailsDialog.copy"; //$NON-NLS-1$
+
+       /**
+        * @param parentShell
+        *            shell in which dialog is displayed
+        */
+       protected EventDetailsDialog(Shell parentShell, IAdaptable selection, ISelectionProvider provider) {
+               super(parentShell);
+               labelProvider = new LogViewLabelProvider();
+               this.provider = (TableTreeViewer) provider;
+               this.entry = (LogEntry)selection;
+               setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
+               clipboard = new Clipboard(parentShell.getDisplay());
+               initialize();
+               createImages();
+               collator = Collator.getInstance();
+               readConfiguration();
+       }
+
+       private void initialize() {
+               elementNum = getParentElementNum();
+               totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
+               parentEntry = (LogEntry) entry.getParent(entry);
+               if (isChild(entry)){
+                       setEntryChildren(parentEntry);
+                       resetChildIndex();
+               }
+       }
+       
+       private void resetChildIndex(){
+               for (int i = 0; i<entryChildren.length; i++){
+                       if (entryChildren[i].getMessage().equals(entry.getMessage())
+                                       && entryChildren[i].getDate().equals(entry.getDate())
+                                       && entryChildren[i].getPluginId().equals(entry.getPluginId())
+                                       && entryChildren[i].getSeverity() == entry.getSeverity() 
+                                       && entryChildren[i].getSeverityText().equals(entry.getSeverityText())){
+                               childIndex = i;
+                               break;
+                       }
+               }
+       }
+       
+       private void createImages(){
+               imgCopyEnabled =
+                       PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY).createImage(
+                               true);
+               //imgNextDisabled. = PHPDegugCorePluginImages.DESC_NEXT_EVENT_DISABLED.createImage(true);
+               //imgPrevDisabled = PHPDegugCorePluginImages.DESC_PREV_EVENT_DISABLED.createImage(true);
+               imgPrevEnabled = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_PREV_EVENT);
+               imgNextEnabled = XDebugUIPluginImages.get(XDebugUIPluginImages.DESC_NEXT_EVENT);
+       }
+
+       private boolean isChild(LogEntry 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/2;
+                       sashWeights = new int[]{width, getSashForm().getClientArea().width-width};
+               }
+               getSashForm().setWeights(sashWeights);
+               return super.open();
+       }
+       
+       public boolean close() {
+               storeSettings();
+               isOpen = false;
+               imgCopyEnabled.dispose();
+               imgNextEnabled.dispose();
+               imgPrevEnabled.dispose();
+               return super.close();
+       }
+
+       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 (isChild(entry)) {
+                       if (childIndex > 0) {
+                               childIndex--;
+                               entry = entryChildren[childIndex];
+                       } else
+                               entry = parentEntry;
+               } else {
+                       if (elementNum - 1 >= 0)
+                               elementNum -= 1;
+                       entry = (LogEntry) provider.getElementAt(elementNum);
+               }
+               setEntrySelectionInTable();
+       }
+
+       protected void nextPressed() {
+               if (isChild(entry) && childIndex < entryChildren.length-1) {
+                       childIndex++;
+                       entry = entryChildren[childIndex];
+               } else if (elementNum + 1 < totalElementCount){
+                               elementNum += 1;
+                       entry = (LogEntry) provider.getElementAt(elementNum);
+               } else { // at end of list but can branch into child elements - bug 58083
+                       setEntryChildren(entry);
+                       entry = entryChildren[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) {
+               }
+               // set the clipboard contents
+               clipboard.setContents(new Object[] { textVersion }, new Transfer[] { TextTransfer.getInstance()});      
+       }
+
+       public void setComparator(Comparator comparator){
+               this.comparator = comparator;
+               updateProperties();
+       }
+       private void setComparator(byte sortType, final int sortOrder){
+               if (sortType == LogView.DATE){
+                       comparator = new Comparator(){
+                               public int compare(Object e1, Object e2) {
+                                       try {
+                                               SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
+                                               Date date1 = formatter.parse(((LogEntry)e1).getDate());
+                                               Date date2 = formatter.parse(((LogEntry)e2).getDate());
+                                               if (sortOrder == ASCENDING) 
+                                                       return date1.before(date2) ? -1 : 1;
+                                               return date1.after(date2) ? -1 : 1;
+                                       } catch (ParseException e) {
+                                       }
+                                       return 0;
+                               }
+                       };
+               } else if (sortType == LogView.PLUGIN){
+                       comparator = new Comparator(){
+                               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(){
+                               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) &&
+                               elementNum == getParentElementNum()){
+                       updateProperties();
+                       return;
+               }
+               entry = (LogEntry)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 = (LogEntry) entry.getParent(entry);
+                       setEntryChildren(parentEntry);
+                       resetChildIndex();
+               }
+
+
+               totalElementCount = provider.getTableTree().getTable().getItemCount() - getVisibleChildrenCount();
+               dateLabel.setText(entry.getDate());
+               severityImageLabel.setImage(labelProvider.getColumnImage(entry, 1));
+               severityLabel.setText(entry.getSeverityText());
+               msgText.setText(entry.getMessage());
+               String stack = entry.getStack();
+               if (stack != null) {
+                       stackTraceText.setText(stack);
+               } else {
+                       stackTraceText.setText(XDebugUIPlugin.getString(EVENT_NO_STACK));
+               }
+               LogSession session = entry.getSession();
+               if (session != null && session.getSessionData() != null)
+                       sessionDataText.setText(session.getSessionData());
+
+               updateButtons();
+       }
+       
+       private void updateButtons(){
+               boolean isAtEnd = elementNum == totalElementCount - 1;
+               if (isChild(entry)){
+                       backButton.setEnabled(true);
+                       boolean isLastChild = childIndex == entryChildren.length-1;
+                       nextButton.setEnabled(!isLastChild || !isAtEnd || entry.hasChildren());
+               } else {
+                       backButton.setEnabled(elementNum != 0);
+                       nextButton.setEnabled(!isAtEnd || entry.hasChildren());
+               }
+       }
+       
+       private void setEntryChildren(LogEntry parent){
+               Object[] children = parent.getChildren(parent);
+               if (comparator != null)
+                       Arrays.sort(children, comparator);
+               entryChildren = new LogEntry[children.length];
+               
+               System.arraycopy(children,0,entryChildren,0,children.length);
+       }
+       
+       private int getParentElementNum(){
+               LogEntry itemEntry = (LogEntry)((IStructuredSelection)provider.getSelection()).getFirstElement();
+               itemEntry = getRootEntry(itemEntry);
+               
+               for (int i = 0; i<provider.getTableTree().getItemCount(); i++){
+                       try {
+                               LogEntry littleEntry = (LogEntry)provider.getElementAt(i);
+                               if (itemEntry.equals(littleEntry)){
+                                       return i;
+                               }
+                       } catch (Exception e){
+                               
+                       }
+               }
+               return 0;
+       }
+       private LogEntry getRootEntry(LogEntry entry){
+               if (!isChild(entry))
+                       return entry;
+               return getRootEntry((LogEntry)entry.getParent(entry));
+       }
+       public SashForm getSashForm(){
+               return sashForm;
+       }
+       private int getVisibleChildrenCount(){
+               Object[] elements = provider.getVisibleExpandedElements();
+               LogEntry[] expandedElements = new LogEntry[elements.length];
+               System.arraycopy(elements, 0, expandedElements, 0, elements.length);
+               int count = 0;
+               for (int i = 0; i<expandedElements.length; i++){
+                       count += expandedElements[i].getChildren(expandedElements[i]).length;
+               }
+               return count;
+       }
+       
+       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);
+               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));
+
+               Composite container = new Composite(comp, SWT.NONE);
+               layout = new GridLayout();
+               layout.marginWidth = 0;
+               layout.marginHeight = 10;
+               layout.numColumns = 1;
+               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);
+               gd.horizontalSpan = 3;
+               gd.verticalSpan = 1;
+               backButton.setLayoutData(gd);
+               backButton.setToolTipText(XDebugUIPlugin.getString(EVENT_PREVIOUS));
+               backButton.setImage(imgPrevEnabled);
+               
+               nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
+               gd = new GridData();
+               gd.horizontalSpan = 3;
+               gd.verticalSpan = 1;
+               nextButton.setLayoutData(gd);
+               nextButton.setToolTipText(XDebugUIPlugin.getString(EVENT_NEXT));
+               nextButton.setImage(imgNextEnabled);
+               
+               copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
+               gd = new GridData();
+               gd.horizontalSpan = 3;
+               gd.verticalSpan = 1;
+               copyButton.setLayoutData(gd);
+               copyButton.setImage(imgCopyEnabled);
+               copyButton.setToolTipText(XDebugUIPlugin.getString(EVENT_COPY));
+       }
+
+       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.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(XDebugUIPlugin.getString("EventDetailsDialog.date")); //$NON-NLS-1$
+               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(XDebugUIPlugin.getString("EventDetailsDialog.severity")); //$NON-NLS-1$
+               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(XDebugUIPlugin.getString("EventDetailsDialog.message")); //$NON-NLS-1$
+               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.verticalSpan = 8;
+               gd.grabExcessVerticalSpace = true;
+               msgText.setLayoutData(gd);
+       }
+
+       private void createStackSection(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_BOTH);
+               gd.heightHint = 100;
+               container.setLayoutData(gd);
+
+               Label label = new Label(container, SWT.NULL);
+               label.setText(XDebugUIPlugin.getString("EventDetailsDialog.exception")); //$NON-NLS-1$
+               gd = new GridData(GridData.FILL_HORIZONTAL);
+               gd.horizontalSpan = 3;
+               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;
+               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(XDebugUIPlugin.getString("EventDetailsDialog.session")); //$NON-NLS-1$
+               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);
+       }
+       
+       //--------------- 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= XDebugCorePlugin.getDefault().getDialogSettings();
+               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[2];
+                       sashWeights[0] = s.getInt("sashWidth1"); //$NON-NLS-1$
+                       sashWeights[1] = 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("sashWidth1", sashWeights[0]); //$NON-NLS-1$
+               s.put("sashWidth2", sashWeights[1]); //$NON-NLS-1$
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialogAction.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/EventDetailsDialogAction.java
new file mode 100644 (file)
index 0000000..b8fb788
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.util.Comparator;
+
+
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.SelectionProviderAction;
+
+
+
+public class EventDetailsDialogAction extends SelectionProviderAction{
+
+       /**
+        * The shell in which to open the property dialog
+        */
+       private Shell shell;
+       private ISelectionProvider provider;
+       private EventDetailsDialog propertyDialog;
+       private Comparator comparator;
+       /**
+        * Creates a new action for opening a property dialog
+        * on the elements from the given selection provider
+        * @param shell - the shell in which the dialog will open
+        * @param provider - the selection provider whose elements
+        * the property dialog will describe
+        */
+       public EventDetailsDialogAction(Shell shell, ISelectionProvider provider){
+       super(provider, "Test Text"); 
+               Assert.isNotNull(shell);
+               this.shell = shell;
+               this.provider = provider;
+               // setToolTipText
+               //WorkbenchHelp.setHelp
+       }
+       
+       public boolean resetSelection(byte sortType, int sortOrder){
+               IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+               if (element == null)
+                       return false;
+               if (propertyDialog != null && propertyDialog.isOpen()){
+                       propertyDialog.resetSelection(element, sortType, sortOrder);
+                       return true;
+               }
+               return false;
+       }
+       public void resetSelection(){
+               IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+               if (element == null)
+                       return;
+               if (propertyDialog != null && propertyDialog.isOpen())
+                       propertyDialog.resetSelection(element);
+       }
+       
+       public void resetDialogButtons(){
+               if (propertyDialog != null && propertyDialog.isOpen())
+                       propertyDialog.resetButtons();
+       }
+       
+       public void setComparator(Comparator comparator){
+               this.comparator = comparator;
+       }
+       public void run(){
+               if (propertyDialog != null && propertyDialog.isOpen()){
+                       resetSelection();
+                       return;
+               }
+               
+               //get initial selection
+               IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+               if (element == null)
+                       return;
+               
+               propertyDialog = new EventDetailsDialog(shell, element, provider);
+               propertyDialog.create();
+               propertyDialog.getShell().setText(XDebugUIPlugin.getString("EventDetailsDialog.title")); //$NON-NLS-1$
+               propertyDialog.setComparator(comparator);
+               propertyDialog.open();
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/FilterDialog.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/FilterDialog.java
new file mode 100644 (file)
index 0000000..57b8828
--- /dev/null
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IMemento;
+
+
+public class FilterDialog extends Dialog {
+       private Button limit;
+       private Text limitText;
+
+       private Button okButton;
+       private Button errorButton;
+       private Button warningButton;
+       private Button infoButton;
+       private Button showAllButton;
+       private IMemento memento;
+
+       public FilterDialog(Shell parentShell, IMemento memento) {
+               super(parentShell);
+               this.memento = memento;
+       }
+       
+       protected Control createDialogArea(Composite parent) {
+               Composite container = (Composite)super.createDialogArea(parent);                
+               createEventTypesGroup(container);
+               createLimitSection(container);
+               createSessionSection(container);
+               
+               Dialog.applyDialogFont(container);
+               return container;
+       }
+       
+       private void createEventTypesGroup(Composite parent) {
+               Group group = new Group(parent, SWT.NONE);
+               group.setLayout(new GridLayout());
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               gd.widthHint = 275;
+               group.setLayoutData(gd);
+               group.setText(XDebugUIPlugin.getString("LogView.FilterDialog.eventTypes")); //$NON-NLS-1$
+               
+               infoButton = new Button(group, SWT.CHECK);
+               infoButton.setText(XDebugUIPlugin.getString("LogView.FilterDialog.information")); //$NON-NLS-1$
+               infoButton.setSelection(memento.getString(LogView.P_LOG_INFO).equals("true")); //$NON-NLS-1$
+               
+               warningButton = new Button(group, SWT.CHECK);
+               warningButton.setText(XDebugUIPlugin.getString("LogView.FilterDialog.warning")); //$NON-NLS-1$
+               warningButton.setSelection(memento.getString(LogView.P_LOG_WARNING).equals("true")); //$NON-NLS-1$
+               
+               errorButton = new Button(group, SWT.CHECK);
+               errorButton.setText(XDebugUIPlugin.getString("LogView.FilterDialog.error")); //$NON-NLS-1$
+               errorButton.setSelection(memento.getString(LogView.P_LOG_ERROR).equals("true"));                 //$NON-NLS-1$
+       }
+       
+       private void createLimitSection(Composite parent) {
+               Composite comp = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               comp.setLayout(layout);
+               comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               
+               limit = new Button(comp, SWT.CHECK);
+               limit.setText(XDebugUIPlugin.getString("LogView.FilterDialog.limitTo")); //$NON-NLS-1$
+               limit.setSelection(memento.getString(LogView.P_USE_LIMIT).equals("true")); //$NON-NLS-1$
+               limit.addSelectionListener(new SelectionAdapter() {
+               public void widgetSelected(SelectionEvent e) {
+                       limitText.setEnabled(((Button)e.getSource()).getSelection());
+               }});
+               
+               limitText = new Text(comp, SWT.BORDER);
+               limitText.addModifyListener(new ModifyListener(){
+                       public void modifyText(ModifyEvent e) {
+                               try {
+                                       if (okButton == null)
+                                               return;
+                                       Integer.parseInt(limitText.getText());
+                                       okButton.setEnabled(true);
+                               } catch (NumberFormatException e1) {
+                                       okButton.setEnabled(false);
+                               }
+                       }});
+               limitText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               limitText.setText(memento.getString(LogView.P_LOG_LIMIT));
+               limitText.setEnabled(limit.getSelection());
+
+       }
+       
+       private void createSessionSection(Composite parent) {
+               Composite container = new Composite(parent, SWT.NONE);
+               container.setLayout(new GridLayout());
+               container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               
+               Label label = new Label(container, SWT.NONE);
+               label.setText(XDebugUIPlugin.getString("LogView.FilterDialog.eventsLogged")); //$NON-NLS-1$
+               
+               showAllButton = new Button(container, SWT.RADIO);
+               showAllButton.setText(XDebugUIPlugin.getString("LogView.FilterDialog.allSessions")); //$NON-NLS-1$
+               GridData gd = new GridData();
+               gd.horizontalIndent = 20;
+               showAllButton.setLayoutData(gd);
+               
+               Button button = new Button(container, SWT.RADIO);
+               button.setText(XDebugUIPlugin.getString("LogView.FilterDialog.recentSession")); //$NON-NLS-1$
+               gd = new GridData();
+               gd.horizontalIndent = 20;
+               button.setLayoutData(gd);
+               
+               if (memento.getString(LogView.P_SHOW_ALL_SESSIONS).equals("true")) { //$NON-NLS-1$
+                       showAllButton.setSelection(true);
+               } else {
+                       button.setSelection(true);
+               }
+       }
+       
+       protected void createButtonsForButtonBar(Composite parent) {
+               okButton = createButton(
+                               parent,
+                               IDialogConstants.OK_ID,
+                               IDialogConstants.OK_LABEL,
+                               true);
+               createButton(
+                       parent,
+                       IDialogConstants.CANCEL_ID,
+                       IDialogConstants.CANCEL_LABEL,
+                       false);
+       }
+       
+       protected void okPressed() {
+               memento.putString(LogView.P_LOG_INFO, infoButton.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+               memento.putString(LogView.P_LOG_WARNING, warningButton.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+               memento.putString(LogView.P_LOG_ERROR, errorButton.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+               memento.putString(LogView.P_LOG_LIMIT, limitText.getText());
+               memento.putString(LogView.P_USE_LIMIT, limit.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+               memento.putString(LogView.P_SHOW_ALL_SESSIONS, showAllButton.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+               super.okPressed();
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogEntry.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogEntry.java
new file mode 100644 (file)
index 0000000..b492240
--- /dev/null
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+public class LogEntry extends PlatformObject implements IWorkbenchAdapter {
+       private static final String KEY_ERROR = "LogView.severity.error"; //$NON-NLS-1$
+       private static final String KEY_WARNING = "LogView.severity.warning"; //$NON-NLS-1$
+       private static final String KEY_INFO = "LogView.severity.info"; //$NON-NLS-1$
+       private ArrayList children;
+       private LogEntry parent;
+       private String pluginId;
+       private int severity;
+       private int code;
+       private String date;
+       private String message;
+       private String stack;
+       private LogSession session;
+
+       public LogEntry() {
+       }
+
+       public LogSession getSession() {
+               return session;
+       }
+
+       void setSession(LogSession session) {
+               this.session = session;
+       }
+
+       public LogEntry(IStatus status) {
+               processStatus(status);
+       }
+       public int getSeverity() {
+               return severity;
+       }
+
+       public boolean isOK() {
+               return severity == IStatus.OK;
+       }
+       public int getCode() {
+               return code;
+       }
+       public String getPluginId() {
+               return pluginId;
+       }
+       public String getMessage() {
+               return message;
+       }
+       public String getStack() {
+               return stack;
+       }
+       public String getDate() {
+               return date;
+       }
+       public String getSeverityText() {
+               return getSeverityText(severity);
+       }
+       public boolean hasChildren() {
+               return children != null && children.size() > 0;
+       }
+       public String toString() {
+               return getSeverityText();
+       }
+       /**
+        * @see IWorkbenchAdapter#getChildren(Object)
+        */
+       public Object[] getChildren(Object parent) {
+               if (children == null)
+                       return new Object[0];
+               return children.toArray();
+       }
+
+       /**
+        * @see IWorkbenchAdapter#getImageDescriptor(Object)
+        */
+       public ImageDescriptor getImageDescriptor(Object arg0) {
+               return null;
+       }
+
+       /**
+        * @see IWorkbenchAdapter#getLabel(Object)
+        */
+       public String getLabel(Object obj) {
+               return getSeverityText();
+       }
+
+       /**
+        * @see IWorkbenchAdapter#getParent(Object)
+        */
+       public Object getParent(Object obj) {
+               return parent;
+       }
+
+       void setParent(LogEntry parent) {
+               this.parent = parent;
+       }
+
+       private String getSeverityText(int severity) {
+               switch (severity) {
+                       case IStatus.ERROR :
+                               return XDebugUIPlugin.getString(KEY_ERROR);
+                       case IStatus.WARNING :
+                               return XDebugUIPlugin.getString(KEY_WARNING);
+                       case IStatus.INFO :
+                               return XDebugUIPlugin.getString(KEY_INFO);
+               }
+               return "?"; //$NON-NLS-1$
+       }
+
+       int processLogLine(String line, boolean root) {
+               //!ENTRY <pluginID> <severity> <code> <date>
+               //!SUBENTRY <depth> <pluginID> <severity> <code> <date>
+               StringTokenizer stok = new StringTokenizer(line, " ", true); //$NON-NLS-1$
+               StringBuffer dateBuffer = new StringBuffer();
+
+               int dateCount = 5;
+               int depth = 0;
+               for (int i = 0; stok.hasMoreTokens();) {
+                       String token = stok.nextToken();
+                       if (i >= dateCount) {
+                               dateBuffer.append(token);
+                               continue;
+                       } else if (token.equals(" ")) //$NON-NLS-1$
+                               continue;
+                       switch (i) {
+                               case 0 : // entry or subentry
+                                       if (root)
+                                               i += 2;
+                                       else
+                                               i++;
+                                       break;
+                               case 1 : // depth
+                                       depth = parseInteger(token);
+                                       i++;
+                                       break;
+                               case 2 :
+                                       pluginId = token;
+                                       i++;
+                                       break;
+                               case 3 : // severity
+                                       severity = parseInteger(token);
+                                       i++;
+                                       break;
+                               case 4 : // code
+                                       code = parseInteger(token);
+                                       i++;
+                                       break;
+                       }
+               }
+               date = dateBuffer.toString().trim();
+               return depth;
+       }
+
+       private int parseInteger(String token) {
+               try {
+                       return Integer.parseInt(token);
+               } catch (NumberFormatException e) {
+                       return 0;
+               }
+       }
+
+       void setStack(String stack) {
+               this.stack = stack;
+       }
+       void setMessage(String message) {
+               this.message = message;
+       }
+
+       private void processStatus(IStatus status) {
+               pluginId = status.getPlugin();
+               severity = status.getSeverity();
+               code = status.getCode();
+               DateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
+               date = formatter.format(new Date());
+               message = status.getMessage();
+               Throwable throwable = status.getException();
+               if (throwable != null) {
+                       StringWriter swriter = new StringWriter();
+                       PrintWriter pwriter = new PrintWriter(swriter);
+                       throwable.printStackTrace(pwriter);
+                       pwriter.flush();
+                       pwriter.close();
+                       stack = swriter.toString();
+               }
+               IStatus[] schildren = status.getChildren();
+               if (schildren.length > 0) {
+                       children = new ArrayList();
+                       for (int i = 0; i < schildren.length; i++) {
+                               LogEntry child = new LogEntry(schildren[i]);
+                               addChild(child);
+                       }
+               }
+       }
+       void addChild(LogEntry child) {
+               if (children == null)
+                       children = new ArrayList();
+               children.add(child);
+               child.setParent(this);
+       }
+       public void write(PrintWriter writer) {
+               writer.print(getSeverityText());
+               if (date != null) {
+                       writer.print(" "); //$NON-NLS-1$
+                       writer.print(getDate());
+               }
+               if (message != null) {
+                       writer.print(" "); //$NON-NLS-1$
+                       writer.print(getMessage());
+               }
+               writer.println();
+               if (stack != null)
+                       writer.println(stack);
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogReader.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogReader.java
new file mode 100644 (file)
index 0000000..7a33d18
--- /dev/null
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Date;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ui.IMemento;
+
+class LogReader {
+       private static final int SESSION_STATE = 10;
+       public static final long MAX_FILE_LENGTH = 1024*1024;
+       private static final int ENTRY_STATE = 20;
+       private static final int SUBENTRY_STATE = 30;
+       private static final int MESSAGE_STATE = 40;
+       private static final int STACK_STATE = 50;
+       private static final int TEXT_STATE = 60;
+       private static final int UNKNOWN_STATE = 70;
+       
+       private static LogSession currentSession;
+       
+       public static void parseLargeFile(File file, ArrayList entries, IMemento memento) {
+               ArrayList parents = new ArrayList();
+               LogEntry current = null;
+               LogSession session = null;
+               int writerState = UNKNOWN_STATE;
+               StringWriter swriter = null;
+               PrintWriter writer = null;
+               int state = UNKNOWN_STATE;
+               currentSession = null;
+               RandomAccessFile random = null;
+               try {
+                       random = new RandomAccessFile(file, "r"); //$NON-NLS-1$
+                       random.seek(file.length() - MAX_FILE_LENGTH);
+                       for (;;) {
+                               String line = random.readLine();
+                               if (line == null)
+                                       break;
+                               
+                               line = line.trim();
+                               if (line.length() == 0)
+                                       continue;
+
+                               if (line.startsWith("!SESSION")) { //$NON-NLS-1$
+                                       state = SESSION_STATE;
+                               } else if (line.startsWith("!ENTRY")) { //$NON-NLS-1$
+                                       state = ENTRY_STATE;
+                               } else if (line.startsWith("!SUBENTRY")) { //$NON-NLS-1$
+                                       state = SUBENTRY_STATE;
+                               } else if (line.startsWith("!MESSAGE")) { //$NON-NLS-1$
+                                       state = MESSAGE_STATE;
+                               } else if (line.startsWith("!STACK")) { //$NON-NLS-1$
+                                       state = STACK_STATE;
+                               } else
+                                       state = TEXT_STATE;
+                       
+                               if (state == TEXT_STATE) {
+                                       if (writer != null)
+                                               writer.println(line);
+                                       continue;
+                               }
+                       
+                               if (writer != null) {
+                                       if (writerState == STACK_STATE && current != null) {
+                                               current.setStack(swriter.toString());
+                                       } else if (writerState == SESSION_STATE && session != null) {
+                                               session.setSessionData(swriter.toString());
+                                       } else if (writerState == MESSAGE_STATE && current != null){
+                                               String message = current.getMessage() + swriter.toString();
+                                               message = message.trim();
+                                               current.setMessage(message);
+                                       }
+                                       writerState = UNKNOWN_STATE;
+                                       swriter = null;
+                                       writer.close();
+                                       writer = null;
+                               }
+                       
+                               if (state == STACK_STATE) {
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       writerState = STACK_STATE;
+                               } else if (state == SESSION_STATE) {
+                                       session = new LogSession();
+                                       session.processLogLine(line);
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       writerState = SESSION_STATE;
+                                       updateCurrentSession(session);
+                                       if (currentSession.equals(session) && !memento.getString(LogView.P_SHOW_ALL_SESSIONS).equals("true")) //$NON-NLS-1$
+                                               entries.clear();
+                               } else if (state == ENTRY_STATE) {
+                                       LogEntry entry = new LogEntry();
+                                       entry.setSession(session);
+                                       entry.processLogLine(line, true);
+                                       setNewParent(parents, entry, 0);
+                                       current = entry;
+                                       addEntry(current, entries, memento, false);
+                               } else if (state == SUBENTRY_STATE) {
+                                       LogEntry entry = new LogEntry();
+                                       entry.setSession(session);
+                                       int depth = entry.processLogLine(line, false);
+                                       setNewParent(parents, entry, depth);
+                                       current = entry;
+                                       LogEntry parent = (LogEntry) parents.get(depth - 1);
+                                       parent.addChild(entry);
+                               } else if (state == MESSAGE_STATE) {
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       String message = ""; //$NON-NLS-1$
+                                       if (line.length() > 8)
+                                               message = line.substring(9).trim();
+                                       message = message.trim();
+                                       if (current != null)
+                                               current.setMessage(message);
+                                       writerState = MESSAGE_STATE;
+                               }
+                       }
+               } catch (FileNotFoundException e) {
+               } catch (IOException e) {
+               } finally {
+                       try {
+                               if (random != null)
+                                       random.close();
+                       } catch (IOException e1) {
+                       }
+               }
+       }
+       
+       public static void parseLogFile(File file, ArrayList entries, IMemento memento) {
+               ArrayList parents = new ArrayList();
+               LogEntry current = null;
+               LogSession session = null;
+               int writerState = UNKNOWN_STATE;
+               StringWriter swriter = null;
+               PrintWriter writer = null;
+               int state = UNKNOWN_STATE;
+               currentSession = null;
+               BufferedReader reader = null;
+               try {
+                                       
+                       reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); //$NON-NLS-1$
+                       while(reader.ready()) {
+                               String line = reader.readLine();
+                               if (line == null)
+                                       continue;
+                               line = line.trim();
+                               if (line.length() == 0)
+                                       continue;
+
+                               if (line.startsWith("!SESSION")) { //$NON-NLS-1$
+                                       state = SESSION_STATE;
+                               } else if (line.startsWith("!ENTRY")) { //$NON-NLS-1$
+                                       state = ENTRY_STATE;
+                               } else if (line.startsWith("!SUBENTRY")) { //$NON-NLS-1$
+                                       state = SUBENTRY_STATE;
+                               } else if (line.startsWith("!MESSAGE")) { //$NON-NLS-1$
+                                       state = MESSAGE_STATE;
+                               } else if (line.startsWith("!STACK")) { //$NON-NLS-1$
+                                       state = STACK_STATE;
+                               } else
+                                       state = TEXT_STATE;
+                       
+                               if (state == TEXT_STATE) {
+                                       if (writer != null)
+                                               writer.println(line);
+                                       continue;
+                               }
+                       
+                               if (writer != null) {
+                                       if (writerState == STACK_STATE && current != null) {
+                                               current.setStack(swriter.toString());
+                                       } else if (writerState == SESSION_STATE && session != null) {
+                                               session.setSessionData(swriter.toString());
+                                       } else if (writerState == MESSAGE_STATE && current != null){
+                                               String message = current.getMessage() + swriter.toString();
+                                               message = message.trim();
+                                               current.setMessage(message);
+                                       }
+                                       writerState = UNKNOWN_STATE;
+                                       swriter = null;
+                                       writer.close();
+                                       writer = null;
+                               }
+                       
+                               if (state == STACK_STATE) {
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       writerState = STACK_STATE;
+                               } else if (state == SESSION_STATE) {
+                                       session = new LogSession();
+                                       session.processLogLine(line);
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       writerState = SESSION_STATE;
+                                       updateCurrentSession(session);
+                                       if (currentSession.equals(session) && !memento.getString(LogView.P_SHOW_ALL_SESSIONS).equals("true")) //$NON-NLS-1$
+                                               entries.clear();
+                               } else if (state == ENTRY_STATE) {
+                                       LogEntry entry = new LogEntry();
+                                       entry.setSession(session);
+                                       entry.processLogLine(line, true);
+                                       setNewParent(parents, entry, 0);
+                                       current = entry;
+                                       addEntry(current, entries, memento, false);
+                               } else if (state == SUBENTRY_STATE) {
+                                       LogEntry entry = new LogEntry();
+                                       entry.setSession(session);
+                                       int depth = entry.processLogLine(line, false);
+                                       setNewParent(parents, entry, depth);
+                                       current = entry;
+                                       LogEntry parent = (LogEntry) parents.get(depth - 1);
+                                       parent.addChild(entry);
+                               } else if (state == MESSAGE_STATE) {
+                                       swriter = new StringWriter();
+                                       writer = new PrintWriter(swriter, true);
+                                       String message = ""; //$NON-NLS-1$
+                                       if (line.length() > 8)
+                                               message = line.substring(9).trim();
+                                       message = message.trim();
+                                       if (current != null)
+                                               current.setMessage(message);
+                                       writerState = MESSAGE_STATE;
+                               }
+                       }
+               } catch (FileNotFoundException e) {
+               } catch (IOException e) {
+               } finally {
+                       try {
+                               if (reader != null)
+                                       reader.close();
+                       } catch (IOException e1) {
+                       }
+               }
+       }
+               
+       private static void updateCurrentSession(LogSession session) {
+               if (currentSession == null) {
+                       currentSession = session;
+                       return;
+               }               
+               Date currentDate = currentSession.getDate();
+               Date sessionDate = session.getDate();           
+               if (currentDate == null && sessionDate != null)
+                       currentSession = session;
+               else if (currentDate != null && sessionDate == null)
+                       currentSession = session;
+               else if (currentDate != null && sessionDate != null && sessionDate.after(currentDate))
+                       currentSession = session;       
+       }
+       
+       public static void addEntry(LogEntry current, ArrayList entries, IMemento memento, boolean useCurrentSession) {
+               int severity = current.getSeverity();
+               boolean doAdd = true;
+               switch(severity) {
+                       case IStatus.INFO:
+                               doAdd = memento.getString(LogView.P_LOG_INFO).equals("true"); //$NON-NLS-1$
+                               break;
+                       case IStatus.WARNING:
+                               doAdd = memento.getString(LogView.P_LOG_WARNING).equals("true"); //$NON-NLS-1$
+                               break;
+                       case IStatus.ERROR:
+                               doAdd = memento.getString(LogView.P_LOG_ERROR).equals("true"); //$NON-NLS-1$
+                               break;
+               }
+               if (doAdd) {
+                       if (useCurrentSession)
+                               current.setSession(currentSession);
+                       entries.add(0, current);
+                       
+                       if (memento.getString(LogView.P_USE_LIMIT).equals("true") //$NON-NLS-1$
+                               && entries.size() > memento.getInteger(LogView.P_LOG_LIMIT).intValue())
+                               entries.remove(entries.size() - 1);
+               }
+       }
+
+       private static void setNewParent(
+               ArrayList parents,
+               LogEntry entry,
+               int depth) {
+               if (depth + 1 > parents.size())
+                       parents.add(entry);
+               else
+                       parents.set(depth, entry);
+       }
+       
+       public static void reset() {
+               currentSession = null;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogSession.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogSession.java
new file mode 100644 (file)
index 0000000..f4adc8c
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+public class LogSession {
+       private String sessionData;
+       private Date date;
+
+       /**
+        * Constructor for LogSession.
+        */
+       public LogSession() {
+       }
+
+       public Date getDate() {
+               return date;
+       }
+       
+       public void setDate(String dateString) {
+               SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
+               try {
+                       date = formatter.parse(dateString);
+               } catch (ParseException e) {
+               }
+       }
+       
+       public String getSessionData() {
+               return sessionData;
+       }
+
+       void setSessionData(String data) {
+               this.sessionData = data;
+       }
+       
+       public void processLogLine(String line) {
+               StringTokenizer tokenizer = new StringTokenizer(line);
+               if (tokenizer.countTokens() == 6) {
+                       tokenizer.nextToken();
+                       StringBuffer dateBuffer = new StringBuffer();
+                       for (int i = 0; i < 4; i++) {
+                               dateBuffer.append(tokenizer.nextToken());
+                               dateBuffer.append(" "); //$NON-NLS-1$
+                       }
+                       setDate(dateBuffer.toString().trim());
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogView.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogView.java
new file mode 100644 (file)
index 0000000..d698b1c
--- /dev/null
@@ -0,0 +1,993 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ **********************************************************************************************************************************/
+
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.text.Collator;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPluginImages;
+
+import org.eclipse.core.runtime.ILogListener;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ColumnPixelData;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableTreeViewer;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.custom.TableTree;
+import org.eclipse.swt.custom.TableTreeItem;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.program.Program;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.XMLMemento;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.part.ViewPart;
+
+public class LogView extends ViewPart implements ILogListener {
+  public final static String ID_LOGVIEW = "net.sourceforge.phpdt.internal.debug.core.logview.LogView"; //$NON-NLS-1$
+
+  private TableTreeViewer tableTreeViewer;
+
+  private ArrayList logs = new ArrayList();
+
+  public static final String P_LOG_WARNING = "warning"; //$NON-NLS-1$
+
+  public static final String P_LOG_ERROR = "error"; //$NON-NLS-1$
+
+  public static final String P_LOG_INFO = "info"; //$NON-NLS-1$
+
+  public static final String P_LOG_LIMIT = "limit"; //$NON-NLS-1$
+
+  public static final String P_USE_LIMIT = "useLimit"; //$NON-NLS-1$
+
+  public static final String P_SHOW_ALL_SESSIONS = "allSessions"; //$NON-NLS-1$
+
+  private static final String P_COLUMN_1 = "column1"; //$NON-NLS-1$
+
+  private static final String P_COLUMN_2 = "column2"; //$NON-NLS-1$
+
+  private static final String P_COLUMN_3 = "column3"; //$NON-NLS-1$
+
+  private static final String P_COLUMN_4 = "column4"; //$NON-NLS-1$
+
+  public static final String P_ACTIVATE = "activate"; //$NON-NLS-1$
+
+  private int MESSAGE_ORDER = -1;
+
+  private int PLUGIN_ORDER = -1;
+
+  private int DATE_ORDER = -1;
+
+  public static byte MESSAGE = 0x0;
+
+  public static byte PLUGIN = 0x1;
+
+  public static byte DATE = 0x2;
+
+  private static int ASCENDING = 1;
+
+  private static int DESCENDING = -1;
+
+  private Action clearAction;
+
+  private Action copyAction;
+
+  private Action readLogAction;
+
+  private Action deleteLogAction;
+
+  private Action exportAction;
+
+  private Action importAction;
+
+  private Action activateViewAction;
+
+  private Action propertiesAction;
+
+  private Action viewLogAction;
+
+  private Action filterAction;
+
+  private Clipboard clipboard;
+
+  private IMemento memento;
+
+  private File inputFile;
+
+  private String directory;
+
+  private TableColumn column0;
+
+  private TableColumn column1;
+
+  private TableColumn column2;
+
+  private TableColumn column3;
+
+  private TableColumn column4;
+
+  private static Font boldFont;
+
+  private Comparator comparator;
+
+  private Collator collator;
+
+  // hover text
+  private boolean canOpenTextShell;
+
+  private Text textLabel;
+
+  private Shell textShell;
+
+  private boolean firstEvent = true;
+
+  public LogView() {
+    logs = new ArrayList();
+    inputFile = Platform.getLogFileLocation().toFile();
+  }
+
+  public void createPartControl(Composite parent) {
+    readLogFile();
+    TableTree tableTree = new TableTree(parent, SWT.FULL_SELECTION);
+    tableTree.setLayoutData(new GridData(GridData.FILL_BOTH));
+    createColumns(tableTree.getTable());
+    createViewer(tableTree);
+    createPopupMenuManager(tableTree);
+    makeActions(tableTree.getTable());
+    fillToolBar();
+    Platform.addLogListener(this);
+    getSite().setSelectionProvider(tableTreeViewer);
+    clipboard = new Clipboard(tableTree.getDisplay());
+    //        WorkbenchHelp.setHelp(tableTree, IHelpContextIds.LOG_VIEW);
+    tableTreeViewer.getTableTree().getTable().setToolTipText(""); //$NON-NLS-1$
+    initializeFonts();
+    applyFonts();
+  }
+
+  private void initializeFonts() {
+    Font tableFont = tableTreeViewer.getTableTree().getFont();
+    FontData[] fontDataList = tableFont.getFontData();
+    FontData fontData;
+    if (fontDataList.length > 0)
+      fontData = fontDataList[0];
+    else
+      fontData = new FontData();
+    fontData.setStyle(SWT.BOLD);
+    boldFont = new Font(tableTreeViewer.getTableTree().getDisplay(), fontData);
+  }
+
+  /*
+   * Set all rows where the tableTreeItem has children to have a <b>bold </b> font.
+   */
+  private void applyFonts() {
+    if (tableTreeViewer == null || tableTreeViewer.getTableTree().isDisposed())
+      return;
+    int max = tableTreeViewer.getTableTree().getItemCount();
+    int index = 0, tableIndex = 0;
+    while (index < max) {
+      LogEntry entry = (LogEntry) tableTreeViewer.getElementAt(index);
+      if (entry == null)
+        return;
+      if (entry.hasChildren()) {
+        tableTreeViewer.getTableTree().getItems()[index].setFont(boldFont);
+        tableIndex = applyChildFonts(entry, tableIndex);
+      } else {
+        tableTreeViewer.getTableTree().getItems()[index].setFont(tableTreeViewer.getTableTree().getFont());
+      }
+      index++;
+      tableIndex++;
+    }
+  }
+
+  private int applyChildFonts(LogEntry parent, int index) {
+    if (!tableTreeViewer.getExpandedState(parent) || !parent.hasChildren())
+      return index;
+    LogEntry[] children = getEntryChildren(parent);
+    for (int i = 0; i < children.length; i++) {
+      index++;
+      if (children[i].hasChildren()) {
+        TableItem tableItem = getTableItem(index);
+        if (tableItem != null) {
+          tableItem.setFont(boldFont);
+        }
+        index = applyChildFonts(children[i], index);
+      } else {
+        TableItem tableItem = getTableItem(index);
+        if (tableItem != null) {
+          tableItem.setFont(tableTreeViewer.getTableTree().getFont());
+        }
+      }
+    }
+    return index;
+  }
+
+  private LogEntry[] getEntryChildren(LogEntry parent) {
+    Object[] entryChildren = parent.getChildren(parent);
+    if (comparator != null)
+      Arrays.sort(entryChildren, comparator);
+    LogEntry[] children = new LogEntry[entryChildren.length];
+    System.arraycopy(entryChildren, 0, children, 0, entryChildren.length);
+    return children;
+  }
+
+  private TableItem getTableItem(int index) {
+    TableItem[] tableItems = tableTreeViewer.getTableTree().getTable().getItems();
+    if (index > tableItems.length - 1)
+      return null;
+    return tableItems[index];
+  }
+
+  private void fillToolBar() {
+    IActionBars bars = getViewSite().getActionBars();
+    bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+    IToolBarManager toolBarManager = bars.getToolBarManager();
+    toolBarManager.add(exportAction);
+    toolBarManager.add(importAction);
+    toolBarManager.add(new Separator());
+    toolBarManager.add(clearAction);
+    toolBarManager.add(deleteLogAction);
+    toolBarManager.add(viewLogAction);
+    toolBarManager.add(readLogAction);
+    toolBarManager.add(new Separator());
+    IMenuManager mgr = bars.getMenuManager();
+    mgr.add(filterAction);
+    mgr.add(new Separator());
+    mgr.add(activateViewAction);
+  }
+
+  private void createViewer(TableTree tableTree) {
+    tableTreeViewer = new TableTreeViewer(tableTree);
+    tableTreeViewer.setContentProvider(new LogViewContentProvider(this));
+    tableTreeViewer.setLabelProvider(new LogViewLabelProvider());
+    tableTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+      public void selectionChanged(SelectionChangedEvent e) {
+        handleSelectionChanged(e.getSelection());
+        if (propertiesAction.isEnabled())
+          ((EventDetailsDialogAction) propertiesAction).resetSelection();
+      }
+    });
+    tableTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+      public void doubleClick(DoubleClickEvent event) {
+        ((EventDetailsDialogAction) propertiesAction).setComparator(comparator);
+        propertiesAction.run();
+      }
+    });
+    tableTreeViewer.addTreeListener(new ITreeViewerListener() {
+      public void treeCollapsed(TreeExpansionEvent event) {
+        applyFonts();
+      }
+
+      public void treeExpanded(TreeExpansionEvent event) {
+        applyFonts();
+      }
+    });
+    addMouseListeners();
+    tableTreeViewer.setInput(Platform.class);
+  }
+
+  private void createPopupMenuManager(TableTree tableTree) {
+    MenuManager popupMenuManager = new MenuManager();
+    IMenuListener listener = new IMenuListener() {
+      public void menuAboutToShow(IMenuManager mng) {
+        fillContextMenu(mng);
+      }
+    };
+    popupMenuManager.addMenuListener(listener);
+    popupMenuManager.setRemoveAllWhenShown(true);
+    Menu menu = popupMenuManager.createContextMenu(tableTree);
+    tableTree.setMenu(menu);
+  }
+
+  private void createColumns(Table table) {
+    column0 = new TableColumn(table, SWT.NULL);
+    column0.setText(""); //$NON-NLS-1$
+    column1 = new TableColumn(table, SWT.NULL);
+    column1.setText(XDebugUIPlugin.getString("LogView.column.severity")); //$NON-NLS-1$
+    column2 = new TableColumn(table, SWT.NULL);
+    column2.setText(XDebugUIPlugin.getString("LogView.column.message")); //$NON-NLS-1$
+    column2.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent e) {
+        MESSAGE_ORDER *= -1;
+        ViewerSorter sorter = getViewerSorter(MESSAGE);
+        tableTreeViewer.setSorter(sorter);
+        collator = sorter.getCollator();
+        boolean isComparatorSet = ((EventDetailsDialogAction) propertiesAction).resetSelection(MESSAGE, MESSAGE_ORDER);
+        setComparator(MESSAGE);
+        if (!isComparatorSet)
+          ((EventDetailsDialogAction) propertiesAction).setComparator(comparator);
+        applyFonts();
+      }
+    });
+    column3 = new TableColumn(table, SWT.NULL);
+    column3.setText(XDebugUIPlugin.getString("LogView.column.plugin"));  //$NON-NLS-1$
+    column3.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent e) {
+        PLUGIN_ORDER *= -1;
+        ViewerSorter sorter = getViewerSorter(PLUGIN);
+        tableTreeViewer.setSorter(sorter);
+        collator = sorter.getCollator();
+        boolean isComparatorSet = ((EventDetailsDialogAction) propertiesAction).resetSelection(PLUGIN, PLUGIN_ORDER);
+        setComparator(PLUGIN);
+        if (!isComparatorSet)
+          ((EventDetailsDialogAction) propertiesAction).setComparator(comparator);
+        applyFonts();
+      }
+    });
+    column4 = new TableColumn(table, SWT.NULL);
+    column4.setText(XDebugUIPlugin.getString("LogView.column.date")); //$NON-NLS-1$
+    column4.addSelectionListener(new SelectionAdapter() {
+      public void widgetSelected(SelectionEvent e) {
+        if (DATE_ORDER == ASCENDING) {
+          DATE_ORDER = DESCENDING;
+        } else {
+          DATE_ORDER = ASCENDING;
+        }
+        ViewerSorter sorter = getViewerSorter(DATE);
+        tableTreeViewer.setSorter(sorter);
+        collator = sorter.getCollator();
+        boolean isComparatorSet = ((EventDetailsDialogAction) propertiesAction).resetSelection(DATE, DATE_ORDER);
+        setComparator(DATE);
+        if (!isComparatorSet)
+          ((EventDetailsDialogAction) propertiesAction).setComparator(comparator);
+        applyFonts();
+      }
+    });
+    TableLayout tlayout = new TableLayout();
+    tlayout.addColumnData(new ColumnPixelData(21));
+    tlayout.addColumnData(new ColumnPixelData(memento.getInteger(P_COLUMN_1).intValue()));
+    tlayout.addColumnData(new ColumnPixelData(memento.getInteger(P_COLUMN_2).intValue()));
+    tlayout.addColumnData(new ColumnPixelData(memento.getInteger(P_COLUMN_3).intValue()));
+    tlayout.addColumnData(new ColumnPixelData(memento.getInteger(P_COLUMN_4).intValue()));
+    table.setLayout(tlayout);
+    table.setHeaderVisible(true);
+  }
+
+  private void makeActions(Table table) {
+    propertiesAction = new EventDetailsDialogAction(table.getShell(), tableTreeViewer);
+    propertiesAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_PROPERTIES));
+    propertiesAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_PROPERTIES));
+    propertiesAction.setToolTipText(XDebugUIPlugin.getString("LogView.properties.tooltip")); //$NON-NLS-1$
+    propertiesAction.setEnabled(false);
+    clearAction = new Action(XDebugUIPlugin.getString("LogView.clear")) { //$NON-NLS-1$
+      public void run() {
+        handleClear();
+      }
+    };
+    clearAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_CLEAR));
+    clearAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_CLEAR));
+    clearAction.setToolTipText(XDebugUIPlugin.getString("LogView.clear.tooltip")); //$NON-NLS-1$
+    clearAction.setText(XDebugUIPlugin.getString("LogView.clear")); //$NON-NLS-1$
+    readLogAction = new Action(XDebugUIPlugin.getString("LogView.readLog.restore")) { //$NON-NLS-1$
+      public void run() {
+        inputFile = Platform.getLogFileLocation().toFile();
+        reloadLog();
+      }
+    };
+    readLogAction.setToolTipText(XDebugUIPlugin.getString("LogView.readLog.restore.tooltip")); //$NON-NLS-1$
+    readLogAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_READ_LOG));
+    readLogAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_READ_LOG));
+    deleteLogAction = new Action(XDebugUIPlugin.getString("LogView.delete")) { //$NON-NLS-1$
+      public void run() {
+        doDeleteLog();
+      }
+    };
+    deleteLogAction.setToolTipText(XDebugUIPlugin.getString("LogView.delete.tooltip")); //$NON-NLS-1$
+    deleteLogAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_REMOVE_LOG));
+    deleteLogAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_REMOVE_LOG));
+    deleteLogAction.setEnabled(inputFile.exists() && inputFile.equals(Platform.getLogFileLocation().toFile()));
+    copyAction = new Action(XDebugUIPlugin.getString("LogView.copy")) { //$NON-NLS-1$
+      public void run() {
+        copyToClipboard(tableTreeViewer.getSelection());
+      }
+    };
+    copyAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+    filterAction = new Action(XDebugUIPlugin.getString("LogView.filter")) { //$NON-NLS-1$
+      public void run() {
+        handleFilter();
+      }
+    };
+    filterAction.setToolTipText(XDebugUIPlugin.getString("LogView.filter")); //$NON-NLS-1$
+    filterAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_FILTER));
+    filterAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_FILTER));
+    exportAction = new Action(XDebugUIPlugin.getString("LogView.export")) { //$NON-NLS-1$
+      public void run() {
+        handleExport();
+      }
+    };
+    exportAction.setToolTipText(XDebugUIPlugin.getString("LogView.export.tooltip")); //$NON-NLS-1$
+    exportAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_EXPORT));
+    exportAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_EXPORT));
+    importAction = new Action(XDebugUIPlugin.getString("LogView.import")) { //$NON-NLS-1$
+      public void run() {
+        handleImport();
+      }
+    };
+    importAction.setToolTipText(XDebugUIPlugin.getString("LogView.import.tooltip")); //$NON-NLS-1$
+    importAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_IMPORT));
+    importAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_IMPORT));
+    activateViewAction = new Action(XDebugUIPlugin.getString("LogView.activate")) { //$NON-NLS-1$
+      public void run() {
+      }
+    };
+    activateViewAction.setChecked(memento.getString(P_ACTIVATE).equals("true")); //$NON-NLS-1$
+    viewLogAction = new Action(XDebugUIPlugin.getString("LogView.view.currentLog")) { //$NON-NLS-1$
+      public void run() {
+        if (inputFile.exists()) {
+          if (inputFile.length() > LogReader.MAX_FILE_LENGTH) {
+            OpenLogDialog openDialog = new OpenLogDialog(getViewSite().getShell(), inputFile);
+            openDialog.create();
+            openDialog.open();
+          } else {
+            boolean canLaunch = Program.launch(inputFile.getAbsolutePath());
+            if (!canLaunch) {
+              Program p = Program.findProgram(".txt"); //$NON-NLS-1$
+              if (p != null)
+                p.execute(inputFile.getAbsolutePath());
+              else {
+                OpenLogDialog openDialog = new OpenLogDialog(getViewSite().getShell(), inputFile);
+                openDialog.create();
+                openDialog.open();
+              }
+            }
+          }
+        }
+      }
+    };
+    viewLogAction.setImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_OPEN_LOG));
+    viewLogAction.setDisabledImageDescriptor(XDebugUIPluginImages.getImageDescriptor(XDebugUIPluginImages.IMG_OPEN_LOG));
+    viewLogAction.setEnabled(inputFile.exists());
+    viewLogAction.setToolTipText(XDebugUIPlugin.getString("LogView.view.currentLog.tooltip")); //$NON-NLS-1$
+  }
+
+  public void dispose() {
+    Platform.removeLogListener(this);
+    clipboard.dispose();
+    LogReader.reset();
+    boldFont.dispose();
+    super.dispose();
+  }
+
+  private void handleImport() {
+    FileDialog dialog = new FileDialog(getViewSite().getShell());
+    dialog.setFilterExtensions(new String[] { "*.log" }); //$NON-NLS-1$
+    if (directory != null)
+      dialog.setFilterPath(directory);
+    String path = dialog.open();
+    if (path != null && new Path(path).toFile().exists()) {
+      inputFile = new Path(path).toFile();
+      directory = inputFile.getParent();
+      IRunnableWithProgress op = new IRunnableWithProgress() {
+        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+          monitor.beginTask(XDebugUIPlugin.getString("LogView.operation.importing"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+          readLogFile();
+        }
+      };
+      ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+      try {
+        pmd.run(true, true, op);
+      } catch (InvocationTargetException e) {
+      } catch (InterruptedException e) {
+      } finally {
+        readLogAction.setText(XDebugUIPlugin.getString("LogView.readLog.reload")); //$NON-NLS-1$
+        readLogAction.setToolTipText(XDebugUIPlugin.getString("LogView.readLog.reload")); //$NON-NLS-1$
+        asyncRefresh(false);
+        resetDialogButtons();
+      }
+    }
+  }
+
+  private void handleExport() {
+    FileDialog dialog = new FileDialog(getViewSite().getShell(), SWT.SAVE);
+    dialog.setFilterExtensions(new String[] { "*.log" }); //$NON-NLS-1$
+    if (directory != null)
+      dialog.setFilterPath(directory);
+    String path = dialog.open();
+    if (path != null) {
+      if (!path.endsWith(".log")) //$NON-NLS-1$
+        path += ".log"; //$NON-NLS-1$
+      File outputFile = new Path(path).toFile();
+      directory = outputFile.getParent();
+      if (outputFile.exists()) {
+         String message = "LogView.confirmOverwrite.message";
+//        String message = PHPDebugUIPlugin.getFormattedMessage("LogView.confirmOverwrite.message", //$NON-NLS-1$
+//            outputFile.toString());
+        if (!MessageDialog.openQuestion(getViewSite().getShell(), exportAction.getText(), message))
+          return;
+      }
+      copy(inputFile, outputFile);
+    }
+  }
+
+  private void copy(File inputFile, File outputFile) {
+    BufferedReader reader = null;
+    BufferedWriter writer = null;
+    try {
+      reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8")); //$NON-NLS-1$
+      writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")); //$NON-NLS-1$
+      while (reader.ready()) {
+        writer.write(reader.readLine());
+        writer.write(System.getProperty("line.separator")); //$NON-NLS-1$
+      }
+    } catch (IOException e) {
+    } finally {
+      try {
+        if (reader != null)
+          reader.close();
+        if (writer != null)
+          writer.close();
+      } catch (IOException e1) {
+      }
+    }
+  }
+
+  private void handleFilter() {
+    FilterDialog dialog = new FilterDialog(XDebugCorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), memento);
+    dialog.create();
+    dialog.getShell().setText(XDebugUIPlugin.getString("LogView.FilterDialog.title")); //$NON-NLS-1$
+    if (dialog.open() == FilterDialog.OK)
+      reloadLog();
+  }
+
+  private void doDeleteLog() {
+    String title = XDebugUIPlugin.getString("LogView.confirmDelete.title"); //$NON-NLS-1$
+    String message = XDebugUIPlugin.getString("LogView.confirmDelete.message"); //$NON-NLS-1$
+    if (!MessageDialog.openConfirm(tableTreeViewer.getControl().getShell(), title, message))
+      return;
+    if (inputFile.delete()) {
+      logs.clear();
+      asyncRefresh(false);
+      resetDialogButtons();
+    }
+  }
+
+  public void fillContextMenu(IMenuManager manager) {
+    manager.add(copyAction);
+    manager.add(new Separator());
+    manager.add(clearAction);
+    manager.add(deleteLogAction);
+    manager.add(viewLogAction);
+    manager.add(readLogAction);
+    manager.add(new Separator());
+    manager.add(exportAction);
+    manager.add(importAction);
+    manager.add(new Separator());
+    ((EventDetailsDialogAction) propertiesAction).setComparator(comparator);
+    manager.add(propertiesAction);
+  }
+
+  public LogEntry[] getLogs() {
+    return (LogEntry[]) logs.toArray(new LogEntry[logs.size()]);
+  }
+
+  protected void handleClear() {
+    BusyIndicator.showWhile(tableTreeViewer.getControl().getDisplay(), new Runnable() {
+      public void run() {
+        logs.clear();
+        asyncRefresh(false);
+        resetDialogButtons();
+      }
+    });
+  }
+
+  protected void reloadLog() {
+    IRunnableWithProgress op = new IRunnableWithProgress() {
+      public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+        monitor.beginTask(XDebugUIPlugin.getString("LogView.operation.reloading"), //$NON-NLS-1$
+            IProgressMonitor.UNKNOWN);
+        readLogFile();
+      }
+    };
+    ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+    try {
+      pmd.run(true, true, op);
+    } catch (InvocationTargetException e) {
+    } catch (InterruptedException e) {
+    } finally {
+      readLogAction.setText(XDebugUIPlugin.getString("LogView.readLog.restore")); //$NON-NLS-1$
+      readLogAction.setToolTipText(XDebugUIPlugin.getString("LogView.readLog.restore")); //$NON-NLS-1$
+      asyncRefresh(false);
+      resetDialogButtons();
+    }
+  }
+
+  private void readLogFile() {
+    logs.clear();
+    if (!inputFile.exists())
+      return;
+    if (inputFile.length() > LogReader.MAX_FILE_LENGTH)
+      LogReader.parseLargeFile(inputFile, logs, memento);
+    else
+      LogReader.parseLogFile(inputFile, logs, memento);
+  }
+
+  public void logging(IStatus status, String plugin) { 
+    if (!inputFile.equals(Platform.getLogFileLocation().toFile()))
+      return;
+    if (firstEvent) {
+      readLogFile();
+      asyncRefresh();
+      firstEvent = false;
+    } else {
+      pushStatus(status);
+    }
+  }
+
+  private void pushStatus(IStatus status) {
+      LogEntry entry = new LogEntry(status);
+      LogReader.addEntry(entry, logs, memento, true);
+      asyncRefresh();
+  }
+
+  private void asyncRefresh() {
+    asyncRefresh(true);
+  }
+
+  private void asyncRefresh(final boolean activate) {
+    final Control control = tableTreeViewer.getControl();
+    if (control.isDisposed())
+      return;
+    Display display = control.getDisplay();
+    final ViewPart view = this;
+    if (display != null) {
+      display.asyncExec(new Runnable() {
+        public void run() {
+          if (!control.isDisposed()) {
+            tableTreeViewer.refresh();
+            deleteLogAction.setEnabled(inputFile.exists() && inputFile.equals(Platform.getLogFileLocation().toFile()));
+            viewLogAction.setEnabled(inputFile.exists());
+            if (activate && activateViewAction.isChecked()) {
+              IWorkbenchPage page = XDebugCorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
+              if (page != null)
+                page.bringToTop(view);
+            }
+          }
+          applyFonts();
+        }
+      });
+    }
+  }
+
+  public void setFocus() {
+    if (tableTreeViewer != null && !tableTreeViewer.getTableTree().isDisposed())
+      tableTreeViewer.getTableTree().getTable().setFocus();
+  }
+
+  private void handleSelectionChanged(ISelection selection) {
+    updateStatus(selection);
+    copyAction.setEnabled(!selection.isEmpty());
+    propertiesAction.setEnabled(!selection.isEmpty());
+  }
+
+  private void updateStatus(ISelection selection) {
+    IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager();
+    if (selection.isEmpty())
+      status.setMessage(null);
+    else {
+      LogEntry entry = (LogEntry) ((IStructuredSelection) selection).getFirstElement();
+      status.setMessage(((LogViewLabelProvider) tableTreeViewer.getLabelProvider()).getColumnText(entry, 2));
+    }
+  }
+
+  private void copyToClipboard(ISelection selection) {
+    StringWriter writer = new StringWriter();
+    PrintWriter pwriter = new PrintWriter(writer);
+    if (selection.isEmpty())
+      return;
+    LogEntry entry = (LogEntry) ((IStructuredSelection) selection).getFirstElement();
+    entry.write(pwriter);
+    pwriter.flush();
+    String textVersion = writer.toString();
+    try {
+      pwriter.close();
+      writer.close();
+    } catch (IOException e) {
+    }
+    if (textVersion.trim().length() > 0) {
+      // set the clipboard contents
+      clipboard.setContents(new Object[] { textVersion }, new Transfer[] { TextTransfer.getInstance() });
+    }
+  }
+
+  public void init(IViewSite site, IMemento memento) throws PartInitException {
+    super.init(site, memento);
+    if (memento == null)
+      this.memento = XMLMemento.createWriteRoot("LOGVIEW"); //$NON-NLS-1$
+    else
+      this.memento = memento;
+    initializeMemento();
+  }
+
+  private void initializeMemento() {
+    if (memento.getString(P_USE_LIMIT) == null)
+      memento.putString(P_USE_LIMIT, "true"); //$NON-NLS-1$
+    if (memento.getInteger(P_LOG_LIMIT) == null)
+      memento.putInteger(P_LOG_LIMIT, 50);
+    if (memento.getString(P_LOG_INFO) == null)
+      memento.putString(P_LOG_INFO, "true"); //$NON-NLS-1$
+    if (memento.getString(P_LOG_WARNING) == null)
+      memento.putString(P_LOG_WARNING, "true"); //$NON-NLS-1$
+    if (memento.getString(P_LOG_ERROR) == null)
+      memento.putString(P_LOG_ERROR, "true"); //$NON-NLS-1$
+    if (memento.getString(P_SHOW_ALL_SESSIONS) == null)
+      memento.putString(P_SHOW_ALL_SESSIONS, "true"); //$NON-NLS-1$
+    Integer width = memento.getInteger(P_COLUMN_1);
+    if (width == null || width.intValue() == 0)
+      memento.putInteger(P_COLUMN_1, 20);
+    width = memento.getInteger(P_COLUMN_2);
+    if (width == null || width.intValue() == 0)
+      memento.putInteger(P_COLUMN_2, 300);
+    width = memento.getInteger(P_COLUMN_3);
+    if (width == null || width.intValue() == 0)
+      memento.putInteger(P_COLUMN_3, 150);
+    width = memento.getInteger(P_COLUMN_4);
+    if (width == null || width.intValue() == 0)
+      memento.putInteger(P_COLUMN_4, 150);
+    if (memento.getString(P_ACTIVATE) == null)
+      memento.putString(P_ACTIVATE, "true"); //$NON-NLS-1$
+  }
+
+  public void saveState(IMemento memento) {
+    if (this.memento == null || memento == null)
+      return;
+    this.memento.putInteger(P_COLUMN_1, column1.getWidth());
+    this.memento.putInteger(P_COLUMN_2, column2.getWidth());
+    this.memento.putInteger(P_COLUMN_3, column3.getWidth());
+    this.memento.putInteger(P_COLUMN_4, column4.getWidth());
+    this.memento.putString(P_ACTIVATE, activateViewAction.isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+    memento.putMemento(this.memento);
+  }
+
+  private void addMouseListeners() {
+    Listener tableListener = new Listener() {
+      public void handleEvent(Event e) {
+        switch (e.type) {
+        case SWT.MouseMove:
+          onMouseMove(e);
+          break;
+        case SWT.MouseHover:
+          onMouseHover(e);
+          break;
+        case SWT.MouseDown:
+          onMouseDown(e);
+          break;
+        }
+      }
+    };
+    int[] tableEvents = new int[] { SWT.MouseDown, SWT.MouseMove, SWT.MouseHover };
+    for (int i = 0; i < tableEvents.length; i++) {
+      tableTreeViewer.getTableTree().getTable().addListener(tableEvents[i], tableListener);
+    }
+  }
+
+  private void makeHoverShell() {
+    Control control = tableTreeViewer.getControl();
+    textShell = new Shell(control.getShell(), SWT.NO_FOCUS | SWT.ON_TOP);
+    Display display = textShell.getDisplay();
+    textShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+    GridLayout layout = new GridLayout(1, false);
+    int border = ((control.getShell().getStyle() & SWT.NO_TRIM) == 0) ? 0 : 1;
+    layout.marginHeight = border;
+    layout.marginWidth = border;
+    textShell.setLayout(layout);
+    textShell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+    Composite shellComposite = new Composite(textShell, SWT.NONE);
+    layout = new GridLayout();
+    layout.marginHeight = 0;
+    layout.marginWidth = 0;
+    shellComposite.setLayout(layout);
+    shellComposite.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING));
+    textLabel = new Text(shellComposite, SWT.WRAP | SWT.MULTI);
+    GridData gd = new GridData(GridData.FILL_BOTH);
+    gd.widthHint = 100;
+    gd.grabExcessHorizontalSpace = true;
+    textLabel.setLayoutData(gd);
+    Color c = control.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
+    textLabel.setBackground(c);
+    c = control.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND);
+    textLabel.setForeground(c);
+    textLabel.setEditable(false);
+    textShell.addDisposeListener(new DisposeListener() {
+      public void widgetDisposed(DisposeEvent e) {
+        onTextShellDispose(e);
+      }
+    });
+  }
+
+  void onTextShellDispose(DisposeEvent e) {
+    canOpenTextShell = true;
+    setFocus();
+  }
+
+  void onMouseDown(Event e) {
+    if (textShell != null && !textShell.isDisposed() && !textShell.isFocusControl()) {
+      textShell.close();
+      canOpenTextShell = true;
+    }
+  }
+
+  void onMouseHover(Event e) {
+    if (!canOpenTextShell)
+      return;
+    canOpenTextShell = false;
+    Point point = new Point(e.x, e.y);
+    TableTree table = tableTreeViewer.getTableTree();
+    TableTreeItem item = table.getItem(point);
+    if (item == null)
+      return;
+    String message = ((LogEntry) item.getData()).getStack();
+    if (message == null)
+      return;
+    makeHoverShell();
+    textLabel.setText(message);
+    int x = point.x + 5;
+    int y = point.y - (table.getItemHeight() * 2) - 20;
+    textShell.setLocation(table.toDisplay(x, y));
+    textShell.setSize(tableTreeViewer.getTableTree().getSize().x - x, 125);
+    textShell.open();
+    setFocus();
+  }
+
+  void onMouseMove(Event e) {
+    if (textShell != null && !textShell.isDisposed()) {
+      textShell.close();
+      canOpenTextShell = textShell.isDisposed() && e.x > column0.getWidth() && e.x < (column0.getWidth() + column1.getWidth());
+    } else {
+      canOpenTextShell = e.x > column0.getWidth() && e.x < (column0.getWidth() + column1.getWidth());
+    }
+  }
+
+  public Comparator getComparator() {
+    return comparator;
+  }
+
+  private void setComparator(byte sortType) {
+    if (sortType == DATE) {
+      comparator = new Comparator() {
+        public int compare(Object e1, Object e2) {
+          try {
+            SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
+            Date date1 = formatter.parse(((LogEntry) e1).getDate());
+            Date date2 = formatter.parse(((LogEntry) e2).getDate());
+            if (DATE_ORDER == ASCENDING)
+              return date1.before(date2) ? -1 : 1;
+            return date1.after(date2) ? -1 : 1;
+          } catch (ParseException e) {
+          }
+          return 0;
+        }
+      };
+    } else if (sortType == PLUGIN) {
+      comparator = new Comparator() {
+        public int compare(Object e1, Object e2) {
+          LogEntry entry1 = (LogEntry) e1;
+          LogEntry entry2 = (LogEntry) e2;
+          return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+        }
+      };
+    } else {
+      comparator = new Comparator() {
+        public int compare(Object e1, Object e2) {
+          LogEntry entry1 = (LogEntry) e1;
+          LogEntry entry2 = (LogEntry) e2;
+          return collator.compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+        }
+      };
+    }
+  }
+
+  private ViewerSorter getViewerSorter(byte sortType) {
+    if (sortType == PLUGIN) {
+      return new ViewerSorter() {
+        public int compare(Viewer viewer, Object e1, Object e2) {
+          LogEntry entry1 = (LogEntry) e1;
+          LogEntry entry2 = (LogEntry) e2;
+          return super.compare(viewer, entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+        }
+      };
+    } else if (sortType == MESSAGE) {
+      return new ViewerSorter() {
+        public int compare(Viewer viewer, Object e1, Object e2) {
+          LogEntry entry1 = (LogEntry) e1;
+          LogEntry entry2 = (LogEntry) e2;
+          return super.compare(viewer, entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+        }
+      };
+    } else {
+      return new ViewerSorter() {
+        public int compare(Viewer viewer, Object e1, Object e2) {
+          try {
+            SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy HH:mm:ss.SS"); //$NON-NLS-1$
+            Date date1 = formatter.parse(((LogEntry) e1).getDate());
+            Date date2 = formatter.parse(((LogEntry) e2).getDate());
+            if (DATE_ORDER == ASCENDING)
+              return date1.before(date2) ? -1 : 1;
+            return date1.after(date2) ? -1 : 1;
+          } catch (ParseException e) {
+          }
+          return 0;
+        }
+      };
+    }
+  }
+
+  private void resetDialogButtons() {
+    ((EventDetailsDialogAction) propertiesAction).resetDialogButtons();
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewContentProvider.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewContentProvider.java
new file mode 100644 (file)
index 0000000..3a12f46
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class LogViewContentProvider
+       implements ITreeContentProvider, IStructuredContentProvider {
+       private LogView logView;
+
+       public LogViewContentProvider(LogView logView) {
+               this.logView = logView;
+       }
+       public void dispose() {
+       }
+       public Object[] getChildren(Object element) {
+               return ((LogEntry) element).getChildren(element);
+       }
+       public Object[] getElements(Object element) {
+               return logView.getLogs();
+       }
+       public Object getParent(Object element) {
+               return ((LogEntry) element).getParent(element);
+       }
+       public boolean hasChildren(Object element) {
+               return ((LogEntry) element).hasChildren();
+       }
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+       }
+       public boolean isDeleted(Object element) {
+               return false;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewLabelProvider.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/LogViewLabelProvider.java
new file mode 100644 (file)
index 0000000..2cc65c3
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPluginImages;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class LogViewLabelProvider
+       extends LabelProvider
+       implements ITableLabelProvider {
+       private Image infoImage;
+       private Image errorImage;
+       private Image warningImage;
+       private Image errorWithStackImage;
+
+       public LogViewLabelProvider() {
+               errorImage = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_ERROR_ST_OBJ);
+               warningImage = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_WARNING_ST_OBJ);
+               infoImage = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_INFO_ST_OBJ);
+               errorWithStackImage = XDebugUIPluginImages.get(XDebugUIPluginImages.IMG_ERROR_STACK_OBJ);
+       }
+       public void dispose() {
+               errorImage.dispose();
+               infoImage.dispose();
+               warningImage.dispose();
+               errorWithStackImage.dispose();
+               super.dispose();
+       }
+       public Image getColumnImage(Object element, int columnIndex) {
+               LogEntry entry = (LogEntry) element;
+               if (columnIndex == 1) {
+                       switch (entry.getSeverity()) {
+                               case IStatus.INFO :
+                                       return infoImage;
+                               case IStatus.WARNING :
+                                       return warningImage;
+                               case IStatus.ERROR :
+                                       return (entry.getStack() == null ? errorImage : errorWithStackImage);
+                       }
+               }
+               return null;
+       }
+       
+       public String getColumnText(Object element, int columnIndex) {
+               LogEntry entry = (LogEntry) element;
+               switch (columnIndex) {
+                       case 2 :
+                               return entry.getMessage();
+                       case 3 :
+                               return entry.getPluginId();
+                       case 4 :
+                               return entry.getDate();
+               }
+               return ""; //$NON-NLS-1$
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/OpenLogDialog.java b/net.sourceforge.phpeclipse.xdebug.ui/src/net/sourceforge/phpeclipse/xdebug/ui/views/logview/OpenLogDialog.java
new file mode 100644 (file)
index 0000000..c1b0bb1
--- /dev/null
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpeclipse.xdebug.ui.views.logview;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.ui.XDebugUIPlugin;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Displays the error log in non-Win32 platforms - see bug 55314.
+ */
+public final class OpenLogDialog extends Dialog {
+    // input log file
+    private File logFile;
+    // location/size configuration
+    private IDialogSettings dialogSettings;
+    private Point dialogLocation;
+    private Point dialogSize;
+    private int DEFAULT_WIDTH = 750;
+    private int DEFAULT_HEIGHT = 800;
+
+    public OpenLogDialog(Shell parentShell, File logFile) {
+        super(parentShell);
+        this.logFile = logFile;
+        setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN | SWT.MODELESS);
+
+    }
+
+    /*
+     * (non-Javadoc) Method declared on Window.
+     */
+    protected void configureShell(Shell newShell) {
+        super.configureShell(newShell);
+        newShell.setText(XDebugUIPlugin.getString("OpenLogDialog.title")); //$NON-NLS-1$
+        readConfiguration();
+    }
+
+    /*
+     * (non-Javadoc) Method declared on Dialog.
+     */
+    protected void createButtonsForButtonBar(Composite parent) {
+        createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL,
+                true);
+    }
+
+    public void create() {
+        super.create();
+        // dialog location
+        if (dialogLocation != null)
+            getShell().setLocation(dialogLocation);
+        // dialog size
+        if (dialogSize != null)
+            getShell().setSize(dialogSize);
+        else
+            getShell().setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+        getButton(IDialogConstants.CLOSE_ID).setFocus();
+    }
+
+    /*
+     * (non-Javadoc) Method declared on Dialog.
+     */
+    protected Control createDialogArea(Composite parent) {
+        Composite outer = (Composite) super.createDialogArea(parent);
+        Text text = new Text(outer, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL
+                | SWT.NO_FOCUS | SWT.H_SCROLL);
+        text.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+        GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+                | GridData.VERTICAL_ALIGN_FILL);
+        gridData.grabExcessVerticalSpace = true;
+        gridData.grabExcessHorizontalSpace = true;
+        text.setLayoutData(gridData);
+        text.setText(getLogSummary());
+        return outer;
+    }
+
+    private String getLogSummary() {
+        StringWriter out = new StringWriter();
+        PrintWriter writer = new PrintWriter(out);
+        if (logFile.length() > LogReader.MAX_FILE_LENGTH) {
+            readLargeFileWithMonitor(writer);
+        } else {
+            readFileWithMonitor(writer);
+        }
+        writer.close();
+        return out.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
+     */
+    protected void buttonPressed(int buttonId) {
+        if (buttonId == IDialogConstants.CLOSE_ID) {
+            storeSettings();
+            close();
+        }
+        super.buttonPressed(buttonId);
+    }
+
+    //--------------- 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 = XDebugCorePlugin.getDefault().getDialogSettings();
+        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);
+        } catch (NumberFormatException e) {
+            dialogLocation = null;
+            dialogSize = 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$
+    }
+
+    // reading file within MAX_FILE_LENGTH size
+    private void readFile(PrintWriter writer) throws FileNotFoundException, IOException {
+        BufferedReader bReader = new BufferedReader(new FileReader(logFile));
+        while (bReader.ready())
+            writer.println(bReader.readLine());
+    }
+
+    // reading large files
+    private void readLargeFile(PrintWriter writer) throws FileNotFoundException,
+            IOException {
+        RandomAccessFile random = null;
+        boolean hasStarted = false;
+        try {
+            random = new RandomAccessFile(logFile, "r"); //$NON-NLS-1$
+            random.seek(logFile.length() - LogReader.MAX_FILE_LENGTH);
+            for (;;) {
+                String line = random.readLine();
+                if (line == null)
+                    break;
+                line = line.trim();
+                if (line.length() == 0)
+                    continue;
+                if (!hasStarted
+                        && (line.startsWith("!ENTRY") || line.startsWith("!SESSION"))) //$NON-NLS-1$ //$NON-NLS-2$
+                    hasStarted = true;
+                if (hasStarted)
+                    writer.println(line);
+                continue;
+            }
+        } finally {
+            try {
+                if (random != null)
+                    random.close();
+            } catch (IOException e1) {
+            }
+        }
+    }
+
+    private void readLargeFileWithMonitor(final PrintWriter writer) {
+        IRunnableWithProgress runnable = new IRunnableWithProgress() {
+            public void run(IProgressMonitor monitor) throws InvocationTargetException,
+                    InterruptedException {
+                monitor
+                        .beginTask(
+                                XDebugUIPlugin.getString("OpenLogDialog.message"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+                try {
+                    readLargeFile(writer);
+                } catch (IOException e) {
+                    writer.println(XDebugUIPlugin.getString("OpenLogDialog.cannotDisplay")); //$NON-NLS-1$
+                }
+            }
+        };
+        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getParentShell());
+        try {
+            dialog.run(true, true, runnable);
+        } catch (InvocationTargetException e) {
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private void readFileWithMonitor(final PrintWriter writer) {
+        IRunnableWithProgress runnable = new IRunnableWithProgress() {
+            public void run(IProgressMonitor monitor) throws InvocationTargetException,
+                    InterruptedException {
+                monitor
+                        .beginTask(
+                                XDebugUIPlugin
+                                        .getString("OpenLogDialog.message"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+                try {
+                    readFile(writer);
+                } catch (IOException e) {
+                    writer.println(XDebugUIPlugin
+                            .getString("OpenLogDialog.cannotDisplay")); //$NON-NLS-1$
+                }
+            }
+        };
+        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getParentShell());
+        try {
+            dialog.run(true, true, runnable);
+        } catch (InvocationTargetException e) {
+        } catch (InterruptedException e) {
+        }
+    }
+}