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