*** empty log message ***
[phpeclipse.git] / net.sourceforge.phpeclipse.xml.ui / src / net / sourceforge / phpeclipse / xml / ui / internal / preferences / XMLSyntaxPreferencePage.java
1 /*
2  * Copyright (c) 2002-2004 Roberto Gonzalez Rocha 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  *     Roberto Gonzalez Rocha - Initial version
10  *     Igor Malinin - refactoring, minor changes
11  *
12  * $Id: XMLSyntaxPreferencePage.java,v 1.1 2004-09-02 18:28:03 jsurfer Exp $
13  */
14
15 package net.sourceforge.phpeclipse.xml.ui.internal.preferences;
16
17 import java.io.BufferedReader;
18 import java.io.IOException;
19 import java.io.InputStreamReader;
20
21 import org.eclipse.jface.preference.IPreferenceStore;
22 import org.eclipse.jface.preference.PreferenceConverter;
23 import org.eclipse.jface.preference.PreferencePage;
24 import org.eclipse.jface.resource.JFaceResources;
25 import org.eclipse.jface.text.Document;
26 import org.eclipse.jface.text.IDocument;
27 import org.eclipse.jface.text.IDocumentPartitioner;
28 import org.eclipse.jface.text.source.ISourceViewer;
29 import org.eclipse.jface.text.source.SourceViewer;
30 import org.eclipse.jface.util.IPropertyChangeListener;
31 import org.eclipse.jface.util.PropertyChangeEvent;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.custom.StyledText;
34 import org.eclipse.swt.events.SelectionEvent;
35 import org.eclipse.swt.events.SelectionListener;
36 import org.eclipse.swt.graphics.Color;
37 import org.eclipse.swt.graphics.RGB;
38 import org.eclipse.swt.layout.GridData;
39 import org.eclipse.swt.layout.GridLayout;
40 import org.eclipse.swt.layout.RowLayout;
41 import org.eclipse.swt.widgets.Button;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.Display;
45 import org.eclipse.swt.widgets.Group;
46 import org.eclipse.swt.widgets.Label;
47 import org.eclipse.swt.widgets.List;
48 import org.eclipse.ui.IWorkbench;
49 import org.eclipse.ui.IWorkbenchPreferencePage;
50 import org.eclipse.ui.texteditor.AbstractTextEditor;
51
52 import net.sourceforge.phpeclipse.ui.ColorEditor;
53 import net.sourceforge.phpeclipse.ui.preferences.ITextStylePreferences;
54 import net.sourceforge.phpeclipse.ui.preferences.OverlayPreferenceStore;
55 import net.sourceforge.phpeclipse.ui.preferences.PreferenceDescriptor;
56 import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
57 import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
58 import net.sourceforge.phpeclipse.xml.ui.text.IXMLSyntaxConstants;
59 import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
60
61 /**
62  * The XMLSyntaxPreferencePage is a preference page that handles setting the colors used by the XML editors.
63  */
64 public class XMLSyntaxPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
65
66   public final PreferenceDescriptor[] fKeys = new PreferenceDescriptor[] {
67       new PreferenceDescriptor(PreferenceDescriptor.BOOLEAN, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT),
68       new PreferenceDescriptor(PreferenceDescriptor.STRING, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND),
69
70       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_DEFAULT
71           + ITextStylePreferences.SUFFIX_FOREGROUND),
72       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_DEFAULT + ITextStylePreferences.SUFFIX_STYLE),
73
74       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_TAG + ITextStylePreferences.SUFFIX_FOREGROUND),
75       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_TAG + ITextStylePreferences.SUFFIX_STYLE),
76
77       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ATT_NAME
78           + ITextStylePreferences.SUFFIX_FOREGROUND),
79       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ATT_NAME + ITextStylePreferences.SUFFIX_STYLE),
80
81       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ATT_VALUE
82           + ITextStylePreferences.SUFFIX_FOREGROUND),
83       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ATT_VALUE + ITextStylePreferences.SUFFIX_STYLE),
84
85       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ENTITY
86           + ITextStylePreferences.SUFFIX_FOREGROUND),
87       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_ENTITY + ITextStylePreferences.SUFFIX_STYLE),
88
89       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_CDATA + ITextStylePreferences.SUFFIX_FOREGROUND),
90       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_CDATA + ITextStylePreferences.SUFFIX_STYLE),
91
92       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_PI + ITextStylePreferences.SUFFIX_FOREGROUND),
93       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_PI + ITextStylePreferences.SUFFIX_STYLE),
94
95       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_COMMENT
96           + ITextStylePreferences.SUFFIX_FOREGROUND),
97       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_COMMENT + ITextStylePreferences.SUFFIX_STYLE),
98
99       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_DECL + ITextStylePreferences.SUFFIX_FOREGROUND),
100       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_DECL + ITextStylePreferences.SUFFIX_STYLE),
101
102       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_SMARTY + ITextStylePreferences.SUFFIX_FOREGROUND),
103       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.XML_SMARTY + ITextStylePreferences.SUFFIX_STYLE), 
104       
105       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.DTD_CONDITIONAL
106           + ITextStylePreferences.SUFFIX_FOREGROUND),
107       new PreferenceDescriptor(PreferenceDescriptor.STRING, IXMLSyntaxConstants.DTD_CONDITIONAL
108           + ITextStylePreferences.SUFFIX_STYLE),};
109
110   OverlayPreferenceStore overlay;
111
112   final String[][] fSyntaxColorListModel = new String[][] { { 
113       XMLPlugin.getResourceString("XmlSyntaxPreferencePage.others"), //$NON-NLS-1$
114       IXMLSyntaxConstants.XML_DEFAULT }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Tag"), //$NON-NLS-1$
115       IXMLSyntaxConstants.XML_TAG }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.AttName"), //$NON-NLS-1$
116       IXMLSyntaxConstants.XML_ATT_NAME }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.AttValue"), //$NON-NLS-1$
117       IXMLSyntaxConstants.XML_ATT_VALUE }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Entity"), //$NON-NLS-1$
118       IXMLSyntaxConstants.XML_ENTITY }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.CDATA"), //$NON-NLS-1$
119       IXMLSyntaxConstants.XML_CDATA }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.PI"), //$NON-NLS-1$
120       IXMLSyntaxConstants.XML_PI }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Comment"), //$NON-NLS-1$
121       IXMLSyntaxConstants.XML_COMMENT }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Declaration"), //$NON-NLS-1$
122       IXMLSyntaxConstants.XML_DECL }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.Conditional"), //$NON-NLS-1$
123       IXMLSyntaxConstants.XML_SMARTY }, { XMLPlugin.getResourceString("XmlSyntaxPreferencePage.SmartyTag"), //$NON-NLS-1$
124       IXMLSyntaxConstants.DTD_CONDITIONAL }, 
125           };
126
127   private XMLTextTools xmlTextTools;
128
129   private Color bgColor;
130
131   Button bgDefault;
132
133   Button bgCustom;
134
135   ColorEditor bgColorEditor;
136
137   List colors;
138
139   ColorEditor fgColorEditor;
140
141   Button fgBold;
142
143   SourceViewer preview;
144
145   /**
146    * Constructor for XMLSyntaxPreferencePage.
147    */
148   public XMLSyntaxPreferencePage() {
149     setDescription(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.description")); //$NON-NLS-1$
150
151     setPreferenceStore(XMLPlugin.getDefault().getPreferenceStore());
152
153     overlay = new OverlayPreferenceStore(getPreferenceStore(), fKeys);
154   }
155
156   protected Control createContents(Composite parent) {
157     overlay.load();
158     overlay.start();
159
160     Composite colorComposite = new Composite(parent, SWT.NULL);
161     colorComposite.setLayout(new GridLayout());
162
163     Group backgroundComposite = new Group(colorComposite, SWT.SHADOW_ETCHED_IN);
164
165     backgroundComposite.setLayout(new RowLayout());
166     backgroundComposite.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.backgroundColor")); //$NON-NLS-1$
167
168     SelectionListener backgroundSelectionListener = new SelectionListener() {
169       public void widgetSelected(SelectionEvent e) {
170         boolean custom = bgCustom.getSelection();
171         bgColorEditor.getButton().setEnabled(custom);
172         overlay.setValue(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT, !custom);
173       }
174
175       public void widgetDefaultSelected(SelectionEvent e) {
176       }
177     };
178
179     bgDefault = new Button(backgroundComposite, SWT.RADIO | SWT.LEFT);
180     bgDefault.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.systemDefault")); //$NON-NLS-1$
181     bgDefault.addSelectionListener(backgroundSelectionListener);
182
183     bgCustom = new Button(backgroundComposite, SWT.RADIO | SWT.LEFT);
184     bgCustom.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.custom")); //$NON-NLS-1$
185     bgCustom.addSelectionListener(backgroundSelectionListener);
186
187     bgColorEditor = new ColorEditor(backgroundComposite);
188
189     Label label = new Label(colorComposite, SWT.LEFT);
190     label.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.foreground")); //$NON-NLS-1$
191     label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
192
193     Composite editorComposite = new Composite(colorComposite, SWT.NONE);
194     GridLayout layout = new GridLayout();
195     layout.numColumns = 2;
196     layout.marginHeight = 0;
197     layout.marginWidth = 0;
198     editorComposite.setLayout(layout);
199     GridData gd = new GridData(GridData.FILL_BOTH);
200     editorComposite.setLayoutData(gd);
201
202     colors = new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
203     gd = new GridData(GridData.FILL_BOTH);
204     gd.heightHint = convertHeightInCharsToPixels(5);
205     colors.setLayoutData(gd);
206
207     Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
208     layout = new GridLayout();
209     layout.marginHeight = 0;
210     layout.marginWidth = 0;
211     layout.numColumns = 2;
212     stylesComposite.setLayout(layout);
213     stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
214
215     label = new Label(stylesComposite, SWT.LEFT);
216     label.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.color")); //$NON-NLS-1$
217     gd = new GridData();
218     gd.horizontalAlignment = GridData.BEGINNING;
219     label.setLayoutData(gd);
220
221     fgColorEditor = new ColorEditor(stylesComposite);
222
223     Button fgColorButton = fgColorEditor.getButton();
224     gd = new GridData(GridData.FILL_HORIZONTAL);
225     gd.horizontalAlignment = GridData.BEGINNING;
226     fgColorButton.setLayoutData(gd);
227
228     label = new Label(stylesComposite, SWT.LEFT);
229     label.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.bold")); //$NON-NLS-1$
230     gd = new GridData();
231     gd.horizontalAlignment = GridData.BEGINNING;
232     label.setLayoutData(gd);
233
234     fgBold = new Button(stylesComposite, SWT.CHECK);
235     gd = new GridData(GridData.FILL_HORIZONTAL);
236     gd.horizontalAlignment = GridData.BEGINNING;
237     fgBold.setLayoutData(gd);
238
239     label = new Label(colorComposite, SWT.LEFT);
240     label.setText(XMLPlugin.getResourceString("XmlSyntaxPreferencePage.preview")); //$NON-NLS-1$
241     label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
242
243     Control previewer = createPreviewer(colorComposite);
244     gd = new GridData(GridData.FILL_BOTH);
245     gd.widthHint = convertWidthInCharsToPixels(20);
246     gd.heightHint = convertHeightInCharsToPixels(5);
247     previewer.setLayoutData(gd);
248
249     colors.addSelectionListener(new SelectionListener() {
250
251       public void widgetDefaultSelected(SelectionEvent e) {
252       }
253
254       public void widgetSelected(SelectionEvent e) {
255         handleSyntaxColorListSelection();
256       }
257     });
258
259     bgColorEditor.getButton().addSelectionListener(new SelectionListener() {
260       public void widgetDefaultSelected(SelectionEvent e) {
261       }
262
263       public void widgetSelected(SelectionEvent e) {
264         PreferenceConverter.setValue(overlay, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND, bgColorEditor.getColorValue());
265       }
266     });
267
268     fgColorButton.addSelectionListener(new SelectionListener() {
269       public void widgetDefaultSelected(SelectionEvent e) {
270       }
271
272       public void widgetSelected(SelectionEvent e) {
273         int i = colors.getSelectionIndex();
274
275         String key = fSyntaxColorListModel[i][1];
276
277         PreferenceConverter.setValue(overlay, key + ITextStylePreferences.SUFFIX_FOREGROUND, fgColorEditor.getColorValue());
278       }
279     });
280
281     fgBold.addSelectionListener(new SelectionListener() {
282       public void widgetDefaultSelected(SelectionEvent e) {
283       }
284
285       public void widgetSelected(SelectionEvent e) {
286         int i = colors.getSelectionIndex();
287
288         String key = fSyntaxColorListModel[i][1];
289
290         String value = (fgBold.getSelection()) ? ITextStylePreferences.STYLE_BOLD : ITextStylePreferences.STYLE_NORMAL;
291
292         overlay.setValue(key + ITextStylePreferences.SUFFIX_STYLE, value);
293       }
294     });
295
296     initialize();
297
298     return colorComposite;
299   }
300
301   private Control createPreviewer(Composite parent) {
302     xmlTextTools = new XMLTextTools(overlay); // REVISIT: DTD
303
304     preview = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
305
306     preview.configure(new XMLConfiguration(xmlTextTools));
307     preview.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT));
308     preview.setEditable(false);
309
310     initializeViewerColors(preview);
311
312     String content = loadPreviewContentFromFile("preview.xml"); //$NON-NLS-1$
313     IDocument document = new Document(content);
314
315     // REVISIT: DTD
316     IDocumentPartitioner partitioner = xmlTextTools.createXMLPartitioner();
317
318     partitioner.connect(document);
319     document.setDocumentPartitioner(partitioner);
320
321     preview.setDocument(document);
322
323     overlay.addPropertyChangeListener(new IPropertyChangeListener() {
324       public void propertyChange(PropertyChangeEvent event) {
325         String p = event.getProperty();
326         if (p.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)
327             || p.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
328           initializeViewerColors(preview);
329         }
330
331         preview.invalidateTextPresentation();
332       }
333     });
334
335     return preview.getControl();
336   }
337
338   /**
339    * Initializes the given viewer's colors.
340    * 
341    * @param viewer
342    *          the viewer to be initialized
343    */
344   void initializeViewerColors(ISourceViewer viewer) {
345     if (overlay != null) {
346       StyledText styledText = viewer.getTextWidget();
347
348       // ---------- background color ----------------------
349       Color color = null;
350       if (!overlay.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
351         color = createColor(overlay, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay());
352       }
353
354       styledText.setBackground(color);
355
356       if (bgColor != null) {
357         bgColor.dispose();
358       }
359
360       bgColor = color;
361     }
362   }
363
364   /**
365    * Creates a color from the information stored in the given preference store. Returns <code>null</code> if there is no such
366    * information available.
367    */
368   private Color createColor(IPreferenceStore store, String key, Display display) {
369     RGB rgb = null;
370
371     if (store.contains(key)) {
372       if (store.isDefault(key)) {
373         rgb = PreferenceConverter.getDefaultColor(store, key);
374       } else {
375         rgb = PreferenceConverter.getColor(store, key);
376       }
377
378       if (rgb != null) {
379         return new Color(display, rgb);
380       }
381     }
382
383     return null;
384   }
385
386   void handleSyntaxColorListSelection() {
387     int i = colors.getSelectionIndex();
388
389     String key = fSyntaxColorListModel[i][1];
390
391     RGB rgb = PreferenceConverter.getColor(overlay, key + ITextStylePreferences.SUFFIX_FOREGROUND);
392
393     fgColorEditor.setColorValue(rgb);
394
395     // REVISIT
396     fgBold.setSelection(overlay.getString(key + ITextStylePreferences.SUFFIX_STYLE).indexOf(ITextStylePreferences.STYLE_BOLD) >= 0);
397   }
398
399   private String loadPreviewContentFromFile(String filename) {
400     StringBuffer string = new StringBuffer(512);
401
402     try {
403       char[] buf = new char[512];
404       BufferedReader reader = new BufferedReader(new InputStreamReader(XMLSyntaxPreferencePage.class.getResourceAsStream(filename)));
405
406       try {
407         while (true) {
408           int n = reader.read(buf);
409           if (n < 0) {
410             break;
411           }
412
413           string.append(buf, 0, n);
414         }
415       } finally {
416         reader.close();
417       }
418     } catch (IOException e) {
419     }
420
421     return string.toString();
422   }
423
424   /**
425    *  
426    */
427   private void initialize() {
428     initializeFields();
429
430     for (int i = 0; i < fSyntaxColorListModel.length; i++) {
431       colors.add(fSyntaxColorListModel[i][0]);
432     }
433
434     colors.getDisplay().asyncExec(new Runnable() {
435
436       public void run() {
437         colors.select(0);
438         handleSyntaxColorListSelection();
439       }
440     });
441   }
442
443   private void initializeFields() {
444     RGB rgb = PreferenceConverter.getColor(overlay, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND);
445     bgColorEditor.setColorValue(rgb);
446
447     boolean def = overlay.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
448     bgDefault.setSelection(def);
449     bgCustom.setSelection(!def);
450     bgColorEditor.getButton().setEnabled(!def);
451   }
452
453   /*
454    * @see IWorkbenchPreferencePage#init(IWorkbench)
455    */
456   public void init(IWorkbench workbench) {
457   }
458
459   /*
460    * @see PreferencePage#performDefaults()
461    */
462   protected void performDefaults() {
463     overlay.loadDefaults();
464     //initializeFields();
465     handleSyntaxColorListSelection();
466
467     super.performDefaults();
468
469     preview.invalidateTextPresentation();
470   }
471
472   /*
473    * @see org.eclipse.jface.preference.IPreferencePage#performOk()
474    */
475   public boolean performOk() {
476     overlay.propagate();
477     XMLPlugin.getDefault().savePluginPreferences();
478
479     return true;
480   }
481
482   /*
483    * @see org.eclipse.jface.dialogs.IDialogPage#dispose()
484    */
485   public void dispose() {
486     if (xmlTextTools != null) {
487       xmlTextTools.dispose();
488       xmlTextTools = null;
489     }
490
491     if (overlay != null) {
492       overlay.stop();
493       overlay = null;
494     }
495
496     super.dispose();
497   }
498 }