1 // Copyright (C) 2010 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include "ConfigDiag.h"
20 #define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
21 #define WXSTR_FROM_STR(s) (wxString::FromAscii((s).c_str()))
22 // ToAscii was causing probs with some extended ascii characters, To8BitData seems to work
23 #define STR_FROM_WXSTR(w) (std::string((w).To8BitData()))
26 void GamepadPage::ConfigExtension( wxCommandEvent
& event
)
28 ControllerEmu::Extension
* const ex
= ((ExtensionButton
*)event
.GetEventObject())->extension
;
30 // show config diag, if "none" isn't selected
31 if ( ex
->switch_extension
)
33 wxDialog
* const dlg
= new wxDialog( this, -1, wxString::FromAscii(ex
->attachments
[ex
->switch_extension
]->GetName().c_str()), wxDefaultPosition
);
34 wxPanel
* const pnl
= new wxPanel( dlg
, -1, wxDefaultPosition
);
35 wxBoxSizer
* const pnl_szr
= new wxBoxSizer( wxHORIZONTAL
);
37 const std::size_t orig_size
= control_groups
.size();
39 ControlGroupsSizer
* const szr
= new ControlGroupsSizer( ex
->attachments
[ex
->switch_extension
], pnl
, this, &control_groups
);
40 pnl
->SetSizerAndFit( szr
); // needed
41 pnl_szr
->Add( pnl
, 0, wxLEFT
, 5 );
42 dlg
->SetSizerAndFit( pnl_szr
); // needed
49 // remove the new groups that were just added, now that the window closed
50 control_groups
.resize( orig_size
);
54 PadSettingExtension::PadSettingExtension( wxWindow
* const parent
, ControllerEmu::Extension
* const ext
)
55 : wxChoice( parent
, -1 )
59 std::vector
<ControllerEmu
*>::const_iterator
60 i
= extension
->attachments
.begin(),
61 e
= extension
->attachments
.end();
64 Append( wxString::FromAscii( (*i
)->GetName().c_str() ) );
69 void PadSettingExtension::UpdateGUI()
71 Select( extension
->switch_extension
);
74 void PadSettingExtension::UpdateValue()
76 extension
->switch_extension
= GetSelection();
79 PadSettingCheckBox::PadSettingCheckBox( wxWindow
* const parent
, ControlState
& _value
, const char* const label
)
80 : wxCheckBox( parent
, -1, wxString::FromAscii( label
), wxDefaultPosition
)
86 void PadSettingCheckBox::UpdateGUI()
88 SetValue( value
> 0 );
91 void PadSettingCheckBox::UpdateValue()
93 // 0.01 so its saved to the ini file as just 1. :(
94 value
= 0.01 * GetValue();
97 void PadSettingChoice::UpdateGUI()
99 SetValue(value
* 100);
102 void PadSettingChoice::UpdateValue()
104 value
= float(GetValue()) / 100;
107 ControlDialog::ControlDialog(GamepadPage
* const parent
, InputPlugin
& plugin
, ControllerInterface::ControlReference
* const ref
)
108 : wxDialog(parent
, -1, wxT("Configure Control"), wxDefaultPosition
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
109 , control_reference(ref
)
113 m_devq
= m_parent
->controller
->default_device
;
115 // GetStrings() sounds slow :/
116 //device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
117 device_cbox
= new wxComboBox(this, -1, WXSTR_FROM_STR(m_devq
.ToString()), wxDefaultPosition
, wxSize(256,-1), parent
->device_cbox
->GetStrings(), wxTE_PROCESS_ENTER
);
119 _connect_macro_( device_cbox
, ControlDialog::SetDevice
, wxEVT_COMMAND_COMBOBOX_SELECTED
, this );
120 _connect_macro_( device_cbox
, ControlDialog::SetDevice
, wxEVT_COMMAND_TEXT_ENTER
, this );
122 wxStaticBoxSizer
* const control_chooser
= CreateControlChooser( this, parent
);
124 wxStaticBoxSizer
* const d_szr
= new wxStaticBoxSizer( wxVERTICAL
, this, wxT("Device") );
125 d_szr
->Add( device_cbox
, 0, wxEXPAND
|wxALL
, 5 );
127 wxBoxSizer
* const szr
= new wxBoxSizer( wxVERTICAL
);
128 szr
->Add( d_szr
, 0, wxEXPAND
|wxLEFT
|wxRIGHT
|wxTOP
, 5 );
129 szr
->Add( control_chooser
, 1, wxEXPAND
|wxALL
, 5 );
131 SetSizerAndFit( szr
); // needed
136 ControlButton::ControlButton( wxWindow
* const parent
, ControllerInterface::ControlReference
* const _ref
, const unsigned int width
, const std::string
& label
)
137 : wxButton( parent
, -1, wxT(""), wxDefaultPosition
, wxSize( width
,20) )
138 , control_reference( _ref
)
141 SetLabel(WXSTR_FROM_STR(_ref
->expression
));
143 SetLabel(WXSTR_FROM_STR(label
));
146 void InputConfigDialog::UpdateProfileComboBox()
148 std::string
pname( File::GetUserPath(D_CONFIG_IDX
) );
149 pname
+= PROFILES_PATH
;
150 pname
+= m_plugin
.profile_name
;
152 CFileSearch::XStringVector exts
;
153 exts
.push_back("*.ini");
154 CFileSearch::XStringVector dirs
;
155 dirs
.push_back( pname
);
156 CFileSearch
cfs( exts
, dirs
);
157 const CFileSearch::XStringVector
& sv
= cfs
.GetFileNames();
160 CFileSearch::XStringVector::const_iterator si
= sv
.begin(),
162 for ( ; si
!=se
; ++si
)
164 std::string
str( si
->begin() + si
->find_last_of('/') + 1 , si
->end() - 4 ) ;
165 strs
.push_back( wxString::FromAscii( str
.c_str() ) );
168 std::vector
< GamepadPage
* >::iterator i
= m_padpages
.begin(),
169 e
= m_padpages
.end();
170 for ( ; i
!= e
; ++i
)
172 (*i
)->profile_cbox
->Clear();
173 (*i
)->profile_cbox
->Append(strs
);
177 void InputConfigDialog::UpdateControlReferences()
179 std::vector
< GamepadPage
* >::iterator i
= m_padpages
.begin(),
180 e
= m_padpages
.end();
181 for ( ; i
!= e
; ++i
)
182 (*i
)->controller
->UpdateReferences( m_plugin
.controller_interface
);
185 void InputConfigDialog::ClickSave( wxCommandEvent
& event
)
187 m_plugin
.SaveConfig();
191 void ControlDialog::UpdateListContents()
193 control_lbox
->Clear();
195 ControllerInterface::Device
* const dev
= m_plugin
.controller_interface
.FindDevice(m_devq
);
198 if (control_reference
->is_input
)
201 std::vector
<ControllerInterface::Device::Input
*>::const_iterator
202 i
= dev
->Inputs().begin(),
203 e
= dev
->Inputs().end();
205 control_lbox
->Append(WXSTR_FROM_STR((*i
)->GetName()));
210 std::vector
<ControllerInterface::Device::Output
*>::const_iterator
211 i
= dev
->Outputs().begin(),
212 e
= dev
->Outputs().end();
214 control_lbox
->Append(WXSTR_FROM_STR((*i
)->GetName()));
219 void ControlDialog::SelectControl(const std::string
& name
)
223 const int f
= control_lbox
->FindString(WXSTR_FROM_STR(name
));
225 control_lbox
->Select(f
);
228 void ControlDialog::UpdateGUI()
231 textctrl
->SetValue(WXSTR_FROM_STR(control_reference
->expression
));
233 // updates the "bound controls:" label
234 size_t bound
= control_reference
->BoundCount();
235 std::ostringstream ss
;
236 ss
<< "Bound Controls: ";
237 if ( bound
) ss
<< bound
; else ss
<< "None";
238 m_bound_label
->SetLabel( wxString::FromAscii(ss
.str().c_str()) );
241 void GamepadPage::UpdateGUI()
243 device_cbox
->SetValue(WXSTR_FROM_STR(controller
->default_device
.ToString()));
245 std::vector
< ControlGroupBox
* >::const_iterator g
= control_groups
.begin(),
246 ge
= control_groups
.end();
250 std::vector
<ControlButton
*>::const_iterator i
= (*g
)->control_buttons
.begin()
251 , e
= (*g
)->control_buttons
.end();
253 //if (std::string::npos == (*i)->control_reference->expression.find_first_of("`|&!#"))
254 (*i
)->SetLabel(WXSTR_FROM_STR((*i
)->control_reference
->expression
));
256 //(*i)->SetLabel(wxT("..."));
259 std::vector
<PadSetting
*>::const_iterator si
= (*g
)->options
.begin()
260 , se
= (*g
)->options
.end();
261 for ( ; si
!=se
; ++si
)
266 void GamepadPage::ClearAll( wxCommandEvent
& event
)
268 m_plugin
.controls_crit
.Enter(); // enter
270 // just load an empty ini section to clear everything :P
271 IniFile::Section section
;
272 controller
->LoadConfig(§ion
);
274 // no point in using the real ControllerInterface i guess
275 ControllerInterface face
;
276 controller
->UpdateReferences(face
);
280 m_plugin
.controls_crit
.Leave(); // leave
283 void ControlDialog::SetControl( wxCommandEvent
& event
)
285 control_reference
->expression
= STR_FROM_WXSTR(textctrl
->GetValue());
287 m_plugin
.controls_crit
.Enter(); // enter
288 m_plugin
.controller_interface
.UpdateReference(control_reference
, m_parent
->controller
->default_device
);
289 m_plugin
.controls_crit
.Leave(); // leave
294 void GamepadPage::SetDevice( wxCommandEvent
& event
)
296 controller
->default_device
.FromString(STR_FROM_WXSTR(device_cbox
->GetValue()));
298 // show user what it was validated as
299 device_cbox
->SetValue(WXSTR_FROM_STR(controller
->default_device
.ToString()));
301 // this will set all the controls to this default device
302 controller
->UpdateDefaultDevice();
305 m_plugin
.controls_crit
.Enter(); // enter
306 controller
->UpdateReferences( m_plugin
.controller_interface
);
307 m_plugin
.controls_crit
.Leave(); // leave
310 void ControlDialog::SetDevice( wxCommandEvent
& event
)
312 m_devq
.FromString(STR_FROM_WXSTR(device_cbox
->GetValue()));
314 // show user what it was validated as
315 device_cbox
->SetValue(WXSTR_FROM_STR(m_devq
.ToString()));
318 UpdateListContents();
321 void ControlDialog::ClearControl(wxCommandEvent
& event
)
323 control_reference
->expression
.clear();
325 m_plugin
.controls_crit
.Leave(); // enter
326 m_plugin
.controller_interface
.UpdateReference(control_reference
, m_parent
->controller
->default_device
);
327 m_plugin
.controls_crit
.Leave(); // leave
332 void ControlDialog::AppendControl(wxCommandEvent
& event
)
334 const int num
= control_lbox
->GetSelection();
340 const wxString lbl
= ((wxButton
*)event
.GetEventObject())->GetLabel();
342 wxString expr
= textctrl
->GetLabel();
344 // append the operator to the expression
345 if (wxT('!') == lbl
[0] || false == expr
.empty())
348 // non-default device
349 if (false == (m_devq
== m_parent
->controller
->default_device
))
350 expr
.append(wxT('`')).append(WXSTR_FROM_STR(m_devq
.ToString())).append(wxT('`'));
352 // append the control name
353 expr
+= control_lbox
->GetString(num
);
355 control_reference
->expression
= STR_FROM_WXSTR(expr
);
357 m_plugin
.controls_crit
.Leave(); // enter
358 m_plugin
.controller_interface
.UpdateReference(control_reference
, m_parent
->controller
->default_device
);
359 m_plugin
.controls_crit
.Leave(); // leave
364 void GamepadPage::AdjustSetting( wxCommandEvent
& event
)
366 m_plugin
.controls_crit
.Enter(); // enter
368 // updates the setting value from the GUI control
369 (dynamic_cast<PadSetting
*>(event
.GetEventObject()))->UpdateValue();
371 m_plugin
.controls_crit
.Leave(); // leave
374 void GamepadPage::AdjustControlOption( wxCommandEvent
& event
)
376 m_plugin
.controls_crit
.Enter(); // enter / prolly fine not being here
378 m_control_dialog
->control_reference
->range
= (ControlState
)(m_control_dialog
->range_slider
->GetValue()) / SLIDER_TICK_COUNT
;
380 m_plugin
.controls_crit
.Leave(); // leave
383 void GamepadPage::ConfigControl( wxCommandEvent
& event
)
385 m_control_dialog
= new ControlDialog(this, m_plugin
, ((ControlButton
*)event
.GetEventObject())->control_reference
);
386 m_control_dialog
->ShowModal();
387 m_control_dialog
->Destroy();
389 // update changes that were made in the dialog
393 void GamepadPage::ClearControl( wxCommandEvent
& event
)
395 ControlButton
* const btn
= (ControlButton
*)event
.GetEventObject();
396 btn
->control_reference
->expression
.clear();
397 //btn->control_reference->device_qualifier = controller->default_device;
399 m_plugin
.controls_crit
.Enter();
400 controller
->UpdateReferences( m_plugin
.controller_interface
);
401 m_plugin
.controls_crit
.Leave();
407 void ControlDialog::DetectControl(wxCommandEvent
& event
)
409 wxButton
* const btn
= (wxButton
*)event
.GetEventObject();
410 const wxString lbl
= btn
->GetLabel();
412 ControllerInterface::Device
* const dev
= m_plugin
.controller_interface
.FindDevice(m_devq
);
415 btn
->SetLabel(wxT("[ waiting ]"));
417 m_plugin
.controls_crit
.Enter(); // enter
418 ControllerInterface::Device::Control
* const ctrl
= control_reference
->Detect(DETECT_WAIT_TIME
, dev
);
420 // if we got input, select it in the list
422 SelectControl(ctrl
->GetName());
424 m_plugin
.controls_crit
.Leave(); // leave
430 void GamepadPage::DetectControl( wxCommandEvent
& event
)
432 ControlButton
* btn
= (ControlButton
*)event
.GetEventObject();
435 ControllerInterface::Device
* const dev
= m_plugin
.controller_interface
.FindDevice(controller
->default_device
);
438 btn
->SetLabel(wxT("[ waiting ]"));
440 m_plugin
.controls_crit
.Enter(); // enter
441 ControllerInterface::Device::Control
* const ctrl
= btn
->control_reference
->Detect(DETECT_WAIT_TIME
, dev
);
443 // if we got input, update expression and reference
446 btn
->control_reference
->expression
= ctrl
->GetName();
447 m_plugin
.controller_interface
.UpdateReference(btn
->control_reference
, controller
->default_device
);
450 m_plugin
.controls_crit
.Leave(); // leave
452 btn
->SetLabel(WXSTR_FROM_STR(btn
->control_reference
->expression
));
456 wxStaticBoxSizer
* ControlDialog::CreateControlChooser( wxWindow
* const parent
, wxWindow
* const eventsink
)
458 wxStaticBoxSizer
* const main_szr
= new wxStaticBoxSizer(wxVERTICAL
, parent
, control_reference
->is_input
? wxT("Input") : wxT("Output"));
460 textctrl
= new wxTextCtrl(parent
, -1, wxEmptyString
, wxDefaultPosition
, wxSize(-1, 48), wxTE_PROCESS_ENTER
| wxTE_MULTILINE
);
461 _connect_macro_(textctrl
, ControlDialog::SetControl
, wxEVT_COMMAND_TEXT_ENTER
, parent
);
463 wxButton
* const detect_button
= new wxButton( parent
, -1, control_reference
->is_input
? wxT("Detect") : wxT("Test") );
464 wxButton
* const clear_button
= new wxButton( parent
, -1, wxT("Clear"), wxDefaultPosition
);
465 wxButton
* const set_button
= new wxButton( parent
, -1, wxT("Set")/*, wxDefaultPosition, wxSize( 32, -1 )*/ );
467 wxButton
* const or_button
= new wxButton( parent
, -1, wxT("| OR"), wxDefaultPosition
);
468 // TODO: check if && is good on other OS
469 wxButton
* const and_button
= new wxButton( parent
, -1, wxT("&& AND"), wxDefaultPosition
);
470 wxButton
* const not_button
= new wxButton( parent
, -1, wxT("! NOT"), wxDefaultPosition
);
471 wxButton
* const add_button
= new wxButton( parent
, -1, wxT("# ADD"), wxDefaultPosition
);
473 _connect_macro_(or_button
, ControlDialog::AppendControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
474 _connect_macro_(and_button
, ControlDialog::AppendControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
475 _connect_macro_(not_button
, ControlDialog::AppendControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
476 _connect_macro_(add_button
, ControlDialog::AppendControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
478 control_lbox
= new wxListBox(parent
, -1, wxDefaultPosition
, wxSize(128, 128));
480 wxBoxSizer
* const button_sizer
= new wxBoxSizer(wxVERTICAL
);
481 button_sizer
->Add(detect_button
, 1, 0, 5);
482 button_sizer
->Add(clear_button
, 1, 0, 5);
483 button_sizer
->Add(or_button
, 1, 0, 5);
484 button_sizer
->Add(and_button
, 1, 0, 5);
485 button_sizer
->Add(not_button
, 1, 0, 5);
486 button_sizer
->Add(add_button
, 1, 0, 5);
487 button_sizer
->Add(set_button
, 1, 0, 5);
489 range_slider
= new wxSlider( parent
, -1, SLIDER_TICK_COUNT
, 0, SLIDER_TICK_COUNT
* 2, wxDefaultPosition
, wxDefaultSize
, wxSL_TOP
| wxSL_LABELS
/*| wxSL_AUTOTICKS*/ );
491 range_slider
->SetValue( control_reference
->range
* SLIDER_TICK_COUNT
);
493 _connect_macro_( detect_button
, ControlDialog::DetectControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
494 _connect_macro_( clear_button
, ControlDialog::ClearControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
495 _connect_macro_( set_button
, ControlDialog::SetControl
, wxEVT_COMMAND_BUTTON_CLICKED
, parent
);
497 _connect_macro_( range_slider
, GamepadPage::AdjustControlOption
, wxEVT_SCROLL_CHANGED
, eventsink
);
498 wxStaticText
* const range_label
= new wxStaticText( parent
, -1, wxT("Range"));
499 m_bound_label
= new wxStaticText( parent
, -1, wxT("") );
501 wxBoxSizer
* const range_sizer
= new wxBoxSizer( wxHORIZONTAL
);
502 range_sizer
->Add( range_label
, 0, wxCENTER
|wxLEFT
, 5 );
503 range_sizer
->Add( range_slider
, 1, wxEXPAND
|wxLEFT
, 5 );
505 wxBoxSizer
* const ctrls_sizer
= new wxBoxSizer(wxHORIZONTAL
);
506 ctrls_sizer
->Add(control_lbox
, 1, wxEXPAND
, 0);
507 ctrls_sizer
->Add(button_sizer
, 0, wxEXPAND
, 0);
509 main_szr
->Add(range_sizer
, 0, wxEXPAND
|wxLEFT
|wxRIGHT
, 5);
510 main_szr
->Add(ctrls_sizer
, 0, wxEXPAND
|wxLEFT
|wxRIGHT
|wxBOTTOM
, 5);
511 main_szr
->Add(textctrl
, 1, wxEXPAND
|wxLEFT
|wxRIGHT
|wxBOTTOM
, 5);
512 main_szr
->Add(m_bound_label
, 0, wxCENTER
, 0);
514 UpdateListContents();
519 void GamepadPage::GetProfilePath(std::string
& path
)
521 const wxString
& name
= profile_cbox
->GetValue();
522 if (false == name
.empty())
524 // TODO: check for dumb characters maybe
526 path
= File::GetUserPath(D_CONFIG_IDX
);
527 path
+= PROFILES_PATH
;
528 path
+= m_plugin
.profile_name
;
530 path
+= STR_FROM_WXSTR(profile_cbox
->GetValue());
535 void GamepadPage::LoadProfile( wxCommandEvent
& event
)
538 GamepadPage::GetProfilePath(fname
);
540 if (false == File::Exists(fname
.c_str()))
546 m_plugin
.controls_crit
.Enter();
547 controller
->LoadConfig(inifile
.GetOrCreateSection("Profile"));
548 controller
->UpdateReferences(m_plugin
.controller_interface
);
549 m_plugin
.controls_crit
.Leave();
554 void GamepadPage::SaveProfile( wxCommandEvent
& event
)
557 GamepadPage::GetProfilePath(fname
);
558 File::CreateFullPath(fname
.c_str());
560 if (false == fname
.empty())
563 controller
->SaveConfig(inifile
.GetOrCreateSection("Profile"));
567 m_config_dialog
->UpdateProfileComboBox();
570 void GamepadPage::DeleteProfile( wxCommandEvent
& event
)
573 GamepadPage::GetProfilePath(fname
);
575 const char* const fnamecstr
= fname
.c_str();
577 if (File::Exists(fnamecstr
))
578 File::Delete(fnamecstr
);
580 m_config_dialog
->UpdateProfileComboBox();
583 void InputConfigDialog::UpdateDeviceComboBox()
585 std::vector
< GamepadPage
* >::iterator i
= m_padpages
.begin(),
586 e
= m_padpages
.end();
587 ControllerInterface::DeviceQualifier dq
;
588 for ( ; i
!= e
; ++i
)
590 (*i
)->device_cbox
->Clear();
591 std::vector
<ControllerInterface::Device
*>::const_iterator di
= m_plugin
.controller_interface
.Devices().begin(),
592 de
= m_plugin
.controller_interface
.Devices().end();
593 for ( ; di
!=de
; ++di
)
595 dq
.FromDevice( *di
);
596 (*i
)->device_cbox
->Append(WXSTR_FROM_STR(dq
.ToString()));
598 (*i
)->device_cbox
->SetValue(WXSTR_FROM_STR((*i
)->controller
->default_device
.ToString()));
602 void GamepadPage::RefreshDevices( wxCommandEvent
& event
)
604 m_plugin
.controls_crit
.Enter(); // enter
607 // TODO: remove hackery of not deinting SDL
608 m_plugin
.controller_interface
.DeInit(true);
609 m_plugin
.controller_interface
.Init();
611 // update all control references
612 m_config_dialog
->UpdateControlReferences();
614 // update device cbox
615 m_config_dialog
->UpdateDeviceComboBox();
617 m_plugin
.controls_crit
.Leave(); // leave
620 ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup
* const group
, wxWindow
* const parent
, wxWindow
* const eventsink
)
621 : wxStaticBoxSizer( wxVERTICAL
, parent
, wxString::FromAscii( group
->name
) )
624 control_group
= group
;
625 static_bitmap
= NULL
;
627 wxFont
m_SmallFont(7, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
);
628 std::vector
<ControllerEmu::ControlGroup::Control
*>::iterator
629 ci
= group
->controls
.begin(),
630 ce
= group
->controls
.end();
631 for ( ; ci
!= ce
; ++ci
)
634 wxStaticText
* const label
= new wxStaticText(parent
, -1, wxString::FromAscii((*ci
)->name
)/*.append(wxT(" :"))*/ );
636 ControlButton
* const control_button
= new ControlButton(parent
, (*ci
)->control_ref
, 80);
637 control_button
->SetFont(m_SmallFont
);
639 controls
.push_back(control_button
);
640 control_buttons
.push_back(control_button
);
642 if ((*ci
)->control_ref
->is_input
)
644 control_button
->SetToolTip(wxT("Left-click to detect input.\nMiddle-click to clear.\nRight-click for more options."));
645 _connect_macro_( control_button
, GamepadPage::DetectControl
, wxEVT_COMMAND_BUTTON_CLICKED
, eventsink
);
649 control_button
->SetToolTip(wxT("Left/Right-click for more options.\nMiddle-click to clear."));
650 _connect_macro_( control_button
, GamepadPage::ConfigControl
, wxEVT_COMMAND_BUTTON_CLICKED
, eventsink
);
653 _connect_macro_( control_button
, GamepadPage::ClearControl
, wxEVT_MIDDLE_DOWN
, eventsink
);
654 _connect_macro_( control_button
, GamepadPage::ConfigControl
, wxEVT_RIGHT_UP
, eventsink
);
656 wxBoxSizer
* const control_sizer
= new wxBoxSizer( wxHORIZONTAL
);
657 control_sizer
->AddStretchSpacer( 1 );
658 control_sizer
->Add( label
, 0, wxCENTER
| wxRIGHT
, 3 );
659 control_sizer
->Add( control_button
, 0, 0, 0 );
661 Add( control_sizer
, 0, wxEXPAND
|wxLEFT
|wxRIGHT
, 3 );
667 switch ( group
->type
)
669 case GROUP_TYPE_STICK
:
670 case GROUP_TYPE_TILT
:
671 case GROUP_TYPE_CURSOR
:
672 case GROUP_TYPE_FORCE
:
674 wxBitmap
bitmap(64, 64);
675 dc
.SelectObject(bitmap
);
677 static_bitmap
= new wxStaticBitmap( parent
, -1, bitmap
, wxDefaultPosition
, wxDefaultSize
, wxBITMAP_TYPE_BMP
);
679 std::vector
< ControllerEmu::ControlGroup::Setting
* >::const_iterator
680 i
= group
->settings
.begin(),
681 e
= group
->settings
.end();
683 wxBoxSizer
* const szr
= new wxBoxSizer( wxVERTICAL
);
686 PadSettingChoice
* cbox
= new PadSettingChoice( parent
, *i
);
687 _connect_macro_( cbox
, GamepadPage::AdjustSetting
, wxEVT_COMMAND_SPINCTRL_UPDATED
, eventsink
);
688 options
.push_back( cbox
);
689 szr
->Add( new wxStaticText( parent
, -1, wxString::FromAscii( (*i
)->name
) ) );
690 szr
->Add( cbox
, 0, wxLEFT
, 0 );
693 wxBoxSizer
* const h_szr
= new wxBoxSizer( wxHORIZONTAL
);
694 h_szr
->Add( szr
, 1, 0, 5 );
695 h_szr
->Add( static_bitmap
, 0, wxALL
|wxCENTER
, 3 );
697 Add( h_szr
, 0, wxEXPAND
|wxLEFT
|wxCENTER
|wxTOP
, 3 );
700 case GROUP_TYPE_BUTTONS
:
702 wxBitmap
bitmap(int(12*group
->controls
.size()+1), 12);
703 dc
.SelectObject(bitmap
);
705 static_bitmap
= new wxStaticBitmap( parent
, -1, bitmap
, wxDefaultPosition
, wxDefaultSize
, wxBITMAP_TYPE_BMP
);
707 PadSettingChoice
* const threshold_cbox
= new PadSettingChoice( parent
, group
->settings
[0] );
708 _connect_macro_( threshold_cbox
, GamepadPage::AdjustSetting
, wxEVT_COMMAND_SPINCTRL_UPDATED
, eventsink
);
710 threshold_cbox
->SetToolTip(wxT("Adjust the analog control pressure required to activate buttons."));
712 options
.push_back( threshold_cbox
);
714 wxBoxSizer
* const szr
= new wxBoxSizer( wxHORIZONTAL
);
715 szr
->Add( new wxStaticText( parent
, -1, wxString::FromAscii( group
->settings
[0]->name
) ), 0, wxCENTER
|wxRIGHT
, 3 );
716 szr
->Add( threshold_cbox
, 0, wxRIGHT
, 3 );
718 Add( szr
, 0, wxALL
|wxCENTER
, 3 );
719 Add( static_bitmap
, 0, wxALL
|wxCENTER
, 3 );
722 case GROUP_TYPE_MIXED_TRIGGERS
:
723 case GROUP_TYPE_TRIGGERS
:
725 int height
= (int)(6 * group
->controls
.size());
727 if (GROUP_TYPE_TRIGGERS
== group
->type
)
732 wxBitmap
bitmap(width
, height
+1);
733 dc
.SelectObject(bitmap
);
735 static_bitmap
= new wxStaticBitmap( parent
, -1, bitmap
, wxDefaultPosition
, wxDefaultSize
, wxBITMAP_TYPE_BMP
);
737 std::vector
<ControllerEmu::ControlGroup::Setting
*>::const_iterator
738 i
= group
->settings
.begin(),
739 e
= group
->settings
.end();
742 PadSettingChoice
* cbox
= new PadSettingChoice( parent
, *i
);
743 _connect_macro_( cbox
, GamepadPage::AdjustSetting
, wxEVT_COMMAND_SPINCTRL_UPDATED
, eventsink
);
744 options
.push_back( cbox
);
745 wxBoxSizer
* const szr
= new wxBoxSizer( wxHORIZONTAL
);
746 szr
->Add( new wxStaticText( parent
, -1, wxString::FromAscii( (*i
)->name
) ), 0, wxCENTER
|wxRIGHT
, 3 );
747 szr
->Add( cbox
, 0, wxRIGHT
, 3 );
748 Add( szr
, 0, wxALL
|wxCENTER
, 3 );
751 Add( static_bitmap
, 0, wxALL
|wxCENTER
, 3 );
754 case GROUP_TYPE_EXTENSION
:
756 PadSettingExtension
* const attachments
= new PadSettingExtension( parent
, (ControllerEmu::Extension
*)group
);
757 wxButton
* const configure
= new ExtensionButton( parent
, (ControllerEmu::Extension
*)group
);
759 options
.push_back( attachments
);
761 _connect_macro_( attachments
, GamepadPage::AdjustSetting
, wxEVT_COMMAND_CHOICE_SELECTED
, eventsink
);
762 _connect_macro_( configure
, GamepadPage::ConfigExtension
, wxEVT_COMMAND_BUTTON_CLICKED
, eventsink
);
764 Add( attachments
, 0, wxTOP
|wxLEFT
|wxRIGHT
|wxEXPAND
, 3 );
765 Add( configure
, 0, wxALL
|wxEXPAND
, 3 );
772 std::vector
<ControllerEmu::ControlGroup::Setting
*>::const_iterator
773 i
= group
->settings
.begin(),
774 e
= group
->settings
.end();
777 PadSettingCheckBox
* setting_cbox
= new PadSettingCheckBox( parent
, (*i
)->value
, (*i
)->name
);
778 _connect_macro_( setting_cbox
, GamepadPage::AdjustSetting
, wxEVT_COMMAND_CHECKBOX_CLICKED
, eventsink
);
779 options
.push_back( setting_cbox
);
781 Add( setting_cbox
, 0, wxALL
|wxLEFT
, 5 );
788 dc
.SelectObject(wxNullBitmap
);
790 //AddStretchSpacer( 0 );
793 ControlGroupsSizer::ControlGroupsSizer( ControllerEmu
* const controller
, wxWindow
* const parent
, wxWindow
* const eventsink
, std::vector
<ControlGroupBox
*>* groups
)
794 : wxBoxSizer( wxHORIZONTAL
)
797 wxBoxSizer
* stacked_groups
= NULL
;
798 for ( unsigned int i
= 0; i
< controller
->groups
.size(); ++i
)
800 ControlGroupBox
* control_group
= new ControlGroupBox( controller
->groups
[i
], parent
, eventsink
);
802 if ( control_group
->control_buttons
.size() > 1 )
804 if ( stacked_groups
)
805 Add( stacked_groups
, 0, /*wxEXPAND|*/wxBOTTOM
|wxRIGHT
, 5 );
807 stacked_groups
= new wxBoxSizer( wxVERTICAL
);
808 stacked_groups
->Add( control_group
, 0, wxEXPAND
);
811 stacked_groups
->Add( control_group
, 0, wxEXPAND
);
814 groups
->push_back( control_group
);
817 if ( stacked_groups
)
818 Add( stacked_groups
, 0, /*wxEXPAND|*/wxBOTTOM
|wxRIGHT
, 5 );
822 GamepadPage::GamepadPage( wxWindow
* parent
, InputPlugin
& plugin
, const unsigned int pad_num
, InputConfigDialog
* const config_dialog
)
823 : wxNotebookPage( parent
, -1 , wxDefaultPosition
, wxDefaultSize
)
824 ,controller(plugin
.controllers
[pad_num
])
825 ,m_config_dialog(config_dialog
)
829 wxBoxSizer
* control_group_sizer
= new ControlGroupsSizer( m_plugin
.controllers
[pad_num
], this, this, &control_groups
);
831 wxStaticBoxSizer
* profile_sbox
= new wxStaticBoxSizer( wxHORIZONTAL
, this, wxT("Profile") );
835 wxStaticBoxSizer
* const device_sbox
= new wxStaticBoxSizer( wxHORIZONTAL
, this, wxT("Device") );
837 device_cbox
= new wxComboBox( this, -1, wxT(""), wxDefaultPosition
, wxSize(128,-1), 0, 0, wxTE_PROCESS_ENTER
);
839 wxButton
* refresh_button
= new wxButton( this, -1, wxT("Refresh"), wxDefaultPosition
, wxSize(60,-1) );
841 _connect_macro_( device_cbox
, GamepadPage::SetDevice
, wxEVT_COMMAND_COMBOBOX_SELECTED
, this );
842 _connect_macro_( device_cbox
, GamepadPage::SetDevice
, wxEVT_COMMAND_TEXT_ENTER
, this );
843 _connect_macro_( refresh_button
, GamepadPage::RefreshDevices
, wxEVT_COMMAND_BUTTON_CLICKED
, this );
845 device_sbox
->Add( device_cbox
, 1, wxLEFT
|wxRIGHT
, 3 );
846 device_sbox
->Add( refresh_button
, 0, wxRIGHT
|wxBOTTOM
, 3 );
848 wxStaticBoxSizer
* const clear_sbox
= new wxStaticBoxSizer( wxHORIZONTAL
, this, wxT("Clear") );
849 wxButton
* all_button
= new wxButton( this, -1, wxT("All"), wxDefaultPosition
, wxSize(48,-1) );
850 clear_sbox
->Add( all_button
, 1, wxLEFT
|wxRIGHT
, 3 );
852 _connect_macro_(all_button
, GamepadPage::ClearAll
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
854 profile_cbox
= new wxComboBox( this, -1, wxT(""), wxDefaultPosition
, wxSize(128,-1) );
856 wxButton
* const pload_btn
= new wxButton( this, -1, wxT("Load"), wxDefaultPosition
, wxSize(48,-1) );
857 wxButton
* const psave_btn
= new wxButton( this, -1, wxT("Save"), wxDefaultPosition
, wxSize(48,-1) );
858 wxButton
* const pdelete_btn
= new wxButton( this, -1, wxT("Delete"), wxDefaultPosition
, wxSize(60,-1) );
860 _connect_macro_(pload_btn
, GamepadPage::LoadProfile
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
861 _connect_macro_(psave_btn
, GamepadPage::SaveProfile
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
862 _connect_macro_(pdelete_btn
, GamepadPage::DeleteProfile
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
864 profile_sbox
->Add( profile_cbox
, 1, wxLEFT
, 3 );
865 profile_sbox
->Add( pload_btn
, 0, wxLEFT
, 3 );
866 profile_sbox
->Add( psave_btn
, 0, 0, 3 );
867 profile_sbox
->Add( pdelete_btn
, 0, wxRIGHT
|wxBOTTOM
, 3 );
869 wxBoxSizer
* const dio
= new wxBoxSizer( wxHORIZONTAL
);
870 dio
->Add( device_sbox
, 1, wxEXPAND
|wxRIGHT
, 5 );
871 dio
->Add( clear_sbox
, 0, wxEXPAND
|wxRIGHT
, 5 );
872 dio
->Add( profile_sbox
, 1, wxEXPAND
|wxRIGHT
, 5 );
874 wxBoxSizer
* const mapping
= new wxBoxSizer( wxVERTICAL
);
876 mapping
->Add( dio
, 1, wxEXPAND
|wxLEFT
|wxTOP
|wxBOTTOM
, 5 );
877 mapping
->Add( control_group_sizer
, 0, wxLEFT
|wxEXPAND
, 5 );
881 SetSizerAndFit( mapping
); // needed
886 InputConfigDialog::InputConfigDialog(wxWindow
* const parent
, InputPlugin
& plugin
, const std::string
& name
)
887 : wxDialog( parent
, wxID_ANY
, wxString::FromAscii(name
.c_str()), wxPoint(128,-1), wxDefaultSize
)
890 m_pad_notebook
= new wxNotebook( this, -1, wxDefaultPosition
, wxDefaultSize
, wxNB_DEFAULT
);
891 for ( unsigned int i
= 0; i
< plugin
.controllers
.size(); ++i
)
893 GamepadPage
* gp
= new GamepadPage( m_pad_notebook
, m_plugin
, i
, this );
894 m_padpages
.push_back( gp
);
895 m_pad_notebook
->AddPage( gp
, wxString::FromAscii( m_plugin
.gui_name
) + wxT(' ') + wxChar('1'+i
) );
898 UpdateDeviceComboBox();
899 UpdateProfileComboBox();
901 wxButton
* const close_button
= new wxButton( this, -1, wxT("Save"));
902 _connect_macro_(close_button
, InputConfigDialog::ClickSave
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
903 _connect_macro_(close_button
, InputConfigDialog::ClickSave
, wxEVT_COMMAND_BUTTON_CLICKED
, this);
905 wxBoxSizer
* btns
= new wxBoxSizer( wxHORIZONTAL
);
906 //btns->Add( new wxStaticText( this, -1, wxString::FromAscii(ver.c_str())), 0, wxLEFT|wxTOP, 5 );
907 btns
->AddStretchSpacer();
908 btns
->Add( close_button
, 0, 0, 0 );
910 wxBoxSizer
* const szr
= new wxBoxSizer( wxVERTICAL
);
911 szr
->Add( m_pad_notebook
, 0, wxEXPAND
|wxTOP
|wxLEFT
|wxRIGHT
, 5 );
912 szr
->Add( btns
, 0, wxEXPAND
|wxALL
, 5 );
914 SetSizerAndFit( szr
); // needed
916 // not needed here it seems, but it cant hurt
921 // live preview update timer
922 m_update_timer
= new wxTimer( this, -1 );
923 Connect( wxID_ANY
, wxEVT_TIMER
, wxTimerEventHandler( InputConfigDialog::UpdateBitmaps
), (wxObject
*)0, this );
924 m_update_timer
->Start( PREVIEW_UPDATE_TIME
, wxTIMER_CONTINUOUS
);
929 bool InputConfigDialog::Destroy()
931 m_update_timer
->Stop();