]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/richtext/demo/SyntaxColorer.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / richtext / demo / SyntaxColorer.java
1 /*\r
2  * (C) Copyright IBM Corp. 1999-2004.  All Rights Reserved.\r
3  *\r
4  * The program is provided "as is" without any warranty express or\r
5  * implied, including the warranty of non-infringement and the implied\r
6  * warranties of merchantibility and fitness for a particular purpose.\r
7  * IBM will not be liable for any damages suffered by you as a result\r
8  * of using the Program. In no event will IBM be liable for any\r
9  * special, indirect or consequential damages or lost profits even if\r
10  * IBM has been advised of the possibility of their occurrence. IBM\r
11  * will not be liable for any third party claims against you.\r
12  */\r
13 \r
14 package com.ibm.richtext.demo;\r
15 \r
16 import com.ibm.richtext.awtui.TextFrame;\r
17 import com.ibm.richtext.textpanel.MTextPanel;\r
18 import com.ibm.richtext.textpanel.TextPanelEvent;\r
19 import com.ibm.richtext.textpanel.TextPanelListener;\r
20 \r
21 import com.ibm.richtext.styledtext.MConstText;\r
22 import com.ibm.richtext.styledtext.MText;\r
23 import com.ibm.richtext.styledtext.StyledText;\r
24 import com.ibm.richtext.styledtext.StyleModifier;\r
25 \r
26 import com.ibm.richtext.textlayout.attributes.AttributeMap;\r
27 import com.ibm.richtext.textlayout.attributes.TextAttribute;\r
28 \r
29 import java.awt.Color;\r
30 \r
31 import java.awt.event.WindowAdapter;\r
32 import java.awt.event.WindowEvent;\r
33 \r
34 import java.text.BreakIterator;\r
35 import java.text.CharacterIterator;\r
36 import java.text.CollationKey;\r
37 import java.text.Collator;\r
38 \r
39 import java.util.Enumeration;\r
40 import java.util.Hashtable;\r
41 \r
42 /**\r
43  * SyntaxColorer is a TextPanelListener that applies a style\r
44  * to a set of words in the TextPanel.\r
45  */\r
46 public final class SyntaxColorer implements TextPanelListener {\r
47     \r
48     static final String COPYRIGHT =\r
49                 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";\r
50     \r
51     private static final class Colorer {\r
52         \r
53         static final String COPYRIGHT =\r
54                 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";\r
55         private int fStart;\r
56         private Hashtable fStyleMap;\r
57         private Collator fCollator = Collator.getInstance();\r
58         private BreakIterator fBreakIter = BreakIterator.getWordInstance();\r
59 \r
60         private String fText;\r
61         private int fCurrentStart;\r
62         private int fCurrentLimit;\r
63         private AttributeMap fCurrentStyle;\r
64         \r
65         Colorer(Hashtable styles) {\r
66 \r
67             fStyleMap = new Hashtable(styles.size());\r
68 \r
69             Enumeration e = styles.keys();\r
70             while (e.hasMoreElements()) {\r
71                 String k = (String) e.nextElement();\r
72                 fStyleMap.put(fCollator.getCollationKey(k), styles.get(k));\r
73             }\r
74         }\r
75         \r
76         void set(CharacterIterator text, int start, int limit) {\r
77             \r
78             fStart = start;\r
79 \r
80             StringBuffer sb = new StringBuffer(limit-start);\r
81             for (char c=text.setIndex(start); text.getIndex() != limit; c=text.next()) {\r
82                 sb.append(c);\r
83             }\r
84             fText = sb.toString();\r
85             fCurrentStart = fCurrentLimit = 0;\r
86             fCurrentStyle = AttributeMap.EMPTY_ATTRIBUTE_MAP;\r
87             \r
88             fBreakIter.setText(fText);\r
89             fBreakIter.first();\r
90         }\r
91             \r
92         boolean next() {\r
93             \r
94             if (fCurrentLimit == fText.length()) {\r
95                 fText = null;\r
96                 return false;\r
97             }\r
98 \r
99             fCurrentStart = fCurrentLimit;\r
100             fCurrentLimit = fBreakIter.next();\r
101             \r
102             String word = fText.substring(fCurrentStart, fCurrentLimit);\r
103             CollationKey ck = fCollator.getCollationKey(word);\r
104             fCurrentStyle = (AttributeMap) fStyleMap.get(ck);\r
105             if (fCurrentStyle == null) {\r
106                 fCurrentStyle = AttributeMap.EMPTY_ATTRIBUTE_MAP;\r
107             }\r
108             \r
109             return true;\r
110         }\r
111             \r
112         int currentStart() {\r
113             return fCurrentStart + fStart;\r
114         }\r
115         \r
116         int currentLimit() {\r
117             return fCurrentLimit + fStart;\r
118         }\r
119         \r
120         AttributeMap currentStyle() {\r
121             return fCurrentStyle;\r
122         }\r
123     }\r
124 \r
125     private BreakIterator fBreakIter = BreakIterator.getWordInstance();\r
126     private Colorer fColorer;\r
127     private boolean fModifying = false;\r
128     private AttributeMap fDefaultKeywordStyle = AttributeMap.EMPTY_ATTRIBUTE_MAP;\r
129     private Hashtable fModifierCache;\r
130     \r
131     public SyntaxColorer() {\r
132         \r
133         this(null);\r
134     }\r
135     \r
136     public SyntaxColorer(MTextPanel panel) {\r
137         \r
138         Hashtable ht = new Hashtable();\r
139 \r
140         //Uncomment this to make keywords appear right-to-left!\r
141         //fDefaultKeywordStyle = fDefaultKeywordStyle.addAttribute(TextAttribute.BIDI_EMBEDDING, \r
142         //                                                         new Integer(-1));\r
143         \r
144         fDefaultKeywordStyle = fDefaultKeywordStyle.addAttribute(TextAttribute.UNDERLINE,\r
145                                                                  TextAttribute.UNDERLINE_ON);\r
146         fDefaultKeywordStyle = fDefaultKeywordStyle.addAttribute(TextAttribute.FOREGROUND, \r
147                                                                  Color.blue);\r
148         \r
149         String[] javaWords = {"abstract" , "boolean", "break", "byte",\r
150                               "byvalue", "case", "cast", "default",\r
151                               "do", "double", "else", "extends", \r
152                               "false", "final", "goto", "if",\r
153                               "implements", "import", "inner", "instanceof",\r
154                               "int", "operator", "outer", "package",\r
155                               "private", "protected", "public", "rest",\r
156                               "synchronized", "this", "throw", "throws",\r
157                               "transient", "true", "try",\r
158                               "catch", "char", "const", "continue",\r
159                               "finally", "float", "for", "future",\r
160                               "generic", "interface", "long", "native",\r
161                               "new", "null", "return", "short",\r
162                               "static", "super", "switch", "var",\r
163                               "void", "volatile", "while", "class"};\r
164 \r
165         for (int i=0; i < javaWords.length; i++) {\r
166             ht.put(javaWords[i], fDefaultKeywordStyle);\r
167         }\r
168         \r
169         fColorer = new Colorer(ht);\r
170         \r
171         if (panel != null) {\r
172             MConstText text = panel.getText();\r
173             colorRange(0, text.length(), text.createCharacterIterator(), panel);\r
174         }\r
175         \r
176         fModifierCache = new Hashtable(2);\r
177         fModifierCache.put(fDefaultKeywordStyle, \r
178                            StyleModifier.createReplaceModifier(fDefaultKeywordStyle));\r
179         fModifierCache.put(AttributeMap.EMPTY_ATTRIBUTE_MAP, \r
180                            StyleModifier.createReplaceModifier(AttributeMap.EMPTY_ATTRIBUTE_MAP));\r
181     }\r
182     \r
183     public boolean respondsToEventType(int type) {\r
184         \r
185         return type == TextPanelEvent.TEXT_CHANGED;\r
186     }\r
187     \r
188     public void textEventOccurred(TextPanelEvent e) {\r
189 \r
190         if (fModifying) {\r
191             return;\r
192         }\r
193         \r
194         MTextPanel panel = (MTextPanel) e.getSource();\r
195         \r
196         final MConstText text = panel.getText();\r
197         int start = text.damagedRangeStart();\r
198         int limit = text.damagedRangeLimit();\r
199         if (start > limit) {\r
200             return;\r
201         }\r
202         \r
203         CharacterIterator textIter = text.createCharacterIterator();\r
204         \r
205         fBreakIter.setText(textIter);\r
206         if (start > 0) {\r
207             if (start == text.length()) {\r
208                 fBreakIter.last();\r
209             }\r
210             else {\r
211                 fBreakIter.following(start-1);\r
212             }\r
213             start = fBreakIter.previous();\r
214         }\r
215         if (limit < text.length()) {\r
216             fBreakIter.following(limit);\r
217             //int l;\r
218             if ((fBreakIter.previous()) <= limit) {\r
219                 limit = fBreakIter.next();\r
220             }\r
221         }\r
222         \r
223         fModifying = true;\r
224         colorRange(start, limit, textIter, panel);\r
225         fModifying = false;\r
226     }\r
227     \r
228     private void colorRange(final int start, \r
229                             final int limit, \r
230                             CharacterIterator textIter,\r
231                             MTextPanel panel) {\r
232         \r
233         fColorer.set(textIter, start, limit);\r
234 \r
235         MConstText oldText = panel.getText();\r
236         MText newText = null;\r
237         \r
238         while (fColorer.next()) {\r
239 \r
240             int rangeStart = fColorer.currentStart();\r
241             int rangeLimit = fColorer.currentLimit();\r
242             \r
243             AttributeMap style = fColorer.currentStyle();\r
244             \r
245             if (oldText.characterStyleLimit(rangeStart) < rangeLimit ||\r
246                     oldText.characterStyleAt(rangeStart) != style) {\r
247             \r
248                 int cstart = rangeStart-start;\r
249                 int climit = rangeLimit-start;\r
250                 if (newText == null) {\r
251                     newText = new StyledText(oldText, start, limit);\r
252                 }\r
253                 StyleModifier mod = (StyleModifier) fModifierCache.get(style);\r
254                 newText.modifyCharacterStyles(cstart, climit, mod);\r
255             }\r
256         }\r
257         \r
258         if (newText != null) {\r
259         \r
260             int oldStart = panel.getSelectionStart();\r
261             int oldLimit = panel.getSelectionEnd();\r
262             \r
263             panel.replaceRange(newText, start, limit);            \r
264     \r
265             panel.select(oldStart, oldLimit);\r
266             if (oldStart == oldLimit) {\r
267                 StyleModifier mod = (StyleModifier) fModifierCache.get(AttributeMap.EMPTY_ATTRIBUTE_MAP);                \r
268                 panel.modifyCharacterStyleOnSelection(mod);\r
269             }\r
270         }\r
271     }\r
272     \r
273     public static void main(String[] args) {\r
274         \r
275         TextFrame f = new TextFrame();\r
276         f.addWindowListener(new WindowAdapter() {\r
277             public void windowClosing(WindowEvent e) {\r
278                 System.exit(0);\r
279             }\r
280         });\r
281         f.setSize(400, 300);\r
282         MTextPanel panel = f.getTextPanel();\r
283         panel.addListener(new SyntaxColorer(panel));\r
284         f.show();\r
285     }\r
286 }