<commit_before>/*************************************************************************
 *
 *  $RCSfile: view1.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2004-06-17 16:07:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif
#ifndef _SVDVIEW_HXX //autogen
#include <svx/svdview.hxx>
#endif
#ifndef _SVX_RULER_HXX //autogen
#include <svx/ruler.hxx>
#endif
#ifndef _IDXMRK_HXX
#include <idxmrk.hxx>
#endif
#ifndef _VIEW_HXX
#include <view.hxx>
#endif
#ifndef _WRTSH_HXX
#include <wrtsh.hxx>
#endif
#ifndef _SWMODULE_HXX
#include <swmodule.hxx>
#endif
#ifndef _VIEWOPT_HXX
#include <viewopt.hxx>
#endif
#ifndef _DOCSH_HXX
#include <docsh.hxx>
#endif
#ifndef _GLOBDOC_HXX
#include <globdoc.hxx>
#endif
#ifndef _NAVIPI_HXX
#include <navipi.hxx>
#endif
#ifndef _FLDWRAP_HXX
#include <fldwrap.hxx>
#endif
#ifndef _REDLNDLG_HXX
#include <redlndlg.hxx>
#endif
#ifndef _DPAGE_HXX
#include <dpage.hxx>
#endif
#ifndef _EDTWIN_HXX
#include <edtwin.hxx>
#endif

#ifndef _CMDID_H
#include <cmdid.h>
#endif

extern int bDocSzUpdated;

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::Activate(BOOL bMDIActivate)
{
    // aktuelle View anmelden an der DocShell
    // die View bleibt solange an der DocShell
    // aktiv bis Sie zerstoert wird oder durch Activate eine
    // neue gesetzt wird
    SwDocShell* pDocSh = GetDocShell();
    if(pDocSh)
        pDocSh->SetView(this);
    SwModule* pSwMod = SW_MOD();
    pSwMod->SetView(this);

    // Dokumentgroesse hat sich geaendert
    if(!bDocSzUpdated)
        DocSzChgd(aDocSz);

    pHRuler->SetActive( TRUE );
    pVRuler->SetActive( TRUE );

    if ( bMDIActivate )
    {
        pWrtShell->ShGetFcs(FALSE);     // Selektionen sichtbar

        if( sSwViewData.Len() )
        {
            ReadUserData( sSwViewData, FALSE );
            sSwViewData.Erase();
        }

        AttrChangedNotify(pWrtShell);

        // Flddlg ggf neu initialisieren (z.B. fuer TYP_SETVAR)
        USHORT nId = SwFldDlgWrapper::GetChildWindowId();
        SfxViewFrame* pVFrame = GetViewFrame();
        SwFldDlgWrapper *pWrp = (SwFldDlgWrapper*)pVFrame->GetChildWindow(nId);
        if (pWrp)
            pWrp->ReInitDlg(GetDocShell());

        // RedlineDlg ggf neu initialisieren
        nId = SwRedlineAcceptChild::GetChildWindowId();
        SwRedlineAcceptChild *pRed = (SwRedlineAcceptChild*)pVFrame->GetChildWindow(nId);
        if (pRed)
            pRed->ReInitDlg(GetDocShell());

        // reinit IdxMarkDlg
        nId = SwInsertIdxMarkWrapper::GetChildWindowId();
        SwInsertIdxMarkWrapper *pIdxMrk = (SwInsertIdxMarkWrapper*)pVFrame->GetChildWindow(nId);
        if (pIdxMrk)
            pIdxMrk->ReInitDlg(*pWrtShell);

        // reinit AuthMarkDlg
        nId = SwInsertAuthMarkWrapper::GetChildWindowId();
        SwInsertAuthMarkWrapper *pAuthMrk = (SwInsertAuthMarkWrapper*)pVFrame->
                                                                GetChildWindow(nId);
        if (pAuthMrk)
            pAuthMrk->ReInitDlg(*pWrtShell);
    }
    else
        //Wenigstens das Notify rufen (vorsichtshalber wegen der SlotFilter
        AttrChangedNotify(pWrtShell);

    SfxViewShell::Activate(bMDIActivate);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::Deactivate(BOOL bMDIActivate)
{
    extern BOOL bFlushCharBuffer ;
        // Befinden sich noch Zeichen im Input Buffer?
    if( bFlushCharBuffer )
        GetEditWin().FlushInBuffer();

    if( bMDIActivate )
    {
        pWrtShell->ShLooseFcs();    // Selektionen unsichtbar

        pHRuler->SetActive( FALSE );
        pVRuler->SetActive( FALSE );
    }
    SfxViewShell::Deactivate(bMDIActivate);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::MarginChanged()
{
    GetWrtShell().SetBrowseBorder( GetMargin() );
}

<commit_msg>INTEGRATION: CWS formatpaintbrush02 (1.8.38); FILE MERGED 2004/07/21 12:25:57 iha 1.8.38.3: #i20119# format paintbrush - disable on incompatible selection 2004/07/14 15:51:48 iha 1.8.38.2: #i20119# format paintbrush - correct double click behaviour 2004/07/13 20:16:33 iha 1.8.38.1: #i20119# format paintbrush<commit_after>/*************************************************************************
 *
 *  $RCSfile: view1.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: kz $ $Date: 2004-08-02 09:59:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif
#ifndef _SVDVIEW_HXX //autogen
#include <svx/svdview.hxx>
#endif
#ifndef _SVX_RULER_HXX //autogen
#include <svx/ruler.hxx>
#endif
#ifndef _IDXMRK_HXX
#include <idxmrk.hxx>
#endif
#ifndef _VIEW_HXX
#include <view.hxx>
#endif
#ifndef _WRTSH_HXX
#include <wrtsh.hxx>
#endif
#ifndef _SWMODULE_HXX
#include <swmodule.hxx>
#endif
#ifndef _VIEWOPT_HXX
#include <viewopt.hxx>
#endif
#ifndef _DOCSH_HXX
#include <docsh.hxx>
#endif
#ifndef _GLOBDOC_HXX
#include <globdoc.hxx>
#endif
#ifndef _NAVIPI_HXX
#include <navipi.hxx>
#endif
#ifndef _FLDWRAP_HXX
#include <fldwrap.hxx>
#endif
#ifndef _REDLNDLG_HXX
#include <redlndlg.hxx>
#endif
#ifndef _DPAGE_HXX
#include <dpage.hxx>
#endif
#ifndef _EDTWIN_HXX
#include <edtwin.hxx>
#endif
#ifndef _SWFORMATCLIPBOARD_HXX
#include "formatclipboard.hxx"
#endif
#ifndef _CMDID_H
#include <cmdid.h>
#endif
// header for class SfxRequest
#ifndef _SFXREQUEST_HXX
#include <sfx2/request.hxx>
#endif

extern int bDocSzUpdated;

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::Activate(BOOL bMDIActivate)
{
    // aktuelle View anmelden an der DocShell
    // die View bleibt solange an der DocShell
    // aktiv bis Sie zerstoert wird oder durch Activate eine
    // neue gesetzt wird
    SwDocShell* pDocSh = GetDocShell();
    if(pDocSh)
        pDocSh->SetView(this);
    SwModule* pSwMod = SW_MOD();
    pSwMod->SetView(this);

    // Dokumentgroesse hat sich geaendert
    if(!bDocSzUpdated)
        DocSzChgd(aDocSz);

    pHRuler->SetActive( TRUE );
    pVRuler->SetActive( TRUE );

    if ( bMDIActivate )
    {
        pWrtShell->ShGetFcs(FALSE);     // Selektionen sichtbar

        if( sSwViewData.Len() )
        {
            ReadUserData( sSwViewData, FALSE );
            sSwViewData.Erase();
        }

        AttrChangedNotify(pWrtShell);

        // Flddlg ggf neu initialisieren (z.B. fuer TYP_SETVAR)
        USHORT nId = SwFldDlgWrapper::GetChildWindowId();
        SfxViewFrame* pVFrame = GetViewFrame();
        SwFldDlgWrapper *pWrp = (SwFldDlgWrapper*)pVFrame->GetChildWindow(nId);
        if (pWrp)
            pWrp->ReInitDlg(GetDocShell());

        // RedlineDlg ggf neu initialisieren
        nId = SwRedlineAcceptChild::GetChildWindowId();
        SwRedlineAcceptChild *pRed = (SwRedlineAcceptChild*)pVFrame->GetChildWindow(nId);
        if (pRed)
            pRed->ReInitDlg(GetDocShell());

        // reinit IdxMarkDlg
        nId = SwInsertIdxMarkWrapper::GetChildWindowId();
        SwInsertIdxMarkWrapper *pIdxMrk = (SwInsertIdxMarkWrapper*)pVFrame->GetChildWindow(nId);
        if (pIdxMrk)
            pIdxMrk->ReInitDlg(*pWrtShell);

        // reinit AuthMarkDlg
        nId = SwInsertAuthMarkWrapper::GetChildWindowId();
        SwInsertAuthMarkWrapper *pAuthMrk = (SwInsertAuthMarkWrapper*)pVFrame->
                                                                GetChildWindow(nId);
        if (pAuthMrk)
            pAuthMrk->ReInitDlg(*pWrtShell);
    }
    else
        //Wenigstens das Notify rufen (vorsichtshalber wegen der SlotFilter
        AttrChangedNotify(pWrtShell);

    SfxViewShell::Activate(bMDIActivate);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::Deactivate(BOOL bMDIActivate)
{
    extern BOOL bFlushCharBuffer ;
        // Befinden sich noch Zeichen im Input Buffer?
    if( bFlushCharBuffer )
        GetEditWin().FlushInBuffer();

    if( bMDIActivate )
    {
        pWrtShell->ShLooseFcs();    // Selektionen unsichtbar

        pHRuler->SetActive( FALSE );
        pVRuler->SetActive( FALSE );
    }
    SfxViewShell::Deactivate(bMDIActivate);
}

/*--------------------------------------------------------------------
    Beschreibung:
 --------------------------------------------------------------------*/

void SwView::MarginChanged()
{
    GetWrtShell().SetBrowseBorder( GetMargin() );
}

/*--------------------------------------------------------------------
 --------------------------------------------------------------------*/

void SwView::ExecFormatPaintbrush(SfxRequest& rReq)
{
    if(!pFormatClipboard)
        return;

    if( pFormatClipboard->HasContent() )
    {
        pFormatClipboard->Erase();

        SwApplyTemplate aTemplate;
        GetEditWin().SetApplyTemplate(aTemplate);
    }
    else
    {
        bool bPersistentCopy = false;
        const SfxItemSet *pArgs = rReq.GetArgs();
        if( pArgs && pArgs->Count() >= 1 )
        {
            bPersistentCopy = static_cast<bool>(((SfxBoolItem &)pArgs->Get(
                                    SID_FORMATPAINTBRUSH)).GetValue());
        }

        pFormatClipboard->Copy( GetWrtShell(), GetPool(), bPersistentCopy );

        SwApplyTemplate aTemplate;
        aTemplate.pFormatClipboard = pFormatClipboard;
        GetEditWin().SetApplyTemplate(aTemplate);
    }
    GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH);
}

void SwView::StateFormatPaintbrush(SfxItemSet &rSet)
{
    if(!pFormatClipboard)
        return;

    bool bHasContent = pFormatClipboard && pFormatClipboard->HasContent();
    rSet.Put(SfxBoolItem(SID_FORMATPAINTBRUSH, bHasContent));
    if(!bHasContent)
    {
        if( !pFormatClipboard->CanCopyThisType( GetWrtShell().GetSelectionType() ) )
            rSet.DisableItem( SID_FORMATPAINTBRUSH );
    }
}
<|endoftext|>


<commit_before>#include <printable_types.hpp>
#include <copy_on_write.hpp>

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

#include <iostream>

namespace bte = boost::type_erasure;
namespace mpl = boost::mpl;

BOOST_TYPE_ERASURE_MEMBER((has_print), print, 1)

using any_printable = bte::any<
    mpl::vector<
        bte::constructible<bte::_self()>,
        bte::copy_constructible<bte::_self>,
        bte::assignable<bte::_self>,
        bte::destructible<bte::_self>,
        has_print<void ()>
    >
>;

using any_printable_param = bte::any<
    has_print<void ()>,
    bte::_self &
>;

void print_printable (any_printable_param printable)
{ printable.print(); }

#define BOOST_TEST_MODULE TypeErasure

#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(hand_rolled)
{
#if INSTRUMENT_COPIES
    reset_allocations();
#endif

    std::cout << "sizeof(any_printable) = " << sizeof(any_printable) << "\n";

#define ECHO(expr)                                                      \
    do {                                                                \
        std::cout << #expr << ";\nap.print() = ";                       \
        expr;                                                           \
        ap.print();                                                     \
        std::cout << "allocations: " << allocations() << "\n\n";        \
        reset_allocations();                                            \
    } while (false)

    ECHO(hi_printable hi; any_printable ap(hi));
    ECHO(large_printable large; any_printable ap(large));
    ECHO(bye_printable bye; any_printable ap(bye));

    ECHO(hi_printable hi; any_printable ap = hi);
    ECHO(large_printable large; any_printable ap = large);
    ECHO(bye_printable bye; any_printable ap = bye);

    ECHO(hi_printable hi; any_printable tmp = hi; any_printable ap = tmp);
    ECHO(large_printable large; any_printable tmp = large; any_printable ap = tmp);
    ECHO(bye_printable bye; any_printable tmp = bye; any_printable ap = tmp);

#if 0 // Does not compile!
    ECHO(hi_printable hi; any_printable ap; ap = hi);
    ECHO(large_printable large; any_printable ap; ap = large);
    ECHO(bye_printable bye; any_printable ap; ap = bye);
#endif

    ECHO(const hi_printable hi{}; any_printable ap(hi));
    ECHO(const large_printable large{}; any_printable ap(large));
    ECHO(const bye_printable bye{}; any_printable ap(bye));

    ECHO(const hi_printable hi{}; any_printable ap = hi);
    ECHO(const large_printable large{}; any_printable ap = large);
    ECHO(const bye_printable bye{}; any_printable ap = bye);

    ECHO(const hi_printable hi{}; any_printable tmp = hi; any_printable ap = tmp);
    ECHO(const large_printable large{}; any_printable tmp = large; any_printable ap = tmp);
    ECHO(const bye_printable bye{}; any_printable tmp = bye; any_printable ap = tmp);

#if 0 // Does not compile!
    ECHO(const hi_printable hi{}; any_printable ap; ap = hi);
    ECHO(const large_printable large{}; any_printable ap; ap = large);
    ECHO(const bye_printable bye{}; any_printable ap; ap = bye);
#endif

    ECHO(any_printable ap(hi_printable{}));
    ECHO(any_printable ap(large_printable{}));
    ECHO(any_printable ap(bye_printable{}));

    ECHO(any_printable ap = hi_printable{});
    ECHO(any_printable ap = large_printable{});
    ECHO(any_printable ap = bye_printable{});

#undef ECHO

#define ECHO(expr)                                                      \
    do {                                                                \
        std::cout << #expr << ";\nap.print() = ";                       \
        expr;                                                           \
        std::cout << "allocations: " << allocations() << "\n\n";        \
        reset_allocations();                                            \
    } while (false)

    ECHO(hi_printable hi; print_printable(hi));
    ECHO(large_printable hi; print_printable(hi));
    ECHO(bye_printable hi; print_printable(hi));

#undef ECHO
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_vector)
{
    std::cout << "copied vector<any_printable>{hi_printable, large_printable}" << "\n";

    std::vector<any_printable> several_printables = {
        hi_printable{},
        large_printable{}
    };

    for (auto & printable : several_printables) {
        printable.print();
    }

    std::vector<any_printable> several_printables_copy = several_printables;

    std::cout << "allocations: " << allocations() << "\n\n";
    reset_allocations();
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_vector_copy_on_write)
{
    std::cout << "copied vector<COW<any_printable>>{hi_printable, large_printable}" << "\n";

    std::vector<copy_on_write<any_printable>> several_printables = {
        {hi_printable{}},
        {large_printable{}}
    };

    for (auto & printable : several_printables) {
        const_cast<any_printable &>(*printable).print();
    }

    std::vector<copy_on_write<any_printable>> several_printables_copy = several_printables;

    std::cout << "allocations: " << allocations() << "\n\n";
    reset_allocations();
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_cow_vector)
{
    std::cout << "copied vector<any_printable[COW]>{hi_printable, large_printable}" << "\n";
    std::cout << "allocations: N/A\n\n";
}

/* Limitations:
   1 - Each non-specific portion of the API (default and copy ctors, etc.) must be specified in the boost::type_erasure::any<> template instantiation.
   2 - Arbitrary types cannot be assigned to an any<>; the acceptable types must be explicitly listed.
   3 - Adapting to const member functions is a bit painful.
   4 - Compile-time errors will make your eyes bleed.
*/
<commit_msg>Also echo the unsupported operations in boost_type_erasure.cpp.<commit_after>#include <printable_types.hpp>
#include <copy_on_write.hpp>

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

#include <iostream>

namespace bte = boost::type_erasure;
namespace mpl = boost::mpl;

BOOST_TYPE_ERASURE_MEMBER((has_print), print, 1)

using any_printable = bte::any<
    mpl::vector<
        bte::constructible<bte::_self()>,
        bte::copy_constructible<bte::_self>,
        bte::assignable<bte::_self>,
        bte::destructible<bte::_self>,
        has_print<void ()>
    >
>;

using any_printable_param = bte::any<
    has_print<void ()>,
    bte::_self &
>;

void print_printable (any_printable_param printable)
{ printable.print(); }

#define BOOST_TEST_MODULE TypeErasure

#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE(hand_rolled)
{
#if INSTRUMENT_COPIES
    reset_allocations();
#endif

    std::cout << "sizeof(any_printable) = " << sizeof(any_printable) << "\n";

#define ECHO(expr)                                                      \
    do {                                                                \
        std::cout << #expr << ";\nap.print() = ";                       \
        expr;                                                           \
        ap.print();                                                     \
        std::cout << "allocations: " << allocations() << "\n\n";        \
        reset_allocations();                                            \
    } while (false)

    ECHO(hi_printable hi; any_printable ap(hi));
    ECHO(large_printable large; any_printable ap(large));
    ECHO(bye_printable bye; any_printable ap(bye));

    ECHO(hi_printable hi; any_printable ap = hi);
    ECHO(large_printable large; any_printable ap = large);
    ECHO(bye_printable bye; any_printable ap = bye);

    ECHO(hi_printable hi; any_printable tmp = hi; any_printable ap = tmp);
    ECHO(large_printable large; any_printable tmp = large; any_printable ap = tmp);
    ECHO(bye_printable bye; any_printable tmp = bye; any_printable ap = tmp);

#define UNSUPPORTED(expr)                                               \
    do {                                                                \
        std::cout << "NOT SUPPORTED: " << #expr << ";\n\n";             \
    } while (false)

    // Does not compile!
    UNSUPPORTED(hi_printable hi; any_printable ap; ap = hi);
    UNSUPPORTED(large_printable large; any_printable ap; ap = large);
    UNSUPPORTED(bye_printable bye; any_printable ap; ap = bye);

    ECHO(const hi_printable hi{}; any_printable ap(hi));
    ECHO(const large_printable large{}; any_printable ap(large));
    ECHO(const bye_printable bye{}; any_printable ap(bye));

    ECHO(const hi_printable hi{}; any_printable ap = hi);
    ECHO(const large_printable large{}; any_printable ap = large);
    ECHO(const bye_printable bye{}; any_printable ap = bye);

    ECHO(const hi_printable hi{}; any_printable tmp = hi; any_printable ap = tmp);
    ECHO(const large_printable large{}; any_printable tmp = large; any_printable ap = tmp);
    ECHO(const bye_printable bye{}; any_printable tmp = bye; any_printable ap = tmp);

    // Does not compile!
    UNSUPPORTED(const hi_printable hi{}; any_printable ap; ap = hi);
    UNSUPPORTED(const large_printable large{}; any_printable ap; ap = large);
    UNSUPPORTED(const bye_printable bye{}; any_printable ap; ap = bye);

#undef UNSUPPORTED

    ECHO(any_printable ap(hi_printable{}));
    ECHO(any_printable ap(large_printable{}));
    ECHO(any_printable ap(bye_printable{}));

    ECHO(any_printable ap = hi_printable{});
    ECHO(any_printable ap = large_printable{});
    ECHO(any_printable ap = bye_printable{});

#undef ECHO

#define ECHO(expr)                                                      \
    do {                                                                \
        std::cout << #expr << ";\nap.print() = ";                       \
        expr;                                                           \
        std::cout << "allocations: " << allocations() << "\n\n";        \
        reset_allocations();                                            \
    } while (false)

    ECHO(hi_printable hi; print_printable(hi));
    ECHO(large_printable hi; print_printable(hi));
    ECHO(bye_printable hi; print_printable(hi));

#undef ECHO
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_vector)
{
    std::cout << "copied vector<any_printable>{hi_printable, large_printable}" << "\n";

    std::vector<any_printable> several_printables = {
        hi_printable{},
        large_printable{}
    };

    for (auto & printable : several_printables) {
        printable.print();
    }

    std::vector<any_printable> several_printables_copy = several_printables;

    std::cout << "allocations: " << allocations() << "\n\n";
    reset_allocations();
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_vector_copy_on_write)
{
    std::cout << "copied vector<COW<any_printable>>{hi_printable, large_printable}" << "\n";

    std::vector<copy_on_write<any_printable>> several_printables = {
        {hi_printable{}},
        {large_printable{}}
    };

    for (auto & printable : several_printables) {
        const_cast<any_printable &>(*printable).print();
    }

    std::vector<copy_on_write<any_printable>> several_printables_copy = several_printables;

    std::cout << "allocations: " << allocations() << "\n\n";
    reset_allocations();
}

BOOST_AUTO_TEST_CASE(boost_type_erasure_cow_vector)
{
    std::cout << "copied vector<any_printable[COW]>{hi_printable, large_printable}" << "\n";
    std::cout << "allocations: N/A\n\n";
}

/* Limitations:
   1 - Each non-specific portion of the API (default and copy ctors, etc.) must be specified in the boost::type_erasure::any<> template instantiation.
   2 - Arbitrary types cannot be assigned to an any<>; the acceptable types must be explicitly listed.
   3 - Adapting to const member functions is a bit painful.
   4 - Compile-time errors will make your eyes bleed.
*/
<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "simple1.h"

CS_IMPLEMENT_APPLICATION

//---------------------------------------------------------------------------

Simple::Simple ()
{
  SetApplicationName ("CrystalSpace.Simple1");
}

Simple::~Simple ()
{
}

void Simple::Frame ()
{
  // First get elapsed time from the virtual clock.
  csTicks elapsed_time = vc->GetElapsedTicks ();
  // Now rotate the camera according to keyboard state
  float speed = (elapsed_time / 1000.0) * (0.06 * 20);

  iCamera* c = view->GetCamera();

  if (kbd->GetKeyState (CSKEY_SHIFT))
  {
    // If the user is holding down shift, the arrow keys will cause
    // the camera to strafe up, down, left or right from it's
    // current position.
    if (kbd->GetKeyState (CSKEY_RIGHT))
      c->Move (CS_VEC_RIGHT * 4 * speed);
    if (kbd->GetKeyState (CSKEY_LEFT))
      c->Move (CS_VEC_LEFT * 4 * speed);
    if (kbd->GetKeyState (CSKEY_UP))
      c->Move (CS_VEC_UP * 4 * speed);
    if (kbd->GetKeyState (CSKEY_DOWN))
      c->Move (CS_VEC_DOWN * 4 * speed);
  }
  else
  {
    // left and right cause the camera to rotate on the global Y
    // axis; page up and page down cause the camera to rotate on the
    // _camera's_ X axis (more on this in a second) and up and down
    // arrows cause the camera to go forwards and backwards.
    if (kbd->GetKeyState (CSKEY_RIGHT))
      rotY += speed;
    if (kbd->GetKeyState (CSKEY_LEFT))
      rotY -= speed;
    if (kbd->GetKeyState (CSKEY_PGUP))
      rotX += speed;
    if (kbd->GetKeyState (CSKEY_PGDN))
      rotX -= speed;
    if (kbd->GetKeyState (CSKEY_UP))
      c->Move (CS_VEC_FORWARD * 4 * speed);
    if (kbd->GetKeyState (CSKEY_DOWN))
      c->Move (CS_VEC_BACKWARD * 4 * speed);
  }

  // We now assign a new rotation transformation to the camera.  You
  // can think of the rotation this way: starting from the zero
  // position, you first rotate "rotY" radians on your Y axis to get
  // the first rotation.  From there you rotate "rotX" radians on the
  // your X axis to get the final rotation.  We multiply the
  // individual rotations on each axis together to get a single
  // rotation matrix.  The rotations are applied in right to left
  // order .
  csMatrix3 rot = csXRotMatrix3 (rotX) * csYRotMatrix3 (rotY);
  csOrthoTransform ot (rot, c->GetTransform().GetOrigin ());
  c->SetTransform (ot);
}

bool Simple::OnKeyboard(iEvent& ev)
{
  // We got a keyboard event.
  csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
  if (eventtype == csKeyEventTypeDown)
  {
    // The user pressed a key (as opposed to releasing it).
    utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
    if (code == CSKEY_ESC)
    {
      // The user pressed escape to exit the application.
      // The proper way to quit a Crystal Space application
      // is by broadcasting a csevQuit event. That will cause the
      // main runloop to stop. To do that we get the event queue from
      // the object registry and then post the event.
      csRef<iEventQueue> q =
        csQueryRegistry<iEventQueue> (GetObjectRegistry());
      if (q.IsValid()) q->GetEventOutlet()->Broadcast(
      	csevQuit(GetObjectRegistry()));
    }
  }
  return false;
}

bool Simple::OnInitialize(int /*argc*/, char* /*argv*/ [])
{
  // RequestPlugins() will load all plugins we specify. In addition
  // it will also check if there are plugins that need to be loaded
  // from the config system (both the application config and CS or
  // global configs). In addition it also supports specifying plugins
  // on the commandline.
  if (!csInitializer::RequestPlugins(GetObjectRegistry(),
    CS_REQUEST_VFS,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_ENGINE,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_LEVELLOADER,
    CS_REQUEST_REPORTER,
    CS_REQUEST_REPORTERLISTENER,
    CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

  // "Warm up" the event handler so it can interact with the world
  csBaseEventHandler::Initialize(GetObjectRegistry());

  // Now we need to register the event handler for our application.
  // Crystal Space is fully event-driven. Everything (except for this
  // initialization) happens in an event.
  // Rather than simply handling all events, we subscribe to the
  // particular events we're interested in.
  csEventID events[] = {
    csevFrame (GetObjectRegistry()),
    csevKeyboardEvent (GetObjectRegistry()),
    CS_EVENTLIST_END
  };
  if (!RegisterQueue(GetObjectRegistry(), events))
    return ReportError("Failed to set up event handler!");

  // Report success
  return true;
}

void Simple::OnExit()
{
  // Shut down the event handlers we spawned earlier.
  drawer.Invalidate();
  printer.Invalidate();
}

bool Simple::Application()
{
  // Open the main system. This will open all the previously loaded plug-ins.
  // i.e. all windows will be opened.
  if (!OpenApplication(GetObjectRegistry()))
    return ReportError("Error opening system!");

  if (SetupModules()) {
    // This calls the default runloop. This will basically just keep
    // broadcasting process events to keep the game going.
    Run();
  }

  return true;
}

bool Simple::SetupModules ()
{
  // Now get the pointer to various modules we need. We fetch them
  // from the object registry. The RequestPlugins() call we did earlier
  // registered all loaded plugins with the object registry.
  g3d = csQueryRegistry<iGraphics3D> (GetObjectRegistry());
  if (!g3d) return ReportError("Failed to locate 3D renderer!");

  engine = csQueryRegistry<iEngine> (GetObjectRegistry());
  if (!engine) return ReportError("Failed to locate 3D engine!");

  vc = csQueryRegistry<iVirtualClock> (GetObjectRegistry());
  if (!vc) return ReportError("Failed to locate Virtual Clock!");

  kbd = csQueryRegistry<iKeyboardDriver> (GetObjectRegistry());
  if (!kbd) return ReportError("Failed to locate Keyboard Driver!");

  loader = csQueryRegistry<iLoader> (GetObjectRegistry());
  if (!loader) return ReportError("Failed to locate Loader!");

  // We need a View to the virtual world.
  view.AttachNew(new csView (engine, g3d));
  iGraphics2D* g2d = g3d->GetDriver2D ();
  // We use the full window to draw the world.
  view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());

  // First disable the lighting cache. Our app is simple enough
  // not to need this.
  engine->SetLightingCacheMode (0);

  // Here we create our world.
  CreateRoom();

  // Let the engine prepare all lightmaps for use and also free all images
  // that were loaded for the texture manager.
  engine->Prepare ();

  // these are used store the current orientation of the camera
  rotY = rotX = 0;

  // Now we need to position the camera in our world.
  view->GetCamera ()->SetSector (room);
  view->GetCamera ()->GetTransform ().SetOrigin (csVector3 (0, 5, -3));

  // We use some other "helper" event handlers to handle
  // pushing our work into the 3D engine and rendering it
  // to the screen.
  drawer.AttachNew(new FrameBegin3DDraw (GetObjectRegistry (), view));
  printer.AttachNew(new FramePrinter (GetObjectRegistry ()));

  return true;
}

void Simple::CreateRoom ()
{
  // Load the texture from the standard library.  This is located in
  // CS/data/standard.zip and mounted as /lib/std using the Virtual
  // File System (VFS) plugin.
  if (!loader->LoadTexture ("stone", "/lib/std/stone4.gif"))
    ReportError("Error loading 'stone4' texture!");

  iMaterialWrapper* tm = engine->GetMaterialList ()->FindByName ("stone");

  // We create a new sector called "room".
  room = engine->CreateSector ("room");

  // Creating the walls for our room.
  csRef<iMeshWrapper> walls (engine->CreateSectorWallsMesh (room, "walls"));
  iMeshObject* walls_object = walls->GetMeshObject ();
  iMeshObjectFactory* walls_factory = walls_object->GetFactory();
  csRef<iThingFactoryState> walls_state =
    scfQueryInterface<iThingFactoryState> (walls_factory);
  walls_state->AddInsideBox (csVector3 (-5, 0, -5), csVector3 (5, 20, 5));
  walls_state->SetPolygonMaterial (CS_POLYRANGE_LAST, tm);
  walls_state->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3);

  // Now we need light to see something.
  csRef<iLight> light;
  iLightList* ll = room->GetLights ();

  light = engine->CreateLight(0, csVector3(-3, 5, 0), 10, csColor(1, 0, 0));
  ll->Add (light);

  light = engine->CreateLight(0, csVector3(3, 5,  0), 10, csColor(0, 0, 1));
  ll->Add (light);

  light = engine->CreateLight(0, csVector3(0, 5, -3), 10, csColor(0, 1, 0));
  ll->Add (light);

  // Create particle system
  csRef<iPluginManager> plugin_mgr (
    CS_QUERY_REGISTRY (object_registry, iPluginManager));

  csRef<iMeshFactoryWrapper> factory (engine->CreateMeshFactory (
    "crystalspace.mesh.object.particles", "partFact"));

  csRef<iMeshWrapper> mesh = engine->CreateMeshWrapper (factory, "part", room,
    csVector3(0,2,0));
  mesh->GetMeshObject ()->SetMaterialWrapper (tm);

  csRef<iMeshObject> particleMesh = mesh->GetMeshObject ();

  {
    csRef<iParticleSystem> partSys = scfQueryInterface<iParticleSystem> (particleMesh);

    partSys->SetParticleRenderOrientation (CS_PARTICLE_CAMERAFACE_APPROX);
    partSys->SetParticleSize (csVector2 (0.08f));
    partSys->SetCommonDirection (csVector3(0,1,0));

    // Get an emitter
    csRef<iParticleBuiltinEmitterFactory> emitFact =
      CS_LOAD_PLUGIN (plugin_mgr, "crystalspace.mesh.object.particles.emitter",
      iParticleBuiltinEmitterFactory);

    csRef<iParticleBuiltinEmitterCylinder> cylEmit = emitFact->CreateCylinder ();

    cylEmit->SetEmissionRate (100.0f);
    cylEmit->SetInitialTTL (5, 5);
    cylEmit->SetInitialVelocity (csVector3 (0.1f, 0.0f, 0.0f), csVector3 (0.0f));
    cylEmit->SetEnabled (true);
    cylEmit->SetParticlePlacement (CS_PARTICLE_BUILTIN_SURFACE);
    cylEmit->SetExtent (csVector3 (3, 0, 0));
    cylEmit->SetRadius (2);

    partSys->AddEmitter (cylEmit);
  }
}

/*-------------------------------------------------------------------------*
 * Main function
 *-------------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  /* Runs the application.
   *
   * csApplicationRunner<> is a small wrapper to support "restartable"
   * applications (ie where CS needs to be completely shut down and loaded
   * again). Simple1 does not use that functionality itself, however, it
   * allows you to later use "Simple.Restart();" and it'll just work.
   */
  return csApplicationRunner<Simple>::Run (argc, argv);
}
<commit_msg>- Marten reverted accidental commit<commit_after>/*
    Copyright (C) 2001 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "simple1.h"

CS_IMPLEMENT_APPLICATION

//---------------------------------------------------------------------------

Simple::Simple ()
{
  SetApplicationName ("CrystalSpace.Simple1");
}

Simple::~Simple ()
{
}

void Simple::Frame ()
{
  // First get elapsed time from the virtual clock.
  csTicks elapsed_time = vc->GetElapsedTicks ();
  // Now rotate the camera according to keyboard state
  float speed = (elapsed_time / 1000.0) * (0.06 * 20);

  iCamera* c = view->GetCamera();

  if (kbd->GetKeyState (CSKEY_SHIFT))
  {
    // If the user is holding down shift, the arrow keys will cause
    // the camera to strafe up, down, left or right from it's
    // current position.
    if (kbd->GetKeyState (CSKEY_RIGHT))
      c->Move (CS_VEC_RIGHT * 4 * speed);
    if (kbd->GetKeyState (CSKEY_LEFT))
      c->Move (CS_VEC_LEFT * 4 * speed);
    if (kbd->GetKeyState (CSKEY_UP))
      c->Move (CS_VEC_UP * 4 * speed);
    if (kbd->GetKeyState (CSKEY_DOWN))
      c->Move (CS_VEC_DOWN * 4 * speed);
  }
  else
  {
    // left and right cause the camera to rotate on the global Y
    // axis; page up and page down cause the camera to rotate on the
    // _camera's_ X axis (more on this in a second) and up and down
    // arrows cause the camera to go forwards and backwards.
    if (kbd->GetKeyState (CSKEY_RIGHT))
      rotY += speed;
    if (kbd->GetKeyState (CSKEY_LEFT))
      rotY -= speed;
    if (kbd->GetKeyState (CSKEY_PGUP))
      rotX += speed;
    if (kbd->GetKeyState (CSKEY_PGDN))
      rotX -= speed;
    if (kbd->GetKeyState (CSKEY_UP))
      c->Move (CS_VEC_FORWARD * 4 * speed);
    if (kbd->GetKeyState (CSKEY_DOWN))
      c->Move (CS_VEC_BACKWARD * 4 * speed);
  }

  // We now assign a new rotation transformation to the camera.  You
  // can think of the rotation this way: starting from the zero
  // position, you first rotate "rotY" radians on your Y axis to get
  // the first rotation.  From there you rotate "rotX" radians on the
  // your X axis to get the final rotation.  We multiply the
  // individual rotations on each axis together to get a single
  // rotation matrix.  The rotations are applied in right to left
  // order .
  csMatrix3 rot = csXRotMatrix3 (rotX) * csYRotMatrix3 (rotY);
  csOrthoTransform ot (rot, c->GetTransform().GetOrigin ());
  c->SetTransform (ot);
}

bool Simple::OnKeyboard(iEvent& ev)
{
  // We got a keyboard event.
  csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
  if (eventtype == csKeyEventTypeDown)
  {
    // The user pressed a key (as opposed to releasing it).
    utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
    if (code == CSKEY_ESC)
    {
      // The user pressed escape to exit the application.
      // The proper way to quit a Crystal Space application
      // is by broadcasting a csevQuit event. That will cause the
      // main runloop to stop. To do that we get the event queue from
      // the object registry and then post the event.
      csRef<iEventQueue> q =
        csQueryRegistry<iEventQueue> (GetObjectRegistry());
      if (q.IsValid()) q->GetEventOutlet()->Broadcast(
      	csevQuit(GetObjectRegistry()));
    }
  }
  return false;
}

bool Simple::OnInitialize(int /*argc*/, char* /*argv*/ [])
{
  // RequestPlugins() will load all plugins we specify. In addition
  // it will also check if there are plugins that need to be loaded
  // from the config system (both the application config and CS or
  // global configs). In addition it also supports specifying plugins
  // on the commandline.
  if (!csInitializer::RequestPlugins(GetObjectRegistry(),
    CS_REQUEST_VFS,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_ENGINE,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_LEVELLOADER,
    CS_REQUEST_REPORTER,
    CS_REQUEST_REPORTERLISTENER,
    CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

  // "Warm up" the event handler so it can interact with the world
  csBaseEventHandler::Initialize(GetObjectRegistry());

  // Now we need to register the event handler for our application.
  // Crystal Space is fully event-driven. Everything (except for this
  // initialization) happens in an event.
  // Rather than simply handling all events, we subscribe to the
  // particular events we're interested in.
  csEventID events[] = {
    csevFrame (GetObjectRegistry()),
    csevKeyboardEvent (GetObjectRegistry()),
    CS_EVENTLIST_END
  };
  if (!RegisterQueue(GetObjectRegistry(), events))
    return ReportError("Failed to set up event handler!");

  // Report success
  return true;
}

void Simple::OnExit()
{
  // Shut down the event handlers we spawned earlier.
  drawer.Invalidate();
  printer.Invalidate();
}

bool Simple::Application()
{
  // Open the main system. This will open all the previously loaded plug-ins.
  // i.e. all windows will be opened.
  if (!OpenApplication(GetObjectRegistry()))
    return ReportError("Error opening system!");

  if (SetupModules()) {
    // This calls the default runloop. This will basically just keep
    // broadcasting process events to keep the game going.
    Run();
  }

  return true;
}

bool Simple::SetupModules ()
{
  // Now get the pointer to various modules we need. We fetch them
  // from the object registry. The RequestPlugins() call we did earlier
  // registered all loaded plugins with the object registry.
  g3d = csQueryRegistry<iGraphics3D> (GetObjectRegistry());
  if (!g3d) return ReportError("Failed to locate 3D renderer!");

  engine = csQueryRegistry<iEngine> (GetObjectRegistry());
  if (!engine) return ReportError("Failed to locate 3D engine!");

  vc = csQueryRegistry<iVirtualClock> (GetObjectRegistry());
  if (!vc) return ReportError("Failed to locate Virtual Clock!");

  kbd = csQueryRegistry<iKeyboardDriver> (GetObjectRegistry());
  if (!kbd) return ReportError("Failed to locate Keyboard Driver!");

  loader = csQueryRegistry<iLoader> (GetObjectRegistry());
  if (!loader) return ReportError("Failed to locate Loader!");

  // We need a View to the virtual world.
  view.AttachNew(new csView (engine, g3d));
  iGraphics2D* g2d = g3d->GetDriver2D ();
  // We use the full window to draw the world.
  view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());

  // First disable the lighting cache. Our app is simple enough
  // not to need this.
  engine->SetLightingCacheMode (0);

  // Here we create our world.
  CreateRoom();

  // Let the engine prepare all lightmaps for use and also free all images
  // that were loaded for the texture manager.
  engine->Prepare ();

  // these are used store the current orientation of the camera
  rotY = rotX = 0;

  // Now we need to position the camera in our world.
  view->GetCamera ()->SetSector (room);
  view->GetCamera ()->GetTransform ().SetOrigin (csVector3 (0, 5, -3));

  // We use some other "helper" event handlers to handle
  // pushing our work into the 3D engine and rendering it
  // to the screen.
  drawer.AttachNew(new FrameBegin3DDraw (GetObjectRegistry (), view));
  printer.AttachNew(new FramePrinter (GetObjectRegistry ()));

  return true;
}

void Simple::CreateRoom ()
{
  // Load the texture from the standard library.  This is located in
  // CS/data/standard.zip and mounted as /lib/std using the Virtual
  // File System (VFS) plugin.
  if (!loader->LoadTexture ("stone", "/lib/std/stone4.gif"))
    ReportError("Error loading 'stone4' texture!");

  iMaterialWrapper* tm = engine->GetMaterialList ()->FindByName ("stone");

  // We create a new sector called "room".
  room = engine->CreateSector ("room");

  // Creating the walls for our room.
  csRef<iMeshWrapper> walls (engine->CreateSectorWallsMesh (room, "walls"));
  iMeshObject* walls_object = walls->GetMeshObject ();
  iMeshObjectFactory* walls_factory = walls_object->GetFactory();
  csRef<iThingFactoryState> walls_state =
    scfQueryInterface<iThingFactoryState> (walls_factory);
  walls_state->AddInsideBox (csVector3 (-5, 0, -5), csVector3 (5, 20, 5));
  walls_state->SetPolygonMaterial (CS_POLYRANGE_LAST, tm);
  walls_state->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3);

  // Now we need light to see something.
  csRef<iLight> light;
  iLightList* ll = room->GetLights ();

  light = engine->CreateLight(0, csVector3(-3, 5, 0), 10, csColor(1, 0, 0));
  ll->Add (light);

  light = engine->CreateLight(0, csVector3(3, 5,  0), 10, csColor(0, 0, 1));
  ll->Add (light);

  light = engine->CreateLight(0, csVector3(0, 5, -3), 10, csColor(0, 1, 0));
  ll->Add (light);
}

/*-------------------------------------------------------------------------*
 * Main function
 *-------------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  /* Runs the application.
   *
   * csApplicationRunner<> is a small wrapper to support "restartable"
   * applications (ie where CS needs to be completely shut down and loaded
   * again). Simple1 does not use that functionality itself, however, it
   * allows you to later use "Simple.Restart();" and it'll just work.
   */
  return csApplicationRunner<Simple>::Run (argc, argv);
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/app/node_main.h"

#include <memory>
#include <string>
#include <utility>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "electron/electron_version.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
#include "native_mate/dictionary.h"
#include "shell/app/uv_task_runner.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/node_debugger.h"
#include "shell/common/api/electron_bindings.h"
#include "shell/common/crash_reporter/crash_reporter.h"
#include "shell/common/native_mate_converters/string16_converter.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"

#if defined(_WIN64)
#include "shell/common/crash_reporter/crash_reporter_win.h"
#endif

namespace electron {

#if !defined(OS_LINUX)
void AddExtraParameter(const std::string& key, const std::string& value) {
  crash_reporter::CrashReporter::GetInstance()->AddExtraParameter(key, value);
}

void RemoveExtraParameter(const std::string& key) {
  crash_reporter::CrashReporter::GetInstance()->RemoveExtraParameter(key);
}
#endif

int NodeMain(int argc, char* argv[]) {
  base::CommandLine::Init(argc, argv);

  int exit_code = 1;
  {
    // Feed gin::PerIsolateData with a task runner.
    argv = uv_setup_args(argc, argv);
    uv_loop_t* loop = uv_default_loop();
    scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
    base::ThreadTaskRunnerHandle handle(uv_task_runner);

    // Initialize feature list.
    auto feature_list = std::make_unique<base::FeatureList>();
    feature_list->InitializeFromCommandLine("", "");
    base::FeatureList::SetInstance(std::move(feature_list));

#if defined(_WIN64)
    crash_reporter::CrashReporterWin::SetUnhandledExceptionFilter();
#endif

    // Explicitly register electron's builtin modules.
    NodeBindings::RegisterBuiltinModules();

    int exec_argc;
    const char** exec_argv;
    node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

    gin::V8Initializer::LoadV8Snapshot(
        gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext);
    gin::V8Initializer::LoadV8Natives();

    // V8 requires a task scheduler apparently
    base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Electron");

    // Initialize gin::IsolateHolder.
    JavascriptEnvironment gin_env(loop);

    node::Environment* env = node::CreateEnvironment(
        node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
        gin_env.context(), argc, argv, exec_argc, exec_argv, false);

    // Enable support for v8 inspector.
    NodeDebugger node_debugger(env);
    node_debugger.Start();

    node::BootstrapEnvironment(env);

    mate::Dictionary process(gin_env.isolate(), env->process_object());
#if defined(OS_WIN)
    process.SetMethod("log", &ElectronBindings::Log);
#endif
    process.SetMethod("crash", &ElectronBindings::Crash);

    // Setup process.crashReporter.start in child node processes
    auto reporter = mate::Dictionary::CreateEmpty(gin_env.isolate());
    reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);

#if !defined(OS_LINUX)
    reporter.SetMethod("addExtraParameter", &AddExtraParameter);
    reporter.SetMethod("removeExtraParameter", &RemoveExtraParameter);
#endif

    process.Set("crashReporter", reporter);

    mate::Dictionary versions;
    if (process.Get("versions", &versions)) {
      versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
    }

    node::LoadEnvironment(env);

    bool more;
    do {
      more = uv_run(env->event_loop(), UV_RUN_ONCE);
      gin_env.platform()->DrainTasks(env->isolate());
      if (more == false) {
        node::EmitBeforeExit(env);

        // Emit `beforeExit` if the loop became alive either after emitting
        // event, or after running some callbacks.
        more = uv_loop_alive(env->event_loop());
        if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
          more = true;
      }
    } while (more == true);

    node_debugger.Stop();
    exit_code = node::EmitExit(env);
    env->set_can_call_into_js(false);
    node::RunAtExit(env);

    v8::Isolate* isolate = env->isolate();
    node::FreeEnvironment(env);

    gin_env.platform()->DrainTasks(isolate);
    gin_env.platform()->CancelPendingDelayedTasks(isolate);
    gin_env.platform()->UnregisterIsolate(isolate);
  }

  // According to "src/gin/shell/gin_main.cc":
  //
  // gin::IsolateHolder waits for tasks running in ThreadPool in its
  // destructor and thus must be destroyed before ThreadPool starts skipping
  // CONTINUE_ON_SHUTDOWN tasks.
  base::ThreadPoolInstance::Get()->Shutdown();

  v8::V8::Dispose();

  return exit_code;
}

}  // namespace electron
<commit_msg>fix: properly free IsolateData in node_main (#20446)<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/app/node_main.h"

#include <memory>
#include <string>
#include <utility>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "electron/electron_version.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
#include "native_mate/dictionary.h"
#include "shell/app/uv_task_runner.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/node_debugger.h"
#include "shell/common/api/electron_bindings.h"
#include "shell/common/crash_reporter/crash_reporter.h"
#include "shell/common/native_mate_converters/string16_converter.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"

#if defined(_WIN64)
#include "shell/common/crash_reporter/crash_reporter_win.h"
#endif

namespace electron {

#if !defined(OS_LINUX)
void AddExtraParameter(const std::string& key, const std::string& value) {
  crash_reporter::CrashReporter::GetInstance()->AddExtraParameter(key, value);
}

void RemoveExtraParameter(const std::string& key) {
  crash_reporter::CrashReporter::GetInstance()->RemoveExtraParameter(key);
}
#endif

int NodeMain(int argc, char* argv[]) {
  base::CommandLine::Init(argc, argv);

  int exit_code = 1;
  {
    // Feed gin::PerIsolateData with a task runner.
    argv = uv_setup_args(argc, argv);
    uv_loop_t* loop = uv_default_loop();
    scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
    base::ThreadTaskRunnerHandle handle(uv_task_runner);

    // Initialize feature list.
    auto feature_list = std::make_unique<base::FeatureList>();
    feature_list->InitializeFromCommandLine("", "");
    base::FeatureList::SetInstance(std::move(feature_list));

#if defined(_WIN64)
    crash_reporter::CrashReporterWin::SetUnhandledExceptionFilter();
#endif

    // Explicitly register electron's builtin modules.
    NodeBindings::RegisterBuiltinModules();

    int exec_argc;
    const char** exec_argv;
    node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

    gin::V8Initializer::LoadV8Snapshot(
        gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext);
    gin::V8Initializer::LoadV8Natives();

    // V8 requires a task scheduler apparently
    base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Electron");

    // Initialize gin::IsolateHolder.
    JavascriptEnvironment gin_env(loop);

    node::IsolateData* isolate_data =
        node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform());
    CHECK_NE(nullptr, isolate_data);

    node::Environment* env =
        node::CreateEnvironment(isolate_data, gin_env.context(), argc, argv,
                                exec_argc, exec_argv, false);
    CHECK_NE(nullptr, env);

    // Enable support for v8 inspector.
    NodeDebugger node_debugger(env);
    node_debugger.Start();

    node::BootstrapEnvironment(env);

    mate::Dictionary process(gin_env.isolate(), env->process_object());
#if defined(OS_WIN)
    process.SetMethod("log", &ElectronBindings::Log);
#endif
    process.SetMethod("crash", &ElectronBindings::Crash);

    // Setup process.crashReporter.start in child node processes
    auto reporter = mate::Dictionary::CreateEmpty(gin_env.isolate());
    reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);

#if !defined(OS_LINUX)
    reporter.SetMethod("addExtraParameter", &AddExtraParameter);
    reporter.SetMethod("removeExtraParameter", &RemoveExtraParameter);
#endif

    process.Set("crashReporter", reporter);

    mate::Dictionary versions;
    if (process.Get("versions", &versions)) {
      versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
    }

    node::LoadEnvironment(env);

    bool more;
    do {
      more = uv_run(env->event_loop(), UV_RUN_ONCE);
      gin_env.platform()->DrainTasks(env->isolate());
      if (more == false) {
        node::EmitBeforeExit(env);

        // Emit `beforeExit` if the loop became alive either after emitting
        // event, or after running some callbacks.
        more = uv_loop_alive(env->event_loop());
        if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
          more = true;
      }
    } while (more == true);

    node_debugger.Stop();
    exit_code = node::EmitExit(env);
    env->set_can_call_into_js(false);
    node::RunAtExit(env);

    v8::Isolate* isolate = env->isolate();
    node::FreeEnvironment(env);
    node::FreeIsolateData(isolate_data);

    gin_env.platform()->DrainTasks(isolate);
    gin_env.platform()->CancelPendingDelayedTasks(isolate);
    gin_env.platform()->UnregisterIsolate(isolate);
  }

  // According to "src/gin/shell/gin_main.cc":
  //
  // gin::IsolateHolder waits for tasks running in ThreadPool in its
  // destructor and thus must be destroyed before ThreadPool starts skipping
  // CONTINUE_ON_SHUTDOWN tasks.
  base::ThreadPoolInstance::Get()->Shutdown();

  v8::V8::Dispose();

  return exit_code;
}

}  // namespace electron
<|endoftext|>


<commit_before>// @(#)root/gviz3d:$Id$
// Author: Tomasz Sosnicki   18/09/09

/************************************************************************
* Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/

#include "TStructViewer.h"
#include "TStructNodeProperty.h"
#include "TStructViewerGUI.h"
#include "TStructNode.h"

#include <TDataMember.h>
#include <TVirtualCollectionProxy.h>
#include <TClassEdit.h>
#include <vector>

ClassImp(TStructViewer);

class TA {
public:
   virtual ~TA() {}
};

//________________________________________________________________________
//////////////////////////////////////////////////////////////////////////
//
// TStructViewer viewer represents class, struct or other type as an object in 3D space.
// At the top of the scene we can see objects which is our pointer. Under it we see
// pointers and collection elements. Collection must inherit from TCollection
// or be STL collecion.
//
// We can change the number of visible levels or objects on the scene with the  GUI or
// methods. The size of geometry objects is proportional to the memory taken by this object
// or to the number of members inside this object.
//
// An easy way to find some class in the viewer is to change the color of the type.
// We can connect for example a TF2 class with red color or connect all classes
// inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us
// that all classes inheriting from TF2 will be red.
//
// Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over
// some object you can see some information about it (e.g. name, size, actual level).
// When you double click this object, it becames top object on scene.
// Undo and redo operation are supported.
//
// Begin_Html
//
 In this picture we can see TStructViewer with pointer to TList which contains
// other collections and objects of various classes

//
// End_Html
//
// Begin_Html
//
 Other screenshot presents opened TStructNodeEditor

//
// End_Html
//
//
//////////////////////////////////////////////////////////////////////////

//________________________________________________________________________
TStructViewer::TStructViewer(void* ptr, const char * clname)
{
   // Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in the viewer

   fPointer = NULL;
   fPointerClass = NULL;
   fTopNode = NULL;

   // add default color
   fColors.Add(new TStructNodeProperty("+", 17));

   // creating GUI
   fGUI = new TStructViewerGUI(this, NULL, &fColors);

   SetPointer(ptr, clname);
}

//________________________________________________________________________
TStructViewer::~TStructViewer()
{
   // Destructor. Clean all object after closing the viewer

   Reset();
   fColors.SetOwner();
   fColors.Clear();
}

//________________________________________________________________________
void TStructViewer::AddNode(TStructNode* node, ULong_t size)
{
   // Find list with nodes on specified level and add node to this list and increment list of sizes and list of members

   TList* list = (TList*)fLevelArray[node->GetLevel()];
   // if list doesn't exist -> create one
   if(!list) {
      fLevelArray[node->GetLevel()] = list = new TList();
   }
   list->Add(node);

   // increase number of members on this level
   fLevelMembersCount(node->GetLevel())++;
   // increase size of this level
   fLevelSize(node->GetLevel()) += size;
}

//________________________________________________________________________
void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
{
   // Count allocated memory, increase member counters, find child nodes

   if(!cl) {
      return;
   }

   if (cl->InheritsFrom(TClass::Class())) {
      return;
   }

   //////////////////////////////////////////////////////////////////////////
   // DATA MEMBERS
   //////////////////////////////////////////////////////////////////////////
   // Set up list of RealData so TClass doesn't create a new object itself
   cl->BuildRealData(parent->GetPointer());
   TIter it(cl->GetListOfDataMembers());
   TDataMember* dm;
   while ((dm = (TDataMember*) it() ))
   {
      // increase counters in parent node
      parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
      parent->SetMembersCount(parent->GetMembersCount() + 1);

      if (dm->Property() & kIsStatic) {
         continue;
      }

      void* ptr = NULL;

      if(dm->IsaPointer()) {
         TString trueTypeName = dm->GetTrueTypeName();

         // skip if pointer to pointer
         if(trueTypeName.EndsWith("**")) {
            continue;
         }

         if (!pointer) {
            continue;
         }

         void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
         ptr = *pptr;

         if (!ptr) {
            continue;
         }

         if(fPointers.GetValue((ULong_t)ptr)) {
            continue;
         } else {
            fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
         }

         ULong_t size = 0;
         if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
            size = cl2->Size();
         }

         if(size == 0) {
            size = dm->GetUnitSize();
         }

         ENodeType type;
         if(dm->GetDataType()) {   // pointer to basic type
            type = kBasic;
         } else {
            type = kClass;
         }

         // creating TStructNode
         TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
         AddNode(node, size);

         CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);

         // total size = size of parent + size of nodes daughters
         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
         // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
      } else {
         ptr = (void*)((ULong_t)pointer + dm->GetOffset());

         if (!ptr) {
            continue;
         }
         CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
      }

      //////////////////////////////////////////////////////////////////////////
      // STL COLLECTION
      //////////////////////////////////////////////////////////////////////////
      if (dm->IsSTLContainer()) {
         parent->SetNodeType(kSTLCollection);

         //it works only for pointer in std object (not pointer)
         TClass* stlClass = TClass::GetClass(dm->GetTypeName());
         if (!stlClass) {
            continue;
         }

         TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
         if (!proxy) {
            continue;
         }
         TVirtualCollectionProxy::TPushPop helper(proxy, ptr);

         UInt_t count = proxy->Size();
         parent->SetMembersCount(parent->GetMembersCount() + count);

         if(!proxy->HasPointers() || proxy->GetType()) { // only objects or pointers to basic type
            parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
            parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
         } else {

            TClass* clProxy = proxy->GetValueClass();
            TString name;
            TString typeName;
            // get size of element
            ULong_t size = 0;
            if (clProxy) {
               name = clProxy->GetName();
               typeName = clProxy->GetName();
               size = clProxy->Size();
            } else {
               continue;
            }

            // if there is no dictionary
            if (size == 0) {
               size = proxy->Sizeof();
            }

            // searching pointer to pointer
            Bool_t ptp = kFALSE;
            std::vector<std::string> parts;
            int loc;
            TClassEdit::GetSplit(dm->GetTypeName(), parts, loc);
            std::vector<std::string>::const_iterator iPart = parts.begin();
            while (iPart != parts.end() && *iPart == "")
               ++iPart;
            if (iPart != parts.end() && *iPart != dm->GetTypeName()) {
               for (std::vector<std::string>::const_iterator iP = iPart,
                  iPE = parts.end(); iP != iPE; ++iP) {
                     if (TString(TClassEdit::ResolveTypedef(iP->c_str(), true).c_str()).EndsWith("**")){
                        ptp = kTRUE;
                        break;
                     }
               }
            }
            if (ptp) {
               continue;
            }

            void* element;
            for (UInt_t i = 0; i < count ; i++) {
               element = *(void**)proxy->At(i);

               if (!element) {
                  continue;
               }
               if (clProxy->InheritsFrom(TObject::Class())) {
                  name = ((TObject*) element)->GetName();
               }

               // create node
               TStructNode* node = new TStructNode(name, typeName, element, parent, size, kClass);
               // add addition information
               AddNode(node, size);
               // increase parents counter
               parent->SetMembersCount(parent->GetMembersCount() + 1);

               CountMembers(clProxy, node, element);
               parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
               parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
            }
         }
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // COLLECTION
   //////////////////////////////////////////////////////////////////////////
   // if our parent node is collection
   if(cl->InheritsFrom(TCollection::Class())) {
      // we change type of node to collection
      parent->SetNodeType(kCollection);

      // return if invalid pointer to collection
      if (!pointer) {
         return;
      }

      TIter it2((TCollection*)pointer);
      TObject* item;
      // loop through all elements in collection
      while((item = it2())) {
         // get size of element
         ULong_t size = 0;
         if (TClass* cl3 = item->IsA()){
            size = cl3->Size();
         }

         // if there is no dictionary
         if (size == 0) {
            size = sizeof(item);
         }

         // create node
         TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
         // add addition information
         AddNode(node, size);
         // increase parents counter
         parent->SetMembersCount(parent->GetMembersCount() + 1);

         CountMembers(item->IsA(), node, item);

         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
      }
   }
}

//________________________________________________________________________
void TStructViewer::Draw(Option_t *option)
{
   // Draw object if there is valid pointer

   TString opt(option);
   if(opt == "count") {

   } else if (opt == "size") {

   }

   if (fTopNode) {
      fGUI->SetNodePtr(fTopNode);
   } else {

   }
}

//________________________________________________________________________
TCanvas* TStructViewer::GetCanvas()
{
   // Returns canvas used to keep TGeoVolumes

   return fGUI->GetCanvas();
}

//________________________________________________________________________
TGMainFrame* TStructViewer::GetFrame()
{
   // Returns pointer to main window

   return fGUI;
}
//________________________________________________________________________
void* TStructViewer::GetPointer() const
{
   // Return main pointer

   return fPointer;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelMembersCount() const
{
   // Returns TExMap with pairs <level number, number of objects>

   return fLevelMembersCount;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelSize() const
{
   // Returns TExMap with pairs <level number, size of level in bytes>

   return fLevelSize;
}

//________________________________________________________________________
Bool_t TStructViewer::GetLinksVisibility() const
{
   // Get visibility of links between objects

   return fGUI->GetLinksVisibility();
}

//________________________________________________________________________
void TStructViewer::Prepare()
{
   // Create top node and find all member nodes
   if (fTopNode) {
      Reset();
   }

   ULong_t size = fPointerClass->Size();

   TString name = "Main pointer";
   if (fPointerClass->InheritsFrom(TObject::Class())) {
      name = ((TObject*) fPointer)->GetName();
   }
   fTopNode = new TStructNode(name, fPointerClass->GetName(), fPointer, NULL, size, kClass);
   AddNode(fTopNode, size);
   CountMembers(fPointerClass, fTopNode, fPointer);
}

//________________________________________________________________________
void TStructViewer::Reset()
{
   // Deleting nodes, maps and array

   TList* lst;
   TIter it(&fLevelArray);
   while ((lst = (TList*) it() )) {
      lst->SetOwner();
      lst->Clear();
   }

   // deleting maps and array
   fLevelMembersCount.Clear();
   fLevelSize.Clear();
   fPointers.Clear();
   fLevelArray.Clear();

   fTopNode = NULL;
}

//________________________________________________________________________
void TStructViewer::SetColor(TString name, Int_t color)
{
   // Sets color for the class "name" to color "color"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while ((prop = (TStructNodeProperty*) it() )) {
      if (name == prop->GetName()) {
         prop->SetColor(TColor::GetColor(color));
         fGUI->Update();

         return;
      }
   }

   // add color
   prop = new TStructNodeProperty(name.Data(), color);
   fColors.Add(prop);
   fColors.Sort();
}

//________________________________________________________________________
void TStructViewer::SetLinksVisibility(Bool_t val)
{
   // ISets links visibility

   fGUI->SetLinksVisibility(val);
}

//________________________________________________________________________
void TStructViewer::SetPointer(void* ptr, const char* clname)
{
   // Set main pointer of class "clname"

   if (ptr) {
      TA* a = (TA*) ptr;
      if (clname) {
         fPointerClass = TClass::GetClass(clname);
      } else {
         fPointerClass = TClass::GetClass(typeid(*a));
      }

      if (!fPointerClass) {
         return;
      }

      fPointer = ptr;
      Prepare();
      fGUI->SetNodePtr(fTopNode);
   }
}

//________________________________________________________________________
TColor TStructViewer::GetColor(const char* typeName)
{
   // Returns color associated with type "typeName"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while((prop = (TStructNodeProperty*) it())) {
      if (!strcmp(prop->GetName(), typeName)) {
         return prop->GetColor();
      }
   }

   return TColor();
}
<commit_msg>Fix enum to bool conversion warning.<commit_after>// @(#)root/gviz3d:$Id$
// Author: Tomasz Sosnicki   18/09/09

/************************************************************************
* Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/

#include "TStructViewer.h"
#include "TStructNodeProperty.h"
#include "TStructViewerGUI.h"
#include "TStructNode.h"

#include <TDataMember.h>
#include <TVirtualCollectionProxy.h>
#include <TClassEdit.h>
#include <vector>

ClassImp(TStructViewer);

class TA {
public:
   virtual ~TA() {}
};

//________________________________________________________________________
//////////////////////////////////////////////////////////////////////////
//
// TStructViewer viewer represents class, struct or other type as an object in 3D space.
// At the top of the scene we can see objects which is our pointer. Under it we see
// pointers and collection elements. Collection must inherit from TCollection
// or be STL collecion.
//
// We can change the number of visible levels or objects on the scene with the  GUI or
// methods. The size of geometry objects is proportional to the memory taken by this object
// or to the number of members inside this object.
//
// An easy way to find some class in the viewer is to change the color of the type.
// We can connect for example a TF2 class with red color or connect all classes
// inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us
// that all classes inheriting from TF2 will be red.
//
// Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over
// some object you can see some information about it (e.g. name, size, actual level).
// When you double click this object, it becames top object on scene.
// Undo and redo operation are supported.
//
// Begin_Html
//
 In this picture we can see TStructViewer with pointer to TList which contains
// other collections and objects of various classes

//
// End_Html
//
// Begin_Html
//
 Other screenshot presents opened TStructNodeEditor

//
// End_Html
//
//
//////////////////////////////////////////////////////////////////////////

//________________________________________________________________________
TStructViewer::TStructViewer(void* ptr, const char * clname)
{
   // Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in the viewer

   fPointer = NULL;
   fPointerClass = NULL;
   fTopNode = NULL;

   // add default color
   fColors.Add(new TStructNodeProperty("+", 17));

   // creating GUI
   fGUI = new TStructViewerGUI(this, NULL, &fColors);

   SetPointer(ptr, clname);
}

//________________________________________________________________________
TStructViewer::~TStructViewer()
{
   // Destructor. Clean all object after closing the viewer

   Reset();
   fColors.SetOwner();
   fColors.Clear();
}

//________________________________________________________________________
void TStructViewer::AddNode(TStructNode* node, ULong_t size)
{
   // Find list with nodes on specified level and add node to this list and increment list of sizes and list of members

   TList* list = (TList*)fLevelArray[node->GetLevel()];
   // if list doesn't exist -> create one
   if(!list) {
      fLevelArray[node->GetLevel()] = list = new TList();
   }
   list->Add(node);

   // increase number of members on this level
   fLevelMembersCount(node->GetLevel())++;
   // increase size of this level
   fLevelSize(node->GetLevel()) += size;
}

//________________________________________________________________________
void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
{
   // Count allocated memory, increase member counters, find child nodes

   if(!cl) {
      return;
   }

   if (cl->InheritsFrom(TClass::Class())) {
      return;
   }

   //////////////////////////////////////////////////////////////////////////
   // DATA MEMBERS
   //////////////////////////////////////////////////////////////////////////
   // Set up list of RealData so TClass doesn't create a new object itself
   cl->BuildRealData(parent->GetPointer());
   TIter it(cl->GetListOfDataMembers());
   TDataMember* dm;
   while ((dm = (TDataMember*) it() ))
   {
      // increase counters in parent node
      parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
      parent->SetMembersCount(parent->GetMembersCount() + 1);

      if (dm->Property() & kIsStatic) {
         continue;
      }

      void* ptr = NULL;

      if(dm->IsaPointer()) {
         TString trueTypeName = dm->GetTrueTypeName();

         // skip if pointer to pointer
         if(trueTypeName.EndsWith("**")) {
            continue;
         }

         if (!pointer) {
            continue;
         }

         void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
         ptr = *pptr;

         if (!ptr) {
            continue;
         }

         if(fPointers.GetValue((ULong_t)ptr)) {
            continue;
         } else {
            fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
         }

         ULong_t size = 0;
         if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
            size = cl2->Size();
         }

         if(size == 0) {
            size = dm->GetUnitSize();
         }

         ENodeType type;
         if(dm->GetDataType()) {   // pointer to basic type
            type = kBasic;
         } else {
            type = kClass;
         }

         // creating TStructNode
         TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
         AddNode(node, size);

         CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);

         // total size = size of parent + size of nodes daughters
         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
         // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
      } else {
         ptr = (void*)((ULong_t)pointer + dm->GetOffset());

         if (!ptr) {
            continue;
         }
         CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
      }

      //////////////////////////////////////////////////////////////////////////
      // STL COLLECTION
      //////////////////////////////////////////////////////////////////////////
      if (dm->IsSTLContainer()) {
         parent->SetNodeType(kSTLCollection);

         //it works only for pointer in std object (not pointer)
         TClass* stlClass = TClass::GetClass(dm->GetTypeName());
         if (!stlClass) {
            continue;
         }

         TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
         if (!proxy) {
            continue;
         }
         TVirtualCollectionProxy::TPushPop helper(proxy, ptr);

         UInt_t count = proxy->Size();
         parent->SetMembersCount(parent->GetMembersCount() + count);

         if (!proxy->HasPointers() || proxy->GetType() != kNoType_t) { // only objects or pointers to basic type
            parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
            parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
         } else {
            TClass* clProxy = proxy->GetValueClass();
            TString name;
            TString typeName;
            // get size of element
            ULong_t size = 0;
            if (clProxy) {
               name = clProxy->GetName();
               typeName = clProxy->GetName();
               size = clProxy->Size();
            } else {
               continue;
            }

            // if there is no dictionary
            if (size == 0) {
               size = proxy->Sizeof();
            }

            // searching pointer to pointer
            Bool_t ptp = kFALSE;
            std::vector<std::string> parts;
            int loc;
            TClassEdit::GetSplit(dm->GetTypeName(), parts, loc);
            std::vector<std::string>::const_iterator iPart = parts.begin();
            while (iPart != parts.end() && *iPart == "")
               ++iPart;
            if (iPart != parts.end() && *iPart != dm->GetTypeName()) {
               for (std::vector<std::string>::const_iterator iP = iPart,
                  iPE = parts.end(); iP != iPE; ++iP) {
                     if (TString(TClassEdit::ResolveTypedef(iP->c_str(), true).c_str()).EndsWith("**")){
                        ptp = kTRUE;
                        break;
                     }
               }
            }
            if (ptp) {
               continue;
            }

            void* element;
            for (UInt_t i = 0; i < count ; i++) {
               element = *(void**)proxy->At(i);

               if (!element) {
                  continue;
               }
               if (clProxy->InheritsFrom(TObject::Class())) {
                  name = ((TObject*) element)->GetName();
               }

               // create node
               TStructNode* node = new TStructNode(name, typeName, element, parent, size, kClass);
               // add addition information
               AddNode(node, size);
               // increase parents counter
               parent->SetMembersCount(parent->GetMembersCount() + 1);

               CountMembers(clProxy, node, element);
               parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
               parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
            }
         }
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // COLLECTION
   //////////////////////////////////////////////////////////////////////////
   // if our parent node is collection
   if(cl->InheritsFrom(TCollection::Class())) {
      // we change type of node to collection
      parent->SetNodeType(kCollection);

      // return if invalid pointer to collection
      if (!pointer) {
         return;
      }

      TIter it2((TCollection*)pointer);
      TObject* item;
      // loop through all elements in collection
      while((item = it2())) {
         // get size of element
         ULong_t size = 0;
         if (TClass* cl3 = item->IsA()){
            size = cl3->Size();
         }

         // if there is no dictionary
         if (size == 0) {
            size = sizeof(item);
         }

         // create node
         TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
         // add addition information
         AddNode(node, size);
         // increase parents counter
         parent->SetMembersCount(parent->GetMembersCount() + 1);

         CountMembers(item->IsA(), node, item);

         parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
         parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
      }
   }
}

//________________________________________________________________________
void TStructViewer::Draw(Option_t *option)
{
   // Draw object if there is valid pointer

   TString opt(option);
   if(opt == "count") {

   } else if (opt == "size") {

   }

   if (fTopNode) {
      fGUI->SetNodePtr(fTopNode);
   } else {

   }
}

//________________________________________________________________________
TCanvas* TStructViewer::GetCanvas()
{
   // Returns canvas used to keep TGeoVolumes

   return fGUI->GetCanvas();
}

//________________________________________________________________________
TGMainFrame* TStructViewer::GetFrame()
{
   // Returns pointer to main window

   return fGUI;
}
//________________________________________________________________________
void* TStructViewer::GetPointer() const
{
   // Return main pointer

   return fPointer;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelMembersCount() const
{
   // Returns TExMap with pairs <level number, number of objects>

   return fLevelMembersCount;
}

//________________________________________________________________________
TExMap TStructViewer::GetLevelSize() const
{
   // Returns TExMap with pairs <level number, size of level in bytes>

   return fLevelSize;
}

//________________________________________________________________________
Bool_t TStructViewer::GetLinksVisibility() const
{
   // Get visibility of links between objects

   return fGUI->GetLinksVisibility();
}

//________________________________________________________________________
void TStructViewer::Prepare()
{
   // Create top node and find all member nodes
   if (fTopNode) {
      Reset();
   }

   ULong_t size = fPointerClass->Size();

   TString name = "Main pointer";
   if (fPointerClass->InheritsFrom(TObject::Class())) {
      name = ((TObject*) fPointer)->GetName();
   }
   fTopNode = new TStructNode(name, fPointerClass->GetName(), fPointer, NULL, size, kClass);
   AddNode(fTopNode, size);
   CountMembers(fPointerClass, fTopNode, fPointer);
}

//________________________________________________________________________
void TStructViewer::Reset()
{
   // Deleting nodes, maps and array

   TList* lst;
   TIter it(&fLevelArray);
   while ((lst = (TList*) it() )) {
      lst->SetOwner();
      lst->Clear();
   }

   // deleting maps and array
   fLevelMembersCount.Clear();
   fLevelSize.Clear();
   fPointers.Clear();
   fLevelArray.Clear();

   fTopNode = NULL;
}

//________________________________________________________________________
void TStructViewer::SetColor(TString name, Int_t color)
{
   // Sets color for the class "name" to color "color"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while ((prop = (TStructNodeProperty*) it() )) {
      if (name == prop->GetName()) {
         prop->SetColor(TColor::GetColor(color));
         fGUI->Update();

         return;
      }
   }

   // add color
   prop = new TStructNodeProperty(name.Data(), color);
   fColors.Add(prop);
   fColors.Sort();
}

//________________________________________________________________________
void TStructViewer::SetLinksVisibility(Bool_t val)
{
   // ISets links visibility

   fGUI->SetLinksVisibility(val);
}

//________________________________________________________________________
void TStructViewer::SetPointer(void* ptr, const char* clname)
{
   // Set main pointer of class "clname"

   if (ptr) {
      TA* a = (TA*) ptr;
      if (clname) {
         fPointerClass = TClass::GetClass(clname);
      } else {
         fPointerClass = TClass::GetClass(typeid(*a));
      }

      if (!fPointerClass) {
         return;
      }

      fPointer = ptr;
      Prepare();
      fGUI->SetNodePtr(fTopNode);
   }
}

//________________________________________________________________________
TColor TStructViewer::GetColor(const char* typeName)
{
   // Returns color associated with type "typeName"

   TIter it(&fColors);
   TStructNodeProperty* prop;
   while((prop = (TStructNodeProperty*) it())) {
      if (!strcmp(prop->GetName(), typeName)) {
         return prop->GetColor();
      }
   }

   return TColor();
}
<|endoftext|>