kicad/eeschema/block.cpp

1783 lines
57 KiB
C++

/****************************************************/
/* BLOCK.CPP */
/* Gestion des Operations sur Blocks et Effacements */
/****************************************************/
#include "fctsys.h"
#include "appl_wxstruct.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "confirm.h"
#include "block_commande.h"
#include "class_drawpickedstruct.h"
#include "program.h"
#include "libcmp.h"
#include "general.h"
#include "protos.h"
/* Variables Locales */
/* Fonctions exportees */
/* Fonctions Locales */
static SCH_ITEM* CopyStruct( WinEDA_DrawPanel* panel,
wxDC* DC,
BASE_SCREEN* screen,
SCH_ITEM* DrawStruct );
static void CollectStructsToDrag( SCH_SCREEN* screen );
static void AddPickedItem( SCH_SCREEN* screen, wxPoint aPosition );
static LibEDA_BaseStruct* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem,
wxPoint& aPosition );
static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel,
wxDC* DC,
bool erase );
static SCH_ITEM* SaveStructListForPaste( SCH_ITEM* DrawStruct );
static bool MirrorStruct( WinEDA_DrawPanel* panel, wxDC* DC,
SCH_ITEM* DrawStruct, wxPoint& Center );
static void MirrorOneStruct( SCH_ITEM* DrawStruct,
wxPoint& Center );
/*************************************************************************/
int WinEDA_SchematicFrame::ReturnBlockCommand( int key )
/*************************************************************************/
/* Return the block command (BLOCK_MOVE, BLOCK_COPY...) corresponding to
* the key (ALT, SHIFT ALT ..)
*/
{
int cmd;
switch( key )
{
default:
cmd = key & 0xFF;
break;
case 0:
cmd = BLOCK_MOVE;
break;
case GR_KB_ALT:
case GR_KB_SHIFT:
cmd = BLOCK_COPY;
break;
case GR_KB_CTRL:
cmd = BLOCK_DRAG;
break;
case GR_KB_SHIFTCTRL:
cmd = BLOCK_DELETE;
break;
case MOUSE_MIDDLE:
cmd = BLOCK_ZOOM;
break;
}
return cmd;
}
/*************************************************/
void WinEDA_SchematicFrame::InitBlockPasteInfos()
/*************************************************/
/* Init the parameters used by the block paste command
*/
{
DrawBlockStruct* block = &GetScreen()->BlockLocate;
block->m_BlockDrawStruct = g_BlockSaveDataList;
DrawPanel->ManageCurseur = DrawMovingBlockOutlines;
}
/******************************************************/
void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC )
/******************************************************/
/* Routine to handle the BLOCK PLACE commande
* Last routine for block operation for:
* - block move & drag
* - block copie & paste
*/
{
bool err = FALSE;
DrawBlockStruct* block = &GetScreen()->BlockLocate;
SCH_ITEM* NewStruct = NULL;
if( DrawPanel->ManageCurseur == NULL )
{
err = TRUE;
DisplayError( this, wxT( "HandleBlockPLace() : ManageCurseur = NULL" ) );
}
if( block->m_BlockDrawStruct == NULL )
{
wxString msg;
err = TRUE;
msg.Printf( wxT( "HandleBlockPLace() : m_BlockDrawStruct = " \
"NULL (cmd %d, state %d)" ),
block->m_Command, block->m_State );
DisplayError( this, msg );
}
block->m_State = STATE_BLOCK_STOP;
switch( block->m_Command )
{
case BLOCK_IDLE:
err = TRUE;
break;
case BLOCK_DRAG: /* Drag */
case BLOCK_MOVE: /* Move */
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
SaveCopyInUndoList( (SCH_ITEM*) block->m_BlockDrawStruct, IS_CHANGED );
MoveStruct( DrawPanel, DC, (SCH_ITEM*) block->m_BlockDrawStruct );
block->m_BlockDrawStruct = NULL;
DrawPanel->Refresh( TRUE );
break;
case BLOCK_COPY: /* Copy */
case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
NewStruct = CopyStruct( DrawPanel, DC,
GetScreen(),
(SCH_ITEM*) block->m_BlockDrawStruct );
SaveCopyInUndoList(
NewStruct,
(block->m_Command ==
BLOCK_PRESELECT_MOVE) ? IS_CHANGED : IS_NEW );
block->m_BlockDrawStruct = NULL;
break;
case BLOCK_PASTE: /* Paste (recopie du dernier bloc sauve */
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
PasteStruct( DC );
block->m_BlockDrawStruct = NULL;
break;
case BLOCK_ZOOM: // Handled by HandleBlockEnd()
case BLOCK_DELETE:
case BLOCK_SAVE:
case BLOCK_ROTATE:
case BLOCK_MIRROR_X:
case BLOCK_MIRROR_Y:
case BLOCK_INVERT:
case BLOCK_ABORT:
case BLOCK_SELECT_ITEMS_ONLY:
break;
}
GetScreen()->SetModify();
/* clear struct.m_Flags */
SCH_ITEM* Struct;
for( Struct = GetScreen()->EEDrawList; Struct != NULL; Struct = Struct->Next() )
Struct->m_Flags = 0;
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
block->m_Flags = 0;
block->m_State = STATE_NO_BLOCK;
block->m_Command = BLOCK_IDLE;
GetScreen()->SetCurItem( NULL );
TestDanglingEnds( GetScreen()->EEDrawList, DC );
if( block->m_BlockDrawStruct )
{
DisplayError( this,
wxT( "HandleBlockPLace() error: DrawStruct != Null" ) );
block->m_BlockDrawStruct = NULL;
}
SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString );
}
/****************************************************/
int WinEDA_SchematicFrame::HandleBlockEnd( wxDC* DC )
/****************************************************/
/* Routine de gestion de la commande BLOCK END
* retourne :
* 0 si aucun composant selectionne
* 1 sinon
* -1 si commande terminee et composants trouves (block delete, block save)
*/
{
int ii = 0;
bool zoom_command = FALSE;
DrawBlockStruct* block = &GetScreen()->BlockLocate;
if( block->m_BlockDrawStruct )
{
BlockState state = block->m_State;
CmdBlockType command = block->m_Command;
if( DrawPanel->ForceCloseManageCurseur )
DrawPanel->ForceCloseManageCurseur( DrawPanel, DC );
block->m_State = state;
block->m_Command = command;
DrawPanel->ManageCurseur = DrawAndSizingBlockOutlines;
DrawPanel->ForceCloseManageCurseur = AbortBlockCurrentCommand;
GetScreen()->m_Curseur.x = block->GetRight();
GetScreen()->m_Curseur.y = block->GetBottom();
if( block->m_Command != BLOCK_ABORT )
DrawPanel->MouseToCursorSchema();
}
if( DrawPanel->ManageCurseur != NULL )
switch( block->m_Command )
{
case BLOCK_IDLE:
DisplayError( this, wxT( "Error in HandleBlockPLace()" ) );
break;
case BLOCK_DRAG: /* Drag */
BreakSegmentOnJunction( (SCH_SCREEN*) GetScreen() );
case BLOCK_MOVE: /* Move */
case BLOCK_COPY: /* Copy */
block->m_BlockDrawStruct =
PickStruct( GetScreen()->BlockLocate, GetScreen(), SEARCHALL );
case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/
if( block->m_BlockDrawStruct != NULL )
{
ii = 1;
CollectStructsToDrag( (SCH_SCREEN*) GetScreen() );
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
DrawPanel->ManageCurseur = DrawMovingBlockOutlines;
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
block->m_State = STATE_BLOCK_MOVE;
}
else
{
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
}
break;
case BLOCK_DELETE: /* Delete */
block->m_BlockDrawStruct =
PickStruct( GetScreen()->BlockLocate,
GetScreen(), SEARCHALL );
DrawAndSizingBlockOutlines( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct != NULL )
{
ii = -1;
DeleteStruct( DrawPanel,
DC,
(SCH_ITEM*) block->m_BlockDrawStruct );
GetScreen()->SetModify();
}
block->m_BlockDrawStruct = NULL;
TestDanglingEnds( GetScreen()->EEDrawList, DC );
break;
case BLOCK_SAVE: /* Save */
block->m_BlockDrawStruct =
PickStruct( GetScreen()->BlockLocate,
GetScreen(), SEARCHALL );
DrawAndSizingBlockOutlines( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct != NULL )
{
wxPoint oldpos = GetScreen()->m_Curseur;
GetScreen()->m_Curseur = wxPoint( 0, 0 );
SCH_ITEM* DrawStructCopy =
SaveStructListForPaste(
(SCH_ITEM*) block->m_BlockDrawStruct );
PlaceStruct( GetScreen(), DrawStructCopy );
GetScreen()->m_Curseur = oldpos;
ii = -1;
}
block->m_BlockDrawStruct = NULL;
break;
case BLOCK_PASTE:
block->m_State = STATE_BLOCK_MOVE;
break;
case BLOCK_INVERT: /* pcbnew only! */
break;
case BLOCK_ROTATE:
case BLOCK_MIRROR_X:
case BLOCK_MIRROR_Y:
break;
case BLOCK_ZOOM: /* Window Zoom */
zoom_command = TRUE;
break;
case BLOCK_SELECT_ITEMS_ONLY: /* Not used */
case BLOCK_ABORT: /* not executed here */
break;
}
if( block->m_Command == BLOCK_ABORT )
{ /* clear struct.m_Flags */
EDA_BaseStruct* Struct;
for( Struct = GetScreen()->EEDrawList;
Struct != NULL;
Struct = Struct->Next() )
Struct->m_Flags = 0;
}
if( ii <= 0 )
{
block->m_Flags = 0;
block->m_State = STATE_NO_BLOCK;
block->m_Command = BLOCK_IDLE;
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
GetScreen()->SetCurItem( NULL );
SetToolID( m_ID_current_state,
DrawPanel->m_PanelDefaultCursor,
wxEmptyString );
}
if( zoom_command )
Window_Zoom( GetScreen()->BlockLocate );
return ii;
}
/***********************************************************************/
void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC )
/***********************************************************************/
/* Routine de gestion de la commande BLOCK END by PopUp
* Appelee apres HandleBlockEnd.
* A partir de la commande bloc move, peut executer une commande autre que bloc move.
*/
{
int ii = 0;
DrawBlockStruct* block = &GetScreen()->BlockLocate;
if( block->m_Command != BLOCK_MOVE )
return;
if( Command == BLOCK_MOVE )
return;
block->m_Command = (CmdBlockType) Command;
block->SetMessageBlock( this );
switch( block->m_Command )
{
case BLOCK_COPY: /* move to copy */
block->m_State = STATE_BLOCK_MOVE;
ii = 1;
break;
case BLOCK_DRAG: /* move to Drag */
/* Effacement de la liste des structures de pointage,
* qui est devenue erronnee */
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct )
{
if( block->m_BlockDrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{ /* Delete the picked wrapper if this is a picked list. */
DrawPickedStruct* PickedList;
PickedList = (DrawPickedStruct*) block->m_BlockDrawStruct;
PickedList->DeleteWrapperList();
}
block->m_BlockDrawStruct = NULL;
}
BreakSegmentOnJunction( (SCH_SCREEN*) GetScreen() );
block->m_BlockDrawStruct =
PickStruct( GetScreen()->BlockLocate,
GetScreen(), SEARCHALL );
if( block->m_BlockDrawStruct != NULL )
{
ii = 1;
CollectStructsToDrag( (SCH_SCREEN*) GetScreen() );
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
block->m_State = STATE_BLOCK_MOVE;
}
break;
case BLOCK_DELETE: /* move to Delete */
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct != NULL )
{
ii = -1;
DeleteStruct( DrawPanel, DC, (SCH_ITEM*) block->m_BlockDrawStruct );
GetScreen()->SetModify();
}
TestDanglingEnds( GetScreen()->EEDrawList, DC );
break;
case BLOCK_SAVE: /* Save */
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct != NULL )
{
wxPoint oldpos = GetScreen()->m_Curseur;
GetScreen()->m_Curseur = wxPoint( 0, 0 );
SCH_ITEM* DrawStructCopy =
SaveStructListForPaste( (SCH_ITEM*) block->m_BlockDrawStruct );
PlaceStruct( GetScreen(), DrawStructCopy );
GetScreen()->m_Curseur = oldpos;
ii = -1;
}
break;
case BLOCK_ZOOM: /* Window Zoom */
DrawPanel->ForceCloseManageCurseur( DrawPanel, DC );
DrawPanel->SetCursor(
DrawPanel->m_PanelCursor = DrawPanel->m_PanelDefaultCursor );
Window_Zoom( GetScreen()->BlockLocate );
break;
case BLOCK_ROTATE:
break;
case BLOCK_MIRROR_X:
case BLOCK_MIRROR_Y:
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
if( block->m_BlockDrawStruct != NULL )
{
SaveCopyInUndoList( (SCH_ITEM*) block->m_BlockDrawStruct,
IS_CHANGED );
ii = -1;
/* Compute the mirror centre and put it on grid */
wxPoint Center = block->Centre();
PutOnGrid( &Center );
MirrorStruct( DrawPanel,
DC,
(SCH_ITEM*) block->m_BlockDrawStruct,
Center );
GetScreen()->SetModify();
}
TestDanglingEnds( GetScreen()->EEDrawList, DC );
break;
default:
break;
}
if( ii <= 0 )
{
block->m_BlockDrawStruct = NULL;
block->m_Flags = 0;
block->m_State = STATE_NO_BLOCK;
block->m_Command = BLOCK_IDLE;
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
GetScreen()->SetCurItem( NULL );
SetToolID( m_ID_current_state,
DrawPanel->m_PanelDefaultCursor,
wxEmptyString );
}
}
/************************************************************************/
static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC,
bool erase )
/************************************************************************/
/* Retrace le contour du block de recherche de structures
* L'ensemble du block suit le curseur
*/
{
DrawBlockStruct* PtBlock;
DrawPickedStruct* PickedList;
BASE_SCREEN* screen = panel->GetScreen();
PtBlock = &panel->GetScreen()->BlockLocate;
GRSetDrawMode( DC, g_XorMode );
/* Effacement ancien cadre */
if( erase && PtBlock->m_BlockDrawStruct )
{
PtBlock->Offset( PtBlock->m_MoveVector );
PtBlock->Draw( panel, DC );
PtBlock->Offset( -PtBlock->m_MoveVector.x, -PtBlock->m_MoveVector.y );
/* Effacement ancien affichage */
if( PtBlock->m_BlockDrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
PickedList = (DrawPickedStruct*) PtBlock->m_BlockDrawStruct;
while( PickedList )
{
DrawStructsInGhost( panel,
DC,
(SCH_ITEM*) PickedList->m_PickedStruct,
PtBlock->m_MoveVector.x,
PtBlock->m_MoveVector.y );
PickedList = (DrawPickedStruct*) PickedList->Next();
}
}
else
DrawStructsInGhost( panel,
DC,
(SCH_ITEM*) PtBlock->m_BlockDrawStruct,
PtBlock->m_MoveVector.x,
PtBlock->m_MoveVector.y );
}
/* Redessin nouvel affichage */
PtBlock->m_MoveVector.x = screen->m_Curseur.x -
PtBlock->m_BlockLastCursorPosition.x;
PtBlock->m_MoveVector.y = screen->m_Curseur.y -
PtBlock->m_BlockLastCursorPosition.y;
GRSetDrawMode( DC, g_XorMode );
PtBlock->Offset( PtBlock->m_MoveVector );
PtBlock->Draw( panel, DC );
PtBlock->Offset( -PtBlock->m_MoveVector.x, -PtBlock->m_MoveVector.y );
if( PtBlock->m_BlockDrawStruct )
{
if( PtBlock->m_BlockDrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
PickedList = (DrawPickedStruct*) PtBlock->m_BlockDrawStruct;
while( PickedList )
{
DrawStructsInGhost( panel,
DC,
(SCH_ITEM*) PickedList->m_PickedStruct,
PtBlock->m_MoveVector.x,
PtBlock->m_MoveVector.y );
PickedList = (DrawPickedStruct*) PickedList->Next();
}
}
else
DrawStructsInGhost( panel,
DC,
(SCH_ITEM*) PtBlock->m_BlockDrawStruct,
PtBlock->m_MoveVector.x,
PtBlock->m_MoveVector.y );
}
}
/*****************************************************************************
* Routine to move an object(s) to a new position. *
* If DrawStruct is of type DrawPickedStruct, a list of objects picked is *
* assumed, otherwise exactly one structure is assumed been picked. *
*****************************************************************************/
bool MoveStruct( WinEDA_DrawPanel* panel, wxDC* DC, SCH_ITEM* DrawStruct )
{
if( !DrawStruct )
return FALSE;
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
DrawPickedStruct* pickedList = (DrawPickedStruct*) DrawStruct;
if( DC )
panel->PostDirtyRect( pickedList->GetBoundingBoxUnion() );
PlaceStruct( panel->GetScreen(), (SCH_ITEM *) pickedList ); // Place it in its new position.
if( DC )
RedrawStructList( panel, DC, (SCH_ITEM *) pickedList,
GR_DEFAULT_DRAWMODE );
// Free the wrapper DrawPickedStruct chain
pickedList->DeleteWrapperList();
}
else
{
if( DC )
panel->PostDirtyRect( DrawStruct->GetBoundingBox() );
PlaceStruct( panel->GetScreen(), DrawStruct ); /* Place it in its new position. */
if( DC )
RedrawOneStruct( panel, DC, DrawStruct, GR_DEFAULT_DRAWMODE );
}
return TRUE;
}
static void MirrorYPoint( wxPoint& point, wxPoint& Center )
{
point.x -= Center.x;
point.x = -point.x;
point.x += Center.x;
}
/**************************************************************/
void MirrorOneStruct( SCH_ITEM* DrawStruct, wxPoint& Center )
/**************************************************************/
/* Given a structure rotate it to 90 degrees refer to the Center point.
*/
{
int dx;
DrawPolylineStruct* DrawPoly;
DrawJunctionStruct* DrawConnect;
EDA_DrawLineStruct* DrawSegment;
DrawBusEntryStruct* DrawRaccord;
SCH_COMPONENT* DrawLibItem;
DrawSheetStruct* DrawSheet;
Hierarchical_PIN_Sheet_Struct* DrawSheetLabel;
DrawMarkerStruct* DrawMarker;
DrawNoConnectStruct* DrawNoConnect;
SCH_TEXT* DrawText;
wxPoint px;
WinEDA_SchematicFrame* frame;
if( !DrawStruct )
return;
frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow();
switch( DrawStruct->Type() )
{
case TYPE_NOT_INIT:
break;
case DRAW_POLYLINE_STRUCT_TYPE:
DrawPoly = (DrawPolylineStruct*) DrawStruct;
for( unsigned ii = 0; ii < DrawPoly->GetCornerCount(); ii++ )
{
wxPoint point;
point = DrawPoly->m_PolyPoints[ii];
MirrorYPoint( point, Center );
DrawPoly->m_PolyPoints[ii] = point;
}
break;
case DRAW_SEGMENT_STRUCT_TYPE:
DrawSegment = (EDA_DrawLineStruct*) DrawStruct;
if( (DrawSegment->m_Flags & STARTPOINT) == 0 )
{
MirrorYPoint( DrawSegment->m_Start, Center );
}
if( (DrawSegment->m_Flags & ENDPOINT) == 0 )
{
MirrorYPoint( DrawSegment->m_End, Center );
}
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
DrawRaccord = (DrawBusEntryStruct*) DrawStruct;
MirrorYPoint( DrawRaccord->m_Pos, Center );
break;
case DRAW_JUNCTION_STRUCT_TYPE:
DrawConnect = (DrawJunctionStruct*) DrawStruct;
MirrorYPoint( DrawConnect->m_Pos, Center );
break;
case DRAW_MARKER_STRUCT_TYPE:
DrawMarker = (DrawMarkerStruct*) DrawStruct;
MirrorYPoint( DrawMarker->m_Pos, Center );
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
DrawNoConnect = (DrawNoConnectStruct*) DrawStruct;
MirrorYPoint( DrawNoConnect->m_Pos, Center );
break;
case TYPE_SCH_TEXT:
case TYPE_SCH_LABEL:
// Text is not really mirrored; it is moved to a suitable position
// which is the closest position for a true mirrored text
// The center position is mirrored and the text is moved for half horizontal len
DrawText = (SCH_TEXT*) DrawStruct;
px = DrawText->m_Pos;
if( DrawText->m_Orient == 0 ) /* horizontal text */
dx = DrawText->Len_Size() / 2;
else if( DrawText->m_Orient == 2 ) /* invert horizontal text*/
dx = -DrawText->Len_Size() / 2;
else
dx = 0;
px.x += dx;
MirrorYPoint( px, Center );
px.x -= dx;
frame->PutOnGrid( &px );
DrawText->m_Pos.x = px.x;
break;
case TYPE_SCH_HIERLABEL:
case TYPE_SCH_GLOBALLABEL:
// Text is not really mirrored: Orientation is changed
DrawText = (SCH_LABEL*) DrawStruct;
if( DrawText->m_Orient == 0 ) /* horizontal text */
DrawText->m_Orient = 2;
else if( DrawText->m_Orient == 2 ) /* invert horizontal text*/
DrawText->m_Orient = 0;
px = DrawText->m_Pos;
MirrorYPoint( px, Center );
frame->PutOnGrid( &px );
DrawText->m_Pos.x = px.x;
break;
case TYPE_SCH_COMPONENT:
DrawLibItem = (SCH_COMPONENT*) DrawStruct;
dx = DrawLibItem->m_Pos.x;
frame->CmpRotationMiroir( DrawLibItem, NULL, CMP_MIROIR_Y );
MirrorYPoint( DrawLibItem->m_Pos, Center );
dx -= DrawLibItem->m_Pos.x;
for( int ii = 0; ii < DrawLibItem->GetFieldCount(); ii++ )
{
/* move the fields to the new position because the component itself has moved */
DrawLibItem->GetField( ii )->m_Pos.x -= dx;
}
break;
case DRAW_SHEET_STRUCT_TYPE:
DrawSheet = (DrawSheetStruct*) DrawStruct;
MirrorYPoint( DrawSheet->m_Pos, Center );
DrawSheet->m_Pos.x -= DrawSheet->m_Size.x;
DrawSheetLabel = DrawSheet->m_Label;
while( DrawSheetLabel != NULL )
{
MirrorYPoint( DrawSheetLabel->m_Pos, Center );
DrawSheetLabel->m_Edge = DrawSheetLabel->m_Edge ? 0 : 1;
DrawSheetLabel =
(Hierarchical_PIN_Sheet_Struct*) DrawSheetLabel->Next();
}
break;
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
DrawSheetLabel = (Hierarchical_PIN_Sheet_Struct*) DrawStruct;
MirrorYPoint( DrawSheetLabel->m_Pos, Center );
break;
case DRAW_PICK_ITEM_STRUCT_TYPE:
break;
default:
break;
}
}
/*****************************************************************************
* Routine to Mirror an object(s). *
* If DrawStruct is of type DrawPickedStruct, a list of objects picked is *
* assumed, otherwise exactly one structure is assumed been picked. *
*****************************************************************************/
bool MirrorStruct( WinEDA_DrawPanel* panel,
wxDC* DC,
SCH_ITEM* DrawStruct,
wxPoint& Center )
{
if( !DrawStruct )
return FALSE;
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
DrawPickedStruct* pickedList = (DrawPickedStruct*) DrawStruct;
if( DC )
panel->PostDirtyRect( pickedList->GetBoundingBoxUnion() );
for( DrawPickedStruct* cur = pickedList; cur; cur = cur->Next() )
{
MirrorOneStruct( (SCH_ITEM*) cur->m_PickedStruct, Center );
cur->m_PickedStruct->m_Flags = 0;
}
if( DC )
RedrawStructList( panel, DC, (SCH_ITEM*) pickedList,
GR_DEFAULT_DRAWMODE );
// Free the wrapper DrawPickedStruct chain
pickedList->DeleteWrapperList();
}
else
{
if( DC )
panel->PostDirtyRect( DrawStruct->GetBoundingBox() );
MirrorOneStruct( DrawStruct, Center ); // Place it in its new position.
if( DC )
RedrawOneStruct( panel, DC, DrawStruct, GR_DEFAULT_DRAWMODE );
DrawStruct->m_Flags = 0;
}
return true;
}
/*****************************************************************************/
static SCH_ITEM* CopyStruct( WinEDA_DrawPanel* panel,
wxDC* DC,
BASE_SCREEN* screen,
SCH_ITEM* DrawStruct )
/*****************************************************************************/
/* Routine to copy a new entity of an object and reposition it.
* If DrawStruct is of type DrawPickedStruct, a list of objects picked is
* assumed, otherwise exactly one structure is assumed been picked.
* Return the new created struct
*/
{
SCH_ITEM* NewDrawStruct;
DrawPickedStruct* PickedList = NULL;
if( !DrawStruct )
return FALSE;
NewDrawStruct = DuplicateStruct( DrawStruct );
if( NewDrawStruct == NULL )
return NULL;
PlaceStruct( screen, NewDrawStruct );
/* Draw the new structure and chain it in: */
if( NewDrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
PickedList = (DrawPickedStruct*) NewDrawStruct;
while( PickedList ) // Clear annotation for new components
{
EDA_BaseStruct* Struct = PickedList->m_PickedStruct;
switch( Struct->Type() )
{
case TYPE_SCH_COMPONENT:
{
( (SCH_COMPONENT*) Struct )->m_TimeStamp = GetTimeStamp();
( (SCH_COMPONENT*) Struct )->ClearAnnotation( NULL );
}
break;
case DRAW_SHEET_STRUCT_TYPE:
{
//DuplicateStruct calls GenCopy, which should handle
//m_AssociatedScreen and m_sRefCount properly.
DrawSheetStruct* sheet = (DrawSheetStruct*) Struct;
sheet->m_TimeStamp = GetTimeStamp();
//sheet->m_AssociatedScreen->m_UndoList = NULL;
//sheet->m_AssociatedScreen->m_RedoList = NULL;
//keep m_AssociatedScreen pointer & associated.
//sheet->m_Son = NULL; m_son is involved in undo and redo.
break;
}
default:
;
}
SetaParent( Struct, screen );
PickedList = (DrawPickedStruct*) PickedList->Next();
}
RedrawStructList( panel, DC, NewDrawStruct, GR_DEFAULT_DRAWMODE );
/* Chain the new items */
PickedList = (DrawPickedStruct*) NewDrawStruct;
while( PickedList )
{
PickedList->m_PickedStruct->SetNext( screen->EEDrawList );
screen->EEDrawList = (SCH_ITEM*) PickedList->m_PickedStruct;
PickedList = PickedList->Next();
}
}
else
{
switch( NewDrawStruct->Type() )
{
case DRAW_POLYLINE_STRUCT_TYPE:
case DRAW_JUNCTION_STRUCT_TYPE:
case DRAW_SEGMENT_STRUCT_TYPE:
case DRAW_BUSENTRY_STRUCT_TYPE:
case TYPE_SCH_TEXT:
case TYPE_SCH_LABEL:
case TYPE_SCH_GLOBALLABEL:
case TYPE_SCH_HIERLABEL:
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
case DRAW_PICK_ITEM_STRUCT_TYPE:
case DRAW_MARKER_STRUCT_TYPE:
case DRAW_NOCONNECT_STRUCT_TYPE:
default:
break;
case DRAW_SHEET_STRUCT_TYPE:
{
DrawSheetStruct* sheet = (DrawSheetStruct*) NewDrawStruct;
sheet->m_TimeStamp = GetTimeStamp();
sheet->SetSon( NULL );
break;
}
case TYPE_SCH_COMPONENT:
( (SCH_COMPONENT*) NewDrawStruct )->m_TimeStamp = GetTimeStamp();
( (SCH_COMPONENT*) NewDrawStruct )->ClearAnnotation( NULL );
break;
}
RedrawOneStruct( panel, DC, NewDrawStruct, GR_DEFAULT_DRAWMODE );
SetaParent( NewDrawStruct, screen );
NewDrawStruct->SetNext( screen->EEDrawList );
screen->EEDrawList = NewDrawStruct;
}
/* Free the original DrawPickedStruct chain: */
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
PickedList = (DrawPickedStruct*) DrawStruct;
PickedList->DeleteWrapperList();
}
return NewDrawStruct;
}
/*********************************************************************************/
void DeleteStruct( WinEDA_DrawPanel* panel, wxDC* DC, SCH_ITEM* DrawStruct )
/*********************************************************************************/
/* Routine to delete an object from global drawing object list.
* Object is put in Undo list
*/
{
SCH_SCREEN* screen = (SCH_SCREEN*) panel->GetScreen();
WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) panel->m_Parent;
if( !DrawStruct )
return;
if( DrawStruct->Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
{
/* Cette stucture est rattachee a une feuille, et n'est pas
* accessible par la liste globale directement */
frame->SaveCopyInUndoList( (SCH_ITEM*) ( (Hierarchical_PIN_Sheet_Struct
*) DrawStruct )->GetParent(),
IS_CHANGED );
frame->DeleteSheetLabel( DC ? true : false,
(Hierarchical_PIN_Sheet_Struct*) DrawStruct );
return;
}
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
// Unlink all picked structs from current EEDrawList
for( DrawPickedStruct* cur = (DrawPickedStruct*) DrawStruct;
cur;
cur = cur->Next() )
{
SCH_ITEM* item = (SCH_ITEM*)cur->m_PickedStruct;
screen->RemoveFromDrawList( item );
panel->PostDirtyRect( item->GetBoundingBox() );
item->SetNext( 0 );
item->SetBack( 0 );
item->m_Flags = IS_DELETED;
}
// Removed items are put onto the Undo list
frame->SaveCopyInUndoList( DrawStruct, IS_DELETED );
}
else /* structure classique */
{
screen->RemoveFromDrawList( DrawStruct );
panel->PostDirtyRect( DrawStruct->GetBoundingBox() );
/* Unlink the structure */
DrawStruct->SetNext( 0 );
DrawStruct->SetBack( 0 ); // Only one struct -> no link
if( DrawStruct->Type() == DRAW_SHEET_STRUCT_TYPE )
{
frame->SaveCopyInUndoList( DrawStruct, IS_DELETED ); // Currently In TEST
}
else
frame->SaveCopyInUndoList( DrawStruct, IS_DELETED );
}
}
/*****************************************************************/
SCH_ITEM* SaveStructListForPaste( SCH_ITEM* DrawStruct )
/*****************************************************************/
/* Routine to Save an object from global drawing object list.
* This routine is the same as delete but:
* - the original list is NOT removed.
* - List is saved in g_BlockSaveDataList
*/
{
DrawPickedStruct* PickedList;
SCH_ITEM* DrawStructCopy;
if( !DrawStruct )
return NULL;
/* Make a copy of the original picked item. */
DrawStructCopy = DuplicateStruct( DrawStruct );
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
/* Delete the picked wrapper if this is a picked list. */
PickedList = (DrawPickedStruct*) DrawStruct;
PickedList->DeleteWrapperList();
}
/* And delete old list and save the new list: */
if( g_BlockSaveDataList ) /* Delete last deleted item or item list */
{
EDA_BaseStruct* item = g_BlockSaveDataList, * next_item;
while( item )
{
next_item = item->Next();
delete item;
item = next_item;
}
}
g_BlockSaveDataList = DrawStructCopy;
DrawStructCopy->SetParent( NULL );
return DrawStructCopy;
}
/*****************************************************************************
* Routine to paste a structure from the g_BlockSaveDataList stack. *
* This routine is the same as undelete but original list is NOT removed. *
*****************************************************************************/
void WinEDA_SchematicFrame::PasteStruct( wxDC* DC )
{
SCH_ITEM* DrawStruct;
DrawPickedStruct* PickedList = NULL;
if( g_BlockSaveDataList == NULL )
{
DisplayError( this, wxT( "No struct to paste" ) );
return;
}
DrawStruct = DuplicateStruct( g_BlockSaveDataList );
PlaceStruct( GetScreen(), DrawStruct );
RedrawStructList( DrawPanel, DC, DrawStruct, GR_DEFAULT_DRAWMODE );
// Clear annotation and init new time stamp for the new components:
if( DrawStruct->Type() == DRAW_PICK_ITEM_STRUCT_TYPE )
{
for( PickedList = (DrawPickedStruct*) DrawStruct; PickedList != NULL; ) // Clear annotation for new components
{
EDA_BaseStruct* Struct = PickedList->m_PickedStruct;
if( Struct->Type() == TYPE_SCH_COMPONENT )
{
( (SCH_COMPONENT*) Struct )->m_TimeStamp = GetTimeStamp();
( (SCH_COMPONENT*) Struct )->ClearAnnotation( NULL );
SetaParent( Struct, GetScreen() );
}
PickedList = (DrawPickedStruct*) PickedList->Next();
}
RedrawStructList( DrawPanel, DC, DrawStruct, GR_DEFAULT_DRAWMODE );
for( PickedList = (DrawPickedStruct*) DrawStruct; PickedList != NULL; )
{
SCH_ITEM* Struct = (SCH_ITEM*) PickedList->m_PickedStruct;
Struct->SetNext( GetScreen()->EEDrawList );
SetaParent( Struct, GetScreen() );
GetScreen()->EEDrawList = Struct;
PickedList = PickedList->Next();
}
/* Save wrapper list in undo stack */
SaveCopyInUndoList( DrawStruct, IS_NEW );
}
else
{
if( DrawStruct->Type() == TYPE_SCH_COMPONENT )
{
( (SCH_COMPONENT*) DrawStruct )->m_TimeStamp = GetTimeStamp();
( (SCH_COMPONENT*) DrawStruct )->ClearAnnotation( NULL );
}
SetaParent( DrawStruct, GetScreen() );
RedrawOneStruct( DrawPanel, DC, DrawStruct, GR_DEFAULT_DRAWMODE );
DrawStruct->SetNext( GetScreen()->EEDrawList );
GetScreen()->EEDrawList = DrawStruct;
SaveCopyInUndoList( DrawStruct, IS_NEW );
}
/* clear .m_Flags member for all items */
SCH_ITEM* Struct;
for( Struct = GetScreen()->EEDrawList;
Struct != NULL;
Struct = Struct->Next() )
Struct->m_Flags = 0;
GetScreen()->SetModify();
return;
}
/*****************************************************************************
* Routine to place a given object. *
*****************************************************************************/
bool PlaceStruct( BASE_SCREEN* screen, SCH_ITEM* DrawStruct )
{
DrawPickedStruct* DrawStructs;
wxPoint move_vector;
if( !DrawStruct )
return FALSE;
move_vector = screen->m_Curseur - screen->BlockLocate.m_BlockLastCursorPosition;
switch( DrawStruct->Type() )
{
default:
case TYPE_NOT_INIT:
return FALSE;
case DRAW_POLYLINE_STRUCT_TYPE:
case DRAW_JUNCTION_STRUCT_TYPE:
case DRAW_SEGMENT_STRUCT_TYPE:
case DRAW_BUSENTRY_STRUCT_TYPE:
case TYPE_SCH_TEXT:
case TYPE_SCH_LABEL:
case TYPE_SCH_GLOBALLABEL:
case TYPE_SCH_HIERLABEL:
case TYPE_SCH_COMPONENT:
case DRAW_SHEET_STRUCT_TYPE:
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
case DRAW_MARKER_STRUCT_TYPE:
case DRAW_NOCONNECT_STRUCT_TYPE:
MoveOneStruct( DrawStruct, move_vector );
break;
case DRAW_PICK_ITEM_STRUCT_TYPE:
DrawStructs = (DrawPickedStruct*) DrawStruct;
while( DrawStructs )
{
MoveOneStruct( (SCH_ITEM*) DrawStructs->m_PickedStruct,
move_vector );
DrawStructs = DrawStructs->Next();
}
break;
}
return TRUE;
}
/**************************************************************************/
void MoveOneStruct( SCH_ITEM* DrawStruct, const wxPoint& move_vector )
/*************************************************************************/
/* Given a structure move it by Dx, Dy.
*/
{
DrawPolylineStruct* DrawPoly;
DrawJunctionStruct* DrawConnect;
EDA_DrawLineStruct* DrawSegment;
DrawBusEntryStruct* DrawRaccord;
SCH_COMPONENT* DrawLibItem;
DrawSheetStruct* DrawSheet;
Hierarchical_PIN_Sheet_Struct* DrawSheetLabel;
DrawMarkerStruct* DrawMarker;
DrawNoConnectStruct* DrawNoConnect;
if( !DrawStruct )
return;
switch( DrawStruct->Type() )
{
case TYPE_NOT_INIT:
break;
case DRAW_POLYLINE_STRUCT_TYPE:
DrawPoly = (DrawPolylineStruct*) DrawStruct;
for( unsigned ii = 0; ii < DrawPoly->GetCornerCount(); ii++ )
{
DrawPoly->m_PolyPoints[ii] += move_vector;
}
break;
case DRAW_SEGMENT_STRUCT_TYPE:
DrawSegment = (EDA_DrawLineStruct*) DrawStruct;
if( (DrawSegment->m_Flags & STARTPOINT) == 0 )
{
DrawSegment->m_Start += move_vector;
}
if( (DrawSegment->m_Flags & ENDPOINT) == 0 )
{
DrawSegment->m_End += move_vector;
}
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
DrawRaccord = (DrawBusEntryStruct*) DrawStruct;
DrawRaccord->m_Pos += move_vector;
break;
case DRAW_JUNCTION_STRUCT_TYPE:
DrawConnect = (DrawJunctionStruct*) DrawStruct;
DrawConnect->m_Pos += move_vector;
break;
case DRAW_MARKER_STRUCT_TYPE:
DrawMarker = (DrawMarkerStruct*) DrawStruct;
DrawMarker->m_Pos += move_vector;
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
DrawNoConnect = (DrawNoConnectStruct*) DrawStruct;
DrawNoConnect->m_Pos += move_vector;
break;
case TYPE_SCH_TEXT:
#define DrawText ( (SCH_TEXT*) DrawStruct )
DrawText->m_Pos += move_vector;
break;
case TYPE_SCH_LABEL:
#define DrawLabel ( (SCH_LABEL*) DrawStruct )
DrawLabel->m_Pos += move_vector;
break;
case TYPE_SCH_HIERLABEL:
case TYPE_SCH_GLOBALLABEL:
#define DrawGHLabel ( (SCH_LABEL*) DrawStruct )
DrawGHLabel->m_Pos += move_vector;
break;
case TYPE_SCH_COMPONENT:
DrawLibItem = (SCH_COMPONENT*) DrawStruct;
DrawLibItem->m_Pos += move_vector;
for( int ii = 0; ii < DrawLibItem->GetFieldCount(); ii++ )
{
DrawLibItem->GetField( ii )->m_Pos += move_vector;
}
break;
case DRAW_SHEET_STRUCT_TYPE:
DrawSheet = (DrawSheetStruct*) DrawStruct;
DrawSheet->m_Pos += move_vector;
DrawSheetLabel = DrawSheet->m_Label;
while( DrawSheetLabel != NULL )
{
DrawSheetLabel->m_Pos += move_vector;
DrawSheetLabel = DrawSheetLabel->Next();
}
break;
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
DrawSheetLabel = (Hierarchical_PIN_Sheet_Struct*) DrawStruct;
DrawSheetLabel->m_Pos += move_vector;
break;
case DRAW_PICK_ITEM_STRUCT_TYPE:
break;
default:
break;
}
}
/************************************************************/
SCH_ITEM* DuplicateStruct( SCH_ITEM* DrawStruct )
/************************************************************/
/* Routine to create a new copy of given struct.
* The new object is not put in draw list (not linked)
*/
{
SCH_ITEM* NewDrawStruct = NULL;
if( DrawStruct == NULL )
{
DisplayError( NULL, wxT( "DuplicateStruct error: NULL struct" ) );
return NULL;
}
switch( DrawStruct->Type() )
{
case DRAW_POLYLINE_STRUCT_TYPE:
NewDrawStruct = ( (DrawPolylineStruct*) DrawStruct )->GenCopy();
break;
case DRAW_SEGMENT_STRUCT_TYPE:
NewDrawStruct = ( (EDA_DrawLineStruct*) DrawStruct )->GenCopy();
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
NewDrawStruct = ( (DrawBusEntryStruct*) DrawStruct )->GenCopy();
break;
case DRAW_JUNCTION_STRUCT_TYPE:
NewDrawStruct = ( (DrawJunctionStruct*) DrawStruct )->GenCopy();
break;
case DRAW_MARKER_STRUCT_TYPE:
NewDrawStruct = ( (DrawMarkerStruct*) DrawStruct )->GenCopy();
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
NewDrawStruct = ( (DrawNoConnectStruct*) DrawStruct )->GenCopy();
break;
case TYPE_SCH_TEXT:
NewDrawStruct = ( (SCH_TEXT*) DrawStruct )->GenCopy();
break;
case TYPE_SCH_LABEL:
NewDrawStruct = ( (SCH_LABEL*) DrawStruct )->GenCopy();
break;
case TYPE_SCH_HIERLABEL:
NewDrawStruct = ( (SCH_HIERLABEL*) DrawStruct )->GenCopy();
break;
case TYPE_SCH_GLOBALLABEL:
NewDrawStruct = ( (SCH_GLOBALLABEL*) DrawStruct )->GenCopy();
break;
case TYPE_SCH_COMPONENT:
NewDrawStruct = ( (SCH_COMPONENT*) DrawStruct )->GenCopy();
break;
case DRAW_SHEET_STRUCT_TYPE:
NewDrawStruct = ( (DrawSheetStruct*) DrawStruct )->GenCopy();
break;
case DRAW_PICK_ITEM_STRUCT_TYPE:
{
DrawPickedStruct* NewPickedItem, * PickedList = NULL,
* LastPickedItem = NULL;
PickedList = (DrawPickedStruct*) DrawStruct;
while( PickedList )
{
NewPickedItem = new DrawPickedStruct();
if( NewDrawStruct == NULL )
NewDrawStruct = (SCH_ITEM*) NewPickedItem;
if( LastPickedItem )
LastPickedItem->SetNext( NewPickedItem );
LastPickedItem = NewPickedItem;
NewPickedItem->m_PickedStruct =
DuplicateStruct( (SCH_ITEM*) PickedList->m_PickedStruct );
PickedList = PickedList->Next();
}
break;
}
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
case DRAW_PART_TEXT_STRUCT_TYPE:
case SCREEN_STRUCT_TYPE:
default:
{
wxString msg;
msg << wxT( "DuplicateStruct error: unexpected StructType " ) <<
DrawStruct->Type() << wxT( " " ) << DrawStruct->GetClass();
DisplayError( NULL, msg );
}
break;
}
NewDrawStruct->m_Image = DrawStruct;
return NewDrawStruct;
}
/****************************************************/
static void CollectStructsToDrag( SCH_SCREEN* screen )
/****************************************************/
/* creates the list of items found when a drag block is initiated.
* items are those slected in window block an some items outside this area but connected
* to a selected item (connected wires to a component or an entry )
*/
{
DrawPickedStruct* DrawStructs, * FirstPicked;
SCH_ITEM* Struct;
EDA_DrawLineStruct* SegmStruct;
int ox, oy, fx, fy;
/* .m_Flags member is used to handle how a wire is exactly slected
* (fully selected, or partially selected by an end point )
*/
for( Struct = screen->EEDrawList; Struct != NULL; Struct = Struct->Next() )
Struct->m_Flags = 0;
// Sel .m_Flags to selected for a wire or buss in selected area if there is only one item:
if( screen->BlockLocate.m_BlockDrawStruct->Type() == DRAW_SEGMENT_STRUCT_TYPE )
screen->BlockLocate.m_BlockDrawStruct->m_Flags = SELECTED;
// Sel .m_Flags to selected for a wire or buss in selected area for a list of items:
else if( screen->BlockLocate.m_BlockDrawStruct->Type() ==
DRAW_PICK_ITEM_STRUCT_TYPE )
{
DrawStructs =
(DrawPickedStruct*) screen->BlockLocate.m_BlockDrawStruct;
while( DrawStructs )
{
Struct = (SCH_ITEM*) DrawStructs->m_PickedStruct;
DrawStructs = DrawStructs->Next();
Struct->m_Flags = SELECTED;
}
}
if( screen->BlockLocate.m_Command != BLOCK_DRAG )
return;
ox = screen->BlockLocate.GetX();
oy = screen->BlockLocate.GetY();
fx = screen->BlockLocate.GetRight();
fy = screen->BlockLocate.GetBottom();
if( fx < ox )
EXCHG( fx, ox );
if( fy < oy )
EXCHG( fy, oy );
/* For drag block only:
* If only one item, change for a list of one item
* in order to have always a list to handle.
*/
if( screen->BlockLocate.m_BlockDrawStruct->Type() !=
DRAW_PICK_ITEM_STRUCT_TYPE )
{
DrawStructs = new DrawPickedStruct(
(SCH_ITEM*) screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct = DrawStructs;
}
/* Suppression du deplacement des extremites de segments hors cadre
* de selection */
DrawStructs = (DrawPickedStruct*) screen->BlockLocate.m_BlockDrawStruct;
while( DrawStructs )
{
Struct = (SCH_ITEM*) DrawStructs->m_PickedStruct;
DrawStructs = DrawStructs->Next();
if( Struct->Type() == DRAW_SEGMENT_STRUCT_TYPE )
{
SegmStruct = (EDA_DrawLineStruct*) Struct;
if( (SegmStruct->m_Start.x < ox) || (SegmStruct->m_Start.x > fx)
|| (SegmStruct->m_Start.y < oy) || (SegmStruct->m_Start.y > fy) )
SegmStruct->m_Flags |= STARTPOINT;
if( (SegmStruct->m_End.x < ox) || (SegmStruct->m_End.x > fx)
|| (SegmStruct->m_End.y < oy) || (SegmStruct->m_End.y > fy) )
SegmStruct->m_Flags |= ENDPOINT;
}
}
/* Search for other items to drag. They are end wires connected to selected items
*/
FirstPicked = DrawStructs =
(DrawPickedStruct*) screen->BlockLocate.m_BlockDrawStruct;
while( DrawStructs )
{
Struct = (SCH_ITEM*) DrawStructs->m_PickedStruct;
DrawStructs = DrawStructs->Next();
if( Struct->Type() == TYPE_SCH_COMPONENT )
{ // Add all pins of the selected component to list
LibEDA_BaseStruct* DrawItem;
wxPoint pos;
DrawItem = GetNextPinPosition( (SCH_COMPONENT*) Struct, pos );
while( DrawItem )
{
if( (pos.x < ox) || (pos.x > fx) || (pos.y < oy) || (pos.y > fy) )
{ // This pin is outside area,
// but because it it the pin of a selected component
// we must also select connected items to this pin
AddPickedItem( screen, pos );
}
DrawItem = GetNextPinPosition( NULL, pos );
}
}
if( Struct->Type() == DRAW_SHEET_STRUCT_TYPE )
{ // Add all pins sheets of a selected hierarchical sheet to the list
Hierarchical_PIN_Sheet_Struct* SLabel =
( (DrawSheetStruct*) Struct )->m_Label;
while( SLabel )
{
if( SLabel->Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
AddPickedItem( screen, SLabel->m_Pos );
SLabel = (Hierarchical_PIN_Sheet_Struct*) SLabel->Next();
}
}
if( Struct->Type() == DRAW_BUSENTRY_STRUCT_TYPE )
{
DrawBusEntryStruct* item = (DrawBusEntryStruct*) Struct;
AddPickedItem( screen, item->m_Pos );
AddPickedItem( screen, item->m_End() );
}
}
}
/******************************************************************/
static void AddPickedItem( SCH_SCREEN* screen, wxPoint position )
/******************************************************************/
{
DrawPickedStruct* DrawStructs;
SCH_ITEM* Struct;
/* Examen de la liste des elements deja selectionnes */
DrawStructs = (DrawPickedStruct*) screen->BlockLocate.m_BlockDrawStruct;
while( DrawStructs )
{
Struct = (SCH_ITEM*) DrawStructs->m_PickedStruct;
DrawStructs = (DrawPickedStruct*) DrawStructs->Next();
switch( Struct->Type() )
{
case DRAW_SEGMENT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ( (EDA_DrawLineStruct*) Struct )
if( STRUCT->m_Start == position )
STRUCT->m_Flags &= ~STARTPOINT;
if( STRUCT->m_End == position )
STRUCT->m_Flags &= ~ENDPOINT;
break;
default:
break;
}
}
/* Examen de la liste des elements non selectionnes */
Struct = screen->EEDrawList;
while( Struct )
{
switch( Struct->Type() )
{
case TYPE_NOT_INIT:
break;
case DRAW_POLYLINE_STRUCT_TYPE:
if( Struct->m_Flags & SELECTED )
break; /* Deja en liste */
break;
case DRAW_JUNCTION_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ( (DrawJunctionStruct*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Deja en liste */
if( STRUCT->m_Pos != position )
break;
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
break;
case DRAW_SEGMENT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ( (EDA_DrawLineStruct*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Deja en liste */
if( STRUCT->m_Start == position )
{
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags = SELECTED | ENDPOINT | STARTPOINT;
Struct->m_Flags &= ~STARTPOINT;
}
else if( STRUCT->m_End == position )
{
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags = SELECTED | ENDPOINT | STARTPOINT;
Struct->m_Flags &= ~ENDPOINT;
}
break;
case DRAW_BUSENTRY_STRUCT_TYPE:
break;
case TYPE_SCH_TEXT:
break;
case TYPE_SCH_LABEL:
#undef STRUCT
#define STRUCT ( (SCH_LABEL*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Already in list */
if( STRUCT->m_Pos != position )
break;
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags |= SELECTED;
break;
case TYPE_SCH_HIERLABEL:
case TYPE_SCH_GLOBALLABEL:
#undef STRUCT
#define STRUCT ( (SCH_LABEL*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Already in list */
if( STRUCT->m_Pos != position )
break;
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags |= SELECTED;
break;
case TYPE_SCH_COMPONENT:
break;
case DRAW_SHEET_STRUCT_TYPE:
break;
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
break;
case DRAW_PICK_ITEM_STRUCT_TYPE:
break;
case DRAW_MARKER_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ( (DrawMarkerStruct*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Already in list */
if( STRUCT->m_Pos != position )
break;
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags |= SELECTED;
break;
case DRAW_NOCONNECT_STRUCT_TYPE:
#undef STRUCT
#define STRUCT ( (DrawNoConnectStruct*) Struct )
if( Struct->m_Flags & SELECTED )
break; /* Already in list */
if( STRUCT->m_Pos != position )
break;
DrawStructs = new DrawPickedStruct( Struct );
DrawStructs->SetNext( screen->BlockLocate.m_BlockDrawStruct );
screen->BlockLocate.m_BlockDrawStruct =
(EDA_BaseStruct*) DrawStructs;
Struct->m_Flags |= SELECTED;
break;
default:
break;
}
Struct = Struct->Next();
}
}
/*********************************************************************************/
static LibEDA_BaseStruct* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem,
wxPoint& aPosition )
/*********************************************************************************/
/** GetNextPinPosition()
* calculate position of the "next" pin of the aDrawLibItem component
* if aDrawLibItem is non null : search for the first pin
* if aDrawLibItem == NULL, search the next pin
* returns its position
* @param aDrawLibItem = component test. search for the first pin
* if NULL, serach for the next pin for each call
* @param aPosition = the calculated pin position, according to the component orientation and position
* @return a pointer to the pin
*/
{
EDA_LibComponentStruct* Entry;
static LibEDA_BaseStruct* NextItem;
static int Multi, convert, TransMat[2][2];
LibEDA_BaseStruct* DEntry;
int orient;
LibDrawPin* Pin;
static wxPoint CmpPosition;
if( aDrawLibItem )
{
NextItem = NULL;
if( ( Entry =
FindLibPart( aDrawLibItem->m_ChipName.GetData(), wxEmptyString,
FIND_ROOT ) ) == NULL )
return NULL;
DEntry = Entry->m_Drawings;
Multi = aDrawLibItem->m_Multi;
convert = aDrawLibItem->m_Convert;
CmpPosition = aDrawLibItem->m_Pos;
memcpy( TransMat, aDrawLibItem->m_Transform, sizeof(TransMat) );
}
else
DEntry = NextItem;
for( ; DEntry != NULL; DEntry = DEntry->Next() )
{
/* Elimination des elements non relatifs a l'unite */
if( Multi && DEntry->m_Unit && (DEntry->m_Unit != Multi) )
continue;
if( convert && DEntry->m_Convert && (DEntry->m_Convert != convert) )
continue;
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
continue;
Pin = (LibDrawPin*) DEntry;
/* Calcul de l'orientation reelle de la Pin */
orient = Pin->ReturnPinDrawOrient( TransMat );
/* Calcul de la position du point de reference */
aPosition = TransformCoordinate( TransMat, Pin->m_Pos ) + CmpPosition;
NextItem = DEntry->Next();
return DEntry;
}
NextItem = NULL;
return NULL;
}