1. /*
  2. * @(#)PasswordView.java 1.13 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 javax.swing.text;
  11. import java.awt.*;
  12. import javax.swing.JPasswordField;
  13. /**
  14. * Implements a View suitable for use in JPasswordField
  15. * UI implementations. This is basically a field ui that
  16. * renders its contents as the echo character specified
  17. * in the associated component (if it can narrow the
  18. * component to a JPasswordField).
  19. *
  20. * @author Timothy Prinzing
  21. * @version 1.13 02/02/00
  22. * @see View
  23. */
  24. public class PasswordView extends FieldView {
  25. /**
  26. * Constructs a new view wrapped on an element.
  27. *
  28. * @param elem the element
  29. */
  30. public PasswordView(Element elem) {
  31. super(elem);
  32. }
  33. /**
  34. * Renders the given range in the model as normal unselected
  35. * text. This sets the foreground color and echos the characters
  36. * using the value returned by getEchoChar().
  37. *
  38. * @param g the graphics context
  39. * @param x the starting X coordinate >= 0
  40. * @param y the starting Y coordinate >= 0
  41. * @param p0 the starting offset in the model >= 0
  42. * @param p1 the ending offset in the model >= p0
  43. * @returns the X location of the end of the range >= 0
  44. * @exception BadLocationException if p0 or p1 are out of range
  45. */
  46. protected int drawUnselectedText(Graphics g, int x, int y,
  47. int p0, int p1) throws BadLocationException {
  48. Container c = getContainer();
  49. if (c instanceof JPasswordField) {
  50. JPasswordField f = (JPasswordField) c;
  51. if (! f.echoCharIsSet()) {
  52. return super.drawUnselectedText(g, x, y, p0, p1);
  53. }
  54. g.setColor(f.getForeground());
  55. char echoChar = f.getEchoChar();
  56. int n = p1 - p0;
  57. for (int i = 0; i < n; i++) {
  58. x = drawEchoCharacter(g, x, y, echoChar);
  59. }
  60. }
  61. return x;
  62. }
  63. /**
  64. * Renders the given range in the model as selected text. This
  65. * is implemented to render the text in the color specified in
  66. * the hosting component. It assumes the highlighter will render
  67. * the selected background. Uses the result of getEchoChar() to
  68. * display the characters.
  69. *
  70. * @param g the graphics context
  71. * @param x the starting X coordinate >= 0
  72. * @param y the starting Y coordinate >= 0
  73. * @param p0 the starting offset in the model >= 0
  74. * @param p1 the ending offset in the model >= p0
  75. * @returns the X location of the end of the range >= 0.
  76. * @exception BadLocationException if p0 or p1 are out of range
  77. */
  78. protected int drawSelectedText(Graphics g, int x,
  79. int y, int p0, int p1) throws BadLocationException {
  80. g.setColor(selected);
  81. Container c = getContainer();
  82. if (c instanceof JPasswordField) {
  83. JPasswordField f = (JPasswordField) c;
  84. if (! f.echoCharIsSet()) {
  85. return super.drawSelectedText(g, x, y, p0, p1);
  86. }
  87. char echoChar = f.getEchoChar();
  88. int n = p1 - p0;
  89. for (int i = 0; i < n; i++) {
  90. x = drawEchoCharacter(g, x, y, echoChar);
  91. }
  92. }
  93. return x;
  94. }
  95. /**
  96. * Renders the echo character, or whatever graphic should be used
  97. * to display the password characters. The color in the Graphics
  98. * object is set to the appropriate foreground color for selected
  99. * or unselected text.
  100. *
  101. * @param g the graphics context
  102. * @param x the starting X coordinate >= 0
  103. * @param y the starting Y coordinate >= 0
  104. * @param c the echo character
  105. * @return the updated X position >= 0
  106. */
  107. protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
  108. ONE[0] = c;
  109. g.drawChars(ONE, 0, 1, x, y);
  110. return x + g.getFontMetrics().charWidth(c);
  111. }
  112. /**
  113. * Provides a mapping from the document model coordinate space
  114. * to the coordinate space of the view mapped to it.
  115. *
  116. * @param pos the position to convert >= 0
  117. * @param a the allocated region to render into
  118. * @return the bounding box of the given position
  119. * @exception BadLocationException if the given position does not
  120. * represent a valid location in the associated document
  121. * @see View#modelToView
  122. */
  123. public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
  124. Container c = getContainer();
  125. if (c instanceof JPasswordField) {
  126. JPasswordField f = (JPasswordField) c;
  127. if (! f.echoCharIsSet()) {
  128. return super.modelToView(pos, a, b);
  129. }
  130. char echoChar = f.getEchoChar();
  131. FontMetrics m = f.getFontMetrics(f.getFont());
  132. Rectangle alloc = adjustAllocation(a).getBounds();
  133. int dx = (pos - getStartOffset()) * m.charWidth(echoChar);
  134. alloc.x += dx;
  135. alloc.width = 1;
  136. return alloc;
  137. }
  138. return null;
  139. }
  140. /**
  141. * Provides a mapping from the view coordinate space to the logical
  142. * coordinate space of the model.
  143. *
  144. * @param fx the X coordinate >= 0.0f
  145. * @param fy the Y coordinate >= 0.0f
  146. * @param a the allocated region to render into
  147. * @return the location within the model that best represents the
  148. * given point in the view
  149. * @see View#viewToModel
  150. */
  151. public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
  152. bias[0] = Position.Bias.Forward;
  153. int n = 0;
  154. Container c = getContainer();
  155. if (c instanceof JPasswordField) {
  156. JPasswordField f = (JPasswordField) c;
  157. if (! f.echoCharIsSet()) {
  158. return super.viewToModel(fx, fy, a, bias);
  159. }
  160. char echoChar = f.getEchoChar();
  161. FontMetrics m = f.getFontMetrics(f.getFont());
  162. a = adjustAllocation(a);
  163. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
  164. a.getBounds();
  165. n = ((int)fx - alloc.x) / m.charWidth(echoChar);
  166. if (n < 0) {
  167. n = 0;
  168. }
  169. else if (n > (getStartOffset() + getDocument().getLength())) {
  170. n = getDocument().getLength() - getStartOffset();
  171. }
  172. }
  173. return getStartOffset() + n;
  174. }
  175. static char[] ONE = new char[1];
  176. }