/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file block_commande.cpp * @brief Common routines for managing on block commands. */ #include #include #include #include #include #include #include #include #include #include BLOCK_SELECTOR::BLOCK_SELECTOR() : EDA_ITEM( BLOCK_LOCATE_STRUCT_TYPE ), EDA_RECT() { m_State = STATE_NO_BLOCK; /* State (enum BlockState) of block. */ m_Command = BLOCK_IDLE; /* Type (enum CmdBlockType) of operation. */ m_Color = BROWN; } BLOCK_SELECTOR::~BLOCK_SELECTOR() { } /* * Print block command message (Block move, Block copy ...) in status bar */ void BLOCK_SELECTOR::SetMessageBlock( EDA_DRAW_FRAME* frame ) { wxString msg; switch( m_Command ) { case BLOCK_IDLE: break; case BLOCK_MOVE: /* Move */ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ msg = _( "Block Move" ); break; case BLOCK_DRAG: /* Drag */ msg = _( "Block Drag" ); break; case BLOCK_COPY: /* Copy */ msg = _( "Block Copy" ); break; case BLOCK_DELETE: /* Delete */ msg = _( "Block Delete" ); break; case BLOCK_SAVE: /* Save */ msg = _( "Block Save" ); break; case BLOCK_PASTE: msg = _( "Block Paste" ); break; case BLOCK_ZOOM: /* Window Zoom */ msg = _( "Win Zoom" ); break; case BLOCK_ROTATE: /* Rotate 90 deg */ msg = _( "Block Rotate" ); break; case BLOCK_FLIP: /* Flip */ msg = _( "Block Flip" ); break; case BLOCK_MIRROR_X: case BLOCK_MIRROR_Y: /* mirror */ msg = _( "Block Mirror" ); break; case BLOCK_ABORT: break; default: msg = wxT( "????" ); break; } frame->DisplayToolMsg( msg ); } void BLOCK_SELECTOR::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, int aDrawMode, int aColor ) { int w = GetWidth(); int h = GetHeight(); GRSetDrawMode( aDC, aDrawMode ); if( w == 0 || h == 0 ) GRLine( aPanel->GetClipBox(), aDC, GetX() + aOffset.x, GetY() + aOffset.y, GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor ); else GRRect( aPanel->GetClipBox(), aDC, GetX() + aOffset.x, GetY() + aOffset.y, GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor ); } /** * Function InitData * Init the initial values of a BLOCK_SELECTOR, before starting a block command */ void BLOCK_SELECTOR::InitData( EDA_DRAW_PANEL* aPanel, const wxPoint& startpos ) { m_State = STATE_BLOCK_INIT; SetOrigin( startpos ); SetSize( wxSize( 0, 0 ) ); m_ItemsSelection.ClearItemsList(); aPanel->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand ); } /** * Function ClearItemsList * delete only the list of EDA_ITEM * pointers, NOT the pointed data * itself */ void BLOCK_SELECTOR::ClearItemsList() { m_ItemsSelection.ClearItemsList(); } /** * Function ClearListAndDeleteItems * delete only the list of EDA_ITEM * 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 ); } void BLOCK_SELECTOR::Clear() { if( m_Command != BLOCK_IDLE ) { m_Flags = 0; m_Command = BLOCK_IDLE; m_State = STATE_NO_BLOCK; ClearItemsList(); } } /* First command block function: * Init the Block infos: command type, initial position, and other variables.. */ bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* DC, int key, const wxPoint& startpos ) { BLOCK_SELECTOR* Block = &GetScreen()->m_BlockLocate; if( ( Block->m_Command != BLOCK_IDLE ) || ( Block->m_State != STATE_NO_BLOCK ) ) return false; Block->ClearFlags(); Block->m_Command = (CmdBlockType) ReturnBlockCommand( key ); if( Block->m_Command == 0 ) return false; switch( Block->m_Command ) { case BLOCK_IDLE: break; case BLOCK_MOVE: /* Move */ case BLOCK_DRAG: /* Drag */ case BLOCK_COPY: /* Copy */ case BLOCK_DELETE: /* Delete */ case BLOCK_SAVE: /* Save */ case BLOCK_ROTATE: /* Rotate 90 deg */ case BLOCK_FLIP: /* Flip */ case BLOCK_ZOOM: /* Window Zoom */ case BLOCK_MIRROR_X: case BLOCK_MIRROR_Y: /* mirror */ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ Block->InitData( m_canvas, startpos ); break; case BLOCK_PASTE: Block->InitData( m_canvas, startpos ); Block->m_BlockLastCursorPosition.x = 0; Block->m_BlockLastCursorPosition.y = 0; InitBlockPasteInfos(); if( Block->m_ItemsSelection.GetCount() == 0 ) /* No data to paste */ { DisplayError( this, wxT( "No Block to paste" ), 20 ); GetScreen()->m_BlockLocate.m_Command = BLOCK_IDLE; m_canvas->SetMouseCaptureCallback( NULL ); return true; } if( !m_canvas->IsMouseCaptured() ) { Block->m_ItemsSelection.ClearItemsList(); DisplayError( this, wxT( "EDA_DRAW_FRAME::HandleBlockBegin() Err: m_mouseCaptureCallback NULL" ) ); return true; } Block->m_State = STATE_BLOCK_MOVE; m_canvas->CallMouseCapture( DC, startpos, false ); break; default: { wxString msg; msg << wxT( "EDA_DRAW_FRAME::HandleBlockBegin() error: Unknown command " ) << Block->m_Command; DisplayError( this, msg ); } break; } Block->SetMessageBlock( this ); return true; } /* 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 * by Initm_BlockLocateDatas(). * The other point of the rectangle is the mouse cursor */ void DrawAndSizingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { BLOCK_SELECTOR* PtBlock; PtBlock = &aPanel->GetScreen()->m_BlockLocate; PtBlock->m_MoveVector = wxPoint( 0, 0 ); if( aErase ) PtBlock->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, PtBlock->m_Color ); PtBlock->m_BlockLastCursorPosition = aPanel->GetScreen()->GetCrossHairPosition(); PtBlock->SetEnd( aPanel->GetScreen()->GetCrossHairPosition() ); PtBlock->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, PtBlock->m_Color ); if( PtBlock->m_State == STATE_BLOCK_INIT ) { if( PtBlock->GetWidth() || PtBlock->GetHeight() ) /* 2nd point exists: the rectangle is not surface anywhere */ PtBlock->m_State = STATE_BLOCK_END; } } /* * Cancel Current block operation. */ void AbortBlockCurrentCommand( EDA_DRAW_PANEL* Panel, wxDC* DC ) { BASE_SCREEN* screen = Panel->GetScreen(); if( Panel->IsMouseCaptured() ) /* Erase current drawing on screen */ { /* Clear block outline. */ Panel->CallMouseCapture( DC, wxDefaultPosition, false ); Panel->SetMouseCapture( NULL, 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.ClearFlags(); screen->m_BlockLocate.m_State = STATE_NO_BLOCK; screen->m_BlockLocate.m_Command = BLOCK_ABORT; Panel->GetParent()->HandleBlockEnd( DC ); screen->m_BlockLocate.m_Command = BLOCK_IDLE; Panel->GetParent()->DisplayToolMsg( wxEmptyString ); Panel->SetCursor( Panel->GetCurrentCursor() ); }