gtbase.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,630 行 · 第 1/4 页

CPP
1,630
字号
                r.y( sibStart );
                r.x( sibSep );
            }
            if( node->resolveChildWard( r ) ) {
                roots[ i ]->setBound( r );          // set the roots bounding box
                roots[ i ]->sortEdges();

                sibOff = ( dir == TreeVertical) ? r.x() + r.w() + sibSep
                                                : r.y() + r.h() + sibSep;

                maxX = maxCoord( maxX, r.x() + r.w() );
                maxY = maxCoord( maxY, r.y() + r.h() );
            } else {
                roots[ i ]->setEnable( FALSE );
            }
        }
    }

    world.w( maxX );
    world.h( maxY );
}

// ============ WARNING -- WARNING -- WARNING -- WARNING =============== //
// the following code is very complicated, and makes several assumptions //
// about how other functions in this section operate.  be _very_ careful //
// when changing anything in this section                                //
// \/\/\/\/\/\/\/\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\ //

/* arrange a specific tree.  this operates by first finding a lower
 * bound for this node and all its children by calling getFirstNonContend():
 * this finds the first available position greater than sibOff.  Next,
 * simple children are identified through isSimple(), and arrangeTree()
 * is called for each of these.  the sibOff passed to each child is the
 * lower bound of _descend.  Next, non-simple children are processed with
 * arrangeTree().  Now the node calls place(), then does its parents,
 * again passing the lower bound of _descend.  the _descend width is
 * set by examining the upper bound of all child and parent _descend's.
 */

void TreeNode::arrangeTree( TreeCoord& sibOff )
//---------------------------------------------
{
    TreeCoord  startSib = sibOff;
    TreeCoord  maxDescend = 0;
    TreeCoord  mySib = sibOff;
    bool       vert  = (_parent->getDirection() == TreeVertical);
    int        i;

    if( !_flags.enabled ) {
        _flags.placed = Placed;
        return;
    }

    _flags.placed = Arranging;
    _flags.arranging = 1;

    // partial results used in getFirstNonContend

    TreeCoord offset = sibOff;
    TreeCoord width = _sibWidth;

    getFirstNonContend( offset, width );
    _descend.x( offset );
    _descend.y( offset );
    _descend.w( width );
    _descend.h( width );

    // scram through and check for simple children (one parent, no kids)
    for( i = 0; i < getCount( ChildList ); i += 1 ) {
        TreeNode * node = getNode( ChildList, i );

        if( node->_flags.placed < Arranging && node->isSimple( ChildList ) ) {
            TreeCoord tmpOff = vert ? _descend.x()
                                    : _descend.y();

            node->arrangeTree( tmpOff );
            tmpOff += sibSep;

            if( getLevel() < 0 || node->getLevel() < 0
                || node->getLevel() == getLevel() + 1 ) {

                sibOff = tmpOff;
            }

            if( node->_flags.enabled > Hidden ) {
                maxDescend = maxCoord( maxDescend,
                            vert ? node->_descend.x() + node->_descend.w()
                                 : node->_descend.y() + node->_descend.h()
                            );
            }
        }
    }

    // do non-simple children

    for( i = 0; i < getCount( ChildList ); i += 1 ) {
        TreeNode * node = getNode( ChildList, i );

        if( node->_flags.placed < Arranging ) {
            TreeCoord tmpOff = vert ? _descend.x()
                                    : _descend.y();

            node->arrangeTree( tmpOff );

            tmpOff += sibSep;
            if( getLevel() < 0 || node->getLevel() < 0 ||
                 node->getLevel() == getLevel() + 1 ) {

                sibOff = tmpOff;
            }

            if( node->_flags.enabled > Hidden ) {
                maxDescend = maxCoord( maxDescend,
                            vert ? node->_descend.x() + node->_descend.w()
                                 : node->_descend.y() + node->_descend.h()
                            );
            }
        }
    }

    place( mySib );

    // do simple parents

    for( i = 0; i < getCount( ParentList ); i += 1 ) {
        TreeNode * node = getNode( ParentList, i );

        sibOff = vert ? _descend.x() : _descend.y();

        if( node->isSimple( ParentList ) && node->_flags.placed < Arranging ) {
            node->arrangeTree( sibOff );

            if( node->_flags.enabled > Hidden ) {
                maxDescend = maxCoord( maxDescend,
                            vert ? node->_descend.x() + node->_descend.w()
                                 : node->_descend.y() + node->_descend.h()
                            );
            }
        }
    }

    // do non-simple parents

    for( i = 0; i < getCount( ParentList ); i += 1 ) {
        TreeNode * node = getNode( ParentList, i );

        sibOff = vert ? _descend.x() : _descend.y();

        if( node->_flags.placed < Arranging ) {
            node->arrangeTree( sibOff );

            if( node->_flags.enabled > Hidden ) {
                maxDescend = maxCoord( maxDescend,
                            vert ? node->_descend.x() + node->_descend.w()
                                 : node->_descend.y() + node->_descend.h()
                            );
            }
        }
    }

    if( _flags.placed != Placed ) {
        _flags.placed = PartiallyPlaced;
    } else {
        vert ? _descend.w( maxCoord( _descend.w(), maxDescend - _descend.x() ) )
             : _descend.h( maxCoord( _descend.h(), maxDescend - _descend.y() ) );
    }

    sibOff = maxCoord( sibOff, vert ? _descend.x() + _descend.w()
                                  : _descend.y() + _descend.h() );

    _flags.arranging = 0;
}

/* place a node in the tree.  this first checks that the node is
 * readyToPlace() (ie. all children placed), then calls getMinMax() to
 * find the minimum and maximum children coordinates (based on _bounding)
 * for centering purposes.  Next, getFirstNonContend() is called to
 * find the minimum _bounding and maximum width
 */

void TreeNode::place( TreeCoord& sibOff )
//---------------------------------------
{
    bool vert = (_parent->getDirection() == TreeVertical );
    if( _flags.placed == Placed ) {
        sibOff +=  (vert) ? _descend.w()
                          : _descend.h();
        return;
    }

    if( !readyToPlace() ) {
        return;
    }

    _flags.placed = Placed;

    TreeCoord maxSibW = _sibWidth;
    TreeCoord minSib = (vert) ? _descend.x()
                              : _descend.y();
    TreeCoord maxSib = sibOff;

    sibOff = maxCoord( sibOff, minSib );

    getMinMax( minSib, maxSib );
    maxSibW = maxCoord( maxSibW, maxSib - maxCoord( minSib, sibOff ) );
    TreeCoord oldMaxSibW = maxSibW;
    getFirstNonContend( sibOff, maxSibW );

    (vert) ? _descend.x( maxCoord( _descend.x(), sibOff ) )
           : _descend.y( maxCoord( _descend.y(), sibOff ) );

    TreeCoord x;
    TreeCoord y;
    TreeCoord tryW;
    if( sibOff > minSib || oldMaxSibW > maxSibW ) {
        x = _descend.x() + maxSibW / 2 - _bounding.w() / 2;
        y = _descend.y() + maxSibW / 2 - _bounding.h() / 2;
        tryW = ( vert ? _descend.x() : _descend.y() ) + maxSibW;
    } else {
        x = minSib + maxSibW / 2 - _bounding.w() / 2;
        y = minSib + maxSibW / 2 - _bounding.h() / 2;
        tryW = minSib + maxSibW;
    }

    (vert) ? _descend.w( maxCoord( _descend.w(), tryW - _descend.x() ) )
           : _descend.h( maxCoord( _descend.h(), tryW - _descend.y() ) );

    move( x, y );
    sibOff += maxSibW;

    _descend.w( maxCoord( _descend.w(), _bounding.x() + _bounding.w() - _descend.x() ) );
    _descend.h( maxCoord( _descend.h(), _bounding.y() + _bounding.h() - _descend.y() ) );
}

/* get the minimum and maximum coordinates of visible children
 */

void TreeNode::getMinMax( TreeCoord& minSib, TreeCoord& maxSib )
//--------------------------------------------------------------
{
    bool        vert = (_parent->getDirection() == TreeVertical);
    TreeCoord   tmpx, tmpy;
    int         i;

    for( i = getCount( ChildList ); i > 0; i -= 1 ) {
        TreeNode * node = getNode( ChildList, i - 1 );
        if( node->_flags.placed > Arranging && node->_flags.enabled != Hidden ) {

            node->getMinSibCoord( tmpx, tmpy );
            minSib = maxCoord( minSib, vert ? tmpx : tmpy );

            break;
        }
    }

    for( i = getCount( ChildList ); i > 0; i -= 1 ) {
        TreeNode * node = getNode( ChildList,  i - 1 );
        if( node->_flags.enabled > Hidden ) {
            node->getMinCoord( tmpx, tmpy );
            minSib = minCoord( minSib, vert ? tmpx : tmpy );

            node->getMaxCoord( tmpx, tmpy );
            maxSib = maxCoord( maxSib, vert ? tmpx : tmpy );
        }
    }
}

/* this function finds the first available location for a node to be placed.
 * it is called twice for each node -- once before the node is placed to
 * find a left boundary for its children, and once again when it is being
 * placed to see if it has to restrict its width.  To find the first
 * available location, it does the following:  start at the minimum
 * position of your parent (his _descend.{x|y}).  Check all nodes at
 * the same level---if this location lies within another, move the active
 * position (sibOff) to be past the other node.  If a common child node
 * is shared, then restrict the other node to its _sibWidth.  Now, since
 * the nodes aren't ordered, the loop must be restarted (i = -1) to make
 * sure that if we fit in to the left of a node before, we still fit.
 *
 * This procedure could definitely be optimized by sorting the nodes; then
 * it wouldn't be necessary to start all over again.
 */

void TreeNode::getFirstNonContend( TreeCoord& sibOff, TreeCoord& width )
//----------------------------------------------------------------------
{
    if( getLevel() < 0 ) {
        return;
    }

    TreeCoord  origW = width;
    bool vert = _parent->getDirection() == TreeVertical;

    for( int i = 0; i < getCount( FlatList ); i += 1 ) {
        TreeNode * node = getNode( FlatList, i );
        TreeCoord    nodeW = maxCoord( node->_sibWidth,
                                       vert ? node->_descend.w()
                                            : node->_descend.h() );

        if( node != this && node->getLevel() == getLevel() &&
            node->_flags.placed != NotPlaced && node->_flags.enabled > Hidden ) {

            TreeCoord lOff = vert ? node->_descend.x() - sibSep
                            : node->_descend.y() - sibSep;
            TreeCoord mOff = vert ? node->_descend.x() + nodeW + sibSep
                            : node->_descend.y() + nodeW + sibSep;
            if( sibOff + width > lOff && sibOff < mOff ) {
                // contention happening -- try to shrink

                width = maxCoord( _sibWidth,
                                vert ? node->_descend.x() - sibOff - sibSep
                                     : node->_descend.y() - sibOff - sibSep );
            }

            if( sibOff + width > lOff && sibOff < mOff ) {
                // shrinking couldn't fix it -- restore to original size
                // and move past this node.

                width = origW;

                bool done = FALSE;
                for( int childCnt1 = getCount( ChildList );
                     childCnt1 > 0 && !done; childCnt1 -= 1 ) {
                    TreeNode * node1 = getNode( ChildList, childCnt1 - 1 );

                    if( node1->_flags.enabled > Hidden ) {
                        for( int childCnt2 = node->getCount( ChildList );
                             childCnt2 > 0 && !done; childCnt2 -= 1 ) {
                            TreeNode * node2;

                            node2 = node->getNode( ChildList, childCnt2 - 1 );
                            if( node1 == node2 ) {
                                nodeW = node->shrinkToSib();
                                done = TRUE;
                            }
                        }
                    }
                }

                TreeCoord newOff = vert ? node->_descend.x()
                                        : node->_descend.y();
                newOff += nodeW + sibSep;

                sibOff = maxCoord( sibOff, newOff );

                i = -1;     // re-start the loop
            }
        }
    }
}

// \/\/\/\/\/\/\/\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\ //
// the above code is very complicated, and makes several assumptions     //
// about how other functions in this section operate.  be _very_ careful //
// when changing anything in this section                                //
// ============ WARNING -- WARNING -- WARNING -- WARNING =============== //



/* check all of a nodes children; if they are all placed, it is ready
 * to place itself
 */

bool TreeNode::readyToPlace( void )
//---------------------------------
{
    for( int i = getCount( ChildList ); i > 0; i -= 1 ) {
        TreeNode * nd = getNode( ChildList, i - 1 );
        if( (nd->_flags.enabled > Hidden) && (nd->_flags.placed != Placed) ) {
            return FALSE;
        }
    }

    return TRUE;
}

/* a node is simple if it has only one parent and no children.  simple
 * nodes are placed first
 */

bool TreeNode::isSimple( TreeList_T lst )
//---------------------------------------
{
    TreeList_T otherList = (lst == ParentList) ? ChildList : ParentList;

    if( getNumEnabled( otherList ) > 1 ) return FALSE;

    if( getNumEnabled( lst ) > 0 ) return FALSE;


    // this is a special case when rings have been placed

    for( int i = getCount( otherList ); i > 0; i -= 1 ) {
        TreeNode * node = getNode( otherList, i - 1 );

        if( node->_flags.enabled > Hidden && node->getLevel() < 0 &&
            node->getCount( otherList ) > 1 ) return FALSE;
    }

    return TRUE;
}

/* are graphs drawn vertically or horizontally ?
 */

TreeDirection TreeNode::getDirection( void ) const
//------------------------------------------------
{

⌨️ 快捷键说明

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