1 /*
2  * @(#)QuaquaTextAreaUI.java  1.4  2007-01-16
3  *
4  * Copyright (c) 2004-2007 Werner Randelshofer
5  * Staldenmattweg 2, Immensee, CH-6405, Switzerland.
6  * All rights reserved.
7  *
8  * The copyright of this software is owned by Werner Randelshofer.
9  * You may not use, copy or modify this software, except in
10  * accordance with the license agreement you entered into with
11  * Werner Randelshofer. For details see accompanying license terms.
12  */
13 
14 package ch.randelshofer.quaqua;
15 
16 import ch.randelshofer.quaqua.util.*;
17 import ch.randelshofer.quaqua.util.Debug;
18 import java.awt.*;
19 import java.awt.event.*;
20 import java.beans.*;
21 
22 import javax.swing.*;
23 import javax.swing.plaf.*;
24 import javax.swing.plaf.basic.*;
25 import javax.swing.text.*;
26 import javax.swing.border.*;
27 
28 
29 /**
30  * QuaquaTextAreaUI.
31  *
32  * @author  Werner Randelshofer
33  * @version 1.4 2007-01-16 Factored focus listener out into QuaquaViewportView.
34  * <br>1.3 2006-04-24 Added support for .popupHandler UIManager property.
35  * <br>1.2 2005-07-17 Adapted to changes in interface VisuallyLayoutable.
36  * <br>1.1.1 2005-06-30 Fixed NPE in method getVisualBounds.
37  * <br>1.1 2004-12-02 Use QuaquaTextEditorKit instead of
38  * DefaulTextEditorKit.
39  * <br>1.0  July 4, 2004  Created.
40  */
41 public class QuaquaTextAreaUI extends BasicTextAreaUI implements VisuallyLayoutable {
42     boolean oldDragState = false;
43     private MouseListener popupListener;
44 
createUI(JComponent jcomponent)45     public static ComponentUI createUI(JComponent jcomponent) {
46         return new QuaquaTextAreaUI();
47     }
48 
installDefaults()49     protected void installDefaults() {
50         if (! QuaquaUtilities.isHeadless()) {
51             oldDragState = Methods.invokeGetter(getComponent(),"getDragEnabled", true);
52             Methods.invokeIfExists(getComponent(),"setDragEnabled", true);
53         }
54         super.installDefaults();
55     }
56 
uninstallDefaults()57     protected void uninstallDefaults() {
58         if (QuaquaUtilities.isHeadless()) {
59             Methods.invokeIfExists(getComponent(),"setDragEnabled", oldDragState);
60         }
61         super.uninstallDefaults();
62     }
63 
installListeners()64     protected void installListeners() {
65         popupListener = createPopupListener();
66         if (popupListener != null) {
67             getComponent().addMouseListener(popupListener);
68         }
69         super.installListeners();
70     }
71 
uninstallListeners()72     protected void uninstallListeners() {
73         if (popupListener != null) {
74             getComponent().removeMouseListener(popupListener);
75             popupListener = null;
76         }
77         super.uninstallListeners();
78     }
79 
createPopupListener()80     protected MouseListener createPopupListener() {
81         return (MouseListener) UIManager.get(getPropertyPrefix()+".popupHandler");
82     }
83 
84 
85     /**
86      * Fetches the EditorKit for the UI.
87      *
88      * @param tc the text component for which this UI is installed
89      * @return the editor capabilities
90      * @see TextUI#getEditorKit
91      */
getEditorKit(JTextComponent tc)92     public EditorKit getEditorKit(JTextComponent tc) {
93         return QuaquaTextFieldUI.defaultKit;
94     }
95 
propertyChange(PropertyChangeEvent event)96     public void propertyChange(PropertyChangeEvent event) {
97         String name = event.getPropertyName();
98         if (name.equals("Frame.active")) {
99             QuaquaUtilities.repaintBorder(getComponent());
100        } else if (name.equals("JComponent.sizeVariant")) {
101             QuaquaUtilities.applySizeVariant(getComponent());
102        } else {
103              super.propertyChange(event);
104     }
105         }
106 
paintSafely(Graphics g)107     protected void paintSafely(Graphics g) {
108 	Object oldHints = QuaquaUtilities.beginGraphics((Graphics2D) g);
109         super.paintSafely(g);
110 	QuaquaUtilities.endGraphics((Graphics2D) g, oldHints);
111         Debug.paint(g, getComponent(), this);
112     }
113     /*
114     protected HierarchyListener createHierarchyListener() {
115         return new ComponentActivationHandler(getComponent());
116     }*/
117 
createCaret()118     protected Caret createCaret() {
119         Window window = SwingUtilities.getWindowAncestor(getComponent());
120         QuaquaCaret caret = new QuaquaCaret(window, getComponent());
121         return caret;
122     }
123 
createHighlighter()124     protected Highlighter createHighlighter() {
125         return new QuaquaHighlighter();
126     }
127 
getBaseline(JComponent c, int width, int height)128     public int getBaseline(JComponent c, int width, int height) {
129         JTextComponent tc = (JTextComponent) c;
130         Insets insets = tc.getInsets();
131         FontMetrics fm = tc.getFontMetrics(tc.getFont());
132         return insets.top + fm.getAscent();
133     }
134 
getVisualBounds(JComponent c, int type, int width, int height)135     public Rectangle getVisualBounds(JComponent c, int type, int width, int height) {
136         Rectangle bounds = new Rectangle(0,0,width,height);
137         if (type == VisuallyLayoutable.CLIP_BOUNDS) {
138             return bounds;
139         }
140 
141         JTextComponent b = (JTextComponent) c;
142         if (type == VisuallyLayoutable.COMPONENT_BOUNDS
143         && b.getBorder() != null) {
144             Border border = b.getBorder();
145             if (border instanceof UIResource) {
146                 //InsetsUtil.subtractInto(getVisualMargin(b), bounds);
147                 // FIXME - Should derive this value from border
148                 // FIXME - If we had layout managers that supported baseline alignment,
149                 //              we wouldn't have to subtract one here
150                 bounds.height -= 1;
151             }
152         } else {
153             bounds = getVisibleEditorRect();
154             FontMetrics fm = c.getFontMetrics(c.getFont());
155 
156             int baseline = getBaseline(c, width, height);
157             Rectangle textBounds = Fonts.getPerceivedBounds(b.getText(), b.getFont(), c);
158             if (bounds == null) {
159                 bounds = textBounds;
160                 bounds.y += baseline;
161             } else {
162                 bounds.y = baseline + textBounds.y;
163                 bounds.height = textBounds.height;
164             }
165             bounds.x += 1;
166             bounds.width -= 2;
167         }
168         return bounds;
169     }
170 }
171