blob: f11f5597c7cd88c3bd0829173b4bfb0cead6ca46 [file] [log] [blame]
/*
* Copyright 1995-2003 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.awt.motif;
import java.awt.*;
import java.awt.peer.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.awt.event.TextEvent;
import java.awt.im.InputMethodRequests;
public class MTextFieldPeer extends MComponentPeer implements TextFieldPeer {
native void pCreate(MComponentPeer parent);
private boolean firstChangeSkipped;
/**
* Initialize JNI field and method IDs
*/
private static native void initIDs();
static {
initIDs();
}
void create(MComponentPeer parent) {
firstChangeSkipped = false;
pCreate(parent);
}
void initialize() {
int start, end;
TextField txt = (TextField)target;
setText(txt.getText());
if (txt.echoCharIsSet()) {
setEchoChar(txt.getEchoChar());
}
start = txt.getSelectionStart();
end = txt.getSelectionEnd();
if (end > start) {
select(start, end);
} else {
setCaretPosition(start);
}
if (!target.isBackgroundSet()) {
// This is a way to set the background color of the TextArea
// without calling setBackground - go through native C code
setTargetBackground(SystemColor.text);
}
if (!target.isForegroundSet()) {
target.setForeground(SystemColor.textText);
}
setEditable(txt.isEditable());
// oldSelectionStart = -1; // accessibility support
// oldSelectionEnd = -1; // accessibility support
super.initialize();
}
public MTextFieldPeer(TextField target) {
super(target);
}
public void setEditable(boolean editable) {
pSetEditable(editable);
/* 4136955 - Calling setBackground() here works around an Xt
* bug by forcing Xt to flush an internal widget cache
*/
setBackground(target.getBackground());
}
public native void pSetEditable(boolean editable);
public native void select(int selStart, int selEnd);
public native int getSelectionStart();
public native int getSelectionEnd();
public native void setText(String l);
public native void insertReplaceText(String l);
public native void preDispose();
public native String getText();
public native void setEchoChar(char c);
public native void setFont(Font f);
public native void setCaretPosition(int pos);
public native int getCaretPosition();
// CDE/Motif defaults: margin=5, shadow=2, highlight=1 -- times 2.
// Should have asked the widgets for correct values (see MTextAreaPeer).
private static final int padding = 16;
public Dimension getMinimumSize() {
FontMetrics fm = getFontMetrics(target.getFont());
return new Dimension(fm.stringWidth(((TextField)target).getText())+20,
fm.getMaxDescent() + fm.getMaxAscent() + padding);
}
public Dimension getPreferredSize(int cols) {
return getMinimumSize(cols);
}
public Dimension getMinimumSize(int cols) {
FontMetrics fm = getFontMetrics(target.getFont());
return new Dimension(fm.charWidth('0') * cols + 20,
fm.getMaxDescent() + fm.getMaxAscent() + padding);
}
public boolean isFocusable() {
return true;
}
// NOTE: This method is called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void action(final long when, final int modifiers) {
MToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
((TextField)target).getText(), when,
modifiers));
}
});
}
protected void disposeImpl() {
preDispose();
super.disposeImpl();
}
/*
* Post a new TextEvent when the value of a text component changes.
*/
public void valueChanged() {
postEvent(new TextEvent(target, TextEvent.TEXT_VALUE_CHANGED));
}
// Called from native widget when paste key is pressed and we
// already own the selection (prevents Motif from hanging while
// waiting for the selection)
//
// NOTE: This method is called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void pasteFromClipboard() {
Clipboard clipboard = target.getToolkit().getSystemClipboard();
Transferable content = clipboard.getContents(this);
if (content != null) {
try {
String data = (String)(content.getTransferData(DataFlavor.stringFlavor));
insertReplaceText(data);
} catch (Exception e) {
}
}
}
/*
* Print the native component by rendering the Motif look ourselves.
* ToDo(aim): needs to query native motif for more accurate size and
* color information, left text offset, and selected text.
*/
public final static int BORDER = 2;
public final static int MARGIN = 4;
public void print(Graphics g) {
TextField txt = (TextField)target;
Dimension d = txt.size();
int w = d.width - (2 * BORDER);
int h = d.height - (2 * BORDER);
Color bg = txt.getBackground();
Color fg = txt.getForeground();
Color highlight = bg.brighter();
String text = txt.getText();
int moved = 0;
int selStart = 0;
int selEnd = 0;
g.setFont(txt.getFont());
g.setColor(txt.isEditable() ? highlight : bg);
g.fillRect(BORDER, BORDER, w, h);
g.setColor(bg);
//g.drawRect(0, 0, d.width-1, d.height-1);
draw3DRect(g, bg, 1, 1, d.width-3, d.height-3, false);
if (text != null) {
g.clipRect(BORDER, MARGIN, w, d.height - (2 * MARGIN));
FontMetrics fm = g.getFontMetrics();
w = d.width - BORDER;
h = d.height - (2 * MARGIN);
int xs = pos2x(selStart) - moved;
int xe = pos2x(selEnd) - moved;
if ((xs < MARGIN) && (xe > w)) {
g.setColor(highlight);
g.fillRect(BORDER, MARGIN, w - BORDER, h);
} else {
g.setColor(bg);
//g.fillRect(BORDER, MARGIN, w - BORDER, h);
if ((xs >= MARGIN) && (xs <= w)) {
g.setColor(highlight); // selected text
if (xe > w) {
g.fillRect(xs, MARGIN, w - xs, h);
} else if (xs == xe) {
//g.fillRect(xs, MARGIN, 1, h);
} else {
g.fillRect(xs, MARGIN, xe - xs, h);
}
} else if ((xe >= MARGIN) && (xe <= w)) {
g.setColor(highlight);
g.fillRect(BORDER, MARGIN, xe - BORDER, h);
}
}
g.setColor(fg);
int x = MARGIN - moved;
char echoChar = txt.getEchoChar();
if (echoChar == 0) {
g.drawString(text, x, BORDER + MARGIN + fm.getMaxAscent());
} else {
char data[] = new char[text.length()];
for (int i = 0 ; i < data.length ; i++) {
data[i] = echoChar;
}
g.drawChars(data, 0, data.length, x,
BORDER + MARGIN + fm.getMaxAscent());
}
}
target.print(g);
}
int pos2x(int pos) {
TextField txt = (TextField)target;
FontMetrics fm = getFontMetrics(txt.getFont());
int x = MARGIN, widths[] = fm.getWidths();
String text = txt.getText();
char echoChar = txt.getEchoChar();
if (echoChar == 0) {
for (int i = 0 ; i < pos ; i++) {
x += widths[text.charAt(i)];
}
} else {
x += widths[echoChar] * pos;
}
return x;
}
/**
* DEPRECATED
*/
public void setEchoCharacter(char c) {
setEchoChar(c);
}
/**
* DEPRECATED
*/
public Dimension minimumSize() {
return getMinimumSize();
}
/**
* DEPRECATED
*/
public Dimension minimumSize(int cols) {
return getMinimumSize(cols);
}
/**
* DEPRECATED
*/
public Dimension preferredSize(int cols) {
return getPreferredSize(cols);
}
void pShow(){
super.pShow();
notifyTextComponentChange(true);
}
void pHide(){
notifyTextComponentChange(false);
super.pHide();
}
void pDispose(){
notifyTextComponentChange(false);
super.pDispose();
}
public InputMethodRequests getInputMethodRequests() {
return null;
}
//
// Accessibility support
//
// stub functions: to be fully implemented in a future release
public int getIndexAtPoint(int x, int y) { return -1; }
public Rectangle getCharacterBounds(int i) { return null; }
public long filterEvents(long mask) { return 0; }
/* To be fully implemented in a future release
int oldSelectionStart;
int oldSelectionEnd;
public native int getIndexAtPoint(int x, int y);
public native Rectangle getCharacterBounds(int i);
public native long filterEvents(long mask);
/**
* Handle a change in the text selection endpoints
* (Note: could be simply a change in the caret location)
*
public void selectionValuesChanged(int start, int end) {
return; // Need to write implemetation of this.
}
*/
}