1 /*
2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package sun.awt.windows;
26
27 import java.awt.*;
28 import java.awt.event.AdjustmentEvent;
29 import java.awt.peer.ScrollPanePeer;
30
31 import sun.awt.AWTAccessor;
32 import sun.awt.AWTAccessor.ComponentAccessor;
33 import sun.awt.PeerEvent;
34
35 import sun.util.logging.PlatformLogger;
36
37 final class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer {
38
39 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WScrollPanePeer");
40
41 int scrollbarWidth;
42 int scrollbarHeight;
43 int prevx;
44 int prevy;
45
46 static {
47 initIDs();
48 }
49
50 static native void initIDs();
51 @Override
52 native void create(WComponentPeer parent);
53 native int getOffset(int orient);
54
55 WScrollPanePeer(Component target) {
56 super(target);
57 scrollbarWidth = _getVScrollbarWidth();
58 scrollbarHeight = _getHScrollbarHeight();
59 }
60
61 @Override
62 void initialize() {
63 super.initialize();
64 setInsets();
65 Insets i = getInsets();
66 setScrollPosition(-i.left,-i.top);
67 }
68
69 @Override
70 public void setUnitIncrement(Adjustable adj, int p) {
71 // The unitIncrement is grabbed from the target as needed.
72 }
73
74 private native void setInsets();
75
76 @Override
77 public synchronized native void setScrollPosition(int x, int y);
78
79 @Override
80 public int getHScrollbarHeight() {
81 return scrollbarHeight;
82 }
83 private native int _getHScrollbarHeight();
84
85 @Override
86 public int getVScrollbarWidth() {
87 return scrollbarWidth;
88 }
89 private native int _getVScrollbarWidth();
90
91 public Point getScrollOffset() {
92 int x = getOffset(Adjustable.HORIZONTAL);
93 int y = getOffset(Adjustable.VERTICAL);
94 return new Point(x, y);
95 }
96
97 /**
98 * The child component has been resized. The scrollbars must be
99 * updated with the new sizes. At the native level the sizes of
100 * the actual windows may not have changed yet, so the size
101 * information from the java-level is passed down and used.
102 */
103 @Override
104 public void childResized(int width, int height) {
105 ScrollPane sp = (ScrollPane)target;
106 Dimension vs = sp.getSize();
107 setSpans(vs.width, vs.height, width, height);
108 setInsets();
109 }
110
111 synchronized native void setSpans(int viewWidth, int viewHeight,
112 int childWidth, int childHeight);
113
114 /**
115 * Called by ScrollPane's internal observer of the scrollpane's adjustables.
116 * This is called whenever a scroll position is changed in one
117 * of adjustables, whether it was modified externally or from the
118 * native scrollbars themselves.
119 */
120 @Override
121 public void setValue(Adjustable adj, int v) {
122 Component c = getScrollChild();
123 if (c == null) {
124 return;
125 }
126
127 Point p = c.getLocation();
128 switch(adj.getOrientation()) {
129 case Adjustable.VERTICAL:
130 setScrollPosition(-(p.x), v);
131 break;
132 case Adjustable.HORIZONTAL:
133 setScrollPosition(v, -(p.y));
134 break;
135 }
136 }
137
138 private Component getScrollChild() {
139 ScrollPane sp = (ScrollPane)target;
140 Component child = null;
141 try {
142 child = sp.getComponent(0);
143 } catch (ArrayIndexOutOfBoundsException e) {
144 // do nothing. in this case we return null
145 }
146 return child;
147 }
148
149 /*
150 * Called from Windows in response to WM_VSCROLL/WM_HSCROLL message
151 */
152 private void postScrollEvent(int orient, int type,
153 int pos, boolean isAdjusting)
154 {
155 Runnable adjustor = new Adjustor(orient, type, pos, isAdjusting);
156 WToolkit.executeOnEventHandlerThread(new ScrollEvent(target, adjustor));
157 }
158
159 /*
160 * Event that executes on the Java dispatch thread to move the
161 * scroll bar thumbs and paint the exposed area in one synchronous
162 * operation.
163 */
164 @SuppressWarnings("serial") // JDK-implementation class
165 class ScrollEvent extends PeerEvent {
166 ScrollEvent(Object source, Runnable runnable) {
167 super(source, runnable, 0L);
168 }
169
170 @Override
171 public PeerEvent coalesceEvents(PeerEvent newEvent) {
172 if (log.isLoggable(PlatformLogger.Level.FINEST)) {
173 log.finest("ScrollEvent coalesced: " + newEvent);
174 }
175 if (newEvent instanceof ScrollEvent) {
176 return newEvent;
177 }
178 return null;
179 }
180 }
181
182 /*
183 * Runnable for the ScrollEvent that performs the adjustment.
184 */
185 class Adjustor implements Runnable {
186 int orient; // selects scrollbar
187 int type; // adjustment type
188 int pos; // new position (only used for absolute)
189 boolean isAdjusting; // isAdjusting status
190
191 Adjustor(int orient, int type, int pos, boolean isAdjusting) {
192 this.orient = orient;
193 this.type = type;
194 this.pos = pos;
195 this.isAdjusting = isAdjusting;
196 }
197
198 @Override
199 public void run() {
200 if (getScrollChild() == null) {
201 return;
202 }
203 ScrollPane sp = (ScrollPane)WScrollPanePeer.this.target;
204 ScrollPaneAdjustable adj = null;
205
206 // ScrollPaneAdjustable made public in 1.4, but
207 // get[HV]Adjustable can't be declared to return
208 // ScrollPaneAdjustable because it would break backward
209 // compatibility -- hence the cast
210
211 if (orient == Adjustable.VERTICAL) {
212 adj = (ScrollPaneAdjustable)sp.getVAdjustable();
213 } else if (orient == Adjustable.HORIZONTAL) {
214 adj = (ScrollPaneAdjustable)sp.getHAdjustable();
215 } else {
216 if (log.isLoggable(PlatformLogger.Level.FINE)) {
217 log.fine("Assertion failed: unknown orient");
218 }
219 }
220
221 if (adj == null) {
222 return;
223 }
224
225 int newpos = adj.getValue();
226 switch (type) {
227 case AdjustmentEvent.UNIT_DECREMENT:
228 newpos -= adj.getUnitIncrement();
229 break;
230 case AdjustmentEvent.UNIT_INCREMENT:
231 newpos += adj.getUnitIncrement();
232 break;
233 case AdjustmentEvent.BLOCK_DECREMENT:
234 newpos -= adj.getBlockIncrement();
235 break;
236 case AdjustmentEvent.BLOCK_INCREMENT:
237 newpos += adj.getBlockIncrement();
238 break;
239 case AdjustmentEvent.TRACK:
240 newpos = this.pos;
241 break;
242 default:
243 if (log.isLoggable(PlatformLogger.Level.FINE)) {
244 log.fine("Assertion failed: unknown type");
245 }
246 return;
247 }
248
249 // keep scroll position in acceptable range
250 newpos = Math.max(adj.getMinimum(), newpos);
251 newpos = Math.min(adj.getMaximum(), newpos);
252
253 // set value, this will synchronously fire an AdjustmentEvent
254 adj.setValueIsAdjusting(isAdjusting);
255
256 // Fix for 4075484 - consider type information when creating AdjustmentEvent
257 // We can't just call adj.setValue() because it creates AdjustmentEvent with type=TRACK
258 // Instead, we call private method setTypedValue of ScrollPaneAdjustable.
259 AWTAccessor.getScrollPaneAdjustableAccessor().setTypedValue(adj,
260 newpos,
261 type);
262
263 // Paint the exposed area right away. To do this - find
264 // the heavyweight ancestor of the scroll child.
265 Component hwAncestor = getScrollChild();
266 final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
267 while (hwAncestor != null
268 && !(acc.getPeer(hwAncestor) instanceof WComponentPeer))
269 {
270 hwAncestor = hwAncestor.getParent();
271 }
272 if (log.isLoggable(PlatformLogger.Level.FINE)) {
273 if (hwAncestor == null) {
274 log.fine("Assertion (hwAncestor != null) failed, " +
275 "couldn't find heavyweight ancestor of scroll pane child");
276 }
277 }
278 WComponentPeer hwPeer = acc.getPeer(hwAncestor);
279 hwPeer.paintDamagedAreaImmediately();
280 }
281 }
282
283 }
--- EOF ---