repaintmanager.java

来自「linux下建立JAVA虚拟机的源码KAFFE」· Java 代码 · 共 784 行 · 第 1/2 页

JAVA
784
字号
  /**   * Add a region to the set of dirty regions for a specified component.   * This involves union'ing the new region with any existing dirty region   * associated with the component. If the {@link #repaintWorker} class   * is not active, insert it in the system event queue.   *   * @param component The component to add a dirty region for   * @param x The left x coordinate of the new dirty region   * @param y The top y coordinate of the new dirty region   * @param w The width of the new dirty region   * @param h The height of the new dirty region   *   * @see #addDirtyRegion   * @see #getDirtyRegion   * @see #isCompletelyDirty   * @see #markCompletelyClean   * @see #markCompletelyDirty   */  public void addDirtyRegion(JComponent component, int x, int y,                             int w, int h)  {    if (w <= 0 || h <= 0 || !component.isShowing())      return;    component.computeVisibleRect(rectCache);    SwingUtilities.computeIntersection(x, y, w, h, rectCache);    if (! rectCache.isEmpty())      {        if (dirtyComponents.containsKey(component))          {            SwingUtilities.computeUnion(rectCache.x, rectCache.y,                                        rectCache.width, rectCache.height,                                   (Rectangle) dirtyComponents.get(component));          }        else          {            synchronized (dirtyComponents)              {                dirtyComponents.put(component, rectCache.getBounds());              }          }        if (! repaintWorker.isLive())          {            repaintWorker.setLive(true);            SwingUtilities.invokeLater(repaintWorker);          }      }  }  /**   * Get the dirty region associated with a component, or <code>null</code>   * if the component has no dirty region.   *   * @param component The component to get the dirty region of   *   * @return The dirty region of the component   *   * @see #dirtyComponents   * @see #addDirtyRegion   * @see #isCompletelyDirty   * @see #markCompletelyClean   * @see #markCompletelyDirty   */  public Rectangle getDirtyRegion(JComponent component)  {    Rectangle dirty = (Rectangle) dirtyComponents.get(component);    if (dirty == null)      dirty = new Rectangle();    return dirty;  }    /**   * Mark a component as dirty over its entire bounds.   *   * @param component The component to mark as dirty   *   * @see #dirtyComponents   * @see #addDirtyRegion   * @see #getDirtyRegion   * @see #isCompletelyDirty   * @see #markCompletelyClean   */  public void markCompletelyDirty(JComponent component)  {    Rectangle r = component.getBounds();    addDirtyRegion(component, r.x, r.y, r.width, r.height);    component.isCompletelyDirty = true;  }  /**   * Remove all dirty regions for a specified component   *   * @param component The component to mark as clean   *   * @see #dirtyComponents   * @see #addDirtyRegion   * @see #getDirtyRegion   * @see #isCompletelyDirty   * @see #markCompletelyDirty   */  public void markCompletelyClean(JComponent component)  {    synchronized (dirtyComponents)      {        dirtyComponents.remove(component);      }    component.isCompletelyDirty = false;  }  /**   * Return <code>true</code> if the specified component is completely   * contained within its dirty region, otherwise <code>false</code>   *   * @param component The component to check for complete dirtyness   *   * @return Whether the component is completely dirty   *   * @see #dirtyComponents   * @see #addDirtyRegion   * @see #getDirtyRegion   * @see #isCompletelyDirty   * @see #markCompletelyClean   */  public boolean isCompletelyDirty(JComponent component)  {    if (! dirtyComponents.containsKey(component))      return false;    return component.isCompletelyDirty;  }  /**   * Validate all components which have been marked invalid in the {@link   * #invalidComponents} vector.   */  public void validateInvalidComponents()  {    // We don't use an iterator here because that would fail when there are    // components invalidated during the validation of others, which happens    // quite frequently. Instead we synchronize the access a little more.    while (invalidComponents.size() > 0)      {        Component comp;        synchronized (invalidComponents)          {            comp = (Component) invalidComponents.remove(0);          }        // Validate the validate component.        if (! (comp.isVisible() && comp.isShowing()))          continue;        comp.validate();      }  }  /**   * Repaint all regions of all components which have been marked dirty in   * the {@link #dirtyComponents} table.   */  public void paintDirtyRegions()  {    // Short cicuit if there is nothing to paint.    if (dirtyComponents.size() == 0)      return;    synchronized (dirtyComponents)      {        // We sort the components by their size here. This way we have a good        // chance that painting the bigger components also paints the smaller        // components and we don't need to paint them twice.        ArrayList repaintOrder = new ArrayList(dirtyComponents.size());        repaintOrder.addAll(dirtyComponents.keySet());        if (comparator == null)          comparator = new ComponentComparator();        Collections.sort(repaintOrder, comparator);        repaintUnderway = true;        for (Iterator i = repaintOrder.iterator(); i.hasNext();)          {            JComponent comp = (JComponent) i.next();            // If a component is marked completely clean in the meantime, then skip            // it.            Rectangle damaged = (Rectangle) dirtyComponents.get(comp);            if (damaged == null || damaged.isEmpty())              continue;            comp.paintImmediately(damaged);            dirtyComponents.remove(comp);          }        repaintUnderway = false;        commitRemainingBuffers();      }  }  /**   * Get an offscreen buffer for painting a component's image. This image   * may be smaller than the proposed dimensions, depending on the value of   * the {@link #doubleBufferMaximumSize} property.   *   * @param component The component to return an offscreen buffer for   * @param proposedWidth The proposed width of the offscreen buffer   * @param proposedHeight The proposed height of the offscreen buffer   *   * @return A shared offscreen buffer for painting   */  public Image getOffscreenBuffer(Component component, int proposedWidth,                                  int proposedHeight)  {    Component root = SwingUtilities.getRoot(component);    Image buffer = (Image) offscreenBuffers.get(root);    if (buffer == null         || buffer.getWidth(null) < proposedWidth         || buffer.getHeight(null) < proposedHeight)      {        int width = Math.max(proposedWidth, root.getWidth());        width = Math.min(doubleBufferMaximumSize.width, width);        int height = Math.max(proposedHeight, root.getHeight());        height = Math.min(doubleBufferMaximumSize.height, height);        buffer = component.createImage(width, height);        offscreenBuffers.put(root, buffer);      }    return buffer;  }  /**   * Blits the back buffer of the specified root component to the screen. If   * the RepaintManager is currently working on a paint request, the commit   * requests are queued up and committed at once when the paint request is   * done (by {@link #commitRemainingBuffers}). This is package private because   * it must get called by JComponent.   *   * @param root the component, either a Window or an Applet instance   * @param area the area to paint on screen   */  void commitBuffer(Component root, Rectangle area)  {    // We synchronize on dirtyComponents here because that is what    // paintDirtyRegions also synchronizes on while painting.    synchronized (dirtyComponents)      {        // If the RepaintManager is not currently painting, then directly        // blit the requested buffer on the screen.        if (! repaintUnderway)          {            Graphics g = root.getGraphics();            Image buffer = (Image) offscreenBuffers.get(root);            Rectangle clip = g.getClipBounds();            if (clip != null)              area = SwingUtilities.computeIntersection(clip.x, clip.y,                                                        clip.width, clip.height,                                                        area);            int dx1 = area.x;            int dy1 = area.y;            int dx2 = area.x + area.width;            int dy2 = area.y + area.height;            // Make sure we have a sane clip at this point.            g.clipRect(area.x, area.y, area.width, area.height);            // Make sure the coordinates are inside the buffer, everything else            // might lead to problems.            // TODO: This code should not really be necessary, however, in fact            // we have two issues here:            // 1. We shouldn't get repaint requests in areas outside the buffer            //    region in the first place. This still happens for example            //    when a component is inside a JViewport, and the component has            //    a size that would reach beyond the window size.            // 2. Graphics.drawImage() should not behave strange when trying            //    to draw regions outside the image.            int bufferWidth = buffer.getWidth(root);            int bufferHeight = buffer.getHeight(root);            dx1 = Math.min(bufferWidth, dx1);            dy1 = Math.min(bufferHeight, dy1);            dx2 = Math.min(bufferWidth, dx2);            dy2 = Math.min(bufferHeight, dy2);            g.drawImage(buffer, dx1, dy1, dx2, dy2,                                dx1, dy1, dx2, dy2, root);            g.dispose();          }        // Otherwise queue this request up, until all the RepaintManager work        // is done.        else          {            if (commitRequests.containsKey(root))              SwingUtilities.computeUnion(area.x, area.y, area.width,                                          area.height,                                         (Rectangle) commitRequests.get(root));            else              commitRequests.put(root, area);          }      }  }  /**   * Commits the queued up back buffers to screen all at once.   */  private void commitRemainingBuffers()  {    // We synchronize on dirtyComponents here because that is what    // paintDirtyRegions also synchronizes on while painting.    synchronized (dirtyComponents)      {        Set entrySet = commitRequests.entrySet();        Iterator i = entrySet.iterator();        while (i.hasNext())          {            Map.Entry entry = (Map.Entry) i.next();            Component root = (Component) entry.getKey();            Rectangle area = (Rectangle) entry.getValue();            commitBuffer(root, area);            i.remove();          }      }  }  /**   * Creates and returns a volatile offscreen buffer for the specified   * component that can be used as a double buffer. The returned image   * is a {@link VolatileImage}. Its size will be <code>(proposedWidth,   * proposedHeight)</code> except when the maximum double buffer size   * has been set in this RepaintManager.   *   * @param comp the Component for which to create a volatile buffer   * @param proposedWidth the proposed width of the buffer   * @param proposedHeight the proposed height of the buffer   *   * @since 1.4   *   * @see VolatileImage   */  public Image getVolatileOffscreenBuffer(Component comp, int proposedWidth,                                          int proposedHeight)  {    int maxWidth = doubleBufferMaximumSize.width;    int maxHeight = doubleBufferMaximumSize.height;    return comp.createVolatileImage(Math.min(maxWidth, proposedWidth),                                    Math.min(maxHeight, proposedHeight));  }    /**   * Get the value of the {@link #doubleBufferMaximumSize} property.   *   * @return The current value of the property   *   * @see #setDoubleBufferMaximumSize   */  public Dimension getDoubleBufferMaximumSize()  {    return doubleBufferMaximumSize;  }  /**   * Set the value of the {@link #doubleBufferMaximumSize} property.   *   * @param size The new value of the property   *   * @see #getDoubleBufferMaximumSize   */  public void setDoubleBufferMaximumSize(Dimension size)  {    doubleBufferMaximumSize = size;  }  /**   * Set the value of the {@link #doubleBufferingEnabled} property.   *   * @param buffer The new value of the property   *   * @see #isDoubleBufferingEnabled   */  public void setDoubleBufferingEnabled(boolean buffer)  {    doubleBufferingEnabled = buffer;  }  /**   * Get the value of the {@link #doubleBufferingEnabled} property.   *   * @return The current value of the property   *   * @see #setDoubleBufferingEnabled   */  public boolean isDoubleBufferingEnabled()  {    return doubleBufferingEnabled;  }    public String toString()  {    return "RepaintManager";  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?