diff --git a/common/base_struct.cpp b/common/base_struct.cpp index d641bc1610..2f255dd54b 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -125,6 +125,16 @@ SEARCH_RESULT EDA_ITEM::Visit( INSPECTOR* inspector, const void* testData, return SEARCH_CONTINUE; } + +wxString EDA_ITEM::GetSelectMenuText() const +{ + wxFAIL_MSG( wxT( "GetSelectMenuText() was not overridden for schematic item type " ) + + GetClass() ); + + return wxString( wxT( "Undefined menu text for " ) + GetClass() ); +} + + #if defined(DEBUG) @@ -637,3 +647,9 @@ void EDA_Rect::Merge( const wxPoint& aPoint ) end.y = MAX( end.y, aPoint.y ); SetEnd( end ); } + + +double EDA_Rect::GetArea() const +{ + return (double) GetWidth() * (double) GetHeight(); +} diff --git a/common/common.cpp b/common/common.cpp index 8c0b27b2e4..af39971c3d 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -708,6 +708,47 @@ const wxString& valeur_param( int valeur, wxString& buf_texte ) } + + +wxString CoordinateToString( int aValue, int aInternalUnits, bool aConvertToMils ) +{ + wxCHECK_MSG( (aInternalUnits == EESCHEMA_INTERNAL_UNIT) + || (aInternalUnits == PCB_INTERNAL_UNIT), + wxString( _( "*** Bad Internal Units ***" ) ), + wxT( "Invalid interanl units value." ) ); + + wxString text; + const wxChar* format; + double value = To_User_Unit( g_UserUnit, aValue, aInternalUnits ); + + if( g_UserUnit == INCHES ) + { + if( aConvertToMils ) + { + format = ( aInternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.0f" ) : wxT( "%.1f" ); + value *= 1000; + } + else + { + format = ( aInternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.3f" ) : wxT( "%.4f" ); + } + } + else + { + format = ( aInternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.2f" ) : wxT( "%.3f" ); + } + + text.Printf( format, value ); + + if( g_UserUnit == INCHES ) + text += ( aConvertToMils ) ? _( " mils" ) : _( " in" ); + else + text += _( " mm" ); + + return text; +} + + /* * */ diff --git a/common/dialog_about/dialog_about.cpp b/common/dialog_about/dialog_about.cpp index 5b41ebeaf9..9223825118 100644 --- a/common/dialog_about/dialog_about.cpp +++ b/common/dialog_about/dialog_about.cpp @@ -41,7 +41,7 @@ dialog_about::dialog_about(wxWindow *parent, AboutAppInfo& appInfo) CreateNotebooks(); GetSizer()->SetSizeHints(this); m_auiNotebook->Update(); - + SetFocus(); Centre(); } diff --git a/common/drawframe.cpp b/common/drawframe.cpp index 1826994bed..1f24a53424 100644 --- a/common/drawframe.cpp +++ b/common/drawframe.cpp @@ -808,33 +808,5 @@ void EDA_DRAW_FRAME::ClearMsgPanel( void ) wxString EDA_DRAW_FRAME::CoordinateToString( int aValue, bool aConvertToMils ) { - wxString text; - const wxChar* format; - double value = To_User_Unit( g_UserUnit, aValue, m_InternalUnits ); - - if( g_UserUnit == INCHES ) - { - if( aConvertToMils ) - { - format = ( m_InternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.0f" ) : wxT( "%.1f" ); - value *= 1000; - } - else - { - format = ( m_InternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.3f" ) : wxT( "%.4f" ); - } - } - else - { - format = ( m_InternalUnits == EESCHEMA_INTERNAL_UNIT ) ? wxT( "%.2f" ) : wxT( "%.3f" ); - } - - text.Printf( format, value ); - - if( g_UserUnit == INCHES ) - text += ( aConvertToMils ) ? _( " mils" ) : _( " in" ); - else - text += _( " mm" ); - - return text; + return ::CoordinateToString( aValue, m_InternalUnits, aConvertToMils ); } diff --git a/common/sch_item_struct.cpp b/common/sch_item_struct.cpp index 3689b8c114..baab79e63e 100644 --- a/common/sch_item_struct.cpp +++ b/common/sch_item_struct.cpp @@ -17,6 +17,12 @@ #include "../eeschema/dialogs/dialog_schematic_find.h" +bool sort_schematic_items( const SCH_ITEM* aItem1, const SCH_ITEM* aItem2 ) +{ + return *aItem1 < *aItem2; +} + + /* Constructor and destructor for SCH_ITEM */ /* They are not inline because this creates problems with gcc at linking time * in debug mode @@ -38,18 +44,18 @@ SCH_ITEM::SCH_ITEM( const SCH_ITEM& aItem ) : SCH_ITEM::~SCH_ITEM() { - // Do not let the connections container go out of scope with any ojbects or they + // Do not let the connections container go out of scope with any objects or they // will be deleted by the container will cause the EESchema to crash. These objects // are owned by the sheet object container. if( !m_connections.empty() ) - m_connections.release(); + m_connections.clear(); } /** * place the struct in m_drawList. * if it is a new item, it it also put in undo list - * for an "old" item, saving it in undo list must be done before editiing, + * for an "old" item, saving it in undo list must be done before editing, * and not here! */ void SCH_ITEM::Place( SCH_EDIT_FRAME* aFrame, wxDC* aDC ) @@ -108,3 +114,10 @@ bool SCH_ITEM::IsConnected( const wxPoint& aPosition ) const return doIsConnected( aPosition ); } + + +bool SCH_ITEM::operator < ( const SCH_ITEM& aItem ) const +{ + wxCHECK_MSG( false, this->Type() < aItem.Type(), + wxT( "Less than operator not defined for " ) + GetClass() ); +} diff --git a/common/trigo.cpp b/common/trigo.cpp index 647d668d82..d3a3aabf2f 100644 --- a/common/trigo.cpp +++ b/common/trigo.cpp @@ -425,6 +425,13 @@ int CrossProduct( wxPoint vectorA, wxPoint vectorB ) } +double GetLineLength( const wxPoint& aPointA, const wxPoint& aPointB ) +{ + return sqrt( pow( (double) aPointA.x - (double) aPointB.x, 2 ) + + pow( (double) aPointA.y - (double) aPointB.y, 2 ) ); +} + + double fsinus[3600] = { 0.0000000000, 0.0017453284, 0.0034906514, 0.0052359638, diff --git a/cvpcb/dialogs/dialog_display_options.cpp b/cvpcb/dialogs/dialog_display_options.cpp index 3bc7d92808..a425efd361 100644 --- a/cvpcb/dialogs/dialog_display_options.cpp +++ b/cvpcb/dialogs/dialog_display_options.cpp @@ -7,7 +7,6 @@ #include "wxstruct.h" #include "common.h" #include "cvpcb.h" -//#include "protos.h" #include "class_drawpanel.h" #include "footprint_info.h" #include "cvstruct.h" @@ -32,8 +31,8 @@ DIALOG_FOOTPRINTS_DISPLAY_OPTIONS::DIALOG_FOOTPRINTS_DISPLAY_OPTIONS( PCB_BASE_F m_Parent = parent; initDialog(); + m_sdbSizer1OK->SetDefault(); GetSizer()->SetSizeHints( this ); - Centre(); } diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 9dc97eb967..17bebfce10 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -104,7 +104,6 @@ set(EESCHEMA_SRCS lib_text.cpp libfield.cpp load_one_schematic_file.cpp - locate.cpp menubar.cpp menubar_libedit.cpp netform.cpp @@ -116,6 +115,7 @@ set(EESCHEMA_SRCS pinedit.cpp plot.cpp sch_bus_entry.cpp + sch_collectors.cpp sch_component.cpp sch_field.cpp sch_junction.cpp diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 920b83aded..54839311e2 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -25,7 +25,6 @@ static void AbortCreateNewLine( EDA_DRAW_PANEL* Panel, wxDC* DC ); -static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer ); static void ComputeBreakPoint( SCH_LINE* segment, const wxPoint& new_pos ); SCH_ITEM* s_OldWiresList; @@ -169,7 +168,7 @@ void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type ) /* Creates the new segment, or terminates the command * if the end point is on a pin, junction or an other wire or bus */ - if( IsTerminalPoint( GetScreen(), cursorpos, oldsegment->GetLayer() ) ) + if( GetScreen()->IsTerminalPoint( cursorpos, oldsegment->GetLayer() ) ) { EndSegment( DC ); return; @@ -572,98 +571,3 @@ void IncrementLabelMember( wxString& name ) name.Remove( ii ); name << number; } } - - -/* Return true if pos can be a terminal point for a wire or a bus - * i.e. : - * for a WIRE, if at pos is found: - * - a junction - * - or a pin - * - or an other wire - * - * - for a BUS, if at pos is found: - * - a BUS - */ -static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer ) -{ - EDA_ITEM* item; - LIB_PIN* pin; - SCH_COMPONENT* LibItem = NULL; - SCH_SHEET_PIN* pinsheet; - wxPoint itempos; - - switch( layer ) - { - case LAYER_BUS: - item = screen->GetItem( pos, 0, BUS_T ); - - if( item ) - return true; - - pinsheet = screen->GetSheetLabel( pos ); - - if( pinsheet && IsBusLabel( pinsheet->m_Text ) ) - { - itempos = pinsheet->m_Pos; - - if( (itempos.x == pos.x) && (itempos.y == pos.y) ) - return true; - } - break; - - case LAYER_NOTES: - item = screen->GetItem( pos, 0, DRAW_ITEM_T ); - if( item ) - return true; - break; - - case LAYER_WIRE: - item = screen->GetItem( pos, MAX( g_DrawDefaultLineThickness, 3 ), - BUS_ENTRY_T | JUNCTION_T ); - - if( item ) - return true; - - pin = screen->GetPin( pos, &LibItem ); - - if( pin && LibItem ) - { - // Calculate the exact position of the connection point of the pin, - // depending on orientation of the component. - itempos = LibItem->GetScreenCoord( pin->GetPosition() ); - itempos.x += LibItem->m_Pos.x; - itempos.y += LibItem->m_Pos.y; - - if( ( itempos.x == pos.x ) && ( itempos.y == pos.y ) ) - return true; - } - - item = screen->GetItem( pos, 0, WIRE_T ); - - if( item ) - return true; - - item = screen->GetItem( pos, 0, LABEL_T ); - if( item && (item->Type() != SCH_TEXT_T) - && ( ( (SCH_GLOBALLABEL*) item )->m_Pos.x == pos.x ) - && ( ( (SCH_GLOBALLABEL*) item )->m_Pos.y == pos.y ) ) - return true; - - pinsheet = screen->GetSheetLabel( pos ); - - if( pinsheet && !IsBusLabel( pinsheet->m_Text ) ) - { - itempos = pinsheet->m_Pos; - - if( ( itempos.x == pos.x ) && ( itempos.y == pos.y ) ) - return true; - } - - break; - - default: - break; - } - - return false; -} diff --git a/eeschema/controle.cpp b/eeschema/controle.cpp index 967dbfc243..31b34b75bd 100644 --- a/eeschema/controle.cpp +++ b/eeschema/controle.cpp @@ -11,6 +11,7 @@ #include "eeschema_id.h" #include "general.h" +#include "hotkeys.h" #include "protos.h" #include "libeditframe.h" #include "viewlib_frame.h" @@ -22,29 +23,8 @@ #include "sch_component.h" -/** - * Function LocateAndShowItem - * search the schematic at \a aPosition in logical (drawing) units for any item. - *

- * The search is first performed at \a aPosition which may be off grid. If no item is - * found at \a aPosition, the search is repeated for the nearest grid position to \a - * aPosition. - * - * The search order is as follows: - *

- * @param aPosition The wxPoint on the schematic to search. - * @param aIncludePin = true to search for pins, false to ignore them - * @return A SCH_ITEM pointer on the item or NULL if no item found - */ -SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, bool aIncludePin ) +SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[], + int aHotKeyCommandId ) { SCH_ITEM* item; wxString msg; @@ -52,13 +32,26 @@ SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, bool aInc SCH_COMPONENT* LibItem = NULL; wxPoint gridPosition = GetScreen()->GetNearestGridPosition( aPosition ); - item = LocateItem( aPosition, aIncludePin ); + // Check the on grid position first. There is more likely to be multple items on + // grid than off grid. + item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId ); - if( !item && aPosition != gridPosition ) - item = LocateItem( gridPosition, aIncludePin ); + // If the user aborted the clarification context menu, don't show it again at the + // off grid position. + if( !item && DrawPanel->m_AbortRequest ) + { + DrawPanel->m_AbortRequest = false; + return NULL; + } + + if( !item && (aPosition != gridPosition) ) + item = LocateItem( aPosition, aFilterList, aHotKeyCommandId ); if( !item ) + { + DrawPanel->m_AbortRequest = false; // Just in case the user aborted the context menu. return NULL; + } /* Cross probing to pcbnew if a pin or a component is found */ switch( item->Type() ) @@ -70,22 +63,16 @@ SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, bool aInc break; case SCH_COMPONENT_T: - Pin = GetScreen()->GetPin( GetScreen()->GetCrossHairPosition(), &LibItem ); - - if( Pin ) - break; // Priority is probing a pin first - LibItem = (SCH_COMPONENT*) item; SendMessageToPCBNEW( item, LibItem ); break; - default: - Pin = GetScreen()->GetPin( GetScreen()->GetCrossHairPosition(), &LibItem ); - break; - case LIB_PIN_T: Pin = (LIB_PIN*) item; break; + + default: + ; } if( Pin ) @@ -105,134 +92,74 @@ SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, bool aInc } -/** - * Function LocateItem - * searches for an item at \a aPosition. - * @param aPosition The wxPoint location where to search. - * @param aIncludePin True to search for pins, false to ignore them. - * @return The SCH_ITEM pointer of the item or NULL if no item found. - */ -SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, bool aIncludePin ) +SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[], + int aHotKeyCommandId ) { - SCH_ITEM* item; - LIB_PIN* Pin; - SCH_COMPONENT* LibItem; - wxString Text; - wxString msg; + SCH_ITEM* item = NULL; - item = GetScreen()->GetItem( aPosition, 0, MARKER_T ); + m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition ); - if( item ) - { - item->DisplayInfo( this ); - return item; - } - - item = GetScreen()->GetItem( aPosition, 0, NO_CONNECT_T ); - - if( item ) + if( m_collectedItems.GetCount() == 0 ) { ClearMsgPanel(); - return item; } - - item = GetScreen()->GetItem( aPosition, 0, JUNCTION_T ); - - if( item ) + else if( m_collectedItems.GetCount() == 1 ) { - ClearMsgPanel(); - return item; + item = m_collectedItems[0]; + GetScreen()->SetCurItem( item ); } - - item = GetScreen()->GetItem( aPosition, MAX( g_DrawDefaultLineThickness, 3 ), - WIRE_T | BUS_T | BUS_ENTRY_T ); - - if( item ) // We have found a wire: Search for a connected pin at the same location + else { - Pin = GetScreen()->GetPin( aPosition, &LibItem ); - - if( Pin ) + // There are certain combinations of items that do not need clarification such as + // a corner were two lines meet or all the items form a junction. + if( aHotKeyCommandId ) { - Pin->DisplayInfo( this ); - - if( LibItem ) - AppendMsgPanel( LibItem->GetRef( GetSheet() ), - LibItem->GetField( VALUE )->m_Text, DARKCYAN ); + switch( aHotKeyCommandId ) + { + case HK_DRAG: + if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false ) ) + { + item = m_collectedItems[0]; + GetScreen()->SetCurItem( item ); + } + default: + ; + } } - else - ClearMsgPanel(); - return item; + if( item == NULL ) + { + wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS, + wxT( "Select item clarification context menu size limit exceeded." ) ); + + wxMenu selectMenu; + wxMenuItem* title = new wxMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ) ); + + selectMenu.Append( title ); + selectMenu.AppendSeparator(); + + for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ ) + { + wxString text = m_collectedItems[i]->GetSelectMenuText(); + const char** xpm = m_collectedItems[i]->GetMenuImage(); + ADD_MENUITEM( &selectMenu, ID_SCH_SELECT_ITEM_START + i, text, xpm ); + } + + // Set to NULL in case user aborts the clarification context menu. + GetScreen()->SetCurItem( NULL ); + DrawPanel->m_AbortRequest = true; // Changed to false if an item is selected + PopupMenu( &selectMenu ); + DrawPanel->MoveCursorToCrossHair(); + item = GetScreen()->GetCurItem(); + } } - item = GetScreen()->GetItem( aPosition, 0, DRAW_ITEM_T ); - if( item ) - { + item->DisplayInfo( this ); + else ClearMsgPanel(); - return item; - } - item = GetScreen()->GetItem( aPosition, 0, FIELD_T ); - - if( item ) - { - wxASSERT( item->Type() == SCH_FIELD_T ); - - SCH_FIELD* Field = (SCH_FIELD*) item; - LibItem = (SCH_COMPONENT*) Field->GetParent(); - LibItem->DisplayInfo( this ); - - return item; - } - - item = GetScreen()->GetItem( aPosition, 0, LABEL_T | TEXT_T ); - - if( item ) - { - ClearMsgPanel(); - return item; - } - - /* search for a pin */ - Pin = GetScreen()->GetPin( aPosition, &LibItem ); - - if( Pin ) - { - Pin->DisplayInfo( this ); - - if( LibItem ) - AppendMsgPanel( LibItem->GetRef( GetSheet() ), - LibItem->GetField( VALUE )->m_Text, DARKCYAN ); - if( aIncludePin ) - return LibItem; - } - - item = GetScreen()->GetItem( aPosition, 0, COMPONENT_T ); - - if( item ) - { - item = LocateSmallestComponent( GetScreen() ); - LibItem = (SCH_COMPONENT*) item; - LibItem->DisplayInfo( this ); - return item; - } - - item = GetScreen()->GetItem( aPosition, 0, SHEET_T ); - - if( item ) - { - ( (SCH_SHEET*) item )->DisplayInfo( this ); - return item; - } - - item = GetScreen()->GetItem( aPosition ); - - if( item ) - return item; - - ClearMsgPanel(); - return NULL; + return item; } diff --git a/eeschema/delete.cpp b/eeschema/delete.cpp index 32293792b6..d9942336cc 100644 --- a/eeschema/delete.cpp +++ b/eeschema/delete.cpp @@ -25,6 +25,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) { SCH_ITEM* item; EDA_ITEM* tmp; + EDA_ITEMS list; PICKED_ITEMS_LIST pickList; SCH_SCREEN* screen = GetScreen(); wxPoint pos = screen->GetCrossHairPosition(); @@ -33,24 +34,19 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) screen->ClearDrawingState(); screen->BreakSegmentsOnJunctions(); - // Save the list entry point of this screen - SCH_ITEM* savedItems = screen->GetDrawItems(); - item = screen->GetDrawItems(); + if( screen->GetNode( pos, list ) == 0 ) + return; - while( item && ( item = screen->GetItem( pos, 0, JUNCTION_T | WIRE_T | BUS_T ) ) != NULL ) + for( size_t i = 0; i < list.size(); i++ ) { + item = (SCH_ITEM*) list[ i ]; item->SetFlags( SELECTEDNODE | STRUCT_DELETED ); /* Put this structure in the picked list: */ ITEM_PICKER picker( item, UR_DELETED ); pickList.PushItem( picker ); - - item = item->Next(); - screen->SetDrawItems( item ); } - screen->SetDrawItems( savedItems ); // Restore the list entry point. - /* Mark all wires, junctions, .. connected to one of the item to delete */ if( DeleteFullConnection ) @@ -172,7 +168,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) if( item->Type() != SCH_LABEL_T ) continue; - tmp = screen->GetItem( ( (SCH_TEXT*) item )->m_Pos, 0, WIRE_T | BUS_T ); + tmp = screen->GetWireOrBus( ( (SCH_TEXT*) item )->m_Pos ); if( tmp && tmp->GetFlags() & STRUCT_DELETED ) { @@ -199,42 +195,23 @@ bool SCH_EDIT_FRAME::DeleteItemAtCrossHair( wxDC* DC ) { SCH_ITEM* item; SCH_SCREEN* screen = GetScreen(); - bool item_deleted = false; - item = screen->GetItem( screen->GetCrossHairPosition(), 0, MARKER_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, JUNCTION_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, NO_CONNECT_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, BUS_ENTRY_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, WIRE_T | BUS_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, DRAW_ITEM_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, TEXT_T | LABEL_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, COMPONENT_T ); - - if( item == NULL ) - item = screen->GetItem( screen->GetCrossHairPosition(), 0, SHEET_T ); + item = LocateItem( screen->GetCrossHairPosition(), SCH_COLLECTOR::ParentItems ); if( item ) { + bool itemHasConnections = item->IsConnectable(); + + GetScreen()->SetCurItem( NULL ); SetRepeatItem( NULL ); DeleteItem( item ); - screen->TestDanglingEnds( DrawPanel, DC ); + + if( itemHasConnections ) + screen->TestDanglingEnds( DrawPanel, DC ); + OnModify(); - item_deleted = true; + return true; } - return item_deleted; + return false; } diff --git a/eeschema/dialogs/dialog_edit_label.cpp b/eeschema/dialogs/dialog_edit_label.cpp index 78fd72695b..1bff3e4f0c 100644 --- a/eeschema/dialogs/dialog_edit_label.cpp +++ b/eeschema/dialogs/dialog_edit_label.cpp @@ -77,13 +77,17 @@ void DialogLabelEditor::InitDialog() break; case SCH_HIERARCHICAL_LABEL_T: - SetTitle( _( "Hierarchal Label Properties" ) ); + SetTitle( _( "Hierarchical Label Properties" ) ); break; case SCH_LABEL_T: SetTitle( _( "Label Properties" ) ); break; + case SCH_SHEET_LABEL_T: + SetTitle( _( "Hierarchical Sheet Pin Properties." ) ); + break; + default: SetTitle( _( "Text Properties" ) ); m_textLabel->Disconnect( wxEVT_COMMAND_TEXT_ENTER, diff --git a/eeschema/edit_component_in_schematic.cpp b/eeschema/edit_component_in_schematic.cpp index 6d7be389c9..ed611a08ca 100644 --- a/eeschema/edit_component_in_schematic.cpp +++ b/eeschema/edit_component_in_schematic.cpp @@ -80,98 +80,91 @@ void SCH_EDIT_FRAME::StartMoveCmpField( SCH_FIELD* aField, wxDC* DC ) /* * Edit a field: text and size */ -void SCH_EDIT_FRAME::EditCmpFieldText( SCH_FIELD* Field, wxDC* DC ) +void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField, wxDC* aDC ) { - int fieldNdx, flag; - LIB_COMPONENT* Entry; + wxCHECK_RET( aField != NULL && aField->Type() == SCH_FIELD_T, + wxT( "Invalid schemaitic field type. " ) ); - if( Field == NULL ) + int fieldNdx, flag; + SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent(); + + wxCHECK_RET( component != NULL && component->Type() == SCH_COMPONENT_T, + wxT( "Invalid schematic field parent item." ) ); + + LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( component->GetLibName() ); + + wxCHECK_RET( entry != NULL, wxT( "Library entry for component <" ) + + component->GetLibName() + wxT( "> could not be found." ) ); + + fieldNdx = aField->GetId(); + + if( fieldNdx == VALUE && entry->IsPower() ) { - DisplayError( this, _( "No Field To Edit" ), 10 ); + DisplayInfoMessage( this, _( "The component is a POWER, it's value cannot be \ +modified!\n\nYou must create a new power component with the value." ) ); return; } - SCH_COMPONENT* Cmp = (SCH_COMPONENT*) Field->GetParent(); - - fieldNdx = Field->m_FieldId; - - if( fieldNdx == VALUE ) - { - Entry = CMP_LIBRARY::FindLibraryComponent( Cmp->GetLibName() ); - - if( Entry && Entry->IsPower() ) - { - DisplayInfoMessage( this, _( "Part is a POWER, value cannot be \ -modified!\nYou must create a new power" ) ); - return; - } - } - flag = 0; - if( fieldNdx == REFERENCE ) - { - Entry = CMP_LIBRARY::FindLibraryComponent( Cmp->GetLibName() ); - if( Entry != NULL ) - { - if( Entry->GetPartCount() > 1 ) - flag = 1; - } - } + if( fieldNdx == REFERENCE && entry->GetPartCount() > 1 ) + flag = 1; /* save old cmp in undo list if not already in edit, or moving ... */ - if( Field->m_Flags == 0 ) - SaveCopyInUndoList( Cmp, UR_CHANGED ); + if( aField->GetFlags() == 0 ) + SaveCopyInUndoList( component, UR_CHANGED ); - wxString newtext = Field->m_Text; - DrawPanel->m_IgnoreMouseEvents = TRUE; + wxString newtext = aField->m_Text; + DrawPanel->m_IgnoreMouseEvents = true; - wxString title = _( "Field: " ) + Field->m_Name; + wxString title = _( "Field " ) + aField->m_Name; wxTextEntryDialog dlg( this, wxEmptyString , title, newtext ); int diag = dlg.ShowModal(); + DrawPanel->MoveCursorToCrossHair(); + DrawPanel->m_IgnoreMouseEvents = false; newtext = dlg.GetValue( ); newtext.Trim( true ); newtext.Trim( false ); - DrawPanel->MoveCursorToCrossHair(); - DrawPanel->m_IgnoreMouseEvents = FALSE; - if ( diag != wxID_OK ) + if ( diag != wxID_OK || newtext == aField->GetText() ) return; // cancelled by user - Field->m_AddExtraText = flag; - Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), g_XorMode ); + aField->m_AddExtraText = flag; + aField->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); if( !newtext.IsEmpty() ) { - if( Field->m_Text.IsEmpty() ) + if( aField->m_Text.IsEmpty() ) { - Field->m_Pos = Cmp->m_Pos; - Field->m_Size.x = Field->m_Size.y = m_TextFieldSize; + aField->m_Pos = component->m_Pos; + aField->m_Size.x = aField->m_Size.y = m_TextFieldSize; } - Field->m_Text = newtext; + + aField->m_Text = newtext; + if( fieldNdx == REFERENCE ) { - Cmp->SetRef( GetSheet(), newtext ); + component->SetRef( GetSheet(), newtext ); } } else { if( fieldNdx == REFERENCE ) { - DisplayError( this, _( "Reference needed !, No change" ) ); + DisplayError( this, _( "The reference field cannot be empty! No change" ) ); } else if( fieldNdx == VALUE ) { - DisplayError( this, _( "Value needed !, No change" ) ); + DisplayError( this, _( "The value field cannot be empty! No change" ) ); } else { - Field->m_Text = wxT( "~" ); + aField->m_Text = wxT( "~" ); } } - Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), g_XorMode ); - Cmp->DisplayInfo( this ); + aField->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); + component->DisplayInfo( this ); OnModify(); } @@ -284,12 +277,12 @@ void SCH_EDIT_FRAME::RotateCmpField( SCH_FIELD* Field, wxDC* DC ) /****************************************************************************/ void SCH_EDIT_FRAME::EditComponentReference( SCH_COMPONENT* Cmp, wxDC* DC ) { + wxCHECK_RET( Cmp != NULL && Cmp->Type() == SCH_COMPONENT_T, + wxT( "Invalid schematic component item." ) ); + LIB_COMPONENT* Entry; int flag = 0; - if( Cmp == NULL ) - return; - Entry = CMP_LIBRARY::FindLibraryComponent( Cmp->GetLibName() ); if( Entry == NULL ) @@ -331,12 +324,12 @@ void SCH_EDIT_FRAME::EditComponentReference( SCH_COMPONENT* Cmp, wxDC* DC ) /*****************************************************************************/ void SCH_EDIT_FRAME::EditComponentValue( SCH_COMPONENT* Cmp, wxDC* DC ) { + wxCHECK_RET( Cmp != NULL && Cmp->Type() == SCH_COMPONENT_T, + wxT( "Invalid schematic component item." ) ); + wxString message; LIB_COMPONENT* Entry; - if( Cmp == NULL ) - return; - Entry = CMP_LIBRARY::FindLibraryComponent( Cmp->GetLibName() ); if( Entry == NULL ) @@ -373,12 +366,12 @@ void SCH_EDIT_FRAME::EditComponentValue( SCH_COMPONENT* Cmp, wxDC* DC ) void SCH_EDIT_FRAME::EditComponentFootprint( SCH_COMPONENT* Cmp, wxDC* DC ) { + wxCHECK_RET( Cmp != NULL && Cmp->Type() == SCH_COMPONENT_T, + wxT( "Invalid schematic component item." ) ); + wxString message; LIB_COMPONENT* Entry; - if( Cmp == NULL ) - return; - Entry = CMP_LIBRARY::FindLibraryComponent( Cmp->GetLibName() ); if( Entry == NULL ) diff --git a/eeschema/edit_label.cpp b/eeschema/edit_label.cpp index d3f30c602e..46392727aa 100644 --- a/eeschema/edit_label.cpp +++ b/eeschema/edit_label.cpp @@ -78,19 +78,7 @@ void SCH_EDIT_FRAME::StartMoveTexte( SCH_TEXT* aTextItem, wxDC* aDC ) void SCH_EDIT_FRAME::ChangeTextOrient( SCH_TEXT* aTextItem, wxDC* aDC ) { - if( aTextItem == NULL ) - aTextItem = (SCH_TEXT*) GetScreen()->GetItem( GetScreen()->GetCrossHairPosition(), 0, - TEXT_T | LABEL_T ); - if( aTextItem == NULL ) - return; - - /* save old text in undo list if is not already in edit */ - if( aTextItem->GetFlags() == 0 ) - SaveCopyInUndoList( aTextItem, UR_CHANGED ); - - /* Erase old text */ - DrawPanel->CrossHairOff( aDC ); - aTextItem->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); + wxCHECK_RET( aTextItem != NULL, wxT( "Invalid schematic text item." ) ); int orient; @@ -100,15 +88,22 @@ void SCH_EDIT_FRAME::ChangeTextOrient( SCH_TEXT* aTextItem, wxDC* aDC ) case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_TEXT_T: - orient = aTextItem->GetOrientation() + 1; - orient &= 3; - aTextItem->SetOrientation( orient ); + orient = ( aTextItem->GetOrientation() + 1 ) & 3; break; default: - break; + wxFAIL_MSG( wxT( "Invalid schematic item <" ) + aTextItem->GetClass() + + wxT( "> passed to SCH_EDIT_FRAME::ChangeTextOrient()" ) ); + return; } + // Save current text orientation in undo list if is not already in edit. + if( aTextItem->GetFlags() == 0 ) + SaveCopyInUndoList( aTextItem, UR_CHANGED ); + + DrawPanel->CrossHairOff( aDC ); + aTextItem->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); + aTextItem->SetOrientation( orient ); OnModify(); aTextItem->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); DrawPanel->CrossHairOn( aDC ); diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index bdfd7b4f82..270c008e31 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -4,6 +4,15 @@ #include "id.h" + +/** + * The maximum number of items in the clarify selection context menu. It is + * highly unlikely that there would ever be more than 10 items at the current + * cursor. Increase this number if that ever becomes a problem. + */ +#define MAX_SELECT_ITEM_IDS 10 + + /** * Command IDs for the schematic editor. * @@ -138,6 +147,9 @@ enum id_eeschema_frm ID_POPUP_SCH_ROTATE_CMP_COUNTERCLOCKWISE, ID_POPUP_SCH_ORIENT_NORMAL_CMP, + ID_SCH_SELECT_ITEM_START, + ID_SCH_SELECT_ITEM_END = ID_SCH_SELECT_ITEM_START + MAX_SELECT_ITEM_IDS, + // Schematic editor commmands. These are command IDs that are generated by multiple // events (menus, toolbar, context menu, etc.) that result in the same event handler. ID_CANCEL_CURRENT_COMMAND, diff --git a/eeschema/getpart.cpp b/eeschema/getpart.cpp index 6bfab4da88..57d5ec4b68 100644 --- a/eeschema/getpart.cpp +++ b/eeschema/getpart.cpp @@ -247,18 +247,12 @@ static void ShowWhileMoving( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& a void SCH_EDIT_FRAME::OnChangeComponentOrientation( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); + SCH_ITEM* item = screen->GetCurItem(); - // Ensure the struct is a component (could be a struct of a - // component, like Field, text..) - if( screen->GetCurItem() == NULL || screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - { - screen->SetCurItem( LocateSmallestComponent( screen ) ); + wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T, + wxT( "Cannot change orientation of invalid schematic item." ) ); - if( screen->GetCurItem() == NULL || screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - return; - } - - SCH_COMPONENT* component = (SCH_COMPONENT*) screen->GetCurItem(); + SCH_COMPONENT* component = (SCH_COMPONENT*) item; int orientation; @@ -287,8 +281,8 @@ void SCH_EDIT_FRAME::OnChangeComponentOrientation( wxCommandEvent& aEvent ) DrawPanel->MoveCursorToCrossHair(); - if( screen->GetCurItem()->GetFlags() == 0 ) - SaveCopyInUndoList( screen->GetCurItem(), UR_CHANGED ); + if( component->GetFlags() == 0 ) + SaveCopyInUndoList( item, UR_CHANGED ); INSTALL_UNBUFFERED_DC( dc, DrawPanel ); @@ -348,28 +342,16 @@ static void ExitPlaceCmp( EDA_DRAW_PANEL* Panel, wxDC* DC ) void SCH_EDIT_FRAME::OnSelectUnit( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); + SCH_ITEM* item = screen->GetCurItem(); - if( screen->GetCurItem() == NULL ) - return; + wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T, + wxT( "Cannot select unit of invalid schematic item." ) ); INSTALL_UNBUFFERED_DC( dc, DrawPanel ); - // Verify the selected item is a component, it may be part of a component such as a field - // or text item. - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - { - screen->SetCurItem( LocateSmallestComponent( screen ) ); - - if( screen->GetCurItem() == NULL ) - return; - } - DrawPanel->MoveCursorToCrossHair(); - SCH_COMPONENT* component = (SCH_COMPONENT*) screen->GetCurItem(); - - wxCHECK_RET( (component != NULL) && (component->Type() == SCH_COMPONENT_T), - wxT( "Cannot select unit for invalid component." ) ); + SCH_COMPONENT* component = (SCH_COMPONENT*) item; int unit = aEvent.GetId() + 1 - ID_POPUP_SCH_SELECT_UNIT1; @@ -414,7 +396,7 @@ void SCH_EDIT_FRAME::OnSelectUnit( wxCommandEvent& aEvent ) else component->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); - GetScreen()->TestDanglingEnds( DrawPanel, &dc ); + screen->TestDanglingEnds( DrawPanel, &dc ); OnModify(); } diff --git a/eeschema/hotkeys.cpp b/eeschema/hotkeys.cpp index a72698e5b6..7089345ff9 100644 --- a/eeschema/hotkeys.cpp +++ b/eeschema/hotkeys.cpp @@ -259,19 +259,21 @@ struct Ki_HotkeyInfoSectionDescriptor s_Viewlib_Hokeys_Descr[] = */ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, EDA_ITEM* aItem ) { + if( aHotKey == 0 ) + return; + wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); cmd.SetEventObject( this ); SCH_SCREEN* screen = GetScreen(); + // itemInEdit == false means no item currently edited. We can ask for editing a new item - bool itemInEdit = screen->GetCurItem() && screen->GetCurItem()->GetFlags(); + bool itemInEdit = screen->GetCurItem() && screen->GetCurItem()->GetFlags(); + // notBusy == true means no item currently edited and no other command in progress // We can change active tool and ask for editing a new item - bool notBusy = (!itemInEdit) && (screen->m_BlockLocate.m_State == STATE_NO_BLOCK); - - if( aHotKey == 0 ) - return; + bool notBusy = (!itemInEdit) && (screen->m_BlockLocate.m_State == STATE_NO_BLOCK); /* Convert lower to upper case (the usual toupper function has problem * with non ascii codes like function keys */ @@ -340,13 +342,9 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, break; case HK_DELETE: - if( notBusy) - { + if( notBusy ) DeleteItemAtCrossHair( aDC ); - OnModify(); - GetScreen()->SetCurItem( NULL ); - GetScreen()->TestDanglingEnds( DrawPanel, aDC ); - } + break; case HK_REPEAT_LAST: @@ -449,7 +447,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, if( notBusy ) { if( GetToolId() != ID_WIRETOBUS_ENTRY_BUTT ) - SetToolID( ID_WIRETOBUS_ENTRY_BUTT, wxCURSOR_PENCIL, _( "Add Wire to Bus entry" ) ); + SetToolID( ID_WIRETOBUS_ENTRY_BUTT, wxCURSOR_PENCIL, _( "Add Wire to Bus Entry" ) ); OnLeftClick( aDC, aPosition ); } @@ -459,7 +457,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, if( notBusy ) { if( GetToolId() != ID_BUSTOBUS_ENTRY_BUTT ) - SetToolID( ID_BUSTOBUS_ENTRY_BUTT, wxCURSOR_PENCIL, _( "Add Bus to Bus entry" ) ); + SetToolID( ID_BUSTOBUS_ENTRY_BUTT, wxCURSOR_PENCIL, _( "Add Bus to Bus Entry" ) ); OnLeftClick( aDC, aPosition ); } @@ -552,7 +550,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, if( notBusy ) { if( GetToolId() != ID_NOCONN_BUTT ) - SetToolID( ID_NOCONN_BUTT, wxCURSOR_PENCIL, _( "Add \"NoNonnect\" Flags" ) ); + SetToolID( ID_NOCONN_BUTT, wxCURSOR_PENCIL, _( "Add \"No Connect\" Flag" ) ); OnLeftClick( aDC, aPosition ); } @@ -568,48 +566,37 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, if( aItem == NULL ) { // Find the schematic object to rotate under the cursor - aItem = LocateAndShowItem( aPosition, false ); - - if( aItem == NULL ) - break; - - if( aItem->Type() == SCH_COMPONENT_T ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::RotatableItems ); if( aItem == NULL ) break; } - if( aItem ) + switch( aItem->Type() ) { - GetScreen()->SetCurItem( (SCH_ITEM*) aItem ); + case SCH_SHEET_T: //TODO allow sheet rotate on hotkey + //wxPostEvent( this, eventRotateSheet ); + break; - switch( aItem->Type() ) - { - case SCH_SHEET_T: //TODO allow sheet rotate on hotkey - //wxPostEvent( this, eventRotateSheet ); - break; + case SCH_COMPONENT_T: + cmd.SetId( ID_POPUP_SCH_ROTATE_CMP_COUNTERCLOCKWISE ); + wxPostEvent( this, cmd ); + break; - case SCH_COMPONENT_T: - cmd.SetId( ID_POPUP_SCH_ROTATE_CMP_COUNTERCLOCKWISE ); - wxPostEvent( this, cmd ); - break; + case SCH_TEXT_T: + case SCH_LABEL_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIERARCHICAL_LABEL_T: + cmd.SetId( ID_POPUP_SCH_ROTATE_TEXT ); + wxPostEvent( this, cmd ); + break; - case SCH_TEXT_T: - case SCH_LABEL_T: - case SCH_GLOBAL_LABEL_T: - case SCH_HIERARCHICAL_LABEL_T: - cmd.SetId( ID_POPUP_SCH_ROTATE_TEXT ); - wxPostEvent( this, cmd ); - break; + case SCH_FIELD_T: + cmd.SetId( ID_POPUP_SCH_ROTATE_FIELD ); + wxPostEvent( this, cmd ); - case SCH_FIELD_T: - cmd.SetId( ID_POPUP_SCH_ROTATE_FIELD ); - wxPostEvent( this, cmd ); - - default: - ; - } + default: + ; } break; @@ -622,7 +609,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, } if( aItem == NULL ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::ComponentsOnly ); if( aItem ) { @@ -640,7 +627,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, } if( aItem == NULL ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::ComponentsOnly ); if( aItem ) { @@ -652,7 +639,7 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, case HK_ORIENT_NORMAL_COMPONENT: // Orient 0, no mirror (Component) if( aItem == NULL ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::ComponentsOnly ); if( aItem ) { @@ -663,71 +650,81 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, break; - case HK_DRAG: // Start drag - case HK_MOVE_COMPONENT_OR_ITEM: // Start move component or other schematic item case HK_COPY_COMPONENT_OR_LABEL: // Duplicate component or text/label if( itemInEdit ) break; if( aItem == NULL ) { - // For a drag or copy command, try to find first a component: - if( aItem == NULL && HK_Descr->m_Idcommand != HK_MOVE_COMPONENT_OR_ITEM ) - aItem = LocateSmallestComponent( GetScreen() ); - - // If no component, find the schematic object to move/drag or copy under the cursor - if( aItem == NULL ) - aItem = LocateAndShowItem( aPosition, false ); - - if( aItem == NULL ) - break; - - if( aItem->Type() == SCH_COMPONENT_T ) - aItem = LocateSmallestComponent( GetScreen() ); - - if( aItem == NULL ) - break; - - if( aItem->Type() == SCH_SHEET_T ) - { - SCH_SHEET* sheet = (SCH_SHEET*) aItem; - // If it's a sheet, then check if a pinsheet is under the cursor - SCH_SHEET_PIN* slabel = sheet->GetLabel( GetScreen()->GetCrossHairPosition() ); - - if( slabel ) - aItem = slabel; - } - - if( aItem->Type() == SCH_JUNCTION_T ) - { - // If it's a junction, pick the underlying wire instead - aItem = screen->GetItem( screen->GetCrossHairPosition(), 0, WIRE_T ); - } + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::MovableItems ); if( aItem == NULL ) break; } - if( HK_Descr->m_Idcommand == HK_COPY_COMPONENT_OR_LABEL ) - { - GetScreen()->SetCurItem( (SCH_ITEM*) aItem ); - wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, HK_Descr->m_IdMenuEvent ); - wxPostEvent( this, event ); + cmd.SetId( HK_Descr->m_IdMenuEvent ); + wxPostEvent( this, cmd ); + break; + + case HK_DRAG: // Start drag + if( itemInEdit ) break; + + if( aItem == NULL ) + { + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::DraggableItems, + HK_Descr->m_Idcommand ); + + if( aItem == NULL ) + break; } - if( aItem && (aItem->GetFlags() == 0) ) + if( aItem->GetFlags() == 0 ) { - GetScreen()->SetCurItem( (SCH_ITEM*) aItem ); + switch( aItem->Type() ) + { + // select the correct event for moving an schematic object + // and add it to the event queue + case SCH_COMPONENT_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIERARCHICAL_LABEL_T: + cmd.SetId( HK_Descr->m_IdMenuEvent ); + wxPostEvent( this, cmd ); + break; - // Create the events for moving a component or other schematic item - wxCommandEvent eventMoveItem( wxEVT_COMMAND_TOOL_CLICKED, - ID_POPUP_SCH_MOVE_ITEM_REQUEST ); - wxCommandEvent eventMovePinsheet( wxEVT_COMMAND_TOOL_CLICKED, - ID_POPUP_SCH_MOVE_PINSHEET ); - wxCommandEvent eventDragWire( wxEVT_COMMAND_TOOL_CLICKED, - ID_POPUP_SCH_DRAG_WIRE_REQUEST ); + case SCH_BUS_ENTRY_T: + case SCH_LINE_T: + if( ((SCH_ITEM*) aItem )->GetLayer() != LAYER_BUS ) + { + cmd.SetId( ID_POPUP_SCH_DRAG_WIRE_REQUEST ); + wxPostEvent( this, cmd ); + } + break; + + default: + ; + } + } + + break; + + + case HK_MOVE_COMPONENT_OR_ITEM: // Start move component or other schematic item + if( itemInEdit ) + break; + + if( aItem == NULL ) + { + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::MovableItems, + HK_Descr->m_Idcommand ); + + if( aItem == NULL ) + break; + } + + if( aItem->GetFlags() == 0 ) + { switch( aItem->Type() ) { // select the correct event for moving an schematic object @@ -737,30 +734,28 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: + case SCH_TEXT_T: + case SCH_FIELD_T: + case SCH_BUS_ENTRY_T: cmd.SetId( HK_Descr->m_IdMenuEvent ); wxPostEvent( this, cmd ); break; - case SCH_TEXT_T: - case SCH_FIELD_T: - case SCH_BUS_ENTRY_T: - if( HK_Descr->m_Idcommand != HK_DRAG ) - wxPostEvent( this, eventMoveItem ); - break; - case SCH_SHEET_LABEL_T: - if( HK_Descr->m_Idcommand != HK_DRAG ) - wxPostEvent( this, eventMovePinsheet ); + cmd.SetId( ID_POPUP_SCH_MOVE_PINSHEET ); + wxPostEvent( this, cmd ); break; case SCH_LINE_T: - if( ( (SCH_ITEM*) aItem )->GetLayer() == LAYER_WIRE ) + /** + * @todo Determine why moving bus lines are not handled here. + */ + if( ((SCH_ITEM*) aItem )->GetLayer() != LAYER_BUS ) { - if( HK_Descr->m_Idcommand == HK_DRAG ) - wxPostEvent( this, eventDragWire ); - else - wxPostEvent( this, eventMoveItem ); + cmd.SetId( ID_POPUP_SCH_MOVE_ITEM_REQUEST ); + wxPostEvent( this, cmd ); } + break; default: @@ -777,43 +772,61 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, if( aItem == NULL ) { - aItem = screen->GetItem( screen->GetCrossHairPosition(), 0, - COMPONENT_T | TEXT_T | LABEL_T | SHEET_T ); - if( aItem == NULL ) - break; - - if( aItem->Type() == SCH_COMPONENT_T ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::EditableItems ); if( aItem == NULL ) break; } - if( aItem ) + switch( aItem->Type() ) { - switch( aItem->Type() ) + case SCH_COMPONENT_T: + InstallCmpeditFrame( this, (SCH_COMPONENT*) aItem ); + break; + + case SCH_SHEET_T: + cmd.SetId( ID_POPUP_SCH_EDIT_SHEET ); + wxPostEvent( this, cmd ); + break; + + case SCH_SHEET_LABEL_T: + cmd.SetId( ID_POPUP_SCH_EDIT_PINSHEET ); + wxPostEvent( this, cmd ); + break; + + case SCH_TEXT_T: + case SCH_LABEL_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIERARCHICAL_LABEL_T: + EditSchematicText( (SCH_TEXT*) aItem ); + break; + + case SCH_FIELD_T: + switch( ( (SCH_FIELD*) aItem )->GetId() ) { - case SCH_COMPONENT_T: - InstallCmpeditFrame( this, (SCH_COMPONENT*) aItem ); + case REFERENCE: + EditComponentReference( (SCH_COMPONENT*)aItem->GetParent(), aDC ); break; - - case SCH_SHEET_T: - GetScreen()->SetCurItem( (SCH_ITEM*) aItem ); - cmd.SetId( ID_POPUP_SCH_EDIT_SHEET ); - wxPostEvent( this, cmd ); + case VALUE: + EditComponentValue( (SCH_COMPONENT*) aItem->GetParent(), aDC ); break; - - case SCH_TEXT_T: - case SCH_LABEL_T: - case SCH_GLOBAL_LABEL_T: - case SCH_HIERARCHICAL_LABEL_T: - EditSchematicText( (SCH_TEXT*) aItem ); + case FOOTPRINT: + EditComponentFootprint( (SCH_COMPONENT*) aItem->GetParent(), aDC ); break; - default: - ; + /** + * @todo Not sure exactly why there are functions specific to the reference, + * value, and footprint fields when the EditComponentFieldText() function + * seems like it was designed to handle any field. This should probably be + * cleaned up. + */ + EditComponentFieldText( (SCH_FIELD*) aItem, aDC ); } + + default: + ; } + break; case HK_EDIT_COMPONENT_VALUE: @@ -821,12 +834,11 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, break; if( aItem == NULL ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::ComponentsOnly ); if( aItem ) - { EditComponentValue( (SCH_COMPONENT*) aItem, aDC ); - } + break; case HK_EDIT_COMPONENT_FOOTPRINT: @@ -834,12 +846,11 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, break; if( aItem == NULL ) - aItem = LocateSmallestComponent( GetScreen() ); + aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::ComponentsOnly ); if( aItem ) - { EditComponentFootprint( (SCH_COMPONENT*) aItem, aDC ); - } + break; } } @@ -852,6 +863,9 @@ void SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, */ void LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, EDA_ITEM* aItem ) { + if( aHotKey == 0 ) + return; + wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); wxCommandEvent toolCmd( wxEVT_COMMAND_TOOL_CLICKED ); @@ -859,9 +873,6 @@ void LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, bool itemInEdit = GetScreen()->GetCurItem() && GetScreen()->GetCurItem()->GetFlags(); - if( aHotKey == 0 ) - return; - /* Convert lower to upper case (the usual toupper function has problem * with non ascii codes like function keys */ if( (aHotKey >= 'a') && (aHotKey <= 'z') ) @@ -880,7 +891,6 @@ void LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, default: case HK_NOT_FOUND: return; - break; case HK_HELP: // Display Current hotkey list DisplayHotkeyList( this, s_Libedit_Hokeys_Descr ); diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp index c2dc05a77b..cd3a137338 100644 --- a/eeschema/lib_pin.cpp +++ b/eeschema/lib_pin.cpp @@ -11,6 +11,7 @@ #include "drawtxt.h" #include "plot_common.h" #include "wxEeschemaStruct.h" +#include "bitmaps.h" #include "general.h" #include "protos.h" @@ -18,8 +19,8 @@ #include "class_libentry.h" #include "lib_pin.h" #include "transform.h" +#include "sch_component.h" -#include "bitmaps.h" /** * Note: The following name lists are sentence capitalized per the GNOME UI @@ -1875,6 +1876,20 @@ const char*** LIB_PIN::GetStyleSymbols() return s_icons_Pins_Shapes; } +const char** LIB_PIN::GetMenuImage() const +{ + return s_icons_Pins_Electrical_Type[m_type]; +} + + +wxString LIB_PIN::GetSelectMenuText() const +{ + wxString tmp = _( "Pin " ); + + return tmp << GetNumberString() << wxT( ", " ) << GetTypeString() << wxT( ", " ) + << wxGetTranslation( pin_style_names[ GetStyleCodeIndex( m_shape ) ] );; +} + #if defined(DEBUG) diff --git a/eeschema/lib_pin.h b/eeschema/lib_pin.h index ad4d1b61a3..8f35295a9f 100644 --- a/eeschema/lib_pin.h +++ b/eeschema/lib_pin.h @@ -9,6 +9,8 @@ #include "lib_draw_item.h" +class SCH_COMPONENT; + #define TARGET_PIN_DIAM 12 /* Circle diameter drawn at the active end of pins */ @@ -134,12 +136,15 @@ public: virtual bool Save( FILE* aFile ); virtual bool Load( char* aLine, wxString& aErrorMsg ); - /** - * Test if the given point is within the bounds of this object. - * + * Function HitTest + * verifies that \a aRefPos within the bounds of this pin attached to \a aComponent. + *

+ * The coordinates of the pin are calculated relative to \a aComponent if not NULL. + * Otherwise, the pin coordinates are relative to the library anchor position. + *

* @param aRefPos A wxPoint to test - * @return - true if a hit, else false + * @return True \a aRefPos lies within the pin bounding box else false. */ virtual bool HitTest( const wxPoint& aRefPos ); @@ -445,6 +450,10 @@ public: */ static const char*** GetElectricalTypeSymbols(); + virtual const char** GetMenuImage() const; + + virtual wxString GetSelectMenuText() const; + protected: virtual LIB_DRAW_ITEM* DoGenCopy(); diff --git a/eeschema/locate.cpp b/eeschema/locate.cpp deleted file mode 100644 index 65da8b42ac..0000000000 --- a/eeschema/locate.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************/ -/* Routines for locating an element of a schematic. */ -/******************************************************/ - -#include "fctsys.h" -#include "common.h" -#include "trigo.h" -#include "macros.h" -#include "class_sch_screen.h" - -#include "general.h" -#include "protos.h" -#include "class_library.h" -#include "sch_bus_entry.h" -#include "sch_marker.h" -#include "sch_junction.h" -#include "sch_component.h" -#include "sch_line.h" -#include "sch_no_connect.h" -#include "sch_polyline.h" -#include "sch_sheet.h" -#include "lib_pin.h" -#include "template_fieldnames.h" - - -/** - * Search the smaller (considering its area) component under the mouse - * cursor or the pcb cursor - * - * If more than 1 component is found, a pointer to the smaller component is - * returned - */ -SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen ) -{ - double area = 0.0; // Quiet compiler - EDA_Rect rect; - PICKED_ITEMS_LIST itemList; - SCH_COMPONENT* component = NULL; - SCH_COMPONENT* lastcomponent = NULL; - - if( Screen->GetItems( Screen->RefPos( true ), itemList, COMPONENT_T ) == 0 ) - { - if( Screen->GetItems( Screen->GetCrossHairPosition(), itemList, COMPONENT_T ) == 0 ) - return NULL; - } - - if( itemList.GetCount() == 1 ) - return (SCH_COMPONENT*) itemList.GetPickedItem( 0 ); - - for( size_t i = 0; i < itemList.GetCount(); i++ ) - { - component = (SCH_COMPONENT*) itemList.GetPickedItem( i ); - - if( lastcomponent == NULL ) // First component - { - lastcomponent = component; - rect = lastcomponent->GetBoundingBox(); - area = ABS( (double) rect.GetWidth() * (double) rect.GetHeight() ); - } - else - { - rect = component->GetBoundingBox(); - double tmp = ABS( (double) rect.GetWidth() * (double) rect.GetHeight() ); - - if( area > tmp ) // a smaller component is found - { - area = tmp; - lastcomponent = component; - } - } - } - - return lastcomponent; -} diff --git a/eeschema/onleftclick.cpp b/eeschema/onleftclick.cpp index d7ee497efd..deef86e7c4 100644 --- a/eeschema/onleftclick.cpp +++ b/eeschema/onleftclick.cpp @@ -80,9 +80,9 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) if( ( item && item->GetFlags() ) || ( g_RootSheet->CountSheets() == 0 ) ) break; - item = LocateAndShowItem( aPosition ); + item = LocateAndShowItem( aPosition, SCH_COLLECTOR::SheetsOnly ); - if( item && ( item->Type() == SCH_SHEET_T ) ) + if( item ) { m_CurrentSheet->Push( (SCH_SHEET*) item ); DisplayCurrentSheet(); @@ -241,7 +241,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) case ID_IMPORT_HLABEL_BUTT: case ID_SHEET_LABEL_BUTT: if( ( item == NULL ) || ( item->GetFlags() == 0 ) ) - item = LocateAndShowItem( aPosition ); + item = LocateAndShowItem( aPosition, SCH_COLLECTOR::SheetsAndSheetLabels ); if( item == NULL ) break; @@ -345,7 +345,7 @@ void SCH_EDIT_FRAME::OnLeftDClick( wxDC* aDC, const wxPoint& aPosition ) break; case SCH_FIELD_T: - EditCmpFieldText( (SCH_FIELD*) item, aDC ); + EditComponentFieldText( (SCH_FIELD*) item, aDC ); DrawPanel->MoveCursorToCrossHair(); break; diff --git a/eeschema/onrightclick.cpp b/eeschema/onrightclick.cpp index bde39fbbbd..4589d70496 100644 --- a/eeschema/onrightclick.cpp +++ b/eeschema/onrightclick.cpp @@ -50,7 +50,7 @@ static void AddMenusForMarkers( wxMenu* aPopMenu, SCH_MARKER* aMarker, SCH_EDIT_ */ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) { - SCH_ITEM* DrawStruct = (SCH_ITEM*) GetScreen()->GetCurItem(); + SCH_ITEM* item = GetScreen()->GetCurItem(); bool BlockActive = GetScreen()->IsBlockActive(); // Do not start a block command on context menu. @@ -64,24 +64,22 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) } // Try to locate items at cursor position. - if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) ) + if( (item == NULL) || (item->GetFlags() == 0) ) { - DrawStruct = LocateAndShowItem( aPosition, false ); + item = LocateAndShowItem( aPosition, SCH_COLLECTOR::AllItemsButPins ); - if( DrawStruct && (DrawStruct->Type() == SCH_SHEET_T) ) + // If the clarify item selection context menu is aborted, don't show the context menu. + if( item == NULL && DrawPanel->m_AbortRequest ) { - SCH_SHEET* sheet = (SCH_SHEET*) DrawStruct; - SCH_SHEET_PIN* slabel = sheet->GetLabel( GetScreen()->GetCrossHairPosition() ); - - if( slabel ) - DrawStruct = slabel; + DrawPanel->m_AbortRequest = false; + return false; } } // If Command in progress: add "cancel" and "end tool" menu if( GetToolId() != ID_NO_TOOL_SELECTED ) { - if( DrawStruct && DrawStruct->GetFlags() ) + if( item && item->GetFlags() ) { ADD_MENUITEM( PopMenu, ID_CANCEL_CURRENT_COMMAND, _( "Cancel" ), cancel_xpm ); } @@ -93,29 +91,25 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) } else { - if( DrawStruct && DrawStruct->GetFlags() ) + if( item && item->GetFlags() ) { ADD_MENUITEM( PopMenu, ID_CANCEL_CURRENT_COMMAND, _( "Cancel" ), cancel_xpm ); PopMenu->AppendSeparator(); } } - if( DrawStruct == NULL ) + if( item == NULL ) { if( GetSheet()->Last() != g_RootSheet ) - { ADD_MENUITEM( PopMenu, ID_POPUP_SCH_LEAVE_SHEET, _( "Leave Sheet" ), leave_sheet_xpm ); - PopMenu->AppendSeparator(); - } + PopMenu->AppendSeparator(); return true; } - GetScreen()->SetCurItem( DrawStruct ); + int flags = item->GetFlags(); + bool is_new = (flags & IS_NEW) ? true : false; - int flags = DrawStruct->GetFlags(); - bool is_new = (flags & IS_NEW) ? TRUE : FALSE; - - switch( DrawStruct->Type() ) + switch( item->Type() ) { case SCH_NO_CONNECT_T: @@ -123,7 +117,7 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) break; case SCH_JUNCTION_T: - AddMenusForJunction( PopMenu, (SCH_JUNCTION*) DrawStruct, this ); + AddMenusForJunction( PopMenu, (SCH_JUNCTION*) item, this ); break; case SCH_BUS_ENTRY_T: @@ -134,7 +128,7 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) ADD_MENUITEM( PopMenu, ID_POPUP_SCH_MOVE_ITEM_REQUEST, msg, move_xpm ); } - if( GetBusEntryShape( (SCH_BUS_ENTRY*) DrawStruct ) == '\\' ) + if( GetBusEntryShape( (SCH_BUS_ENTRY*) item ) == '\\' ) PopMenu->Append( ID_POPUP_SCH_ENTRY_SELECT_SLASH, _( "Set Bus Entry /" ) ); else PopMenu->Append( ID_POPUP_SCH_ENTRY_SELECT_ANTISLASH, _( "Set Bus Entry \\" ) ); @@ -142,57 +136,42 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) break; case SCH_MARKER_T: - AddMenusForMarkers( PopMenu, (SCH_MARKER*) DrawStruct, this ); + AddMenusForMarkers( PopMenu, (SCH_MARKER*) item, this ); break; case SCH_TEXT_T: - AddMenusForText( PopMenu, (SCH_TEXT*) DrawStruct ); + AddMenusForText( PopMenu, (SCH_TEXT*) item ); break; case SCH_LABEL_T: - AddMenusForLabel( PopMenu, (SCH_LABEL*) DrawStruct ); + AddMenusForLabel( PopMenu, (SCH_LABEL*) item ); break; case SCH_GLOBAL_LABEL_T: - AddMenusForGLabel( PopMenu, (SCH_GLOBALLABEL*) DrawStruct ); + AddMenusForGLabel( PopMenu, (SCH_GLOBALLABEL*) item ); break; case SCH_HIERARCHICAL_LABEL_T: - AddMenusForHLabel( PopMenu, (SCH_HIERLABEL*) DrawStruct ); + AddMenusForHLabel( PopMenu, (SCH_HIERLABEL*) item ); break; case SCH_FIELD_T: - { - AddMenusForComponentField( PopMenu, (SCH_FIELD*) DrawStruct ); - - if( flags ) - break; - - // Many fields are inside a component. If this is the case, add the - // component menu - SCH_COMPONENT* Component = LocateSmallestComponent( GetScreen() ); - - if( Component ) - { - PopMenu->AppendSeparator(); - AddMenusForComponent( PopMenu, Component ); - } - } + AddMenusForComponentField( PopMenu, (SCH_FIELD*) item ); break; case SCH_COMPONENT_T: - AddMenusForComponent( PopMenu, (SCH_COMPONENT*) DrawStruct ); + AddMenusForComponent( PopMenu, (SCH_COMPONENT*) item ); break; case SCH_LINE_T: - switch( DrawStruct->GetLayer() ) + switch( item->GetLayer() ) { case LAYER_WIRE: - AddMenusForWire( PopMenu, (SCH_LINE*) DrawStruct, this ); + AddMenusForWire( PopMenu, (SCH_LINE*) item, this ); break; case LAYER_BUS: - AddMenusForBus( PopMenu, (SCH_LINE*) DrawStruct, this ); + AddMenusForBus( PopMenu, (SCH_LINE*) item, this ); break; default: @@ -204,17 +183,17 @@ bool SCH_EDIT_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) break; case SCH_SHEET_T: - AddMenusForHierchicalSheet( PopMenu, (SCH_SHEET*) DrawStruct ); + AddMenusForHierchicalSheet( PopMenu, (SCH_SHEET*) item ); break; case SCH_SHEET_LABEL_T: - AddMenusForPinSheet( PopMenu, (SCH_SHEET_PIN*) DrawStruct ); + AddMenusForPinSheet( PopMenu, (SCH_SHEET_PIN*) item ); break; default: wxString msg; msg.Printf( wxT( "SCH_EDIT_FRAME::OnRightClick Error: unknown DrawType %d" ), - DrawStruct->Type() ); + item->Type() ); DisplayError( this, msg ); break; } @@ -495,15 +474,14 @@ void AddMenusForJunction( wxMenu* PopMenu, SCH_JUNCTION* Junction, SCH_EDIT_FRAM if( !is_new ) { - if( screen->GetItem( screen->GetCrossHairPosition(), 0, - WIRE_T | BUS_T | EXCLUDE_ENDPOINTS_T ) ) + if( screen->GetWire( screen->GetCrossHairPosition(), EXCLUDE_END_POINTS_T ) ) ADD_MENUITEM( PopMenu, ID_POPUP_SCH_BREAK_WIRE, _( "Break Wire" ), break_line_xpm ); } msg = AddHotkeyName( _( "Delete Junction" ), s_Schematic_Hokeys_Descr, HK_DELETE ); ADD_MENUITEM( PopMenu, ID_POPUP_SCH_DELETE, msg, delete_xpm ); - if( screen->GetItem( screen->GetCrossHairPosition(), 0, WIRE_T | BUS_T ) ) + if( screen->GetWireOrBus( screen->GetCrossHairPosition() ) ) { ADD_MENUITEM( PopMenu, ID_POPUP_SCH_DELETE_NODE, _( "Delete Node" ), delete_node_xpm ); ADD_MENUITEM( PopMenu, ID_POPUP_SCH_DELETE_CONNECTION, _( "Delete Connection" ), @@ -534,8 +512,9 @@ void AddMenusForWire( wxMenu* PopMenu, SCH_LINE* Wire, SCH_EDIT_FRAME* frame ) ADD_MENUITEM( PopMenu, ID_POPUP_SCH_DELETE_CONNECTION, _( "Delete Connection" ), delete_connection_xpm ); - if( screen->GetItem( screen->GetCrossHairPosition(), 0, - WIRE_T | BUS_T | EXCLUDE_ENDPOINTS_T ) ) + SCH_LINE* line = screen->GetWireOrBus( screen->GetCrossHairPosition() ); + + if( line && !line->IsEndPoint( screen->GetCrossHairPosition() ) ) ADD_MENUITEM( PopMenu, ID_POPUP_SCH_BREAK_WIRE, _( "Break Wire" ), break_line_xpm ); PopMenu->AppendSeparator(); diff --git a/eeschema/protos.h b/eeschema/protos.h index 31f7cead58..9b3ffd77dc 100644 --- a/eeschema/protos.h +++ b/eeschema/protos.h @@ -67,12 +67,6 @@ void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ); */ SCH_ITEM* DuplicateStruct( SCH_ITEM* DrawStruct, bool aClone = false ); -/*************/ -/* LOCATE.CPP */ -/*************/ - -SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen ); - /***************/ /* EEREDRAW.CPP */ diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp index bf96dbb7b1..5aaee3f678 100644 --- a/eeschema/sch_bus_entry.cpp +++ b/eeschema/sch_bus_entry.cpp @@ -224,11 +224,17 @@ void SCH_BUS_ENTRY::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_BUS_ENTRY::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_BUS_ENTRY::GetSelectMenuText() const { - if( !( aFilter & BUS_ENTRY_T ) ) - return false; + if( m_Layer == LAYER_WIRE ) + return wxString( _( "Bus to Wire Entry" ) ); + return wxString( _( "Bus to Bus Entry" ) ); +} + + +bool SCH_BUS_ENTRY::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ return TestSegmentHit( aPoint, m_Pos, m_End(), aAccuracy ); } diff --git a/eeschema/sch_bus_entry.h b/eeschema/sch_bus_entry.h index 5bf370397e..e59e773617 100644 --- a/eeschema/sch_bus_entry.h +++ b/eeschema/sch_bus_entry.h @@ -107,8 +107,12 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_entry_xpm; } + private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_collectors.cpp b/eeschema/sch_collectors.cpp new file mode 100644 index 0000000000..15e46c000b --- /dev/null +++ b/eeschema/sch_collectors.cpp @@ -0,0 +1,256 @@ +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 2004-2011 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "general.h" +#include "transform.h" +#include "sch_collectors.h" +#include "sch_component.h" +#include "sch_line.h" + + +const KICAD_T SCH_COLLECTOR::AllItems[] = { + SCH_MARKER_T, + SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_ENTRY_T, + SCH_LINE_T, + SCH_POLYLINE_T, + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + LIB_PIN_T, + SCH_SHEET_LABEL_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::AllItemsButPins[] = { + SCH_MARKER_T, + SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_ENTRY_T, + SCH_LINE_T, + SCH_POLYLINE_T, + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + SCH_SHEET_LABEL_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::EditableItems[] = { + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + SCH_SHEET_LABEL_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::MovableItems[] = { + SCH_MARKER_T, +// SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_ENTRY_T, +// SCH_LINE_T, + SCH_POLYLINE_T, + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + SCH_SHEET_LABEL_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::DraggableItems[] = { + SCH_JUNCTION_T, + SCH_BUS_ENTRY_T, + SCH_LINE_T, + SCH_POLYLINE_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_COMPONENT_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::RotatableItems[] = { + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_FIELD_T, + SCH_COMPONENT_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::ParentItems[] = { + SCH_MARKER_T, + SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_ENTRY_T, + SCH_LINE_T, + SCH_POLYLINE_T, + SCH_TEXT_T, + SCH_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_HIERARCHICAL_LABEL_T, + SCH_COMPONENT_T, + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::ComponentsOnly[] = { + SCH_COMPONENT_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::SheetsOnly[] = { + SCH_SHEET_T, + EOT +}; + + +const KICAD_T SCH_COLLECTOR::SheetsAndSheetLabels[] = { + SCH_SHEET_LABEL_T, + SCH_SHEET_T, + EOT +}; + + +SEARCH_RESULT SCH_COLLECTOR::Inspect( EDA_ITEM* aItem, const void* aTestData ) +{ + if( aItem->Type() != LIB_PIN_T && !aItem->HitTest( m_RefPos ) ) + return SEARCH_CONTINUE; + + // Pins have special hit testing requirements that are relative to their parent + // SCH_COMPONENT item. + if( aItem->Type() == LIB_PIN_T ) + { + wxCHECK_MSG( aTestData && ( (EDA_ITEM*) aTestData )->Type() == SCH_COMPONENT_T, + SEARCH_CONTINUE, wxT( "Cannot inspect invalid data. Bad programmer!" ) ); + + // Pin hit testing is relative to the components position and orientation in the + // schematic. The hit test position must be converted to library coordinates. + SCH_COMPONENT* component = (SCH_COMPONENT*) aTestData; + TRANSFORM transform = component->GetTransform().InverseTransform(); + wxPoint position = transform.TransformCoordinate( m_RefPos - component->m_Pos ); + + position.y *= -1; // Y axis polarity in schematic is inverted from library. + + if( !aItem->HitTest( position ) ) + return SEARCH_CONTINUE; + } + + Append( aItem ); + + return SEARCH_CONTINUE; +} + + +void SCH_COLLECTOR::Collect( SCH_ITEM* aItem, const KICAD_T aFilterList[], + const wxPoint& aPosition ) +{ + Empty(); // empty the collection just in case + + SetScanTypes( aFilterList ); + + // remember where the snapshot was taken from and pass refPos to the Inspect() function. + SetRefPos( aPosition ); + + EDA_ITEM::IterateForward( aItem, this, NULL, m_ScanTypes ); +} + + +bool SCH_COLLECTOR::IsCorner() const +{ + if( GetCount() != 2 ) + return false; + + if( (m_List[0]->Type() == SCH_LINE_T) && (m_List[1]->Type() == SCH_LINE_T) ) + return true; + + if( (m_List[0]->Type() == SCH_LINE_T) && (m_List[1]->Type() == SCH_BUS_ENTRY_T) ) + return true; + + if( (m_List[0]->Type() == SCH_BUS_ENTRY_T) && (m_List[1]->Type() == SCH_LINE_T) ) + return true; + + return false; +} + + +bool SCH_COLLECTOR::IsNode( bool aIncludePins ) const +{ + for( size_t i = 0; i < m_List.size(); i++ ) + { + SCH_ITEM* item = (SCH_ITEM*) m_List[ i ]; + KICAD_T type = item->Type(); + + if( type == SCH_JUNCTION_T ) + continue; + + if( type == SCH_LINE_T ) + { + if( item->GetLayer() != LAYER_WIRE ) + return false; + + continue; + } + + if( type == LIB_PIN_T ) + { + if( !aIncludePins ) + return false; + + continue; + } + + // Any other item types indicate that this collection is not a node. + return false; + } + + return true; +} diff --git a/eeschema/sch_collectors.h b/eeschema/sch_collectors.h new file mode 100644 index 0000000000..c0376717e9 --- /dev/null +++ b/eeschema/sch_collectors.h @@ -0,0 +1,154 @@ +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 2004-20011 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _SCH_COLLECTORS_H_ +#define _SCH_COLLECTORS_H_ + + +#include "class_collector.h" +#include "sch_item_struct.h" + + +/** + * Class SCH_COLLECTOR + */ +class SCH_COLLECTOR : public COLLECTOR +{ +public: + + /** + * A scan list for all schematic items. + */ + static const KICAD_T AllItems[]; + + /** + * A scan list for all editable schematic items. + */ + static const KICAD_T EditableItems[]; + + /** + * A scan list for all movable schematic items. + */ + static const KICAD_T MovableItems[]; + + /** + * A scan list for all draggable schematic items. + */ + static const KICAD_T DraggableItems[]; + + /** + * A scan list for all rotatable schematic items. + */ + static const KICAD_T RotatableItems[]; + + /** + * A scan list for only parent schematic items. + */ + static const KICAD_T ParentItems[]; + + /** + * A scan list for all schematic items except pins. + */ + static const KICAD_T AllItemsButPins[]; + + /** + * A scan list for schematic component items only. + */ + static const KICAD_T ComponentsOnly[]; + + /** + * A scan list for schematic sheet items only. + */ + static const KICAD_T SheetsOnly[]; + + /** + * A scan list for schematic sheet and sheet label items. + */ + static const KICAD_T SheetsAndSheetLabels[]; + + /** + * Constructor SCH_COLLECTOR + */ + SCH_COLLECTOR( const KICAD_T* aScanTypes = SCH_COLLECTOR::AllItems ) + { + SetScanTypes( aScanTypes ); + } + + /** + * Operator [] + * overloads COLLECTOR::operator[](int) to return a SCH_ITEM* instead of + * an EDA_ITEM* type. + * @param aIndex The index into the list. + * @return SCH_ITEM* at \a aIndex or NULL. + */ + SCH_ITEM* operator[]( int aIndex ) const + { + if( (unsigned)aIndex < (unsigned)GetCount() ) + return (SCH_ITEM*) m_List[ aIndex ]; + + return NULL; + } + + /** + * Function Inspect + * is the examining function within the INSPECTOR which is passed to the + * Iterate function. + * + * @param aItem An EDA_ITEM to examine. + * @param aTestData is not used in this class. + * @return SEARCH_RESULT #SEARCH_QUIT if the iterator is to stop the scan, + * else #SEARCH_CONTINUE; + */ + SEARCH_RESULT Inspect( EDA_ITEM* aItem, const void* aTestData = NULL ); + + /** + * Function Collect + * scans a SCH_ITEM using this class's Inspector method, which does the collection. + * @param aItem A SCH_ITEM to scan. + * @param aFilterList A list of #KICAD_T types with a terminating #EOT, that determines + * what is to be collected and the priority order of the resulting + * collection. + * @param aPosition A wxPoint to use in hit-testing. + */ + void Collect( SCH_ITEM* aItem, const KICAD_T aScanList[], const wxPoint& aPositiion ); + + /** + * Function IsCorner + * tests if the collected items forms as corner of two line segments. + * @return True if the collected items form a corner of two line segments. + */ + bool IsCorner() const; + + /** + * Function IsNode + * tests if the collected items form a node. + * + * @param aIncludePins Indicate if component pin items should be included in the test. + * @return True if the collected items form a node. + */ + bool IsNode( bool aIncludePins = true ) const; +}; + + +#endif // _SCH_COLLECTORS_H_ diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index 42e7259b90..62a4b7d54f 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -326,22 +326,6 @@ void SCH_COMPONENT::AddHierarchicalReference( const wxString& aPath, } -wxString SCH_COMPONENT::ReturnFieldName( int aFieldNdx ) const -{ - SCH_FIELD* field = GetField( aFieldNdx ); - - if( field ) - { - if( !field->m_Name.IsEmpty() ) - return field->m_Name; - else - return TEMPLATE_FIELDNAME::GetDefaultFieldName( aFieldNdx ); - } - - return wxEmptyString; -} - - wxString SCH_COMPONENT::GetPath( SCH_SHEET_PATH* sheet ) { wxString str; @@ -865,7 +849,7 @@ void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) { // for now, make it look like XML: NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() - << " ref=\"" << TO_UTF8( ReturnFieldName( 0 ) ) + << " ref=\"" << TO_UTF8( GetField( 0 )->GetName() ) << '"' << " chipName=\"" << TO_UTF8( m_ChipName ) << '"' << m_Pos << " layer=\"" << m_Layer @@ -879,7 +863,7 @@ void SCH_COMPONENT::Show( int nestLevel, std::ostream& os ) if( !value.IsEmpty() ) { NestedSpace( nestLevel + 1, os ) << "GetName() ) << '"' << " value=\"" << TO_UTF8( value ) << "\"/>\n"; } @@ -1405,18 +1389,7 @@ EDA_Rect SCH_COMPONENT::GetBodyBoundingBox() const EDA_Rect SCH_COMPONENT::GetBoundingBox() const { - EDA_Rect bBox = GetBodyBoundingBox(); - - // Include BoundingBoxes of fields if they are visible and not empty. - for( int ii = 0; ii < GetFieldCount(); ii++ ) - { - if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() ) - continue; - - bBox.Merge( GetField( ii )->GetBoundingBox() ); - } - - return bBox; + return GetBodyBoundingBox(); } @@ -1672,34 +1645,88 @@ LIB_DRAW_ITEM* SCH_COMPONENT::GetDrawItem( const wxPoint& aPosition, KICAD_T aTy } -bool SCH_COMPONENT::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_COMPONENT::GetSelectMenuText() const { - EDA_Rect bBox; + wxString tmp = _( "Component " ); - if( aFilter & FIELD_T ) + return tmp << m_ChipName << wxT( ", " ) << GetField( REFERENCE )->GetText(); +} + + +SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR* aInspector, const void* aTestData, + const KICAD_T aFilterTypes[] ) +{ + KICAD_T stype; + + for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p ) { - // Test the bounding boxes of fields if they are visible and not empty. - for( int ii = 0; ii < GetFieldCount(); ii++ ) + // If caller wants to inspect component type or and component children types. + if( stype == Type() ) { - if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() ) - continue; + if( SEARCH_QUIT == aInspector->Inspect( this, aTestData ) ) + return SEARCH_QUIT; + } + else if( stype == SCH_FIELD_T ) + { + // Test the bounding boxes of fields if they are visible and not empty. + for( int ii = 0; ii < GetFieldCount(); ii++ ) + { + if( SEARCH_QUIT == aInspector->Inspect( GetField( ii ), aTestData ) ) + return SEARCH_QUIT; + } + } + else if( stype == LIB_PIN_T ) + { + LIB_COMPONENT* component = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); - bBox = GetField( ii )->GetBoundingBox(); - bBox.Inflate( aAccuracy ); + if( component != NULL ) + { + LIB_PIN_LIST pins; - if( bBox.Contains( aPoint ) ) - return true; + component->GetPins( pins, m_unit, m_convert ); + + for( size_t i = 0; i < pins.size(); i++ ) + { + if( SEARCH_QUIT == aInspector->Inspect( pins[ i ], (void*) this ) ) + return SEARCH_QUIT; + } + } } } - if( aFilter & COMPONENT_T ) - { - bBox = GetBodyBoundingBox(); - bBox.Inflate( aAccuracy ); + return SEARCH_CONTINUE; +} - if( bBox.Contains( aPoint ) ) - return true; - } + +bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const +{ + if( Type() != aItem.Type() ) + return Type() < aItem.Type(); + + SCH_COMPONENT* component = (SCH_COMPONENT*) &aItem; + + EDA_Rect rect = GetBodyBoundingBox(); + + if( rect.GetArea() != component->GetBodyBoundingBox().GetArea() ) + return rect.GetArea() < component->GetBodyBoundingBox().GetArea(); + + if( m_Pos.x != component->m_Pos.x ) + return m_Pos.x < component->m_Pos.x; + + if( m_Pos.y != component->m_Pos.y ) + return m_Pos.y < component->m_Pos.y; + + return false; +} + + +bool SCH_COMPONENT::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ + EDA_Rect bBox = GetBodyBoundingBox(); + bBox.Inflate( aAccuracy ); + + if( bBox.Contains( aPoint ) ) + return true; return false; } diff --git a/eeschema/sch_component.h b/eeschema/sch_component.h index 87fee6dc15..307797001c 100644 --- a/eeschema/sch_component.h +++ b/eeschema/sch_component.h @@ -50,7 +50,7 @@ class SCH_COMPONENT : public SCH_ITEM wxArrayString m_PathsAndReferences; public: - wxPoint m_Pos; + wxPoint m_Pos; private: @@ -152,7 +152,7 @@ public: * ( a CMP_MIRROR_Y is find as a CMP_MIRROR_X + orientation 180, because * they are equivalent) */ - int GetOrientation(); + int GetOrientation(); /** * Function GetScreenCoord @@ -161,9 +161,9 @@ public: * @param aPoint The coordinates to transform. * @return The transformed point. */ - wxPoint GetScreenCoord( const wxPoint& aPoint ); + wxPoint GetScreenCoord( const wxPoint& aPoint ); - void DisplayInfo( EDA_DRAW_FRAME* frame ); + void DisplayInfo( EDA_DRAW_FRAME* frame ); /** * Function ClearAnnotation @@ -171,7 +171,7 @@ public: * @param aSheetPath: SCH_SHEET_PATH value: if NULL remove all annotations, * else remove annotation relative to this sheetpath */ - void ClearAnnotation( SCH_SHEET_PATH* aSheetPath ); + void ClearAnnotation( SCH_SHEET_PATH* aSheetPath ); /** * Function SetTimeStamp @@ -179,7 +179,7 @@ public: * @see m_PathsAndReferences * @param aNewTimeStamp = new time stamp */ - void SetTimeStamp( long aNewTimeStamp ); + void SetTimeStamp( long aNewTimeStamp ); /** * Function GetBoundingBox @@ -189,17 +189,10 @@ public: * few counts. * @return The bounding rectangle of the component. */ - EDA_Rect GetBoundingBox() const; + EDA_Rect GetBoundingBox() const; //---------------------------------------------------------------- - /** - * Function ReturnFieldName - * returns the Field name given a field index like (REFERENCE, VALUE ..) - * @return wxString - the field name or wxEmptyString if invalid field index. - */ - wxString ReturnFieldName( int aFieldNdx ) const; - /** * Function GetField * returns a field. @@ -261,12 +254,12 @@ public: int Color, bool DrawPinText ); - void SwapData( SCH_COMPONENT* copyitem ); + void SwapData( SCH_COMPONENT* copyitem ); - void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); + void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); // returns a unique ID, in the form of a path. - wxString GetPath( SCH_SHEET_PATH* sheet ); + wxString GetPath( SCH_SHEET_PATH* sheet ); /** * Function GetRef @@ -275,7 +268,7 @@ public: const wxString GetRef( SCH_SHEET_PATH* sheet ); // Set the reference, for the given sheet path. - void SetRef( SCH_SHEET_PATH* sheet, const wxString& ref ); + void SetRef( SCH_SHEET_PATH* sheet, const wxString& ref ); /** * Function AddHierarchicalReference @@ -285,15 +278,15 @@ public: * @param aRef :local reference like C45, R56 * @param aMulti Part selection, used in multi part per package (0 or 1 for non multi) */ - void AddHierarchicalReference( const wxString& aPath, - const wxString& aRef, - int aMulti ); + void AddHierarchicalReference( const wxString& aPath, + const wxString& aRef, + int aMulti ); // returns the unit selection, for the given sheet path. - int GetUnitSelection( SCH_SHEET_PATH* aSheet ); + 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 ); // Geometric transforms (used in block operations): @@ -353,6 +346,9 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, + const KICAD_T scanTypes[] ); + /** * Function GetDrawItem(). * Return the component library item at \a aPosition that is part of this component. @@ -362,6 +358,13 @@ public: * @return A pointer to the component library object if found, otherwise NULL. */ LIB_DRAW_ITEM* GetDrawItem( const wxPoint& aPosition, KICAD_T aType = TYPE_NOT_INIT ); + + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_component_xpm; } + + virtual bool operator <( const SCH_ITEM& aItem ) const; + #if defined(DEBUG) /** @@ -371,12 +374,12 @@ public: * of nesting of this object within the overall tree. * @param os The ostream& to output to. */ - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool doIsConnected( const wxPoint& aPosition ) const; virtual EDA_ITEM* doClone() const; diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index f8bc48fc06..50e34aa06a 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -447,10 +447,42 @@ void SCH_FIELD::Rotate( wxPoint rotationPoint ) } -bool SCH_FIELD::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_FIELD::GetSelectMenuText() const +{ + wxString tmp = _( "Field " ); + + return tmp + GetName(); +} + + +wxString SCH_FIELD::GetName() const +{ + if( !m_Name.IsEmpty() ) + return m_Name; + else + return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_FieldId ); +} + + +const char** SCH_FIELD::GetMenuImage() const +{ + if( m_FieldId == REFERENCE ) + return (const char**) edit_comp_ref_xpm; + + if( m_FieldId == VALUE ) + return (const char**) edit_comp_value_xpm; + + if( m_FieldId == FOOTPRINT ) + return (const char**) edit_comp_footprint_xpm; + + return (const char**) edit_text_xpm; +} + + +bool SCH_FIELD::doHitTest( const wxPoint& aPoint, int aAccuracy ) const { // Do not hit test hidden or empty fields. - if( !(aFilter & FIELD_T) || !IsVisible() || IsVoid() ) + if( !IsVisible() || IsVoid() ) return false; EDA_Rect rect = GetBoundingBox(); @@ -464,7 +496,7 @@ bool SCH_FIELD::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aF bool SCH_FIELD::doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const { // Do not hit test hidden fields. - if( !IsVisible() ) + if( !IsVisible() || IsVoid() ) return false; EDA_Rect rect = aRect; diff --git a/eeschema/sch_field.h b/eeschema/sch_field.h index 4292d675b2..9aa68399c7 100644 --- a/eeschema/sch_field.h +++ b/eeschema/sch_field.h @@ -50,6 +50,16 @@ public: return wxT( "SCH_FIELD" ); } + /** + * Function GetName + * returns the field name. If the field name is emply, the default field name is + * returned. Field names are VALUE, REFERENCE, etc. + * @return The name of the field. + */ + wxString GetName() const; + + int GetId() const { return m_FieldId; } + void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); EDA_Rect GetBoundingBox() const; @@ -161,10 +171,14 @@ public: * @return True if this field text matches the search criteria. */ virtual bool Matches( wxFindReplaceData& aSearchData, - void* aAuxData, wxPoint * aFindLocation ); + void* aAuxData, wxPoint* aFindLocation ); + + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const; private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_junction.cpp b/eeschema/sch_junction.cpp index bb1aeab1c2..04a05e64a3 100644 --- a/eeschema/sch_junction.cpp +++ b/eeschema/sch_junction.cpp @@ -177,11 +177,8 @@ void SCH_JUNCTION::Show( int nestLevel, std::ostream& os ) #endif -bool SCH_JUNCTION::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +bool SCH_JUNCTION::doHitTest( const wxPoint& aPoint, int aAccuracy ) const { - if( !( aFilter & JUNCTION_T ) ) - return false; - EDA_Rect rect = GetBoundingBox(); rect.Inflate( aAccuracy ); diff --git a/eeschema/sch_junction.h b/eeschema/sch_junction.h index b05e9f0aaa..8ebdefd4d6 100644 --- a/eeschema/sch_junction.h +++ b/eeschema/sch_junction.h @@ -91,12 +91,16 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual wxString GetSelectMenuText() const { return wxString( _( "Junction" ) ); } + + virtual const char** GetMenuImage() const { return (const char**) add_junction_xpm; } + #if defined(DEBUG) - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool doIsConnected( const wxPoint& aPosition ) const; virtual EDA_ITEM* doClone() const; diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp index e144820f81..060adbdf0b 100644 --- a/eeschema/sch_line.cpp +++ b/eeschema/sch_line.cpp @@ -108,6 +108,12 @@ EDA_Rect SCH_LINE::GetBoundingBox() const } +double SCH_LINE::GetLength() const +{ + return GetLineLength( m_Start, m_End ); +} + + bool SCH_LINE::Save( FILE* aFile ) const { bool success = true; @@ -411,31 +417,75 @@ void SCH_LINE::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_LINE::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_LINE::GetSelectMenuText() const { - if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) ) - return false; + wxString menuText; - if( ( ( aFilter & DRAW_ITEM_T ) && ( m_Layer == LAYER_NOTES ) ) - || ( ( aFilter & WIRE_T ) && ( m_Layer == LAYER_WIRE ) ) - || ( ( aFilter & BUS_T ) && ( m_Layer == LAYER_BUS ) ) ) + switch( m_Layer ) { - if( !TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ) ) - return false; + case LAYER_NOTES: + menuText = _( "Graphic Line " ); + break; - if( ( aFilter & EXCLUDE_ENDPOINTS_T ) && IsEndPoint( aPoint ) ) - return false; + case LAYER_WIRE: + menuText = _( "Wire " ); + break; - if( ( aFilter & ENDPOINTS_ONLY_T ) && !IsEndPoint( aPoint ) ) - return false; + case LAYER_BUS: + menuText = _( "Bus " ); + break; - return true; + default: + menuText = _( "Line on Unkown Layer " ); } + menuText << wxT( "from (" ) << CoordinateToString( m_Start.x, EESCHEMA_INTERNAL_UNIT ) + << wxT( "," ) << CoordinateToString( m_Start.y, EESCHEMA_INTERNAL_UNIT ) + << wxT( ")" ); + menuText << wxT( " to (" ) << CoordinateToString( m_End.x, EESCHEMA_INTERNAL_UNIT ) + << wxT( "," ) << CoordinateToString( m_End.y, EESCHEMA_INTERNAL_UNIT ) << wxT( ")" ); + + return menuText; +} + + +const char** SCH_LINE::GetMenuImage() const +{ + if( m_Layer == LAYER_NOTES ) + return (const char**) add_dashed_line_xpm; + else if( m_Layer == LAYER_WIRE ) + return (const char**) add_line_xpm; + + return (const char**) add_bus_xpm; +} + + +bool SCH_LINE::operator <( const SCH_ITEM& aItem ) const +{ + if( Type() != aItem.Type() ) + return Type() < aItem.Type(); + + SCH_LINE* line = (SCH_LINE*) &aItem; + + if( GetLength() != line->GetLength() ) + return GetLength() < line->GetLength(); + + if( m_Start.x != line->m_Start.x ) + return m_Start.x < line->m_Start.x; + + if( m_Start.y != line->m_Start.y ) + return m_Start.y < line->m_Start.y; + return false; } +bool SCH_LINE::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ + return TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ); +} + + bool SCH_LINE::doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const { EDA_Rect rect = aRect; diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h index aebfe90836..97ee517469 100644 --- a/eeschema/sch_line.h +++ b/eeschema/sch_line.h @@ -54,6 +54,12 @@ public: */ EDA_Rect GetBoundingBox() const; + /** + * Function GetLength + * @return The length of the line segment. + */ + double GetLength() const; + virtual void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, int aDrawMode, int aColor = -1 ); @@ -127,12 +133,18 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const; + + virtual bool operator <( const SCH_ITEM& aItem ) const; + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const; #endif private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool doIsConnected( const wxPoint& aPosition ) const; virtual EDA_ITEM* doClone() const; diff --git a/eeschema/sch_marker.cpp b/eeschema/sch_marker.cpp index 64aca43d30..a82dddb931 100644 --- a/eeschema/sch_marker.cpp +++ b/eeschema/sch_marker.cpp @@ -195,11 +195,8 @@ bool SCH_MARKER::IsSelectStateChanged( const wxRect& aRect ) } -bool SCH_MARKER::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +bool SCH_MARKER::doHitTest( const wxPoint& aPoint, int aAccuracy ) const { - if( !( aFilter & MARKER_T ) ) - return false; - return HitTestMarker( aPoint ); } diff --git a/eeschema/sch_marker.h b/eeschema/sch_marker.h index 21ebe94e6f..33fa400d87 100644 --- a/eeschema/sch_marker.h +++ b/eeschema/sch_marker.h @@ -93,16 +93,20 @@ public: * * @param aFrame - Top window that owns the message panel. */ - void DisplayInfo( EDA_DRAW_FRAME* aFrame ); + void DisplayInfo( EDA_DRAW_FRAME* aFrame ); virtual bool IsSelectStateChanged( const wxRect& aRect ); + virtual wxString GetSelectMenuText() const { return wxString( _( "ERC Marker" ) ); } + + virtual const char** GetMenuImage() const { return (const char**) erc_xpm; } + #if defined(DEBUG) - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_no_connect.cpp b/eeschema/sch_no_connect.cpp index a650123106..06d8d0d4b4 100644 --- a/eeschema/sch_no_connect.cpp +++ b/eeschema/sch_no_connect.cpp @@ -157,11 +157,8 @@ bool SCH_NO_CONNECT::doIsConnected( const wxPoint& aPosition ) const return m_Pos == aPosition; } -bool SCH_NO_CONNECT::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +bool SCH_NO_CONNECT::doHitTest( const wxPoint& aPoint, int aAccuracy ) const { - if( !( aFilter & NO_CONNECT_T ) ) - return false; - int delta = ( ( m_Size.x + g_DrawDefaultLineThickness ) / 2 ) + aAccuracy; wxPoint dist = aPoint - m_Pos; diff --git a/eeschema/sch_no_connect.h b/eeschema/sch_no_connect.h index 6d322ebde9..4a718f3678 100644 --- a/eeschema/sch_no_connect.h +++ b/eeschema/sch_no_connect.h @@ -94,9 +94,13 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual wxString GetSelectMenuText() const { return wxString( _( "No Connect" ) ); } + + virtual const char** GetMenuImage() const { return (const char**) noconn_button; } + private: virtual bool doIsConnected( const wxPoint& aPosition ) const; - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_polyline.cpp b/eeschema/sch_polyline.cpp index 944090cb1f..75821a12fe 100644 --- a/eeschema/sch_polyline.cpp +++ b/eeschema/sch_polyline.cpp @@ -205,11 +205,47 @@ void SCH_POLYLINE::Rotate( wxPoint rotationPoint ) } -bool SCH_POLYLINE::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_POLYLINE::GetSelectMenuText() const { - if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) ) - return false; + wxString menuText; + switch( m_Layer ) + { + case LAYER_NOTES: + menuText = _( "Graphic Polyline " ); + break; + + case LAYER_WIRE: + menuText = _( "Polyline Wire " ); + break; + + case LAYER_BUS: + menuText = _( "Polyline Bus " ); + break; + + default: + menuText = _( "Polyline on Unkown Layer " ); + } + + menuText += wxString::Format( _( "with %d Points" ), m_PolyPoints.size() ); + + return menuText; +} + + +const char** SCH_POLYLINE::GetMenuImage() const +{ + if( m_Layer == LAYER_NOTES ) + return (const char**) add_dashed_line_xpm; + else if( m_Layer == LAYER_WIRE ) + return (const char**) add_line_xpm; + + return (const char**) add_bus_xpm; +} + + +bool SCH_POLYLINE::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ for( size_t i = 0; i < m_PolyPoints.size() - 1; i++ ) { if( TestSegmentHit( aPoint, m_PolyPoints[i], m_PolyPoints[i + 1], aAccuracy ) ) diff --git a/eeschema/sch_polyline.h b/eeschema/sch_polyline.h index 013ad9a591..b7dd50446e 100644 --- a/eeschema/sch_polyline.h +++ b/eeschema/sch_polyline.h @@ -94,8 +94,12 @@ public: virtual void Rotate( wxPoint rotationPoint ); + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const; + private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index ab3ed1fcbc..c9c6f3db44 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -21,6 +21,8 @@ #include "sch_no_connect.h" #include "sch_sheet.h" #include "sch_component.h" +#include "sch_collectors.h" +#include "sch_text.h" #include @@ -117,9 +119,6 @@ void SCH_SCREEN::FreeDrawList() } -/* If found in GetDrawItems(), remove DrawStruct from GetDrawItems(). - * DrawStruct is not deleted or modified - */ void SCH_SCREEN::RemoveFromDrawList( SCH_ITEM * DrawStruct ) { if( DrawStruct == GetDrawItems() ) @@ -210,56 +209,36 @@ void SCH_SCREEN::AddToDrawList( SCH_ITEM* st ) } -int SCH_SCREEN::GetItems( const wxPoint& aPosition, SCH_ITEMS& aItemList ) const +SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType ) const { for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) { - if( item->HitTest( aPosition ) ) - aItemList.push_back( item ); - } + if( item->HitTest( aPosition, aAccuracy ) && (aType == NOT_USED) ) + return item; - return aItemList.size(); -} - - -int SCH_SCREEN::GetItems( const wxPoint& aPosition, PICKED_ITEMS_LIST& aItemList, - int aAccuracy, int aFilter ) const -{ - for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) - { - if( item->HitTest( aPosition, aAccuracy, (SCH_FILTER_T) aFilter ) ) + if( (aType == SCH_FIELD_T) && (item->Type() == SCH_COMPONENT_T) ) { - ITEM_PICKER picker( (EDA_ITEM*) item ); - aItemList.PushItem( picker ); - } - } + SCH_COMPONENT* component = (SCH_COMPONENT*) item; - return aItemList.GetCount(); -} - - -SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, int aFilter ) const -{ - for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) - { - if( item->HitTest( aPosition, aAccuracy, (SCH_FILTER_T) aFilter ) ) - { - if( (aFilter & FIELD_T) && (item->Type() == SCH_COMPONENT_T) ) + for( int i = REFERENCE; i < component->GetFieldCount(); i++ ) { - SCH_COMPONENT* component = (SCH_COMPONENT*) item; + SCH_FIELD* field = component->GetField( i ); - for( int i = REFERENCE; i < component->GetFieldCount(); i++ ) - { - SCH_FIELD* field = component->GetField( i ); - - if( field->HitTest( aPosition, aAccuracy ) ) - return (SCH_ITEM*) field; - } - - if( !(aFilter & COMPONENT_T) ) - return NULL; + if( field->HitTest( aPosition, aAccuracy ) ) + return (SCH_ITEM*) field; } + } + else if( (aType == SCH_SHEET_LABEL_T) && (item->Type() == SCH_SHEET_T) ) + { + SCH_SHEET* sheet = (SCH_SHEET*)item; + SCH_SHEET_PIN* label = sheet->GetLabel( aPosition ); + + if( label ) + return (SCH_ITEM*) label; + } + else if( (item->Type() == aType) && item->HitTest( aPosition, aAccuracy ) ) + { return item; } } @@ -374,14 +353,14 @@ void SCH_SCREEN::MarkConnections( SCH_LINE* aSegment ) } -bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition ) const +bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition ) { - if( GetItem( aPosition, 0, JUNCTION_T ) ) + if( GetItem( aPosition, 0, SCH_JUNCTION_T ) ) return false; - if( GetItem( aPosition, 0, WIRE_T | EXCLUDE_ENDPOINTS_T ) ) + if( GetWire( aPosition, 0, EXCLUDE_END_POINTS_T ) ) { - if( GetItem( aPosition, 0, WIRE_T | ENDPOINTS_ONLY_T ) ) + if( GetWire( aPosition, 0, END_POINTS_ONLY_T ) ) return true; if( GetPin( aPosition, NULL, true ) ) @@ -392,10 +371,74 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition ) const } -/* Routine cleaning: - * - Includes segments or buses aligned in only 1 segment - * - Detects identical objects superimposed - */ +bool SCH_SCREEN::IsTerminalPoint( const wxPoint& aPosition, int aLayer ) +{ + wxCHECK_MSG( aLayer == LAYER_NOTES || aLayer == LAYER_BUS || aLayer == LAYER_WIRE, false, + wxT( "Invalid layer type passed to SCH_SCREEN::IsTerminalPoint()." ) ); + + SCH_SHEET_PIN* label; + SCH_TEXT* text; + + switch( aLayer ) + { + case LAYER_BUS: + + if( GetBus( aPosition ) ) + return true; + + label = GetSheetLabel( aPosition ); + + if( label && IsBusLabel( label->m_Text ) && label->IsConnected( aPosition ) ) + return true; + + text = GetLabel( aPosition ); + + if( text && IsBusLabel( text->GetText() ) && text->IsConnected( aPosition ) + && (text->Type() != SCH_LABEL_T) ) + return true; + + break; + + case LAYER_NOTES: + + if( GetLine( aPosition ) ) + return true; + + break; + + case LAYER_WIRE: + if( GetItem( aPosition, MAX( g_DrawDefaultLineThickness, 3 ), SCH_BUS_ENTRY_T ) ) + return true; + + if( GetItem( aPosition, MAX( g_DrawDefaultLineThickness, 3 ), SCH_JUNCTION_T ) ) + return true; + + if( GetPin( aPosition, NULL, true ) ) + return true; + + if( GetWire( aPosition ) ) + return true; + + text = GetLabel( aPosition ); + + if( text && text->IsConnected( aPosition ) && !IsBusLabel( text->GetText() ) ) + return true; + + label = GetSheetLabel( aPosition ); + + if( label && label->IsConnected( aPosition ) && !IsBusLabel( label->m_Text ) ) + return true; + + break; + + default: + break; + } + + return false; +} + + bool SCH_SCREEN::SchematicCleanUp( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ) { SCH_ITEM* DrawList, * TstDrawList; @@ -445,12 +488,6 @@ bool SCH_SCREEN::SchematicCleanUp( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ) } -/** - * Function Save - * writes the data structures for this object out to a FILE in "*.sch" format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ bool SCH_SCREEN::Save( FILE* aFile ) const { // Creates header @@ -572,7 +609,12 @@ LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponen } if( pin && aEndPointOnly && ( component->GetPinPhysicalPosition( pin ) != aPosition ) ) + { + wxPoint endpt = component->GetPinPhysicalPosition( pin ); + wxLogDebug( wxString::Format( wxT( "Pin end point at (%d, %d) not (%d, %d )." ), + endpt.x, endpt.y, aPosition.x, aPosition.y ) ); pin = NULL; + } if( aComponent ) *aComponent = component; @@ -633,7 +675,7 @@ void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath ) } -void SCH_SCREEN::GetHierarchicalItems( std::vector & aItems ) +void SCH_SCREEN::GetHierarchicalItems( EDA_ITEMS& aItems ) { SCH_ITEM* item = GetDrawItems(); @@ -810,16 +852,15 @@ bool SCH_SCREEN::BreakSegment( const wxPoint& aPoint ) SCH_LINE* segment; SCH_LINE* newSegment; bool brokenSegments = false; - SCH_FILTER_T filter = ( SCH_FILTER_T ) ( WIRE_T | BUS_T | EXCLUDE_ENDPOINTS_T ); for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) { - if( item->Type() != SCH_LINE_T ) + if( (item->Type() != SCH_LINE_T) || (item->GetLayer() == LAYER_NOTES) ) continue; segment = (SCH_LINE*) item; - if( !segment->HitTest( aPoint, 0, filter ) ) + if( !segment->HitTest( aPoint, 0 ) || segment->IsEndPoint( aPoint ) ) continue; // Break the segment at aPoint and create a new segment. @@ -862,6 +903,95 @@ bool SCH_SCREEN::BreakSegmentsOnJunctions() } +int SCH_SCREEN::GetNode( const wxPoint& aPosition, EDA_ITEMS& aList ) +{ + for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) + { + if( item->Type() == SCH_LINE_T && item->HitTest( aPosition ) + && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) ) + { + aList.push_back( item ); + } + else if( item->Type() == SCH_JUNCTION_T && item->HitTest( aPosition ) ) + { + aList.push_back( item ); + } + } + + return (int) aList.size(); +} + + +SCH_LINE* SCH_SCREEN::GetWireOrBus( const wxPoint& aPosition ) +{ + for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) + { + if( (item->Type() == SCH_LINE_T) && item->HitTest( aPosition ) + && (item->GetLayer() == LAYER_BUS || item->GetLayer() == LAYER_WIRE) ) + { + return (SCH_LINE*) item; + } + } + + return NULL; +} + + +SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer, + SCH_LINE_TEST_T aSearchType ) +{ + for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) + { + if( item->Type() != SCH_LINE_T ) + continue; + + if( item->GetLayer() != aLayer ) + continue; + + if( !item->HitTest( aPosition, aAccuracy ) ) + continue; + + switch( aSearchType ) + { + case ENTIRE_LENGTH_T: + return (SCH_LINE*) item; + + case EXCLUDE_END_POINTS_T: + if( !( (SCH_LINE*) item )->IsEndPoint( aPosition ) ) + return (SCH_LINE*) item; + break; + + case END_POINTS_ONLY_T: + if( ( (SCH_LINE*) item )->IsEndPoint( aPosition ) ) + return (SCH_LINE*) item; + } + } + + return NULL; +} + + +SCH_TEXT* SCH_SCREEN::GetLabel( const wxPoint& aPosition, int aAccuracy ) +{ + for( SCH_ITEM* item = GetDrawItems(); item != NULL; item = item->Next() ) + { + switch( item->Type() ) + { + case SCH_LABEL_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIERARCHICAL_LABEL_T: + if( item->HitTest( aPosition, aAccuracy ) ) + return (SCH_TEXT*) item; + + default: + ; + } + } + + return NULL; +} + + /******************************************************************/ /* Class SCH_SCREENS to handle the list of screens in a hierarchy */ /******************************************************************/ @@ -870,7 +1000,7 @@ bool SCH_SCREEN::BreakSegmentsOnJunctions() * Function SortByTimeStamp * sorts a list of schematic items by time stamp and type. */ -static bool SortByTimeStamp( const SCH_ITEM* item1, const SCH_ITEM* item2 ) +static bool SortByTimeStamp( const EDA_ITEM* item1, const EDA_ITEM* item2 ) { int ii = item1->m_TimeStamp - item2->m_TimeStamp; @@ -989,8 +1119,8 @@ void SCH_SCREENS::SchematicCleanUp() int SCH_SCREENS::ReplaceDuplicateTimeStamps() { - std::vector items; - SCH_ITEM* item; + EDA_ITEMS items; + SCH_ITEM* item; for( size_t i = 0; i < m_screens.size(); i++ ) m_screens[i]->GetHierarchicalItems( items ); @@ -1004,9 +1134,10 @@ int SCH_SCREENS::ReplaceDuplicateTimeStamps() for( size_t ii = 0; ii < items.size() - 1; ii++ ) { - item = items[ii]; + item = (SCH_ITEM*)items[ii]; + + SCH_ITEM* nextItem = (SCH_ITEM*)items[ii + 1]; - SCH_ITEM* nextItem = items[ii + 1]; if( item->m_TimeStamp == nextItem->m_TimeStamp ) { count++; diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 1319143cb2..4cb6a4815b 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -965,11 +965,42 @@ void SCH_SHEET::GetConnectionPoints( vector< wxPoint >& aPoints ) const } -bool SCH_SHEET::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +SEARCH_RESULT SCH_SHEET::Visit( INSPECTOR* aInspector, const void* aTestData, + const KICAD_T aFilterTypes[] ) { - if( !( aFilter & SHEET_T ) ) - return false; + KICAD_T stype; + for( const KICAD_T* p = aFilterTypes; (stype = *p) != EOT; ++p ) + { + // If caller wants to inspect my type + if( stype == Type() ) + { + if( SEARCH_QUIT == aInspector->Inspect( this, aTestData ) ) + return SEARCH_QUIT; + } + else if( stype == SCH_SHEET_LABEL_T ) + { + // Test the bounding boxes of sheet labels. + for( size_t i = 0; i < m_labels.size(); i++ ) + { + if( SEARCH_QUIT == aInspector->Inspect( &m_labels[ i ], aTestData ) ) + return SEARCH_QUIT; + } + } + } + + return SEARCH_CONTINUE; +} + + +wxString SCH_SHEET::GetSelectMenuText() const +{ + return wxString( _( "Hierarchical Sheet " ) ) + m_SheetName; +} + + +bool SCH_SHEET::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ EDA_Rect rect = GetBoundingBox(); rect.Inflate( aAccuracy ); diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index 4c42c518bf..7170f59add 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -49,6 +49,8 @@ private: virtual EDA_ITEM* doClone() const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; + public: SCH_SHEET_PIN( SCH_SHEET* parent, const wxPoint& pos = wxPoint( 0, 0 ), @@ -65,11 +67,11 @@ public: bool operator ==( const SCH_SHEET_PIN* aPin ) const; - virtual void Draw( EDA_DRAW_PANEL* aPanel, - wxDC* aDC, - const wxPoint& aOffset, - int aDraw_mode, - int aColor = -1 ); + virtual void Draw( EDA_DRAW_PANEL* aPanel, + wxDC* aDC, + const wxPoint& aOffset, + int aDraw_mode, + int aColor = -1 ); /** * Function CreateGraphicShape (virual) @@ -77,8 +79,7 @@ public: * @param aCorner_list = a buffer to fill with polygon corners coordinates * @param aPos = Position of the shape */ - virtual void CreateGraphicShape( std::vector & aCorner_list, - const wxPoint& aPos ); + virtual void CreateGraphicShape( std::vector & aCorner_list, const wxPoint& aPos ); void SwapData( SCH_SHEET_PIN* copyitem ); @@ -94,16 +95,16 @@ public: * * @param aNumber - New sheet number label. */ - void SetNumber( int aNumber ); - void SetEdge( int aEdge ); - int GetEdge(); + void SetNumber( int aNumber ); + void SetEdge( int aEdge ); + int GetEdge(); /** * Function ConstraintOnEdge * is used to adjust label position to egde based on proximity to vertical / horizontal edge * of the parent sheet. */ - void ConstraintOnEdge( wxPoint Pos ); + void ConstraintOnEdge( wxPoint Pos ); /** * Get the parent sheet object of this sheet pin. @@ -113,7 +114,7 @@ public: */ SCH_SHEET* GetParent() const { return (SCH_SHEET*) m_Parent; } - void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); + void Place( SCH_EDIT_FRAME* frame, wxDC* DC ); /** * Function Save @@ -122,7 +123,7 @@ public: * @param aFile The FILE to write to. * @return bool - true if success writing else false. */ - bool Save( FILE* aFile ) const; + bool Save( FILE* aFile ) const; /** * Load schematic sheet hierarchical lable from \a aLine in a .sch file. @@ -137,7 +138,7 @@ public: #if defined(DEBUG) // comment inherited by Doxygen from Base_Struct - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif @@ -184,6 +185,10 @@ public: virtual void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ); virtual bool IsConnectable() const { return true; } + + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_hierar_pin_xpm; } }; @@ -486,13 +491,13 @@ public: * Function GetSheetNamePosition * @return the position of the anchor of sheet name text */ - wxPoint GetSheetNamePosition (); + wxPoint GetSheetNamePosition(); /** * Function GetFileNamePosition * @return the position of the anchor of filename text */ - wxPoint GetFileNamePosition (); + wxPoint GetFileNamePosition(); virtual void GetEndPoints( std::vector & aItemList ); @@ -506,10 +511,20 @@ public: virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; + virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, + const KICAD_T scanTypes[] ); + + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const + { + return (const char**) add_hierarchical_subsheet_xpm; + } + #if defined(DEBUG) // comment inherited by Doxygen from Base_Struct - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif @@ -525,7 +540,7 @@ protected: void renumberLabels(); private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/sch_sheet_pin.cpp b/eeschema/sch_sheet_pin.cpp index 9d04cf3d1b..005b3b9851 100644 --- a/eeschema/sch_sheet_pin.cpp +++ b/eeschema/sch_sheet_pin.cpp @@ -459,6 +459,22 @@ void SCH_SHEET_PIN::GetEndPoints( std::vector & aItemList ) } +wxString SCH_SHEET_PIN::GetSelectMenuText() const +{ + return wxString( _( "Hierarchical Sheet Label " ) ) + GetText(); +} + + +bool SCH_SHEET_PIN::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ + EDA_Rect rect = GetBoundingBox(); + + rect.Inflate( aAccuracy ); + + return rect.Contains( aPoint ); +} + + #if defined(DEBUG) void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os ) diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index f49281454e..c19852f6e8 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -620,11 +620,20 @@ EDA_Rect SCH_TEXT::GetBoundingBox() const } -bool SCH_TEXT::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_TEXT::GetSelectMenuText() const { - if( !( aFilter & TEXT_T ) ) - return false; + wxString tmp = GetText(); + tmp.Replace( wxT( "\n" ), wxT( " " ) ); + tmp.Replace( wxT( "\r" ), wxT( " " ) ); + tmp.Replace( wxT( "\t" ), wxT( " " ) ); + tmp =( tmp.Length() > 15 ) ? tmp.Left( 12 ) + wxT( "..." ) : tmp; + return wxString( _( "Graphic Text " ) ) + tmp; +} + + +bool SCH_TEXT::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ return TextHitTest( aPoint, aAccuracy ); } @@ -846,11 +855,16 @@ EDA_Rect SCH_LABEL::GetBoundingBox() const } -bool SCH_LABEL::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_LABEL::GetSelectMenuText() const { - if( !( aFilter & LABEL_T ) ) - return false; + wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText(); + return wxString( _( "Label " ) ) + tmp; +} + + +bool SCH_LABEL::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ return TextHitTest( aPoint, aAccuracy ); } @@ -1272,11 +1286,16 @@ EDA_Rect SCH_GLOBALLABEL::GetBoundingBox() const } -bool SCH_GLOBALLABEL::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_GLOBALLABEL::GetSelectMenuText() const { - if( !( aFilter & LABEL_T ) ) - return false; + wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText(); + return wxString( _( "Global Label " ) ) + tmp; +} + + +bool SCH_GLOBALLABEL::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ return TextHitTest( aPoint, aAccuracy ); } @@ -1622,10 +1641,15 @@ void SCH_HIERLABEL::Rotate( wxPoint rotationPoint ) } -bool SCH_HIERLABEL::doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const +wxString SCH_HIERLABEL::GetSelectMenuText() const { - if( !( aFilter & LABEL_T ) ) - return false; + wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText(); + return wxString( _( "Hierarchical Label " ) ) + tmp; +} + + +bool SCH_HIERLABEL::doHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ return TextHitTest( aPoint, aAccuracy ); } diff --git a/eeschema/sch_text.h b/eeschema/sch_text.h index 5e0bf2ce3d..89bbe43cee 100644 --- a/eeschema/sch_text.h +++ b/eeschema/sch_text.h @@ -202,12 +202,16 @@ public: virtual bool CanIncrementLabel() const { return true; } + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_text_xpm; } + #if defined(DEBUG) - void Show( int nestLevel, std::ostream& os ); + void Show( int nestLevel, std::ostream& os ); #endif private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool doHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual EDA_ITEM* doClone() const; }; @@ -246,7 +250,7 @@ public: * position of 0 * 3 = bottom . This can be seen as the mirrored position of up */ - virtual void SetOrientation( int aSchematicOrientation ); + virtual void SetOrientation( int aSchematicOrientation ); /** * Function GetSchematicTextOffset (virtual) @@ -258,9 +262,9 @@ public: */ virtual wxPoint GetSchematicTextOffset(); - virtual void Mirror_X( int aXaxis_position ); + virtual void Mirror_X( int aXaxis_position ); - virtual void Rotate( wxPoint rotationPoint ); + virtual void Rotate( wxPoint rotationPoint ); /** * Function GetBoundingBox @@ -269,7 +273,7 @@ public: * object, and the units should be in the pcb or schematic coordinate system. * It is OK to overestimate the size by a few counts. */ - EDA_Rect GetBoundingBox() const; + EDA_Rect GetBoundingBox() const; /** * Function Save @@ -278,7 +282,7 @@ public: * @param aFile The FILE to write to. * @return bool - true if success writing else false. */ - bool Save( FILE* aFile ) const; + bool Save( FILE* aFile ) const; /** * Load schematic label entry from \a aLine in a .sch file. @@ -292,8 +296,13 @@ public: virtual bool IsConnectable() const { return true; } + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_line_label_xpm; } + private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool doIsConnected( const wxPoint& aPosition ) const { return m_Pos == aPosition; } virtual EDA_ITEM* doClone() const; }; @@ -331,7 +340,7 @@ public: * position of 0 * 3 = bottom . This can be seen as the mirrored position of up */ - virtual void SetOrientation( int aSchematicOrientation ); + virtual void SetOrientation( int aSchematicOrientation ); /** * Function GetSchematicTextOffset (virtual) @@ -350,7 +359,7 @@ public: * @param aFile The FILE to write to. * @return bool - true if success writing else false. */ - bool Save( FILE* aFile ) const; + bool Save( FILE* aFile ) const; /** * Load schematic global label entry from \a aLine in a .sch file. @@ -369,7 +378,7 @@ public: * object, and the units should be in the pcb or schematic coordinate system. * It is OK to overestimate the size by a few counts. */ - EDA_Rect GetBoundingBox() const; + EDA_Rect GetBoundingBox() const; /** * Function CreateGraphicShape (virual) @@ -377,22 +386,27 @@ public: * @param aCorner_list = a buffer to fill with polygon corners coordinates * @param aPos = Position of the shape */ - virtual void CreateGraphicShape( std::vector & aCorner_list, const wxPoint& aPos ); + virtual void CreateGraphicShape( std::vector & aCorner_list, const wxPoint& aPos ); /** 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 ); + virtual void Mirror_Y( int aYaxis_position ); - virtual void Mirror_X( int aXaxis_position ); + virtual void Mirror_X( int aXaxis_position ); - virtual void Rotate( wxPoint rotationPoint ); + virtual void Rotate( wxPoint rotationPoint ); virtual bool IsConnectable() const { return true; } + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_glabel_xpm; } + private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool doIsConnected( const wxPoint& aPosition ) const { return m_Pos == aPosition; } virtual EDA_ITEM* doClone() const; }; @@ -432,7 +446,7 @@ public: * position of 0 * 3 = bottom . This can be seen as the mirrored position of up */ - virtual void SetOrientation( int aSchematicOrientation ); + virtual void SetOrientation( int aSchematicOrientation ); /** * Function GetSchematicTextOffset (virtual) @@ -459,7 +473,7 @@ public: * @param aFile The FILE to write to. * @return bool - true if success writing else false. */ - bool Save( FILE* aFile ) const; + bool Save( FILE* aFile ) const; /** * Load schematic hierarchical label entry from \a aLine in a .sch file. @@ -478,22 +492,27 @@ public: * object, and the units should be in the pcb or schematic coordinate system. * It is OK to overestimate the size by a few counts. */ - EDA_Rect GetBoundingBox() const; + EDA_Rect GetBoundingBox() const; /** 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 ); + virtual void Mirror_Y( int aYaxis_position ); - virtual void Mirror_X( int aXaxis_position ); + virtual void Mirror_X( int aXaxis_position ); - virtual void Rotate( wxPoint rotationPoint ); + virtual void Rotate( wxPoint rotationPoint ); virtual bool IsConnectable() const { return true; } + virtual wxString GetSelectMenuText() const; + + virtual const char** GetMenuImage() const { return (const char**) add_hierarchical_label_xpm; } + private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const; + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const; + virtual bool doIsConnected( const wxPoint& aPosition ) const { return m_Pos == aPosition; } virtual EDA_ITEM* doClone() const; }; diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index 0801c458dd..7ac4bca3e1 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -30,6 +30,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) int id = event.GetId(); wxPoint pos; SCH_SCREEN* screen = GetScreen(); + SCH_ITEM* item = screen->GetCurItem(); pos = wxGetMousePosition(); @@ -126,12 +127,12 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_SCH_ENTRY_SELECT_SLASH: DrawPanel->MoveCursorToCrossHair(); - SetBusEntryShape( &dc, (SCH_BUS_ENTRY*) screen->GetCurItem(), '/' ); + SetBusEntryShape( &dc, (SCH_BUS_ENTRY*) item, '/' ); break; case ID_POPUP_SCH_ENTRY_SELECT_ANTISLASH: DrawPanel->MoveCursorToCrossHair(); - SetBusEntryShape( &dc, (SCH_BUS_ENTRY*) screen->GetCurItem(), '\\' ); + SetBusEntryShape( &dc, (SCH_BUS_ENTRY*) item, '\\' ); break; case ID_POPUP_CANCEL_CURRENT_COMMAND: @@ -150,12 +151,12 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_SCH_EDIT_TEXT: - EditSchematicText( (SCH_TEXT*) screen->GetCurItem() ); + EditSchematicText( (SCH_TEXT*) item ); break; case ID_POPUP_SCH_ROTATE_TEXT: DrawPanel->MoveCursorToCrossHair(); - ChangeTextOrient( (SCH_TEXT*) screen->GetCurItem(), &dc ); + ChangeTextOrient( (SCH_TEXT*) item, &dc ); break; case ID_POPUP_SCH_SET_SHAPE_TEXT: @@ -165,11 +166,11 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_SCH_ROTATE_FIELD: DrawPanel->MoveCursorToCrossHair(); - RotateCmpField( (SCH_FIELD*) screen->GetCurItem(), &dc ); + RotateCmpField( (SCH_FIELD*) item, &dc ); break; case ID_POPUP_SCH_EDIT_FIELD: - EditCmpFieldText( (SCH_FIELD*) screen->GetCurItem(), &dc ); + EditComponentFieldText( (SCH_FIELD*) item, &dc ); break; case ID_POPUP_SCH_DELETE_NODE: @@ -196,18 +197,7 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_SCH_DELETE_CMP: - if( screen->GetCurItem() == NULL ) - break; - - // Ensure the struct is a component (could be a struct of a - // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); - case ID_POPUP_SCH_DELETE: - { - SCH_ITEM* item = screen->GetCurItem(); - if( item == NULL ) break; @@ -217,34 +207,33 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) screen->TestDanglingEnds( DrawPanel, &dc ); SetSheetNumberAndCount(); OnModify(); - } - break; + break; case ID_POPUP_SCH_END_SHEET: DrawPanel->MoveCursorToCrossHair(); - screen->GetCurItem()->Place( this, &dc ); + item->Place( this, &dc ); break; case ID_POPUP_SCH_RESIZE_SHEET: DrawPanel->MoveCursorToCrossHair(); - ReSizeSheet( (SCH_SHEET*) screen->GetCurItem(), &dc ); + ReSizeSheet( (SCH_SHEET*) item, &dc ); screen->TestDanglingEnds( DrawPanel, &dc ); break; case ID_POPUP_SCH_EDIT_SHEET: - if( EditSheet( (SCH_SHEET*) screen->GetCurItem(), &dc ) ) + if( EditSheet( (SCH_SHEET*) item, &dc ) ) OnModify(); break; case ID_POPUP_IMPORT_GLABEL: - if( screen->GetCurItem() && screen->GetCurItem()->Type() == SCH_SHEET_T ) - screen->SetCurItem( Import_PinSheet( (SCH_SHEET*) screen->GetCurItem(), &dc ) ); + if( item != NULL && item->Type() == SCH_SHEET_T ) + screen->SetCurItem( Import_PinSheet( (SCH_SHEET*) item, &dc ) ); break; case ID_POPUP_SCH_CLEANUP_SHEET: - if( screen->GetCurItem() && screen->GetCurItem()->Type() == SCH_SHEET_T ) + if( item != NULL && item->Type() == SCH_SHEET_T ) { - SCH_SHEET* sheet = (SCH_SHEET*) screen->GetCurItem(); + SCH_SHEET* sheet = (SCH_SHEET*) item; if( !sheet->HasUndefinedLabels() ) { @@ -265,35 +254,21 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_SCH_EDIT_PINSHEET: - Edit_PinSheet( (SCH_SHEET_PIN*) screen->GetCurItem(), &dc ); + Edit_PinSheet( (SCH_SHEET_PIN*) item, &dc ); break; case ID_POPUP_SCH_MOVE_PINSHEET: DrawPanel->MoveCursorToCrossHair(); - StartMove_PinSheet( (SCH_SHEET_PIN*) screen->GetCurItem(), &dc ); + StartMove_PinSheet( (SCH_SHEET_PIN*) item, &dc ); break; case ID_POPUP_SCH_DRAG_CMP_REQUEST: case ID_POPUP_SCH_MOVE_CMP_REQUEST: - - // Ensure the struct is a component (could be a struct of a - // component, like Field, text..) or a hierarchical sheet - // or a label - if( (screen->GetCurItem()->Type() != SCH_COMPONENT_T) - && (screen->GetCurItem()->Type() != SCH_LABEL_T) - && (screen->GetCurItem()->Type() != SCH_GLOBAL_LABEL_T) - && (screen->GetCurItem()->Type() != SCH_HIERARCHICAL_LABEL_T) - && (screen->GetCurItem()->Type() != SCH_SHEET_T) ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); - - if( screen->GetCurItem() == NULL ) - break; - - // fall through case ID_POPUP_SCH_MOVE_ITEM_REQUEST: + case ID_POPUP_SCH_DRAG_WIRE_REQUEST: DrawPanel->MoveCursorToCrossHair(); - if( id == ID_POPUP_SCH_DRAG_CMP_REQUEST ) + if( (id == ID_POPUP_SCH_DRAG_CMP_REQUEST) || (id == ID_POPUP_SCH_DRAG_WIRE_REQUEST) ) { // The easiest way to handle a drag component or sheet command // is to simulate a block drag command @@ -308,39 +283,16 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) } } else - Process_Move_Item( (SCH_ITEM*) screen->GetCurItem(), &dc ); - break; + Process_Move_Item( item, &dc ); - case ID_POPUP_SCH_DRAG_WIRE_REQUEST: - DrawPanel->MoveCursorToCrossHair(); - - // The easiest way to handle a drag component is to simulate a block drag command - if( screen->m_BlockLocate.m_State == STATE_NO_BLOCK ) - { - if( !HandleBlockBegin( &dc, BLOCK_DRAG, screen->GetCrossHairPosition() ) ) - break; - - // Ensure the block selection contains the segment, or one end of - // the segment. The initial rect is only one point (w = h = 2) - // The rect contains one or 0 ends. - // If one end is selected, this is a drag Node - // if no ends selected the current segment is dragged - screen->m_BlockLocate.Inflate( 1 ); - HandleBlockEnd( &dc ); - } break; case ID_POPUP_SCH_EDIT_CMP: - // Ensure the struct is a component (could be a struct of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); + if( item && item->Type() == SCH_COMPONENT_T ) + InstallCmpeditFrame( this, (SCH_COMPONENT*) item ); - if( screen->GetCurItem() == NULL ) - break; - - InstallCmpeditFrame( this, (SCH_COMPONENT*) screen->GetCurItem() ); break; case ID_POPUP_SCH_INIT_CMP: @@ -351,39 +303,27 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) // Ensure the struct is a component (could be a struct of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); + if( item != NULL && item->Type() == SCH_COMPONENT_T ) + EditComponentValue( (SCH_COMPONENT*) item, &dc ); - if( screen->GetCurItem() == NULL ) - break; - - EditComponentValue( (SCH_COMPONENT*) screen->GetCurItem(), &dc ); break; case ID_POPUP_SCH_EDIT_REF_CMP: // Ensure the struct is a component (could be a struct of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); + if( item != NULL && item->Type() == SCH_COMPONENT_T ) + EditComponentReference( (SCH_COMPONENT*) item, &dc ); - if( screen->GetCurItem() == NULL ) - break; - - EditComponentReference( (SCH_COMPONENT*) screen->GetCurItem(), &dc ); break; case ID_POPUP_SCH_EDIT_FOOTPRINT_CMP: // Ensure the struct is a component (could be a struct of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); + if( item && item->Type() == SCH_COMPONENT_T ) + EditComponentFootprint( (SCH_COMPONENT*) item, &dc ); - if( screen->GetCurItem() == NULL ) - break; - - EditComponentFootprint( (SCH_COMPONENT*) screen->GetCurItem(), &dc ); break; @@ -391,28 +331,22 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) // Ensure the struct is a component (could be a struct of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); + if( item && item->Type() == SCH_COMPONENT_T ) + { + DrawPanel->MoveCursorToCrossHair(); + ConvertPart( (SCH_COMPONENT*) item, &dc ); + } - if( screen->GetCurItem() == NULL ) - break; - - DrawPanel->MoveCursorToCrossHair(); - ConvertPart( (SCH_COMPONENT*) screen->GetCurItem(), &dc ); break; case ID_POPUP_SCH_DISPLAYDOC_CMP: // Ensure the struct is a component (could be a piece of a // component, like Field, text..) - if( screen->GetCurItem()->Type() != SCH_COMPONENT_T ) - screen->SetCurItem( LocateSmallestComponent( screen ) ); - - if( screen->GetCurItem() ) + if( item && item->Type() == SCH_COMPONENT_T ) { LIB_ALIAS* LibEntry; - LibEntry = CMP_LIBRARY::FindLibraryEntry( - ( (SCH_COMPONENT*) screen->GetCurItem() )->GetLibName() ); + LibEntry = CMP_LIBRARY::FindLibraryEntry( ( (SCH_COMPONENT*) item )->GetLibName() ); if( LibEntry && LibEntry->GetDocFileName() != wxEmptyString ) { @@ -423,16 +357,14 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_SCH_ENTER_SHEET: - { - EDA_ITEM* item = screen->GetCurItem(); if( item && (item->Type() == SCH_SHEET_T) ) { m_CurrentSheet->Push( (SCH_SHEET*) item ); DisplayCurrentSheet(); } - } - break; + + break; case ID_POPUP_SCH_LEAVE_SHEET: m_CurrentSheet->Pop(); @@ -499,17 +431,20 @@ void SCH_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_SCH_ADD_GLABEL: screen->SetCurItem( CreateNewText( &dc, id == ID_POPUP_SCH_ADD_LABEL ? LAYER_LOCLABEL : LAYER_GLOBLABEL ) ); - if( screen->GetCurItem() ) + item = screen->GetCurItem(); + + if( item ) { - ( (SCH_ITEM*) screen->GetCurItem() )->Place( this, &dc ); + item->Place( this, &dc ); screen->TestDanglingEnds( DrawPanel, &dc ); screen->SetCurItem( NULL ); } + break; case ID_POPUP_SCH_GETINFO_MARKER: - if( screen->GetCurItem() && screen->GetCurItem()->Type() == SCH_MARKER_T ) - ( (SCH_MARKER*) screen->GetCurItem() )->DisplayMarkerInfo( this ); + if( item && item->Type() == SCH_MARKER_T ) + ( (SCH_MARKER*) item )->DisplayMarkerInfo( this ); break; diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index ad20f080ba..1366df6b90 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -127,6 +127,10 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_POPUP_SCH_MIROR_X_CMP, ID_POPUP_SCH_ORIENT_NORMAL_CMP, SCH_EDIT_FRAME::OnChangeComponentOrientation ) + // Multple item selection context menu commands. + EVT_MENU_RANGE( ID_SCH_SELECT_ITEM_START, ID_SCH_SELECT_ITEM_END, + SCH_EDIT_FRAME::OnSelectItem ) + /* Handle user interface update events. */ EVT_UPDATE_UI( wxID_CUT, SCH_EDIT_FRAME::OnUpdateBlockSelected ) EVT_UPDATE_UI( wxID_COPY, SCH_EDIT_FRAME::OnUpdateBlockSelected ) @@ -712,3 +716,18 @@ void SCH_EDIT_FRAME::SVG_Print( wxCommandEvent& event ) frame.ShowModal(); } + + +void SCH_EDIT_FRAME::OnSelectItem( wxCommandEvent& aEvent ) +{ + int id = aEvent.GetId(); + int index = id - ID_SCH_SELECT_ITEM_START; + + if( (id >= ID_SCH_SELECT_ITEM_START && id <= ID_SCH_SELECT_ITEM_END) + && (index >= 0 && index < m_collectedItems.GetCount()) ) + { + SCH_ITEM* item = m_collectedItems[index]; + DrawPanel->m_AbortRequest = false; + GetScreen()->SetCurItem( item ); + } +} diff --git a/eeschema/sheetlab.cpp b/eeschema/sheetlab.cpp index cdb1eb4759..d60c1b9d1a 100644 --- a/eeschema/sheetlab.cpp +++ b/eeschema/sheetlab.cpp @@ -127,9 +127,6 @@ int SCH_EDIT_FRAME::Edit_PinSheet( SCH_SHEET_PIN* aLabel, wxDC* aDC ) if( aLabel == NULL ) return wxID_CANCEL; - if( aDC ) - aLabel->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); - DIALOG_SCH_EDIT_SHEET_PIN dlg( this ); dlg.SetLabelName( aLabel->m_Text ); @@ -151,6 +148,9 @@ int SCH_EDIT_FRAME::Edit_PinSheet( SCH_SHEET_PIN* aLabel, wxDC* aDC ) if( dlg.ShowModal() == wxID_CANCEL ) return wxID_CANCEL; + if( aDC ) + aLabel->Draw( DrawPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); + aLabel->m_Text = dlg.GetLabelName(); aLabel->m_Size.y = ReturnValueFromString( g_UserUnit, dlg.GetTextHeight(), m_InternalUnits ); aLabel->m_Size.x = ReturnValueFromString( g_UserUnit, dlg.GetTextWidth(), m_InternalUnits ); diff --git a/include/base_struct.h b/include/base_struct.h index 1a94713927..367ee9bcc0 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -6,6 +6,7 @@ #define BASE_STRUCT_H #include "colors.h" +#include "bitmaps.h" #include @@ -39,27 +40,29 @@ enum KICAD_T { TYPE_ZONE, // a segment used to fill a zone area (segment on a // copper layer) TYPE_MARKER_PCB, // a marker used to show something - TYPE_DIMENSION, // a dimension (graphic item) + TYPE_DIMENSION, // a dimension (graphic item) TYPE_MIRE, // a target (graphic item) TYPE_ZONE_EDGE_CORNER, // in zone outline: a point to define an outline TYPE_ZONE_CONTAINER, // a zone area TYPE_BOARD_ITEM_LIST, // a list of board items - // Draw Items in schematic - SCH_POLYLINE_T, + // Schematic draw Items. The order of these items effects the sort order. + // It is currenlty ordered to mimic the old EESchema locate behavior where + // the smallest item is the selected item. + SCH_MARKER_T, SCH_JUNCTION_T, + SCH_NO_CONNECT_T, + SCH_BUS_ENTRY_T, + SCH_LINE_T, + SCH_POLYLINE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIERARCHICAL_LABEL_T, - SCH_COMPONENT_T, - SCH_LINE_T, - SCH_BUS_ENTRY_T, - SCH_SHEET_T, - SCH_SHEET_LABEL_T, - SCH_MARKER_T, - SCH_NO_CONNECT_T, SCH_FIELD_T, + SCH_COMPONENT_T, + SCH_SHEET_LABEL_T, + SCH_SHEET_T, // General SCH_SCREEN_T, @@ -267,14 +270,21 @@ public: * mainly used to calculate bounding boxes. * @param aRect The rectangle to merge with this rectangle. */ - void Merge( const EDA_Rect& aRect ); + void Merge( const EDA_Rect& aRect ); /** * Function Merge * modifies the position and size of the rectangle in order to contain the given point. * @param aPoint The point to merge with the rectangle. */ - void Merge( const wxPoint& aPoint ); + void Merge( const wxPoint& aPoint ); + + /** + * Function GetArea + * returns the area of the rectangle. + * @return The area of the rectangle. + */ + double GetArea() const; }; @@ -460,7 +470,7 @@ public: * @param refArea : the given EDA_Rect * @return bool - true if a hit, else false */ - virtual bool HitTest( EDA_Rect& refArea ) + virtual bool HitTest( EDA_Rect& refArea ) { return false; // derived classes should override this function } @@ -519,7 +529,6 @@ public: const void* testData, const KICAD_T scanTypes[] ); - /** * Function Visit * may be re-implemented for each derived class in order to handle @@ -537,7 +546,6 @@ public: virtual SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] ); - /** * Function GetClass * returns the class name. @@ -548,6 +556,26 @@ public: return wxT( "EDA_ITEM" ); } + /** + * Function GetSelectMenuText + * returns the text to display to be used in the selection clarification context menu + * when multiple items are found at the current cursor position. The default version + * of this function raises an assertion in the debug mode and returns a string to + * indicate that it was not overridden to provide the object specific text. + * + * @return The menu text string. + */ + virtual wxString GetSelectMenuText() const; + + /** + * Function GetMenuImage + * returns a pointer to an image to be used in menus. The default version returns + * the right arrow image. Overide this function to provide object specific menu + * images. + * @return The menu image associated with the item. + */ + virtual const char** GetMenuImage() const { return (const char**) right_xpm; } + #if defined(DEBUG) @@ -576,7 +604,7 @@ public: /** * Function new_clone - * provides cloning capabilities for all Boost pointer containers of EDA_ITEMs. + * provides cloning capabilities for all Boost pointer containers of EDA_ITEM pointers. * * @param aItem EDA_ITEM to clone. * @return Clone of \a aItem. @@ -587,10 +615,10 @@ inline EDA_ITEM* new_clone( const EDA_ITEM& aItem ) { return aItem.Clone(); } /** * 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. + * The standard C++ containter was choosen so the pointer can be removed from a list without + * it being destroyed. */ -typedef boost::ptr_vector< EDA_ITEM > EDA_ITEMS; +typedef std::vector< EDA_ITEM* > EDA_ITEMS; // Graphic Text justify: diff --git a/include/class_collector.h b/include/class_collector.h index 1aa2f27e22..8d4e85b83d 100644 --- a/include/class_collector.h +++ b/include/class_collector.h @@ -142,6 +142,23 @@ public: return &m_List[0]; } + /** + * Function HasItem + * tests if \a aItem has already been collected. + * + * @param aItem The EDA_ITEM* to be tested. + * @return True if \a aItem is already collected. + */ + bool HasItem( const EDA_ITEM* aItem ) const + { + for( size_t i = 0; i < m_List.size(); i++ ) + { + if( m_List[i] == aItem ) + return true; + } + + return false; + } /** * Function SetScanTypes @@ -159,6 +176,7 @@ public: { m_TimeAtCollection = GetTimeStamp(); } + int GetTime() { return m_TimeAtCollection; diff --git a/include/class_drawpanel.h b/include/class_drawpanel.h index 414de47136..720bbe5bdc 100644 --- a/include/class_drawpanel.h +++ b/include/class_drawpanel.h @@ -101,7 +101,7 @@ public: * @see EDA_DRAW_FRAME::GetGridColor() for the color of the grid. * @param aDC The device context to draw the grid. */ - void DrawGrid( wxDC* DC ); + void DrawGrid( wxDC* aDC ); /** * Function DrawAuxiliaryAxis diff --git a/include/class_sch_screen.h b/include/class_sch_screen.h index 76c13dfc41..a5fca4637e 100644 --- a/include/class_sch_screen.h +++ b/include/class_sch_screen.h @@ -9,12 +9,23 @@ #include "sch_item_struct.h" #include "class_base_screen.h" +#include "../eeschema/general.h" + class LIB_PIN; class SCH_COMPONENT; class SCH_SHEET_PATH; class SCH_SHEET_PIN; class SCH_LINE; +class SCH_TEXT; + + +enum SCH_LINE_TEST_T +{ + ENTIRE_LENGTH_T, + END_POINTS_ONLY_T, + EXCLUDE_END_POINTS_T +}; /* Max number of sheets in a hierarchy project: */ @@ -30,7 +41,7 @@ class SCH_SCREEN : public BASE_SCREEN * Function addConnectedItemsToBlock * add items connected at \a aPosition to the block pick list. *

- * This method tests all connectable unselected items in the screen that are connected to + * This method tests all connectible unselected items in the screen that are connected to * \a aPosition and adds them to the block selection pick list. This is used when a block * drag is being performed to ensure connections to items in the block are not lost. *

@@ -84,39 +95,15 @@ public: void FreeDrawList(); /** - * Function GetItems - * adds all items found at \a aPosition to \a aItemList. Please note that \a aItemList - * will own the item pointers added to it. Do not allow it to go out of scope without - * first calling the release() method. Otherwise, the pointer will be deleted and - * EESchema will crash. - * @param aPosition The position to test. - * @param aItemList The list to place items into. - * @return The number of items found at \a aPosition. - */ - int GetItems( const wxPoint& aPosition, SCH_ITEMS& aItemList ) const; - - /** - * Function FindItem + * Function GetItem * checks \a aPosition within a distance of \a aAccuracy for items of type \a aFilter. * @param aPosition Position in drawing units. * @param aAccuracy The maximum distance within \a Position to check for an item. - * @param aFilter The type of items to find. + * @param aType The type of item to find or #NOT_USED to find any item type. * @return The item found that meets the search criteria or NULL if none found. */ SCH_ITEM* GetItem( const wxPoint& aPosition, int aAccuracy = 0, - int aFilter = NO_FILTER_T ) const; - - /** - * Function GetItems - * checks \a aPosition within a distance of \a aAccuracy for items of type \a aFilter. - * @param aPosition Position in drawing units. - * @param aItemList The list to add found items to. - * @param aAccuracy The maximum distance within \a Position to check for an item. - * @param aFilter The type of items to find. - * @return The number of items found that meets the search criteria. - */ - int GetItems( const wxPoint& aPosition, PICKED_ITEMS_LIST& aItemList, int aAccuracy = 0, - int aFilter = NO_FILTER_T ) const; + KICAD_T aType = NOT_USED ) const; void Place( SCH_EDIT_FRAME* frame, wxDC* DC ) { }; @@ -150,6 +137,15 @@ public: void AddToDrawList( SCH_ITEM* st ); + /** + * Function SchematicCleanUp + * performs routine schematic cleaning including breaking wire and buses and + * deleting identical objects superimposed on top of each other. + * + * @param aCanvas The window to draw on. + * @param aDC The device context used for drawing to \a aCanvas. + * @return True if any schematic clean up was performed. + */ bool SchematicCleanUp( EDA_DRAW_PANEL* aCanvas = NULL, wxDC* aDC = NULL ); /** @@ -167,8 +163,8 @@ public: * them with a copy. Old item must be put in undo list, and the new ones can be * modified by clean up safely. If an abort command is made, old wires must be put * in GetDrawItems(), and copies must be deleted. This is because previously stored - * undo commands can handle pointers on wires or busses, and we do not delete wires or - * busses, we must put they in undo list. + * undo commands can handle pointers on wires or buses, and we do not delete wires or + * buss-es, we must put they in undo list. * * Because cleanup delete and/or modify bus and wires, the it is easier is to put * all wires in undo list and use a new copy of wires for cleanup. @@ -187,7 +183,6 @@ public: * add all wires and junctions connected to \a aSegment which are not connected any * component pin to \a aItemList. * @param aSegment The segment to test for connections. - * @param aItemList List of items to add connections. */ void MarkConnections( SCH_LINE* aSegment ); @@ -257,7 +252,18 @@ public: * @param aPosition The position to test. * @return True if a junction is required at \a aPosition. */ - bool IsJunctionNeeded( const wxPoint& aPosition ) const; + bool IsJunctionNeeded( const wxPoint& aPosition ); + + /** + * Function IsTerminalPoint + * tests if \a aPosition is a connection point on \a aLayer. + * + * @param aPosition Position to test. + * @param aLayer The layer type to test against. Valid layer types are #LAYER_NOTES, + * #LAYER_BUS, and #LAYER_WIRE. + * @return True if \a Position is a connection point on \a aLayer. + */ + bool IsTerminalPoint( const wxPoint& aPosition, int aLayer ); /** * Function GetPin @@ -292,7 +298,64 @@ public: * adds all schematic sheet and component object in the screen to \a aItems. * @param aItems Hierarchical item list to fill. */ - void GetHierarchicalItems( std::vector & aItems ); + void GetHierarchicalItems( EDA_ITEMS& aItems ); + + /** + * Function GetNode + * returns all the items at \a aPosition that form a node. + * + * @param aPosition The wxPoint to test for node items. + * @param aList A #EDA_ITEMS container to place the items found. + * @return The number of node items found at \a aPosition. + */ + int GetNode( const wxPoint& aPosition, EDA_ITEMS& aList ); + + /** + * Function GetWireOrBus + * returns a wire or bus item located at \a aPosition. + * + * @param aPosition The wxPoint to test for node items. + * @return The SCH_LINE* of the wire or bus item found at \a aPosition or NULL if item not + * found. + */ + SCH_LINE* GetWireOrBus( const wxPoint& aPosition ); + + /** + * Function GetLine + * returns a line item located at \a aPosition. + * + * @param aPosition The wxPoint to test for a line item. + * @param aAccuracy Amount to inflate the item hit test bounding box. + * @param aLayer The layer the line is drawn upon. + * @param aSearchType Additional line test criteria. + * @return The SCH_LINE* of the wire item found at \a aPosition or NULL if item not + * found. + */ + SCH_LINE* GetLine( const wxPoint& aPosition, int aAccuracy = 0, int aLayer = LAYER_NOTES, + SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T ); + + SCH_LINE* GetWire( const wxPoint& aPosition, int aAccuracy = 0, + SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T ) + { + return GetLine( aPosition, aAccuracy, LAYER_WIRE, aSearchType ); + } + + SCH_LINE* GetBus( const wxPoint& aPosition, int aAccuracy = 0, + SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T ) + { + return GetLine( aPosition, aAccuracy, LAYER_BUS, aSearchType ); + } + + /** + * Function GetLabel + * returns a label item located at \a aPosition. + * + * @param aPosition The wxPoint to test for label items. + * @param aAccuracy Amount to inflate the item hit test bounding box. + * @return The SCH_TEXT* of the label item found at \a aPosition or NULL if item not + * found. + */ + SCH_TEXT* GetLabel( const wxPoint& aPosition, int aAccuracy = 0 ); /** * Function SelectBlockItems @@ -370,7 +433,7 @@ public: * Function DeleteAllMarkers * deletes all electronic rules check markers of \a aMarkerType from all the screens in * the list. - * @param aType Type of markers to be deleted. + * @param aMarkerType Type of markers to be deleted. */ void DeleteAllMarkers( int aMarkerType ); diff --git a/include/common.h b/include/common.h index 7c7594297e..54245b1955 100644 --- a/include/common.h +++ b/include/common.h @@ -301,6 +301,20 @@ int GetCommandOptions( const int argc, const char** argv, */ const wxString& valeur_param( int valeur, wxString& buf_texte ); +/** + * Function CoordinateToString + * is a helper to convert the integer coordinate \a aValue to a string in inches, + * millimeters, or unscaled units according to the current user units setting. + * + * @param aValue The coordinate to convert. + * @param aInternalUnits The internal units of the application. #EESCHEMA_INTERNAL_UNIT + * and #PCB_INTERNAL_UNIT are the only valid value. + * @param aConvertToMils Convert inch values to mils if true. This setting has no effect if + * the current user unit is millimeters. + * @return The converted string for display in user interface elements. + */ +wxString CoordinateToString( int aValue, int aInternalUnits, bool aConvertToMils = false ); + /** * Returns the units symbol. * diff --git a/include/sch_item_struct.h b/include/sch_item_struct.h index bf2be9e467..f48e4535ca 100644 --- a/include/sch_item_struct.h +++ b/include/sch_item_struct.h @@ -22,28 +22,6 @@ typedef SCH_ITEMS::iterator SCH_ITEMS_ITR; typedef vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS; -// Schematic item filter mask for hit test objects in schematic editor. -enum SCH_FILTER_T { - COMPONENT_T = 0x0001, - WIRE_T = 0X0002, - BUS_T = 0x0004, - BUS_ENTRY_T = 0x0008, - JUNCTION_T = 0x0010, - DRAW_ITEM_T = 0x0020, - TEXT_T = 0x0040, - LABEL_T = 0x0080, - SHEET_T = 0x0100, - MARKER_T = 0x0200, - NO_CONNECT_T = 0x0400, - SHEET_LABEL_T = 0x0800, - FIELD_T = 0x1000, - EXCLUDE_ENDPOINTS_T = 0x2000, - ENDPOINTS_ONLY_T = 0x4000, - PIN_T = 0x8000, - NO_FILTER_T = 0xFFFF -}; - - /* used to calculate the pen size from default value * the actual pen size is default value * BUS_WIDTH_EXPAND */ @@ -147,7 +125,7 @@ public: /** * Function Move * moves the item by \a aMoveVector to a new position. - * @param aMoveVector = the deplacement vector + * @param aMoveVector = the displacement vector */ virtual void Move( const wxPoint& aMoveVector ) = 0; @@ -248,7 +226,7 @@ public: * 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. + * @param aRect - Rectangle to test against. */ virtual bool IsSelectStateChanged( const wxRect& aRect ) { return false; } @@ -275,7 +253,7 @@ public: * 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(); } + void ClearConnections() { m_connections.clear(); } /** * Function IsConnected @@ -286,19 +264,19 @@ public: */ bool IsConnected( const wxPoint& aPoint ) const; + virtual bool HitTest( const wxPoint& aPosition ) { return HitTest( aPosition, 0 ); } + /** * Function HitTest * tests if \a aPoint is contained within or on the bounding box of an item. * * @param aPoint - Point to test. * @param aAccuracy - Increase the item bounding box by this amount. - * @param aFilter - Mask to provide more granular hit testing. See enum SCH_FILTER_T. - * @return True if \a aPoint is within the item and meets the filter criteria. + * @return True if \a aPoint is within the item bounding box. */ - bool HitTest( const wxPoint& aPoint, int aAccuracy = 0, - SCH_FILTER_T aFilter = NO_FILTER_T ) const + bool HitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const { - return doHitTest( aPoint, aAccuracy, aFilter ); + return doHitTest( aPoint, aAccuracy ); } /** @@ -317,6 +295,8 @@ public: virtual bool CanIncrementLabel() const { return false; } + virtual bool operator <( const SCH_ITEM& aItem ) const; + /** * @note - The DoXXX() functions below are used to enforce the interface while retaining * the ability of change the implementation behavior of derived classes. See @@ -324,7 +304,7 @@ public: * http://www.gotw.ca/publications/mill18.htm. */ private: - virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const + virtual bool doHitTest( const wxPoint& aPoint, int aAccuracy ) const { return false; } @@ -337,4 +317,8 @@ private: virtual bool doIsConnected( const wxPoint& aPosition ) const { return false; } }; + +extern bool sort_schematic_items( const SCH_ITEM* aItem1, const SCH_ITEM* aItem2 ); + + #endif /* SCH_ITEM_STRUCT_H */ diff --git a/include/trigo.h b/include/trigo.h index 2868ea5e0e..d65aeb163d 100644 --- a/include/trigo.h +++ b/include/trigo.h @@ -27,30 +27,30 @@ bool DistanceTest( int seuil, int dx, int dy, int spot_cX, int spot_cY ); //! @param linePointA Point on line //! @param linePointB Point on line //! @param referencePoint Reference point -double DistanceLinePoint(wxPoint linePointA, wxPoint linePointB, wxPoint referencePoint); +double DistanceLinePoint( wxPoint linePointA, wxPoint linePointB, wxPoint referencePoint ); //! @brief Euclidean norm of a 2D vector //! @param vector Two-dimensional vector //! @return Euclidean norm of the vector -double EuclideanNorm(wxPoint vector); +double EuclideanNorm( wxPoint vector ); //! @brief Vector between two points //! @param startPoint The start point //! @param endPoint The end point //! @return Vector between the points -wxPoint TwoPointVector(wxPoint startPoint, wxPoint endPoint); +wxPoint TwoPointVector( wxPoint startPoint, wxPoint endPoint ); //! @brief Test, if two points are near each other //! @param pointA First point //! @param pointB Second point //! @param threshold The maximum distance //! @return True or false -bool HitTestPoints(wxPoint pointA, wxPoint pointB, double threshold); +bool HitTestPoints( wxPoint pointA, wxPoint pointB, double threshold ); //! @brief Determine the cross product //! @param vectorA Two-dimensional vector //! @param vectorB Two-dimensional vector -int CrossProduct(wxPoint vectorA, wxPoint vectorB); +int CrossProduct( wxPoint vectorA, wxPoint vectorB ); /** @@ -62,9 +62,14 @@ int CrossProduct(wxPoint vectorA, wxPoint vectorB); * @param aEnd is the second end-point of the line segment * @param aDist = maximum distance for hit */ -bool TestSegmentHit( wxPoint aRefPoint, wxPoint aStart, wxPoint aEnd, - int aDist ); +bool TestSegmentHit( wxPoint aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist ); +/** + * Function GetLineLength + * returns the length of a line segment defined by \a aPointA and \a aPointB. + * @return Length of a line. + */ +double GetLineLength( const wxPoint& aPointA, const wxPoint& aPointB ); /*******************/ diff --git a/include/wxEeschemaStruct.h b/include/wxEeschemaStruct.h index 480ab31560..70a54ab0eb 100644 --- a/include/wxEeschemaStruct.h +++ b/include/wxEeschemaStruct.h @@ -11,6 +11,7 @@ #include "template_fieldnames.h" #include "block_commande.h" #include "class_sch_screen.h" +#include "sch_collectors.h" class LIB_EDIT_FRAME; @@ -94,6 +95,7 @@ private: BLOCK_SELECTOR m_blockItems; ///< List of selected items. SCH_ITEM* m_itemToRepeat; ///< Last item to insert by the repeat command. int m_repeatLabelDelta; ///< Repeat label number increment step. + SCH_COLLECTOR m_collectedItems; ///< List of collected items. public: SCH_EDIT_FRAME( wxWindow* father, @@ -204,24 +206,52 @@ public: void OnSelectOptionToolbar( wxCommandEvent& event ); int BestZoom(); - SCH_ITEM* LocateAndShowItem( const wxPoint& aPosition, bool aIncludePin = true ); - SCH_ITEM* LocateItem( const wxPoint& aPosition, bool aIncludePin ); + /** + * Function LocateAndShowItem + * checks the schematic at \a aPosition in logical (drawing) units for a item + * matching \a aFilterList and \a aGuide. + *

+ * The search is first performed at the nearest grid position to \a aPosition. If no + * item if found on grid, then \a aPosition is tested for any items. If the item found + * can be cross probed, a message is send to PCBNew and the selected item is highlighted + * in PCB editor. + *

+ * @param aPosition The wxPoint on the schematic to search. + * @param aFilterList A list of #KICAD_T types to to filter. + * @param aHotKeyCommandId A hot key command ID for performing additional tests when + * multiple items are found at \a aPosition. + * @return A SCH_ITEM pointer of the item found or NULL if no item found + */ + SCH_ITEM* LocateAndShowItem( const wxPoint& aPosition, + const KICAD_T aFilterList[] = SCH_COLLECTOR::AllItems, + int aHotKeyCommandId = 0 ); + + /** + * Function LocateItem + * checks for items at \a aPosition matching \a aFilter. + *

+ * If multiple items are located at \a aPosition, a context menu is displayed to clarify + * which item the user intended to select. If the user aborts the context menu, NULL is + * returned and the abort request flag will be set to true. Make sure to clear this flag + * before attempting to display any other context menus. + *

+ * + * @param aPosition The wxPoint location where to search. + * @param aFilterList A list of #KICAD_T types to to filter. + * @param aHotKeyCommandId A hot key command ID for performing additional tests when + * multiple items are found at \a aPosition. + * @return The SCH_ITEM pointer of the item found or NULL if no item found. + */ + SCH_ITEM* LocateItem( const wxPoint& aPosition, + const KICAD_T aFilterList[] = SCH_COLLECTOR::AllItems, + int aHotKeyCommandId = 0 ); /** * Function DeleteItemAtCrossHair - * delete the item found under the cross hair. - *

- * If more than one item found, the priority order is: - *

    - * Marker - * Junction - * No connect - * Wire or bus - * Graphic item - * Text - * Component - * Sheet - *

+ * delete the item found under the cross hair. If multiple items are found at the + * cross hair position, a context menu is displayed to clarify which item to delete. + * See LocateItem() for more information on locating multiple items. + * * @param aDC The device context to update if and item is deleted. * @return True if an item was deleted. */ @@ -440,6 +470,8 @@ private: void OnSetOptions( wxCommandEvent& event ); void OnCancelCurrentCommand( wxCommandEvent& aEvent ); + void OnSelectItem( wxCommandEvent& aEvent ); + /* edition events functions */ void OnCopySchematicItemRequest( wxCommandEvent& event ); @@ -552,13 +584,11 @@ private: void OnSelectUnit( wxCommandEvent& aEvent ); void ConvertPart( SCH_COMPONENT* DrawComponent, wxDC* DC ); void SetInitCmp( SCH_COMPONENT* DrawComponent, wxDC* DC ); - void EditComponentReference( SCH_COMPONENT* DrawLibItem, - wxDC* DC ); + void EditComponentReference( SCH_COMPONENT* DrawLibItem, wxDC* DC ); void EditComponentValue( SCH_COMPONENT* DrawLibItem, wxDC* DC ); - void EditComponentFootprint( SCH_COMPONENT* DrawLibItem, - wxDC* DC ); + void EditComponentFootprint( SCH_COMPONENT* DrawLibItem, wxDC* DC ); void StartMoveCmpField( SCH_FIELD* Field, wxDC* DC ); - void EditCmpFieldText( SCH_FIELD* Field, wxDC* DC ); + void EditComponentFieldText( SCH_FIELD* aField, wxDC* aDC ); void RotateCmpField( SCH_FIELD* Field, wxDC* DC ); void PasteListOfItems( wxDC* DC ); diff --git a/include/wxstruct.h b/include/wxstruct.h index 75dc08f635..8a42b4ed82 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -191,20 +191,23 @@ public: virtual void SetLanguage( wxCommandEvent& event ); /** - * function GetFileFromHistory - * Fetch the file name from the file history list. - * @param aFileHistory = the wxFileHistory in use. If null, - * the main application file history is used + * Function GetFileFromHistory + * fetches the file name from the file history list. + * @param cmdId The command ID associated with the \a aFileHistory object. + * @param type Please document me! + * @param aFileHistory The wxFileHistory in use. If null, the main application file + * history is used * @return a wxString containing the selected filename */ wxString GetFileFromHistory( int cmdId, const wxString& type, - wxFileHistory * aFileHistory = NULL); + wxFileHistory* aFileHistory = NULL); /** * Function UpdateFileHistory - * Update the list of recent opened files. - * @param aFileHistory = the wxFileHistory in use. If NULL, - * the main application file history is used + * ypdates the list of recently opened files. + * @param FullFileName The full file name including the path. + * @param aFileHistory The wxFileHistory in use. If NULL, the main application file + * history is used. */ void UpdateFileHistory( const wxString& FullFileName, wxFileHistory * aFileHistory = NULL );