/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.laf;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.*;
import javax.swing.text.*;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaTextPasswordFieldUI extends AquaTextFieldUI {
static final RecyclableSingleton<CapsLockSymbolPainter> capsLockPainter = new RecyclableSingletonFromDefaultConstructor<CapsLockSymbolPainter>(CapsLockSymbolPainter.class);
static CapsLockSymbolPainter getCapsLockPainter() {
return capsLockPainter.get();
}
public static ComponentUI createUI(final JComponent c) {
return new AquaTextPasswordFieldUI();
}
@Override
protected String getPropertyPrefix() {
return "PasswordField";
}
@Override
public View create(final Element elem) {
return new AquaPasswordView(elem);
}
@Override
protected void installListeners() {
super.installListeners();
getComponent().addKeyListener(getCapsLockPainter());
}
@Override
protected void uninstallListeners() {
getComponent().removeKeyListener(getCapsLockPainter());
super.uninstallListeners();
}
@Override
protected void paintBackgroundSafely(final Graphics g) {
super.paintBackgroundSafely(g);
final JTextComponent component = getComponent();
if (component == null) return;
if (!component.isFocusOwner()) return;
final boolean capsLockDown = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);
if (!capsLockDown) return;
final Rectangle bounds = component.getBounds();
getCapsLockPainter().paintBorder(component, g, bounds.x, bounds.y, bounds.width, bounds.height);
}
protected class AquaPasswordView extends PasswordView {
public AquaPasswordView(final Element elem) {
super(elem);
setupDefaultEchoCharacter();
}
protected void setupDefaultEchoCharacter() {
// this allows us to change the echo character in CoreAquaLookAndFeel.java
final Character echoChar = (Character)UIManager.getDefaults().get(getPropertyPrefix() + ".echoChar");
if (echoChar != null) {
LookAndFeel.installProperty(getComponent(), "echoChar", echoChar);
}
}
}
static class CapsLockSymbolPainter extends KeyAdapter implements Border, UIResource {
protected Shape capsLockShape;
protected Shape getCapsLockShape() {
if (capsLockShape != null) return capsLockShape;
final RoundRectangle2D rect = new RoundRectangle2D.Double(0.5, 0.5, 16, 16, 8, 8);
final GeneralPath shape = new GeneralPath(rect);
shape.setWindingRule(Path2D.WIND_EVEN_ODD);
// arrow
shape.moveTo( 8.50, 2.00);
shape.lineTo( 4.00, 7.00);
shape.lineTo( 6.25, 7.00);
shape.lineTo( 6.25, 10.25);
shape.lineTo(10.75, 10.25);
shape.lineTo(10.75, 7.00);
shape.lineTo(13.00, 7.00);
shape.lineTo( 8.50, 2.00);
// base line
shape.moveTo(10.75, 12.00);
shape.lineTo( 6.25, 12.00);
shape.lineTo( 6.25, 14.25);
shape.lineTo(10.75, 14.25);
shape.lineTo(10.75, 12.00);
return capsLockShape = shape;
}
@Override
public Insets getBorderInsets(final Component c) {
return new Insets(0, 0, 0, 0);
}
@Override
public boolean isBorderOpaque() {
return false;
}
@Override
public void paintBorder(final Component c, Graphics g, final int x, final int y, final int width, final int height) {
g = g.create(width - 23, height / 2 - 8, 18, 18);
g.setColor(UIManager.getColor("PasswordField.capsLockIconColor"));
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
((Graphics2D)g).fill(getCapsLockShape());
g.dispose();
}
@Override
public void keyPressed(final KeyEvent e) {
update(e);
}
@Override
public void keyReleased(final KeyEvent e) {
update(e);
}
void update(final KeyEvent e) {
if (KeyEvent.VK_CAPS_LOCK != e.getKeyCode()) return;
e.getComponent().repaint();
}
}
}