📄 mosaiclayout.java
字号:
for( i = 0; i < comp.length; ++i )
addNode( lookupNode( comp[i] ) );
if( m_root != null )
m_root.initializeGeometry();
m_initialized = true;
//printTree();
}
//
// a d d N o d e
//
protected void addNode( MosaicLeafNode N )
{
Enumeration coord = N.m_coordStack.elements();
MosaicCoord c =
coord.hasMoreElements() ?
(MosaicCoord) coord.nextElement() : new MosaicCoord( 0, 0 );
if( m_root == null ) {
if( ! coord.hasMoreElements() && c.m_col == 0 && c.m_row == 0 ) {
N.setParent();
m_root = N;
return;
}
m_root = new MosaicInteriorNode( this );
}
MosaicInteriorNode parent =
m_root.ensureCapacity( c.m_col, c.m_row );
m_root = parent;
while( coord.hasMoreElements() ) {
MosaicNode child = parent.m_node[c.m_col][c.m_row];
MosaicCoord c1 = (MosaicCoord) coord.nextElement();
if( child == null && ! coord.hasMoreElements() &&
c1.m_col == 0 && c1.m_row == 0 ) {
break;
}
if( child == null ) {
child = new MosaicInteriorNode( this );
child.setParent( parent, c.m_col, c.m_row );
}
parent = child.ensureCapacity( c1.m_col, c1.m_row );
c = c1;
}
parent.m_node[c.m_col][c.m_row] = N;
N.setParent( parent, c.m_col, c.m_row );
}
//
// d e f a u l t C u r s o r
//
protected void defaultCursor()
{
if( m_frame != null ) {
if( m_frame.getCursor().getType() != Cursor.DEFAULT_CURSOR )
m_frame.setCursor( Cursor.getDefaultCursor() );
}
}
//
// p r i n t T r e e
//
protected void printTree()
{
if( m_root != null )
m_root.print( "" );
}
}
///////////////////////////////////////////////////////////////
//
// M o s a i c N o d e
//
///////////////////////////////////////////////////////////////
abstract class MosaicNode extends Object
{
// For each node, its minimum size, preferred size and actual
// size are stored separately. Minimum and preferred sizes are
// fixed and initialized only once. The actual size can vary.
// The minimum size of a grid is the sum of the minimum size
// of all its columns/rows, plus the space that is needed for
// sashes. The same holds for the preferred and actual size.
// The minimum/preferred size of a column/row is the maximum
// of the minimum/preferred size of each box in the column/row,
// in the corresponding dimension. The actual size of a node
// is never less than its minimum size.
protected Dimension m_minSize = null;
protected Dimension m_prefSize = null;
protected Dimension m_size = null;
// There are two passes. During initialization, the minimum
// and preferred sizes and weights are determined and
// propagated bottom-up. During finalization, the available
// space is subdivided into regions according to the weights
// and passed down (top-down). Initialization takes place only
// once. Finalization takes place whenever the size of the
// container changes.
// During finalization, the origin relative to the parent
// container is determined and stored here.
protected int m_orgx = 0;
protected int m_orgy = 0;
// Each node has a weight assigned to it, separately for each
// dimension. The weight determines how much the grid wins or
// loses when extra space is available or needed. A weight of
// zero means the grid never wins or loses any space. The
// higher the weight, the more prominent the node when it comes
// to the distribution of extra space. The weight of leaf nodes
// is looked up in the constraints of the corresponding component;
// the weight of interior nodes is computed recursively by
// averaging over the weight parameters of its children, giving
// higher priority to children whose preferred size is higher.
protected double m_weightx = 0;
protected double m_weighty = 0;
// Each node knows its parent node and the position it takes
// there.
protected MosaicInteriorNode m_parent = null;
protected int m_parentCol = 0;
protected int m_parentRow = 0;
// Each node also has direct contact to the layout manager,
// since it has to access some of its parameters.
protected MosaicLayout m_layout = null;
//
// M o s a i c N o d e
//
protected MosaicNode( MosaicLayout layout )
{
m_layout = layout;
}
//
// i n i t i a l i z e G e o m e t r y
//
protected abstract void initializeGeometry();
//
// f i n a l i z e G e o m e t r y
//
protected abstract void finalizeGeometry( int orgx, int orgy,
int width, int height, boolean liveDrag );
//
// e n s u r e C a p a c i t y
//
protected abstract MosaicInteriorNode ensureCapacity(
int col, int row );
//
// s e t P a r e n t
//
protected void setParent()
{
setParent( null, 0, 0 );
}
//
// s e t P a r e n t
//
protected void setParent( MosaicInteriorNode parent,
int col, int row )
{
m_parent = parent;
m_parentCol = col;
m_parentRow = row;
if( m_parent != null )
m_parent.m_node[m_parentCol][m_parentRow] = this;
}
//
// h a n d l e E v e n t
//
protected abstract void handleEvent( Event evt );
//
// p a i n t
//
protected abstract void paint( Graphics g );
//
// p r i n t
//
protected void print( String indent )
{
if( m_parent == null ) {
System.out.println( indent + "no parent" );
}
else {
if( m_parent.m_node[m_parentCol][m_parentRow] != this ) {
System.out.println( indent +
"parent (" + m_parentCol + "," + m_parentRow + ") not found" );
}
else {
System.out.println( indent +
"parent (" + m_parentCol + "," + m_parentRow + ") found" );
}
}
}
}
///////////////////////////////////////////////////////////////
//
// M o s a i c L e a f N o d e
//
///////////////////////////////////////////////////////////////
final class MosaicLeafNode extends MosaicNode
{
// There is a one-to-one correspondence between leaf nodes and
// components. Leaf nodes are the wrappers of components and their
// layout constraints. The position (coord stack) of components in
// the hierarchy can also be looked up in the corresponding leaf node.
// The coord stack directly corresponds to the path that has to be
// followed in the tree in order to arrive at the leaf node (the
// tree is constructed by consulting the coord stacks).
// Note that an empty leaf node (comp == null) is allowed, but
// should be regarded as an oddity that should not occur.
protected Component m_comp = null;
protected MosaicConstraints m_constraints = null;
protected MosaicCoordStack m_coordStack = null;
// The size of the box of the leaf node is stored in m_size of
// the super class. The component itself can be laid out in a
// slightly different manner, however, according to its layout
// constraints. The screen coordinates of the component itself
// are stored in the following variables (they are computed by
// checking the m_anchor, m_fill and m_insets fields of the
// constraints object).
protected int m_compOrgx = 0;
protected int m_compOrgy = 0;
protected int m_compWidth = 0;
protected int m_compHeight = 0;
// Indicates if m_minSize and m_prefSize have been determined.
protected boolean m_initialized = false;
//
// M o s a i c L e a f N o d e
//
protected MosaicLeafNode( MosaicLayout layout, Component comp,
MosaicConstraints constraints, MosaicCoordStack coordStack )
{
super( layout );
m_comp = comp;
m_constraints = constraints;
m_coordStack = coordStack;
}
//
// i n i t i a l i z e G e o m e t r y
//
protected void initializeGeometry()
{
if( m_initialized )
return;
if( m_comp == null ) {
m_prefSize = m_minSize = new Dimension( 0, 0 );
}
else {
m_minSize = new Dimension( m_comp.getMinimumSize() );
m_prefSize = new Dimension( m_comp.getPreferredSize() );
}
m_weightx = m_constraints.m_weightx;
m_weighty = m_constraints.m_weighty;
if( m_constraints.m_insets != null ) {
int w = m_constraints.m_insets.left + m_constraints.m_insets.right;
int h = m_constraints.m_insets.top + m_constraints.m_insets.bottom;
m_minSize.width += w;
m_minSize.height += h;
m_prefSize.width += w;
m_prefSize.height += h;
}
m_size = new Dimension( m_prefSize );
m_initialized = true;
}
//
// f i n a l i z e G e o m e t r y
//
protected void finalizeGeometry( int orgx, int orgy,
int width, int height, boolean liveDrag )
{
m_orgx = orgx;
m_orgy = orgy;
m_size.width = width;
m_size.height = height;
if( m_comp != null ) {
Insets insets = m_constraints.m_insets;
if( insets != null ) {
m_compOrgx = orgx + insets.left;
m_compOrgy = orgy + insets.top;
m_compWidth = width - ( insets.right + insets.left );
m_compHeight = height - ( insets.bottom + insets.top );
}
else {
m_compOrgx = orgx;
m_compOrgy = orgy;
m_compWidth = width;
m_compHeight = height;
}
adjustForGravity();
if( liveDrag ) {
m_comp.setBounds( m_compOrgx, m_compOrgy, m_compWidth, m_compHeight );
m_comp.validate();
}
}
}
//
// e n s u r e C a p a c i t y
//
// Converts the leaf node into an interior node that is
// guaranteed to be big enough to contain a slot at grid
// position (col,row). Parent pointers are taken care of,
// and the new node is returned.
protected MosaicInteriorNode ensureCapacity( int col, int row )
{
MosaicInteriorNode N = new MosaicInteriorNode( m_layout );
N.setParent( m_parent, m_parentCol, m_parentRow );
N.ensureCapacity( col, row );
setParent( N, 0, 0 );
return N;
}
//
// a d j u s t F o r G r a v i t y
//
protected void adjustForGravity()
{
int dx, dy;
if( m_constraints.m_fill == MosaicConstraints.BOTH )
return;
if( m_constraints.m_fill == MosaicConstraints.HORIZONTAL ) {
dx = 0;
}
else {
dx = m_compWidth - m_minSize.width;
m_compWidth = m_minSize.width;
}
if( m_constraints.m_fill == MosaicConstraints.VERTICAL ) {
dy = 0;
}
else {
dy = m_compHeight - m_minSize.height;
m_compHeight = m_minSize.height;
}
switch( m_constraints.m_anchor ) {
case MosaicConstraints.CENTER:
m_compOrgx += dx / 2; m_compOrgy += dy / 2; break;
case MosaicConstraints.EAST:
m_compOrgx += dx; m_compOrgy += dy / 2; break;
case MosaicConstraints.NORTH:
m_compOrgx += dx / 2; break;
case MosaicConstraints.NORTHEAST:
m_compOrgx += dx; break;
case MosaicConstraints.NORTHWEST:
break;
case MosaicConstraints.SOUTH:
m_compOrgx += dx / 2; m_compOrgy += dy; break;
case MosaicConstraints.SOUTHEAST:
m_compOrgx += dx; m_compOrgy += dy; break;
case MosaicConstraints.SOUTHWEST:
m_compOrgy += dy; break;
case MosaicConstraints.WEST:
m_compOrgy += dy / 2; break;
}
}
//
// h a n d l e E v e n t
//
protected void handleEvent( Event evt )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -