/*********************************************************************/
/*	EESchema - edition des librairies: Edition des champs ( Fields ) */
/*********************************************************************/

/*	Fichier fieldedi.cpp	*/

#include "fctsys.h"
#include "gr_basic.h"

#include "common.h"
#include "program.h"
#include "libcmp.h"
#include "general.h"

#include "protos.h"

#include "wx/spinctrl.h"

static char* PanelText[] =
{
    "Ref",  /* Champ Reference of part, i.e. "IC21" */
    "Name", /* Champ Value of part, i.e. "3.3K" */
    "Fld1",
    "Fld2",
    "Fld3",
    "Fld4",
    "Fld5",
    "Fld6",
    "Fld7",
    "Fld8",
    "Pcb",              /* Champ Name Module PCB, i.e. "16DIP300" */
    "Sheet"             /* Champ Name Schema component, i.e. "cnt16.sch" */
};


/* Routines locales */
static void     MoveField( wxDC* DC, int flag );
static char*    PrefixText( LibraryEntryStruct* LibEntry, int Unit );

/* Variables locales */

extern int     CurrentUnit;
static wxPoint StartCursor;

/* Classe de la frame des propri�t�s d'un composant en librairie */

enum id_libedit {
    ID_LIBEDIT_NOTEBOOK = 3200,
    ID_PANEL_BASIC,
    ID_PANEL_ALIAS,
    ID_PANEL_REFERENCE,
    ID_PANEL_VALUE,
    ID_PANEL_FIELD1,
    ID_PANEL_FIELD2,
    ID_PANEL_FIELD3,
    ID_PANEL_FIELD4,
    ID_PANEL_FIELD5,
    ID_PANEL_FIELD6,
    ID_PANEL_FIELD7,
    ID_PANEL_FIELD8,
    ID_PANEL_MODULEPCB,
    ID_PANEL_SUBSCHEMATIC,
    ID_CLOSE_PART_PROPERTIES,
    ID_ACCEPT_PART_PROPERTIES,
    ID_ADD_ALIAS,
    ID_DELETE_ONE_ALIAS,
    ID_DELETE_ALL_ALIAS
};


/************************************/
/* class WinEDA_PartPropertiesFrame */
/************************************/

class WinEDA_PartPropertiesFrame : public wxDialog
{
private:

    WinEDA_LibeditFrame*    m_Parent;
    wxNotebook*             m_NoteBook;
    wxListBox*              PartAliasList;
    wxPanel*                PanelBasic;
    wxPanel*                PanelAlias;
    wxPanel*                PanelDoc;
    wxPanel*                PanelField[NUMBER_OF_FIELDS];

    wxCheckBox*             AsConvertButt;

    wxCheckBox*             ShowFieldText[NUMBER_OF_FIELDS];
    wxCheckBox*             VorientFieldText[NUMBER_OF_FIELDS];
    wxCheckBox*             ShowPinNumButt;
    wxCheckBox*             ShowPinNameButt;
    wxCheckBox*             PinsNameInsideButt;
    wxSpinCtrl*             SelNumberOfUnits;
    wxSpinCtrl*             m_SetSkew;

    WinEDA_GraphicTextCtrl* FieldTextCtrl[NUMBER_OF_FIELDS];
    WinEDA_PositionCtrl*    FieldPosition[NUMBER_OF_FIELDS];
    int FieldFlags[NUMBER_OF_FIELDS];
    int FieldOrient[NUMBER_OF_FIELDS];
    WinEDA_EnterText*       NewDoc;
    WinEDA_EnterText*       NewDocfile;
    WinEDA_EnterText*       NewKeywords;
    ListOfAliasStruct*      AliasListCopy;


public:

    // Constructor and destructor
    WinEDA_PartPropertiesFrame( WinEDA_LibeditFrame * parent, wxPoint & pos );
    ~WinEDA_PartPropertiesFrame()
    {
        if( AliasListCopy )
            AliasListCopy->FreeList();
    };

private:
    void    PartPropertiesAccept( wxCommandEvent& event );
    void    DeleteAllAliasOfPart();
    void    DeleteAliasOfPart();
    void    AddAliasOfPart();
    bool    ChangeNbUnitsPerPackage( int newUnit );
    bool    SetUnsetConvert();

    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE( WinEDA_PartPropertiesFrame, wxDialog )
EVT_BUTTON( ID_ACCEPT_PART_PROPERTIES, WinEDA_PartPropertiesFrame::PartPropertiesAccept )
EVT_BUTTON( ID_CLOSE_PART_PROPERTIES, WinEDA_PartPropertiesFrame::Close )
EVT_BUTTON( ID_ADD_ALIAS, WinEDA_PartPropertiesFrame::AddAliasOfPart )
EVT_BUTTON( ID_DELETE_ONE_ALIAS, WinEDA_PartPropertiesFrame::DeleteAliasOfPart )
EVT_BUTTON( ID_DELETE_ALL_ALIAS, WinEDA_PartPropertiesFrame::DeleteAllAliasOfPart )
END_EVENT_TABLE()


void InstallLibeditFrame( WinEDA_LibeditFrame* parent, wxPoint& pos )
{
    WinEDA_PartPropertiesFrame* frame = new WinEDA_PartPropertiesFrame( parent, pos );

    frame->ShowModal(); frame->Destroy();
}


WinEDA_PartPropertiesFrame::WinEDA_PartPropertiesFrame( WinEDA_LibeditFrame* parent,
                                                        wxPoint& framepos ) :
    wxDialog( parent, -1, _( "Componant properties" ), framepos, wxSize( 320, 300 ),
              wxDEFAULT_DIALOG_STYLE | FLOAT_ON_PARENT )
{
    wxPoint pos;
    wxLayoutConstraints* c;

    m_Parent = parent;

    SetAutoLayout( TRUE );

    Doc[0] = 0; Docfile[0] = 0; Keywords[0] = 0;
    AliasListCopy = NULL;

    for( int ii = 0; ii < NUMBER_OF_FIELDS; ii++ )
    {
        FieldFlags[ii] = 0;
    }

    if( CurrentLibEntry )
    {
        if( ListAlias )
            AliasListCopy = ListAlias->DupList();

        if( CurrentLibEntry->Doc )
            strncpy( Doc, CurrentLibEntry->Doc, 256 );
        if( CurrentLibEntry->KeyWord )
            strncpy( Keywords, CurrentLibEntry->KeyWord, 256 );
        if( CurrentLibEntry->DocFile )
            strncpy( Docfile, CurrentLibEntry->DocFile, 256 );

        FieldFlags[REFERENCE]  = CurrentLibEntry->m_Prefix.m_Attributs;
        FieldOrient[REFERENCE] = CurrentLibEntry->m_Prefix.m_Orient;

        FieldFlags[VALUE]  = CurrentLibEntry->m_Name.m_Attributs;
        FieldOrient[VALUE] = CurrentLibEntry->m_Name.m_Orient;

        LibDrawField* Field = CurrentLibEntry->Fields;
        while( Field )
        {
            FieldFlags[Field->m_FieldId]  = Field->m_Attributs;
            FieldOrient[Field->m_FieldId] = Field->m_Orient;
            Field = (LibDrawField*) Field->Pnext;
        }
    }

    m_NoteBook = new wxNotebook( this, ID_LIBEDIT_NOTEBOOK );

    c = new wxLayoutConstraints;
    c->left.SameAs( this, wxLeft, 4 );
    c->right.SameAs( this, wxRight, 4 );
    c->top.SameAs( this, wxTop, 4 );
    c->bottom.SameAs( this, wxBottom, 40 );
    m_NoteBook->SetConstraints( c );
    m_NoteBook->SetAutoLayout( TRUE );

    /* Creation des boutons de commande */
    pos.x = 80; pos.y = 240;
    wxButton* Button = new wxButton( this, ID_CLOSE_PART_PROPERTIES,
                                     _( "Close" ), pos );

    c = new wxLayoutConstraints;
    c->left.SameAs( this, wxLeft, 20 );
    c->height.AsIs();
    c->width.AsIs();
    c->bottom.SameAs( this, wxBottom, 5 );
    Button->SetConstraints( c );

    pos.x += Button->GetDefaultSize().x + 10;
    Button = new wxButton( this, ID_ACCEPT_PART_PROPERTIES,
                           _( "Ok" ), pos );

    c = new wxLayoutConstraints;
    c->right.SameAs( this, wxRight, 20 );
    c->height.AsIs();
    c->width.AsIs();
    c->bottom.SameAs( this, wxBottom, 5 );
    Button->SetConstraints( c );

    // Add panel Basic
    PanelBasic = new wxPanel( m_NoteBook, ID_PANEL_BASIC );

    c = new wxLayoutConstraints;
    c->left.SameAs( m_NoteBook, wxLeft );
    c->right.SameAs( m_NoteBook, wxRight );
    c->bottom.SameAs( m_NoteBook, wxBottom );
    PanelBasic->SetConstraints( c );
    m_NoteBook->AddPage( PanelBasic, _( "Options" ), TRUE );

    pos.x = 5; pos.y = 25;
    new                 wxStaticBox( PanelBasic, -1, _( " General : " ), pos, wxSize( 150, 120 ) );

    pos.x = 10; pos.y += 22;
    AsConvertButt = new wxCheckBox( PanelBasic, -1, _( "As Convert" ), pos );

    if( g_AsDeMorgan )
        AsConvertButt->SetValue( TRUE );

    pos.y += 20;
    ShowPinNumButt = new  wxCheckBox( PanelBasic, -1, _( "Show Pin Num" ), pos );

    if( CurrentLibEntry )
    {
        if( CurrentLibEntry->DrawPinNum )
            ShowPinNumButt->SetValue( TRUE );
    }
    else
        ShowPinNumButt->SetValue( TRUE );

    pos.y += 20;
    ShowPinNameButt = new wxCheckBox( PanelBasic, -1, _( "Show Pin Name" ), pos );

    if( CurrentLibEntry )
    {
        if( CurrentLibEntry->DrawPinName )
            ShowPinNameButt->SetValue( TRUE );
    }
    else
        ShowPinNameButt->SetValue( TRUE );

    pos.y += 20;
    PinsNameInsideButt = new wxCheckBox( PanelBasic, -1, _( "Pin Name Inside" ), pos );

    if( CurrentLibEntry )
    {
        if( CurrentLibEntry->TextInside )
            PinsNameInsideButt->SetValue( TRUE );
    }
    else
        PinsNameInsideButt->SetValue( TRUE );

    pos.y += 40;
    new wxStaticText( PanelBasic, -1, _( "Number of Units:" ), pos );

    pos.y += 15;
    wxString number;
    if( CurrentLibEntry )
        number.Printf( "%d", CurrentLibEntry->NumOfUnits );
    else
        number = "1";
    SelNumberOfUnits = new  wxSpinCtrl( PanelBasic, -1, number, pos,
                                        wxDefaultSize, wxSP_ARROW_KEYS | wxSP_WRAP,
                                        1, 16 );

    pos.y -= 15; pos.x += 140;
    new                     wxStaticText( PanelBasic, -1, _( "Skew:" ), pos );

    pos.y += 15;
    if( CurrentLibEntry && CurrentLibEntry->TextInside )
        number.Printf( "%d", CurrentLibEntry->TextInside );
    else
        number = "40";
    m_SetSkew = new wxSpinCtrl( PanelBasic, -1, number, pos,
                                wxDefaultSize, wxSP_ARROW_KEYS | wxSP_WRAP,
                                1, 100 );

    // Add Panel Documentation
    PanelDoc = new  wxPanel( m_NoteBook, -1 );

    c = new wxLayoutConstraints;
    c->left.SameAs( m_NoteBook, wxLeft );
    c->right.SameAs( m_NoteBook, wxRight );
    c->bottom.SameAs( m_NoteBook, wxBottom );
    PanelDoc->SetConstraints( c );
    m_NoteBook->AddPage( PanelDoc, _( "Doc" ), FALSE );
    pos.x  = 5; pos.y = 40;
    NewDoc = new        WinEDA_EnterText( PanelDoc,
                                         _( "Doc:" ), Doc,
                                         pos, wxSize( 285, -1 ) );

    pos.y     += 50;
    NewKeywoed = new    WinEDA_EnterText( PanelDoc,
                                         _( "Keywords:" ), Keywords,
                                         pos, wxSize( 285, -1 ) );

    pos.y     += 50;
    NewDocFile = new    WinEDA_EnterText( PanelDoc,
                                         _( "DocFileName:" ), Docfile,
                                         pos, wxSize( 285, -1 ) );

    // Add Panel Alias List
    PanelAlias = new    wxPanel( m_NoteBook, -1 );

    c = new wxLayoutConstraints;
    c->left.SameAs( m_NoteBook, wxLeft );
    c->right.SameAs( m_NoteBook, wxRight );
    c->bottom.SameAs( m_NoteBook, wxBottom );
    PanelAlias->SetConstraints( c );
    m_NoteBook->AddPage( PanelAlias, _( "Alias" ), FALSE );

    pos.x = 200; pos.y = 70;
    new                 wxButton( PanelAlias, ID_ADD_ALIAS,
                                  _( "Add" ), pos );

    pos.y += Button->GetDefaultSize().y + 10;
    new                 wxButton( PanelAlias, ID_DELETE_ONE_ALIAS,
                                  _( "Delete" ), pos );

    pos.y += Button->GetDefaultSize().y + 10;
    new                 wxButton( PanelAlias, ID_DELETE_ALL_ALIAS,
                                  _( "Delete All" ), pos );

    pos.x = 5; pos.y = 30;
    PartAliasList = new wxListBox( PanelAlias,
                                   -1,
                                   pos, wxSize( 160, 170 ),
                                   0, NULL,
                                   wxLB_ALWAYS_SB | wxLB_SINGLE );

    wxStaticText* Msg = new wxStaticText( PanelAlias, -1, _( "Alias" ),
                                         wxPoint (pos.x, pos.y - 20) );

    Msg->SetForegroundColour( wxColour( 200, 0, 0 ) );
    /* lecture des alias */
    ListOfAliasStruct* Alias = AliasListCopy;
    while( Alias )
    {
        PartAliasList->Append( Alias->m_Name.m_Text );
        Alias = Alias->Next;
    }

    // Add panel Fields
    for( int ii = 0; ii < NUMBER_OF_FIELDS; ii++ )
    {
        PanelField[ii] = new wxPanel( m_NoteBook, ID_PANEL_REFERENCE + ii );

        c = new wxLayoutConstraints;
        c->left.SameAs( m_NoteBook, wxLeft );
        c->right.SameAs( m_NoteBook, wxRight );
        c->bottom.SameAs( m_NoteBook, wxBottom );
        PanelField[ii]->SetConstraints( c );
        m_NoteBook->AddPage( PanelField[ii], PanelText[ii], FALSE );

        pos.x = 10; pos.y = 20;
        ShowFieldText[ii] = new wxCheckBox( PanelField[ii], -1,
                                            _( "Show Text" ), pos );

        if( (FieldFlags[ii] & TEXT_NO_VISIBLE ) == 0 )
            ShowFieldText[ii]->SetValue( TRUE );

        pos.x += 150;
        VorientFieldText[ii] = new wxCheckBox( PanelField[ii], -1,
                                               _( "Vertical" ), pos );

        if( FieldOrient[ii] )
            VorientFieldText[ii]->SetValue( TRUE );

        pos.x = 10; pos.y += 50;
        wxPoint txtpos;

        switch( ii )
        {
        case REFERENCE:
            if( CurrentLibEntry )
                txtpos = CurrentLibEntry->m_Prefix.m_Pos;
            else
                txtpos = wxPoint( 0, 0 );
            FieldTextCtrl[ii] = new WinEDA_GraphicTextCtrl(
                PanelField[ii],
                PanelText[ii],
                CurrentLibEntry ? CurrentLibEntry->
                m_Prefix.m_Text : (char*) "U",
                CurrentLibEntry ? CurrentLibEntry->
                m_Prefix.m_Size : 50,
                UnitMetric,
                pos,
                200,
                TRUE );

            FieldPosition[ii] = new WinEDA_PositionCtrl( PanelField[ii],
                                                        txtpos,
                                                        UnitMetric, wxPoint (pos.x + 150,
                                                                             pos.y + 32) );

            break;

        case VALUE:
            if( CurrentLibEntry )
                txtpos = CurrentLibEntry->m_Name.m_Pos;
            else
                txtpos = wxPoint( 0, 0 );
            FieldTextCtrl[ii] = new WinEDA_GraphicTextCtrl(
                PanelField[ii],
                PanelText[ii],
                CurrentLibEntry ? CurrentLibEntry->
                m_Name.m_Text : NULL,
                CurrentLibEntry ? CurrentLibEntry->
                m_Name.m_Size : 50,
                UnitMetric,
                pos,
                200,
                TRUE );

            FieldPosition[ii] = new WinEDA_PositionCtrl( PanelField[ii],
                                                        txtpos,
                                                        UnitMetric, wxPoint (pos.x + 150,
                                                                             pos.y + 32) );

            break;

        default:
            int fsize; char* ftext; wxPoint fpos;
            fsize = 50; ftext = NULL;
            LibDrawField*    Field = NULL;
            fpos = wxPoint( 0, 0 );

            //recherche du Field de FieldId correspondant, s'il existe
            if( CurrentLibEntry )
            {
                Field = CurrentLibEntry->Fields;
                while( Field )
                {
                    if( Field->m_FieldId == ii )
                    {
                        fsize = Field->m_Size; ftext = Field->m_Text;
                        fpos  = Field->m_Pos;
                        break;
                    }
                    Field = (LibDrawField*) Field->Pnext;
                }
            }

            FieldTextCtrl[ii] = new WinEDA_GraphicTextCtrl( PanelField[ii],
                                                            PanelText[ii],
                                                            ftext, fsize,
                                                            UnitMetric,
                                                            pos, 200, TRUE );

            FieldPosition[ii] = new WinEDA_PositionCtrl( PanelField[ii],
                                                        fpos,
                                                        UnitMetric, wxPoint (pos.x + 150,
                                                                             pos.y + 32) );

            break;
        }
    }

    SetModal( TRUE );
}


/***************************************************************************/
/* WinEDA_PartPropertiesFrame::PartPropertiesAccept(wxCommandEvent& event) */
/***************************************************************************/

/* Met a jour les differents parametres pour le composant en cours d'�dition
 */

void WinEDA_PartPropertiesFrame::PartPropertiesAccept( wxCommandEvent& event )
{
    bool recreateTB = FALSE;

    if( CurrentLibEntry == NULL )
    {
        Close(); return;
    }

    m_Parent->CurrentScreen->SetModify();
    m_Parent->CurrentScreen->SetRefreshReq();

    if( ListAlias )
        ListAlias->FreeList();
    if( AliasListCopy )
        ListAlias = AliasListCopy->DupList();

    if( CurrentLibEntry->Doc && strcmp( Doc, CurrentLibEntry->Doc ) )
    {
        free( CurrentLibEntry->Doc ); CurrentLibEntry->Doc = NULL;
    }
    if( strlen( Doc ) )
        CurrentLibEntry->Doc = strdup( Doc );

    if( CurrentLibEntry->KeyWord && strcmp( Keywords, CurrentLibEntry->KeyWord ) )
    {
        free( CurrentLibEntry->KeyWord ); CurrentLibEntry->KeyWord = NULL;
    }
    if( strlen( Keywords ) )
        CurrentLibEntry->KeyWord = strdup( Keywords );

    if( CurrentLibEntry->DocFile && strcmp( Docfile, CurrentLibEntry->DocFile ) )
    {
        free( CurrentLibEntry->DocFile ); CurrentLibEntry->DocFile = NULL;
    }
    if( strlen( Docfile ) )
        CurrentLibEntry->DocFile = strdup( Docfile );


    CurrentLibEntry->m_Prefix.SetText( (char*) FieldTextCtrl[REFERENCE]->GetText() );
    CurrentLibEntry->m_Name.SetText( (char*) FieldTextCtrl[VALUE]->GetText() );

    CurrentLibEntry->m_Prefix.m_Size = FieldTextCtrl[REFERENCE]->GetTextSize();
    CurrentLibEntry->m_Name.m_Size   = FieldTextCtrl[VALUE]->GetTextSize();

    CurrentLibEntry->m_Prefix.m_Pos = FieldPosition[REFERENCE]->GetCoord();
    CurrentLibEntry->m_Name.m_Pos   = FieldPosition[VALUE]->GetCoord();

    CurrentLibEntry->m_Prefix.m_Orient = VorientFieldText[REFERENCE]->GetValue() ? 1 : 0;
    CurrentLibEntry->m_Name.m_Orient   = VorientFieldText[VALUE]->GetValue() ? 1 : 0;

    if( ShowFieldText[REFERENCE]->GetValue() )
        CurrentLibEntry->m_Prefix.m_Attributs &= ~TEXT_NO_VISIBLE;
    else
        CurrentLibEntry->m_Prefix.m_Attributs |= TEXT_NO_VISIBLE;

    if( ShowFieldText[VALUE]->GetValue() )
        CurrentLibEntry->m_Name.m_Attributs &= ~TEXT_NO_VISIBLE;
    else
        CurrentLibEntry->m_Name.m_Attributs |= TEXT_NO_VISIBLE;

    for( int ii = FIELD1; ii < NUMBER_OF_FIELDS; ii++ )
    {
        LibDrawField* Field = CurrentLibEntry->Fields;
        LibDrawField* NextField, * previousField = NULL;
        while( Field )
        {
            NextField = (LibDrawField*) Field->Pnext;
            if( Field->m_FieldId == ii )
            {
                Field->SetText( (char*) FieldTextCtrl[ii]->GetText() );
                Field->m_Size = FieldTextCtrl[ii]->GetTextSize();
                if( ShowFieldText[ii]->GetValue() )
                    Field->m_Attributs &= ~TEXT_NO_VISIBLE;
                else
                    Field->m_Attributs |= TEXT_NO_VISIBLE;
                Field->m_Orient = VorientFieldText[ii]->GetValue() ? 1 : 0;
                Field->m_Pos    = FieldPosition[Field->m_FieldId]->GetCoord();
                if( Field->m_Text == NULL )
                {
                    delete Field;
                    if( previousField )
                        previousField->Pnext = NextField;
                    else
                        CurrentLibEntry->Fields = NextField;
                }
                break;
            }

            previousField = Field;
            Field = NextField;
        }

        if( (Field == NULL) && strlen( FieldTextCtrl[ii]->GetText() ) )
        {       // N'existe pas: a creer
            Field = new LibDrawField( ii );

            Field->SetText( (char*) FieldTextCtrl[ii]->GetText() );
            Field->m_Size = FieldTextCtrl[ii]->GetTextSize();
            Field->Pnext  = CurrentLibEntry->Fields;
            if( ShowFieldText[Field->m_FieldId]->GetValue() )
                Field->m_Attributs &= ~TEXT_NO_VISIBLE;
            else
                Field->m_Attributs |= TEXT_NO_VISIBLE;
            Field->m_Orient = VorientFieldText[Field->m_FieldId]->GetValue() ? 1 : 0;
            Field->m_Pos    = FieldPosition[Field->m_FieldId]->GetCoord();
            CurrentLibEntry->Fields = Field;
        }
    }

    int ii = SelNumberOfUnits->GetValue();
    if( ChangeNbUnitsPerPackage( ii ) )
        recreateTB = TRUE;

    if( AsConvertButt->GetValue() )
    {
        if( !g_AsDeMorgan )
        {
            g_AsDeMorgan = 1;
            if( SetUnsetConvert() )
                recreateTB = TRUE;
        }
    }
    else
    {
        if( g_AsDeMorgan )
        {
            g_AsDeMorgan = 0;
            if( SetUnsetConvert() )
                recreateTB = TRUE;
        }
    }

    CurrentLibEntry->DrawPinNum  = ShowPinNumButt->GetValue() ? 1 : 0;
    CurrentLibEntry->DrawPinName = ShowPinNameButt->GetValue() ? 1 : 0;

    if( PinsNameInsideButt->GetValue() == FALSE )
        CurrentLibEntry->TextInside = 0;
    else
        CurrentLibEntry->TextInside = m_SetSkew->GetValue();

    if( recreateTB )
        m_Parent->ReCreateHToolbar();

    Close();
}


/***************************************************************/
/* void WinEDA_PartPropertiesFrame::DeleteAllAliasOfPart() */
/***************************************************************/

void WinEDA_PartPropertiesFrame::DeleteAllAliasOfPart()
{
    if( CurrentLibEntry && AliasListCopy )
    {
        if( confirmation( _( "Ok to Delete Alias LIST" ) ) == YES )
        {
            if( AliasListCopy )
                AliasListCopy->FreeList();
            AliasListCopy = NULL;
            PartAliasList->Clear();
        }
    }
}


/*********************************************************/
/* void WinEDA_PartPropertiesFrame::AddAliasOfPart() */
/*********************************************************/

void WinEDA_PartPropertiesFrame::AddAliasOfPart()
{
    char Line[LINE_LEN];
    int  llen;
    ListOfAliasStruct* NewAlias;

    if( CurrentLibEntry == NULL )
        return;

    *Line = 0;
    if( Get_Message( _( "Alias:" ), Line, this ) != 0 )
        return;

    ChangeSpaces( Line, '_' );
    llen = strlen( Line ) + 1;

    NewAlias = LocateAlias( AliasListCopy, Line );
    if( NewAlias )
    {
        DisplayError( _( "Already in use" ), 10 ); return;
    }
    NewAlias = new ListOfAliasStruct( Line );

    NewAlias->Next = AliasListCopy;
    AliasListCopy  = NewAlias;

    /* affichage des alias */
    PartAliasList->Clear();
    ListOfAliasStruct* Alias = AliasListCopy;
    while( Alias )
    {
        PartAliasList->Append( Alias->m_Name.m_Text );
        Alias = Alias->Next;
    }
}


/********************************/
/* void DeleteAliasOfPart() */
/********************************/

void WinEDA_PartPropertiesFrame::DeleteAliasOfPart()
{
    ListOfAliasStruct* Alias;
    wxString           aliasname;

    if( CurrentLibEntry == NULL )
        return;
    if( AliasListCopy == NULL )
        return;

    aliasname = PartAliasList->GetStringSelection();
    if( aliasname == "" )
        return;

    Alias = AliasListCopy;
    ListOfAliasStruct* Previous = NULL;
    while( Alias )
    {
        if( stricmp( aliasname.GetData(), Alias->m_Name.m_Text ) == 0 )
        {
            if( Previous )
                Previous->Next = Alias->Next;
            else
                AliasListCopy = Alias->Next;
            delete Alias;
            break;
        }
        Previous = Alias;
        Alias    = Alias->Next;
    }

    /* affichage des alias */
    PartAliasList->Clear();
    Alias = AliasListCopy;
    while( Alias )
    {
        PartAliasList->Append( Alias->m_Name.m_Text );
        Alias = Alias->Next;
    }
}


/************************************************************/
static void ExitMoveField( WinEDA_DrawFrame* frame, wxDC* DC )
/************************************************************/
{
    frame->CurrentScreen->ManageCurseur = NULL;
    frame->CurrentScreen->ForceCloseManageCurseur = NULL;
    if( CurrentDrawItem == NULL )
        return;

    wxPoint curpos;
    curpos = frame->CurrentScreen->Curseur;
    frame->CurrentScreen->Curseur = StartCursor;
    MoveField( DC, 1 );
    frame->CurrentScreen->Curseur = curpos;
    CurrentDrawItem->m_Flags = 0;

    CurrentDrawItem = NULL;
}


/*********************************************/
/* static void StartMoveField(COMMAND * Cmd) */
/*********************************************/
/* Initialise le deplacement d'un champ ( ref ou Name) */
void WinEDA_LibeditFrame::StartMoveField( wxDC* DC, LibDrawField* field )
{
    if( (CurrentLibEntry == NULL) || ( field == NULL ) )
        return;
    CurrentDrawItem = field;
    CurrentDrawItem->m_Flags    |= IS_MOVED;
    CurrentScreen->ManageCurseur = MoveField;
    CurrentScreen->ForceCloseManageCurseur = ExitMoveField;
    CurrentScreen->ManageCurseur( DC, 1 );
    StartCursor = CurrentScreen->Curseur;
}


/*****************************************************************/
/* Routine d'affichage du texte 'Field' en cours de deplacement. */
/*	Routine normalement attachee au curseur						*/
/*****************************************************************/
static void MoveField( wxDC* DC, int flag )
{
    int           color;
    LibDrawField* Field = (LibDrawField*) CurrentDrawItem;

    if( (CurrentLibEntry == NULL) || (Field == NULL) )
        return;

    GRSetDrawMode( DC, XOR_MODE );

    switch( Field->m_FieldId )
    {
    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;
    if( flag >= 0 )
        Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                    color, Field->m_Text,
                    Field->m_Orient, Field->m_Size,
                    GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );

    Field->m_Pos.x = ActiveScreen->Curseur.x;
    Field->m_Pos.y = -ActiveScreen->Curseur.y;

    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );
}


/********************************/
/* static void PlaceField() */
/********************************/

void WinEDA_LibeditFrame::PlaceField( wxDC* DC, LibDrawField* Field )
{
    int color;

    if( Field == NULL )
        return;

    GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;
    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );

    Field->m_Flags = 0;

    CurrentScreen->SetModify();
    CurrentScreen->ManageCurseur = NULL;
    CurrentScreen->ForceCloseManageCurseur = NULL;
    CurrentDrawItem = NULL;
}


/****************************************/
/* static void EditField(COMMAND * Cmd) */
/****************************************/

void WinEDA_LibeditFrame::EditField( wxDC* DC, LibDrawField* Field )
{
    char Text[LINE_LEN];
    int  color;

    wxClientDC dc( DrawPanel );

    if( Field== NULL )
        return;

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    *Text = 0;
    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;

    if( Field->m_Text )
        strcpy( Text, Field->m_Text );
    Get_Message( _( "Text: " ), Text, this );
    ChangeSpaces( Text, '_' );

    GRSetDrawMode( &dc, XOR_MODE );
    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );

    Field->SetText( Text );

    if( Field->m_Flags == 0 )
        GRSetDrawMode( &dc, GR_DEFAULT_DRAWMODE );

    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );

    CurrentScreen->SetModify();
}


/*******************************************************************/
void WinEDA_LibeditFrame::RotateField( wxDC* DC, LibDrawField* Field )
/*******************************************************************/

/*
 *  Routine de modification de l'orientation ( Horiz ou Vert. ) du champ.
 *  si un champ est en cours d'edition, modif de celui ci.
 *  sinon Modif du champ pointe par la souris
 */
{
    int color;

    if( Field == NULL )
        return;

    CurrentScreen->SetModify();

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( Field->m_Attributs & TEXT_NO_VISIBLE  )
        color = DARKGRAY;

    GRSetDrawMode( DC, XOR_MODE );
    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );

    if( Field->m_Orient )
        Field->m_Orient = 0;
    else
        Field->m_Orient = 1;

    if( Field->m_Flags == 0 )
        GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    Gr_E_texte( DC, Field->m_Pos.x, -Field->m_Pos.y,
                color, Field->m_Text,
                Field->m_Orient, Field->m_Size,
                GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER );
}


/********************************************************/
/* static int LocateField(LibraryEntryStruct *LibEntry) */
/********************************************************/

/* Localise le champ (ref ou name) pointe par la souris
 *   retourne:
 *      < 0: Pas de champ
 *      0: Ref
 *      1: Name(s)
 *      > 2 = Num Field
 */
LibDrawField* WinEDA_LibeditFrame::LocateField( LibraryEntryStruct* LibEntry )
{
    int           x0, y0, x1, y1;   /* Rectangle d'encadrement des textes a localiser */
    int           dx, dy;           /* Dimensions du texte */
    LibDrawField* Field;

    /* Localisation du Nom */
    x0 = LibEntry->m_Name.m_Pos.x;
    y0 = -LibEntry->m_Name.m_Pos.y;
    dx = LibEntry->m_Name.m_Size * strlen( LibEntry->m_Name.m_Text ),
    dy = LibEntry->m_Name.m_Size;
    if( LibEntry->m_Name.m_Orient )
        EXCHG( dx, dy );
    x0 -= dx / 2; y0 -= dy / 2;
    x1  = x0 + dx; y1 = y0 + dy;

    if( (CurrentScreen->Curseur.x >= x0) && ( CurrentScreen->Curseur.x <= x1)
       && (CurrentScreen->Curseur.y >= y0) && ( CurrentScreen->Curseur.y <= y1) )
        return &LibEntry->m_Name;

    /* Localisation du Prefix */
    x0 = LibEntry->m_Prefix.m_Pos.x;
    y0 = -LibEntry->m_Prefix.m_Pos.y;
    dx = LibEntry->m_Prefix.m_Size * strlen( LibEntry->m_Prefix.m_Text ),
    dy = LibEntry->m_Prefix.m_Size;
    if( LibEntry->m_Prefix.m_Orient )
        EXCHG( dx, dy );
    x0 -= dx / 2; y0 -= dy / 2;
    x1  = x0 + dx; y1 = y0 + dy;

    if( (CurrentScreen->Curseur.x >= x0) && ( CurrentScreen->Curseur.x <= x1)
       && (CurrentScreen->Curseur.y >= y0) && ( CurrentScreen->Curseur.y <= y1) )
        return &LibEntry->m_Prefix;

    /* Localisation des autres fields */
    for( Field = LibEntry->Fields; Field != NULL;
         Field = (LibDrawField*) Field->Pnext )
    {
        if( Field->m_Text == NULL )
            continue;
        x0 = Field->m_Pos.x; y0 = -Field->m_Pos.y;
        dx = Field->m_Size * strlen( Field->m_Text ),
        dy = Field->m_Size;
        if( Field->m_Orient )
            EXCHG( dx, dy );
        x0 -= dx / 2; y0 -= dy / 2;
        x1  = x0 + dx; y1 = y0 + dy;
        if( (CurrentScreen->Curseur.x >= x0) && ( CurrentScreen->Curseur.x <= x1)
           && (CurrentScreen->Curseur.y >= y0) && ( CurrentScreen->Curseur.y <= y1) )
            return Field;
    }

    return NULL;
}


/*********************************************************************/
/* static char * PrefixText(LibraryEntryStruct * LibEntry, int Unit) */
/*********************************************************************/

/* Calcule l'affichage complet du prefixe ( texte + '?' + ident unit )
 *  Retourne un pointeur sur le nouveau texte (allocation statique)
 */
static char* PrefixText( LibraryEntryStruct* LibEntry, int Unit )
{
    static char Text[LINE_LEN];

    if( LibEntry->NumOfUnits > 1 )
        sprintf( Text, "%s?%c", LibEntry->m_Prefix.m_Text, Unit + 'A' - 1 );
    else
        sprintf( Text, "%s?", LibEntry->m_Prefix.m_Text );
    return Text;
}


/*****************************************************************/
/* void WinEDA_PartPropertiesFrame::ChangeNbUnitsPerPackagevoid) */
/*****************************************************************/

/* Routine de modification du nombre d'unites par package pour le
 *  composant courant;
 */
bool WinEDA_PartPropertiesFrame::ChangeNbUnitsPerPackage( int MaxUnit )
{
    int OldNumUnits, ii, FlagDel = -1;
    LibEDA_BaseStruct* DrawItem, * NextDrawItem;

    if( CurrentLibEntry == NULL )
        return FALSE;

    /* Si pas de changement: termine */
    if( CurrentLibEntry->NumOfUnits == MaxUnit )
        return FALSE;

    OldNumUnits = CurrentLibEntry->NumOfUnits;
    if( OldNumUnits < 1 )
        OldNumUnits = 1;

    CurrentLibEntry->NumOfUnits = MaxUnit;


    /* Traitement des unites enlevees ou rajoutees */
    if( OldNumUnits > CurrentLibEntry->NumOfUnits )
    {
        DrawItem = CurrentLibEntry->Drawings;
        for( ; DrawItem != NULL; DrawItem = NextDrawItem )
        {
            NextDrawItem = DrawItem->Pnext;
            if( DrawItem->m_Unit > MaxUnit )  /* Item a effacer */
            {
                if( FlagDel < 0 )
                {
                    if( confirmation( _( "Delete units" ) ) == YES )
                    {
                        /* Si part selectee n'existe plus: selection 1ere unit */
                        if( CurrentUnit > MaxUnit )
                            CurrentUnit = 1;
                        FlagDel = 1;
                    }
                    else
                    {
                        FlagDel = 0;
                        MaxUnit = OldNumUnits;
                        CurrentLibEntry->NumOfUnits = MaxUnit;
                        return FALSE;
                    }
                }
                DeleteOneLibraryDrawStruct( NULL, CurrentLibEntry,
                                            DrawItem, 0 );
            }
        }

        return TRUE;
    }

    if( OldNumUnits < CurrentLibEntry->NumOfUnits )
    {
        DrawItem = CurrentLibEntry->Drawings;
        for( ; DrawItem != NULL; DrawItem = DrawItem->Pnext )
        {
            /* Duplication des items pour autres elements */
            if( DrawItem->m_Unit == 1 )
            {
                for( ii = OldNumUnits + 1; ii <= MaxUnit; ii++ )
                {
                    NextDrawItem = CopyDrawEntryStruct( DrawItem );
                    NextDrawItem->Pnext = CurrentLibEntry->Drawings;
                    CurrentLibEntry->Drawings = NextDrawItem;
                    NextDrawItem->m_Unit = ii;
                }
            }
        }
    }
    return TRUE;
}


/**********************************************************/
/* void WinEDA_PartPropertiesFrame::SetUnsetConvert() */
/**********************************************************/

/* cr�e ou efface (selon option AsConvert) les �l�ments
 *  de la repr�sentation convertie d'un composant
 */
bool WinEDA_PartPropertiesFrame::SetUnsetConvert()
{
    int FlagDel = 0;
    LibEDA_BaseStruct* DrawItem = NULL, * NextDrawItem;

    if( g_AsDeMorgan )  /* Representation convertie a creer */
    {
        /* Traitement des elements a ajouter ( pins seulement ) */
        if( CurrentLibEntry )
            DrawItem = CurrentLibEntry->Drawings;
        for( ; DrawItem != NULL; DrawItem = DrawItem->Pnext )
        {
            /* Duplication des items pour autres elements */
            if( DrawItem->Type() != PIN_DRAW_TYPE )
                continue;
            if( DrawItem->m_Convert == 1 )
            {
                if( FlagDel == 0 )
                {
                    if( confirmation( _( "Create pins for Convert items" ) ) == YES )
                        FlagDel = 1;
                    else
                    {
                        if( confirmation( _( "Part as \"De Morgan\" anymore" ) ) == YES )
                            return TRUE;

                        g_AsDeMorgan = 0; return FALSE;
                    }
                }
                NextDrawItem = CopyDrawEntryStruct( DrawItem );
                NextDrawItem->Pnext = CurrentLibEntry->Drawings;
                CurrentLibEntry->Drawings = NextDrawItem;
                NextDrawItem->m_Convert   = 2;
            }
        }
    }
    else               /* Representation convertie a supprimer */
    {
        /* Traitement des elements � supprimer */
        if( CurrentLibEntry )
            DrawItem = CurrentLibEntry->Drawings;
        for( ; DrawItem != NULL; DrawItem = NextDrawItem )
        {
            NextDrawItem = DrawItem->Pnext;
            if( DrawItem->m_Convert > 1 )  /* Item a effacer */
            {
                if( FlagDel == 0 )
                {
                    if( confirmation( _( "Delete Convert items" ) ) == YES )
                    {
                        CurrentConvert = 1;
                        FlagDel = 1;
                    }
                    else
                    {
                        g_AsDeMorgan = 1;
                        return FALSE;
                    }
                }
                ActiveScreen->SetModify();
                DeleteOneLibraryDrawStruct( NULL, CurrentLibEntry, DrawItem, 0 );
            }
        }
    }
    return TRUE;
}