1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.java.swing.plaf.windows;
  27 
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import java.beans.PropertyChangeEvent;
  31 import javax.swing.plaf.*;
  32 import javax.swing.plaf.basic.BasicTextFieldUI;
  33 import javax.swing.text.*;
  34 import javax.swing.*;
  35 import javax.swing.plaf.UIResource;
  36 import sun.swing.DefaultLookup;
  37 
  38 
  39 
  40 /**
  41  * Provides the Windows look and feel for a text field.  This
  42  * is basically the following customizations to the default
  43  * look-and-feel.
  44  * <ul>
  45  * <li>The border is beveled (using the standard control color).
  46  * <li>The background is white by default.
  47  * <li>The highlight color is a dark color, blue by default.
  48  * <li>The foreground color is high contrast in the selected
  49  *  area, white by default.  The unselected foreground is black.
  50  * <li>The cursor blinks at about 1/2 second intervals.
  51  * <li>The entire value is selected when focus is gained.
  52  * <li>Shift-left-arrow and shift-right-arrow extend selection
  53  * <li>Ctrl-left-arrow and ctrl-right-arrow act like home and
  54  *   end respectively.
  55  * </ul>
  56  * <p>
  57  * <strong>Warning:</strong>
  58  * Serialized objects of this class will not be compatible with
  59  * future Swing releases.  The current serialization support is appropriate
  60  * for short term storage or RMI between applications running the same
  61  * version of Swing.  A future release of Swing will provide support for
  62  * long term persistence.
  63  *
  64  * @author  Timothy Prinzing
  65  */
  66 public class WindowsTextFieldUI extends BasicTextFieldUI
  67 {
  68     /**
  69      * Creates a UI for a JTextField.
  70      *
  71      * @param c the text field
  72      * @return the UI
  73      */
  74     public static ComponentUI createUI(JComponent c) {
  75         return new WindowsTextFieldUI();
  76     }
  77 
  78     /**
  79      * Paints a background for the view.  This will only be
  80      * called if isOpaque() on the associated component is
  81      * true.  The default is to paint the background color
  82      * of the component.
  83      *
  84      * @param g the graphics context
  85      */
  86     protected void paintBackground(Graphics g) {
  87         super.paintBackground(g);
  88     }
  89 
  90     /**
  91      * Creates the caret for a field.
  92      *
  93      * @return the caret
  94      */
  95     protected Caret createCaret() {
  96         return new WindowsFieldCaret();
  97     }
  98 
  99     /**
 100      * WindowsFieldCaret has different scrolling behavior than
 101      * DefaultCaret.
 102      */
 103     static class WindowsFieldCaret extends DefaultCaret implements UIResource {
 104 
 105         public WindowsFieldCaret() {
 106             super();
 107         }
 108 
 109         /**
 110          * Adjusts the visibility of the caret according to
 111          * the windows feel which seems to be to move the
 112          * caret out into the field by about a quarter of
 113          * a field length if not visible.
 114          */
 115         protected void adjustVisibility(Rectangle r) {
 116             SwingUtilities.invokeLater(new SafeScroller(r));
 117         }
 118 
 119         /**
 120          * Gets the painter for the Highlighter.
 121          *
 122          * @return the painter
 123          */
 124         protected Highlighter.HighlightPainter getSelectionPainter() {
 125             return WindowsTextUI.WindowsPainter;
 126         }
 127 
 128 
 129         private class SafeScroller implements Runnable {
 130             SafeScroller(Rectangle r) {
 131                 this.r = r;
 132             }
 133 
 134             public void run() {
 135                 JTextField field = (JTextField) getComponent();
 136                 if (field != null) {
 137                     TextUI ui = field.getUI();
 138                     int dot = getDot();
 139                     // PENDING: We need to expose the bias in DefaultCaret.
 140                     Position.Bias bias = Position.Bias.Forward;
 141                     Rectangle startRect = null;
 142                     try {
 143                         startRect = ui.modelToView(field, dot, bias);
 144                     } catch (BadLocationException ble) {}
 145 
 146                     Insets i = field.getInsets();
 147                     BoundedRangeModel vis = field.getHorizontalVisibility();
 148                     int x = r.x + vis.getValue() - i.left;
 149                     int quarterSpan = vis.getExtent() / 4;
 150                     if (r.x < i.left) {
 151                         vis.setValue(x - quarterSpan);
 152                     } else if (r.x + r.width > i.left + vis.getExtent()) {
 153                         vis.setValue(x - (3 * quarterSpan));
 154                     }
 155                     // If we scroll, our visual location will have changed,
 156                     // but we won't have updated our internal location as
 157                     // the model hasn't changed. This checks for the change,
 158                     // and if necessary, resets the internal location.
 159                     if (startRect != null) {
 160                         try {
 161                             Rectangle endRect;
 162                             endRect = ui.modelToView(field, dot, bias);
 163                             if (endRect != null && !endRect.equals(startRect)){
 164                                 damage(endRect);
 165                             }
 166                         } catch (BadLocationException ble) {}
 167                     }
 168                 }
 169             }
 170 
 171             private Rectangle r;
 172         }
 173     }
 174 
 175 }