1 // This is core/vgui/wx/wxSliderPanel.cxx
2 #include "wxSliderPanel.h"
3 //:
4 // \file
5 
6 //: For compilers that support precompilation, includes "wx/wx.h".
7 #include <wx/wxprec.h>
8 
9 #ifndef WX_PRECOMP
10 #  include <wx/wx.h>
11 #endif
12 
13 #include <cassert>
14 #ifdef _MSC_VER
15 #  include "vcl_msvc_warnings.h"
16 #endif
17 #include "vgui/vgui_message.h"
18 
19 
20 IMPLEMENT_DYNAMIC_CLASS(wxSliderPanel, wxScrolledWindow)
21 
22 
23 //: Event Table
24 BEGIN_EVENT_TABLE(wxSliderPanel, wxPanel)
25 EVT_SCROLL_THUMBTRACK(wxSliderPanel::OnSliderTrack)
26 EVT_SCROLL_PAGEDOWN(wxSliderPanel::OnSliderTrack)
27 EVT_SCROLL_PAGEUP(wxSliderPanel::OnSliderTrack)
28 EVT_SCROLL_LINEDOWN(wxSliderPanel::OnSliderTrack)
29 EVT_SCROLL_LINEUP(wxSliderPanel::OnSliderTrack)
30 EVT_SCROLL_CHANGED(wxSliderPanel::OnSliderChange)
31 EVT_TEXT(wxID_ANY, wxSliderPanel::OnChangeText)
32 EVT_TEXT_ENTER(wxID_ANY, wxSliderPanel::OnEnterText)
33 END_EVENT_TABLE()
34 
35 
36 const char wxSliderPanel::update[] = "";
37 const char wxSliderPanel::enter[] = "";
38 
39 
40 //: Constructor - Default
wxSliderPanel()41 wxSliderPanel::wxSliderPanel()
42   : base_id_(10100)
43   , send_messages_(true)
44 {
45   Init();
46 }
47 
48 //: Constructor
wxSliderPanel(wxWindow * parent,wxWindowID id,wxWindowID base_id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)49 wxSliderPanel::wxSliderPanel(wxWindow * parent,
50                              wxWindowID id,
51                              wxWindowID base_id,
52                              const wxPoint & pos,
53                              const wxSize & size,
54                              long style,
55                              const wxString & name)
56   : send_messages_(true)
57 {
58   Init();
59   Create(parent, id, base_id, pos, size, style, name);
60 }
61 
62 
63 //: Creator
64 bool
Create(wxWindow * parent,wxWindowID id,wxWindowID base_id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)65 wxSliderPanel::Create(wxWindow * parent,
66                       wxWindowID id,
67                       wxWindowID base_id,
68                       const wxPoint & pos,
69                       const wxSize & size,
70                       long style,
71                       const wxString & name)
72 {
73   base_id_ = base_id;
74   wxScrolledWindow::Create(parent, id, pos, size, style, name);
75   return true;
76 }
77 
78 
79 //: Destructor
~wxSliderPanel()80 wxSliderPanel::~wxSliderPanel() {}
81 
82 
83 //: Initialization
84 void
Init()85 wxSliderPanel::Init()
86 {}
87 
88 //: Convert slider position to a double value
89 double
sp_to_val(unsigned int idx,int sp) const90 wxSliderPanel::sp_to_val(unsigned int idx, int sp) const
91 {
92   return (sp / 1000.0) * (max_vals_[idx] - min_vals_[idx]) + min_vals_[idx];
93 }
94 
95 //: Convert a double value to a slider position
96 int
val_to_sp(unsigned int idx,double val) const97 wxSliderPanel::val_to_sp(unsigned int idx, double val) const
98 {
99   return static_cast<int>((1000.0 * (val - min_vals_[idx]) / (max_vals_[idx] - min_vals_[idx])));
100 }
101 
102 
103 //: Create the controls
104 void
CreateControls()105 wxSliderPanel::CreateControls()
106 {
107   wxFlexGridSizer * itemFlexGridSizer = new wxFlexGridSizer(vals_.size(), 3, 0, 0);
108   itemFlexGridSizer->AddGrowableCol(1);
109   this->SetSizer(itemFlexGridSizer);
110 
111   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
112   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
113   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
114   for (unsigned int i = 0; i < vals_.size(); ++i)
115   {
116     wxStaticText * itemLabel =
117       new wxStaticText(this, wxID_STATIC, wxString::Format(wxT("%u"), i + 1), wxDefaultPosition, wxDefaultSize, 0);
118     itemFlexGridSizer->Add(itemLabel, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP | wxLEFT, 3);
119 
120     int pos = val_to_sp(i, vals_[i]);
121     wxSlider * itemSlider =
122       new wxSlider(this, base_id_ + 2 * i, pos, 0, 1000, wxDefaultPosition, wxSize(100, -1), wxSL_HORIZONTAL);
123     itemFlexGridSizer->Add(itemSlider, 1, wxGROW | wxALIGN_CENTER_VERTICAL | wxLEFT, 3);
124 
125     wxTextCtrl * itemTextCtrl = new wxTextCtrl(this,
126                                                base_id_ + 2 * i + 1,
127                                                wxString::Format(wxT("%g"), vals_[i]),
128                                                wxDefaultPosition,
129                                                wxSize(70, -1),
130                                                wxTE_PROCESS_ENTER);
131     itemFlexGridSizer->Add(itemTextCtrl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 3);
132     // Numeric text validator
133     itemTextCtrl->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
134   }
135   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
136   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
137   itemFlexGridSizer->Add(0, 3, 0, wxGROW, 0);
138 }
139 
140 void
CreateSliders(const std::vector<double> & init_vals,const std::vector<double> & min_vals,const std::vector<double> & max_vals)141 wxSliderPanel::CreateSliders(const std::vector<double> & init_vals,
142                              const std::vector<double> & min_vals,
143                              const std::vector<double> & max_vals)
144 {
145   assert(init_vals.size() == min_vals.size());
146   assert(init_vals.size() == max_vals.size());
147   vals_ = init_vals;
148   min_vals_ = min_vals;
149   max_vals_ = max_vals;
150 
151 
152   Freeze();
153   DestroyChildren();
154   wxScrolledWindow::Create(GetParent(), GetId(), GetPosition(), GetSize(), GetWindowStyleFlag(), GetName());
155   CreateControls();
156   FitInside();
157   SetScrollRate(0, 20);
158   Thaw();
159   Refresh();
160 }
161 
162 
163 bool
ShowToolTips()164 wxSliderPanel::ShowToolTips()
165 {
166   return true;
167 }
168 
169 
170 //: Used by event handles to validate and lookup widgets
171 int
GetWidgets(const wxEvent & event,wxSlider * & slider,wxTextCtrl * & text)172 wxSliderPanel::GetWidgets(const wxEvent & event, wxSlider *& slider, wxTextCtrl *& text)
173 {
174   slider = NULL;
175   text = NULL;
176   int idx = (event.GetId() - base_id_) / 2;
177   if (idx < 0 || idx >= static_cast<int>(vals_.size()))
178     return -1;
179 
180   text = dynamic_cast<wxTextCtrl *>(FindWindowById(base_id_ + 2 * idx + 1));
181   slider = dynamic_cast<wxSlider *>(FindWindowById(base_id_ + 2 * idx));
182   return idx;
183 }
184 
185 
186 //: Handle Slider Tracking (dragging)
187 void
OnSliderTrack(wxScrollEvent & event)188 wxSliderPanel::OnSliderTrack(wxScrollEvent & event)
189 {
190   wxSlider * slider;
191   wxTextCtrl * text;
192   int idx = GetWidgets(event, slider, text);
193   if (!slider || !text)
194   {
195     event.Skip();
196     return;
197   }
198 
199   int spos = event.GetInt();
200   double val = sp_to_val(idx, spos);
201   text->SetValue(wxString::Format(wxT("%g"), val));
202 }
203 
204 //: Handle Slider Release (stop dragging)
205 void
OnSliderChange(wxScrollEvent & event)206 wxSliderPanel::OnSliderChange(wxScrollEvent & event)
207 {
208   wxSlider * slider;
209   wxTextCtrl * text;
210   int idx = GetWidgets(event, slider, text);
211   if (!slider || !text)
212   {
213     event.Skip();
214     return;
215   }
216 
217   if (send_messages_)
218   {
219     vgui_message m;
220     m.from = this;
221     m.user = wxSliderPanel::enter;
222     m.data = &idx;
223     notify(m);
224   }
225 }
226 
227 
228 //: Handle Textbox value change (typing)
229 void
OnChangeText(wxCommandEvent & event)230 wxSliderPanel::OnChangeText(wxCommandEvent & event)
231 {
232   wxSlider * slider;
233   wxTextCtrl * text;
234   int idx = GetWidgets(event, slider, text);
235   if (!slider || !text)
236   {
237     event.Skip();
238     return;
239   }
240 
241   event.GetString().ToDouble(&vals_[idx]);
242   int spos = val_to_sp(idx, vals_[idx]);
243   slider->SetValue(spos);
244   event.Skip();
245 
246   if (send_messages_)
247   {
248     vgui_message m;
249     m.from = this;
250     m.user = wxSliderPanel::update;
251     m.data = &idx;
252     notify(m);
253   }
254 }
255 
256 
257 //: Handle Textbox press of Enter key
258 void
OnEnterText(wxCommandEvent & event)259 wxSliderPanel::OnEnterText(wxCommandEvent & event)
260 {
261   wxSlider * slider;
262   wxTextCtrl * text;
263   int idx = GetWidgets(event, slider, text);
264   if (!slider || !text)
265   {
266     event.Skip();
267     return;
268   }
269 
270   if (send_messages_)
271   {
272     vgui_message m;
273     m.from = this;
274     m.user = wxSliderPanel::enter;
275     m.data = &idx;
276     notify(m);
277   }
278 }
279 
280 
281 //: Update the data
282 void
update_data(std::vector<double> & data,bool send_messages)283 wxSliderPanel::update_data(std::vector<double> & data, bool send_messages)
284 {
285   for (unsigned int i = 0; i < data.size() && i < vals_.size(); ++i)
286   {
287     update_data(i, data[i], send_messages);
288   }
289 }
290 
291 //: Update a single value
292 void
update_data(unsigned int i,double val,bool send_messages)293 wxSliderPanel::update_data(unsigned int i, double val, bool send_messages)
294 {
295   vals_[i] = val;
296   int id = base_id_ + 2 * i + 1; // id of text control
297   wxTextCtrl * text = dynamic_cast<wxTextCtrl *>(FindWindowById(id));
298 
299   // optionally disable sending messages about this update
300   send_messages_ = send_messages;
301   text->SetValue(wxString::Format(wxT("%g"), val));
302   send_messages_ = true;
303 }
304