<commit_before>/*************************************************************************
 *
 *  $RCSfile: sdpopup.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: cl $ $Date: 2002-09-27 13:10:41 $
 *
 *  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 _EEITEM_HXX //autogen
#include <svx/eeitem.hxx>
#endif

#include <svx/editeng.hxx>
#define ITEMID_FIELD    EE_FEATURE_FIELD
#include <svx/flditem.hxx>
#ifndef _ZFORLIST_HXX
#include <svtools/zforlist.hxx>
#endif
#ifndef _SVX_ADRITEM_HXX
#include <svx/adritem.hxx>
#endif
#ifndef _SFX_OBJSH_HXX
#include <sfx2/objsh.hxx>
#endif
#ifndef _SFXDOCFILE_HXX
#include <sfx2/docfile.hxx>
#endif

#include "strings.hrc"
#include "sdpopup.hxx"
#include "sdresid.hxx"
#include "sdmod.hxx"
#include "drawdoc.hxx"
#include "docshell.hxx"

/*************************************************************************
|*
|* PopupMenu zum Bearbeiten von Feldbefehlen
|*
\************************************************************************/

SdFieldPopup::SdFieldPopup( const SvxFieldData* pInField, LanguageType eLanguage ) :
        PopupMenu   (),
        pField      ( pInField )
{
    Fill( eLanguage );
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SdFieldPopup::~SdFieldPopup()
{
}

/*************************************************************************
|*
|* Fill
|*
\************************************************************************/

void SdFieldPopup::Fill( LanguageType eLanguage )
{
    USHORT nID = 1;
    USHORT nStyle = MIB_RADIOCHECK | MIB_AUTOCHECK;
    InsertItem( nID++, String( SdResId( STR_FIX ) ), nStyle );
    InsertItem( nID++, String( SdResId( STR_VAR ) ), nStyle );
    InsertSeparator();

    if( pField->ISA( SvxDateField ) )
    {
        const SvxDateField* pDateField = (const SvxDateField*) pField;
        SvxDateField aDateField( *pDateField );

        if( pDateField->GetType() == SVXDATETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        //SVXDATEFORMAT_APPDEFAULT,     // Wird nicht benutzt
        //SVXDATEFORMAT_SYSTEM,         // Wird nicht benutzt
        InsertItem( nID++, String( SdResId( STR_STANDARD_SMALL ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_STANDARD_BIG ) ), nStyle );

        SvNumberFormatter* pNumberFormatter = SD_MOD()->GetNumberFormatter();
        aDateField.SetFormat( SVXDATEFORMAT_A );    // 13.02.96
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_B );    // 13.02.1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_C );    // 13.Feb 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        aDateField.SetFormat( SVXDATEFORMAT_D );    // 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_E );    // Die, 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_F );    // Dienstag, 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        CheckItem( (USHORT) ( pDateField->GetFormat() ) + 1 ); // - 2 + 3 !
    }
    else if( pField->ISA( SvxExtTimeField ) )
    {
        const SvxExtTimeField* pTimeField = (const SvxExtTimeField*) pField;
        SvxExtTimeField aTimeField( *pTimeField );

        if( pTimeField->GetType() == SVXTIMETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        //SVXTIMEFORMAT_APPDEFAULT,     // Wird nicht benutzt
        //SVXTIMEFORMAT_SYSTEM,         // Wird nicht benutzt
        InsertItem( nID++, String( SdResId( STR_STANDARD_NORMAL ) ), nStyle );

        SvNumberFormatter* pNumberFormatter = SD_MOD()->GetNumberFormatter();
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HM );    // 13:49
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HMS );   // 13:49:38
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HMSH );  // 13:49:38.78
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        aTimeField.SetFormat( SVXTIMEFORMAT_12_HM );    // 01:49
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_12_HMS );   // 01:49:38
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_12_HMSH );  // 01:49:38.78
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        //SVXTIMEFORMAT_AM_HM,  // 01:49 PM
        //SVXTIMEFORMAT_AM_HMS, // 01:49:38 PM
        //SVXTIMEFORMAT_AM_HMSH // 01:49:38.78 PM

        CheckItem( (USHORT) ( pTimeField->GetFormat() ) + 1 ); // - 2 + 3 !
    }
    else if( pField->ISA( SvxExtFileField ) )
    {
        const SvxExtFileField* pFileField = (const SvxExtFileField*) pField;
        //SvxExtFileField aFileField( *pFileField );

        if( pFileField->GetType() == SVXFILETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_NAME_EXT ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_FULLPATH ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_PATH ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_NAME ) ), nStyle );

        CheckItem( (USHORT) ( pFileField->GetFormat() ) + 3 );
    }
    else if( pField->ISA( SvxAuthorField ) )
    {
        const SvxAuthorField* pAuthorField = (const SvxAuthorField*) pField;
        SvxAuthorField aAuthorField( *pAuthorField );

        if( pAuthorField->GetType() == SVXAUTHORTYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        for( USHORT i = 0; i < 4; i++ )
        {
            aAuthorField.SetFormat( (SvxAuthorFormat) i );
            InsertItem( nID++, aAuthorField.GetFormatted(), nStyle );
        }
        CheckItem( (USHORT) ( pAuthorField->GetFormat() ) + 3 );
    }
}

/*************************************************************************
|*
|* Gibt das neue Feld zurueck, gehoert dem Caller.
|* Liefert NULL, wenn sich nichts geaendert hat.
|*
\************************************************************************/

SvxFieldData* SdFieldPopup::GetField()
{
    SvxFieldData* pNewField = NULL;
    USHORT nCount = GetItemCount();

    if( pField->ISA( SvxDateField ) )
    {
        const SvxDateField* pDateField = (const SvxDateField*) pField;
        SvxDateType   eType;
        SvxDateFormat eFormat;

        if( IsItemChecked( 1 ) )
            eType = SVXDATETYPE_FIX;
        else
            eType = SVXDATETYPE_VAR;

        for( USHORT i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxDateFormat) ( i - 1 );

        if( pDateField->GetFormat() != eFormat ||
            pDateField->GetType() != eType )
        {
            pNewField = new SvxDateField( *pDateField );
            ( (SvxDateField*) pNewField )->SetType( eType );
            ( (SvxDateField*) pNewField )->SetFormat( eFormat );

            if( (pDateField->GetType() == SVXDATETYPE_VAR) && (eType == SVXDATETYPE_FIX) )
            {
                Date aDate;
                ( (SvxDateField*) pNewField )->SetFixDate( aDate );
            }
        }
    }
    else if( pField->ISA( SvxExtTimeField ) )
    {
        const SvxExtTimeField* pTimeField = (const SvxExtTimeField*) pField;
        SvxTimeType   eType;
        SvxTimeFormat eFormat;

        if( IsItemChecked( 1 ) )
            eType = SVXTIMETYPE_FIX;
        else
            eType = SVXTIMETYPE_VAR;

        for( USHORT i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxTimeFormat) ( i - 1 );

        if( pTimeField->GetFormat() != eFormat ||
            pTimeField->GetType() != eType )
        {
            pNewField = new SvxExtTimeField( *pTimeField );
            ( (SvxExtTimeField*) pNewField )->SetType( eType );
            ( (SvxExtTimeField*) pNewField )->SetFormat( eFormat );

            if( (pTimeField->GetType() == SVXTIMETYPE_VAR) && (eType == SVXTIMETYPE_FIX) )
            {
                Time aTime;
                ( (SvxExtTimeField*) pNewField )->SetFixTime( aTime );
            }

        }
    }
    else if( pField->ISA( SvxExtFileField ) )
    {
        const SvxExtFileField* pFileField = (const SvxExtFileField*) pField;
        SvxFileType   eType;
        SvxFileFormat eFormat;

        if( IsItemChecked( 1 ) )
            eType = SVXFILETYPE_FIX;
        else
            eType = SVXFILETYPE_VAR;

        for( USHORT i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxFileFormat) ( i - 3 );

        if( pFileField->GetFormat() != eFormat ||
            pFileField->GetType() != eType )
        {
            SdDrawDocShell* pDocSh = PTR_CAST( SdDrawDocShell,
                                               SfxObjectShell::Current() );

            if( pDocSh )
            {
                SvxExtFileField aFileField( *pFileField );

                String aName;
                if( pDocSh->HasName() )
                    aName = pDocSh->GetMedium()->GetName();

                // #91225# Get current filename, not the one stored in the old field
                pNewField = new SvxExtFileField( aName );
                ( (SvxExtFileField*) pNewField )->SetType( eType );
                ( (SvxExtFileField*) pNewField )->SetFormat( eFormat );
            }
        }
    }
    else if( pField->ISA( SvxAuthorField ) )
    {
        const SvxAuthorField* pAuthorField = (const SvxAuthorField*) pField;
        SvxAuthorType   eType;
        SvxAuthorFormat eFormat;

        if( IsItemChecked( 1 ) )
            eType = SVXAUTHORTYPE_FIX;
        else
            eType = SVXAUTHORTYPE_VAR;

        for( USHORT i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxAuthorFormat) ( i - 3 );

        if( pAuthorField->GetFormat() != eFormat ||
            pAuthorField->GetType() != eType )
        {
            // #91225# Get current state of address, not the old one
            pNewField = new SvxAuthorField( SvxAddressItem() );
            ( (SvxAuthorField*) pNewField )->SetType( eType );
            ( (SvxAuthorField*) pNewField )->SetFormat( eFormat );
        }
    }
    return( pNewField );
}

<commit_msg>INTEGRATION: CWS ooo20031110 (1.5.246); FILE MERGED 2003/11/11 14:07:52 waratah 1.5.246.1: #i22301# Correct for scoping rules<commit_after>/*************************************************************************
 *
 *  $RCSfile: sdpopup.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2003-12-01 17:44:36 $
 *
 *  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 _EEITEM_HXX //autogen
#include <svx/eeitem.hxx>
#endif

#include <svx/editeng.hxx>
#define ITEMID_FIELD    EE_FEATURE_FIELD
#include <svx/flditem.hxx>
#ifndef _ZFORLIST_HXX
#include <svtools/zforlist.hxx>
#endif
#ifndef _SVX_ADRITEM_HXX
#include <svx/adritem.hxx>
#endif
#ifndef _SFX_OBJSH_HXX
#include <sfx2/objsh.hxx>
#endif
#ifndef _SFXDOCFILE_HXX
#include <sfx2/docfile.hxx>
#endif

#include "strings.hrc"
#include "sdpopup.hxx"
#include "sdresid.hxx"
#include "sdmod.hxx"
#include "drawdoc.hxx"
#include "docshell.hxx"

/*************************************************************************
|*
|* PopupMenu zum Bearbeiten von Feldbefehlen
|*
\************************************************************************/

SdFieldPopup::SdFieldPopup( const SvxFieldData* pInField, LanguageType eLanguage ) :
        PopupMenu   (),
        pField      ( pInField )
{
    Fill( eLanguage );
}

/*************************************************************************
|*
|* Dtor
|*
\************************************************************************/

SdFieldPopup::~SdFieldPopup()
{
}

/*************************************************************************
|*
|* Fill
|*
\************************************************************************/

void SdFieldPopup::Fill( LanguageType eLanguage )
{
    USHORT nID = 1;
    USHORT nStyle = MIB_RADIOCHECK | MIB_AUTOCHECK;
    InsertItem( nID++, String( SdResId( STR_FIX ) ), nStyle );
    InsertItem( nID++, String( SdResId( STR_VAR ) ), nStyle );
    InsertSeparator();

    if( pField->ISA( SvxDateField ) )
    {
        const SvxDateField* pDateField = (const SvxDateField*) pField;
        SvxDateField aDateField( *pDateField );

        if( pDateField->GetType() == SVXDATETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        //SVXDATEFORMAT_APPDEFAULT,     // Wird nicht benutzt
        //SVXDATEFORMAT_SYSTEM,         // Wird nicht benutzt
        InsertItem( nID++, String( SdResId( STR_STANDARD_SMALL ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_STANDARD_BIG ) ), nStyle );

        SvNumberFormatter* pNumberFormatter = SD_MOD()->GetNumberFormatter();
        aDateField.SetFormat( SVXDATEFORMAT_A );    // 13.02.96
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_B );    // 13.02.1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_C );    // 13.Feb 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        aDateField.SetFormat( SVXDATEFORMAT_D );    // 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_E );    // Die, 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aDateField.SetFormat( SVXDATEFORMAT_F );    // Dienstag, 13.Februar 1996
        InsertItem( nID++, aDateField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        CheckItem( (USHORT) ( pDateField->GetFormat() ) + 1 ); // - 2 + 3 !
    }
    else if( pField->ISA( SvxExtTimeField ) )
    {
        const SvxExtTimeField* pTimeField = (const SvxExtTimeField*) pField;
        SvxExtTimeField aTimeField( *pTimeField );

        if( pTimeField->GetType() == SVXTIMETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        //SVXTIMEFORMAT_APPDEFAULT,     // Wird nicht benutzt
        //SVXTIMEFORMAT_SYSTEM,         // Wird nicht benutzt
        InsertItem( nID++, String( SdResId( STR_STANDARD_NORMAL ) ), nStyle );

        SvNumberFormatter* pNumberFormatter = SD_MOD()->GetNumberFormatter();
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HM );    // 13:49
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HMS );   // 13:49:38
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_24_HMSH );  // 13:49:38.78
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );

        aTimeField.SetFormat( SVXTIMEFORMAT_12_HM );    // 01:49
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_12_HMS );   // 01:49:38
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        aTimeField.SetFormat( SVXTIMEFORMAT_12_HMSH );  // 01:49:38.78
        InsertItem( nID++, aTimeField.GetFormatted( *pNumberFormatter, eLanguage ), nStyle );
        //SVXTIMEFORMAT_AM_HM,  // 01:49 PM
        //SVXTIMEFORMAT_AM_HMS, // 01:49:38 PM
        //SVXTIMEFORMAT_AM_HMSH // 01:49:38.78 PM

        CheckItem( (USHORT) ( pTimeField->GetFormat() ) + 1 ); // - 2 + 3 !
    }
    else if( pField->ISA( SvxExtFileField ) )
    {
        const SvxExtFileField* pFileField = (const SvxExtFileField*) pField;
        //SvxExtFileField aFileField( *pFileField );

        if( pFileField->GetType() == SVXFILETYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_NAME_EXT ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_FULLPATH ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_PATH ) ), nStyle );
        InsertItem( nID++, String( SdResId( STR_FILEFORMAT_NAME ) ), nStyle );

        CheckItem( (USHORT) ( pFileField->GetFormat() ) + 3 );
    }
    else if( pField->ISA( SvxAuthorField ) )
    {
        const SvxAuthorField* pAuthorField = (const SvxAuthorField*) pField;
        SvxAuthorField aAuthorField( *pAuthorField );

        if( pAuthorField->GetType() == SVXAUTHORTYPE_FIX )
            CheckItem( 1 );
        else
            CheckItem( 2 );

        for( USHORT i = 0; i < 4; i++ )
        {
            aAuthorField.SetFormat( (SvxAuthorFormat) i );
            InsertItem( nID++, aAuthorField.GetFormatted(), nStyle );
        }
        CheckItem( (USHORT) ( pAuthorField->GetFormat() ) + 3 );
    }
}

/*************************************************************************
|*
|* Gibt das neue Feld zurueck, gehoert dem Caller.
|* Liefert NULL, wenn sich nichts geaendert hat.
|*
\************************************************************************/

SvxFieldData* SdFieldPopup::GetField()
{
    SvxFieldData* pNewField = NULL;
    USHORT nCount = GetItemCount();

    if( pField->ISA( SvxDateField ) )
    {
        const SvxDateField* pDateField = (const SvxDateField*) pField;
        SvxDateType   eType;
        SvxDateFormat eFormat;
        USHORT i;

        if( IsItemChecked( 1 ) )
            eType = SVXDATETYPE_FIX;
        else
            eType = SVXDATETYPE_VAR;

        for( i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxDateFormat) ( i - 1 );

        if( pDateField->GetFormat() != eFormat ||
            pDateField->GetType() != eType )
        {
            pNewField = new SvxDateField( *pDateField );
            ( (SvxDateField*) pNewField )->SetType( eType );
            ( (SvxDateField*) pNewField )->SetFormat( eFormat );

            if( (pDateField->GetType() == SVXDATETYPE_VAR) && (eType == SVXDATETYPE_FIX) )
            {
                Date aDate;
                ( (SvxDateField*) pNewField )->SetFixDate( aDate );
            }
        }
    }
    else if( pField->ISA( SvxExtTimeField ) )
    {
        const SvxExtTimeField* pTimeField = (const SvxExtTimeField*) pField;
        SvxTimeType   eType;
        SvxTimeFormat eFormat;
        USHORT i;

        if( IsItemChecked( 1 ) )
            eType = SVXTIMETYPE_FIX;
        else
            eType = SVXTIMETYPE_VAR;

        for( i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxTimeFormat) ( i - 1 );

        if( pTimeField->GetFormat() != eFormat ||
            pTimeField->GetType() != eType )
        {
            pNewField = new SvxExtTimeField( *pTimeField );
            ( (SvxExtTimeField*) pNewField )->SetType( eType );
            ( (SvxExtTimeField*) pNewField )->SetFormat( eFormat );

            if( (pTimeField->GetType() == SVXTIMETYPE_VAR) && (eType == SVXTIMETYPE_FIX) )
            {
                Time aTime;
                ( (SvxExtTimeField*) pNewField )->SetFixTime( aTime );
            }

        }
    }
    else if( pField->ISA( SvxExtFileField ) )
    {
        const SvxExtFileField* pFileField = (const SvxExtFileField*) pField;
        SvxFileType   eType;
        SvxFileFormat eFormat;
        USHORT i;

        if( IsItemChecked( 1 ) )
            eType = SVXFILETYPE_FIX;
        else
            eType = SVXFILETYPE_VAR;

        for( i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxFileFormat) ( i - 3 );

        if( pFileField->GetFormat() != eFormat ||
            pFileField->GetType() != eType )
        {
            SdDrawDocShell* pDocSh = PTR_CAST( SdDrawDocShell,
                                               SfxObjectShell::Current() );

            if( pDocSh )
            {
                SvxExtFileField aFileField( *pFileField );

                String aName;
                if( pDocSh->HasName() )
                    aName = pDocSh->GetMedium()->GetName();

                // #91225# Get current filename, not the one stored in the old field
                pNewField = new SvxExtFileField( aName );
                ( (SvxExtFileField*) pNewField )->SetType( eType );
                ( (SvxExtFileField*) pNewField )->SetFormat( eFormat );
            }
        }
    }
    else if( pField->ISA( SvxAuthorField ) )
    {
        const SvxAuthorField* pAuthorField = (const SvxAuthorField*) pField;
        SvxAuthorType   eType;
        SvxAuthorFormat eFormat;
        USHORT i;

        if( IsItemChecked( 1 ) )
            eType = SVXAUTHORTYPE_FIX;
        else
            eType = SVXAUTHORTYPE_VAR;

        for( i = 3; i <= nCount; i++ )
        {
            if( IsItemChecked( i ) )
                break;
        }
        eFormat = (SvxAuthorFormat) ( i - 3 );

        if( pAuthorField->GetFormat() != eFormat ||
            pAuthorField->GetType() != eType )
        {
            // #91225# Get current state of address, not the old one
            pNewField = new SvxAuthorField( SvxAddressItem() );
            ( (SvxAuthorField*) pNewField )->SetType( eType );
            ( (SvxAuthorField*) pNewField )->SetFormat( eFormat );
        }
    }
    return( pNewField );
}

<|endoftext|>


<commit_before>#ifndef _SDD_HOM_EXPRESSION_SIMPLE_HH_
#define _SDD_HOM_EXPRESSION_SIMPLE_HH_

#include <algorithm> // any_of, copy, find
#include <cassert>
#include <utility>   // pair

#include "sdd/dd/definition.hh"
#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/evaluation_error.hh"
#include "sdd/hom/expression/evaluator.hh"
#include "sdd/hom/expression/stacks.hh"
#include "sdd/order/order.hh"

namespace sdd { namespace hom { namespace expr {

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

/// @internal
/// @brief
template <typename C>
struct simple
{
  /// @brief Needed by mem::variant.
  using result_type = SDD<C>;

  /// @brief A variable type.
  using variable_type = typename C::Variable;

  /// @brief The type of a set of values.
  using values_type = typename C::Values;

  /// @brief The evaluation's context.
  context<C>& cxt_;

  /// @brief The target of the evaluated expression.
  const order_position_type target_;

  /// @brief User evaluator of the expression.
  evaluator_base<C>& eval_;

  /// @brief Constructor.
  simple(context<C>& cxt, order_position_type target, evaluator_base<C>& eval)
    : cxt_(cxt), target_(target), eval_(eval)
  {}

  /// @brief Evaluation on hierarchical nodes.
  SDD<C>
  operator()( const hierarchical_node<C>& node, const SDD<C>& s
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    auto& sdd_cxt = cxt_.sdd_context();

    if (not o.contains(o.position(), target_)) // not the last level?
    {
      const bool nested_variables = std::any_of( cit, end
                                               , [&](order_position_type pos)
                                                    {
                                                      return o.contains(o.position(), pos);
                                                    });

      if (not nested_variables)
      {
        // We are not interested in this level, thus the visitor is propagated to the next level.
        dd::square_union<C, SDD<C>> su;
        su.reserve(node.size());
        for (const auto& arc : node)
        {
          const SDD<C> successor = visit_self(*this, arc.successor(), o.next(), app, res, cit, end);
          su.add(successor, arc.valuation());
        }
        return SDD<C>(o.variable(), su(cxt_.sdd_context()));
      }
      else
      {
        // We are interested in this level, but the target is not nested into it. Thus, we must
        // propagate on both nesteds SDD and successors.
        dd::sum_builder<C, SDD<C>> operands;
        operands.reserve(node.size());
        try
        {
          for (const auto& arc : node)
          {
            // push on stacks
            const auto local_app = std::make_shared<app_stack<C>>(arc.successor(), o.next(), app);
            const auto local_res = std::make_shared<res_stack<C>>(res);

            const auto nested = visit_self( *this, arc.valuation(), o.nested(), local_app, local_res
                                          , cit, end);

            assert(not local_res->result.empty() && "Invalid empty successor result");
            operands.add( SDD<C>( o.variable(), nested
                                , dd::sum<C>(sdd_cxt, std::move(local_res->result))));
          }
          return dd::sum<C>(sdd_cxt, std::move(operands));
        }
        catch (top<C>& t)
        {
          evaluation_error<C> e(s);
          e.add_top(t);
          throw e;
        }
      }
    }
    else
    {
      // Final level, we just need to propagate in the nested SDD.
      dd::sum_builder<C, SDD<C>> operands;
      operands.reserve(node.size());
      for (const auto& arc : node)
      {
        const auto nested = visit_self(*this, arc.valuation(), o.nested(), app, res, cit, end);
        operands.add(SDD<C>(o.variable(), nested, arc.successor()));
      }
      try
      {
        return dd::sum<C>(sdd_cxt, std::move(operands));
      }
      catch (top<C>& t)
      {
        evaluation_error<C> e(s);
        e.add_top(t);
        throw e;
      }
    }
  }

  /// @brief Evaluation on flat nodes.
  SDD<C>
  operator()( const flat_node<C>& node, const SDD<C>& s
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    auto& sdd_cxt = cxt_.sdd_context();
    const bool last_level = o.position() == target_;
    const bool update_values = std::find(cit, end, o.position()) != end;

    if (update_values)
    {
      // Narrow the range for future searches of identifiers.
      cit = std::next(cit);
    }

    if (last_level)
    {
      dd::sum_builder<C, SDD<C>> operands;
      operands.reserve(node.size());
      for (const auto& arc : node)
      {
        if (update_values)
        {
          eval_.update(o.identifier(), arc.valuation());
        }
        operands.add(SDD<C>(o.variable(), eval_.evaluate(), arc.successor()));
      }
      try
      {
        return dd::sum<C>(sdd_cxt, std::move(operands));
      }
      catch (top<C>& t)
      {
        evaluation_error<C> e(s);
        e.add_top(t);
        throw e;
      }
    }
    else
    {
      // Not the last level, we just need to update values if necessary and to propagate on
      // successors.
      dd::square_union<C, values_type> su;
      for (const auto& arc : node)
      {
        if (update_values)
        {
          eval_.update(o.identifier(), arc.valuation());
        }
        const auto successor = visit_self(*this, arc.successor(), o.next(), app, res, cit, end);
        su.add(successor, arc.valuation());
      }
      return SDD<C>(o.variable(), su(sdd_cxt));
    }
  }

  /// @brief Evaluation on |1|.
  SDD<C>
  operator()( const one_terminal<C>&, const SDD<C>&
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    assert(app && "Target never encountered while evaluating SimpleExpression");
    // Continue to the stacked successor of a previously visited hierachical node.
    const auto stacked_succ = visit_self(*this, app->sdd, app->ord, app->next, res->next, cit, end);
    res->result.add(stacked_succ);
    return sdd::one<C>();
  }

  /// @brief Evaluation on |0|.
  ///
  /// Should never happen.
  SDD<C>
  operator()( const zero_terminal<C>&, const SDD<C>&
            , const order<C>&
            , const std::shared_ptr<app_stack<C>>&, const std::shared_ptr<res_stack<C>>&
            , order_positions_iterator, order_positions_iterator)
  const noexcept
  {
    assert(false);
    __builtin_unreachable();
  }
}; // struct simple

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

}}} // namespace sdd::hom::expr

#endif // _SDD_HOM_EXPRESSION_SIMPLE_HH_
<commit_msg>Reserve size for a square_union.<commit_after>#ifndef _SDD_HOM_EXPRESSION_SIMPLE_HH_
#define _SDD_HOM_EXPRESSION_SIMPLE_HH_

#include <algorithm> // any_of, copy, find
#include <cassert>
#include <utility>   // pair

#include "sdd/dd/definition.hh"
#include "sdd/hom/context_fwd.hh"
#include "sdd/hom/definition_fwd.hh"
#include "sdd/hom/evaluation_error.hh"
#include "sdd/hom/expression/evaluator.hh"
#include "sdd/hom/expression/stacks.hh"
#include "sdd/order/order.hh"

namespace sdd { namespace hom { namespace expr {

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

/// @internal
/// @brief
template <typename C>
struct simple
{
  /// @brief Needed by mem::variant.
  using result_type = SDD<C>;

  /// @brief A variable type.
  using variable_type = typename C::Variable;

  /// @brief The type of a set of values.
  using values_type = typename C::Values;

  /// @brief The evaluation's context.
  context<C>& cxt_;

  /// @brief The target of the evaluated expression.
  const order_position_type target_;

  /// @brief User evaluator of the expression.
  evaluator_base<C>& eval_;

  /// @brief Constructor.
  simple(context<C>& cxt, order_position_type target, evaluator_base<C>& eval)
    : cxt_(cxt), target_(target), eval_(eval)
  {}

  /// @brief Evaluation on hierarchical nodes.
  SDD<C>
  operator()( const hierarchical_node<C>& node, const SDD<C>& s
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    auto& sdd_cxt = cxt_.sdd_context();

    if (not o.contains(o.position(), target_)) // not the last level?
    {
      const bool nested_variables = std::any_of( cit, end
                                               , [&](order_position_type pos)
                                                    {
                                                      return o.contains(o.position(), pos);
                                                    });

      if (not nested_variables)
      {
        // We are not interested in this level, thus the visitor is propagated to the next level.
        dd::square_union<C, SDD<C>> su;
        su.reserve(node.size());
        for (const auto& arc : node)
        {
          const SDD<C> successor = visit_self(*this, arc.successor(), o.next(), app, res, cit, end);
          su.add(successor, arc.valuation());
        }
        return SDD<C>(o.variable(), su(cxt_.sdd_context()));
      }
      else
      {
        // We are interested in this level, but the target is not nested into it. Thus, we must
        // propagate on both nesteds SDD and successors.
        dd::sum_builder<C, SDD<C>> operands;
        operands.reserve(node.size());
        try
        {
          for (const auto& arc : node)
          {
            // push on stacks
            const auto local_app = std::make_shared<app_stack<C>>(arc.successor(), o.next(), app);
            const auto local_res = std::make_shared<res_stack<C>>(res);

            const auto nested = visit_self( *this, arc.valuation(), o.nested(), local_app, local_res
                                          , cit, end);

            assert(not local_res->result.empty() && "Invalid empty successor result");
            operands.add( SDD<C>( o.variable(), nested
                                , dd::sum<C>(sdd_cxt, std::move(local_res->result))));
          }
          return dd::sum<C>(sdd_cxt, std::move(operands));
        }
        catch (top<C>& t)
        {
          evaluation_error<C> e(s);
          e.add_top(t);
          throw e;
        }
      }
    }
    else
    {
      // Final level, we just need to propagate in the nested SDD.
      dd::sum_builder<C, SDD<C>> operands;
      operands.reserve(node.size());
      for (const auto& arc : node)
      {
        const auto nested = visit_self(*this, arc.valuation(), o.nested(), app, res, cit, end);
        operands.add(SDD<C>(o.variable(), nested, arc.successor()));
      }
      try
      {
        return dd::sum<C>(sdd_cxt, std::move(operands));
      }
      catch (top<C>& t)
      {
        evaluation_error<C> e(s);
        e.add_top(t);
        throw e;
      }
    }
  }

  /// @brief Evaluation on flat nodes.
  SDD<C>
  operator()( const flat_node<C>& node, const SDD<C>& s
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    auto& sdd_cxt = cxt_.sdd_context();
    const bool last_level = o.position() == target_;
    const bool update_values = std::find(cit, end, o.position()) != end;

    if (update_values)
    {
      // Narrow the range for future searches of identifiers.
      cit = std::next(cit);
    }

    if (last_level)
    {
      dd::sum_builder<C, SDD<C>> operands;
      operands.reserve(node.size());
      for (const auto& arc : node)
      {
        if (update_values)
        {
          eval_.update(o.identifier(), arc.valuation());
        }
        operands.add(SDD<C>(o.variable(), eval_.evaluate(), arc.successor()));
      }
      try
      {
        return dd::sum<C>(sdd_cxt, std::move(operands));
      }
      catch (top<C>& t)
      {
        evaluation_error<C> e(s);
        e.add_top(t);
        throw e;
      }
    }
    else
    {
      // Not the last level, we just need to update values if necessary and to propagate on
      // successors.
      dd::square_union<C, values_type> su;
      su.reserve(node.size());
      for (const auto& arc : node)
      {
        if (update_values)
        {
          eval_.update(o.identifier(), arc.valuation());
        }
        const auto successor = visit_self(*this, arc.successor(), o.next(), app, res, cit, end);
        su.add(successor, arc.valuation());
      }
      return SDD<C>(o.variable(), su(sdd_cxt));
    }
  }

  /// @brief Evaluation on |1|.
  SDD<C>
  operator()( const one_terminal<C>&, const SDD<C>&
            , const order<C>& o
            , const std::shared_ptr<app_stack<C>>& app, const std::shared_ptr<res_stack<C>>& res
            , order_positions_iterator cit, order_positions_iterator end)
  const
  {
    assert(app && "Target never encountered while evaluating SimpleExpression");
    // Continue to the stacked successor of a previously visited hierachical node.
    const auto stacked_succ = visit_self(*this, app->sdd, app->ord, app->next, res->next, cit, end);
    res->result.add(stacked_succ);
    return sdd::one<C>();
  }

  /// @brief Evaluation on |0|.
  ///
  /// Should never happen.
  SDD<C>
  operator()( const zero_terminal<C>&, const SDD<C>&
            , const order<C>&
            , const std::shared_ptr<app_stack<C>>&, const std::shared_ptr<res_stack<C>>&
            , order_positions_iterator, order_positions_iterator)
  const noexcept
  {
    assert(false);
    __builtin_unreachable();
  }
}; // struct simple

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

}}} // namespace sdd::hom::expr

#endif // _SDD_HOM_EXPRESSION_SIMPLE_HH_
<|endoftext|>


<commit_before>
/*!
	\file

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2014 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

// Qt include.
#include <QObject>
#include <QtTest/QtTest>

// QtMWidgets include.
#include <QtMWidgets/Picker>

class TestPicker
	:	public QObject
{
	Q_OBJECT

private slots:

	void testPicker()
	{
		QtMWidgets::Picker picker;
		picker.setMouseTracking( true );

		picker.addItem( QLatin1String( "English" ) );
		picker.addItem( QLatin1String( "Russian" ) );
		picker.addItem( QLatin1String( "German" ) );
		picker.addItem( QLatin1String( "Spanish" ) );
		picker.addItem( QLatin1String( "Portuguese" ) );
		picker.addItem( QLatin1String( "Belorussian" ) );
		picker.addItem( QLatin1String( "Polish" ) );
		picker.addItem( QLatin1String( "Ukrainian" ) );

		QFont font = picker.font();
		font.setBold( true );
		font.setPixelSize( 15 );

		picker.setFont( font );
		picker.setCurrentIndex( 1 );

		picker.show();

		QVERIFY( QTest::qWaitForWindowActive( &picker ) );

		picker.setCurrentIndex( 2 );

		QVERIFY( picker.currentIndex() == 2 );
		QVERIFY( picker.currentText() == QStringLiteral( "German" ) );

		QVERIFY( picker.count() == 8 );

		QVERIFY( picker.findText( QStringLiteral( "Polish" ) ) == 6 );
		QVERIFY( picker.itemText( 6 ) == QStringLiteral( "Polish" ) );

		QPoint c( picker.width() / 2, picker.height() / 2 );
		QFontMetrics fm( font );
		const auto h = fm.boundingRect( QLatin1String( "A" ) ).height();
		QPoint d = QPoint( 0, - ( h + h / 3 ) );

		QTest::mouseMove( &picker, c );
		QTest::mousePress( &picker, Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + d, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( &picker, &me );
		QTest::mouseRelease( &picker, Qt::LeftButton, {}, c + d, 20 );
		QTest::mouseMove( &picker, c, 20 );
		QTest::mouseClick( &picker, Qt::LeftButton, {}, c, 20 );

		QVERIFY( picker.currentIndex() == 3 );

		for( int i = 0; i < 8; ++i )
		{
			QTest::mouseMove( &picker, c );
			QTest::mousePress( &picker, Qt::LeftButton, {}, c );
			QMouseEvent me( QEvent::MouseMove, c + d, Qt::LeftButton,
				Qt::LeftButton, {} );
			QApplication::sendEvent( &picker, &me );
			QTest::mouseRelease( &picker, Qt::LeftButton, {}, c + d, 20 );
			QTest::mouseMove( &picker, c, 20 );
			QTest::mouseClick( &picker, Qt::LeftButton, {}, c, 20 );
		}

		QVERIFY( picker.currentIndex() == 3 );
	}
};

QTEST_MAIN( TestPicker )

#include "main.moc"
<commit_msg>Improve test.<commit_after>
/*!
	\file

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2014 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

// Qt include.
#include <QObject>
#include <QtTest/QtTest>
#include <QSharedPointer>

// QtMWidgets include.
#include <QtMWidgets/Picker>

class TestPicker
	:	public QObject
{
	Q_OBJECT

private slots:

	void initTestCase()
	{
		m_data.append( QStringLiteral( "English" ) );
		m_data.append( QStringLiteral( "Russian" ) );
		m_data.append( QStringLiteral( "German" ) );
		m_data.append( QStringLiteral( "Spanish" ) );
		m_data.append( QStringLiteral( "Portuguese" ) );
		m_data.append( QStringLiteral( "Belorussian" ) );
		m_data.append( QStringLiteral( "Polish" ) );
		m_data.append( QStringLiteral( "Ukrainian" ) );

		m_picker.reset( new QtMWidgets::Picker );

		m_picker->setMouseTracking( true );

		for( int i = 0; i < m_data.size(); ++i )
			m_picker->addItem( m_data.at( i ) );

		m_font = m_picker->font();
		m_font.setBold( true );
		m_font.setPixelSize( 15 );

		m_picker->setFont( m_font );

		m_picker->show();

		QVERIFY( QTest::qWaitForWindowActive( m_picker.data() ) );

		QFontMetrics fm( m_font );
		m_lineHeight = fm.boundingRect( QStringLiteral( "A" ) ).height();

		m_delta = QPoint( 0, - ( m_lineHeight + m_lineHeight / 3 ) );
	}

	void testPicker()
	{
		m_picker->setCurrentIndex( 2 );

		QVERIFY( m_picker->currentIndex() == 2 );
		QVERIFY( m_picker->currentText() == QStringLiteral( "German" ) );

		QVERIFY( m_picker->count() == 8 );

		QVERIFY( m_picker->findText( QStringLiteral( "Polish" ) ) == 6 );
		QVERIFY( m_picker->itemText( 6 ) == QStringLiteral( "Polish" ) );

		QPoint c( m_picker->width() / 2, m_picker->height() / 2 );

		QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( m_picker.data(), &me );
		QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
		QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

		QVERIFY( m_picker->currentIndex() == 3 );

		int idx = 4;

		for( int i = 0; i < 8; ++i )
		{
			QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
			QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
				Qt::LeftButton, {} );
			QApplication::sendEvent( m_picker.data(), &me );
			QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
			QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

			QVERIFY( m_picker->currentIndex() == idx );

			++idx;

			if( idx == m_data.size() )
				idx = 0;
		}

		QVERIFY( m_picker->currentIndex() == 3 );
	}

private:
	QStringList m_data;
	QSharedPointer< QtMWidgets::Picker > m_picker;
	QFont m_font;
	int m_lineHeight;
	QPoint m_delta;
};

QTEST_MAIN( TestPicker )

#include "main.moc"
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbuttoniconview.h"
#include "mbuttoniconview_p.h"

#include <QPainter>
#include <QTimeLine>

#include "mviewcreator.h"
#include "mbutton.h"
#include "mbutton_p.h"
#include "mlabel.h"
#include "mtheme.h"

MButtonIconViewPrivate::MButtonIconViewPrivate()
    : timelineShrink(new QTimeLine())
    , timelineGlow(new QTimeLine())
    , glowCacheKey( 0 )
    , glowRadius( 0 )
{
    timelineShrink->setCurveShape(QTimeLine::EaseInCurve);
    timelineGlow->setCurveShape(QTimeLine::SineCurve);
}

MButtonIconViewPrivate::~MButtonIconViewPrivate()
{
    delete timelineShrink;
    delete timelineGlow;
}

void MButtonIconViewPrivate::drawGlowIcon(QPainter *painter, const QRectF &iconRect) const
{
    Q_Q(const MButtonIconView);

    if (!icon)
        return;

    QRectF glowRect = iconRect;
    QPointF offset(-q->style()->glowRadius(),
                   -q->style()->glowRadius());
    glowRect.translate(offset);
    glowRect.setSize(QSizeF(icon->pixmap->width() + 2 * q->style()->glowRadius(), icon->pixmap->height() + 2 * q->style()->glowRadius()));

    painter->setOpacity(controller->effectiveOpacity() * timelineGlow->currentValue());
    painter->drawImage(glowRect, const_cast<MButtonIconViewPrivate*>(this)->glowIcon(icon->pixmap, q->style()->glowRadius(), q->style()->glowColor()));
}

MButtonIconView::MButtonIconView(MButton *controller) :
    MButtonView(* new MButtonIconViewPrivate, controller)
{
    Q_D(MButtonIconView);

    connect(d->timelineShrink, SIGNAL(valueChanged(qreal)),
            this, SLOT(scaleValueChanged(qreal)));

    connect(d->timelineGlow, SIGNAL(valueChanged(qreal)),
            this, SLOT(glowValueChanged(qreal)));
}

MButtonIconView::~MButtonIconView()
{
}

void MButtonIconView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_D(const MButtonIconView);

    bool scaling = (d->timelineShrink->state() == QTimeLine::Running) || (model()->down());
    bool glowing = (!model()->down()) && (d->timelineGlow->state() == QTimeLine::Running) &&
                   model()->iconVisible();

    if (!scaling && !glowing) {
        MButtonView::drawContents(painter, option);
    } else {
        QRectF iconRect = d->iconRect;

        if (scaling) {
            int w = size().width() / 2;
            int h = size().height() / 2;
            painter->translate(QPoint(w, h));

            // update iconRect and textRect for translate
            QPointF offset(-w, -h);
            iconRect.translate(offset);

            // Scales the painting if zoom timeline running or button pressed
            float value = d->timelineShrink->currentValue();
            float s = 1.0f - style()->shrinkFactor() * value;
            painter->setRenderHint(QPainter::SmoothPixmapTransform);
            painter->scale(s, s);
        }

        // draw glow icon
        if (glowing)
            d->drawGlowIcon(painter, iconRect);

        painter->setOpacity(d->controller->effectiveOpacity());

        drawIcon(painter, iconRect);
    }
}

void MButtonIconView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    MButtonView::drawBackground(painter, option);
}

void MButtonIconView::applyStyle()
{
    Q_D(MButtonIconView);

    MButtonView::applyStyle();

    d->timelineShrink->setDuration(style()->shrinkDuration());
    d->timelineGlow->setDuration(style()->glowDuration());
}

void MButtonIconView::scaleValueChanged(qreal value)
{
    Q_UNUSED(value);
    Q_D(MButtonIconView);

    float s = 1.0f - style()->shrinkFactor() * value;
    if (s != 1.0f)
        d->label->setTransformOriginPoint(d->label->size().width() / 2.0f, d->label->size().height() / 2.0f);
    else
        d->label->setTransformOriginPoint(0.0f, 0.0f);
    d->label->setScale(s);

    update();
}

void MButtonIconView::glowValueChanged(qreal value)
{
    Q_UNUSED(value);
    update();
}

void MButtonIconView::updateData(const QList<const char *>& modifications)
{
    Q_D(MButtonIconView);

    MButtonView::updateData(modifications);
    const char *member;
    foreach(member, modifications) {
        if (member == MButtonModel::Down) {
            //start shrinking animation
            d->timelineShrink->setDirection(model()->down() ? QTimeLine::Forward : QTimeLine::Backward);
            if (style()->shrinkDuration() > 0 && d->timelineShrink->state() == QTimeLine::NotRunning)
                d->timelineShrink->start();

            //start glowing if the button was released
            if (!model()->down()) {
                if (d->timelineGlow->state() == QTimeLine::Running)
                    d->timelineGlow->setCurrentTime(0);
                else if (style()->glowDuration() > 0) {
                    d->timelineGlow->start();
                }
            }
        }
    }
}

M_REGISTER_VIEW_NEW(MButtonIconView, MButton)

////////////////////////////////////////////////////
// glow generation

// blur image
static void blur(const QImage *source, QImage *destination, int radius, const QColor &color)
{
    QSize s = destination->size();
    int width = s.width();
    int height = s.height();

    QImage tmp(s, QImage::Format_ARGB32);

    qreal GlowColorR  = color.redF();
    qreal GlowColorG  = color.greenF();
    qreal GlowColorB  = color.blueF();

    int total, alpha;
    QRgb *buffer;

    // horizontal
    for (int y = 0; y < height; ++y) {
        total = 0;
        buffer = (QRgb *)tmp.scanLine(y);

        // Process entire window for first pixel
        //for (int kx = -radius; kx <= radius; ++kx)
        if (y >= radius && y < height - radius) {
            total = qAlpha(source->pixel(0, y - radius));

            alpha = total / (radius * 2 + 1);
            *buffer = qRgba(0, 0, 0, alpha);
            buffer++;

            // Subsequent pixels just update window total
            for (int x = 1; x < width; ++x) {
                // Subtract pixel leaving window
                if (x - radius * 2 - 1 >= 0) // && x - radius*2 < source->size().width())
                    total -= qAlpha(source->pixel(x - radius * 2 - 1, y - radius));

                // Add pixel entering window
                if (x > 0 && x < source->size().width())
                    total += qAlpha(source->pixel(x, y - radius));

                alpha = total / (radius * 2 + 1);

                *buffer = qRgba(0, 0, 0, alpha);
                buffer++;
            }
        } else {
            for (int x = 0; x < width; ++x) {
                *buffer = qRgba(0, 0, 0, 0);
                buffer++;
            }
        }
    }

    qreal r, g, b, a;
    // vertical
    for (int x = 0; x < width; ++x) {
        total = 0;

        // Process entire window for first pixel
        //for (int ky = -radius; ky <= radius; ++ky)
        for (int ky = 0; ky <= radius; ++ky)
            total += qAlpha(tmp.pixel(x, ky));

        alpha = total / (radius * 2 + 1);

        r = alpha * GlowColorR * 2;
        g = alpha * GlowColorG * 2;
        b = alpha * GlowColorB * 2;
        a = alpha * 2;
        if (r > 255) r = 255;
        if (g > 255) g = 255;
        if (b > 255) b = 255;
        if (a > 255) a = 255;

        buffer = (QRgb *)destination->scanLine(0);
        *(buffer + x) = qRgba(r, g, b, a);

        // Subsequent pixels just update window total
        for (int y = 1; y < height; ++y) {
            // Subtract pixel leaving window
            if (y - radius - 1 >= 0)
                total -= qAlpha(tmp.pixel(x, y - radius - 1));

            // Add pixel entering window
            if (y + radius < height)
                total += qAlpha(tmp.pixel(x, y + radius));

            alpha = total / (radius * 2 + 1);

            r = alpha * GlowColorR * 2;
            g = alpha * GlowColorG * 2;
            b = alpha * GlowColorB * 2;
            a = alpha * 2;
            if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;
            if (a > 255) a = 255;

            buffer = (QRgb *)destination->scanLine(y);
            *(buffer + x) = qRgba(r, g, b, a);
        }
    }
}

// TODO: to be removed when the glow pixmap generation is moved to application side as an effect.
const QImage& MButtonIconViewPrivate::glowIcon(const QPixmap* pm, int radius, const QColor &color)
{
    if( glowImage.isNull() || glowCacheKey != pm->cacheKey() || glowRadius != radius || glowColor != color ) {
        QImage image = pm->toImage();
        glowImage = QImage(pm->width() + 2 * radius, pm->height() + 2 * radius, QImage::Format_ARGB32);
        blur(&image, &glowImage, radius, color);
        glowCacheKey = pm->cacheKey();
        glowRadius = radius;
        glowColor = color;
    }
    return glowImage;
}
<commit_msg>Changes: checking before to apply the style that duration for QTimeLine::setDuration is >0 RevBy: Daniel d'Andrada Details: QTimeLine::setDuration() needs that the parameter is >0. Some styles come with 0 as nothing/default and a warning is printed when the app is executed. This fix avoid to invoke the function with a wrong value (<=0)<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbuttoniconview.h"
#include "mbuttoniconview_p.h"

#include <QPainter>
#include <QTimeLine>

#include "mviewcreator.h"
#include "mbutton.h"
#include "mbutton_p.h"
#include "mlabel.h"
#include "mtheme.h"

MButtonIconViewPrivate::MButtonIconViewPrivate()
    : timelineShrink(new QTimeLine())
    , timelineGlow(new QTimeLine())
    , glowCacheKey( 0 )
    , glowRadius( 0 )
{
    timelineShrink->setCurveShape(QTimeLine::EaseInCurve);
    timelineGlow->setCurveShape(QTimeLine::SineCurve);
}

MButtonIconViewPrivate::~MButtonIconViewPrivate()
{
    delete timelineShrink;
    delete timelineGlow;
}

void MButtonIconViewPrivate::drawGlowIcon(QPainter *painter, const QRectF &iconRect) const
{
    Q_Q(const MButtonIconView);

    if (!icon)
        return;

    QRectF glowRect = iconRect;
    QPointF offset(-q->style()->glowRadius(),
                   -q->style()->glowRadius());
    glowRect.translate(offset);
    glowRect.setSize(QSizeF(icon->pixmap->width() + 2 * q->style()->glowRadius(), icon->pixmap->height() + 2 * q->style()->glowRadius()));

    painter->setOpacity(controller->effectiveOpacity() * timelineGlow->currentValue());
    painter->drawImage(glowRect, const_cast<MButtonIconViewPrivate*>(this)->glowIcon(icon->pixmap, q->style()->glowRadius(), q->style()->glowColor()));
}

MButtonIconView::MButtonIconView(MButton *controller) :
    MButtonView(* new MButtonIconViewPrivate, controller)
{
    Q_D(MButtonIconView);

    connect(d->timelineShrink, SIGNAL(valueChanged(qreal)),
            this, SLOT(scaleValueChanged(qreal)));

    connect(d->timelineGlow, SIGNAL(valueChanged(qreal)),
            this, SLOT(glowValueChanged(qreal)));
}

MButtonIconView::~MButtonIconView()
{
}

void MButtonIconView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_D(const MButtonIconView);

    bool scaling = (d->timelineShrink->state() == QTimeLine::Running) || (model()->down());
    bool glowing = (!model()->down()) && (d->timelineGlow->state() == QTimeLine::Running) &&
                   model()->iconVisible();

    if (!scaling && !glowing) {
        MButtonView::drawContents(painter, option);
    } else {
        QRectF iconRect = d->iconRect;

        if (scaling) {
            int w = size().width() / 2;
            int h = size().height() / 2;
            painter->translate(QPoint(w, h));

            // update iconRect and textRect for translate
            QPointF offset(-w, -h);
            iconRect.translate(offset);

            // Scales the painting if zoom timeline running or button pressed
            float value = d->timelineShrink->currentValue();
            float s = 1.0f - style()->shrinkFactor() * value;
            painter->setRenderHint(QPainter::SmoothPixmapTransform);
            painter->scale(s, s);
        }

        // draw glow icon
        if (glowing)
            d->drawGlowIcon(painter, iconRect);

        painter->setOpacity(d->controller->effectiveOpacity());

        drawIcon(painter, iconRect);
    }
}

void MButtonIconView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    MButtonView::drawBackground(painter, option);
}

void MButtonIconView::applyStyle()
{
    Q_D(MButtonIconView);

    MButtonView::applyStyle();

    if (style()->shrinkDuration() > 0)
        d->timelineShrink->setDuration(style()->shrinkDuration());

    if (style()->glowDuration() > 0)
        d->timelineGlow->setDuration(style()->glowDuration());
}

void MButtonIconView::scaleValueChanged(qreal value)
{
    Q_UNUSED(value);
    Q_D(MButtonIconView);

    float s = 1.0f - style()->shrinkFactor() * value;
    if (s != 1.0f)
        d->label->setTransformOriginPoint(d->label->size().width() / 2.0f, d->label->size().height() / 2.0f);
    else
        d->label->setTransformOriginPoint(0.0f, 0.0f);
    d->label->setScale(s);

    update();
}

void MButtonIconView::glowValueChanged(qreal value)
{
    Q_UNUSED(value);
    update();
}

void MButtonIconView::updateData(const QList<const char *>& modifications)
{
    Q_D(MButtonIconView);

    MButtonView::updateData(modifications);
    const char *member;
    foreach(member, modifications) {
        if (member == MButtonModel::Down) {
            //start shrinking animation
            d->timelineShrink->setDirection(model()->down() ? QTimeLine::Forward : QTimeLine::Backward);
            if (style()->shrinkDuration() > 0 && d->timelineShrink->state() == QTimeLine::NotRunning)
                d->timelineShrink->start();

            //start glowing if the button was released
            if (!model()->down()) {
                if (d->timelineGlow->state() == QTimeLine::Running)
                    d->timelineGlow->setCurrentTime(0);
                else if (style()->glowDuration() > 0) {
                    d->timelineGlow->start();
                }
            }
        }
    }
}

M_REGISTER_VIEW_NEW(MButtonIconView, MButton)

////////////////////////////////////////////////////
// glow generation

// blur image
static void blur(const QImage *source, QImage *destination, int radius, const QColor &color)
{
    QSize s = destination->size();
    int width = s.width();
    int height = s.height();

    QImage tmp(s, QImage::Format_ARGB32);

    qreal GlowColorR  = color.redF();
    qreal GlowColorG  = color.greenF();
    qreal GlowColorB  = color.blueF();

    int total, alpha;
    QRgb *buffer;

    // horizontal
    for (int y = 0; y < height; ++y) {
        total = 0;
        buffer = (QRgb *)tmp.scanLine(y);

        // Process entire window for first pixel
        //for (int kx = -radius; kx <= radius; ++kx)
        if (y >= radius && y < height - radius) {
            total = qAlpha(source->pixel(0, y - radius));

            alpha = total / (radius * 2 + 1);
            *buffer = qRgba(0, 0, 0, alpha);
            buffer++;

            // Subsequent pixels just update window total
            for (int x = 1; x < width; ++x) {
                // Subtract pixel leaving window
                if (x - radius * 2 - 1 >= 0) // && x - radius*2 < source->size().width())
                    total -= qAlpha(source->pixel(x - radius * 2 - 1, y - radius));

                // Add pixel entering window
                if (x > 0 && x < source->size().width())
                    total += qAlpha(source->pixel(x, y - radius));

                alpha = total / (radius * 2 + 1);

                *buffer = qRgba(0, 0, 0, alpha);
                buffer++;
            }
        } else {
            for (int x = 0; x < width; ++x) {
                *buffer = qRgba(0, 0, 0, 0);
                buffer++;
            }
        }
    }

    qreal r, g, b, a;
    // vertical
    for (int x = 0; x < width; ++x) {
        total = 0;

        // Process entire window for first pixel
        //for (int ky = -radius; ky <= radius; ++ky)
        for (int ky = 0; ky <= radius; ++ky)
            total += qAlpha(tmp.pixel(x, ky));

        alpha = total / (radius * 2 + 1);

        r = alpha * GlowColorR * 2;
        g = alpha * GlowColorG * 2;
        b = alpha * GlowColorB * 2;
        a = alpha * 2;
        if (r > 255) r = 255;
        if (g > 255) g = 255;
        if (b > 255) b = 255;
        if (a > 255) a = 255;

        buffer = (QRgb *)destination->scanLine(0);
        *(buffer + x) = qRgba(r, g, b, a);

        // Subsequent pixels just update window total
        for (int y = 1; y < height; ++y) {
            // Subtract pixel leaving window
            if (y - radius - 1 >= 0)
                total -= qAlpha(tmp.pixel(x, y - radius - 1));

            // Add pixel entering window
            if (y + radius < height)
                total += qAlpha(tmp.pixel(x, y + radius));

            alpha = total / (radius * 2 + 1);

            r = alpha * GlowColorR * 2;
            g = alpha * GlowColorG * 2;
            b = alpha * GlowColorB * 2;
            a = alpha * 2;
            if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;
            if (a > 255) a = 255;

            buffer = (QRgb *)destination->scanLine(y);
            *(buffer + x) = qRgba(r, g, b, a);
        }
    }
}

// TODO: to be removed when the glow pixmap generation is moved to application side as an effect.
const QImage& MButtonIconViewPrivate::glowIcon(const QPixmap* pm, int radius, const QColor &color)
{
    if( glowImage.isNull() || glowCacheKey != pm->cacheKey() || glowRadius != radius || glowColor != color ) {
        QImage image = pm->toImage();
        glowImage = QImage(pm->width() + 2 * radius, pm->height() + 2 * radius, QImage::Format_ARGB32);
        blur(&image, &glowImage, radius, color);
        glowCacheKey = pm->cacheKey();
        glowRadius = radius;
        glowColor = color;
    }
    return glowImage;
}
<|endoftext|>


<commit_before>#include "../lib.hpp"
#include <iostream>

using namespace std;

int main() {
	cout <<
    cout << "Test begin!" << endl;
    // cout << "file_put_contents" << endl;
    // file_put_contents("tmp", "Hello World");
    cout << "ls(\"db\")" << endl;
    cout << ls("db") << endl;
    // cout << "rm_r(\"tmp\")" << endl;
    // rm_r("tmp/");
    cout << "mkpath" << endl;
    mkpath("a/b/c/d/e/xxx");
    cout << "pathExists(\"db/\")" << endl;
    cout << pathExists("db") << endl;
    cout << "pathExists(\"README.md\")" << endl;
    cout << pathExists("README.md") << endl;
    cout << "pathExists(\"notExistFile\")" << endl;
    cout << pathExists("notExistFile") << endl;
    return 0;
}
<commit_msg>Update test.cpp<commit_after>#include "../lib.hpp"
#include <iostream>

using namespace std;

int main() {
	cout <<
    cout << "Test begin!" << endl;
    // cout << "file_put_contents" << endl;
    // file_put_contents("tmp", "Hello World");
    cout << "ls(\"db\")" << endl;
    cout << ls("db") << endl;
    // cout << "rm_r(\"tmp\")" << endl;
    // rm_r("tmp/");
    cout << "mkpath" << endl;
    // mkpath("a/b/c/d/e/xxx");
    cout << "pathExists(\"db\")" << endl;
    cout << pathExists("db") << endl;
    cout << "pathExists(\"README.md\")" << endl;
    cout << pathExists("README.md") << endl;
    cout << "pathExists(\"notExistFile\")" << endl;
    cout << pathExists("notExistFile") << endl;
    return 0;
}
<|endoftext|>


<commit_before>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <cmath>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    if(id >= next_id)
    {
        next_id = id + 1;
    }

    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto time_to_use = genome.time_to_examine(board, clock);

    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         Math::lose_score,
                                         board.whose_turn(),
                                         0,
                                         ""};
    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::win_score,
                                        board.whose_turn(),
                                        0,
                                        ""};

    auto result = search_game_tree(board,
                                   time_to_use,
                                   clock,
                                   0,
                                   alpha_start,
                                   beta_start);
    if(result.depth > 0)
    {
        board.add_commentary_to_next_move(result.commentary);
    }
    return result.move;
}

bool better_than(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b, Color perspective)
{
    auto scoreA = a.corrected_score(perspective);
    auto scoreB = b.corrected_score(perspective);

    if(scoreA > scoreB)
    {
        return true;
    }

    if(scoreA < scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    // Shorter path to winning is better
    if(scoreA == Math::win_score)
    {
        return a.depth < b.depth;
    }

    // Longer path to losing is better
    if(scoreA == Math::lose_score)
    {
        return a.depth > b.depth;
    }

    return false;
}

bool operator==(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b)
{
    auto scoreA = a.corrected_score(WHITE);
    auto scoreB = b.corrected_score(WHITE);

    if(scoreA != scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    if(std::abs(scoreA) == Math::win_score)
    {
        return a.depth == b.depth;
    }

    return true;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   const double time_to_examine,
                                                   const Clock& clock,
                                                   const int depth,
                                                   Game_Tree_Node_Result alpha,
                                                   Game_Tree_Node_Result beta) const
{
    auto perspective = board.whose_turn();
    auto time_start = clock.time_left(clock.running_for());
    int moves_examined = 0;

    Game_Tree_Node_Result best_result = {board.all_legal_moves().front(),
                                         Math::lose_score,
                                         perspective,
                                         depth,
                                         ""};

    for(const auto& move : board.all_legal_moves())
    {
        int moves_left = board.all_legal_moves().size() - moves_examined;
        if(depth > 0 && clock.time_left(clock.running_for()) < time_to_examine/moves_left)
        {
            return best_result;
        }

        auto next_board = board;

        try
        {
            next_board.submit_move(move);
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();

            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draws get scored like any other board position
        }

        Game_Tree_Node_Result result;
        double time_left = time_to_examine - (time_start - clock.time_left(clock.running_for()));
        double time_alloted_for_this_move = time_left/moves_left;
        auto minimum_time_to_recurse = genome.minimum_time_to_recurse(next_board);

        bool recurse;
        if(next_board.game_has_ended())
        {
            recurse = false;
        }
        else if(next_board.all_legal_moves().size() == 1)
        {
            recurse = true;
        }
        else if(time_alloted_for_this_move < minimum_time_to_recurse)
        {
            recurse = false;
        }
        else
        {
            recurse = genome.good_enough_to_examine(board, next_board, perspective);
        }

        if(recurse)
        {
            result = search_game_tree(next_board,
                                      time_alloted_for_this_move,
                                      clock,
                                      depth + 1,
                                      beta,
                                      alpha);

            // Update last result with this game tree node's data
            result.move = move;
            result.commentary = next_board.get_game_record().back()
                                        + " "
                                        + result.commentary;
        }
        else
        {
            // Record immediate result without looking ahead further
            result = {move,
                      genome.evaluate(next_board, perspective),
                      perspective,
                      depth,
                      next_board.get_game_record().back()};
        }

        if(better_than(result, best_result, perspective))
        {
            best_result = result;
            if(better_than(best_result, alpha, perspective))
            {
                alpha = best_result;
                if(better_than(alpha, beta, perspective) || alpha == beta)
                {
                    break;
                }
            }
        }

        ++moves_examined;
    }

    return best_result;
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

std::string Genetic_AI::author() const
{
    return "Mark Harrison";
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<commit_msg>Simpler time management for Genetic AI<commit_after>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <cmath>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    if(id >= next_id)
    {
        next_id = id + 1;
    }

    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto time_to_use = genome.time_to_examine(board, clock);

    Game_Tree_Node_Result alpha_start = {Complete_Move(),
                                         Math::lose_score,
                                         board.whose_turn(),
                                         0,
                                         ""};
    Game_Tree_Node_Result beta_start = {Complete_Move(),
                                        Math::win_score,
                                        board.whose_turn(),
                                        0,
                                        ""};

    auto result = search_game_tree(board,
                                   time_to_use,
                                   clock,
                                   0,
                                   alpha_start,
                                   beta_start);
    if(result.depth > 0)
    {
        board.add_commentary_to_next_move(result.commentary);
    }
    return result.move;
}

bool better_than(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b, Color perspective)
{
    auto scoreA = a.corrected_score(perspective);
    auto scoreB = b.corrected_score(perspective);

    if(scoreA > scoreB)
    {
        return true;
    }

    if(scoreA < scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    // Shorter path to winning is better
    if(scoreA == Math::win_score)
    {
        return a.depth < b.depth;
    }

    // Longer path to losing is better
    if(scoreA == Math::lose_score)
    {
        return a.depth > b.depth;
    }

    return false;
}

bool operator==(const Game_Tree_Node_Result& a, const Game_Tree_Node_Result& b)
{
    auto scoreA = a.corrected_score(WHITE);
    auto scoreB = b.corrected_score(WHITE);

    if(scoreA != scoreB)
    {
        return false;
    }

    // scoreA == scoreB

    if(std::abs(scoreA) == Math::win_score)
    {
        return a.depth == b.depth;
    }

    return true;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   const double time_to_examine,
                                                   const Clock& clock,
                                                   const int depth,
                                                   Game_Tree_Node_Result alpha,
                                                   Game_Tree_Node_Result beta) const
{
    auto perspective = board.whose_turn();
    auto time_start = clock.time_left(clock.running_for());
    int moves_examined = 0;

    Game_Tree_Node_Result best_result = {board.all_legal_moves().front(),
                                         Math::lose_score,
                                         perspective,
                                         depth,
                                         ""};

    const auto current_legal_moves_count = board.all_legal_moves().size();
    for(const auto& move : board.all_legal_moves())
    {
        auto next_board = board;

        try
        {
            next_board.submit_move(move);
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();

            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draws get scored like any other board position
        }

        Game_Tree_Node_Result result;
        int moves_left = current_legal_moves_count - moves_examined;
        double time_left = time_to_examine - (time_start - clock.time_left(clock.running_for()));
        double time_alloted_for_this_move = time_left/moves_left;

        bool recurse;
        if(next_board.game_has_ended())
        {
            recurse = false;
        }
        else if(next_board.all_legal_moves().size() == 1)
        {
            recurse = true;
        }
        else if(time_alloted_for_this_move < genome.minimum_time_to_recurse(next_board))
        {
            recurse = false;
        }
        else
        {
            recurse = genome.good_enough_to_examine(board, next_board, perspective);
        }

        if(recurse)
        {
            result = search_game_tree(next_board,
                                      time_alloted_for_this_move,
                                      clock,
                                      depth + 1,
                                      beta,
                                      alpha);

            // Update last result with this game tree node's data
            result.move = move;
            result.commentary = next_board.get_game_record().back()
                                        + " "
                                        + result.commentary;
        }
        else
        {
            // Record immediate result without looking ahead further
            result = {move,
                      genome.evaluate(next_board, perspective),
                      perspective,
                      depth,
                      next_board.get_game_record().back()};
        }

        if(better_than(result, best_result, perspective))
        {
            best_result = result;
            if(better_than(best_result, alpha, perspective))
            {
                alpha = best_result;
                if(better_than(alpha, beta, perspective) || alpha == beta)
                {
                    break;
                }
            }
        }

        ++moves_examined;
    }

    return best_result;
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

std::string Genetic_AI::author() const
{
    return "Mark Harrison";
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<|endoftext|>


<commit_before>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "../xpd/xpd.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

using namespace xpd;

class instance_test : public instance
{
public:
    instance_test(const size_t index) : m_index(index)
    {
        m_vecteurs = new float*[2];
        m_vecteurs[0] = new float[128];
        m_vecteurs[1] = new float[128];
    }

    ~instance_test()
    {
        delete [] m_vecteurs[0];
        delete [] m_vecteurs[1];
        delete [] m_vecteurs;
    }

    void receive(console::post post) xpd_final
    {
        if(post.type == console::fatal)
        {
            std::cout << "instace " << m_index << " (fatal) : " << post.text << "\n";
        }
        else if(post.type == console::error)
        {
            std::cout << "instace " << m_index << " (error) : " << post.text << "\n";
        }
        else if(post.type == console::normal)
        {
            std::cout << "instace " << m_index << " (normal) : " << post.text << "\n";
        }
        std::cout << "instace " << m_index << " (log) : " << post.text << "\n";
    }

    void receive(tie tie, symbol s, std::vector<atom> atoms) xpd_final
    {
        std::cout << "instace " << m_index << s.name() << " :";
        for(size_t i = 0; i < atoms.size(); ++i)
        {
            if(atoms[i].type() == atom::float_t)
            {
                std::cout << " " << float(atoms[i]);
            }
            else if(atoms[i].type() == atom::symbol_t)
            {
                std::cout << " " << symbol(atoms[i]).name();
            }
            else
            {
                std::cout << " null";
            }
        }
        std::cout << "\n";
    }

    void receive(midi::event event)
    {
        std::cout << "instace " << m_index << "midi :";
        std::cout << "\n";
    }
    size_t const m_index;
    float** m_vecteurs;
};

static char* test_get_patch_folder(char* location)
{
    size_t size, i;
    if(location)
    {
        size = strlen(location);
        for(i = 0; i < size; ++i)
        {
            if(strncmp(location+i, "/build/", 7) == 0)
            {
                memset(location+i+7, '\0', size-i);
                sprintf(location+i+7, "../test/");
                return location;
            }
            if(strncmp(location+i, "/zpd/", 5) == 0)
            {
                memset(location+i+5, '\0', size-i);
                sprintf(location+i+5, "/test/");
                return location;
            }
            if(strncmp(location+i, "/test/", 6) == 0)
            {
                memset(location+i+6, '\0', size-i);
                return location;
            }
        }
    }
    return NULL;
}

int main(int argc, char** argv)
{
    instance_test *inst1, *inst2;
    patch *p1, *p2;
    try
    {
        inst1 = new instance_test(1);
    }
    catch(...)
    {
        std::cout << "error can't allocate instance";
        return -1;
    }
    try
    {
        inst2 = new instance_test(2);
    }
    catch(...)
    {
        std::cout << "error can't allocate instance";
        return -1;
    }

    std::cout << "version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    environment::searchpath_add(test_get_patch_folder(argv[0]));

    p1 = inst1->load("test.pd", "");
    p2 = inst2->load("test.pd", "");
    if(p1 && p2)
    {
        inst1->prepare(2, 2, 44100, 64);
        inst2->prepare(1, 1, 44100, 128);

        for(size_t i = 0; i < 8; ++i)
        {
            inst1->perform(64, 2, const_cast<float const **>(inst1->m_vecteurs), 2, inst1->m_vecteurs);
            inst2->perform(128, 1, const_cast<float const **>(inst1->m_vecteurs), 1, inst1->m_vecteurs);
        }

        inst1->release();
        inst2->release();

        inst1->close(*p1);
        inst2->close(*p2);
    }
    delete inst1;
    delete inst2;
    return 0;
}<commit_msg>avec bang<commit_after>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "../xpd/xpd.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

using namespace xpd;

class instance_test : public instance
{
public:
    instance_test(const size_t index) : m_index(index)
    {
        m_vecteurs = new float*[2];
        m_vecteurs[0] = new float[128];
        m_vecteurs[1] = new float[128];
    }

    ~instance_test()
    {
        delete [] m_vecteurs[0];
        delete [] m_vecteurs[1];
        delete [] m_vecteurs;
    }

    void receive(console::post post) xpd_final
    {
        if(post.type == console::fatal)
        {
            std::cout << "instace " << m_index << " (fatal) : " << post.text << "\n";
        }
        else if(post.type == console::error)
        {
            std::cout << "instace " << m_index << " (error) : " << post.text << "\n";
        }
        else if(post.type == console::normal)
        {
            std::cout << "instace " << m_index << " (normal) : " << post.text << "\n";
        }
        std::cout << "instace " << m_index << " (log) : " << post.text << "\n";
    }

    void receive(tie tie, symbol s, std::vector<atom> atoms) xpd_final
    {
        std::cout << "instace " << m_index << s.name() << " :";
        for(size_t i = 0; i < atoms.size(); ++i)
        {
            if(atoms[i].type() == atom::float_t)
            {
                std::cout << " " << float(atoms[i]);
            }
            else if(atoms[i].type() == atom::symbol_t)
            {
                std::cout << " " << symbol(atoms[i]).name();
            }
            else
            {
                std::cout << " null";
            }
        }
        std::cout << "\n";
    }

    void receive(midi::event event)
    {
        std::cout << "instace " << m_index << "midi :";
        std::cout << "\n";
    }
    size_t const m_index;
    float** m_vecteurs;
};

static char* test_get_patch_folder(char* location)
{
    size_t size, i;
    if(location)
    {
        size = strlen(location);
        for(i = 0; i < size; ++i)
        {
            if(strncmp(location+i, "/build/", 7) == 0)
            {
                memset(location+i+7, '\0', size-i);
                sprintf(location+i+7, "../test/");
                return location;
            }
            if(strncmp(location+i, "/zpd/", 5) == 0)
            {
                memset(location+i+5, '\0', size-i);
                sprintf(location+i+5, "/test/");
                return location;
            }
            if(strncmp(location+i, "/test/", 6) == 0)
            {
                memset(location+i+6, '\0', size-i);
                return location;
            }
        }
    }
    return NULL;
}

int main(int argc, char** argv)
{
    instance_test *inst1, *inst2;
    patch *p1, *p2;
    try
    {
        inst1 = new instance_test(1);
    }
    catch(...)
    {
        std::cout << "error can't allocate instance";
        return -1;
    }
    try
    {
        inst2 = new instance_test(2);
    }
    catch(...)
    {
        std::cout << "error can't allocate instance";
        return -1;
    }

    std::cout << "version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    environment::searchpath_add(test_get_patch_folder(argv[0]));

    p1 = inst1->load("test.pd", "");
    p2 = inst2->load("test.pd", "");
    if(p1 && p2)
    {
        inst1->prepare(2, 2, 44100, 64);
        inst2->prepare(1, 1, 44100, 128);

        for(size_t i = 0; i < 8; ++i)
        {
            char truc1[512];
            sprintf(truc1, "%i", int(p1->unique_id()));
            inst1->send(tie(std::string(truc1) + "-bang"), symbol("bang"), std::vector<atom>());
            inst1->perform(64, 2, const_cast<float const **>(inst1->m_vecteurs), 2, inst1->m_vecteurs);
            char truc2[512];
            sprintf(truc2, "%i", int(p1->unique_id()));
            inst1->send(tie(std::string(truc2) + "-bang"), symbol("bang"), std::vector<atom>());
            inst2->perform(128, 1, const_cast<float const **>(inst1->m_vecteurs), 1, inst1->m_vecteurs);
        }

        inst1->release();
        inst2->release();

        inst1->close(*p1);
        inst2->close(*p2);
    }
    delete inst1;
    delete inst2;
    return 0;
}<|endoftext|>