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 Anton Avtamonov, Sergey Burlak
020: * @version $Revision$
021: */package javax.swing;
022:
023: import java.awt.Component;
024: import java.awt.Dimension;
025: import java.awt.Graphics;
026: import java.awt.Image;
027: import java.awt.Insets;
028: import java.awt.LayoutManager;
029: import java.awt.Point;
030: import java.awt.Rectangle;
031: import java.awt.event.ComponentAdapter;
032: import java.awt.event.ComponentEvent;
033: import java.awt.event.ComponentListener;
034: import java.io.Serializable;
035:
036: import javax.accessibility.Accessible;
037: import javax.accessibility.AccessibleContext;
038: import javax.accessibility.AccessibleRole;
039: import javax.swing.border.Border;
040: import javax.swing.event.ChangeEvent;
041: import javax.swing.event.ChangeListener;
042: import javax.swing.event.EventListenerList;
043: import javax.swing.plaf.ViewportUI;
044:
045: import org.apache.harmony.x.swing.BlitSupport;
046:
047: import org.apache.harmony.x.swing.internal.nls.Messages;
048:
049: public class JViewport extends JComponent implements Accessible {
050: private static final long serialVersionUID = -633250949788872287L;
051:
052: protected class ViewListener extends ComponentAdapter implements
053: Serializable {
054: private static final long serialVersionUID = 6947347842254105360L;
055:
056: @Override
057: public void componentResized(final ComponentEvent e) {
058: fireStateChanged();
059: revalidate();
060: }
061: }
062:
063: protected class AccessibleJViewport extends AccessibleJComponent {
064: private static final long serialVersionUID = 481322936279100213L;
065:
066: @Override
067: public AccessibleRole getAccessibleRole() {
068: return AccessibleRole.VIEWPORT;
069: }
070: }
071:
072: public static final int BACKINGSTORE_SCROLL_MODE = 2;
073: public static final int BLIT_SCROLL_MODE = 1;
074: public static final int SIMPLE_SCROLL_MODE = 0;
075: private static final String UI_CLASS_ID = "ViewportUI";
076:
077: protected Point lastPaintPosition;
078: protected boolean isViewSizeSet;
079: @Deprecated
080: protected boolean backingStore;
081: protected transient Image backingStoreImage;
082: protected boolean scrollUnderway;
083:
084: private final EventListenerList eventListenerList;
085: private ViewportLayout viewportLayout;
086: private int scrollMode = BLIT_SCROLL_MODE;
087:
088: private final ComponentListener viewListener = new ViewListener();
089:
090: private BlitSupport blitSupport;
091:
092: public JViewport() {
093: eventListenerList = new EventListenerList();
094: setLayout(createLayoutManager());
095:
096: updateUI();
097: }
098:
099: public Point toViewCoordinates(final Point p) {
100: return new Point(p);
101: }
102:
103: public Dimension toViewCoordinates(final Dimension d) {
104: return new Dimension(d);
105: }
106:
107: @Override
108: public final Insets getInsets(final Insets insets) {
109: insets.top = 0;
110: insets.left = 0;
111: insets.bottom = 0;
112: insets.right = 0;
113:
114: return insets;
115: }
116:
117: public void setUI(final ViewportUI ui) {
118: super .setUI(ui);
119: }
120:
121: public ViewportUI getUI() {
122: return (ViewportUI) ui;
123: }
124:
125: @Override
126: public void updateUI() {
127: setUI((ViewportUI) UIManager.getUI(this ));
128: }
129:
130: public void removeChangeListener(final ChangeListener l) {
131: eventListenerList.remove(ChangeListener.class, l);
132: }
133:
134: public void addChangeListener(final ChangeListener l) {
135: eventListenerList.add(ChangeListener.class, l);
136: }
137:
138: public ChangeListener[] getChangeListeners() {
139: return eventListenerList.getListeners(ChangeListener.class);
140: }
141:
142: @Override
143: public final void setBorder(final Border b) {
144: if (b != null) {
145: throw new IllegalArgumentException(Messages
146: .getString("swing.27")); //$NON-NLS-1$
147: }
148: }
149:
150: protected ViewListener createViewListener() {
151: return new ViewListener();
152: }
153:
154: @Override
155: public AccessibleContext getAccessibleContext() {
156: return new AccessibleJViewport();
157: }
158:
159: @Override
160: protected String paramString() {
161: StringBuffer result = new StringBuffer(super .paramString());
162: result.append(",isViewSizeSet=").append(isViewSizeSet).append(
163: ",lastPaintPosition=").append(lastPaintPosition)
164: .append(",scrollUnderway=").append(scrollUnderway);
165:
166: return result.toString();
167: }
168:
169: @Override
170: public String getUIClassID() {
171: return UI_CLASS_ID;
172: }
173:
174: @Override
175: public void scrollRectToVisible(final Rectangle r) {
176: Point viewPos = getViewPosition();
177: Dimension viewSize = getExtentSize();
178:
179: int dx;
180: int dy;
181:
182: if (r.x > 0) {
183: if (r.x + r.width > viewSize.width) {
184: int dx2 = r.x + r.width - viewSize.width;
185: dx = Math.min(r.x, dx2);
186: } else {
187: dx = 0;
188: }
189: } else if (r.x < 0) {
190: if (r.x + r.width < viewSize.width) {
191: int dx2 = r.x + r.width - viewSize.width;
192: dx = Math.max(r.x, dx2);
193: } else {
194: dx = 0;
195: }
196: } else {
197: dx = 0;
198: }
199:
200: if (r.y > 0) {
201: if (r.y + r.height > viewSize.height) {
202: int dy2 = r.y + r.height - viewSize.height;
203: dy = Math.min(r.y, dy2);
204: } else {
205: dy = 0;
206: }
207: } else if (r.y < 0) {
208: if (r.y + r.height < viewSize.height) {
209: int dy2 = r.y + r.height - viewSize.height;
210: dy = Math.max(r.y, dy2);
211: } else {
212: dy = 0;
213: }
214: } else {
215: dy = 0;
216: }
217:
218: if (dx != 0 || dy != 0) {
219: int x = viewPos.x + dx;
220: int y = viewPos.y + dy;
221:
222: Point point = new Point(x, y);
223:
224: scrollUnderway = true;
225: setViewPosition(point);
226: scrollUnderway = false;
227: }
228: }
229:
230: public Rectangle getViewRect() {
231: return new Rectangle(getViewPosition(), getExtentSize());
232: }
233:
234: public void setViewPosition(final Point p) {
235: if (getView() == null) {
236: return;
237: }
238:
239: if (getViewPosition().equals(p)) {
240: return;
241: }
242:
243: int x = p.x;
244: int y = p.y;
245: if (getExtentSize().width < getViewSize().width
246: && x + getExtentSize().width > getViewSize().width) {
247: x = getViewSize().width - getExtentSize().width;
248: }
249: if (getExtentSize().height < getViewSize().height
250: && y + getExtentSize().height > getViewSize().height) {
251: y = getViewSize().height - getExtentSize().height;
252: }
253: if (x + getExtentSize().width < 0) {
254: x = 0;
255: }
256: if (y + getExtentSize().height < 0) {
257: y = 0;
258: }
259:
260: getView().setLocation(-x, -y);
261:
262: if (scrollMode == BLIT_SCROLL_MODE && !scrollUnderway
263: && blitSupport != null) {
264: blitSupport.paint();
265: }
266:
267: fireStateChanged();
268: }
269:
270: public Point getViewPosition() {
271: if (getView() == null) {
272: return new Point(0, 0);
273: }
274:
275: Point location = getView().getLocation();
276: return new Point(-location.x, -location.y);
277: }
278:
279: protected LayoutManager createLayoutManager() {
280: if (viewportLayout == null) {
281: viewportLayout = new ViewportLayout();
282: }
283: return viewportLayout;
284: }
285:
286: @Override
287: public final Insets getInsets() {
288: return new Insets(0, 0, 0, 0);
289: }
290:
291: public void setViewSize(final Dimension d) {
292: if (getView() == null) {
293: return;
294: }
295:
296: getView().setSize(d);
297:
298: fireStateChanged();
299: isViewSizeSet = true;
300: }
301:
302: public void setExtentSize(final Dimension d) {
303: setSize(d);
304: fireStateChanged();
305: }
306:
307: public Dimension getViewSize() {
308: Component view = getView();
309: if (view == null) {
310: return new Dimension(0, 0);
311: }
312: return isViewSizeSet ? view.getSize() : view.getPreferredSize();
313: }
314:
315: public Dimension getExtentSize() {
316: return getSize();
317: }
318:
319: public void setView(final Component c) {
320: remove(getView());
321: if (c != null) {
322: add(c, 0);
323: c.addComponentListener(viewListener);
324:
325: if (c instanceof JComponent) {
326: if (blitSupport == null) {
327: blitSupport = new BlitSupport((JComponent) c);
328: } else {
329: blitSupport.setBlitComponent((JComponent) c);
330: }
331: } else {
332: blitSupport = null;
333: }
334: }
335: }
336:
337: @Override
338: public void remove(final Component c) {
339: if (c == null) {
340: return;
341: }
342: c.removeComponentListener(viewListener);
343: super .remove(c);
344: }
345:
346: public Component getView() {
347: if (getComponentCount() > 0) {
348: return getComponent(0);
349: }
350: return null;
351: }
352:
353: @Deprecated
354: public void setBackingStoreEnabled(final boolean b) {
355: backingStore = b;
356: }
357:
358: @Override
359: public void paint(final Graphics g) {
360: lastPaintPosition = getViewPosition();
361: if (blitSupport != null) {
362: blitSupport.onPaint();
363: }
364:
365: if ((scrollMode == BACKINGSTORE_SCROLL_MODE || scrollMode == BLIT_SCROLL_MODE
366: && RepaintManager.currentManager(this )
367: .isDoubleBufferingEnabled())
368: && !insideDoubleBuffering()) {
369:
370: paintDoubleBuffered(g);
371: } else {
372: super .paint(g);
373: }
374: }
375:
376: public void setScrollMode(final int mode) {
377: scrollMode = mode;
378: }
379:
380: @Override
381: public boolean isOptimizedDrawingEnabled() {
382: return false;
383: }
384:
385: @Deprecated
386: public boolean isBackingStoreEnabled() {
387: return backingStore;
388: }
389:
390: public int getScrollMode() {
391: return scrollMode;
392: }
393:
394: @SuppressWarnings("deprecation")
395: @Override
396: public void reshape(final int x, final int y, final int w,
397: final int h) {
398: boolean fireEvent = getWidth() != w || getHeight() != h;
399: super .reshape(x, y, w, h);
400: if (fireEvent) {
401: fireStateChanged();
402: }
403: }
404:
405: /*
406: * In our implementation special BlitSupport class is used to control blit paintings.
407: * Therefore this method is not used, all this functionality is provided by BlitSupport
408: */
409: protected boolean computeBlit(final int dx, final int dy,
410: final Point blitFrom, final Point blitTo,
411: final Dimension blitSize, final Rectangle blitPaint) {
412: if ((Math.abs(dx) >= blitSize.width)
413: || (Math.abs(dy) >= blitSize.height)
414: || ((dx == 0) && (dy == 0)) || ((dx != 0) && (dy != 0))) {
415:
416: return false;
417: }
418: blitSize.setSize(blitSize.width - Math.abs(dx), blitSize.height
419: - Math.abs(dy));
420: if (dx < 0) {
421: blitTo.setLocation(0, 0);
422: blitFrom.setLocation(-dx, -dy);
423: blitPaint
424: .setBounds(blitSize.width, 0, -dx, blitSize.height);
425: } else if (dx > 0) {
426: blitFrom.setLocation(0, 0);
427: blitTo.setLocation(dx, dy);
428: blitPaint.setBounds(0, 0, dx, blitSize.height);
429: } else if (dy < 0) {
430: blitTo.setLocation(0, 0);
431: blitFrom.setLocation(-dx, -dy);
432: blitPaint
433: .setBounds(0, blitSize.height, blitSize.width, -dy);
434: } else {
435: blitFrom.setLocation(0, 0);
436: blitTo.setLocation(dx, dy);
437: blitPaint.setBounds(0, 0, blitSize.width, dy);
438: }
439:
440: return true;
441: }
442:
443: protected void fireStateChanged() {
444: ChangeListener[] changeListeners = getChangeListeners();
445: ChangeEvent changeEvent = new ChangeEvent(this );
446: for (ChangeListener element : changeListeners) {
447: element.stateChanged(changeEvent);
448: }
449: }
450:
451: @Override
452: protected void firePropertyChange(final String propName,
453: final Object oldVal, final Object newVal) {
454: super .firePropertyChange(propName, oldVal, newVal);
455: }
456:
457: @Override
458: protected void addImpl(final Component c, final Object obj,
459: final int index) {
460: if (c != null) {
461: super .addImpl(c, null, 0);
462: } else {
463: removeAll();
464: }
465: }
466: }
|