1) Fixed issue #751: Pathmap 'Edit' button enable/disable handling.
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.ui / src / net / sourceforge / phpeclipse / xdebug / ui / php / launching / PHPPathMapTab.java
1 package net.sourceforge.phpeclipse.xdebug.ui.php.launching;
2
3 import java.text.MessageFormat;
4 //import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.List;
7 //import java.util.Map;
8 import java.util.Vector;
9
10 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
11 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
12 import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
13 import net.sourceforge.phpeclipse.xdebug.ui.EditPathMapDialog;
14 /*import net.sourceforge.phpeclipse.xdebug.ui.EnvironmentVariable;
15 import net.sourceforge.phpeclipse.xdebug.ui.MultipleInputDialog;
16 import net.sourceforge.phpeclipse.xdebug.ui.php.launching.PHPEnvironmentTab.EnvironmentVariableContentProvider;
17 import net.sourceforge.phpeclipse.xdebug.ui.php.launching.PHPEnvironmentTab.EnvironmentVariableLabelProvider;
18 */
19 //import org.eclipse.core.resources.IProject;
20 //import org.eclipse.core.resources.ResourcesPlugin;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.IPath;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.Path;
25 import org.eclipse.core.runtime.Status;
26 import org.eclipse.debug.core.ILaunchConfiguration;
27 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
28 //import org.eclipse.debug.core.ILaunchManager;
29 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
30 import org.eclipse.jface.dialogs.Dialog;
31 import org.eclipse.jface.dialogs.MessageDialog;
32 import org.eclipse.jface.viewers.ColumnLayoutData;
33 import org.eclipse.jface.viewers.ColumnWeightData;
34 import org.eclipse.jface.viewers.DoubleClickEvent;
35 import org.eclipse.jface.viewers.IDoubleClickListener;
36 import org.eclipse.jface.viewers.ISelectionChangedListener;
37 import org.eclipse.jface.viewers.IStructuredContentProvider;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.ITableLabelProvider;
40 import org.eclipse.jface.viewers.LabelProvider;
41 import org.eclipse.jface.viewers.SelectionChangedEvent;
42 import org.eclipse.jface.viewers.StructuredSelection;
43 import org.eclipse.jface.viewers.TableLayout;
44 import org.eclipse.jface.viewers.TableViewer;
45 import org.eclipse.jface.viewers.Viewer;
46 //import org.eclipse.jface.viewers.ViewerSorter;
47 //import org.eclipse.jface.window.Window;
48 import org.eclipse.swt.SWT;
49 import org.eclipse.swt.events.SelectionAdapter;
50 import org.eclipse.swt.events.SelectionEvent;
51 import org.eclipse.swt.graphics.Font;
52 import org.eclipse.swt.graphics.Image;
53 import org.eclipse.swt.layout.GridData;
54 import org.eclipse.swt.layout.GridLayout;
55 import org.eclipse.swt.widgets.Button;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Label;
58 import org.eclipse.swt.widgets.Table;
59 import org.eclipse.swt.widgets.TableColumn;
60 import org.eclipse.swt.widgets.TableItem;
61
62 public class PHPPathMapTab extends AbstractLaunchConfigurationTab {
63         protected TableViewer fPathMapTable;
64         protected Button fAddButton;
65         protected Button envAddCGIButton;
66         protected Button fEditButton;
67         protected Button fRemoveButton;
68         protected Button fUpButton;
69         protected Button fDownButton;
70
71         
72         protected String[] fPathMapTableColumnHeaders = { "Local", "Remote" };
73
74         protected ColumnLayoutData[] fPathMapTableColumnLayouts = {
75                         new ColumnWeightData(50), new ColumnWeightData(50) };
76         
77         protected static final String P_REMOTE = "remote"; //$NON-NLS-1$
78         protected static final String P_LOCAL = "local"; //$NON-NLS-1$
79         protected static String[] fPathMapTableColumnProperties = { P_REMOTE, P_LOCAL };
80
81         
82         /**
83          * Content provider for the environment table
84          */
85         protected class PathMapContentProvider implements IStructuredContentProvider {
86                 public Object[] getElements(Object inputElement) {
87                         PathMapItem[] elements = new PathMapItem[0];
88                         ILaunchConfiguration config = (ILaunchConfiguration) inputElement;
89                         List l;
90                         try {
91                                 l = config.getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
92                         } catch (CoreException e) {
93                                 XDebugCorePlugin.log(new Status(IStatus.ERROR,
94                                                 XDebugCorePlugin.PLUGIN_ID, IStatus.ERROR,
95                                                 "Error reading configuration", e)); //$NON-NLS-1$
96                                 return elements;
97                         }
98                         if (l != null && !l.isEmpty()) {
99                                 elements = new PathMapItem[l.size()];
100                                 for (int i = 0; i < l.size(); i++) {
101                                         elements[i] = new PathMapItem((String) l.get(i));
102                                 }
103                         }
104
105                         return elements;
106                 }
107
108                 public void dispose() {
109                 }
110
111                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
112                 }
113         }
114         
115         /**
116          * Label provider for the environment table
117          */
118         public class PathMapItemLabelProvider extends LabelProvider
119                         implements ITableLabelProvider {
120                 public String getColumnText(Object element, int columnIndex) {
121                         String result = null;
122                         if (element != null) {
123                                 PathMapItem var = (PathMapItem) element;
124                                 switch (columnIndex) {
125                                 case 0: // local
126                                         result = var.getLocalPath().toOSString();
127                                         break;
128                                 case 1: // remote
129                                         result = var.getRemotePath().toString();
130                                         break;
131                                 }
132                         }
133                         return result;
134                 }
135
136                 public Image getColumnImage(Object element, int columnIndex) {
137                         return null;
138                 }
139         }
140
141
142         public void createControl(Composite parent) {
143                 // Create main composite
144                 Composite mainComposite = new Composite(parent, SWT.NONE);
145                 setControl(mainComposite);
146                 // WorkbenchHelp.setHelp(getControl(),
147                 // IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_ENVIRONMENT_TAB);
148                 GridLayout layout = new GridLayout();
149                 layout.numColumns = 2;
150                 GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
151                 mainComposite.setLayout(layout);
152                 mainComposite.setLayoutData(gridData);
153                 mainComposite.setFont(parent.getFont());
154
155                 createPathMapTable(mainComposite);
156                 createTableButtons(mainComposite);
157
158                 Dialog.applyDialogFont(mainComposite);
159         }
160         
161         /**
162          * Creates the add/edit/remove buttons for the environment table
163          * 
164          * @param parent
165          *            the composite in which the buttons should be created
166          */
167         protected void createTableButtons(Composite parent) {
168                 // Create button composite
169                 Composite buttonComposite = new Composite(parent, SWT.NONE);
170                 GridLayout glayout = new GridLayout();
171                 glayout.marginHeight = 0;
172                 glayout.marginWidth = 0;
173                 glayout.numColumns = 1;
174                 GridData gdata = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
175                                 | GridData.HORIZONTAL_ALIGN_END);
176                 buttonComposite.setLayout(glayout);
177                 buttonComposite.setLayoutData(gdata);
178                 buttonComposite.setFont(parent.getFont());
179
180                 createVerticalSpacer(buttonComposite, 1);
181                 // Create buttons
182                 fAddButton = createPushButton(buttonComposite, "New", null);
183                 fAddButton.addSelectionListener(new SelectionAdapter() {
184                         public void widgetSelected(SelectionEvent event) {
185                                 handleAddButtonSelected();
186                         }
187                 });
188
189                 fEditButton = createPushButton(buttonComposite, "Edit", null);
190                 fEditButton.addSelectionListener(new SelectionAdapter() {
191                         public void widgetSelected(SelectionEvent event) {
192                                 handleEditButtonSelected();
193                         }
194                 });
195                 fEditButton.setEnabled(false);
196
197                 fRemoveButton = createPushButton(buttonComposite, "Remove", null);
198                 fRemoveButton.addSelectionListener(new SelectionAdapter() {
199                         public void widgetSelected(SelectionEvent event) {
200                                 handleRemoveButtonSelected();
201                         }
202                 });
203                 fRemoveButton.setEnabled(false);
204                 
205                 fUpButton = createPushButton(buttonComposite, "Up", null);
206                 fUpButton.addSelectionListener(new SelectionAdapter() {
207                         public void widgetSelected(SelectionEvent event) {
208                                 handleUpButtonSelected();
209                         }
210                 });
211                 fUpButton.setEnabled(false);
212                 
213                 fDownButton = createPushButton(buttonComposite, "Down", null);
214                 fDownButton.addSelectionListener(new SelectionAdapter() {
215                         public void widgetSelected(SelectionEvent event) {
216                                 handleDownButtonSelected();
217                         }
218                 });
219                 fDownButton.setEnabled(false);
220         }
221
222         
223         /**
224          * Creates and configures the table that displayed the key/value pairs that
225          * comprise the environment.
226          * 
227          * @param parent
228          *            the composite in which the table should be created
229          */
230         protected void createPathMapTable(Composite parent) {
231                 Font font = parent.getFont();
232                 // Create table composite
233                 Composite tableComposite = new Composite(parent, SWT.NONE);
234                 GridLayout layout = new GridLayout();
235                 layout.marginHeight = 0;
236                 layout.marginWidth = 0;
237                 layout.numColumns = 1;
238                 GridData gridData = new GridData(GridData.FILL_BOTH);
239                 gridData.heightHint = 150;
240                 tableComposite.setLayout(layout);
241                 tableComposite.setLayoutData(gridData);
242                 tableComposite.setFont(font);
243                 // Create label
244                 Label label = new Label(tableComposite, SWT.NONE);
245                 label.setFont(font);
246                 label.setText("&Map remote path to local path");
247                 // Create table
248                 fPathMapTable = new TableViewer(tableComposite, SWT.BORDER
249                                 | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
250                 Table table = fPathMapTable.getTable();
251                 TableLayout tableLayout = new TableLayout();
252                 table.setLayout(tableLayout);
253                 table.setHeaderVisible(true);
254                 table.setFont(font);
255                 gridData = new GridData(GridData.FILL_BOTH);
256                 fPathMapTable.getControl().setLayoutData(gridData);
257                 fPathMapTable.setContentProvider(new PathMapContentProvider());
258                 fPathMapTable.setLabelProvider(new PathMapItemLabelProvider());
259                 fPathMapTable.setColumnProperties(fPathMapTableColumnProperties);
260                 fPathMapTable.addSelectionChangedListener(new ISelectionChangedListener() {
261                         public void selectionChanged(SelectionChangedEvent event) {
262                                 handleTableSelectionChanged(event);
263                         }
264                 });
265                 fPathMapTable.addDoubleClickListener(new IDoubleClickListener() {
266                         public void doubleClick(DoubleClickEvent event) {
267                                 if (!fPathMapTable.getSelection().isEmpty()) {
268                                         handleEditButtonSelected();
269                                 }
270                         }
271                 });
272                 // Create columns
273                 for (int i = 0; i < fPathMapTableColumnHeaders.length; i++) {
274                         tableLayout.addColumnData(fPathMapTableColumnLayouts[i]);
275                         TableColumn tc = new TableColumn(table, SWT.NONE, i);
276                         tc.setResizable(fPathMapTableColumnLayouts[i].resizable);
277                         tc.setText(fPathMapTableColumnHeaders[i]);
278                 }
279         }
280         
281         /**
282          * Responds to a selection changed event in the environment table
283          * @param event the selection change event
284          */
285         protected void handleTableSelectionChanged(SelectionChangedEvent event) {
286                 int size  = ((IStructuredSelection)event.getSelection()).size();  // Get number of selected items
287                 int idx   = fPathMapTable.getTable().getSelectionIndex();         // Get the index of the selected item
288                 int count = fPathMapTable.getTable().getItemCount();              // Get the number of entries within the pathmap list
289                 
290                 if (size == 1) {                                              // If one pathmap entry is selected
291                         fEditButton.setEnabled (idx >= 0);                        // Enable 'Edit' button if a pathmap entry is selected
292                         fUpButton.setEnabled (idx > 0);                           // Enable 'Up' button only if the selected entry is not the very first one
293                         fDownButton.setEnabled ((idx >= 0) && (idx < count-1));   // Enable 'Down' button only if the selected entry is not the very last one
294                 }
295                 else {                                                        // If nothing selected, or more than one entry selected
296                     fEditButton.setEnabled (false);                           // Disable 'Edit' button 
297                     fUpButton.setEnabled (false);                             // Disable 'Up' button
298                     fDownButton.setEnabled (false);                           // Disable 'Down' button
299                 }
300                 
301                 fRemoveButton.setEnabled (size > 0);                          // Enable 'Remove' if at least on entry is selected                    
302         }
303         
304         /**
305          * Creates an editor for the value of the selected environment variable.
306          */
307         private void handleUpButtonSelected() {
308                 IStructuredSelection sel = (IStructuredSelection) fPathMapTable.getSelection();
309                 PathMapItem mapItem = (PathMapItem) sel.getFirstElement();
310                 boolean found=false;
311                 if (mapItem == null) {
312                         return;
313                 }
314                 IPath local = mapItem.getLocalPath();
315                 TableItem[] items = fPathMapTable.getTable().getItems();
316                 int i;
317                 for (i = 0; i < items.length; i++) {
318                         PathMapItem item = (PathMapItem) items[i].getData();
319                         if (item.getLocalPath().equals(local)) {
320                                 found=true;
321                                 break;
322                         }
323                 }
324                 if ((i>0) && found) {
325                         fPathMapTable.getControl().setRedraw(false);
326                         fPathMapTable.remove(mapItem);
327                         fPathMapTable.insert(mapItem,i-1);
328                         fPathMapTable.getControl().setRedraw(true);
329                         fPathMapTable.setSelection(new StructuredSelection(mapItem),true);
330                         updateLaunchConfigurationDialog();
331                 }
332         }
333         
334         private void handleDownButtonSelected() {
335                 IStructuredSelection sel = (IStructuredSelection) fPathMapTable.getSelection();
336                 PathMapItem mapItem = (PathMapItem) sel.getFirstElement();
337                 boolean found=false;
338                 if (mapItem == null) {
339                         return;
340                 }
341                 IPath local = mapItem.getLocalPath();
342                 TableItem[] items = fPathMapTable.getTable().getItems();
343                 int i;
344                 for (i = 0; i < items.length; i++) {
345                         PathMapItem item = (PathMapItem) items[i].getData();
346                         if (item.getLocalPath().equals(local)) {
347                                 found=true;
348                                 break;
349                         }
350                 }
351
352                 if ((i<items.length-1) && found) {
353                         fPathMapTable.getControl().setRedraw(false);
354                         fPathMapTable.remove(mapItem);
355                         fPathMapTable.insert(mapItem,i+1);
356                         fPathMapTable.getControl().setRedraw(true);
357                         fPathMapTable.setSelection(new StructuredSelection(mapItem),true);
358                         updateLaunchConfigurationDialog();
359                 }
360         }
361         
362         /**
363          * Creates an editor for the value of the selected environment variable.
364          */
365         private void handleEditButtonSelected() {
366                 IStructuredSelection sel = (IStructuredSelection) fPathMapTable.getSelection();
367                 PathMapItem item = (PathMapItem) sel.getFirstElement();
368                 if (item == null) {
369                         return;
370                 }
371
372                 EditPathMapDialog dialog = new EditPathMapDialog(getShell(), "Edit pathmap", new String[] { item.getLocalPath().toString(),item.getRemotePath().toString() });
373
374                 if (dialog.open() != EditPathMapDialog.OK) {
375                         return;
376                 }
377                 String[] pathPair = dialog.getPathPair();
378                 String newLocalPath=pathPair[0];
379                 String newRemotePath=pathPair[1];
380                 
381                 if (!item.getLocalPath().toString().equals(newLocalPath)) {
382                         if (addVariable(new PathMapItem(newLocalPath,newRemotePath))) {
383                                 fPathMapTable.remove(item);
384                         }
385                 } else {
386                         item.setRemotePath(newRemotePath);
387                         fPathMapTable.update(item, null);
388                         updateLaunchConfigurationDialog();
389                 }
390         }
391         
392         /**
393          * Adds a new environment variable to the table.
394          */
395         protected void handleAddButtonSelected() {
396             EditPathMapDialog dialog = new EditPathMapDialog(getShell(), "Edit File Map", new String[] { "", "" });
397                 if (dialog.open() != EditPathMapDialog.OK) {
398                         return;
399                 }
400                 String[] pathPair = dialog.getPathPair();
401                 
402                 Path local = new Path(pathPair[0]);
403                 Path remote = new Path(pathPair[1]);
404                 
405                 String strlocal = local.toString();
406                 String strremote = remote.toString();
407                 if (strlocal != null && strremote != null && strlocal.length() > 0 && strremote.length() > 0) {
408                                 addVariable(new PathMapItem(strlocal,strremote));
409                 }
410         }
411         
412         /**
413          * Removes the selected environment variable from the table.
414          */
415         private void handleRemoveButtonSelected() {
416                 IStructuredSelection sel = (IStructuredSelection) fPathMapTable.getSelection();
417                 fPathMapTable.getControl().setRedraw(false);
418                 for (Iterator i = sel.iterator(); i.hasNext();) {
419                         PathMapItem item = (PathMapItem) i.next();
420                         fPathMapTable.remove(item);
421                 }
422                 fPathMapTable.getControl().setRedraw(true);
423                 updateLaunchConfigurationDialog();
424         }
425
426         /**
427          * Attempts to add the given variable. Returns whether the variable was
428          * added or not (as when the user answers not to overwrite an existing
429          * variable).
430          * 
431          * @param variable the variable to add
432          * @return whether the variable was added
433          */
434         protected boolean addVariable(PathMapItem mapItem) {
435                 IPath local = mapItem.getLocalPath();
436                 TableItem[] items = fPathMapTable.getTable().getItems();
437                 for (int i = 0; i < items.length; i++) {
438                         PathMapItem item = (PathMapItem) items[i].getData();
439                         if (item.getLocalPath().equals(local)) {
440                                 boolean overWrite = MessageDialog.openQuestion(getShell(),"Overwrite variable?",
441                                                 MessageFormat.format("A local path named {0} already exists. Overwrite?",new String[] { local.toString() }));
442                                 if (!overWrite) {
443                                         return false;
444                                 }
445                                 fPathMapTable.remove(item);
446                                 break;
447                         }
448                 }
449                 fPathMapTable.add(mapItem);
450                 updateLaunchConfigurationDialog();
451                 return true;
452         }
453         
454
455
456         public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
457                 // TODO Auto-generated method stub
458
459         }
460
461         public void initializeFrom(ILaunchConfiguration configuration) {
462                 fPathMapTable.setInput(configuration);
463         }
464
465         public void performApply(ILaunchConfigurationWorkingCopy configuration) {
466                 // Convert the table's items into a List so that this can be saved in the
467                 // configuration's attributes.
468                 TableItem[] items = fPathMapTable.getTable().getItems();
469                 List vec = new Vector(items.length);
470                 for (int i = 0; i < items.length; i++) {
471                         PathMapItem item = (PathMapItem) items[i].getData();
472                         vec.add(item.getStringData());
473                 }
474                 if (vec.size() == 0) {
475                         configuration.setAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
476                 } else {
477                         configuration.setAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, vec);
478                 }
479         }
480
481         /* (non-Javadoc)
482          * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
483          */
484         public boolean isValid(ILaunchConfiguration launchConfig) {
485                 // need to use exception here!
486                 setErrorMessage(null);
487                 
488                 if (fPathMapTable.getTable().getItems().length == 0) {
489                         setErrorMessage("Mappath empty!");
490                         return false;
491                 }
492                 return true;
493         }
494                 
495         public String getName() {
496                 return "Pathmap";
497         }
498 }