Pastebin is 300% more awesome when you are logged in. Sign Up, it's FREE!
Guest

JScrollNavigator Paint Corruption

By: a guest on Aug 3rd, 2012  |  syntax: Java  |  size: 7.98 KB  |  hits: 42  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package gsa.flow.ui.util;
  2.  
  3. import javax.swing.*;
  4. import javax.swing.border.LineBorder;
  5. import java.awt.*;
  6. import java.awt.event.*;
  7. import java.awt.image.BufferedImage;
  8.  
  9. public class JScrollNavigator extends JPanel implements ComponentListener, AdjustmentListener {
  10.  
  11.     private JScrollPane jScrollPane;
  12.  
  13.     private NavBox overBox = new NavBox();
  14.  
  15.     boolean isAdjusting = false;
  16.  
  17.     public JScrollNavigator() {
  18.  
  19.         this.setSize(new Dimension(80, 100));
  20.  
  21.         setBackground(Color.BLACK);
  22.  
  23.         setLayout(null);
  24.         add(overBox);
  25.  
  26.         overBox.setOpaque(false);
  27.  
  28.         addComponentListener(new ComponentAdapter() {
  29.  
  30.             public void componentResized(ComponentEvent e) {
  31.                 updateOverBox();
  32.             }
  33.  
  34.         });
  35.  
  36.         overBox.addComponentListener(this);
  37.     }
  38.  
  39.     public void setJScrollPane(JScrollPane jScrollPane) {
  40.         this.jScrollPane = jScrollPane;
  41.  
  42.         Component view = jScrollPane.getViewport().getView();
  43.  
  44.         if(view != null) {
  45.             view.addComponentListener(this);
  46.             jScrollPane.getViewport().addComponentListener(this);
  47.             jScrollPane.getHorizontalScrollBar().addAdjustmentListener(this);
  48.             jScrollPane.getVerticalScrollBar().addAdjustmentListener(this);
  49.             updateOverBox();
  50.         }
  51.  
  52.     }
  53.  
  54.     private void updateOverBox() {
  55.         isAdjusting = true;
  56.  
  57.         JViewport viewport = this.jScrollPane.getViewport();
  58.  
  59.         Dimension d = viewport.getViewSize();
  60.         Rectangle vRect = viewport.getViewRect();
  61.  
  62.         int vWidth = d.width;
  63.         int vHeight = d.height;
  64.  
  65.         int w = getWidth();
  66.         int h = getHeight();
  67.  
  68.         float xMult = (float) w / vWidth;
  69.         float yMult = (float) h / vHeight;
  70.  
  71.         int newX = (int) (vRect.x * xMult);
  72.         int newY = (int) (vRect.y * yMult);
  73.         int newW = (int) (vRect.width * xMult);
  74.         int newH = (int) (vRect.height * yMult);
  75.  
  76.         overBox.setLocation(newX, newY);
  77.         overBox.setSize(newW, newH);
  78.  
  79.         isAdjusting = false;
  80.  
  81.     }
  82.  
  83.     /**
  84.      * @param args
  85.      */
  86.     public static void main(String[] args) {
  87.         SwingUtilities.invokeLater(new Runnable() {
  88.             @Override
  89.             public void run() {
  90.                 JScrollPane jsp = new JScrollPane();
  91.                 JTextPane blueEditorPane = new JTextPane();
  92.  
  93.                 StringBuffer buffer = new StringBuffer();
  94.                 for(int i = 0; i < 10; i++) {
  95.                     for(int j = 0; j < 4; ++j) {
  96.                         buffer.append("test" + i + ", " + j);
  97.                     }
  98.  
  99.                     if(i == 5) {
  100.                         for(int j = 0; j < 5; ++j) {
  101.                             buffer.append("\n");
  102.                         }
  103.                     }
  104.                     buffer.append("\n");
  105.                 }
  106.                 blueEditorPane.setText(buffer.toString());
  107.  
  108.                 //jsp.setViewportView(blueEditorPane);
  109.                 jsp.setViewportView(new JPanel() {
  110.                     {
  111.                         setBackground(Color.GREEN);
  112.                         setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
  113.                     }
  114.                 });
  115.  
  116.                 JScrollNavigator nav = new JScrollNavigator();
  117.                 nav.setJScrollPane(jsp);
  118.  
  119.                 JFrame f = new JFrame();
  120.                 JMenuBar bar = new JMenuBar();
  121.                 bar.add(new JMenu("File"));
  122.                 f.setJMenuBar(bar);
  123.  
  124.                 f.getContentPane().add(jsp);
  125.                 nav.setPreferredSize(new Dimension(100, 100));
  126.                 f.getContentPane().add(nav, BorderLayout.WEST);
  127.                 f.setSize(300, 200);
  128.                 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  129.                 f.setVisible(true);
  130.             }
  131.         });
  132.     }
  133.  
  134.     @Override
  135.     protected void paintComponent(Graphics g) {
  136.         super.paintComponent(g);
  137.         Component view = jScrollPane.getViewport().getView();
  138.         BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
  139.         Graphics2D g2d = img.createGraphics();
  140.         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  141.  
  142.         // Paint JScrollPane view to off-screen image and then scale.
  143.         // It is this action that causes the display corruption!
  144.         view.paint(g2d);
  145.         g2d.drawImage(img, 0, 0, null);
  146.         Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
  147.  
  148.         g.drawImage(scaled, 0, 0, null);
  149.     }
  150.  
  151.     public void componentResized(ComponentEvent e) {
  152.         if(e.getSource() == jScrollPane.getViewport() || e.getSource() == jScrollPane.getViewport().getView()) {
  153.             updateOverBox();
  154.         }
  155.     }
  156.  
  157.     public void componentMoved(ComponentEvent e) {
  158.         if(e.getSource() == overBox) {
  159.             isAdjusting = true;
  160.  
  161.             Rectangle r = overBox.getBounds();
  162.  
  163.             JViewport viewport = this.jScrollPane.getViewport();
  164.             Dimension d = viewport.getViewSize();
  165.  
  166.             int vWidth = d.width;
  167.             int vHeight = d.height;
  168.  
  169.             int w = getWidth();
  170.             int h = getHeight();
  171.  
  172.             float xMult = (float) vWidth / w;
  173.             float yMult = (float) vHeight / h;
  174.  
  175.             int newX = (int) (r.x * xMult);
  176.             int newY = (int) (r.y * yMult);
  177.             int newW = (int) (r.width * xMult);
  178.             int newH = (int) (r.height * yMult);
  179.  
  180.             Rectangle newRect = new Rectangle(newX, newY, newW, newH);
  181.  
  182.             ((JComponent) viewport.getView()).scrollRectToVisible(newRect);
  183.  
  184.             isAdjusting = false;
  185.         }
  186.     }
  187.  
  188.     public void componentShown(ComponentEvent e) {
  189.     }
  190.  
  191.     public void componentHidden(ComponentEvent e) {
  192.     }
  193.  
  194.     public void adjustmentValueChanged(AdjustmentEvent e) {
  195.         if(!isAdjusting) {
  196.             updateOverBox();
  197.         }
  198.     }
  199.  
  200.     class NavBox extends JPanel {
  201.         boolean dragging = false;
  202.  
  203.         Point origin = null;
  204.  
  205.         int originX = -1;
  206.  
  207.         int originY = -1;
  208.  
  209.         public NavBox() {
  210.             this.setBorder(new LineBorder(Color.GREEN, 1));
  211.  
  212.             this.addMouseListener(new MouseAdapter() {
  213.  
  214.                 public void mousePressed(MouseEvent e) {
  215.                     origin = SwingUtilities.convertPoint(NavBox.this, e.getPoint(), NavBox.this.getParent());
  216.                     originX = NavBox.this.getX();
  217.                     originY = NavBox.this.getY();
  218.                 }
  219.  
  220.                 public void mouseReleased(MouseEvent e) {
  221.                     origin = null;
  222.                     originX = -1;
  223.                     originY = -1;
  224.                 }
  225.  
  226.             });
  227.  
  228.             this.addMouseMotionListener(new MouseMotionAdapter() {
  229.  
  230.                 public void mouseDragged(MouseEvent e) {
  231.                     NavBox box = NavBox.this;
  232.                     Container c = box.getParent();
  233.  
  234.                     int leftBound = -originX;
  235.                     int rightBound = c.getWidth() - box.getWidth() - originX;
  236.                     int topBound = -originY;
  237.                     int bottomBound = c.getHeight() - box.getHeight() - originY;
  238.  
  239.                     Point p = SwingUtilities.convertPoint(box, e.getPoint(), c);
  240.  
  241.                     int xDiff = p.x - origin.x;
  242.                     int yDiff = p.y - origin.y;
  243.  
  244.                     if(xDiff < leftBound) {
  245.                         xDiff = leftBound;
  246.                     }
  247.  
  248.                     if(xDiff > rightBound) {
  249.                         xDiff = rightBound;
  250.                     }
  251.  
  252.                     if(yDiff < topBound) {
  253.                         yDiff = topBound;
  254.                     }
  255.  
  256.                     if(yDiff > bottomBound) {
  257.                         yDiff = bottomBound;
  258.                     }
  259.  
  260.                     box.setLocation(originX + xDiff, originY + yDiff);
  261.                 }
  262.  
  263.             });
  264.         }
  265.     }
  266.  
  267. }