001: /*
002: * Sun Public License Notice
003: *
004: * The contents of this file are subject to the Sun Public License
005: * Version 1.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://www.sun.com/
008: *
009: * The Original Code is NetBeans. The Initial Developer of the Original
010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
011: * Microsystems, Inc. All Rights Reserved.
012: */
013:
014: package org.netbeans.editor.ext.java;
015:
016: import java.awt.Color;
017: import java.awt.Component;
018: import java.awt.Dimension;
019: import java.awt.Font;
020: import java.awt.FontMetrics;
021: import java.awt.Graphics;
022: import java.awt.Insets;
023: import java.lang.reflect.Modifier;
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.Map;
027:
028: import javax.swing.BorderFactory;
029: import javax.swing.Icon;
030: import javax.swing.JList;
031: import javax.swing.JPanel;
032: import javax.swing.ListCellRenderer;
033:
034: /**
035: * Java completion query specifications
036: *
037: * @author Miloslav Metelka
038: * @version 1.00
039: */
040:
041: public class JCCellRenderer extends JPanel implements ListCellRenderer {
042:
043: public static final int CLASS_ICON = 0;
044: public static final int INTERFACE_ICON = 4;
045: public static final int FIELD_ICON = 8;
046: public static final int FIELD_STATIC_ICON = 12;
047: public static final int CONSTRUCTOR_ICON = 16;
048: public static final int METHOD_ICON = 20;
049: public static final int METHOD_STATIC_ICON = 24;
050: public static final int PACKAGE_ICON = 28;
051: private static final int END_ICON = 29;
052:
053: public static final int CLASS_COLOR = 0;
054: public static final int INTERFACE_COLOR = 4;
055: public static final int FIELD_COLOR = 8;
056: public static final int FIELD_STATIC_COLOR = 12;
057: public static final int CONSTRUCTOR_COLOR = 16;
058: public static final int METHOD_COLOR = 20;
059: public static final int METHOD_STATIC_COLOR = 24;
060: public static final int PACKAGE_COLOR = 28;
061: public static final int KEYWORD_COLOR = 29;
062: public static final int TYPE_COLOR = 30;
063: public static final int PARAMETER_NAME_COLOR = 31;
064: private static final int END_COLOR = 32;
065:
066: private static final String THROWS = " throws "; // NOI18N
067:
068: private static final String[] frequentWords = new String[] { "",
069: " ", "[]", "(", ")", ", ", "String", THROWS // NOI18N
070: };
071:
072: static final long serialVersionUID = 4737618682220847017L;
073:
074: Map widths;
075:
076: Icon[] icons = new Icon[END_ICON];
077:
078: Color[] colors = new Color[END_COLOR];
079:
080: private FontMetrics fontMetrics;
081:
082: private int fontHeight;
083:
084: private int ascent;
085:
086: private int iconTextGap = 5;
087:
088: protected JList list;
089:
090: protected Object value;
091:
092: protected boolean isSelected;
093:
094: protected boolean packageLastNameOnly;
095:
096: protected boolean displayStaticWord;
097:
098: protected int classDisplayOffset;
099:
100: protected boolean classDisplayFullName;
101:
102: protected int drawX;
103:
104: protected int drawY;
105:
106: protected int drawHeight;
107:
108: public JCCellRenderer() {
109: setOpaque(true);
110: setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
111: for (int i = 0; i < colors.length; i++) {
112: colors[i] = Color.black;
113: }
114: setForeColor(Color.green.darker().darker().darker(),
115: PACKAGE_COLOR);
116: setForeColor(Color.red.darker().darker().darker(), CLASS_COLOR);
117: setForeColor(Color.darkGray, INTERFACE_COLOR);
118: setForeColor(Color.blue.darker(), FIELD_COLOR);
119: setForeColor(Color.orange.darker(), CONSTRUCTOR_COLOR);
120: setForeColor(Color.red.darker().darker(), METHOD_COLOR);
121: setForeColor(Color.darkGray, KEYWORD_COLOR);
122: setForeColor(Color.magenta.darker(), PARAMETER_NAME_COLOR);
123:
124: setPackageLastNameOnly(true);
125: // setDisplayStaticWord(true);
126: }
127:
128: public void setFont(Font font) {
129: super .setFont(font);
130:
131: fontMetrics = this .getFontMetrics(font);
132: fontHeight = fontMetrics.getHeight();
133: ascent = fontMetrics.getAscent();
134: if (widths != null) {
135: widths.clear();
136: } else {
137: widths = new HashMap();
138: }
139: for (int i = 0; i < frequentWords.length; i++) {
140: storeWidth(frequentWords[i]);
141: }
142: Iterator i = JavaCompletion.getPrimitiveClassIterator();
143: while (i.hasNext()) {
144: storeWidth(((JCClass) i.next()).getName());
145: }
146: }
147:
148: public void setIconTextGap(int iconTextGap) {
149: this .iconTextGap = iconTextGap;
150: }
151:
152: public int getIconTextGap() {
153: return iconTextGap;
154: }
155:
156: private void storeWidth(String s) {
157: fontMetrics.stringWidth(s);
158: }
159:
160: public void setIcon(Icon icon, int type) {
161: if (type < PACKAGE_ICON) {
162: for (int i = 0; i < 4; i++) {
163: icons[type + i] = icon;
164: }
165: } else { // package icon
166: icons[type] = icon;
167: }
168: }
169:
170: public void setIcon(Icon icon, int type, int level) {
171: icons[type + level] = icon;
172: }
173:
174: public void setForeColor(Color color, int type) {
175: if (type < PACKAGE_COLOR) {
176: for (int i = 0; i < 4; i++) {
177: colors[type + i] = color;
178: }
179: } else { // package icon
180: colors[type] = color;
181: }
182: }
183:
184: public void setForeColor(Color color, int type, int level) {
185: colors[type + level] = color;
186: }
187:
188: public void setPackageLastNameOnly(boolean packageLastNameOnly) {
189: this .packageLastNameOnly = packageLastNameOnly;
190: }
191:
192: public void setDisplayStaticWord(boolean displayStaticWord) {
193: this .displayStaticWord = displayStaticWord;
194: }
195:
196: public void setClassDisplayOffset(int classDisplayOffset) {
197: this .classDisplayOffset = classDisplayOffset;
198: }
199:
200: public void setClassDisplayFullName(boolean classDisplayFullName) {
201: this .classDisplayFullName = classDisplayFullName;
202: }
203:
204: protected Color getColor(String s, Color defaultColor) {
205: return isSelected ? getForeground() : defaultColor;
206: }
207:
208: protected int getWidth(String s) {
209: Integer i = (Integer) widths.get(s);
210: if (i != null) {
211: return i.intValue();
212: } else {
213: return fontMetrics.stringWidth(s);
214: }
215: }
216:
217: /** Draw string using the foreground color */
218: protected void drawString(Graphics g, String s) {
219: if (g != null) {
220: g.setColor(getForeground());
221: }
222: drawStringToGraphics(g, s);
223: }
224:
225: protected void drawString(Graphics g, String s, int type) {
226: drawString(g, s, colors[type]);
227: }
228:
229: /**
230: * Draw string with given color which is first possibly modified by calling
231: * getColor() method to care about selection etc.
232: */
233: protected void drawString(Graphics g, String s, Color c) {
234: if (g != null) {
235: g.setColor(getColor(s, c));
236: }
237: drawStringToGraphics(g, s);
238: }
239:
240: protected void drawStringToGraphics(Graphics g, String s) {
241: if (g != null) {
242: g.drawString(s, drawX, drawY);
243: }
244: drawX += getWidth(s);
245: }
246:
247: /**
248: * Draw the icon if it is valid for the given type. Here the initial drawing
249: * assignments are also done.
250: */
251: protected void drawIcon(Graphics g, Icon icon) {
252: Insets i = getInsets();
253: if (i != null) {
254: drawX = i.left;
255: drawY = i.top;
256: } else {
257: drawX = 0;
258: drawY = 0;
259: }
260:
261: if (icon != null) {
262: if (g != null) {
263: icon.paintIcon(this , g, drawX, drawY);
264: }
265: drawX += icon.getIconWidth() + iconTextGap;
266: drawHeight = Math.max(fontHeight, icon.getIconHeight());
267: } else {
268: drawHeight = fontHeight;
269: }
270: if (i != null) {
271: drawHeight += i.bottom;
272: }
273: drawHeight += drawY;
274: drawY += ascent;
275: }
276:
277: protected Color getTypeColor(String s) {
278: return colors[(JavaCompletion.isPrimitiveClassName(s)) ? KEYWORD_COLOR
279: : TYPE_COLOR];
280: }
281:
282: protected void drawType(Graphics g, JCType typ) {
283: Color c = getTypeColor(typ.getClazz().getName());
284: drawString(g, typ.format(false), c);
285: }
286:
287: protected void drawParameter(Graphics g, JCParameter prm) {
288: drawType(g, prm.getType());
289: String name = prm.getName();
290: if (name.length() > 0) {
291: drawString(g, " "); // NOI18N
292: drawString(g, prm.getName(), PARAMETER_NAME_COLOR);
293: }
294: }
295:
296: protected void drawParameterList(Graphics g, JCConstructor ctr) {
297: drawString(g, "("); // NOI18N
298: JCParameter[] p = ctr.getParameters();
299: for (int i = 0; i < p.length; i++) {
300: drawParameter(g, p[i]);
301: if (i != p.length - 1) {
302: drawString(g, ", "); // NOI18N
303: }
304: }
305: drawString(g, ")"); // NOI18N
306: }
307:
308: protected void drawExceptions(Graphics g, JCConstructor ctr) {
309: JCClass[] exc = ctr.getExceptions();
310: if (exc.length > 0) {
311: drawString(g, THROWS, KEYWORD_COLOR);
312: for (int i = 0; i < exc.length; i++) {
313: String name = exc[i].getName();
314: Color c = getTypeColor(name);
315: drawString(g, name, c);
316: if (i != exc.length - 1) {
317: drawString(g, ", "); // NOI18N
318: }
319: }
320: }
321: }
322:
323: protected void drawPackage(Graphics g, JCPackage pkg) {
324: drawIcon(g, icons[PACKAGE_ICON]);
325: String name = pkg.getName();
326: if (packageLastNameOnly) {
327: name = pkg.getLastName();
328: }
329: drawString(g, name, PACKAGE_COLOR);
330: }
331:
332: protected void drawClass(Graphics g, JCClass cls) {
333: boolean ic = cls.isInterface();
334: int level = JavaCompletion.getLevel(cls.getModifiers());
335: String text = cls.getName();
336: if (classDisplayFullName) {
337: text = cls.getFullName();
338: } else if (classDisplayOffset > 0
339: && classDisplayOffset < text.length()) {
340: text = text.substring(classDisplayOffset);
341: }
342:
343: drawIcon(g, icons[(ic ? INTERFACE_ICON : CLASS_ICON) + level]);
344: drawString(g, text, (ic ? INTERFACE_ICON : CLASS_ICON));
345: }
346:
347: protected void drawField(Graphics g, JCField fld) {
348: int level = JavaCompletion.getLevel(fld.getModifiers());
349: drawIcon(
350: g,
351: ((fld.getModifiers() & Modifier.STATIC) == 0) ? icons[FIELD_ICON
352: + level]
353: : icons[FIELD_STATIC_ICON + level]);
354: if (displayStaticWord) {
355: if ((fld.getModifiers() & Modifier.STATIC) != 0) {
356: drawString(g, "static ", KEYWORD_COLOR); // NOI18N
357: }
358: }
359: drawType(g, fld.getType());
360: drawString(g, " "); // NOI18N
361: drawString(g, fld.getName(), FIELD_COLOR + level);
362: }
363:
364: protected void drawConstructor(Graphics g, JCConstructor ctr) {
365: int level = JavaCompletion.getLevel(ctr.getModifiers());
366: drawIcon(g, icons[CONSTRUCTOR_ICON + level]);
367: drawString(g, ctr.getClazz().getName(), CONSTRUCTOR_COLOR
368: + level);
369: drawParameterList(g, ctr);
370: drawExceptions(g, ctr);
371: }
372:
373: protected void drawMethod(Graphics g, JCMethod mtd) {
374: int level = JavaCompletion.getLevel(mtd.getModifiers());
375: drawIcon(
376: g,
377: ((mtd.getModifiers() & Modifier.STATIC) == 0) ? icons[METHOD_ICON
378: + level]
379: : icons[METHOD_STATIC_ICON + level]);
380: if (displayStaticWord) {
381: if ((mtd.getModifiers() & Modifier.STATIC) != 0) {
382: drawString(g, "static ", KEYWORD_COLOR); // NOI18N
383: }
384: }
385: drawType(g, mtd.getReturnType());
386: drawString(g, " "); // NOI18N
387: drawString(g, mtd.getName(), METHOD_COLOR + level);
388: drawParameterList(g, mtd);
389: drawExceptions(g, mtd);
390: }
391:
392: protected void draw(Graphics g) {
393: if (value instanceof JCPackage) {
394: drawPackage(g, (JCPackage) value);
395: } else if (value instanceof JCClass) {
396: drawClass(g, (JCClass) value);
397: } else if (value instanceof JCField) {
398: drawField(g, (JCField) value);
399: } else if (value instanceof JCMethod) {
400: drawMethod(g, (JCMethod) value);
401: } else if (value instanceof JCConstructor) {
402: drawConstructor(g, (JCConstructor) value);
403: } else if (value instanceof JCParameter) {
404: drawParameter(g, (JCParameter) value);
405: } else {
406: drawString(g, value.toString());
407: }
408: }
409:
410: public Dimension getPreferredSize() {
411: draw(null);
412: Insets i = getInsets();
413: if (i != null) {
414: drawX += i.right;
415: }
416: return new Dimension(drawX, drawHeight);
417: }
418:
419: public void paintComponent(Graphics g) {
420: // clear background
421: g.setColor(getBackground());
422: java.awt.Rectangle r = g.getClipBounds();
423: g.fillRect(r.x, r.y, r.width, r.height);
424:
425: draw(g);
426: }
427:
428: public Component getListCellRendererComponent(JList list,
429: Object value, int index, boolean isSelected,
430: boolean cellHasFocus) {
431: if (isSelected) {
432: setBackground(list.getSelectionBackground());
433: setForeground(list.getSelectionForeground());
434: } else {
435: setBackground(list.getBackground());
436: setForeground(list.getForeground());
437: }
438: this.list = list;
439: this.value = value;
440: this.isSelected = isSelected;
441: this.getAccessibleContext().setAccessibleName(
442: this.value.toString());
443: this.getAccessibleContext().setAccessibleDescription(
444: this.value.toString());
445: return this;
446: }
447:
448: }
|