Enable editing of sheet fields.

This commit is contained in:
Jeff Young 2020-03-06 20:02:58 +00:00
parent a2ad9d67ba
commit 535033c5c9
31 changed files with 1760 additions and 1853 deletions

View File

@ -68,11 +68,11 @@ DIALOG_CONFIGURE_PATHS::DIALOG_CONFIGURE_PATHS( wxWindow* aParent, FILENAME_RESO
m_EnvVars->UseNativeColHeader( true );
wxGridCellAttr* attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir ) );
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) );
m_EnvVars->SetColAttr( EV_PATH_COL, attr );
attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir ) );
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, &m_curdir, wxEmptyString ) );
m_SearchPaths->SetColAttr( EV_PATH_COL, attr );
// Give a bit more room for combobox editors

View File

@ -371,7 +371,10 @@ protected:
void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
wxEvtHandler* aEventHandler )
{
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
if( m_ext.IsEmpty() )
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir );
else
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_currentDir, &m_ext );
#if wxUSE_VALIDATORS
// validate text in textctrl, if validator is set

View File

@ -215,24 +215,26 @@ DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD(
}
DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD(
SCH_BASE_FRAME* aParent, const wxString& aTitle, const SCH_FIELD* aField )
: DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField )
DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle,
const SCH_FIELD* aField ) :
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, aField )
{
m_fieldId = aField->GetId();
const SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
wxASSERT_MSG( component && component->Type() == SCH_COMPONENT_T,
wxT( "Invalid schematic field parent item." ) );
m_isPower = false;
// The library symbol may have been removed so using SCH_COMPONENT::GetPartRef() here
// could result in a segfault. If the library symbol is no longer available, the
// schematic fields can still edit so set the power symbol flag to false. This may not
// be entirely accurate if the power library is missing but it's better then a segfault.
const LIB_PART* part = GetParent()->GetLibPart( component->GetLibId(), true );
if( aField->GetParent() && aField->GetParent()->Type() == SCH_COMPONENT_T )
{
const SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
const LIB_PART* part = GetParent()->GetLibPart( component->GetLibId(), true );
m_isPower = ( part ) ? part->IsPower() : false;
if( part && part->IsPower() )
m_isPower = true;
}
init();
}
@ -240,16 +242,13 @@ DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD(
void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH* aSheetPath )
{
if( aField->GetId() == REFERENCE )
EDA_ITEM* parent = aField->GetParent();
if( parent && parent->Type() == SCH_COMPONENT_T && aField->GetId() == REFERENCE )
{
wxASSERT( aSheetPath );
SCH_COMPONENT* component = dynamic_cast< SCH_COMPONENT* >( aField->GetParent() );
wxASSERT( component );
if( component )
component->SetRef( aSheetPath, m_text );
static_cast<SCH_COMPONENT*>( parent )->SetRef( aSheetPath, m_text );
}
bool positioningModified = false;
@ -270,8 +269,5 @@ void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH*
updateText( aField );
if( positioningModified )
{
auto component = static_cast< SCH_COMPONENT* >( aField->GetParent() );
component->ClearFieldsAutoplaced();
}
static_cast<SCH_ITEM*>( parent )->ClearFieldsAutoplaced();
}

View File

@ -25,6 +25,7 @@
#include <dialog_sch_sheet_props.h>
#include <kiface_i.h>
#include <wx/string.h>
#include <wx/tooltip.h>
#include <confirm.h>
#include <validators.h>
#include <wildcards_and_files_ext.h>
@ -32,120 +33,603 @@
#include <sch_edit_frame.h>
#include <sch_sheet.h>
#include <bitmaps.h>
#include <eeschema_settings.h>
DIALOG_SCH_SHEET_PROPS::DIALOG_SCH_SHEET_PROPS( SCH_EDIT_FRAME* parent, SCH_SHEET* aSheet ) :
DIALOG_SCH_SHEET_PROPS_BASE( parent ),
m_sheet( aSheet ),
m_filenameTextSize( parent, m_filenameSizeLabel, m_filenameSizeCtrl, m_filenameSizeUnits, true ),
m_sheetnameTextSize( parent, m_sheetnameSizeLabel, m_sheetnameSizeCtrl, m_sheetnameSizeUnits, true )
DIALOG_SCH_SHEET_PROPS::DIALOG_SCH_SHEET_PROPS( SCH_EDIT_FRAME* aParent, SCH_SHEET* aSheet,
bool* aClearAnnotationNewItems ) :
DIALOG_SCH_SHEET_PROPS_BASE( aParent ),
m_frame( aParent ),
m_clearAnnotationNewItems( aClearAnnotationNewItems )
{
m_textFileName->SetValidator( FILE_NAME_WITH_PATH_CHAR_VALIDATOR() );
m_textFileName->SetFocus();
m_sdbSizer1OK->SetDefault();
m_sheet = aSheet;
m_fields = new FIELDS_GRID_TABLE<SCH_FIELD>( this, aParent, m_sheet );
m_browseButton->SetBitmap( KiBitmap( folder_xpm ) );
m_width = 0;
m_delayedFocusRow = SHEETNAME;
m_delayedFocusColumn = FDC_VALUE;
// We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
// implementation on MSW
m_tabOrder = {
m_textFileName,
m_browseButton,
m_filenameVisible,
m_filenameSizeCtrl,
// Give a bit more room for combobox editors
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
m_textSheetName,
m_sheetnameSizeCtrl,
m_sheetnameVisible,
m_grid->SetTable( m_fields );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
m_sdbSizer1OK,
m_sdbSizer1Cancel
};
// Show/hide columns according to user's preference
auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
m_shownColumns = cfg->m_Appearance.edit_sheet_visible_columns;
m_grid->ShowHideColumns( m_shownColumns );
SetInitialFocus( m_textFileName );
wxToolTip::Enable( true );
m_stdDialogButtonSizerOK->SetDefault();
// Configure button logos
m_bpAdd->SetBitmap( KiBitmap( small_plus_xpm ) );
m_bpDelete->SetBitmap( KiBitmap( trash_xpm ) );
m_bpMoveUp->SetBitmap( KiBitmap( small_up_xpm ) );
m_bpMoveDown->SetBitmap( KiBitmap( small_down_xpm ) );
// wxFormBuilder doesn't include this event...
m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_SCH_SHEET_PROPS::OnGridCellChanging ),
NULL, this );
// Now all widgets have the size fixed, call FinishDialogSettings
FinishDialogSettings();
}
/*
* This ugly hack fixes a bug in wxWidgets 2.8.7 and likely earlier versions for the flex
* grid sizer in wxGTK that prevents the last column from being sized correctly. It doesn't
* appear to cause any problems on other platforms so we don't use conditional compilation.
* Still present in wxWidgets 3.0.2
*/
Layout();
Fit();
SetMinSize( GetSize() );
GetSizer()->Fit( this );
DIALOG_SCH_SHEET_PROPS::~DIALOG_SCH_SHEET_PROPS()
{
auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
cfg->m_Appearance.edit_sheet_visible_columns = m_grid->GetShownColumns();
// Prevents crash bug in wxGrid's d'tor
m_grid->DestroyTable( m_fields );
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
wxGridEventHandler( DIALOG_SCH_SHEET_PROPS::OnGridCellChanging ),
NULL, this );
// Delete the GRID_TRICKS.
m_grid->PopEventHandler( true );
}
bool DIALOG_SCH_SHEET_PROPS::TransferDataToWindow()
{
// Filenames are stored using unix notation
wxString fname = m_sheet->GetFileName();
if( !wxDialog::TransferDataToWindow() )
return false;
// Push a copy of each field into m_fields
for( SCH_FIELD& field : m_sheet->GetFields() )
{
SCH_FIELD field_copy( field );
#ifdef __WINDOWS__
fname.Replace( wxT("/"), wxT("\\") );
// Filenames are stored using unix notation
if( field_copy.GetId() == SHEETFILENAME )
{
wxString filename = field_copy.GetText();
filename.Replace( wxT("/"), wxT("\\") ) );
field_copy.SetText( filename );
}
#endif
m_textFileName->SetValue( fname );
m_filenameVisible->SetValue( m_sheet->GetShowFileName() );
m_textSheetName->SetValue( m_sheet->GetName() );
m_sheetnameVisible->SetValue( m_sheet->GetShowSheetName() );
// change offset to be symbol-relative
field_copy.Offset( -m_sheet->GetPosition() );
m_filenameTextSize.SetValue( m_sheet->GetFileNameSize() );
m_sheetnameTextSize.SetValue( m_sheet->GetSheetNameSize() );
m_fields->push_back( field_copy );
}
m_textCtrlUuid->SetValue( m_sheet->m_Uuid.AsString() );
m_textCtrlHpath->SetValue( g_CurrentSheet->PathHumanReadable() );
// notify the grid
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->size() );
m_grid->ProcessTableMessage( msg );
AdjustGridColumns( m_grid->GetRect().GetWidth() );
m_heirarchyPath->SetValue( g_CurrentSheet->PathHumanReadable() );
// Set the component's unique ID time stamp.
m_textCtrlTimeStamp->SetValue( m_sheet->m_Uuid.AsString() );
Layout();
return true;
}
bool DIALOG_SCH_SHEET_PROPS::Validate()
{
wxString msg;
LIB_ID id;
if( !m_grid->CommitPendingChanges() || !m_grid->Validate() )
return false;
// Check for missing field names.
for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields->size(); ++i )
{
SCH_FIELD& field = m_fields->at( i );
wxString fieldName = field.GetName( false );
if( fieldName.IsEmpty() )
{
DisplayErrorMessage( this, _( "Fields must have a name." ) );
m_delayedFocusColumn = FDC_NAME;
m_delayedFocusRow = i;
return false;
}
}
return true;
}
static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b )
{
if( a.GetPosition() != b.GetPosition() )
return true;
if( a.GetHorizJustify() != b.GetHorizJustify() )
return true;
if( a.GetVertJustify() != b.GetVertJustify() )
return true;
if( a.GetTextAngle() != b.GetTextAngle() )
return true;
return false;
}
static bool positioningChanged( FIELDS_GRID_TABLE<SCH_FIELD>* a, std::vector<SCH_FIELD>& b )
{
for( int i = 0; i < a->size(); ++i )
{
if( positioningChanged( a->at( i ), b.at( i ) ) )
return true;
}
return false;
}
bool DIALOG_SCH_SHEET_PROPS::TransferDataFromWindow()
{
wxFileName fileName = GetFileName();
if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
return false;
wxString newRelativeNativeFilename = m_fields->at( SHEETFILENAME ).GetText();
wxString newRelativeFilename = newRelativeNativeFilename;
// Inside Eeschema, filenames are stored using unix notation
newRelativeFilename.Replace( wxT( "\\" ), wxT( "/" ) );
wxString newSheetname = m_fields->at( SHEETNAME ).GetText();
if( newSheetname.IsEmpty() )
newSheetname = _( "Untitled Sheet" );
// Relative file names are relative to the path of the current sheet. This allows for
// nesting of schematic files in subfolders.
wxFileName fileName( newRelativeNativeFilename );
fileName.SetExt( SchematicFileExtension );
if( !fileName.IsOk() )
if( !fileName.IsAbsolute() )
{
DisplayError( this, _( "File name is not valid!" ) );
return false;
const SCH_SCREEN* currentScreen = g_CurrentSheet->LastScreen();
wxCHECK_MSG( currentScreen, false, "Invalid sheet path object." );
wxFileName currentSheetFileName = currentScreen->GetFileName();
wxCHECK_MSG( fileName.Normalize( wxPATH_NORM_ALL, currentSheetFileName.GetPath() ), false,
"Cannot normalize new sheet schematic file path." );
}
m_sheet->SetShowFileName( m_filenameVisible->GetValue() );
m_sheet->SetFileNameSize( m_filenameTextSize.GetValue() );
m_sheet->SetShowSheetName( m_sheetnameVisible->GetValue() );
m_sheet->SetSheetNameSize( m_sheetnameTextSize.GetValue() );
wxString newAbsoluteFilename = fileName.GetFullPath();
// Inside Eeschema, filenames are stored using unix notation
newAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
wxString msg;
bool renameFile = false;
bool loadFromFile = false;
bool clearAnnotation = false;
bool restoreSheet = false;
bool isExistingSheet = false;
SCH_SCREEN* useScreen = NULL;
// Search for a schematic file having the same filename already in use in the hierarchy
// or on disk, in order to reuse it.
if( !g_RootSheet->SearchHierarchy( newAbsoluteFilename, &useScreen ) )
{
loadFromFile = wxFileExists( newAbsoluteFilename );
wxLogDebug( "Sheet requested file \"%s\", %s",
newAbsoluteFilename,
( loadFromFile ) ? "found" : "not found" );
}
if( m_sheet->GetScreen() == NULL ) // New sheet.
{
if( !m_frame->AllowCaseSensitiveFileNameClashes( newAbsoluteFilename ) )
return false;
if( useScreen || loadFromFile ) // Load from existing file.
{
clearAnnotation = true;
wxString existsMsg;
wxString linkMsg;
existsMsg.Printf( _( "\"%s\" already exists." ), fileName.GetFullName() );
linkMsg.Printf( _( "Link \"%s\" to this file?" ), newSheetname );
msg.Printf( wxT( "%s\n\n%s" ), existsMsg, linkMsg );
if( !IsOK( this, msg ) )
return false;
}
else // New file.
{
m_frame->InitSheet( m_sheet, newAbsoluteFilename );
}
}
else // Existing sheet.
{
bool isUndoable = true;
wxString replaceMsg;
wxString newMsg;
wxString noUndoMsg;
isExistingSheet = true;
if( !m_frame->AllowCaseSensitiveFileNameClashes( newAbsoluteFilename ) )
return false;
// Changing the filename of a sheet can modify the full hierarchy structure
// and can be not always undoable.
// So prepare messages for user notifications:
replaceMsg.Printf( _( "Change \"%s\" link from \"%s\" to \"%s\"?" ),
newSheetname,
m_sheet->GetFileName(),
fileName.GetFullName() );
newMsg.Printf( _( "Create new file \"%s\" with contents of \"%s\"?" ),
fileName.GetFullName(),
m_sheet->GetFileName() );
noUndoMsg = _( "This action cannot be undone." );
// We are always using here a case insensitive comparison to avoid issues
// under Windows, although under Unix filenames are case sensitive.
// But many users create schematic under both Unix and Windows
// **
// N.B. 1: aSheet->GetFileName() will return a relative path
// aSheet->GetScreen()->GetFileName() returns a full path
//
// N.B. 2: newFilename uses the unix notation for separator.
// so we must use it also to compare the old and new filenames
wxString oldAbsoluteFilename = m_sheet->GetScreen()->GetFileName();
oldAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
if( newAbsoluteFilename.Cmp( oldAbsoluteFilename ) != 0 )
{
// Sheet file name changes cannot be undone.
isUndoable = false;
if( useScreen || loadFromFile ) // Load from existing file.
{
clearAnnotation = true;
msg.Printf( wxT( "%s\n\n%s" ), replaceMsg, noUndoMsg );
if( !IsOK( this, msg ) )
return false;
if( loadFromFile )
m_sheet->SetScreen( NULL );
}
else // Save to new file name.
{
if( m_sheet->GetScreenCount() > 1 )
{
msg.Printf( wxT( "%s\n\n%s" ), newMsg, noUndoMsg );
if( !IsOK( this, msg ) )
return false;
}
renameFile = true;
}
}
if( isUndoable )
m_frame->SaveCopyInUndoList( m_sheet, UR_CHANGED );
if( renameFile )
{
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
// If the the associated screen is shared by more than one sheet, do not
// change the filename of the corresponding screen here.
// (a new screen will be created later)
// if it is not shared, update the filename
if( m_sheet->GetScreenCount() <= 1 )
m_sheet->GetScreen()->SetFileName( newAbsoluteFilename );
try
{
pi->Save( newAbsoluteFilename, m_sheet->GetScreen(), &Kiway() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error occurred saving schematic file \"%s\"." ), newAbsoluteFilename );
DisplayErrorMessage( this, msg, ioe.What() );
msg.Printf( _( "Failed to save schematic \"%s\"" ), newAbsoluteFilename );
m_frame->AppendMsgPanel( wxEmptyString, msg, CYAN );
return false;
}
// If the the associated screen is shared by more than one sheet, remove the
// screen and reload the file to a new screen. Failure to do this will trash
// the screen reference counting in complex hierarchies.
if( m_sheet->GetScreenCount() > 1 )
{
m_sheet->SetScreen( NULL );
loadFromFile = true;
}
}
}
wxFileName nativeFileName( newRelativeNativeFilename );
nativeFileName.SetExt( SchematicFileExtension );
if( useScreen )
{
// Create a temporary sheet for recursion testing to prevent a possible recursion error.
std::unique_ptr< SCH_SHEET> tmpSheet( new SCH_SHEET );
tmpSheet->SetName( m_fields->at( SHEETNAME ).GetText() );
tmpSheet->SetFileName( nativeFileName.GetFullPath() );
tmpSheet->SetScreen( useScreen );
// No need to check for valid library IDs if we are using an existing screen.
if( m_frame->CheckSheetForRecursion( tmpSheet.get(), g_CurrentSheet ) )
{
if( restoreSheet )
g_CurrentSheet->LastScreen()->Append( m_sheet );
return false;
}
// It's safe to set the sheet screen now.
m_sheet->SetScreen( useScreen );
}
else if( loadFromFile )
{
if( isExistingSheet )
{
// Temporarily remove the sheet from the current schematic page so that recursion
// and symbol library link tests can be performed with the modified sheet settings.
restoreSheet = true;
g_CurrentSheet->LastScreen()->Remove( m_sheet );
}
if( !m_frame->LoadSheetFromFile( m_sheet, g_CurrentSheet, newAbsoluteFilename )
|| m_frame->CheckSheetForRecursion( m_sheet, g_CurrentSheet ) )
{
if( restoreSheet )
g_CurrentSheet->LastScreen()->Append( m_sheet );
return false;
}
if( restoreSheet )
g_CurrentSheet->LastScreen()->Append( m_sheet );
}
m_fields->at( SHEETFILENAME ).SetText( newRelativeFilename );
m_fields->at( SHEETNAME ).SetText( newSheetname );
// change all field positions from relative to absolute
for( unsigned i = 0; i < m_fields->size(); ++i )
m_fields->at( i ).Offset( m_sheet->GetPosition() );
if( positioningChanged( m_fields, m_sheet->GetFields() ) )
m_sheet->ClearFieldsAutoplaced();
m_sheet->SetFields( *m_fields );
if( m_clearAnnotationNewItems )
*m_clearAnnotationNewItems = clearAnnotation;
m_frame->TestDanglingEnds();
m_frame->RefreshItem( m_sheet );
m_frame->OnModify();
return true;
}
void DIALOG_SCH_SHEET_PROPS::OnBrowseClicked( wxCommandEvent& event )
void DIALOG_SCH_SHEET_PROPS::OnGridCellChanging( wxGridEvent& event )
{
// Build the absolute path of current sheet to preselect it when opening the dialog.
wxString path = Prj().AbsolutePath( m_textFileName->GetValue() );
wxFileName fn( path );
wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
wxControl* control = editor->GetControl();
wxFileDialog fileDialog( this, _( "Sheet File" ), fn.GetPath(), fn.GetFullName(),
SchematicFileExtension, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( fileDialog.ShowModal() == wxID_OK )
if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
{
fn.Assign( fileDialog.GetPath() );
fn.MakeRelativeTo( Prj().GetProjectPath() );
event.Veto();
m_delayedFocusRow = event.GetRow();
m_delayedFocusColumn = event.GetCol();
}
m_textFileName->ChangeValue( fn.GetFullPath() );
editor->DecRef();
}
void DIALOG_SCH_SHEET_PROPS::OnAddField( wxCommandEvent& event )
{
if( !m_grid->CommitPendingChanges() )
return;
int fieldID = m_fields->size();
SCH_FIELD newField( wxPoint( 0, 0 ), fieldID, m_sheet );
newField.SetName( SCH_SHEET::GetDefaultFieldName( fieldID ) );
newField.SetTextAngle( m_fields->at( SHEETNAME ).GetTextAngle() );
m_fields->push_back( newField );
// notify the grid
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
m_grid->ProcessTableMessage( msg );
m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
m_grid->SetGridCursor( m_fields->size() - 1, 0 );
m_grid->EnableCellEditControl();
m_grid->ShowCellEditControl();
}
void DIALOG_SCH_SHEET_PROPS::OnDeleteField( wxCommandEvent& event )
{
int curRow = m_grid->GetGridCursorRow();
if( curRow < 0 )
return;
else if( curRow < SHEET_MANDATORY_FIELDS )
{
DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
SHEET_MANDATORY_FIELDS ) );
return;
}
m_grid->CommitPendingChanges( true /* quiet mode */ );
m_fields->erase( m_fields->begin() + curRow );
// notify the grid
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
m_grid->ProcessTableMessage( msg );
if( m_grid->GetNumberRows() > 0 )
{
m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() );
}
}
const wxString DIALOG_SCH_SHEET_PROPS::GetFileName()
void DIALOG_SCH_SHEET_PROPS::OnMoveUp( wxCommandEvent& event )
{
// Filenames are stored using unix notation
wxString fname = m_textFileName->GetValue();
fname.Replace( wxT("\\"), wxT("/") );
return fname;
if( !m_grid->CommitPendingChanges() )
return;
int i = m_grid->GetGridCursorRow();
if( i > SHEET_MANDATORY_FIELDS )
{
SCH_FIELD tmp = m_fields->at( (unsigned) i );
m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
m_fields->insert( m_fields->begin() + i - 1, tmp );
m_grid->ForceRefresh();
m_grid->SetGridCursor( i - 1, m_grid->GetGridCursorCol() );
m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
}
else
wxBell();
}
void DIALOG_SCH_SHEET_PROPS::OnMoveDown( wxCommandEvent& event )
{
if( !m_grid->CommitPendingChanges() )
return;
int i = m_grid->GetGridCursorRow();
if( i >= SHEET_MANDATORY_FIELDS && i < m_grid->GetNumberRows() - 1 )
{
SCH_FIELD tmp = m_fields->at( (unsigned) i );
m_fields->erase( m_fields->begin() + i, m_fields->begin() + i + 1 );
m_fields->insert( m_fields->begin() + i + 1, tmp );
m_grid->ForceRefresh();
m_grid->SetGridCursor( i + 1, m_grid->GetGridCursorCol() );
m_grid->MakeCellVisible( m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol() );
}
else
wxBell();
}
void DIALOG_SCH_SHEET_PROPS::AdjustGridColumns( int aWidth )
{
m_width = aWidth;
// Account for scroll bars
aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
m_grid->AutoSizeColumn( 0 );
int fixedColsWidth = m_grid->GetColSize( 0 );
for( int i = 2; i < m_grid->GetNumberCols(); i++ )
fixedColsWidth += m_grid->GetColSize( i );
m_grid->SetColSize( 1, aWidth - fixedColsWidth );
}
void DIALOG_SCH_SHEET_PROPS::OnUpdateUI( wxUpdateUIEvent& event )
{
wxString shownColumns = m_grid->GetShownColumns();
if( shownColumns != m_shownColumns )
{
m_shownColumns = shownColumns;
if( !m_grid->IsCellEditControlShown() )
AdjustGridColumns( m_grid->GetRect().GetWidth() );
}
// Handle a delayed focus
if( m_delayedFocusRow >= 0 )
{
m_grid->SetFocus();
m_grid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
m_grid->SetGridCursor( m_delayedFocusRow, m_delayedFocusColumn );
m_grid->EnableCellEditControl( true );
m_grid->ShowCellEditControl();
m_delayedFocusRow = -1;
m_delayedFocusColumn = -1;
}
}
void DIALOG_SCH_SHEET_PROPS::OnSizeGrid( wxSizeEvent& event )
{
auto new_size = event.GetSize().GetX();
if( m_width != new_size )
{
AdjustGridColumns( new_size );
}
// Always propagate for a grid repaint (needed if the height changes, as well as width)
event.Skip();
}
void DIALOG_SCH_SHEET_PROPS::OnInitDlg( wxInitDialogEvent& event )
{
TransferDataToWindow();
// Now all widgets have the size fixed, call FinishDialogSettings
FinishDialogSettings();
}

View File

@ -26,32 +26,49 @@
#define __dialog_sch_sheet_props__
#include <dialog_sch_sheet_props_base.h>
#include <widgets/unit_binder.h>
#include <fields_grid_table.h>
class SCH_SHEET;
class SCH_EDIT_FRAME;
/** Implementing DIALOG_SCH_SHEET_PROPS_BASE */
class DIALOG_SCH_SHEET_PROPS : public DIALOG_SCH_SHEET_PROPS_BASE
{
SCH_SHEET* m_sheet;
UNIT_BINDER m_filenameTextSize;
UNIT_BINDER m_sheetnameTextSize;
public:
/** Constructor */
DIALOG_SCH_SHEET_PROPS( SCH_EDIT_FRAME* parent, SCH_SHEET* aSheet );
DIALOG_SCH_SHEET_PROPS( SCH_EDIT_FRAME* aParent, SCH_SHEET* aSheet,
bool* aClearAnnotationNewItems );
~DIALOG_SCH_SHEET_PROPS() override;
private:
SCH_EDIT_FRAME* m_frame;
SCH_SHEET* m_sheet;
bool* m_clearAnnotationNewItems;
int m_width;
int m_delayedFocusRow;
int m_delayedFocusColumn;
wxString m_shownColumns;
FIELDS_GRID_TABLE<SCH_FIELD>* m_fields;
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
void OnBrowseClicked( wxCommandEvent& event ) override;
bool Validate() override;
const wxString GetFileName();
wxString GetSheetName() { return m_textSheetName->GetValue(); }
// event handlers
void OnAddField( wxCommandEvent& event ) override;
void OnDeleteField( wxCommandEvent& event ) override;
void OnMoveUp( wxCommandEvent& event ) override;
void OnMoveDown( wxCommandEvent& event ) override;
void OnSizeGrid( wxSizeEvent& event ) override;
void OnGridCellChanging( wxGridEvent& event );
void OnUpdateUI( wxUpdateUIEvent& event ) override;
void OnInitDlg( wxInitDialogEvent& event ) override;
void AdjustGridColumns( int aWidth );
};
#endif // __dialog_sch_sheet_props__

View File

@ -1,147 +1,193 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 10 2019)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "widgets/wx_grid.h"
#include "dialog_sch_sheet_props_base.h"
///////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE( DIALOG_SCH_SHEET_PROPS_BASE, DIALOG_SHIM )
EVT_BUTTON( ID_BUTTON_BROWSE_SHEET, DIALOG_SCH_SHEET_PROPS_BASE::_wxFB_OnBrowseClicked )
END_EVENT_TABLE()
DIALOG_SCH_SHEET_PROPS_BASE::DIALOG_SCH_SHEET_PROPS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( 500,150 ), wxDefaultSize );
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* mainSizer;
mainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bupperSizer;
bupperSizer = new wxBoxSizer( wxVERTICAL );
m_longForm = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
wxStaticBoxSizer* sbFields;
sbFields = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Fields") ), wxVERTICAL );
m_filenameLabel = new wxStaticText( this, wxID_ANY, _("&File name:"), wxDefaultPosition, wxDefaultSize, 0 );
m_filenameLabel->Wrap( -1 );
bSizer3->Add( m_filenameLabel, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_grid = new WX_GRID( sbFields->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_textFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_textFileName->SetMinSize( wxSize( 360,-1 ) );
// Grid
m_grid->CreateGrid( 4, 11 );
m_grid->EnableEditing( true );
m_grid->EnableGridLines( true );
m_grid->EnableDragGridSize( false );
m_grid->SetMargins( 0, 0 );
bSizer3->Add( m_textFileName, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
// Columns
m_grid->SetColSize( 0, 72 );
m_grid->SetColSize( 1, 120 );
m_grid->SetColSize( 2, 48 );
m_grid->SetColSize( 3, 72 );
m_grid->SetColSize( 4, 72 );
m_grid->SetColSize( 5, 48 );
m_grid->SetColSize( 6, 48 );
m_grid->SetColSize( 7, 84 );
m_grid->SetColSize( 8, 84 );
m_grid->SetColSize( 9, 84 );
m_grid->SetColSize( 10, 84 );
m_grid->EnableDragColMove( false );
m_grid->EnableDragColSize( true );
m_grid->SetColLabelSize( 22 );
m_grid->SetColLabelValue( 0, _("Name") );
m_grid->SetColLabelValue( 1, _("Value") );
m_grid->SetColLabelValue( 2, _("Show") );
m_grid->SetColLabelValue( 3, _("H Align") );
m_grid->SetColLabelValue( 4, _("V Align") );
m_grid->SetColLabelValue( 5, _("Italic") );
m_grid->SetColLabelValue( 6, _("Bold") );
m_grid->SetColLabelValue( 7, _("Text Size") );
m_grid->SetColLabelValue( 8, _("Orientation") );
m_grid->SetColLabelValue( 9, _("X Position") );
m_grid->SetColLabelValue( 10, _("Y Position") );
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
m_browseButton = new wxBitmapButton( this, ID_BUTTON_BROWSE_SHEET, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_browseButton->SetMinSize( wxSize( 30,28 ) );
// Rows
m_grid->EnableDragRowSize( true );
m_grid->SetRowLabelSize( 0 );
m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
bSizer3->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
// Label Appearance
// Cell Defaults
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
m_grid->SetMinSize( wxSize( -1,180 ) );
sbFields->Add( m_grid, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* bButtonSize;
bButtonSize = new wxBoxSizer( wxHORIZONTAL );
m_bpAdd = new wxBitmapButton( sbFields->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_bpAdd->SetToolTip( _("Add field") );
m_bpAdd->SetMinSize( wxSize( 30,30 ) );
bButtonSize->Add( m_bpAdd, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_bpMoveUp = new wxBitmapButton( sbFields->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_bpMoveUp->SetToolTip( _("Move up") );
m_bpMoveUp->SetMinSize( wxSize( 30,30 ) );
bButtonSize->Add( m_bpMoveUp, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_bpMoveDown = new wxBitmapButton( sbFields->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_bpMoveDown->SetToolTip( _("Move down") );
m_bpMoveDown->SetMinSize( wxSize( 30,30 ) );
bButtonSize->Add( m_bpMoveDown, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bupperSizer->Add( bSizer3, 0, wxEXPAND, 5 );
bButtonSize->Add( 0, 0, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
wxBoxSizer* bSizerFilenameSettings;
bSizerFilenameSettings = new wxBoxSizer( wxHORIZONTAL );
m_bpDelete = new wxBitmapButton( sbFields->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_bpDelete->SetToolTip( _("Delete field") );
m_bpDelete->SetMinSize( wxSize( 30,30 ) );
m_filenameVisible = new wxCheckBox( this, wxID_ANY, _("Visible"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerFilenameSettings->Add( m_filenameVisible, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 36 );
m_filenameSizeLabel = new wxStaticText( this, wxID_ANY, _("Text size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_filenameSizeLabel->Wrap( -1 );
bSizerFilenameSettings->Add( m_filenameSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_filenameSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bSizerFilenameSettings->Add( m_filenameSizeCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_filenameSizeUnits = new wxStaticText( this, wxID_ANY, _("units"), wxDefaultPosition, wxDefaultSize, 0 );
m_filenameSizeUnits->Wrap( -1 );
bSizerFilenameSettings->Add( m_filenameSizeUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
bButtonSize->Add( m_bpDelete, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bupperSizer->Add( bSizerFilenameSettings, 0, wxEXPAND, 5 );
bButtonSize->Add( 0, 0, 1, wxEXPAND, 5 );
bupperSizer->Add( 0, 15, 0, wxEXPAND, 5 );
sbFields->Add( bButtonSize, 0, wxALL|wxEXPAND, 5 );
m_longForm->Add( sbFields, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxHORIZONTAL );
m_sheetnameLabel = new wxStaticText( this, wxID_ANY, _("&Sheet name:"), wxDefaultPosition, wxDefaultSize, 0 );
m_sheetnameLabel->Wrap( -1 );
bSizer5->Add( m_sheetnameLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_staticText2 = new wxStaticText( this, wxID_ANY, _("Hierarchical Path:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
bSizer5->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_textSheetName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_textSheetName, 5, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
m_heirarchyPath = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
bSizer5->Add( m_heirarchyPath, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bupperSizer->Add( bSizer5, 0, wxEXPAND, 5 );
wxBoxSizer* bSizerSheetnameSettings;
bSizerSheetnameSettings = new wxBoxSizer( wxHORIZONTAL );
m_sheetnameVisible = new wxCheckBox( this, wxID_ANY, _("Visible"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerSheetnameSettings->Add( m_sheetnameVisible, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 36 );
m_sheetnameSizeLabel = new wxStaticText( this, wxID_ANY, _("Text size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_sheetnameSizeLabel->Wrap( -1 );
bSizerSheetnameSettings->Add( m_sheetnameSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_sheetnameSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bSizerSheetnameSettings->Add( m_sheetnameSizeCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_sheetnameSizeUnits = new wxStaticText( this, wxID_ANY, _("units"), wxDefaultPosition, wxDefaultSize, 0 );
m_sheetnameSizeUnits->Wrap( -1 );
bSizerSheetnameSettings->Add( m_sheetnameSizeUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_longForm->Add( bSizer5, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bupperSizer->Add( bSizerSheetnameSettings, 0, wxEXPAND, 5 );
bupperSizer->Add( 0, 20, 0, 0, 5 );
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bupperSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
m_staticTextUuid = new wxStaticText( this, wxID_ANY, _("UUID:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextUuid->Wrap( -1 );
bupperSizer->Add( m_staticTextUuid, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_textCtrlUuid = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
bupperSizer->Add( m_textCtrlUuid, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_staticTextHpath = new wxStaticText( this, wxID_ANY, _("Hierarchical Path:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextHpath->Wrap( -1 );
bupperSizer->Add( m_staticTextHpath, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_textCtrlHpath = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
bupperSizer->Add( m_textCtrlHpath, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
mainSizer->Add( bupperSizer, 0, wxEXPAND|wxALL, 5 );
mainSizer->Add( m_longForm, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
mainSizer->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
wxBoxSizer* bSizerBottom;
bSizerBottom = new wxBoxSizer( wxHORIZONTAL );
mainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* bSizerUUID;
bSizerUUID = new wxBoxSizer( wxHORIZONTAL );
wxStaticText* timeStampLabel;
timeStampLabel = new wxStaticText( this, wxID_ANY, _("Unique ID:"), wxDefaultPosition, wxDefaultSize, 0 );
timeStampLabel->Wrap( -1 );
bSizerUUID->Add( timeStampLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_textCtrlTimeStamp = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_textCtrlTimeStamp->SetToolTip( _("Unique ID that identifies the symbol") );
bSizerUUID->Add( m_textCtrlTimeStamp, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bSizerBottom->Add( bSizerUUID, 3, wxEXPAND|wxRIGHT|wxLEFT, 5 );
bSizerBottom->Add( 0, 0, 1, wxEXPAND, 5 );
m_stdDialogButtonSizer = new wxStdDialogButtonSizer();
m_stdDialogButtonSizerOK = new wxButton( this, wxID_OK );
m_stdDialogButtonSizer->AddButton( m_stdDialogButtonSizerOK );
m_stdDialogButtonSizerCancel = new wxButton( this, wxID_CANCEL );
m_stdDialogButtonSizer->AddButton( m_stdDialogButtonSizerCancel );
m_stdDialogButtonSizer->Realize();
bSizerBottom->Add( m_stdDialogButtonSizer, 0, wxEXPAND|wxALL, 5 );
mainSizer->Add( bSizerBottom, 0, wxEXPAND|wxLEFT, 5 );
this->SetSizer( mainSizer );
this->Layout();
mainSizer->Fit( this );
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnInitDlg ) );
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnUpdateUI ) );
m_grid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnSizeGrid ), NULL, this );
m_bpAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnAddField ), NULL, this );
m_bpMoveUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnMoveUp ), NULL, this );
m_bpMoveDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnMoveDown ), NULL, this );
m_bpDelete->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnDeleteField ), NULL, this );
}
DIALOG_SCH_SHEET_PROPS_BASE::~DIALOG_SCH_SHEET_PROPS_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnInitDlg ) );
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnUpdateUI ) );
m_grid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnSizeGrid ), NULL, this );
m_bpAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnAddField ), NULL, this );
m_bpMoveUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnMoveUp ), NULL, this );
m_bpMoveDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnMoveDown ), NULL, this );
m_bpDelete->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCH_SHEET_PROPS_BASE::OnDeleteField ), NULL, this );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 10 2019)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -10,74 +10,65 @@
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class WX_GRID;
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/textctrl.h>
#include <wx/string.h>
#include <wx/font.h>
#include <wx/grid.h>
#include <wx/gdicmn.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/statbox.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/statline.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_SCH_SHEET_PROPS_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_SCH_SHEET_PROPS_BASE : public DIALOG_SHIM
{
DECLARE_EVENT_TABLE()
private:
// Private event handlers
void _wxFB_OnBrowseClicked( wxCommandEvent& event ){ OnBrowseClicked( event ); }
protected:
enum
{
ID_BUTTON_BROWSE_SHEET = 1000
};
wxStaticText* m_filenameLabel;
wxTextCtrl* m_textFileName;
wxBitmapButton* m_browseButton;
wxCheckBox* m_filenameVisible;
wxStaticText* m_filenameSizeLabel;
wxTextCtrl* m_filenameSizeCtrl;
wxStaticText* m_filenameSizeUnits;
wxStaticText* m_sheetnameLabel;
wxTextCtrl* m_textSheetName;
wxCheckBox* m_sheetnameVisible;
wxStaticText* m_sheetnameSizeLabel;
wxTextCtrl* m_sheetnameSizeCtrl;
wxStaticText* m_sheetnameSizeUnits;
wxStaticLine* m_staticline2;
wxStaticText* m_staticTextUuid;
wxTextCtrl* m_textCtrlUuid;
wxStaticText* m_staticTextHpath;
wxTextCtrl* m_textCtrlHpath;
wxBoxSizer* m_longForm;
WX_GRID* m_grid;
wxBitmapButton* m_bpAdd;
wxBitmapButton* m_bpMoveUp;
wxBitmapButton* m_bpMoveDown;
wxBitmapButton* m_bpDelete;
wxStaticText* m_staticText2;
wxTextCtrl* m_heirarchyPath;
wxStaticLine* m_staticline1;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
wxTextCtrl* m_textCtrlTimeStamp;
wxStdDialogButtonSizer* m_stdDialogButtonSizer;
wxButton* m_stdDialogButtonSizerOK;
wxButton* m_stdDialogButtonSizerCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnSizeGrid( wxSizeEvent& event ) { event.Skip(); }
virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); }
virtual void OnMoveUp( wxCommandEvent& event ) { event.Skip(); }
virtual void OnMoveDown( wxCommandEvent& event ) { event.Skip(); }
virtual void OnDeleteField( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_SCH_SHEET_PROPS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Schematic Sheet Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DIALOG_SCH_SHEET_PROPS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Symbol Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 864,440 ), long style = wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU );
~DIALOG_SCH_SHEET_PROPS_BASE();
};

View File

@ -73,7 +73,7 @@ SEARCH_RESULT EE_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
if( aItem->Type() == LIB_PIN_T )
{
// Special selection rules apply to pins of different units when edited in
// synchronized pins mode. Leave it to EE_SELECTION_TOOL::isSelectable() to
// synchronized pins mode. Leave it to EE_SELECTION_TOOL::Selectable() to
// decide what to do with them.
}
else if( m_Unit || m_Convert )

View File

@ -40,6 +40,9 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : APP_SETTINGS_BASE( "eeschema", eeschema
m_params.emplace_back( new PARAM<wxString>( "appearance.edit_component_visible_columns",
&m_Appearance.edit_component_visible_columns, "0 1 2 3 4 5 6 7" ) );
m_params.emplace_back( new PARAM<wxString>( "appearance.edit_sheet_visible_columns",
&m_Appearance.edit_sheet_visible_columns, "0 1 2 3 4 5 6 7" ) );
m_params.emplace_back( new PARAM<bool>( "appearance.footprint_preview",
&m_Appearance.footprint_preview, true ) );

View File

@ -34,6 +34,7 @@ public:
struct APPEARANCE
{
wxString edit_component_visible_columns;
wxString edit_sheet_visible_columns;
bool footprint_preview;
bool navigator_stays_open;
bool print_sheet_reference;

View File

@ -33,6 +33,7 @@
#include <template_fieldnames.h>
#include <widgets/grid_icon_text_helpers.h>
#include <widgets/grid_text_button_helpers.h>
#include <wildcards_and_files_ext.h>
#include "eda_doc.h"
@ -47,15 +48,45 @@ enum
template <class T>
FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame,
LIB_PART* aPart ) :
m_frame( aFrame ),
m_userUnits( aDialog->GetUserUnits() ),
m_part( aPart ),
m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ),
m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
m_libIdValidator( LIB_ID::ID_PCB ),
m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE )
m_frame( aFrame ),
m_userUnits( aDialog->GetUserUnits() ),
m_parentType( SCH_COMPONENT_T ),
m_mandatoryFieldCount( MANDATORY_FIELDS ),
m_part( aPart ),
m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ),
m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
m_libIdValidator( LIB_ID::ID_PCB ),
m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME )
{
initGrid( aDialog );
}
template <class T>
FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame,
SCH_SHEET* aSheet ) :
m_frame( aFrame ),
m_userUnits( aDialog->GetUserUnits() ),
m_parentType( SCH_SHEET_T ),
m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ),
m_part( nullptr ),
m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ),
m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
m_libIdValidator( LIB_ID::ID_PCB ),
m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME )
{
initGrid( aDialog );
}
template <class T>
void FIELDS_GRID_TABLE<T>::initGrid( DIALOG_SHIM* aDialog )
{
// Build the various grid cell attributes.
// NOTE: validators and cellAttrs are member variables to get the destruction order
@ -94,6 +125,13 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
nonUrlEditor->SetValidator( m_nonUrlValidator );
m_nonUrlAttr->SetEditor( nonUrlEditor );
m_curdir = m_frame->Prj().GetProjectPath();
m_filepathAttr = new wxGridCellAttr;
GRID_CELL_PATH_EDITOR* filepathEditor = new GRID_CELL_PATH_EDITOR( aDialog, &m_curdir,
SchematicFileExtension );
filepathEditor->SetValidator( m_filepathValidator );
m_filepathAttr->SetEditor( filepathEditor );
m_boolAttr = new wxGridCellAttr;
m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
m_boolAttr->SetEditor( new wxGridCellBoolEditor() );
@ -135,6 +173,7 @@ FIELDS_GRID_TABLE<T>::~FIELDS_GRID_TABLE()
m_footprintAttr->DecRef();
m_urlAttr->DecRef();
m_nonUrlAttr->DecRef();
m_filepathAttr->DecRef();
m_vAlignAttr->DecRef();
m_hAlignAttr->DecRef();
m_orientationAttr->DecRef();
@ -207,7 +246,7 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
switch( aCol )
{
case FDC_NAME:
if( aRow < MANDATORY_FIELDS || rowIsReadOnly )
if( aRow < m_mandatoryFieldCount || rowIsReadOnly )
{
tmp = m_fieldNameAttr->Clone();
tmp->SetReadOnly( true );
@ -221,7 +260,7 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
}
case FDC_VALUE:
if( aRow == REFERENCE )
if( m_parentType == SCH_COMPONENT_T && aRow == REFERENCE )
{
if( rowIsReadOnly )
{
@ -236,7 +275,7 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
return m_referenceAttr;
}
}
else if( aRow == VALUE )
else if( m_parentType == SCH_COMPONENT_T && aRow == VALUE )
{
// For power symbols, the value is not editable, because value and pin name must
// be the same and can be edited only in library editor.
@ -254,7 +293,7 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
return m_valueAttr;
}
}
else if( aRow == FOOTPRINT )
else if( m_parentType == SCH_COMPONENT_T && aRow == FOOTPRINT )
{
if( rowIsReadOnly )
{
@ -269,11 +308,16 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
return m_footprintAttr;
}
}
else if( aRow == DATASHEET )
else if( m_parentType == SCH_COMPONENT_T && aRow == DATASHEET )
{
m_urlAttr->IncRef();
return m_urlAttr;
}
else if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
{
m_filepathAttr->IncRef();
return m_filepathAttr;
}
else
{
wxString fieldname = GetValue( aRow, FDC_NAME );
@ -403,10 +447,15 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
case FDC_NAME:
// Use default field name for mandatory fields, because they are translated
// according to the current locale
if( aRow < MANDATORY_FIELDS )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow );
else
return field.GetName( false );
if( aRow < m_mandatoryFieldCount )
{
if( m_parentType == SCH_COMPONENT_T )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow );
else if( m_parentType == SCH_SHEET_T )
return SCH_SHEET::GetDefaultFieldName( aRow );
}
return field.GetName( false );
case FDC_VALUE:
return field.GetText();

View File

@ -73,6 +73,7 @@ class FIELDS_GRID_TABLE : public wxGridTableBase, public std::vector<T>
{
public:
FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame, LIB_PART* aPart );
FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame, SCH_SHEET* aSheet );
~FIELDS_GRID_TABLE();
int GetNumberRows() override { return (int) this->size(); }
@ -98,10 +99,16 @@ public:
wxString StringFromBool( bool aValue );
bool BoolFromString( wxString aValue );
protected:
void initGrid( DIALOG_SHIM* aDialog );
private:
SCH_BASE_FRAME* m_frame;
EDA_UNITS m_userUnits;
KICAD_T m_parentType;
int m_mandatoryFieldCount;
LIB_PART* m_part;
wxString m_curdir;
SCH_FIELD_VALIDATOR m_fieldNameValidator;
SCH_FIELD_VALIDATOR m_referenceValidator;
@ -109,6 +116,7 @@ private:
LIB_ID_VALIDATOR m_libIdValidator;
SCH_FIELD_VALIDATOR m_urlValidator;
SCH_FIELD_VALIDATOR m_nonUrlValidator;
SCH_FIELD_VALIDATOR m_filepathValidator;
wxGridCellAttr* m_readOnlyAttr;
wxGridCellAttr* m_fieldNameAttr;
@ -117,6 +125,7 @@ private:
wxGridCellAttr* m_footprintAttr;
wxGridCellAttr* m_urlAttr;
wxGridCellAttr* m_nonUrlAttr;
wxGridCellAttr* m_filepathAttr;
wxGridCellAttr* m_boolAttr;
wxGridCellAttr* m_vAlignAttr;
wxGridCellAttr* m_hAlignAttr;

View File

@ -928,11 +928,11 @@ void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
m_Fields.swap( component->m_Fields ); // std::vector's swap()
for( int ii = 0; ii < component->GetFieldCount(); ++ii )
component->GetField( ii )->SetParent( component );
for( SCH_FIELD& field : component->m_Fields )
field.SetParent( component );
for( int ii = 0; ii < GetFieldCount(); ++ii )
GetField( ii )->SetParent( this );
for( SCH_FIELD& field : m_Fields )
field.SetParent( this );
TRANSFORM tmp = m_transform;
@ -1345,12 +1345,12 @@ void SCH_COMPONENT::MirrorY( int aYaxis_position )
MIRROR( m_Pos.x, aYaxis_position );
dx -= m_Pos.x; // dx,0 is the move vector for this transform
for( int ii = 0; ii < GetFieldCount(); ii++ )
for( SCH_FIELD& field : m_Fields )
{
// Move the fields to the new position because the component itself has moved.
wxPoint pos = GetField( ii )->GetTextPos();
wxPoint pos = field.GetTextPos();
pos.x -= dx;
GetField( ii )->SetTextPos( pos );
field.SetTextPos( pos );
}
}
@ -1363,12 +1363,12 @@ void SCH_COMPONENT::MirrorX( int aXaxis_position )
MIRROR( m_Pos.y, aXaxis_position );
dy -= m_Pos.y; // dy,0 is the move vector for this transform
for( int ii = 0; ii < GetFieldCount(); ii++ )
for( SCH_FIELD& field : m_Fields )
{
// Move the fields to the new position because the component itself has moved.
wxPoint pos = GetField( ii )->GetTextPos();
wxPoint pos = field.GetTextPos();
pos.y -= dy;
GetField( ii )->SetTextPos( pos );
field.SetTextPos( pos );
}
}
@ -1530,9 +1530,9 @@ SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
if( stype == SCH_LOCATE_ANY_T || stype == SCH_FIELD_T )
{
// Test the bounding boxes of fields if they are visible and not empty.
for( int ii = 0; ii < GetFieldCount(); ii++ )
for( SCH_FIELD& field : m_Fields )
{
if( SEARCH_RESULT::QUIT == aInspector( GetField( ii ), (void*) this ) )
if( SEARCH_RESULT::QUIT == aInspector( &field, (void*) this ) )
return SEARCH_RESULT::QUIT;
}
}

View File

@ -124,8 +124,6 @@ private:
SCH_PINS m_pins; ///< a SCH_PIN for every LIB_PIN (across all units)
SCH_PIN_MAP m_pinMap; ///< the component's pins mapped by LIB_PIN*
FIELDS_AUTOPLACED m_fieldsAutoplaced; ///< indicates status of field autoplacement
bool m_isInNetlist; ///< True if the component should appear in the netlist
// Defines the hierarchical path and reference of the component. This allows support
@ -424,16 +422,6 @@ public:
*/
int GetFieldCount() const { return (int)m_Fields.size(); }
/**
* Return whether the fields have been automatically placed.
*/
FIELDS_AUTOPLACED GetFieldsAutoplaced() const { return m_fieldsAutoplaced; }
/**
* Set fields automatically placed flag false.
*/
void ClearFieldsAutoplaced() { m_fieldsAutoplaced = FIELDS_AUTOPLACED_NO; }
/**
* Automatically orient all the fields in the component.
*
@ -443,21 +431,7 @@ public:
* or a menu item). Some more 'intelligent' routines will be used that would be
* annoying if done automatically during moves.
*/
void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual );
/**
* Autoplace fields only if correct to do so automatically.
*
* Fields that have been moved by hand are not automatically placed.
*
* @param aScreen is the SCH_SCREEN associated with the current instance of the
* component.
*/
void AutoAutoplaceFields( SCH_SCREEN* aScreen )
{
if( GetFieldsAutoplaced() )
AutoplaceFields( aScreen, GetFieldsAutoplaced() == FIELDS_AUTOPLACED_MANUAL );
}
void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual ) override;
//-----</Fields>----------------------------------------------------------
@ -558,8 +532,8 @@ public:
m_Pos += aMoveVector;
for( int ii = 0; ii < GetFieldCount(); ii++ )
GetField( ii )->Move( aMoveVector );
for( SCH_FIELD& field : m_Fields )
field.Move( aMoveVector );
SetModified();
}

View File

@ -725,16 +725,6 @@ private:
*/
void UpdateTitle();
/**
* Verify that \a aSheet will not cause a recursion error in \a aHierarchy.
*
* @param aSheet is the #SCH_SHEET object to test.
* @param aHierarchy is the #SCH_SHEET_PATH where \a aSheet is going to reside.
*
* @return true if \a aSheet will cause a resursion error in \a aHierarchy.
*/
bool checkSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy );
/**
* Verify that the symbol library links \a aSheet and all of it's child sheets have
* been remapped to the symbol library table.
@ -753,6 +743,17 @@ private:
*/
bool importFile( const wxString& aFileName, int aFileType );
public:
/**
* Verify that \a aSheet will not cause a recursion error in \a aHierarchy.
*
* @param aSheet is the #SCH_SHEET object to test.
* @param aHierarchy is the #SCH_SHEET_PATH where \a aSheet is going to reside.
*
* @return true if \a aSheet will cause a resursion error in \a aHierarchy.
*/
bool CheckSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy );
/**
* Check \a aSchematicFileName for a potential file name case sensitivity clashes.
*
@ -764,9 +765,8 @@ private:
* @param aSchematicFileName is the absolute path and file name of the file to test.
* @return true if the user accepts the potential file name clase risk.
*/
bool allowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName );
bool AllowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName );
public:
/**
* Change a text type to another one.
*

View File

@ -216,18 +216,26 @@ const EDA_RECT SCH_FIELD::GetBoundingBox() const
RotatePoint( &begin, pos, GetTextAngle() );
RotatePoint( &end, pos, GetTextAngle() );
// Due to the Y axis direction, we must mirror the bounding box,
// relative to the text position:
MIRROR( begin.y, pos.y );
MIRROR( end.y, pos.y );
// Now, apply the component transform (mirror/rot)
TRANSFORM transform;
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
{
// Due to the Y axis direction, we must mirror the bounding box,
// relative to the text position:
MIRROR( begin.y, pos.y );
MIRROR( end.y, pos.y );
SCH_COMPONENT* parentComponent = static_cast<SCH_COMPONENT*>( m_Parent );
rect.SetOrigin( parentComponent->GetTransform().TransformCoordinate( begin ));
rect.SetEnd( parentComponent->GetTransform().TransformCoordinate( end ));
transform = parentComponent->GetTransform();
}
else
{
transform = TRANSFORM( 1, 0, 0, 1 ); // identity transform
}
rect.SetOrigin( transform.TransformCoordinate( begin ) );
rect.SetEnd( transform.TransformCoordinate( end ) );
rect.Move( origin );
rect.Normalize();
@ -296,14 +304,23 @@ bool SCH_FIELD::Matches( wxFindReplaceData& aSearchData, void* aAuxData )
bool SCH_FIELD::IsReplaceable() const
{
if( m_id != VALUE )
return true;
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
{
if( m_id == VALUE )
{
LIB_PART* part = static_cast<SCH_COMPONENT*>( GetParent() )->GetPartRef().get();
SCH_COMPONENT* component = dynamic_cast<SCH_COMPONENT*>( GetParent() );
LIB_PART* part = component ? component->GetPartRef().get() : nullptr;
bool isPower = part ? part->IsPower() : false;
if( part && part->IsPower() )
return false;
}
}
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
{
if( m_id == SHEETFILENAME )
return false;
}
return !isPower;
return true;
}
@ -311,10 +328,8 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
{
bool isReplaced = false;
wxString text = GetFullyQualifiedText();
bool isReference = m_Parent && m_Parent->Type() == SCH_COMPONENT_T && m_id == REFERENCE;
bool isFilename = m_Parent && m_Parent->Type() == SCH_SHEET_T && m_id == SHEETFILENAME;
if( isReference )
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T && m_id == REFERENCE )
{
wxCHECK_MSG( aAuxData != NULL, false,
wxT( "Cannot replace reference designator without valid sheet path." ) );
@ -324,8 +339,6 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
SCH_COMPONENT* component = (SCH_COMPONENT*) m_Parent;
wxCHECK_MSG( component != NULL, false, wxT( "No symbol associated with field" ) + text );
text = component->GetRef( (SCH_SHEET_PATH*) aAuxData );
// if( component->GetUnitCount() > 1 )
@ -336,7 +349,7 @@ bool SCH_FIELD::Replace( wxFindReplaceData& aSearchData, void* aAuxData )
if( isReplaced )
component->SetRef( (SCH_SHEET_PATH*) aAuxData, text );
}
else if( isFilename )
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T && m_id == SHEETFILENAME )
{
// This is likely too dangerous to allow....
}
@ -368,7 +381,12 @@ wxString SCH_FIELD::GetName( bool aUseDefaultName ) const
if( !m_name.IsEmpty() )
return m_name;
else if( aUseDefaultName )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_id );
{
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_id );
else if( m_Parent && m_Parent->Type() == SCH_SHEET_T )
return SCH_SHEET::GetDefaultFieldName( m_id );
}
return wxEmptyString;
}
@ -376,7 +394,7 @@ wxString SCH_FIELD::GetName( bool aUseDefaultName ) const
BITMAP_DEF SCH_FIELD::GetMenuImage() const
{
if( dynamic_cast<SCH_COMPONENT*>( m_Parent ) )
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
{
switch( m_id )
{
@ -475,16 +493,20 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter )
void SCH_FIELD::SetPosition( const wxPoint& aPosition )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) GetParent();
wxPoint pos = ( (SCH_COMPONENT*) GetParent() )->GetPosition();
wxPoint pos = GetParentPosition();
// Actual positions are calculated by the rotation/mirror transform of the
// parent component of the field. The inverse transform is used to calculate
// the position relative to the parent component.
wxPoint pt = aPosition - pos;
if( m_Parent && m_Parent->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) GetParent();
wxPoint pt = aPosition - pos;
SetTextPos( pos + component->GetTransform().InverseTransform().TransformCoordinate( pt ) );
pos += component->GetTransform().InverseTransform().TransformCoordinate( pt );
}
SetTextPos( pos );
}

View File

@ -37,14 +37,6 @@ class SCH_COMPONENT;
class LIB_FIELD;
enum FIELDS_AUTOPLACED
{
FIELDS_AUTOPLACED_NO = 0,
FIELDS_AUTOPLACED_AUTO,
FIELDS_AUTOPLACED_MANUAL
};
/**
* SCH_FIELD
* instances are attached to a component and provide a place for the component's value,

View File

@ -43,7 +43,16 @@ class NETLIST_OBJECT;
class NETLIST_OBJECT_LIST;
enum DANGLING_END_T {
enum FIELDS_AUTOPLACED
{
FIELDS_AUTOPLACED_NO = 0,
FIELDS_AUTOPLACED_AUTO,
FIELDS_AUTOPLACED_MANUAL
};
enum DANGLING_END_T
{
UNKNOWN = 0,
WIRE_START_END,
WIRE_END_END,
@ -140,10 +149,11 @@ class SCH_ITEM : public EDA_ITEM
friend class CONNECTION_GRAPH;
protected:
SCH_LAYER_ID m_Layer;
EDA_ITEMS m_connections; ///< List of items connected to this item.
wxPoint m_storedPos; ///< a temporary variable used in some move commands
///> to store a initial pos (of the item or mouse cursor)
SCH_LAYER_ID m_Layer;
EDA_ITEMS m_connections; // List of items connected to this item.
FIELDS_AUTOPLACED m_fieldsAutoplaced; // indicates status of field autoplacement
wxPoint m_storedPos; // a temporary variable used in some move commands
// to store a initial pos of the item or mouse cursor
/// Stores pointers to other items that are connected to this one, per sheet
std::unordered_map<SCH_SHEET_PATH, ITEM_SET> m_connected_items;
@ -388,6 +398,32 @@ public:
virtual bool CanIncrementLabel() const { return false; }
/**
* Return whether the fields have been automatically placed.
*/
FIELDS_AUTOPLACED GetFieldsAutoplaced() const { return m_fieldsAutoplaced; }
/**
* Set fields automatically placed flag false.
*/
void ClearFieldsAutoplaced() { m_fieldsAutoplaced = FIELDS_AUTOPLACED_NO; }
/**
* Autoplace fields only if correct to do so automatically.
*
* Fields that have been moved by hand are not automatically placed.
*
* @param aScreen is the SCH_SCREEN associated with the current instance of the
* component.
*/
void AutoAutoplaceFields( SCH_SCREEN* aScreen )
{
if( GetFieldsAutoplaced() )
AutoplaceFields( aScreen, GetFieldsAutoplaced() == FIELDS_AUTOPLACED_MANUAL );
}
virtual void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual ) { }
/**
* Function Plot
* plots the schematic item to \a aPlotter.

View File

@ -1387,7 +1387,7 @@ void SCH_PAINTER::draw( SCH_FIELD *aField, int aLayer )
}
/* Calculate the text justification, according to the component orientation/mirror.
* Tthis is a bit complicated due to cumulative calculations:
* This is a bit complicated due to cumulative calculations:
* - numerous cases (mirrored or not, rotation)
* - the DrawGraphicText function recalculate also H and H justifications according to the
* text orientation.
@ -1410,8 +1410,8 @@ void SCH_PAINTER::draw( SCH_FIELD *aField, int aLayer )
m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
boundaryBox.RevertYAxis();
m_gal->DrawRectangle(
mapCoords( boundaryBox.GetPosition() ), mapCoords( boundaryBox.GetEnd() ) );
m_gal->DrawRectangle( mapCoords( boundaryBox.GetPosition() ),
mapCoords( boundaryBox.GetEnd() ) );
}
else
{
@ -1424,7 +1424,7 @@ void SCH_PAINTER::draw( SCH_FIELD *aField, int aLayer )
m_gal->SetTextMirrored( aField->IsMirrored() );
strokeText( aField->GetFullyQualifiedText(), textpos,
orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
}
// Draw the umbilical line
@ -1511,7 +1511,7 @@ void SCH_PAINTER::draw( SCH_SHEET *aSheet, int aLayer )
{
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
if( aLayer == LAYER_HIERLABEL || drawingShadows )
if( aLayer == LAYER_HIERLABEL || aLayer == LAYER_SELECTION_SHADOWS )
{
for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
{
@ -1542,9 +1542,6 @@ void SCH_PAINTER::draw( SCH_SHEET *aSheet, int aLayer )
}
}
if( drawingShadows && !aSheet->IsSelected() )
return;
VECTOR2D pos = aSheet->GetPosition();
VECTOR2D size = aSheet->GetSize();
@ -1571,7 +1568,7 @@ void SCH_PAINTER::draw( SCH_SHEET *aSheet, int aLayer )
m_gal->DrawRectangle( pos, pos + size );
}
if( aLayer == LAYER_SHEET || drawingShadows )
if( aLayer == LAYER_SHEET || aLayer == LAYER_SELECTION_SHADOWS )
{
m_gal->SetStrokeColor( getRenderColor( aSheet, LAYER_SHEET, drawingShadows ) );
m_gal->SetIsStroke( true );
@ -1580,7 +1577,7 @@ void SCH_PAINTER::draw( SCH_SHEET *aSheet, int aLayer )
m_gal->DrawRectangle( pos, pos + size );
if( drawingShadows && !GetSelectionDrawChildItems() )
if( drawingShadows && !GetSelectionDrawChildItems() && aSheet->IsSelected() )
return;
for( SCH_FIELD& field : aSheet->GetFields() )

View File

@ -40,7 +40,7 @@
#include <pgm_base.h>
const wxString GetDefaultFieldName( int aFieldNdx )
const wxString SCH_SHEET::GetDefaultFieldName( int aFieldNdx )
{
static void* locale = nullptr;
static wxString sheetnameDefault;
@ -51,9 +51,9 @@ const wxString GetDefaultFieldName( int aFieldNdx )
// so only do it when necessary.
if( Pgm().GetLocale() != locale )
{
sheetnameDefault = _( "Sheet Name" );
sheetfilenameDefault = _( "Sheet Filename" );
fieldDefault = _( "Field" );
sheetnameDefault = _( "Sheet name" );
sheetfilenameDefault = _( "Sheet file" );
fieldDefault = _( "Field%d" );
locale = Pgm().GetLocale();
}
@ -426,43 +426,45 @@ int SCH_SHEET::GetPenSize() const
}
wxPoint SCH_SHEET::getSheetNamePosition()
{
wxSize textSize = m_fields[ SHEETNAME ].GetTextSize();
int margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.3 );
if( IsVerticalOrientation() )
return wxPoint( -margin, m_size.y );
else
return wxPoint( 0, -margin );
}
wxPoint SCH_SHEET::getFileNamePosition()
{
wxSize textSize = m_fields[ SHEETNAME ].GetTextSize();
int margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.4 );
if( IsVerticalOrientation() )
return wxPoint( m_size.x + margin, m_size.y );
else
return wxPoint( 0, m_size.y + margin );
}
void SCH_SHEET::AutoplaceFields( SCH_SCREEN* aScreen, bool aManual )
{
wxASSERT_MSG( !aManual, "manual autoplacement not currently supported for sheets" );
m_fields[ SHEETNAME ].SetTextPos( getSheetNamePosition() );
m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETNAME ].SetVertJustify(GR_TEXT_VJUSTIFY_BOTTOM );
m_fields[ SHEETNAME ].SetTextAngle( IsVerticalOrientation() ? 900 : 0 );
wxSize textSize = m_fields[ SHEETNAME ].GetTextSize();
int margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.5 );
m_fields[ SHEETFILENAME ].SetTextPos( getFileNamePosition() );
m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETFILENAME ].SetVertJustify(GR_TEXT_VJUSTIFY_TOP );
m_fields[ SHEETFILENAME ].SetTextAngle( IsVerticalOrientation() ? 900 : 0 );
if( IsVerticalOrientation() )
{
m_fields[ SHEETNAME ].SetTextPos( m_pos + wxPoint( -margin, m_size.y ) );
m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETNAME ].SetVertJustify(GR_TEXT_VJUSTIFY_BOTTOM );
m_fields[ SHEETNAME ].SetTextAngle( TEXT_ANGLE_VERT );
}
else
{
m_fields[ SHEETNAME ].SetTextPos( m_pos + wxPoint( 0, -margin ) );
m_fields[ SHEETNAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETNAME ].SetVertJustify(GR_TEXT_VJUSTIFY_BOTTOM );
m_fields[ SHEETNAME ].SetTextAngle( TEXT_ANGLE_HORIZ );
}
textSize = m_fields[ SHEETFILENAME ].GetTextSize();
margin = KiROUND( GetPenSize() / 2.0 + 4 + std::max( textSize.x, textSize.y ) * 0.4 );
if( IsVerticalOrientation() )
{
m_fields[ SHEETFILENAME ].SetTextPos( m_pos + wxPoint( m_size.x + margin, m_size.y ) );
m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETFILENAME ].SetVertJustify(GR_TEXT_VJUSTIFY_TOP );
m_fields[ SHEETFILENAME ].SetTextAngle( TEXT_ANGLE_VERT );
}
else
{
m_fields[ SHEETFILENAME ].SetTextPos( m_pos + wxPoint( 0, m_size.y + margin ) );
m_fields[ SHEETFILENAME ].SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
m_fields[ SHEETFILENAME ].SetVertJustify(GR_TEXT_VJUSTIFY_TOP );
m_fields[ SHEETFILENAME ].SetTextAngle( TEXT_ANGLE_HORIZ );
}
m_fieldsAutoplaced = FIELDS_AUTOPLACED_AUTO;
}
@ -496,7 +498,7 @@ void SCH_SHEET::Print( wxDC* aDC, const wxPoint& aOffset )
}
const EDA_RECT SCH_SHEET::GetBoundingBox() const
const EDA_RECT SCH_SHEET::GetBodyBoundingBox() const
{
wxPoint end;
EDA_RECT box( m_pos, m_size );
@ -513,8 +515,16 @@ const EDA_RECT SCH_SHEET::GetBoundingBox() const
box.SetEnd( end );
box.Inflate( lineWidth / 2 );
for( size_t i = 0; i < m_fields.size(); i++ )
box.Merge( m_fields[i].GetBoundingBox() );
return box;
}
const EDA_RECT SCH_SHEET::GetBoundingBox() const
{
EDA_RECT box = GetBodyBoundingBox();
for( const SCH_FIELD& field : m_fields )
box.Merge( field.GetBoundingBox() );
return box;
}
@ -659,17 +669,26 @@ void SCH_SHEET::Rotate(wxPoint aPosition)
m_size.y = -m_size.y;
}
for( SCH_FIELD& field : m_fields )
{
// Move the fields to the new position because the sheet itself has moved.
wxPoint pos = field.GetTextPos();
pos.x -= prev.x - m_pos.x;
pos.y -= prev.y - m_pos.y;
field.SetTextPos( pos );
}
// Pins must be rotated first as that's how we determine vertical vs horizontal
// orientation for auto-placement
for( SCH_SHEET_PIN* sheetPin : m_pins )
sheetPin->Rotate( aPosition );
if( m_fieldsAutoplaced == FIELDS_AUTOPLACED_AUTO )
{
AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
}
else
{
// Move the fields to the new position because the component itself has moved.
for( SCH_FIELD& field : m_fields )
{
wxPoint pos = field.GetTextPos();
pos.x -= prev.x - m_pos.x;
pos.y -= prev.y - m_pos.y;
field.SetTextPos( pos );
}
}
}
@ -783,6 +802,16 @@ SEARCH_RESULT SCH_SHEET::Visit( INSPECTOR aInspector, void* testData, const KICA
return SEARCH_RESULT::QUIT;
}
if( stype == SCH_LOCATE_ANY_T || stype == SCH_FIELD_T )
{
// Test the sheet fields.
for( SCH_FIELD& field : m_fields )
{
if( SEARCH_RESULT::QUIT == aInspector( &field, this ) )
return SEARCH_RESULT::QUIT;
}
}
if( stype == SCH_LOCATE_ANY_T || stype == SCH_SHEET_PIN_T )
{
// Test the sheet labels.
@ -812,7 +841,7 @@ BITMAP_DEF SCH_SHEET::GetMenuImage() const
bool SCH_SHEET::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
EDA_RECT rect = GetBoundingBox();
EDA_RECT rect = GetBodyBoundingBox();
rect.Inflate( aAccuracy );
@ -827,9 +856,9 @@ bool SCH_SHEET::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
rect.Inflate( aAccuracy );
if( aContained )
return rect.Contains( GetBoundingBox() );
return rect.Contains( GetBodyBoundingBox() );
return rect.Intersects( GetBoundingBox() );
return rect.Intersects( GetBodyBoundingBox() );
}

View File

@ -263,6 +263,16 @@ public:
std::vector<SCH_FIELD>& GetFields() { return m_fields; }
/**
* Set multiple schematic fields.
*
* @param aFields are the fields to set in this symbol.
*/
void SetFields( const std::vector<SCH_FIELD>& aFields )
{
m_fields = aFields; // vector copying, length is changed possibly
}
// JEY TODO: retite these once new dialog is implemented...
wxString GetName() const { return m_fields[ SHEETNAME ].GetText(); }
void SetName( const wxString& aName ) { m_fields[ SHEETNAME ].SetText( aName ); }
@ -411,7 +421,12 @@ public:
void Print( wxDC* aDC, const wxPoint& aOffset ) override;
EDA_RECT const GetBoundingBox() const override;
/**
* Return a bounding box for the sheet body but not the fields.
*/
const EDA_RECT GetBodyBoundingBox() const;
const EDA_RECT GetBoundingBox() const override;
/**
* Rotating around the boundingBox's center can cause walking when the sheetname or
@ -500,17 +515,7 @@ public:
*/
void Resize( const wxSize& aSize );
/**
* Return whether the fields have been automatically placed.
*/
FIELDS_AUTOPLACED GetFieldsAutoplaced() const { return m_fieldsAutoplaced; }
/**
* Set fields automatically placed flag false.
*/
void ClearFieldsAutoplaced() { m_fieldsAutoplaced = FIELDS_AUTOPLACED_NO; }
void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual );
void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual ) override;
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
@ -557,18 +562,9 @@ public:
void Show( int nestLevel, std::ostream& os ) const override;
#endif
static const wxString GetDefaultFieldName( int aFieldNdx );
protected:
/**
* @return the position of the anchor of sheet name text
*/
wxPoint getSheetNamePosition();
/**
* @return the position of the anchor of filename text
*/
wxPoint getFileNamePosition();
/**
* Renumber the sheet pins in the sheet.
*

View File

@ -175,20 +175,11 @@ void SCH_SHEET_PIN::ConstrainOnEdge( wxPoint Pos )
switch( sheetEdge.NearestSegment( Pos ) )
{
case 0:
SetEdge( SHEET_TOP_SIDE );
break;
case 1:
SetEdge( SHEET_RIGHT_SIDE );
break;
case 2:
SetEdge( SHEET_BOTTOM_SIDE );
break;
case 3:
SetEdge( SHEET_LEFT_SIDE );
break;
default:
wxASSERT( "Invalid segment number" );
case 0: SetEdge( SHEET_TOP_SIDE ); break;
case 1: SetEdge( SHEET_RIGHT_SIDE ); break;
case 2: SetEdge( SHEET_BOTTOM_SIDE ); break;
case 3: SetEdge( SHEET_LEFT_SIDE ); break;
default: wxASSERT( "Invalid segment number" );
}
switch( GetEdge() )
@ -257,16 +248,6 @@ void SCH_SHEET_PIN::Rotate( wxPoint aPosition )
{
wxPoint pt = GetTextPos();
RotatePoint( &pt, aPosition, 900 );
switch( m_edge )
{
case SHEET_LEFT_SIDE: SetEdge( SHEET_BOTTOM_SIDE ); break;
case SHEET_RIGHT_SIDE: SetEdge( SHEET_TOP_SIDE ); break;
case SHEET_TOP_SIDE: SetEdge( SHEET_LEFT_SIDE ); break;
case SHEET_BOTTOM_SIDE: SetEdge( SHEET_RIGHT_SIDE ); break;
default: break;
}
ConstrainOnEdge( pt );
}
@ -283,14 +264,9 @@ void SCH_SHEET_PIN::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wx
switch( m_shape )
{
case PINSHEETLABEL_SHAPE::PS_INPUT:
m_shape = PINSHEETLABEL_SHAPE::PS_OUTPUT;
break;
case PINSHEETLABEL_SHAPE::PS_OUTPUT:
m_shape = PINSHEETLABEL_SHAPE::PS_INPUT;
break;
default:
break;
case PINSHEETLABEL_SHAPE::PS_INPUT: m_shape = PINSHEETLABEL_SHAPE::PS_OUTPUT; break;
case PINSHEETLABEL_SHAPE::PS_OUTPUT: m_shape = PINSHEETLABEL_SHAPE::PS_INPUT; break;
default: break;
}
SCH_HIERLABEL::CreateGraphicShape( aPoints, aPos );

View File

@ -41,7 +41,7 @@
#include <tool/actions.h>
bool SCH_EDIT_FRAME::checkSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
bool SCH_EDIT_FRAME::CheckSheetForRecursion( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
{
wxASSERT( aSheet && aHierarchy );
@ -207,7 +207,7 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
SCH_SHEET_LIST hierarchy( g_RootSheet ); // This is the schematic sheet hierarchy.
SCH_SHEET_LIST sheetHierarchy( newSheet.get() ); // This is the hierarchy of the loaded file.
if( checkSheetForRecursion( newSheet.get(), aHierarchy )
if( CheckSheetForRecursion( newSheet.get(), aHierarchy )
|| checkForNoFullyDefinedLibIds( newSheet.get() ) )
return false;
@ -483,247 +483,11 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
return false;
// Get the new texts
DIALOG_SCH_SHEET_PROPS dlg( this, aSheet );
DIALOG_SCH_SHEET_PROPS dlg( this, aSheet, aClearAnnotationNewItems );
if( dlg.ShowModal() == wxID_CANCEL )
return false;
wxFileName fileName = dlg.GetFileName();
fileName.SetExt( SchematicFileExtension );
wxString msg;
bool renameFile = false;
bool loadFromFile = false;
bool clearAnnotation = false;
bool restoreSheet = false;
bool isExistingSheet = false;
SCH_SCREEN* useScreen = NULL;
// Relative file names are relative to the path of the current sheet. This allows for
// nesting of schematic files in subfolders.
if( !fileName.IsAbsolute() )
{
const SCH_SCREEN* currentScreen = aHierarchy->LastScreen();
wxCHECK_MSG( currentScreen, false, "Invalid sheet path object." );
wxFileName currentSheetFileName = currentScreen->GetFileName();
wxCHECK_MSG( fileName.Normalize( wxPATH_NORM_ALL, currentSheetFileName.GetPath() ), false,
"Cannot normalize new sheet schematic file path." );
}
wxString newFilename = fileName.GetFullPath();
// Search for a schematic file having the same filename already in use in the hierarchy
// or on disk, in order to reuse it.
if( !g_RootSheet->SearchHierarchy( newFilename, &useScreen ) )
{
loadFromFile = wxFileExists( newFilename );
wxLogDebug( "Sheet requested file \"%s\", %s",
newFilename,
( loadFromFile ) ? "found" : "not found" );
}
// Inside Eeschema, filenames are stored using unix notation
newFilename.Replace( wxT( "\\" ), wxT( "/" ) );
if( aSheet->GetScreen() == NULL ) // New sheet.
{
if( !allowCaseSensitiveFileNameClashes( newFilename ) )
return false;
if( useScreen || loadFromFile ) // Load from existing file.
{
clearAnnotation = true;
wxString existsMsg;
wxString linkMsg;
existsMsg.Printf( _( "\"%s\" already exists." ), fileName.GetFullName() );
linkMsg.Printf( _( "Link \"%s\" to this file?" ), dlg.GetSheetName() );
msg.Printf( wxT( "%s\n\n%s" ), existsMsg, linkMsg );
if( !IsOK( this, msg ) )
return false;
}
else // New file.
{
InitSheet( aSheet, newFilename );
}
}
else // Existing sheet.
{
bool isUndoable = true;
wxString replaceMsg;
wxString newMsg;
wxString noUndoMsg;
isExistingSheet = true;
if( !allowCaseSensitiveFileNameClashes( newFilename ) )
return false;
// Changing the filename of a sheet can modify the full hierarchy structure
// and can be not always undoable.
// So prepare messages for user notifications:
replaceMsg.Printf( _( "Change \"%s\" link from \"%s\" to \"%s\"?" ),
dlg.GetSheetName(),
aSheet->GetFileName(),
fileName.GetFullName() );
newMsg.Printf( _( "Create new file \"%s\" with contents of \"%s\"?" ),
fileName.GetFullName(),
aSheet->GetFileName() );
noUndoMsg = _( "This action cannot be undone." );
// We are always using here a case insensitive comparison
// to avoid issues under Windows, although under Unix
// filenames are case sensitive.
// But many users create schematic under both Unix and Windows
// **
// N.B. 1: aSheet->GetFileName() will return a relative path
// aSheet->GetScreen()->GetFileName() returns a full path
//
// N.B. 2: newFilename uses the unix notation for separator.
// so we must use it also to compare the old filename to the new filename
wxString oldFilename = aSheet->GetScreen()->GetFileName();
oldFilename.Replace( wxT( "\\" ), wxT( "/" ) );
if( newFilename.Cmp( oldFilename ) != 0 )
{
// Sheet file name changes cannot be undone.
isUndoable = false;
if( useScreen || loadFromFile ) // Load from existing file.
{
clearAnnotation = true;
msg.Printf( wxT( "%s\n\n%s" ), replaceMsg, noUndoMsg );
if( !IsOK( this, msg ) )
return false;
if( loadFromFile )
aSheet->SetScreen( NULL );
}
else // Save to new file name.
{
if( aSheet->GetScreenCount() > 1 )
{
msg.Printf( wxT( "%s\n\n%s" ), newMsg, noUndoMsg );
if( !IsOK( this, msg ) )
return false;
}
renameFile = true;
}
}
if( isUndoable )
SaveCopyInUndoList( aSheet, UR_CHANGED );
if( renameFile )
{
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
// If the the associated screen is shared by more than one sheet, do not
// change the filename of the corresponding screen here.
// (a new screen will be created later)
// if it is not shared, update the filename
if( aSheet->GetScreenCount() <= 1 )
aSheet->GetScreen()->SetFileName( newFilename );
try
{
pi->Save( newFilename, aSheet->GetScreen(), &Kiway() );
}
catch( const IO_ERROR& ioe )
{
msg.Printf( _( "Error occurred saving schematic file \"%s\"." ), newFilename );
DisplayErrorMessage( this, msg, ioe.What() );
msg.Printf( _( "Failed to save schematic \"%s\"" ), newFilename );
AppendMsgPanel( wxEmptyString, msg, CYAN );
return false;
}
// If the the associated screen is shared by more than one sheet, remove the
// screen and reload the file to a new screen. Failure to do this will trash
// the screen reference counting in complex hierarchies.
if( aSheet->GetScreenCount() > 1 )
{
aSheet->SetScreen( NULL );
loadFromFile = true;
}
}
}
wxFileName userFileName = dlg.GetFileName();
userFileName.SetExt( SchematicFileExtension );
if( useScreen )
{
// Create a temporary sheet for recursion testing to prevent a possible recursion error.
std::unique_ptr< SCH_SHEET> tmpSheet( new SCH_SHEET );
tmpSheet->SetName( dlg.GetSheetName() );
tmpSheet->SetFileName( userFileName.GetFullPath() );
tmpSheet->SetScreen( useScreen );
// No need to check for valid library IDs if we are using an existing screen.
if( checkSheetForRecursion( tmpSheet.get(), aHierarchy ) )
{
if( restoreSheet )
aHierarchy->LastScreen()->Append( aSheet );
return false;
}
// It's safe to set the sheet screen now.
aSheet->SetScreen( useScreen );
}
else if( loadFromFile )
{
if( isExistingSheet )
{
// Temporarily remove the sheet from the current schematic page so that recursion
// and symbol library link tests can be performed with the modified sheet settings.
restoreSheet = true;
aHierarchy->LastScreen()->Remove( aSheet );
}
if( !LoadSheetFromFile( aSheet, aHierarchy, newFilename )
|| checkSheetForRecursion( aSheet, aHierarchy ) )
{
if( restoreSheet )
aHierarchy->LastScreen()->Append( aSheet );
return false;
}
if( restoreSheet )
aHierarchy->LastScreen()->Append( aSheet );
}
wxString tmpFn = userFileName.GetFullPath();
if( wxFileName::GetPathSeparator() == '\\' )
tmpFn.Replace( "\\", "/" );
aSheet->SetFileName( tmpFn );
aSheet->SetName( dlg.GetSheetName() );
if( aSheet->GetName().IsEmpty() )
aSheet->SetName( wxT( "Untitled Sheet" ) );
if( aClearAnnotationNewItems )
*aClearAnnotationNewItems = clearAnnotation;
GetCanvas()->GetView()->Update( aSheet );
OnModify();
return true;
}
@ -870,7 +634,7 @@ void SCH_EDIT_FRAME::DrawCurrentSheetToClipboard()
}
bool SCH_EDIT_FRAME::allowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName )
bool SCH_EDIT_FRAME::AllowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName )
{
wxString msg;
SCH_SCREENS screens;

View File

@ -607,10 +607,18 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const KICAD_T aFilterList[] )
{
// Filter an existing selection
if( !m_selection.Empty() )
if( m_selection.Empty() )
{
for( int i = m_selection.GetSize() - 1; i >= 0; --i )
VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
ClearSelection();
SelectPoint( cursorPos, aFilterList );
m_selection.SetIsHover( true );
m_selection.ClearReferencePoint();
}
else // Trim an existing selection by aFilterList
{
for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
{
EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
@ -620,18 +628,6 @@ EE_SELECTION& EE_SELECTION_TOOL::RequestSelection( const KICAD_T aFilterList[] )
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
}
}
}
// If nothing was selected, or we filtered everything out, do a hover selection
if( m_selection.Empty() )
{
VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
ClearSelection();
SelectPoint( cursorPos, aFilterList );
m_selection.SetIsHover( true );
m_selection.ClearReferencePoint();
}
updateReferencePoint();

View File

@ -446,11 +446,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
field->SetTextAngle( TEXT_ANGLE_HORIZ );
// Now that we're moving a field, they're no longer autoplaced.
if( item->GetParent()->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* parent = static_cast<SCH_COMPONENT*>( item->GetParent() );
parent->ClearFieldsAutoplaced();
}
static_cast<SCH_ITEM*>( item->GetParent() )->ClearFieldsAutoplaced();
break;
}
@ -469,7 +465,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
// Rotate the sheet on itself. Sheets do not have an anchor point.
for( int i = 0; clockwise ? i < 1 : i < 3; ++i )
for( int i = 0; clockwise ? i < 3 : i < 1; ++i )
{
rotPoint = m_frame->GetNearestGridPosition( sheet->GetRotationCenter() );
sheet->Rotate( rotPoint );
@ -635,11 +631,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
field->SetHorizJustify( (EDA_TEXT_HJUSTIFY_T)-field->GetHorizJustify() );
// Now that we're re-justifying a field, they're no longer autoplaced.
if( item->GetParent()->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT *parent = static_cast<SCH_COMPONENT*>( item->GetParent() );
parent->ClearFieldsAutoplaced();
}
static_cast<SCH_ITEM*>( item->GetParent() )->ClearFieldsAutoplaced();
break;
}
@ -1065,13 +1057,11 @@ int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
}
void SCH_EDIT_TOOL::editComponentFieldText( SCH_FIELD* aField )
void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
// Save old component in undo list if not already in edit, or moving.
if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved
m_frame->SaveCopyInUndoList( component, UR_CHANGED );
m_frame->SaveCopyInUndoList( (SCH_ITEM*) aField->GetParent(), UR_CHANGED );
wxString title = wxString::Format( _( "Edit %s Field" ), aField->GetName() );
@ -1083,8 +1073,8 @@ void SCH_EDIT_TOOL::editComponentFieldText( SCH_FIELD* aField )
dlg.UpdateField( aField, g_CurrentSheet );
if( m_frame->GetAutoplaceFields() )
component->AutoAutoplaceFields( m_frame->GetScreen() );
if( m_frame->GetAutoplaceFields() || aField->GetParent()->Type() == SCH_SHEET_T )
static_cast<SCH_ITEM*>( aField->GetParent() )->AutoAutoplaceFields( m_frame->GetScreen() );
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
m_frame->RefreshItem( aField );
@ -1120,15 +1110,15 @@ int SCH_EDIT_TOOL::EditField( const TOOL_EVENT& aEvent )
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
if( aEvent.IsAction( &EE_ACTIONS::editReference ) )
editComponentFieldText( component->GetField( REFERENCE ) );
editFieldText( component->GetField( REFERENCE ) );
else if( aEvent.IsAction( &EE_ACTIONS::editValue ) )
editComponentFieldText( component->GetField( VALUE ) );
editFieldText( component->GetField( VALUE ) );
else if( aEvent.IsAction( &EE_ACTIONS::editFootprint ) )
editComponentFieldText( component->GetField( FOOTPRINT ) );
editFieldText( component->GetField( FOOTPRINT ) );
}
else if( item->Type() == SCH_FIELD_T )
{
editComponentFieldText( (SCH_FIELD*) item );
editFieldText( (SCH_FIELD*) item );
}
return 0;
@ -1288,7 +1278,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
break;
case SCH_FIELD_T:
editComponentFieldText( (SCH_FIELD*) item );
editFieldText( (SCH_FIELD*) item );
break;
case SCH_BITMAP_T:

View File

@ -69,7 +69,7 @@ public:
int DeleteItemCursor( const TOOL_EVENT& aEvent );
private:
void editComponentFieldText( SCH_FIELD* aField );
void editFieldText( SCH_FIELD* aField );
///> Sets up handlers for various events.
void setTransitions() override;

View File

@ -443,8 +443,11 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF
{
case SCH_FIELD_T:
case LIB_FIELD_T:
component = (SCH_COMPONENT*) item->GetParent();
m_frame->SendMessageToPCBNEW( item, component );
if( item->GetParent() && item->GetParent()->Type() == SCH_COMPONENT_T )
{
component = (SCH_COMPONENT*) item->GetParent();
m_frame->SendMessageToPCBNEW( item, component );
}
break;
case SCH_COMPONENT_T:

View File

@ -621,15 +621,22 @@ void SCH_MOVE_TOOL::moveItem( EDA_ITEM* aItem, VECTOR2I aDelta, bool isDrag )
case SCH_PIN_T:
case SCH_FIELD_T:
{
SCH_COMPONENT* component = (SCH_COMPONENT*) aItem->GetParent();
TRANSFORM transform = component->GetTransform().InverseTransform();
wxPoint transformedDelta = transform.TransformCoordinate( (wxPoint) aDelta );
SCH_ITEM* parent = (SCH_ITEM*) aItem->GetParent();
wxPoint delta( aDelta );
static_cast<SCH_ITEM*>( aItem )->Move( transformedDelta );
if( parent && parent->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) aItem->GetParent();
TRANSFORM transform = component->GetTransform().InverseTransform();
delta = transform.TransformCoordinate( delta );
}
static_cast<SCH_ITEM*>( aItem )->Move( delta );
// If we're moving a field with respect to its parent then it's no longer auto-placed
if( aItem->Type() == SCH_FIELD_T && !component->IsSelected() )
component->ClearFieldsAutoplaced();
if( aItem->Type() == SCH_FIELD_T && !parent->IsSelected() )
parent->ClearFieldsAutoplaced();
break;
}

View File

@ -131,14 +131,15 @@ protected:
class GRID_CELL_PATH_EDITOR : public GRID_CELL_TEXT_BUTTON
{
public:
GRID_CELL_PATH_EDITOR( DIALOG_SHIM* aParent, wxString* aCurrentDir ) :
GRID_CELL_PATH_EDITOR( DIALOG_SHIM* aParent, wxString* aCurrentDir, const wxString& aExt ) :
m_dlg( aParent ),
m_currentDir( aCurrentDir )
m_currentDir( aCurrentDir ),
m_ext( aExt )
{ }
wxGridCellEditor* Clone() const override
{
return new GRID_CELL_PATH_EDITOR( m_dlg, m_currentDir );
return new GRID_CELL_PATH_EDITOR( m_dlg, m_currentDir, m_ext );
}
void Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler ) override;
@ -146,6 +147,7 @@ public:
protected:
DIALOG_SHIM* m_dlg;
wxString* m_currentDir;
wxString m_ext;
};

View File

@ -389,7 +389,7 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
wxGridCellAttr* attr;
attr = new wxGridCellAttr;
attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, &m_lastBrowseDir ) );
attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, &m_lastBrowseDir, wxEmptyString ) );
g->SetColAttr( COL_URI, attr );
attr = new wxGridCellAttr;