1 /*
2  * @(#)QuaquaViewportUI.java  1.4  2007-11-1
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.ViewportPainter;
18 import java.awt.*;
19 import java.awt.datatransfer.*;
20 import java.awt.dnd.*;
21 import java.awt.event.*;
22 import java.awt.image.*;
23 import java.beans.*;
24 import java.util.*;
25 import javax.swing.*;
26 import javax.swing.event.*;
27 import javax.swing.plaf.*;
28 import javax.swing.plaf.basic.*;
29 import javax.swing.table.*;
30 import javax.swing.event.*;
31 import javax.swing.text.*;
32 
33 /**
34  * The Quaqua user interface delegate for a JViewport.
35  *
36  * @author  Werner Randelshofer
37  * @version 1.4 2007-11-11 Added property change listener.
38  * <br>1.3 2007-01-16 Listen to focus changes on the viewport and its
39  * child component, and repaint the parent scroll pane border on focus change.
40  * <br>1.2.2 2005-11-26 Retrieve default opaqueness from UIManager.
41  * Fixed broken invocation of ViewportPainter.
42  * <br>1.2.1 2005-09-17 Only paint viewport if it is opaque.
43  * <br>1.2 2005-08-25 Fill the viewport with the background color of its
44  * viewport view if the UI of the viewport is not an instance of ViewportPainter.
45  * <br>1.1 2004-12-14 Do not check whether the view is striped or not,
46  * always use the view for drawing the viewport.
47  * <br>1.0  June 22, 2004  Created.
48  */
49 public class QuaquaViewportUI extends BasicViewportUI {
50     private ChangeListener changeListener;
51     private ContainerListener containerListener;
52     private FocusListener focusListener;
53     private PropertyChangeListener propertyChangeListener;
54     private JViewport viewport;
55 
createUI(JComponent c)56     public static ComponentUI createUI(JComponent c) {
57         return new QuaquaViewportUI();
58     }
paint(Graphics g, JComponent c)59     public void paint(Graphics g, JComponent c) {
60         if (c.isOpaque()) {
61             Component view = viewport.getView();
62             Object ui = (view == null) ? null : Methods.invokeGetter(view, "getUI", null);
63             if (ui instanceof ViewportPainter) {
64                 ((ViewportPainter) ui).paintViewport(g, viewport);
65             } else {
66                 if (viewport.getView() != null) {
67                     g.setColor(viewport.getView().getBackground());
68                     g.fillRect(0,0,c.getWidth(),c.getHeight());
69                 }
70             }
71         }
72         Debug.paint(g, c, this);
73     }
74 
installUI(JComponent c)75     public void installUI(JComponent c) {
76         viewport = (JViewport) c;
77         super.installUI(c);
78         //c.setOpaque(QuaquaManager.getBoolean("Viewport.opaque"));
79 	QuaquaUtilities.installProperty(c, "opaque", UIManager.get("Viewport.opaque"));
80         installListeners();
81     }
82 
uninstallUI(JComponent c)83     public void uninstallUI(JComponent c) {
84         viewport = (JViewport) c;
85         super.uninstallUI(c);
86         uninstallListeners();
87     }
88     /**
89      * Attaches listeners to the JTable.
90      */
installListeners()91     protected void installListeners() {
92         changeListener = createChangeListener();
93         viewport.addChangeListener(changeListener);
94         containerListener = createContainerListener();
95         viewport.addContainerListener(containerListener);
96         focusListener = createFocusListener();
97         viewport.addFocusListener(focusListener);
98         propertyChangeListener = createPropertyChangeListener();
99         viewport.addPropertyChangeListener(propertyChangeListener);
100         if (viewport.getView() != null) {
101             viewport.getView().addFocusListener(focusListener);
102         }
103     }
uninstallListeners()104     protected void uninstallListeners() {
105         viewport.removeChangeListener(changeListener);
106         viewport.removeContainerListener(containerListener);
107         viewport.removeFocusListener(focusListener);
108         viewport.removePropertyChangeListener(propertyChangeListener);
109         changeListener = null;
110         containerListener = null;
111 
112     }
createPropertyChangeListener()113     protected PropertyChangeListener createPropertyChangeListener() {
114         return new QuaquaPropertyChangeHandler();
115     }
116 
createChangeListener()117     private ChangeListener createChangeListener() {
118         return new ChangeHandler();
119     }
createContainerListener()120     private ContainerListener createContainerListener() {
121         return new ContainerHandler();
122     }
createFocusListener()123     private FocusListener createFocusListener() {
124         return QuaquaFocusHandler.getInstance();
125     }
126 
127     /**
128      * We need to repaint the viewport if the location of a striped view
129      * changes.
130      */
131     private class ChangeHandler implements ChangeListener {
132         private Point previousLocation = new Point();
stateChanged(ChangeEvent e)133         public void stateChanged(ChangeEvent e) {
134 
135             if (viewport.getView() != null) {
136                 Component view = viewport.getView();
137 
138                 Point newLocation = view.getLocation();
139                 if (! previousLocation.equals(newLocation)) {
140                     if (view.getHeight() < viewport.getHeight()) {
141                         if (newLocation.x > previousLocation.x) {
142                             viewport.repaint(0, view.getHeight(), newLocation.x - previousLocation.x, viewport.getHeight() - view.getHeight());
143                         }
144                         if (newLocation.x < previousLocation.x) {
145                             viewport.repaint(viewport.getWidth() + newLocation.x - previousLocation.x, view.getHeight(), previousLocation.x - newLocation.x, viewport.getHeight() - view.getHeight());
146                         }
147                     }
148                     if (view.getWidth() < viewport.getWidth()) {
149                         if (newLocation.y > previousLocation.y) {
150                             viewport.repaint(view.getWidth(), 0, viewport.getWidth() - view.getWidth(), Math.min(view.getHeight(),newLocation.y - previousLocation.y));
151                         }
152                         if (newLocation.y < previousLocation.y) {
153                             viewport.repaint(
154                             view.getWidth(),
155                             Math.min(view.getHeight(),viewport.getHeight()) - previousLocation.y + newLocation.y,
156                             viewport.getWidth() - view.getWidth(),
157                             previousLocation.y - newLocation.y
158                             );
159                         }
160                     }
161                     previousLocation = newLocation;
162                 }
163             }
164         }
165     }
166     private class ContainerHandler implements ContainerListener {
componentRemoved(ContainerEvent e)167         public void componentRemoved(ContainerEvent e) {
168             e.getChild().removeFocusListener(focusListener);
169         }
170 
componentAdded(ContainerEvent e)171         public void componentAdded(ContainerEvent e) {
172             e.getChild().addFocusListener(focusListener);
173         }
174     }
175     public class QuaquaPropertyChangeHandler implements PropertyChangeListener {
propertyChange(PropertyChangeEvent e)176         public void propertyChange(PropertyChangeEvent e) {
177             String name = e.getPropertyName();
178             if ("Frame.active" == name) {
179                 // we don't need to do anything here yet.
180        } else if (name.equals("JComponent.sizeVariant")) {
181             QuaquaUtilities.applySizeVariant(viewport);
182             }
183         }
184     }
185 }
186