/* * @(#)PixmapStyle.java 1.19 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.java.swing.plaf.gtk; import javax.swing.plaf.synth.*; import java.awt.*; import java.util.*; import javax.swing.*; import java.security.*; import sun.swing.plaf.synth.*; /** * PixmapStyle extends GTKStyle adding support for a set of Infos. * * @version 1.19, 12/19/03 * @author Scott Violet */ class PixmapStyle extends GTKStyle implements GTKConstants { /** * There should only ever be one pixmap engine. */ private static final GTKEngine PIXMAP_ENGINE = new PixmapEngine(); /** * Set of Infos used to determine what to paint. */ private Info[] info; /** * Creates a duplicate of the passed in style. */ public PixmapStyle(DefaultSynthStyle style) { super(style); if (style instanceof PixmapStyle) { this.info = ((PixmapStyle)style).info; } } /** * Creates a PixmapStyle from the passed in arguments. */ public PixmapStyle(StateInfo[] states, CircularIdentityList classSpecificValues, Font font, int xThickness, int yThickness, GTKStockIconInfo[] icons, Info[] info) { super(states, classSpecificValues, font, xThickness, yThickness, icons); this.info = info; } /** * Adds the state of this PixmapStyle to that of s * returning a combined SynthStyle. */ public DefaultSynthStyle addTo(DefaultSynthStyle s) { if (!(s instanceof PixmapStyle)) { s = new PixmapStyle(s); } PixmapStyle style = (PixmapStyle)super.addTo(s); if (info != null) { if (style.info == null) { style.info = info; } else { // Place the more specific first. Info[] merged = new Info[style.info.length + info.length]; System.arraycopy(info, 0, merged, 0, info.length); System.arraycopy(style.info, 0, merged, info.length, style.info.length); style.info = merged; } } return style; } /** * Creates a copy of the reciever and returns it. */ public Object clone() { PixmapStyle style = (PixmapStyle)super.clone(); // Info is immutable, no need to clone it. style.info = this.info; return style; } /** * Returns a GTKEngine to use for rendering. */ public GTKEngine getEngine(SynthContext context) { return PIXMAP_ENGINE; } /** * Returns the first instance of Info that matches the past in args, may * return null if nothing matches. * * @param function String name for the painting method * @param detail Description of what is being painted * @param componentState State of the Component * @param shadow Shadow type * @param orientation Orientation of what is being painted * @param gapSide Side of the gap being drawn * @param arrowDirection direction of the arrow. * @return Best matching Info, or null if none match */ public Info getInfo(String function, String detail, int componentState, int shadow, int orientation, int gapSide, int arrowDirection) { if (info != null) { for (int counter = 0, max = info.length; counter < max;counter++) { if (info[counter].getFunction() == function && info[counter]. getMatchCount(detail, componentState, shadow, orientation, gapSide, arrowDirection) != -1) { return info[counter]; } } } return null; } /** * Returns the number of non-null arugments and arguments that are * != UNDEFINED. */ private int getMaxMatchCount(int componentState, int shadow, int orientation, int gapSide, int arrowDirection, String detail) { int count = 0; if (detail != null) { count++; } if (componentState != UNDEFINED) { count++; } if (shadow != UNDEFINED) { count++; } if (orientation != UNDEFINED) { count++; } if (gapSide != UNDEFINED) { count++; } if (arrowDirection != UNDEFINED) { count++; } return count; } /** * A description of how to paint a portion of a widget. */ public static class Info { // match data private String function = null; private String detail = null; int gapSide = UNDEFINED; int orientation = UNDEFINED; int componentState = UNDEFINED; int shadow = UNDEFINED; int arrowDirection = UNDEFINED; boolean recolorable = false; // background Object image = null; Insets fileInsets = null; boolean stretch = false; // overlay Object overlayImage = null; Insets overlayInsets = null; boolean overlayStretch = false; // gap start Object gapStartImage = null; Insets gapStartInsets = null; // gap Object gapImage = null; Insets gapInsets = null; // gap end Object gapEndImage = null; Insets gapEndInsets = null; public void setFunction(String function) { this.function = function.intern(); } public void setDetail(String detail) { this.detail = detail.intern(); } public String getFunction() { return function; } public Image getImage() { image = getImage(image); return (Image)image; } public boolean isRecolorable() { return recolorable; } public Insets getImageInsets() { return fileInsets; } public boolean getStretch() { return stretch; } public String getDetail() { return detail; } public int getComponentState() { return componentState; } public int getShadow() { return shadow; } public int getGapSide() { return gapSide; } public Image getGapImage() { gapImage = getImage(gapImage); return (Image)gapImage; } public Insets getGapInsets() { return gapInsets; } public Image getGapStartImage() { gapStartImage = getImage(gapStartImage); return (Image)gapStartImage; } public Insets getGapStartInsets() { return gapStartInsets; } public Image getGapEndImage() { gapEndImage = getImage(gapEndImage); return (Image)gapEndImage; } public Insets getGapEndInsets() { return gapEndInsets; } public Image getOverlayImage() { overlayImage = getImage(overlayImage); return (Image)overlayImage; } public Insets getOverlayInsets() { return overlayInsets; } public boolean getOverlayStretch() { return overlayStretch; } public int getArrowDirection() { return arrowDirection; } public int getOrientation() { return orientation; } private Image getImage(final Object o) { if (o == null || o instanceof Image) { return (Image)o; } ImageIcon ii = (ImageIcon)AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return new ImageIcon((String)o); } }); if (ii.getIconWidth() > 0 && ii.getIconHeight() > 0) { return ii.getImage(); } return null; } /** * Will return < 0 if doesn't match, otherwise return the * number of parameters that match. */ int getMatchCount(String detail, int componentState, int shadow, int orientation, int gapSide, int arrowDirection) { int matchCount = 0; if (this.componentState != UNDEFINED) { if (componentState != UNDEFINED && this.componentState != componentState) { return -1; } matchCount++; } if (this.shadow != UNDEFINED) { if (shadow != UNDEFINED && this.shadow != shadow) { return -1; } matchCount++; } if (this.orientation != UNDEFINED) { if (orientation != UNDEFINED && this.orientation != orientation) { return -1; } matchCount++; } if (this.gapSide != UNDEFINED) { if (gapSide != UNDEFINED && this.gapSide != gapSide) { return -1; } matchCount++; } if (this.arrowDirection != UNDEFINED) { if (arrowDirection != UNDEFINED && this.arrowDirection != arrowDirection) { return -1; } matchCount++; } if (this.detail != null) { if (this.detail != detail) { return -1; } matchCount++; } return matchCount; } /** * Returns true if this Info matches that of the passed in Info. * This differs from equals in so far as this only compares the * properties that are used in lookup vs the actual images or * insets. * * @return true if the receiver and info can be considered equal * for lookup. */ boolean matches(Info info) { return (info.function == function && info.detail == detail && info.componentState == componentState && info.shadow == shadow && info.gapSide == gapSide && info.arrowDirection == arrowDirection && info.orientation == orientation); } public String toString() { StringBuffer buf = new StringBuffer(); buf.append("IMAGE:\n"); if (function != null) { buf.append(" function=").append(function).append('\n'); } if (detail != null) { buf.append(" detail=").append(detail).append('\n'); } if (gapSide != UNDEFINED) { buf.append(" gapSide="); buf.append(getSideName(gapSide)).append('\n'); } if (orientation != UNDEFINED) { buf.append(" orientation="); buf.append(getOrientName(orientation)).append('\n'); } if (componentState != UNDEFINED) { buf.append(" componentState="); buf.append(getStateName(componentState, "UNDEFINED")).append('\n'); } if (shadow != UNDEFINED) { buf.append(" shadow="); buf.append(getShadowName(shadow)).append('\n'); } if (arrowDirection != UNDEFINED) { buf.append(" arrowDirection="); buf.append(getArrowDirectionName(arrowDirection)).append('\n'); } if (recolorable != false) { buf.append(" recolorable=").append(recolorable).append('\n'); } if (image != null) { buf.append(" image=").append(image).append('\n'); } if (fileInsets != null) { buf.append(" fileInsets=").append(fileInsets).append('\n'); } if (stretch != false) { buf.append(" stretch=").append(stretch).append('\n'); } if (overlayImage != null) { buf.append(" overlayImage=").append(overlayImage).append('\n'); } if (overlayInsets != null) { buf.append(" overlayInsets=").append(overlayInsets).append('\n'); } if (overlayStretch != false) { buf.append(" overlayStretch=").append(overlayStretch).append('\n'); } if (gapStartImage != null) { buf.append(" gapStartImage=").append(gapStartImage).append('\n'); } if (gapStartInsets != null) { buf.append(" gapStartInsets=").append(gapStartInsets).append('\n'); } if (gapImage != null) { buf.append(" gapImage=").append(gapImage).append('\n'); } if (gapInsets != null) { buf.append(" gapInsets=").append(gapInsets).append('\n'); } if (gapEndImage != null) { buf.append(" gapEndImage=").append(gapEndImage).append('\n'); } if (gapEndInsets != null) { buf.append(" gapEndInsets=").append(gapEndInsets).append('\n'); } buf.deleteCharAt(buf.length() - 1); return buf.toString(); } private static String getSideName(int side) { switch(side) { case TOP: return "TOP"; case BOTTOM: return "BOTTOM"; case LEFT: return "LEFT"; case RIGHT: return "RIGHT"; case UNDEFINED: return "UNDEFINED"; } return "UNKNOWN"; } private static String getOrientName(int orient) { switch(orient) { case HORIZONTAL: return "HORIZONTAL"; case VERTICAL: return "VERTICAL"; case UNDEFINED: return "UNDEFINED"; } return "UNKNOWN"; } private static String getShadowName(int shadow) { switch(shadow) { case SHADOW_IN: return "SHADOW_IN"; case SHADOW_OUT: return "SHADOW_OUT"; case SHADOW_ETCHED_IN: return "SHADOW_ETCHED_IN"; case SHADOW_ETCHED_OUT: return "SHADOW_ETCHED_OUT"; case SHADOW_NONE: return "SHADOW_NONE"; case UNDEFINED: return "UNDEFINED"; } return "UNKNOWN"; } private static String getArrowDirectionName(int dir) { switch(dir) { case ARROW_UP: return "ARROW_UP"; case ARROW_DOWN: return "ARROW_DOWN"; case ARROW_LEFT: return "ARROW_LEFT"; case ARROW_RIGHT: return "ARROW_RIGHT"; case UNDEFINED: return "UNDEFINED"; } return "UNKNOWN"; } } public String toString() { if (info == null) { return super.toString(); } else { StringBuffer buf = new StringBuffer(super.toString()); if (buf.length() > 0) { buf.append('\n'); } buf.append("*** Pixmap Engine Info ***\n"); for (int i = 0; i < info.length; i++) { buf.append(info[i].toString()).append('\n'); } // remove last newline buf.deleteCharAt(buf.length() - 1); return buf.toString(); } } }