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.

652 lines
18 KiB

16 years ago
15 years ago
17 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
  1. /**********************************************/
  2. /* Footprints selection and loading functions */
  3. /**********************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "class_drawpanel.h"
  8. #include "confirm.h"
  9. #include "eda_doc.h"
  10. #include "kicad_string.h"
  11. #include "gestfich.h"
  12. #include "dialog_get_component.h"
  13. #include "appl_wxstruct.h"
  14. #include "pcbnew.h"
  15. #include "wxPcbStruct.h"
  16. #include "module_editor_frame.h"
  17. #include "dialog_helpers.h"
  18. #include "richio.h"
  19. #include "filter_reader.h"
  20. class FOOTPRINT_ITEM
  21. {
  22. public:
  23. FOOTPRINT_ITEM* Next;
  24. wxString m_Name, m_Doc, m_KeyWord;
  25. public:
  26. FOOTPRINT_ITEM()
  27. {
  28. Next = NULL;
  29. }
  30. ~FOOTPRINT_ITEM()
  31. {
  32. }
  33. };
  34. static void DisplayCmpDoc( wxString& Name );
  35. static void ReadDocLib( const wxString& ModLibName );
  36. static FOOTPRINT_ITEM* MList;
  37. /**
  38. * Function Load_Module_From_BOARD
  39. * load in Modedit a footfrint from the main board
  40. * @param Module = the module to load. If NULL, a module reference will we asked to user
  41. * @return true if a module isloaded, false otherwise.
  42. */
  43. bool WinEDA_ModuleEditFrame::Load_Module_From_BOARD( MODULE* Module )
  44. {
  45. MODULE* NewModule;
  46. WinEDA_BasePcbFrame* parent = (WinEDA_BasePcbFrame*) GetParent();
  47. if( Module == NULL )
  48. {
  49. if( ! parent->GetBoard() || ! parent->GetBoard()->m_Modules )
  50. return false;
  51. Module = Select_1_Module_From_BOARD( parent->GetBoard() );
  52. }
  53. if( Module == NULL )
  54. return false;
  55. SetCurItem( NULL );
  56. Clear_Pcb( false );
  57. GetBoard()->m_Status_Pcb = 0;
  58. NewModule = new MODULE( GetBoard() );
  59. NewModule->Copy( Module );
  60. NewModule->m_Link = Module->m_TimeStamp;
  61. Module = NewModule;
  62. GetBoard()->Add( Module );
  63. Module->m_Flags = 0;
  64. GetBoard()->m_NetInfo->BuildListOfNets();
  65. GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) );
  66. Place_Module( Module, NULL );
  67. if( Module->GetLayer() != LAYER_N_FRONT )
  68. Module->Flip( Module->m_Pos );
  69. Rotate_Module( NULL, Module, 0, false );
  70. GetScreen()->ClrModify();
  71. Zoom_Automatique( TRUE );
  72. return true;
  73. }
  74. MODULE* WinEDA_BasePcbFrame::Load_Module_From_Library( const wxString& library,
  75. wxDC* DC )
  76. {
  77. MODULE* module;
  78. wxPoint curspos = GetScreen()->GetCrossHairPosition();
  79. wxString ModuleName, keys;
  80. static wxArrayString HistoryList;
  81. static wxString lastCommponentName;
  82. bool AllowWildSeach = TRUE;
  83. /* Ask for a component name or key words */
  84. DIALOG_GET_COMPONENT dlg( this, GetComponentDialogPosition(), HistoryList,
  85. _( "Place Module" ), false );
  86. dlg.SetComponentName( lastCommponentName );
  87. if( dlg.ShowModal() == wxID_CANCEL )
  88. return NULL;
  89. ModuleName = dlg.GetComponentName();
  90. if( ModuleName.IsEmpty() ) /* Cancel command */
  91. {
  92. DrawPanel->MoveCursorToCrossHair();
  93. return NULL;
  94. }
  95. ModuleName.MakeUpper();
  96. if( ModuleName[0] == '=' ) // Selection by keywords
  97. {
  98. AllowWildSeach = false;
  99. keys = ModuleName.AfterFirst( '=' );
  100. ModuleName = Select_1_Module_From_List( this, library, wxEmptyString,
  101. keys );
  102. if( ModuleName.IsEmpty() ) /* Cancel command */
  103. {
  104. DrawPanel->MoveCursorToCrossHair();
  105. return NULL;
  106. }
  107. }
  108. else if( ( ModuleName.Contains( wxT( "?" ) ) )
  109. || ( ModuleName.Contains( wxT( "*" ) ) ) ) // Selection wild card
  110. {
  111. AllowWildSeach = false;
  112. ModuleName = Select_1_Module_From_List( this, library, ModuleName,
  113. wxEmptyString );
  114. if( ModuleName.IsEmpty() )
  115. {
  116. DrawPanel->MoveCursorToCrossHair();
  117. return NULL; /* Cancel command. */
  118. }
  119. }
  120. module = Get_Librairie_Module( library, ModuleName, false );
  121. if( ( module == NULL ) && AllowWildSeach ) /* Search with wildcard */
  122. {
  123. AllowWildSeach = false;
  124. wxString wildname = wxChar( '*' ) + ModuleName + wxChar( '*' );
  125. ModuleName = wildname;
  126. ModuleName = Select_1_Module_From_List( this, library, ModuleName,
  127. wxEmptyString );
  128. if( ModuleName.IsEmpty() )
  129. {
  130. DrawPanel->MoveCursorToCrossHair();
  131. return NULL; /* Cancel command. */
  132. }
  133. else
  134. module = Get_Librairie_Module( library, ModuleName, TRUE );
  135. }
  136. GetScreen()->SetCrossHairPosition( curspos );
  137. DrawPanel->MoveCursorToCrossHair();
  138. if( module )
  139. {
  140. lastCommponentName = ModuleName;
  141. AddHistoryComponentName( HistoryList, ModuleName );
  142. module->m_Flags = IS_NEW;
  143. module->m_Link = 0;
  144. module->m_TimeStamp = GetTimeStamp();
  145. GetBoard()->m_Status_Pcb = 0;
  146. module->SetPosition( curspos );
  147. /* TODO: call RecalculateAllTracksNetcode() only if some pads pads have
  148. * a netname.
  149. * If all pads are not connected (usually the case in module libraries,
  150. * rebuild only the pad and list of nets ( faster)
  151. */
  152. // GetBoard()->m_Pcb->m_NetInfo->BuildListOfNets();
  153. RecalculateAllTracksNetcode();
  154. if( DC )
  155. module->Draw( DrawPanel, DC, GR_OR );
  156. }
  157. return module;
  158. }
  159. /**
  160. * Function Get_Librairie_Module
  161. *
  162. * Read active libraries or one library to find and load a given module
  163. * If found the module is linked to the tail of linked list of modules
  164. * @param aLibraryFullFilename: the full filename of the library to read. If empty,
  165. * all active libraries are read
  166. * @param aModuleName = module name to load
  167. * @param aDisplayMessageError = true to display an error message if any.
  168. * @return a MODULE * pointer to the new module, or NULL
  169. *
  170. */
  171. MODULE* WinEDA_BasePcbFrame::Get_Librairie_Module(
  172. const wxString& aLibraryFullFilename,
  173. const wxString& aModuleName,
  174. bool aDisplayMessageError )
  175. {
  176. int Found = 0;
  177. wxFileName fn;
  178. char* Line;
  179. wxString Name;
  180. wxString msg, tmp;
  181. MODULE* NewModule;
  182. FILE* file = NULL;
  183. unsigned ii;
  184. bool one_lib = aLibraryFullFilename.IsEmpty() ? false : true;
  185. for( ii = 0; ii < g_LibName_List.GetCount(); ii++ )
  186. {
  187. if( one_lib )
  188. fn = aLibraryFullFilename;
  189. else
  190. fn = wxFileName( wxEmptyString, g_LibName_List[ii],
  191. ModuleFileExtension );
  192. tmp = wxGetApp().FindLibraryPath( fn );
  193. if( !tmp )
  194. {
  195. if( aDisplayMessageError )
  196. {
  197. msg.Printf( _( "PCB footprint library file <%s> not found in search paths." ),
  198. GetChars( fn.GetFullName() ) );
  199. wxMessageBox( msg, _( "Library Load Error" ),
  200. wxOK | wxICON_ERROR, this );
  201. }
  202. continue;
  203. }
  204. file = wxFopen( tmp, wxT( "rt" ) );
  205. if( file == NULL )
  206. {
  207. msg.Printf( _( "Could not open PCB footprint library file <%s>." ),
  208. GetChars( tmp ) );
  209. wxMessageBox( msg, _( "Library Load Error" ),
  210. wxOK | wxICON_ERROR, this );
  211. continue;
  212. }
  213. FILE_LINE_READER fileReader( file, tmp );
  214. FILTER_READER reader( fileReader );
  215. msg.Printf( _( "Scan Lib: %s" ), GetChars( tmp ) );
  216. SetStatusText( msg );
  217. /* Reading header ENTETE_LIBRAIRIE */
  218. reader.ReadLine();
  219. Line = reader.Line();
  220. StrPurge( Line );
  221. if( strnicmp( Line, ENTETE_LIBRAIRIE, L_ENTETE_LIB ) != 0 )
  222. {
  223. msg.Printf( _( "<%s> is not a valid Kicad PCB footprint library file." ),
  224. GetChars( tmp ) );
  225. wxMessageBox( msg, _( "Library Load Error" ),
  226. wxOK | wxICON_ERROR, this );
  227. return NULL;
  228. }
  229. /* Reading the list of modules in the library. */
  230. Found = 0;
  231. while( !Found && reader.ReadLine() )
  232. {
  233. Line = reader.Line();
  234. if( strnicmp( Line, "$MODULE", 6 ) == 0 )
  235. break;
  236. if( strnicmp( Line, "$INDEX", 6 ) == 0 )
  237. {
  238. while( reader.ReadLine() )
  239. {
  240. Line = reader.Line();
  241. if( strnicmp( Line, "$EndINDEX", 9 ) == 0 )
  242. break;
  243. StrPurge( Line );
  244. msg = CONV_FROM_UTF8( Line );
  245. if( msg.CmpNoCase( aModuleName ) == 0 )
  246. {
  247. Found = 1;
  248. break; /* Found! */
  249. }
  250. }
  251. }
  252. }
  253. /* Read library. */
  254. while( Found && reader.ReadLine() )
  255. {
  256. Line = reader.Line();
  257. if( Line[0] != '$' )
  258. continue;
  259. if( Line[1] != 'M' )
  260. continue;
  261. if( strnicmp( Line, "$MODULE", 7 ) != 0 )
  262. continue;
  263. StrPurge( Line + 8 );
  264. // Read module name.
  265. Name = CONV_FROM_UTF8( Line + 8 );
  266. if( Name.CmpNoCase( aModuleName ) == 0 )
  267. {
  268. NewModule = new MODULE( GetBoard() );
  269. // Switch the locale to standard C (needed to print
  270. // floating point numbers like 1.3)
  271. SetLocaleTo_C_standard();
  272. NewModule->ReadDescr( &reader );
  273. SetLocaleTo_Default(); // revert to the current locale
  274. GetBoard()->Add( NewModule, ADD_APPEND );
  275. SetStatusText( wxEmptyString );
  276. return NewModule;
  277. }
  278. }
  279. if( one_lib )
  280. break;
  281. }
  282. if( aDisplayMessageError )
  283. {
  284. msg.Printf( _( "Module <%s> not found" ), GetChars( aModuleName ) );
  285. DisplayError( NULL, msg );
  286. }
  287. return NULL;
  288. }
  289. /**
  290. * Function Select_1_Module_From_List
  291. * Display a list of modules found in active libraries or a given library
  292. *
  293. * @param aWindow - The active window.
  294. * @param aLibraryFullFilename = library to list (if aLibraryFullFilename ==
  295. * void, list all modules)
  296. * @param aMask = Display filter (wildcard)( Mask = wxEmptyString if not used )
  297. * @param aKeyWord = keyword list, to display a filtered list of module having
  298. * one (or more) of these keyworks in their keywork list
  299. * ( aKeyWord = wxEmptyString if not used )
  300. *
  301. * @return wxEmptyString if abort or fails, or the selected module name if Ok
  302. */
  303. wxString WinEDA_BasePcbFrame::Select_1_Module_From_List( EDA_DRAW_FRAME* aWindow,
  304. const wxString& aLibraryFullFilename,
  305. const wxString& aMask,
  306. const wxString& aKeyWord )
  307. {
  308. unsigned ii;
  309. char* Line;
  310. wxFileName fn;
  311. static wxString OldName; /* Save the name of the last module loaded. */
  312. wxString CmpName;
  313. wxString libFullName;
  314. FILE* file;
  315. wxString msg;
  316. wxArrayString itemslist;
  317. wxBeginBusyCursor();
  318. /* Find modules in libraries. */
  319. for( ii = 0; ii < g_LibName_List.GetCount(); ii++ )
  320. {
  321. /* Calculate the full file name of the library. */
  322. if( aLibraryFullFilename.IsEmpty() )
  323. {
  324. fn = wxFileName( wxEmptyString, g_LibName_List[ii],
  325. ModuleFileExtension );
  326. }
  327. else
  328. fn = aLibraryFullFilename;
  329. libFullName = wxGetApp().FindLibraryPath( fn );
  330. if( libFullName.IsEmpty() )
  331. {
  332. msg.Printf( _( "PCB footprint library file <%s> not found in search paths." ),
  333. GetChars( fn.GetFullName() ) );
  334. wxMessageBox( msg, _( "Library Load Error" ),
  335. wxOK | wxICON_ERROR, this );
  336. continue;
  337. }
  338. ReadDocLib( libFullName );
  339. if( !aKeyWord.IsEmpty() ) /* Don't read the library if selection
  340. * by keywords, already read. */
  341. {
  342. if( !aLibraryFullFilename.IsEmpty() )
  343. break;
  344. continue;
  345. }
  346. file = wxFopen( libFullName, wxT( "rt" ) );
  347. if( file == NULL )
  348. {
  349. if( !aLibraryFullFilename.IsEmpty() )
  350. break;
  351. continue;
  352. }
  353. FILE_LINE_READER fileReader( file, libFullName );
  354. FILTER_READER reader( fileReader );
  355. // Statusbar library loaded message
  356. msg = _( "Library " ) + fn.GetFullPath() + _( " loaded" );
  357. SetStatusText( msg );
  358. /* Read header. */
  359. reader.ReadLine();
  360. Line = reader.Line();
  361. if( strnicmp( Line, ENTETE_LIBRAIRIE, L_ENTETE_LIB ) != 0 )
  362. {
  363. msg.Printf( _( "<%s> is not a valid Kicad PCB footprint library file." ),
  364. GetChars( libFullName ) );
  365. wxMessageBox( msg, _( "Library Load Error" ), wxOK | wxICON_ERROR, this );
  366. continue;
  367. }
  368. /* Read library. */
  369. while( reader.ReadLine() )
  370. {
  371. Line = reader.Line();
  372. if( Line[0] != '$' )
  373. continue;
  374. if( strnicmp( Line, "$MODULE", 6 ) == 0 )
  375. break;
  376. if( strnicmp( Line, "$INDEX", 6 ) == 0 )
  377. {
  378. while( reader.ReadLine() )
  379. {
  380. Line = reader.Line();
  381. if( strnicmp( Line, "$EndINDEX", 9 ) == 0 )
  382. break;
  383. strupper( Line );
  384. msg = CONV_FROM_UTF8( StrPurge( Line ) );
  385. if( aMask.IsEmpty() )
  386. itemslist.Add( msg );
  387. else if( WildCompareString( aMask, msg, false ) )
  388. itemslist.Add( msg );
  389. }
  390. } /* End read INDEX */
  391. }
  392. /* End read library. */
  393. file = NULL;
  394. if( !aLibraryFullFilename.IsEmpty() )
  395. break;
  396. }
  397. /* Create list of modules if search by keyword. */
  398. if( !aKeyWord.IsEmpty() )
  399. {
  400. FOOTPRINT_ITEM* ItemMod = MList;
  401. while( ItemMod != NULL )
  402. {
  403. if( KeyWordOk( aKeyWord, ItemMod->m_KeyWord ) )
  404. itemslist.Add( ItemMod->m_Name );
  405. ItemMod = ItemMod->Next;
  406. }
  407. }
  408. wxEndBusyCursor();
  409. msg.Printf( _( "Modules [%d items]" ), itemslist.GetCount() );
  410. WinEDAListBox dlg( aWindow, msg, itemslist, OldName,
  411. DisplayCmpDoc, GetComponentDialogPosition() );
  412. dlg.SortList();
  413. if( dlg.ShowModal() == wxID_OK )
  414. CmpName = dlg.GetTextSelection();
  415. else
  416. CmpName.Empty();
  417. while( MList != NULL )
  418. {
  419. FOOTPRINT_ITEM* NewMod = MList->Next;
  420. delete MList;
  421. MList = NewMod;
  422. }
  423. if( CmpName != wxEmptyString )
  424. OldName = CmpName;
  425. return CmpName;
  426. }
  427. /* Find and display the doc Component Name
  428. * The list of doc is pointed to by mlist.
  429. */
  430. static void DisplayCmpDoc( wxString& Name )
  431. {
  432. FOOTPRINT_ITEM* Mod = MList;
  433. if( !Mod )
  434. {
  435. Name.Empty();
  436. return;
  437. }
  438. while( Mod )
  439. {
  440. if( !Mod->m_Name.IsEmpty() && ( Mod->m_Name.CmpNoCase( Name ) == 0 ) )
  441. break;
  442. Mod = Mod->Next;
  443. }
  444. if( Mod )
  445. {
  446. Name = !Mod->m_Doc.IsEmpty() ? Mod->m_Doc : wxT( "No Doc" );
  447. Name += wxT( "\nKeyW: " );
  448. Name += !Mod->m_KeyWord.IsEmpty() ? Mod->m_KeyWord : wxT( "No Keyword" );
  449. }
  450. else
  451. Name = wxEmptyString;
  452. }
  453. /* Read the doc file and combine with a library ModLibName.
  454. * Load in memory the list of docs string pointed to by mlist
  455. * ModLibName = full file name of the library modules
  456. */
  457. static void ReadDocLib( const wxString& ModLibName )
  458. {
  459. FOOTPRINT_ITEM* NewMod;
  460. char* Line;
  461. FILE* LibDoc;
  462. wxFileName fn = ModLibName;
  463. fn.SetExt( EXT_DOC );
  464. if( ( LibDoc = wxFopen( fn.GetFullPath(), wxT( "rt" ) ) ) == NULL )
  465. return;
  466. FILE_LINE_READER fileReader( LibDoc, fn.GetFullPath() );
  467. FILTER_READER reader( fileReader );
  468. reader.ReadLine();
  469. Line = reader.Line();
  470. if( strnicmp( Line, ENTETE_LIBDOC, L_ENTETE_LIB ) != 0 )
  471. return;
  472. while( reader.ReadLine() )
  473. {
  474. Line = reader.Line();
  475. if( Line[0] != '$' )
  476. continue;
  477. if( Line[1] == 'E' )
  478. break; ;
  479. if( Line[1] == 'M' ) /* Debut decription 1 module */
  480. {
  481. NewMod = new FOOTPRINT_ITEM();
  482. NewMod->Next = MList;
  483. MList = NewMod;
  484. while( reader.ReadLine() )
  485. {
  486. Line = reader.Line();
  487. if( Line[0] == '$' ) /* $EndMODULE */
  488. break;
  489. switch( Line[0] )
  490. {
  491. case 'L': /* LibName */
  492. NewMod->m_Name = CONV_FROM_UTF8( StrPurge( Line + 3 ) );
  493. break;
  494. case 'K': /* KeyWords */
  495. NewMod->m_KeyWord = CONV_FROM_UTF8( StrPurge( Line + 3 ) );
  496. break;
  497. case 'C': /* Doc */
  498. NewMod->m_Doc = CONV_FROM_UTF8( StrPurge( Line + 3 ) );
  499. break;
  500. }
  501. }
  502. } /* End read 1 module. */
  503. }
  504. }
  505. /**
  506. * Function Select_1_Module_From_BOARD
  507. * Display the list of modules currently existing on the BOARD
  508. * @return a pointer to a module if this module is selected or NULL otherwise
  509. * @param aPcb = the board from modules can be loaded
  510. */
  511. MODULE* WinEDA_ModuleEditFrame::Select_1_Module_From_BOARD( BOARD* aPcb )
  512. {
  513. MODULE* Module;
  514. static wxString OldName; /* Save name of last module selectec. */
  515. wxString CmpName, msg;
  516. wxArrayString listnames;
  517. Module = aPcb->m_Modules;
  518. for( ; Module != NULL; Module = (MODULE*) Module->Next() )
  519. listnames.Add( Module->m_Reference->m_Text );
  520. msg.Printf( _( "Modules [%d items]" ), listnames.GetCount() );
  521. WinEDAListBox dlg( this, msg, listnames, wxEmptyString );
  522. dlg.SortList();
  523. if( dlg.ShowModal() == wxID_OK )
  524. CmpName = dlg.GetTextSelection();
  525. else
  526. return NULL;
  527. OldName = CmpName;
  528. Module = aPcb->m_Modules;
  529. for( ; Module != NULL; Module = (MODULE*) Module->Next() )
  530. {
  531. if( CmpName == Module->m_Reference->m_Text )
  532. break;
  533. }
  534. return Module;
  535. }