0001: /*
0002: * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package sun.awt.X11;
0027:
0028: import java.awt.*;
0029: import java.awt.peer.ComponentPeer;
0030: import java.awt.peer.TextAreaPeer;
0031: import java.awt.event.*;
0032: import javax.swing.event.DocumentListener;
0033: import javax.swing.event.DocumentEvent;
0034: import javax.swing.JTextArea;
0035: import javax.swing.JComponent;
0036: import javax.swing.JScrollPane;
0037: import javax.swing.JScrollBar;
0038: import javax.swing.plaf.ComponentUI;
0039: import com.sun.java.swing.plaf.motif.MotifTextAreaUI;
0040: import javax.swing.plaf.UIResource;
0041: import javax.swing.UIDefaults;
0042: import javax.swing.border.Border;
0043: import javax.swing.border.EmptyBorder;
0044: import javax.swing.border.CompoundBorder;
0045: import javax.swing.border.AbstractBorder;
0046: import javax.swing.JButton;
0047: import javax.swing.JViewport;
0048: import javax.swing.InputMap;
0049: import javax.swing.SwingUtilities;
0050: import javax.swing.TransferHandler;
0051: import javax.swing.plaf.basic.BasicArrowButton;
0052: import javax.swing.plaf.basic.BasicScrollBarUI;
0053: import javax.swing.plaf.basic.BasicScrollPaneUI;
0054: import java.beans.PropertyChangeEvent;
0055: import java.beans.PropertyChangeListener;
0056: import javax.swing.text.Caret;
0057: import javax.swing.text.DefaultCaret;
0058: import javax.swing.text.JTextComponent;
0059:
0060: import javax.swing.plaf.BorderUIResource;
0061: import java.awt.im.InputMethodRequests;
0062: import sun.awt.CausedFocusEvent;
0063: import sun.awt.ComponentAccessor;
0064:
0065: class XTextAreaPeer extends XComponentPeer implements TextAreaPeer {
0066: boolean editable;
0067:
0068: AWTTextPane textPane;
0069: AWTTextArea jtext;
0070:
0071: boolean firstChangeSkipped;
0072:
0073: private final JavaMouseEventHandler javaMouseEventHandler = new JavaMouseEventHandler(
0074: this );
0075:
0076: /* FIXME */
0077:
0078: public long filterEvents(long mask) {
0079: Thread.dumpStack();
0080: return 0;
0081: }
0082:
0083: /* FIXME */
0084: public Rectangle getCharacterBounds(int i) {
0085: Thread.dumpStack();
0086: return null;
0087: }
0088:
0089: public int getIndexAtPoint(int x, int y) {
0090: Thread.dumpStack();
0091: return 0;
0092: }
0093:
0094: /**
0095: * Create a Text area.
0096: */
0097: XTextAreaPeer(TextArea target) {
0098: super (target);
0099:
0100: // some initializations require that target be set even
0101: // though init(target) has not been called
0102: this .target = target;
0103:
0104: //ComponentAccessor.enableEvents(target,AWTEvent.MOUSE_WHEEL_EVENT_MASK);
0105: target.enableInputMethods(true);
0106:
0107: firstChangeSkipped = false;
0108: String text = ((TextArea) target).getText();
0109: jtext = new AWTTextArea(text, this );
0110: jtext.setWrapStyleWord(true);
0111: jtext.getDocument().addDocumentListener(jtext);
0112: XToolkit.specialPeerMap.put(jtext, this );
0113: jtext.enableInputMethods(true);
0114: textPane = new AWTTextPane(jtext, this , target.getParent());
0115:
0116: setBounds(x, y, width, height, SET_BOUNDS);
0117: textPane.setVisible(true);
0118: textPane.validate();
0119:
0120: foreground = ComponentAccessor.getForeground(target);
0121: if (foreground == null) {
0122: foreground = SystemColor.textText;
0123: }
0124: setForeground(foreground);
0125:
0126: background = ComponentAccessor.getBackground(target);
0127: if (background == null) {
0128: if (target.isEditable())
0129: background = SystemColor.text;
0130: else
0131: background = SystemColor.control;
0132: }
0133: setBackground(background);
0134:
0135: if (!target.isBackgroundSet()) {
0136: // This is a way to set the background color of the TextArea
0137: // without calling setBackground - go through reflection
0138: ComponentAccessor.setBackground(target, background);
0139: }
0140: if (!target.isForegroundSet()) {
0141: target.setForeground(SystemColor.textText);
0142: }
0143:
0144: setFont(font);
0145:
0146: int start = target.getSelectionStart();
0147: int end = target.getSelectionEnd();
0148:
0149: if (end > start) {
0150: select(start, end);
0151: }
0152: // Fix for 5100200
0153: // Restoring Motif behaviour
0154: // Since the end position of the selected text can be greater then the length of the text,
0155: // so we should set caret to max position of the text
0156: int caretPosition = Math.min(end, text.length());
0157: setCaretPosition(caretPosition);
0158:
0159: setEditable(target.isEditable());
0160:
0161: setScrollBarVisibility();
0162: // set the text of this object to the text of its target
0163: setTextImpl(target.getText()); //?? should this be setText
0164:
0165: // After this line we should not change the component's text
0166: firstChangeSkipped = true;
0167: }
0168:
0169: public void dispose() {
0170: XToolkit.specialPeerMap.remove(jtext);
0171: jtext.removeNotify();
0172: textPane.removeNotify();
0173: super .dispose();
0174: }
0175:
0176: void setScrollBarVisibility() {
0177: int visibility = ((TextArea) target).getScrollbarVisibility();
0178: jtext.setLineWrap(false);
0179:
0180: if (visibility == TextArea.SCROLLBARS_NONE) {
0181: textPane
0182: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0183: textPane
0184: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
0185: jtext.setLineWrap(true);
0186: } else if (visibility == TextArea.SCROLLBARS_BOTH) {
0187:
0188: textPane
0189: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
0190: textPane
0191: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
0192: } else if (visibility == TextArea.SCROLLBARS_VERTICAL_ONLY) {
0193: textPane
0194: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0195: textPane
0196: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
0197: jtext.setLineWrap(true);
0198: } else if (visibility == TextArea.SCROLLBARS_HORIZONTAL_ONLY) {
0199: textPane
0200: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
0201: textPane
0202: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
0203: }
0204: }
0205:
0206: /**
0207: * Compute minimum size.
0208: */
0209: public Dimension getMinimumSize() {
0210: return getMinimumSize(10, 60);
0211: }
0212:
0213: public Dimension getPreferredSize(int rows, int cols) {
0214: return getMinimumSize(rows, cols);
0215: }
0216:
0217: /**
0218: * @see java.awt.peer.TextAreaPeer
0219: */
0220:
0221: public Dimension getMinimumSize(int rows, int cols) {
0222: /* Dimension d = null;
0223: if (jtext != null) {
0224: d = jtext.getMinimumSize(rows,cols);
0225: }
0226: return d;
0227: */
0228:
0229: int vsbwidth = 0;
0230: int hsbheight = 0;
0231:
0232: JScrollBar vsb = textPane.getVerticalScrollBar();
0233: if (vsb != null) {
0234: vsbwidth = vsb.getMinimumSize().width;
0235: }
0236:
0237: JScrollBar hsb = textPane.getHorizontalScrollBar();
0238: if (hsb != null) {
0239: hsbheight = hsb.getMinimumSize().height;
0240: }
0241:
0242: Font f = jtext.getFont();
0243: FontMetrics fm = jtext.getFontMetrics(f);
0244:
0245: return new Dimension(fm.charWidth('0') * cols
0246: + /*2*XMARGIN +*/vsbwidth, fm.getHeight() * rows
0247: + /*2*YMARGIN +*/hsbheight);
0248: }
0249:
0250: public boolean isFocusable() {
0251: return true;
0252: }
0253:
0254: public void setVisible(boolean b) {
0255: super .setVisible(b);
0256: if (textPane != null)
0257: textPane.setVisible(b);
0258: }
0259:
0260: void repaintText() {
0261: jtext.repaintNow();
0262: }
0263:
0264: public void focusGained(FocusEvent e) {
0265: super .focusGained(e);
0266: jtext.forwardFocusGained(e);
0267: }
0268:
0269: public void focusLost(FocusEvent e) {
0270: super .focusLost(e);
0271: jtext.forwardFocusLost(e);
0272: }
0273:
0274: /**
0275: * Paint the component
0276: * this method is called when the repaint instruction has been used
0277: */
0278:
0279: public void repaint() {
0280: if (textPane != null) {
0281: //textPane.validate();
0282: textPane.repaint();
0283: }
0284: }
0285:
0286: public void paint(Graphics g) {
0287: if (textPane != null) {
0288: textPane.paint(g);
0289: }
0290: }
0291:
0292: public void setBounds(int x, int y, int width, int height, int op) {
0293: super .setBounds(x, y, width, height, op);
0294: if (textPane != null) {
0295: /*
0296: * Fixed 6277332, 6198290:
0297: * the coordinates is coming (to peer): relatively to closest HW parent
0298: * the coordinates is setting (to textPane): relatively to closest ANY parent
0299: * the parent of peer is target.getParent()
0300: * the parent of textPane is the same
0301: * see 6277332, 6198290 for more information
0302: */
0303: int childX = x;
0304: int childY = y;
0305: Component parent = target.getParent();
0306: // we up to heavyweight parent in order to be sure
0307: // that the coordinates of the text pane is relatively to closest parent
0308: while (parent.isLightweight()) {
0309: childX -= parent.getX();
0310: childY -= parent.getY();
0311: parent = parent.getParent();
0312: }
0313: textPane.setBounds(childX, childY, width, height);
0314: textPane.validate();
0315: }
0316: }
0317:
0318: void handleJavaKeyEvent(KeyEvent e) {
0319: ComponentAccessor.processEvent(jtext, e);
0320: }
0321:
0322: public boolean handlesWheelScrolling() {
0323: return true;
0324: }
0325:
0326: void handleJavaMouseWheelEvent(MouseWheelEvent e) {
0327: ComponentAccessor.processEvent(textPane, e);
0328: }
0329:
0330: public void handleJavaMouseEvent(MouseEvent e) {
0331: super .handleJavaMouseEvent(e);
0332: javaMouseEventHandler.handle(e);
0333: }
0334:
0335: void handleJavaInputMethodEvent(InputMethodEvent e) {
0336: if (jtext != null)
0337: jtext.processInputMethodEventPublic((InputMethodEvent) e);
0338: }
0339:
0340: /**
0341: * @see java.awt.peer.TextComponentPeer
0342: */
0343: public void select(int s, int e) {
0344: jtext.select(s, e);
0345: // Fixed 5100806
0346: // We must take care that Swing components repainted correctly
0347: jtext.repaint();
0348: }
0349:
0350: public void setBackground(Color c) {
0351: super .setBackground(c);
0352: // synchronized (getStateLock()) {
0353: // background = c;
0354: // }
0355: if (jtext != null) {
0356: jtext.setBackground(c);
0357: jtext.setSelectedTextColor(c);
0358: }
0359: // repaintText();
0360: }
0361:
0362: public void setForeground(Color c) {
0363: super .setForeground(c);
0364: // synchronized (getStateLock()) {
0365: // foreground = c;
0366: // }
0367: if (jtext != null) {
0368: jtext.setForeground(foreground);
0369: jtext.setSelectionColor(foreground);
0370: jtext.setCaretColor(foreground);
0371: }
0372: // repaintText();
0373: }
0374:
0375: public void setFont(Font f) {
0376: super .setFont(f);
0377: // synchronized (getStateLock()) {
0378: // font = f;
0379: // }
0380: if (jtext != null) {
0381: jtext.setFont(font);
0382: }
0383: textPane.validate();
0384: }
0385:
0386: /**
0387: * @see java.awt.peer.TextComponentPeer
0388: */
0389: public void setEditable(boolean editable) {
0390: this .editable = editable;
0391: if (jtext != null)
0392: jtext.setEditable(editable);
0393: repaintText();
0394: }
0395:
0396: /**
0397: * @see java.awt.peer.ComponentPeer
0398: */
0399: public void setEnabled(boolean enabled) {
0400: super .setEnabled(enabled);
0401: if (jtext != null) {
0402: jtext.setEnabled(enabled);
0403: jtext.repaint();
0404: }
0405: }
0406:
0407: /**
0408: * @see java.awt.peer.TextComponentPeer
0409: */
0410: public InputMethodRequests getInputMethodRequests() {
0411: if (jtext != null)
0412: return jtext.getInputMethodRequests();
0413: else
0414: return null;
0415: }
0416:
0417: /**
0418: * @see java.awt.peer.TextComponentPeer
0419: */
0420: public int getSelectionStart() {
0421: return jtext.getSelectionStart();
0422: }
0423:
0424: /**
0425: * @see java.awt.peer.TextComponentPeer
0426: */
0427: public int getSelectionEnd() {
0428: return jtext.getSelectionEnd();
0429: }
0430:
0431: /**
0432: * @see java.awt.peer.TextComponentPeer
0433: */
0434: public String getText() {
0435: return jtext.getText();
0436: }
0437:
0438: /**
0439: * @see java.awt.peer.TextComponentPeer
0440: */
0441: public void setText(String txt) {
0442: setTextImpl(txt);
0443: repaintText();
0444: }
0445:
0446: protected boolean setTextImpl(String txt) {
0447: if (jtext != null) {
0448: // Please note that we do not want to post an event
0449: // if setText() replaces an empty text by an empty text,
0450: // that is, if component's text remains unchanged.
0451: if (jtext.getDocument().getLength() == 0
0452: && txt.length() == 0) {
0453: return true;
0454: }
0455:
0456: // JTextArea.setText() posts two different events (remove & insert).
0457: // Since we make no differences between text events,
0458: // the document listener has to be disabled while
0459: // JTextArea.setText() is called.
0460: jtext.getDocument().removeDocumentListener(jtext);
0461: jtext.setText(txt);
0462: if (firstChangeSkipped) {
0463: postEvent(new TextEvent(target,
0464: TextEvent.TEXT_VALUE_CHANGED));
0465: }
0466: jtext.getDocument().addDocumentListener(jtext);
0467: }
0468: return true;
0469: }
0470:
0471: /**
0472: * insert the text "txt on position "pos" in the array lines
0473: * @see java.awt.peer.TextAreaPeer
0474: */
0475: public void insert(String txt, int p) {
0476: if (jtext != null) {
0477: boolean doScroll = (p >= jtext.getDocument().getLength() && jtext
0478: .getDocument().getLength() != 0);
0479: jtext.insert(txt, p);
0480: textPane.validate();
0481: if (doScroll) {
0482: JScrollBar bar = textPane.getVerticalScrollBar();
0483: if (bar != null) {
0484: bar.setValue(bar.getMaximum()
0485: - bar.getVisibleAmount());
0486: }
0487: }
0488: }
0489: }
0490:
0491: /**
0492: * replace the text between the position "s" and "e" with "txt"
0493: * @see java.awt.peer.TextAreaPeer
0494: */
0495: public void replaceRange(String txt, int s, int e) {
0496: if (jtext != null) {
0497: // JTextArea.replaceRange() posts two different events.
0498: // Since we make no differences between text events,
0499: // the document listener has to be disabled while
0500: // JTextArea.replaceRange() is called.
0501: jtext.getDocument().removeDocumentListener(jtext);
0502: jtext.replaceRange(txt, s, e);
0503: postEvent(new TextEvent(target,
0504: TextEvent.TEXT_VALUE_CHANGED));
0505: jtext.getDocument().addDocumentListener(jtext);
0506: }
0507: }
0508:
0509: /**
0510: * to be implemented.
0511: * @see java.awt.peer.TextComponentPeer
0512: */
0513: public void setCaretPosition(int position) {
0514: jtext.setCaretPosition(position);
0515: }
0516:
0517: /**
0518: * to be implemented.
0519: * @see java.awt.peer.TextComponentPeer
0520: */
0521: public int getCaretPosition() {
0522: return jtext.getCaretPosition();
0523: }
0524:
0525: /**
0526: * DEPRECATED
0527: * @see java.awt.peer.TextAreaPeer
0528: */
0529: public void insertText(String txt, int pos) {
0530: insert(txt, pos);
0531: }
0532:
0533: /**
0534: * DEPRECATED
0535: * @see java.awt.peer.TextAreaPeer
0536: */
0537: public void replaceText(String txt, int start, int end) {
0538: replaceRange(txt, start, end);
0539: }
0540:
0541: /**
0542: * DEPRECATED
0543: * @see java.awt.peer.TextAreaPeer
0544: */
0545: public Dimension minimumSize(int rows, int cols) {
0546: return getMinimumSize(rows, cols);
0547: }
0548:
0549: /**
0550: * DEPRECATED
0551: * @see java.awt.peer.TextAreaPeer
0552: */
0553: public Dimension preferredSize(int rows, int cols) {
0554: return getPreferredSize(rows, cols);
0555: }
0556:
0557: class AWTTextAreaUI extends MotifTextAreaUI {
0558: /**
0559: * Creates a UI for a JTextArea.
0560: *
0561: * @param c the text field
0562: * @return the UI
0563: */
0564: JTextArea jta;
0565:
0566: protected String getPropertyPrefix() {
0567: return "TextArea";
0568: }
0569:
0570: public void installUI(JComponent c) {
0571: super .installUI(c);
0572:
0573: jta = (JTextArea) c;
0574:
0575: JTextArea editor = jta;
0576:
0577: UIDefaults uidefaults = XToolkit.getUIDefaults();
0578:
0579: String prefix = getPropertyPrefix();
0580: Font f = editor.getFont();
0581: if ((f == null) || (f instanceof UIResource)) {
0582: editor.setFont(uidefaults.getFont(prefix + ".font"));
0583: }
0584:
0585: Color bg = editor.getBackground();
0586: if ((bg == null) || (bg instanceof UIResource)) {
0587: editor.setBackground(uidefaults.getColor(prefix
0588: + ".background"));
0589: }
0590:
0591: Color fg = editor.getForeground();
0592: if ((fg == null) || (fg instanceof UIResource)) {
0593: editor.setForeground(uidefaults.getColor(prefix
0594: + ".foreground"));
0595: }
0596:
0597: Color color = editor.getCaretColor();
0598: if ((color == null) || (color instanceof UIResource)) {
0599: editor.setCaretColor(uidefaults.getColor(prefix
0600: + ".caretForeground"));
0601: }
0602:
0603: Color s = editor.getSelectionColor();
0604: if ((s == null) || (s instanceof UIResource)) {
0605: editor.setSelectionColor(uidefaults.getColor(prefix
0606: + ".selectionBackground"));
0607: }
0608:
0609: Color sfg = editor.getSelectedTextColor();
0610: if ((sfg == null) || (sfg instanceof UIResource)) {
0611: editor.setSelectedTextColor(uidefaults.getColor(prefix
0612: + ".selectionForeground"));
0613: }
0614:
0615: Color dfg = editor.getDisabledTextColor();
0616: if ((dfg == null) || (dfg instanceof UIResource)) {
0617: editor.setDisabledTextColor(uidefaults.getColor(prefix
0618: + ".inactiveForeground"));
0619: }
0620:
0621: Border b = new BevelBorder(false,
0622: SystemColor.controlDkShadow,
0623: SystemColor.controlLtHighlight);
0624: editor
0625: .setBorder(new BorderUIResource.CompoundBorderUIResource(
0626: b, new EmptyBorder(2, 2, 2, 2)));
0627:
0628: Insets margin = editor.getMargin();
0629: if (margin == null || margin instanceof UIResource) {
0630: editor.setMargin(uidefaults.getInsets(prefix
0631: + ".margin"));
0632: }
0633: }
0634:
0635: protected void installKeyboardActions() {
0636: super .installKeyboardActions();
0637:
0638: JTextComponent comp = getComponent();
0639:
0640: UIDefaults uidefaults = XToolkit.getUIDefaults();
0641:
0642: String prefix = getPropertyPrefix();
0643:
0644: InputMap map = (InputMap) uidefaults.get(prefix
0645: + ".focusInputMap");
0646:
0647: if (map != null) {
0648: SwingUtilities.replaceUIInputMap(comp,
0649: JComponent.WHEN_FOCUSED, map);
0650: }
0651: }
0652:
0653: protected Caret createCaret() {
0654: return new XAWTCaret();
0655: }
0656: }
0657:
0658: // TODO : fix this duplicate code
0659: class XAWTCaret extends DefaultCaret {
0660: public void focusGained(FocusEvent e) {
0661: super .focusGained(e);
0662: getComponent().repaint();
0663: }
0664:
0665: public void focusLost(FocusEvent e) {
0666: super .focusLost(e);
0667: getComponent().repaint();
0668: }
0669:
0670: // Fix for 5100950: textarea.getSelectedText() returns the de-selected text, on XToolkit
0671: // Restoring Motif behaviour
0672: // If the text is unhighlighted then we should sets the selection range to zero
0673: public void setSelectionVisible(boolean vis) {
0674: if (vis) {
0675: super .setSelectionVisible(vis);
0676: } else {
0677: // In order to de-select the selection
0678: setDot(getDot());
0679: }
0680: }
0681: }
0682:
0683: class XAWTScrollBarButton extends BasicArrowButton {
0684: UIDefaults uidefaults = XToolkit.getUIDefaults();
0685: private Color darkShadow = SystemColor.controlShadow;
0686: private Color lightShadow = SystemColor.controlLtHighlight;
0687: private Color buttonBack = uidefaults
0688: .getColor("ScrollBar.track");
0689:
0690: public XAWTScrollBarButton(int direction) {
0691: super (direction);
0692:
0693: switch (direction) {
0694: case NORTH:
0695: case SOUTH:
0696: case EAST:
0697: case WEST:
0698: this .direction = direction;
0699: break;
0700: default:
0701: throw new IllegalArgumentException("invalid direction");
0702: }
0703:
0704: setRequestFocusEnabled(false);
0705: setOpaque(true);
0706: setBackground(uidefaults.getColor("ScrollBar.thumb"));
0707: setForeground(uidefaults.getColor("ScrollBar.foreground"));
0708: }
0709:
0710: public Dimension getPreferredSize() {
0711: switch (direction) {
0712: case NORTH:
0713: case SOUTH:
0714: return new Dimension(11, 12);
0715: case EAST:
0716: case WEST:
0717: default:
0718: return new Dimension(12, 11);
0719: }
0720: }
0721:
0722: public Dimension getMinimumSize() {
0723: return getPreferredSize();
0724: }
0725:
0726: public Dimension getMaximumSize() {
0727: return getPreferredSize();
0728: }
0729:
0730: public boolean isFocusTraversable() {
0731: return false;
0732: }
0733:
0734: public void paint(Graphics g) {
0735: int w = getWidth();
0736: int h = getHeight();
0737:
0738: if (isOpaque()) {
0739: g.setColor(buttonBack);
0740: g.fillRect(0, 0, w, h);
0741: }
0742:
0743: boolean isPressed = getModel().isPressed();
0744: Color lead = (isPressed) ? darkShadow : lightShadow;
0745: Color trail = (isPressed) ? lightShadow : darkShadow;
0746: Color fill = getBackground();
0747:
0748: int cx = w / 2;
0749: int cy = h / 2;
0750: int s = Math.min(w, h);
0751:
0752: switch (direction) {
0753: case NORTH:
0754: g.setColor(lead);
0755: g.drawLine(cx, 0, cx, 0);
0756: for (int x = cx - 1, y = 1, dx = 1; y <= s - 2; y += 2) {
0757: g.setColor(lead);
0758: g.drawLine(x, y, x, y);
0759: if (y >= (s - 2)) {
0760: g.drawLine(x, y + 1, x, y + 1);
0761: }
0762: g.setColor(fill);
0763: g.drawLine(x + 1, y, x + dx, y);
0764: if (y < (s - 2)) {
0765: g.drawLine(x, y + 1, x + dx + 1, y + 1);
0766: }
0767: g.setColor(trail);
0768: g.drawLine(x + dx + 1, y, x + dx + 1, y);
0769: if (y >= (s - 2)) {
0770: g.drawLine(x + 1, y + 1, x + dx + 1, y + 1);
0771: }
0772: dx += 2;
0773: x -= 1;
0774: }
0775: break;
0776:
0777: case SOUTH:
0778: g.setColor(trail);
0779: g.drawLine(cx, s, cx, s);
0780: for (int x = cx - 1, y = s - 1, dx = 1; y >= 1; y -= 2) {
0781: g.setColor(lead);
0782: g.drawLine(x, y, x, y);
0783: if (y <= 2) {
0784: g.drawLine(x, y - 1, x + dx + 1, y - 1);
0785: }
0786: g.setColor(fill);
0787: g.drawLine(x + 1, y, x + dx, y);
0788: if (y > 2) {
0789: g.drawLine(x, y - 1, x + dx + 1, y - 1);
0790: }
0791: g.setColor(trail);
0792: g.drawLine(x + dx + 1, y, x + dx + 1, y);
0793:
0794: dx += 2;
0795: x -= 1;
0796: }
0797: break;
0798:
0799: case EAST:
0800: g.setColor(lead);
0801: g.drawLine(s, cy, s, cy);
0802: for (int y = cy - 1, x = s - 1, dy = 1; x >= 1; x -= 2) {
0803: g.setColor(lead);
0804: g.drawLine(x, y, x, y);
0805: if (x <= 2) {
0806: g.drawLine(x - 1, y, x - 1, y + dy + 1);
0807: }
0808: g.setColor(fill);
0809: g.drawLine(x, y + 1, x, y + dy);
0810: if (x > 2) {
0811: g.drawLine(x - 1, y, x - 1, y + dy + 1);
0812: }
0813: g.setColor(trail);
0814: g.drawLine(x, y + dy + 1, x, y + dy + 1);
0815:
0816: dy += 2;
0817: y -= 1;
0818: }
0819: break;
0820:
0821: case WEST:
0822: g.setColor(trail);
0823: g.drawLine(0, cy, 0, cy);
0824: for (int y = cy - 1, x = 1, dy = 1; x <= s - 2; x += 2) {
0825: g.setColor(lead);
0826: g.drawLine(x, y, x, y);
0827: if (x >= (s - 2)) {
0828: g.drawLine(x + 1, y, x + 1, y);
0829: }
0830: g.setColor(fill);
0831: g.drawLine(x, y + 1, x, y + dy);
0832: if (x < (s - 2)) {
0833: g.drawLine(x + 1, y, x + 1, y + dy + 1);
0834: }
0835: g.setColor(trail);
0836: g.drawLine(x, y + dy + 1, x, y + dy + 1);
0837: if (x >= (s - 2)) {
0838: g.drawLine(x + 1, y + 1, x + 1, y + dy + 1);
0839: }
0840: dy += 2;
0841: y -= 1;
0842: }
0843: break;
0844: }
0845: }
0846: }
0847:
0848: class XAWTScrollBarUI extends BasicScrollBarUI {
0849: public XAWTScrollBarUI() {
0850: super ();
0851: }
0852:
0853: protected void installDefaults() {
0854: super .installDefaults();
0855: scrollbar.setBorder(new BevelBorder(false,
0856: SystemColor.controlDkShadow,
0857: SystemColor.controlLtHighlight));
0858: }
0859:
0860: protected void configureScrollBarColors() {
0861: UIDefaults uidefaults = XToolkit.getUIDefaults();
0862: Color bg = scrollbar.getBackground();
0863: if (bg == null || bg instanceof UIResource) {
0864: scrollbar.setBackground(uidefaults
0865: .getColor("ScrollBar.background"));
0866: }
0867:
0868: Color fg = scrollbar.getForeground();
0869: if (fg == null || fg instanceof UIResource) {
0870: scrollbar.setForeground(uidefaults
0871: .getColor("ScrollBar.foreground"));
0872: }
0873:
0874: thumbHighlightColor = uidefaults
0875: .getColor("ScrollBar.thumbHighlight");
0876: thumbLightShadowColor = uidefaults
0877: .getColor("ScrollBar.thumbShadow");
0878: thumbDarkShadowColor = uidefaults
0879: .getColor("ScrollBar.thumbDarkShadow");
0880: thumbColor = uidefaults.getColor("ScrollBar.thumb");
0881: trackColor = uidefaults.getColor("ScrollBar.track");
0882:
0883: trackHighlightColor = uidefaults
0884: .getColor("ScrollBar.trackHighlight");
0885:
0886: }
0887:
0888: protected JButton createDecreaseButton(int orientation) {
0889: JButton b = new XAWTScrollBarButton(orientation);
0890: return b;
0891:
0892: }
0893:
0894: protected JButton createIncreaseButton(int orientation) {
0895: JButton b = new XAWTScrollBarButton(orientation);
0896: return b;
0897: }
0898:
0899: public JButton getDecreaseButton() {
0900: return decrButton;
0901: }
0902:
0903: public JButton getIncreaseButton() {
0904: return incrButton;
0905: }
0906:
0907: public void paint(Graphics g, JComponent c) {
0908: paintTrack(g, c, getTrackBounds());
0909: Rectangle thumbBounds = getThumbBounds();
0910: paintThumb(g, c, thumbBounds);
0911: }
0912:
0913: public void paintThumb(Graphics g, JComponent c,
0914: Rectangle thumbBounds) {
0915: if (!scrollbar.isEnabled()) {
0916: return;
0917: }
0918:
0919: if (thumbBounds.isEmpty())
0920: thumbBounds = getTrackBounds();
0921:
0922: int w = thumbBounds.width;
0923: int h = thumbBounds.height;
0924:
0925: g.translate(thumbBounds.x, thumbBounds.y);
0926: g.setColor(thumbColor);
0927: g.fillRect(0, 0, w - 1, h - 1);
0928:
0929: g.setColor(thumbHighlightColor);
0930: g.drawLine(0, 0, 0, h - 1);
0931: g.drawLine(1, 0, w - 1, 0);
0932:
0933: g.setColor(thumbLightShadowColor);
0934: g.drawLine(1, h - 1, w - 1, h - 1);
0935: g.drawLine(w - 1, 1, w - 1, h - 2);
0936:
0937: g.translate(-thumbBounds.x, -thumbBounds.y);
0938: }
0939: }
0940:
0941: class AWTTextArea extends JTextArea implements DocumentListener {
0942: boolean isFocused = false;
0943: XTextAreaPeer peer;
0944:
0945: public AWTTextArea(String text, XTextAreaPeer peer) {
0946: super (text);
0947: setFocusable(false);
0948: this .peer = peer;
0949: }
0950:
0951: public void insertUpdate(DocumentEvent e) {
0952: if (peer != null) {
0953: peer.postEvent(new TextEvent(peer.target,
0954: TextEvent.TEXT_VALUE_CHANGED));
0955: }
0956: }
0957:
0958: public void removeUpdate(DocumentEvent e) {
0959: if (peer != null) {
0960: peer.postEvent(new TextEvent(peer.target,
0961: TextEvent.TEXT_VALUE_CHANGED));
0962: }
0963: }
0964:
0965: public void changedUpdate(DocumentEvent e) {
0966: if (peer != null) {
0967: peer.postEvent(new TextEvent(peer.target,
0968: TextEvent.TEXT_VALUE_CHANGED));
0969: }
0970: }
0971:
0972: void forwardFocusGained(FocusEvent e) {
0973: isFocused = true;
0974: FocusEvent fe = CausedFocusEvent.retarget(e, this );
0975: super .processFocusEvent(fe);
0976: }
0977:
0978: void forwardFocusLost(FocusEvent e) {
0979: isFocused = false;
0980: FocusEvent fe = CausedFocusEvent.retarget(e, this );
0981: super .processFocusEvent(fe);
0982: }
0983:
0984: public boolean hasFocus() {
0985: return isFocused;
0986: }
0987:
0988: public void repaintNow() {
0989: paintImmediately(getBounds());
0990: }
0991:
0992: public void processMouseEventPublic(MouseEvent e) {
0993: processMouseEvent(e);
0994: }
0995:
0996: public void processMouseMotionEventPublic(MouseEvent e) {
0997: processMouseMotionEvent(e);
0998: }
0999:
1000: public void processInputMethodEventPublic(InputMethodEvent e) {
1001: processInputMethodEvent(e);
1002: }
1003:
1004: public void updateUI() {
1005: ComponentUI ui = new AWTTextAreaUI();
1006: setUI(ui);
1007: }
1008:
1009: // Fix for 4915454 - override the default implementation to avoid
1010: // loading SystemFlavorMap and associated classes.
1011: public void setTransferHandler(TransferHandler newHandler) {
1012: TransferHandler oldHandler = (TransferHandler) getClientProperty(XTextTransferHelper
1013: .getTransferHandlerKey());
1014: putClientProperty(XTextTransferHelper
1015: .getTransferHandlerKey(), newHandler);
1016:
1017: firePropertyChange("transferHandler", oldHandler,
1018: newHandler);
1019: }
1020: }
1021:
1022: class XAWTScrollPaneUI extends BasicScrollPaneUI {
1023: private final Border vsbMarginBorderR = new EmptyBorder(0, 2,
1024: 0, 0);
1025: private final Border vsbMarginBorderL = new EmptyBorder(0, 0,
1026: 0, 2);
1027: private final Border hsbMarginBorder = new EmptyBorder(2, 0, 0,
1028: 0);
1029:
1030: private Border vsbBorder;
1031: private Border hsbBorder;
1032:
1033: private PropertyChangeListener propertyChangeHandler;
1034:
1035: protected void installListeners(JScrollPane scrollPane) {
1036: super .installListeners(scrollPane);
1037: propertyChangeHandler = createPropertyChangeHandler();
1038: scrollPane.addPropertyChangeListener(propertyChangeHandler);
1039: }
1040:
1041: public void paint(Graphics g, JComponent c) {
1042: Border vpBorder = scrollpane.getViewportBorder();
1043: if (vpBorder != null) {
1044: Rectangle r = scrollpane.getViewportBorderBounds();
1045: vpBorder.paintBorder(scrollpane, g, r.x, r.y, r.width,
1046: r.height);
1047: }
1048: }
1049:
1050: protected void uninstallListeners(JScrollPane scrollPane) {
1051: super .uninstallListeners(scrollPane);
1052: scrollPane
1053: .removePropertyChangeListener(propertyChangeHandler);
1054: }
1055:
1056: private PropertyChangeListener createPropertyChangeHandler() {
1057: return new PropertyChangeListener() {
1058: public void propertyChange(PropertyChangeEvent e) {
1059: String propertyName = e.getPropertyName();
1060:
1061: if (propertyName.equals("componentOrientation")) {
1062: JScrollPane pane = (JScrollPane) e.getSource();
1063: JScrollBar vsb = pane.getVerticalScrollBar();
1064: if (vsb != null) {
1065: if (isLeftToRight(pane)) {
1066: vsbBorder = new CompoundBorder(
1067: new EmptyBorder(0, 4, 0, -4),
1068: vsb.getBorder());
1069: } else {
1070: vsbBorder = new CompoundBorder(
1071: new EmptyBorder(0, -4, 0, 4),
1072: vsb.getBorder());
1073: }
1074: vsb.setBorder(vsbBorder);
1075: }
1076: }
1077: }
1078: };
1079: }
1080:
1081: boolean isLeftToRight(Component c) {
1082: return c.getComponentOrientation().isLeftToRight();
1083: }
1084:
1085: protected void installDefaults(JScrollPane scrollpane) {
1086: Border b = scrollpane.getBorder();
1087: UIDefaults uidefaults = XToolkit.getUIDefaults();
1088: scrollpane.setBorder(uidefaults
1089: .getBorder("ScrollPane.border"));
1090: scrollpane.setBackground(uidefaults
1091: .getColor("ScrollPane.background"));
1092: scrollpane.setViewportBorder(uidefaults
1093: .getBorder("TextField.border"));
1094: JScrollBar vsb = scrollpane.getVerticalScrollBar();
1095: if (vsb != null) {
1096: if (isLeftToRight(scrollpane)) {
1097: vsbBorder = new CompoundBorder(vsbMarginBorderR,
1098: vsb.getBorder());
1099: } else {
1100: vsbBorder = new CompoundBorder(vsbMarginBorderL,
1101: vsb.getBorder());
1102: }
1103: vsb.setBorder(vsbBorder);
1104: }
1105:
1106: JScrollBar hsb = scrollpane.getHorizontalScrollBar();
1107: if (hsb != null) {
1108: hsbBorder = new CompoundBorder(hsbMarginBorder, hsb
1109: .getBorder());
1110: hsb.setBorder(hsbBorder);
1111: }
1112: }
1113:
1114: protected void uninstallDefaults(JScrollPane c) {
1115: super .uninstallDefaults(c);
1116:
1117: JScrollBar vsb = scrollpane.getVerticalScrollBar();
1118: if (vsb != null) {
1119: if (vsb.getBorder() == vsbBorder) {
1120: vsb.setBorder(null);
1121: }
1122: vsbBorder = null;
1123: }
1124:
1125: JScrollBar hsb = scrollpane.getHorizontalScrollBar();
1126: if (hsb != null) {
1127: if (hsb.getBorder() == hsbBorder) {
1128: hsb.setBorder(null);
1129: }
1130: hsbBorder = null;
1131: }
1132: }
1133: }
1134:
1135: private class AWTTextPane extends JScrollPane implements
1136: FocusListener {
1137: JTextArea jtext;
1138: XWindow xwin;
1139:
1140: Color control = SystemColor.control;
1141: Color focus = SystemColor.activeCaptionBorder;
1142:
1143: public AWTTextPane(JTextArea jt, XWindow xwin, Container parent) {
1144: super (jt);
1145: this .xwin = xwin;
1146: setDoubleBuffered(true);
1147: jt.addFocusListener(this );
1148: ComponentAccessor.setParent(this , parent);
1149: setViewportBorder(new BevelBorder(false,
1150: SystemColor.controlDkShadow,
1151: SystemColor.controlLtHighlight));
1152: this .jtext = jt;
1153: setFocusable(false);
1154: addNotify();
1155: }
1156:
1157: public void focusGained(FocusEvent e) {
1158: Graphics g = getGraphics();
1159: Rectangle r = getViewportBorderBounds();
1160: g.setColor(focus);
1161: g.drawRect(r.x, r.y, r.width, r.height);
1162: g.dispose();
1163: }
1164:
1165: public void focusLost(FocusEvent e) {
1166: Graphics g = getGraphics();
1167: Rectangle r = getViewportBorderBounds();
1168: g.setColor(control);
1169: g.drawRect(r.x, r.y, r.width, r.height);
1170: g.dispose();
1171: }
1172:
1173: public Window getRealParent() {
1174: return (Window) xwin.target;
1175: }
1176:
1177: public ComponentPeer getPeer() {
1178: return (ComponentPeer) (xwin);
1179: }
1180:
1181: public void updateUI() {
1182: ComponentUI ui = new XAWTScrollPaneUI();
1183: setUI(ui);
1184: }
1185:
1186: public JScrollBar createVerticalScrollBar() {
1187: return new XAWTScrollBar(JScrollBar.VERTICAL);
1188: }
1189:
1190: public JScrollBar createHorizontalScrollBar() {
1191: return new XAWTScrollBar(JScrollBar.HORIZONTAL);
1192: }
1193:
1194: public JTextArea getTextArea() {
1195: return this .jtext;
1196: }
1197:
1198: public Graphics getGraphics() {
1199: return xwin.getGraphics();
1200: }
1201:
1202: class XAWTScrollBar extends ScrollBar {
1203:
1204: public XAWTScrollBar(int i) {
1205: super (i);
1206: setFocusable(false);
1207: }
1208:
1209: public void updateUI() {
1210: ComponentUI ui = new XAWTScrollBarUI();
1211: setUI(ui);
1212: }
1213: }
1214: }
1215:
1216: static class BevelBorder extends AbstractBorder implements
1217: UIResource {
1218: private Color darkShadow = SystemColor.controlDkShadow;
1219: private Color lightShadow = SystemColor.controlLtHighlight;
1220: private Color control = SystemColor.controlShadow;
1221: private boolean isRaised;
1222:
1223: public BevelBorder(boolean isRaised, Color darkShadow,
1224: Color lightShadow) {
1225: this .isRaised = isRaised;
1226: this .darkShadow = darkShadow;
1227: this .lightShadow = lightShadow;
1228: }
1229:
1230: public void paintBorder(Component c, Graphics g, int x, int y,
1231: int w, int h) {
1232: g.setColor((isRaised) ? lightShadow : darkShadow);
1233: g.drawLine(x, y, x + w - 1, y); // top
1234: g.drawLine(x, y + h - 1, x, y + 1); // left
1235:
1236: g.setColor(control);
1237: g.drawLine(x + 1, y + 1, x + w - 2, y + 1); // top
1238: g.drawLine(x + 1, y + h - 1, x + 1, y + 1); // left
1239:
1240: g.setColor((isRaised) ? darkShadow : lightShadow);
1241: g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); // bottom
1242: g.drawLine(x + w - 1, y + h - 1, x + w - 1, y + 1); // right
1243:
1244: g.setColor(control);
1245: g.drawLine(x + 1, y + h - 2, x + w - 2, y + h - 2); // bottom
1246: g.drawLine(x + w - 2, y + h - 2, x + w - 2, y + 1); // right
1247: }
1248:
1249: public Insets getBorderInsets(Component c) {
1250: return getBorderInsets(c, new Insets(0, 0, 0, 0));
1251: }
1252:
1253: public Insets getBorderInsets(Component c, Insets insets) {
1254: insets.top = insets.left = insets.bottom = insets.right = 2;
1255: return insets;
1256: }
1257:
1258: public boolean isOpaque(Component c) {
1259: return true;
1260: }
1261: }
1262:
1263: // This class dispatches 'MouseEvent's to 'XTextAreaPeer''s (hidden)
1264: // subcomponents, and overrides mouse cursor, e.g. for scrollbars.
1265: //
1266: // However, current dispatching is a kind of fake, and is tuned to do only
1267: // what is necessary/possible. E.g. no additional mouse-exited/entered
1268: // events are generated, when mouse exits scrollbar and enters viewport
1269: // with JTextArea inside. Actually, no events are ever generated here (for
1270: // now). They are only dispatched as correctly as possible/neccessary.
1271: //
1272: // In future, it would be better to replace fake-emulation of grab-detection
1273: // and event-dispatching here, by reusing some common implementation of this
1274: // functionality. Mouse-cursor setting should also be freed of hacked
1275: // overloading here.
1276:
1277: private static final class JavaMouseEventHandler {
1278: private final XTextAreaPeer outer;
1279: private final Pointer current = new Pointer();
1280: private boolean grabbed = false;
1281:
1282: JavaMouseEventHandler(XTextAreaPeer outer) {
1283: this .outer = outer;
1284: }
1285:
1286: // 1. We can make grab-tracking emulation here more robust to variations in
1287: // in mouse-events order and consistence. E.g. by using such code:
1288: // if( grabbed && event.getID()==MouseEvent.MOUSE_MOVED ) grabbed = false;
1289: // Or we can also use 'assert'ions.
1290: // 2. WARNING: Currently, while grab-detection mechanism _here_ says, that
1291: // grab is in progress, we do not update 'current'. In case 'current'
1292: // is set to a scrollbar or to a scroll-button, then references to their
1293: // 'Component'-instances are "remembered". And events are dispatched to
1294: // these remembered components, without checking, if XTextAreaPeer has
1295: // replaced these instances with another ones. This also aplies to
1296: // mouse-drags-from-outside (see comment in 'grabbed_update' method).
1297:
1298: void handle(MouseEvent event) {
1299: if (!grabbed) {
1300: // dispatch() needs up-to-date pointer in ungrabbed case.
1301: setPointerToUnderEventPoint(event);
1302: }
1303: dispatch(event);
1304: boolean wasGrabbed = grabbed;
1305: grabbed_update(event);
1306: if (wasGrabbed && !grabbed) {
1307: setPointerToUnderEventPoint(event);
1308: }
1309: setCursor();
1310: }
1311:
1312: // Following is internally private:
1313:
1314: // Here dispatching is performed, of 'MouseEvent's to (some)
1315: // 'XTextAreaPeer''s (hidden) subcomponents.
1316: private void dispatch(MouseEvent event) {
1317: switch (current.getType()) {
1318: case TEXT:
1319: Point point = toViewportChildLocalSpace(outer.textPane
1320: .getViewport(), event.getPoint());
1321: XTextAreaPeer.AWTTextArea jtext = outer.jtext;
1322: MouseEvent newEvent = newMouseEvent(jtext, point, event);
1323: int id = newEvent.getID();
1324: if (id == MouseEvent.MOUSE_MOVED
1325: || id == MouseEvent.MOUSE_DRAGGED) {
1326: jtext.processMouseMotionEventPublic(newEvent);
1327: } else {
1328: jtext.processMouseEventPublic(newEvent);
1329: }
1330: break;
1331:
1332: // We perform (additional) dispatching of events to buttons of
1333: // scrollbar, instead of leaving it to JScrollbar. This is
1334: // required, because of different listeners in Swing and AWT,
1335: // which trigger scrolling (ArrowButtonListener vs. TrackListener,
1336: // accordingly). So we dispatch events to scroll-buttons, to
1337: // invoke a correct Swing button listener.
1338: // See CR 6175401 for more information.
1339: case BAR:
1340: case BUTTON:
1341: Component c = current.getBar();
1342: Point p = toLocalSpace(c, event.getPoint());
1343: if (current.getType() == Pointer.Type.BUTTON) {
1344: c = current.getButton();
1345: p = toLocalSpace(c, p);
1346: }
1347: ComponentAccessor.processEvent(c, newMouseEvent(c, p,
1348: event));
1349: break;
1350: }
1351: }
1352:
1353: private static MouseEvent newMouseEvent(Component source,
1354: Point point, MouseEvent template) {
1355: MouseEvent e = template;
1356: return new MouseEvent(source, e.getID(), e.getWhen(), e
1357: .getModifiersEx()
1358: | e.getModifiers(), point.x, point.y, e
1359: .getXOnScreen(), e.getYOnScreen(), e
1360: .getClickCount(), e.isPopupTrigger(), e.getButton());
1361: }
1362:
1363: private void setCursor() {
1364: if (current.getType() == Pointer.Type.TEXT) {
1365: // 'target.getCursor()' is also applied from elsewhere
1366: // (at least now), but only when mouse "entered", and
1367: // before 'XTextAreaPeer.handleJavaMouseEvent' is invoked.
1368: outer.pSetCursor(outer.target.getCursor());
1369: } else {
1370: // We can write here a more intelligent cursor selection
1371: // mechanism, like getting cursor from 'current' component.
1372: // However, I see no point in doing so now. But if you feel
1373: // like implementing it, you'll probably need to introduce
1374: // 'Pointer.Type.PANEL'.
1375: outer.pSetCursor(outer.textPane.getCursor());
1376: }
1377: }
1378:
1379: // Current way of grab-detection causes interesting (but harmless)
1380: // side-effect. If mouse is draged from outside to inside of TextArea,
1381: // we will then (in some cases) be asked to dispatch mouse-entered/exited
1382: // events. But, as at least one mouse-button is down, we will detect
1383: // grab-mode is on (though the grab isn't ours).
1384: //
1385: // Thus, we will not update 'current' (see 'handle' method), and will
1386: // dispatch events to the last subcomponent, the 'current' was set to.
1387: // As always, we set cursor in this case also. But, all this seems
1388: // harmless, because mouse entered/exited events seem to have no effect
1389: // here, and cursor setting is ignored in case of drags from outside.
1390: //
1391: // Grab-detection can be further improved, e.g. by taking into account
1392: // current event-ID, but I see not point in doing it now.
1393:
1394: private void grabbed_update(MouseEvent event) {
1395: final int allButtonsMask = MouseEvent.BUTTON1_DOWN_MASK
1396: | MouseEvent.BUTTON2_DOWN_MASK
1397: | MouseEvent.BUTTON3_DOWN_MASK;
1398: grabbed = ((event.getModifiersEx() & allButtonsMask) != 0);
1399: }
1400:
1401: // 'toLocalSpace' and 'toViewportChildLocalSpace' can be "optimized" to
1402: // 'return' 'void' and use 'Point' input-argument also as output.
1403: private static Point toLocalSpace(Component local,
1404: Point inParentSpace) {
1405: Point p = inParentSpace;
1406: Point l = local.getLocation();
1407: return new Point(p.x - l.x, p.y - l.y);
1408: }
1409:
1410: private static Point toViewportChildLocalSpace(JViewport v,
1411: Point inViewportParentSpace) {
1412: Point l = toLocalSpace(v, inViewportParentSpace);
1413: Point p = v.getViewPosition();
1414: l.x += p.x;
1415: l.y += p.y;
1416: return l;
1417: }
1418:
1419: private void setPointerToUnderEventPoint(MouseEvent event) {
1420: Point point = event.getPoint();
1421: if (outer.textPane.getViewport().getBounds()
1422: .contains(point)) {
1423: current.setText();
1424: } else if (!setPointerIfPointOverScrollbar(outer.textPane
1425: .getVerticalScrollBar(), point)) {
1426: if (!setPointerIfPointOverScrollbar(outer.textPane
1427: .getHorizontalScrollBar(), point)) {
1428: current.setNone();
1429: }
1430: }
1431: }
1432:
1433: private boolean setPointerIfPointOverScrollbar(JScrollBar bar,
1434: Point point) {
1435: if (!bar.getBounds().contains(point)) {
1436: return false;
1437: }
1438: current.setBar(bar);
1439: Point local = toLocalSpace(bar, point);
1440:
1441: XTextAreaPeer.XAWTScrollBarUI ui = (XTextAreaPeer.XAWTScrollBarUI) bar
1442: .getUI();
1443:
1444: if (!setPointerIfPointOverButton(ui.getIncreaseButton(),
1445: local)) {
1446: setPointerIfPointOverButton(ui.getDecreaseButton(),
1447: local);
1448: }
1449:
1450: return true;
1451: }
1452:
1453: private boolean setPointerIfPointOverButton(JButton button,
1454: Point point) {
1455: if (!button.getBounds().contains(point)) {
1456: return false;
1457: }
1458: current.setButton(button);
1459: return true;
1460: }
1461:
1462: private static final class Pointer {
1463: static enum Type {
1464: NONE, TEXT, BAR, BUTTON
1465: // , PANEL
1466: }
1467:
1468: Type getType() {
1469: return type;
1470: }
1471:
1472: boolean isNone() {
1473: return type == Type.NONE;
1474: }
1475:
1476: JScrollBar getBar() {
1477: boolean ok = type == Type.BAR || type == Type.BUTTON;
1478: assert ok;
1479: return ok ? bar : null;
1480: }
1481:
1482: JButton getButton() {
1483: boolean ok = type == Type.BUTTON;
1484: assert ok;
1485: return ok ? button : null;
1486: }
1487:
1488: void setNone() {
1489: type = Type.NONE;
1490: }
1491:
1492: void setText() {
1493: type = Type.TEXT;
1494: }
1495:
1496: void setBar(JScrollBar bar) {
1497: this .bar = bar;
1498: type = Type.BAR;
1499: }
1500:
1501: void setButton(JButton button) {
1502: this .button = button;
1503: type = Type.BUTTON;
1504: }
1505:
1506: private Type type;
1507: private JScrollBar bar;
1508: private JButton button;
1509: }
1510: }
1511: }
|