1 | /*
|
---|
2 | * 02/24/2004
|
---|
3 | *
|
---|
4 | * RSyntaxTextAreaUI.java - UI for an RSyntaxTextArea.
|
---|
5 | *
|
---|
6 | * This library is distributed under a modified BSD license. See the included
|
---|
7 | * RSyntaxTextArea.License.txt file for details.
|
---|
8 | */
|
---|
9 | package org.fife.ui.rsyntaxtextarea;
|
---|
10 |
|
---|
11 | import java.awt.Color;
|
---|
12 | import java.awt.Graphics;
|
---|
13 | import java.awt.Rectangle;
|
---|
14 | import java.beans.PropertyChangeEvent;
|
---|
15 | import javax.swing.InputMap;
|
---|
16 | import javax.swing.JComponent;
|
---|
17 | import javax.swing.UIManager;
|
---|
18 | import javax.swing.plaf.ComponentUI;
|
---|
19 | import javax.swing.plaf.InputMapUIResource;
|
---|
20 | import javax.swing.text.*;
|
---|
21 |
|
---|
22 | import org.fife.ui.rtextarea.RTextArea;
|
---|
23 | import org.fife.ui.rtextarea.RTextAreaUI;
|
---|
24 |
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * UI used by <code>RSyntaxTextArea</code>. This allows us to implement
|
---|
28 | * syntax highlighting.
|
---|
29 | *
|
---|
30 | * @author Robert Futrell
|
---|
31 | * @version 0.1
|
---|
32 | */
|
---|
33 | public class RSyntaxTextAreaUI extends RTextAreaUI {
|
---|
34 |
|
---|
35 | private static final String SHARED_ACTION_MAP_NAME = "RSyntaxTextAreaUI.actionMap";
|
---|
36 | private static final String SHARED_INPUT_MAP_NAME = "RSyntaxTextAreaUI.inputMap";
|
---|
37 | private static final EditorKit defaultKit = new RSyntaxTextAreaEditorKit();
|
---|
38 |
|
---|
39 |
|
---|
40 | public static ComponentUI createUI(JComponent ta) {
|
---|
41 | return new RSyntaxTextAreaUI(ta);
|
---|
42 | }
|
---|
43 |
|
---|
44 |
|
---|
45 | /**
|
---|
46 | * Constructor.
|
---|
47 | */
|
---|
48 | public RSyntaxTextAreaUI(JComponent rSyntaxTextArea) {
|
---|
49 | super(rSyntaxTextArea);
|
---|
50 | }
|
---|
51 |
|
---|
52 |
|
---|
53 | /**
|
---|
54 | * Creates the view for an element.
|
---|
55 | *
|
---|
56 | * @param elem The element.
|
---|
57 | * @return The view.
|
---|
58 | */
|
---|
59 | public View create(Element elem) {
|
---|
60 | RTextArea c = getRTextArea();
|
---|
61 | if (c instanceof RSyntaxTextArea) {
|
---|
62 | RSyntaxTextArea area = (RSyntaxTextArea) c;
|
---|
63 | View v;
|
---|
64 | if (area.getLineWrap())
|
---|
65 | v = new WrappedSyntaxView(elem);
|
---|
66 | else
|
---|
67 | v = new SyntaxView(elem);
|
---|
68 | return v;
|
---|
69 | }
|
---|
70 | return null;
|
---|
71 | }
|
---|
72 |
|
---|
73 |
|
---|
74 | /**
|
---|
75 | * Creates the highlighter to use for syntax text areas.
|
---|
76 | *
|
---|
77 | * @return The highlighter.
|
---|
78 | */
|
---|
79 | protected Highlighter createHighlighter() {
|
---|
80 | return new RSyntaxTextAreaHighlighter();
|
---|
81 | }
|
---|
82 |
|
---|
83 |
|
---|
84 | /**
|
---|
85 | * Returns the name to use to cache/fetch the shared action map. This
|
---|
86 | * should be overridden by subclasses if the subclass has its own custom
|
---|
87 | * editor kit to install, so its actions get picked up.
|
---|
88 | *
|
---|
89 | * @return The name of the cached action map.
|
---|
90 | */
|
---|
91 | protected String getActionMapName() {
|
---|
92 | return SHARED_ACTION_MAP_NAME;
|
---|
93 | }
|
---|
94 |
|
---|
95 |
|
---|
96 | /**
|
---|
97 | * Fetches the EditorKit for the UI.
|
---|
98 | *
|
---|
99 | * @param tc The text component for which this UI is installed.
|
---|
100 | * @return The editor capabilities.
|
---|
101 | * @see javax.swing.plaf.TextUI#getEditorKit
|
---|
102 | */
|
---|
103 | public EditorKit getEditorKit(JTextComponent tc) {
|
---|
104 | return defaultKit;
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | /**
|
---|
109 | * Get the InputMap to use for the UI.<p>
|
---|
110 | *
|
---|
111 | * This method is not named <code>getInputMap()</code> because there is
|
---|
112 | * a package-private method in <code>BasicTextAreaUI</code> with that name.
|
---|
113 | * Thus, creating a new method with that name causes certain compilers to
|
---|
114 | * issue warnings that you are not actually overriding the original method
|
---|
115 | * (since it is package-private).
|
---|
116 | */
|
---|
117 | protected InputMap getRTextAreaInputMap() {
|
---|
118 | InputMap map = new InputMapUIResource();
|
---|
119 | InputMap shared = (InputMap)UIManager.get(SHARED_INPUT_MAP_NAME);
|
---|
120 | if (shared==null) {
|
---|
121 | shared = new RSyntaxTextAreaDefaultInputMap();
|
---|
122 | UIManager.put(SHARED_INPUT_MAP_NAME, shared);
|
---|
123 | }
|
---|
124 | //KeyStroke[] keys = shared.allKeys();
|
---|
125 | //for (int i=0; i<keys.length; i++)
|
---|
126 | // System.err.println(keys[i] + " -> " + shared.get(keys[i]));
|
---|
127 | map.setParent(shared);
|
---|
128 | return map;
|
---|
129 | }
|
---|
130 |
|
---|
131 |
|
---|
132 | /**
|
---|
133 | * Paints the text area's background.
|
---|
134 | *
|
---|
135 | * @param g The graphics component on which to paint.
|
---|
136 | */
|
---|
137 | protected void paintBackground(Graphics g) {
|
---|
138 | super.paintBackground(g);
|
---|
139 | paintMatchedBracket(g);
|
---|
140 | }
|
---|
141 |
|
---|
142 |
|
---|
143 | /**
|
---|
144 | * Paints the "matched bracket", if any.
|
---|
145 | *
|
---|
146 | * @param g The graphics context.
|
---|
147 | */
|
---|
148 | protected void paintMatchedBracket(Graphics g) {
|
---|
149 | // We must add "-1" to the height because otherwise we'll paint below
|
---|
150 | // the region that gets invalidated.
|
---|
151 | RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
|
---|
152 | if (rsta.isBracketMatchingEnabled()) {
|
---|
153 | Rectangle match = rsta.match;
|
---|
154 | if (match!=null) {
|
---|
155 | if (rsta.getAnimateBracketMatching()) {
|
---|
156 | Color bg = rsta.getMatchedBracketBGColor();
|
---|
157 | if (bg!=null) {
|
---|
158 | g.setColor(bg);
|
---|
159 | g.fillRoundRect(match.x,match.y, match.width,match.height-1, 5,5);
|
---|
160 | }
|
---|
161 | g.setColor(rsta.getMatchedBracketBorderColor());
|
---|
162 | g.drawRoundRect(match.x,match.y, match.width,match.height-1, 5,5);
|
---|
163 | }
|
---|
164 | else {
|
---|
165 | Color bg = rsta.getMatchedBracketBGColor();
|
---|
166 | if (bg!=null) {
|
---|
167 | g.setColor(bg);
|
---|
168 | g.fillRect(match.x,match.y, match.width,match.height-1);
|
---|
169 | }
|
---|
170 | g.setColor(rsta.getMatchedBracketBorderColor());
|
---|
171 | g.drawRect(match.x,match.y, match.width,match.height-1);
|
---|
172 | }
|
---|
173 | }
|
---|
174 | }
|
---|
175 | }
|
---|
176 |
|
---|
177 | /**
|
---|
178 | * Gets called whenever a bound property is changed on this UI's
|
---|
179 | * <code>RSyntaxTextArea</code>.
|
---|
180 | *
|
---|
181 | * @param e The property change event.
|
---|
182 | */
|
---|
183 | protected void propertyChange(PropertyChangeEvent e) {
|
---|
184 |
|
---|
185 | String name = e.getPropertyName();
|
---|
186 |
|
---|
187 | // If they change the syntax scheme, we must do this so that
|
---|
188 | // WrappedSyntaxView(_TEST) updates its child views properly.
|
---|
189 | if (name.equals(RSyntaxTextArea.SYNTAX_SCHEME_PROPERTY)) {
|
---|
190 | modelChanged();
|
---|
191 | }
|
---|
192 |
|
---|
193 | // Everything else is general to all RTextAreas.
|
---|
194 | else {
|
---|
195 | super.propertyChange(e);
|
---|
196 | }
|
---|
197 |
|
---|
198 | }
|
---|
199 |
|
---|
200 |
|
---|
201 | /**
|
---|
202 | * Updates the view. This should be called when the underlying
|
---|
203 | * <code>RSyntaxTextArea</code> changes its syntax editing style.
|
---|
204 | */
|
---|
205 | public void refreshSyntaxHighlighting() {
|
---|
206 | modelChanged();
|
---|
207 | }
|
---|
208 |
|
---|
209 |
|
---|
210 | /**
|
---|
211 | * Returns the y-coordinate of the specified line.<p>
|
---|
212 | *
|
---|
213 | * This method is quicker than using traditional
|
---|
214 | * <code>modelToView(int)</code> calls, as the entire bounding box isn't
|
---|
215 | * computed.
|
---|
216 | */
|
---|
217 | public int yForLine(int line) throws BadLocationException {
|
---|
218 | Rectangle alloc = getVisibleEditorRect();
|
---|
219 | if (alloc!=null) {
|
---|
220 | RSTAView view = (RSTAView)getRootView(textArea).getView(0);
|
---|
221 | return view.yForLine(alloc, line);
|
---|
222 | }
|
---|
223 | return -1;
|
---|
224 | }
|
---|
225 |
|
---|
226 |
|
---|
227 | /**
|
---|
228 | * Returns the y-coordinate of the line containing a specified offset.<p>
|
---|
229 | *
|
---|
230 | * This is faster than calling <code>modelToView(offs).y</code>, so it is
|
---|
231 | * preferred if you do not need the actual bounding box.
|
---|
232 | */
|
---|
233 | public int yForLineContaining(int offs) throws BadLocationException {
|
---|
234 | Rectangle alloc = getVisibleEditorRect();
|
---|
235 | if (alloc!=null) {
|
---|
236 | RSTAView view = (RSTAView)getRootView(textArea).getView(0);
|
---|
237 | return view.yForLineContaining(alloc, offs);
|
---|
238 | }
|
---|
239 | return -1;
|
---|
240 | }
|
---|
241 |
|
---|
242 |
|
---|
243 | } |
---|