1 /* |
1 /* |
2 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. |
2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Sun designates this |
7 * published by the Free Software Foundation. Sun designates this |
53 public final static int VERSCROLLBAR = 1; |
53 public final static int VERSCROLLBAR = 1; |
54 public final static int HORSCROLLBAR = 2; |
54 public final static int HORSCROLLBAR = 2; |
55 public final static int DEFAULT_VISIBLE_ROWS = 4; // From java.awt.List, |
55 public final static int DEFAULT_VISIBLE_ROWS = 4; // From java.awt.List, |
56 public final static int HORIZ_SCROLL_AMT = 10; |
56 public final static int HORIZ_SCROLL_AMT = 10; |
57 |
57 |
58 final static int |
58 private final static int PAINT_VSCROLL = 2; |
59 PAINT_VSCROLL = 2, |
59 private final static int PAINT_HSCROLL = 4; |
60 PAINT_HSCROLL = 4, |
60 private final static int PAINT_ITEMS = 8; |
61 PAINT_ITEMS = 8, |
61 private final static int PAINT_FOCUS = 16; |
62 PAINT_FOCUS = 16, |
62 private final static int PAINT_BACKGROUND = 32; |
63 PAINT_BACKGROUND = 32, |
63 private final static int PAINT_HIDEFOCUS = 64; |
64 PAINT_HIDEFOCUS = 64, |
64 private final static int PAINT_ALL = |
65 PAINT_ALL = PAINT_VSCROLL | PAINT_HSCROLL | PAINT_ITEMS | PAINT_FOCUS | PAINT_BACKGROUND; |
65 PAINT_VSCROLL | PAINT_HSCROLL | PAINT_ITEMS | PAINT_FOCUS | PAINT_BACKGROUND; |
|
66 private final static int COPY_AREA = 128; |
66 |
67 |
67 XVerticalScrollbar vsb; |
68 XVerticalScrollbar vsb; |
68 XHorizontalScrollbar hsb; |
69 XHorizontalScrollbar hsb; |
69 ListPainter painter; |
70 ListPainter painter; |
70 |
71 |
361 } else { |
362 } else { |
362 return Math.min(items.size()-1, itemsInWindow()-1); |
363 return Math.min(items.size()-1, itemsInWindow()-1); |
363 } |
364 } |
364 } |
365 } |
365 |
366 |
366 Area getItemsArea(int firstItem, int lastItem) { |
|
367 firstItem = Math.max(getFirstVisibleItem(), firstItem); |
|
368 lastItem = Math.min(lastItem, getLastVisibleItem()); |
|
369 if (lastItem < getFirstVisibleItem()) { |
|
370 return new Area(); |
|
371 } |
|
372 if (firstItem <= lastItem) { |
|
373 int startY = getItemY(firstItem); |
|
374 int endY = getItemY(lastItem) + getItemHeight(); |
|
375 // Account for focus rectangle, instead should be called twice - before change |
|
376 // of focusIndex and after |
|
377 startY -= 2; |
|
378 endY += 2; |
|
379 // x is 0 since we need to account for focus rectangle, |
|
380 // the same with width |
|
381 return new Area(new Rectangle(0, startY, getItemWidth() + 3, endY-startY+1)); |
|
382 } else { |
|
383 return new Area(); |
|
384 } |
|
385 } |
|
386 |
|
387 Rectangle getItemRect(int item) { |
|
388 return new Rectangle(MARGIN, getItemY(item), getItemWidth(), getItemHeight()); |
|
389 } |
|
390 |
|
391 Area getItemArea(int item) { |
|
392 return new Area(getItemRect(item)); |
|
393 } |
|
394 |
|
395 public void repaintScrollbarRequest(XScrollbar scrollbar) { |
367 public void repaintScrollbarRequest(XScrollbar scrollbar) { |
396 Graphics g = getGraphics(); |
368 Graphics g = getGraphics(); |
397 if (scrollbar == hsb) { |
369 if (scrollbar == hsb) { |
398 repaint(PAINT_HSCROLL); |
370 repaint(PAINT_HSCROLL); |
399 } |
371 } |
409 */ |
381 */ |
410 public void repaint() { |
382 public void repaint() { |
411 repaint(getFirstVisibleItem(), getLastVisibleItem(), PAINT_ALL); |
383 repaint(getFirstVisibleItem(), getLastVisibleItem(), PAINT_ALL); |
412 } |
384 } |
413 |
385 |
414 public void repaint(int options) { |
386 private void repaint(int options) { |
415 repaint(getFirstVisibleItem(), getLastVisibleItem(), options); |
387 repaint(getFirstVisibleItem(), getLastVisibleItem(), options); |
416 } |
388 } |
417 |
389 |
418 public void repaint(int firstItem, int lastItem, int options) { |
390 private void repaint(int firstItem, int lastItem, int options) { |
|
391 repaint(firstItem, lastItem, options, null, null); |
|
392 } |
|
393 |
|
394 /** |
|
395 * In most cases the entire area of the component doesn't have |
|
396 * to be repainted. The method repaints the particular areas of |
|
397 * the component. The areas to repaint is specified by the option |
|
398 * parameter. The possible values of the option parameter are: |
|
399 * PAINT_VSCROLL, PAINT_HSCROLL, PAINT_ITEMS, PAINT_FOCUS, |
|
400 * PAINT_HIDEFOCUS, PAINT_BACKGROUND, PAINT_ALL, COPY_AREA. |
|
401 * |
|
402 * Note that the COPY_AREA value initiates copy of a source area |
|
403 * of the component by a distance by means of the copyArea method |
|
404 * of the Graphics class. |
|
405 * |
|
406 * @param firstItem the position of the first item of the range to repaint |
|
407 * @param lastItem the position of the last item of the range to repaint |
|
408 * @param options specifies the particular area of the component to repaint |
|
409 * @param source the area of the component to copy |
|
410 * @param distance the distance to copy the source area |
|
411 */ |
|
412 private void repaint(int firstItem, int lastItem, int options, Rectangle source, Point distance) { |
419 Graphics g = getGraphics(); |
413 Graphics g = getGraphics(); |
420 try { |
414 try { |
421 painter.paint(g, firstItem, lastItem, options); |
415 painter.paint(g, firstItem, lastItem, options, source, distance); |
422 } finally { |
416 } finally { |
423 g.dispose(); |
417 g.dispose(); |
424 } |
418 } |
425 } |
419 } |
426 |
420 |
1447 if (vsb.getValue() < -y) { |
1441 if (vsb.getValue() < -y) { |
1448 y = -vsb.getValue(); |
1442 y = -vsb.getValue(); |
1449 } |
1443 } |
1450 vsb.setValue(vsb.getValue() + y); |
1444 vsb.setValue(vsb.getValue() + y); |
1451 |
1445 |
|
1446 Rectangle source = null; |
|
1447 Point distance = null; |
|
1448 int firstItem = 0, lastItem = 0; |
|
1449 int options = PAINT_HIDEFOCUS | PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS; |
1452 if (y > 0) { |
1450 if (y > 0) { |
1453 // Fixed 6308295: XAWTduplicate list item is displayed |
1451 if (y < itemsInWin) { |
1454 // Window resizing leads to the buffer flushing |
1452 source = new Rectangle(MARGIN, MARGIN + pixelsToScroll, width - SCROLLBAR_AREA, h * (itemsInWin - y - 1)-1); |
1455 // That's why the repainting with the PAINT_HIDEFOCUS option is the repainting with PAINT_ALL option |
1453 distance = new Point(0, -pixelsToScroll); |
1456 // So we should do only the repainting instead of the copy area |
1454 options |= COPY_AREA; |
1457 if (y < itemsInWin && painter.isBuffer()) { |
1455 } |
1458 if (log.isLoggable(Level.FINEST)) { |
1456 firstItem = vsb.getValue() + itemsInWin - y - 1; |
1459 log.finest("Copying " + "" + MARGIN + "," + ( MARGIN + pixelsToScroll) |
1457 lastItem = vsb.getValue() + itemsInWin - 1; |
1460 + "," + (width - SCROLLBAR_AREA) + "," + (h * (itemsInWin - y)-1) + |
1458 |
1461 "," + 0 + "," + (-pixelsToScroll)); |
1459 } else if (y < 0) { |
1462 } |
|
1463 // Unpaint focus before copying |
|
1464 repaint(PAINT_HIDEFOCUS); |
|
1465 painter.copyArea(MARGIN, MARGIN + pixelsToScroll, width - SCROLLBAR_AREA, h * (itemsInWin - y - 1)-1, 0, -pixelsToScroll); |
|
1466 } |
|
1467 repaint(vsb.getValue() + (itemsInWin - y)-1, (vsb.getValue() + itemsInWin) - 1, PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS); |
|
1468 } else if (y < 0 && painter.isBuffer()) { |
|
1469 if (y + itemsInWindow() > 0) { |
1460 if (y + itemsInWindow() > 0) { |
1470 if (log.isLoggable(Level.FINEST)) { |
1461 source = new Rectangle(MARGIN, MARGIN, width - SCROLLBAR_AREA, h * (itemsInWin + y)); |
1471 log.finest("Copying " + MARGIN + "," + MARGIN +"," + |
1462 distance = new Point(0, -pixelsToScroll); |
1472 (width - SCROLLBAR_AREA) + "," + |
1463 options |= COPY_AREA; |
1473 (h * (itemsInWin + y)) + "," + "0" +"," +(-pixelsToScroll)); |
1464 } |
1474 } |
1465 firstItem = vsb.getValue(); |
1475 repaint(PAINT_HIDEFOCUS); |
1466 lastItem = Math.min(getLastVisibleItem(), vsb.getValue() + -y); |
1476 painter.copyArea(MARGIN, MARGIN, width - SCROLLBAR_AREA, h * (itemsInWin + y), 0, -pixelsToScroll); |
1467 } |
1477 } |
1468 repaint(firstItem, lastItem, options, source, distance); |
1478 int e = Math.min(getLastVisibleItem(), vsb.getValue() + -y); |
|
1479 repaint(vsb.getValue(), e, PAINT_ITEMS | PAINT_VSCROLL | PAINT_FOCUS); |
|
1480 } |
|
1481 } |
1469 } |
1482 |
1470 |
1483 /** |
1471 /** |
1484 * scrollHorizontal |
1472 * scrollHorizontal |
1485 * x is the number of pixels to scroll |
1473 * x is the number of pixels to scroll |
1489 int w = getListWidth(); |
1477 int w = getListWidth(); |
1490 w -= ((2 * SPACE) + (2 * MARGIN)); |
1478 w -= ((2 * SPACE) + (2 * MARGIN)); |
1491 int h = height - (SCROLLBAR_AREA + (2 * MARGIN)); |
1479 int h = height - (SCROLLBAR_AREA + (2 * MARGIN)); |
1492 hsb.setValue(hsb.getValue() + x); |
1480 hsb.setValue(hsb.getValue() + x); |
1493 |
1481 |
1494 if (x < 0 && painter.isBuffer()) { |
1482 Rectangle source = null; |
1495 painter.copyArea(MARGIN + SPACE, MARGIN, w + x, h, -x, 0); |
1483 Point distance = null; |
1496 } else if (x > 0 && painter.isBuffer()) { |
1484 if (x < 0) { |
1497 painter.copyArea(MARGIN + SPACE + x, MARGIN, w - x, h, -x, 0); |
1485 source = new Rectangle(MARGIN + SPACE, MARGIN, w + x, h); |
1498 } |
1486 distance = new Point(-x, 0); |
1499 repaint(vsb.getValue(), lastItemDisplayed(), PAINT_ITEMS | PAINT_HSCROLL); |
1487 } else if (x > 0) { |
|
1488 source = new Rectangle(MARGIN + SPACE + x, MARGIN, w - x, h); |
|
1489 distance = new Point(-x, 0); |
|
1490 } |
|
1491 int options = COPY_AREA | PAINT_ITEMS | PAINT_HSCROLL; |
|
1492 repaint(vsb.getValue(), lastItemDisplayed(), options, source, distance); |
1500 } |
1493 } |
1501 |
1494 |
1502 /** |
1495 /** |
1503 * return the index |
1496 * return the index |
1504 */ |
1497 */ |
1744 XToolkit.awtUnlock(); |
1736 XToolkit.awtUnlock(); |
1745 } |
1737 } |
1746 } |
1738 } |
1747 |
1739 |
1748 private void paint(Graphics listG, int firstItem, int lastItem, int options) { |
1740 private void paint(Graphics listG, int firstItem, int lastItem, int options) { |
|
1741 paint(listG, firstItem, lastItem, options, null, null); |
|
1742 } |
|
1743 |
|
1744 private void paint(Graphics listG, int firstItem, int lastItem, int options, |
|
1745 Rectangle source, Point distance) { |
1749 if (log.isLoggable(Level.FINER)) log.finer("Repaint from " + firstItem + " to " + lastItem + " options " + options); |
1746 if (log.isLoggable(Level.FINER)) log.finer("Repaint from " + firstItem + " to " + lastItem + " options " + options); |
1750 if (firstItem > lastItem) { |
1747 if (firstItem > lastItem) { |
1751 int t = lastItem; |
1748 int t = lastItem; |
1752 lastItem = firstItem; |
1749 lastItem = firstItem; |
1753 firstItem = t; |
1750 firstItem = t; |
1771 switch (localBuffer.validate(getGraphicsConfiguration())) { |
1768 switch (localBuffer.validate(getGraphicsConfiguration())) { |
1772 case VolatileImage.IMAGE_INCOMPATIBLE: |
1769 case VolatileImage.IMAGE_INCOMPATIBLE: |
1773 invalidate(); |
1770 invalidate(); |
1774 options = PAINT_ALL; |
1771 options = PAINT_ALL; |
1775 continue; |
1772 continue; |
|
1773 case VolatileImage.IMAGE_RESTORED: |
|
1774 options = PAINT_ALL; |
1776 } |
1775 } |
1777 Graphics g = localBuffer.createGraphics(); |
1776 Graphics g = localBuffer.createGraphics(); |
1778 |
1777 |
|
1778 // Note that the order of the following painting operations |
|
1779 // should not be modified |
1779 try { |
1780 try { |
1780 g.setFont(getFont()); |
1781 g.setFont(getFont()); |
|
1782 |
|
1783 // hiding the focus rectangle must be done prior to copying |
|
1784 // area and so this is the first action to be performed |
|
1785 if ((options & (PAINT_HIDEFOCUS)) != 0) { |
|
1786 paintFocus(g, PAINT_HIDEFOCUS); |
|
1787 } |
|
1788 /* |
|
1789 * The shift of the component contents occurs while someone |
|
1790 * scrolls the component, the only purpose of the shift is to |
|
1791 * increase the painting performance. The shift should be done |
|
1792 * prior to painting any area (except hiding focus) and actually |
|
1793 * it should never be done jointly with erase background. |
|
1794 */ |
|
1795 if ((options & COPY_AREA) != 0) { |
|
1796 g.copyArea(source.x, source.y, source.width, source.height, |
|
1797 distance.x, distance.y); |
|
1798 } |
1781 if ((options & PAINT_BACKGROUND) != 0) { |
1799 if ((options & PAINT_BACKGROUND) != 0) { |
1782 g.setColor(SystemColor.window); |
1800 paintBackground(g); |
1783 g.fillRect(0, 0, width, height); |
|
1784 g.setColor(getListBackground()); |
|
1785 g.fillRect(0, 0, listWidth, listHeight); |
|
1786 draw3DRect(g, getSystemColors(), 0, 0, listWidth - 1, listHeight - 1, false); |
|
1787 // Since we made full erase update items |
1801 // Since we made full erase update items |
1788 firstItem = getFirstVisibleItem(); |
1802 firstItem = getFirstVisibleItem(); |
1789 lastItem = getLastVisibleItem(); |
1803 lastItem = getLastVisibleItem(); |
1790 } |
1804 } |
1791 if ((options & PAINT_ITEMS) != 0) { |
1805 if ((options & PAINT_ITEMS) != 0) { |
1797 } |
1811 } |
1798 if ((options & PAINT_HSCROLL) != 0 && hsbVis) { |
1812 if ((options & PAINT_HSCROLL) != 0 && hsbVis) { |
1799 g.setClip(getHScrollBarRec()); |
1813 g.setClip(getHScrollBarRec()); |
1800 paintHorScrollbar(g, true); |
1814 paintHorScrollbar(g, true); |
1801 } |
1815 } |
1802 if ((options & (PAINT_FOCUS|PAINT_HIDEFOCUS)) != 0) { |
1816 if ((options & (PAINT_FOCUS)) != 0) { |
1803 paintFocus(g, options); |
1817 paintFocus(g, PAINT_FOCUS); |
1804 } |
1818 } |
1805 } finally { |
1819 } finally { |
1806 g.dispose(); |
1820 g.dispose(); |
1807 } |
1821 } |
1808 } while (localBuffer.contentsLost()); |
1822 } while (localBuffer.contentsLost()); |
1809 listG.drawImage(localBuffer, 0, 0, null); |
1823 listG.drawImage(localBuffer, 0, 0, null); |
|
1824 } |
|
1825 |
|
1826 private void paintBackground(Graphics g) { |
|
1827 g.setColor(SystemColor.window); |
|
1828 g.fillRect(0, 0, width, height); |
|
1829 g.setColor(getListBackground()); |
|
1830 g.fillRect(0, 0, listWidth, listHeight); |
|
1831 draw3DRect(g, getSystemColors(), 0, 0, listWidth - 1, listHeight - 1, false); |
1810 } |
1832 } |
1811 |
1833 |
1812 private void paintItems(Graphics g, int firstItem, int lastItem, int options) { |
1834 private void paintItems(Graphics g, int firstItem, int lastItem, int options) { |
1813 if (log.isLoggable(Level.FINER)) log.finer("Painting items from " + firstItem + " to " + lastItem + ", focused " + focusIndex + ", first " + getFirstVisibleItem() + ", last " + getLastVisibleItem()); |
1835 if (log.isLoggable(Level.FINER)) log.finer("Painting items from " + firstItem + " to " + lastItem + ", focused " + focusIndex + ", first " + getFirstVisibleItem() + ", last " + getLastVisibleItem()); |
1814 |
1836 |
1930 g.drawRect(rect.x, rect.y, rect.width, rect.height); |
1952 g.drawRect(rect.x, rect.y, rect.width, rect.height); |
1931 prevFocusRect = rect; |
1953 prevFocusRect = rect; |
1932 } |
1954 } |
1933 g.setClip(clip); |
1955 g.setClip(clip); |
1934 } |
1956 } |
1935 |
|
1936 public void copyArea(int x, int y, int width, int height, int dx, int dy) { |
|
1937 if (log.isLoggable(Level.FINER)) log.finer("Copying area " + x + ", " + y + " " + width + |
|
1938 "x" + height + ", (" + dx + "," + dy + ")"); |
|
1939 VolatileImage localBuffer = null; |
|
1940 do { |
|
1941 XToolkit.awtLock(); |
|
1942 try { |
|
1943 if (createBuffer()) { |
|
1944 // Newly created buffer should be painted over at full |
|
1945 repaint(PAINT_ALL); |
|
1946 return; |
|
1947 } |
|
1948 localBuffer = buffer; |
|
1949 } finally { |
|
1950 XToolkit.awtUnlock(); |
|
1951 } |
|
1952 switch (localBuffer.validate(getGraphicsConfiguration())) { |
|
1953 case VolatileImage.IMAGE_INCOMPATIBLE: |
|
1954 invalidate(); |
|
1955 case VolatileImage.IMAGE_RESTORED: |
|
1956 // Since we've lost the content we can't just scroll - we should paint again |
|
1957 repaint(PAINT_ALL); |
|
1958 return; |
|
1959 } |
|
1960 Graphics g = localBuffer.createGraphics(); |
|
1961 try { |
|
1962 g.copyArea(x, y, width, height, dx, dy); |
|
1963 } finally { |
|
1964 g.dispose(); |
|
1965 } |
|
1966 } while (localBuffer.contentsLost()); |
|
1967 Graphics listG = getGraphics(); |
|
1968 listG.setClip(x, y, width, height); |
|
1969 listG.drawImage(localBuffer, 0, 0, null); |
|
1970 listG.dispose(); |
|
1971 } |
|
1972 |
|
1973 public boolean isBuffer() { |
|
1974 boolean isBuffer; |
|
1975 XToolkit.awtLock(); |
|
1976 try { |
|
1977 isBuffer = (buffer != null); |
|
1978 } finally { |
|
1979 XToolkit.awtUnlock(); |
|
1980 } |
|
1981 return isBuffer; |
|
1982 } |
|
1983 } |
1957 } |
1984 } |
1958 } |