// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/gui/dock/DockLayout.java,v $
// $RCSfile: DockLayout.java,v $
// $Revision: 1.5 $
// $Date: 2005/08/09 17:50:51 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.gui.dock;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.util.Iterator;
import javax.swing.JComponent;
import com.bbn.openmap.util.Debug;
/**
* A Layout manager used for the docking component...
*
* @author Ben Lubin
* @version $Revision: 1.5 $ on $Date: 2005/08/09 17:50:51 $
* @since 12/5/02
*/
public class DockLayout implements LayoutManager2 {
private BasicDockPanel p;
/** Size of the background control */
protected Rectangle occludingBounds;
/** Size of the background control */
protected Rectangle backgroundBounds;
public DockLayout(BasicDockPanel p) {
this.p = p;
}
//Layout Query Functions:
/////////////////////////
/** Account for the extra size of the cardinal DockWrapper. */
protected int getHeightAtLeftCardinal(DockWrapper dw) {
return getHeightAtLeft(dw) - p.getOverlapTolerance();
}
/** Account for the extra size of the cardinal DockWrapper. */
protected int getHeightAtRightCardinal(DockWrapper dw) {
return getHeightAtRight(dw) - p.getOverlapTolerance();
}
/** Account for the extra size of the cardinal DockWrapper. */
protected int getWidthAtYCardinal(DockWrapper dw, int y) {
return getWidthAtY(dw, y) - p.getOverlapTolerance();
}
/**
* Get the height at the left point for a north or south
* DockWrapper.
*/
protected int getHeightAtLeft(DockWrapper dw) {
int ret = dw.getPreferredSize().height;
java.util.List l = dw.getDockedWrappers();
if (!l.isEmpty()) {
ret += getHeightAtLeft((DockWrapper) l.get(0));
}
return ret;
}
/**
* Get the height at the right point for a north or south
* DockWrapper.
*/
protected int getHeightAtRight(DockWrapper dw) {
int ret = dw.getPreferredSize().height;
java.util.List l = dw.getDockedWrappers();
if (!l.isEmpty()) {
ret += getHeightAtRight((DockWrapper) l.get(l.size() - 1));
}
return ret;
}
/**
* Get the width at the given point for a east or west
* DockWrapper.
*/
protected int getWidthAtY(DockWrapper dw, int y) {
Rectangle bounds = dw.getBounds();
int ret = 0;
if ((bounds.y <= y) && (bounds.y + bounds.height >= y)) {
ret = bounds.width;
}
for (Iterator iter = dw.getDockedWrappers().iterator(); iter.hasNext();) {
DockWrapper c = (DockWrapper) iter.next();
ret += getWidthAtY(c, y);
}
return ret;
}
//Layout Functions:
///////////////////
/**
* Layout the entire container.
*/
protected void layoutContainer() {
Rectangle inBounds = p.getBounds();
Insets insets = p.getInsets();
inBounds.x += insets.left;
inBounds.width -= insets.left;
inBounds.width -= insets.right;
inBounds.y += insets.top;
inBounds.height -= insets.top;
inBounds.height -= insets.bottom;
backgroundBounds = (Rectangle) inBounds.clone();
occludingBounds = (Rectangle) inBounds.clone();
layoutCardinals();
layoutEast(p.getEast(),
occludingBounds.x + occludingBounds.width,
occludingBounds.y,
occludingBounds.width,
occludingBounds.height);
layoutWest(p.getWest(),
occludingBounds.x,
occludingBounds.y,
occludingBounds.width,
occludingBounds.height);
int southLeft = inBounds.x
+ getWidthAtYCardinal(p.getWest(), inBounds.y + inBounds.height
- getHeightAtLeftCardinal(p.getSouth()));
int southRight = inBounds.x
+ inBounds.width
- getWidthAtYCardinal(p.getEast(), inBounds.y + inBounds.height
- getHeightAtRightCardinal(p.getSouth()));
layoutSouth(p.getSouth(),
southLeft,
occludingBounds.y + occludingBounds.height,
southRight - southLeft,
occludingBounds.height);
int northLeft = inBounds.x
+ getWidthAtYCardinal(p.getWest(), inBounds.y
+ getHeightAtLeftCardinal(p.getNorth()));
int northRight = inBounds.x
+ inBounds.width
- getWidthAtYCardinal(p.getEast(), inBounds.y
+ getHeightAtRightCardinal(p.getNorth()));
layoutNorth(p.getNorth(), northLeft, occludingBounds.y, northRight
- northLeft, occludingBounds.height);
layoutBackground();
}
protected void layoutCardinals() {
p.getNorth().setBounds(0, 0, p.getWidth(), p.getOverlapTolerance());
p.getSouth().setBounds(0,
p.getHeight() - p.getOverlapTolerance(),
p.getWidth(),
p.getOverlapTolerance());
p.getEast().setBounds(p.getWidth() - p.getOverlapTolerance(),
0,
p.getOverlapTolerance(),
p.getWidth());
p.getWest().setBounds(0, 0, p.getOverlapTolerance(), p.getWidth());
}
/**
* Layout west side.
*
* @param x right most edge.
* @param y top most edge.
*/
protected void layoutEast(DockWrapper base, int x, int y, int maxwidth,
int maxheight) {
for (Iterator iter = base.getDockedWrappers().iterator(); iter.hasNext();) {
DockWrapper dw = (DockWrapper) iter.next();
Dimension d = dw.getPreferredSize();
int w = min(d.width, maxwidth);
int h = min(d.height, maxheight);
dw.setBounds(x - w, y, w, h);
if (!dw.canOcclude()) {
updateRight(backgroundBounds, x - w);
}
updateRight(occludingBounds, x - w);
layoutEast(dw, x - w, y, maxwidth - w, maxheight);
y += h;
maxheight -= h;
}
}
/**
* Layout west side.
*
* @param x left most edge.
* @param y top most edge.
*/
protected void layoutWest(DockWrapper base, int x, int y, int maxwidth,
int maxheight) {
for (Iterator iter = base.getDockedWrappers().iterator(); iter.hasNext();) {
DockWrapper dw = (DockWrapper) iter.next();
Dimension d = dw.getPreferredSize();
int w = min(d.width, maxwidth);
int h = min(d.height, maxheight);
dw.setBounds(x, y, w, h);
if (!dw.canOcclude()) {
updateLeft(backgroundBounds, x + w);
}
updateLeft(occludingBounds, x + w);
layoutWest(dw, x + w, y, maxwidth - w, maxheight);
y += h;
maxheight -= h;
}
}
/**
* Layout north side.
*
* @param x left most edge.
* @param y top most edge.
*/
protected void layoutNorth(DockWrapper base, int x, int y, int maxwidth,
int maxheight) {
for (Iterator iter = base.getDockedWrappers().iterator(); iter.hasNext();) {
DockWrapper dw = (DockWrapper) iter.next();
Dimension d = dw.getPreferredSize();
int w = min(d.width, maxwidth);
int h = min(d.height, maxheight);
dw.setBounds(x, y, w, h);
if (!dw.canOcclude()) {
updateTop(backgroundBounds, y + h);
}
updateTop(occludingBounds, y + h);
layoutNorth(dw, x, y + h, maxwidth, maxheight - h);
x += w;
maxwidth -= w;
}
}
/**
* Layout north side.
*
* @param x left most edge.
* @param y bottom most edge.
*/
protected void layoutSouth(DockWrapper base, int x, int y, int maxwidth,
int maxheight) {
for (Iterator iter = base.getDockedWrappers().iterator(); iter.hasNext();) {
DockWrapper dw = (DockWrapper) iter.next();
Dimension d = dw.getPreferredSize();
int w = min(d.width, maxwidth);
int h = min(d.height, maxheight);
dw.setBounds(x, y - h, w, h);
// System.out.println("RES: "+ dw.getBounds());
if (!dw.canOcclude()) {
updateBottom(backgroundBounds, y - h);
}
updateBottom(occludingBounds, y - h);
layoutSouth(dw, x, y - h, maxwidth, maxheight - h);
x += w;
maxwidth -= w;
}
}
protected void layoutBackground() {
JComponent background = p.getBackgroundComponent();
if (background != null) {
/*
* backgroundBounds.x += 10; backgroundBounds.y += 10;
* backgroundBounds.width -= 20; backgroundBounds.height -=
* 20;
*/
background.setBounds(backgroundBounds);
}
}
// Utilities:
/////////////
protected int min(int a, int b) {
return Math.min(a, b);
}
protected int max(int a, int b) {
return Math.max(a, b);
}
protected void updateLeft(Rectangle r, int left) {
int tmp = left - r.x;
if (tmp > 0) {
r.x += tmp;
r.width -= tmp;
}
}
protected void updateRight(Rectangle r, int right) {
r.width = min(r.x + r.width, right);
}
protected void updateTop(Rectangle r, int top) {
int tmp = top - r.y;
if (tmp > 0) {
r.y += tmp;
r.height -= tmp;
}
}
protected void updateBottom(Rectangle r, int bottom) {
r.height = min(r.y + r.height, bottom);
}
// From LayoutManager2:
///////////////////////
public void layoutContainer(Container parent) {
if (parent != p) {
Debug.error("DockLayout: Asked to layout unexpected container");
return;
}
layoutContainer();
}
public void addLayoutComponent(String name, Component comp) {}
public void addLayoutComponent(Component comp, Object constraints) {}
public void removeLayoutComponent(Component comp) {}
public Dimension preferredLayoutSize(Container parent) {
JComponent background = p.getBackgroundComponent();
if (background != null) {
return background.getPreferredSize();
}
return new Dimension(0, 0);
}
public Dimension minimumLayoutSize(Container parent) {
JComponent background = p.getBackgroundComponent();
if (background != null) {
return background.getMinimumSize();
}
return new Dimension(0, 0);
}
public Dimension maximumLayoutSize(Container parent) {
JComponent background = p.getBackgroundComponent();
if (background != null) {
return background.getMaximumSize();
}
return new Dimension(0, 0);
}
public float getLayoutAlignmentX(Container target) {
return .5f;
}
public float getLayoutAlignmentY(Container target) {
return .5f;
}
public void invalidateLayout(Container target) {}
}