001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Sergey Burlak, Anton Avtamonov
020: * @version $Revision$
021: */package javax.swing.plaf.basic;
022:
023: import java.awt.Dimension;
024: import java.awt.Graphics;
025: import java.awt.Point;
026: import java.awt.Rectangle;
027: import java.awt.event.MouseWheelEvent;
028: import java.awt.event.MouseWheelListener;
029: import java.beans.PropertyChangeEvent;
030: import java.beans.PropertyChangeListener;
031:
032: import javax.swing.BoundedRangeModel;
033: import javax.swing.JComponent;
034: import javax.swing.JScrollBar;
035: import javax.swing.JScrollPane;
036: import javax.swing.JViewport;
037: import javax.swing.LookAndFeel;
038: import javax.swing.ScrollPaneConstants;
039: import javax.swing.ScrollPaneLayout;
040: import javax.swing.border.Border;
041: import javax.swing.event.ChangeEvent;
042: import javax.swing.event.ChangeListener;
043: import javax.swing.plaf.ComponentUI;
044: import javax.swing.plaf.ScrollPaneUI;
045:
046: import org.apache.harmony.x.swing.StringConstants;
047: import org.apache.harmony.x.swing.Utilities;
048:
049: public class BasicScrollPaneUI extends ScrollPaneUI implements
050: ScrollPaneConstants {
051:
052: public class HSBChangeListener implements ChangeListener {
053: public void stateChanged(final ChangeEvent e) {
054: JScrollBar hsb = scrollpane.getHorizontalScrollBar();
055: int value = hsb.getValue();
056: boolean isLeftToRight = hsb.getComponentOrientation()
057: .isLeftToRight();
058: scrollViewport(scrollpane.getViewport(), value,
059: isLeftToRight);
060: scrollViewport(scrollpane.getColumnHeader(), value,
061: isLeftToRight);
062: }
063:
064: private void scrollViewport(final JViewport viewport,
065: final int value, final boolean isLeftToRight) {
066: if (viewport != null) {
067: viewport.setViewPosition(new Point(
068: getHorizontalPosition(viewport, value,
069: isLeftToRight), viewport
070: .getViewPosition().y));
071: }
072: }
073: }
074:
075: public class VSBChangeListener implements ChangeListener {
076: public void stateChanged(final ChangeEvent e) {
077: JScrollBar vsb = scrollpane.getVerticalScrollBar();
078: int value = vsb.getValue();
079: scrollViewport(scrollpane.getViewport(), value);
080: scrollViewport(scrollpane.getRowHeader(), value);
081: }
082:
083: private void scrollViewport(final JViewport viewport,
084: final int value) {
085: if (viewport != null) {
086: viewport.setViewPosition(new Point(viewport
087: .getViewPosition().x, value));
088: }
089: }
090: }
091:
092: public class PropertyChangeHandler implements
093: PropertyChangeListener {
094: public void propertyChange(final PropertyChangeEvent e) {
095: String changedProperty = e.getPropertyName();
096: if (StringConstants.VERTICAL_SCROLLBAR_PROPERTY
097: .equals(changedProperty)
098: || StringConstants.HORIZONTAL_SCROLLBAR_PROPERTY
099: .equals(changedProperty)
100: || StringConstants.VERTICAL_SCROLLBAR_POLICY_PROPERTY
101: .equals(changedProperty)
102: || StringConstants.HORIZONTAL_SCROLLBAR_POLICY_PROPERTY
103: .equals(changedProperty)) {
104:
105: updateScrollBarDisplayPolicy(e);
106: } else if (StringConstants.COLUMN_HEADER_PROPERTY
107: .equals(changedProperty)) {
108: updateColumnHeader(e);
109: } else if (StringConstants.ROW_HEADER_PROPERTY
110: .equals(changedProperty)) {
111: updateRowHeader(e);
112: } else if (StringConstants.VIEWPORT_PROPERTY
113: .equals(changedProperty)) {
114: updateViewport(e);
115: } else if (StringConstants.COMPONENT_ORIENTATION
116: .equals(changedProperty)) {
117: uninstallKeyboardActions(scrollpane);
118: installKeyboardActions(scrollpane);
119: }
120:
121: scrollpane.revalidate();
122: scrollpane.repaint();
123: }
124: }
125:
126: public class ViewportChangeHandler implements ChangeListener {
127: public void stateChanged(final ChangeEvent e) {
128: syncScrollPaneWithViewport();
129: }
130: }
131:
132: protected class MouseWheelHandler implements MouseWheelListener {
133: public void mouseWheelMoved(final MouseWheelEvent e) {
134: if (scrollpane.isWheelScrollingEnabled()) {
135: if (scrollpane.getVerticalScrollBar().isVisible()) {
136: scroll(scrollpane.getVerticalScrollBar(), e);
137: } else if (scrollpane.getHorizontalScrollBar()
138: .isVisible()) {
139: scroll(scrollpane.getHorizontalScrollBar(), e);
140: }
141: }
142: }
143:
144: private void scroll(final JScrollBar sb, final MouseWheelEvent e) {
145: int totalAmount = 0;
146: if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
147: totalAmount = e.getUnitsToScroll()
148: * sb.getUnitIncrement(e.getWheelRotation());
149: } else if (e.getScrollType() == MouseWheelEvent.WHEEL_BLOCK_SCROLL) {
150: totalAmount = e.getWheelRotation()
151: * sb.getBlockIncrement(e.getWheelRotation());
152: }
153: sb.setValue(sb.getValue() + totalAmount);
154: }
155: }
156:
157: private class HSBPropertyChangeHandler implements
158: PropertyChangeListener {
159: public void propertyChange(final PropertyChangeEvent e) {
160: String propertyName = e.getPropertyName();
161: if (StringConstants.MODEL_PROPERTY_CHANGED
162: .equals(propertyName)) {
163: BoundedRangeModel oldValue = (BoundedRangeModel) e
164: .getOldValue();
165: if (oldValue != null) {
166: oldValue.removeChangeListener(hsbChangeListener);
167: }
168:
169: BoundedRangeModel newValue = (BoundedRangeModel) e
170: .getNewValue();
171: if (newValue != null) {
172: newValue.addChangeListener(hsbChangeListener);
173: }
174: } else if (StringConstants.COMPONENT_ORIENTATION
175: .equals(propertyName)) {
176: hsbChangeListener.stateChanged(new ChangeEvent(e
177: .getSource()));
178: }
179: }
180: }
181:
182: private class VSBPropertyChangeHandler implements
183: PropertyChangeListener {
184: public void propertyChange(final PropertyChangeEvent e) {
185: String propertyName = e.getPropertyName();
186: if (StringConstants.MODEL_PROPERTY_CHANGED
187: .equals(propertyName)) {
188: BoundedRangeModel oldValue = (BoundedRangeModel) e
189: .getOldValue();
190: if (oldValue != null) {
191: oldValue.removeChangeListener(vsbChangeListener);
192: }
193:
194: BoundedRangeModel newValue = (BoundedRangeModel) e
195: .getNewValue();
196: if (newValue != null) {
197: newValue.addChangeListener(vsbChangeListener);
198: }
199: }
200: }
201: }
202:
203: protected JScrollPane scrollpane;
204: protected ChangeListener hsbChangeListener;
205: protected ChangeListener vsbChangeListener;
206: protected ChangeListener viewportChangeListener;
207: protected PropertyChangeListener spPropertyChangeListener;
208: private PropertyChangeListener hsbPropertyChangeListener;
209: private PropertyChangeListener vsbPropertyChangeListener;
210:
211: private MouseWheelListener mouseWheelListener;
212:
213: public static ComponentUI createUI(final JComponent x) {
214: return new BasicScrollPaneUI();
215: }
216:
217: public void paint(final Graphics g, final JComponent c) {
218: Border viewportBorder = scrollpane.getViewportBorder();
219: if (viewportBorder != null) {
220: Rectangle borderBounds = scrollpane
221: .getViewportBorderBounds();
222: viewportBorder.paintBorder(scrollpane, g, borderBounds.x,
223: borderBounds.y, borderBounds.width,
224: borderBounds.height);
225: }
226: }
227:
228: public Dimension getMaximumSize(final JComponent c) {
229: return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
230: }
231:
232: public void installUI(final JComponent c) {
233: scrollpane = (JScrollPane) c;
234: installDefaults(scrollpane);
235: installListeners(scrollpane);
236: installKeyboardActions(scrollpane);
237:
238: scrollpane.setLayout(new ScrollPaneLayout());
239: }
240:
241: public void uninstallUI(final JComponent c) {
242: uninstallKeyboardActions(scrollpane);
243: uninstallListeners(scrollpane);
244: uninstallDefaults(scrollpane);
245:
246: scrollpane.setLayout(null);
247: scrollpane = null;
248: }
249:
250: protected void installDefaults(final JScrollPane scrollPane) {
251: LookAndFeel.installProperty(scrollpane, "opaque", Boolean.TRUE);
252: LookAndFeel.installBorder(scrollPane, "ScrollPane.border");
253: LookAndFeel.installColorsAndFont(scrollPane,
254: "ScrollPane.background", "ScrollPane.foreground",
255: "ScrollPane.font");
256: }
257:
258: protected void uninstallDefaults(final JScrollPane scrollPane) {
259: LookAndFeel.uninstallBorder(scrollPane);
260: Utilities.uninstallColorsAndFont(scrollPane);
261: }
262:
263: protected void installListeners(final JScrollPane scrollPane) {
264: vsbChangeListener = createVSBChangeListener();
265: if (scrollpane.getVerticalScrollBar() != null) {
266: scrollpane.getVerticalScrollBar().getModel()
267: .addChangeListener(vsbChangeListener);
268: }
269:
270: hsbChangeListener = createHSBChangeListener();
271: if (scrollpane.getHorizontalScrollBar() != null) {
272: scrollpane.getHorizontalScrollBar().getModel()
273: .addChangeListener(hsbChangeListener);
274: }
275:
276: viewportChangeListener = createViewportChangeListener();
277: if (scrollpane.getViewport() != null) {
278: scrollpane.getViewport().addChangeListener(
279: viewportChangeListener);
280: }
281:
282: spPropertyChangeListener = createPropertyChangeListener();
283: scrollpane.addPropertyChangeListener(spPropertyChangeListener);
284:
285: hsbPropertyChangeListener = new HSBPropertyChangeHandler();
286: if (scrollpane.getHorizontalScrollBar() != null) {
287: scrollpane.getHorizontalScrollBar()
288: .addPropertyChangeListener(
289: hsbPropertyChangeListener);
290: }
291:
292: vsbPropertyChangeListener = new VSBPropertyChangeHandler();
293: if (scrollpane.getVerticalScrollBar() != null) {
294: scrollpane.getVerticalScrollBar()
295: .addPropertyChangeListener(
296: vsbPropertyChangeListener);
297: }
298:
299: mouseWheelListener = createMouseWheelListener();
300: scrollpane.addMouseWheelListener(mouseWheelListener);
301: }
302:
303: protected void uninstallListeners(final JComponent c) {
304: if (scrollpane.getVerticalScrollBar() != null) {
305: scrollpane.getVerticalScrollBar().getModel()
306: .removeChangeListener(vsbChangeListener);
307: }
308: vsbChangeListener = null;
309:
310: if (scrollpane.getHorizontalScrollBar() != null) {
311: scrollpane.getHorizontalScrollBar().getModel()
312: .removeChangeListener(hsbChangeListener);
313: }
314: hsbChangeListener = null;
315:
316: if (scrollpane.getViewport() != null) {
317: scrollpane.getViewport().removeChangeListener(
318: viewportChangeListener);
319: }
320: viewportChangeListener = null;
321:
322: scrollpane
323: .removePropertyChangeListener(spPropertyChangeListener);
324: spPropertyChangeListener = null;
325:
326: scrollpane.removeMouseWheelListener(mouseWheelListener);
327: mouseWheelListener = null;
328: }
329:
330: protected void installKeyboardActions(final JScrollPane scrollPane) {
331: BasicScrollPaneKeyboardActions
332: .installKeyboardActions(scrollPane);
333: }
334:
335: protected void uninstallKeyboardActions(final JScrollPane scrollPane) {
336: BasicScrollPaneKeyboardActions
337: .uninstallKeyboardActions(scrollPane);
338: }
339:
340: protected ChangeListener createViewportChangeListener() {
341: return new ViewportChangeHandler();
342: }
343:
344: protected ChangeListener createHSBChangeListener() {
345: return new HSBChangeListener();
346: }
347:
348: protected ChangeListener createVSBChangeListener() {
349: return new VSBChangeListener();
350: }
351:
352: protected MouseWheelListener createMouseWheelListener() {
353: return new MouseWheelHandler();
354: }
355:
356: protected PropertyChangeListener createPropertyChangeListener() {
357: return new PropertyChangeHandler();
358: }
359:
360: protected void syncScrollPaneWithViewport() {
361: JViewport viewport = scrollpane.getViewport();
362: Point viewPosition = viewport.getViewPosition();
363: Dimension extentSize = viewport.getExtentSize();
364: Dimension maximumSize = viewport.getViewSize();
365: if (scrollpane.getVerticalScrollBar() != null) {
366: JScrollBar vsb = scrollpane.getVerticalScrollBar();
367: vsb.setValues(viewPosition.y, extentSize.height, 0,
368: maximumSize.height);
369: }
370: if (scrollpane.getHorizontalScrollBar() != null) {
371: JScrollBar hsb = scrollpane.getHorizontalScrollBar();
372: int newValue = getHorizontalPosition(viewport,
373: viewPosition.x, hsb.getComponentOrientation()
374: .isLeftToRight());
375: hsb.setValues(newValue, extentSize.width, 0,
376: maximumSize.width);
377: }
378: }
379:
380: protected void updateScrollBarDisplayPolicy(
381: final PropertyChangeEvent e) {
382: String changedProperty = e.getPropertyName();
383: if (StringConstants.VERTICAL_SCROLLBAR_PROPERTY
384: .equals(changedProperty)) {
385: JScrollBar oldValue = (JScrollBar) e.getOldValue();
386: if (oldValue != null) {
387: oldValue.getModel().removeChangeListener(
388: vsbChangeListener);
389: oldValue
390: .removePropertyChangeListener(vsbPropertyChangeListener);
391: }
392: JScrollBar newValue = (JScrollBar) e.getNewValue();
393: if (newValue != null) {
394: newValue.getModel()
395: .addChangeListener(vsbChangeListener);
396: newValue
397: .addPropertyChangeListener(vsbPropertyChangeListener);
398: }
399: } else if (StringConstants.HORIZONTAL_SCROLLBAR_PROPERTY
400: .equals(changedProperty)) {
401: JScrollBar oldValue = (JScrollBar) e.getOldValue();
402: if (oldValue != null) {
403: oldValue.getModel().removeChangeListener(
404: hsbChangeListener);
405: oldValue
406: .removePropertyChangeListener(hsbPropertyChangeListener);
407: }
408: JScrollBar newValue = (JScrollBar) e.getNewValue();
409: if (newValue != null) {
410: newValue.getModel()
411: .addChangeListener(hsbChangeListener);
412: newValue
413: .addPropertyChangeListener(hsbPropertyChangeListener);
414: }
415: } else if (StringConstants.HORIZONTAL_SCROLLBAR_POLICY_PROPERTY
416: .equals(changedProperty)) {
417: ((ScrollPaneLayout) scrollpane.getLayout())
418: .setHorizontalScrollBarPolicy(((Integer) e
419: .getNewValue()).intValue());
420: } else if (StringConstants.VERTICAL_SCROLLBAR_POLICY_PROPERTY
421: .equals(changedProperty)) {
422: ((ScrollPaneLayout) scrollpane.getLayout())
423: .setVerticalScrollBarPolicy(((Integer) e
424: .getNewValue()).intValue());
425: }
426: }
427:
428: protected void updateViewport(final PropertyChangeEvent e) {
429: JViewport oldValue = (JViewport) e.getOldValue();
430: if (oldValue != null) {
431: oldValue.removeChangeListener(viewportChangeListener);
432: }
433:
434: JViewport newValue = (JViewport) e.getNewValue();
435: if (newValue != null) {
436: newValue.addChangeListener(viewportChangeListener);
437: if (oldValue != null) {
438: newValue.setViewPosition(oldValue.getViewPosition());
439: } else {
440:
441: }
442: syncUpColumnHeader();
443: syncUpRowHeader();
444: }
445: }
446:
447: protected void updateRowHeader(final PropertyChangeEvent e) {
448: syncUpRowHeader();
449: }
450:
451: protected void updateColumnHeader(final PropertyChangeEvent e) {
452: syncUpColumnHeader();
453: }
454:
455: private int getHorizontalPosition(final JViewport viewport,
456: final int value, final boolean isLeftToRight) {
457: return isLeftToRight ? value : viewport.getViewSize().width
458: - viewport.getExtentSize().width - value;
459: }
460:
461: private void syncUpColumnHeader() {
462: if (scrollpane.getColumnHeader() != null
463: && scrollpane.getViewport() != null) {
464: scrollpane.getColumnHeader().setViewPosition(
465: new Point(scrollpane.getViewport()
466: .getViewPosition().x, scrollpane
467: .getColumnHeader().getViewPosition().y));
468: }
469: }
470:
471: private void syncUpRowHeader() {
472: if (scrollpane.getRowHeader() != null
473: && scrollpane.getViewport() != null) {
474: scrollpane.getRowHeader().setViewPosition(
475: new Point(scrollpane.getRowHeader()
476: .getViewPosition().x, scrollpane
477: .getViewport().getViewPosition().y));
478: }
479: }
480:
481: }
|