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