2011-10-27 13:34:28 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2015-04-26 16:32:16 +00:00
|
|
|
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
2018-02-20 21:01:52 +00:00
|
|
|
* Copyright (C) 2004-2018 KiCad Developers, see change_log.txt for contributors.
|
2011-10-27 13:34:28 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file sheet.cpp
|
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
2018-08-03 12:18:26 +00:00
|
|
|
#include <sch_draw_panel.h>
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <confirm.h>
|
2015-06-07 20:31:55 +00:00
|
|
|
#include <kiface_i.h>
|
2017-11-17 17:00:04 +00:00
|
|
|
#include <project.h>
|
|
|
|
#include <wildcards_and_files_ext.h>
|
2009-02-04 15:25:03 +00:00
|
|
|
|
2018-01-30 10:49:51 +00:00
|
|
|
#include <sch_edit_frame.h>
|
2017-11-17 17:00:04 +00:00
|
|
|
#include <sch_legacy_plugin.h>
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <sch_sheet.h>
|
2015-06-07 20:31:55 +00:00
|
|
|
#include <sch_sheet_path.h>
|
2018-08-03 12:18:26 +00:00
|
|
|
#include <sch_view.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <dialogs/dialog_sch_sheet_props.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
|
2018-10-24 19:37:32 +00:00
|
|
|
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
|
|
|
bool* aClearAnnotationNewItems )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2015-06-07 20:31:55 +00:00
|
|
|
if( aSheet == NULL || aHierarchy == NULL )
|
2009-12-15 21:11:05 +00:00
|
|
|
return false;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2016-03-06 21:22:01 +00:00
|
|
|
SCH_SHEET_LIST hierarchy( g_RootSheet ); // This is the schematic sheet hierarchy.
|
2015-06-07 20:31:55 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
// Get the new texts
|
2018-02-02 15:56:09 +00:00
|
|
|
DIALOG_SCH_SHEET_PROPS dlg( this, aSheet );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
wxFileName fileName = dlg.GetFileName();
|
|
|
|
fileName.SetExt( SchematicFileExtension );
|
|
|
|
|
|
|
|
wxString msg;
|
|
|
|
bool loadFromFile = false;
|
2018-04-18 00:07:51 +00:00
|
|
|
bool clearAnnotation = false;
|
2011-01-20 16:34:57 +00:00
|
|
|
SCH_SCREEN* useScreen = NULL;
|
|
|
|
|
2018-02-05 14:01:55 +00:00
|
|
|
// 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." );
|
|
|
|
}
|
|
|
|
|
2014-11-02 13:17:48 +00:00
|
|
|
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.
|
2018-02-05 14:01:55 +00:00
|
|
|
if( !g_RootSheet->SearchHierarchy( newFilename, &useScreen ) )
|
2014-11-02 13:17:48 +00:00
|
|
|
{
|
2017-11-17 17:00:04 +00:00
|
|
|
loadFromFile = wxFileExists( newFilename );
|
2018-02-02 15:56:09 +00:00
|
|
|
wxLogDebug( "Sheet requested file \"%s\", %s",
|
|
|
|
newFilename,
|
|
|
|
( loadFromFile ) ? "found" : "not found" );
|
2014-11-02 13:17:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Inside Eeschema, filenames are stored using unix notation
|
2015-06-07 20:31:55 +00:00
|
|
|
newFilename.Replace( wxT( "\\" ), wxT( "/" ) );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
2017-11-17 17:00:04 +00:00
|
|
|
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
|
|
|
|
|
2015-06-07 20:31:55 +00:00
|
|
|
if( aSheet->GetScreen() == NULL ) // New sheet.
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2014-11-02 13:17:48 +00:00
|
|
|
if( useScreen || loadFromFile ) // Load from existing file.
|
2011-01-20 16:34:57 +00:00
|
|
|
{
|
2018-04-18 00:07:51 +00:00
|
|
|
clearAnnotation = true;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2018-04-18 00:07:51 +00:00
|
|
|
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 );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
|
|
|
if( !IsOK( this, msg ) )
|
|
|
|
return false;
|
2018-04-18 00:07:51 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
}
|
|
|
|
else // New file.
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
Modular KiCad Blueprint Milestone B), major portions:
*) When kicad.exe closes a project, close any open KIFACEs so that they cannot
get disassociated from their true PROJECT.
*) Allow loading eeschema library editor from kicad.exe
*) Allow loading pcbnew library editor from kicad.exe
*) Rename LIB_COMPONENT to LIB_PART.
*) Add class PART_LIBS, and PART_LIB.
*) Make PART_LIBS non-global, i.e. PROJECT specific.
*) Implement "data on demand" for PART_LIBS
*) Implement "data on demand" for schematic SEARCH_STACK.
*) Use RSTRINGs to retain eeschema editor's notion of last library and part being edited.
*) Get rid of library search on every SCH_COMPONENT::Draw() call, instead use
a weak pointer.
*) Remove all chdir() calls so projects don't need to be CWD.
*) Romove APPEND support from OpenProjectFiles().
*) Make OpenProjectFiles() robust, even for creating new projects.
*) Load EESCHEMA colors in the KIWAY::OnKiwayStart() rather in window open,
and save them in the .eeschema config file, not in the project file.
*) Fix bug with wxDir() while accessing protected dirs in kicad.exe
*) Consolidate template copying into PROJECT class, not in kicad.exe source.
*) Generally untangle eeschema, making its libraries not global but rather
held in the PROJECT.
2014-08-13 20:28:54 +00:00
|
|
|
aSheet->SetScreen( new SCH_SCREEN( &Kiway() ) );
|
2017-12-04 21:43:34 +00:00
|
|
|
aSheet->GetScreen()->SetModify();
|
2015-08-06 00:10:52 +00:00
|
|
|
aSheet->GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax );
|
2014-11-02 13:17:48 +00:00
|
|
|
aSheet->GetScreen()->SetFileName( newFilename );
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
}
|
|
|
|
else // Existing sheet.
|
|
|
|
{
|
|
|
|
bool isUndoable = true;
|
|
|
|
bool renameFile = false;
|
2018-04-18 00:07:51 +00:00
|
|
|
wxString replaceMsg;
|
|
|
|
wxString newMsg;
|
|
|
|
wxString noUndoMsg;
|
|
|
|
|
2018-06-23 14:54:51 +00:00
|
|
|
// Changing the filename of a sheet can modify the full hierarchy structure
|
|
|
|
// and can be not always undoable.
|
|
|
|
// So prepare messages for user notifications:
|
2018-04-18 00:07:51 +00:00
|
|
|
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." );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
2012-10-13 18:54:33 +00:00
|
|
|
// 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
|
2018-03-29 20:48:14 +00:00
|
|
|
// **
|
2018-06-23 14:54:51 +00:00
|
|
|
// 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.CmpNoCase( oldFilename ) != 0 )
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2011-01-20 16:34:57 +00:00
|
|
|
// Sheet file name changes cannot be undone.
|
|
|
|
isUndoable = false;
|
|
|
|
|
2015-06-07 20:31:55 +00:00
|
|
|
if( useScreen || loadFromFile ) // Load from existing file.
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2018-04-18 00:07:51 +00:00
|
|
|
clearAnnotation = true;
|
2015-06-07 20:31:55 +00:00
|
|
|
|
2018-04-18 00:07:51 +00:00
|
|
|
msg.Printf( wxT( "%s\n\n%s" ), replaceMsg, noUndoMsg );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
|
|
|
if( !IsOK( this, msg ) )
|
|
|
|
return false;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
if( loadFromFile )
|
|
|
|
aSheet->SetScreen( NULL );
|
|
|
|
}
|
|
|
|
else // Save to new file name.
|
|
|
|
{
|
|
|
|
if( aSheet->GetScreenCount() > 1 )
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2018-04-18 00:07:51 +00:00
|
|
|
msg.Printf( wxT( "%s\n\n%s" ), newMsg, noUndoMsg );
|
2009-12-15 21:11:05 +00:00
|
|
|
|
2018-04-18 00:07:51 +00:00
|
|
|
if( !IsOK( this, msg ) )
|
2011-01-20 16:34:57 +00:00
|
|
|
return false;
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
|
|
|
|
renameFile = true;
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
}
|
2010-11-20 21:59:00 +00:00
|
|
|
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->SetIgnoreMouseEvents( true );
|
2009-12-15 21:11:05 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
if( isUndoable )
|
|
|
|
SaveCopyInUndoList( aSheet, UR_CHANGED );
|
2009-12-15 21:11:05 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
if( renameFile )
|
|
|
|
{
|
2018-05-29 17:57:18 +00:00
|
|
|
// 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 );
|
2017-11-17 17:00:04 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pi->Save( newFilename, aSheet->GetScreen(), &Kiway() );
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
2017-12-15 11:37:46 +00:00
|
|
|
msg.Printf( _( "Error occurred saving schematic file \"%s\"." ), newFilename );
|
2017-11-17 17:00:04 +00:00
|
|
|
DisplayErrorMessage( this, msg, ioe.What() );
|
|
|
|
|
2017-12-15 11:37:46 +00:00
|
|
|
msg.Printf( _( "Failed to save schematic \"%s\"" ), newFilename );
|
2017-11-17 17:00:04 +00:00
|
|
|
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2009-12-15 21:11:05 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
// 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 )
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2011-01-20 16:34:57 +00:00
|
|
|
aSheet->SetScreen( NULL );
|
|
|
|
loadFromFile = true;
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
|
2018-02-05 14:01:55 +00:00
|
|
|
wxFileName userFileName = dlg.GetFileName();
|
2018-02-20 21:01:52 +00:00
|
|
|
userFileName.SetExt( SchematicFileExtension );
|
2018-02-05 14:01:55 +00:00
|
|
|
aSheet->SetFileName( userFileName.GetFullPath( wxPATH_UNIX ) );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
|
|
|
if( useScreen )
|
2017-11-17 17:00:04 +00:00
|
|
|
{
|
2011-01-20 16:34:57 +00:00
|
|
|
aSheet->SetScreen( useScreen );
|
2017-11-17 17:00:04 +00:00
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
else if( loadFromFile )
|
2017-11-17 17:00:04 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
aSheet = pi->Load( newFilename, &Kiway(), aSheet );
|
2017-12-07 00:10:45 +00:00
|
|
|
|
|
|
|
if( !pi->GetError().IsEmpty() )
|
|
|
|
{
|
|
|
|
DisplayErrorMessage( this,
|
2018-02-02 15:56:09 +00:00
|
|
|
_( "The entire schematic could not be loaded.\n"
|
|
|
|
"Errors occurred loading hierarchical sheets." ),
|
2017-12-07 00:10:45 +00:00
|
|
|
pi->GetError() );
|
|
|
|
}
|
2017-11-17 17:00:04 +00:00
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
2017-12-15 11:37:46 +00:00
|
|
|
msg.Printf( _( "Error occurred loading schematic file \"%s\"." ), newFilename );
|
2017-11-17 17:00:04 +00:00
|
|
|
DisplayErrorMessage( this, msg, ioe.What() );
|
|
|
|
|
2017-12-15 11:37:46 +00:00
|
|
|
msg.Printf( _( "Failed to load schematic \"%s\"" ), newFilename );
|
2017-11-17 17:00:04 +00:00
|
|
|
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-01-20 16:34:57 +00:00
|
|
|
|
2018-02-02 15:56:09 +00:00
|
|
|
aSheet->SetFileNameSize( dlg.GetFileNameTextSize() );
|
2011-12-08 15:45:01 +00:00
|
|
|
aSheet->SetName( dlg.GetSheetName() );
|
2018-02-02 15:56:09 +00:00
|
|
|
aSheet->SetSheetNameSize( dlg.GetSheetNameTextSize() );
|
2011-01-20 16:34:57 +00:00
|
|
|
|
2011-12-08 15:45:01 +00:00
|
|
|
if( aSheet->GetName().IsEmpty() )
|
2015-04-23 19:43:45 +00:00
|
|
|
aSheet->SetName( wxString::Format( wxT( "Sheet%8.8lX" ),
|
|
|
|
(long unsigned) aSheet->GetTimeStamp() ) );
|
2009-06-11 14:26:17 +00:00
|
|
|
|
2015-06-07 20:31:55 +00:00
|
|
|
// Make sure the sheet changes do not cause any recursion.
|
2016-02-15 20:12:42 +00:00
|
|
|
SCH_SHEET_LIST sheetHierarchy( aSheet );
|
2015-06-07 20:31:55 +00:00
|
|
|
|
|
|
|
// Make sure files have fully qualified path and file name.
|
2016-02-15 20:12:42 +00:00
|
|
|
wxFileName destFn = aHierarchy->Last()->GetFileName();
|
2015-06-07 20:31:55 +00:00
|
|
|
|
|
|
|
if( destFn.IsRelative() )
|
|
|
|
destFn.MakeAbsolute( Prj().GetProjectPath() );
|
|
|
|
|
2016-02-15 20:12:42 +00:00
|
|
|
if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
|
2015-06-07 20:31:55 +00:00
|
|
|
{
|
|
|
|
msg.Printf( _( "The sheet changes cannot be made because the destination sheet already "
|
2017-12-15 11:37:46 +00:00
|
|
|
"has the sheet \"%s\" or one of it's subsheets as a parent somewhere in "
|
2015-06-07 20:31:55 +00:00
|
|
|
"the schematic hierarchy." ),
|
2017-11-17 17:00:04 +00:00
|
|
|
newFilename );
|
2015-06-07 20:31:55 +00:00
|
|
|
DisplayError( this, msg );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-17 17:00:04 +00:00
|
|
|
// Check to make sure the symbols have been remapped to the symbol library table.
|
|
|
|
SCH_SCREENS newScreens( aSheet );
|
|
|
|
|
|
|
|
if( newScreens.HasNoFullyDefinedLibIds() )
|
|
|
|
{
|
2018-10-24 19:37:32 +00:00
|
|
|
msg.Printf(_( "The schematic \"%s\" has not been remapped to the symbol\nlibrary table. "
|
|
|
|
" The project this schematic belongs to must first be remapped\nbefore it "
|
|
|
|
"can be imported into the current project." ), fileName.GetFullName() );
|
2017-11-17 17:00:04 +00:00
|
|
|
|
2018-10-24 19:37:32 +00:00
|
|
|
DisplayInfoMessage( this, msg );
|
|
|
|
return false;
|
2017-11-17 17:00:04 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 10:11:39 +00:00
|
|
|
if( aClearAnnotationNewItems )
|
|
|
|
*aClearAnnotationNewItems = clearAnnotation;
|
2018-04-18 00:07:51 +00:00
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->MoveCursorToCrossHair();
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->SetIgnoreMouseEvents( false );
|
2018-08-03 12:18:26 +00:00
|
|
|
|
|
|
|
GetCanvas()->GetView()->Update( aSheet );
|
|
|
|
|
2011-10-27 13:34:28 +00:00
|
|
|
OnModify();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-01-20 16:34:57 +00:00
|
|
|
return true;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-15 21:11:05 +00:00
|
|
|
/* Move selected sheet with the cursor.
|
2015-02-28 16:56:09 +00:00
|
|
|
* Callback function used by m_mouseCaptureCallback.
|
2017-10-23 13:35:03 +00:00
|
|
|
* Note also now this function is called only when resizing the sheet
|
2015-02-28 16:56:09 +00:00
|
|
|
* But the (very small code) relative to sheet move is still present here
|
2008-02-29 12:33:07 +00:00
|
|
|
*/
|
2015-02-28 16:56:09 +00:00
|
|
|
static void resizeSheetWithMouseCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
|
2015-06-07 20:31:55 +00:00
|
|
|
bool aErase )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2009-12-15 21:11:05 +00:00
|
|
|
BASE_SCREEN* screen = aPanel->GetScreen();
|
2017-10-23 13:35:03 +00:00
|
|
|
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( screen->GetCurItem() );
|
|
|
|
|
|
|
|
if( sheet == nullptr ) // Be sure we are using the right object
|
|
|
|
return;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-12-08 15:45:01 +00:00
|
|
|
wxPoint pos = sheet->GetPosition();
|
|
|
|
|
2017-08-23 16:06:33 +00:00
|
|
|
int width = aPanel->GetParent()->GetCrossHairPosition().x - pos.x;
|
|
|
|
int height = aPanel->GetParent()->GetCrossHairPosition().y - pos.y;
|
2011-06-07 15:29:01 +00:00
|
|
|
|
2015-02-28 16:56:09 +00:00
|
|
|
// If the sheet doesn't have any pins, clamp the minimum size to the default values.
|
|
|
|
width = ( width < MIN_SHEET_WIDTH ) ? MIN_SHEET_WIDTH : width;
|
|
|
|
height = ( height < MIN_SHEET_HEIGHT ) ? MIN_SHEET_HEIGHT : height;
|
2011-06-07 15:29:01 +00:00
|
|
|
|
2015-02-28 16:56:09 +00:00
|
|
|
if( sheet->HasPins() )
|
2008-02-28 20:39:04 +00:00
|
|
|
{
|
2015-02-28 16:56:09 +00:00
|
|
|
int gridSizeX = KiROUND( screen->GetGridSize().x );
|
|
|
|
int gridSizeY = KiROUND( screen->GetGridSize().y );
|
|
|
|
|
2017-08-23 16:06:33 +00:00
|
|
|
// If the sheet has pins, use the pin positions to clamp the minimum width and height.
|
2015-02-28 16:56:09 +00:00
|
|
|
height = ( height < sheet->GetMinHeight() + gridSizeY ) ?
|
|
|
|
sheet->GetMinHeight() + gridSizeY : height;
|
|
|
|
width = ( width < sheet->GetMinWidth() + gridSizeX ) ?
|
|
|
|
sheet->GetMinWidth() + gridSizeX : width;
|
2008-02-28 20:39:04 +00:00
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2015-02-28 16:56:09 +00:00
|
|
|
wxPoint grid = aPanel->GetParent()->GetNearestGridPosition(
|
|
|
|
wxPoint( pos.x + width, pos.y + height ) );
|
|
|
|
sheet->Resize( wxSize( grid.x - pos.x, grid.y - pos.y ) );
|
|
|
|
|
2018-08-03 12:18:26 +00:00
|
|
|
auto panel = static_cast<SCH_DRAW_PANEL*>( aPanel );
|
|
|
|
auto view = panel->GetView();
|
2018-10-23 16:16:23 +00:00
|
|
|
|
|
|
|
view->Hide( sheet );
|
2018-08-03 12:18:26 +00:00
|
|
|
view->ClearPreview();
|
2018-10-23 16:16:23 +00:00
|
|
|
view->AddToPreview( sheet->Clone() );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
// Complete sheet move.
|
2011-01-21 19:30:59 +00:00
|
|
|
static void ExitSheet( EDA_DRAW_PANEL* aPanel, wxDC* aDC )
|
2008-04-14 19:22:48 +00:00
|
|
|
{
|
2009-12-15 21:11:05 +00:00
|
|
|
SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen();
|
2013-08-05 21:02:41 +00:00
|
|
|
SCH_ITEM* item = screen->GetCurItem();
|
|
|
|
|
Modular-Kicad milestone B), major portions:
*) Rework the set language support, simplify it by using KIWAY. Now any major
frame with a "change language" menu can change the language for all KIWAY_PLAYERs
in the whole KIWAY. Multiple KIWAYs are not supported yet.
*) Simplify "modal wxFrame" support, and add that support exclusively to
KIWAY_PLAYER where it is inherited by all derivatives. The function
KIWAY_PLAYER::ShowModal() is in the vtable and so is cross module capable.
*) Remove the requirements and assumptions that the wxFrame hierarchy always
had PCB_EDIT_FRAME and SCH_EDIT_FRAME as immediate parents of their viewers
and editors. This is no longer the case, nor required.
*) Use KIWAY::Player() everywhere to make KIWAY_PLAYERs, this registers the
KIWAY_PLAYER within the KIWAY and makes it very easy to find an open frame
quickly. It also gives control to the KIWAY as to frame hierarchical
relationships.
*) Change single_top to use the KIWAY for loading a KIFACE and instantiating
the single KIWAY_PLAYER, see bullet immediately above.
*) Add KIWAY::OnKiwayEnd() and call it from PGM_BASE at program termination, this
gives the KIFACEs a chance to save their final configuration dope to disk.
*) Add dedicated FRAME_T's for the modal frames, so m_Ident can be tested and
these modal frames are distinctly different than their non-modal equivalents.
KIWAY_PLAYER::IsModal() is !not! a valid test during the wxFrame's constructor,
so this is another important reason for having a dedicated FRAME_T for each
modal wxFrame.
On balance, more lines were deleted than were added to achieve all this.
2014-05-03 17:40:19 +00:00
|
|
|
SCH_EDIT_FRAME* parent = (SCH_EDIT_FRAME*) aPanel->GetParent();
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-06-07 15:29:01 +00:00
|
|
|
if( (item == NULL) || (item->Type() != SCH_SHEET_T) || (parent == NULL) )
|
2009-12-15 21:11:05 +00:00
|
|
|
return;
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-06-07 15:29:01 +00:00
|
|
|
parent->SetRepeatItem( NULL );
|
|
|
|
|
|
|
|
if( item->IsNew() )
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2013-04-28 14:28:13 +00:00
|
|
|
delete item;
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
2011-07-08 19:55:41 +00:00
|
|
|
else if( item->IsMoving() || item->IsResized() )
|
2009-12-15 21:11:05 +00:00
|
|
|
{
|
2018-08-03 12:18:26 +00:00
|
|
|
parent->RemoveFromScreen( item );
|
2011-06-07 15:29:01 +00:00
|
|
|
delete item;
|
|
|
|
|
|
|
|
item = parent->GetUndoItem();
|
|
|
|
|
|
|
|
wxCHECK_RET( item != NULL, wxT( "Cannot restore undefined last sheet item." ) );
|
|
|
|
|
2018-08-03 12:18:26 +00:00
|
|
|
parent->AddToScreen( item );
|
|
|
|
|
2011-06-16 19:52:12 +00:00
|
|
|
// the owner of item is no more parent, this is the draw list of screen:
|
2011-06-07 15:29:01 +00:00
|
|
|
parent->SetUndoItem( NULL );
|
2011-06-16 19:52:12 +00:00
|
|
|
|
2011-06-07 15:29:01 +00:00
|
|
|
item->ClearFlags();
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-07 15:29:01 +00:00
|
|
|
item->ClearFlags();
|
2009-12-15 21:11:05 +00:00
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2018-08-03 12:18:26 +00:00
|
|
|
auto panel = static_cast<SCH_DRAW_PANEL*>( aPanel );
|
|
|
|
auto view = panel->GetView();
|
|
|
|
view->ClearPreview();
|
|
|
|
|
2009-12-15 21:11:05 +00:00
|
|
|
screen->SetCurItem( NULL );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-05 21:02:41 +00:00
|
|
|
// Create hierarchy sheet.
|
2010-12-08 20:12:46 +00:00
|
|
|
SCH_SHEET* SCH_EDIT_FRAME::CreateSheet( wxDC* aDC )
|
2008-04-14 19:22:48 +00:00
|
|
|
{
|
2013-08-05 21:02:41 +00:00
|
|
|
SetRepeatItem( NULL );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2013-08-03 05:15:23 +00:00
|
|
|
SCH_SHEET* sheet = new SCH_SHEET( GetCrossHairPosition() );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-04-05 14:46:51 +00:00
|
|
|
sheet->SetFlags( IS_NEW | IS_RESIZED );
|
2011-12-12 08:37:05 +00:00
|
|
|
sheet->SetTimeStamp( GetNewTimeStamp() );
|
2016-02-15 20:13:27 +00:00
|
|
|
sheet->SetParent( GetScreen() );
|
2011-01-20 16:34:57 +00:00
|
|
|
sheet->SetScreen( NULL );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
// need to check if this is being added to the GetDrawItems().
|
2009-12-15 21:11:05 +00:00
|
|
|
// also need to update the hierarchy, if we are adding
|
2008-02-26 19:19:54 +00:00
|
|
|
// a sheet to a screen that already has multiple instances (!)
|
2009-12-15 21:11:05 +00:00
|
|
|
GetScreen()->SetCurItem( sheet );
|
2015-02-28 16:56:09 +00:00
|
|
|
m_canvas->SetMouseCapture( resizeSheetWithMouseCursor, ExitSheet );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->CrossHairOff( aDC );
|
2013-08-03 05:15:23 +00:00
|
|
|
|
|
|
|
SetCrossHairPosition( sheet->GetResizePosition() );
|
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->MoveCursorToCrossHair();
|
|
|
|
m_canvas->CrossHairOn( aDC );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-12-15 21:11:05 +00:00
|
|
|
return sheet;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-08 20:12:46 +00:00
|
|
|
void SCH_EDIT_FRAME::ReSizeSheet( SCH_SHEET* aSheet, wxDC* aDC )
|
2008-04-14 19:22:48 +00:00
|
|
|
{
|
2011-02-21 13:54:29 +00:00
|
|
|
if( aSheet == NULL || aSheet->IsNew() )
|
2007-08-20 01:20:48 +00:00
|
|
|
return;
|
|
|
|
|
2011-06-07 15:29:01 +00:00
|
|
|
wxCHECK_RET( aSheet->Type() == SCH_SHEET_T,
|
|
|
|
wxString::Format( wxT( "Cannot perform sheet resize on %s object." ),
|
|
|
|
GetChars( aSheet->GetClass() ) ) );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->CrossHairOff( aDC );
|
2013-08-03 05:15:23 +00:00
|
|
|
SetCrossHairPosition( aSheet->GetResizePosition() );
|
2011-12-22 13:28:11 +00:00
|
|
|
m_canvas->MoveCursorToCrossHair();
|
|
|
|
m_canvas->CrossHairOn( aDC );
|
2011-07-08 19:55:41 +00:00
|
|
|
|
2011-06-07 15:29:01 +00:00
|
|
|
SetUndoItem( aSheet );
|
|
|
|
aSheet->SetFlags( IS_RESIZED );
|
2009-12-15 21:11:05 +00:00
|
|
|
|
2015-02-28 16:56:09 +00:00
|
|
|
m_canvas->SetMouseCapture( resizeSheetWithMouseCursor, ExitSheet );
|
2011-12-29 20:11:42 +00:00
|
|
|
m_canvas->CallMouseCapture( aDC, wxDefaultPosition, true );
|
2010-03-24 18:26:04 +00:00
|
|
|
|
2011-02-21 13:54:29 +00:00
|
|
|
if( aSheet->IsNew() ) // not already in edit, save a copy for undo/redo
|
2011-04-05 14:46:51 +00:00
|
|
|
SetUndoItem( aSheet );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2015-06-07 20:31:55 +00:00
|
|
|
|
2015-04-26 16:32:16 +00:00
|
|
|
void SCH_EDIT_FRAME::RotateHierarchicalSheet( SCH_SHEET* aSheet, bool aRotCCW )
|
|
|
|
{
|
|
|
|
if( aSheet == NULL )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Save old sheet in undo list if not already in edit, or moving.
|
|
|
|
if( aSheet->GetFlags() == 0 )
|
|
|
|
SaveCopyInUndoList( aSheet, UR_CHANGED );
|
|
|
|
|
|
|
|
// Rotate the sheet on itself. Sheets do not have a anchor point.
|
|
|
|
// Rotation is made around it center
|
|
|
|
wxPoint rotPoint = aSheet->GetBoundingBox().Centre();
|
|
|
|
|
2018-04-16 08:39:34 +00:00
|
|
|
// Keep this rotation point on the grid, otherwise all items of this sheet
|
|
|
|
// will be moved off grid
|
|
|
|
rotPoint = GetNearestGridPosition( rotPoint );
|
|
|
|
|
2015-04-26 16:32:16 +00:00
|
|
|
// rotate CCW, or CW. to rotate CW, rotate 3 times
|
|
|
|
aSheet->Rotate( rotPoint );
|
|
|
|
|
|
|
|
if( !aRotCCW )
|
|
|
|
{
|
|
|
|
aSheet->Rotate( rotPoint );
|
|
|
|
aSheet->Rotate( rotPoint );
|
|
|
|
}
|
|
|
|
|
2018-08-03 12:18:26 +00:00
|
|
|
GetCanvas()->GetView()->Update( aSheet );
|
2015-04-26 16:32:16 +00:00
|
|
|
OnModify();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SCH_EDIT_FRAME::MirrorSheet( SCH_SHEET* aSheet, bool aFromXaxis )
|
|
|
|
{
|
|
|
|
if( aSheet == NULL )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Save old sheet in undo list if not already in edit, or moving.
|
|
|
|
if( aSheet->GetFlags() == 0 )
|
|
|
|
SaveCopyInUndoList( aSheet, UR_CHANGED );
|
|
|
|
|
|
|
|
// Mirror the sheet on itself. Sheets do not have a anchor point.
|
|
|
|
// Mirroring is made around it center
|
|
|
|
wxPoint mirrorPoint = aSheet->GetBoundingBox().Centre();
|
|
|
|
|
|
|
|
if( aFromXaxis ) // mirror relative to Horizontal axis
|
|
|
|
aSheet->MirrorX( mirrorPoint.y );
|
|
|
|
else // Mirror relative to vertical axis
|
|
|
|
aSheet->MirrorY( mirrorPoint.x );
|
|
|
|
|
2018-08-03 12:18:26 +00:00
|
|
|
GetCanvas()->GetView()->Update( aSheet );
|
2015-04-26 16:32:16 +00:00
|
|
|
OnModify();
|
|
|
|
}
|