diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b5d10e7a1d..952aa093a6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,20 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-nov-3 UPDATE Wayne Stambaugh +================================================================================ +++common + * Initial ground work for using Boost container for storing draw items + instead of internal linked list. +++EESchema + * Move tests for dangling end code back into schematic objects. + * Add clear draw object state helper to SCH_SCREEN object. + * Add support for schematic objects to keep temporary list of connection + objects for dangling end and other connection related tests. + * Rearrange schematic label object code. + * Remove duplicate error message boxes when loading schematic items. + + 2010-oct-28, UPDATE Jean-Pierre Charras ================================================================================ PolyLine.cpp: diff --git a/common/base_screen.cpp b/common/base_screen.cpp index 2cd5f6b42c..8e85ca74f7 100644 --- a/common/base_screen.cpp +++ b/common/base_screen.cpp @@ -542,6 +542,22 @@ PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromRedoList( ) } +void BASE_SCREEN::AddItem( EDA_BaseStruct* aItem ) +{ + wxCHECK_RET( aItem != NULL, wxT( "Attempt to add NULL item pointer to " ) + GetClass() + + wxT( "item list" ) ); + m_items.push_back( aItem ); +} + + +void BASE_SCREEN::InsertItem( EDA_ITEMS::iterator aIter, EDA_BaseStruct* aItem ) +{ + wxCHECK_RET( aItem != NULL, wxT( "Attempt to insert NULL item pointer to " ) + GetClass() + + wxT( "item list" ) ); + m_items.insert( aIter, aItem ); +} + + #if defined(DEBUG) /** * Function Show diff --git a/eeschema/block.cpp b/eeschema/block.cpp index 2fed57923b..395c6f9e90 100644 --- a/eeschema/block.cpp +++ b/eeschema/block.cpp @@ -19,16 +19,11 @@ // Imported functions: -void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, - const wxPoint aMoveVector ); -void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, - wxPoint& Center ); -void Mirror_X_ListOfItems( PICKED_ITEMS_LIST& aItemsList, - wxPoint& aMirrorPoint ); -void MirrorListOfItems( PICKED_ITEMS_LIST& aItemsList, - wxPoint& Center ); -void DeleteItemsInList( WinEDA_DrawPanel* panel, - PICKED_ITEMS_LIST& aItemsList ); +void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ); +void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center ); +void Mirror_X_ListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ); +void MirrorListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center ); +void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList ); void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ); @@ -38,9 +33,7 @@ static void AddPickedItem( SCH_SCREEN* screen, wxPoint aPosition ); static LIB_PIN* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem, wxPoint& aPosition, bool aSearchFirst ); -static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, - wxDC* DC, - bool erase ); +static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void SaveStructListForPaste( PICKED_ITEMS_LIST& aItemsList ); @@ -114,8 +107,7 @@ void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC ) { wxString msg; err = TRUE; - msg.Printf( wxT( "HandleBlockPLace() error : no items to place (cmd \ -%d, state %d)" ), + msg.Printf( wxT( "HandleBlockPLace() error : no items to place (cmd %d, state %d)" ), block->m_Command, block->m_State ); DisplayError( this, msg ); } @@ -136,10 +128,7 @@ void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC ) if( DrawPanel->ManageCurseur ) DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); - SaveCopyInUndoList( block->m_ItemsSelection, - UR_MOVED, - block->m_MoveVector ); - + SaveCopyInUndoList( block->m_ItemsSelection, UR_MOVED, block->m_MoveVector ); MoveItemsInList( block->m_ItemsSelection, block->m_MoveVector ); block->ClearItemsList(); break; @@ -149,13 +138,10 @@ void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC ) if( DrawPanel->ManageCurseur ) DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); - DuplicateItemsInList( - GetScreen(), block->m_ItemsSelection, block->m_MoveVector ); + DuplicateItemsInList( GetScreen(), block->m_ItemsSelection, block->m_MoveVector ); - SaveCopyInUndoList( - block->m_ItemsSelection, - (block->m_Command == - BLOCK_PRESELECT_MOVE) ? UR_CHANGED : UR_NEW ); + SaveCopyInUndoList( block->m_ItemsSelection, + ( block->m_Command == BLOCK_PRESELECT_MOVE ) ? UR_CHANGED : UR_NEW ); block->ClearItemsList(); break; @@ -178,12 +164,8 @@ void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC ) OnModify(); - /* clear struct.m_Flags */ - SCH_ITEM* Struct; - for( Struct = GetScreen()->EEDrawList; - Struct != NULL; - Struct = Struct->Next() ) - Struct->m_Flags = 0; + // clear struct.m_Flags. + GetScreen()->ClearDrawingState(); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; @@ -196,13 +178,11 @@ void WinEDA_SchematicFrame::HandleBlockPlace( wxDC* DC ) if( block->GetCount() ) { - DisplayError( this, - wxT( "HandleBlockPLace() error: some items left in buffer" ) ); + DisplayError( this, wxT( "HandleBlockPLace() error: some items left in buffer" ) ); block->ClearItemsList(); } - SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, - wxEmptyString ); + SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString ); DrawPanel->Refresh(); } @@ -288,11 +268,9 @@ int WinEDA_SchematicFrame::HandleBlockEnd( wxDC* DC ) DrawAndSizingBlockOutlines( DrawPanel, DC, FALSE ); if( block->GetCount() ) { - wxPoint move_vector = - -GetScreen()->m_BlockLocate.m_BlockLastCursorPosition; + wxPoint move_vector = -GetScreen()->m_BlockLocate.m_BlockLastCursorPosition; SaveStructListForPaste( block->m_ItemsSelection ); - MoveItemsInList( g_BlockSaveDataList.m_ItemsSelection, - move_vector ); + MoveItemsInList( g_BlockSaveDataList.m_ItemsSelection, move_vector ); ii = -1; } block->ClearItemsList(); @@ -317,12 +295,7 @@ int WinEDA_SchematicFrame::HandleBlockEnd( wxDC* DC ) 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; + GetScreen()->ClearDrawingState(); } if( ii <= 0 ) @@ -333,9 +306,7 @@ int WinEDA_SchematicFrame::HandleBlockEnd( wxDC* DC ) DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; GetScreen()->SetCurItem( NULL ); - SetToolID( m_ID_current_state, - DrawPanel->m_PanelDefaultCursor, - wxEmptyString ); + SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString ); } if( zoom_command ) @@ -415,8 +386,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); if( block->GetCount() ) { - wxPoint move_vector = - -GetScreen()->m_BlockLocate.m_BlockLastCursorPosition; + wxPoint move_vector = -GetScreen()->m_BlockLocate.m_BlockLastCursorPosition; SaveStructListForPaste( block->m_ItemsSelection ); MoveItemsInList( g_BlockSaveDataList.m_ItemsSelection, move_vector ); } @@ -424,8 +394,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) case BLOCK_ZOOM: /* Window Zoom */ DrawPanel->ForceCloseManageCurseur( DrawPanel, DC ); - DrawPanel->SetCursor( - DrawPanel->m_PanelCursor = DrawPanel->m_PanelDefaultCursor ); + DrawPanel->SetCursor( DrawPanel->m_PanelCursor = DrawPanel->m_PanelDefaultCursor ); Window_Zoom( GetScreen()->m_BlockLocate ); break; @@ -439,9 +408,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) /* Compute the rotation center and put it on grid */ wxPoint rotationPoint = block->Centre(); PutOnGrid( &rotationPoint ); - SaveCopyInUndoList( block->m_ItemsSelection, - UR_ROTATED, - rotationPoint ); + SaveCopyInUndoList( block->m_ItemsSelection, UR_ROTATED, rotationPoint ); RotateListOfItems( block->m_ItemsSelection, rotationPoint ); OnModify(); } @@ -460,9 +427,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) /* Compute the mirror center and put it on grid */ wxPoint mirrorPoint = block->Centre(); PutOnGrid( &mirrorPoint ); - SaveCopyInUndoList( block->m_ItemsSelection, - UR_MIRRORED_X, - mirrorPoint ); + SaveCopyInUndoList( block->m_ItemsSelection, UR_MIRRORED_X, mirrorPoint ); Mirror_X_ListOfItems( block->m_ItemsSelection, mirrorPoint ); OnModify(); // block->m_State = STATE_BLOCK_MOVE; @@ -481,9 +446,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) /* Compute the mirror center and put it on grid */ wxPoint mirrorPoint = block->Centre(); PutOnGrid( &mirrorPoint ); - SaveCopyInUndoList( block->m_ItemsSelection, - UR_MIRRORED_Y, - mirrorPoint ); + SaveCopyInUndoList( block->m_ItemsSelection, UR_MIRRORED_Y, mirrorPoint ); MirrorListOfItems( block->m_ItemsSelection, mirrorPoint ); OnModify(); // block->m_State = STATE_BLOCK_MOVE; @@ -506,9 +469,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; GetScreen()->SetCurItem( NULL ); - SetToolID( m_ID_current_state, - DrawPanel->m_PanelDefaultCursor, - wxEmptyString ); + SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString ); } } @@ -516,8 +477,7 @@ void WinEDA_SchematicFrame::HandleBlockEndByPopUp( int Command, wxDC* DC ) /* Traces the outline of the search block structures * The entire block follows the cursor */ -static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, - bool erase ) +static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) { BLOCK_SELECTOR* block = &panel->GetScreen()->m_BlockLocate;; @@ -555,9 +515,7 @@ static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, */ void SaveStructListForPaste( PICKED_ITEMS_LIST& aItemsList ) { - g_BlockSaveDataList.ClearListAndDeleteItems(); // delete previous - // saved list, if - // exists + g_BlockSaveDataList.ClearListAndDeleteItems(); // delete previous saved list, if exists /* save the new list: */ ITEM_PICKER item; @@ -569,8 +527,7 @@ void SaveStructListForPaste( PICKED_ITEMS_LIST& aItemsList ) for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { /* Make a copy of the original picked item. */ - SCH_ITEM* DrawStructCopy = DuplicateStruct( - (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); + SCH_ITEM* DrawStructCopy = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); DrawStructCopy->SetParent( NULL ); item.m_PickedItem = DrawStructCopy; g_BlockSaveDataList.PushItem( item ); @@ -599,8 +556,7 @@ void WinEDA_SchematicFrame::PasteListOfItems( wxDC* DC ) for( unsigned ii = 0; ii < g_BlockSaveDataList.GetCount(); ii++ ) { Struct = DuplicateStruct( - (SCH_ITEM*) g_BlockSaveDataList.m_ItemsSelection.GetPickedItem( - ii ) ); + (SCH_ITEM*) g_BlockSaveDataList.m_ItemsSelection.GetPickedItem( ii ) ); picker.m_PickedItem = Struct; picklist.PushItem( picker ); @@ -621,10 +577,7 @@ void WinEDA_SchematicFrame::PasteListOfItems( wxDC* DC ) MoveItemsInList( picklist, GetScreen()->m_BlockLocate.m_MoveVector ); /* clear .m_Flags member for all items */ - for( Struct = GetScreen()->EEDrawList; - Struct != NULL; - Struct = Struct->Next() ) - Struct->m_Flags = 0; + GetScreen()->ClearDrawingState(); OnModify(); @@ -646,11 +599,7 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) if( pickedlist->GetCount() == 0 ) return; - /* .m_Flags member is used to handle how a wire is exactly selected - * (fully selected, or partially selected by an end point ) - */ - for( Struct = screen->EEDrawList; Struct != NULL; Struct = Struct->Next() ) - Struct->m_Flags = 0; + screen->ClearDrawingState(); for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { @@ -724,7 +673,8 @@ static void CollectStructsToDrag( SCH_SCREEN* screen ) SCH_SHEET* sheet = (SCH_SHEET*) Struct; // Add all pins sheets of a selected hierarchical sheet to the list - BOOST_FOREACH( SCH_SHEET_PIN label, sheet->GetSheetPins() ) { + BOOST_FOREACH( SCH_SHEET_PIN label, sheet->GetSheetPins() ) + { AddPickedItem( screen, label.m_Pos ); } } diff --git a/eeschema/class_drawsheet.cpp b/eeschema/class_drawsheet.cpp index 23fd4c61c9..1f0cded178 100644 --- a/eeschema/class_drawsheet.cpp +++ b/eeschema/class_drawsheet.cpp @@ -898,6 +898,70 @@ void SCH_SHEET::renumberLabels() } +void SCH_SHEET::GetEndPoints( std::vector & aItemList ) +{ + // Using BOOST_FOREACH here creates problems (bad pointer value to pinsheet). + // I do not know why. + for( unsigned ii = 0; ii < GetSheetPins().size(); ii++ ) + { + SCH_SHEET_PIN &pinsheet = GetSheetPins()[ii]; + + wxCHECK2_MSG( pinsheet.Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE, continue, + wxT( "Invalid item in schematic sheet pin list. Bad programmer!" ) ); + + pinsheet.GetEndPoints( aItemList ); + } +} + + +bool SCH_SHEET::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ) +{ + bool currentState = IsDangling(); + + BOOST_FOREACH( SCH_SHEET_PIN& pinsheet, GetSheetPins() ) + { + pinsheet.IsDanglingStateChanged( aItemList ); + } + + return currentState != IsDangling(); +} + + +bool SCH_SHEET::IsDangling() const +{ + // If any hierarchical label in the sheet is dangling, then the sheet is dangling. + for( size_t i = 0; i < GetSheetPins().size(); i++ ) + { + if( GetSheetPins()[i].IsDangling() ) + return true; + } + + return false; +} + + +bool SCH_SHEET::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + EDA_Rect boundingBox = GetBoundingBox(); + + if( aRect.Intersects( boundingBox ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_SHEET::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + for( size_t i = 0; i < GetSheetPins().size(); i++ ) + aPoints.push_back( GetSheetPins()[i].m_Pos ); +} + + #if defined(DEBUG) void SCH_SHEET::Show( int nestLevel, std::ostream& os ) diff --git a/eeschema/class_drawsheet.h b/eeschema/class_drawsheet.h index 6354379229..03ddac4d1b 100644 --- a/eeschema/class_drawsheet.h +++ b/eeschema/class_drawsheet.h @@ -23,7 +23,6 @@ extern SCH_SHEET* g_RootSheet; * the sheet, it corresponds to a hierarchical label. */ -//class SCH_SHEET_PIN : public SCH_ITEM, public EDA_TextStruct class SCH_SHEET_PIN : public SCH_HIERLABEL { private: @@ -31,15 +30,15 @@ private: ///< Sheet label numbering begins at 2. ///< 0 is reserved for the sheet name. ///< 1 is reserve for the sheet file name. - int m_Edge; /* For pin labels only: sheet edge (0 to 3) of the pin - * m_Edge define on which edge the pin is positionned: - * 0: pin on left side - * 1: pin on right side - * 2: pin on top side - * 3: pin on bottom side - * for compatibility reasons, this does not follow same values as text - * orientation. - */ + int m_Edge; /* For pin labels only: sheet edge (0 to 3) of the pin + * m_Edge define on which edge the pin is positionned: + * 0: pin on left side + * 1: pin on right side + * 2: pin on top side + * 3: pin on bottom side + * for compatibility reasons, this does not follow same values as text + * orientation. + */ public: SCH_SHEET_PIN( SCH_SHEET* parent, @@ -168,8 +167,9 @@ public: * @param aFindLocation - a wxPoint where to put the location of matched item. can be NULL. * @return True if this item matches the search criteria. */ - virtual bool Matches( wxFindReplaceData& aSearchData, - void* aAuxData, wxPoint * aFindLocation ); + virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + + virtual void GetEndPoints( std::vector & aItemList ); }; @@ -251,6 +251,11 @@ public: SCH_SHEET_PIN_LIST& GetSheetPins() { return m_labels; } + SCH_SHEET_PIN_LIST& GetSheetPins() const + { + return const_cast< SCH_SHEET_PIN_LIST& >( m_labels ); + } + /** * Remove a sheet label from this sheet. * @@ -412,7 +417,9 @@ public: virtual void Move( const wxPoint& aMoveVector ) { m_Pos += aMoveVector; - BOOST_FOREACH( SCH_SHEET_PIN & label, m_labels ) { + + BOOST_FOREACH( SCH_SHEET_PIN & label, m_labels ) + { label.Move( aMoveVector ); } } @@ -437,8 +444,7 @@ public: * * @return True if this item matches the search criteria. */ - virtual bool Matches( wxFindReplaceData& aSearchData, - void* aAuxData, wxPoint * aFindLocation ); + virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); /** * Resize this sheet to aSize and adjust all of the labels accordingly. @@ -457,6 +463,16 @@ public: */ wxPoint GetFileNamePosition (); + virtual void GetEndPoints( std::vector & aItemList ); + + virtual bool IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ); + + virtual bool IsDangling() const; + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + #if defined(DEBUG) // comment inherited by Doxygen from Base_Struct diff --git a/eeschema/class_hierarchical_PIN_sheet.cpp b/eeschema/class_hierarchical_PIN_sheet.cpp index af88daa653..3a43994b9d 100644 --- a/eeschema/class_hierarchical_PIN_sheet.cpp +++ b/eeschema/class_hierarchical_PIN_sheet.cpp @@ -340,6 +340,46 @@ void SCH_SHEET_PIN::Rotate( wxPoint rotationPoint ) } +/** Virtual Function SCH_SHEET_PIN::CreateGraphicShape + * calculates the graphic shape (a polygon) associated to the text + * @param aCorner_list = a buffer to fill with polygon corners coordinates + * @param aPos = Position of the shape + */ +void SCH_SHEET_PIN::CreateGraphicShape( std::vector & aCorner_list, + const wxPoint& aPos ) +{ + /* This is the same icon shapes as SCH_HIERLABEL + * but the graphic icon is slightly different in 2 cases: + * for INPUT type the icon is the OUTPUT shape of SCH_HIERLABEL + * for OUTPUT type the icon is the INPUT shape of SCH_HIERLABEL + */ + int tmp = m_Shape; + switch( m_Shape ) + { + case NET_INPUT: + m_Shape = NET_OUTPUT; + break; + + case NET_OUTPUT: + m_Shape = NET_INPUT; + break; + + default: + break; + } + SCH_HIERLABEL::CreateGraphicShape( aCorner_list, aPos ); + m_Shape = tmp; +} + + +void SCH_SHEET_PIN::GetEndPoints( std::vector & aItemList ) +{ + DANGLING_END_ITEM item( SHEET_LABEL_END, this ); + item.m_Pos = m_Pos; + aItemList.push_back( item ); +} + + #if defined(DEBUG) void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os ) { diff --git a/eeschema/class_marker_sch.cpp b/eeschema/class_marker_sch.cpp index c6daaefa6a..4ef1ef7320 100644 --- a/eeschema/class_marker_sch.cpp +++ b/eeschema/class_marker_sch.cpp @@ -180,3 +180,16 @@ void SCH_MARKER::Mirror_Y( int aYaxis_position ) m_Pos.x = -m_Pos.x; m_Pos.x += aYaxis_position; } + + +bool SCH_MARKER::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + if( aRect.Contains( m_Pos ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} diff --git a/eeschema/class_marker_sch.h b/eeschema/class_marker_sch.h index 0993471985..66a840b604 100644 --- a/eeschema/class_marker_sch.h +++ b/eeschema/class_marker_sch.h @@ -116,6 +116,8 @@ public: */ void DisplayInfo( WinEDA_DrawFrame* aFrame ); + virtual bool IsSelectStateChanged( const wxRect& aRect ); + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ); diff --git a/eeschema/class_sch_component.cpp b/eeschema/class_sch_component.cpp index 103c2ce4fe..de22999356 100644 --- a/eeschema/class_sch_component.cpp +++ b/eeschema/class_sch_component.cpp @@ -973,9 +973,9 @@ bool SCH_COMPONENT::Save( FILE* f ) const if( GetField( REFERENCE )->m_Text.IsEmpty() ) strncpy( Name1, CONV_TO_UTF8( m_PrefixString ), sizeof( Name1 ) ); else - strncpy( Name1, CONV_TO_UTF8( GetField( REFERENCE )->m_Text ), - sizeof( Name1 ) ); + strncpy( Name1, CONV_TO_UTF8( GetField( REFERENCE )->m_Text ), sizeof( Name1 ) ); } + for( ii = 0; ii < (int) strlen( Name1 ); ii++ ) { #if defined(KICAD_GOST) @@ -1284,3 +1284,77 @@ bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxP return false; } + + +void SCH_COMPONENT::GetEndPoints( std::vector & aItemList ) +{ + LIB_COMPONENT* Entry = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); + + if( Entry == NULL ) + return; + + for( LIB_PIN* Pin = Entry->GetNextPin(); Pin != NULL; Pin = Entry->GetNextPin( Pin ) ) + { + wxASSERT( Pin->Type() == COMPONENT_PIN_DRAW_TYPE ); + + if( Pin->GetUnit() && m_Multi && ( m_Multi != Pin->GetUnit() ) ) + continue; + + if( Pin->GetConvert() && m_Convert && ( m_Convert != Pin->GetConvert() ) ) + continue; + + DANGLING_END_ITEM item( PIN_END, Pin ); + item.m_Pos = GetPinPhysicalPosition( Pin ); + aItemList.push_back( item ); + } +} + + +wxPoint SCH_COMPONENT::GetPinPhysicalPosition( LIB_PIN* Pin ) +{ + wxCHECK_MSG( Pin != NULL && Pin->Type() == COMPONENT_PIN_DRAW_TYPE, wxPoint( 0, 0 ), + wxT( "Cannot get physical position of pin." ) ); + + return m_Transform.TransformCoordinate( Pin->m_Pos ) + m_Pos; +} + + +bool SCH_COMPONENT::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + EDA_Rect boundingBox = GetBoundingBox(); + + if( aRect.Intersects( boundingBox ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_COMPONENT::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + LIB_PIN* pin; + LIB_COMPONENT* component = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); + + wxCHECK_RET( component != NULL, + wxT( "Cannot add connection points to list. Cannot find component <" ) + + m_ChipName + wxT( "> in any of the loaded libraries." ) ); + + for( pin = component->GetNextPin( pin ); pin != NULL; pin = component->GetNextPin( pin ) ) + { + wxCHECK_RET( pin->Type() == COMPONENT_PIN_DRAW_TYPE, + wxT( "GetNextPin() did not return a pin object. Bad programmer!" ) ); + + // Skip items not used for this part. + if( m_Multi && pin->GetUnit() && ( pin->GetUnit() != m_Multi ) ) + continue; + if( m_Convert && pin->GetConvert() && ( pin->GetConvert() != m_Convert ) ) + continue; + + // Calculate the pin position relative to the component position and orientation. + aPoints.push_back( m_Transform.TransformCoordinate( pin->m_Pos ) + m_Pos ); + } +} diff --git a/eeschema/class_sch_component.h b/eeschema/class_sch_component.h index 6cc5801d73..ca6b1980d3 100644 --- a/eeschema/class_sch_component.h +++ b/eeschema/class_sch_component.h @@ -1,6 +1,6 @@ -/*****************************************************/ +/******************************************************/ /* Definitions for the Component classes for EESchema */ -/*****************************************************/ +/******************************************************/ #ifndef COMPONENT_CLASS_H #define COMPONENT_CLASS_H @@ -85,8 +85,7 @@ private: void Init( const wxPoint& pos = wxPoint( 0, 0 ) ); public: - SCH_COMPONENT( const wxPoint& pos = wxPoint( 0, 0 ), - SCH_ITEM* aParent = NULL ); + SCH_COMPONENT( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = NULL ); /** * Create schematic component from library component object. @@ -122,6 +121,7 @@ public: return wxT( "SCH_COMPONENT" ); } + TRANSFORM& GetTransform() const { return const_cast< TRANSFORM& >( m_Transform ); } /** * Function Save @@ -312,8 +312,7 @@ public: int GetUnitSelection( SCH_SHEET_PATH* aSheet ); // Set the unit selection, for the given sheet path. - void SetUnitSelection( SCH_SHEET_PATH* aSheet, - int aUnitSelection ); + void SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection ); /** Function GetPenSize * @return the size of the "pen" that be used to draw or plot this item @@ -355,8 +354,15 @@ public: * @param aFindLocation - a wxPoint where to put the location of matched item. can be NULL. * @return True if this component reference or value field matches the search criteria. */ - virtual bool Matches( wxFindReplaceData& aSearchData, - void* aAuxData, wxPoint * aFindLocation ); + virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + + virtual void GetEndPoints( std::vector & aItemList ); + + wxPoint GetPinPhysicalPosition( LIB_PIN* Pin ); + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; #if defined(DEBUG) diff --git a/eeschema/class_sch_screen.cpp b/eeschema/class_sch_screen.cpp index 5bb6c92f04..4842158f7e 100644 --- a/eeschema/class_sch_screen.cpp +++ b/eeschema/class_sch_screen.cpp @@ -353,6 +353,13 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount } +void SCH_SCREEN::ClearDrawingState() +{ + for( SCH_ITEM* item = EEDrawList; item != NULL; item = item->Next() ) + item->m_Flags = 0; +} + + /******************************************************************/ /* Class SCH_SCREENS to handle the list of screens in a hierarchy */ /******************************************************************/ diff --git a/eeschema/class_schematic_items.cpp b/eeschema/class_schematic_items.cpp index 86b8f5dfd1..289fa14647 100644 --- a/eeschema/class_schematic_items.cpp +++ b/eeschema/class_schematic_items.cpp @@ -167,12 +167,45 @@ void SCH_BUS_ENTRY::Rotate( wxPoint rotationPoint ) } +void SCH_BUS_ENTRY::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) +{ + DANGLING_END_ITEM item( ENTRY_END, this ); + item.m_Pos = m_Pos; + + DANGLING_END_ITEM item1( ENTRY_END, this ); + item1.m_Pos = m_End(); + aItemList.push_back( item ); + aItemList.push_back( item1 ); +} + + +bool SCH_BUS_ENTRY::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + // If either end of the bus entry is inside the selection rectangle, the entire + // bus entry is selected. Bus entries have a fixed length and angle. + if( aRect.Contains( m_Pos ) || aRect.Contains( m_End() ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_BUS_ENTRY::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + aPoints.push_back( m_Pos ); + aPoints.push_back( m_End() ); +} + + /**********************/ /* class SCH_JUNCTION */ /**********************/ -SCH_JUNCTION::SCH_JUNCTION( const wxPoint& pos ) : - SCH_ITEM( NULL, DRAW_JUNCTION_STRUCT_TYPE ) +SCH_JUNCTION::SCH_JUNCTION( const wxPoint& pos ) : SCH_ITEM( NULL, DRAW_JUNCTION_STRUCT_TYPE ) { #define DRAWJUNCTION_DIAMETER 32 /* Diameter of junction symbol between wires */ m_Pos = pos; @@ -289,6 +322,33 @@ void SCH_JUNCTION::Rotate( wxPoint rotationPoint ) } +void SCH_JUNCTION::GetEndPoints( std::vector & aItemList ) +{ + DANGLING_END_ITEM item( JUNCTION_END, this ); + item.m_Pos = m_Pos; + aItemList.push_back( item ); +} + + +bool SCH_JUNCTION::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + if( aRect.Contains( m_Pos ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_JUNCTION::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + aPoints.push_back( m_Pos ); +} + + #if defined(DEBUG) void SCH_JUNCTION::Show( int nestLevel, std::ostream& os ) { @@ -306,8 +366,7 @@ void SCH_JUNCTION::Show( int nestLevel, std::ostream& os ) /* class SCH_NO_CONNECT */ /************************/ -SCH_NO_CONNECT::SCH_NO_CONNECT( const wxPoint& pos ) : - SCH_ITEM( NULL, DRAW_NOCONNECT_STRUCT_TYPE ) +SCH_NO_CONNECT::SCH_NO_CONNECT( const wxPoint& pos ) : SCH_ITEM( NULL, DRAW_NOCONNECT_STRUCT_TYPE ) { #define DRAWNOCONNECT_SIZE 48 /* No symbol connection range. */ m_Pos = pos; @@ -430,6 +489,25 @@ void SCH_NO_CONNECT::Rotate( wxPoint rotationPoint ) } +bool SCH_NO_CONNECT::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + if( aRect.Contains( m_Pos ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_NO_CONNECT::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + aPoints.push_back( m_Pos ); +} + + /******************/ /* Class SCH_LINE */ /******************/ @@ -634,9 +712,7 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine ) wxCHECK_MSG( aLine != NULL && aLine->Type() == DRAW_SEGMENT_STRUCT_TYPE, false, wxT( "Cannot test line segment for overlap." ) ); - if( this == aLine ) - return false; - if( GetLayer() != aLine->GetLayer() ) + if( this == aLine || GetLayer() != aLine->GetLayer() ) return false; // Search for a common end, and modify coordinates to ensure RefSegm->m_End @@ -658,8 +734,10 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine ) EXCHG( aLine->m_Start, aLine->m_End ); } else if( m_End != aLine->m_Start ) + { // No common end point, segments cannot be merged. return false; + } /* Test alignment: */ if( m_Start.y == m_End.y ) // Horizontal segment @@ -693,12 +771,86 @@ bool SCH_LINE::MergeOverlap( SCH_LINE* aLine ) } -/***********************/ -/* Class SCH_POLYLINE */ -/***********************/ +void SCH_LINE::GetEndPoints( std::vector & aItemList ) +{ + if( GetLayer() == LAYER_NOTES ) + return; -SCH_POLYLINE::SCH_POLYLINE( int layer ) : - SCH_ITEM( NULL, DRAW_POLYLINE_STRUCT_TYPE ) + if( ( GetLayer() == LAYER_BUS ) || ( GetLayer() == LAYER_WIRE ) ) + { + DANGLING_END_ITEM item( (GetLayer() == LAYER_BUS) ? BUS_START_END : WIRE_START_END, this ); + item.m_Pos = m_Start; + DANGLING_END_ITEM item1( (GetLayer() == LAYER_BUS) ? BUS_END_END : WIRE_END_END, this ); + item1.m_Pos = m_End; + + aItemList.push_back( item ); + aItemList.push_back( item1 ); + } +} + + +bool SCH_LINE::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ) +{ + bool previousStartState = m_StartIsDangling; + bool previousEndState = m_EndIsDangling; + + if( GetLayer() == LAYER_WIRE ) + { + BOOST_FOREACH( DANGLING_END_ITEM item, aItemList ) + { + if( item.m_Item == this ) + continue; + + if( m_Start == item.m_Pos ) + m_StartIsDangling = false; + + if( m_End == item.m_Pos ) + m_EndIsDangling = false; + + if( (m_StartIsDangling == false) && (m_EndIsDangling == false) ) + break; + } + } + else if( GetLayer() == LAYER_BUS || GetLayer() == LAYER_NOTES ) + { + // Lines on the notes layer and the bus layer cannot be tested for dangling ends. + previousStartState = previousEndState = m_StartIsDangling = m_EndIsDangling = false; + } + + return ( previousStartState != m_StartIsDangling ) || ( previousEndState != m_EndIsDangling ); +} + + +bool SCH_LINE::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + if( aRect.Contains( m_Start ) ) + m_Flags |= STARTPOINT | SELECTED; + else + m_Flags &= ~( STARTPOINT | SELECTED ); + + if( aRect.Contains( m_End ) ) + m_Flags |= ENDPOINT | SELECTED; + else + m_Flags &= ~( ENDPOINT | SELECTED ); + + return previousState != IsSelected(); +} + + +void SCH_LINE::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + aPoints.push_back( m_Start ); + aPoints.push_back( m_End ); +} + + +/**********************/ +/* Class SCH_POLYLINE */ +/**********************/ + +SCH_POLYLINE::SCH_POLYLINE( int layer ) : SCH_ITEM( NULL, DRAW_POLYLINE_STRUCT_TYPE ) { m_Width = 0; diff --git a/eeschema/class_schematic_items.h b/eeschema/class_schematic_items.h index 4d71dc3301..62d4be162e 100644 --- a/eeschema/class_schematic_items.h +++ b/eeschema/class_schematic_items.h @@ -108,6 +108,16 @@ public: */ bool MergeOverlap( SCH_LINE* aLine ); + virtual void GetEndPoints( std::vector & aItemList ); + + virtual bool IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ); + + virtual bool IsDangling() const { return m_StartIsDangling || m_EndIsDangling; } + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ); @@ -185,6 +195,10 @@ public: virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_X( int aXaxis_position ); virtual void Rotate( wxPoint rotationPoint ); + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; }; @@ -259,6 +273,12 @@ public: virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_X( int aXaxis_position ); virtual void Rotate( wxPoint rotationPoint ); + + virtual void GetEndPoints( std::vector & aItemList ); + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; }; class SCH_POLYLINE : public SCH_ITEM @@ -405,6 +425,12 @@ public: virtual void Mirror_X( int aXaxis_position ); virtual void Rotate( wxPoint rotationPoint ); + virtual void GetEndPoints( std::vector & aItemList ); + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ); diff --git a/eeschema/class_text-label.cpp b/eeschema/class_text-label.cpp index 90f599d9ed..a95060a900 100644 --- a/eeschema/class_text-label.cpp +++ b/eeschema/class_text-label.cpp @@ -65,29 +65,21 @@ static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 }; static int* TemplateShape[5][4] = { - { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, - TemplateIN_BOTTOM }, - { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, - TemplateOUT_BOTTOM }, - { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, - TemplateBIDI_BOTTOM }, - { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, - Template3STATE_BOTTOM }, - { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, - TemplateUNSPC_BOTTOM } + { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM }, + { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM }, + { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM }, + { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM }, + { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM } }; -/**************************************************************************/ -SCH_TEXT::SCH_TEXT( const wxPoint& pos, const wxString& text, - KICAD_T aType ) : +SCH_TEXT::SCH_TEXT( const wxPoint& pos, const wxString& text, KICAD_T aType ) : SCH_ITEM( NULL, aType ), EDA_TextStruct( text ) { -/**************************************************************************/ m_Layer = LAYER_NOTES; m_Pos = pos; m_Shape = 0; - m_IsDangling = FALSE; + m_IsDangling = false; m_MultilineAllowed = true; m_SchematicOrientation = 0; } @@ -103,10 +95,8 @@ bool SCH_TEXT::HitTest( const wxPoint& aPosRef ) } -/*********************************************/ SCH_TEXT* SCH_TEXT::GenCopy() { -/*********************************************/ SCH_TEXT* newitem; switch( Type() ) @@ -190,23 +180,11 @@ bool SCH_TEXT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint *aFindLocation = BoundaryBox.Centre(); return true; } - + return false; } -/** function GetSchematicTextOffset (virtual) - * @return the offset between the SCH_TEXT position and the text itself - * position - * This offset depend on orientation, and the type of text - * (room to draw an associated graphic symbol, or put the text above a wire) - */ -wxPoint SCH_LABEL::GetSchematicTextOffset() -{ - return SCH_TEXT::GetSchematicTextOffset(); -} - - /** virtual function Mirror_Y * mirror item relative to an Y axis * @param aYaxis_position = the y axis position @@ -330,95 +308,512 @@ void SCH_TEXT::Rotate( wxPoint rotationPoint ) } +/** function SetTextOrientAndJustifyParmeters (virtual) + * Set m_SchematicOrientation, and initialize + * m_orient,m_HJustified and m_VJustified, according to the value of + * m_SchematicOrientation + * must be called after changing m_SchematicOrientation + * @param aSchematicOrientation = + * 0 = normal (horizontal, left justified). + * 1 = up (vertical) + * 2 = (horizontal, right justified). This can be seen as the mirrored + * position of 0 + * 3 = bottom . This can be seen as the mirrored position of up + */ +void SCH_TEXT::SetSchematicTextOrientation( int aSchematicOrientation ) +{ + m_SchematicOrientation = aSchematicOrientation; + + switch( m_SchematicOrientation ) + { + default: + case 0: /* Horiz Normal Orientation (left justified) */ + m_Orient = TEXT_ORIENT_HORIZ; + m_HJustify = GR_TEXT_HJUSTIFY_LEFT; + m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; + break; + + case 1: /* Vert Orientation UP */ + m_Orient = TEXT_ORIENT_VERT; + m_HJustify = GR_TEXT_HJUSTIFY_LEFT; + m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; + break; + + case 2: /* Horiz Orientation - Right justified */ + m_Orient = TEXT_ORIENT_HORIZ; + m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; + m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; + break; + + case 3: /* Vert Orientation BOTTOM */ + m_Orient = TEXT_ORIENT_VERT; + m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; + m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; + break; + } +} + + +void SCH_TEXT::SwapData( SCH_TEXT* copyitem ) +{ + EXCHG( m_Text, copyitem->m_Text ); + EXCHG( m_Pos, copyitem->m_Pos ); + EXCHG( m_Size, copyitem->m_Size ); + EXCHG( m_Width, copyitem->m_Width ); + EXCHG( m_Shape, copyitem->m_Shape ); + EXCHG( m_Orient, copyitem->m_Orient ); + + EXCHG( m_Layer, copyitem->m_Layer ); + EXCHG( m_HJustify, copyitem->m_HJustify ); + EXCHG( m_VJustify, copyitem->m_VJustify ); + EXCHG( m_IsDangling, copyitem->m_IsDangling ); + EXCHG( m_SchematicOrientation, copyitem->m_SchematicOrientation ); +} + + +void SCH_TEXT::Place( WinEDA_SchematicFrame* frame, wxDC* DC ) +{ + /* save old text in undo list */ + if( g_ItemToUndoCopy && ( (m_Flags & IS_NEW) == 0 ) ) + { + /* restore old values and save new ones */ + SwapData( (SCH_TEXT*) g_ItemToUndoCopy ); + + /* save in undo list */ + frame->SaveCopyInUndoList( this, UR_CHANGED ); + + /* restore new values */ + SwapData( (SCH_TEXT*) g_ItemToUndoCopy ); + + SAFE_DELETE( g_ItemToUndoCopy ); + } + + SCH_ITEM::Place( frame, DC ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int SCH_TEXT::GetPenSize() +{ + int pensize = m_Width; + + if( pensize == 0 ) // Use default values for pen size + { + if( m_Bold ) + pensize = GetPenSizeForBold( m_Size.x ); + else + pensize = g_DrawDefaultLineThickness; + } + + // Clip pen size for small texts: + pensize = Clamp_Text_PenSize( pensize, m_Size, m_Bold ); + return pensize; +} + + +/* Text type Comment (text on layer "NOTE") have 4 directions, and the Text + * origin is the first letter + */ +void SCH_TEXT::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& aOffset, + int DrawMode, int Color ) +{ + EDA_Colors color; + int linewidth = ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; + + linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); + + if( Color >= 0 ) + color = (EDA_Colors) Color; + else + color = ReturnLayerColor( m_Layer ); + GRSetDrawMode( DC, DrawMode ); + + wxPoint text_offset = aOffset + GetSchematicTextOffset(); + + EXCHG( linewidth, m_Width ); // Set the minimum width + EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR ); + EXCHG( linewidth, m_Width ); // set initial value + if( m_IsDangling ) + DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color ); + + // Enable these line to draw the bounding box (debug tests purposes only) +#if 0 + { + EDA_Rect BoundaryBox; + BoundaryBox = GetBoundingBox(); + int x1 = BoundaryBox.GetX(); + int y1 = BoundaryBox.GetY(); + int x2 = BoundaryBox.GetRight(); + int y2 = BoundaryBox.GetBottom(); + GRRect( &panel->m_ClipBox, DC, x1, y1, x2, y2, BROWN ); + } +#endif +} + + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ +bool SCH_TEXT::Save( FILE* aFile ) const +{ + bool success = true; + const char* shape = "~"; + + if( m_Italic ) + shape = "Italic"; + + wxString text = m_Text; + + for( ; ; ) + { + int i = text.find( '\n' ); + if( i == wxNOT_FOUND ) + break; + + text.erase( i, 1 ); + text.insert( i, wxT( "\\n" ) ); + } + + if( fprintf( aFile, "Text Notes %-4d %-4d %-4d %-4d %s %d\n%s\n", + m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, + shape, m_Width, CONV_TO_UTF8( text ) ) == EOF ) + { + success = false; + } + + return success; +} + + +void SCH_TEXT::GetEndPoints( std::vector & aItemList ) +{ + // Normal text labels cannot be tested for dangling ends. + if( Type() == TYPE_SCH_TEXT ) + return; + + DANGLING_END_ITEM item( LABEL_END, this ); + item.m_Pos = m_Pos; + aItemList.push_back( item ); +} + + +bool SCH_TEXT::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ) +{ + // Normal text labels cannot be tested for dangling ends. + if( Type() == TYPE_SCH_TEXT ) + return false; + + bool previousState = m_IsDangling; + + for( unsigned ii = 0; ii < aItemList.size(); ii++ ) + { + DANGLING_END_ITEM& item = aItemList[ii]; + + if( item.m_Item == this ) + continue; + + switch( item.m_Type ) + { + case PIN_END: + case LABEL_END: + case SHEET_LABEL_END: + if( m_Pos == item.m_Pos ) + m_IsDangling = false; + break; + + case WIRE_START_END: + case BUS_START_END: + { + // These schematic items have created 2 DANGLING_END_ITEM one per end. But being + // a paranoid programmer, I'll check just in case. + ii++; + + wxCHECK_MSG( ii < aItemList.size(), previousState != m_IsDangling, + wxT( "Dangling end type list overflow. Bad programmer!" ) ); + + DANGLING_END_ITEM & nextItem = aItemList[ii]; + m_IsDangling = !SegmentIntersect( item.m_Pos, nextItem.m_Pos, m_Pos ); + } + break; + + default: + break; + } + + if( m_IsDangling == false ) + break; + } + + return previousState != m_IsDangling; +} + + +bool SCH_TEXT::IsSelectStateChanged( const wxRect& aRect ) +{ + bool previousState = IsSelected(); + + if( aRect.Contains( m_Pos ) ) + m_Flags |= SELECTED; + else + m_Flags &= ~SELECTED; + + return previousState != IsSelected(); +} + + +void SCH_TEXT::GetConnectionPoints( vector< wxPoint >& aPoints ) const +{ + // Normal text labels do not have connection points. All others do. + if( Type() == TYPE_SCH_TEXT ) + return; + + aPoints.push_back( m_Pos ); +} + + +EDA_Rect SCH_TEXT::GetBoundingBox() +{ + // We must pass the effective text thickness to GetTextBox + // when calculating the bounding box + int linewidth = ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; + + linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); + EXCHG( linewidth, m_Width ); // Set the real width + EDA_Rect rect = GetTextBox( -1 ); + EXCHG( linewidth, m_Width ); // set initial value + + if( m_Orient ) // Rotate rect + { + wxPoint pos = rect.GetOrigin(); + wxPoint end = rect.GetEnd(); + RotatePoint( &pos, m_Pos, m_Orient ); + RotatePoint( &end, m_Pos, m_Orient ); + rect.SetOrigin( pos ); + rect.SetEnd( end ); + } + + rect.Normalize(); + return rect; +} + + +#if defined(DEBUG) + +void SCH_TEXT::Show( int nestLevel, std::ostream& os ) +{ + // XML output: + wxString s = GetClass(); + + NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() + << " layer=\"" << m_Layer << '"' + << " shape=\"" << m_Shape << '"' + << " dangling=\"" << m_IsDangling << '"' + << '>' + << CONV_TO_UTF8( m_Text ) + << "\n"; +} + + +#endif + + /** function GetSchematicTextOffset (virtual) * @return the offset between the SCH_TEXT position and the text itself * position * This offset depend on orientation, and the type of text * (room to draw an associated graphic symbol, or put the text above a wire) */ -wxPoint SCH_HIERLABEL::GetSchematicTextOffset() +wxPoint SCH_LABEL::GetSchematicTextOffset() { - wxPoint text_offset; + return SCH_TEXT::GetSchematicTextOffset(); +} - int width = MAX( m_Width, g_DrawDefaultLineThickness ); - int ii = m_Size.x + TXTMARGE + width; +/** function SetTextOrientAndJustifyParmeters + * Set m_SchematicOrientation, and initialize + * m_orient,m_HJustified and m_VJustified, according to the value of + * m_SchematicOrientation (for a label) + * must be called after changing m_SchematicOrientation + * @param aSchematicOrientation = + * 0 = normal (horizontal, left justified). + * 1 = up (vertical) + * 2 = (horizontal, right justified). This can be seen as the mirrored + * position of 0 + * 3 = bottom . This can be seen as the mirrored position of up + */ +void SCH_LABEL::SetSchematicTextOrientation( int aSchematicOrientation ) +{ + SCH_TEXT::SetSchematicTextOrientation( aSchematicOrientation ); +} + + +SCH_LABEL::SCH_LABEL( const wxPoint& pos, const wxString& text ) : + SCH_TEXT( pos, text, TYPE_SCH_LABEL ) +{ + m_Layer = LAYER_LOCLABEL; + m_Shape = NET_INPUT; + m_IsDangling = TRUE; + m_MultilineAllowed = false; +} + + +/** virtual function Mirror_X + * mirror item relative to an X axis + * @param aXaxis_position = the x axis position + */ +void SCH_LABEL::Mirror_X( int aXaxis_position ) +{ + // 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 + int py = m_Pos.y; + + py -= aXaxis_position; + NEGATE( py ); + py += aXaxis_position; + m_Pos.y = py; +} + + +void SCH_LABEL::Rotate( wxPoint rotationPoint ) +{ + RotatePoint( &m_Pos, rotationPoint, 900 ); + SetSchematicTextOrientation( (GetSchematicTextOrientation() + 1) % 4 ); +} + + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ +bool SCH_LABEL::Save( FILE* aFile ) const +{ + bool success = true; + const char* shape = "~"; + + if( m_Italic ) + shape = "Italic"; + + if( fprintf( aFile, "Text Label %-4d %-4d %-4d %-4d %s %d\n%s\n", + m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, shape, + m_Width, CONV_TO_UTF8( m_Text ) ) == EOF ) + { + success = false; + } + + return success; +} + + +/** Function SCH_LABEL::Draw + * a label is drawn like a text. So just call SCH_TEXT::Draw + */ +void SCH_LABEL::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, + int DrawMode, int Color ) +{ + SCH_TEXT::Draw( panel, DC, offset, DrawMode, Color ); +} + + +EDA_Rect SCH_LABEL::GetBoundingBox() +{ + int x, y, dx, dy, length, height; + + x = m_Pos.x; + y = m_Pos.y; + int width = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; + length = LenSize( m_Text ); + height = m_Size.y + width; + dx = dy = 0; switch( m_SchematicOrientation ) { - case 0: /* Orientation horiz normale */ - text_offset.x = -ii; + case 0: /* Horiz Normal Orientation (left justified) */ + dx = 2 * DANGLING_SYMBOL_SIZE + length; + dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; + x -= DANGLING_SYMBOL_SIZE; + y += DANGLING_SYMBOL_SIZE; break; - case 1: /* Orientation vert UP */ - text_offset.y = -ii; + case 1: /* Vert Orientation UP */ + dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; + dy = -2 * DANGLING_SYMBOL_SIZE - length; + x += DANGLING_SYMBOL_SIZE; + y += DANGLING_SYMBOL_SIZE; break; - case 2: /* Orientation horiz inverse */ - text_offset.x = ii; + case 2: /* Horiz Orientation - Right justified */ + dx = -2 * DANGLING_SYMBOL_SIZE - length; + dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; + x += DANGLING_SYMBOL_SIZE; + y += DANGLING_SYMBOL_SIZE; break; - case 3: /* Orientation vert BOTTOM */ - text_offset.y = ii; + case 3: /* Vert Orientation BOTTOM */ + dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; + dy = 2 * DANGLING_SYMBOL_SIZE + length; + x += DANGLING_SYMBOL_SIZE; + y -= DANGLING_SYMBOL_SIZE; break; } - return text_offset; + EDA_Rect box( wxPoint( x, y ), wxSize( dx, dy ) ); + box.Normalize(); + return box; } -/** virtual function Mirror_Y - * mirror item relative to an Y axis - * @param aYaxis_position = the y axis position +SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) : + SCH_TEXT( pos, text, TYPE_SCH_GLOBALLABEL ) +{ + m_Layer = LAYER_GLOBLABEL; + m_Shape = NET_BIDI; + m_IsDangling = TRUE; + m_MultilineAllowed = false; +} + + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. */ -void SCH_HIERLABEL::Mirror_Y( int aYaxis_position ) +bool SCH_GLOBALLABEL::Save( FILE* aFile ) const { -/* The hierarchical label is NOT really mirrored. - * for an horizontal label, the schematic orientation is changed. - * for a vericalal label, the schematic orientation is not changed. - * and the label is moved to a suitable position + bool success = true; + const char* shape = "~"; + + if( m_Italic ) + shape = "Italic"; + if( fprintf( aFile, "Text GLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n", + m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, + SheetLabelType[m_Shape], shape, m_Width, CONV_TO_UTF8( m_Text ) ) == EOF ) + { + success = false; + } + + return success; +} + + +/** Function HitTest + * @return true if the point aPosRef is within item area + * @param aPosRef = a wxPoint to test */ - - switch( GetSchematicTextOrientation() ) - { - case 0: /* horizontal text */ - SetSchematicTextOrientation( 2 ); - break; - - case 2: /* invert horizontal text*/ - SetSchematicTextOrientation( 0 ); - break; - } - - m_Pos.x -= aYaxis_position; - NEGATE( m_Pos.x ); - m_Pos.x += aYaxis_position; -} - - -void SCH_HIERLABEL::Mirror_X( int aXaxis_position ) +bool SCH_GLOBALLABEL::HitTest( const wxPoint& aPosRef ) { - switch( GetSchematicTextOrientation() ) - { - case 1: /* vertical text */ - SetSchematicTextOrientation( 3 ); - break; + EDA_Rect rect = GetBoundingBox(); - case 3: /* invert vertical text*/ - SetSchematicTextOrientation( 1 ); - break; - } - - m_Pos.y -= aXaxis_position; - NEGATE( m_Pos.y ); - m_Pos.y += aXaxis_position; -} - - -void SCH_HIERLABEL::Rotate( wxPoint rotationPoint ) -{ - RotatePoint( &m_Pos, rotationPoint, 900 ); - SetSchematicTextOrientation( (GetSchematicTextOrientation() + 3) % 4 ); + return rect.Inside( aPosRef ); } @@ -531,70 +926,6 @@ wxPoint SCH_GLOBALLABEL::GetSchematicTextOffset() } -/** function SetTextOrientAndJustifyParmeters (virtual) - * Set m_SchematicOrientation, and initialize - * m_orient,m_HJustified and m_VJustified, according to the value of - * m_SchematicOrientation - * must be called after changing m_SchematicOrientation - * @param aSchematicOrientation = - * 0 = normal (horizontal, left justified). - * 1 = up (vertical) - * 2 = (horizontal, right justified). This can be seen as the mirrored - * position of 0 - * 3 = bottom . This can be seen as the mirrored position of up - */ -void SCH_TEXT::SetSchematicTextOrientation( int aSchematicOrientation ) -{ - m_SchematicOrientation = aSchematicOrientation; - - switch( m_SchematicOrientation ) - { - default: - case 0: /* Horiz Normal Orientation (left justified) */ - m_Orient = TEXT_ORIENT_HORIZ; - m_HJustify = GR_TEXT_HJUSTIFY_LEFT; - m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; - break; - - case 1: /* Vert Orientation UP */ - m_Orient = TEXT_ORIENT_VERT; - m_HJustify = GR_TEXT_HJUSTIFY_LEFT; - m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; - break; - - case 2: /* Horiz Orientation - Right justified */ - m_Orient = TEXT_ORIENT_HORIZ; - m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; - m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; - break; - - case 3: /* Vert Orientation BOTTOM */ - m_Orient = TEXT_ORIENT_VERT; - m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; - m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM; - break; - } -} - - -/** function SetTextOrientAndJustifyParmeters - * Set m_SchematicOrientation, and initialize - * m_orient,m_HJustified and m_VJustified, according to the value of - * m_SchematicOrientation (for a label) - * must be called after changing m_SchematicOrientation - * @param aSchematicOrientation = - * 0 = normal (horizontal, left justified). - * 1 = up (vertical) - * 2 = (horizontal, right justified). This can be seen as the mirrored - * position of 0 - * 3 = bottom . This can be seen as the mirrored position of up - */ -void SCH_LABEL::SetSchematicTextOrientation( int aSchematicOrientation ) -{ - SCH_TEXT::SetSchematicTextOrientation( aSchematicOrientation ); -} - - /** function SetTextOrientAndJustifyParmeters * Set m_SchematicOrientation, and initialize * m_orient,m_HJustified and m_VJustified, according to the value of @@ -641,571 +972,14 @@ void SCH_GLOBALLABEL::SetSchematicTextOrientation( int aSchematicOrientation ) } -/** function SetTextOrientAndJustifyParmeters - * Set m_SchematicOrientation, and initialize - * m_orient,m_HJustified and m_VJustified, according to the value of - * m_SchematicOrientation - * must be called after changing m_SchematicOrientation - * @param aSchematicOrientation = - * 0 = normal (horizontal, left justified). - * 1 = up (vertical) - * 2 = (horizontal, right justified). This can be seen as the mirrored - * position of 0 - * 3 = bottom . This can be seen as the mirrored position of up +/* Texts type Global Label have 4 directions, and the Text origin is the graphic icon */ -void SCH_HIERLABEL::SetSchematicTextOrientation( int aSchematicOrientation ) -{ - m_SchematicOrientation = aSchematicOrientation; - - switch( m_SchematicOrientation ) - { - default: - case 0: /* Horiz Normal Orientation */ - m_Orient = TEXT_ORIENT_HORIZ; - m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; - m_VJustify = GR_TEXT_VJUSTIFY_CENTER; - break; - - case 1: /* Vert Orientation UP */ - m_Orient = TEXT_ORIENT_VERT; - m_HJustify = GR_TEXT_HJUSTIFY_LEFT; - m_VJustify = GR_TEXT_VJUSTIFY_CENTER; - break; - - case 2: /* Horiz Orientation */ - m_Orient = TEXT_ORIENT_HORIZ; - m_HJustify = GR_TEXT_HJUSTIFY_LEFT; - m_VJustify = GR_TEXT_VJUSTIFY_CENTER; - break; - - case 3: /* Vert Orientation BOTTOM */ - m_Orient = TEXT_ORIENT_VERT; - m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; - m_VJustify = GR_TEXT_VJUSTIFY_CENTER; - break; - } -} - - -/********************************************************/ -void SCH_TEXT::SwapData( SCH_TEXT* copyitem ) -{ -/********************************************************/ - EXCHG( m_Text, copyitem->m_Text ); - EXCHG( m_Pos, copyitem->m_Pos ); - EXCHG( m_Size, copyitem->m_Size ); - EXCHG( m_Width, copyitem->m_Width ); - EXCHG( m_Shape, copyitem->m_Shape ); - EXCHG( m_Orient, copyitem->m_Orient ); - - EXCHG( m_Layer, copyitem->m_Layer ); - EXCHG( m_HJustify, copyitem->m_HJustify ); - EXCHG( m_VJustify, copyitem->m_VJustify ); - EXCHG( m_IsDangling, copyitem->m_IsDangling ); - EXCHG( m_SchematicOrientation, copyitem->m_SchematicOrientation ); -} - - -/***************************************************************/ -void SCH_TEXT::Place( WinEDA_SchematicFrame* frame, wxDC* DC ) -{ -/***************************************************************/ - /* save old text in undo list */ - if( g_ItemToUndoCopy && ( (m_Flags & IS_NEW) == 0 ) ) - { - /* restore old values and save new ones */ - SwapData( (SCH_TEXT*) g_ItemToUndoCopy ); - - /* save in undo list */ - frame->SaveCopyInUndoList( this, UR_CHANGED ); - - /* restore new values */ - SwapData( (SCH_TEXT*) g_ItemToUndoCopy ); - - SAFE_DELETE( g_ItemToUndoCopy ); - } - - SCH_ITEM::Place( frame, DC ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int SCH_TEXT::GetPenSize() -{ - int pensize = m_Width; - - if( pensize == 0 ) // Use default values for pen size - { - if( m_Bold ) - pensize = GetPenSizeForBold( m_Size.x ); - else - pensize = g_DrawDefaultLineThickness; - } - - // Clip pen size for small texts: - pensize = Clamp_Text_PenSize( pensize, m_Size, m_Bold ); - return pensize; -} - - -/****************************************************************************/ -void SCH_TEXT::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& aOffset, - int DrawMode, int Color ) -{ -/****************************************************************************/ - -/* Text type Comment (text on layer "NOTE") have 4 directions, and the Text - * origin is the first letter - */ - EDA_Colors color; - int linewidth = - (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; - - linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); - - if( Color >= 0 ) - color = (EDA_Colors) Color; - else - color = ReturnLayerColor( m_Layer ); - GRSetDrawMode( DC, DrawMode ); - - wxPoint text_offset = aOffset + GetSchematicTextOffset(); - - EXCHG( linewidth, m_Width ); // Set the minimum width - EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, - UNSPECIFIED_COLOR ); - EXCHG( linewidth, m_Width ); // set initial value - if( m_IsDangling ) - DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color ); - - // Enable these line to draw the bounding box (debug tests purposes only) -#if 0 - { - EDA_Rect BoundaryBox; - BoundaryBox = GetBoundingBox(); - int x1 = BoundaryBox.GetX(); - int y1 = BoundaryBox.GetY(); - int x2 = BoundaryBox.GetRight(); - int y2 = BoundaryBox.GetBottom(); - GRRect( &panel->m_ClipBox, DC, x1, y1, x2, y2, BROWN ); - } -#endif -} - - -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ -bool SCH_TEXT::Save( FILE* aFile ) const -{ - bool success = true; - const char* shape = "~"; - - if( m_Italic ) - shape = "Italic"; - - wxString text = m_Text; - - for( ; ; ) - { - int i = text.find( '\n' ); - if( i==wxNOT_FOUND ) - break; - - text.erase( i, 1 ); - text.insert( i, wxT( "\\n" ) ); - } - - if( fprintf( aFile, "Text Notes %-4d %-4d %-4d %-4d %s %d\n%s\n", - m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, - shape, m_Width, CONV_TO_UTF8( text ) ) == EOF ) - { - success = false; - } - - return success; -} - - -#if defined(DEBUG) - -void SCH_TEXT::Show( int nestLevel, std::ostream& os ) -{ - // XML output: - wxString s = GetClass(); - - NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() - << " layer=\"" << m_Layer << '"' - << " shape=\"" << m_Shape << '"' - << " dangling=\"" << m_IsDangling << '"' - << '>' - << CONV_TO_UTF8( m_Text ) - << "\n"; -} - - -#endif - -/****************************************************************************/ -SCH_LABEL::SCH_LABEL( const wxPoint& pos, const wxString& text ) : - SCH_TEXT( pos, text, TYPE_SCH_LABEL ) -{ -/****************************************************************************/ - m_Layer = LAYER_LOCLABEL; - m_Shape = NET_INPUT; - m_IsDangling = TRUE; - m_MultilineAllowed = false; -} - - -/** virtual function Mirror_X - * mirror item relative to an X axis - * @param aXaxis_position = the x axis position - */ -void SCH_LABEL::Mirror_X( int aXaxis_position ) -{ - // 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 - int py = m_Pos.y; - - py -= aXaxis_position; - NEGATE( py ); - py += aXaxis_position; - m_Pos.y = py; -} - - -void SCH_LABEL::Rotate( wxPoint rotationPoint ) -{ - RotatePoint( &m_Pos, rotationPoint, 900 ); - SetSchematicTextOrientation( (GetSchematicTextOrientation() + 1) % 4 ); -} - - -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ -bool SCH_LABEL::Save( FILE* aFile ) const -{ - bool success = true; - const char* shape = "~"; - - if( m_Italic ) - shape = "Italic"; - - if( fprintf( aFile, "Text Label %-4d %-4d %-4d %-4d %s %d\n%s\n", - m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, shape, - m_Width, CONV_TO_UTF8( m_Text ) ) == EOF ) - { - success = false; - } - - return success; -} - - -/*****************************************************************************/ -SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) : - SCH_TEXT( pos, text, TYPE_SCH_GLOBALLABEL ) -{ -/*****************************************************************************/ - m_Layer = LAYER_GLOBLABEL; - m_Shape = NET_BIDI; - m_IsDangling = TRUE; - m_MultilineAllowed = false; -} - - -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ -bool SCH_GLOBALLABEL::Save( FILE* aFile ) const -{ - bool success = true; - const char* shape = "~"; - - if( m_Italic ) - shape = "Italic"; - if( fprintf( aFile, "Text GLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n", - m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, - SheetLabelType[m_Shape], shape, m_Width, - CONV_TO_UTF8( m_Text ) ) == EOF ) - { - success = false; - } - - return success; -} - - -/************************************************/ -bool SCH_GLOBALLABEL::HitTest( const wxPoint& aPosRef ) -{ -/************************************************/ - -/** Function HitTest - * @return true if the point aPosRef is within item area - * @param aPosRef = a wxPoint to test - */ - EDA_Rect rect = GetBoundingBox(); - - return rect.Inside( aPosRef ); -} - - -/*****************************************************************************/ -SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) : - SCH_TEXT( pos, text, aType ) -{ -/*****************************************************************************/ - m_Layer = LAYER_HIERLABEL; - m_Shape = NET_INPUT; - m_IsDangling = TRUE; - m_MultilineAllowed = false; -} - - -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ -bool SCH_HIERLABEL::Save( FILE* aFile ) const -{ - bool success = true; - const char* shape = "~"; - - if( m_Italic ) - shape = "Italic"; - if( fprintf( aFile, "Text HLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n", - m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, - SheetLabelType[m_Shape], shape, m_Width, - CONV_TO_UTF8( m_Text ) ) == EOF ) - { - success = false; - } - - return success; -} - - -/************************************************/ -bool SCH_HIERLABEL::HitTest( const wxPoint& aPosRef ) -{ -/************************************************/ - -/** Function HitTest - * @return true if the point aPosRef is within item area - * @param aPosRef = a wxPoint to test - */ - EDA_Rect rect = GetBoundingBox(); - - return rect.Inside( aPosRef ); -} - - -/** Function SCH_LABEL::Draw - * a label is drawn like a text. So just call SCH_TEXT::Draw - */ -void SCH_LABEL::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, - int DrawMode, int Color ) -{ - SCH_TEXT::Draw( panel, DC, offset, DrawMode, Color ); -} - - -/*****************************************************************************/ -void SCH_HIERLABEL::Draw( WinEDA_DrawPanel* panel, - wxDC* DC, - const wxPoint& offset, - int DrawMode, - int Color ) -{ -/*****************************************************************************/ - -/* Hierarchical Label have a text and a graphic icon. - * Texts type have 4 directions, and the text origin is the graphic icon - */ - static std::vector Poly; - EDA_Colors color; - int linewidth = - ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; - - linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); - - if( Color >= 0 ) - color = (EDA_Colors) Color; - else - color = ReturnLayerColor( m_Layer ); - - GRSetDrawMode( DC, DrawMode ); - - EXCHG( linewidth, m_Width ); // Set the minimum width - wxPoint text_offset = offset + GetSchematicTextOffset(); - EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, - UNSPECIFIED_COLOR ); - EXCHG( linewidth, m_Width ); // set initial value - - CreateGraphicShape( Poly, m_Pos + offset ); - GRPoly( &panel->m_ClipBox, DC, Poly.size(), &Poly[0], 0, linewidth, - color, color ); - - if( m_IsDangling ) - DrawDanglingSymbol( panel, DC, m_Pos + offset, color ); - - // Enable these line to draw the bounding box (debug tests purposes only) -#if 0 - { - EDA_Rect BoundaryBox; - BoundaryBox = GetBoundingBox(); - int x1 = BoundaryBox.GetX(); - int y1 = BoundaryBox.GetY(); - int x2 = BoundaryBox.GetRight(); - int y2 = BoundaryBox.GetBottom(); - GRRect( &panel->m_ClipBox, DC, x1, y1, x2, y2, BROWN ); - } -#endif -} - - -/** Function CreateGraphicShape - * calculates the graphic shape (a polygon) associated to the text - * @param aCorner_list = a buffer to fill with polygon corners coordinates - * @param Pos = Postion of the shape - */ -void SCH_HIERLABEL::CreateGraphicShape( std::vector & aCorner_list, - const wxPoint& Pos ) -{ - int* Template = TemplateShape[m_Shape][m_SchematicOrientation]; - int HalfSize = m_Size.x / 2; - - int imax = *Template; Template++; - - aCorner_list.clear(); - for( int ii = 0; ii < imax; ii++ ) - { - wxPoint corner; - corner.x = ( HalfSize * (*Template) ) + Pos.x; - Template++; - - corner.y = ( HalfSize * (*Template) ) + Pos.y; - Template++; - - aCorner_list.push_back( corner ); - } -} - -/** Virtual Function SCH_SHEET_PIN::CreateGraphicShape - * calculates the graphic shape (a polygon) associated to the text - * @param aCorner_list = a buffer to fill with polygon corners coordinates - * @param aPos = Position of the shape - */ -void SCH_SHEET_PIN::CreateGraphicShape( std::vector & aCorner_list, - const wxPoint& aPos ) -{ - /* This is the same icon shapes as SCH_HIERLABEL - * but the graphic icon is slightly different in 2 cases: - * for INPUT type the icon is the OUTPUT shape of SCH_HIERLABEL - * for OUTPUT type the icon is the INPUT shape of SCH_HIERLABEL - */ - int tmp = m_Shape; - switch( m_Shape ) - { - case NET_INPUT: - m_Shape = NET_OUTPUT; - break; - - case NET_OUTPUT: - m_Shape = NET_INPUT; - break; - - default: - break; - } - SCH_HIERLABEL::CreateGraphicShape( aCorner_list, aPos ); - m_Shape = tmp; -} - -/****************************************/ -EDA_Rect SCH_HIERLABEL::GetBoundingBox() -{ -/****************************************/ - int x, y, dx, dy, length, height; - - x = m_Pos.x; - y = m_Pos.y; - dx = dy = 0; - - int width = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; - height = m_Size.y + width + 2 * TXTMARGE; - length = LenSize( m_Text ) - + height // add height for triangular shapes - + 2 * DANGLING_SYMBOL_SIZE; - - switch( m_SchematicOrientation ) // respect orientation - { - case 0: /* Horiz Normal Orientation (left - *justified) */ - dx = -length; - dy = height; - x += DANGLING_SYMBOL_SIZE; - y -= height / 2; - break; - - case 1: /* Vert Orientation UP */ - dx = height; - dy = -length; - x -= height / 2; - y += DANGLING_SYMBOL_SIZE; - break; - - case 2: /* Horiz Orientation - Right justified */ - dx = length; - dy = height; - x -= DANGLING_SYMBOL_SIZE; - y -= height / 2; - break; - - case 3: /* Vert Orientation BOTTOM */ - dx = height; - dy = length; - x -= height / 2; - y -= DANGLING_SYMBOL_SIZE; - break; - } - - EDA_Rect box( wxPoint( x, y ), wxSize( dx, dy ) ); - box.Normalize(); - return box; -} - - -/*****************************************************************************/ void SCH_GLOBALLABEL::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& aOffset, int DrawMode, int Color ) { -/*****************************************************************************/ - -/* Texts type Global Label have 4 directions, and the Text origin is the - * graphic icon - */ static std::vector Poly; EDA_Colors color; wxPoint text_offset = aOffset + GetSchematicTextOffset(); @@ -1221,13 +995,11 @@ void SCH_GLOBALLABEL::Draw( WinEDA_DrawPanel* panel, int linewidth = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); EXCHG( linewidth, m_Width ); // Set the minimum width - EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, - UNSPECIFIED_COLOR ); + EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR ); EXCHG( linewidth, m_Width ); // set initial value CreateGraphicShape( Poly, m_Pos + aOffset ); - GRPoly( &panel->m_ClipBox, DC, Poly.size(), &Poly[0], 0, linewidth, - color, color ); + GRPoly( &panel->m_ClipBox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color ); if( m_IsDangling ) DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color ); @@ -1336,10 +1108,8 @@ void SCH_GLOBALLABEL::CreateGraphicShape( std::vector & aCorner_list, } -/******************************************/ EDA_Rect SCH_GLOBALLABEL::GetBoundingBox() { -/******************************************/ int x, y, dx, dy, length, height; x = m_Pos.x; @@ -1389,46 +1159,216 @@ EDA_Rect SCH_GLOBALLABEL::GetBoundingBox() } -/***********************************/ -EDA_Rect SCH_LABEL::GetBoundingBox() -/***********************************/ +SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) : + SCH_TEXT( pos, text, aType ) { - int x, y, dx, dy, length, height; + m_Layer = LAYER_HIERLABEL; + m_Shape = NET_INPUT; + m_IsDangling = TRUE; + m_MultilineAllowed = false; +} - x = m_Pos.x; - y = m_Pos.y; - int width = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; - length = LenSize( m_Text ); - height = m_Size.y + width; - dx = dy = 0; + +/** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ +bool SCH_HIERLABEL::Save( FILE* aFile ) const +{ + bool success = true; + const char* shape = "~"; + + if( m_Italic ) + shape = "Italic"; + if( fprintf( aFile, "Text HLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n", + m_Pos.x, m_Pos.y, m_SchematicOrientation, m_Size.x, + SheetLabelType[m_Shape], shape, m_Width, CONV_TO_UTF8( m_Text ) ) == EOF ) + { + success = false; + } + + return success; +} + + + +/** Function HitTest + * @return true if the point aPosRef is within item area + * @param aPosRef = a wxPoint to test + */ +bool SCH_HIERLABEL::HitTest( const wxPoint& aPosRef ) +{ + EDA_Rect rect = GetBoundingBox(); + + return rect.Inside( aPosRef ); +} + + +/** function SetTextOrientAndJustifyParmeters + * Set m_SchematicOrientation, and initialize + * m_orient,m_HJustified and m_VJustified, according to the value of + * m_SchematicOrientation + * must be called after changing m_SchematicOrientation + * @param aSchematicOrientation = + * 0 = normal (horizontal, left justified). + * 1 = up (vertical) + * 2 = (horizontal, right justified). This can be seen as the mirrored + * position of 0 + * 3 = bottom . This can be seen as the mirrored position of up + */ +void SCH_HIERLABEL::SetSchematicTextOrientation( int aSchematicOrientation ) +{ + m_SchematicOrientation = aSchematicOrientation; switch( m_SchematicOrientation ) { - case 0: /* Horiz Normal Orientation (left justified) */ - dx = 2 * DANGLING_SYMBOL_SIZE + length; - dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; - x -= DANGLING_SYMBOL_SIZE; - y += DANGLING_SYMBOL_SIZE; + default: + case 0: /* Horiz Normal Orientation */ + m_Orient = TEXT_ORIENT_HORIZ; + m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; + m_VJustify = GR_TEXT_VJUSTIFY_CENTER; + break; + + case 1: /* Vert Orientation UP */ + m_Orient = TEXT_ORIENT_VERT; + m_HJustify = GR_TEXT_HJUSTIFY_LEFT; + m_VJustify = GR_TEXT_VJUSTIFY_CENTER; + break; + + case 2: /* Horiz Orientation */ + m_Orient = TEXT_ORIENT_HORIZ; + m_HJustify = GR_TEXT_HJUSTIFY_LEFT; + m_VJustify = GR_TEXT_VJUSTIFY_CENTER; + break; + + case 3: /* Vert Orientation BOTTOM */ + m_Orient = TEXT_ORIENT_VERT; + m_HJustify = GR_TEXT_HJUSTIFY_RIGHT; + m_VJustify = GR_TEXT_VJUSTIFY_CENTER; + break; + } +} + + +/* Hierarchical Label have a text and a graphic icon. + * Texts type have 4 directions, and the text origin is the graphic icon + */ +void SCH_HIERLABEL::Draw( WinEDA_DrawPanel* panel, + wxDC* DC, + const wxPoint& offset, + int DrawMode, + int Color ) +{ + static std::vector Poly; + EDA_Colors color; + int linewidth = ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; + + linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); + + if( Color >= 0 ) + color = (EDA_Colors) Color; + else + color = ReturnLayerColor( m_Layer ); + + GRSetDrawMode( DC, DrawMode ); + + EXCHG( linewidth, m_Width ); // Set the minimum width + wxPoint text_offset = offset + GetSchematicTextOffset(); + EDA_TextStruct::Draw( panel, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR ); + EXCHG( linewidth, m_Width ); // set initial value + + CreateGraphicShape( Poly, m_Pos + offset ); + GRPoly( &panel->m_ClipBox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color ); + + if( m_IsDangling ) + DrawDanglingSymbol( panel, DC, m_Pos + offset, color ); + + // Enable these line to draw the bounding box (debug tests purposes only) +#if 0 + { + EDA_Rect BoundaryBox; + BoundaryBox = GetBoundingBox(); + int x1 = BoundaryBox.GetX(); + int y1 = BoundaryBox.GetY(); + int x2 = BoundaryBox.GetRight(); + int y2 = BoundaryBox.GetBottom(); + GRRect( &panel->m_ClipBox, DC, x1, y1, x2, y2, BROWN ); + } +#endif +} + + +/** Function CreateGraphicShape + * calculates the graphic shape (a polygon) associated to the text + * @param aCorner_list = a buffer to fill with polygon corners coordinates + * @param Pos = Postion of the shape + */ +void SCH_HIERLABEL::CreateGraphicShape( std::vector & aCorner_list, + const wxPoint& Pos ) +{ + int* Template = TemplateShape[m_Shape][m_SchematicOrientation]; + int HalfSize = m_Size.x / 2; + + int imax = *Template; Template++; + + aCorner_list.clear(); + for( int ii = 0; ii < imax; ii++ ) + { + wxPoint corner; + corner.x = ( HalfSize * (*Template) ) + Pos.x; + Template++; + + corner.y = ( HalfSize * (*Template) ) + Pos.y; + Template++; + + aCorner_list.push_back( corner ); + } +} + +EDA_Rect SCH_HIERLABEL::GetBoundingBox() +{ + int x, y, dx, dy, length, height; + + x = m_Pos.x; + y = m_Pos.y; + dx = dy = 0; + + int width = (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; + height = m_Size.y + width + 2 * TXTMARGE; + length = LenSize( m_Text ) + + height // add height for triangular shapes + + 2 * DANGLING_SYMBOL_SIZE; + + switch( m_SchematicOrientation ) // respect orientation + { + case 0: /* Horiz Normal Orientation (left + *justified) */ + dx = -length; + dy = height; + x += DANGLING_SYMBOL_SIZE; + y -= height / 2; break; case 1: /* Vert Orientation UP */ - dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; - dy = -2 * DANGLING_SYMBOL_SIZE - length; - x += DANGLING_SYMBOL_SIZE; + dx = height; + dy = -length; + x -= height / 2; y += DANGLING_SYMBOL_SIZE; break; case 2: /* Horiz Orientation - Right justified */ - dx = -2 * DANGLING_SYMBOL_SIZE - length; - dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; - x += DANGLING_SYMBOL_SIZE; - y += DANGLING_SYMBOL_SIZE; + dx = length; + dy = height; + x -= DANGLING_SYMBOL_SIZE; + y -= height / 2; break; case 3: /* Vert Orientation BOTTOM */ - dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE; - dy = 2 * DANGLING_SYMBOL_SIZE + length; - x += DANGLING_SYMBOL_SIZE; + dx = height; + dy = length; + x -= height / 2; y -= DANGLING_SYMBOL_SIZE; break; } @@ -1439,30 +1379,93 @@ EDA_Rect SCH_LABEL::GetBoundingBox() } -/***********************************/ -EDA_Rect SCH_TEXT::GetBoundingBox() -/***********************************/ +/** function GetSchematicTextOffset (virtual) + * @return the offset between the SCH_TEXT position and the text itself + * position + * This offset depend on orientation, and the type of text + * (room to draw an associated graphic symbol, or put the text above a wire) + */ +wxPoint SCH_HIERLABEL::GetSchematicTextOffset() { - // We must pass the effective text thickness to GetTextBox - // when calculating the bounding box - int linewidth = - (m_Width == 0) ? g_DrawDefaultLineThickness : m_Width; + wxPoint text_offset; - linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold ); - EXCHG( linewidth, m_Width ); // Set the real width - EDA_Rect rect = GetTextBox( -1 ); - EXCHG( linewidth, m_Width ); // set initial value + int width = MAX( m_Width, g_DrawDefaultLineThickness ); - if( m_Orient ) // Rotate rect + int ii = m_Size.x + TXTMARGE + width; + + switch( m_SchematicOrientation ) { - wxPoint pos = rect.GetOrigin(); - wxPoint end = rect.GetEnd(); - RotatePoint( &pos, m_Pos, m_Orient ); - RotatePoint( &end, m_Pos, m_Orient ); - rect.SetOrigin( pos ); - rect.SetEnd( end ); + case 0: /* Orientation horiz normale */ + text_offset.x = -ii; + break; + + case 1: /* Orientation vert UP */ + text_offset.y = -ii; + break; + + case 2: /* Orientation horiz inverse */ + text_offset.x = ii; + break; + + case 3: /* Orientation vert BOTTOM */ + text_offset.y = ii; + break; } - rect.Normalize(); - return rect; + return text_offset; +} + + +/** virtual function Mirror_Y + * mirror item relative to an Y axis + * @param aYaxis_position = the y axis position + */ +void SCH_HIERLABEL::Mirror_Y( int aYaxis_position ) +{ +/* The hierarchical label is NOT really mirrored. + * for an horizontal label, the schematic orientation is changed. + * for a vericalal label, the schematic orientation is not changed. + * and the label is moved to a suitable position + */ + + switch( GetSchematicTextOrientation() ) + { + case 0: /* horizontal text */ + SetSchematicTextOrientation( 2 ); + break; + + case 2: /* invert horizontal text*/ + SetSchematicTextOrientation( 0 ); + break; + } + + m_Pos.x -= aYaxis_position; + NEGATE( m_Pos.x ); + m_Pos.x += aYaxis_position; +} + + +void SCH_HIERLABEL::Mirror_X( int aXaxis_position ) +{ + switch( GetSchematicTextOrientation() ) + { + case 1: /* vertical text */ + SetSchematicTextOrientation( 3 ); + break; + + case 3: /* invert vertical text*/ + SetSchematicTextOrientation( 1 ); + break; + } + + m_Pos.y -= aXaxis_position; + NEGATE( m_Pos.y ); + m_Pos.y += aXaxis_position; +} + + +void SCH_HIERLABEL::Rotate( wxPoint rotationPoint ) +{ + RotatePoint( &m_Pos, rotationPoint, 900 ); + SetSchematicTextOrientation( (GetSchematicTextOrientation() + 3) % 4 ); } diff --git a/eeschema/class_text-label.h b/eeschema/class_text-label.h index 7e4c455826..141f02a711 100644 --- a/eeschema/class_text-label.h +++ b/eeschema/class_text-label.h @@ -167,8 +167,17 @@ public: * @param aFindLocation - a wxPoint where to put the location of matched item. can be NULL. * @return True if this schematic text item matches the search criteria. */ - virtual bool Matches( wxFindReplaceData& aSearchData, - void* aAuxData, wxPoint * aFindLocation ); + virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ); + + virtual void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ); + + virtual bool IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList ); + + virtual bool IsDangling() const { return m_IsDangling; } + + virtual bool IsSelectStateChanged( const wxRect& aRect ); + + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ); diff --git a/eeschema/dangling_ends.cpp b/eeschema/dangling_ends.cpp index 5a3e151178..163c35150a 100644 --- a/eeschema/dangling_ends.cpp +++ b/eeschema/dangling_ends.cpp @@ -4,55 +4,14 @@ #include "fctsys.h" #include "gr_basic.h" -#include "common.h" #include "program.h" #include "general.h" -#include "netlist.h" #include "protos.h" -#include "class_library.h" +#include "class_libentry.h" #include "lib_pin.h" -enum End_Type { - UNKNOWN = 0, - WIRE_START_END, - WIRE_END_END, - BUS_START_END, - BUS_END_END, - JUNCTION_END, - PIN_END, - LABEL_END, - ENTRY_END, - SHEET_LABEL_END -}; - -// A helper class to store a list of items that can be connected to something: -class DANGLING_END_ITEM -{ -public: - const void* m_Item; // a pointer to the parent - wxPoint m_Pos; // the position of the connecting point - int m_Type; // type of parent - - DANGLING_END_ITEM( int type, const void* aItem ) - { - m_Item = aItem; - m_Type = type; - } -}; - -static void TestWireForDangling( std::vector & aItemList, - SCH_LINE* DrawRef, - WinEDA_SchematicFrame* frame, - wxDC* aDC ); -void TestLabelForDangling( std::vector & aItemList, - SCH_TEXT* aLabel, - WinEDA_SchematicFrame* aFrame, - wxDC* aDC ); -void RebuildEndPointsList( std::vector & aItemList, SCH_ITEM* aDrawList ); - - /* Returns true if the point P is on the segment S. */ bool SegmentIntersect( wxPoint aSegStart, wxPoint aSegEnd, wxPoint aTestPoint ) { @@ -64,60 +23,27 @@ bool SegmentIntersect( wxPoint aSegStart, wxPoint aSegEnd, wxPoint aTestPoint ) return false; /* Cross product non-zero, vectors not parallel */ if( ( (long long) vectSeg.x * vectPoint.x + (long long) vectSeg.y * vectPoint.y ) < - ( (long long) vectPoint.x * vectPoint.x + (long long) vectPoint.y * vectPoint.y ) ) + ( (long long) vectPoint.x * vectPoint.x + (long long) vectPoint.y * vectPoint.y ) ) return false; /* Point not on segment */ return true; } -void WinEDA_SchematicFrame::TestDanglingEnds( SCH_ITEM* DrawList, wxDC* DC ) +void WinEDA_SchematicFrame::TestDanglingEnds( SCH_ITEM* aDrawList, wxDC* aDC ) { - // this list is static to avoid many useles memory allocation. - std::vector itemList; + SCH_ITEM* item; + std::vector< DANGLING_END_ITEM > endPoints; - RebuildEndPointsList( itemList, DrawList ); + for( item = aDrawList; item != NULL; item = item->Next() ) + item->GetEndPoints( endPoints ); - for( SCH_ITEM* item = DrawList; item; item = item->Next() ) + for( item = aDrawList; item; item = item->Next() ) { - switch( item->Type() ) + if( item->IsDanglingStateChanged( endPoints ) && aDC != NULL ) { - case TYPE_SCH_GLOBALLABEL: - case TYPE_SCH_HIERLABEL: - case TYPE_SCH_LABEL: - TestLabelForDangling( itemList, (SCH_LABEL*) item, this, DC ); - break; - - case DRAW_SHEET_STRUCT_TYPE: - { - SCH_SHEET* sheet = (SCH_SHEET*) item; - // Read the hierarchical pins list and teast for dangling pins: - BOOST_FOREACH( SCH_SHEET_PIN & pinsheet, sheet->GetSheetPins() ) - { - TestLabelForDangling( itemList, &pinsheet, this, DC ); - } - } - break; - - case DRAW_SEGMENT_STRUCT_TYPE: - #undef STRUCT - #define STRUCT ( (SCH_LINE*) item ) - if( STRUCT->GetLayer() == LAYER_WIRE ) - { - TestWireForDangling( itemList, STRUCT, this, DC ); - break; - } - if( STRUCT->GetLayer() == LAYER_NOTES ) - break; - if( STRUCT->GetLayer() == LAYER_BUS ) - { - STRUCT->m_StartIsDangling = STRUCT->m_EndIsDangling = false; - break; - } - break; - - default: - break; + RedrawOneStruct( DrawPanel, aDC, item, g_XorMode ); + RedrawOneStruct( DrawPanel, aDC, item, GR_DEFAULT_DRAWMODE ); } } } @@ -129,8 +55,7 @@ void WinEDA_SchematicFrame::TestDanglingEnds( SCH_ITEM* DrawList, wxDC* DC ) * @param DrawList = List of SCH_ITEMs to check. * @return a LIB_PIN pointer to the located pin or NULL if no pin was found. */ -LIB_PIN* WinEDA_SchematicFrame::LocatePinEnd( SCH_ITEM* DrawList, - const wxPoint& pos ) +LIB_PIN* WinEDA_SchematicFrame::LocatePinEnd( SCH_ITEM* DrawList, const wxPoint& pos ) { SCH_COMPONENT* DrawLibItem; LIB_PIN* Pin; @@ -153,234 +78,3 @@ LIB_PIN* WinEDA_SchematicFrame::LocatePinEnd( SCH_ITEM* DrawList, return Pin; return NULL; } - - -void TestWireForDangling( std::vector & aItemList, - SCH_LINE* DrawRef, - WinEDA_SchematicFrame* frame, - wxDC* DC ) -{ - bool Sdangstate = true, Edangstate = true; - - BOOST_FOREACH( DANGLING_END_ITEM terminal_item, aItemList ) - { - if( terminal_item.m_Item == DrawRef ) - continue; - - if( DrawRef->m_Start == terminal_item.m_Pos ) - Sdangstate = false; - - if( DrawRef->m_End == terminal_item.m_Pos ) - Edangstate = false; - - if( (Sdangstate == false) && (Edangstate == false) ) - break; - } - - if( (Sdangstate != DrawRef->m_StartIsDangling) - || (Edangstate != DrawRef->m_EndIsDangling) ) - { - if( DC ) - RedrawOneStruct( frame->DrawPanel, DC, DrawRef, g_XorMode ); - DrawRef->m_StartIsDangling = Sdangstate; - DrawRef->m_EndIsDangling = Edangstate; - if( DC ) - RedrawOneStruct( frame->DrawPanel, DC, DrawRef, - GR_DEFAULT_DRAWMODE ); - } -} - - -void TestLabelForDangling( std::vector & aItemList, - SCH_TEXT* aLabel, - WinEDA_SchematicFrame* aFrame, - wxDC* aDC ) -{ - bool dangstate = true; - - for( unsigned ii = 0; ii < aItemList.size(); ii++ ) - { - DANGLING_END_ITEM & terminal_item = aItemList[ii]; - - if( terminal_item.m_Item == aLabel ) - continue; - - switch( terminal_item.m_Type ) - { - case PIN_END: - case LABEL_END: - case SHEET_LABEL_END: - if( aLabel->m_Pos == terminal_item.m_Pos ) - dangstate = false; - break; - - case WIRE_START_END: - case BUS_START_END: - { - // these schematic items have created 2 DANGLING_END_ITEM - // one per end. - ii++; - DANGLING_END_ITEM & next_terminal = aItemList[ii]; - dangstate = !SegmentIntersect( terminal_item.m_Pos, - next_terminal.m_Pos, - aLabel->m_Pos ); - } - break; - - case UNKNOWN: - case JUNCTION_END: - case ENTRY_END: - case WIRE_END_END: - case BUS_END_END: - break; - } - - if( dangstate == false ) - break; - } - - if( dangstate != aLabel->m_IsDangling ) - { - if( aDC ) - RedrawOneStruct( aFrame->DrawPanel, aDC, aLabel, g_XorMode ); - aLabel->m_IsDangling = dangstate; - if( aDC ) - RedrawOneStruct( aFrame->DrawPanel, aDC, aLabel, GR_DEFAULT_DRAWMODE ); - } -} - - -/* Returns the physical position of the pin relative to the component - * orientation. */ -wxPoint ReturnPinPhysicalPosition( LIB_PIN* Pin, SCH_COMPONENT* DrawLibItem ) -{ - wxPoint PinPos = Pin->m_Pos; - - if( DrawLibItem == NULL ) - NEGATE( PinPos.y ); - - else - PinPos = DrawLibItem->m_Transform.TransformCoordinate( Pin->m_Pos ) + DrawLibItem->m_Pos; - - return PinPos; -} - - -void RebuildEndPointsList( std::vector & aItemList, SCH_ITEM* aDrawList ) -{ - SCH_ITEM* schItem; - - aItemList.clear(); - - for( schItem = aDrawList; schItem != NULL; schItem = schItem->Next() ) - { - switch( schItem->Type() ) - { - case TYPE_SCH_LABEL: - case TYPE_SCH_GLOBALLABEL: - case TYPE_SCH_HIERLABEL: - { - #undef STRUCT - #define STRUCT ( (SCH_LABEL*) schItem ) - DANGLING_END_ITEM item( LABEL_END, schItem ); - item.m_Pos = STRUCT->m_Pos; - aItemList.push_back( item ); - } - break; - - case DRAW_SEGMENT_STRUCT_TYPE: - #undef STRUCT - #define STRUCT ( (SCH_LINE*) schItem ) - if( STRUCT->GetLayer() == LAYER_NOTES ) - break; - if( ( STRUCT->GetLayer() == LAYER_BUS ) - || (STRUCT->GetLayer() == LAYER_WIRE ) ) - { - DANGLING_END_ITEM item( (STRUCT->GetLayer() == LAYER_BUS) ? - BUS_START_END : WIRE_START_END, schItem ); - item.m_Pos = STRUCT->m_Start; - DANGLING_END_ITEM item1( (STRUCT->GetLayer() == LAYER_BUS) ? - BUS_END_END : WIRE_END_END, schItem ); - item1.m_Pos = STRUCT->m_End; - - aItemList.push_back( item ); - aItemList.push_back( item1 ); - } - break; - - case DRAW_JUNCTION_STRUCT_TYPE: - { - #undef STRUCT - #define STRUCT ( (SCH_JUNCTION*) schItem ) - DANGLING_END_ITEM item( JUNCTION_END, schItem ); - item.m_Pos = STRUCT->m_Pos; - aItemList.push_back( item ); - } - break; - - case DRAW_BUSENTRY_STRUCT_TYPE: - { - #undef STRUCT - #define STRUCT ( (SCH_BUS_ENTRY*) schItem ) - DANGLING_END_ITEM item( ENTRY_END, schItem ); - item.m_Pos = STRUCT->m_Pos; - - DANGLING_END_ITEM item1( ENTRY_END, schItem ); - item1.m_Pos = STRUCT->m_End(); - aItemList.push_back( item ); - aItemList.push_back( item1 ); - } - break; - - case TYPE_SCH_COMPONENT: - { - #undef STRUCT - #define STRUCT ( (SCH_COMPONENT*) schItem ) - LIB_COMPONENT* Entry; - Entry = CMP_LIBRARY::FindLibraryComponent( STRUCT->m_ChipName ); - if( Entry == NULL ) - break; - - for( LIB_PIN* Pin = Entry->GetNextPin(); Pin != NULL; - Pin = Entry->GetNextPin( Pin ) ) - { - wxASSERT( Pin->Type() == COMPONENT_PIN_DRAW_TYPE ); - - if( Pin->GetUnit() && STRUCT->m_Multi && ( STRUCT->m_Multi != Pin->GetUnit() ) ) - continue; - - if( Pin->GetConvert() && STRUCT->m_Convert - && ( STRUCT->m_Convert != Pin->GetConvert() ) ) - continue; - - DANGLING_END_ITEM item( PIN_END, Pin ); - item.m_Pos = ReturnPinPhysicalPosition( Pin, STRUCT ); - aItemList.push_back( item ); - } - - break; - } - - case DRAW_SHEET_STRUCT_TYPE: - { - SCH_SHEET* sheet = (SCH_SHEET*) schItem; - - // Using BOOST_FOREACH here creates problems (bad pointer value to pinsheet). - // I do not know why. - for( unsigned ii = 0; ii < sheet->GetSheetPins().size(); ii++ ) - { - SCH_SHEET_PIN &pinsheet = sheet->GetSheetPins()[ii]; - wxASSERT( pinsheet.Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE ); - - DANGLING_END_ITEM item( SHEET_LABEL_END, &pinsheet ); - item.m_Pos = pinsheet.m_Pos; - aItemList.push_back( item ); - } - } - break; - - default: - ; - } - } -} diff --git a/eeschema/load_one_schematic_file.cpp b/eeschema/load_one_schematic_file.cpp index 1785c2f4ff..1eec680fb7 100644 --- a/eeschema/load_one_schematic_file.cpp +++ b/eeschema/load_one_schematic_file.cpp @@ -16,11 +16,11 @@ /* in read_from_file_schematic_items_description.cpp */ SCH_ITEM* ReadTextDescr( LINE_READER* aLine, wxString& aMsgDiag, int aSchematicFileVersion ); -int ReadSheetDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); +int ReadSheetDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); -bool ReadSchemaDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); +bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); -int ReadPartDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); +int ReadPartDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ); static void LoadLayers( LINE_READER* aLine ); @@ -29,8 +29,7 @@ static void LoadLayers( LINE_READER* aLine ); * Routine to load an EESchema file. * Returns true if file has been loaded (at least partially.) */ -bool WinEDA_SchematicFrame::LoadOneEEFile( SCH_SCREEN* screen, - const wxString& FullFileName ) +bool WinEDA_SchematicFrame::LoadOneEEFile( SCH_SCREEN* screen, const wxString& FullFileName ) { char Name1[256], Name2[256]; @@ -122,13 +121,13 @@ again." ); { case '$': // identification block if( line[1] == 'C' ) - Failed = ReadPartDescr( this, &reader, MsgDiag, screen ); + Failed = ReadPartDescr( &reader, MsgDiag, screen ); else if( line[1] == 'S' ) - Failed = ReadSheetDescr( this, &reader, MsgDiag, screen ); + Failed = ReadSheetDescr( &reader, MsgDiag, screen ); else if( line[1] == 'D' ) - Failed = ReadSchemaDescr( this, &reader, MsgDiag, screen ); + Failed = ReadSchemaDescr( &reader, MsgDiag, screen ); else if( line[1] == 'T' ) // text part { @@ -148,7 +147,7 @@ again." ); break; case 'L': // Its a library item. - Failed = ReadPartDescr( this, &reader, MsgDiag, screen ); + Failed = ReadPartDescr( &reader, MsgDiag, screen ); break; case 'W': // Its a Segment (WIRE or BUS) item. diff --git a/eeschema/read_from_file_schematic_items_descriptions.cpp b/eeschema/read_from_file_schematic_items_descriptions.cpp index 2e1be73c87..121c658616 100644 --- a/eeschema/read_from_file_schematic_items_descriptions.cpp +++ b/eeschema/read_from_file_schematic_items_descriptions.cpp @@ -175,7 +175,7 @@ SCH_ITEM* ReadTextDescr( LINE_READER* aLine, wxString& aMsgDiag, int aSchematicF /* Function used by LoadEEFile(). * Get the lines for a description of a piece of hierarchy. */ -int ReadSheetDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) +int ReadSheetDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) { int ii, fieldNdx, size; char Name1[256], Char1[256], Char2[256]; @@ -286,7 +286,6 @@ int ReadSheetDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BAS aLine->LineNumber() ); aMsgDiag << CONV_FROM_UTF8( line ); - DisplayError( frame, aMsgDiag ); } if( size == 0 ) size = DEFAULT_SIZE_TEXT; @@ -316,7 +315,6 @@ int ReadSheetDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BAS aMsgDiag.Printf( wxT( "EESchema file sheet label error at line %d, ignoring.\n" ), aLine->LineNumber() ); aMsgDiag << CONV_FROM_UTF8( line ); - DisplayError( frame, aMsgDiag ); continue; } @@ -391,7 +389,7 @@ int ReadSheetDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BAS /* Read the schematic header. */ -bool ReadSchemaDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) +bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) { char Text[256], buf[1024]; int ii; @@ -427,7 +425,6 @@ bool ReadSchemaDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, B line %d, \aAbort reading file.\n" ), aLine->LineNumber() ); aMsgDiag << CONV_FROM_UTF8( line ); - DisplayError( frame, aMsgDiag ); } Window->m_CurrentSheetDesc = wsheet; @@ -509,7 +506,7 @@ line %d, \aAbort reading file.\n" ), * Get the lines for a description of a schematic component. */ -int ReadPartDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) +int ReadPartDescr( LINE_READER* aLine, wxString& aMsgDiag, BASE_SCREEN* Window ) { int ii; char Name1[256], Name2[256], @@ -754,7 +751,6 @@ int ReadPartDescr( wxWindow* frame, LINE_READER* aLine, wxString& aMsgDiag, BASE aMsgDiag.Printf( wxT( "Component Field error line %d, aborted" ), aLine->LineNumber() ); - DisplayError( frame, aMsgDiag ); continue; } diff --git a/include/base_struct.h b/include/base_struct.h index a0febffc53..94b79b2952 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -348,6 +348,7 @@ public: inline bool IsModified() const { return m_Flags & IS_CHANGED; } inline bool IsMoving() const { return m_Flags & IS_MOVED; } inline bool IsDragging() const { return m_Flags & IS_DRAGGED; } + inline bool IsSelected() const { return m_Flags & SELECTED; } int GetState( int type ) const { diff --git a/include/class_base_screen.h b/include/class_base_screen.h index 7d322af960..654c13b7da 100644 --- a/include/class_base_screen.h +++ b/include/class_base_screen.h @@ -14,12 +14,23 @@ #include "block_commande.h" #include "common.h" +#include + // Forward declarations: class SCH_ITEM; class Ki_PageDescr; +/** + * Define list of drawing items for screens. + * + * The Boost containter was choosen over the statand C++ contain because you can detach + * the pointer from a list with the release method. + */ +typedef boost::ptr_vector< EDA_BaseStruct > EDA_ITEMS; + + /* Simple class for handling grid arrays. */ class GRID_TYPE { @@ -56,17 +67,16 @@ WX_DECLARE_OBJARRAY( GRID_TYPE, GridArray ); /*******************************************************************/ class BASE_SCREEN : public EDA_BaseStruct { + EDA_ITEMS m_items; ///< The drawing items associated with this screen. + public: - wxPoint m_DrawOrg; /* offsets for drawing the circuit on the - * screen */ - wxPoint m_Curseur; /* Screen cursor coordinate (on grid) in user - * units. */ - wxPoint m_MousePosition; /* Mouse cursor coordinate (off grid) in user - * units. */ + wxPoint m_DrawOrg; /* offsets for drawing the circuit on the screen */ + wxPoint m_Curseur; /* Screen cursor coordinate (on grid) in user units. */ + wxPoint m_MousePosition; /* Mouse cursor coordinate (off grid) in user units. */ wxPoint m_MousePositionInPixels; - wxPoint m_O_Curseur; /* Relative Screen cursor coordinate (on grid) - * in user units. - * (coordinates from last reset position)*/ + wxPoint m_O_Curseur; /* Relative Screen cursor coordinate (on grid) + * in user units. + * (coordinates from last reset position)*/ // Scrollbars management: int m_ScrollPixelsPerUnitX; /* Pixels per scroll unit in the horizontal direction. */ int m_ScrollPixelsPerUnitY; /* Pixels per scroll unit in the vertical direction. */ @@ -280,8 +290,7 @@ public: /** * Function SetZoomList * sets the list of zoom factors. - * @param aZoomList An array of zoom factors in ascending order, zero - * terminated + * @param aZoomList An array of zoom factors in ascending order, zero terminated */ void SetZoomList( const wxArrayInt& zoomlist ); @@ -300,8 +309,7 @@ public: bool SetFirstZoom(); bool SetLastZoom(); - //-------------------------------------------------------------- + //-------------------------------------------------------------- /** * Return the command ID of the currently selected grid. @@ -359,6 +367,13 @@ public: return wxT( "BASE_SCREEN" ); } + /** + * Helpers for accessing the draw item list. + */ + EDA_ITEMS::iterator Begin() { return m_items.begin(); } + EDA_ITEMS::iterator End() { return m_items.end(); } + virtual void AddItem( EDA_BaseStruct* aItem ); + virtual void InsertItem( EDA_ITEMS::iterator aIter, EDA_BaseStruct* aItem ); #if defined(DEBUG) diff --git a/include/class_sch_screen.h b/include/class_sch_screen.h index a4a7e900e3..24e45d1b68 100644 --- a/include/class_sch_screen.h +++ b/include/class_sch_screen.h @@ -6,7 +6,7 @@ #define CLASS_SCREEN_H #include "macros.h" -#include "base_struct.h" +#include "sch_item_struct.h" #include "class_base_screen.h" @@ -17,8 +17,9 @@ class SCH_SCREEN : public BASE_SCREEN { public: - int m_RefCount; /*how many sheets reference this screen? - * delete when it goes to zero. */ + int m_RefCount; ///< Number of sheets referencing this screen. + ///< Delete when it goes to zero. + SCH_SCREEN( KICAD_T aType = SCREEN_STRUCT_TYPE ); ~SCH_SCREEN(); @@ -80,7 +81,7 @@ public: * items are removed from the beginning of the list. * So this function can be called to remove old commands */ - virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 ); + virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 ); /** * Function Save @@ -90,6 +91,17 @@ public: * @return bool - true if success writing else false. */ bool Save( FILE* aFile ) const; + + /** + * Clear the state flags of all the items in the screen. + */ + void ClearDrawingState(); + + virtual void AddItem( SCH_ITEM* aItem ) { BASE_SCREEN::AddItem( (EDA_BaseStruct*) aItem ); } + virtual void InsertItem( EDA_ITEMS::iterator aIter, SCH_ITEM* aItem ) + { + BASE_SCREEN::InsertItem( aIter, (EDA_BaseStruct*) aItem ); + } }; diff --git a/include/sch_item_struct.h b/include/sch_item_struct.h index ce5a933d2a..6eadb588d9 100644 --- a/include/sch_item_struct.h +++ b/include/sch_item_struct.h @@ -5,11 +5,46 @@ #ifndef SCH_ITEM_STRUCT_H #define SCH_ITEM_STRUCT_H +#include +#include +using namespace std; + + +class SCH_ITEM; class WinEDA_SchematicFrame; class wxFindReplaceData; +enum DANGLING_END_T { + UNKNOWN = 0, + WIRE_START_END, + WIRE_END_END, + BUS_START_END, + BUS_END_END, + JUNCTION_END, + PIN_END, + LABEL_END, + ENTRY_END, + SHEET_LABEL_END +}; + +// A helper class to store a list of items that can be connected to something: +class DANGLING_END_ITEM +{ +public: + const void* m_Item; // a pointer to the parent + wxPoint m_Pos; // the position of the connecting point + DANGLING_END_T m_Type; // type of parent + + DANGLING_END_ITEM( DANGLING_END_T type, const void* aItem ) + { + m_Item = aItem; + m_Type = type; + } +}; + + /** * Class SCH_ITEM * is a base class for any item which can be embedded within the SCHEMATIC @@ -21,7 +56,7 @@ class SCH_ITEM : public EDA_BaseStruct { protected: int m_Layer; - + EDA_ITEMS m_connections; ///< List of items connected to this item. public: SCH_ITEM( EDA_BaseStruct* aParent, KICAD_T aType ); @@ -72,15 +107,15 @@ public: * move item to a new position. * @param aMoveVector = the deplacement vector */ - virtual void Move(const wxPoint& aMoveVector) = 0; + virtual void Move( const wxPoint& aMoveVector ) = 0; /** virtual function Mirror_Y * mirror item relative to an Y axis * @param aYaxis_position = the y axis position */ - virtual void Mirror_Y(int aYaxis_position) = 0; - virtual void Mirror_X(int aXaxis_position) = 0; - virtual void Rotate(wxPoint rotationPoint) = 0; + virtual void Mirror_Y( int aYaxis_position ) = 0; + virtual void Mirror_X( int aXaxis_position ) = 0; + virtual void Rotate( wxPoint rotationPoint ) = 0; /** @@ -109,8 +144,7 @@ public: * @param aFindLocation - a wxPoint where to put the location of matched item. can be NULL. * @return True if this schematic text item matches the search criteria. */ - virtual bool Matches( wxFindReplaceData& aSearchData, - void * aAuxData, wxPoint * aFindLocation ) + virtual bool Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint* aFindLocation ) { return false; } /** @@ -121,6 +155,62 @@ public: * @return True if this item matches the search criteria. */ bool Matches( const wxString& aText, wxFindReplaceData& aSearchData ); + + /** + * Add schematic item end points to \a aItemList if the item has endpoints. + * + * The default version doesn't do anything since many of the schematic object cannot + * be tested for dangling ends. If you add a new schematic item that can have a + * dangling end ( no connect ), override this method to provide the correct end + * points. + * + * @param aItemList - List of DANGLING_END_ITEMS to add to. + */ + virtual void GetEndPoints( vector< DANGLING_END_ITEM >& aItemList ) {} + + /** + * Test the schematic item to \a aItemList to check if it's dangling state has changed. + * + * Note that the return value only true when the state of the test has changed. Use + * the IsDangling() method to get the current dangling state of the item. Some of + * the schematic objects cannot be tested for a dangling state, the default method + * always returns false. Only override the method if the item can be tested for a + * dangling state. + * + * @param aItemList - List of items to test item against. + * @return True if the dangling state has changed from it's current setting. + */ + virtual bool IsDanglingStateChanged( vector< DANGLING_END_ITEM >& aItemList ) { return false; } + + virtual bool IsDangling() const { return false; } + + /** + * Check if the selection state of an item inside \a aRect has changed. + * + * The is used by the block selection code to verify if an item is selected or not. + * True is be return anytime the select state changes. If you need to know the + * the current selection state, use the IsSelected() method. + * + * @param aRect - Rectange to test against. + */ + virtual bool IsSelectStateChanged( const wxRect& aRect ) { return false; } + + /** + * Get a list of connection points for this item. + * + * Not all schematic items have connection points so the default method does nothing. + * + * @param aPoints - List of connection points to add to. + */ + virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const { } + + /** + * Clear all of the connection items from the list. + * + * The vector release method is used to prevent the item pointers from being deleted. + * Do not use the vector erase method on the connection list. + */ + void ClearConnections() { m_connections.release(); } }; #endif /* SCH_ITEM_STRUCT_H */