1. /*
  2. * @(#)WindowsTextUI.java 1.10 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.windows;
  8. import java.awt.Color;
  9. import java.awt.Graphics;
  10. import java.awt.Rectangle;
  11. import java.awt.Shape;
  12. import javax.swing.plaf.basic.*;
  13. import javax.swing.*;
  14. import javax.swing.plaf.TextUI;
  15. import javax.swing.plaf.UIResource;
  16. import javax.swing.text.*;
  17. /**
  18. * Windows text rendering.
  19. * <p>
  20. * <strong>Warning:</strong>
  21. * Serialized objects of this class will not be compatible with
  22. * future Swing releases. The current serialization support is appropriate
  23. * for short term storage or RMI between applications running the same
  24. * version of Swing. A future release of Swing will provide support for
  25. * long term persistence.
  26. */
  27. public abstract class WindowsTextUI extends BasicTextUI {
  28. /**
  29. * Creates the object to use for a caret. By default an
  30. * instance of WindowsCaret is created. This method
  31. * can be redefined to provide something else that implements
  32. * the InputPosition interface or a subclass of DefaultCaret.
  33. *
  34. * @return the caret object
  35. */
  36. protected Caret createCaret() {
  37. return new WindowsCaret();
  38. }
  39. /* public */
  40. static LayeredHighlighter.LayerPainter WindowsPainter = new WindowsHighlightPainter(null);
  41. /* public */
  42. static class WindowsCaret extends DefaultCaret
  43. implements UIResource {
  44. /**
  45. * Gets the painter for the Highlighter.
  46. *
  47. * @return the painter
  48. */
  49. protected Highlighter.HighlightPainter getSelectionPainter() {
  50. return WindowsTextUI.WindowsPainter;
  51. }
  52. }
  53. /* public */
  54. static class WindowsHighlightPainter extends
  55. DefaultHighlighter.DefaultHighlightPainter {
  56. WindowsHighlightPainter(Color c) {
  57. super(c);
  58. }
  59. // --- HighlightPainter methods ---------------------------------------
  60. /**
  61. * Paints a highlight.
  62. *
  63. * @param g the graphics context
  64. * @param offs0 the starting model offset >= 0
  65. * @param offs1 the ending model offset >= offs1
  66. * @param bounds the bounding box for the highlight
  67. * @param c the editor
  68. */
  69. public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
  70. Rectangle alloc = bounds.getBounds();
  71. try {
  72. // --- determine locations ---
  73. TextUI mapper = c.getUI();
  74. Rectangle p0 = mapper.modelToView(c, offs0);
  75. Rectangle p1 = mapper.modelToView(c, offs1);
  76. // --- render ---
  77. Color color = getColor();
  78. if (color == null) {
  79. g.setColor(c.getSelectionColor());
  80. }
  81. else {
  82. g.setColor(color);
  83. }
  84. boolean firstIsDot = false;
  85. boolean secondIsDot = false;
  86. if (c.isEditable()) {
  87. int dot = c.getCaretPosition();
  88. firstIsDot = (offs0 == dot);
  89. secondIsDot = (offs1 == dot);
  90. }
  91. if (p0.y == p1.y) {
  92. // same line, render a rectangle
  93. Rectangle r = p0.union(p1);
  94. if (r.width > 0) {
  95. if (firstIsDot) {
  96. r.x++;
  97. r.width--;
  98. }
  99. else if (secondIsDot) {
  100. r.width--;
  101. }
  102. }
  103. g.fillRect(r.x, r.y, r.width, r.height);
  104. } else {
  105. // different lines
  106. int p0ToMarginWidth = alloc.x + alloc.width - p0.x;
  107. if (firstIsDot && p0ToMarginWidth > 0) {
  108. p0.x++;
  109. p0ToMarginWidth--;
  110. }
  111. g.fillRect(p0.x, p0.y, p0ToMarginWidth, p0.height);
  112. if ((p0.y + p0.height) != p1.y) {
  113. g.fillRect(alloc.x, p0.y + p0.height, alloc.width,
  114. p1.y - (p0.y + p0.height));
  115. }
  116. if (secondIsDot && p1.x > alloc.x) {
  117. p1.x--;
  118. }
  119. g.fillRect(alloc.x, p1.y, (p1.x - alloc.x), p1.height);
  120. }
  121. } catch (BadLocationException e) {
  122. // can't render
  123. }
  124. }
  125. // --- LayerPainter methods ----------------------------
  126. /**
  127. * Paints a portion of a highlight.
  128. *
  129. * @param g the graphics context
  130. * @param offs0 the starting model offset >= 0
  131. * @param offs1 the ending model offset >= offs1
  132. * @param bounds the bounding box of the view, which is not
  133. * necessarily the region to paint.
  134. * @param c the editor
  135. * @param view View painting for
  136. * @return region drawing occured in
  137. */
  138. public Shape paintLayer(Graphics g, int offs0, int offs1,
  139. Shape bounds, JTextComponent c, View view) {
  140. Color color = getColor();
  141. if (color == null) {
  142. g.setColor(c.getSelectionColor());
  143. }
  144. else {
  145. g.setColor(color);
  146. }
  147. boolean firstIsDot = false;
  148. boolean secondIsDot = false;
  149. if (c.isEditable()) {
  150. int dot = c.getCaretPosition();
  151. firstIsDot = (offs0 == dot);
  152. secondIsDot = (offs1 == dot);
  153. }
  154. if (offs0 == view.getStartOffset() &&
  155. offs1 == view.getEndOffset()) {
  156. // Contained in view, can just use bounds.
  157. Rectangle alloc;
  158. if (bounds instanceof Rectangle) {
  159. alloc = (Rectangle)bounds;
  160. }
  161. else {
  162. alloc = bounds.getBounds();
  163. }
  164. if (firstIsDot && alloc.width > 0) {
  165. g.fillRect(alloc.x + 1, alloc.y, alloc.width - 1,
  166. alloc.height);
  167. }
  168. else if (secondIsDot && alloc.width > 0) {
  169. g.fillRect(alloc.x, alloc.y, alloc.width - 1,
  170. alloc.height);
  171. }
  172. else {
  173. g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height);
  174. }
  175. return alloc;
  176. }
  177. else {
  178. // Should only render part of View.
  179. try {
  180. // --- determine locations ---
  181. Shape shape = view.modelToView(offs0, Position.Bias.Forward,
  182. offs1,Position.Bias.Backward,
  183. bounds);
  184. Rectangle r = (shape instanceof Rectangle) ?
  185. (Rectangle)shape : shape.getBounds();
  186. if (firstIsDot && r.width > 0) {
  187. g.fillRect(r.x + 1, r.y, r.width - 1, r.height);
  188. }
  189. else if (secondIsDot && r.width > 0) {
  190. g.fillRect(r.x, r.y, r.width - 1, r.height);
  191. }
  192. else {
  193. g.fillRect(r.x, r.y, r.width, r.height);
  194. }
  195. return r;
  196. } catch (BadLocationException e) {
  197. // can't render
  198. }
  199. }
  200. // Only if exception
  201. return null;
  202. }
  203. }
  204. }