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 ); }
XNODE* NETLIST_EXPORTER_GENERIC::makeDesignHeader() { SCH_SCREEN* screen; XNODE* xdesign = node( wxT( "design" ) ); XNODE* xtitleBlock; XNODE* xsheet; XNODE* xcomment; wxString sheetTxt; wxFileName sourceFileName; // the root sheet is a special sheet, call it source xdesign->AddChild( node( wxT( "source" ), g_RootSheet->GetScreen()->GetFileName() ) ); xdesign->AddChild( node( wxT( "date" ), DateAndTime() ) ); // which Eeschema tool xdesign->AddChild( node( wxT( "tool" ), wxT( "Eeschema " ) + GetBuildVersion() ) ); /* Export the sheets information */ SCH_SHEET_LIST sheetList( g_RootSheet ); for( unsigned i = 0; i < sheetList.size(); i++ ) { screen = sheetList[i].LastScreen(); xdesign->AddChild( xsheet = node( wxT( "sheet" ) ) ); // get the string representation of the sheet index number. // Note that sheet->GetIndex() is zero index base and we need to increment the // number by one to make it human readable sheetTxt.Printf( wxT( "%u" ), i + 1 ); xsheet->AddAttribute( wxT( "number" ), sheetTxt ); xsheet->AddAttribute( wxT( "name" ), sheetList[i].PathHumanReadable() ); xsheet->AddAttribute( wxT( "tstamps" ), sheetList[i].Path() ); TITLE_BLOCK tb = screen->GetTitleBlock(); xsheet->AddChild( xtitleBlock = node( wxT( "title_block" ) ) ); xtitleBlock->AddChild( node( wxT( "title" ), tb.GetTitle() ) ); xtitleBlock->AddChild( node( wxT( "company" ), tb.GetCompany() ) ); xtitleBlock->AddChild( node( wxT( "rev" ), tb.GetRevision() ) ); xtitleBlock->AddChild( node( wxT( "date" ), tb.GetDate() ) ); // We are going to remove the fileName directories. sourceFileName = wxFileName( screen->GetFileName() ); xtitleBlock->AddChild( node( wxT( "source" ), sourceFileName.GetFullName() ) ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("1") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment1() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("2") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment2() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("3") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment3() ); xtitleBlock->AddChild( xcomment = node( wxT( "comment" ) ) ); xcomment->AddAttribute( wxT("number"), wxT("4") ); xcomment->AddAttribute( wxT( "value" ), tb.GetComment4() ); } return xdesign; }
bool DIALOG_SYMBOL_REMAP::backupProject( REPORTER& aReporter ) { static wxString backupFolder = "rescue-backup"; wxString tmp; wxString errorMsg; wxFileName srcFileName; wxFileName destFileName; wxFileName backupPath; SCH_SCREENS schematic; // Copy backup files to different folder so as not to pollute the project folder. destFileName.SetPath( Prj().GetProjectPath() ); destFileName.AppendDir( backupFolder ); backupPath = destFileName; if( !destFileName.DirExists() ) { if( !destFileName.Mkdir() ) { errorMsg.Printf( _( "Cannot create project remap back up folder \"%s\"." ), destFileName.GetPath() ); wxMessageDialog dlg( this, errorMsg, _( "Backup Error" ), wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION ); dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ), wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) ); if( dlg.ShowModal() == wxID_NO ) return false; } } // Time stamp to append to file name in case multiple remappings are performed. wxString timeStamp = wxDateTime::Now().Format( "-%Y-%m-%d-%H-%M-%S" ); // Back up symbol library table. srcFileName.SetPath( Prj().GetProjectPath() ); srcFileName.SetName( SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() ); destFileName = srcFileName; destFileName.AppendDir( backupFolder ); destFileName.SetName( destFileName.GetName() + timeStamp ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( wxFileName::Exists( srcFileName.GetFullPath() ) && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the schematic files. for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() ) { destFileName = screen->GetFileName(); destFileName.SetName( destFileName.GetName() + timeStamp ); // Check for nest hierarchical schematic paths. if( destFileName.GetPath() != backupPath.GetPath() ) { destFileName.SetPath( backupPath.GetPath() ); wxArrayString srcDirs = wxFileName( screen->GetFileName() ).GetDirs(); wxArrayString destDirs = wxFileName( Prj().GetProjectPath() ).GetDirs(); for( size_t i = destDirs.GetCount(); i < srcDirs.GetCount(); i++ ) destFileName.AppendDir( srcDirs[i] ); } else { destFileName.AppendDir( backupFolder ); } tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), screen->GetFileName(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( !destFileName.DirExists() && !destFileName.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) ) { tmp.Printf( _( "Failed to create backup folder \"%s\"\n" ), destFileName.GetPath() ); errorMsg += tmp; continue; } if( wxFileName::Exists( screen->GetFileName() ) && !wxCopyFile( screen->GetFileName(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), screen->GetFileName() ); errorMsg += tmp; } } // Back up the project file. destFileName = Prj().GetProjectFullName(); destFileName.SetName( destFileName.GetName() + timeStamp ); destFileName.AppendDir( backupFolder ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), Prj().GetProjectFullName(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( wxFileName::Exists( Prj().GetProjectFullName() ) && !wxCopyFile( Prj().GetProjectFullName(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), Prj().GetProjectFullName() ); errorMsg += tmp; } // Back up the cache library. srcFileName.SetPath( Prj().GetProjectPath() ); srcFileName.SetName( Prj().GetProjectName() + "-cache" ); srcFileName.SetExt( SchematicLibraryFileExtension ); destFileName = srcFileName; destFileName.SetName( destFileName.GetName() + timeStamp ); destFileName.AppendDir( backupFolder ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the rescue symbol library if it exists. srcFileName.SetName( Prj().GetProjectName() + "-rescue" ); destFileName.SetName( srcFileName.GetName() + timeStamp ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the rescue symbol library document file if it exists. srcFileName.SetExt( "dcm" ); destFileName.SetExt( srcFileName.GetExt() ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } if( !errorMsg.IsEmpty() ) { wxMessageDialog dlg( this, _( "Some of the project files could not be backed up." ), _( "Backup Error" ), wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION ); errorMsg.Trim(); dlg.SetExtendedMessage( errorMsg ); dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ), wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) ); if( dlg.ShowModal() == wxID_NO ) return false; } return true; }
bool DIALOG_PAGES_SETTINGS::SavePageSettings() { bool success = false; wxString fileName = GetWksFileName(); if( fileName != BASE_SCREEN::m_PageLayoutDescrFileName ) { wxString fullFileName = WORKSHEET_LAYOUT::MakeFullFileName( fileName, m_projectPath ); if( !fullFileName.IsEmpty() && !wxFileExists( fullFileName ) ) { wxString msg; msg.Printf( _( "Page layout description file \"%s\" not found." ), GetChars( fullFileName ) ); wxMessageBox( msg ); return false; } BASE_SCREEN::m_PageLayoutDescrFileName = fileName; WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); pglayout.SetPageLayout( fullFileName ); m_localPrjConfigChanged = true; } int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 ); const wxString paperType = m_pageFmt[idx]; if( paperType.Contains( PAGE_INFO::Custom ) ) { GetCustomSizeMilsFromDialog(); success = m_pageInfo.SetType( PAGE_INFO::Custom ); if( success ) { PAGE_INFO::SetCustomWidthMils( m_layout_size.x ); PAGE_INFO::SetCustomHeightMils( m_layout_size.y ); m_pageInfo.SetWidthMils( m_layout_size.x ); m_pageInfo.SetHeightMils( m_layout_size.y ); } } else { // search for longest common string first, e.g. A4 before A if( paperType.Contains( PAGE_INFO::USLetter ) ) success = m_pageInfo.SetType( PAGE_INFO::USLetter ); else if( paperType.Contains( PAGE_INFO::USLegal ) ) success = m_pageInfo.SetType( PAGE_INFO::USLegal ); else if( paperType.Contains( PAGE_INFO::USLedger ) ) success = m_pageInfo.SetType( PAGE_INFO::USLedger ); else if( paperType.Contains( PAGE_INFO::GERBER ) ) success = m_pageInfo.SetType( PAGE_INFO::GERBER ); else if( paperType.Contains( PAGE_INFO::A4 ) ) success = m_pageInfo.SetType( PAGE_INFO::A4 ); else if( paperType.Contains( PAGE_INFO::A3 ) ) success = m_pageInfo.SetType( PAGE_INFO::A3 ); else if( paperType.Contains( PAGE_INFO::A2 ) ) success = m_pageInfo.SetType( PAGE_INFO::A2 ); else if( paperType.Contains( PAGE_INFO::A1 ) ) success = m_pageInfo.SetType( PAGE_INFO::A1 ); else if( paperType.Contains( PAGE_INFO::A0 ) ) success = m_pageInfo.SetType( PAGE_INFO::A0 ); else if( paperType.Contains( PAGE_INFO::A ) ) success = m_pageInfo.SetType( PAGE_INFO::A ); else if( paperType.Contains( PAGE_INFO::B ) ) success = m_pageInfo.SetType( PAGE_INFO::B ); else if( paperType.Contains( PAGE_INFO::C ) ) success = m_pageInfo.SetType( PAGE_INFO::C ); else if( paperType.Contains( PAGE_INFO::D ) ) success = m_pageInfo.SetType( PAGE_INFO::D ); else if( paperType.Contains( PAGE_INFO::E ) ) success = m_pageInfo.SetType( PAGE_INFO::E ); if( success ) { int choice = m_orientationComboBox->GetSelection(); m_pageInfo.SetPortrait( choice != 0 ); } } if( !success ) { wxASSERT_MSG( false, _( "the translation for paper size must preserve original spellings" ) ); m_pageInfo.SetType( PAGE_INFO::A4 ); } m_parent->SetPageSettings( m_pageInfo ); m_tb.SetRevision( m_TextRevision->GetValue() ); m_tb.SetDate( m_TextDate->GetValue() ); m_tb.SetCompany( m_TextCompany->GetValue() ); m_tb.SetTitle( m_TextTitle->GetValue() ); m_tb.SetComment1( m_TextComment1->GetValue() ); m_tb.SetComment2( m_TextComment2->GetValue() ); m_tb.SetComment3( m_TextComment3->GetValue() ); m_tb.SetComment4( m_TextComment4->GetValue() ); m_parent->SetTitleBlock( m_tb ); #ifdef EESCHEMA // Exports settings to other sheets if requested: SCH_SCREEN* screen; // Build the screen list SCH_SCREENS ScreenList; // Update title blocks for all screens for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { if( screen == m_screen ) continue; TITLE_BLOCK tb2 = screen->GetTitleBlock(); if( m_RevisionExport->IsChecked() ) tb2.SetRevision( m_tb.GetRevision() ); if( m_DateExport->IsChecked() ) tb2.SetDate( m_tb.GetDate() ); if( m_TitleExport->IsChecked() ) tb2.SetTitle( m_tb.GetTitle() ); if( m_CompanyExport->IsChecked() ) tb2.SetCompany( m_tb.GetCompany() ); if( m_Comment1Export->IsChecked() ) tb2.SetComment1( m_tb.GetComment1() ); if( m_Comment2Export->IsChecked() ) tb2.SetComment2( m_tb.GetComment2() ); if( m_Comment3Export->IsChecked() ) tb2.SetComment3( m_tb.GetComment3() ); if( m_Comment4Export->IsChecked() ) tb2.SetComment4( m_tb.GetComment4() ); screen->SetTitleBlock( tb2 ); } #endif return true; }
bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) { // implement the pseudo code from KIWAY_PLAYER.h: SCH_SCREENS screenList; // This is for python: if( aFileSet.size() != 1 ) { UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename", __func__ ); DisplayError( this, msg ); return false; } wxString fullFileName( aFileSet[0] ); // We insist on caller sending us an absolute path, if it does not, we say it's a bug. wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "bug in single_top.cpp or project manager." ) ); if( !LockFile( fullFileName ) ) { wxString msg = wxString::Format( _( "Schematic file '%s' is already open." ), GetChars( fullFileName ) ); DisplayError( this, msg ); return false; } // save any currently open and modified project files. for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() ) { if( screen->IsModify() ) { int response = YesNoCancelDialog( this, _( "The current schematic has been modified. Do you wish to save the changes?" ), wxEmptyString, _( "Save and Load" ), _( "Load Without Saving" ) ); if( response == wxID_CANCEL ) { return false; } else if( response == wxID_YES ) { wxCommandEvent dummy; OnSaveProject( dummy ); } else { // response == wxID_NO, fall thru } break; } } wxFileName pro = fullFileName; pro.SetExt( ProjectFileExtension ); bool is_new = !wxFileName::IsFileReadable( fullFileName ); // If its a non-existent schematic and caller thinks it exists if( is_new && !( aCtl & KICTL_CREATE ) ) { // notify user that fullFileName does not exist, ask if user wants to create it. wxString ask = wxString::Format( _( "Schematic '%s' does not exist. Do you wish to create it?" ), GetChars( fullFileName ) ); if( !IsOK( this, ask ) ) return false; } // unload current project file before loading new { delete g_RootSheet; g_RootSheet = NULL; CreateScreens(); } GetScreen()->SetFileName( fullFileName ); g_RootSheet->SetFileName( fullFileName ); SetStatusText( wxEmptyString ); ClearMsgPanel(); wxString msg = wxString::Format( _( "Ready\nProject dir: '%s'\n" ), GetChars( wxPathOnly( Prj().GetProjectFullName() ) ) ); SetStatusText( msg ); // PROJECT::SetProjectFullName() is an impactful function. It should only be // called under carefully considered circumstances. // The calling code should know not to ask me here to change projects unless // it knows what consequences that will have on other KIFACEs running and using // this same PROJECT. It can be very harmful if that calling code is stupid. Prj().SetProjectFullName( pro.GetFullPath() ); LoadProjectFile(); // load the libraries here, not in SCH_SCREEN::Draw() which is a context // that will not tolerate DisplayError() dialog since we're already in an // event handler in there. // And when a schematic file is loaded, we need these libs to initialize // some parameters (links to PART LIB, dangling ends ...) Prj().SchLibs(); if( is_new ) { // mark new, unsaved file as modified. GetScreen()->SetModify(); } else { g_RootSheet->SetScreen( NULL ); DBG( printf( "%s: loading schematic %s\n", __func__, TO_UTF8( fullFileName ) );) bool diag = g_RootSheet->Load( this ); (void) diag; SetScreen( m_CurrentSheet->LastScreen() ); GetScreen()->ClrModify(); UpdateFileHistory( fullFileName ); }
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 ); }
bool SCH_EDIT_FRAME::LoadOneEEProject( const wxString& aFileName, bool aIsNew ) { SCH_SCREEN* screen; wxString FullFileName, msg; bool LibCacheExist = false; SCH_SCREENS ScreenList; for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { if( screen->IsModify() ) break; } if( screen ) { int response = YesNoCancelDialog( this, _( "The current schematic has been modified. Do " "you wish to save the changes?" ), wxEmptyString, _( "Save and Load" ), _( "Load Without Saving" ) ); if( response == wxID_CANCEL ) { return false; } else if( response == wxID_YES ) { wxCommandEvent dummy; OnSaveProject( dummy ); } } FullFileName = aFileName; if( FullFileName.IsEmpty() && !aIsNew ) { wxFileDialog dlg( this, _( "Open Schematic" ), wxGetCwd(), wxEmptyString, SchematicFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_CANCEL ) return false; FullFileName = dlg.GetPath(); } wxFileName fn = FullFileName; if( fn.IsRelative() ) { fn.MakeAbsolute(); FullFileName = fn.GetFullPath(); } if( !wxGetApp().LockFile( FullFileName ) ) { DisplayError( this, _( "This file is already open." ) ); return false; } // Clear the screen before open a new file if( g_RootSheet ) { delete g_RootSheet; g_RootSheet = NULL; } CreateScreens(); screen = GetScreen(); wxLogDebug( wxT( "Loading schematic " ) + FullFileName ); wxSetWorkingDirectory( fn.GetPath() ); screen->SetFileName( FullFileName ); g_RootSheet->SetFileName( FullFileName ); SetStatusText( wxEmptyString ); ClearMsgPanel(); screen->ClrModify(); if( aIsNew ) { /* SCH_SCREEN constructor does this now screen->SetPageSettings( PAGE_INFO( wxT( "A4" ) ) ); */ screen->SetZoom( 32 ); screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); TITLE_BLOCK tb; wxString title; title += NAMELESS_PROJECT; title += wxT( ".sch" ); tb.SetTitle( title ); screen->SetTitleBlock( tb ); GetScreen()->SetFileName( title ); LoadProjectFile( wxEmptyString, true ); Zoom_Automatique( false ); SetSheetNumberAndCount(); m_canvas->Refresh(); return true; } // Reloading configuration. msg.Printf( _( "Ready\nWorking dir: <%s>\n" ), GetChars( wxGetCwd() ) ); PrintMsg( msg ); LoadProjectFile( wxEmptyString, false ); // Clear (if needed) the current active library in libedit because it could be // removed from memory LIB_EDIT_FRAME::EnsureActiveLibExists(); // Delete old caches. CMP_LIBRARY::RemoveCacheLibrary(); LibCacheExist = LoadCacheLibrary( g_RootSheet->GetScreen()->GetFileName() ); if( !wxFileExists( g_RootSheet->GetScreen()->GetFileName() ) && !LibCacheExist ) { Zoom_Automatique( false ); msg.Printf( _( "File <%s> not found." ), GetChars( g_RootSheet->GetScreen()->GetFileName() ) ); DisplayInfoMessage( this, msg ); return false; } // load the project. g_RootSheet->SetScreen( NULL ); bool diag = g_RootSheet->Load( this ); SetScreen( m_CurrentSheet->LastScreen() ); UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() ); /* Redraw base screen (ROOT) if necessary. */ GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); Zoom_Automatique( false ); SetSheetNumberAndCount(); m_canvas->Refresh( true ); return diag; }
/* * 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; }
void LIB_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 the 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 ) { OnHotKey( aDC, aHotKey, aPosition, NULL ); } UpdateStatusBar(); }
/* * 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 DIALOG_PLOT_SCHEMATIC::createHPGLFile( bool aPlotAll, bool aPlotFrameRef ) { SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); /* When printing all pages, the printed page is not the current page. * In complex hierarchies, we must setup references and other parameters * in the printed SCH_SCREEN * because in complex hierarchies a SCH_SCREEN (a schematic drawings) * is shared between many sheets */ SCH_SHEET_LIST sheetList; if( aPlotAll ) sheetList.BuildSheetList( g_RootSheet ); else sheetList.push_back( m_parent->GetCurrentSheet() ); REPORTER& reporter = m_MessagesBox->Reporter(); SetHPGLPenWidth(); for( unsigned i = 0; i < sheetList.size(); i++ ) { m_parent->SetCurrentSheet( sheetList[i] ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); if( !screen ) // LastScreen() may return NULL screen = m_parent->GetScreen(); const PAGE_INFO& curPage = screen->GetPageSettings(); PAGE_INFO plotPage = curPage; // if plotting on a page size other than curPage if( m_HPGLPaperSizeOption->GetSelection() != PAGE_DEFAULT ) plotPage.SetType( plot_sheet_list( m_HPGLPaperSizeOption->GetSelection() ) ); // Calculation of conversion scales. double plot_scale = (double) plotPage.GetWidthMils() / curPage.GetWidthMils(); // Calculate offsets wxPoint plotOffset; wxString msg; if( GetPlotOriginCenter() ) { plotOffset.x = plotPage.GetWidthIU() / 2; plotOffset.y = -plotPage.GetHeightIU() / 2; } try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = HPGL_PLOTTER::GetDefaultFileExtension(); wxFileName plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); LOCALE_IO toggle; if( Plot_1_Page_HPGL( plotFileName.GetFullPath(), screen, plotPage, plotOffset, plot_scale, aPlotFrameRef ) ) { msg.Printf( _( "Plot: '%s' OK.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { msg.Printf( _( "Unable to create file '%s'.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } catch( IO_ERROR& e ) { msg.Printf( wxT( "HPGL Plotter exception: %s"), GetChars( e.errorText ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); }
void SCH_SCREENS::TestDanglingEnds() { for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() ) screen->TestDanglingEnds(); }
void SCH_SCREENS::UpdateSymbolLinks( bool aForce ) { for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() ) screen->UpdateSymbolLinks( aForce ); }
void Diagnose( NETLIST_OBJECT* aNetItemRef, NETLIST_OBJECT* aNetItemTst, int aMinConn, int aDiag ) { SCH_MARKER* marker = NULL; SCH_SCREEN* screen; ELECTRICAL_PINTYPE ii, jj; if( aDiag == OK || aMinConn < 1 ) return; /* Create new marker for ERC error. */ marker = new SCH_MARKER(); marker->SetTimeStamp( GetNewTimeStamp() ); marker->SetMarkerType( MARKER_BASE::MARKER_ERC ); marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_WARNING ); screen = aNetItemRef->m_SheetPath.LastScreen(); screen->Append( marker ); wxString msg; ii = aNetItemRef->m_ElectricalPinType; wxString cmp_ref( "?" ); if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link ) cmp_ref = aNetItemRef->GetComponentParent()->GetRef( &aNetItemRef->m_SheetPath ); if( aNetItemTst == NULL ) { if( aMinConn == NOD ) /* Nothing driving the net. */ { if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link ) cmp_ref = aNetItemRef->GetComponentParent()->GetRef( &aNetItemRef->m_SheetPath ); msg.Printf( _( "Pin %s (%s) of component %s is not driven (Net %d)." ), aNetItemRef->m_PinNum, GetChars( GetText( ii ) ), GetChars( cmp_ref ), aNetItemRef->GetNet() ); marker->SetData( ERCE_PIN_NOT_DRIVEN, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); return; } } if( aNetItemTst ) /* Error between 2 pins */ { jj = aNetItemTst->m_ElectricalPinType; int errortype = ERCE_PIN_TO_PIN_WARNING; if( aDiag == ERR ) { marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_ERROR ); errortype = ERCE_PIN_TO_PIN_ERROR; } wxString alt_cmp( "?" ); if( aNetItemTst->m_Type == NET_PIN && aNetItemTst->m_Link ) alt_cmp = aNetItemTst->GetComponentParent()->GetRef( &aNetItemTst->m_SheetPath ); msg.Printf( _( "Pin %s (%s) of component %s is connected to " ), aNetItemRef->m_PinNum, GetChars( GetText( ii ) ), GetChars( cmp_ref ) ); marker->SetData( errortype, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); msg.Printf( _( "pin %s (%s) of component %s (net %d)." ), aNetItemTst->m_PinNum, GetChars( GetText( jj ) ), GetChars( alt_cmp ), aNetItemRef->GetNet() ); marker->SetAuxiliaryData( msg, aNetItemTst->m_Start ); } }
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 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::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 Diagnose( NETLIST_OBJECT* aNetItemRef, NETLIST_OBJECT* aNetItemTst, int aMinConn, int aDiag ) { SCH_MARKER* marker = NULL; SCH_SCREEN* screen; int ii, jj; if( aDiag == OK ) return; /* Create new marker for ERC error. */ marker = new SCH_MARKER(); marker->SetTimeStamp( GetNewTimeStamp() ); marker->SetMarkerType( MARK_ERC ); marker->SetErrorLevel( WAR ); screen = aNetItemRef->m_SheetPath.LastScreen(); screen->Append( marker ); wxString msg; if( aMinConn < 0 ) { if( (aNetItemRef->m_Type == NET_HIERLABEL) || (aNetItemRef->m_Type == NET_HIERBUSLABELMEMBER) ) { msg.Printf( _( "Hierarchical label %s is not connected to a sheet label." ), GetChars( aNetItemRef->m_Label ) ); } else { msg.Printf( _( "Sheet label %s is not connected to a hierarchical label." ), GetChars( aNetItemRef->m_Label ) ); } marker->SetData( ERCE_HIERACHICAL_LABEL, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); return; } ii = aNetItemRef->m_ElectricalType; wxString string_pinnum, cmp_ref; char ascii_buf[5]; ascii_buf[4] = 0; memcpy( ascii_buf, &aNetItemRef->m_PinNum, 4 ); string_pinnum = FROM_UTF8( ascii_buf ); cmp_ref = wxT( "?" ); if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link ) cmp_ref = aNetItemRef->GetComponentParent()->GetRef( &aNetItemRef->m_SheetPath ); if( aNetItemTst == NULL ) { if( aMinConn == NOC ) /* Only 1 element in the net. */ { msg.Printf( _( "Pin %s (%s) of component %s is unconnected." ), GetChars( string_pinnum ), MsgPinElectricType[ii], GetChars( cmp_ref ) ); marker->SetData( ERCE_PIN_NOT_CONNECTED, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); return; } if( aMinConn == NOD ) /* Nothing driving the net. */ { if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link ) cmp_ref = aNetItemRef->GetComponentParent()->GetRef( &aNetItemRef->m_SheetPath ); msg.Printf( _( "Pin %s (%s) of component %s is not driven (Net %d)." ), GetChars( string_pinnum ), MsgPinElectricType[ii], GetChars( cmp_ref ), aNetItemRef->GetNet() ); marker->SetData( ERCE_PIN_NOT_DRIVEN, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); return; } if( aDiag == UNC ) { msg.Printf( _( "More than 1 pin connected to an UnConnect symbol." ) ); marker->SetData( ERCE_NOCONNECT_CONNECTED, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); return; } } if( aNetItemTst ) /* Error between 2 pins */ { jj = aNetItemTst->m_ElectricalType; int errortype = ERCE_PIN_TO_PIN_WARNING; if( aDiag == ERR ) { marker->SetErrorLevel( ERR ); errortype = ERCE_PIN_TO_PIN_ERROR; } wxString alt_string_pinnum, alt_cmp; memcpy( ascii_buf, &aNetItemTst->m_PinNum, 4 ); alt_string_pinnum = FROM_UTF8( ascii_buf ); alt_cmp = wxT( "?" ); if( aNetItemTst->m_Type == NET_PIN && aNetItemTst->m_Link ) alt_cmp = aNetItemTst->GetComponentParent()->GetRef( &aNetItemTst->m_SheetPath ); msg.Printf( _( "Pin %s (%s) of component %s is connected to " ), GetChars( string_pinnum ), MsgPinElectricType[ii], GetChars( cmp_ref ) ); marker->SetData( errortype, aNetItemRef->m_Start, msg, aNetItemRef->m_Start ); msg.Printf( _( "pin %s (%s) of component %s (net %d)." ), GetChars( alt_string_pinnum ), MsgPinElectricType[jj], GetChars( alt_cmp ), aNetItemRef->GetNet() ); marker->SetAuxiliaryData( msg, aNetItemTst->m_Start ); } }
void DIALOG_PLOT_SCHEMATIC::createPSFile( bool aPlotAll, bool aPlotFrameRef ) { SCH_SCREEN* screen = m_parent->GetScreen(); SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); // sheetpath is saved here PAGE_INFO actualPage; // page size selected in schematic PAGE_INFO plotPage; // page size selected to plot /* When printing all pages, the printed page is not the current page. * In complex hierarchies, we must update component references * and others parameters in the given printed SCH_SCREEN, accordint to the sheet path * because in complex hierarchies a SCH_SCREEN (a drawing ) * is shared between many sheets and component references depend on the actual sheet path used */ SCH_SHEET_LIST sheetList; if( aPlotAll ) sheetList.BuildSheetList( g_RootSheet ); else sheetList.push_back( m_parent->GetCurrentSheet() ); for( unsigned i = 0; i < sheetList.size(); i++ ) { m_parent->SetCurrentSheet( sheetList[i] ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); actualPage = screen->GetPageSettings(); switch( m_pageSizeSelect ) { case PAGE_SIZE_A: plotPage.SetType( wxT( "A" ) ); plotPage.SetPortrait( actualPage.IsPortrait() ); break; case PAGE_SIZE_A4: plotPage.SetType( wxT( "A4" ) ); plotPage.SetPortrait( actualPage.IsPortrait() ); break; case PAGE_SIZE_AUTO: default: plotPage = actualPage; break; } double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); double scale = std::min( scalex, scaley ); wxPoint plot_offset; wxString outputDirName = m_outputDirectoryName->GetValue(); wxString msg; REPORTER& reporter = m_MessagesBox->Reporter(); try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = PS_PLOTTER::GetDefaultFileExtension(); wxFileName plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); if( plotOneSheetPS( plotFileName.GetFullPath(), screen, plotPage, plot_offset, scale, aPlotFrameRef ) ) { msg.Printf( _( "Plot: '%s' OK.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { // Error msg.Printf( _( "Unable to create file '%s'.\n" ), GetChars( plotFileName.GetFullPath() ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } catch( IO_ERROR& e ) { msg.Printf( wxT( "PS Plotter exception: %s"), GetChars( e.errorText ) ); reporter.Report( msg, REPORTER::RPT_ERROR ); } } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); }
void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; m_writeErcFile = m_WriteResultOpt->GetValue(); m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); // Build the whole sheet list in hierarchy (sheet, not screen) SCH_SHEET_LIST sheets; sheets.AnnotatePowerSymbols( Prj().SchLibs() ); if( m_parent->CheckAnnotate( aMessagesList, false ) ) { if( aMessagesList ) { wxString msg = _( "Annotation required!" ); msg += wxT( "\n" ); aMessagesList->Add( msg ); } return; } SCH_SCREENS screens; // Erase all previous DRC markers. screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC ); for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() ) { /* Ff wire list has changed, delete Undo Redo list to avoid pointers on deleted * data problems. */ if( screen->SchematicCleanUp( NULL ) ) screen->ClearUndoRedoList(); } /* Test duplicate sheet names inside a given sheet, one cannot have sheets with * duplicate names (file names can be duplicated). */ TestDuplicateSheetNames( true ); std::auto_ptr<NETLIST_OBJECT_LIST> objectsConnectedList( m_parent->BuildNetListBase() ); // Reset the connection type indicator objectsConnectedList->ResetConnectionsType(); unsigned lastNet; unsigned nextNet = lastNet = 0; int MinConn = NOC; for( unsigned net = 0; net < objectsConnectedList->size(); net++ ) { if( objectsConnectedList->GetItemNet( lastNet ) != objectsConnectedList->GetItemNet( net ) ) { // New net found: MinConn = NOC; nextNet = net; } switch( objectsConnectedList->GetItemType( net ) ) { // These items do not create erc problems case NET_ITEM_UNSPECIFIED: case NET_SEGMENT: case NET_BUS: case NET_JUNCTION: case NET_LABEL: case NET_BUSLABELMEMBER: case NET_PINLABEL: case NET_GLOBBUSLABELMEMBER: break; case NET_HIERLABEL: case NET_HIERBUSLABELMEMBER: case NET_SHEETLABEL: case NET_SHEETBUSLABELMEMBER: // ERC problems when pin sheets do not match hierarchical labels. // Each pin sheet must match a hierarchical label // Each hierarchical label must match a pin sheet objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_GLOBLABEL: if( m_tstUniqueGlobalLabels ) objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_NOCONNECT: // ERC problems when a noconnect symbol is connected to more than one pin. MinConn = NET_NC; if( objectsConnectedList->CountPinsInNet( nextNet ) > 1 ) Diagnose( objectsConnectedList->GetItem( net ), NULL, MinConn, UNC ); break; case NET_PIN: // Look for ERC problems between pins: TestOthersItems( objectsConnectedList.get(), net, nextNet, &MinConn ); break; } lastNet = net; } // Test similar labels (i;e. labels which are identical when // using case insensitive comparisons) if( m_TestSimilarLabels ) objectsConnectedList->TestforSimilarLabels(); // Displays global results: updateMarkerCounts( &screens ); // Display diags: DisplayERC_MarkersList(); // Display new markers: m_parent->GetCanvas()->Refresh(); if( m_writeErcFile ) { fn = g_RootSheet->GetScreen()->GetFileName(); fn.SetExt( wxT( "erc" ) ); wxFileDialog dlg( this, _( "ERC File" ), fn.GetPath(), fn.GetFullName(), _( "Electronic rule check file (.erc)|*.erc" ), wxFD_SAVE ); if( dlg.ShowModal() == wxID_CANCEL ) return; if( WriteDiagnosticERC( dlg.GetPath() ) ) { Close( true ); ExecuteFile( this, Pgm().GetEditorName(), QuoteFullPath( fn ) ); } } }
bool SCH_EDIT_FRAME::AppendOneEEProject() { SCH_SCREEN* screen; wxString FullFileName; wxString msg; screen = GetScreen(); if( !screen ) { wxLogError( wxT("Document not ready, cannot import") ); return false; } // open file chooser dialog wxFileDialog dlg( this, _( "Import Schematic" ), wxGetCwd(), wxEmptyString, SchematicFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_CANCEL ) return false; FullFileName = dlg.GetPath(); wxFileName fn = FullFileName; if( fn.IsRelative() ) { fn.MakeAbsolute(); FullFileName = fn.GetFullPath(); } LoadCacheLibrary( FullFileName ); wxLogDebug( wxT( "Importing schematic " ) + FullFileName ); // load the project bool success = LoadOneEEFile( screen, FullFileName, true ); if( success ) { // load sub-sheets EDA_ITEM* bs = screen->GetDrawItems(); while( bs ) { // do not append hierarchical sheets if( bs->Type() == SCH_SHEET_T ) { screen->Remove( (SCH_SHEET*) bs ); } // clear annotation and init new time stamp for the new components else if( bs->Type() == SCH_COMPONENT_T ) { ( (SCH_COMPONENT*) bs )->SetTimeStamp( GetNewTimeStamp() ); ( (SCH_COMPONENT*) bs )->ClearAnnotation( NULL ); // Clear flags, which are set by these previous modifications: bs->ClearFlags(); } bs = bs->Next(); } } // redraw base screen (ROOT) if necessary GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); Zoom_Automatique( false ); SetSheetNumberAndCount(); m_canvas->Refresh( true ); return success; }
bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName ) { SCH_SCREENS screens; PART_LIBS* libs = Prj().SchLibs(); std::unique_ptr<PART_LIB> libCache( new PART_LIB( LIBRARY_TYPE_EESCHEMA, aFileName ) ); libCache->SetCache(); /* examine all screens (not sheets) used and build the list of components * found in lib. * Complex hierarchies are not a problem because we just want * to know used components in libraries */ for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) { for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() ) { if( item->Type() != SCH_COMPONENT_T ) continue; SCH_COMPONENT* component = (SCH_COMPONENT*) item; // If not already saved in the new cache, put it: if( !libCache->FindEntry( component->GetPartName() ) ) { if( LIB_PART* part = libs->FindLibPart( component->GetPartName() ) ) { // AddPart() does first clone the part before adding. libCache->AddPart( part ); } } } } try { FILE_OUTPUTFORMATTER formatter( aFileName ); if( !libCache->Save( formatter ) ) { wxString msg = wxString::Format( _( "An error occurred attempting to save component library '%s'." ), GetChars( aFileName ) ); DisplayError( this, msg ); return false; } } catch( ... /* IO_ERROR ioe */ ) { wxString msg = wxString::Format( _( "Failed to create component library file '%s'" ), GetChars( aFileName ) ); DisplayError( this, msg ); return false; } return true; }
void DIALOG_PLOT_SCHEMATIC::createSVGFile( bool aPrintAll, bool aPrintFrameRef ) { wxString msg; if( aPrintAll ) { SCH_SHEET_PATH* sheetpath; SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); SCH_SHEET_LIST SheetList( NULL ); sheetpath = SheetList.GetFirst(); SCH_SHEET_PATH list; WX_TEXT_CTRL_REPORTER reporter(m_MessagesBox); for( ; ; ) { if( sheetpath == NULL ) { break; } SCH_SCREEN* screen; list.Clear(); if( list.BuildSheetPathInfoFromSheetPathValue( sheetpath->Path() ) ) { m_parent->SetCurrentSheet( list ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); screen = m_parent->GetCurrentSheet().LastScreen(); } else // Should not happen { return; } sheetpath = SheetList.GetNext(); try { wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); wxString ext = SVG_PLOTTER::GetDefaultFileExtension(); wxFileName plotFileName = createPlotFileName( m_outputDirectoryName, fname, ext, &reporter ); bool success = plotOneSheetSVG( m_parent, plotFileName.GetFullPath(), screen, getModeColor() ? false : true, aPrintFrameRef ); if( !success ) { msg.Printf( _( "Error creating file '%s'\n" ), GetChars( plotFileName.GetFullPath() ) ); } else { msg.Printf( _( "File '%s' OK\n" ), GetChars( plotFileName.GetFullPath() ) ); } m_MessagesBox->AppendText( msg ); } catch( const IO_ERROR& e ) { // Cannot plot SVG file msg.Printf( wxT( "SVG Plotter Exception : '%s'" ), GetChars( e.errorText ) ); m_MessagesBox->AppendText( msg ); m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); return; } } m_parent->SetCurrentSheet( oldsheetpath ); m_parent->GetCurrentSheet().UpdateAllScreenReferences(); m_parent->SetSheetNumberAndCount(); } else // Print current sheet { SCH_SCREEN* screen = (SCH_SCREEN*) m_parent->GetScreen(); try { wxString fname = screen->GetFileName(); wxString ext = SVG_PLOTTER::GetDefaultFileExtension(); wxFileName fn = createPlotFileName( m_outputDirectoryName, fname, ext ); bool success = plotOneSheetSVG( m_parent, fn.GetFullPath(), screen, getModeColor() ? false : true, aPrintFrameRef ); if( success ) { msg.Printf( _( "Plot: <%s> OK\n" ), GetChars( fn.GetFullPath() ) ); } else // Error { msg.Printf( _( "Unable to create <%s>\n" ), GetChars( fn.GetFullPath() ) ); } m_MessagesBox->AppendText( msg ); } catch( const IO_ERROR& e ) { // Cannot plot SVG file msg.Printf( wxT( "SVG Plotter Exception : <%s>"), GetChars( e.errorText ) ); m_MessagesBox->AppendText( msg ); return; } } }
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 ); }
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 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 DeleteSubHierarchy(DrawSheetStruct * FirstSheet) /*********************************************************/ /* Supprime tous les elements de la sous hierarchie correspondante a la feuille FirstSheet FirstSheet n'est pas touche */ { SCH_SCREEN *Screen; EDA_BaseStruct *DrawStruct; EDA_BaseStruct *EEDrawList; WinEDA_SchematicFrame * frame = EDA_Appl->SchematicFrame; char Line[256]; if( FirstSheet == NULL ) return; if( FirstSheet->m_StructType != DRAW_SHEET_STRUCT_TYPE) { DisplayError(NULL, "DeleteSubHierarchy error: NOT a SubSheet"); return; } /* effacement du sous schema correspondant */ Screen = (SCH_SCREEN*)FirstSheet->m_Son; if(Screen == NULL) return; if( Screen->IsModify() ) { sprintf(Line,"Sheet %s (file %s) modified. Save ?", FirstSheet->m_Field[VALUE].m_Text.GetData(), Screen->m_FileName.GetData()); if( IsOK(frame, Line) ) { frame->SaveEEFile(Screen, FILE_SAVE_AS); } } /* Effacement des sous feuilles */ EEDrawList = Screen->EEDrawList; while (EEDrawList != NULL) { DrawStruct = EEDrawList; EEDrawList = EEDrawList->Pnext; if( DrawStruct->m_StructType == DRAW_SHEET_STRUCT_TYPE) { DeleteSubHierarchy((DrawSheetStruct *) DrawStruct); } } /* Effacement des elements autres que les sous feuilles */ Screen->ClearDrawList(); /* Modification du chainage des structures ecran et suppression de l'ecran */ SCH_SCREEN * Pscreen, * Nscreen; Pscreen = (SCH_SCREEN*) Screen->Pback; Nscreen = Screen->Next(); if( Pscreen ) Pscreen->Pnext = Nscreen; if ( Nscreen ) Nscreen->Pback = Pscreen; if ( frame->GetScreen() == Screen ) frame->m_CurrentScreen = ScreenSch; ActiveScreen = frame->GetScreen(); if( Screen != ScreenSch ) delete(Screen); }
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::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::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 ); }