/**
  * Returns the location where to dock the given {@code JToolBar}, at the given constraint
  * position. The constraint position must be one of the constants {@code BorderLayout.NORTH
  * NORTH}, {@code BorderLayout.EAST EAST}, {@code BorderLayout.SOUTH SOUTH}, or {@code
  * BorderLayout.WEST WEST}.
  *
  * <p><b>Note:</b> This method is accessed in the current executing thread. Such thread may or may
  * not be the event dispatch thread (EDT.) Client code must call this method from the EDT.
  *
  * @param toolBar the target {@code JToolBar}.
  * @param dock the container where to dock the {@code JToolBar} to.
  * @param constraint the constraint position.
  * @return the location where to dock the given {@code JToolBar}.
  * @throws IllegalArgumentException if the constraint has an invalid value.
  */
 @RunsInCurrentThread
 public @Nonnull Point dockLocation(
     @Nonnull JToolBar toolBar, @Nonnull Container dock, @Nonnull String constraint) {
   checkValid(constraint);
   Insets insets = dock.getInsets();
   // BasicToolBarUI prioritizes location N/E/W/S by proximity to the respective border. Close to
   // top border is N, even
   // if close to the left or right border.
   int offset = isHorizontal(toolBar) ? toolBar.getHeight() : toolBar.getWidth();
   Dimension dockSize = dock.getSize();
   if (NORTH.equals(constraint)) {
     return new Point(dockSize.width / 2, insets.top);
   }
   if (EAST.equals(constraint)) {
     return new Point(
         dockSize.width - insets.right - 1,
         verticalDockingYCoordinate(dockSize.height, insets, offset));
   }
   if (WEST.equals(constraint)) {
     return new Point(insets.left, verticalDockingYCoordinate(dockSize.height, insets, offset));
   }
   int x = dockSize.width / 2;
   // Make sure we don't get mistaken for EAST or WEST
   if (x < insets.left + offset) {
     x = insets.left + offset;
   } else if (x > dockSize.width - insets.right - offset - 1) {
     x = dockSize.width - insets.right - offset - 1;
   }
   return new Point(x, dockSize.height - insets.bottom - 1);
 }
 /**
  * Returns the point where to grab the given {@code JToolBar}.
  *
  * <p><b>Note:</b> This method is accessed in the current executing thread. Such thread may or may
  * not be the event dispatch thread (EDT.) Client code must call this method from the EDT.
  *
  * @param toolBar the target {@code JToolBar}.
  * @return the point where to grab the given {@code JToolBar}.
  */
 @RunsInCurrentThread
 public @Nonnull Point pointToGrab(@Nonnull JToolBar toolBar) {
   Insets insets = toolBar.getInsets();
   int width = toolBar.getWidth();
   int height = toolBar.getHeight();
   if (max(max(max(insets.left, insets.top), insets.right), insets.bottom) == insets.left) {
     return new Point(insets.left / 2, height / 2);
   }
   if (max(max(insets.top, insets.right), insets.bottom) == insets.top) {
     return new Point(width / 2, insets.top / 2);
   }
   if (max(insets.right, insets.bottom) == insets.right) {
     return new Point(width - insets.right / 2, height / 2);
   }
   return new Point(width / 2, height - insets.bottom / 2);
 }
    public void layoutContainer(Container parent) {
      JToolBar tb = (JToolBar) parent;
      Insets insets = tb.getInsets();
      boolean ltr = tb.getComponentOrientation().isLeftToRight();
      SeaGlassContext context = getContext(tb);

      Component c;
      Dimension d;

      // JToolBar by default uses a somewhat modified BoxLayout as
      // its layout manager. For compatibility reasons, we want to
      // support Box "glue" as a way to move things around on the
      // toolbar. "glue" is represented in BoxLayout as a Box.Filler
      // with a minimum and preferred size of (0,0).
      // So what we do here is find the number of such glue fillers
      // and figure out how much space should be allocated to them.
      int glueCount = 0;
      for (int i = 0; i < tb.getComponentCount(); i++) {
        if (isGlue(tb.getComponent(i))) glueCount++;
      }

      if (tb.getOrientation() == JToolBar.HORIZONTAL) {
        int handleWidth = tb.isFloatable() ? SeaGlassIcon.getIconWidth(handleIcon, context) : 0;

        // Note: contentRect does not take insets into account
        // since it is used for determining the bounds that are
        // passed to paintToolBarContentBackground().
        contentRect.x = ltr ? handleWidth : 0;
        contentRect.y = 0;
        contentRect.width = tb.getWidth() - handleWidth;
        contentRect.height = tb.getHeight();

        // However, we do take the insets into account here for
        // the purposes of laying out the toolbar child components.
        int x = ltr ? handleWidth + insets.left : tb.getWidth() - handleWidth - insets.right;
        int baseY = insets.top;
        int baseH = tb.getHeight() - insets.top - insets.bottom;

        // we need to get the minimum width for laying things out
        // so that we can calculate how much empty space needs to
        // be distributed among the "glue", if any
        int extraSpacePerGlue = 0;
        if (glueCount > 0) {
          int minWidth = minimumLayoutSize(parent).width;
          extraSpacePerGlue = (tb.getWidth() - minWidth) / glueCount;
          if (extraSpacePerGlue < 0) extraSpacePerGlue = 0;
        }

        for (int i = 0; i < tb.getComponentCount(); i++) {
          c = tb.getComponent(i);
          if (c.isVisible()) {
            d = c.getPreferredSize();
            int y, h;
            if (d.height >= baseH || c instanceof JSeparator) {
              // Fill available height
              y = baseY;
              h = baseH;
            } else {
              // Center component vertically in the available
              // space
              y = baseY + (baseH / 2) - (d.height / 2);
              h = d.height;
            }
            // if the component is a "glue" component then add to
            // its
            // width the extraSpacePerGlue it is due
            if (isGlue(c)) d.width += extraSpacePerGlue;
            c.setBounds(ltr ? x : x - d.width, y, d.width, h);
            x = ltr ? x + d.width : x - d.width;
          }
        }
      } else {
        int handleHeight = tb.isFloatable() ? SeaGlassIcon.getIconHeight(handleIcon, context) : 0;

        // See notes above regarding the use of insets
        contentRect.x = 0;
        contentRect.y = handleHeight;
        contentRect.width = tb.getWidth();
        contentRect.height = tb.getHeight() - handleHeight;

        int baseX = insets.left;
        int baseW = tb.getWidth() - insets.left - insets.right;
        int y = handleHeight + insets.top;

        // we need to get the minimum height for laying things out
        // so that we can calculate how much empty space needs to
        // be distributed among the "glue", if any
        int extraSpacePerGlue = 0;
        if (glueCount > 0) {
          int minHeight = minimumLayoutSize(parent).height;
          extraSpacePerGlue = (tb.getHeight() - minHeight) / glueCount;
          if (extraSpacePerGlue < 0) extraSpacePerGlue = 0;
        }

        for (int i = 0; i < tb.getComponentCount(); i++) {
          c = tb.getComponent(i);
          if (c.isVisible()) {
            d = c.getPreferredSize();
            int x, w;
            if (d.width >= baseW || c instanceof JSeparator) {
              // Fill available width
              x = baseX;
              w = baseW;
            } else {
              // Center component horizontally in the available
              // space
              x = baseX + (baseW / 2) - (d.width / 2);
              w = d.width;
            }
            // if the component is a "glue" component then add to
            // its
            // height the extraSpacePerGlue it is due
            if (isGlue(c)) d.height += extraSpacePerGlue;
            c.setBounds(x, y, w, d.height);
            y += d.height;
          }
        }
      }
      context.dispose();
    }