39#include <wx/display.h>
40#include <wx/evtloop.h>
44#include <wx/propgrid/propgrid.h>
45#include <wx/checklst.h>
46#include <wx/dataview.h>
47#include <wx/bmpbuttn.h>
48#include <wx/textctrl.h>
49#include <wx/stc/stc.h>
50#include <wx/combobox.h>
51#include <wx/odcombo.h>
53#include <wx/checkbox.h>
54#include <wx/spinctrl.h>
55#include <wx/splitter.h>
56#include <wx/radiobox.h>
57#include <wx/radiobut.h>
58#include <wx/variant.h>
62#include <nlohmann/json.hpp>
78 std::string title = aTitle.ToStdString();
79 size_t parenPos = title.rfind(
'(' );
81 if( parenPos != std::string::npos && parenPos > 0 )
83 size_t end = parenPos;
85 while(
end > 0 && title[
end - 1] ==
' ' )
88 return title.substr( 0,
end );
96 const wxSize& size,
long style,
const wxString&
name ) :
97 wxDialog( aParent, id, title, pos, size, style,
name ),
120 while( !kiwayHolder && aParent->GetParent() )
122 aParent = aParent->GetParent();
136 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
137 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
139 if( toolMgr && toolMgr->IsContextMenuActive() )
140 toolMgr->VetoContextMenuMouseWarp();
148 Kiway().SetBlockingDialog(
this );
166 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
182 std::function<void( wxWindowList& )> disconnectFocusHandlers =
183 [&]( wxWindowList& children )
185 for( wxWindow* child : children )
187 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
192 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
199 disconnectFocusHandlers( child->GetChildren() );
204 disconnectFocusHandlers( GetChildren() );
206 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
207 [&]( wxWindowList& children )
209 for( wxWindow* child : children )
211 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
215 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
219 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
224 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
228 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
232 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
237 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
242 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
246 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
250 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
254 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
258 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
262 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
268 disconnectUndoRedoHandlers( child->GetChildren() );
273 disconnectUndoRedoHandlers( GetChildren() );
300 GetSizer()->SetSizeHints(
this );
307 SetSize( ConvertDialogToPixels( sz ) );
314 return ConvertDialogToPixels( sz ).x;
321 return ConvertDialogToPixels( sz ).y;
333 wxDialog::SetPosition( aNewPosition );
346 ret = wxDialog::Show( show );
348 wxRect savedDialogRect;
353 auto dlgIt = settings->m_dialogControlValues.find( key );
355 if( dlgIt != settings->m_dialogControlValues.end() )
357 auto geoIt = dlgIt->second.find(
"__geometry" );
359 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
361 const nlohmann::json& g = geoIt->second;
362 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
363 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
368 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
372 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
373 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
377 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
378 std::max( wxDialog::GetSize().x, savedDialogRect.GetSize().x ),
379 std::max( wxDialog::GetSize().y, savedDialogRect.GetSize().y ), 0 );
385 SetMinSize( wxDefaultSize );
386 InvalidateBestSize();
387 SetMinSize( GetBestSize() );
391 if( m_parent !=
nullptr )
393 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
394 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
408 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
421 m_eventLoop->Exit( GetReturnCode() );
424 ret = wxDialog::Show( show );
429 m_parent->SetFocus();
442 auto dlgIt = settings->m_dialogControlValues.find( key );
444 if( dlgIt == settings->m_dialogControlValues.end() )
447 dlgIt->second.erase(
"__geometry" );
466 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
467 int myDisplay = wxDisplay::GetFromWindow(
this );
469 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
494 return wxDialog::Enable( enable );
500 auto getSiblingIndex =
501 [](
const wxWindow* parent,
const wxWindow* child )
503 wxString childClass = child->GetClassInfo()->GetClassName();
506 for(
const wxWindow* sibling : parent->GetChildren() )
508 if( sibling->GetClassInfo()->GetClassName() != childClass )
511 if( sibling == child )
521 [&](
const wxWindow* window )
523 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
525 if( window->GetParent() )
526 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
531 std::string key =
makeKey( aWin );
533 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
550 wxRect rect( GetPosition(), GetSize() );
552 geom[
"x" ] = rect.GetX();
553 geom[
"y" ] = rect.GetY();
554 geom[
"w" ] = rect.GetWidth();
555 geom[
"h" ] = rect.GetHeight();
556 dlgMap[
"__geometry" ] = geom;
558 std::function<void( wxWindow* )> saveFn =
563 if( !props->GetPropertyOr(
"persist",
false ) )
575 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
577 dlgMap[ key ] = combo->GetValue();
579 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
581 dlgMap[ key ] = od_combo->GetSelection();
583 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
585 dlgMap[ key ] = textEntry->GetValue();
587 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
589 dlgMap[ key ] = choice->GetSelection();
591 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
593 dlgMap[ key ] = check->GetValue();
595 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
597 dlgMap[ key ] = spin->GetValue();
599 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
601 dlgMap[ key ] = radio->GetValue();
603 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
605 dlgMap[ key ] = radioBox->GetSelection();
607 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
609 dlgMap[ key ] = splitter->GetSashPosition();
611 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
613 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
615 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
617 int index = notebook->GetSelection();
619 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
620 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
622 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
624 int index = auiNotebook->GetSelection();
626 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
627 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
631 dlgMap[ key ] =
grid->GetShownColumnsAsString();
635 for( wxWindow* child : win->GetChildren() )
641 if( !props->GetPropertyOr(
"persist",
false ) )
645 for( wxWindow* child : GetChildren() )
663 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
665 std::function<void( wxWindow* )> loadFn =
670 if( !props->GetPropertyOr(
"persist",
false ) )
678 auto it = dlgMap.find( key );
680 if( it != dlgMap.end() )
682 const nlohmann::json& j = it->second;
686 if( j.is_number_integer() )
689 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
692 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
694 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
696 if( j.is_number_integer() )
698 int index = j.get<
int>();
700 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
701 od_combo->SetSelection(
index );
704 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
707 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
709 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
711 if( j.is_number_integer() )
713 int index = j.get<
int>();
715 if(
index >= 0 &&
index < (
int) choice->GetCount() )
716 choice->SetSelection(
index );
719 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
722 check->SetValue( j.get<
bool>() );
724 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
726 if( j.is_number_integer() )
727 spin->SetValue( j.get<
int>() );
729 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
737 radio->SetValue(
true );
740 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
742 if( j.is_number_integer() )
744 int index = j.get<
int>();
746 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
747 radioBox->SetSelection(
index );
750 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
752 if( j.is_number_integer() )
753 splitter->SetSashPosition( j.get<
int>() );
755 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
757 if( j.is_number_integer() )
758 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
760 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
764 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
766 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
768 if( notebook->GetPageText( page ) == pageTitle )
769 notebook->SetSelection( page );
773 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
777 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
779 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
781 if( auiNotebook->GetPageText( page ) == pageTitle )
782 auiNotebook->ChangeSelection( page );
789 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
794 for( wxWindow* child : win->GetChildren() )
800 if( !props->GetPropertyOr(
"persist",
false ) )
804 for( wxWindow* child : GetChildren() )
813 aWindow->SetClientData( props );
828 for( wxWindow* child : children )
830 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
839#if defined( __WXMAC__ ) || defined( __WXMSW__ )
840 if( !textCtrl->GetStringSelection().IsEmpty() )
844 else if( textCtrl->IsEditable() )
846 textCtrl->SelectAll();
852 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
855 scintilla->Connect( wxEVT_SET_FOCUS,
859 if( !scintilla->GetSelectedText().IsEmpty() )
863 else if( scintilla->GetMarginWidth( 0 ) > 0 )
867 else if( scintilla->IsEditable() )
869 scintilla->SelectAll();
875 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
878 wxRect rect = child->GetRect();
880 child->ConvertDialogToPixels(
minSize );
882 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
883 std::max( 0,
minSize.y - rect.GetHeight() ) );
885 child->SetMinSize( rect.GetSize() );
886 child->SetSize( rect );
899 for( wxWindow* child : children )
901 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
906 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
911 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
917 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
920 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
922 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
927 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
933 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
939 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
944 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
947 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
949 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
954 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
959 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
964 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
982 if( before != after )
1053 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1054 return wxVariant( textCtrl->GetValue() );
1055 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1056 return wxVariant( scintilla->GetText() );
1057 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1058 return wxVariant( combo->GetValue() );
1059 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1060 return wxVariant( (
long) choice->GetSelection() );
1061 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1062 return wxVariant( check->GetValue() );
1063 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1064 return wxVariant( (
long) spin->GetValue() );
1065 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1066 return wxVariant( spinD->GetValue() );
1067 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1068 return wxVariant( radio->GetValue() );
1069 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1070 return wxVariant( (
long) radioBox->GetSelection() );
1071 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1073 nlohmann::json j = nlohmann::json::array();
1074 int rows =
grid->GetNumberRows();
1075 int cols =
grid->GetNumberCols();
1077 for(
int r = 0; r < rows; ++r )
1079 nlohmann::json row = nlohmann::json::array();
1081 for(
int c = 0; c < cols; ++c )
1082 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1087 return wxVariant( wxString( j.dump() ) );
1089 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1093 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1095 wxPGProperty* prop = *it;
1096 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1099 return wxVariant( wxString( j.dump() ) );
1101 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1103 nlohmann::json j = nlohmann::json::array();
1104 unsigned int count = checkList->GetCount();
1106 for(
unsigned int i = 0; i < count; ++i )
1108 if( checkList->IsChecked( i ) )
1112 return wxVariant( wxString( j.dump() ) );
1114 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1116 nlohmann::json j = nlohmann::json::array();
1117 unsigned int rows = dataList->GetItemCount();
1118 unsigned int cols = dataList->GetColumnCount();
1120 for(
unsigned int r = 0; r < rows; ++r )
1122 nlohmann::json row = nlohmann::json::array();
1124 for(
unsigned int c = 0; c < cols; ++c )
1127 dataList->GetValue( val, r, c );
1128 row.push_back( std::string( val.GetString().ToUTF8() ) );
1134 return wxVariant( wxString( j.dump() ) );
1143 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1144 textCtrl->SetValue( aValue.GetString() );
1145 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1146 scintilla->SetText( aValue.GetString() );
1147 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1148 combo->SetValue( aValue.GetString() );
1149 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1150 choice->SetSelection( (
int) aValue.GetLong() );
1151 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1152 check->SetValue( aValue.GetBool() );
1153 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1154 spin->SetValue( (
int) aValue.GetLong() );
1155 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1156 spinD->SetValue( aValue.GetDouble() );
1157 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1158 radio->SetValue( aValue.GetBool() );
1159 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1160 radioBox->SetSelection( (
int) aValue.GetLong() );
1161 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1163 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1167 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1169 for(
int r = 0; r < rows; ++r )
1171 nlohmann::json row = j[r];
1172 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1174 for(
int c = 0; c < cols; ++c )
1175 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1179 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1181 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1185 for(
auto it = j.begin(); it != j.end(); ++it )
1186 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1189 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1191 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1195 unsigned int count = checkList->GetCount();
1197 for(
unsigned int i = 0; i < count; ++i )
1198 checkList->Check( i,
false );
1200 for(
auto& idx : j )
1202 unsigned int i = idx.get<
unsigned int>();
1205 checkList->Check( i,
true );
1209 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1211 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1215 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1216 static_cast<unsigned int>( dataList->GetItemCount() ) );
1218 for(
unsigned int r = 0; r < rows; ++r )
1220 nlohmann::json row = j[r];
1221 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1223 for(
unsigned int c = 0; c < cols; ++c )
1225 wxVariant val( wxString( row[c].get<std::string>() ) );
1226 dataList->SetValue( val, r, c );
1287 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1288 SetTitle( wxS(
"*" ) + GetTitle() );
1294 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1295 SetTitle( GetTitle().AfterFirst(
'*' ) );
1307 return wxDialog::ShowModal();
1343 if( wxWindow* win = wxWindow::GetCapture() )
1344 win->ReleaseMouse();
1347 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1364 wxGUIEventLoop event_loop;
1375 return GetReturnCode();
1397 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1400 SetReturnCode( retCode );
1404 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1427 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1445 const int id = aEvent.GetId();
1449 if(
id == GetAffirmativeId() )
1453 else if(
id == wxID_APPLY )
1462 else if(
id == wxID_CANCEL )
1485 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1487 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1497 int key = aEvt.GetKeyCode();
1500 if( aEvt.ControlDown() )
1502 if( aEvt.ShiftDown() )
1504 if( aEvt.AltDown() )
1507 int hotkey = key | mods;
1510 if( hotkey == (
MD_CTRL +
'Z') )
1521 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1530 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1532 wxObject* eventSource = aEvt.GetEventObject();
1534 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1537 if( !textCtrl->IsMultiLine() )
1539 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1543#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1544 wxString eol =
"\r\n";
1546 wxString eol =
"\n";
1549 long pos = textCtrl->GetInsertionPoint();
1550 textCtrl->WriteText( eol );
1551 textCtrl->SetInsertionPoint( pos + eol.length() );
1554 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1556 wxString eol =
"\n";
1558 switch( scintilla->GetEOLMode() )
1560 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1561 case wxSTC_EOL_CR: eol =
"\r";
break;
1562 case wxSTC_EOL_LF: eol =
"\n";
break;
1565 long pos = scintilla->GetCurrentPos();
1566 scintilla->InsertText( pos, eol );
1567 scintilla->GotoPos( pos + eol.length() );
1573 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1575 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1578 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1580 wxWindow* currentWindow = wxWindow::FindFocus();
1581 int currentIdx = -1;
1582 int delta = aEvt.ShiftDown() ? -1 : 1;
1589 idx = ( ( idx +
delta ) % size + size ) % size;
1592 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1597 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1599 currentIdx = (int) i;
1604 if( currentIdx >= 0 )
1606 advance( currentIdx );
1609 int startIdx = currentIdx;
1613 advance( currentIdx );
1615 if( currentIdx == startIdx )
1622 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1623 advance( currentIdx );
1630 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1632 wxObject* eventSource = aEvt.GetEventObject();
1634 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1640 textCtrl->SelectAll();
1644 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1650 scintilla->SelectAll();
1662 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1665 [&]( wxButton* aButton )
1667 if( aLabels.count( aButton->GetId() ) > 0 )
1669 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1675 switch( aButton->GetId() )
1677 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1678 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1679 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1680 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1681 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1682 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1683 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1684 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1691 if( sdbSizer->GetAffirmativeButton() )
1692 setupButton( sdbSizer->GetAffirmativeButton() );
1694 if( sdbSizer->GetApplyButton() )
1695 setupButton( sdbSizer->GetApplyButton() );
1697 if( sdbSizer->GetNegativeButton() )
1698 setupButton( sdbSizer->GetNegativeButton() );
1700 if( sdbSizer->GetCancelButton() )
1701 setupButton( sdbSizer->GetCancelButton() );
1703 if( sdbSizer->GetHelpButton() )
1704 setupButton( sdbSizer->GetHelpButton() );
1708 if( sdbSizer->GetAffirmativeButton() )
1709 sdbSizer->GetAffirmativeButton()->SetDefault();
1712 for( wxSizerItem* item : aSizer->GetChildren() )
1714 if( item->GetSizer() )
std::map< std::string, std::map< std::string, nlohmann::json > > m_dialogControlValues
Persistent dialog control values.
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::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 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)
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)
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 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.