37#include <wx/display.h>
38#include <wx/evtloop.h>
43#include <wx/propgrid/propgrid.h>
44#include <wx/checklst.h>
45#include <wx/dataview.h>
46#include <wx/bmpbuttn.h>
47#include <wx/textctrl.h>
48#include <wx/stc/stc.h>
49#include <wx/combobox.h>
50#include <wx/odcombo.h>
52#include <wx/checkbox.h>
53#include <wx/spinctrl.h>
54#include <wx/splitter.h>
55#include <wx/radiobox.h>
56#include <wx/radiobut.h>
57#include <wx/variant.h>
61#include <nlohmann/json.hpp>
77 std::string title = aTitle.ToStdString();
78 size_t parenPos = title.rfind(
'(' );
80 if( parenPos != std::string::npos && parenPos > 0 )
82 size_t end = parenPos;
84 while(
end > 0 && title[
end - 1] ==
' ' )
87 return title.substr( 0,
end );
95 const wxSize& size,
long style,
const wxString&
name ) :
96 wxDialog( aParent, id, title, pos, size, style,
name ),
119 while( !kiwayHolder && aParent->GetParent() )
121 aParent = aParent->GetParent();
135 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
136 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
138 if( toolMgr && toolMgr->IsContextMenuActive() )
139 toolMgr->VetoContextMenuMouseWarp();
147 Kiway().SetBlockingDialog(
this );
165 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
181 std::function<void( wxWindowList& )> disconnectFocusHandlers =
182 [&]( wxWindowList& children )
184 for( wxWindow* child : children )
186 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
191 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
198 disconnectFocusHandlers( child->GetChildren() );
203 disconnectFocusHandlers( GetChildren() );
205 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
206 [&]( wxWindowList& children )
208 for( wxWindow* child : children )
210 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
214 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
218 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
223 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
227 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
231 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
236 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
241 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
245 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
249 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
253 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
257 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
261 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
267 disconnectUndoRedoHandlers( child->GetChildren() );
272 disconnectUndoRedoHandlers( GetChildren() );
277 binder->DetachFromDialogShim();
296 if( wxSizer* sz = GetSizer() )
313 GetSizer()->SetSizeHints(
this );
320 SetSize( ConvertDialogToPixels( sz ) );
327 return ConvertDialogToPixels( sz ).x;
334 return ConvertDialogToPixels( sz ).y;
346 wxDialog::SetPosition( aNewPosition );
353 wxWindow* target = toolCanvas ? toolCanvas : m_parent;
360 if( !aDeferUntilFrameActive || !toolCanvas )
396 ret = wxDialog::Show( show );
398 wxRect savedDialogRect;
403 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
405 if( dlgIt != settings->CsInternals().m_dialogControlValues.end() )
407 auto geoIt = dlgIt->second.find(
"__geometry" );
409 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
411 const nlohmann::json& g = geoIt->second;
412 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
413 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
418 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
421 wxSize restoredSize = FromDIP( savedDialogRect.GetSize() );
425 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
426 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
430 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
431 std::max( wxDialog::GetSize().x, restoredSize.x ),
432 std::max( wxDialog::GetSize().y, restoredSize.y ), 0 );
438 SetMinSize( wxDefaultSize );
439 InvalidateBestSize();
440 SetMinSize( GetBestSize() );
444 if( m_parent !=
nullptr )
446 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
447 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
461 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
474 m_eventLoop->Exit( GetReturnCode() );
477 ret = wxDialog::Show( show );
493 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
495 if( dlgIt == settings->CsInternals().m_dialogControlValues.end() )
498 dlgIt->second.erase(
"__geometry" );
517 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
518 int myDisplay = wxDisplay::GetFromWindow(
this );
520 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
545 return wxDialog::Enable( enable );
551 auto getSiblingIndex =
552 [](
const wxWindow* parent,
const wxWindow* child )
554 wxString childClass = child->GetClassInfo()->GetClassName();
557 for(
const wxWindow* sibling : parent->GetChildren() )
559 if( sibling->GetClassInfo()->GetClassName() != childClass )
562 if( sibling == child )
572 [&](
const wxWindow* window )
574 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
576 if( window->GetParent() )
577 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
582 std::string key =
makeKey( aWin );
584 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
601 wxPoint pos = GetPosition();
602 wxSize dipSize = ToDIP( GetSize() );
606 geom[
"w" ] = dipSize.x;
607 geom[
"h" ] = dipSize.y;
608 dlgMap[
"__geometry" ] = geom;
610 std::function<void( wxWindow* )> saveFn =
615 if( !props->GetPropertyOr(
"persist",
false ) )
627 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
629 dlgMap[ key ] = combo->GetValue();
631 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
633 dlgMap[ key ] = od_combo->GetSelection();
635 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
637 dlgMap[ key ] = textEntry->GetValue();
639 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
641 dlgMap[ key ] = choice->GetSelection();
643 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
645 dlgMap[ key ] = check->GetValue();
647 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
649 dlgMap[ key ] = spin->GetValue();
651 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
653 dlgMap[ key ] = radio->GetValue();
655 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
657 dlgMap[ key ] = radioBox->GetSelection();
659 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
661 dlgMap[ key ] = splitter->GetSashPosition();
663 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
665 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
667 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
669 int index = notebook->GetSelection();
671 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
672 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
674 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
676 int index = auiNotebook->GetSelection();
678 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
679 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
683 dlgMap[ key ] =
grid->GetShownColumnsAsString();
687 for( wxWindow* child : win->GetChildren() )
693 if( !props->GetPropertyOr(
"persist",
false ) )
697 for( wxWindow* child : GetChildren() )
715 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
717 std::function<void( wxWindow* )> loadFn =
722 if( !props->GetPropertyOr(
"persist",
false ) )
730 auto it = dlgMap.find( key );
732 if( it != dlgMap.end() )
734 const nlohmann::json& j = it->second;
738 if( j.is_number_integer() )
742 else if( j.is_string() )
744 if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
745 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
748 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
751 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
753 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
755 if( j.is_number_integer() )
757 int index = j.get<
int>();
759 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
760 od_combo->SetSelection(
index );
763 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
766 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
768 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
770 if( j.is_number_integer() )
772 int index = j.get<
int>();
774 if(
index >= 0 &&
index < (
int) choice->GetCount() )
775 choice->SetSelection(
index );
778 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
781 check->SetValue( j.get<
bool>() );
783 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
785 if( j.is_number_integer() )
786 spin->SetValue( j.get<
int>() );
788 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
796 radio->SetValue(
true );
799 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
801 if( j.is_number_integer() )
803 int index = j.get<
int>();
805 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
806 radioBox->SetSelection(
index );
809 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
811 if( j.is_number_integer() )
812 splitter->SetSashPosition( j.get<
int>() );
814 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
816 if( j.is_number_integer() )
817 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
819 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
823 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
825 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
827 if( notebook->GetPageText( page ) == pageTitle )
828 notebook->ChangeSelection( page );
832 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
836 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
838 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
840 if( auiNotebook->GetPageText( page ) == pageTitle )
841 auiNotebook->ChangeSelection( page );
848 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
853 for( wxWindow* child : win->GetChildren() )
859 if( !props->GetPropertyOr(
"persist",
false ) )
863 for( wxWindow* child : GetChildren() )
872 aWindow->SetClientData( props );
893 [aUnitBinder](
const auto& aEntry )
895 return aEntry.second == aUnitBinder;
905 for( wxWindow* child : children )
907 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
916#if defined( __WXMAC__ ) || defined( __WXMSW__ )
917 if( !textCtrl->GetStringSelection().IsEmpty() )
921 else if( textCtrl->IsEditable() )
923 textCtrl->SelectAll();
929 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
932 scintilla->Connect( wxEVT_SET_FOCUS,
936 if( !scintilla->GetSelectedText().IsEmpty() )
940 else if( scintilla->GetMarginWidth( 0 ) > 0 )
944 else if( scintilla->IsEditable() )
946 scintilla->SelectAll();
952 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
955 wxRect rect = child->GetRect();
957 child->ConvertDialogToPixels(
minSize );
959 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
960 std::max( 0,
minSize.y - rect.GetHeight() ) );
962 child->SetMinSize( rect.GetSize() );
963 child->SetSize( rect );
976 for( wxWindow* child : children )
981 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
986 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
991 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
997 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
1000 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
1002 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
1007 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
1013 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
1019 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
1024 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
1027 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
1029 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
1034 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
1039 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
1044 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
1062 if( before != after )
1064 m_undoStack.push_back( { aCtrl, before, after } );
1133 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1134 return wxVariant( textCtrl->GetValue() );
1135 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1136 return wxVariant( scintilla->GetText() );
1137 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1138 return wxVariant( combo->GetValue() );
1139 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1140 return wxVariant( (
long) choice->GetSelection() );
1141 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1142 return wxVariant( check->GetValue() );
1143 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1144 return wxVariant( (
long) spin->GetValue() );
1145 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1146 return wxVariant( spinD->GetValue() );
1147 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1148 return wxVariant( radio->GetValue() );
1149 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1150 return wxVariant( (
long) radioBox->GetSelection() );
1151 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1155 table &&
table->HasUndoStateSerialization() )
1157 return wxVariant(
table->SerializeUndoState() );
1160 nlohmann::json j = nlohmann::json::array();
1161 int rows =
grid->GetNumberRows();
1162 int cols =
grid->GetNumberCols();
1164 for(
int r = 0; r < rows; ++r )
1166 nlohmann::json row = nlohmann::json::array();
1168 for(
int c = 0; c < cols; ++c )
1169 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1174 return wxVariant( wxString( j.dump() ) );
1176 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1180 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1182 wxPGProperty* prop = *it;
1183 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1186 return wxVariant( wxString( j.dump() ) );
1188 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1190 nlohmann::json j = nlohmann::json::array();
1191 unsigned int count = checkList->GetCount();
1193 for(
unsigned int i = 0; i < count; ++i )
1195 if( checkList->IsChecked( i ) )
1199 return wxVariant( wxString( j.dump() ) );
1201 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1203 nlohmann::json j = nlohmann::json::array();
1204 unsigned int rows = dataList->GetItemCount();
1205 unsigned int cols = dataList->GetColumnCount();
1207 for(
unsigned int r = 0; r < rows; ++r )
1209 nlohmann::json row = nlohmann::json::array();
1211 for(
unsigned int c = 0; c < cols; ++c )
1214 dataList->GetValue( val, r, c );
1215 row.push_back( std::string( val.GetString().ToUTF8() ) );
1221 return wxVariant( wxString( j.dump() ) );
1230 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1231 textCtrl->SetValue( aValue.GetString() );
1232 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1233 scintilla->SetText( aValue.GetString() );
1234 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1235 combo->SetValue( aValue.GetString() );
1236 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1237 choice->SetSelection( (
int) aValue.GetLong() );
1238 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1239 check->SetValue( aValue.GetBool() );
1240 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1241 spin->SetValue( (
int) aValue.GetLong() );
1242 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1243 spinD->SetValue( aValue.GetDouble() );
1244 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1245 radio->SetValue( aValue.GetBool() );
1246 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1247 radioBox->SetSelection( (
int) aValue.GetLong() );
1248 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1251 table &&
table->HasUndoStateSerialization() )
1253 table->RestoreUndoState( aValue.GetString() );
1257 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1261 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1263 for(
int r = 0; r < rows; ++r )
1265 nlohmann::json row = j[r];
1266 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1268 for(
int c = 0; c < cols; ++c )
1269 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1273 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1275 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1279 for(
auto it = j.begin(); it != j.end(); ++it )
1280 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1283 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1285 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1289 unsigned int count = checkList->GetCount();
1291 for(
unsigned int i = 0; i < count; ++i )
1292 checkList->Check( i,
false );
1294 for(
auto& idx : j )
1296 unsigned int i = idx.get<
unsigned int>();
1299 checkList->Check( i,
true );
1303 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1305 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1309 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1310 static_cast<unsigned int>( dataList->GetItemCount() ) );
1312 for(
unsigned int r = 0; r < rows; ++r )
1314 nlohmann::json row = j[r];
1315 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1317 for(
unsigned int c = 0; c < cols; ++c )
1319 wxVariant val( wxString( row[c].get<std::string>() ) );
1320 dataList->SetValue( val, r, c );
1381 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1382 SetTitle( wxS(
"*" ) + GetTitle() );
1388 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1389 SetTitle( GetTitle().AfterFirst(
'*' ) );
1403 return wxDialog::ShowModal();
1439 if( wxWindow* win = wxWindow::GetCapture() )
1440 win->ReleaseMouse();
1443 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1460 wxGUIEventLoop event_loop;
1469 return GetReturnCode();
1491 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1494 SetReturnCode( retCode );
1498 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1532 for( wxWindow* child : aWindow->GetChildren() )
1539 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1557 const int id = aEvent.GetId();
1561 if(
id == GetAffirmativeId() )
1565 else if(
id == wxID_APPLY )
1574 else if(
id == wxID_CANCEL )
1597 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1599 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1609 int key = aEvt.GetKeyCode();
1612 if( aEvt.ControlDown() )
1614 if( aEvt.ShiftDown() )
1616 if( aEvt.AltDown() )
1619 int hotkey = key | mods;
1622 if( hotkey == (
MD_CTRL +
'Z') )
1633 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1642 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1644 wxObject* eventSource = aEvt.GetEventObject();
1646 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1649 if( !textCtrl->IsMultiLine() )
1651 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1655#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1656 wxString eol =
"\r\n";
1658 wxString eol =
"\n";
1661 long pos = textCtrl->GetInsertionPoint();
1662 textCtrl->WriteText( eol );
1663 textCtrl->SetInsertionPoint( pos + eol.length() );
1666 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1668 wxString eol =
"\n";
1670 switch( scintilla->GetEOLMode() )
1672 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1673 case wxSTC_EOL_CR: eol =
"\r";
break;
1674 case wxSTC_EOL_LF: eol =
"\n";
break;
1677 long pos = scintilla->GetCurrentPos();
1678 scintilla->InsertText( pos, eol );
1679 scintilla->GotoPos( pos + eol.length() );
1685 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1687 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1690 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1692 wxWindow* currentWindow = wxWindow::FindFocus();
1693 int currentIdx = -1;
1694 int delta = aEvt.ShiftDown() ? -1 : 1;
1701 idx = ( ( idx +
delta ) % size + size ) % size;
1704 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1709 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1711 currentIdx = (int) i;
1716 if( currentIdx >= 0 )
1718 advance( currentIdx );
1721 int startIdx = currentIdx;
1725 advance( currentIdx );
1727 if( currentIdx == startIdx )
1734 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1735 advance( currentIdx );
1742 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1744 wxObject* eventSource = aEvt.GetEventObject();
1746 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1752 textCtrl->SelectAll();
1756 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1762 scintilla->SelectAll();
1774 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1777 [&]( wxButton* aButton )
1779 if( aLabels.count( aButton->GetId() ) > 0 )
1781 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1787 switch( aButton->GetId() )
1789 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1790 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1791 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1792 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1793 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1794 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1795 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1796 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1803 if( sdbSizer->GetAffirmativeButton() )
1804 setupButton( sdbSizer->GetAffirmativeButton() );
1806 if( sdbSizer->GetApplyButton() )
1807 setupButton( sdbSizer->GetApplyButton() );
1809 if( sdbSizer->GetNegativeButton() )
1810 setupButton( sdbSizer->GetNegativeButton() );
1812 if( sdbSizer->GetCancelButton() )
1813 setupButton( sdbSizer->GetCancelButton() );
1815 if( sdbSizer->GetHelpButton() )
1816 setupButton( sdbSizer->GetHelpButton() );
1820 if( sdbSizer->GetAffirmativeButton() )
1821 sdbSizer->GetAffirmativeButton()->SetDefault();
1824 for( wxSizerItem* item : aSizer->GetChildren() )
1826 if( item->GetSizer() )
COMMON_SETTINGS_INTERNALS & CsInternals()
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
void SelectAllInTextCtrls(wxWindowList &children)
wxVariant getControlValue(wxWindow *aCtrl)
void onPropertyGridChanged(wxPropertyGridEvent &aEvent)
std::set< wxWindow * > m_noControlUndoRedo
std::vector< wxWindow * > m_tabOrder
void OnPaint(wxPaintEvent &event)
virtual void TearDownQuasiModal()
Override this method to perform dialog tear down actions not suitable for object dtor.
void recordControlChange(wxWindow *aCtrl)
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
bool Show(bool show) override
std::vector< UNDO_STEP > m_redoStack
void setControlValue(wxWindow *aCtrl, const wxVariant &aValue)
wxGUIEventLoop * m_qmodal_loop
void onChildSetFocus(wxFocusEvent &aEvent)
void LoadControlState()
Load persisted control values from the current project's local settings.
void ExcludeFromControlUndoRedo(wxWindow *aWindow)
Opt a control out of the dialog's generic Ctrl+Z/Ctrl+Y undo/redo.
void UnregisterUnitBinder(UNIT_BINDER *aUnitBinder)
Remove a UNIT_BINDER from the control-state save/restore map.
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SaveControlState()
Save control values and geometry to the current project's local settings.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
WINDOW_DISABLER * m_qmodal_parent_disabler
void onInitDialog(wxInitDialogEvent &aEvent)
void onSpinDoubleEvent(wxSpinDoubleEvent &aEvent)
void resetUndoRedoForNewContent(wxWindowList &aChildren)
Reset undo/redo tracking after dynamically replacing child panels.
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void resetSize()
Clear the existing dialog size and position.
std::map< wxWindow *, wxString > m_beforeEditValues
void setSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
void onDataViewListChanged(wxDataViewEvent &aEvent)
void unregisterUnitBinders(wxWindow *aWindow)
Remove UNIT_BINDER registrations for a window and all its descendants.
bool IsQuasiModal() const
std::map< wxWindow *, UNIT_BINDER * > m_unitBinders
void EndQuasiModal(int retCode)
void RegisterUnitBinder(UNIT_BINDER *aUnitBinder, wxWindow *aWindow)
Register a UNIT_BINDER so that it can handle units in control-state save/restore.
void OnMove(wxMoveEvent &aEvent)
void onCommandEvent(wxCommandEvent &aEvent)
void CleanupAfterModalSubDialog()
std::string generateKey(const wxWindow *aWin) const
void PrepareForModalSubDialog()
void OnButton(wxCommandEvent &aEvent)
Properly handle the default button events when in the quasimodal mode when not calling EndQuasiModal ...
void onGridCellChanged(wxGridEvent &aEvent)
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void registerUndoRedoHandlers(wxWindowList &aChildren)
wxWindow * m_initialFocusTarget
void OnSize(wxSizeEvent &aEvent)
bool Enable(bool enable) override
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
void focusParentCanvas(bool aDeferUntilFrameActive=false)
Set focus back to the parent frame's tool canvas if available, otherwise to the parent window.
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
void onSpinEvent(wxSpinEvent &aEvent)
void OnCloseWindow(wxCloseEvent &aEvent)
Properly handle the wxCloseEvent when in the quasimodal mode when not calling EndQuasiModal which is ...
std::map< wxWindow *, wxVariant > m_currentValues
EDA_BASE_FRAME * m_parentFrame
virtual void OnCharHook(wxKeyEvent &aEvt)
std::vector< UNDO_STEP > m_undoStack
void onStyledTextChanged(wxStyledTextEvent &aEvent)
The base frame for deriving all KiCad main window classes.
KIWAY_HOLDER(KIWAY *aKiway, HOLDER_TYPE aType)
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
bool HasKiway() const
Safety check before asking for the Kiway reference.
HOLDER_TYPE GetType() const
void SetBlockingDialog(wxWindow *aWin)
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
bool SetProperty(const std::string &aKey, T &&aValue)
Set a property with the given key and value.
static PROPERTY_HOLDER * SafeCast(void *aPtr) noexcept
Safely cast a void pointer to PROPERTY_HOLDER*.
EDA_UNITS GetUserUnits() const
Temporarily disable a window, and then re-enable on destruction.
static std::string getDialogKeyFromTitle(const wxString &aTitle)
Strip parenthetical suffixes from dialog titles to create stable persistence keys.
static void recursiveDescent(wxSizer *aSizer, std::map< int, wxString > &aLabels)
const int minSize
Push and Shove router track width and via size dialog.
void ignore_unused(const T &)
void AddNavigationBreadcrumb(const wxString &aMsg, const wxString &aCategory)
Add a navigation breadcrumb.
static wxString makeKey(const wxString &aFirst, const wxString &aSecond)
Assemble a two part key as a simple concatenation of aFirst and aSecond parts, using a separator.
PGM_BASE & Pgm()
The global program "get" accessor.
std::map< std::string, std::map< std::string, nlohmann::json > > m_dialogControlValues
static const long long MM
std::vector< std::vector< std::string > > table