improved include detection
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / preferences / OptionsConfigurationBlock.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.preferences;
12
13 import java.lang.reflect.InvocationTargetException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
17 import java.util.Map;
18 import java.util.StringTokenizer;
19
20 import net.sourceforge.phpdt.core.IJavaProject;
21 import net.sourceforge.phpdt.core.JavaCore;
22 import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
23 import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
24 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
25
26 import org.eclipse.core.resources.IncrementalProjectBuilder;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.SubProgressMonitor;
30 import org.eclipse.jface.dialogs.IDialogConstants;
31 import org.eclipse.jface.dialogs.MessageDialog;
32 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
33 import org.eclipse.jface.operation.IRunnableWithProgress;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.ModifyEvent;
36 import org.eclipse.swt.events.ModifyListener;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.layout.GridData;
40 import org.eclipse.swt.layout.GridLayout;
41 import org.eclipse.swt.widgets.Button;
42 import org.eclipse.swt.widgets.Combo;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Control;
45 import org.eclipse.swt.widgets.Label;
46 import org.eclipse.swt.widgets.Shell;
47 import org.eclipse.swt.widgets.Text;
48 import org.eclipse.swt.widgets.Widget;
49
50 /**
51   */
52 public abstract class OptionsConfigurationBlock {
53
54         protected static class ControlData {
55                 private String fKey;
56                 private String[] fValues;
57                 
58                 public ControlData(String key, String[] values) {
59                         fKey= key;
60                         fValues= values;
61                 }
62                 
63                 public String getKey() {
64                         return fKey;
65                 }
66                 
67                 public String getValue(boolean selection) {
68                         int index= selection ? 0 : 1;
69                         return fValues[index];
70                 }
71                 
72                 public String getValue(int index) {
73                         return fValues[index];
74                 }               
75                 
76                 public int getSelection(String value) {
77                         for (int i= 0; i < fValues.length; i++) {
78                                 if (value.equals(fValues[i])) {
79                                         return i;
80                                 }
81                         }
82                         return 0;
83                 }
84         }
85         
86         
87         protected Map fWorkingValues;
88
89         protected ArrayList fCheckBoxes;
90         protected ArrayList fComboBoxes;
91         protected ArrayList fTextBoxes;
92         protected HashMap fLabels;
93         
94         private SelectionListener fSelectionListener;
95         private ModifyListener fTextModifyListener;
96
97         protected IStatusChangeListener fContext;
98         protected IJavaProject fProject; // project or null
99         
100         private Shell fShell;
101
102         public OptionsConfigurationBlock(IStatusChangeListener context, IJavaProject project) {
103                 fContext= context;
104                 fProject= project;
105                 
106                 fWorkingValues= getOptions(true);
107                 
108                 fCheckBoxes= new ArrayList();
109                 fComboBoxes= new ArrayList();
110                 fTextBoxes= new ArrayList(2);
111                 fLabels= new HashMap();
112         }
113         
114         protected abstract String[] getAllKeys();
115         
116         protected Map getOptions(boolean inheritJavaCoreOptions) {
117                 if (fProject != null) {
118                         return fProject.getOptions(inheritJavaCoreOptions);
119                 } else {
120                         return JavaCore.getOptions();
121                 }       
122         }
123         
124         protected Map getDefaultOptions() {
125                 return JavaCore.getDefaultOptions();
126         }       
127         
128         public final boolean hasProjectSpecificOptions() {
129                 if (fProject != null) {
130                         Map settings= fProject.getOptions(false);
131                         String[] allKeys= getAllKeys();
132                         for (int i= 0; i < allKeys.length; i++) {
133                                 if (settings.get(allKeys[i]) != null) {
134                                         return true;
135                                 }
136                         }
137                 }
138                 return false;
139         }       
140                 
141         protected void setOptions(Map map) {
142                 if (fProject != null) {
143                         fProject.setOptions(map);
144                 } else {
145                         JavaCore.setOptions((Hashtable) map);
146                 }       
147         } 
148         
149         protected Shell getShell() {
150                 return fShell;
151         }
152         
153         protected void setShell(Shell shell) {
154                 fShell= shell;
155         }       
156         
157         protected abstract Control createContents(Composite parent);
158         
159         protected Button addCheckBox(Composite parent, String label, String key, String[] values, int indent) {
160                 ControlData data= new ControlData(key, values);
161                 
162                 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
163                 gd.horizontalSpan= 3;
164                 gd.horizontalIndent= indent;
165                 
166                 Button checkBox= new Button(parent, SWT.CHECK);
167                 checkBox.setText(label);
168                 checkBox.setData(data);
169                 checkBox.setLayoutData(gd);
170                 checkBox.addSelectionListener(getSelectionListener());
171                 
172                 String currValue= (String)fWorkingValues.get(key);      
173                 checkBox.setSelection(data.getSelection(currValue) == 0);
174                 
175                 fCheckBoxes.add(checkBox);
176                 
177                 return checkBox;
178         }
179         
180         protected Combo addComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) {
181                 ControlData data= new ControlData(key, values);
182                 
183                 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
184                 gd.horizontalIndent= indent;
185                                 
186                 Label labelControl= new Label(parent, SWT.LEFT | SWT.WRAP);
187                 labelControl.setText(label);
188                 labelControl.setLayoutData(gd);
189                 
190                 Combo comboBox= new Combo(parent, SWT.READ_ONLY);
191                 comboBox.setItems(valueLabels);
192                 comboBox.setData(data);
193                 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
194                 comboBox.addSelectionListener(getSelectionListener());
195                 
196                 fLabels.put(comboBox, labelControl);
197                 
198                 Label placeHolder= new Label(parent, SWT.NONE);
199                 placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
200                 
201                 String currValue= (String)fWorkingValues.get(key);      
202                 comboBox.select(data.getSelection(currValue));
203                 
204                 fComboBoxes.add(comboBox);
205                 return comboBox;
206         }
207         
208         protected void addInversedComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) {
209                 ControlData data= new ControlData(key, values);
210                 
211                 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
212                 gd.horizontalIndent= indent;
213                 gd.horizontalSpan= 3;
214                 
215                 Composite composite= new Composite(parent, SWT.NONE);
216                 GridLayout layout= new GridLayout();
217                 layout.marginHeight= 0;
218                 layout.marginWidth= 0;
219                 layout.numColumns= 2;
220                 composite.setLayout(layout);
221                 composite.setLayoutData(gd);
222                 
223                 Combo comboBox= new Combo(composite, SWT.READ_ONLY);
224                 comboBox.setItems(valueLabels);
225                 comboBox.setData(data);
226                 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
227                 comboBox.addSelectionListener(getSelectionListener());
228                 
229                 Label labelControl= new Label(composite, SWT.LEFT | SWT.WRAP);
230                 labelControl.setText(label);
231                 labelControl.setLayoutData(new GridData());
232                 
233                 fLabels.put(comboBox, labelControl);
234                 
235                 String currValue= (String)fWorkingValues.get(key);      
236                 comboBox.select(data.getSelection(currValue));
237                 
238                 fComboBoxes.add(comboBox);
239         }
240         
241         protected Text addTextField(Composite parent, String label, String key, int indent, int widthHint) {    
242                 Label labelControl= new Label(parent, SWT.NONE);
243                 labelControl.setText(label);
244                 labelControl.setLayoutData(new GridData());
245                                 
246                 Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
247                 textBox.setData(key);
248                 textBox.setLayoutData(new GridData());
249                 
250                 fLabels.put(textBox, labelControl);
251                 
252                 String currValue= (String) fWorkingValues.get(key);     
253                 textBox.setText(currValue);
254                 textBox.addModifyListener(getTextModifyListener());
255
256                 GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
257                 if (widthHint != 0) {
258                         data.widthHint= widthHint;
259                 }
260                 data.horizontalIndent= indent;
261                 data.horizontalSpan= 2;
262                 textBox.setLayoutData(data);
263
264                 fTextBoxes.add(textBox);
265                 return textBox;
266         }       
267
268         protected SelectionListener getSelectionListener() {
269                 if (fSelectionListener == null) {
270                         fSelectionListener= new SelectionListener() {
271                                 public void widgetDefaultSelected(SelectionEvent e) {}
272         
273                                 public void widgetSelected(SelectionEvent e) {
274                                         controlChanged(e.widget);
275                                 }
276                         };
277                 }
278                 return fSelectionListener;
279         }
280         
281         protected ModifyListener getTextModifyListener() {
282                 if (fTextModifyListener == null) {
283                         fTextModifyListener= new ModifyListener() {
284                                 public void modifyText(ModifyEvent e) {
285                                         textChanged((Text) e.widget);
286                                 }
287                         };
288                 }
289                 return fTextModifyListener;
290         }               
291         
292         protected void controlChanged(Widget widget) {
293                 ControlData data= (ControlData) widget.getData();
294                 String newValue= null;
295                 if (widget instanceof Button) {
296                         newValue= data.getValue(((Button)widget).getSelection());                       
297                 } else if (widget instanceof Combo) {
298                         newValue= data.getValue(((Combo)widget).getSelectionIndex());
299                 } else {
300                         return;
301                 }
302                 fWorkingValues.put(data.getKey(), newValue);
303                 
304                 validateSettings(data.getKey(), newValue);
305         }
306         
307         protected void textChanged(Text textControl) {
308                 String key= (String) textControl.getData();
309                 String number= textControl.getText();
310                 fWorkingValues.put(key, number);
311                 validateSettings(key, number);
312         }       
313
314         protected boolean checkValue(String key, String value) {
315                 return value.equals(fWorkingValues.get(key));
316         }
317         
318         /* (non-javadoc)
319          * Update fields and validate.
320          * @param changedKey Key that changed, or null, if all changed.
321          */     
322         protected abstract void validateSettings(String changedKey, String newValue);
323         
324         
325         protected String[] getTokens(String text, String separator) {
326                 StringTokenizer tok= new StringTokenizer(text, separator); //$NON-NLS-1$
327                 int nTokens= tok.countTokens();
328                 String[] res= new String[nTokens];
329                 for (int i= 0; i < res.length; i++) {
330                         res[i]= tok.nextToken().trim();
331                 }
332                 return res;
333         }       
334
335         
336         public boolean performOk(boolean enabled) {
337                 String[] allKeys= getAllKeys();
338                 Map actualOptions= getOptions(false);
339                 
340                 // preserve other options
341                 boolean hasChanges= false;
342                 for (int i= 0; i < allKeys.length; i++) {
343                         String key= allKeys[i];
344                         String oldVal= (String) actualOptions.get(key);
345                         String val= null;
346                         if (enabled) {
347                                 val= (String) fWorkingValues.get(key);
348                                 if (!val.equals(oldVal)) {
349                                         hasChanges= true;
350                                         actualOptions.put(key, val);
351                                 }
352                         } else {
353                                 if (oldVal != null) {
354                                         actualOptions.remove(key);
355                                         hasChanges= true;
356                                 }
357                         }
358                 }
359                 
360                 
361                 if (hasChanges) {
362                         boolean doBuild= false;
363                         String[] strings= getFullBuildDialogStrings(fProject == null);
364                         if (strings != null) {
365                                 MessageDialog dialog= new MessageDialog(getShell(), strings[0], null, strings[1], MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 2);
366                                 int res= dialog.open();
367                                 if (res == 0) {
368                                         doBuild= true;
369                                 } else if (res != 1) {
370                                         return false; // cancel pressed
371                                 }
372                         }
373                         setOptions(actualOptions);
374                         if (doBuild) {
375                                 doFullBuild();
376                         }
377                 }
378                 return true;
379         }
380         
381         protected abstract String[] getFullBuildDialogStrings(boolean workspaceSettings);
382                 
383         protected void doFullBuild() {
384                 ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell());
385                 try {
386                         dialog.run(true, true, new IRunnableWithProgress() { 
387                                 public void run(IProgressMonitor monitor) throws InvocationTargetException {
388                                         monitor.beginTask("", 2); //$NON-NLS-1$
389                                         try {
390                                                 if (fProject != null) {
391                                                         monitor.setTaskName(PreferencesMessages.getFormattedString("OptionsConfigurationBlock.buildproject.taskname", fProject.getElementName())); //$NON-NLS-1$
392                                                         fProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor,1));
393                                                         PHPeclipsePlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, new SubProgressMonitor(monitor,1));
394                                                 } else {
395                                                         monitor.setTaskName(PreferencesMessages.getString("OptionsConfigurationBlock.buildall.taskname")); //$NON-NLS-1$
396                                                         PHPeclipsePlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor, 2));
397                                                 }
398                                         } catch (CoreException e) {
399                                                 throw new InvocationTargetException(e);
400                                         } finally {
401                                                 monitor.done();
402                                         }
403                                 }
404                         });
405                 } catch (InterruptedException e) {
406                         // cancelled by user
407                 } catch (InvocationTargetException e) {
408                         String title= PreferencesMessages.getString("OptionsConfigurationBlock.builderror.title"); //$NON-NLS-1$
409                         String message= PreferencesMessages.getString("OptionsConfigurationBlock.builderror.message"); //$NON-NLS-1$
410                         ExceptionHandler.handle(e, getShell(), title, message);
411                 }
412         }               
413         
414         public void performDefaults() {
415                 fWorkingValues= getDefaultOptions();
416                 updateControls();
417                 validateSettings(null, null);
418         }
419         
420         protected void updateControls() {
421                 // update the UI
422                 for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
423                         Button curr= (Button) fCheckBoxes.get(i);
424                         ControlData data= (ControlData) curr.getData();
425                                         
426                         String currValue= (String) fWorkingValues.get(data.getKey());   
427                         curr.setSelection(data.getSelection(currValue) == 0);                   
428                 }
429                 for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
430                         Combo curr= (Combo) fComboBoxes.get(i);
431                         ControlData data= (ControlData) curr.getData();
432                                         
433                         String currValue= (String) fWorkingValues.get(data.getKey());   
434                         curr.select(data.getSelection(currValue));                      
435                 }
436                 for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
437                         Text curr= (Text) fTextBoxes.get(i);
438                         String key= (String) curr.getData();
439                         
440                         String currValue= (String) fWorkingValues.get(key);
441                         curr.setText(currValue);
442                 }
443         }
444         
445         protected Button getCheckBox(String key) {
446                 for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
447                         Button curr= (Button) fCheckBoxes.get(i);
448                         ControlData data= (ControlData) curr.getData();
449                         if (key.equals(data.getKey())) {
450                                 return curr;
451                         }
452                 }
453                 return null;            
454         }
455         
456         protected Combo getComboBox(String key) {
457                 for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
458                         Combo curr= (Combo) fComboBoxes.get(i);
459                         ControlData data= (ControlData) curr.getData();
460                         if (key.equals(data.getKey())) {
461                                 return curr;
462                         }
463                 }
464                 return null;            
465         }
466         
467         protected void setComboEnabled(String key, boolean enabled) {
468                 Combo combo= getComboBox(key);
469                 Label label= (Label) fLabels.get(combo);
470                 combo.setEnabled(enabled);
471                 label.setEnabled(enabled);
472         }
473         
474         
475         
476 }