gtring.cpp

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

CPP
964
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "wbrdefs.h"
#include "assure.h"
#include "gtring.h"
#include "gtedges.h"
#include "gtwin.h"

#define ChildOff 25
#define ChildH   10
#define ChildW   10
const sibSep = 10;

const int POOLSIZE = 64;

#pragma warning 549 5           // sizeof contains compiler genned info.
MemoryPool TreeRing::_pool( sizeof( TreeRing ), "TreeRing", POOLSIZE );
#pragma warning 549 3

#define CONFLICTCOLOUR (ColorWhite)

TreeRing::TreeRing( TreeWindow * parent, TreePtr * ptr )
            : TreeNode( parent )
            , _sorted( FALSE )
            , _cut( FALSE )
            , _hasLineTop( FALSE )
            , _hasLineBottom( FALSE )
            , _hasLineConnector( FALSE )
            , _level( 0 )
//------------------------------------------------------
{
    TreeNode * parnt = ptr->getTo();
    TreeNode * child = ptr->getFrom();
    TreePtr *  pPtr = ptr->makeClone();

    _level = parnt->getLevel();

    pPtr->setFrom( this );
    _parents.add( pPtr );
    parnt->swapNode( ChildList, child, this );

    ptr->setTo( this );
    _children.add( ptr );

    #if DEBUG
    _nm = "TreeRing";
    #endif
}

TreeRing::~TreeRing()
{
    int i;

    for( i = _parents.count(); i > 0; i -= 1 ) {
        delete _parents[ i - 1 ];
    }
}

void * TreeRing::operator new( size_t )
//-------------------------------------
{
    return( _pool.alloc() );
}

void TreeRing::operator delete( void * mem )
//------------------------------------------
{
    _pool.free( mem );
}

void TreeRing::unWrap( void )
//---------------------------
{
    int     i;

    for( i = _children.count(); i > 0; i -= 1 )  {
        TreePtr * ptr = _children[ i - 1 ]->makeClone();

        for( int j = _parents.count(); j > 0; j -= 1 ) {
            TreeNode * node = _parents[ j - 1 ]->getTo();
            ptr->setTo( node );
            node->addPtr( ChildList, ptr );
        }
        delete ptr;
    }

    for( i = _parents.count(); i > 0; i -= 1 ) {
        TreePtr * ptr = _parents[ i - 1 ]->makeClone();

        for( int j = _children.count(); j > 0; j -= 1 ) {
            TreeNode * node = _children[ j - 1 ]->getFrom();

            ptr->setFrom( node );
            node->addPtr( ParentList, ptr );
            ptr = ptr->makeClone();
        }
        delete ptr;
    }

    TreeNode * rem;
    for( i = _parents.count(); i > 0; i -= 1 ) {
        rem =_parents[ i - 1 ]->getTo()->removeNode( ChildList, this );
        ASSERT( rem == this, "gtring::unwrap parent didn't remove", 0 );
    }
    for( i = _children.count(); i > 0; i -= 1 ) {
        rem = _children[ i - 1 ]->getFrom()->removeNode( ParentList, this );
        ASSERT( rem == this, "gtring::unwrap parent didn't remove", 0 );
    }
}

bool TreeRing::addPtr( TreePtr * ptr )
//------------------------------------
{
    bool found = FALSE;
    TreeNode * parnt = ptr->getTo();
    TreeNode * child = ptr->getFrom();

    _sorted = FALSE;

    if( isParent( parnt ) ) {
        if( canJoin( parnt, child ) ) {
            ptr->setTo( this );
            _children.add( ptr );
            return TRUE;
        } else {
            return FALSE;
        }
    }
    if( isChild( child ) ) {
        if( canJoin( parnt, child ) ) {
            TreePtr * pPtr = ptr->makeClone();
            pPtr->setFrom( this );
            _parents.add( pPtr );
            parnt->swapNode( ChildList, child, this );

            _level = maxInt( _level, parnt->getLevel() );

            return TRUE;
        } else {
            return FALSE;
        }
    }

    return FALSE;
}

void TreeRing::paint( OutputDevice *dev, TreeRect * r )
//-----------------------------------------------------
{
    PaintInfo * pinf;
    TreeCoord xOff = _parent->getXOff();
    TreeCoord yOff = _parent->getYOff();
    int i;

    pinf = dev->getPaintInfo();
    dev->setPaintInfo( getPaintInfo() );

    /*
     * _hasLineTop, _hasLineBottom, _hasLineConnector are set
     * in addEdges
     */
    if( _hasLineTop ) {
        _lineTop.paint( dev, xOff, yOff );
    }

    if( _hasLineBottom ) {
        _lineBottom.paint( dev, xOff, yOff );
    }

    if( _hasLineConnector ) {
        _lineConnector.paint( dev, xOff, yOff );
    }

    for( i = 0; i < _parents.count(); i += 1 ) {
        _parents[ i ]->paint( dev, r );
    }

    delete dev->getPaintInfo();
    dev->setPaintInfo( pinf );
}

PaintInfo * TreeRing::getPaintInfo( void )
//----------------------------------------
// go through all parents and children -- if they are all the
// same colour and style, then use that.  Otherwise, use a
// conflict colour and style
{
    PaintInfo * pinf;
    Color       clr = ColorBlack;
    WLineStyle  stl = LS_PEN_SOLID;
    unsigned    thk = 1;
    int         i;

    if( _parents.count() > 0 ) {
        pinf = _parents[ 0 ]->getPaintInfo();
        clr = pinf->getColour();
        stl = pinf->getStyle();
        thk = pinf->getThickness();
        delete pinf;
    }

    for( i = 1; i < _parents.count(); i += 1 ) {
        pinf = _parents[ i ]->getPaintInfo();
        if( clr != pinf->getColour() ||
            stl != pinf->getStyle()  ||
            thk != pinf->getThickness() ) {

            clr = CONFLICTCOLOUR;
            stl = LS_PEN_SOLID;
            thk = 1;
            delete pinf;
            break;
        }

        delete pinf;
    }

    for( i = 0; i < _children.count(); i += 1 ) {
        pinf = _children[ i ]->getPaintInfo();
        if( clr != pinf->getColour() ||
            stl != pinf->getStyle()  ||
            thk != pinf->getThickness() ) {

            clr = CONFLICTCOLOUR;
            stl = LS_PEN_SOLID;
            thk = 1;
            delete pinf;
            break;
        }

        delete pinf;
    }

    return new PaintInfo( clr, thk, stl );
}

void TreeRing::addEdges( TreeEdgeBreaker * breaker )
//--------------------------------------------------
{
    bool    vert = (_parent->getDirection() == TreeVertical);

    TreeCoord cfx, cfy, clx, cly;   //child first x, ..., child lasty
    TreeCoord pfx, pfy, plx, ply;   //parent first x, ..., parent lasty
    TreeCoord mx, my;               //middle x, middle y
    TreeCoord tmpx, tmpy;
    TreeCoord xOff = _parent->getXOff();
    TreeCoord yOff = _parent->getYOff();
    bool      cSet = FALSE;
    int       i;

    setChildWard();

    if( !_sorted ) {
        sortPrtKids();
    }

    for( i = 0; i < _children.count(); i += 1 ) {
        if( _children[ i ]->getFrom()->getEnable() > Hidden ) {
            _children[i]->getFrom()->getFromCoord( _children[i], tmpx, tmpy );

            if( !cSet ) {
                cfx = clx = tmpx;
                cfy = cly = tmpy;
                cSet = TRUE;
            } else {
                cfx = minCoord( cfx, tmpx );
                cfy = minCoord( cfy, tmpy );
                clx = maxCoord( clx, tmpx );
                cly = maxCoord( cly, tmpy );
            }
        }
    }

    /*
     * If there aren't any children, then we don't need to draw any parts
     * of the tree ring
     */
    if( !cSet ) {
        return;
    }

    cSet = FALSE;
    for( i = 0; i < _parents.count(); i += 1 ) {
        if( _parents[i]->getTo()->getEnable() > Hidden ) {
            _parents[i]->getTo()->getToCoord( _parents[i], tmpx, tmpy );

            if( !cSet ) {
                pfx = plx = tmpx;
                pfy = ply = tmpy;
                cSet = TRUE;
            } else {
                pfx = minCoord( pfx, tmpx );
                pfy = minCoord( pfy, tmpy );
                plx = maxCoord( plx, tmpx );
                ply = maxCoord( ply, tmpy );
            }
        }
    }

    /*
     * If there aren't any parents, then we don't need to draw any parts
     * of the tree ring
     */
    if( !cSet ) {
        return;
    }

    mx = minInt(cfx,pfx) + (maxInt(clx,plx) - minInt(cfx,pfx)) / 2;
    my = minInt(cfy,pfy) + (maxInt(cly,ply) - minInt(cfy,pfy)) / 2;

    _hasLineBottom = FALSE;
    _hasLineTop = FALSE;
    _hasLineConnector = FALSE;
    if( vert ) {
        /*
         * If there's more then one enabled child, we need a horizontal
         * bar to join the children's edges
         */
        if( getNumEnabled( ChildList ) > 1 ) {

            _lineBottom.set( minInt(mx,cfx),
                             _bounding.y() + _bounding.h() + 1,
                             maxInt(mx,clx)+1,
                             _bounding.y() + _bounding.h() + 1,
                             TreeLine::RingBottom );
            breaker->addLine( &_lineBottom );
            _hasLineBottom = TRUE;
        } else {
            // numEnabled == 1, so cfx == clx
            _lineConnector.set( cfx, _bounding.y(), cfx,
                               _bounding.y() + _bounding.h() + 2,
                               TreeLine::RingConnector );
            breaker->addLine( &_lineConnector );
            _hasLineConnector = TRUE;
        }

        /*
         * If there's more than one parent or the parents aren't aligned
         * over the children, then we need a horizontal line to join
         * the parents
         */
        if( getNumEnabled( ParentList ) > 1 || clx < pfx || cfx > plx ) {

            _lineTop.set( minInt(minInt(mx,pfx),clx), _bounding.y(),
                          maxInt(maxInt(mx,plx),cfx) + 1,
                          _bounding.y(),
                          TreeLine::RingTop );
            breaker->addLine( &_lineTop );
            _hasLineTop = TRUE;
        } else {
            if( _hasLineBottom ) {          // child hasn't already drawn
                _lineConnector.set( pfx, _bounding.y(), pfx,
                                    _bounding.y() + _bounding.h() + 1,
                                    TreeLine::RingConnector );
            breaker->addLine( &_lineConnector );
            _hasLineConnector = TRUE;
            }
        }

        if( _hasLineBottom && _hasLineTop ) {
            _lineConnector.set( mx, _bounding.y(), mx,
                                _bounding.y() + _bounding.h() + 1,
                                TreeLine::RingConnector );
            breaker->addLine( &_lineConnector );
            _hasLineConnector = TRUE;
        }
    } else {
        if( getNumEnabled( ChildList ) > 1 ) {
            _lineBottom.set( _bounding.x() + _bounding.w() + 1, minInt( my, cfy ),
                             _bounding.x() + _bounding.w() + 1, maxInt( my, cly ),
                             TreeLine::TreeLine::RingBottom );
            breaker->addLine( &_lineBottom );
            _hasLineBottom = TRUE;
        } else {
            _lineConnector.set( _bounding.x(), cfy,
                                _bounding.x() + _bounding.w() + 2, cfy,
                                TreeLine::RingConnector );
            breaker->addLine( &_lineConnector );
            _hasLineConnector = TRUE;
        }

        if( getNumEnabled( ParentList ) > 1 || cly < pfy || cfy > ply ) {
            _lineTop.set( _bounding.x(), minInt( minInt( my, pfy ), cly ),
                                _bounding.x(), maxInt( maxInt( my, ply ), cfy ) + 1,
                                TreeLine::RingTop );
            breaker->addLine( &_lineTop );
            _hasLineTop = TRUE;
        } else {
            if( _hasLineBottom ) {
                _lineConnector.set( _bounding.x(), pfy,
                                    _bounding.x() + _bounding.w() + 1, pfy,
                                    TreeLine::RingConnector );
                breaker->addLine( &_lineConnector );
                _hasLineConnector = TRUE;
            }
        }

        if( _hasLineBottom && _hasLineTop ) {
            _lineConnector.set( _bounding.x(), my,
                                _bounding.x() + _bounding.w() + 1, my,
                                TreeLine::RingConnector );
            breaker->addLine( &_lineConnector );
            _hasLineConnector = TRUE;
        }
    }

    for( i = 0; i < _parents.count(); i += 1 ) {
        _parents[ i ]->addEdges( breaker );
    }
}

void TreeRing::joinRings( TreeRingList & list )
//---------------------------------------------
//
// Try to join as many rings as possible, using a "greedy" algorithm
{
    bool joinMore;

    /*
     * In each pass of this loop, we try to join any of the rings in the
     * ring list.  We stop when we can't join any more rings.
     */
    do {
        int     i;

        joinMore = FALSE;

        /*
         * Go through the list of rings, trying to join pairs of rings
         */
        for( i = list.count(); i > 0; i -= 1 ) {
            TreeRing * tryRing = list[ i - 1 ];

            if( tryRing != NULL ) {
                for( int j = list.count(); j > 0; j -= 1 ) {
                    if( list[ j - 1 ] != NULL && j != i ) {
                        if( tryRing->sameRing( list[ j - 1 ] ) ) {
                            joinMore = TRUE;

                            tryRing->joinTo( list[ j - 1 ] );
                            delete list[ j - 1 ];
                            list.replaceAt( j - 1, NULL );
                        }
                    }
                }
            }
        }

        for( i = list.count(); i > 0; i -= 1 ) {
            if( list[ i - 1 ] == NULL ) {
                list.removeAt( i - 1 );
            }

⌨️ 快捷键说明

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