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 + -
显示快捷键?