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