⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mosaiclayout.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////
//
// MosaicLayout.java 1.0 97/02/05 Robert Buff buff@cs.nyu.edu
//                   1.1 97/06/19 Robert Buff buff@cs.nyu.edu
//                   1.2 97/07/10 Robert Buff buff@cs.nyu.edu
//                   1.3 97/07/30 Robert Buff buff@cs.nyu.edu
//                   1.4 98/01/30 Robert Buff buff@cs.nyu.edu

//                  1.5A 06/05/98 Antranig Basman amb26@eng.cam.ac.uk

//  !!!!!! represents fixes performed for 1.5A by AMB.

//
// Copyright (c) 1997, 98 Robert Buff. All Rights Reserved.
//
// You may use, copy, modify, and distribute this software
// for NON-COMMERCIAL purposes and without fee provided that
// this copyright notice appears in all copies. If you would
// like to use this software for COMMERCIAL purposes, contact
// the author and we will work something out.
//
// It would also be nice to give credit to the author in the
// Help/About dialog window of any application that uses this
// software.
//
///////////////////////////////////////////////////////////////
//
// This class defines a layout manager that a) organizes its
// components in a hierarchical manner, and b) allows the user
// to resize its components by clicking on and dragging of sashes.
//
// The layout manager mirrors the subdivision of the panel space 
// in a tree whose leaf nodes point to the components, and whose
// interior nodes correspond to rectangular grids.  The columns
// and rows of each interior grid can be resized by the user by
// dragging the sashes that are inserted between adjacent columns
// and rows.
//
// In addition, the layout manager follows a dynamic resizing
// policy that is activated when the underlying panel changes
// its size.  Weights can be assigned to each component; these
// weights, together with the minimum and preferred size of
// the components, determine how the actual size of each
// component changes.
//
// Supporting classes:
//
//   MosaicConstraints: its relation to MosaicLayout is similar
//       to the relation of GridBagConstraints to GridBagLayout.
//       For each component, weights and gravity parameters can
//       be specified.
//
//   MosaicCoordStack: contains the position that is assigned to
//       a component.  Basically, a sequence of (column/row)
//       pairs whose length corresponds to the level of the
//       component in the hierarchy.  Describes the path to
//       the component in the tree.
//
//   MosaicPanel: a subclass of Panel that notifies the layout
//       manager of mouse events and paint requests, for it is
//       the layout manager's responsibility to draw the sashes
//       and handle resize requests delivered by mouse events.
//       If the parent of the layout manager is NOT a MosaicPanel,
//       the layout manager is still functioning, but does not
//       draw sashes any more. The possibility of manually
//       rearranging the components is then no longer given.
//       The layout manager checks for the type of its parent
//       and acts accordingly.
//
// The sashes are painted directly on the parent MosaicPanel,
// without additional components.  The look of the sashes comes
// close to the look of sashes in Windows environments.  I didn't
// bother to make them look nice on black-and-white monitors.
//
// Resizing is done online - while dragging - by default, but this
// can be switched off if repainting the components is expensive
// (see m_liveDrag).
//
// No component is ever made smaller than its minimum size,
// even if the underlying panel gets smaller.  However, components
// can be manually made larger than their preferred size even if
// their assigned weight is zero.
//
// It is possible to create named constraints and load them into
// a dictionary that the layout manager maintains.  Later on,
// these constraints can be assigned to any number of components
// by specifying their name in the add( name, comp ) version of
// the add function of the underlying container panel.
//
// In general, the features of the layout manager can be discovered
// best by studying the commented public member functions of the
// class MosaicLayout, listed in the top section of the class
// definition.  Other features and strategies are only sparsely
// commented.
//
// The following is an example of how to use MosaicLayout. Note
// that the position of components can be indicated by submitting
// MosaicCoordStack objects directly to the layout manager, or
// by calling the layout manager's setPos() function which
// essentially creates a MosaicCoordStack object for the next
// component that is registered with the add( name, comp )
// function of the underlying panel (you must use the version
// that supplies a name in this case, as the other version
// delays transfering the data to the layout manager, thus
// disrupting the order).
//
// The example without using MosaicCoordStack directly (order
// is crucial):
//
//   MosaicPanel m_panel = new MosaicPanel();
//   MosaicLayout m_layout = new MosaicLayout();
//
//   setLayout( new BorderLayout() );
//   add( "Center", m_panel );
//   m_panel.setLayout( m_layout );
//
//   Button button1 = new Button( "Monday" );
//   Button button2 = new Button( "Tuesday" );
//   Button button3 = new Button( "Wednesday" );
//   Button button4 = new Button( "Thursday" );
//   Button button5 = new Button( "Friday" );
//   Button button6 = new Button( "Saturday" );
//   Button button7 = new Button( "Sunday" );
//
//   m_layout.setPos( 0, 0, 0, 0 );
//   m_panel.add( "", button1 );
//
//   m_layout.setPos( 0, 0, 1, 0, 0, 0 );
//   m_panel.add( "", button2 );
//
//   m_layout.setPos( 0, 0, 1, 0, 1, 0 );
//   m_panel.add( "", button3 );
//
//   m_layout.setPos( 0, 0, 1, 0, 0, 1 );
//   m_panel.add( "", button4 );
//
//   m_layout.setPos( 0, 0, 1, 0, 1, 1 );
//   m_panel.add( "", button5 );
//
//   m_layout.setPos( 0, 1, 0, 0 );
//   m_panel.add( "", button6 );
//
//   m_layout.setPos( 0, 1, 1, 0 );
//   m_panel.add( "", button7 );
//
//   m_layout.setConstraints( button3, new MosaicConstraints(
//     MosaicConstraints.CENTER, MosaicConstraints.HORIZONTAL ) );
//
//   m_layout.setConstraints( button5, new MosaicConstraints(
//     MosaicConstraints.CENTER, MosaicConstraints.HORIZONTAL ) );
//
// The example when MosaicCoordStack is used (the order
// does not matter any more; only the middle section of
// the code is repeated):
//
//   m_panel.add( button1 );
//   m_panel.add( button2 );
//   m_panel.add( button3 );
//   m_panel.add( button4 );
//   m_panel.add( button5 );
//   m_panel.add( button6 );
//   m_panel.add( button7 );
//
//   MosaicCoordStack c;
//	 
//   c.setPos( 0, 0, 0, 0 );
//   m_layout.setCoordStack( button1, c );
//   c.setPos( 0, 0, 1, 0, 0, 0 );
//   m_layout.setCoordStack( button2, c );
//   c.setPos( 0, 0, 1, 0, 1, 0 );
//   m_layout.setCoordStack( button3, c );
//   c.setPos( 0, 0, 1, 0, 0, 1 );
//   m_layout.setCoordStack( button4, c );
//   c.setPos( 0, 0, 1, 0, 1, 1 );
//   m_layout.setCoordStack( button5, c );
//   c.setPos( 0, 1, 0, 0 );
//   m_layout.setCoordStack( button6, c );
//   c.setPos( 0, 1, 1, 0 );
//   m_layout.setCoordStack( button7, c );
//
// No guarantee is made that this code actually does what
// has been described above.  This is a first version that
// surely contains bugs.
//
///////////////////////////////////////////////////////////////
//
// History:
//
//
//  1.1  Default cursor is activated in empty tiles.
//       layout() is now called recursively for all components.
//
//  1.2  checkPanel() is now called in minimumLayoutSize() and
//       preferredLayoutSize. These functions are called before
//       layoutContainer() by parent layout managers.
//
//  1.3  After dragging the sashes, the event MOUSE_UP triggers
//       a final recursion in the component tree, to determine the
//       correct cursor shape. Note, however, that (at least in
//       my version of VJ++) the default shape becomes only 
//       active again after the mouse is moved. Don't know why.
//
//  1.4  Minor bugfix: now calling validate() instead of
//       layout() in 1.1.
//
///////////////////////////////////////////////////////////////

package nom.rb.common;

import java.awt.*;
import java.util.*;

import nom.rb.common.MosaicConstraints;
import nom.rb.common.MosaicCoordStack;
import nom.rb.common.MosaicPanel;

///////////////////////////////////////////////////////////////
//
//   M o s a i c L a y o u t
//
///////////////////////////////////////////////////////////////

public class MosaicLayout extends Object implements LayoutManager
{
  // The layout manager maintains a repository of reusable
  // constraint objects, that can be assigned to components
  // many times.  They are identified by their unique name
  // and stored in the following hashtable.

  protected Hashtable m_name2Constraints = null;

  // Each component is represented by a leaf node in the tree
  // that mirrors the hierarchy.  The leaf node that corresponds
  // to a particular component can be found in this hashtable.

  protected Hashtable m_comp2Node = null;

  // Whenever a MosaicCoordStack object is passed to the layout
  // manager, it is copied and the column counter at its lowest
  // level is advanced to the next column to the right.  When a
  // new component is registered, this generated MosaicCoordStack
  // object is taken as its default position.

  protected MosaicCoordStack m_lastCoordStack = null;
  protected MosaicCoordStack m_nextCoordStack = null;

  // This is the root node of the hierarchy tree.

  protected MosaicNode m_root = null;

  // If the parent of the layout manager is a MosaicPanel,
  // then sashes are displayed between components that can
  // be grabbed by the user in order to resize the components.
  // In addition to that, the layout manager tries to detect
  // the frame that contains the panel, because cursor types
  // can only be changed for frames.
  // If the parent of the layout manager is not a MosaicPanel,
  // m_panel is set to null.

  protected MosaicPanel m_panel = null;
  protected Frame m_frame = null;

  // Dragging does always refer to a particular interior
  // node in the hierarchy.  Which one?  This one:

  protected MosaicInteriorNode m_activeNode = null;
  
  // The cursor changes its shape on sashes (if the frame of
  // the parent could be found) according to the following
  // values.  On Windows systems, a different shape is chosen
  // for column and row sashes and for intersections.  On all
  // other systems, the cursor is uniformly changed to
  // MOVE_CURSOR.

  protected int colSashCursor = Frame.DEFAULT_CURSOR;
  protected int rowSashCursor = Frame.DEFAULT_CURSOR;
  protected int crossSashCursor = Frame.DEFAULT_CURSOR;

  // The size of sashes can be set for top level sashes and
  // sashes on all other levels of the hierarchy separately.

  protected int m_topLevelSashSize = 7;
  protected int m_medLevelSashSize = 7;

  // The following variable controls whether the repositioning
  // that results from dragging operations is done while the
  // dragging is going on, thus giving online feedback,
  // or if it should be delayed until the mouse button is
  // released (better for components that take a long time to
  // draw).  Note that if the latter is chosen, there is no
  // hint like outlined sashes.

  protected boolean m_liveDrag = true;

  // Remember if the tree has been constructed (m_initialized)
  // and the components have been reshaped (m_finalized).

  protected boolean m_initialized = false;
  protected boolean m_finalized = false;

  //
  //   M o s a i c L a y o u t
  //

  // The constructor. MosaicConstraints object are registered
  // under the name "Default" and "Centered."  The latter one
  // centers its component at its minimum size.

  public MosaicLayout()
  {
    m_name2Constraints = new Hashtable();
    m_comp2Node = new Hashtable();
    setConstraints( "Default", new MosaicConstraints() );
    setConstraints( "Centered",
      new MosaicConstraints( MosaicConstraints.CENTER,
        MosaicConstraints.NONE ) );
  }

  //
  //   a d d L a y o u t C o m p o n e n t
  //

  // One of the required callbacks of a layout manager.
  // The component comp is added with the constraints that have
  // previously been registered under the specified name.  Its
  // position in the hierarchy is initialized as being to
  // the right of the last position that has been registered
  // or generated.  If the component has already been
  // added (meaning it is found in the m_comp2Node hashtable),
  // only the constraints are changed; its position remains
  // unchanged.

  public void addLayoutComponent( String name, Component comp )
  {
    if( m_comp2Node.containsKey( comp ) ) {
      lookupNode( comp ).m_constraints = newConstraints( name );
    }
    else {
      m_comp2Node.put( comp, new MosaicLeafNode( this, comp,
        newConstraints( name ), newCoordStack() ) );
    }
    m_initialized = m_finalized = false;
  }

  //
  //   l a y o u t C o n t a i n e r
  //

  // One of the required callbacks of a layout manager.
  // The hierarchy tree is generated from all the components
  // that belong to the container parent.  This contains all
  // the components that have been registered with the
  // addLayoutComponent() function, but also others.  For
  // those others that cannot be found in the hashtable
  // m_comp2Node, leaf nodes are generated on the fly.
  // (Their constraints and positions - coord stacks - are
  // generated on the fly as well.)  Note that one can
  // very well register the constraints or position of
  // a component that has not been added with
  // addLayoutComponent(); as a general rule, leaf nodes
  // are created whenever necessary.

  public void layoutContainer( Container parent )
  {
    checkPanel( parent );
    initializeGeometry( parent );
    if( m_root != null ) {
      Insets insets = parent.getInsets();
      Dimension size = parent.getSize();
      m_root.finalizeGeometry( insets.left, insets.top,
        size.width - insets.left - insets.right,
        size.height - insets.top - insets.bottom, true );
    }
    m_finalized = true;
  }

  //
  //   m i n i m u m L a y o u t S i z e
  //

  // One of the required callbacks of a layout manager.
  // Returns the overall minimum size derived from the
  // minimum sizes of all components.  The tree is
  // generated first if it doesn't exist yet.

  public Dimension minimumLayoutSize( Container parent )
  {
    checkPanel( parent );
    initializeGeometry( parent );
    if( m_root == null )
      return new Dimension( 0, 0 );
    return m_root.m_minSize;
  }

  //
  //   p r e f e r r e d L a y o u t S i z e
  //

  // One of the required callbacks of a layout manager.
  // Returns the overall preferred size derived from the
  // preferred sizes of all components.  The tree is
  // generated first if it doesn't exist yet.

  public Dimension preferredLayoutSize( Container parent )
  {
    checkPanel( parent );
    initializeGeometry( parent );
    if( m_root == null )
      return new Dimension( 0, 0 );
    // !!!!!! *BIG* bug fix here - line used to read m_root.m_size. AMB 05/98
    return m_root.m_prefSize;
  }

  //
  //   r e m o v e L a y o u t C o m p o n e n t
  //

  // One of the required callbacks of a layout manager.
  // The component comp is removed from the hashtable
  // m_comp2Node, and is thus no longer part of the
  // construction.  The hierachy tree is marked as 
  // invalid; it is rebuilt when layoutContainer() is
  // called later on.

  public void removeLayoutComponent( Component comp )
  {
    if( m_comp2Node.containsKey( comp ) ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -