Commit 8ec8cf3f authored by charras's avatar charras
Browse files

Rework on undo/redo and block functions

parent 6d14766e
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,14 @@ KiCad ChangeLog 2009
Please add newer entries at the top, list the date and your name with
Please add newer entries at the top, list the date and your name with
email address.
email address.


2009-july-25 UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++all
    Rework on undo/redo and block functions
    Better and simpler coding of block and undo/redo functions
    The goal is to have the same functions in eeschema and pcbnew.
    and have a full undo/redo in pcbnew.

2009-july-18 UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
2009-july-18 UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
================================================================================
++pcbnew
++pcbnew
+112 −96
Original line number Original line Diff line number Diff line
@@ -19,31 +19,30 @@




/*******************/
/*******************/
/* DrawBlockStruct */
/* BLOCK_SELECTOR */
/*******************/
/*******************/


/****************************************************************************/
/****************************************************************************/
DrawBlockStruct::DrawBlockStruct() :
BLOCK_SELECTOR::BLOCK_SELECTOR() :
    EDA_BaseStruct( BLOCK_LOCATE_STRUCT_TYPE )
    EDA_BaseStruct( BLOCK_LOCATE_STRUCT_TYPE ),
    , EDA_Rect()
    EDA_Rect()
/****************************************************************************/
/****************************************************************************/
{
{
    m_State   = STATE_NO_BLOCK; /* Etat (enum BlockState) du block */
    m_State   = STATE_NO_BLOCK; /* Etat (enum BlockState) du block */
    m_Command = BLOCK_IDLE;     /* Type (enum CmdBlockType) d'operation */
    m_Command = BLOCK_IDLE;     /* Type (enum CmdBlockType) d'operation */
    m_BlockDrawStruct = NULL;   /* pointeur sur la structure */
    m_Color   = BROWN;
    m_Color   = BROWN;
}
}




/****************************************/
/****************************************/
DrawBlockStruct::~DrawBlockStruct()
BLOCK_SELECTOR::~BLOCK_SELECTOR()
/****************************************/
/****************************************/
{
{
}
}




/***************************************************************/
/***************************************************************/
void DrawBlockStruct::SetMessageBlock( WinEDA_DrawFrame* frame )
void BLOCK_SELECTOR::SetMessageBlock( WinEDA_DrawFrame* frame )
/***************************************************************/
/***************************************************************/


/*
/*
@@ -112,21 +111,69 @@ void DrawBlockStruct::SetMessageBlock( WinEDA_DrawFrame* frame )




/**************************************************************/
/**************************************************************/
void DrawBlockStruct::Draw( WinEDA_DrawPanel* panel, wxDC* DC )
void BLOCK_SELECTOR::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
                           const wxPoint& aOffset,
                           int aDrawMode,
                           int aColor )
/**************************************************************/
/**************************************************************/
{
{
    int w = panel->GetScreen()->Scale( GetWidth() );
    int w = aPanel->GetScreen()->Scale( GetWidth() );
    int h = panel->GetScreen()->Scale( GetHeight() );
    int h = aPanel->GetScreen()->Scale( GetHeight() );


    GRSetDrawMode( aDC, aDrawMode );
    if(  w == 0 || h == 0 )
    if(  w == 0 || h == 0 )
        GRLine( &panel->m_ClipBox, DC, GetX(), GetY(),
        GRLine( &aPanel->m_ClipBox, aDC, GetX() + aOffset.x, GetY() + aOffset.y,
                GetRight(), GetBottom(), 0, m_Color );
                GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor );
    else
    else
        GRRect( &panel->m_ClipBox, DC, GetX(), GetY(),
        GRRect( &aPanel->m_ClipBox, aDC, GetX() + aOffset.x, GetY() + aOffset.y,
                GetRight(), GetBottom(), 0, m_Color );
                GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor );
}
}




/*************************************************************************/
void BLOCK_SELECTOR::InitData( WinEDA_DrawPanel* aPanel, const wxPoint& startpos )
/*************************************************************************/

/** function InitData
 *  Init the initial values of a BLOCK_SELECTOR, before starting a block command
 */
{
    m_State = STATE_BLOCK_INIT;
    SetOrigin( startpos );
    SetSize( wxSize( 0, 0 ) );
    m_ItemsSelection.ClearItemsList();
    aPanel->ManageCurseur = DrawAndSizingBlockOutlines;
    aPanel->ForceCloseManageCurseur = AbortBlockCurrentCommand;
}


/** Function ClearItemsList
 * delete only the list of EDA_BaseStruct * pointers, NOT the pointed data itself
 */
void BLOCK_SELECTOR::ClearItemsList()
{
    m_ItemsSelection.ClearItemsList();
}

/** Function ClearListAndDeleteItems
 * delete only the list of EDA_BaseStruct * pointers, AND the data pinted by m_Item
 */
void BLOCK_SELECTOR::ClearListAndDeleteItems()
{
     m_ItemsSelection.ClearListAndDeleteItems();
}

/** Function PushItem
 * Add aItem to the list of items
 * @param aItem = an ITEM_PICKER to add to the list
 */
void BLOCK_SELECTOR::PushItem( ITEM_PICKER& aItem )
{
    m_ItemsSelection.PushItem(  aItem );
}



/*************************************************************************/
/*************************************************************************/
bool WinEDA_DrawFrame::HandleBlockBegin( wxDC* DC, int key,
bool WinEDA_DrawFrame::HandleBlockBegin( wxDC* DC, int key,
                                         const wxPoint& startpos )
                                         const wxPoint& startpos )
@@ -136,7 +183,7 @@ bool WinEDA_DrawFrame::HandleBlockBegin( wxDC* DC, int key,
 *  Init the Block infos: command type, initial position, and other variables..
 *  Init the Block infos: command type, initial position, and other variables..
 */
 */
{
{
    DrawBlockStruct* Block = & GetBaseScreen()->BlockLocate;
    BLOCK_SELECTOR* Block = &GetBaseScreen()->m_BlockLocate;


    if( ( Block->m_Command != BLOCK_IDLE )
    if( ( Block->m_Command != BLOCK_IDLE )
       || ( Block->m_State != STATE_NO_BLOCK ) )
       || ( Block->m_State != STATE_NO_BLOCK ) )
@@ -163,24 +210,24 @@ bool WinEDA_DrawFrame::HandleBlockBegin( wxDC* DC, int key,
    case BLOCK_MIRROR_X:
    case BLOCK_MIRROR_X:
    case BLOCK_MIRROR_Y:            /* mirror */
    case BLOCK_MIRROR_Y:            /* mirror */
    case BLOCK_PRESELECT_MOVE:      /* Move with preselection list*/
    case BLOCK_PRESELECT_MOVE:      /* Move with preselection list*/
        InitBlockLocateDatas( DrawPanel, startpos );
        Block->InitData( DrawPanel, startpos );
        break;
        break;


    case BLOCK_PASTE:
    case BLOCK_PASTE:
        InitBlockLocateDatas( DrawPanel, startpos );
        Block->InitData( DrawPanel, startpos );
        Block->m_BlockLastCursorPosition.x = 0;
        Block->m_BlockLastCursorPosition.x = 0;
        Block->m_BlockLastCursorPosition.y = 0;
        Block->m_BlockLastCursorPosition.y = 0;
        InitBlockPasteInfos();
        InitBlockPasteInfos();
        if( Block->m_BlockDrawStruct == NULL )      /* No data to paste */
        if( Block->m_ItemsSelection.GetCount() == 0 )      /* No data to paste */
        {
        {
            DisplayError( this, wxT( "No Block to paste" ), 20 );
            DisplayError( this, wxT( "No Block to paste" ), 20 );
            GetBaseScreen()->BlockLocate.m_Command = BLOCK_IDLE;
            GetBaseScreen()->m_BlockLocate.m_Command = BLOCK_IDLE;
            DrawPanel->ManageCurseur = NULL;
            DrawPanel->ManageCurseur = NULL;
            return TRUE;
            return TRUE;
        }
        }
        if( DrawPanel->ManageCurseur == NULL )
        if( DrawPanel->ManageCurseur == NULL )
        {
        {
            Block->m_BlockDrawStruct = NULL;
            Block->m_ItemsSelection.ClearItemsList();
            DisplayError( this,
            DisplayError( this,
                         wxT( "WinEDA_DrawFrame::HandleBlockBegin() Err: ManageCurseur NULL" ) );
                         wxT( "WinEDA_DrawFrame::HandleBlockBegin() Err: ManageCurseur NULL" ) );
            return TRUE;
            return TRUE;
@@ -203,95 +250,30 @@ bool WinEDA_DrawFrame::HandleBlockBegin( wxDC* DC, int key,
    return TRUE;
    return TRUE;
}
}



/******************************************************************/
void AbortBlockCurrentCommand( WinEDA_DrawPanel* Panel, wxDC* DC )
/******************************************************************/

/*
 *  Cancel Current block operation.
 */
{
    BASE_SCREEN* screen = Panel->GetScreen();

    if( Panel->ManageCurseur )                      /* Erase current drawing on screen */
    {
        Panel->ManageCurseur( Panel, DC, FALSE );   /* Efface dessin fantome */
        Panel->ManageCurseur = NULL;
        Panel->ForceCloseManageCurseur = NULL;
        screen->SetCurItem( NULL );

        /* Delete the picked wrapper if this is a picked list. */
        if( (screen->BlockLocate.m_Command != BLOCK_PASTE)
           && screen->BlockLocate.m_BlockDrawStruct )
        {
            if( screen->BlockLocate.m_BlockDrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
            {
                DrawPickedStruct* PickedList;
                PickedList = (DrawPickedStruct*) screen->BlockLocate.m_BlockDrawStruct;
                PickedList->DeleteWrapperList();
            }
            screen->BlockLocate.m_BlockDrawStruct = NULL;
        }
    }

    screen->BlockLocate.m_Flags = 0;
    screen->BlockLocate.m_State = STATE_NO_BLOCK;

    screen->BlockLocate.m_Command = BLOCK_ABORT;
    Panel->m_Parent->HandleBlockEnd( DC );

    screen->BlockLocate.m_Command = BLOCK_IDLE;
    Panel->m_Parent->DisplayToolMsg( wxEmptyString );
}


/*************************************************************************/
void InitBlockLocateDatas( WinEDA_DrawPanel* Panel, const wxPoint& startpos )
/*************************************************************************/

/*
 *  Init the initial values of a BlockLocate, before starting a block command
 */
{
    BASE_SCREEN* screen = Panel->GetScreen();

    screen->BlockLocate.m_State = STATE_BLOCK_INIT;
    screen->BlockLocate.SetOrigin( startpos );
    screen->BlockLocate.SetSize( wxSize( 0, 0 ) );
    screen->BlockLocate.SetNext( NULL );
    screen->BlockLocate.m_BlockDrawStruct = NULL;
    Panel->ManageCurseur = DrawAndSizingBlockOutlines;
    Panel->ForceCloseManageCurseur = AbortBlockCurrentCommand;
}


/********************************************************************************/
/********************************************************************************/
void DrawAndSizingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
void DrawAndSizingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/********************************************************************************/
/********************************************************************************/


/* Redraw the outlines of the block which shows the search area for block commands
/* Redraw the outlines of the block which shows the search area for block commands
 *  The first point of the rectangle showing the area is initialised
 *  The first point of the rectangle showing the area is initialised
 *  by InitBlockLocateDatas().
 *  by Initm_BlockLocateDatas().
 *  The other point of the rectangle is the mouse cursor
 *  The other point of the rectangle is the mouse cursor
 */
 */
{
{
    DrawBlockStruct* PtBlock;
    BLOCK_SELECTOR* PtBlock;


    PtBlock = &panel->GetScreen()->BlockLocate;
    PtBlock = &panel->GetScreen()->m_BlockLocate;


    PtBlock->m_MoveVector = wxPoint( 0, 0 );
    PtBlock->m_MoveVector = wxPoint( 0, 0 );


    GRSetDrawMode( DC, g_XorMode );

    /* Effacement ancien cadre */
    /* Effacement ancien cadre */
    if( erase )
    if( erase )
        PtBlock->Draw( panel, DC );
        PtBlock->Draw( panel, DC, wxPoint( 0, 0 ), g_XorMode, PtBlock->m_Color );


    PtBlock->m_BlockLastCursorPosition = panel->GetScreen()->m_Curseur;
    PtBlock->m_BlockLastCursorPosition = panel->GetScreen()->m_Curseur;
    PtBlock->SetEnd( panel->GetScreen()->m_Curseur );
    PtBlock->SetEnd( panel->GetScreen()->m_Curseur );


    PtBlock->Draw( panel, DC );
    PtBlock->Draw( panel, DC, wxPoint( 0, 0 ), g_XorMode, PtBlock->m_Color );


    if( PtBlock->m_State == STATE_BLOCK_INIT )
    if( PtBlock->m_State == STATE_BLOCK_INIT )
    {
    {
@@ -300,3 +282,37 @@ void DrawAndSizingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
            PtBlock->m_State = STATE_BLOCK_END;
            PtBlock->m_State = STATE_BLOCK_END;
    }
    }
}
}


/******************************************************************/
void AbortBlockCurrentCommand( WinEDA_DrawPanel* Panel, wxDC* DC )
/******************************************************************/

/*
 *  Cancel Current block operation.
 */
{
    BASE_SCREEN* screen = Panel->GetScreen();

    if( Panel->ManageCurseur )                      /* Erase current drawing on screen */
    {
        Panel->ManageCurseur( Panel, DC, FALSE );   /* Efface dessin fantome */
        Panel->ManageCurseur = NULL;
        Panel->ForceCloseManageCurseur = NULL;
        screen->SetCurItem( NULL );

        /* Delete the picked wrapper if this is a picked list. */
        if( screen->m_BlockLocate.m_Command != BLOCK_PASTE )
            screen->m_BlockLocate.ClearItemsList();
    }

    screen->m_BlockLocate.m_Flags = 0;
    screen->m_BlockLocate.m_State = STATE_NO_BLOCK;

    screen->m_BlockLocate.m_Command = BLOCK_ABORT;
    Panel->m_Parent->HandleBlockEnd( DC );

    screen->m_BlockLocate.m_Command = BLOCK_IDLE;
    Panel->m_Parent->DisplayToolMsg( wxEmptyString );
}
+22 −0
Original line number Original line Diff line number Diff line
@@ -67,6 +67,14 @@ void PICKED_ITEMS_LIST::PICKED_ITEMS_LIST::ClearItemsList()
    m_ItemsList.clear();
    m_ItemsList.clear();
}
}


void PICKED_ITEMS_LIST::ClearListAndDeleteItems()
{
    for(unsigned ii = 0; ii < m_ItemsList.size(); ii++ )
        delete m_ItemsList[ii].m_Item;
    m_ItemsList.clear();
}


ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx )
ITEM_PICKER PICKED_ITEMS_LIST::GetItemWrapper( unsigned int aIdx )
{
{
    ITEM_PICKER picker;
    ITEM_PICKER picker;
@@ -160,6 +168,20 @@ bool PICKED_ITEMS_LIST::RemoveItem( unsigned aIdx )
    return true;
    return true;
}
}


/** Function CopyList
 * copy all data from aSource
 * Items picked are not copied. just pointer on them are copied
 */
void PICKED_ITEMS_LIST::CopyList(const PICKED_ITEMS_LIST & aSource)
{
    ITEM_PICKER picker;
    for(unsigned ii = 0; ii < aSource.GetCount(); ii++ )
    {
        picker = aSource.m_ItemsList[ii];
        PushItem(picker);
    }
}



/**********************************************/
/**********************************************/
/********** UNDO_REDO_CONTAINER ***************/
/********** UNDO_REDO_CONTAINER ***************/
+6 −6
Original line number Original line Diff line number Diff line
@@ -35,7 +35,7 @@ void WinEDA_DrawFrame::CopyToClipboard( wxCommandEvent& event )


    if(  event.GetId() == ID_GEN_COPY_BLOCK_TO_CLIPBOARD )
    if(  event.GetId() == ID_GEN_COPY_BLOCK_TO_CLIPBOARD )
    {
    {
        if( GetBaseScreen()->BlockLocate.m_Command != BLOCK_IDLE )
        if( GetBaseScreen()->m_BlockLocate.m_Command != BLOCK_IDLE )
            DrawPanel->SetCursor( wxCursor( DrawPanel->m_PanelCursor =
            DrawPanel->SetCursor( wxCursor( DrawPanel->m_PanelCursor =
                        DrawPanel->m_PanelDefaultCursor ) );
                        DrawPanel->m_PanelDefaultCursor ) );


@@ -74,13 +74,13 @@ bool DrawPage( WinEDA_DrawPanel* panel )
    /* scale is the ratio resolution/internal units */
    /* scale is the ratio resolution/internal units */
    float   scale = 82.0 / panel->m_Parent->m_InternalUnits;
    float   scale = 82.0 / panel->m_Parent->m_InternalUnits;


    if( ActiveScreen->BlockLocate.m_Command != BLOCK_IDLE )
    if( ActiveScreen->m_BlockLocate.m_Command != BLOCK_IDLE )
    {
    {
        DrawBlock = TRUE;
        DrawBlock = TRUE;
        DrawArea.SetX( (int) ( ActiveScreen->BlockLocate.GetX() ) );
        DrawArea.SetX( ActiveScreen->m_BlockLocate.GetX() );
        DrawArea.SetY( (int) ( ActiveScreen->BlockLocate.GetY() ) );
        DrawArea.SetY( ActiveScreen->m_BlockLocate.GetY() );
        DrawArea.SetWidth( (int) ( ActiveScreen->BlockLocate.GetWidth() ) );
        DrawArea.SetWidth( ActiveScreen->m_BlockLocate.GetWidth() );
        DrawArea.SetHeight( (int) ( ActiveScreen->BlockLocate.GetHeight() ) );
        DrawArea.SetHeight( ActiveScreen->m_BlockLocate.GetHeight() );
    }
    }


    /* modification des cadrages et reglages locaux */
    /* modification des cadrages et reglages locaux */
+44 −10
Original line number Original line Diff line number Diff line
@@ -488,7 +488,7 @@ int WinEDA_DrawFrame::ReturnBlockCommand( int key )


void WinEDA_DrawFrame::InitBlockPasteInfos()
void WinEDA_DrawFrame::InitBlockPasteInfos()
{
{
    GetBaseScreen()->BlockLocate.m_BlockDrawStruct = NULL;
    GetBaseScreen()->m_BlockLocate.ClearItemsList();
    DrawPanel->ManageCurseur = NULL;
    DrawPanel->ManageCurseur = NULL;
}
}


@@ -652,7 +652,31 @@ void WinEDA_DrawFrame::SetLanguage( wxCommandEvent& event )
    }
    }
}
}


/* used in UpdateStatusBar() when coordinates are in mm
 * try to approximate a coordinate (in 0.001 mm) to an easy to read number
 * ie round the unit value to 0 if unit is 1 or 2, or 8 or 9
 */
double Round_To_0(double x)
{
    long long ix = wxRound(x * 1000); // ix is in 0.001 mm
    if ( x < 0 ) NEGATE(ix);

    int remainder = ix%10;  // remainder is in 0.001 mm
    if ( remainder <= 2 )
        ix -= remainder;    // truncate to the near number
    else if (remainder >= 8 )
        ix += 10 - remainder;   // round to near number


    if ( x < 0 ) NEGATE(ix);
    return (double)ix/1000.0;
}

/** Function UpdateStatusBar()
 * Displays in the bottom of the main window a stust:
 *  - Absolute Cursor coordinates
 *  - Relative Cursor coordinates (relative to the last coordinate stored when actiavte the space bar)
 * ( in this status is also displayed the zoom level, but this is not made by this function)
 */
void WinEDA_DrawFrame::UpdateStatusBar()
void WinEDA_DrawFrame::UpdateStatusBar()
{
{
    wxString        Line;
    wxString        Line;
@@ -670,20 +694,30 @@ void WinEDA_DrawFrame::UpdateStatusBar()
    SetStatusText( Line, 1 );
    SetStatusText( Line, 1 );


    /* Display absolute coordinates:  */
    /* Display absolute coordinates:  */
    Line.Printf( g_UnitMetric ? wxT( "X %.3f  Y %.3f" ) : wxT( "X %.4f  Y %.4f" ),
    double dXpos = To_User_Unit( g_UnitMetric, screen->m_Curseur.x, m_InternalUnits );
                 To_User_Unit( g_UnitMetric, screen->m_Curseur.x,
    double dYpos = To_User_Unit( g_UnitMetric, screen->m_Curseur.y, m_InternalUnits );
                               m_InternalUnits ),
    /* When using mm the conversion from 1/10000 inch to mm can give some non easy to read numbers,
                 To_User_Unit( g_UnitMetric, screen->m_Curseur.y,
     * like 1.999 or 2.001 that be better if displayed 2.000, so small diffs are filtered here.
                               m_InternalUnits ) );
    */
    if ( g_UnitMetric )
    {
        dXpos = Round_To_0(dXpos);
        dYpos = Round_To_0(dYpos);
    }
    Line.Printf( g_UnitMetric ? wxT( "X %.3f  Y %.3f" ) : wxT( "X %.4f  Y %.4f" ), dXpos, dYpos );
    SetStatusText( Line, 2 );
    SetStatusText( Line, 2 );


    /* Display relative coordinates:  */
    /* Display relative coordinates:  */
    dx = screen->m_Curseur.x - screen->m_O_Curseur.x;
    dx = screen->m_Curseur.x - screen->m_O_Curseur.x;
    dy = screen->m_Curseur.y - screen->m_O_Curseur.y;
    dy = screen->m_Curseur.y - screen->m_O_Curseur.y;

    dXpos = To_User_Unit( g_UnitMetric, dx, m_InternalUnits );
    Line.Printf( g_UnitMetric ? wxT( "x %.3f  y %.3f" ) : wxT( "x %.4f  y %.4f" ),
    dYpos = To_User_Unit( g_UnitMetric, dy, m_InternalUnits );
                 To_User_Unit( g_UnitMetric, dx, m_InternalUnits ),
    if ( g_UnitMetric )
                 To_User_Unit( g_UnitMetric, dy, m_InternalUnits ) );
    {
        dXpos = Round_To_0(dXpos);
        dYpos = Round_To_0(dYpos);
    }
    Line.Printf( g_UnitMetric ? wxT( "x %.3f  y %.3f" ) : wxT( "x %.4f  y %.4f" ), dXpos, dYpos );


    SetStatusText( Line, 3 );
    SetStatusText( Line, 3 );
}
}
Loading