001/* PasswordView.java -- 
002 Copyright (C) 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING.  If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library.  Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module.  An independent module is a module which is not derived from
033 or based on this library.  If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so.  If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039package javax.swing.text;
040
041import java.awt.Color;
042import java.awt.FontMetrics;
043import java.awt.Graphics;
044import java.awt.Rectangle;
045import java.awt.Shape;
046
047import javax.swing.JPasswordField;
048
049public class PasswordView
050  extends FieldView
051{
052  /**
053   * Buffer for putting the echo char into it and
054   * then using it to draw it into the view.
055   */
056  private char[] oneCharBuffer = new char[1];
057
058  public PasswordView(Element elem)
059  {
060    super(elem);
061  }
062
063  /**
064   * Draws one echo character at a given position.
065   *
066   * @param g the <code>Graphics</code> object to draw to
067   * @param x the x-position
068   * @param y the y-position
069   * @param ch the echo character
070   *
071   * @return the next x position right of the drawn character
072   */
073  protected int drawEchoCharacter(Graphics g, int x, int y, char ch)
074  {
075    // Update font metrics.
076    updateMetrics();
077
078    // Draw character.
079    oneCharBuffer[0] = ch;
080    g.drawChars(oneCharBuffer, 0, 1, x, y);
081
082    // Return new x position right of drawn character.
083    return x + metrics.charWidth(ch);
084  }
085
086  private char getEchoChar()
087  {
088    char ch = ((JPasswordField) getContainer()).getEchoChar();
089
090    if (ch == 0)
091      ch = '*';
092
093    return ch;
094  }
095
096  /**
097   * Draws selected text at a given position.
098   *
099   * @param g the <code>Graphics</code> object to draw to
100   * @param x the x-position
101   * @param y the y-position
102   * @param p0 the position of the first character to draw
103   * @param p1 the position of the first character not to draw
104   *
105   * @return the next x position right of the drawn character
106   */
107  protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
108    throws BadLocationException
109  {
110    // Update font metrics.
111    updateMetrics();
112
113    // Get echo character.
114    char ch = getEchoChar();
115
116    // Set color for selected text.
117    g.setColor(selectedColor);
118    g.setColor(Color.BLACK);
119
120    // Draw echo character using drawEchoCharacter() method.
121    for (int index = p0; index < p1; ++index)
122      x = drawEchoCharacter(g, x, y, ch);
123    return x;
124  }
125
126  /**
127   * Draws unselected text at a given position.
128   *
129   * @param g the <code>Graphics</code> object to draw to
130   * @param x the x-position of the start of the baseline
131   * @param y the y-position of the start of the baseline
132   * @param p0 the position of the first character to draw
133   * @param p1 the position of the first character not to draw
134   *
135   * @return the next x position right of the drawn character
136   */
137  protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
138    throws BadLocationException
139  {
140    // Update font metrics.
141    updateMetrics();
142
143    // Get echo character.
144    char ch = getEchoChar();
145
146    // Set color for unselected text.
147    g.setColor(unselectedColor);
148    g.setColor(Color.BLACK);
149
150    // Draw echo character using drawEchoCharacter() method.
151    for (int index = p0; index < p1; ++index)
152      x = drawEchoCharacter(g, x, y, ch);
153    return x;
154  }
155
156  /**
157   * Determines the preferred span for this view along an axis.
158   * 
159   * @param axis to get the preferred span of
160   * @return the preferred span of the axis
161   */
162  public float getPreferredSpan(int axis)
163  {
164    if (axis != X_AXIS && axis != Y_AXIS)
165      throw new IllegalArgumentException();
166
167    FontMetrics fm = getFontMetrics();
168
169    if (axis == Y_AXIS)
170        return fm.getHeight();
171
172    String text;
173    Element elem = getElement();
174
175    try
176      {
177        text = elem.getDocument().getText(elem.getStartOffset(),
178                                          elem.getEndOffset());
179      }
180    catch (BadLocationException e)
181      {
182        // This should never happen.
183        text = "";
184      }
185    return fm.stringWidth(text);
186  }
187
188  /**
189   * Provides a mapping from the document model coordinate space to the
190   * coordinate space of the view mapped to it.
191   *
192   * This method is overridden to provide a correct mapping with respect to the
193   * echo char and not to the real content.
194   *
195   * @param pos - the position to convert >= 0
196   * @param a - the allocated region to render into
197   * @param b - typesafe enumeration to indicate bias to a position in the model.
198   * @return the bounding box of the given position
199   * @throws BadLocationException if the given position does not 
200   * represent a valid location in the associated document
201   */
202  public Shape modelToView(int pos, Shape a, Position.Bias b)
203    throws BadLocationException
204  {
205    Shape newAlloc = adjustAllocation(a);
206
207    // Ensure metrics are up-to-date.
208    updateMetrics();
209    
210    // Get rectangle of the line containing position.
211    int lineIndex = getElement().getElementIndex(pos);
212    Rectangle rect = lineToRect(newAlloc, lineIndex);
213
214    // Get the rectangle for position.
215    Element line = getElement().getElement(lineIndex);
216    int lineStart = line.getStartOffset();
217    Segment segment = getLineBuffer();
218    segment.array = new char[pos - lineStart];
219    char echoChar = getEchoChar();
220    for (int i = 0; i < segment.array.length; ++i)
221      segment.array[i] = echoChar;
222    segment.offset = 0;
223    segment.count = segment.array.length;
224
225    int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
226                           this, lineStart);
227
228    // Calc the real rectangle.
229    rect.x += xoffset;
230    rect.width = 1;
231    rect.height = metrics.getHeight();
232
233    return rect;
234  }
235
236  /**
237   * Provides a mapping from the view coordinate space to the logical 
238   * coordinate space of the model.
239   * 
240   * @param fx - the X coordinate >= 0.0f
241   * @param fy - the Y coordinate >= 0.0f
242   * @param a - the allocated region to render into 
243   * @param bias - typesafe enumeration to indicate bias to a position in the model.
244   * @return the location within the model that best represents 
245   * the given point in the view
246   * 
247   */
248  public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
249  {
250    // FIXME: This only provides a view->model mapping for the real text
251    // content and does not respect the echo char.
252    return super.viewToModel(fx, fy, a, bias);
253  }
254}