KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_edit_symbols_libid.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright 2017 Jean-Pierre Charras, [email protected]
5 * Copyright 1992-2022, 2024 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
31#include <confirm.h>
32#include <sch_commit.h>
33#include <sch_edit_frame.h>
34#include <sch_symbol.h>
35#include <sch_reference_list.h>
36#include <schematic.h>
37#include <symbol_lib_table.h>
38#include <trace_helpers.h>
39#include <widgets/wx_grid.h>
40
42#include <wx/tokenzr.h>
43#include <wx/choicdlg.h>
44#include <wx/dcclient.h>
45#include <wx/msgdlg.h>
46#include <grid_tricks.h>
48#include <kiplatform/ui.h>
49#include <string_utils.h>
50#include <project_sch.h>
51
52
53#define COL_REFS 0
54#define COL_CURR_LIBID 1
55#define COL_NEW_LIBID 2
56
57// a re-implementation of wxGridCellAutoWrapStringRenderer to allow workaround to autorowsize bug
58class GRIDCELL_AUTOWRAP_STRINGRENDERER : public wxGridCellAutoWrapStringRenderer
59{
60public:
61 int GetHeight( wxDC& aDC, wxGrid* aGrid, int aRow, int aCol );
62
63 wxGridCellRenderer *Clone() const override
65
66private:
67 // HELPER ROUTINES UNCHANGED FROM wxWidgets IMPLEMENTATION
68
69 wxArrayString GetTextLines( wxGrid& grid, wxDC& dc, const wxGridCellAttr& attr,
70 const wxRect& rect, int row, int col );
71
72 // Helper methods of GetTextLines()
73
74 // Break a single logical line of text into several physical lines, all of
75 // which are added to the lines array. The lines are broken at maxWidth and
76 // the dc is used for measuring text extent only.
77 void BreakLine( wxDC& dc, const wxString& logicalLine, wxCoord maxWidth, wxArrayString& lines );
78
79 // Break a word, which is supposed to be wider than maxWidth, into several
80 // lines, which are added to lines array and the last, incomplete, of which
81 // is returned in line output parameter.
82 //
83 // Returns the width of the last line.
84 wxCoord BreakWord( wxDC& dc, const wxString& word, wxCoord maxWidth, wxArrayString& lines,
85 wxString& line );
86};
87
88
89// PRIVATE METHOD UNCHANGED FROM wxWidgets IMPLEMENTATION
91 const wxGridCellAttr& attr,
92 const wxRect& rect, int row, int col )
93{
94 dc.SetFont( attr.GetFont() );
95 const wxCoord maxWidth = rect.GetWidth();
96
97 // Transform logical lines into physical ones, wrapping the longer ones.
98 const wxArrayString logicalLines = wxSplit( grid.GetCellValue( row, col ), '\n', '\0' );
99
100 // Trying to do anything if the column is hidden anyhow doesn't make sense
101 // and we run into problems in BreakLine() in this case.
102 if( maxWidth <= 0 )
103 return logicalLines;
104
105 wxArrayString physicalLines;
106
107 for( const wxString& line : logicalLines )
108 {
109 if( dc.GetTextExtent( line ).x > maxWidth )
110 {
111 // Line does not fit, break it up.
112 BreakLine( dc, line, maxWidth, physicalLines );
113 }
114 else // The entire line fits as is
115 {
116 physicalLines.push_back( line );
117 }
118 }
119
120 return physicalLines;
121}
122
123
124// PRIVATE METHOD UNCHANGED FROM wxWidgets IMPLEMENTATION
125void GRIDCELL_AUTOWRAP_STRINGRENDERER::BreakLine( wxDC& dc, const wxString& logicalLine,
126 wxCoord maxWidth, wxArrayString& lines )
127{
128 wxCoord lineWidth = 0;
129 wxString line;
130
131 // For each word
132 wxStringTokenizer wordTokenizer( logicalLine, wxS( " \t" ), wxTOKEN_RET_DELIMS );
133
134 while( wordTokenizer.HasMoreTokens() )
135 {
136 const wxString word = wordTokenizer.GetNextToken();
137 const wxCoord wordWidth = dc.GetTextExtent( word ).x;
138
139 if( lineWidth + wordWidth < maxWidth )
140 {
141 // Word fits, just add it to this line.
142 line += word;
143 lineWidth += wordWidth;
144 }
145 else
146 {
147 // Word does not fit, check whether the word is itself wider that
148 // available width
149 if( wordWidth < maxWidth )
150 {
151 // Word can fit in a new line, put it at the beginning
152 // of the new line.
153 lines.push_back( line );
154 line = word;
155 lineWidth = wordWidth;
156 }
157 else // Word cannot fit in available width at all.
158 {
159 if( !line.empty() )
160 {
161 lines.push_back( line );
162 line.clear();
163 lineWidth = 0;
164 }
165
166 // Break it up in several lines.
167 lineWidth = BreakWord( dc, word, maxWidth, lines, line );
168 }
169 }
170 }
171
172 if( !line.empty() )
173 lines.push_back( line );
174}
175
176
177// PRIVATE METHOD UNCHANGED FROM wxWidgets IMPLEMENTATION
178wxCoord GRIDCELL_AUTOWRAP_STRINGRENDERER::BreakWord( wxDC& dc, const wxString& word,
179 wxCoord maxWidth, wxArrayString& lines,
180 wxString& line )
181{
182 wxArrayInt widths;
183 dc.GetPartialTextExtents( word, widths );
184
185 // TODO: Use binary search to find the first element > maxWidth.
186 const unsigned count = widths.size();
187 unsigned n;
188
189 for( n = 0; n < count; n++ )
190 {
191 if( widths[n] > maxWidth )
192 break;
193 }
194
195 if( n == 0 )
196 {
197 // This is a degenerate case: the first character of the word is
198 // already wider than the available space, so we just can't show it
199 // completely and have to put the first character in this line.
200 n = 1;
201 }
202
203 lines.push_back( word.substr( 0, n ) );
204
205 // Check if the remainder of the string fits in one line.
206 //
207 // Unfortunately we can't use the existing partial text extents as the
208 // extent of the remainder may be different when it's rendered in a
209 // separate line instead of as part of the same one, so we have to
210 // recompute it.
211 const wxString rest = word.substr( n );
212 const wxCoord restWidth = dc.GetTextExtent( rest ).x;
213
214 if( restWidth <= maxWidth )
215 {
216 line = rest;
217 return restWidth;
218 }
219
220 // Break the rest of the word into lines.
221 //
222 // TODO: Perhaps avoid recursion? The code is simpler like this but using a
223 // loop in this function would probably be more efficient.
224 return BreakWord( dc, rest, maxWidth, lines, line );
225}
226
227
228#define GRID_CELL_MARGIN 4
229
230int GRIDCELL_AUTOWRAP_STRINGRENDERER::GetHeight( wxDC& aDC, wxGrid* aGrid, int aRow, int aCol )
231{
232 wxGridCellAttr* attr = aGrid->GetOrCreateCellAttr( aRow, aCol );
233 wxRect rect;
234
235 aDC.SetFont( attr->GetFont() );
236 rect.SetWidth( aGrid->GetColSize( aCol ) - ( 2 * GRID_CELL_MARGIN ) );
237
238 const size_t numLines = GetTextLines( *aGrid, aDC, *attr, rect, aRow, aCol ).size();
239 const int textHeight = numLines * aDC.GetCharHeight();
240
241 attr->DecRef();
242
243 return textHeight + ( 2 * GRID_CELL_MARGIN );
244}
245
246
251{
252public:
254 {
255 m_Symbol = aSymbol;
257 m_Row = -1;
258 m_IsOrphan = false;
259 m_Screen = nullptr;
260 }
261
262 // Return a string like mylib:symbol_name from the #LIB_ID of the symbol.
263 wxString GetStringLibId()
264 {
266 }
267
268 SCH_SYMBOL* m_Symbol; // the schematic symbol
269 int m_Row; // the row index in m_grid
270 SCH_SCREEN* m_Screen; // the screen where m_Symbol lives
271 wxString m_Reference; // the schematic reference, only to display it in list
272 wxString m_InitialLibId; // the Lib Id of the symbol before any change.
273 bool m_IsOrphan; // true if a symbol has no corresponding symbol found in libs.
274};
275
276
286{
287public:
290
292
294
295private:
296 void initDlg();
297
305 void AddRowToGrid( bool aMarkRow, const wxString& aReferences, const wxString& aStrLibId );
306
308 bool validateLibIds();
309
316 bool setLibIdByBrowser( int aRow );
317
318 // Event handlers
319
320 // called on a right click or a left double click:
321 void onCellBrowseLib( wxGridEvent& event ) override;
322
323 // Cancel all changes, and close the dialog
324 void onCancel( wxCommandEvent& event ) override
325 {
326 // Just skipping the event doesn't work after the library browser was run
327 if( IsQuasiModal() )
328 EndQuasiModal( wxID_CANCEL );
329 else
330 event.Skip();
331 }
332
333 // Try to find a candidate for non existing symbols
334 void onClickOrphansButton( wxCommandEvent& event ) override;
335
336 // Automatically called when click on OK button
337 bool TransferDataFromWindow() override;
338
339 void AdjustGridColumns();
340
341 void OnSizeGrid( wxSizeEvent& event ) override;
342
343 bool m_isModified; // set to true if the schematic is modified
344 std::vector<int> m_OrphansRowIndexes; // list of rows containing orphan lib_id
345
346 std::vector<SYMBOL_CANDIDATE> m_symbols;
347
349};
350
351
354{
356
357 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
358
359 initDlg();
360
362}
363
364
366{
367 // Delete the GRID_TRICKS.
368 m_grid->PopEventHandler( true );
369
370 m_autoWrapRenderer->DecRef();
371}
372
373
374// A sort compare function to sort symbols list by LIB_ID and then reference.
375static bool sort_by_libid( const SYMBOL_CANDIDATE& candidate1, const SYMBOL_CANDIDATE& candidate2 )
376{
377 if( candidate1.m_Symbol->GetLibId() == candidate2.m_Symbol->GetLibId() )
378 return candidate1.m_Reference.Cmp( candidate2.m_Reference ) < 0;
379
380 return candidate1.m_Symbol->GetLibId() < candidate2.m_Symbol->GetLibId();
381}
382
383
385{
386 // Clear the FormBuilder rows
387 m_grid->ClearRows();
388
389 m_isModified = false;
390
391 // This option build the full symbol list.
392 // In complex hierarchies, the same symbol is in fact duplicated, but
393 // it is listed with different references (one by sheet instance)
394 // the list is larger and looks like it contains all symbols.
395 SCH_REFERENCE_LIST references;
396
397 // build the full list of symbols including symbol having no symbol in loaded libs
398 // (orphan symbols)
399 GetParent()->Schematic().Hierarchy().GetSymbols( references,
400 true /* include power symbols */,
401 true /* include orphan symbols */ );
402
403 for( unsigned ii = 0; ii < references.GetCount(); ii++ )
404 {
405 SCH_REFERENCE& item = references[ii];
406 SYMBOL_CANDIDATE candidate( item.GetSymbol() );
407 candidate.m_Screen = item.GetSheetPath().LastScreen();
408 SCH_SHEET_PATH sheetpath = item.GetSheetPath();
409 candidate.m_Reference = candidate.m_Symbol->GetRef( &sheetpath );
410 int unitcount = candidate.m_Symbol->GetUnitCount();
411 candidate.m_IsOrphan = ( unitcount == 0 );
412 m_symbols.push_back( candidate );
413 }
414
415 if( m_symbols.size() == 0 )
416 return;
417
418 // now sort by lib id to create groups of items having the same lib id
419 std::sort( m_symbols.begin(), m_symbols.end(), sort_by_libid );
420
421 // Now, fill m_grid
422 wxString last_str_libid = m_symbols.front().GetStringLibId();
423 int row = 0;
424 wxString refs;
425 wxString last_ref;
426 bool mark_cell = m_symbols.front().m_IsOrphan;
427
428 for( SYMBOL_CANDIDATE& symbol : m_symbols )
429 {
430 wxString str_libid = symbol.GetStringLibId();
431
432 if( last_str_libid != str_libid )
433 {
434 // Add last group to grid
435 AddRowToGrid( mark_cell, refs, last_str_libid );
436
437 // prepare next entry
438 mark_cell = symbol.m_IsOrphan;
439 last_str_libid = str_libid;
440 refs.Empty();
441 row++;
442 }
443 else if( symbol.m_Reference == last_ref )
444 {
445 symbol.m_Row = row;
446 continue;
447 }
448
449 last_ref = symbol.m_Reference;
450
451 if( !refs.IsEmpty() )
452 refs += wxT( ", " );
453
454 refs += symbol.m_Reference;
455 symbol.m_Row = row;
456 }
457
458 // Add last symbol group:
459 AddRowToGrid( mark_cell, refs, last_str_libid );
460
461 // Allows only the selection by row
462 m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
463
464 m_buttonOrphanItems->Enable( m_OrphansRowIndexes.size() > 0 );
465 Layout();
466}
467
468
470{
471 return dynamic_cast<SCH_EDIT_FRAME*>( wxDialog::GetParent() );
472}
473
474
475void DIALOG_EDIT_SYMBOLS_LIBID::AddRowToGrid( bool aMarkRow, const wxString& aReferences,
476 const wxString& aStrLibId )
477{
478 int row = m_grid->GetNumberRows();
479
480 if( aMarkRow ) // An orphaned symbol exists, set m_AsOrphanCmp as true.
481 m_OrphansRowIndexes.push_back( row );
482
483 m_grid->AppendRows( 1 );
484
485 m_grid->SetCellValue( row, COL_REFS, UnescapeString( aReferences ) );
486 m_grid->SetReadOnly( row, COL_REFS );
487
488 m_grid->SetCellValue( row, COL_CURR_LIBID, UnescapeString( aStrLibId ) );
489 m_grid->SetReadOnly( row, COL_CURR_LIBID );
490
491 if( aMarkRow ) // A symbol is not existing in libraries: mark the cell
492 {
493 wxFont font = m_grid->GetDefaultCellFont();
494 font.MakeBold();
495 font.MakeItalic();
496 m_grid->SetCellFont( row, COL_CURR_LIBID, font );
497 }
498
499 m_grid->SetCellRenderer( row, COL_REFS, m_autoWrapRenderer->Clone() );
500
501 // wxWidgets' AutoRowHeight fails when used with wxGridCellAutoWrapStringRenderer
502 // (fixed in 2014, but didn't get in to wxWidgets 3.0.2)
503 wxClientDC dc( this );
504 m_grid->SetRowSize( row, m_autoWrapRenderer->GetHeight( dc, m_grid, row, COL_REFS ) );
505
506 // set new libid column browse button
507 wxGridCellAttr* attr = new wxGridCellAttr;
508 attr->SetEditor( new GRID_CELL_SYMBOL_ID_EDITOR( this, UnescapeString( aStrLibId ) ) );
509 m_grid->SetAttr( row, COL_NEW_LIBID, attr );
510}
511
512
513wxString getLibIdValue( const WX_GRID* aGrid, int aRow, int aCol )
514{
515 wxString rawValue = aGrid->GetCellValue( aRow, aCol );
516
517 if( rawValue.IsEmpty() )
518 return rawValue;
519
520 wxString itemName;
521 wxString libName = rawValue.BeforeFirst( ':', &itemName );
522
523 return EscapeString( libName, CTX_LIBID ) + ':' + EscapeString( itemName, CTX_LIBID );
524}
525
526
528{
530 return false;
531
532 int row_max = m_grid->GetNumberRows() - 1;
533
534 for( int row = 0; row <= row_max; row++ )
535 {
536 wxString new_libid = getLibIdValue( m_grid, row, COL_NEW_LIBID );
537
538 if( new_libid.IsEmpty() )
539 continue;
540
541 // a new lib id is found. validate this new value
542 LIB_ID id;
543 id.Parse( new_libid );
544
545 if( !id.IsValid() )
546 {
547 wxString msg;
548 msg.Printf( _( "Symbol library identifier %s is not valid." ), new_libid );
549 wxMessageBox( msg );
550
551 m_grid->SetFocus();
552 m_grid->MakeCellVisible( row, COL_NEW_LIBID );
553 m_grid->SetGridCursor( row, COL_NEW_LIBID );
554
555 m_grid->EnableCellEditControl( true );
556 m_grid->ShowCellEditControl();
557
558 return false;
559 }
560 }
561
562 return true;
563}
564
565
567{
568 int row = event.GetRow();
569 m_grid->SelectRow( row ); // only for user, to show the selected line
570
571 setLibIdByBrowser( row );
572
573}
574
575
577{
578 std::vector<wxString> libs = PROJECT_SCH::SchSymbolLibTable( &Prj() )->GetLogicalLibs();
579 wxArrayString aliasNames;
580 wxArrayString candidateSymbNames;
581
582 unsigned fixesCount = 0;
583
584 // Try to find a candidate for non existing symbols in any loaded library
585 for( int orphanRow : m_OrphansRowIndexes )
586 {
587 wxString orphanLibid = getLibIdValue( m_grid, orphanRow, COL_CURR_LIBID );
588 int grid_row_idx = orphanRow; //row index in m_grid for the current item
589
590 LIB_ID curr_libid;
591 curr_libid.Parse( orphanLibid, true );
592 wxString symbolName = curr_libid.GetLibItemName();
593
594 // number of full LIB_ID candidates (because we search for a symbol name
595 // inside all available libraries, perhaps the same symbol name can be found
596 // in more than one library, giving ambiguity
597 int libIdCandidateCount = 0;
598 candidateSymbNames.Clear();
599
600 // now try to find a candidate
601 for( const wxString &lib : libs )
602 {
603 aliasNames.Clear();
604
605 try
606 {
607 PROJECT_SCH::SchSymbolLibTable( &Prj() )->EnumerateSymbolLib( lib, aliasNames );
608 }
609 catch( const IO_ERROR& ) {} // ignore, it is handled below
610
611 if( aliasNames.IsEmpty() )
612 continue;
613
614 // Find a symbol name in symbols inside this library:
615 int index = aliasNames.Index( symbolName );
616
617 if( index != wxNOT_FOUND )
618 {
619 // a candidate is found!
620 libIdCandidateCount++;
621 wxString newLibid = lib + ':' + symbolName;
622
623 // Uses the first found. Most of time, it is alone.
624 // Others will be stored in a candidate list
625 if( libIdCandidateCount <= 1 )
626 {
627 m_grid->SetCellValue( grid_row_idx, COL_NEW_LIBID, UnescapeString( newLibid ) );
628 candidateSymbNames.Add( m_grid->GetCellValue( grid_row_idx, COL_NEW_LIBID ) );
629 fixesCount++;
630 }
631 else // Store other candidates for later selection
632 {
633 candidateSymbNames.Add( UnescapeString( newLibid ) );
634 }
635 }
636 }
637
638 // If more than one LIB_ID candidate, ask for selection between candidates:
639 if( libIdCandidateCount > 1 )
640 {
641 // Mainly for user: select the row being edited
642 m_grid->SelectRow( grid_row_idx );
643
644 wxString msg;
645 msg.Printf( _( "Available Candidates for %s " ),
646 m_grid->GetCellValue( grid_row_idx, COL_CURR_LIBID ) );
647
648 wxSingleChoiceDialog dlg ( this, msg,
649 wxString::Format( _( "Candidates count %d " ),
650 libIdCandidateCount ),
651 candidateSymbNames );
652
653 if( dlg.ShowModal() == wxID_OK )
654 m_grid->SetCellValue( grid_row_idx, COL_NEW_LIBID, dlg.GetStringSelection() );
655 }
656 }
657
658 if( fixesCount < m_OrphansRowIndexes.size() ) // Not all orphan symbols are fixed.
659 {
660 wxMessageBox( wxString::Format( _( "%u link(s) mapped, %u not found" ),
661 fixesCount,
662 (unsigned) m_OrphansRowIndexes.size() - fixesCount ) );
663 }
664 else
665 {
666 wxMessageBox( wxString::Format( _( "All %u link(s) resolved" ), fixesCount ) );
667 }
668}
669
670
672{
673 // Use library viewer to choose a symbol
674 std::vector<PICKED_SYMBOL> dummyHistory;
675 std::vector<PICKED_SYMBOL> dummyAlreadyPlaced;
676 LIB_ID preselected;
677 wxString current = getLibIdValue( m_grid, aRow, COL_NEW_LIBID );
678
679 if( current.IsEmpty() )
680 current = getLibIdValue( m_grid, aRow, COL_CURR_LIBID );
681
682 if( !current.IsEmpty() )
683 preselected.Parse( current, true );
684
686 nullptr, dummyHistory, dummyAlreadyPlaced, false, &preselected, false );
687
688 if( sel.LibId.empty() ) // command aborted
689 return false;
690
691 if( !sel.LibId.IsValid() ) // Should not occur
692 {
693 wxMessageBox( _( "Invalid symbol library identifier" ) );
694 return false;
695 }
696
697 wxString new_libid;
698 new_libid = sel.LibId.Format().wx_str();
699
700 m_grid->SetCellValue( aRow, COL_NEW_LIBID, UnescapeString( new_libid ) );
701
702 return true;
703}
704
705
707{
708 if( !validateLibIds() )
709 return false;
710
711 SCH_COMMIT commit( GetParent() );
712
713 auto getName = []( const LIB_ID& aLibId )
714 {
715 return UnescapeString( aLibId.GetLibItemName().wx_str() );
716 };
717
718 int row_max = m_grid->GetNumberRows() - 1;
719
720 for( int row = 0; row <= row_max; row++ )
721 {
722 wxString new_libid = getLibIdValue( m_grid, row, COL_NEW_LIBID );
723
724 if( new_libid.IsEmpty() || new_libid == getLibIdValue( m_grid, row, COL_CURR_LIBID ) )
725 continue;
726
727 // A new lib id is found and was already validated.
728 LIB_ID id;
729 id.Parse( new_libid, true );
730
731 for( SYMBOL_CANDIDATE& candidate : m_symbols )
732 {
733 if( candidate.m_Row != row )
734 continue;
735
736 LIB_SYMBOL* symbol = nullptr;
737
738 try
739 {
740 symbol = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( id );
741 }
742 catch( const IO_ERROR& ioe )
743 {
744 wxString msg;
745
746 msg.Printf( _( "Error loading symbol %s from library %s.\n\n%s" ),
747 id.GetLibItemName().wx_str(),
748 id.GetLibNickname().wx_str(),
749 ioe.What() );
750
751 DisplayErrorMessage( this, msg );
752 }
753
754 if( symbol == nullptr )
755 continue;
756
757 commit.Modify( candidate.m_Symbol, candidate.m_Screen );
758 m_isModified = true;
759
760 candidate.m_Screen->Remove( candidate.m_Symbol );
761 SCH_FIELD* value = candidate.m_Symbol->GetField( VALUE_FIELD );
762
763 // If value is a proxy for the itemName then make sure it gets updated
764 if( getName( candidate.m_Symbol->GetLibId() ) == value->GetText() )
765 candidate.m_Symbol->SetValueFieldText( getName( id ) );
766
767 candidate.m_Symbol->SetLibId( id );
768 candidate.m_Symbol->SetLibSymbol( symbol->Flatten().release() );
769 candidate.m_Screen->Append( candidate.m_Symbol );
770 candidate.m_Screen->SetContentModified();
771
772 if ( m_checkBoxUpdateFields->IsChecked() )
773 {
774 candidate.m_Symbol->UpdateFields( nullptr,
775 false, /* update style */
776 false, /* update ref */
777 false, /* update other fields */
778 false, /* reset ref */
779 true /* reset other fields */ );
780 }
781 }
782 }
783
784 if( m_modified )
785 commit.Push( wxS( "Change Symbol Library Indentifier" ) );
786
787 return true;
788}
789
790
792{
793 // Account for scroll bars
795
796 int colWidth = width / 3;
797
798 m_grid->SetColSize( COL_REFS, colWidth );
799 width -= colWidth;
800
801 colWidth = 0;
802
803 for( int row = 0; row < m_grid->GetNumberRows(); ++row )
804 {
805 wxString cellValue = m_grid->GetCellValue( row, COL_CURR_LIBID );
806 colWidth = std::max( colWidth, KIUI::GetTextSize( cellValue, m_grid ).x );
807 }
808
809 colWidth += 20;
810 m_grid->SetColSize( COL_CURR_LIBID, colWidth );
811 width -= colWidth;
812
813 colWidth = 0;
814
815 for( int row = 0; row < m_grid->GetNumberRows(); ++row )
816 {
817 wxString cellValue = m_grid->GetCellValue( row, COL_NEW_LIBID );
818 colWidth = std::max( colWidth, KIUI::GetTextSize( cellValue, m_grid ).x );
819 }
820
821 colWidth += 20;
822 m_grid->SetColSize( COL_NEW_LIBID, std::max( colWidth, width ) );
823}
824
825
827{
829
830 wxClientDC dc( this );
831
832 // wxWidgets' AutoRowHeight fails when used with wxGridCellAutoWrapStringRenderer
833 for( int row = 0; row < m_grid->GetNumberRows(); ++row )
834 m_grid->SetRowSize( row, m_autoWrapRenderer->GetHeight( dc, m_grid, row, COL_REFS ) );
835
836 event.Skip();
837}
838
839
841{
842 // This dialog itself subsequently can invoke a KIWAY_PLAYER as a quasimodal
843 // frame. Therefore this dialog as a modal frame parent, MUST be run under
844 // quasimodal mode for the quasimodal frame support to work. So don't use
845 // the QUASIMODAL macros here.
846 DIALOG_EDIT_SYMBOLS_LIBID dlg( aCaller );
847
848 // DO NOT use ShowModal() here, otherwise the library browser will not work properly.
849 dlg.ShowQuasiModal();
850
851 return dlg.IsSchematicModified();
852}
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
Class DIALOG_EDIT_SYMBOLS_LIBID_BASE.
Dialog to globally edit the LIB_ID of groups if symbols having the same initial LIB_ID.
void OnSizeGrid(wxSizeEvent &event) override
std::vector< SYMBOL_CANDIDATE > m_symbols
void onClickOrphansButton(wxCommandEvent &event) override
DIALOG_EDIT_SYMBOLS_LIBID(SCH_EDIT_FRAME *aParent)
bool setLibIdByBrowser(int aRow)
Run the lib browser and set the selected LIB_ID for aRow.
void onCancel(wxCommandEvent &event) override
void onCellBrowseLib(wxGridEvent &event) override
bool validateLibIds()
returns true if all new lib id are valid
GRIDCELL_AUTOWRAP_STRINGRENDERER * m_autoWrapRenderer
void AddRowToGrid(bool aMarkRow, const wxString &aReferences, const wxString &aStrLibId)
Add a new row (new entry) in m_grid.
int ShowQuasiModal()
bool IsQuasiModal() const
Definition: dialog_shim.h:113
void EndQuasiModal(int retCode)
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
wxArrayString GetTextLines(wxGrid &grid, wxDC &dc, const wxGridCellAttr &attr, const wxRect &rect, int row, int col)
int GetHeight(wxDC &aDC, wxGrid *aGrid, int aRow, int aCol)
wxCoord BreakWord(wxDC &dc, const wxString &word, wxCoord maxWidth, wxArrayString &lines, wxString &line)
void BreakLine(wxDC &dc, const wxString &logicalLine, wxCoord maxWidth, wxArrayString &lines)
wxGridCellRenderer * Clone() const override
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:51
bool IsValid() const
Check if this LID_ID is valid.
Definition: lib_id.h:172
bool empty() const
Definition: lib_id.h:193
wxString GetUniStringLibId() const
Definition: lib_id.h:148
UTF8 Format() const
Definition: lib_id.cpp:118
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
Define a library symbol object.
Definition: lib_symbol.h:78
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:304
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
PICKED_SYMBOL PickSymbolFromLibrary(const SYMBOL_LIBRARY_FILTER *aFilter, std::vector< PICKED_SYMBOL > &aHistoryList, std::vector< PICKED_SYMBOL > &aAlreadyPlaced, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Call the library viewer to select symbol to import into schematic.
Definition: picksymbol.cpp:51
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:432
Schematic editor (Eeschema) main window.
SCHEMATIC & Schematic() const
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
size_t GetCount() const
A helper to define a symbol's reference designator in a schematic.
const SCH_SHEET_PATH & GetSheetPath() const
SCH_SYMBOL * GetSymbol() const
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
Schematic symbol object.
Definition: sch_symbol.h:104
const LIB_ID & GetLibId() const override
Definition: sch_symbol.h:193
int GetUnitCount() const override
Return the number of units per package of the symbol.
Definition: sch_symbol.cpp:468
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:737
A helper to handle symbols to edit.
SYMBOL_CANDIDATE(SCH_SYMBOL *aSymbol)
void EnumerateSymbolLib(const wxString &aNickname, wxArrayString &aAliasNames, bool aPowerSymbolsOnly=false)
Return a list of symbol alias names contained within the library given by aNickname.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
wxString wx_str() const
Definition: utf8.cpp:45
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:184
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:637
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
This file is part of the common library.
static bool sort_by_libid(const SYMBOL_CANDIDATE &candidate1, const SYMBOL_CANDIDATE &candidate2)
#define COL_REFS
wxString getLibIdValue(const WX_GRID *aGrid, int aRow, int aCol)
#define COL_NEW_LIBID
#define GRID_CELL_MARGIN
#define COL_CURR_LIBID
bool InvokeDialogEditSymbolsLibId(SCH_EDIT_FRAME *aCaller)
Run a dialog to modify the LIB_ID of symbols for instance when a symbol has moved from a symbol libra...
#define _(s)
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: wxgtk/ui.cpp:195
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition: ui_common.cpp:77
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
Definition: string_utils.h:54
LIB_ID LibId
Definition: sch_screen.h:79
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
wxLogTrace helper definitions.