// This function is a callback function, called by the mouse cursor movin event // when an item is currently moved static void moveItemWithMouseCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen(); SCH_ITEM* item = screen->GetCurItem(); wxCHECK_RET( (item != NULL), wxT( "Cannot move invalid schematic item." ) ); SCH_COMPONENT* cmp = NULL; if( item->Type() == SCH_COMPONENT_T ) cmp = static_cast< SCH_COMPONENT* >( item ); #ifndef USE_WX_OVERLAY // Erase the current item at its current position. if( aErase ) { if( cmp ) // Use fast mode (do not draw pin texts) cmp->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, UNSPECIFIED_COLOR, false ); else item->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); } #endif wxPoint cpos = aPanel->GetParent()->GetCrossHairPosition(); cpos -= item->GetStoredPos(); item->SetPosition( cpos ); // Draw the item item at it's new position. item->SetWireImage(); // While moving, the item may choose to render differently if( cmp ) // Use fast mode (do not draw pin texts) cmp->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, UNSPECIFIED_COLOR, false ); else item->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode ); }
void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); // Allows block rotate operation on hot key. if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ) { if( aEvent.GetId() == ID_SCH_MIRROR_X ) { m_canvas->MoveCursorToCrossHair(); screen->m_BlockLocate.SetMessageBlock( this ); screen->m_BlockLocate.SetCommand( BLOCK_MIRROR_X ); HandleBlockEnd( &dc ); } else if( aEvent.GetId() == ID_SCH_MIRROR_Y ) { m_canvas->MoveCursorToCrossHair(); screen->m_BlockLocate.SetMessageBlock( this ); screen->m_BlockLocate.SetCommand( BLOCK_MIRROR_Y ); HandleBlockEnd( &dc ); } else { wxFAIL_MSG( wxT( "Unknown block oriention command ID." ) ); } return; } if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::OrientableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } switch( item->Type() ) { case SCH_COMPONENT_T: if( aEvent.GetId() == ID_SCH_MIRROR_X ) OrientComponent( CMP_MIRROR_X ); else if( aEvent.GetId() == ID_SCH_MIRROR_Y ) OrientComponent( CMP_MIRROR_Y ); else if( aEvent.GetId() == ID_SCH_ORIENT_NORMAL ) OrientComponent( CMP_NORMAL ); else wxFAIL_MSG( wxT( "Invalid orient schematic component command ID." ) ); break; case SCH_BITMAP_T: if( aEvent.GetId() == ID_SCH_MIRROR_X ) MirrorImage( (SCH_BITMAP*) item, true ); else if( aEvent.GetId() == ID_SCH_MIRROR_Y ) MirrorImage( (SCH_BITMAP*) item, false ); break; default: wxFAIL_MSG( wxString::Format( wxT( "Schematic object type %s cannot be oriented." ), GetChars( item->GetClass() ) ) ); } if( item->GetFlags() == 0 ) screen->SetCurItem( NULL ); }
void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::DraggableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } switch( item->Type() ) { case SCH_BUS_BUS_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T: case SCH_LINE_T: case SCH_JUNCTION_T: if( item->GetLayer() == LAYER_BUS ) break; // Fall thru if item is not on bus layer. case SCH_COMPONENT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_SHEET_T: m_canvas->MoveCursorToCrossHair(); // The easiest way to handle a drag component or sheet command // is to simulate a block drag command if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK ) { if( !HandleBlockBegin( &dc, BLOCK_DRAG, GetCrossHairPosition() ) ) break; // Give a non null size to the search block: screen->m_BlockLocate.Inflate( 1 ); HandleBlockEnd( &dc ); } break; default: wxFAIL_MSG( wxString::Format( wxT( "Cannot drag schematic item type %s." ), GetChars( item->GetClass() ) ) ); } }
void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); // Set the locat filter, according to the edit command const KICAD_T* filterList = SCH_COLLECTOR::EditableItems; const KICAD_T* filterListAux = NULL; switch( aEvent.GetId() ) { case ID_SCH_EDIT_COMPONENT_REFERENCE: filterList = SCH_COLLECTOR::CmpFieldReferenceOnly; filterListAux = SCH_COLLECTOR::ComponentsOnly; break; case ID_SCH_EDIT_COMPONENT_VALUE: filterList = SCH_COLLECTOR::CmpFieldValueOnly; filterListAux = SCH_COLLECTOR::ComponentsOnly; break; case ID_SCH_EDIT_COMPONENT_FOOTPRINT: filterList = SCH_COLLECTOR::CmpFieldFootprintOnly; filterListAux = SCH_COLLECTOR::ComponentsOnly; break; default: break; } item = LocateAndShowItem( data->GetPosition(), filterList, aEvent.GetInt() ); // If no item found, and if an auxiliary filter exists, try to use it if( !item && filterListAux ) item = LocateAndShowItem( data->GetPosition(), filterListAux, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } switch( item->Type() ) { case SCH_COMPONENT_T: { switch( aEvent.GetId() ) { case ID_SCH_EDIT_COMPONENT_REFERENCE: EditComponentFieldText( ( (SCH_COMPONENT*) item )->GetField( REFERENCE ) ); break; case ID_SCH_EDIT_COMPONENT_VALUE: EditComponentFieldText( ( (SCH_COMPONENT*) item )->GetField( VALUE ) ); break; case ID_SCH_EDIT_COMPONENT_FOOTPRINT: EditComponentFieldText( ( (SCH_COMPONENT*) item )->GetField( FOOTPRINT ) ); break; case ID_SCH_EDIT_ITEM: EditComponent( (SCH_COMPONENT*) item ); break; default: wxFAIL_MSG( wxString::Format( wxT( "Invalid schematic component edit command ID %d" ), aEvent.GetId() ) ); } break; } case SCH_SHEET_T: EditSheet( (SCH_SHEET*) item, &dc ); break; case SCH_SHEET_PIN_T: EditSheetPin( (SCH_SHEET_PIN*) item, &dc ); break; case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: EditSchematicText( (SCH_TEXT*) item ); break; case SCH_FIELD_T: EditComponentFieldText( (SCH_FIELD*) item ); break; case SCH_BITMAP_T: EditImage( (SCH_BITMAP*) item ); break; default: wxFAIL_MSG( wxString::Format( wxT( "Cannot edit schematic item type %s." ), GetChars( item->GetClass() ) ) ); } if( item->GetFlags() == 0 ) screen->SetCurItem( NULL ); }
void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); // Allows block rotate operation on hot key. if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ) { screen->m_BlockLocate.SetCommand( BLOCK_ROTATE ); HandleBlockEnd( &dc ); return; } if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::RotatableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } switch( item->Type() ) { case SCH_COMPONENT_T: if( aEvent.GetId() == ID_SCH_ROTATE_CLOCKWISE ) OrientComponent( CMP_ROTATE_CLOCKWISE ); else if( aEvent.GetId() == ID_SCH_ROTATE_COUNTERCLOCKWISE ) OrientComponent( CMP_ROTATE_COUNTERCLOCKWISE ); else wxFAIL_MSG( wxT( "Unknown rotate item command ID." ) ); break; case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: m_canvas->MoveCursorToCrossHair(); ChangeTextOrient( (SCH_TEXT*) item, &dc ); break; case SCH_FIELD_T: m_canvas->MoveCursorToCrossHair(); RotateField( (SCH_FIELD*) item, &dc ); break; case SCH_BITMAP_T: RotateImage( (SCH_BITMAP*) item ); break; case SCH_SHEET_T: /// @todo allow sheet rotate on hotkey default: wxFAIL_MSG( wxString::Format( wxT( "Cannot rotate schematic item type %s." ), GetChars( item->GetClass() ) ) ); } if( item->GetFlags() == 0 ) screen->SetCurItem( NULL ); }
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(); pos.y += 20; // If needed, stop the current command and deselect current tool switch( id ) { case wxID_CUT: case wxID_COPY: case ID_POPUP_CANCEL_CURRENT_COMMAND: case ID_POPUP_SCH_ENTRY_SELECT_SLASH: case ID_POPUP_SCH_ENTRY_SELECT_ANTISLASH: case ID_POPUP_SCH_BEGIN_WIRE: case ID_POPUP_SCH_BEGIN_BUS: case ID_POPUP_END_LINE: case ID_POPUP_SCH_SET_SHAPE_TEXT: case ID_POPUP_SCH_CLEANUP_SHEET: case ID_POPUP_SCH_END_SHEET: case ID_POPUP_SCH_RESIZE_SHEET: case ID_POPUP_IMPORT_GLABEL: case ID_POPUP_SCH_INIT_CMP: case ID_POPUP_SCH_DISPLAYDOC_CMP: case ID_POPUP_SCH_EDIT_CONVERT_CMP: case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_DRAG_BLOCK: case ID_POPUP_COPY_BLOCK: case ID_POPUP_SCH_DELETE_NODE: case ID_POPUP_SCH_DELETE_CONNECTION: case ID_POPUP_SCH_ENTER_SHEET: case ID_POPUP_SCH_LEAVE_SHEET: case ID_POPUP_SCH_ADD_JUNCTION: case ID_POPUP_SCH_ADD_LABEL: case ID_POPUP_SCH_GETINFO_MARKER: /* At this point: Do nothing. these commands do not need to stop the * current command (mainly a block command) or reset the current state * They will be executed later, in next switch structure. */ break; case ID_POPUP_SCH_DELETE_CMP: case ID_POPUP_SCH_DELETE: // Stop the current command (if any) but keep the current tool m_canvas->EndMouseCapture(); break; default: // Stop the current command and deselect the current tool m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); break; } INSTALL_UNBUFFERED_DC( dc, m_canvas ); item = screen->GetCurItem(); // Can be modified by previous calls. switch( id ) { case ID_HIERARCHY: InstallHierarchyFrame( &dc, pos ); SetRepeatItem( NULL ); break; case wxID_CUT: if( screen->m_BlockLocate.GetCommand() != BLOCK_MOVE ) break; screen->m_BlockLocate.SetCommand( BLOCK_DELETE ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); SetRepeatItem( NULL ); SetSheetNumberAndCount(); break; case wxID_PASTE: HandleBlockBegin( &dc, BLOCK_PASTE, GetCrossHairPosition() ); break; case ID_POPUP_SCH_ENTRY_SELECT_SLASH: m_canvas->MoveCursorToCrossHair(); SetBusEntryShape( &dc, dynamic_cast<SCH_BUS_ENTRY_BASE*>( item ), '/' ); break; case ID_POPUP_SCH_ENTRY_SELECT_ANTISLASH: m_canvas->MoveCursorToCrossHair(); SetBusEntryShape( &dc, dynamic_cast<SCH_BUS_ENTRY_BASE*>( item ), '\\' ); break; case ID_POPUP_CANCEL_CURRENT_COMMAND: if( m_canvas->IsMouseCaptured() ) { m_canvas->EndMouseCapture(); SetToolID( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString ); } else { SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); } break; case ID_POPUP_END_LINE: m_canvas->MoveCursorToCrossHair(); EndSegment( &dc ); break; case ID_POPUP_SCH_BEGIN_WIRE: m_canvas->MoveCursorToCrossHair(); OnLeftClick( &dc, GetCrossHairPosition() ); break; case ID_POPUP_SCH_BEGIN_BUS: m_canvas->MoveCursorToCrossHair(); OnLeftClick( &dc, GetCrossHairPosition() ); break; case ID_POPUP_SCH_SET_SHAPE_TEXT: // Not used break; case ID_POPUP_SCH_DELETE_NODE: case ID_POPUP_SCH_DELETE_CONNECTION: m_canvas->MoveCursorToCrossHair(); DeleteConnection( id == ID_POPUP_SCH_DELETE_CONNECTION ); screen->SetCurItem( NULL ); SetRepeatItem( NULL ); screen->TestDanglingEnds( m_canvas, &dc ); m_canvas->Refresh(); break; case ID_POPUP_SCH_BREAK_WIRE: { DLIST< SCH_ITEM > oldWires; oldWires.SetOwnership( false ); // Prevent DLIST for deleting items in destructor. m_canvas->MoveCursorToCrossHair(); screen->ExtractWires( oldWires, true ); screen->BreakSegment( GetCrossHairPosition() ); if( oldWires.GetCount() != 0 ) { PICKED_ITEMS_LIST oldItems; oldItems.m_Status = UR_WIRE_IMAGE; while( oldWires.GetCount() != 0 ) { ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE ); oldItems.PushItem( picker ); } SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE ); } screen->TestDanglingEnds( m_canvas, &dc ); } break; case ID_POPUP_SCH_DELETE_CMP: case ID_POPUP_SCH_DELETE: if( item == NULL ) break; DeleteItem( item ); screen->SetCurItem( NULL ); SetRepeatItem( NULL ); screen->TestDanglingEnds( m_canvas, &dc ); SetSheetNumberAndCount(); OnModify(); break; case ID_POPUP_SCH_END_SHEET: m_canvas->MoveCursorToCrossHair(); addCurrentItemToList( &dc ); break; case ID_POPUP_SCH_RESIZE_SHEET: ReSizeSheet( (SCH_SHEET*) item, &dc ); screen->TestDanglingEnds( m_canvas, &dc ); break; case ID_POPUP_IMPORT_GLABEL: if( item != NULL && item->Type() == SCH_SHEET_T ) screen->SetCurItem( ImportSheetPin( (SCH_SHEET*) item, &dc ) ); break; case ID_POPUP_SCH_CLEANUP_SHEET: if( item != NULL && item->Type() == SCH_SHEET_T ) { SCH_SHEET* sheet = (SCH_SHEET*) item; if( !sheet->HasUndefinedPins() ) { DisplayInfoMessage( this, _( "There are no undefined labels in this sheet to clean up." ) ); return; } if( !IsOK( this, _( "Do you wish to cleanup this sheet?" ) ) ) return; /* Save sheet in undo list before cleaning up unreferenced hierarchical labels. */ SaveCopyInUndoList( sheet, UR_CHANGED ); sheet->CleanupSheet(); OnModify(); m_canvas->RefreshDrawingRect( sheet->GetBoundingBox() ); } break; case ID_POPUP_SCH_INIT_CMP: m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_SCH_EDIT_CONVERT_CMP: // Ensure the struct is a component (could be a struct of a component, like Field, text..) if( item && item->Type() == SCH_COMPONENT_T ) { m_canvas->MoveCursorToCrossHair(); ConvertPart( (SCH_COMPONENT*) item, &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( item && item->Type() == SCH_COMPONENT_T ) { LIB_ALIAS* LibEntry; LibEntry = CMP_LIBRARY::FindLibraryEntry( ( (SCH_COMPONENT*) item )->GetLibName() ); if( LibEntry && LibEntry->GetDocFileName() != wxEmptyString ) { GetAssociatedDocument( this, LibEntry->GetDocFileName(), &wxGetApp().GetLibraryPathList() ); } } break; case ID_POPUP_SCH_ENTER_SHEET: if( item && (item->Type() == SCH_SHEET_T) ) { m_CurrentSheet->Push( (SCH_SHEET*) item ); DisplayCurrentSheet(); } break; case ID_POPUP_SCH_LEAVE_SHEET: m_CurrentSheet->Pop(); DisplayCurrentSheet(); break; case wxID_COPY: // really this is a Save block for paste screen->m_BlockLocate.SetCommand( BLOCK_SAVE ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_PLACE_BLOCK: m_canvas->SetAutoPanRequest( false ); m_canvas->MoveCursorToCrossHair(); HandleBlockPlace( &dc ); break; case ID_POPUP_ZOOM_BLOCK: screen->m_BlockLocate.SetCommand( BLOCK_ZOOM ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: m_canvas->MoveCursorToCrossHair(); screen->m_BlockLocate.SetCommand( BLOCK_DELETE ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); SetSheetNumberAndCount(); break; case ID_POPUP_COPY_BLOCK: m_canvas->MoveCursorToCrossHair(); screen->m_BlockLocate.SetCommand( BLOCK_COPY ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DRAG_BLOCK: m_canvas->MoveCursorToCrossHair(); screen->m_BlockLocate.SetCommand( BLOCK_DRAG ); screen->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_SCH_ADD_JUNCTION: m_canvas->MoveCursorToCrossHair(); screen->SetCurItem( AddJunction( &dc, GetCrossHairPosition(), true ) ); screen->TestDanglingEnds( m_canvas, &dc ); screen->SetCurItem( NULL ); break; case ID_POPUP_SCH_ADD_LABEL: case ID_POPUP_SCH_ADD_GLABEL: screen->SetCurItem( CreateNewText( &dc, id == ID_POPUP_SCH_ADD_LABEL ? LAYER_LOCLABEL : LAYER_GLOBLABEL ) ); item = screen->GetCurItem(); if( item ) addCurrentItemToList( &dc ); break; case ID_POPUP_SCH_GETINFO_MARKER: if( item && item->Type() == SCH_MARKER_T ) ( (SCH_MARKER*) item )->DisplayMarkerInfo( this ); break; default: // Log error: wxFAIL_MSG( wxString::Format( wxT( "Cannot process command event ID %d" ), event.GetId() ) ); break; } // End switch ( id ) (Command execution) if( GetToolId() == ID_NO_TOOL_SELECTED ) SetRepeatItem( NULL ); }
void SCH_EDIT_FRAME::OnMoveItem( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ) { // trying to move an item when there is a block at the same time is not acceptable return; } if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::MovableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } INSTALL_UNBUFFERED_DC( dc, m_canvas ); switch( item->Type() ) { case SCH_LINE_T: break; case SCH_JUNCTION_T: case SCH_NO_CONNECT_T: case SCH_BUS_BUS_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_TEXT_T: case SCH_COMPONENT_T: case SCH_SHEET_PIN_T: case SCH_FIELD_T: MoveItem( item, &dc ); break; case SCH_BITMAP_T: MoveImage( (SCH_BITMAP*) item, &dc ); break; case SCH_SHEET_T: StartMoveSheet( (SCH_SHEET*) item, &dc ); break; case SCH_MARKER_T: default: wxFAIL_MSG( wxString::Format( wxT( "Cannot move item type %s" ), GetChars( item->GetClass() ) ) ); break; } if( GetToolId() == ID_NO_TOOL_SELECTED ) SetRepeatItem( NULL ); }
void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); // The easiest way to handle a menu or a hot key drag command // is to simulate a block drag command // // When a drag item is requested, some items use a BLOCK_DRAG_ITEM drag type // an some items use a BLOCK_DRAG drag type (mainly a junction) // a BLOCK_DRAG collects all items in a block (here a 2x2 rect centered on the cursor) // and BLOCK_DRAG_ITEM drag only the selected item BLOCK_COMMAND_T dragType = BLOCK_DRAG_ITEM; if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::DraggableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; // When a junction or a node is found, a BLOCK_DRAG is better if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false ) || m_collectedItems.IsDraggableJunction() ) dragType = BLOCK_DRAG; } switch( item->Type() ) { case SCH_BUS_BUS_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T: case SCH_LINE_T: case SCH_JUNCTION_T: case SCH_COMPONENT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_SHEET_T: m_canvas->MoveCursorToCrossHair(); if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK ) { INSTALL_UNBUFFERED_DC( dc, m_canvas ); if( !HandleBlockBegin( &dc, dragType, GetCrossHairPosition() ) ) break; // Give a non null size to the search block: screen->m_BlockLocate.Inflate( 1 ); HandleBlockEnd( &dc ); } break; default: wxFAIL_MSG( wxString::Format( wxT( "Cannot drag schematic item type %s." ), GetChars( item->GetClass() ) ) ); } }
void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey ) { wxRealPoint gridSize; SCH_SCREEN* screen = GetScreen(); wxPoint oldpos; wxPoint pos = aPosition; // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed // for next cursor position // ( shift or ctrl key down are PAN command with mouse wheel) bool snapToGrid = true; if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) ) snapToGrid = false; // Cursor is left off grid only if no block in progress if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK ) snapToGrid = true; if( snapToGrid ) pos = screen->GetNearestGridPosition( pos ); oldpos = screen->GetCrossHairPosition(); gridSize = screen->GetGridSize(); switch( aHotKey ) { case 0: break; case WXK_NUMPAD8: case WXK_UP: pos.y -= KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD2: case WXK_DOWN: pos.y += KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD4: case WXK_LEFT: pos.x -= KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD6: case WXK_RIGHT: pos.x += KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; default: break; } // Update cursor position. screen->SetCrossHairPosition( pos, snapToGrid ); if( oldpos != screen->GetCrossHairPosition() ) { pos = screen->GetCrossHairPosition(); screen->SetCrossHairPosition( oldpos, false); m_canvas->CrossHairOff( aDC ); screen->SetCrossHairPosition( pos, snapToGrid ); m_canvas->CrossHairOn( aDC ); if( m_canvas->IsMouseCaptured() ) { #ifdef USE_WX_OVERLAY wxDCOverlay oDC( m_overlay, (wxWindowDC*)aDC ); oDC.Clear(); m_canvas->CallMouseCapture( aDC, aPosition, false ); #else m_canvas->CallMouseCapture( aDC, aPosition, true ); #endif } #ifdef USE_WX_OVERLAY else { m_overlay.Reset(); } #endif } if( aHotKey ) { if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() ) OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() ); else OnHotKey( aDC, aHotKey, aPosition, NULL ); } UpdateStatusBar(); /* Display cursor coordinates info */ }
/* * Hot keys. Some commands are relative to the item under the mouse cursor * Commands are case insensitive */ bool SCH_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, EDA_ITEM* aItem ) { if( aHotKey == 0 ) return false; wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); 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(); // blocInProgress == false means no block in progress. // Because a drag command uses a drag block, false means also no drag in progress // If false, we can ask for editing a new item bool blocInProgress = screen->m_BlockLocate.GetState() != STATE_NO_BLOCK; // 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) && (!blocInProgress); /* Convert lower to upper case (the usual toupper function has problem * with non ascii codes like function keys */ if( (aHotKey >= 'a') && (aHotKey <= 'z') ) aHotKey += 'A' - 'a'; // Search command from key : EDA_HOTKEY* hotKey = GetDescriptorFromHotkey( aHotKey, common_Hotkey_List ); if( hotKey == NULL ) hotKey = GetDescriptorFromHotkey( aHotKey, schematic_Hotkey_List ); if( hotKey == NULL ) return false; switch( hotKey->m_Idcommand ) { default: case HK_NOT_FOUND: return false; case HK_HELP: // Display Current hotkey list DisplayHotkeyList( this, g_Schematic_Hokeys_Descr ); break; case HK_RESET_LOCAL_COORD: // Reset the relative coord GetScreen()->m_O_Curseur = GetCrossHairPosition(); break; case ID_HOTKEY_HIGHLIGHT: if( notBusy ) HighlightConnectionAtPosition( GetCrossHairPosition() ); break; case HK_LEFT_CLICK: case HK_LEFT_DCLICK: // Simulate a double left click: generate 2 events if( screen->m_BlockLocate.GetState() == STATE_BLOCK_MOVE ) { GetCanvas()->SetAutoPanRequest( false ); HandleBlockPlace( aDC ); } else if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK ) { OnLeftClick( aDC, aPosition ); if( hotKey->m_Idcommand == HK_LEFT_DCLICK ) OnLeftDClick( aDC, aPosition ); } break; case HK_ZOOM_IN: case HK_ZOOM_OUT: case HK_ZOOM_REDRAW: case HK_ZOOM_CENTER: case HK_ZOOM_AUTO: case HK_ZOOM_SELECTION: case HK_MOVEBLOCK_TO_DRAGBLOCK: // Switch to drag mode, when block moving case HK_SAVE_BLOCK: // Copy block to paste buffer. cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); break; case HK_DELETE: if( notBusy ) DeleteItemAtCrossHair( aDC ); break; case HK_REPEAT_LAST: if( notBusy ) RepeatDrawItem( aDC ); break; case HK_END_CURR_LINEWIREBUS: // this key terminates a new line/bus/wire in progress if( aItem && aItem->IsNew() && aItem->Type() == SCH_LINE_T ) { cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); } break; case HK_UNDO: // Hot keys that map to command IDs that cannot be called case HK_REDO: // while busy performing another command. case HK_FIND_ITEM: case HK_FIND_REPLACE: case HK_DELETE_NODE: case HK_LEAVE_SHEET: if( notBusy ) { cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); } break; case HK_FIND_NEXT_ITEM: case HK_FIND_NEXT_DRC_MARKER: if( notBusy ) { wxFindDialogEvent event( hotKey->m_IdMenuEvent, GetId() ); event.SetEventObject( this ); event.SetFlags( m_findReplaceData->GetFlags() ); event.SetFindString( m_findReplaceData->GetFindString() ); GetEventHandler()->ProcessEvent( event ); } break; case HK_ADD_NEW_COMPONENT: // Add component case HK_ADD_NEW_POWER: // Add power component case HK_ADD_LABEL: case HK_ADD_HLABEL: case HK_ADD_GLABEL: case HK_ADD_JUNCTION: case HK_ADD_WIRE_ENTRY: case HK_ADD_BUS_ENTRY: case HK_ADD_HIER_SHEET: case HK_ADD_GRAPHIC_TEXT: case HK_ADD_GRAPHIC_POLYLINE: case HK_ADD_NOCONN_FLAG: // Add a no connected flag case HK_BEGIN_BUS: case HK_BEGIN_WIRE: if( notBusy ) { EDA_HOTKEY_CLIENT_DATA data( aPosition ); cmd.SetInt( aHotKey ); cmd.SetClientObject( &data ); cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); } else if( aItem && aItem->IsNew() ) { // If the item is a bus or a wire, a begin command is not possible. if( (GetToolId() == ID_BUS_BUTT) && (aItem->Type() == SCH_LINE_T) ) { SCH_LINE* segment = (SCH_LINE*) aItem; if( segment->GetLayer() != LAYER_BUS ) break; // Bus in progress: OnLeftClick( aDC, aPosition ); } else if( (GetToolId() == ID_WIRE_BUTT ) && (aItem->Type() == SCH_LINE_T) ) { SCH_LINE* segment = (SCH_LINE*) aItem; if( segment->GetLayer() != LAYER_WIRE ) break; // Wire in progress: OnLeftClick( aDC, aPosition ); } } break; case HK_COPY_COMPONENT_OR_LABEL: // Duplicate component or text/label if( itemInEdit ) break; if( aItem == NULL ) { aItem = LocateAndShowItem( aPosition, SCH_COLLECTOR::CopyableItems ); if( aItem == NULL ) break; } cmd.SetId( hotKey->m_IdMenuEvent ); wxPostEvent( this, cmd ); break; case HK_DRAG: // Start drag case HK_MOVE_COMPONENT_OR_ITEM: // Start move schematic item. if( ! notBusy ) break; // Fall through case HK_EDIT: // Edit schematic item. Do not allow sheet edition when mowing // Because a sheet edition can be complex. if( itemInEdit && screen->GetCurItem()->Type() == SCH_SHEET_T ) break; // Fall through case HK_EDIT_COMPONENT_VALUE: // Edit component value field. case HK_EDIT_COMPONENT_REFERENCE: // Edit component value reference. case HK_EDIT_COMPONENT_FOOTPRINT: // Edit component footprint field. case HK_MIRROR_Y: // Mirror Y case HK_MIRROR_X: // Mirror X case HK_ORIENT_NORMAL_COMPONENT: // Orient 0, no mirror (Component) case HK_ROTATE: // Rotate schematic item. case HK_EDIT_COMPONENT_WITH_LIBEDIT: // Call Libedit and load the current component case HK_AUTOPLACE_FIELDS: // Autoplace all fields around component { // force a new item search on hot keys at current position, // if there is no currently edited item, // to avoid using a previously selected item if( ! itemInEdit ) screen->SetCurItem( NULL ); EDA_HOTKEY_CLIENT_DATA data( aPosition ); cmd.SetInt( hotKey->m_Idcommand ); cmd.SetClientObject( &data ); cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); } break; } // Hot key handled. return true; }
/* * OnConvertTextType is a command event handler to change a text type to an other one. * The new text, label, hierarchical label, or global label is created from the old text * The old text is deleted. * A tricky case is when the 'old" text is being edited (i.e. moving) * because we must create a new text, and prepare the undo/redo command data for this * change and the current move/edit command */ void SCH_EDIT_FRAME::OnConvertTextType( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_TEXT* text = (SCH_TEXT*) screen->GetCurItem(); wxCHECK_RET( (text != NULL) && text->CanIncrementLabel(), wxT( "Cannot convert text type." ) ); KICAD_T type; switch( aEvent.GetId() ) { case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_LABEL: type = SCH_LABEL_T; break; case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_GLABEL: type = SCH_GLOBAL_LABEL_T; break; case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_HLABEL: type = SCH_HIERARCHICAL_LABEL_T; break; case ID_POPUP_SCH_CHANGE_TYPE_TEXT_TO_COMMENT: type = SCH_TEXT_T; break; default: wxFAIL_MSG( wxString::Format( wxT( "Invalid text type command ID %d." ), aEvent.GetId() ) ); return; } if( text->Type() == type ) return; SCH_TEXT* newtext; const wxPoint &position = text->GetPosition(); const wxString &txt = text->GetText(); switch( type ) { case SCH_LABEL_T: newtext = new SCH_LABEL( position, txt ); break; case SCH_GLOBAL_LABEL_T: newtext = new SCH_GLOBALLABEL( position, txt ); break; case SCH_HIERARCHICAL_LABEL_T: newtext = new SCH_HIERLABEL( position, txt ); break; case SCH_TEXT_T: newtext = new SCH_TEXT( position, txt ); break; default: newtext = NULL; wxFAIL_MSG( wxString::Format( wxT( "Cannot convert text type to %d" ), type ) ); return; } /* Copy the old text item settings to the new one. Justifications are not copied because * they are not used in labels. Justifications will be set to default value in the new * text item type. */ newtext->SetFlags( text->GetFlags() ); newtext->SetShape( text->GetShape() ); newtext->SetOrientation( text->GetOrientation() ); newtext->SetSize( text->GetSize() ); newtext->SetThickness( text->GetThickness() ); newtext->SetItalic( text->IsItalic() ); newtext->SetBold( text->IsBold() ); /* Save the new text in undo list if the old text was not itself a "new created text" * In this case, the old text is already in undo list as a deleted item. * Of course if the old text was a "new created text" the new text will be * put in undo list later, at the end of the current command (if not aborted) */ INSTALL_UNBUFFERED_DC( dc, m_canvas ); m_canvas->CrossHairOff( &dc ); // Erase schematic cursor text->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode ); // For an exiting item (i.e. already in list): // replace the existing item by the new text in list for( SCH_ITEM* item = screen->GetDrawItems(); item != NULL; item = item->Next() ) { if( item == text ) { screen->Remove( text ); screen->Append( newtext ); break; } } SetRepeatItem( NULL ); OnModify(); newtext->Draw( m_canvas, &dc, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); m_canvas->CrossHairOn( &dc ); // redraw schematic cursor // if the old item is the current schematic item, replace it by the new text: if( screen->GetCurItem() == text ) screen->SetCurItem( newtext ); if( text->IsNew() ) { // if the previous text is new, no undo command to prepare here // just delete this previous text. delete text; return; } // previous text is not new and we replace text by new text. // So this is equivalent to delete text and add newtext // If text if being currently edited (i.e. moved) // we also save the initial copy of text, and prepare undo command for new text modifications. // we must save it as modified text,if it is currently edited, then save as deleted text, // and replace text with newtext PICKED_ITEMS_LIST pickList; ITEM_PICKER picker( text, UR_CHANGED ); if( text->GetFlags() ) { // text is being edited, save initial text for undo command picker.SetLink( GetUndoItem() ); pickList.PushItem( picker ); // the owner of undoItem is no more "this", it is now "picker": SetUndoItem( NULL ); // save current newtext copy for undo/abort current command SetUndoItem( newtext ); } // Prepare undo command for delete old text picker.SetStatus( UR_DELETED ); picker.SetLink( NULL ); pickList.PushItem( picker ); // Prepare undo command for new text picker.SetStatus( UR_NEW ); picker.SetItem(newtext); pickList.PushItem( picker ); SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); }
void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); INSTALL_UNBUFFERED_DC( dc, m_canvas ); // Allows block rotate operation on hot key. if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ) { screen->m_BlockLocate.SetCommand( BLOCK_ROTATE ); HandleBlockEnd( &dc ); return; } if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::RotatableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } switch( item->Type() ) { case SCH_COMPONENT_T: { SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item ); if( aEvent.GetId() == ID_SCH_ROTATE_CLOCKWISE ) OrientComponent( CMP_ROTATE_CLOCKWISE ); else if( aEvent.GetId() == ID_SCH_ROTATE_COUNTERCLOCKWISE ) OrientComponent( CMP_ROTATE_COUNTERCLOCKWISE ); else wxFAIL_MSG( wxT( "Unknown rotate item command ID." ) ); if( m_autoplaceFields ) component->AutoAutoplaceFields( GetScreen() ); m_canvas->Refresh(); break; } case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: m_canvas->MoveCursorToCrossHair(); ChangeTextOrient( (SCH_TEXT*) item ); m_canvas->Refresh(); break; case SCH_FIELD_T: m_canvas->MoveCursorToCrossHair(); RotateField( (SCH_FIELD*) item ); if( item->GetParent()->Type() == SCH_COMPONENT_T ) { // Now that we're moving a field, they're no longer autoplaced. SCH_COMPONENT *parent = static_cast<SCH_COMPONENT*>( item->GetParent() ); parent->ClearFieldsAutoplaced(); } m_canvas->Refresh(); break; case SCH_BITMAP_T: RotateImage( (SCH_BITMAP*) item ); break; case SCH_SHEET_T: if( !item->IsNew() ) // rotate a sheet during its creation has no sense { bool retCCW = ( aEvent.GetId() == ID_SCH_ROTATE_COUNTERCLOCKWISE ); RotateHierarchicalSheet( static_cast<SCH_SHEET*>( item ), retCCW ); } break; case SCH_JUNCTION_T: case SCH_NO_CONNECT_T: // these items are not rotated, because rotation does not change them. break; default: // Other items (wires...) cannot be rotated, at least during creation if( item->IsNew() ) break; wxFAIL_MSG( wxString::Format( wxT( "Cannot rotate schematic item type %s." ), GetChars( item->GetClass() ) ) ); } if( item->GetFlags() == 0 ) screen->SetCurItem( NULL ); }
void SCH_EDIT_FRAME::OnMoveItem( wxCommandEvent& aEvent ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ) { // trying to move an item when there is a block at the same time is not acceptable return; } if( item == NULL ) { // If we didn't get here by a hot key, then something has gone wrong. if( aEvent.GetInt() == 0 ) return; EDA_HOTKEY_CLIENT_DATA* data = (EDA_HOTKEY_CLIENT_DATA*) aEvent.GetClientObject(); wxCHECK_RET( data != NULL, wxT( "Invalid hot key client object." ) ); item = LocateAndShowItem( data->GetPosition(), SCH_COLLECTOR::MovableItems, aEvent.GetInt() ); // Exit if no item found at the current location or the item is already being edited. if( (item == NULL) || (item->GetFlags() != 0) ) return; } INSTALL_UNBUFFERED_DC( dc, m_canvas ); switch( item->Type() ) { case SCH_LINE_T: break; case SCH_JUNCTION_T: case SCH_NO_CONNECT_T: case SCH_BUS_BUS_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_TEXT_T: case SCH_COMPONENT_T: case SCH_SHEET_PIN_T: case SCH_FIELD_T: case SCH_SHEET_T: PrepareMoveItem( item, &dc ); break; case SCH_BITMAP_T: // move an image is a special case: // we cannot undraw/redraw a bitmap just using our xor mode // the MoveImage function handle this undraw/redraw difficulty // By redrawing the full bounding box MoveImage( (SCH_BITMAP*) item, &dc ); break; case SCH_MARKER_T: // Moving a marker has no sense break; default: // Unknown items cannot be moved wxFAIL_MSG( wxString::Format( wxT( "Cannot move item type %d" ), item->Type() ) ); break; } if( GetToolId() == ID_NO_TOOL_SELECTED ) SetRepeatItem( NULL ); }
bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey ) { // Filter out the 'fake' mouse motion after a keyboard movement if( !aHotKey && m_movingCursorWithKeyboard ) { m_movingCursorWithKeyboard = false; return false; } // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed // for next cursor position // ( shift or ctrl key down are PAN command with mouse wheel) bool snapToGrid = true; if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) ) snapToGrid = false; // Cursor is left off grid only if no block in progress if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK ) snapToGrid = true; wxPoint pos = aPosition; bool keyHandled = GeneralControlKeyMovement( aHotKey, &pos, snapToGrid ); if( GetToolId() == ID_NO_TOOL_SELECTED ) m_canvas->CrossHairOff( aDC ); else m_canvas->CrossHairOn( aDC ); GetGalCanvas()->GetViewControls()->SetSnapping( snapToGrid ); SetCrossHairPosition( pos, snapToGrid ); if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( aDC, aPosition, true ); if( aHotKey ) { if( m_movingCursorWithKeyboard ) // The hotkey was a move crossahir cursor command { // The crossair was moved. move the mouse cursor to the new crosshair position: GetGalCanvas()->GetViewControls()->WarpCursor( GetCrossHairPosition(), true ); m_movingCursorWithKeyboard = 0; } else { SCH_SCREEN* screen = GetScreen(); bool hk_handled; if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() ) hk_handled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() ); else hk_handled = OnHotKey( aDC, aHotKey, aPosition, NULL ); if( hk_handled ) keyHandled = true; } } UpdateStatusBar(); /* Display cursor coordinates info */ return keyHandled; }
void LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey ) { wxRealPoint gridSize; SCH_SCREEN* screen = GetScreen(); wxPoint oldpos; wxPoint pos = aPosition; pos = screen->GetNearestGridPosition( pos ); oldpos = screen->GetCrossHairPosition(); gridSize = screen->GetGridSize(); switch( aHotKey ) { case 0: break; case WXK_NUMPAD8: case WXK_UP: pos.y -= KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD2: case WXK_DOWN: pos.y += KiROUND( gridSize.y ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD4: case WXK_LEFT: pos.x -= KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; case WXK_NUMPAD6: case WXK_RIGHT: pos.x += KiROUND( gridSize.x ); m_canvas->MoveCursor( pos ); break; default: break; } // Update cursor position. screen->SetCrossHairPosition( pos ); if( oldpos != screen->GetCrossHairPosition() ) { pos = screen->GetCrossHairPosition(); screen->SetCrossHairPosition( oldpos ); m_canvas->CrossHairOff( aDC ); screen->SetCrossHairPosition( pos ); m_canvas->CrossHairOn( aDC ); if( m_canvas->IsMouseCaptured() ) { m_canvas->CallMouseCapture( aDC, aPosition, true ); } } if( aHotKey ) { if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() ) OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() ); else OnHotKey( aDC, aHotKey, aPosition, NULL ); } UpdateStatusBar(); }
void SCH_EDIT_FRAME::EndSegment( wxDC* DC ) { SCH_SCREEN* screen = GetScreen(); SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem(); if( segment == NULL || segment->Type() != SCH_LINE_T || !segment->IsNew() ) return; // Delete zero length segments and clear item flags. SCH_ITEM* item = s_wires.begin(); while( item ) { item->ClearFlags(); wxCHECK_RET( item->Type() == SCH_LINE_T, wxT( "Unexpected object type in wire list." ) ); segment = (SCH_LINE*) item; item = item->Next(); if( segment->IsNull() ) delete s_wires.Remove( segment ); } if( s_wires.GetCount() == 0 ) return; // Get the last non-null wire (this is the last created segment). SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() ); screen->SetCurItem( NULL ); m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false ); // store the terminal point of this last segment: a junction could be needed // (the last wire could be merged/deleted/modified, and lost) wxPoint endpoint = segment->GetEndPoint(); // store the starting point of this first segment: a junction could be needed SCH_LINE* firstsegment = (SCH_LINE*) s_wires.GetFirst(); wxPoint startPoint = firstsegment->GetStartPoint(); // Save the old wires for the undo command DLIST< SCH_ITEM > oldWires; // stores here the old wires GetScreen()->ExtractWires( oldWires, true ); // Save them in oldWires list // Put the snap shot of the previous wire, buses, and junctions in the undo/redo list. PICKED_ITEMS_LIST oldItems; oldItems.m_Status = UR_WIRE_IMAGE; while( oldWires.GetCount() != 0 ) { ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE ); oldItems.PushItem( picker ); } SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE ); // Remove segments backtracking over others RemoveBacktracks( s_wires ); // Add the new wires screen->Append( s_wires ); // Correct and remove segments that need to be merged. screen->SchematicCleanUp(); // A junction could be needed to connect the end point of the last created segment. if( screen->IsJunctionNeeded( endpoint ) ) screen->Append( AddJunction( DC, endpoint ) ); // A junction could be needed to connect the start point of the set of new created wires if( screen->IsJunctionNeeded( startPoint ) ) screen->Append( AddJunction( DC, startPoint ) ); m_canvas->Refresh(); OnModify(); }
void SCH_EDIT_FRAME::addCurrentItemToList( wxDC* aDC ) { SCH_SCREEN* screen = GetScreen(); SCH_ITEM* item = screen->GetCurItem(); wxCHECK_RET( item != NULL, wxT( "Cannot add current item to list." ) ); m_canvas->SetAutoPanRequest( false ); SCH_ITEM* undoItem = item; if( item->Type() == SCH_SHEET_PIN_T ) { SCH_SHEET* sheet = (SCH_SHEET*) item->GetParent(); wxCHECK_RET( (sheet != NULL) && (sheet->Type() == SCH_SHEET_T), wxT( "Cannot place sheet pin in invalid schematic sheet object." ) ); undoItem = sheet; } else if( item->Type() == SCH_FIELD_T ) { SCH_COMPONENT* cmp = (SCH_COMPONENT*) item->GetParent(); wxCHECK_RET( (cmp != NULL) && (cmp->Type() == SCH_COMPONENT_T), wxT( "Cannot place field in invalid schematic component object." ) ); undoItem = cmp; } if( item->IsNew() ) { if( item->Type() == SCH_SHEET_T ) { // Fix the size and position of the new sheet using the last values set by // the m_mouseCaptureCallback function. m_canvas->SetMouseCapture( NULL, NULL ); if( !EditSheet( (SCH_SHEET*)item, aDC ) ) { screen->SetCurItem( NULL ); item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); delete item; return; } SetSheetNumberAndCount(); } if( undoItem == item ) { if( !screen->CheckIfOnDrawList( item ) ) // don't want a loop! screen->Append( item ); SetRepeatItem( item ); SaveCopyInUndoList( undoItem, UR_NEW ); } else { // Here, item is not a basic schematic item, but an item inside // a parent basic schematic item, // currently: sheet pin or component field. // currently, only a sheet pin can be found as new item, // because new component fields have a specific handling, and do not appears here SaveCopyInUndoList( undoItem, UR_CHANGED ); if( item->Type() == SCH_SHEET_PIN_T ) ( (SCH_SHEET*)undoItem )->AddPin( (SCH_SHEET_PIN*) item ); else wxLogMessage(wxT( "addCurrentItemToList: expected type = SCH_SHEET_PIN_T, actual type = %d" ), item->Type() ); } } else { SaveUndoItemInUndoList( undoItem ); } // Erase the wire representation before the 'normal' view is drawn. if ( item->IsWireImage() ) item->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode ); item->ClearFlags(); screen->SetModify(); screen->SetCurItem( NULL ); m_canvas->SetMouseCapture( NULL, NULL ); m_canvas->EndMouseCapture(); if( item->IsConnectable() ) screen->TestDanglingEnds(); if( aDC ) { EDA_CROSS_HAIR_MANAGER( m_canvas, aDC ); // Erase schematic cursor undoItem->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE ); } }