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