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

  1. /****************************/
  2. /* EESchema - libedit.cpp */
  3. /****************************/
  4. /* Routines de maintenanace des librairies:
  5. * sauvegarde, modification de librairies.
  6. * creation edition suppression de composants
  7. */
  8. #include "fctsys.h"
  9. #include "gr_basic.h"
  10. #include "common.h"
  11. #include "class_drawpanel.h"
  12. #include "confirm.h"
  13. #include "gestfich.h"
  14. #include "eeschema_id.h"
  15. #include "program.h"
  16. #include "general.h"
  17. #include "protos.h"
  18. #include "libeditfrm.h"
  19. #include "class_library.h"
  20. #include "dialog_lib_new_component.h"
  21. /* Update the main window title bar with the current library name. */
  22. void WinEDA_LibeditFrame::DisplayLibInfos()
  23. {
  24. wxString msg = _( "Component Library Editor: " );
  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. CMP_LIB_ENTRY* LibEntry = NULL;
  55. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  56. if( GetBaseScreen()->IsModify() && !IsOK( this, _( "Current part not \
  57. 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. }
  76. /* Load the new library component */
  77. LibEntry = m_library->FindEntry( CmpName );
  78. if( LibEntry == NULL )
  79. {
  80. msg.Printf( _( "Component or alias name \"%s\" not found in \
  81. 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 = false;
  90. GetScreen()->ClearUndoRedoList();
  91. Zoom_Automatique( false );
  92. DrawPanel->Refresh();
  93. SetShowDeMorgan(m_component->HasConversion() );
  94. }
  95. /*
  96. * Routine Pour Charger en memoire la copie de 1 libpart.
  97. * retourne
  98. * 0 si OK
  99. * 1 si err
  100. * m_component pointe la copie ainsi creee
  101. */
  102. bool WinEDA_LibeditFrame::LoadOneLibraryPartAux( CMP_LIB_ENTRY* LibEntry,
  103. CMP_LIBRARY* Library )
  104. {
  105. wxString msg, cmpName, rootName;
  106. LIB_COMPONENT* component;
  107. if( ( LibEntry == NULL ) || ( Library == NULL ) )
  108. return false;
  109. if( LibEntry->GetName().IsEmpty() )
  110. {
  111. wxLogWarning( wxT( "Entry in library <%s> has empty name field." ),
  112. GetChars( Library->GetName() ) );
  113. return false;
  114. }
  115. cmpName = LibEntry->GetName();
  116. m_aliasName.Empty();
  117. if( LibEntry->Type != ROOT )
  118. {
  119. LIB_ALIAS* alias = (LIB_ALIAS*) LibEntry;
  120. component = alias->GetComponent();
  121. wxASSERT( component != NULL && component->Type == ROOT );
  122. wxLogDebug( wxT( "\"<%s>\" is alias of \"<%s>\"" ),
  123. GetChars( cmpName ),
  124. GetChars( component->GetName() ) );
  125. m_aliasName = cmpName;
  126. }
  127. else
  128. {
  129. component = (LIB_COMPONENT*) LibEntry;
  130. }
  131. if( m_component )
  132. SAFE_DELETE( m_component );
  133. m_component = new LIB_COMPONENT( *component );
  134. if( m_component == NULL )
  135. {
  136. msg.Printf( _( "Could not create copy of part <%s> in library <%s>." ),
  137. GetChars( LibEntry->GetName() ),
  138. GetChars( Library->GetName() ) );
  139. DisplayError( this, msg );
  140. return false;
  141. }
  142. m_unit = 1;
  143. m_convert = 1;
  144. m_showDeMorgan = false;
  145. if( m_component->HasConversion() )
  146. m_showDeMorgan = true;
  147. GetBaseScreen()->ClrModify();
  148. DisplayLibInfos();
  149. UpdateAliasSelectList();
  150. UpdatePartSelectList();
  151. /* Display the document information based on the entry selected just in
  152. * case the entry is an alias. */
  153. DisplayCmpDoc();
  154. return true;
  155. }
  156. /* Function to redraw the current loaded library component */
  157. void WinEDA_LibeditFrame::RedrawActiveWindow( wxDC* DC, bool EraseBg )
  158. {
  159. if( GetScreen() == NULL )
  160. return;
  161. ActiveScreen = GetScreen();
  162. DC->SetBackground( *wxBLACK_BRUSH );
  163. DC->SetBackgroundMode( wxTRANSPARENT );
  164. GRResetPenAndBrush( DC );
  165. DrawPanel->CursorOff( DC ); // erase cursor
  166. if( DrawPanel->ManageCurseur )
  167. {
  168. DrawPanel->ManageCurseur( DrawPanel, DC, false );
  169. }
  170. if( EraseBg )
  171. DrawPanel->EraseScreen( DC );
  172. DrawPanel->DrawBackGround( DC );
  173. if( m_component )
  174. m_component->Draw( DrawPanel, DC, wxPoint( 0, 0 ), m_unit,
  175. m_convert, GR_DEFAULT_DRAWMODE );
  176. DrawPanel->CursorOn( DC ); // redraw cursor
  177. if( DrawPanel->ManageCurseur )
  178. {
  179. DrawPanel->ManageCurseur( DrawPanel, DC, false );
  180. }
  181. GetScreen()->ClrRefreshReq();
  182. DisplayLibInfos();
  183. UpdateStatusBar();
  184. }
  185. /*
  186. * Save (on disk) the current library
  187. * if exists the old file is renamed (.bak)
  188. */
  189. void WinEDA_LibeditFrame::SaveActiveLibrary( wxCommandEvent& event )
  190. {
  191. wxFileName fn;
  192. wxString msg;
  193. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  194. if( GetScreen()->IsModify() )
  195. {
  196. if( IsOK( this, _( "Include last component changes?" ) ) )
  197. SaveOnePartInMemory();
  198. }
  199. if( m_library == NULL )
  200. {
  201. DisplayError( this, wxT( "No library specified." ) );
  202. return;
  203. }
  204. fn = wxFileName( m_library->GetFullFileName() );
  205. msg = _( "Modify library file \"" ) + fn.GetFullPath() + _( "\"?" );
  206. if( !IsOK( this, msg ) )
  207. return;
  208. bool success = m_library->Save( fn.GetFullPath(), true );
  209. ClearMsgPanel();
  210. if( !success )
  211. {
  212. msg = _( "Error while saving library file \"" ) + fn.GetFullPath() +
  213. _( "\"." );
  214. AppendMsgPanel( _( "*** ERROR: ***" ), msg, RED );
  215. DisplayError( this, msg );
  216. }
  217. else
  218. {
  219. msg = _( "Library file \"" ) + fn.GetFullName() + wxT( "\" Ok" );
  220. fn.SetExt( DOC_EXT );
  221. wxString msg1 = _( "Document file \"" ) + fn.GetFullPath() +
  222. wxT( "\" Ok" );
  223. AppendMsgPanel( msg, msg1, BLUE );
  224. }
  225. }
  226. /*
  227. * Affiche la documentation du composant selectionne
  228. * Utilise lors de l'affichage de la liste des composants en librairie
  229. */
  230. void WinEDA_LibeditFrame::DisplayCmpDoc()
  231. {
  232. wxString msg;
  233. LIB_ALIAS* alias = NULL;
  234. ClearMsgPanel();
  235. if( m_library == NULL || m_component == NULL )
  236. return;
  237. msg = m_component->GetName();
  238. AppendMsgPanel( _( "Part" ), msg, BLUE, 8 );
  239. if( m_aliasName.IsEmpty() )
  240. {
  241. msg = _( "None" );
  242. }
  243. else
  244. {
  245. msg = m_aliasName;
  246. alias = m_library->FindAlias( m_aliasName );
  247. }
  248. AppendMsgPanel( _( "Alias" ), msg, RED, 8 );
  249. static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
  250. msg = UnitLetter[m_unit];
  251. AppendMsgPanel( _( "Unit" ), msg, BROWN, 8 );
  252. if( m_convert > 1 )
  253. msg = _( "Convert" );
  254. else
  255. msg = _( "Normal" );
  256. AppendMsgPanel( _( "Body" ), msg, GREEN, 8 );
  257. if( m_component->m_Options == ENTRY_POWER )
  258. msg = _( "Power Symbol" );
  259. else
  260. msg = _( "Component" );
  261. AppendMsgPanel( _( "Type" ), msg, MAGENTA, 8 );
  262. if( alias != NULL )
  263. msg = alias->m_Doc;
  264. else
  265. msg = m_component->m_Doc;
  266. AppendMsgPanel( _( "Description" ), msg, CYAN, 8 );
  267. if( alias != NULL )
  268. msg = alias->m_KeyWord;
  269. else
  270. msg = m_component->m_KeyWord;
  271. AppendMsgPanel( _( "Key words" ), msg, DARKDARKGRAY );
  272. }
  273. /*
  274. * Routine de suppression d'un composant dans la librairie courante
  275. * (effacement en memoire uniquement, le fichier n'est pas modifie)
  276. * Le composant peut etre un alias, ou la definition de base.
  277. * Si c'est un alias:
  278. * il est supprime, et la liste des alias de la definition
  279. * de base est modifiee
  280. * Si c'est le composant de base:
  281. * Si la liste des alias est nulle, il est supprime
  282. * Sinon le premier alias devient le composant de base, et les autres
  283. * alias deviennent dependants de celui ci.
  284. */
  285. void WinEDA_LibeditFrame::DeleteOnePart( wxCommandEvent& event )
  286. {
  287. wxString CmpName;
  288. CMP_LIB_ENTRY* LibEntry;
  289. wxArrayString ListNames;
  290. wxString msg;
  291. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  292. m_lastDrawItem = NULL;
  293. m_drawItem = NULL;
  294. if( m_library == NULL )
  295. {
  296. SelectActiveLibrary();
  297. if( m_library == NULL )
  298. {
  299. DisplayError( this, _( "Please select a component library." ) );
  300. return;
  301. }
  302. }
  303. m_library->GetEntryNames( ListNames );
  304. if( ListNames.IsEmpty() )
  305. {
  306. msg.Printf( _( "Component library <%s> is empty." ),
  307. GetChars( m_library->GetName() ) );
  308. wxMessageBox( msg, _( "Delete Entry Error" ),
  309. wxID_OK | wxICON_EXCLAMATION, this );
  310. return;
  311. }
  312. msg.Printf( _( "Select 1 of %d components to delete\nfrom library <%s>." ),
  313. ListNames.GetCount(),
  314. GetChars( m_library->GetName() ) );
  315. wxSingleChoiceDialog dlg( this, msg, _( "Delete Component" ), ListNames );
  316. if( dlg.ShowModal() == wxID_CANCEL || dlg.GetStringSelection().IsEmpty() )
  317. return;
  318. LibEntry = m_library->FindEntry( dlg.GetStringSelection() );
  319. if( LibEntry == NULL )
  320. {
  321. msg.Printf( _( "Entry <%s> not found in library <%s>." ),
  322. GetChars( dlg.GetStringSelection() ),
  323. GetChars( m_library->GetName() ) );
  324. DisplayError( this, msg );
  325. return;
  326. }
  327. msg.Printf( _( "Delete component \"%s\" from library \"%s\"?" ),
  328. GetChars( LibEntry->GetName() ),
  329. GetChars( m_library->GetName() ) );
  330. if( !IsOK( this, msg ) )
  331. return;
  332. if( m_component == NULL
  333. || ( m_component->GetName().CmpNoCase( LibEntry->GetName() ) != 0
  334. && !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. wxString newCmpName;
  347. CMP_LIB_ENTRY* nextEntry;
  348. /*
  349. * If the current component has no aliases, then the next entry
  350. * in the library will be shown. If the current component has
  351. * aliases, the updated component will be shown
  352. */
  353. if( m_component->GetName().CmpNoCase( LibEntry->GetName() ) == 0 )
  354. {
  355. if( m_component->m_AliasList.IsEmpty() )
  356. {
  357. nextEntry = m_library->GetNextEntry( m_component->GetName() );
  358. if( nextEntry != NULL )
  359. newCmpName = nextEntry->GetName();
  360. }
  361. else
  362. {
  363. newCmpName = m_component->m_AliasList[ 0 ];
  364. }
  365. }
  366. else
  367. {
  368. newCmpName = m_component->GetName();
  369. }
  370. m_library->RemoveEntry( LibEntry );
  371. if( !newCmpName.IsEmpty() )
  372. {
  373. nextEntry = m_library->FindEntry( newCmpName );
  374. if( nextEntry != NULL && LoadOneLibraryPartAux( nextEntry, m_library ) )
  375. Zoom_Automatique( false );
  376. DrawPanel->Refresh();
  377. }
  378. }
  379. /*
  380. * Routine to create a new library component
  381. *
  382. * If an old component is currently in edit, it is deleted.
  383. */
  384. void WinEDA_LibeditFrame::CreateNewLibraryPart( wxCommandEvent& event )
  385. {
  386. wxString name;
  387. if( m_component && GetScreen()->IsModify()
  388. && !IsOK( this, _( "All changes to the current component will be \
  389. lost!\n\nClear the current component from the screen?" ) ) )
  390. return;
  391. DrawPanel->UnManageCursor( 0, wxCURSOR_ARROW );
  392. m_drawItem = NULL;
  393. DIALOG_LIB_NEW_COMPONENT dlg( this );
  394. if( dlg.ShowModal() == wxID_CANCEL )
  395. return;
  396. if( dlg.GetName().IsEmpty() )
  397. {
  398. wxMessageBox(_("This new component has no name and cannot be created. Aborted"));
  399. return;
  400. }
  401. name = dlg.GetName().MakeUpper();
  402. name.Replace( wxT( " " ), wxT( "_" ) );
  403. /* Test: y a t-il un composant deja de ce nom */
  404. if( m_library && m_library->FindEntry( name ) )
  405. {
  406. wxString msg;
  407. msg.Printf( _( "Component \"%s\" already exists in library \"%s\"." ),
  408. GetChars( name ),
  409. GetChars( m_library->GetName() ) );
  410. DisplayError( this, msg );
  411. return;
  412. }
  413. LIB_COMPONENT* component = new LIB_COMPONENT( name );
  414. component->GetReferenceField().m_Text = dlg.GetReference();
  415. component->SetPartCount( dlg.GetPartCount() );
  416. // Initialize component->m_TextInside member:
  417. // if 0, pin text is outside the body (on the pin)
  418. // if > 0, pin text is inside the body
  419. component->SetConversion( dlg.GetAlternateBodyStyle() );
  420. SetShowDeMorgan( dlg.GetAlternateBodyStyle() );
  421. if( dlg.GetPinNameInside( ) )
  422. {
  423. component->m_TextInside = dlg.GetPinTextPosition();
  424. if( component->m_TextInside == 0 )
  425. component->m_TextInside = 1;
  426. }
  427. else
  428. component->m_TextInside = 0;
  429. component->m_Options = ( dlg.GetPowerSymbol() ) ? ENTRY_POWER : ENTRY_NORMAL;
  430. component->m_DrawPinNum = dlg.GetShowPinNumber();
  431. component->m_DrawPinName = dlg.GetShowPinName();
  432. component->m_UnitSelectionLocked = dlg.GetLockItems();
  433. if( dlg.GetPartCount() < 2 )
  434. component->m_UnitSelectionLocked = false;
  435. if( m_component )
  436. {
  437. SAFE_DELETE( m_component );
  438. }
  439. m_component = component;
  440. m_unit = 1;
  441. m_convert = 1;
  442. DisplayLibInfos();
  443. DisplayCmpDoc();
  444. UpdateAliasSelectList();
  445. UpdatePartSelectList();
  446. g_EditPinByPinIsOn = false;
  447. m_lastDrawItem = NULL;
  448. GetScreen()->ClearUndoRedoList();
  449. GetScreen()->SetModify();
  450. DrawPanel->Refresh();
  451. }
  452. /*
  453. * Routine de sauvegarde de la "partlib" courante dans la librairie courante
  454. *
  455. * Sauvegarde en memoire uniquement, et PAS sur fichier
  456. * La routine efface l'ancien composant ( ou / et les alias ) a remplacer
  457. * s'il existe, et sauve le nouveau et cree les alias correspondants.
  458. */
  459. void WinEDA_LibeditFrame::SaveOnePartInMemory()
  460. {
  461. LIB_COMPONENT* oldComponent;
  462. LIB_COMPONENT* Component;
  463. wxString msg;
  464. if( m_component == NULL )
  465. {
  466. DisplayError( this, _( "No component to save." ) );
  467. return;
  468. }
  469. if( m_library == NULL )
  470. SelectActiveLibrary();
  471. if( m_library == NULL )
  472. {
  473. DisplayError( this, _( "No library specified." ) );
  474. return;
  475. }
  476. GetBaseScreen()->ClrModify();
  477. oldComponent = m_library->FindComponent( m_component->GetName() );
  478. if( oldComponent != NULL )
  479. {
  480. msg.Printf( _( "Component \"%s\" exists. Change it?" ),
  481. GetChars( oldComponent->GetName() ) );
  482. if( !IsOK( this, msg ) )
  483. return;
  484. }
  485. m_drawItem = m_lastDrawItem = NULL;
  486. wxASSERT( m_component->Type == ROOT );
  487. if( oldComponent != NULL )
  488. Component = m_library->ReplaceComponent( oldComponent, m_component );
  489. else
  490. Component = m_library->AddComponent( m_component );
  491. if( Component == NULL )
  492. return;
  493. msg.Printf( _( "Component %s saved in library %s" ),
  494. GetChars( Component->GetName() ),
  495. GetChars( m_library->GetName() ) );
  496. Affiche_Message( msg );
  497. }