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