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