KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_sheet_properties.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 (C) 2009 Wayne Stambaugh <[email protected]>
5 * Copyright The KiCad Developers, see CHANGELOG.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
26
27#include <kiface_base.h>
28#include <wx/string.h>
29#include <wx/log.h>
30#include <wx/tooltip.h>
31#include <common.h>
32#include <confirm.h>
33#include <kidialog.h>
34#include <validators.h>
35#include <wx_filename.h>
38#include <kiplatform/ui.h>
39#include <sch_commit.h>
40#include <sch_edit_frame.h>
41#include <sch_io/sch_io.h>
42#include <sch_sheet.h>
43#include <schematic.h>
44#include <bitmaps.h>
45#include <eeschema_settings.h>
47#include <trace_helpers.h>
49#include "wx/dcclient.h"
50#include "string_utils.h"
51
53 bool* aIsUndoable, bool* aClearAnnotationNewItems,
54 bool* aUpdateHierarchyNavigator,
55 wxString* aSourceSheetFilename ) :
57 m_frame( aParent ),
58 m_isUndoable( aIsUndoable ),
59 m_clearAnnotationNewItems( aClearAnnotationNewItems ),
60 m_updateHierarchyNavigator( aUpdateHierarchyNavigator ),
61 m_sourceSheetFilename( aSourceSheetFilename ),
62 m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits ),
63 m_dummySheet( *aSheet ),
64 m_dummySheetNameField( &m_dummySheet, FIELD_T::SHEET_NAME )
65{
66 m_sheet = aSheet;
67 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_sheet );
70
72 m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, { &aParent->Schematic() },
73 [&]( wxCommandEvent& aEvent )
74 {
75 OnAddField( aEvent );
76 } ) );
77 m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
78
79 // Show/hide columns according to user's preference
80 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
81 {
82 m_grid->ShowHideColumns( cfg->m_Appearance.edit_sheet_visible_columns );
84 }
85
87 m_infoBar->ShowMessage( _( "Note: individual item colors overridden in Preferences." ) );
88
89 wxSize minSize = m_pageNumberTextCtrl->GetMinSize();
90 int minWidth = m_pageNumberTextCtrl->GetTextExtent( wxT( "XXX.XXX" ) ).GetWidth();
91
92 m_pageNumberTextCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
93
94 wxToolTip::Enable( true );
96
97 // Configure button logos
98 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
99 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
100 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
101 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
102
103 // Set font sizes
105 m_hierarchicalPath->SetFont( KIUI::GetSmallInfoFont( this ) );
106
107 // wxFormBuilder doesn't include this event...
108 m_grid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ),
109 nullptr, this );
110
112}
113
114
116{
117 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
118 cfg->m_Appearance.edit_sheet_visible_columns = m_grid->GetShownColumnsAsString();
119
120 // Prevents crash bug in wxGrid's d'tor
122
123 m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ),
124 nullptr, this );
125
126 // Delete the GRID_TRICKS.
127 m_grid->PopEventHandler( true );
128}
129
130
132{
133 if( !wxDialog::TransferDataToWindow() )
134 return false;
135
136 // Push a copy of each field into m_updateFields
137 for( SCH_FIELD& field : m_sheet->GetFields() )
138 {
139 SCH_FIELD field_copy( field );
140
141#ifdef __WINDOWS__
142 // Filenames are stored using unix notation, so convert to Windows notation
143 if( field_copy.GetId() == FIELD_T::SHEET_FILENAME )
144 {
145 wxString filename = field_copy.GetText();
146 filename.Replace( wxT( "/" ), wxT( "\\" ) );
147 field_copy.SetText( filename );
148 }
149#endif
150
151 // change offset to be symbol-relative
152 field_copy.Offset( -m_sheet->GetPosition() );
153
154 m_fields->push_back( field_copy );
155 }
156
157 // notify the grid
158 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->size() );
159 m_grid->ProcessTableMessage( msg );
161
162 // border width
164
165 // set up color swatches
166 KIGFX::COLOR4D borderColor = m_sheet->GetBorderColor();
167 KIGFX::COLOR4D backgroundColor = m_sheet->GetBackgroundColor();
168
169 m_borderSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
170 m_backgroundSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
171
172 m_borderSwatch->SetSwatchColor( borderColor, false );
173 m_backgroundSwatch->SetSwatchColor( backgroundColor, false );
174
178
180 instance.push_back( m_sheet );
181
182 m_pageNumberTextCtrl->ChangeValue( instance.GetPageNumber() );
183
187 m_cbDNP->SetValue( m_sheet->GetDNP() );
188
189 return true;
190}
191
192
194{
195 if( !m_grid->CommitPendingChanges() || !m_grid->Validate() )
196 return false;
197
198 // Check for missing field names.
199 for( size_t i = 0; i < m_fields->size(); ++i )
200 {
201 SCH_FIELD& field = m_fields->at( i );
202
203 if( field.IsMandatory() )
204 continue;
205
206 if( field.GetName( false ).empty() && !field.GetText().empty() )
207 {
208 DisplayErrorMessage( this, _( "Fields must have a name." ) );
209
211 m_delayedFocusRow = (int) i;
212
213 return false;
214 }
215 }
216
217 return true;
218}
219
220
221static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b )
222{
223 if( a.GetPosition() != b.GetPosition() )
224 return true;
225
226 if( a.GetHorizJustify() != b.GetHorizJustify() )
227 return true;
228
229 if( a.GetVertJustify() != b.GetVertJustify() )
230 return true;
231
232 if( a.GetTextAngle() != b.GetTextAngle() )
233 return true;
234
235 return false;
236}
237
238
240{
242 return true;
243
245 return true;
246
247 return false;
248}
249
250
252{
253 wxCHECK( m_sheet && m_frame, false );
254
255 if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
256 return false;
257
258 if( m_isUndoable )
259 *m_isUndoable = true;
260
261 // Sheet file names can be relative or absolute.
262 wxString sheetFileName = m_fields->GetField( FIELD_T::SHEET_FILENAME )->GetText();
263
264 // Ensure filepath is not empty. (In normal use will be caught by grid validators,
265 // but unedited data from existing files can be bad.)
266 if( sheetFileName.IsEmpty() )
267 {
268 DisplayError( this, _( "A sheet must have a valid file name." ) );
269 return false;
270 }
271
272 // Ensure the filename extension is OK. (In normal use will be caught by grid validators,
273 // but unedited data from existing files can be bad.)
274 sheetFileName = EnsureFileExtension( sheetFileName, FILEEXT::KiCadSchematicFileExtension );
275
276 // Ensure sheetFileName is legal
277 if( !IsFullFileNameValid( sheetFileName ) )
278 {
279 DisplayError( this, _( "A sheet must have a valid file name." ) );
280 return false;
281 }
282
283 wxFileName fn( sheetFileName );
284
285 wxString newRelativeFilename = fn.GetFullPath();
286
287 // Inside Eeschema, filenames are stored using unix notation
288 newRelativeFilename.Replace( wxT( "\\" ), wxT( "/" ) );
289
290 wxString oldFilename = m_sheet->GetField( FIELD_T::SHEET_FILENAME )->GetText();
291 oldFilename.Replace( wxT( "\\" ), wxT( "/" ) );
292
293 bool filename_changed = oldFilename != newRelativeFilename;
294
295 if( filename_changed || m_sheet->IsNew() )
296 {
297 SCH_SCREEN* currentScreen = m_frame->GetCurrentSheet().LastScreen();
298
299 wxCHECK( currentScreen, false );
300
301 bool clearFileName = false;
302
303 // This can happen for the root sheet when opening Eeschema in the stand alone mode.
304 if( currentScreen->GetFileName().IsEmpty() )
305 {
306 clearFileName = true;
307 currentScreen->SetFileName( m_frame->Prj().AbsolutePath( wxT( "noname.kicad_sch" ) ) );
308 }
309
310 wxFileName tmp( fn );
311 wxFileName screenFileName = currentScreen->GetFileName();
312
313 if( fn.IsAbsolute() && fn.MakeRelativeTo( screenFileName.GetPath() ) )
314 {
315 wxMessageDialog makeRelDlg( this, _( "Use relative path for sheet file?" ), _( "Sheet File Path" ),
316 wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
317
318 makeRelDlg.SetExtendedMessage( _( "Using relative hierarchical sheet file name paths improves "
319 "schematic portability across systems and platforms. Using "
320 "absolute paths can result in portability issues." ) );
321 makeRelDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Use Relative Path" ) ),
322 wxMessageDialog::ButtonLabel( _( "Use Absolute Path" ) ) );
323
324 if( makeRelDlg.ShowModal() == wxID_YES )
325 {
326 wxLogTrace( tracePathsAndFiles, "\n Converted absolute path: '%s'"
327 "\n to relative path: '%s'",
328 tmp.GetPath(),
329 fn.GetPath() );
330 m_fields->GetField( FIELD_T::SHEET_FILENAME )->SetText( fn.GetFullPath() );
331 newRelativeFilename = fn.GetFullPath();
332 }
333 }
334
335 if( !onSheetFilenameChanged( newRelativeFilename ) )
336 {
337 if( clearFileName )
338 currentScreen->SetFileName( wxEmptyString );
339 else
340 FindField( *m_fields, FIELD_T::SHEET_FILENAME )->SetText( oldFilename );
341
342 return false;
343 }
345 {
347 }
348
349 if( clearFileName )
350 currentScreen->SetFileName( wxEmptyString );
351
352 // One last validity check (and potential repair) just to be sure to be sure
353 SCH_SHEET_LIST repairedList;
354 repairedList.BuildSheetList( &m_frame->Schematic().Root(), true );
355 }
356
357 wxString newSheetname = m_fields->GetField( FIELD_T::SHEET_NAME )->GetText();
358
359 if( ( newSheetname != m_sheet->GetName() ) && m_updateHierarchyNavigator )
361
362 if( newSheetname.IsEmpty() )
363 newSheetname = _( "Untitled Sheet" );
364
365 m_fields->GetField( FIELD_T::SHEET_NAME )->SetText( newSheetname );
366
367 // change all field positions from relative to absolute
368 for( SCH_FIELD& m_field : *m_fields)
369 m_field.Offset( m_sheet->GetPosition() );
370
373
374 for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
375 {
376 SCH_FIELD& field = m_fields->at( ii );
377
378 if( field.IsMandatory() )
379 continue;
380
381 const wxString& fieldName = field.GetCanonicalName();
382
383 if( field.IsEmpty() )
384 m_fields->erase( m_fields->begin() + ii );
385 else if( fieldName.IsEmpty() )
386 field.SetName( _( "untitled" ) );
387 }
388
390
392
393 COLOR_SETTINGS* colorSettings = m_frame->GetColorSettings();
394
395 if( colorSettings->GetOverrideSchItemColors()
398 {
399 wxPanel temp( this );
400 temp.Hide();
401 PANEL_EESCHEMA_COLOR_SETTINGS prefs( &temp );
402 wxString checkboxLabel = prefs.m_optOverrideColors->GetLabel();
403
404 KIDIALOG dlg( this, _( "Note: item colors are overridden in the current color theme." ),
406 dlg.ShowDetailedText( wxString::Format( _( "To see individual item colors uncheck '%s'\n"
407 "in Preferences > Schematic Editor > Colors." ),
408 checkboxLabel ) );
409 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
410 dlg.ShowModal();
411 }
412
415
419 m_sheet->SetDNP( m_cbDNP->GetValue() );
420
422
423 instance.push_back( m_sheet );
424
425 instance.SetPageNumber( m_pageNumberTextCtrl->GetValue() );
426
428
429 // Refresh all sheets in case ordering changed.
430 for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_SHEET_T ) )
431 m_frame->UpdateItem( item );
432
433 return true;
434}
435
436
437bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilename )
438{
439 wxString msg;
440 wxFileName sheetFileName( EnsureFileExtension( aNewFilename, FILEEXT::KiCadSchematicFileExtension ) );
441
442 // Sheet file names are relative to the path of the current sheet. This allows for
443 // nesting of schematic files in subfolders. Screen file names are always absolute.
444 SCHEMATIC& schematic = m_frame->Schematic();
445 SCH_SHEET_LIST fullHierarchy = schematic.Hierarchy();
446 wxFileName screenFileName( sheetFileName );
447 wxFileName tmp( sheetFileName );
448 SCH_SCREEN* currentScreen = m_frame->GetCurrentSheet().LastScreen();
449
450 wxCHECK( currentScreen, false );
451
452 // SCH_SCREEN file names are always absolute.
453 wxFileName currentScreenFileName = currentScreen->GetFileName();
454
455 if( !screenFileName.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentScreenFileName.GetPath() ) )
456 {
457 msg = wxString::Format( _( "Cannot normalize new sheet schematic file path:\n"
458 "'%s'\n"
459 "against parent sheet schematic file path:\n"
460 "'%s'." ),
461 sheetFileName.GetPath(),
462 currentScreenFileName.GetPath() );
463 DisplayError( this, msg );
464 return false;
465 }
466
467 wxString newAbsoluteFilename = screenFileName.GetFullPath();
468
469 // Inside Eeschema, filenames are stored using unix notation
470 newAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
471
472 bool renameFile = false;
473 bool loadFromFile = false;
474 bool clearAnnotation = false;
475 bool isExistingSheet = false;
476 SCH_SCREEN* useScreen = nullptr;
477 SCH_SCREEN* oldScreen = nullptr;
478
479 // Search for a schematic file having the same filename already in use in the hierarchy
480 // or on disk, in order to reuse it.
481 if( !schematic.Root().SearchHierarchy( newAbsoluteFilename, &useScreen ) )
482 {
483 loadFromFile = wxFileExists( newAbsoluteFilename );
484
485 wxLogTrace( tracePathsAndFiles, "\n Sheet requested file '%s', %s",
486 newAbsoluteFilename,
487 loadFromFile ? "found" : "not found" );
488 }
489
490 if( m_sheet->GetScreen() == nullptr ) // New just created sheet.
491 {
492 if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), newAbsoluteFilename ) )
493 return false;
494
495 if( useScreen || loadFromFile ) // Load from existing file.
496 {
497 clearAnnotation = true;
498
499 if( !IsOK( this, wxString::Format( _( "'%s' already exists." ), sheetFileName.GetFullName() )
500 + wxT( "\n\n" )
501 + wxString::Format( _( "Link '%s' to this file?" ), newAbsoluteFilename ) ) )
502 {
503 return false;
504 }
505 }
506 // If we are drawing a sheet from a design block/sheet import, we need to copy the
507 // sheet to the current directory.
508 else if( m_sourceSheetFilename && !m_sourceSheetFilename->IsEmpty() )
509 {
510 loadFromFile = true;
511
512 if( !wxCopyFile( *m_sourceSheetFilename, newAbsoluteFilename, false ) )
513 {
514 msg.Printf( _( "Failed to copy schematic file '%s' to destination '%s'." ),
515 currentScreenFileName.GetFullPath(),
516 newAbsoluteFilename );
517
518 DisplayError( m_frame, msg );
519
520 return false;
521 }
522 }
523 else // New file.
524 {
525 m_frame->InitSheet( m_sheet, newAbsoluteFilename );
526 }
527 }
528 else // Existing sheet.
529 {
530 isExistingSheet = true;
531
532 if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), newAbsoluteFilename ) )
533 return false;
534
535 // We are always using here a case insensitive comparison to avoid issues
536 // under Windows, although under Unix filenames are case sensitive.
537 // But many users create schematic under both Unix and Windows
538 // **
539 // N.B. 1: aSheet->GetFileName() will return a relative path
540 // aSheet->GetScreen()->GetFileName() returns a full path
541 //
542 // N.B. 2: newFilename uses the unix notation for separator.
543 // so we must use it also to compare the old and new filenames
544 wxString oldAbsoluteFilename = m_sheet->GetScreen()->GetFileName();
545 oldAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
546
547 if( newAbsoluteFilename.Cmp( oldAbsoluteFilename ) != 0 )
548 {
549 // Sheet file name changes cannot be undone.
550 if( m_isUndoable )
551 *m_isUndoable = false;
552
553 if( useScreen || loadFromFile ) // Load from existing file.
554 {
555 clearAnnotation = true;
556 oldScreen = m_sheet->GetScreen();
557
558 if( !IsOK( this, wxString::Format( _( "Change '%s' link from '%s' to '%s'?" ),
559 newAbsoluteFilename,
561 sheetFileName.GetFullName() )
562 + wxT( "\n\n" )
563 + _( "This action cannot be undone." ) ) )
564 {
565 return false;
566 }
567
568 if( loadFromFile )
569 m_sheet->SetScreen( nullptr );
570 }
571 else // Save to new file name.
572 {
573 if( m_sheet->GetScreenCount() > 1 )
574 {
575 if( !IsOK( this, wxString::Format( _( "Create new file '%s' with contents of '%s'?" ),
576 sheetFileName.GetFullName(),
578 + wxT( "\n\n" )
579 + _( "This action cannot be undone." ) ) )
580 {
581 return false;
582 }
583 }
584
585 renameFile = true;
586 }
587 }
588
589 if( renameFile )
590 {
591 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
592
593 // If the associated screen is shared by more than one sheet, do not
594 // change the filename of the corresponding screen here.
595 // (a new screen will be created later)
596 // if it is not shared, update the filename
597 if( m_sheet->GetScreenCount() <= 1 )
598 m_sheet->GetScreen()->SetFileName( newAbsoluteFilename );
599
600 try
601 {
602 pi->SaveSchematicFile( newAbsoluteFilename, m_sheet, &schematic );
603 }
604 catch( const IO_ERROR& ioe )
605 {
606 msg = wxString::Format( _( "Error occurred saving schematic file '%s'." ), newAbsoluteFilename );
607 DisplayErrorMessage( this, msg, ioe.What() );
608
609 msg = wxString::Format( _( "Failed to save schematic '%s'" ), newAbsoluteFilename );
610 m_frame->SetMsgPanel( wxEmptyString, msg );
611 return false;
612 }
613
614 // If the associated screen is shared by more than one sheet, remove the
615 // screen and reload the file to a new screen. Failure to do this will trash
616 // the screen reference counting in complex hierarchies.
617 if( m_sheet->GetScreenCount() > 1 )
618 {
619 oldScreen = m_sheet->GetScreen();
620 m_sheet->SetScreen( nullptr );
621 loadFromFile = true;
622 }
623 }
624 }
625
626 SCH_SHEET_PATH& currentSheet = m_frame->GetCurrentSheet();
627
628 if( useScreen )
629 {
630 // Create a temporary sheet for recursion testing to prevent a possible recursion error.
631 std::unique_ptr< SCH_SHEET> tmpSheet = std::make_unique<SCH_SHEET>( &schematic );
632 *tmpSheet->GetField( FIELD_T::SHEET_NAME ) = m_fields->GetField( FIELD_T::SHEET_NAME );
633 tmpSheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( sheetFileName.GetFullPath() );
634 tmpSheet->SetScreen( useScreen );
635
636 // No need to check for valid library IDs if we are using an existing screen.
637 if( m_frame->CheckSheetForRecursion( tmpSheet.get(), &currentSheet ) )
638 return false;
639
640 // It's safe to set the sheet screen now.
641 m_sheet->SetScreen( useScreen );
642
643 SCH_SHEET_LIST sheetHierarchy( m_sheet ); // The hierarchy of the loaded file.
644
645 sheetHierarchy.AddNewSymbolInstances( currentSheet, m_frame->Prj().GetProjectName() );
646 sheetHierarchy.AddNewSheetInstances( currentSheet, fullHierarchy.GetLastVirtualPageNumber() );
647 }
648 else if( loadFromFile )
649 {
650 bool restoreSheet = false;
651
652 if( isExistingSheet )
653 {
654 // Temporarily remove the sheet from the current schematic page so that recursion
655 // and symbol library link tests can be performed with the modified sheet settings.
656 restoreSheet = true;
657 currentSheet.LastScreen()->Remove( m_sheet );
658 }
659
660 if( !m_frame->LoadSheetFromFile( m_sheet, &currentSheet, newAbsoluteFilename, false, true )
661 || m_frame->CheckSheetForRecursion( m_sheet, &currentSheet ) )
662 {
663 if( restoreSheet )
664 {
665 // If we cleared the previous screen, restore it before returning to the user
666 if( oldScreen )
667 m_sheet->SetScreen( oldScreen );
668
669 currentSheet.LastScreen()->Append( m_sheet );
670 }
671
672 return false;
673 }
674
675 if( restoreSheet )
676 currentSheet.LastScreen()->Append( m_sheet );
677 }
678
680 *m_clearAnnotationNewItems = clearAnnotation;
681
682 // Rebuild the entire connection graph.
684
685 return true;
686}
687
688
690{
691 bool success = true;
692 wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
693 wxControl* control = editor->GetControl();
694
695 if( control && control->GetValidator() )
696 success = control->GetValidator()->Validate( control );
697
698 if( !success )
699 {
700 event.Veto();
701 m_delayedFocusRow = event.GetRow();
702 m_delayedFocusColumn = event.GetCol();
703 }
704
705 editor->DecRef();
706}
707
708
709void DIALOG_SHEET_PROPERTIES::OnAddField( wxCommandEvent& event )
710{
712 [&]() -> std::pair<int, int>
713 {
714 SCH_FIELD newField( m_sheet, FIELD_T::SHEET_USER, GetUserFieldName( m_fields->size(), DO_TRANSLATE ) );
715
716 newField.SetTextAngle( m_fields->GetField( FIELD_T::SHEET_NAME )->GetTextAngle() );
717 newField.SetVisible( false );
718 m_fields->push_back( newField );
719
720 // notify the grid
721 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
722 m_grid->ProcessTableMessage( msg );
723 return { m_fields->size() - 1, FDC_NAME };
724 } );
725}
726
727
728void DIALOG_SHEET_PROPERTIES::OnDeleteField( wxCommandEvent& event )
729{
731 [&]( int row )
732 {
733 if( row < m_fields->GetMandatoryRowCount() )
734 {
735 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
737 return false;
738 }
739
740 return true;
741 },
742 [&]( int row )
743 {
744 m_fields->erase( m_fields->begin() + row );
745
746 // notify the grid
747 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
748 m_grid->ProcessTableMessage( msg );
749 } );
750}
751
752
753void DIALOG_SHEET_PROPERTIES::OnMoveUp( wxCommandEvent& event )
754{
756 [&]( int row )
757 {
758 return row > m_fields->GetMandatoryRowCount();
759 },
760 [&]( int row )
761 {
762 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row - 1 ) );
763 m_grid->ForceRefresh();
764 } );
765}
766
767
768void DIALOG_SHEET_PROPERTIES::OnMoveDown( wxCommandEvent& event )
769{
771 [&]( int row )
772 {
773 return row >= m_fields->GetMandatoryRowCount();
774 },
775 [&]( int row )
776 {
777 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row + 1 ) );
778 m_grid->ForceRefresh();
779 } );
780}
781
782
784{
785 // Account for scroll bars
787
788 m_grid->AutoSizeColumn( FDC_NAME );
789 m_grid->SetColSize( FDC_NAME, std::max( 72, m_grid->GetColSize( FDC_NAME ) ) );
790
791 int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
792
793 for( int i = 2; i < m_grid->GetNumberCols(); i++ )
794 fixedColsWidth += m_grid->GetColSize( i );
795
796 m_grid->SetColSize( 1, std::max( 120, width - fixedColsWidth ) );
797}
798
799
800void DIALOG_SHEET_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
801{
802 std::bitset<64> shownColumns = m_grid->GetShownColumns();
803
804 if( shownColumns != m_shownColumns )
805 {
806 m_shownColumns = shownColumns;
807
808 if( !m_grid->IsCellEditControlShown() )
810 }
811
812 // Propagate changes in sheetname to displayed hierarchical path
813 int sheetnameRow = m_fields->GetFieldRow( FIELD_T::SHEET_NAME );
814 wxString path = m_frame->GetCurrentSheet().PathHumanReadable( false );
815
816 if( path.Last() != '/' )
817 path.Append( '/' );
818
819 wxGridCellEditor* editor = m_grid->GetCellEditor( sheetnameRow, FDC_VALUE );
820 wxControl* control = editor->GetControl();
821 wxTextEntry* textControl = dynamic_cast<wxTextEntry*>( control );
822 wxString sheetName;
823
824 if( textControl )
825 sheetName = textControl->GetValue();
826 else
827 sheetName = m_grid->GetCellValue( sheetnameRow, FDC_VALUE );
828
830 m_dummySheetNameField.SetText( sheetName );
832
833 editor->DecRef();
834
835 wxClientDC dc( m_hierarchicalPathLabel );
836 int width = m_sizerBottom->GetSize().x - m_stdDialogButtonSizer->GetSize().x
837 - m_hierarchicalPathLabel->GetSize().x
838 - 30;
839
840 path = wxControl::Ellipsize( path, dc, wxELLIPSIZE_START, width, wxELLIPSIZE_FLAGS_NONE );
841
842 if( m_hierarchicalPath->GetLabel() != path )
843 m_hierarchicalPath->SetLabel( path );
844
845 // Handle a delayed focus
846 if( m_delayedFocusRow >= 0 )
847 {
848 m_grid->SetFocus();
849 m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
851
852 m_grid->EnableCellEditControl( true );
853 m_grid->ShowCellEditControl();
854
857 }
858}
859
860
861void DIALOG_SHEET_PROPERTIES::OnSizeGrid( wxSizeEvent& event )
862{
863 auto new_size = event.GetSize();
864
865 if( m_size != new_size )
866 {
867 m_size = new_size;
869 }
870
871 // Always propagate for a grid repaint (needed if the height changes, as well as width)
872 event.Skip();
873}
874
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
Color settings are a bit different than most of the settings objects in that there can be more than o...
bool GetOverrideSchItemColors() const
COLOR4D GetColor(int aLayer) const
void SetSwatchColor(const KIGFX::COLOR4D &aColor, bool aSendEvent)
Set the current swatch color directly.
KIGFX::COLOR4D GetSwatchColor() const
void SetDefaultColor(const KIGFX::COLOR4D &aColor)
Sets the color that will be chosen with the "Reset to Default" button in the chooser.
void SetSwatchBackground(const KIGFX::COLOR4D &aBackground)
Set the swatch background color.
Class DIALOG_SHEET_PROPERTIES_BASE.
wxStdDialogButtonSizer * m_stdDialogButtonSizer
void OnAddField(wxCommandEvent &event) override
void OnMoveDown(wxCommandEvent &event) override
void OnGridCellChanging(wxGridEvent &event)
void OnDeleteField(wxCommandEvent &event) override
bool onSheetFilenameChanged(const wxString &aNewFilename)
void OnSizeGrid(wxSizeEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
void OnMoveUp(wxCommandEvent &event) override
DIALOG_SHEET_PROPERTIES(SCH_EDIT_FRAME *aParent, SCH_SHEET *aSheet, bool *aIsUndoable, bool *aClearAnnotationNewItems, bool *aUpdateHierarchyNavigator, wxString *aSourceSheetFilename)
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool IsNew() const
Definition: eda_item.h:124
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:144
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:97
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:596
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:197
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:200
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:299
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:241
SCH_FIELD * GetField(FIELD_T aFieldId)
int GetNumberRows() override
void push_back(const SCH_FIELD &field)
int GetMandatoryRowCount() const
int GetFieldRow(FIELD_T aFieldId)
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
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:50
@ KD_WARNING
Definition: kidialog.h:53
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:161
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:373
Holds all the data relating to one schematic.
Definition: schematic.h:88
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:258
SCH_SHEET & Root() const
Definition: schematic.h:140
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
Schematic editor (Eeschema) main window.
bool AllowCaseSensitiveFileNameClashes(const wxString &aOldName, const wxString &aSchematicFileName)
Check aSchematicFileName for a potential file name case sensitivity clashes.
Definition: sheet.cpp:720
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void InitSheet(SCH_SHEET *aSheet, const wxString &aNewFilename)
Definition: sheet.cpp:110
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet, const wxString &aFileName, bool aSkipRecursionCheck=false, bool aSkipLibCheck=false)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition: sheet.cpp:169
SCH_SHEET_PATH & GetCurrentSheet() const
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
SCHEMATIC & Schematic() const
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet)
Verify that aSheet will not cause a recursion error in aCurrentSheet.
Definition: sheet.cpp:54
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
bool IsMandatory() const
Definition: sch_field.cpp:1359
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1337
FIELD_T GetId() const
Definition: sch_field.h:116
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1117
bool IsEmpty()
Return true if both the name and value of the field are empty.
Definition: sch_field.h:155
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1103
void SetName(const wxString &aName)
Definition: sch_field.cpp:1079
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
Definition: sch_field.cpp:191
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1089
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
Definition: sch_item.h:598
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:160
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition: sch_screen.h:117
const wxString & GetFileName() const
Definition: sch_screen.h:152
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:123
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:330
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this list of sheet paths prefixed with aPrefix...
int GetLastVirtualPageNumber() const
void AddNewSheetInstances(const SCH_SHEET_PATH &aPrefixSheetPath, int aLastVirtualPageNumber)
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:47
bool GetExcludedFromBoard() const override
Definition: sch_sheet.h:397
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:125
void SetExcludedFromBoard(bool aExcludeFromBoard) override
Set or clear exclude from board netlist flag.
Definition: sch_sheet.h:396
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:321
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
Definition: sch_sheet.h:87
bool GetExcludedFromBOM() const override
Definition: sch_sheet.h:391
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
Definition: sch_sheet.cpp:367
wxString GetName() const
Definition: sch_sheet.h:113
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:751
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:128
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:116
VECTOR2I GetPosition() const override
Definition: sch_sheet.h:415
void SetExcludedFromBOM(bool aExcludeFromBOM) override
Set or clear the exclude from schematic bill of materials flag.
Definition: sch_sheet.h:390
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.cpp:389
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
Definition: sch_sheet.cpp:160
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:137
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:124
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:122
bool GetExcludedFromSim() const override
Definition: sch_sheet.h:385
int GetBorderWidth() const
Definition: sch_sheet.h:121
void SetDNP(bool aDNP) override
Definition: sch_sheet.h:403
bool GetDNP() const override
Set or clear the 'Do Not Populate' flags.
Definition: sch_sheet.h:402
void SetExcludedFromSim(bool aExcludeFromSim) override
Set or clear the exclude from simulation flag.
Definition: sch_sheet.h:384
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:127
void SetBitmap(const wxBitmapBundle &aBmp)
int GetIntValue()
Definition: unit_binder.h:134
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:494
void OnMoveRowUp(const std::function< void(int row)> &aMover)
Definition: wx_grid.cpp:766
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:273
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:450
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:464
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
std::bitset< 64 > GetShownColumns()
Definition: wx_grid.cpp:483
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:156
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition: common.cpp:429
The common library.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:251
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
static bool positioningChanged(const SCH_FIELD &a, const SCH_FIELD &b)
static bool positioningChanged(const SCH_FIELD &a, const SCH_FIELD &b)
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
@ FDC_NAME
@ FDC_VALUE
static const std::string KiCadSchematicFileExtension
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
This file is part of the common library.
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:478
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition: wxgtk/ui.cpp:258
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:162
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
Definition: sch_field.h:359
@ AUTOPLACE_NONE
Definition: sch_item.h:70
@ GLOBAL_CLEANUP
Definition: schematic.h:77
bool IsFullFileNameValid(const wxString &aFullFilename)
Checks if a full filename is valid, i.e.
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ SHEET_FILENAME
wxLogTrace helper definitions.
@ SCH_SHEET_T
Definition: typeinfo.h:176
Custom text control validator definitions.
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39