/*
* ScrollLayout.java
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2004 Slava Pestov
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.textarea;
//{{{ Imports
import java.awt.*;
import javax.swing.border.Border;
import javax.swing.JComponent;
//}}}
/**
* Similar to a javax.swing.ScrollPaneLayout, but not as restrictive on the
* components that can be added. This layout is essentially a 3 x 3 grid layout,
* with the intent that the bottom and right will hold scroll bars. When installed
* a TextArea, the bottom has a scroll bar, the right has a vertical box containing
* a scroll bar, the left has a Gutter, and the center holds a TextAreaPainter.
* The corners and top are not used by the TextArea.
*
* The corners are intended to be a place to put a button or other small component.
* The corner dimensions are constrained by the left, right, top, and bottom
* components, so, for example, the width of the top left corner is the width
* of the left component and the height of the top left corner is the height of
* the top component.
*/
public class ScrollLayout implements LayoutManager
{
public static final String CENTER = "center";
public static final String RIGHT = "right";
public static final String LEFT = "left";
public static final String BOTTOM = "bottom";
public static final String TOP = "top";
public static final String TOP_LEFT = "topLeft";
public static final String TOP_RIGHT = "topRight";
public static final String BOTTOM_LEFT = "bottomLeft";
public static final String BOTTOM_RIGHT = "bottomRight";
//{{{ addLayoutComponent() method
/**
* Adds a component to the layout using the <code>name</code> parameter to
* position the component.
* @param name One of CENTER, RIGHT, LEFT, BOTTOM, TOP, TOP_LEFT, TOP_RIGHT,
* BOTTOM_LEFT, BOTTOM_RIGHT.
* @param comp The component to add at the given position. If <code>null</code>, the
* component will be removed from that position.
*/
public void addLayoutComponent(String name, Component comp)
{
switch(name) {
case CENTER:
center = comp;
break;
case RIGHT:
right = comp;
break;
case LEFT:
left = comp;
break;
case BOTTOM:
bottom = comp;
break;
case TOP:
top = comp;
break;
case TOP_LEFT:
topLeft = comp;
break;
case TOP_RIGHT:
topRight = comp;
break;
case BOTTOM_LEFT:
bottomLeft = comp;
break;
case BOTTOM_RIGHT:
bottomRight = comp;
break;
}
} //}}}
//{{{ removeLayoutComponent() method
/**
* Removes the specified component from the layout.
* @param comp The component to be removed.
*/
public void removeLayoutComponent(Component comp)
{
if(center == comp)
center = null;
else if(right == comp)
right = null;
else if(left == comp)
left = null;
else if(bottom == comp)
bottom = null;
else if(top == comp)
top = null;
else if(topLeft == comp)
topLeft = null;
else if(topRight == comp)
topRight = null;
else if(bottomLeft == comp)
bottomLeft = null;
else if(bottomRight == comp)
bottomRight = null;
} //}}}
//{{{ preferredLayoutSize() method
public Dimension preferredLayoutSize(Container parent)
{
Dimension dim = new Dimension();
Insets insets = getInsets(parent);
dim.width = insets.left + insets.right;
dim.width += getLeftPreferredWidth();
dim.width += getCenterPreferredWidth();
dim.width += getRightPreferredWidth();
dim.height = insets.top + insets.bottom;
dim.height += getTopPreferredHeight();
dim.height += getCenterPreferredHeight();
dim.height += getBottomPreferredHeight();
return dim;
} //}}}
//{{{ preferred widths
// constrained by left component preferred width
private int getLeftPreferredWidth()
{
if (left != null)
{
return left.getPreferredSize().width;
}
int tlw = topLeft == null ? 0 : topLeft.getPreferredSize().width;
int lw = left == null ? 0 : left.getPreferredSize().width;
int blw = bottomLeft == null ? 0 : bottomLeft.getPreferredSize().width;
return Math.max(lw, Math.max(tlw, blw));
}
private int getCenterPreferredWidth()
{
int tw = top == null ? 0 : top.getPreferredSize().width;
int cw = center == null ? 0 : center.getPreferredSize().width;
int bw = bottom == null ? 0 : bottom.getPreferredSize().width;
return Math.max(cw, Math.max(tw, bw));
}
// constrained by right component preferred width
private int getRightPreferredWidth()
{
if (right != null)
{
return right.getPreferredSize().width;
}
int trw = topRight == null ? 0 : topRight.getPreferredSize().width;
int rw = right == null ? 0 : right.getPreferredSize().width;
int brw = bottomRight == null ? 0 : bottomRight.getPreferredSize().width;
return Math.max(rw, Math.max(trw, brw));
}
//}}}
//{{{ preferred heights
// constrained by top component preferred height
private int getTopPreferredHeight()
{
if (top != null)
{
return top.getPreferredSize().height;
}
int tlh = topLeft == null ? 0 : topLeft.getPreferredSize().height;
int th = top == null ? 0 : top.getPreferredSize().height;
int trh = topRight == null ? 0 : topRight.getPreferredSize().height;
return Math.max(th, Math.max(tlh, trh));
}
private int getCenterPreferredHeight()
{
int lh = left == null ? 0 : left.getPreferredSize().height;
int ch = center == null ? 0 : center.getPreferredSize().height;
int rh = right == null ? 0 : right.getPreferredSize().height;
return Math.max(ch, Math.max(lh, rh));
}
// constrained by bottom component preferred height
private int getBottomPreferredHeight()
{
if (bottom != null)
{
return bottom.getPreferredSize().height;
}
int blh = bottomLeft == null ? 0 : bottomLeft.getPreferredSize().height;
int bh = bottom == null ? 0 : bottom.getPreferredSize().height;
int brh = bottomRight == null ? 0 : bottomRight.getPreferredSize().height;
return Math.max(bh, Math.max(brh, blh));
}
//}}}
//{{{ minimumLayoutSize() method
public Dimension minimumLayoutSize(Container parent)
{
Dimension dim = new Dimension();
Insets insets = getInsets(parent);
dim.width = insets.left + insets.right;
dim.height = insets.top + insets.bottom;
int tlw = topLeft == null ? 0 : topLeft.getMinimumSize().width;
int lw = left == null ? 0 : left.getMinimumSize().width;
int blw = bottomLeft == null ? 0 : bottomLeft.getMinimumSize().width;
dim.width += Math.max(lw, Math.max(tlw, blw));
int tw = top == null ? 0 : top.getMinimumSize().width;
int cw = center == null ? 0 : center.getMinimumSize().width;
int bw = bottom == null ? 0 : bottom.getMinimumSize().width;
dim.width += Math.max(cw, Math.max(tw, bw));
int trw = topRight == null ? 0 : topRight.getMinimumSize().width;
int rw = right == null ? 0 : right.getMinimumSize().width;
int brw = bottomRight == null ? 0 : bottomRight.getMinimumSize().width;
dim.width += Math.max(rw, Math.max(trw, brw));
int tlh = topLeft == null ? 0 : topLeft.getMinimumSize().height;
int lh = left == null ? 0 : left.getMinimumSize().height;
int blh = bottomLeft == null ? 0 : bottomLeft.getMinimumSize().height;
dim.height += Math.max(lh, Math.max(tlh, blh));
int th = top == null ? 0 : top.getMinimumSize().height;
int ch = center == null ? 0 : center.getMinimumSize().height;
int bh = bottom == null ? 0 : bottom.getMinimumSize().height;
dim.height += Math.max(ch, Math.max(th, bh));
int trh = topRight == null ? 0 : topRight.getMinimumSize().height;
int rh = right == null ? 0 : right.getMinimumSize().height;
int brh = bottomRight == null ? 0 : bottomRight.getMinimumSize().height;
dim.height += Math.max(rh, Math.max(trh, brh));
return dim;
} //}}}
//{{{ layoutContainer() method
public void layoutContainer(Container parent)
{
Dimension size = parent.getSize();
Insets insets = getInsets(parent);
int itop = insets.top;
int ileft = insets.left;
int ibottom = insets.bottom;
int iright = insets.right;
int leftWidth = getLeftPreferredWidth();
int rightWidth = getRightPreferredWidth();
int topHeight = getTopPreferredHeight();
int bottomHeight = getBottomPreferredHeight();
int centerWidth = Math.max(0,size.width - leftWidth
- rightWidth - ileft - iright);
int centerHeight = Math.max(0,size.height - topHeight
- bottomHeight - itop - ibottom);
if (left != null)
{
left.setBounds(
ileft,
itop+topHeight,
leftWidth,
centerHeight);
}
if (center != null)
{
center.setBounds(
ileft + leftWidth,
itop+topHeight,
centerWidth,
centerHeight);
}
if (right != null)
{
right.setBounds(
ileft + leftWidth + centerWidth,
itop + topHeight,
rightWidth,
centerHeight);
}
if (bottom != null)
{
bottom.setBounds(
ileft + leftWidth,
itop + topHeight + centerHeight,
centerWidth,
bottomHeight);
}
if(top != null)
{
top.setBounds(
ileft + leftWidth,
itop,
centerWidth,
topHeight);
}
if (topLeft != null)
{
topLeft.setBounds(
ileft,
itop,
leftWidth,
topHeight);
}
if (topRight != null)
{
topRight.setBounds(
ileft + leftWidth + centerWidth,
itop,
rightWidth,
topHeight);
}
if (bottomLeft != null)
{
bottomLeft.setBounds(
ileft,
itop + topHeight + centerHeight,
leftWidth,
bottomHeight);
}
if (bottomRight != null)
{
bottomRight.setBounds(
ileft + leftWidth + centerWidth,
itop + topHeight + centerHeight,
rightWidth,
bottomHeight);
}
} //}}}
//{{{ Private members
private Component center;
private Component left;
private Component right;
private Component bottom;
private Component top;
private Component topLeft;
private Component topRight;
private Component bottomLeft;
private Component bottomRight;
//{{{ getInsets() method
private Insets getInsets(Component parent)
{
Border border = ((JComponent)parent).getBorder();
if(border == null)
return new Insets(0,0,0,0);
else
return border.getBorderInsets(parent);
} //}}}
//}}}
}