/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor; import java.awt.*; import java.beans.PropertyChangeSupport; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.ResourceBundle; /** Definition of the annotation type. Annotation type is defined by attributes like * highlight color, foreground color, glyph icon, etc. Each annotation added to document * has reference to the name of the annotation type which defines how the annotation * will be drawn. * * @author David Konecny * @since 07/2001 */ public class AnnotationType { /** Property name for Name (String) */ public static final String PROP_NAME = "name"; /** Property name for Description (String) */ public static final String PROP_DESCRIPTION = "description"; /** Property name for Visible (boolean) */ public static final String PROP_VISIBLE = "visible"; /** Property name for Glyph (URL) */ public static final String PROP_GLYPH_URL = "glyph"; /** Property name for Highlight (Color) */ public static final String PROP_HIGHLIGHT_COLOR = "highlight"; /** Property name for Foreground (Color) */ public static final String PROP_FOREGROUND_COLOR = "foreground"; /** Property name for WaveUnderline (Color) */ public static final String PROP_WAVEUNDERLINE_COLOR = "waveunderline"; /** Property name for WholeLine (boolean) */ public static final String PROP_WHOLE_LINE = "wholeline"; /** Property name for ContentType (String) */ public static final String PROP_CONTENT_TYPE = "contenttype"; /** Property name for Actions (Action[]) */ public static final String PROP_ACTIONS = "actions"; /** Property name for TooltipText (String) */ public static final String PROP_TOOLTIP_TEXT = "tooltipText"; /** Property name for InheritForegroundColor (Boolean) */ public static final String PROP_INHERIT_FOREGROUND_COLOR = "inheritForegroundColor"; /** Property name for UseHighlightColor (Boolean) */ public static final String PROP_USE_HIGHLIGHT_COLOR = "useHighlightColor"; /** Property name for UseWaveUnderlineColor (Boolean) */ public static final String PROP_USE_WAVEUNDERLINE_COLOR = "useWaveUnderlineColor"; /** Property name for Combinations (AnnotationType.CombinationMember[]). * If some annotation type has set this property, it means that editor * must check if line contains all types which are defined in this array. * If it contains, then all this annotation types become hidden and this * type is shown instead of them. */ public static final String PROP_COMBINATIONS = "combinations"; public static final String PROP_COMBINATION_ORDER = "combinationOrder"; public static final String PROP_COMBINATION_MINIMUM_OPTIONALS = "combinationMinimumOptionals"; /** Property holding the object which represent the source of this annotation type. * This property is used during the saving of the changes in annotation type. */ public static final String PROP_FILE = "file"; public static final String PROP_LOCALIZING_BUNDLE = "bundle"; public static final String PROP_DESCRIPTION_KEY = "desciptionKey"; public static final String PROP_ACTIONS_FOLDER = "actionsFolder"; public static final String PROP_COMBINATION_TOOLTIP_TEXT_KEY = "tooltipTextKey"; /** Storage of all annotation type properties. */ private Map properties; /** Support for property change listeners*/ private PropertyChangeSupport support; /** Glyph icon loaded from URL into Image */ private Image img = null; /** Coloring composed from foreground and highlight color*/ private Coloring col; public AnnotationType() { properties = new HashMap(15*4/3); support = new PropertyChangeSupport(this); } /** Getter for Glyph property * @return URL of the glyph icon */ public java.net.URL getGlyph() { URL u = (java.net.URL)getProp(PROP_GLYPH_URL); if (u == null) u = AnnotationTypes.getDefaultGlyphURL(); return u; } /** Setter for the Glyph property * @param glyph URL to gpylh icon */ public void setGlyph(java.net.URL glyph) { putProp(PROP_GLYPH_URL, glyph); } /** Gets Image which represent the glyph. This method is called * only from AWT thead and so it is not necessary to synchronize it. */ public Image getGlyphImage() { if (img == null) { img = Toolkit.getDefaultToolkit().getImage(getGlyph()); } return img; } /** Whether the annotation type has its own glyph icon or not */ public boolean isDefaultGlyph() { if (getProp(PROP_GLYPH_URL) == null) return true; else return false; } /** Getter for Highlight property * @return highlight color */ public java.awt.Color getHighlight() { return (java.awt.Color)getProp(PROP_HIGHLIGHT_COLOR); } /** Setter for the Highlight property * @param highlight highlight color */ public void setHighlight(java.awt.Color highlight) { col = null; // force the create new coloring putProp(PROP_HIGHLIGHT_COLOR, highlight); firePropertyChange(PROP_HIGHLIGHT_COLOR, null, null); processChange(); } /** Getter for UseHighlightColor property * @return whether the highlight color should be used or not */ public boolean isUseHighlightColor() { Boolean b = (Boolean)getProp(PROP_USE_HIGHLIGHT_COLOR); if (b == null) return true; return b.booleanValue(); } /** Setter for the UseHighlightColor property * @param use use highlight color */ public void setUseHighlightColor(boolean use) { if (isUseHighlightColor() != use) { col = null; // force the create new coloring putProp(PROP_USE_HIGHLIGHT_COLOR, use ? Boolean.TRUE : Boolean.FALSE); firePropertyChange(PROP_USE_HIGHLIGHT_COLOR, null, null); processChange(); } } /** Getter for Foreground property * @return foreground color */ public java.awt.Color getForegroundColor() { return (java.awt.Color)getProp(PROP_FOREGROUND_COLOR); } /** Setter for the Foreground property * @param foregroundColor foreground color */ public void setForegroundColor(java.awt.Color foregroundColor) { col = null; // force the create new coloring putProp(PROP_FOREGROUND_COLOR, foregroundColor); firePropertyChange(PROP_FOREGROUND_COLOR, null, null); processChange(); } /** Getter for InheritForegroundColor property * @return whether the foreground color should be inherit or not */ public boolean isInheritForegroundColor() { Boolean b = (Boolean)getProp(PROP_INHERIT_FOREGROUND_COLOR); if (b == null) return true; return b.booleanValue(); } /** Setter for the InheritfForegroundColor property * @param inherit inherit foreground color */ public void setInheritForegroundColor(boolean inherit) { if (isInheritForegroundColor() != inherit) { col = null; // force the create new coloring putProp(PROP_INHERIT_FOREGROUND_COLOR, inherit ? Boolean.TRUE : Boolean.FALSE); firePropertyChange(PROP_INHERIT_FOREGROUND_COLOR, null, null); processChange(); } } /** Getter for WaveUnderline property * @return waveunderline color */ public java.awt.Color getWaveUnderlineColor() { return (java.awt.Color)getProp(PROP_WAVEUNDERLINE_COLOR); } /** Setter for the WaveUnderline property * @param waveunderline wave underline color */ public void setWaveUnderlineColor(java.awt.Color waveunderline) { col = null; // force the create new coloring putProp(PROP_WAVEUNDERLINE_COLOR, waveunderline); firePropertyChange(PROP_WAVEUNDERLINE_COLOR, null, null); processChange(); } /** Getter for UseWaveUnderlineColor property * @return whether the waveunderline color should be used or not */ public boolean isUseWaveUnderlineColor() { Boolean b = (Boolean)getProp(PROP_USE_WAVEUNDERLINE_COLOR); if (b == null) return true; return b.booleanValue(); } /** Setter for the UseWaveUnderlineColor property * @param use use wave underline color */ public void setUseWaveUnderlineColor(boolean use) { if (isUseWaveUnderlineColor() != use) { col = null; // force the create new coloring putProp(PROP_USE_WAVEUNDERLINE_COLOR, use ? Boolean.TRUE : Boolean.FALSE); firePropertyChange(PROP_USE_WAVEUNDERLINE_COLOR, null, null); processChange(); } } /** Process change of some setting. It means that * listeners are notified and change is saved. */ private void processChange() { // if type does not have this property it is just being loaded if (getProp(AnnotationType.PROP_FILE) == null) return; // force repaint of all documents Settings.touchValue(null, null); AnnotationTypes.getTypes().saveType(this); } /** Gets all the colors composed as Coloring * @return coloring containing all colors */ public Coloring getColoring() { if (col == null) col = new Coloring(null, Coloring.FONT_MODE_DEFAULT, isInheritForegroundColor() ? null : getForegroundColor(), isUseHighlightColor() ? getHighlight() : null, null, null, isUseWaveUnderlineColor() ? getWaveUnderlineColor() : null); return col; } /** Getter for Actions property * @return array of actions */ public javax.swing.Action[] getActions() { return (javax.swing.Action[])getProp(PROP_ACTIONS); } /** Setter for Actions property * @return array of actions */ public void setActions(javax.swing.Action[] actions) { putProp(PROP_ACTIONS, actions); } /** Getter for Combinations property * @return array of combinations */ public CombinationMember[] getCombinations() { return (CombinationMember[])getProp(PROP_COMBINATIONS); } /** Setter for Combinations property */ public void setCombinations(CombinationMember[] combs) { putProp(PROP_COMBINATIONS, combs); } /** Getter for Name property * @return annotation type name */ public String getName() { return (String)getProp(PROP_NAME); } /** Setter for the Name property * @param name name of the annotation type */ public void setName(String name) { putProp(PROP_NAME, name); } /** Getter for Description property * @return localized description of the annotation type */ public String getDescription() { String desc = (String)getProp(PROP_DESCRIPTION); if (desc == null) { String localizer = (String)getProp(PROP_LOCALIZING_BUNDLE); String key = (String)getProp(PROP_DESCRIPTION_KEY); ResourceBundle bundle = ImplementationProvider.getDefault().getResourceBundle(localizer); desc = bundle.getString(key); setDescription(desc); // cache it } return desc; } /** Setter for the Description property * @param name localized description of the annotation type */ public void setDescription(String name) { putProp(PROP_DESCRIPTION, name); } /** Getter for TooltipText property * @return localized TooltipText of the annotation type */ public String getTooltipText() { String text = (String)getProp(PROP_TOOLTIP_TEXT); if (text == null) { String localizer = (String)getProp(PROP_LOCALIZING_BUNDLE); String key = (String)getProp(PROP_COMBINATION_TOOLTIP_TEXT_KEY); ResourceBundle bundle = ImplementationProvider.getDefault().getResourceBundle(localizer); text = bundle.getString(key); setTooltipText(text); // cache it } return text; } /** Setter for the TooltipText property * @param name localized TooltipText of the annotation type */ public void setTooltipText(String text) { putProp(PROP_TOOLTIP_TEXT, text); } /** Getter for CombinationOrder property * @return order of the annotation type */ public int getCombinationOrder() { if (getProp(PROP_COMBINATION_ORDER) == null) return 0; return ((Integer)getProp(PROP_COMBINATION_ORDER)).intValue(); } /** Setter for the CombinationOrder property * @param order order of the annotation type combination */ public void setCombinationOrder(int order) { putProp(PROP_COMBINATION_ORDER, new Integer(order)); } /** Setter for the CombinationOrder property * @param ord order of the annotation type combination */ public void setCombinationOrder(String ord) { int order; try { order = Integer.parseInt(ord); } catch (NumberFormatException ex) { if( Boolean.getBoolean( "netbeans.debug.exceptions" ) ) ex.printStackTrace(); return; } putProp(PROP_COMBINATION_ORDER, new Integer(order)); } /** Getter for MinimumOptionals property * @return minimum number of the optional annotation types which * must be matched */ public int getMinimumOptionals() { if (getProp(PROP_COMBINATION_MINIMUM_OPTIONALS) == null) return 0; return ((Integer)getProp(PROP_COMBINATION_MINIMUM_OPTIONALS)).intValue(); } public void setMinimumOptionals(int min) { putProp(PROP_COMBINATION_MINIMUM_OPTIONALS, new Integer(min)); } public void setMinimumOptionals(String m) { int min; try { min = Integer.parseInt(m); } catch (NumberFormatException ex) { if( Boolean.getBoolean( "netbeans.debug.exceptions" ) ) ex.printStackTrace(); return; } putProp(PROP_COMBINATION_MINIMUM_OPTIONALS, new Integer(min)); } /** Getter for Visible property * @return whether the annoation type is visible or not */ public boolean isVisible() { Boolean b = (Boolean)getProp(PROP_VISIBLE); if (b == null) return false; return b.booleanValue(); } /** Setter for the Visible property * @param vis visibility of the annotation type */ public void setVisible(boolean vis) { putProp(PROP_VISIBLE, vis ? Boolean.TRUE : Boolean.FALSE); } /** Setter for the Visible property * @param vis visibility of the annotation type */ public void setVisible(String vis) { putProp(PROP_VISIBLE, Boolean.valueOf(vis)); } /** Getter for WholeLine property * @return whether this annotation type is whole line or not */ public boolean isWholeLine() { Boolean b = (Boolean)getProp(PROP_WHOLE_LINE); if (b == null) return true; return b.booleanValue(); } /** Setter for the WholeLine property * @param wl whether the annotation type is whole line or not */ public void setWholeLine(boolean wl) { putProp(PROP_WHOLE_LINE, wl ? Boolean.TRUE : Boolean.FALSE); } /** Setter for the WholeLine property * @param wl whether the annotation type is whole line or not */ public void setWholeLine(String wl) { putProp(PROP_WHOLE_LINE, Boolean.valueOf(wl)); } /** Getter for ContentType property * @return list of content types separated by commas */ public String getContentType() { return (String)getProp(PROP_CONTENT_TYPE); } /** Setter for the ContentType property * @param ct list of content type separeted by commas */ public void setContentType(String ct) { putProp(PROP_CONTENT_TYPE, ct); } /** Gets property for appropriate string value */ public Object getProp(String prop){ return properties.get(prop); } /** Puts property to Map */ public void putProp(Object key, Object value){ if (value == null) { properties.remove(key); return; } properties.put(key,value); } public String toString() { return "AnnotationType: name='" + getName() + "', description='" + getDescription() + // NOI18N "', visible=" + isVisible() + ", wholeline=" + isWholeLine() + // NOI18N ", glyph=" + getGlyph() + ", highlight=" + getHighlight() + // NOI18N ", foreground=" + getForegroundColor() + // NOI18N "', inheritForeground=" + isInheritForegroundColor() + //NOI18N ", contenttype="+getContentType(); //NOI18N } /** Add listeners on changes of annotation type properties * @param l change listener*/ final public void addPropertyChangeListener(java.beans.PropertyChangeListener l) { support.addPropertyChangeListener (l); } /** Remove listeners on changes of annotation type properties * @param l change listener*/ final public void removePropertyChangeListener(java.beans.PropertyChangeListener l) { support.removePropertyChangeListener (l); } /** Fire property change to registered listeners. */ final protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { support.firePropertyChange(propertyName, oldValue, newValue); } /** Hepler class describing annotation type and whether all * occurences of this type should be absorbed by combination or not. * The annonation type which want to combine some other types, must * define array of instances of this helper class. See * AnnotationType.PROP_COMBINATIONS property. */ public static final class CombinationMember { /** Name of the annotation type */ private String type; /** Whether all occurences of this type should be absorbed or not */ private boolean absorbAll; /** Whether this combination member is options or not */ private boolean optional; /** Minimum count of this type which must be found on the line to make * valid combination */ private int minimumCount; public CombinationMember(String type, boolean absorbAll, boolean optional, int minimumCount) { this.type = type; this.absorbAll = absorbAll; this.optional = optional; this.minimumCount = minimumCount; } public CombinationMember(String type, boolean absorbAll, boolean optional, String minimumCount) { this.type = type; this.absorbAll = absorbAll; this.optional = optional; if (minimumCount != null && minimumCount.length() > 0) { try { this.minimumCount = Integer.parseInt(minimumCount); } catch (NumberFormatException ex) { if( Boolean.getBoolean( "netbeans.debug.exceptions" ) ) ex.printStackTrace(); this.minimumCount = 0; } } else this.minimumCount = 0; } /** Gets name of the annotation type */ public String getName() { return type; } /** Getter for AbsorbAll property */ public boolean isAbsorbAll() { return absorbAll; } /** Getter for Optional property */ public boolean isOptional() { return optional; } /** Getter for MinimumCount property */ public int getMinimumCount() { return minimumCount; } } }