1. /*
  2. * @(#)DefaultSynthStyle.java 1.19 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import java.awt.*;
  9. import java.util.*;
  10. import javax.swing.*;
  11. import javax.swing.border.Border;
  12. /**
  13. * @version 1.19, 01/23/03
  14. * @author Scott Violet
  15. */
  16. class DefaultSynthStyle extends SynthStyle implements Cloneable{
  17. /**
  18. * Should the component be opaque?
  19. */
  20. private boolean opaque;
  21. /**
  22. * Insets.
  23. */
  24. private Insets insets;
  25. /**
  26. * Information specific to ComponentState.
  27. */
  28. StateInfo[] states;
  29. /**
  30. * User specific data.
  31. */
  32. Map data;
  33. /**
  34. * Nullary constructor, intended for subclassers.
  35. */
  36. protected DefaultSynthStyle() {
  37. }
  38. /**
  39. * Creates a new DefaultSynthStyle that is a copy of the passed in
  40. * style.
  41. */
  42. public DefaultSynthStyle(DefaultSynthStyle style) {
  43. opaque = style.opaque;
  44. if (style.insets != null) {
  45. insets = new Insets(style.insets.top, style.insets.left,
  46. style.insets.bottom, style.insets.right);
  47. }
  48. if (style.states != null) {
  49. states = new StateInfo[style.states.length];
  50. for (int counter = style.states.length - 1; counter >= 0;
  51. counter--) {
  52. states[counter] = (StateInfo)style.states[counter].clone();
  53. }
  54. }
  55. if (style.data != null) {
  56. data = new HashMap();
  57. data.putAll(style.data);
  58. }
  59. }
  60. public DefaultSynthStyle(Insets insets, boolean opaque,
  61. StateInfo[] states, Map data) {
  62. this.insets = insets;
  63. this.opaque = opaque;
  64. this.states = states;
  65. this.data = data;
  66. }
  67. protected Color _getColor(JComponent c, Region id, int state,
  68. ColorType type) {
  69. StateInfo si = getStateInfo(state);
  70. if (si != null) {
  71. return si.getColor(type);
  72. }
  73. return null;
  74. }
  75. protected Font _getFont(JComponent c, Region id, int state) {
  76. StateInfo si = getStateInfo(state);
  77. if (si != null) {
  78. return si.getFont();
  79. }
  80. return null;
  81. }
  82. public Insets getInsets(SynthContext state, Insets to) {
  83. if (to == null) {
  84. to = new Insets(0, 0, 0, 0);
  85. }
  86. if (insets != null) {
  87. to.left = insets.left;
  88. to.right = insets.right;
  89. to.top = insets.top;
  90. to.bottom = insets.bottom;
  91. }
  92. else {
  93. to.left = to.right = to.top = to.bottom = 0;
  94. }
  95. return to;
  96. }
  97. /**
  98. * Returns the Border for the passed in Component. This may return null.
  99. */
  100. public SynthPainter getBorderPainter(SynthContext ss) {
  101. StateInfo si = getStateInfo(ss.getComponentState());
  102. if (si != null) {
  103. return si.getBorderPainter();
  104. }
  105. return null;
  106. }
  107. /**
  108. * Returns the Painter used to paint the background.
  109. */
  110. public SynthPainter getBackgroundPainter(SynthContext ss) {
  111. StateInfo si = getStateInfo(ss.getComponentState());
  112. if (si != null) {
  113. return si.getBackgroundPainter();
  114. }
  115. return null;
  116. }
  117. /**
  118. * Returns the value to initialize the opacity property of the Component
  119. * to. A Style should NOT assume the opacity will remain this value, the
  120. * developer may reset it or override it.
  121. */
  122. public boolean isOpaque(SynthContext ss) {
  123. return opaque;
  124. }
  125. public Object get(SynthContext state, Object key) {
  126. if (data != null) {
  127. return data.get(key);
  128. }
  129. return null;
  130. }
  131. /**
  132. * Creates a clone of the receiver.
  133. */
  134. public Object clone() {
  135. DefaultSynthStyle style;
  136. try {
  137. style = (DefaultSynthStyle)super.clone();
  138. } catch (CloneNotSupportedException cnse) {
  139. return null;
  140. }
  141. if (states != null) {
  142. style.states = new StateInfo[states.length];
  143. for (int counter = states.length - 1; counter >= 0; counter--) {
  144. style.states[counter] = (StateInfo)states[counter].clone();
  145. }
  146. }
  147. if (data != null) {
  148. style.data = new HashMap();
  149. style.data.putAll(data);
  150. }
  151. return style;
  152. }
  153. /**
  154. * Merges the contents of this Style with that of the passed in Style,
  155. * returning the resulting merged syle.
  156. */
  157. public DefaultSynthStyle addTo(DefaultSynthStyle style) {
  158. if (insets != null) {
  159. style.insets = this.insets;
  160. }
  161. style.opaque = opaque;
  162. if (states != null) {
  163. if (style.states == null) {
  164. style.states = new StateInfo[states.length];
  165. for (int counter = states.length - 1; counter >= 0; counter--){
  166. if (states[counter] != null) {
  167. style.states[counter] = (StateInfo)states[counter].
  168. clone();
  169. }
  170. }
  171. }
  172. else {
  173. // Find the number of new states in unique
  174. int unique = 0;
  175. for (int thisCounter = states.length - 1; thisCounter >= 0;
  176. thisCounter--) {
  177. int state = states[thisCounter].getComponentState();
  178. boolean found = false;
  179. for (int oCounter = style.states.length - 1; oCounter >= 0;
  180. oCounter--) {
  181. if (state == style.states[oCounter].
  182. getComponentState()) {
  183. states[thisCounter].addTo(style.states[oCounter]);
  184. found = true;
  185. break;
  186. }
  187. }
  188. if (!found) {
  189. unique++;
  190. }
  191. }
  192. if (unique != 0) {
  193. // There are states that exist in this Style that
  194. // don't exist in the other style, recreate the array
  195. // and add them.
  196. StateInfo[] newStates = new StateInfo[
  197. unique + style.states.length];
  198. int newIndex = style.states.length;
  199. System.arraycopy(style.states, 0, newStates, 0,
  200. style.states.length);
  201. for (int thisCounter = states.length - 1; thisCounter >= 0;
  202. thisCounter--) {
  203. int state = states[thisCounter].getComponentState();
  204. boolean found = false;
  205. for (int oCounter = style.states.length - 1;
  206. oCounter >= 0; oCounter--) {
  207. if (state == style.states[oCounter].
  208. getComponentState()) {
  209. found = true;
  210. break;
  211. }
  212. }
  213. if (!found) {
  214. newStates[newIndex++] = (StateInfo)states[
  215. thisCounter].clone();
  216. }
  217. }
  218. style.states = newStates;
  219. }
  220. }
  221. }
  222. if (data != null) {
  223. if (style.data == null) {
  224. style.data = new HashMap();
  225. }
  226. style.data.putAll(data);
  227. }
  228. return style;
  229. }
  230. StateInfo getStateInfo(int state) {
  231. if (states != null) {
  232. int bestCount = 0;
  233. int bestIndex = -1;
  234. for (int counter = states.length - 1; counter >= 0; counter--) {
  235. int matchCount = states[counter].getMatchCount(state);
  236. if (matchCount > bestCount) {
  237. bestIndex = counter;
  238. bestCount = matchCount;
  239. }
  240. }
  241. if (bestIndex != -1) {
  242. return states[bestIndex];
  243. }
  244. }
  245. return null;
  246. }
  247. /**
  248. * StateInfo represents Style information specific to a ComponentState.
  249. */
  250. public static class StateInfo {
  251. private SynthPainter borderPainter;
  252. private SynthPainter backgroundPainter;
  253. private Font font;
  254. Color[] colors;
  255. private int state;
  256. public StateInfo(int state, SynthPainter bPainter,
  257. SynthPainter bgPainter, Font font, Color[] colors) {
  258. this.state = state;
  259. this.borderPainter = bPainter;
  260. this.backgroundPainter = bgPainter;
  261. this.font = font;
  262. this.colors = colors;
  263. }
  264. public StateInfo(StateInfo info) {
  265. this.state = info.state;
  266. this.borderPainter = info.borderPainter;
  267. this.backgroundPainter = info.backgroundPainter;
  268. this.font = info.font;
  269. if (info.colors != null) {
  270. this.colors = new Color[info.colors.length];
  271. System.arraycopy(info.colors, 0, colors, 0,info.colors.length);
  272. }
  273. }
  274. public SynthPainter getBorderPainter() {
  275. return borderPainter;
  276. }
  277. public SynthPainter getBackgroundPainter() {
  278. return backgroundPainter;
  279. }
  280. public Font getFont() {
  281. return font;
  282. }
  283. protected Color[] getColors() {
  284. return colors;
  285. }
  286. public Color getColor(ColorType type) {
  287. if (colors != null) {
  288. int id = type.getID();
  289. if (id < colors.length) {
  290. return colors[id];
  291. }
  292. }
  293. return null;
  294. }
  295. public StateInfo addTo(StateInfo info) {
  296. info.borderPainter = borderPainter;
  297. info.backgroundPainter = backgroundPainter;
  298. if (font != null) {
  299. info.font = font;
  300. }
  301. if (colors != null) {
  302. if (info.colors == null) {
  303. info.colors = new Color[colors.length];
  304. System.arraycopy(colors, 0, info.colors, 0,
  305. colors.length);
  306. }
  307. else {
  308. if (info.colors.length < colors.length) {
  309. Color[] old = info.colors;
  310. info.colors = new Color[colors.length];
  311. System.arraycopy(old, 0, info.colors, 0, old.length);
  312. }
  313. for (int counter = colors.length - 1; counter >= 0;
  314. counter--) {
  315. if (colors[counter] != null) {
  316. info.colors[counter] = colors[counter];
  317. }
  318. }
  319. }
  320. }
  321. return info;
  322. }
  323. public int getComponentState() {
  324. return state;
  325. }
  326. /**
  327. * Returns the number of states that are similar between the
  328. * ComponentState this StateInfo represents and val.
  329. */
  330. private final int getMatchCount(int val) {
  331. // This comes from BigInteger.bitCnt
  332. val &= state;
  333. val -= (0xaaaaaaaa & val) >>> 1;
  334. val = (val & 0x33333333) + ((val >>> 2) & 0x33333333);
  335. val = val + (val >>> 4) & 0x0f0f0f0f;
  336. val += val >>> 8;
  337. val += val >>> 16;
  338. return val & 0xff;
  339. }
  340. public Object clone() {
  341. return new StateInfo(this);
  342. }
  343. }
  344. }