KiCad PCB EDA Suite
dialog_sch_sheet_props.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 <stambaughw@gmail.com>
5  * Copyright (C) 2014-2020 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 
25 #include <dialog_sch_sheet_props.h>
26 #include <kiface_i.h>
27 #include <wx/string.h>
28 #include <wx/tooltip.h>
29 #include <confirm.h>
30 #include <validators.h>
32 #include <widgets/tab_traversal.h>
33 #include <sch_edit_frame.h>
34 #include <sch_sheet.h>
35 #include <schematic.h>
36 #include <bitmaps.h>
37 #include <eeschema_settings.h>
39 #include <trace_helpers.h>
41 
43  bool* aClearAnnotationNewItems ) :
44  DIALOG_SCH_SHEET_PROPS_BASE( aParent ),
45  m_frame( aParent ),
46  m_clearAnnotationNewItems( aClearAnnotationNewItems ),
47  m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits, true )
48 {
49  m_sheet = aSheet;
50  m_fields = new FIELDS_GRID_TABLE<SCH_FIELD>( this, aParent, m_sheet );
51  m_width = 100; // Will be later set to a better value
54 
55  // Give a bit more room for combobox editors
56  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
57 
59  m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
60 
61  // Show/hide columns according to user's preference
62  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
63  wxASSERT( cfg );
64 
65  if( cfg )
66  {
67  m_shownColumns = cfg->m_Appearance.edit_sheet_visible_columns;
69  }
70 
71  wxToolTip::Enable( true );
72  m_stdDialogButtonSizerOK->SetDefault();
73 
74  // Configure button logos
75  m_bpAdd->SetBitmap( KiBitmap( small_plus_xpm ) );
76  m_bpDelete->SetBitmap( KiBitmap( trash_xpm ) );
77  m_bpMoveUp->SetBitmap( KiBitmap( small_up_xpm ) );
78  m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
79 
80  // Set font sizes
81  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
82  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
83  m_hiearchicalPathLabel->SetFont( infoFont );
84  m_heirarchyPath->SetFont( infoFont );
85  m_heirarchyPath->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) );
86  m_timestampLabel->SetFont( infoFont );
87  m_textCtrlTimeStamp->SetFont( infoFont );
88  m_textCtrlTimeStamp->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) );
89 
90  // wxFormBuilder doesn't include this event...
91  m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
92  wxGridEventHandler( DIALOG_SCH_SHEET_PROPS::OnGridCellChanging ),
93  NULL, this );
94 
96 }
97 
98 
100 {
101  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
102  wxASSERT( cfg );
103 
104  if( cfg )
105  cfg->m_Appearance.edit_sheet_visible_columns = m_grid->GetShownColumns();
106 
107  // Prevents crash bug in wxGrid's d'tor
109 
110  m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
111  wxGridEventHandler( DIALOG_SCH_SHEET_PROPS::OnGridCellChanging ),
112  NULL, this );
113 
114  // Delete the GRID_TRICKS.
115  m_grid->PopEventHandler( true );
116 }
117 
118 
120 {
121  if( !wxDialog::TransferDataToWindow() )
122  return false;
123 
124  // Push a copy of each field into m_updateFields
125  for( SCH_FIELD& field : m_sheet->GetFields() )
126  {
127  SCH_FIELD field_copy( field );
128 
129 #ifdef __WINDOWS__
130  // Filenames are stored using unix notation
131  if( field_copy.GetId() == SHEETFILENAME )
132  {
133  wxString filename = field_copy.GetText();
134  filename.Replace( wxT("/"), wxT("\\") );
135  field_copy.SetText( filename );
136  }
137 #endif
138 
139  // change offset to be symbol-relative
140  field_copy.Offset( -m_sheet->GetPosition() );
141 
142  m_fields->push_back( field_copy );
143  }
144 
145  // notify the grid
146  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->size() );
147  m_grid->ProcessTableMessage( msg );
148  AdjustGridColumns( m_grid->GetRect().GetWidth() );
149 
150  // border width
152 
153  // set up color swatches
154  COLOR_SETTINGS* colorSettings = m_frame->GetColorSettings();
155  KIGFX::COLOR4D borderColor = m_sheet->GetBorderColor();
156  KIGFX::COLOR4D backgroundColor = m_sheet->GetBackgroundColor();
157 
158  if( borderColor == COLOR4D::UNSPECIFIED )
159  borderColor = colorSettings->GetColor( LAYER_SHEET );
160 
161  if( backgroundColor == COLOR4D::UNSPECIFIED )
162  backgroundColor = colorSettings->GetColor( LAYER_SHEET_BACKGROUND );
163 
164  m_borderSwatch->SetSwatchColor( borderColor, false );
165  m_backgroundSwatch->SetSwatchColor( backgroundColor, false );
166 
170 
171  // set up the read-only fields
173  m_textCtrlTimeStamp->SetValue( m_sheet->m_Uuid.AsString() );
174 
175  Layout();
176 
177  return true;
178 }
179 
180 
182 {
183  wxString msg;
184  LIB_ID id;
185 
186  if( !m_grid->CommitPendingChanges() || !m_grid->Validate() )
187  return false;
188 
189  // Check for missing field names.
190  for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields->size(); ++i )
191  {
192  SCH_FIELD& field = m_fields->at( i );
193  wxString fieldName = field.GetName( false );
194 
195  if( fieldName.IsEmpty() )
196  {
197  DisplayErrorMessage( this, _( "Fields must have a name." ) );
198 
200  m_delayedFocusRow = i;
201 
202  return false;
203  }
204  }
205 
206  return true;
207 }
208 
209 
210 static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b )
211 {
212  if( a.GetPosition() != b.GetPosition() )
213  return true;
214 
215  if( a.GetHorizJustify() != b.GetHorizJustify() )
216  return true;
217 
218  if( a.GetVertJustify() != b.GetVertJustify() )
219  return true;
220 
221  if( a.GetTextAngle() != b.GetTextAngle() )
222  return true;
223 
224  return false;
225 }
226 
227 
228 static bool positioningChanged( FIELDS_GRID_TABLE<SCH_FIELD>* a, std::vector<SCH_FIELD>& b )
229 {
230  for( size_t i = 0; i < SHEET_MANDATORY_FIELDS; ++i )
231  {
232  if( positioningChanged( a->at( i ), b.at( i ) ) )
233  return true;
234  }
235 
236  return false;
237 }
238 
239 
241 {
242  if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
243  return false;
244 
245  wxString newRelativeNativeFilename = m_fields->at( SHEETFILENAME ).GetText();
246 
247  // Ensure filepath is not empty. (In normal use will be caught by grid validators,
248  // but unedited data from existing files can be bad.)
249 
250  // @todo What happens when there are invalid file name characters?
251  if( newRelativeNativeFilename.IsEmpty() )
252  {
253  wxMessageBox( _( "A sheet must have a valid file name." ) );
254  return false;
255  }
256 
257  // Ensure the filename extension is OK. (In normaly use will be caught by grid
258  // validators, but unedited data from existing files can be bad.)
259  wxFileName fn( newRelativeNativeFilename );
260 
261  if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
262  {
263  wxMessageBox( _( "Sheet file must have a '.kicad_sch' extension." ) );
264  return false;
265  }
266 
267  wxString newRelativeFilename = fn.GetFullPath();
268 
269  // Inside Eeschema, filenames are stored using unix notation
270  newRelativeFilename.Replace( wxT( "\\" ), wxT( "/" ) );
271 
272  wxString oldFilename = m_sheet->GetFields()[ SHEETFILENAME ].GetText();
273  oldFilename.Replace( wxT( "\\" ), wxT( "/" ) );
274 
275  bool filename_changed = oldFilename != newRelativeFilename;
276 
277  if( filename_changed || m_sheet->IsNew() )
278  {
279  if( !onSheetFilenameChanged( newRelativeFilename ) )
280  return false;
281  }
282 
283  wxString newSheetname = m_fields->at( SHEETNAME ).GetText();
284 
285  if( newSheetname.IsEmpty() )
286  newSheetname = _( "Untitled Sheet" );
287 
288  m_fields->at( SHEETNAME ).SetText( newSheetname );
289 
290  // change all field positions from relative to absolute
291  for( unsigned i = 0; i < m_fields->size(); ++i )
292  m_fields->at( i ).Offset( m_sheet->GetPosition() );
293 
296 
298 
300 
301  COLOR_SETTINGS* colorSettings = m_frame->GetColorSettings();
302 
303  if( colorSettings->GetOverrideSchItemColors()
306  {
307  wxPanel temp( this );
308  temp.Hide();
309  PANEL_EESCHEMA_COLOR_SETTINGS prefs( m_frame, &temp );
310  wxString checkboxLabel = prefs.m_optOverrideColors->GetLabel();
311 
312  KIDIALOG dlg( this, _( "Note: item colors are overridden in the current color theme." ),
314  dlg.ShowDetailedText( wxString::Format( _( "To see individual item colors uncheck '%s'\n"
315  "in Preferences > Eeschema > Colors." ),
316  checkboxLabel ) );
317  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
318  dlg.ShowModal();
319  }
320 
323 
325 
326  // Refresh all sheets in case ordering changed.
327  for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_SHEET_T ) )
328  m_frame->RefreshItem( item );
329 
330  m_frame->OnModify();
331 
332  return true;
333 }
334 
335 
336 bool DIALOG_SCH_SHEET_PROPS::onSheetFilenameChanged( const wxString& aNewFilename )
337 {
338  wxString msg;
339 
340  // Relative file names are relative to the path of the current sheet. This allows for
341  // nesting of schematic files in subfolders.
342  wxFileName fileName( aNewFilename );
343 
344  if( fileName.GetExt().IsEmpty() )
345  {
346  fileName.SetExt( KiCadSchematicFileExtension );
347  }
348  else if( fileName.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
349  {
350  msg.Printf( _( "The file \"%s\" does not appear to be a valid schematic file." ),
351  fileName.GetFullName() );
352  wxMessageDialog badSchFileDialog( this, msg, _( "Invalid Schematic File" ),
353  wxOK | wxCENTRE | wxICON_EXCLAMATION );
354  badSchFileDialog.ShowModal();
355  return false;
356  }
357 
358  if( !fileName.IsAbsolute() )
359  {
360  const SCH_SCREEN* currentScreen = m_frame->GetCurrentSheet().LastScreen();
361  wxCHECK_MSG( currentScreen, false, "Invalid sheet path object." );
362 
363  wxFileName currentSheetFileName = currentScreen->GetFileName();
364 
365  if( !fileName.Normalize( wxPATH_NORM_ALL, currentSheetFileName.GetPath() ) )
366  {
367  wxFAIL_MSG( "Cannot normalize new sheet schematic file path." );
368  return false;
369  }
370  }
371 
372  wxString newAbsoluteFilename = fileName.GetFullPath();
373 
374  // Inside Eeschema, filenames are stored using unix notation
375  newAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
376 
377  bool renameFile = false;
378  bool loadFromFile = false;
379  bool clearAnnotation = false;
380  bool restoreSheet = false;
381  bool isExistingSheet = false;
382  SCH_SCREEN* useScreen = NULL;
383 
384  // Search for a schematic file having the same filename already in use in the hierarchy
385  // or on disk, in order to reuse it.
386  if( !m_frame->Schematic().Root().SearchHierarchy( newAbsoluteFilename, &useScreen ) )
387  {
388  loadFromFile = wxFileExists( newAbsoluteFilename );
389 
390  wxLogTrace( tracePathsAndFiles, "Sheet requested file \"%s\", %s",
391  newAbsoluteFilename,
392  ( loadFromFile ) ? "found" : "not found" );
393  }
394 
395  if( m_sheet->GetScreen() == NULL ) // New just created sheet.
396  {
397  if( !m_frame->AllowCaseSensitiveFileNameClashes( newAbsoluteFilename ) )
398  return false;
399 
400  if( useScreen || loadFromFile ) // Load from existing file.
401  {
402  clearAnnotation = true;
403  wxString existsMsg;
404  wxString linkMsg;
405  existsMsg.Printf( _( "\"%s\" already exists." ), fileName.GetFullName() );
406  linkMsg.Printf( _( "Link \"%s\" to this file?" ), newAbsoluteFilename );
407  msg.Printf( wxT( "%s\n\n%s" ), existsMsg, linkMsg );
408 
409  if( !IsOK( this, msg ) )
410  return false;
411  }
412  else // New file.
413  {
414  m_frame->InitSheet( m_sheet, newAbsoluteFilename );
415  }
416  }
417  else // Existing sheet.
418  {
419  bool isUndoable = true;
420  wxString replaceMsg;
421  wxString newMsg;
422  wxString noUndoMsg;
423  isExistingSheet = true;
424 
425  if( !m_frame->AllowCaseSensitiveFileNameClashes( newAbsoluteFilename ) )
426  return false;
427 
428  // Changing the filename of a sheet can modify the full hierarchy structure
429  // and can be not always undoable.
430  // So prepare messages for user notifications:
431  replaceMsg.Printf( _( "Change \"%s\" link from \"%s\" to \"%s\"?" ),
432  newAbsoluteFilename,
433  m_sheet->GetFileName(),
434  fileName.GetFullName() );
435  newMsg.Printf( _( "Create new file \"%s\" with contents of \"%s\"?" ),
436  fileName.GetFullName(),
437  m_sheet->GetFileName() );
438  noUndoMsg = _( "This action cannot be undone." );
439 
440  // We are always using here a case insensitive comparison to avoid issues
441  // under Windows, although under Unix filenames are case sensitive.
442  // But many users create schematic under both Unix and Windows
443  // **
444  // N.B. 1: aSheet->GetFileName() will return a relative path
445  // aSheet->GetScreen()->GetFileName() returns a full path
446  //
447  // N.B. 2: newFilename uses the unix notation for separator.
448  // so we must use it also to compare the old and new filenames
449  wxString oldAbsoluteFilename = m_sheet->GetScreen()->GetFileName();
450  oldAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
451 
452  if( newAbsoluteFilename.Cmp( oldAbsoluteFilename ) != 0 )
453  {
454  // Sheet file name changes cannot be undone.
455  isUndoable = false;
456 
457  if( useScreen || loadFromFile ) // Load from existing file.
458  {
459  clearAnnotation = true;
460 
461  msg.Printf( wxT( "%s\n\n%s" ), replaceMsg, noUndoMsg );
462 
463  if( !IsOK( this, msg ) )
464  return false;
465 
466  if( loadFromFile )
467  m_sheet->SetScreen( NULL );
468  }
469  else // Save to new file name.
470  {
471  if( m_sheet->GetScreenCount() > 1 )
472  {
473  msg.Printf( wxT( "%s\n\n%s" ), newMsg, noUndoMsg );
474 
475  if( !IsOK( this, msg ) )
476  return false;
477  }
478 
479  renameFile = true;
480  }
481  }
482 
483  if( isUndoable )
485 
486  if( renameFile )
487  {
488  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
489 
490  // If the the associated screen is shared by more than one sheet, do not
491  // change the filename of the corresponding screen here.
492  // (a new screen will be created later)
493  // if it is not shared, update the filename
494  if( m_sheet->GetScreenCount() <= 1 )
495  m_sheet->GetScreen()->SetFileName( newAbsoluteFilename );
496 
497  try
498  {
499  pi->Save( newAbsoluteFilename, m_sheet, &m_frame->Schematic() );
500  }
501  catch( const IO_ERROR& ioe )
502  {
503  msg.Printf( _( "Error occurred saving schematic file \"%s\"." ),
504  newAbsoluteFilename );
505  DisplayErrorMessage( this, msg, ioe.What() );
506 
507  msg.Printf( _( "Failed to save schematic \"%s\"" ), newAbsoluteFilename );
508  m_frame->AppendMsgPanel( wxEmptyString, msg, CYAN );
509 
510  return false;
511  }
512 
513  // If the the associated screen is shared by more than one sheet, remove the
514  // screen and reload the file to a new screen. Failure to do this will trash
515  // the screen reference counting in complex hierarchies.
516  if( m_sheet->GetScreenCount() > 1 )
517  {
518  m_sheet->SetScreen( NULL );
519  loadFromFile = true;
520  }
521  }
522  }
523 
524  wxFileName nativeFileName( aNewFilename );
525  SCH_SHEET_PATH& currentSheet = m_frame->GetCurrentSheet();
526 
527  if( useScreen )
528  {
529  // Create a temporary sheet for recursion testing to prevent a possible recursion error.
530  std::unique_ptr< SCH_SHEET> tmpSheet( new SCH_SHEET );
531  tmpSheet->GetFields()[SHEETNAME] = m_fields->at( SHEETNAME );
532  tmpSheet->GetFields()[SHEETFILENAME].SetText( nativeFileName.GetFullPath() );
533  tmpSheet->SetScreen( useScreen );
534 
535  // No need to check for valid library IDs if we are using an existing screen.
536  if( m_frame->CheckSheetForRecursion( tmpSheet.get(), &currentSheet ) )
537  {
538  if( restoreSheet )
539  currentSheet.LastScreen()->Append( m_sheet );
540 
541  return false;
542  }
543 
544  // It's safe to set the sheet screen now.
545  m_sheet->SetScreen( useScreen );
546  }
547  else if( loadFromFile )
548  {
549  if( isExistingSheet )
550  {
551  // Temporarily remove the sheet from the current schematic page so that recursion
552  // and symbol library link tests can be performed with the modified sheet settings.
553  restoreSheet = true;
554  currentSheet.LastScreen()->Remove( m_sheet );
555  }
556 
557  if( !m_frame->LoadSheetFromFile( m_sheet, &currentSheet, newAbsoluteFilename )
558  || m_frame->CheckSheetForRecursion( m_sheet, &currentSheet ) )
559  {
560  if( restoreSheet )
561  currentSheet.LastScreen()->Append( m_sheet );
562 
563  return false;
564  }
565 
566  if( restoreSheet )
567  currentSheet.LastScreen()->Append( m_sheet );
568  }
569 
571  *m_clearAnnotationNewItems = clearAnnotation;
572 
573  return true;
574 }
575 
576 
578 {
579  bool success = true;
580  wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
581  wxControl* control = editor->GetControl();
582  wxTextEntry* textControl = dynamic_cast<wxTextEntry*>( control );
583 
584  // Short-circuit the validator's more generic "can't be empty" message for the
585  // two mandatory fields:
586  if( event.GetRow() == SHEETNAME && event.GetCol() == FDC_VALUE )
587  {
588  if( textControl && textControl->IsEmpty() )
589  {
590  wxMessageBox( _( "A sheet must have a name." ) );
591  success = false;
592  }
593  }
594  else if( event.GetRow() == SHEETFILENAME && event.GetCol() == FDC_VALUE && textControl )
595  {
596  if( textControl->IsEmpty() )
597  {
598  wxMessageBox( _( "A sheet must have a file specified." ) );
599  success = false;
600  }
601  else
602  {
603  wxFileName fn = textControl->GetValue();
604 
605  if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
606  {
607  wxMessageBox( _( "Sheet filename must have a '.kicad_sch' extension." ) );
608  success = false;
609  }
610  }
611  }
612 
613  if( success && control && control->GetValidator() )
614  success = control->GetValidator()->Validate( control );
615 
616  if( !success )
617  {
618  event.Veto();
619  m_delayedFocusRow = event.GetRow();
620  m_delayedFocusColumn = event.GetCol();
621  }
622 
623  editor->DecRef();
624 }
625 
626 
627 void DIALOG_SCH_SHEET_PROPS::OnAddField( wxCommandEvent& event )
628 {
629  if( !m_grid->CommitPendingChanges() )
630  return;
631 
632  int fieldID = m_fields->size();
633  SCH_FIELD newField( wxPoint( 0, 0 ), fieldID, m_sheet,
634  SCH_SHEET::GetDefaultFieldName( fieldID ) );
635 
636  newField.SetTextAngle( m_fields->at( SHEETNAME ).GetTextAngle() );
637 
638  m_fields->push_back( newField );
639 
640  // notify the grid
641  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
642  m_grid->ProcessTableMessage( msg );
643 
644  m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
645  m_grid->SetGridCursor( m_fields->size() - 1, 0 );
646 
647  m_grid->EnableCellEditControl();
648  m_grid->ShowCellEditControl();
649 }
650 
651 
652 void DIALOG_SCH_SHEET_PROPS::OnDeleteField( wxCommandEvent& event )
653 {
654  int curRow = m_grid->GetGridCursorRow();
655 
656  if( curRow < 0 )
657  return;
658  else if( curRow < SHEET_MANDATORY_FIELDS )
659  {
660  DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
662  return;
663  }
664 
665  m_grid->CommitPendingChanges( true /* quiet mode */ );
666 
667  m_fields->erase( m_fields->begin() + curRow );
668 
669  // notify the grid
670  wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
671  m_grid->ProcessTableMessage( msg );
672 
673  if( m_grid->GetNumberRows() > 0 )
674  {
675  m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
676  m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
677  }
678 }
679 
680 
681 void DIALOG_SCH_SHEET_PROPS::OnMoveUp( wxCommandEvent& event )
682 {
683  if( !m_grid->CommitPendingChanges() )
684  return;
685 
686  int i = m_grid->GetGridCursorRow();
687 
688  if( i > SHEET_MANDATORY_FIELDS )
689  {
690  SCH_FIELD tmp = m_fields->at( (unsigned) i );
691  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
692  m_fields->insert( m_fields->begin() + i - 1, tmp );
693  m_grid->ForceRefresh();
694 
695  m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
696  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
697  }
698  else
699  wxBell();
700 }
701 
702 
703 void DIALOG_SCH_SHEET_PROPS::OnMoveDown( wxCommandEvent& event )
704 {
705  if( !m_grid->CommitPendingChanges() )
706  return;
707 
708  int i = m_grid->GetGridCursorRow();
709 
710  if( i >= SHEET_MANDATORY_FIELDS && i < m_grid->GetNumberRows() - 1 )
711  {
712  SCH_FIELD tmp = m_fields->at( (unsigned) i );
713  m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
714  m_fields->insert( m_fields->begin() + i + 1, tmp );
715  m_grid->ForceRefresh();
716 
717  m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
718  m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
719  }
720  else
721  wxBell();
722 }
723 
724 
726 {
727  m_width = aWidth;
728  // Account for scroll bars
729  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
730 
731  m_grid->AutoSizeColumn( 0 );
732 
733  int fixedColsWidth = m_grid->GetColSize( 0 );
734 
735  for( int i = 2; i < m_grid->GetNumberCols(); i++ )
736  fixedColsWidth += m_grid->GetColSize( i );
737 
738  m_grid->SetColSize( 1, aWidth - fixedColsWidth );
739 }
740 
741 
742 void DIALOG_SCH_SHEET_PROPS::OnUpdateUI( wxUpdateUIEvent& event )
743 {
744  wxString shownColumns = m_grid->GetShownColumns();
745 
746  if( shownColumns != m_shownColumns )
747  {
748  m_shownColumns = shownColumns;
749 
750  if( !m_grid->IsCellEditControlShown() )
751  AdjustGridColumns( m_grid->GetRect().GetWidth() );
752  }
753 
754  // Handle a delayed focus
755  if( m_delayedFocusRow >= 0 )
756  {
757  m_grid->SetFocus();
758  m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
759  m_grid->SetGridCursor( m_delayedFocusRow, m_delayedFocusColumn );
760 
761 
762  m_grid->EnableCellEditControl( true );
763  m_grid->ShowCellEditControl();
764 
765  m_delayedFocusRow = -1;
767  }
768 }
769 
770 
771 void DIALOG_SCH_SHEET_PROPS::OnSizeGrid( wxSizeEvent& event )
772 {
773  auto new_size = event.GetSize().GetX();
774 
775  if( m_width != new_size )
776  {
777  AdjustGridColumns( new_size );
778  }
779 
780  // Always propagate for a grid repaint (needed if the height changes, as well as width)
781  event.Skip();
782 }
783 
784 
785 void DIALOG_SCH_SHEET_PROPS::OnInitDlg( wxInitDialogEvent& event )
786 {
788 
789  // Now all widgets have the size fixed, call FinishDialogSettings
791 }
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy)
Verify that aSheet will not cause a recursion error in aHierarchy.
Definition: sheet.cpp:46
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:46
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:252
Functions for manipulating tab traversal in forms and dialogs.
const wxString & GetFileName() const
Definition: sch_screen.h:185
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:53
bool Remove(SCH_ITEM *aItem)
Remove aItem from the schematic associated with this screen.
Definition: sch_screen.cpp:245
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:632
KIGFX::COLOR4D GetSwatchColor() const
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:199
void SetSwatchColor(KIGFX::COLOR4D aColor, bool sendEvent)
Set the current swatch color directly.
void OnMoveUp(wxCommandEvent &event) override
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
void SetFields(const std::vector< SCH_FIELD > &aFields)
Set multiple schematic fields.
Definition: sch_sheet.h:275
void OnDeleteField(wxCommandEvent &event) override
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
Definition: sch_sheet.h:70
This file is part of the common library.
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:121
wxPoint GetPosition() const override
Definition: sch_field.cpp:579
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:151
EE_TYPE OfType(KICAD_T aType)
Definition: sch_rtree.h:219
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
double GetTextAngle() const
Definition: eda_text.h:173
int GetId() const
Definition: sch_field.h:114
void InitSheet(SCH_SHEET *aSheet, const wxString &aNewFilename)
Definition: sheet.cpp:95
wxString AsString() const
Definition: common.cpp:165
KIGFX::COLOR4D GetBorderColor() const
Definition: sch_sheet.h:290
Schematic editor (Eeschema) main window.
void SetSwatchBackground(KIGFX::COLOR4D aBackground)
Set the swatch background color.
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
COLOR_SETTINGS * GetColorSettings() override
Returns a pointer to the active color theme settings.
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:59
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:282
void OnAddField(wxCommandEvent &event) override
bool IsNew() const
Definition: base_struct.h:199
KIGFX::COLOR4D GetBackgroundColor() const
Definition: sch_sheet.h:293
void SetBorderWidth(int aWidth)
Definition: sch_sheet.h:288
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:90
std::vector< SCH_FIELD > & GetFields()
Definition: sch_sheet.h:268
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
Definition: sch_sheet.cpp:174
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
int GetBorderWidth() const
Definition: sch_sheet.h:287
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, const wxString &aFileName)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition: sheet.cpp:104
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:294
bool AllowCaseSensitiveFileNameClashes(const wxString &aSchematicFileName)
Check aSchematicFileName for a potential file name case sensitivity clashes.
Definition: sheet.cpp:623
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:198
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:116
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
void OnGridCellChanging(wxGridEvent &event)
const BITMAP_OPAQUE small_down_xpm[1]
Definition: small_down.cpp:25
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
SCHEMATIC & Schematic() const
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:291
Definition of file extensions used in Kicad.
void ClearFieldsAutoplaced()
Set fields automatically placed flag false.
Definition: sch_item.h:440
Definition: color4d.h:58
wxLogTrace helper definitions.
void OnInitDlg(wxInitDialogEvent &event) override
static const wxString GetDefaultFieldName(int aFieldNdx)
Definition: sch_sheet.cpp:45
SCH_SHEET_PATH.
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:174
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:496
static bool positioningChanged(const SCH_FIELD &a, const SCH_FIELD &b)
wxPoint GetPosition() const override
Definition: sch_sheet.h:570
const BITMAP_OPAQUE small_up_xpm[1]
Definition: small_up.cpp:26
void OnUpdateUI(wxUpdateUIEvent &event) override
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:216
const KIID m_Uuid
Definition: base_struct.h:162
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:468
wxString GetShownColumns()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:103
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
Class DIALOG_SCH_SHEET_PROPS_BASE.
COLOR4D GetColor(int aLayer) const
SCH_SHEET & Root() const
Definition: schematic.h:97
SCH_SCREEN * LastScreen()
Function LastScreen.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:133
void RefreshItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
#define _(s)
Definition: 3d_actions.cpp:33
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
wxString GetName(bool aUseDefaultName=true) const
Function GetName returns the field name.
Definition: sch_field.cpp:420
EE_RTREE & Items()
Definition: sch_screen.h:158
const std::string KiCadSchematicFileExtension
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
void OnSizeGrid(wxSizeEvent &event) override
int ShowModal() override
Definition: confirm.cpp:95
Color settings are a bit different than most of the settings objects in that there can be more than o...
SCH_SHEET_PATH & GetCurrentSheet() const
bool GetOverrideSchItemColors() const
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:166
void SetFileName(const wxString &aFileName)
Definition: sch_screen.h:183
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
bool onSheetFilenameChanged(const wxString &aNewFilename)
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:187
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:283
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
Custom text control validator definitions.
FIELDS_GRID_TABLE< SCH_FIELD > * m_fields
DIALOG_SCH_SHEET_PROPS(SCH_EDIT_FRAME *aParent, SCH_SHEET *aSheet, bool *aClearAnnotationNewItems)
void OnMoveDown(wxCommandEvent &event) override
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99