/**
  * Paints a line at the current location of the divider.
  *
  * @param g the Graphics used to paint
  */
 public void paint(Graphics g) {
   if (station.isResizingEnabled() && !station.isDisabled()) {
     if (current != null && pressed) {
       station.getPaint().drawDivider(g, bounds);
     }
   }
 }
    public void install(Component container) {
      if (this.container != null) {
        throw new IllegalStateException("already initialized");
      }
      this.container = container;
      container.addMouseListener(this);
      container.addMouseMotionListener(this);

      station.addDockHierarchyListener(this);
      setController(station.getController());
    }
    public void mouseDragged(MouseEvent e) {
      if (station.isResizingEnabled() && !station.isDisabled()) {
        if (pressed && current != null) {
          divider = current.getDividerAt(e.getX() + deltaX, e.getY() + deltaY);
          divider = current.validateDivider(divider);
          repaint(bounds.x, bounds.y, bounds.width, bounds.height);
          bounds = current.getDividerBounds(divider, bounds);
          repaint(bounds.x, bounds.y, bounds.width, bounds.height);

          if (station.isContinousDisplay() && current != null) {
            setDivider(current, divider);
            station.updateBounds();
          }
        }
      }
    }
 @Override
 public void mousePressed(MouseEvent e) {
   if (station.isResizingEnabled() && !station.isDisabled()) {
     if (!pressed) {
       pressed = true;
       mouseMoved(e);
       if (current != null) {
         divider = current.getDividerAt(e.getX() + deltaX, e.getY() + deltaY);
         divider = current.validateDivider(divider);
         repaint(bounds.x, bounds.y, bounds.width, bounds.height);
         bounds = current.getDividerBounds(divider, bounds);
         repaint(bounds.x, bounds.y, bounds.width, bounds.height);
       }
     }
   }
 }
    /**
     * Asynchronously checks the current position of the mouse and updates the cursor if necessary.
     */
    protected void checkMousePositionAsync() {
      DockController controller = station.getController();
      if (controller != null && !awtListenerEnabled) {
        SwingUtilities.invokeLater(
            new Runnable() {
              public void run() {
                if (container != null) {
                  PointerInfo p = MouseInfo.getPointerInfo();
                  Point e = p.getLocation();
                  SwingUtilities.convertPointFromScreen(e, container);
                  current = getDividerNode(e.x, e.y);

                  if (current == null) {
                    mouseExited(null);
                  } else {
                    // check bounds with one pixel delta -> divider needs to be greater than 2
                    // pixels, because divider bounds will be shrinked by 1 pixel at each side
                    if (bounds.width > 2 && bounds.height > 2) {
                      if (e.x <= bounds.x
                          || e.x >= bounds.x + bounds.width - 1
                          || e.y <= bounds.y
                          || e.y >= bounds.y + bounds.height - 1) {
                        // mouse is likely to be not on divider anymore
                        mouseExited(null);
                      }
                    }
                  }
                }
              }
            });
      }
    }
    public void mouseMoved(MouseEvent e) {
      if (station.isResizingEnabled()) {
        current = station.getRoot().getDividerNode(e.getX(), e.getY());

        if (current == null) setCursor(null);
        else if (current.getOrientation() == Orientation.HORIZONTAL)
          setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
        else setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));

        if (current != null) {
          bounds = current.getDividerBounds(current.getDivider(), bounds);
          deltaX = bounds.width / 2 + bounds.x - e.getX();
          deltaY = bounds.height / 2 + bounds.y - e.getY();
        }
      }
    }
 @Override
 public void mouseExited(MouseEvent e) {
   if (station.isResizingEnabled()) {
     if (!pressed) {
       current = null;
       setCursor(null);
     }
   }
 }
    public void mouseMoved(MouseEvent e) {
      if (station.isResizingEnabled() && !station.isDisabled()) {
        current = getDividerNode(e.getX(), e.getY());

        if (current == null) setCursor(null);
        else if (current.getOrientation() == Orientation.HORIZONTAL)
          setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
        else setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));

        if (current != null) {
          bounds = current.getDividerBounds(current.getActualDivider(), bounds);
          deltaX = bounds.width / 2 + bounds.x - e.getX();
          deltaY = bounds.height / 2 + bounds.y - e.getY();

          // mouse is over divider
          withinBounds = true;
        } else {
          // mouse is not over divider anymore
          withinBounds = false;
        }
      }
    }
 @Override
 public void mouseReleased(MouseEvent e) {
   if (pressed) {
     pressed = false;
     if (current != null) {
       current.setDivider(divider);
       repaint(bounds.x, bounds.y, bounds.width, bounds.height);
       station.updateBounds();
     }
     setCursor(null);
     mouseMoved(e);
     checkMousePositionAsync();
   }
 }
    /** Disposes all resources that are used by this handler. */
    public void destroy() {
      if (container != null) {
        setCursor(null);
        current = null;
        container.removeMouseListener(this);
        container.removeMouseMotionListener(this);
        container = null;

        try {
          java.awt.Toolkit.getDefaultToolkit().removeAWTEventListener(this);
        } catch (Throwable e) {
          e.printStackTrace();
        }

        setController(null);
        station.removeDockHierarchyListener(this);
      }
    }
    /**
     * Asynchronously checks the current position of the mouse and updates the cursor if necessary.
     */
    protected void checkMousePositionAsync() {
      DockController controller = station.getController();
      if (controller != null && !controller.isRestrictedEnvironment()) {
        SwingUtilities.invokeLater(
            new Runnable() {
              public void run() {
                if (container != null) {
                  PointerInfo p = MouseInfo.getPointerInfo();
                  Point e = p.getLocation();
                  SwingUtilities.convertPointFromScreen(e, container);
                  current = station.getRoot().getDividerNode(e.x, e.y);

                  if (current == null) {
                    setCursor(null);
                  }
                }
              }
            });
      }
    }
    @Override
    public void mouseReleased(MouseEvent e) {
      if (pressed) {
        pressed = false;
        if (current != null) {
          setDivider(current, divider);
          repaint(bounds.x, bounds.y, bounds.width, bounds.height);
          station.updateBounds();
        }
        setCursor(null);
        mouseMoved(e);

        if (controller != null && !controller.isRestrictedEnvironment() && awtListenerEnabled) {
          // new solution
          eventDispatched(e);
        } else {
          // old solution with a little tweaking
          checkMousePositionAsync();
        }
      }
    }
    /**
     * AWT event listener. Used to reset the mouse cursor when divider was changed and mouse exited
     * event had not occurred normally.
     *
     * @param event
     */
    public void eventDispatched(AWTEvent event) {
      if (event.getID() == MouseEvent.MOUSE_MOVED || event.getID() == MouseEvent.MOUSE_RELEASED) {
        MouseEvent mev = (MouseEvent) event;
        if (mev.getSource() != Handler.this.container && withinBounds) {
          if (mev.getSource() instanceof GlassedPane.GlassPane) {
            // on glass pane -> check with traditional method

            // Question by Beni: does this ever happen?
            checkMousePositionAsync();
          } else {
            // mouse is over another component which is not the registered container and the mouse
            // cursor had not been reseted yet -> reset mouse cursor
            Point p = SwingUtilities.convertPoint(mev.getComponent(), mev.getPoint(), station);
            if (station.getBounds().contains(p)) {
              // only if mouse is within our station
              setCursor(null);
              withinBounds = false;
            }
          }
        }
      }
    }
 /**
  * Gets the node whose dividier contains <code>x, y</code>.
  *
  * @param x the x coordinate
  * @param y the y coordinate
  * @return the node containing <code>x, y</code>
  */
 protected Divideable getDividerNode(int x, int y) {
   return station.getRoot().getDividerNode(x, y);
 }
 public void controllerChanged(DockHierarchyEvent event) {
   setController(station.getController());
 }