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