private static JMenu getMoveToMenuItems(final DockingWindow window) {
    JMenu moveToMenu = new JMenu("Move to Window Bar");

    if (window.isMinimizable()) {
      final RootWindow root = window.getRootWindow();
      final Direction[] directions = Direction.getDirections();

      for (int i = 0; i < 4; i++) {
        final Direction dir = directions[i];

        if (!DockingUtil.isAncestor(root.getWindowBar(dir), window)
            && root.getWindowBar(dir).isEnabled()) {
          moveToMenu
              .add(new JMenuItem(dir.getName(), ARROW_ICONS[i]))
              .addActionListener(
                  new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                      root.getWindowBar(dir).addTab(window);
                    }
                  });
        }
      }
    }

    return moveToMenu;
  }
  private static void addTabDirectionMenuItems(JPopupMenu menu, DockingWindow window) {
    final AbstractTabWindow tabWindow = getTabWindowFor(window);

    if (tabWindow == null) return;

    JMenu directionMenu = new JMenu("Tab Direction");
    TitledTabProperties properties = TitledTabProperties.getDefaultProperties();
    properties.addSuperObject(
        tabWindow.getTabWindowProperties().getTabProperties().getTitledTabProperties());
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++) {
      final Direction dir = directions[i];

      if (dir != Direction.LEFT) {
        JMenuItem item = directionMenu.add(new JMenuItem(dir.getName(), ARROW_ICONS[i]));
        item.setEnabled(dir != properties.getNormalProperties().getDirection());
        item.addActionListener(
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                tabWindow
                    .getTabWindowProperties()
                    .getTabProperties()
                    .getTitledTabProperties()
                    .getNormalProperties()
                    .setDirection(dir);
              }
            });
      }
    }

    menu.add(directionMenu);
  }
  private static void addTabOrientationMenuItems(JPopupMenu menu, DockingWindow window) {
    final AbstractTabWindow tabWindow = getTabWindowFor(window);

    if (tabWindow == null || tabWindow instanceof WindowBar) return;

    JMenu orientationMenu = new JMenu("Tab Orientation");
    TabbedPanelProperties properties =
        tabWindow.getTabWindowProperties().getTabbedPanelProperties();
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++) {
      final Direction dir = directions[i];
      JMenuItem item = orientationMenu.add(new JMenuItem(dir.getName(), ARROW_ICONS[i]));
      item.setEnabled(dir != properties.getTabAreaOrientation());
      item.addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              tabWindow
                  .getTabWindowProperties()
                  .getTabbedPanelProperties()
                  .setTabAreaOrientation(dir);
            }
          });
    }

    menu.add(orientationMenu);
  }
  /**
   * Creates the Titled Tab menu
   *
   * @return the titled tab menu
   */
  private JMenu createTitledTabMenu() {
    JMenu titledTabMenu = new JMenu("Titled Tab");

    // Get all avaliable directions
    Direction[] directions = Direction.getDirections();
    for (int i = 0; i < directions.length; i++) {
      final Direction direction = directions[i];
      titledTabMenu.add(
          createMenuItem(
              "Direction: " + direction.getName(),
              new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  // Sets in what direction the icon, text and title
                  // components are laid out (as a line).
                  // If no direction have been set for the highlighted and/or
                  // disabled state then those
                  // states will use the direction for the normal state and
                  // therefore we only need to
                  // set the direction for the normal state because we want
                  // the same direction for all
                  // states in this example. The titled tab is automatically
                  // updated.
                  titledTabProperties.getNormalProperties().setDirection(direction);
                }
              }));
    }

    titledTabMenu.add(new JSeparator());

    // Get all size policies
    TitledTabSizePolicy[] titledTabSizePolicies = TitledTabSizePolicy.getSizePolicies();
    for (int i = 0; i < titledTabSizePolicies.length; i++) {
      final TitledTabSizePolicy titledTabSizePolicy = titledTabSizePolicies[i];
      titledTabMenu.add(
          createMenuItem(
              "Size Policy: " + titledTabSizePolicy.getName(),
              new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  // Sets the size policy for the entire titled tab. This
                  // means that if equal size is
                  // set then titled tab will calculate its maximum size for
                  // all its state and use that
                  // size regardless of the current state for the tab. If
                  // individual size is used then
                  // titled tab will only use the size for the active state
                  // even i.e. if the states have
                  // different sizes i.e. titled tab will change size
                  // depending on what state it is in.
                  // The titled tab is automatically updated.
                  titledTabProperties.setSizePolicy(titledTabSizePolicy);
                }
              }));
    }

    return titledTabMenu;
  }
 public void setComponentDirection(Direction componentDirection) {
   if (componentDirection != this.componentDirection) {
     this.componentDirection = componentDirection;
     getDirectionLayout()
         .setDirection(
             componentDirection == Direction.UP
                 ? Direction.RIGHT
                 : componentDirection == Direction.LEFT
                     ? Direction.DOWN
                     : componentDirection == Direction.DOWN ? Direction.RIGHT : Direction.DOWN);
     if (scrollEnabled) {
       scrollButtonBox.setVertical(componentDirection.isHorizontal());
       ((ScrollableBox) componentContainer).setVertical(componentDirection.isHorizontal());
     }
   }
 }
  static {
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++)
      ARROW_ICONS[i] =
          new ArrowIcon(InternalDockingUtil.DEFAULT_BUTTON_ICON_SIZE + 1, directions[i]);
  }
  private Insets getRealTabInsets(
      Direction areaOrientation, Direction tabDirection, Insets insets) {
    Insets insetsTemp = insets;
    insetsTemp = InsetsUtil.rotate(tabDirection, insetsTemp);

    if (swapWidthHeights[getDirectionIndex(areaOrientation)]) {

      insetsTemp = InsetsUtil.rotate(areaOrientation.getNextCCW(), insetsTemp);
    }

    return insetsTemp;
  }
  private void initialize() {
    if (componentContainer != null) remove(componentContainer);

    DirectionLayout layout = getDirectionLayout();
    layout.setCompressing(!scrollEnabled);

    if (scrollEnabled) {
      if (useDefaultScrollButtons)
        scrollButtonBox = new ScrollButtonBox(componentDirection.isHorizontal(), iconSize);
      else
        scrollButtonBox =
            new ScrollButtonBox(componentDirection.isHorizontal(), null, null, null, null);

      final ScrollableBox scrollableBox =
          new ScrollableBox(componentBox, componentDirection.isHorizontal(), scrollOffset);
      scrollableBox.setLayoutOrderList(layoutOrderList);
      scrollButtonBox.addListener(
          new ScrollButtonBoxListener() {
            public void scrollButton1() {
              scrollableBox.scrollLeft(1);
            }

            public void scrollButton2() {
              scrollableBox.scrollRight(1);
            }
          });

      scrollableBox.addComponentListener(
          new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
              scrollButtonBox.setButton1Enabled(!scrollableBox.isLeftEnd());
              scrollButtonBox.setButton2Enabled(!scrollableBox.isRightEnd());
            }
          });

      scrollButtonBox.setButton1Enabled(!scrollableBox.isLeftEnd());
      scrollButtonBox.setButton2Enabled(!scrollableBox.isRightEnd());

      scrollableBox.addScrollableBoxListener(
          new ScrollableBoxListener() {
            public void scrolledLeft(ScrollableBox box) {
              scrollButtonBox.setButton1Enabled(!box.isLeftEnd());
              scrollButtonBox.setButton2Enabled(true);
            }

            public void scrolledRight(ScrollableBox box) {
              scrollButtonBox.setButton1Enabled(true);
              scrollButtonBox.setButton2Enabled(!box.isRightEnd());
            }

            public void changed(ScrollableBox box) {
              fireChangedEvent();
            }
          });
      componentContainer = scrollableBox;
    } else {
      scrollButtonBox = null;
      componentContainer = componentBox;
    }

    componentContainer.setAlignmentY(0);
    add(componentContainer, BorderLayout.CENTER);

    revalidate();
  }
 /**
  * Constructor.
  *
  * @param group the property group
  * @param name the property name
  * @param description the property description
  * @param valueHandler handles values for this property
  */
 public DirectionProperty(
     PropertyGroup group, String name, String description, PropertyValueHandler valueHandler) {
   super(group, name, Direction.class, description, valueHandler, Direction.getDirections());
 }
  private void estimateContentTabAreaBorderColor(
      PanePainter pane, int index, final Direction direction) {
    Dimension preSize = pane.getSize();

    reset(pane);

    pane.addTab(EMPTY_STRING, SizeIcon.EMPTY, getComponent());

    pane.setSelectedIndex(-1);

    Dimension paneSize = pane.getMinimumSize();

    if (direction.isHorizontal()) pane.setSize(paneSize.width, paneSize.height * 2);
    else pane.setSize(paneSize.width * 2, paneSize.height);

    pane.doValidation();

    Rectangle tabBounds = pane.getBoundsAt(0);

    BufferedImage img =
        new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_ARGB);

    int x = 0;
    int y = 0;

    if (direction == Direction.UP) {
      x = tabBounds.x + (tabBounds.width / 2);
      y = pane.getHeight() - contentInsets[index].top - contentInsets[index].bottom - 1;
    } else if (direction == Direction.DOWN) {
      x = tabBounds.x + (tabBounds.width / 2);
      y = contentInsets[index].top + contentInsets[index].bottom;
    } else if (direction == Direction.LEFT) {
      x = pane.getWidth() - contentInsets[index].left - contentInsets[index].right - 1;
      y = tabBounds.y + (tabBounds.height / 2);
    } else {
      x += contentInsets[index].left + contentInsets[index].right;
      y = tabBounds.y + (tabBounds.height / 2);
    }

    final int px = x;
    final int py = y;

    RGBImageFilter colorFilter =
        new RGBImageFilter() {
          @Override
          public int filterRGB(int x, int y, int rgb) {
            if (px == x && py == y) {
              int r = (rgb >> 16) & 0xff;
              int g = (rgb >> 8) & 0xff;
              int b = (rgb) & 0xff;
              int a = (rgb >> 24) & 0xff;
              contentTabAreaBorderColors[getDirectionIndex(direction.getOpposite())] =
                  new Color(r, g, b, a);
            }

            return rgb;
          }
        };

    FilteredImageSource source = new FilteredImageSource(img.getSource(), colorFilter);
    pane.paint(img.getGraphics());

    BufferedImage img2 =
        new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_ARGB);
    img2.getGraphics().drawImage(Toolkit.getDefaultToolkit().createImage(source), 0, 0, null);

    pane.setSize(preSize);

    pane.doValidation();
  }
  private void calculateAreaInsets(PanePainter pane, int index, Direction direction) {

    // Area insets
    pane.setSelectedIndex(0);
    Rectangle selectedBounds = pane.getBoundsAt(0);
    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    Rectangle normalBounds = pane.getBoundsAt(0);
    int left = 0;
    int top = 0;
    int bottom = 0;
    int right = 0;

    if (direction == Direction.UP) {
      left = Math.min(selectedBounds.x, normalBounds.x);
      top = Math.min(selectedBounds.y, normalBounds.y);
      bottom = 0;
    } else if (direction == Direction.DOWN) {
      left = Math.min(selectedBounds.x, normalBounds.x);
      top = 0;
      bottom =
          pane.getHeight()
              - Math.max(
                  selectedBounds.y + selectedBounds.height, normalBounds.y + normalBounds.height);
    } else if (direction == Direction.LEFT) {
      top = Math.min(selectedBounds.y, normalBounds.y);
      left = Math.min(selectedBounds.x, normalBounds.x);
      right = 0;
    } else {
      top = Math.min(selectedBounds.y, normalBounds.y);
      left = 0;
      right =
          pane.getWidth()
              - Math.max(
                  selectedBounds.x + selectedBounds.width, normalBounds.x + normalBounds.width);
    }

    Dimension sizeTemp = pane.getSize();

    reset(pane);

    for (int i = 0; i < 4; i++) pane.addTab(EMPTY_STRING, SizeIcon.EMPTY, getComponent());

    pane.setSelectedIndex(-1);

    pane.setSize(pane.getMinimumSize());
    pane.doValidation();

    if (!direction.isHorizontal()) {
      int width = pane.getWidth() - 1;

      boolean found = false;

      while (!found) {
        width++;
        pane.setSize(width, pane.getHeight());

        pane.doValidation();
        found = pane.getBoundsAt(0).y == pane.getBoundsAt(3).y;
      }

      Rectangle endBounds = pane.getBoundsAt(3);
      right = pane.getWidth() - endBounds.x - endBounds.width - spacings[index];
    } else {
      int height = pane.getHeight() - 1;

      boolean found = false;

      while (!found) {
        height++;
        pane.setSize(pane.getWidth(), height);

        pane.doValidation();
        found = pane.getBoundsAt(0).x == pane.getBoundsAt(3).x;
      }

      Rectangle endBounds = pane.getBoundsAt(3);
      bottom = pane.getHeight() - endBounds.y - endBounds.height - spacings[index];
    }

    areaInsets[index] = new Insets(top, left, bottom, right);

    pane.setSize(sizeTemp);

    pane.doValidation();
  }
  private void initValues(PanePainter pane, int index, Direction direction) {
    estimateSwappedTabDirection(pane, index);

    reset(pane);

    pane.setSize(1000, 1000);

    boolean upDown = !direction.isHorizontal();

    for (int i = 0; i < DEFAULT_TAB_COUNT; i++) {
      pane.addTab(EMPTY_STRING, getComponent());
    }

    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    pane.doValidation();

    // Tab insets if any from UImanager
    Insets insets = UIManager.getInsets("TabbedPane.tabInsets");
    if (insets == null) insets = new Insets(0, 0, 0, 0);

    if (!upDown) tabInsets[index] = new Insets(0, insets.left, 0, insets.right);
    else tabInsets[index] = InsetsUtil.EMPTY_INSETS;

    // Raised
    Rectangle bounds = pane.getBoundsAt(0);
    Rectangle bounds2 = pane.getBoundsAt(pane.getSelectedIndex());

    if (direction == Direction.UP) raiseds[index] = Math.max(0, bounds.y - bounds2.y);
    else if (direction == Direction.LEFT) raiseds[index] = Math.max(0, bounds.x - bounds2.x);
    else if (direction == Direction.DOWN) raiseds[index] = raiseds[getDirectionIndex(Direction.UP)];
    else raiseds[index] = raiseds[getDirectionIndex(Direction.LEFT)];

    // Spacing
    Insets normal = getCalculatedInsets(pane, 0, false, direction);
    Insets selected = getCalculatedInsets(pane, 0, true, direction);

    if (upDown) spacings[index] = normal.left + normal.right - selected.left - selected.right;
    else spacings[index] = normal.top + normal.bottom - selected.top - selected.bottom;

    // Normal insets
    normalInsets[index] = getCalculatedInsets(pane, 0, false, direction);

    // Selected insets
    Insets insetsTemp = getCalculatedInsets(pane, 0, true, direction);
    int spacing = spacings[index];
    int spaceFirst = spacing / 2;
    int spaceAfter = spacing / 2 + spacing % 2;

    if (direction == Direction.UP) {
      insetsTemp.bottom = normalInsets[index].bottom;
      insetsTemp.top = normalInsets[index].top;
      insetsTemp.left += spaceFirst;
      insetsTemp.right += spaceAfter;
    } else if (direction == Direction.LEFT) {
      insetsTemp.right = normalInsets[index].right;
      insetsTemp.left = normalInsets[index].left;
      insetsTemp.top += spaceFirst;
      insetsTemp.bottom += spaceAfter;
    } else if (direction == Direction.RIGHT) {
      insetsTemp.right = normalInsets[index].right;
      insetsTemp.left = normalInsets[index].left;
      insetsTemp.top += spaceFirst;
      insetsTemp.bottom += spaceAfter;
    } else {
      insetsTemp.bottom = normalInsets[index].bottom;
      insetsTemp.top = normalInsets[index].top;
      insetsTemp.left += spaceFirst;
      insetsTemp.right += spaceAfter;
    }

    selectedInsets[index] = insetsTemp;

    // Content insets
    JPanel c = new JPanel();
    pane.addTab(EMPTY_STRING, c);
    pane.setSelectedIndex(pane.getTabCount() - 1);
    pane.doValidation();

    Point l = SwingUtilities.convertPoint(c.getParent(), c.getLocation(), pane);

    Rectangle boundsTemp = pane.getBoundsAt(0);
    int top = 0;
    int left = 0;
    int bottom = 0;
    int right = 0;

    if (direction == Direction.UP) {
      top = l.y - boundsTemp.height - boundsTemp.y;
      left = l.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - l.x - c.getWidth();
    } else if (direction == Direction.DOWN) {
      top = l.y;
      left = l.x;
      bottom = pane.getHeight() - c.getHeight() - l.y - (pane.getHeight() - boundsTemp.y);
      right = pane.getWidth() - l.x - c.getWidth();
    } else if (direction == Direction.LEFT) {
      top = l.y;
      left = l.x - boundsTemp.width - boundsTemp.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - l.x - c.getWidth();
    } else {
      top = l.y;
      left = l.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - c.getWidth() - l.x - (pane.getWidth() - boundsTemp.x);
    }

    contentInsets[index] = new Insets(top, left, bottom, right);

    Insets i = contentInsets[0];
    Insets i2 = InsetsUtil.rotate(direction.getNextCW(), i);
    Insets adjustedInsets = InsetsUtil.max(i, i2);
    adjustedContentInsets[index] = adjustedInsets;
    adjustedContentInsetsTabAreaHidden[index] =
        new Insets(
            direction == Direction.UP ? adjustedInsets.left : adjustedInsets.top,
            direction == Direction.LEFT ? adjustedInsets.top : adjustedInsets.left,
            direction == Direction.DOWN ? adjustedInsets.right : adjustedInsets.bottom,
            direction == Direction.RIGHT ? adjustedInsets.bottom : adjustedInsets.right);

    pane.removeTabAt(pane.getTabCount() - 1);
    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    pane.doValidation();

    // Minimum sizes
    Rectangle rectangleBounds = pane.getBoundsAt(DEFAULT_SELECTED_INDEX);
    tabMinimumSizes[index] = new Dimension(rectangleBounds.width, rectangleBounds.height);
    minimumSizes[index] =
        new Dimension(
            rectangleBounds.width - tabInsets[index].left - tabInsets[index].right,
            rectangleBounds.height - tabInsets[index].top - tabInsets[index].bottom);

    calculateAreaInsets(pane, index, direction);

    estimateContentTabAreaBorderColor(pane, index, direction);
  }
  public static Dimension rotate(Direction source, Dimension d, Direction destination) {
    if (source.isHorizontal() && destination.isHorizontal()) return d;

    return new Dimension(d.height, d.width);
  }
 public static WindowSplitLocation decode(ObjectInputStream in, RootWindow rootWindow)
     throws IOException {
   WindowSplitLocation location = new WindowSplitLocation(Direction.decode(in), in.readFloat());
   location.read(in, rootWindow);
   return location;
 }
 public void write(ObjectOutputStream out) throws IOException {
   out.writeInt(LocationDecoder.SPLIT);
   direction.write(out);
   out.writeFloat(dividerLocation);
   super.write(out);
 }
  /**
   * Creates the Tabbed Panel menu
   *
   * @return the tabbed panel menu
   */
  private JMenu createTabbedPanelMenu() {
    JMenu tabbedPanelMenu = new JMenu("Tabbed Panel");

    tabbedPanelMenu.add(
        createMenuItem(
            "Add a Titled Tab",
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                tabbedPanel.addTab(createTab());
              }
            }));

    tabbedPanelMenu.add(new JSeparator());

    // Get all avaliable directions
    Direction[] directions = Direction.getDirections();
    for (int i = 0; i < directions.length; i++) {
      final Direction direction = directions[i];
      tabbedPanelMenu.add(
          createMenuItem(
              "Tab Area Orientation: " + direction.getName(),
              new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  // Sets the orientation (direction) for the tab area in the
                  // TabbedPanelProperties
                  // for the tabbed panel. The tabbed panel is automatically
                  // updated.
                  tabbedPanel.getProperties().setTabAreaOrientation(direction);
                }
              }));
    }

    tabbedPanelMenu.add(new JSeparator());

    // Get all available tab layout policies i.e. how the tabs can be laid
    // out in the tab area
    TabLayoutPolicy[] tabLayoutPolicies = TabLayoutPolicy.getLayoutPolicies();
    for (int i = 0; i < tabLayoutPolicies.length; i++) {
      final TabLayoutPolicy tabLayoutPolicy = tabLayoutPolicies[i];
      tabbedPanelMenu.add(
          createMenuItem(
              "Tab Layout: " + tabLayoutPolicy.getName(),
              new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  // Sets the layout for the tab area in the
                  // TabbedPanelProperties
                  // for the tabbed panel. The tabbed panel is automatically
                  // updated.
                  tabbedPanel.getProperties().setTabLayoutPolicy(tabLayoutPolicy);
                }
              }));
    }

    tabbedPanelMenu.add(new JSeparator());

    // Get all available tab drop down list visible policies i.e. when to
    // show a button (as
    // a tab area component) that shows a drop down list of all the tabs in
    // the tabbed panel
    // where a tab can be selected.
    TabDropDownListVisiblePolicy[] tabDropDownListVisiblePolicies =
        TabDropDownListVisiblePolicy.getDropDownListVisiblePolicies();
    for (int i = 0; i < tabDropDownListVisiblePolicies.length; i++) {
      final TabDropDownListVisiblePolicy tabDropDownListVisiblePolicy =
          tabDropDownListVisiblePolicies[i];
      tabbedPanelMenu.add(
          createMenuItem(
              "Tab Drop Down List: " + tabDropDownListVisiblePolicy.getName(),
              new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  // Sets the tab drop down list visible policy for the tabbed
                  // panel. The
                  // tabbed panel is automatically updated.
                  tabbedPanel
                      .getProperties()
                      .setTabDropDownListVisiblePolicy(tabDropDownListVisiblePolicy);
                }
              }));
    }

    tabbedPanelMenu.add(new JSeparator());

    tabbedPanelMenu.add(
        createMenuItem(
            "Shadow: Enable",
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                tabbedPanel
                    .getProperties()
                    .setShadowEnabled(!tabbedPanel.getProperties().getShadowEnabled());
                // Enable or disable (toggle) the shadow for the tabbed panel.
                // The tabbed panel is
                // automatically updated.
                ((JMenuItem) e.getSource())
                    .setText(
                        "Shadow: "
                            + (tabbedPanel.getProperties().getShadowEnabled()
                                ? "Disable"
                                : "Enable"));
              }
            }));

    return tabbedPanelMenu;
  }