f448ac6186aa6aae24a8f286b27be2647732393f
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / preferences / CodeFormatterPreferencePage.java
1 /*
2  * (c) Copyright IBM Corp. 2000, 2001.
3  * All Rights Reserved.
4  */
5 package net.sourceforge.phpdt.internal.ui.preferences;
6
7 import java.io.BufferedReader;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.util.ArrayList;
11 import java.util.Hashtable;
12
13 import net.sourceforge.phpdt.core.ICodeFormatter;
14 import net.sourceforge.phpdt.core.JavaCore;
15 import net.sourceforge.phpdt.core.ToolFactory;
16 import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
17 import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
18 import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
19 import net.sourceforge.phpdt.internal.ui.util.TabFolderLayout;
20 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
21
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.jface.preference.PreferencePage;
24 import org.eclipse.jface.text.Document;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.events.ModifyEvent;
28 import org.eclipse.swt.events.ModifyListener;
29 import org.eclipse.swt.events.SelectionEvent;
30 import org.eclipse.swt.events.SelectionListener;
31 import org.eclipse.swt.layout.GridData;
32 import org.eclipse.swt.layout.GridLayout;
33 import org.eclipse.swt.widgets.Button;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Control;
36 import org.eclipse.swt.widgets.Label;
37 import org.eclipse.swt.widgets.TabFolder;
38 import org.eclipse.swt.widgets.TabItem;
39 import org.eclipse.swt.widgets.Text;
40 import org.eclipse.ui.IWorkbench;
41 import org.eclipse.ui.IWorkbenchPreferencePage;
42
43 /*
44  * The page for setting code formatter options
45  */
46 public class CodeFormatterPreferencePage extends PreferencePage implements
47                 IWorkbenchPreferencePage {
48
49         // Preference store keys, see PHPCore.getOptions
50         private static final String PREF_NEWLINE_OPENING_BRACES = JavaCore.FORMATTER_NEWLINE_OPENING_BRACE;
51
52         private static final String PREF_NEWLINE_CONTROL_STATEMENT = JavaCore.FORMATTER_NEWLINE_CONTROL;
53
54         private static final String PREF_NEWLINE_CLEAR_ALL = JavaCore.FORMATTER_CLEAR_BLANK_LINES;
55
56         // private static final String PREF_NEWLINE_ELSE_IF=
57         // PHPCore.FORMATTER_NEWLINE_ELSE_IF;
58         private static final String PREF_NEWLINE_EMPTY_BLOCK = JavaCore.FORMATTER_NEWLINE_EMPTY_BLOCK;
59
60         private static final String PREF_LINE_SPLIT = JavaCore.FORMATTER_LINE_SPLIT;
61
62         private static final String PREF_STYLE_COMPACT_ASSIGNEMENT = JavaCore.FORMATTER_COMPACT_ASSIGNMENT;
63
64         private static final String PREF_TAB_CHAR = JavaCore.FORMATTER_TAB_CHAR;
65
66         private static final String PREF_TAB_SIZE = JavaCore.FORMATTER_TAB_SIZE;
67
68         // values
69         private static final String INSERT = JavaCore.INSERT;
70
71         private static final String DO_NOT_INSERT = JavaCore.DO_NOT_INSERT;
72
73         private static final String COMPACT = JavaCore.COMPACT;
74
75         private static final String NORMAL = JavaCore.NORMAL;
76
77         private static final String TAB = JavaCore.TAB;
78
79         private static final String SPACE = JavaCore.SPACE;
80
81         private static final String CLEAR_ALL = JavaCore.CLEAR_ALL;
82
83         private static final String PRESERVE_ONE = JavaCore.PRESERVE_ONE;
84
85         private static String[] getAllKeys() {
86                 return new String[] { PREF_NEWLINE_OPENING_BRACES,
87                                 PREF_NEWLINE_CONTROL_STATEMENT, PREF_NEWLINE_CLEAR_ALL,
88                                 // PREF_NEWLINE_ELSE_IF,
89                                 PREF_NEWLINE_EMPTY_BLOCK, PREF_LINE_SPLIT,
90                                 PREF_STYLE_COMPACT_ASSIGNEMENT, PREF_TAB_CHAR, PREF_TAB_SIZE };
91         }
92
93         /**
94          * Gets the currently configured tab size
95          * 
96          * @deprecated Inline to avoid reference to preference page
97          */
98         public static int getTabSize() {
99                 String string = (String) JavaCore.getOptions().get(PREF_TAB_SIZE);
100                 return getPositiveIntValue(string, 4);
101         }
102
103         /**
104          * Gets the current compating assignement configuration
105          * 
106          * @deprecated Inline to avoid reference to preference page
107          */
108         public static boolean isCompactingAssignment() {
109                 return COMPACT.equals(JavaCore.getOptions().get(
110                                 PREF_STYLE_COMPACT_ASSIGNEMENT));
111         }
112
113         /**
114          * Gets the current compating assignement configuration
115          * 
116          * @deprecated Inline to avoid reference to preference page
117          */
118         public static boolean useSpaces() {
119                 return SPACE.equals(JavaCore.getOptions().get(PREF_TAB_CHAR));
120         }
121
122         private static int getPositiveIntValue(String string, int dflt) {
123                 try {
124                         int i = Integer.parseInt(string);
125                         if (i >= 0) {
126                                 return i;
127                         }
128                 } catch (NumberFormatException e) {
129                 }
130                 return dflt;
131         }
132
133         private static class ControlData {
134                 private String fKey;
135
136                 private String[] fValues;
137
138                 public ControlData(String key, String[] values) {
139                         fKey = key;
140                         fValues = values;
141                 }
142
143                 public String getKey() {
144                         return fKey;
145                 }
146
147                 public String getValue(boolean selection) {
148                         int index = selection ? 0 : 1;
149                         return fValues[index];
150                 }
151
152                 public String getValue(int index) {
153                         return fValues[index];
154                 }
155
156                 public int getSelection(String value) {
157                         for (int i = 0; i < fValues.length; i++) {
158                                 if (value.equals(fValues[i])) {
159                                         return i;
160                                 }
161                         }
162                         throw new IllegalArgumentException();
163                 }
164         }
165
166         private Hashtable fWorkingValues;
167
168         private ArrayList fCheckBoxes;
169
170         private ArrayList fTextBoxes;
171
172         private SelectionListener fButtonSelectionListener;
173
174         private ModifyListener fTextModifyListener;
175
176         private String fPreviewText;
177
178         private IDocument fPreviewDocument;
179
180         private Text fTabSizeTextBox;
181
182         // private SourceViewer fSourceViewer;
183
184         public CodeFormatterPreferencePage() {
185                 setPreferenceStore(PHPeclipsePlugin.getDefault().getPreferenceStore());
186                 setDescription(PHPUIMessages
187                                 .getString("CodeFormatterPreferencePage.description")); //$NON-NLS-1$
188
189                 fWorkingValues = JavaCore.getOptions();
190                 fCheckBoxes = new ArrayList();
191                 fTextBoxes = new ArrayList();
192
193                 fButtonSelectionListener = new SelectionListener() {
194                         public void widgetDefaultSelected(SelectionEvent e) {
195                         }
196
197                         public void widgetSelected(SelectionEvent e) {
198                                 if (!e.widget.isDisposed()) {
199                                         controlChanged((Button) e.widget);
200                                 }
201                         }
202                 };
203
204                 fTextModifyListener = new ModifyListener() {
205                         public void modifyText(ModifyEvent e) {
206                                 if (!e.widget.isDisposed()) {
207                                         textChanged((Text) e.widget);
208                                 }
209                         }
210                 };
211
212                 fPreviewDocument = new Document();
213                 fPreviewText = loadPreviewFile("CodeFormatterPreviewCode.txt"); //$NON-NLS-1$   
214         }
215
216         /*
217          * @see IWorkbenchPreferencePage#init()
218          */
219         public void init(IWorkbench workbench) {
220         }
221
222         /*
223          * @see PreferencePage#createControl(Composite)
224          */
225         public void createControl(Composite parent) {
226                 super.createControl(parent);
227                 // WorkbenchHelp.setHelp(getControl(),
228                 // IJavaHelpContextIds.CODEFORMATTER_PREFERENCE_PAGE);
229         }
230
231         /*
232          * @see PreferencePage#createContents(Composite)
233          */
234         protected Control createContents(Composite parent) {
235
236                 GridLayout layout = new GridLayout();
237                 layout.marginHeight = 0;
238                 layout.marginWidth = 0;
239
240                 Composite composite = new Composite(parent, SWT.NONE);
241                 composite.setLayout(layout);
242
243                 TabFolder folder = new TabFolder(composite, SWT.NONE);
244                 folder.setLayout(new TabFolderLayout());
245                 folder.setLayoutData(new GridData(GridData.FILL_BOTH));
246
247                 String[] insertNotInsert = new String[] { INSERT, DO_NOT_INSERT };
248
249                 layout = new GridLayout();
250                 layout.numColumns = 2;
251
252                 Composite newlineComposite = new Composite(folder, SWT.NULL);
253                 newlineComposite.setLayout(layout);
254
255                 String label = PHPUIMessages
256                                 .getString("CodeFormatterPreferencePage.newline_opening_braces.label"); //$NON-NLS-1$
257                 addCheckBox(newlineComposite, label, PREF_NEWLINE_OPENING_BRACES,
258                                 insertNotInsert);
259
260                 label = PHPUIMessages
261                                 .getString("CodeFormatterPreferencePage.newline_control_statement.label"); //$NON-NLS-1$
262                 addCheckBox(newlineComposite, label, PREF_NEWLINE_CONTROL_STATEMENT,
263                                 insertNotInsert);
264
265                 label = PHPUIMessages
266                                 .getString("CodeFormatterPreferencePage.newline_clear_lines"); //$NON-NLS-1$
267                 addCheckBox(newlineComposite, label, PREF_NEWLINE_CLEAR_ALL,
268                                 new String[] { CLEAR_ALL, PRESERVE_ONE });
269
270                 // label=
271                 // PHPUIMessages.getString("CodeFormatterPreferencePage.newline_else_if.label");
272                 // //$NON-NLS-1$
273                 // addCheckBox(newlineComposite, label, PREF_NEWLINE_ELSE_IF,
274                 // insertNotInsert);
275
276                 label = PHPUIMessages
277                                 .getString("CodeFormatterPreferencePage.newline_empty_block.label"); //$NON-NLS-1$
278                 addCheckBox(newlineComposite, label, PREF_NEWLINE_EMPTY_BLOCK,
279                                 insertNotInsert);
280
281                 layout = new GridLayout();
282                 layout.numColumns = 2;
283
284                 Composite lineSplittingComposite = new Composite(folder, SWT.NULL);
285                 lineSplittingComposite.setLayout(layout);
286
287                 label = PHPUIMessages
288                                 .getString("CodeFormatterPreferencePage.split_line.label"); //$NON-NLS-1$
289                 addTextField(lineSplittingComposite, label, PREF_LINE_SPLIT);
290
291                 layout = new GridLayout();
292                 layout.numColumns = 2;
293
294                 Composite styleComposite = new Composite(folder, SWT.NULL);
295                 styleComposite.setLayout(layout);
296
297                 label = PHPUIMessages
298                                 .getString("CodeFormatterPreferencePage.style_compact_assignement.label"); //$NON-NLS-1$
299                 addCheckBox(styleComposite, label, PREF_STYLE_COMPACT_ASSIGNEMENT,
300                                 new String[] { COMPACT, NORMAL });
301
302                 label = PHPUIMessages
303                                 .getString("CodeFormatterPreferencePage.tab_char.label"); //$NON-NLS-1$
304                 addCheckBox(styleComposite, label, PREF_TAB_CHAR, new String[] { TAB,
305                                 SPACE });
306
307                 label = PHPUIMessages
308                                 .getString("CodeFormatterPreferencePage.tab_size.label"); //$NON-NLS-1$
309                 fTabSizeTextBox = addTextField(styleComposite, label, PREF_TAB_SIZE);
310
311                 TabItem item = new TabItem(folder, SWT.NONE);
312                 item.setText(PHPUIMessages
313                                 .getString("CodeFormatterPreferencePage.tab.newline.tabtitle")); //$NON-NLS-1$
314                 item.setControl(newlineComposite);
315
316                 item = new TabItem(folder, SWT.NONE);
317                 item
318                                 .setText(PHPUIMessages
319                                                 .getString("CodeFormatterPreferencePage.tab.linesplit.tabtitle")); //$NON-NLS-1$
320                 item.setControl(lineSplittingComposite);
321
322                 item = new TabItem(folder, SWT.NONE);
323                 item.setText(PHPUIMessages
324                                 .getString("CodeFormatterPreferencePage.tab.style.tabtitle")); //$NON-NLS-1$
325                 item.setControl(styleComposite);
326
327                 // fSourceViewer= createPreview(parent);
328
329                 updatePreview();
330
331                 return composite;
332         }
333
334         // private SourceViewer createPreview(Composite parent) {
335         // SourceViewer previewViewer= new SourceViewer(parent, null, SWT.V_SCROLL |
336         // SWT.H_SCROLL | SWT.BORDER);
337         // JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
338         // previewViewer.configure(new PHPSourceViewerConfiguration(tools, null));
339         // previewViewer.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
340         // previewViewer.getTextWidget().setTabs(getPositiveIntValue((String)
341         // fWorkingValues.get(PREF_TAB_SIZE), 0));
342         // previewViewer.setEditable(false);
343         // previewViewer.setDocument(fPreviewDocument);
344         // Control control= previewViewer.getControl();
345         // GridData gdata= new GridData(GridData.FILL_BOTH);
346         // gdata.widthHint= convertWidthInCharsToPixels(30);
347         // gdata.heightHint= convertHeightInCharsToPixels(5);
348         // control.setLayoutData(gdata);
349         // return previewViewer;
350         // }
351
352         private Button addCheckBox(Composite parent, String label, String key,
353                         String[] values) {
354                 ControlData data = new ControlData(key, values);
355
356                 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
357                 gd.horizontalSpan = 2;
358
359                 Button checkBox = new Button(parent, SWT.CHECK);
360                 checkBox.setText(label);
361                 checkBox.setData(data);
362                 checkBox.setLayoutData(gd);
363
364                 String currValue = (String) fWorkingValues.get(key);
365                 checkBox.setSelection(data.getSelection(currValue) == 0);
366                 checkBox.addSelectionListener(fButtonSelectionListener);
367
368                 fCheckBoxes.add(checkBox);
369                 return checkBox;
370         }
371
372         private Text addTextField(Composite parent, String label, String key) {
373                 Label labelControl = new Label(parent, SWT.NONE);
374                 labelControl.setText(label);
375                 labelControl.setLayoutData(new GridData());
376
377                 Text textBox = new Text(parent, SWT.BORDER | SWT.SINGLE);
378                 textBox.setData(key);
379                 textBox.setLayoutData(new GridData());
380
381                 String currValue = (String) fWorkingValues.get(key);
382                 textBox.setText(String.valueOf(getPositiveIntValue(currValue, 1)));
383                 textBox.setTextLimit(3);
384                 textBox.addModifyListener(fTextModifyListener);
385
386                 GridData gd = new GridData();
387                 gd.widthHint = convertWidthInCharsToPixels(5);
388                 textBox.setLayoutData(gd);
389
390                 fTextBoxes.add(textBox);
391                 return textBox;
392         }
393
394         private void controlChanged(Button button) {
395                 ControlData data = (ControlData) button.getData();
396                 boolean selection = button.getSelection();
397                 String newValue = data.getValue(selection);
398                 fWorkingValues.put(data.getKey(), newValue);
399                 updatePreview();
400
401                 if (PREF_TAB_CHAR.equals(data.getKey())) {
402                         updateStatus(new StatusInfo());
403                         if (selection) {
404                                 fTabSizeTextBox.setText((String) fWorkingValues
405                                                 .get(PREF_TAB_SIZE));
406                         }
407                 }
408         }
409
410         private void textChanged(Text textControl) {
411                 String key = (String) textControl.getData();
412                 String number = textControl.getText();
413                 IStatus status = validatePositiveNumber(number);
414                 if (!status.matches(IStatus.ERROR)) {
415                         fWorkingValues.put(key, number);
416                 }
417                 // if (PREF_TAB_SIZE.equals(key)) {
418                 // fSourceViewer.getTextWidget().setTabs(getPositiveIntValue(number,
419                 // 0));
420                 // }
421                 updateStatus(status);
422                 updatePreview();
423         }
424
425         /*
426          * @see IPreferencePage#performOk()
427          */
428         public boolean performOk() {
429                 String[] allKeys = getAllKeys();
430                 // preserve other options
431                 // store in JCore
432                 Hashtable actualOptions = JavaCore.getOptions();
433                 for (int i = 0; i < allKeys.length; i++) {
434                         String key = allKeys[i];
435                         String val = (String) fWorkingValues.get(key);
436                         actualOptions.put(key, val);
437                 }
438                 JavaCore.setOptions(actualOptions);
439                 PHPeclipsePlugin.getDefault().savePluginPreferences();
440                 return super.performOk();
441         }
442
443         /*
444          * @see PreferencePage#performDefaults()
445          */
446         protected void performDefaults() {
447                 fWorkingValues = JavaCore.getDefaultOptions();
448                 updateControls();
449                 super.performDefaults();
450         }
451
452         private String loadPreviewFile(String filename) {
453                 String separator = System.getProperty("line.separator"); //$NON-NLS-1$
454                 StringBuffer btxt = new StringBuffer(512);
455                 BufferedReader rin = null;
456                 try {
457                         rin = new BufferedReader(new InputStreamReader(getClass()
458                                         .getResourceAsStream(filename)));
459                         String line;
460                         while ((line = rin.readLine()) != null) {
461                                 btxt.append(line);
462                                 btxt.append(separator);
463                         }
464                 } catch (IOException io) {
465                         PHPeclipsePlugin.log(io);
466                 } finally {
467                         if (rin != null) {
468                                 try {
469                                         rin.close();
470                                 } catch (IOException e) {
471                                 }
472                         }
473                 }
474                 return btxt.toString();
475         }
476
477         private void updatePreview() {
478                 ICodeFormatter formatter = ToolFactory
479                                 .createDefaultCodeFormatter(fWorkingValues);
480                 fPreviewDocument.set(formatter.format(fPreviewText, 0, null, "\n")); //$NON-NLS-1$
481         }
482
483         private void updateControls() {
484                 // update the UI
485                 for (int i = fCheckBoxes.size() - 1; i >= 0; i--) {
486                         Button curr = (Button) fCheckBoxes.get(i);
487                         ControlData data = (ControlData) curr.getData();
488
489                         String currValue = (String) fWorkingValues.get(data.getKey());
490                         curr.setSelection(data.getSelection(currValue) == 0);
491                 }
492                 for (int i = fTextBoxes.size() - 1; i >= 0; i--) {
493                         Text curr = (Text) fTextBoxes.get(i);
494                         String key = (String) curr.getData();
495                         String currValue = (String) fWorkingValues.get(key);
496                         curr.setText(currValue);
497                 }
498         }
499
500         private IStatus validatePositiveNumber(String number) {
501                 StatusInfo status = new StatusInfo();
502                 if (number.length() == 0) {
503                         status.setError(PHPUIMessages
504                                         .getString("CodeFormatterPreferencePage.empty_input")); //$NON-NLS-1$
505                 } else {
506                         try {
507                                 int value = Integer.parseInt(number);
508                                 if (value < 0) {
509                                         status
510                                                         .setError(PHPUIMessages
511                                                                         .getFormattedString(
512                                                                                         "CodeFormatterPreferencePage.invalid_input", number)); //$NON-NLS-1$
513                                 }
514                         } catch (NumberFormatException e) {
515                                 status.setError(PHPUIMessages.getFormattedString(
516                                                 "CodeFormatterPreferencePage.invalid_input", number)); //$NON-NLS-1$
517                         }
518                 }
519                 return status;
520         }
521
522         private void updateStatus(IStatus status) {
523                 if (!status.matches(IStatus.ERROR)) {
524                         // look if there are more severe errors
525                         for (int i = 0; i < fTextBoxes.size(); i++) {
526                                 Text curr = (Text) fTextBoxes.get(i);
527                                 if (!(curr == fTabSizeTextBox && usesTabs())) {
528                                         IStatus currStatus = validatePositiveNumber(curr.getText());
529                                         status = StatusUtil.getMoreSevere(currStatus, status);
530                                 }
531                         }
532                 }
533                 setValid(!status.matches(IStatus.ERROR));
534                 StatusUtil.applyToStatusLine(this, status);
535         }
536
537         private boolean usesTabs() {
538                 return TAB.equals(fWorkingValues.get(PREF_TAB_CHAR));
539         }
540
541 }