41#include <wx/display.h>
42#include <wx/evtloop.h>
46#include <wx/propgrid/propgrid.h>
47#include <wx/checklst.h>
48#include <wx/dataview.h>
49#include <wx/bmpbuttn.h>
50#include <wx/textctrl.h>
51#include <wx/stc/stc.h>
52#include <wx/combobox.h>
53#include <wx/odcombo.h>
55#include <wx/checkbox.h>
56#include <wx/spinctrl.h>
57#include <wx/splitter.h>
58#include <wx/radiobox.h>
59#include <wx/radiobut.h>
60#include <wx/variant.h>
64#include <nlohmann/json.hpp>
80 std::string title = aTitle.ToStdString();
81 size_t parenPos = title.rfind(
'(' );
83 if( parenPos != std::string::npos && parenPos > 0 )
85 size_t end = parenPos;
87 while(
end > 0 && title[
end - 1] ==
' ' )
90 return title.substr( 0,
end );
98 const wxSize& size,
long style,
const wxString&
name ) :
99 wxDialog( aParent, id, title, pos, size, style,
name ),
122 while( !kiwayHolder && aParent->GetParent() )
124 aParent = aParent->GetParent();
138 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
139 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
141 if( toolMgr && toolMgr->IsContextMenuActive() )
142 toolMgr->VetoContextMenuMouseWarp();
150 Kiway().SetBlockingDialog(
this );
168 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
184 std::function<void( wxWindowList& )> disconnectFocusHandlers =
185 [&]( wxWindowList& children )
187 for( wxWindow* child : children )
189 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
194 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
201 disconnectFocusHandlers( child->GetChildren() );
206 disconnectFocusHandlers( GetChildren() );
208 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
209 [&]( wxWindowList& children )
211 for( wxWindow* child : children )
213 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
217 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
221 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
226 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
230 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
234 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
239 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
244 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
248 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
252 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
256 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
260 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
264 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
270 disconnectUndoRedoHandlers( child->GetChildren() );
275 disconnectUndoRedoHandlers( GetChildren() );
302 GetSizer()->SetSizeHints(
this );
309 SetSize( ConvertDialogToPixels( sz ) );
316 return ConvertDialogToPixels( sz ).x;
323 return ConvertDialogToPixels( sz ).y;
335 wxDialog::SetPosition( aNewPosition );
353 m_parent->SetFocus();
366 ret = wxDialog::Show( show );
368 wxRect savedDialogRect;
373 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
375 if( dlgIt != settings->CsInternals().m_dialogControlValues.end() )
377 auto geoIt = dlgIt->second.find(
"__geometry" );
379 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
381 const nlohmann::json& g = geoIt->second;
382 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
383 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
388 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
391 wxSize restoredSize = FromDIP( savedDialogRect.GetSize() );
395 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
396 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
400 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
401 std::max( wxDialog::GetSize().x, restoredSize.x ),
402 std::max( wxDialog::GetSize().y, restoredSize.y ), 0 );
408 SetMinSize( wxDefaultSize );
409 InvalidateBestSize();
410 SetMinSize( GetBestSize() );
414 if( m_parent !=
nullptr )
416 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
417 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
431 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
444 m_eventLoop->Exit( GetReturnCode() );
447 ret = wxDialog::Show( show );
463 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
465 if( dlgIt == settings->CsInternals().m_dialogControlValues.end() )
468 dlgIt->second.erase(
"__geometry" );
487 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
488 int myDisplay = wxDisplay::GetFromWindow(
this );
490 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
515 return wxDialog::Enable( enable );
521 auto getSiblingIndex =
522 [](
const wxWindow* parent,
const wxWindow* child )
524 wxString childClass = child->GetClassInfo()->GetClassName();
527 for(
const wxWindow* sibling : parent->GetChildren() )
529 if( sibling->GetClassInfo()->GetClassName() != childClass )
532 if( sibling == child )
542 [&](
const wxWindow* window )
544 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
546 if( window->GetParent() )
547 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
552 std::string key =
makeKey( aWin );
554 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
571 wxPoint pos = GetPosition();
572 wxSize dipSize = ToDIP( GetSize() );
576 geom[
"w" ] = dipSize.x;
577 geom[
"h" ] = dipSize.y;
578 dlgMap[
"__geometry" ] = geom;
580 std::function<void( wxWindow* )> saveFn =
585 if( !props->GetPropertyOr(
"persist",
false ) )
597 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
599 dlgMap[ key ] = combo->GetValue();
601 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
603 dlgMap[ key ] = od_combo->GetSelection();
605 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
607 dlgMap[ key ] = textEntry->GetValue();
609 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
611 dlgMap[ key ] = choice->GetSelection();
613 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
615 dlgMap[ key ] = check->GetValue();
617 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
619 dlgMap[ key ] = spin->GetValue();
621 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
623 dlgMap[ key ] = radio->GetValue();
625 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
627 dlgMap[ key ] = radioBox->GetSelection();
629 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
631 dlgMap[ key ] = splitter->GetSashPosition();
633 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
635 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
637 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
639 int index = notebook->GetSelection();
641 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
642 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
644 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
646 int index = auiNotebook->GetSelection();
648 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
649 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
653 dlgMap[ key ] =
grid->GetShownColumnsAsString();
657 for( wxWindow* child : win->GetChildren() )
663 if( !props->GetPropertyOr(
"persist",
false ) )
667 for( wxWindow* child : GetChildren() )
685 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
687 std::function<void( wxWindow* )> loadFn =
692 if( !props->GetPropertyOr(
"persist",
false ) )
700 auto it = dlgMap.find( key );
702 if( it != dlgMap.end() )
704 const nlohmann::json& j = it->second;
708 if( j.is_number_integer() )
711 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
714 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
716 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
718 if( j.is_number_integer() )
720 int index = j.get<
int>();
722 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
723 od_combo->SetSelection(
index );
726 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
729 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
731 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
733 if( j.is_number_integer() )
735 int index = j.get<
int>();
737 if(
index >= 0 &&
index < (
int) choice->GetCount() )
738 choice->SetSelection(
index );
741 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
744 check->SetValue( j.get<
bool>() );
746 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
748 if( j.is_number_integer() )
749 spin->SetValue( j.get<
int>() );
751 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
759 radio->SetValue(
true );
762 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
764 if( j.is_number_integer() )
766 int index = j.get<
int>();
768 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
769 radioBox->SetSelection(
index );
772 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
774 if( j.is_number_integer() )
775 splitter->SetSashPosition( j.get<
int>() );
777 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
779 if( j.is_number_integer() )
780 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
782 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
786 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
788 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
790 if( notebook->GetPageText( page ) == pageTitle )
791 notebook->ChangeSelection( page );
795 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
799 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
801 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
803 if( auiNotebook->GetPageText( page ) == pageTitle )
804 auiNotebook->ChangeSelection( page );
811 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
816 for( wxWindow* child : win->GetChildren() )
822 if( !props->GetPropertyOr(
"persist",
false ) )
826 for( wxWindow* child : GetChildren() )
835 aWindow->SetClientData( props );
850 for( wxWindow* child : children )
852 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
861#if defined( __WXMAC__ ) || defined( __WXMSW__ )
862 if( !textCtrl->GetStringSelection().IsEmpty() )
866 else if( textCtrl->IsEditable() )
868 textCtrl->SelectAll();
874 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
877 scintilla->Connect( wxEVT_SET_FOCUS,
881 if( !scintilla->GetSelectedText().IsEmpty() )
885 else if( scintilla->GetMarginWidth( 0 ) > 0 )
889 else if( scintilla->IsEditable() )
891 scintilla->SelectAll();
897 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
900 wxRect rect = child->GetRect();
902 child->ConvertDialogToPixels(
minSize );
904 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
905 std::max( 0,
minSize.y - rect.GetHeight() ) );
907 child->SetMinSize( rect.GetSize() );
908 child->SetSize( rect );
921 for( wxWindow* child : children )
923 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
928 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
933 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
939 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
942 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
944 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
949 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
955 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
961 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
966 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
969 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
971 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
976 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
981 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
986 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
1004 if( before != after )
1006 m_undoStack.push_back( { aCtrl, before, after } );
1075 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1076 return wxVariant( textCtrl->GetValue() );
1077 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1078 return wxVariant( scintilla->GetText() );
1079 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1080 return wxVariant( combo->GetValue() );
1081 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1082 return wxVariant( (
long) choice->GetSelection() );
1083 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1084 return wxVariant( check->GetValue() );
1085 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1086 return wxVariant( (
long) spin->GetValue() );
1087 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1088 return wxVariant( spinD->GetValue() );
1089 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1090 return wxVariant( radio->GetValue() );
1091 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1092 return wxVariant( (
long) radioBox->GetSelection() );
1093 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1095 nlohmann::json j = nlohmann::json::array();
1096 int rows =
grid->GetNumberRows();
1097 int cols =
grid->GetNumberCols();
1099 for(
int r = 0; r < rows; ++r )
1101 nlohmann::json row = nlohmann::json::array();
1103 for(
int c = 0; c < cols; ++c )
1104 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1109 return wxVariant( wxString( j.dump() ) );
1111 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1115 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1117 wxPGProperty* prop = *it;
1118 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1121 return wxVariant( wxString( j.dump() ) );
1123 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1125 nlohmann::json j = nlohmann::json::array();
1126 unsigned int count = checkList->GetCount();
1128 for(
unsigned int i = 0; i < count; ++i )
1130 if( checkList->IsChecked( i ) )
1134 return wxVariant( wxString( j.dump() ) );
1136 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1138 nlohmann::json j = nlohmann::json::array();
1139 unsigned int rows = dataList->GetItemCount();
1140 unsigned int cols = dataList->GetColumnCount();
1142 for(
unsigned int r = 0; r < rows; ++r )
1144 nlohmann::json row = nlohmann::json::array();
1146 for(
unsigned int c = 0; c < cols; ++c )
1149 dataList->GetValue( val, r, c );
1150 row.push_back( std::string( val.GetString().ToUTF8() ) );
1156 return wxVariant( wxString( j.dump() ) );
1165 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1166 textCtrl->SetValue( aValue.GetString() );
1167 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1168 scintilla->SetText( aValue.GetString() );
1169 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1170 combo->SetValue( aValue.GetString() );
1171 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1172 choice->SetSelection( (
int) aValue.GetLong() );
1173 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1174 check->SetValue( aValue.GetBool() );
1175 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1176 spin->SetValue( (
int) aValue.GetLong() );
1177 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1178 spinD->SetValue( aValue.GetDouble() );
1179 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1180 radio->SetValue( aValue.GetBool() );
1181 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1182 radioBox->SetSelection( (
int) aValue.GetLong() );
1183 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1185 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1189 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1191 for(
int r = 0; r < rows; ++r )
1193 nlohmann::json row = j[r];
1194 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1196 for(
int c = 0; c < cols; ++c )
1197 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1201 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1203 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1207 for(
auto it = j.begin(); it != j.end(); ++it )
1208 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1211 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1213 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1217 unsigned int count = checkList->GetCount();
1219 for(
unsigned int i = 0; i < count; ++i )
1220 checkList->Check( i,
false );
1222 for(
auto& idx : j )
1224 unsigned int i = idx.get<
unsigned int>();
1227 checkList->Check( i,
true );
1231 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1233 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1237 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1238 static_cast<unsigned int>( dataList->GetItemCount() ) );
1240 for(
unsigned int r = 0; r < rows; ++r )
1242 nlohmann::json row = j[r];
1243 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1245 for(
unsigned int c = 0; c < cols; ++c )
1247 wxVariant val( wxString( row[c].get<std::string>() ) );
1248 dataList->SetValue( val, r, c );
1309 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1310 SetTitle( wxS(
"*" ) + GetTitle() );
1316 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1317 SetTitle( GetTitle().AfterFirst(
'*' ) );
1329 return wxDialog::ShowModal();
1365 if( wxWindow* win = wxWindow::GetCapture() )
1366 win->ReleaseMouse();
1369 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1386 wxGUIEventLoop event_loop;
1395 return GetReturnCode();
1417 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1420 SetReturnCode( retCode );
1424 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1458 for( wxWindow* child : aWindow->GetChildren() )
1465 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1483 const int id = aEvent.GetId();
1487 if(
id == GetAffirmativeId() )
1491 else if(
id == wxID_APPLY )
1500 else if(
id == wxID_CANCEL )
1523 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1525 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1535 int key = aEvt.GetKeyCode();
1538 if( aEvt.ControlDown() )
1540 if( aEvt.ShiftDown() )
1542 if( aEvt.AltDown() )
1545 int hotkey = key | mods;
1548 if( hotkey == (
MD_CTRL +
'Z') )
1559 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1568 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1570 wxObject* eventSource = aEvt.GetEventObject();
1572 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1575 if( !textCtrl->IsMultiLine() )
1577 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1581#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1582 wxString eol =
"\r\n";
1584 wxString eol =
"\n";
1587 long pos = textCtrl->GetInsertionPoint();
1588 textCtrl->WriteText( eol );
1589 textCtrl->SetInsertionPoint( pos + eol.length() );
1592 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1594 wxString eol =
"\n";
1596 switch( scintilla->GetEOLMode() )
1598 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1599 case wxSTC_EOL_CR: eol =
"\r";
break;
1600 case wxSTC_EOL_LF: eol =
"\n";
break;
1603 long pos = scintilla->GetCurrentPos();
1604 scintilla->InsertText( pos, eol );
1605 scintilla->GotoPos( pos + eol.length() );
1611 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1613 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1616 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1618 wxWindow* currentWindow = wxWindow::FindFocus();
1619 int currentIdx = -1;
1620 int delta = aEvt.ShiftDown() ? -1 : 1;
1627 idx = ( ( idx +
delta ) % size + size ) % size;
1630 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1635 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1637 currentIdx = (int) i;
1642 if( currentIdx >= 0 )
1644 advance( currentIdx );
1647 int startIdx = currentIdx;
1651 advance( currentIdx );
1653 if( currentIdx == startIdx )
1660 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1661 advance( currentIdx );
1668 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1670 wxObject* eventSource = aEvt.GetEventObject();
1672 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1678 textCtrl->SelectAll();
1682 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1688 scintilla->SelectAll();
1700 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1703 [&]( wxButton* aButton )
1705 if( aLabels.count( aButton->GetId() ) > 0 )
1707 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1713 switch( aButton->GetId() )
1715 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1716 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1717 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1718 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1719 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1720 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1721 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1722 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1729 if( sdbSizer->GetAffirmativeButton() )
1730 setupButton( sdbSizer->GetAffirmativeButton() );
1732 if( sdbSizer->GetApplyButton() )
1733 setupButton( sdbSizer->GetApplyButton() );
1735 if( sdbSizer->GetNegativeButton() )
1736 setupButton( sdbSizer->GetNegativeButton() );
1738 if( sdbSizer->GetCancelButton() )
1739 setupButton( sdbSizer->GetCancelButton() );
1741 if( sdbSizer->GetHelpButton() )
1742 setupButton( sdbSizer->GetHelpButton() );
1746 if( sdbSizer->GetAffirmativeButton() )
1747 sdbSizer->GetAffirmativeButton()->SetDefault();
1750 for( wxSizerItem* item : aSizer->GetChildren() )
1752 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::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)
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 focusParentCanvas()
Set focus back to the parent frame's tool canvas if available, otherwise to the parent window.
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.
std::map< std::string, std::map< std::string, nlohmann::json > > m_dialogControlValues