You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

628 lines
16 KiB

16 years ago
  1. /****************************/
  2. /* EESchema - libedit.cpp */
  3. /****************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "macros.h"
  8. #include "appl_wxstruct.h"
  9. #include "class_drawpanel.h"
  10. #include "confirm.h"
  11. #include "gestfich.h"
  12. #include "class_sch_screen.h"
  13. #include "eeschema_id.h"
  14. #include "general.h"
  15. #include "protos.h"
  16. #include "libeditframe.h"
  17. #include "class_library.h"
  18. #include "template_fieldnames.h"
  19. #include "dialog_lib_new_component.h"
  20. /* Update the main window title bar with the current library name. */
  21. void WinEDA_LibeditFrame::DisplayLibInfos()
  22. {
  23. wxString msg = _( "Component Library Editor: " );
  24. EnsureActiveLibExists();
  25. if( m_library )
  26. msg += m_library->GetFullFileName();
  27. else
  28. msg += _( "no library selected" );
  29. SetTitle( msg );
  30. }
  31. /* Function to select the current library (working library) */
  32. void WinEDA_LibeditFrame::SelectActiveLibrary()
  33. {
  34. CMP_LIBRARY* Lib;
  35. Lib = SelectLibraryFromList( this );
  36. if( Lib )
  37. {
  38. m_library = Lib;
  39. }
  40. DisplayLibInfos();
  41. }
  42. /**
  43. * Function LoadOneLibraryPart()
  44. * load a library component from the current selected library
  45. * Prompt user for component name
  46. * If there is no current selected library,
  47. * prompt user for library name and make the selected library the current lib.
  48. */
  49. void WinEDA_LibeditFrame::LoadOneLibraryPart( wxCommandEvent& event )
  50. {
  51. int i;
  52. wxString msg;
  53. wxString CmpName;
  54. LIB_ALIAS* LibEntry = NULL;
  55. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  56. if( GetBaseScreen()->IsModify()
  57. && !IsOK( this, _( "Current part not saved.\n\nDiscard current changes?" ) ) )
  58. return;
  59. // No current lib, ask user for the library to use.
  60. if( m_library == NULL )
  61. {
  62. SelectActiveLibrary();
  63. if( m_library == NULL )
  64. return;
  65. }
  66. i = GetNameOfPartToLoad( this, m_library, CmpName );
  67. if( i == 0 )
  68. return;
  69. GetBaseScreen()->ClrModify();
  70. m_lastDrawItem = m_drawItem = NULL;
  71. // Delete previous library component, if any
  72. if( m_component )
  73. {
  74. SAFE_DELETE( m_component );
  75. m_aliasName.Empty();
  76. }
  77. /* Load the new library component */
  78. LibEntry = m_library->FindEntry( CmpName );
  79. if( LibEntry == NULL )
  80. {
  81. msg.Printf( _( "Component name \"%s\" not found in library \"%s\"." ),
  82. GetChars( CmpName ),
  83. GetChars( m_library->GetName() ) );
  84. DisplayError( this, msg );
  85. return;
  86. }
  87. if( !LoadOneLibraryPartAux( LibEntry, m_library ) )
  88. return;
  89. g_EditPinByPinIsOn = m_component->UnitsLocked() ? true : false;
  90. m_HToolBar->ToggleTool( ID_LIBEDIT_EDIT_PIN_BY_PIN, g_EditPinByPinIsOn );
  91. GetScreen()->ClearUndoRedoList();
  92. Zoom_Automatique( false );
  93. DrawPanel->Refresh();
  94. SetShowDeMorgan( m_component->HasConversion() );
  95. m_HToolBar->Refresh();
  96. }
  97. /*
  98. * Routine to load into memory a copy of 1 library part.
  99. * Returns
  100. * 0 if OK
  101. * 1 if error
  102. * m_component advanced copy and created
  103. */
  104. bool WinEDA_LibeditFrame::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, CMP_LIBRARY* aLibrary )
  105. {
  106. wxString msg, cmpName, rootName;
  107. LIB_COMPONENT* component;
  108. if( ( aEntry == NULL ) || ( aLibrary == NULL ) )
  109. return false;
  110. if( aEntry->GetName().IsEmpty() )
  111. {
  112. wxLogWarning( wxT( "Entry in library <%s> has empty name field." ),
  113. GetChars( aLibrary->GetName() ) );
  114. return false;
  115. }
  116. cmpName = m_aliasName = aEntry->GetName();
  117. LIB_ALIAS* alias = (LIB_ALIAS*) aEntry;
  118. component = alias->GetComponent();
  119. wxASSERT( component != NULL );
  120. wxLogDebug( wxT( "\"<%s>\" is alias of \"<%s>\"" ),
  121. GetChars( cmpName ),
  122. GetChars( component->GetName() ) );
  123. if( m_component )
  124. {
  125. SAFE_DELETE( m_component );
  126. m_aliasName.Empty();
  127. m_oldRootName.Empty();
  128. }
  129. m_component = new LIB_COMPONENT( *component );
  130. if( m_component == NULL )
  131. {
  132. msg.Printf( _( "Could not create copy of part <%s> in library <%s>." ),
  133. GetChars( aEntry->GetName() ),
  134. GetChars( aLibrary->GetName() ) );
  135. DisplayError( this, msg );
  136. return false;
  137. }
  138. m_oldRootName = m_aliasName = aEntry->GetName();
  139. m_unit = 1;
  140. m_convert = 1;
  141. m_showDeMorgan = false;
  142. if( m_component->HasConversion() )
  143. m_showDeMorgan = true;
  144. GetBaseScreen()->ClrModify();
  145. DisplayLibInfos();
  146. UpdateAliasSelectList();
  147. UpdatePartSelectList();
  148. /* Display the document information based on the entry selected just in
  149. * case the entry is an alias. */
  150. DisplayCmpDoc();
  151. return true;
  152. }
  153. /* Function to redraw the current loaded library component */
  154. void WinEDA_LibeditFrame::RedrawActiveWindow( wxDC* DC, bool EraseBg )
  155. {
  156. if( GetScreen() == NULL )
  157. return;
  158. ActiveScreen = GetScreen();
  159. DrawPanel->DrawBackGround( DC );
  160. if( m_component )
  161. {
  162. // display reference like in schematic (a reference U is shown U? or U?A)
  163. // although it is stored without ? and part id.
  164. // So temporary change the reference by a schematic like reference
  165. LIB_FIELD* Field = m_component->GetField( REFERENCE );
  166. wxString fieldText = Field->m_Text;
  167. wxString fieldfullText = Field->GetFullText( m_unit );
  168. Field->m_Text = fieldfullText;
  169. m_component->Draw( DrawPanel, DC, wxPoint( 0, 0 ), m_unit,
  170. m_convert, GR_DEFAULT_DRAWMODE );
  171. Field->m_Text = fieldText;
  172. }
  173. GetScreen()->ClrRefreshReq();
  174. if( DrawPanel->ManageCurseur )
  175. DrawPanel->ManageCurseur( DrawPanel, DC, false );
  176. DrawPanel->DrawCursor( DC );
  177. DisplayLibInfos();
  178. UpdateStatusBar();
  179. }
  180. /*
  181. * Save (on disk) the current library
  182. * if exists the old file is renamed (.bak)
  183. */
  184. void WinEDA_LibeditFrame::SaveActiveLibrary( wxCommandEvent& event )
  185. {
  186. wxFileName fn;
  187. wxString msg;
  188. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  189. if( GetScreen()->IsModify() )
  190. {
  191. if( IsOK( this, _( "Include last component changes?" ) ) )
  192. SaveOnePartInMemory();
  193. }
  194. if( m_library == NULL )
  195. {
  196. DisplayError( this, wxT( "No library specified." ) );
  197. return;
  198. }
  199. if( event.GetId() == ID_LIBEDIT_SAVE_CURRENT_LIB_AS )
  200. { // Get a new name for the library
  201. wxString default_path = wxGetApp().ReturnLastVisitedLibraryPath();
  202. wxFileDialog dlg( this, _( "Component Library Name:" ), default_path,
  203. wxEmptyString, CompLibFileWildcard,
  204. wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
  205. if( dlg.ShowModal() == wxID_CANCEL )
  206. return;
  207. fn = dlg.GetPath();
  208. /* The GTK file chooser doesn't return the file extension added to
  209. * file name so add it here. */
  210. if( fn.GetExt().IsEmpty() )
  211. fn.SetExt( SymbolFileExtension );
  212. wxGetApp().SaveLastVisitedLibraryPath( fn.GetPath() );
  213. }
  214. else
  215. {
  216. fn = wxFileName( m_library->GetFullFileName() );
  217. msg = _( "Modify library file \"" ) + fn.GetFullPath() + _( "\"?" );
  218. if( !IsOK( this, msg ) )
  219. return;
  220. }
  221. bool success = m_library->Save( fn.GetFullPath(), true );
  222. ClearMsgPanel();
  223. if( !success )
  224. {
  225. msg = _( "Error while saving library file \"" ) + fn.GetFullPath() + _( "\"." );
  226. AppendMsgPanel( _( "*** ERROR: ***" ), msg, RED );
  227. DisplayError( this, msg );
  228. }
  229. else
  230. {
  231. msg = _( "Library file \"" ) + fn.GetFullName() + wxT( "\" Ok" );
  232. fn.SetExt( DOC_EXT );
  233. wxString msg1 = _( "Document file \"" ) + fn.GetFullPath() + wxT( "\" Ok" );
  234. AppendMsgPanel( msg, msg1, BLUE );
  235. }
  236. }
  237. /*
  238. * Display the documentation of the selected component.
  239. *
  240. * Used when displaying the list of library components.
  241. */
  242. void WinEDA_LibeditFrame::DisplayCmpDoc()
  243. {
  244. wxString msg;
  245. LIB_ALIAS* alias;
  246. ClearMsgPanel();
  247. if( m_library == NULL || m_component == NULL )
  248. return;
  249. msg = m_component->GetName();
  250. AppendMsgPanel( _( "Part" ), msg, BLUE, 8 );
  251. if( m_aliasName == m_component->GetName() )
  252. msg = _( "None" );
  253. else
  254. msg = m_aliasName;
  255. alias = m_component->GetAlias( m_aliasName );
  256. wxCHECK_RET( alias != NULL, wxT( "Alias not found in component." ) );
  257. AppendMsgPanel( _( "Alias" ), msg, RED, 8 );
  258. static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
  259. msg = UnitLetter[m_unit];
  260. AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 );
  261. if( m_convert > 1 )
  262. msg = _( "Convert" );
  263. else
  264. msg = _( "Normal" );
  265. AppendMsgPanel( _( "Body" ), msg, GREEN, 8 );
  266. if( m_component->IsPower() )
  267. msg = _( "Power Symbol" );
  268. else
  269. msg = _( "Component" );
  270. AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 );
  271. AppendMsgPanel( _( "Description" ), alias->GetDescription(), CYAN, 8 );
  272. AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY );
  273. AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY );
  274. }
  275. /*
  276. * Delete component in the current library.
  277. *
  278. * (Delete only in memory, the file does not change)
  279. *
  280. * The entry can be an alias or a component.
  281. * If an alias:
  282. * It is removed, and the list of alias is updated.
  283. *
  284. * If a component:
  285. * If the list of aliases is zero, it deletes the component
  286. * Otherwise the alias becomes the new component name, and the other
  287. * aliases become dependent on newly named component.
  288. */
  289. void WinEDA_LibeditFrame::DeleteOnePart( wxCommandEvent& event )
  290. {
  291. wxString CmpName;
  292. LIB_ALIAS* LibEntry;
  293. wxArrayString ListNames;
  294. wxString msg;
  295. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  296. m_lastDrawItem = NULL;
  297. m_drawItem = NULL;
  298. if( m_library == NULL )
  299. {
  300. SelectActiveLibrary();
  301. if( m_library == NULL )
  302. {
  303. DisplayError( this, _( "Please select a component library." ) );
  304. return;
  305. }
  306. }
  307. m_library->GetEntryNames( ListNames );
  308. if( ListNames.IsEmpty() )
  309. {
  310. msg.Printf( _( "Component library <%s> is empty." ), GetChars( m_library->GetName() ) );
  311. wxMessageBox( msg, _( "Delete Entry Error" ), wxID_OK | wxICON_EXCLAMATION, this );
  312. return;
  313. }
  314. msg.Printf( _( "Select 1 of %d components to delete\nfrom library <%s>." ),
  315. ListNames.GetCount(),
  316. GetChars( m_library->GetName() ) );
  317. wxSingleChoiceDialog dlg( this, msg, _( "Delete Component" ), ListNames );
  318. if( dlg.ShowModal() == wxID_CANCEL || dlg.GetStringSelection().IsEmpty() )
  319. return;
  320. LibEntry = m_library->FindEntry( dlg.GetStringSelection() );
  321. if( LibEntry == NULL )
  322. {
  323. msg.Printf( _( "Entry <%s> not found in library <%s>." ),
  324. GetChars( dlg.GetStringSelection() ),
  325. GetChars( m_library->GetName() ) );
  326. DisplayError( this, msg );
  327. return;
  328. }
  329. msg.Printf( _( "Delete component \"%s\" from library \"%s\"?" ),
  330. GetChars( LibEntry->GetName() ),
  331. GetChars( m_library->GetName() ) );
  332. if( !IsOK( this, msg ) )
  333. return;
  334. if( m_component == NULL || !m_component->HasAlias( LibEntry->GetName() ) )
  335. {
  336. m_library->RemoveEntry( LibEntry );
  337. return;
  338. }
  339. /* If deleting the current entry or removing one of the aliases for
  340. * the current entry, sync the changes in the current entry as well.
  341. */
  342. if( GetScreen()->IsModify()
  343. && !IsOK( this, _( "The component being deleted has been modified. \
  344. All changes will be lost. Discard changes?" ) ) )
  345. return;
  346. LIB_ALIAS* nextEntry = m_library->RemoveEntry( LibEntry );
  347. if( nextEntry != NULL )
  348. {
  349. if( LoadOneLibraryPartAux( nextEntry, m_library ) )
  350. Zoom_Automatique( false );
  351. }
  352. else
  353. {
  354. SAFE_DELETE( m_component );
  355. m_aliasName.Empty();
  356. m_oldRootName.Empty();
  357. }
  358. DrawPanel->Refresh();
  359. }
  360. /*
  361. * Routine to create a new library component
  362. *
  363. * If an old component is currently in edit, it is deleted.
  364. */
  365. void WinEDA_LibeditFrame::CreateNewLibraryPart( wxCommandEvent& event )
  366. {
  367. wxString name;
  368. if( m_component && GetScreen()->IsModify()
  369. && !IsOK( this, _( "All changes to the current component will be \
  370. lost!\n\nClear the current component from the screen?" ) ) )
  371. return;
  372. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  373. m_drawItem = NULL;
  374. DIALOG_LIB_NEW_COMPONENT dlg( this );
  375. dlg.SetMinSize( dlg.GetSize() );
  376. if( dlg.ShowModal() == wxID_CANCEL )
  377. return;
  378. if( dlg.GetName().IsEmpty() )
  379. {
  380. wxMessageBox( _( "This new component has no name and cannot be created. Aborted" ) );
  381. return;
  382. }
  383. #ifndef KICAD_KEEPCASE
  384. name = dlg.GetName().MakeUpper();
  385. #else
  386. name = dlg.GetName();
  387. #endif
  388. name.Replace( wxT( " " ), wxT( "_" ) );
  389. /* Test if there a component with this name already. */
  390. if( m_library && m_library->FindEntry( name ) )
  391. {
  392. wxString msg;
  393. msg.Printf( _( "Component \"%s\" already exists in library \"%s\"." ),
  394. GetChars( name ),
  395. GetChars( m_library->GetName() ) );
  396. DisplayError( this, msg );
  397. return;
  398. }
  399. m_oldRootName.Empty();
  400. LIB_COMPONENT* component = new LIB_COMPONENT( name );
  401. component->GetReferenceField().m_Text = dlg.GetReference();
  402. component->SetPartCount( dlg.GetPartCount() );
  403. // Initialize component->m_TextInside member:
  404. // if 0, pin text is outside the body (on the pin)
  405. // if > 0, pin text is inside the body
  406. component->SetConversion( dlg.GetAlternateBodyStyle() );
  407. SetShowDeMorgan( dlg.GetAlternateBodyStyle() );
  408. if( dlg.GetPinNameInside( ) )
  409. {
  410. component->SetPinNameOffset( dlg.GetPinTextPosition() );
  411. if( component->GetPinNameOffset() == 0 )
  412. component->SetPinNameOffset( 1 );
  413. }
  414. else
  415. {
  416. component->SetPinNameOffset( 0 );
  417. }
  418. ( dlg.GetPowerSymbol() ) ? component->SetPower() : component->SetNormal();
  419. component->SetShowPinNumbers( dlg.GetShowPinNumber() );
  420. component->SetShowPinNames( dlg.GetShowPinName() );
  421. component->LockUnits( dlg.GetLockItems() );
  422. if( dlg.GetPartCount() < 2 )
  423. component->LockUnits( false );
  424. m_aliasName = component->GetName();
  425. if( m_component )
  426. {
  427. SAFE_DELETE( m_component );
  428. m_aliasName.Empty();
  429. }
  430. m_component = component;
  431. m_aliasName = m_component->GetName();
  432. m_unit = 1;
  433. m_convert = 1;
  434. DisplayLibInfos();
  435. DisplayCmpDoc();
  436. UpdateAliasSelectList();
  437. UpdatePartSelectList();
  438. g_EditPinByPinIsOn = m_component->UnitsLocked() ? true : false;
  439. m_HToolBar->ToggleTool( ID_LIBEDIT_EDIT_PIN_BY_PIN, g_EditPinByPinIsOn );
  440. m_lastDrawItem = NULL;
  441. GetScreen()->ClearUndoRedoList();
  442. OnModify( );
  443. DrawPanel->Refresh();
  444. m_HToolBar->Refresh();
  445. }
  446. /*
  447. * Routine backup of "partlib" current in the current library.
  448. *
  449. * Save in memory only and NOT on file.
  450. * The routine deletes the old component (and / or aliases) to replace
  451. * If any, and saves the new and creates the corresponding alias.
  452. */
  453. void WinEDA_LibeditFrame::SaveOnePartInMemory()
  454. {
  455. LIB_COMPONENT* oldComponent;
  456. LIB_COMPONENT* Component;
  457. wxString msg;
  458. wxString rootName;
  459. if( m_component == NULL )
  460. {
  461. DisplayError( this, _( "No component to save." ) );
  462. return;
  463. }
  464. if( m_library == NULL )
  465. SelectActiveLibrary();
  466. if( m_library == NULL )
  467. {
  468. DisplayError( this, _( "No library specified." ) );
  469. return;
  470. }
  471. GetBaseScreen()->ClrModify();
  472. // If the component root name was changed, that is still the name of the component
  473. // in the library.
  474. if( !m_oldRootName.IsEmpty() && m_oldRootName != m_component->GetName() )
  475. rootName = m_oldRootName;
  476. else
  477. rootName = m_component->GetName();
  478. oldComponent = m_library->FindComponent( rootName );
  479. if( oldComponent != NULL )
  480. {
  481. msg.Printf( _( "Component \"%s\" exists. Change it?" ), GetChars( rootName ) );
  482. if( !IsOK( this, msg ) )
  483. return;
  484. }
  485. m_drawItem = m_lastDrawItem = NULL;
  486. if( oldComponent != NULL )
  487. Component = m_library->ReplaceComponent( oldComponent, m_component );
  488. else
  489. Component = m_library->AddComponent( m_component );
  490. if( Component == NULL )
  491. return;
  492. msg.Printf( _( "Component %s saved in library %s" ),
  493. GetChars( Component->GetName() ),
  494. GetChars( m_library->GetName() ) );
  495. SetStatusText( msg );
  496. }