intial source from ttp://www.sf.net/projects/wdte
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.css.ui / src / net / sourceforge / phpeclipse / css / ui / internal / text / AbstractCssScanner.java
1 /*
2  * Copyright (c) 2003-2004 Christopher Lenz 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  *     Christopher Lenz - initial API and implementation
10  * 
11  * $Id: AbstractCssScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
12  */
13
14 package net.sourceforge.phpeclipse.css.ui.internal.text;
15
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.Map;
19
20 import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
21
22 import org.eclipse.jface.preference.IPreferenceStore;
23 import org.eclipse.jface.preference.PreferenceConverter;
24 import org.eclipse.jface.resource.StringConverter;
25 import org.eclipse.jface.text.TextAttribute;
26 import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
27 import org.eclipse.jface.text.rules.IToken;
28 import org.eclipse.jface.text.rules.Token;
29 import org.eclipse.jface.util.IPropertyChangeListener;
30 import org.eclipse.jface.util.PropertyChangeEvent;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.graphics.RGB;
33
34 /**
35  * 
36  */
37 public abstract class AbstractCssScanner extends BufferedRuleBasedScanner {
38
39         // Inner Classes -----------------------------------------------------------
40
41         /**
42          * Internal data structure for associating the various style preferences 
43          * of tokens with each other.
44          */
45         private static final class StyleKeys {
46
47                 /**
48                  * The preference key that determines the foreground color of the token.
49                  */
50                 private String colorKey;
51
52                 /**
53                  * The preference key that indicates whether the token is to be 
54                  * displayed in bold face.
55                  */
56                 private String boldKey;
57
58                 /**
59                  * Constructor.
60                  * 
61                  * @param colorKey The color preference key
62                  * @param boldKey The preference key determining whether the
63                  *        corresponding tokens should be rendered bold
64                  */
65                 private StyleKeys(String colorKey, String boldKey) {
66                         this.colorKey = colorKey;
67                         this.boldKey = boldKey;
68                 }
69
70                 /**
71                  * @see Object#equals(Object)
72                  */
73                 public boolean equals(Object o) {
74                         if (!(o instanceof StyleKeys)) {
75                                 return false;
76                         }
77                         StyleKeys styleKeys = (StyleKeys) o;
78                         if (((colorKey != null) && !colorKey.equals(styleKeys.colorKey))
79                          || (colorKey != styleKeys.colorKey)) {
80                                 return false;
81                         }
82                         if (((boldKey != null) && !boldKey.equals(styleKeys.boldKey))
83                          || (boldKey != styleKeys.boldKey)) {
84                                 return false;
85                         }
86                         return true;
87                 }
88
89                 /**
90                  * @see Object#hashCode()
91                  */
92                 public int hashCode() {
93                         int retVal = 17;
94                         retVal = (retVal * 37) +
95                                 (colorKey != null ? colorKey.hashCode() : 0);
96                         retVal = (retVal * 37) +
97                                 (boldKey != null ? boldKey.hashCode() : 0);
98                         return retVal;
99                 }
100
101         }
102
103         // Instance Variables ------------------------------------------------------
104
105         /**
106          * The preference store associated with the scanner.
107          */
108         private IPreferenceStore store;
109
110         /**
111          * Listener for preference store changes related to tokens.
112          */
113         private IPropertyChangeListener propertyChangeListener =
114                 new IPropertyChangeListener() {
115                         public void propertyChange(PropertyChangeEvent event) {
116                                 String property = event.getProperty();
117                                 StyleKeys styleKeys = getStyleKeysContaining(property);
118                                 if (styleKeys != null) {
119                                         if (styleKeys.colorKey.equals(property)) {
120                                                 Token token = (Token) tokens.get(styleKeys);
121                                                 handleColorChange(token, event);
122                                         } else if (styleKeys.boldKey.equals(property)) {
123                                                 Token token = (Token) tokens.get(styleKeys);
124                                                 handleBoldChange(token, event);
125                                         }
126                                 }
127                         }
128                 };
129         
130         /**
131          * The shared text colors.
132          */
133         private IColorManager colorManager;
134
135         /**
136          * A map containing the defined tokens keyed by the color preference key.
137          */
138         private Map tokens = new HashMap(4);
139
140         // Constructors ------------------------------------------------------------
141
142         /**
143          * Constructor.
144          * 
145          * @param store the preference store
146          * @param manager the color manager
147          */
148         public AbstractCssScanner(IPreferenceStore store, IColorManager manager) {
149                 store.addPropertyChangeListener(propertyChangeListener);
150                 this.store = store;
151                 this.colorManager = manager;
152         }
153
154         // Public Methods ----------------------------------------------------------
155
156         /**
157          * Adapts the tokens managed by this scanner to changes made to the 
158          * corresponding preferences.
159          * 
160          * @param event the change event fired by the preference store
161          */
162         public void adaptToPreferenceChange(PropertyChangeEvent event) {
163                 String property = event.getProperty();
164                 StyleKeys styleKeys = getStyleKeysContaining(property);
165                 if (styleKeys != null) {
166                         if (styleKeys.colorKey.equals(property)) {
167                                 Token token = (Token) tokens.get(styleKeys);
168                                 handleColorChange(token, event);
169                         } else if (styleKeys.boldKey.equals(property)) {
170                                 Token token = (Token) tokens.get(styleKeys);
171                                 handleBoldChange(token, event);
172                         }
173                 }
174         }
175
176         /**
177          * Called to determine whether the change of a specific preference affects
178          * the presentation of the tokens managed by the scanner.
179          * 
180          * @param event the preference change event
181          * @return <code>true</code> if the change affects the presentation of one
182          *         of the tokens managed by the scanner, <code>false</code>
183          *         otherwise
184          */
185         public boolean affectsPresentation(PropertyChangeEvent event) {
186                 String property = event.getProperty();
187                 return (getStyleKeysContaining(property) != null);
188         }
189
190         // Protected Methods -------------------------------------------------------
191
192         /**
193          * Creates a token with the specified color and style as associated text
194          * attribute. The color and style are specified as preference keys.
195          * 
196          * @param colorKey The preference key of the color
197          * @param boldKey The preference key of the boolean value that determines
198          *        whether the text should be rendered bold, or <code>null</code>
199          * @return the created token
200          */
201         protected final IToken createToken(String colorKey, String boldKey) {
202                 RGB rgb = PreferenceConverter.getColor(store, colorKey);
203                 colorManager.unbindColor(colorKey);
204                 colorManager.bindColor(colorKey, rgb);
205                 int style = SWT.NORMAL;
206                 if ((boldKey != null) && store.getBoolean(boldKey)) {
207                         style |= SWT.BOLD;
208                 }
209                 IToken token = new Token(new TextAttribute(
210                         colorManager.getColor(colorKey), null, style));
211                 StyleKeys styleKeys = new StyleKeys(colorKey, boldKey);
212                 tokens.put(styleKeys, token);
213                 return token;
214         }
215
216         // Private Methods ---------------------------------------------------------
217
218         private StyleKeys getStyleKeysContaining(String key) {
219                 for (Iterator i = tokens.keySet().iterator(); i.hasNext(); ) {
220                         StyleKeys styleKeys = (StyleKeys) i.next();
221                         if (styleKeys.colorKey.equals(key)
222                          || styleKeys.boldKey.equals(key)) {
223                                 return styleKeys;
224                         } 
225                 }
226                 return null;
227         }
228
229         private void handleColorChange(Token token, PropertyChangeEvent event) {
230                 RGB rgb = null;
231                 Object value = event.getNewValue();
232                 if (value instanceof RGB) {
233                         rgb = (RGB) value;
234                 } else if (value instanceof String) {
235                         rgb = StringConverter.asRGB((String) value);
236                 }
237                 if (rgb != null) {
238                         String key = event.getProperty();
239                         colorManager.unbindColor(key);
240                         colorManager.bindColor(key, rgb);
241                         Object data = token.getData();
242                         if (data instanceof TextAttribute) {
243                                 TextAttribute oldAttr = (TextAttribute) data;
244                                 token.setData(new TextAttribute(colorManager.getColor(key),
245                                         oldAttr.getBackground(), oldAttr.getStyle()));
246                         }
247                 }
248         }
249
250         private void handleBoldChange(Token token, PropertyChangeEvent event) {
251                 boolean bold = false;
252                 Object value = event.getNewValue();
253                 if (value instanceof Boolean) {
254                         bold = ((Boolean) value).booleanValue();
255                 } else if (value instanceof String) {
256                         StringConverter.asBoolean((String) value);
257                 }
258                 Object data = token.getData();
259                 if (data instanceof TextAttribute) {
260                         TextAttribute oldAttr = (TextAttribute) data;
261                         boolean wasBold = ((oldAttr.getStyle() & SWT.BOLD) != 0);
262                         if (wasBold != bold) {
263                                 int newStyle = bold ? oldAttr.getStyle() | SWT.BOLD
264                                                                         : oldAttr.getStyle() ^ SWT.BOLD;
265                                 token.setData(new TextAttribute(oldAttr.getForeground(),
266                                         oldAttr.getBackground(), newStyle));
267                         }
268                 }
269         }
270
271 }