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 );
383 if( m_parent !=
nullptr )
385 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
386 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
400 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
413 m_eventLoop->Exit( GetReturnCode() );
416 ret = wxDialog::Show( show );
421 m_parent->SetFocus();
434 auto dlgIt = settings->m_dialogControlValues.find( key );
436 if( dlgIt == settings->m_dialogControlValues.end() )
439 dlgIt->second.erase(
"__geometry" );
458 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
459 int myDisplay = wxDisplay::GetFromWindow(
this );
461 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
486 return wxDialog::Enable( enable );
492 auto getSiblingIndex =
493 [](
const wxWindow* parent,
const wxWindow* child )
495 wxString childClass = child->GetClassInfo()->GetClassName();
498 for(
const wxWindow* sibling : parent->GetChildren() )
500 if( sibling->GetClassInfo()->GetClassName() != childClass )
503 if( sibling == child )
513 [&](
const wxWindow* window )
515 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
517 if( window->GetParent() )
518 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
523 std::string key =
makeKey( aWin );
525 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
542 wxRect rect( GetPosition(), GetSize() );
544 geom[
"x" ] = rect.GetX();
545 geom[
"y" ] = rect.GetY();
546 geom[
"w" ] = rect.GetWidth();
547 geom[
"h" ] = rect.GetHeight();
548 dlgMap[
"__geometry" ] = geom;
550 std::function<void( wxWindow* )> saveFn =
555 if( !props->GetPropertyOr(
"persist",
false ) )
567 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
569 dlgMap[ key ] = combo->GetValue();
571 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
573 dlgMap[ key ] = od_combo->GetSelection();
575 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
577 dlgMap[ key ] = textEntry->GetValue();
579 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
581 dlgMap[ key ] = choice->GetSelection();
583 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
585 dlgMap[ key ] = check->GetValue();
587 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
589 dlgMap[ key ] = spin->GetValue();
591 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
593 dlgMap[ key ] = radio->GetValue();
595 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
597 dlgMap[ key ] = radioBox->GetSelection();
599 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
601 dlgMap[ key ] = splitter->GetSashPosition();
603 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
605 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
607 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
609 int index = notebook->GetSelection();
611 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
612 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
614 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
616 int index = auiNotebook->GetSelection();
618 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
619 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
623 dlgMap[ key ] =
grid->GetShownColumnsAsString();
627 for( wxWindow* child : win->GetChildren() )
633 if( !props->GetPropertyOr(
"persist",
false ) )
637 for( wxWindow* child : GetChildren() )
655 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
657 std::function<void( wxWindow* )> loadFn =
662 if( !props->GetPropertyOr(
"persist",
false ) )
670 auto it = dlgMap.find( key );
672 if( it != dlgMap.end() )
674 const nlohmann::json& j = it->second;
678 if( j.is_number_integer() )
681 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
684 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
686 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
688 if( j.is_number_integer() )
690 int index = j.get<
int>();
692 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
693 od_combo->SetSelection(
index );
696 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
699 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
701 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
703 if( j.is_number_integer() )
705 int index = j.get<
int>();
707 if(
index >= 0 &&
index < (
int) choice->GetCount() )
708 choice->SetSelection(
index );
711 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
714 check->SetValue( j.get<
bool>() );
716 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
718 if( j.is_number_integer() )
719 spin->SetValue( j.get<
int>() );
721 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
729 radio->SetValue(
true );
732 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
734 if( j.is_number_integer() )
736 int index = j.get<
int>();
738 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
739 radioBox->SetSelection(
index );
742 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
744 if( j.is_number_integer() )
745 splitter->SetSashPosition( j.get<
int>() );
747 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
749 if( j.is_number_integer() )
750 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
752 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
756 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
758 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
760 if( notebook->GetPageText( page ) == pageTitle )
761 notebook->SetSelection( page );
765 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
769 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
771 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
773 if( auiNotebook->GetPageText( page ) == pageTitle )
774 auiNotebook->ChangeSelection( page );
781 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
786 for( wxWindow* child : win->GetChildren() )
792 if( !props->GetPropertyOr(
"persist",
false ) )
796 for( wxWindow* child : GetChildren() )
805 aWindow->SetClientData( props );
820 for( wxWindow* child : children )
822 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
831#if defined( __WXMAC__ ) || defined( __WXMSW__ )
832 if( !textCtrl->GetStringSelection().IsEmpty() )
836 else if( textCtrl->IsEditable() )
838 textCtrl->SelectAll();
844 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
847 scintilla->Connect( wxEVT_SET_FOCUS,
851 if( !scintilla->GetSelectedText().IsEmpty() )
855 else if( scintilla->GetMarginWidth( 0 ) > 0 )
859 else if( scintilla->IsEditable() )
861 scintilla->SelectAll();
867 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
870 wxRect rect = child->GetRect();
872 child->ConvertDialogToPixels(
minSize );
874 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
875 std::max( 0,
minSize.y - rect.GetHeight() ) );
877 child->SetMinSize( rect.GetSize() );
878 child->SetSize( rect );
891 for( wxWindow* child : children )
893 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
898 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
903 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
909 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
912 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
914 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
919 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
925 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
931 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
936 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
939 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
941 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
946 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
951 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
956 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
974 if( before != after )
1045 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1046 return wxVariant( textCtrl->GetValue() );
1047 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1048 return wxVariant( scintilla->GetText() );
1049 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1050 return wxVariant( combo->GetValue() );
1051 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1052 return wxVariant( (
long) choice->GetSelection() );
1053 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1054 return wxVariant( check->GetValue() );
1055 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1056 return wxVariant( (
long) spin->GetValue() );
1057 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1058 return wxVariant( spinD->GetValue() );
1059 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1060 return wxVariant( radio->GetValue() );
1061 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1062 return wxVariant( (
long) radioBox->GetSelection() );
1063 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1065 nlohmann::json j = nlohmann::json::array();
1066 int rows =
grid->GetNumberRows();
1067 int cols =
grid->GetNumberCols();
1069 for(
int r = 0; r < rows; ++r )
1071 nlohmann::json row = nlohmann::json::array();
1073 for(
int c = 0; c < cols; ++c )
1074 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1079 return wxVariant( wxString( j.dump() ) );
1081 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1085 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1087 wxPGProperty* prop = *it;
1088 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1091 return wxVariant( wxString( j.dump() ) );
1093 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1095 nlohmann::json j = nlohmann::json::array();
1096 unsigned int count = checkList->GetCount();
1098 for(
unsigned int i = 0; i < count; ++i )
1100 if( checkList->IsChecked( i ) )
1104 return wxVariant( wxString( j.dump() ) );
1106 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1108 nlohmann::json j = nlohmann::json::array();
1109 unsigned int rows = dataList->GetItemCount();
1110 unsigned int cols = dataList->GetColumnCount();
1112 for(
unsigned int r = 0; r < rows; ++r )
1114 nlohmann::json row = nlohmann::json::array();
1116 for(
unsigned int c = 0; c < cols; ++c )
1119 dataList->GetValue( val, r, c );
1120 row.push_back( std::string( val.GetString().ToUTF8() ) );
1126 return wxVariant( wxString( j.dump() ) );
1135 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1136 textCtrl->SetValue( aValue.GetString() );
1137 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1138 scintilla->SetText( aValue.GetString() );
1139 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1140 combo->SetValue( aValue.GetString() );
1141 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1142 choice->SetSelection( (
int) aValue.GetLong() );
1143 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1144 check->SetValue( aValue.GetBool() );
1145 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1146 spin->SetValue( (
int) aValue.GetLong() );
1147 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1148 spinD->SetValue( aValue.GetDouble() );
1149 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1150 radio->SetValue( aValue.GetBool() );
1151 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1152 radioBox->SetSelection( (
int) aValue.GetLong() );
1153 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1155 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1159 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1161 for(
int r = 0; r < rows; ++r )
1163 nlohmann::json row = j[r];
1164 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1166 for(
int c = 0; c < cols; ++c )
1167 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1171 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1173 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1177 for(
auto it = j.begin(); it != j.end(); ++it )
1178 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1181 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1183 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1187 unsigned int count = checkList->GetCount();
1189 for(
unsigned int i = 0; i < count; ++i )
1190 checkList->Check( i,
false );
1192 for(
auto& idx : j )
1194 unsigned int i = idx.get<
unsigned int>();
1197 checkList->Check( i,
true );
1201 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1203 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1207 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1208 static_cast<unsigned int>( dataList->GetItemCount() ) );
1210 for(
unsigned int r = 0; r < rows; ++r )
1212 nlohmann::json row = j[r];
1213 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1215 for(
unsigned int c = 0; c < cols; ++c )
1217 wxVariant val( wxString( row[c].get<std::string>() ) );
1218 dataList->SetValue( val, r, c );
1279 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1280 SetTitle( wxS(
"*" ) + GetTitle() );
1286 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1287 SetTitle( GetTitle().AfterFirst(
'*' ) );
1299 return wxDialog::ShowModal();
1335 if( wxWindow* win = wxWindow::GetCapture() )
1336 win->ReleaseMouse();
1339 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1356 wxGUIEventLoop event_loop;
1367 return GetReturnCode();
1389 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1392 SetReturnCode( retCode );
1396 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1419 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1437 const int id = aEvent.GetId();
1441 if(
id == GetAffirmativeId() )
1445 else if(
id == wxID_APPLY )
1454 else if(
id == wxID_CANCEL )
1477 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1479 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1489 int key = aEvt.GetKeyCode();
1492 if( aEvt.ControlDown() )
1494 if( aEvt.ShiftDown() )
1496 if( aEvt.AltDown() )
1499 int hotkey = key | mods;
1502 if( hotkey == (
MD_CTRL +
'Z') )
1513 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1522 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1524 wxObject* eventSource = aEvt.GetEventObject();
1526 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1529 if( !textCtrl->IsMultiLine() )
1531 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1535#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1536 wxString eol =
"\r\n";
1538 wxString eol =
"\n";
1541 long pos = textCtrl->GetInsertionPoint();
1542 textCtrl->WriteText( eol );
1543 textCtrl->SetInsertionPoint( pos + eol.length() );
1546 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1548 wxString eol =
"\n";
1550 switch( scintilla->GetEOLMode() )
1552 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1553 case wxSTC_EOL_CR: eol =
"\r";
break;
1554 case wxSTC_EOL_LF: eol =
"\n";
break;
1557 long pos = scintilla->GetCurrentPos();
1558 scintilla->InsertText( pos, eol );
1559 scintilla->GotoPos( pos + eol.length() );
1565 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1567 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1570 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1572 wxWindow* currentWindow = wxWindow::FindFocus();
1573 int currentIdx = -1;
1574 int delta = aEvt.ShiftDown() ? -1 : 1;
1581 idx = ( ( idx +
delta ) % size + size ) % size;
1584 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1589 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1591 currentIdx = (int) i;
1596 if( currentIdx >= 0 )
1598 advance( currentIdx );
1601 int startIdx = currentIdx;
1605 advance( currentIdx );
1607 if( currentIdx == startIdx )
1614 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1615 advance( currentIdx );
1622 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1624 wxObject* eventSource = aEvt.GetEventObject();
1626 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1632 textCtrl->SelectAll();
1636 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1642 scintilla->SelectAll();
1654 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1657 [&]( wxButton* aButton )
1659 if( aLabels.count( aButton->GetId() ) > 0 )
1661 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1667 switch( aButton->GetId() )
1669 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1670 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1671 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1672 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1673 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1674 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1675 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1676 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1683 if( sdbSizer->GetAffirmativeButton() )
1684 setupButton( sdbSizer->GetAffirmativeButton() );
1686 if( sdbSizer->GetApplyButton() )
1687 setupButton( sdbSizer->GetApplyButton() );
1689 if( sdbSizer->GetNegativeButton() )
1690 setupButton( sdbSizer->GetNegativeButton() );
1692 if( sdbSizer->GetCancelButton() )
1693 setupButton( sdbSizer->GetCancelButton() );
1695 if( sdbSizer->GetHelpButton() )
1696 setupButton( sdbSizer->GetHelpButton() );
1700 if( sdbSizer->GetAffirmativeButton() )
1701 sdbSizer->GetAffirmativeButton()->SetDefault();
1704 for( wxSizerItem* item : aSizer->GetChildren() )
1706 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.