1 /* 2 * Copyright (c) 1996, 2015, 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 @Override 75 public Insets insets() { 76 return getInsets(); 77 } 78 private native void setInsets(); 79 80 @Override 81 public synchronized native void setScrollPosition(int x, int y); 82 83 @Override 84 public int getHScrollbarHeight() { 85 return scrollbarHeight; 86 } 87 private native int _getHScrollbarHeight(); 88 89 @Override 90 public int getVScrollbarWidth() { 91 return scrollbarWidth; 92 } 93 private native int _getVScrollbarWidth(); 94 95 public Point getScrollOffset() { 96 int x = getOffset(Adjustable.HORIZONTAL); 97 int y = getOffset(Adjustable.VERTICAL); 98 return new Point(x, y); 99 } 100 101 /** 102 * The child component has been resized. The scrollbars must be 103 * updated with the new sizes. At the native level the sizes of 104 * the actual windows may not have changed yet, so the size 105 * information from the java-level is passed down and used. 106 */ 107 @Override 108 public void childResized(int width, int height) { 109 ScrollPane sp = (ScrollPane)target; 110 if(sp.getScrollbarDisplayPolicy() != ScrollPane.SCROLLBARS_NEVER) { 111 Dimension vs = sp.getSize(); 112 setSpans(vs.width, vs.height, width, height); 113 } 114 setInsets(); 115 } 116 117 synchronized native void setSpans(int viewWidth, int viewHeight, 118 int childWidth, int childHeight); 119 120 /** 121 * Called by ScrollPane's internal observer of the scrollpane's adjustables. 122 * This is called whenever a scroll position is changed in one 123 * of adjustables, whether it was modified externally or from the 124 * native scrollbars themselves. 125 */ 126 @Override 127 public void setValue(Adjustable adj, int v) { 128 Component c = getScrollChild(); 129 if (c == null) { 130 return; 131 } 132 133 Point p = c.getLocation(); 134 switch(adj.getOrientation()) { 135 case Adjustable.VERTICAL: 136 setScrollPosition(-(p.x), v); 137 break; 138 case Adjustable.HORIZONTAL: 139 setScrollPosition(v, -(p.y)); 140 break; 141 } 142 } 143 144 private Component getScrollChild() { 145 ScrollPane sp = (ScrollPane)target; 146 Component child = null; 147 try { 148 child = sp.getComponent(0); 149 } catch (ArrayIndexOutOfBoundsException e) { 150 // do nothing. in this case we return null 151 } 152 return child; 153 } 154 155 /* 156 * Called from Windows in response to WM_VSCROLL/WM_HSCROLL message 157 */ 158 private void postScrollEvent(int orient, int type, 159 int pos, boolean isAdjusting) 160 { 161 Runnable adjustor = new Adjustor(orient, type, pos, isAdjusting); 162 WToolkit.executeOnEventHandlerThread(new ScrollEvent(target, adjustor)); 163 } 164 165 /* 166 * Event that executes on the Java dispatch thread to move the 167 * scroll bar thumbs and paint the exposed area in one synchronous 168 * operation. 169 */ 170 @SuppressWarnings("serial") // JDK-implementation class 171 class ScrollEvent extends PeerEvent { 172 ScrollEvent(Object source, Runnable runnable) { 173 super(source, runnable, 0L); 174 } 175 176 @Override 177 public PeerEvent coalesceEvents(PeerEvent newEvent) { 178 if (log.isLoggable(PlatformLogger.Level.FINEST)) { 179 log.finest("ScrollEvent coalesced: " + newEvent); 180 } 181 if (newEvent instanceof ScrollEvent) { 182 return newEvent; 183 } 184 return null; 185 } 186 } 187 188 /* 189 * Runnable for the ScrollEvent that performs the adjustment. 190 */ 191 class Adjustor implements Runnable { 192 int orient; // selects scrollbar 193 int type; // adjustment type 194 int pos; // new position (only used for absolute) 195 boolean isAdjusting; // isAdjusting status 196 197 Adjustor(int orient, int type, int pos, boolean isAdjusting) { 198 this.orient = orient; 199 this.type = type; 200 this.pos = pos; 201 this.isAdjusting = isAdjusting; 202 } 203 204 @Override 205 public void run() { 206 if (getScrollChild() == null) { 207 return; 208 } 209 ScrollPane sp = (ScrollPane)WScrollPanePeer.this.target; 210 ScrollPaneAdjustable adj = null; 211 212 // ScrollPaneAdjustable made public in 1.4, but 213 // get[HV]Adjustable can't be declared to return 214 // ScrollPaneAdjustable because it would break backward 215 // compatibility -- hence the cast 216 217 if (orient == Adjustable.VERTICAL) { 218 adj = (ScrollPaneAdjustable)sp.getVAdjustable(); 219 } else if (orient == Adjustable.HORIZONTAL) { 220 adj = (ScrollPaneAdjustable)sp.getHAdjustable(); 221 } else { 222 if (log.isLoggable(PlatformLogger.Level.FINE)) { 223 log.fine("Assertion failed: unknown orient"); 224 } 225 } 226 227 if (adj == null) { 228 return; 229 } 230 231 int newpos = adj.getValue(); 232 switch (type) { 233 case AdjustmentEvent.UNIT_DECREMENT: 234 newpos -= adj.getUnitIncrement(); 235 break; 236 case AdjustmentEvent.UNIT_INCREMENT: 237 newpos += adj.getUnitIncrement(); 238 break; 239 case AdjustmentEvent.BLOCK_DECREMENT: 240 newpos -= adj.getBlockIncrement(); 241 break; 242 case AdjustmentEvent.BLOCK_INCREMENT: 243 newpos += adj.getBlockIncrement(); 244 break; 245 case AdjustmentEvent.TRACK: 246 newpos = this.pos; 247 break; 248 default: 249 if (log.isLoggable(PlatformLogger.Level.FINE)) { 250 log.fine("Assertion failed: unknown type"); 251 } 252 return; 253 } 254 255 // keep scroll position in acceptable range 256 newpos = Math.max(adj.getMinimum(), newpos); 257 newpos = Math.min(adj.getMaximum(), newpos); 258 259 // set value, this will synchronously fire an AdjustmentEvent 260 adj.setValueIsAdjusting(isAdjusting); 261 262 // Fix for 4075484 - consider type information when creating AdjustmentEvent 263 // We can't just call adj.setValue() because it creates AdjustmentEvent with type=TRACK 264 // Instead, we call private method setTypedValue of ScrollPaneAdjustable. 265 AWTAccessor.getScrollPaneAdjustableAccessor().setTypedValue(adj, 266 newpos, 267 type); 268 269 // Paint the exposed area right away. To do this - find 270 // the heavyweight ancestor of the scroll child. 271 Component hwAncestor = getScrollChild(); 272 final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); 273 while (hwAncestor != null 274 && !(acc.getPeer(hwAncestor) instanceof WComponentPeer)) 275 { 276 hwAncestor = hwAncestor.getParent(); 277 } 278 if (log.isLoggable(PlatformLogger.Level.FINE)) { 279 if (hwAncestor == null) { 280 log.fine("Assertion (hwAncestor != null) failed, " + 281 "couldn't find heavyweight ancestor of scroll pane child"); 282 } 283 } 284 WComponentPeer hwPeer = acc.getPeer(hwAncestor); 285 hwPeer.paintDamagedAreaImmediately(); 286 } 287 } 288 289 } --- EOF ---