1 /*
2  *  configdialog.cpp
3  *  PHD Guiding
4  *
5  *  Created by Bret McKee
6  *  Copyright (c) 2012 Bret McKee
7  *  All rights reserved.
8  *
9  *  This source code is distributed under the following "BSD" license
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions are met:
12  *    Redistributions of source code must retain the above copyright notice,
13  *     this list of conditions and the following disclaimer.
14  *    Redistributions in binary form must reproduce the above copyright notice,
15  *     this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *    Neither the name of Craig Stark, Stark Labs nor the names of its
18  *     contributors may be used to endorse or promote products derived from
19  *     this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  *  POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include "phd.h"
36 
ConfigDialogPane(const wxString & heading,wxWindow * pParent)37 ConfigDialogPane::ConfigDialogPane(const wxString& heading, wxWindow *pParent)
38     : wxStaticBoxSizer(new wxStaticBox(pParent, wxID_ANY, heading), wxVERTICAL)
39 {
40     m_pParent = pParent;
41 }
42 
DoAdd(wxSizer * pSizer)43 void ConfigDialogPane::DoAdd(wxSizer *pSizer)
44 {
45     this->Add(pSizer, wxSizerFlags().Expand().Border(wxALL,3));
46 }
47 
DoAdd(wxWindow * pWindow)48 void ConfigDialogPane::DoAdd(wxWindow *pWindow)
49 {
50     this->Add(pWindow, wxSizerFlags().Expand().Border(wxALL,3));
51 }
52 
DoAdd(wxWindow * pWindow,const wxString & toolTip)53 void ConfigDialogPane::DoAdd(wxWindow *pWindow, const wxString& toolTip)
54 {
55     pWindow->SetToolTip(toolTip);
56     DoAdd(pWindow);
57 }
58 
MakeLabeledControl(const wxString & label,wxWindow * pControl,const wxString & toolTip,wxWindow * pControl2)59 wxSizer *ConfigDialogPane::MakeLabeledControl(const wxString& label, wxWindow *pControl, const wxString& toolTip, wxWindow *pControl2)
60 {
61     wxStaticText *pLabel = new wxStaticText(m_pParent, wxID_ANY, label + _(": "));
62     pControl->SetToolTip(toolTip);
63 
64     wxBoxSizer *pSizer = new wxBoxSizer(wxHORIZONTAL);
65     pSizer->Add(pLabel, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
66     pSizer->Add(pControl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
67     if (pControl2)
68         pSizer->Add(pControl2, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
69 
70     return pSizer;
71 }
72 
DoAdd(const wxString & label,wxWindow * pControl,const wxString & toolTip,wxWindow * pControl2)73 void ConfigDialogPane::DoAdd(const wxString& label, wxWindow *pControl, const wxString& toolTip, wxWindow *pControl2)
74 {
75     DoAdd(MakeLabeledControl(label, pControl, toolTip, pControl2));
76 }
77 
StringWidth(const wxString & string)78 int ConfigDialogPane::StringWidth(const wxString& string)
79 {
80     int width, height;
81 
82     m_pParent->GetTextExtent(string, &width, &height);
83 
84     return width;
85 }
86 
StringArrayWidth(wxString string[],int nElements)87 int ConfigDialogPane::StringArrayWidth(wxString string[], int nElements)
88 {
89     int width = 0;
90 
91     for(int i=0;i<nElements;i++)
92     {
93         int thisWidth = StringWidth(string[i]);
94 
95         if (thisWidth > width)
96         {
97             width = thisWidth;
98         }
99     }
100 
101     return width;
102 }
103 
104 // Default implementation does nothing because most config dialogs don't need an 'undo' function - simply not calling 'Unload' prevents any pending changes from
105 // being saved.  But if non-scalar objects are involved - as in guide algorithms - a specific Undo may be required
Undo(void)106 void ConfigDialogPane::Undo(void)
107 {
108 }
109 
GetSingleCtrl(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id)110 wxWindow *ConfigDialogPane::GetSingleCtrl(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id)
111 {
112     wxWindow *ctrl = 0;
113     BrainCtrlIdMap::iterator it = CtrlMap.find(id);
114     if (it != CtrlMap.end())
115     {
116         ctrl = static_cast<wxWindow *>(it->second.panelCtrl);
117         if (ctrl)
118             it->second.isPositioned = true;
119     }
120     return ctrl;           // May return null but client can use CondAddCtrl
121 }
122 
123 // Handle the case where a control is not created because of state.  wxWidgets handles a null window correctly in 'Add' but the behavior
124 // is technically undocumented.
CondAddCtrl(wxSizer * szr,BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,const wxSizerFlags & flags)125 void ConfigDialogPane::CondAddCtrl(wxSizer *szr, BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, const wxSizerFlags& flags)
126 {
127     wxWindow *ctrl = GetSingleCtrl(CtrlMap, id);
128     if (ctrl)
129         szr->Add(ctrl, flags);
130 }
131 
GetSizerCtrl(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id)132 wxSizer *ConfigDialogPane::GetSizerCtrl(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id)
133 {
134     wxSizer *ctrl = 0;
135     BrainCtrlIdMap::iterator it = CtrlMap.find(id);
136     if (it != CtrlMap.end())
137     {
138         ctrl = static_cast<wxSizer *>(it->second.panelCtrl);
139         if (ctrl)
140             it->second.isPositioned = true;
141     }
142     return ctrl;           // May return null, won't add entry in CtrlMap
143 }
144 
OnImageScaleChange()145 void ConfigDialogPane::OnImageScaleChange()
146 {
147     // Do nothing by default - subclasses will override if needed
148 }
149 
EnableDecControls(bool enable)150 void ConfigDialogPane::EnableDecControls(bool enable)
151 {
152     // Do nothing by default - subclasses will override if needed
153 }
154 
ConfigDialogCtrlSet(wxWindow * pParent,AdvancedDialog * pAdvancedDialog,BrainCtrlIdMap & CtrlMap)155 ConfigDialogCtrlSet::ConfigDialogCtrlSet(wxWindow *pParent, AdvancedDialog* pAdvancedDialog, BrainCtrlIdMap& CtrlMap)
156 {
157     m_pParent = pParent;
158     m_pAdvDlg = pAdvancedDialog;
159 }
160 
StringWidth(const wxString & string)161 int ConfigDialogCtrlSet::StringWidth(const wxString& string)
162 {
163     int width, height;
164 
165     m_pParent->GetTextExtent(string, &width, &height);
166 
167     return width;
168 }
169 
StringArrayWidth(wxString string[],int nElements)170 int ConfigDialogCtrlSet::StringArrayWidth(wxString string[], int nElements)
171 {
172     int width = 0;
173 
174     for (int i = 0; i < nElements; i++)
175     {
176         int thisWidth = StringWidth(string[i]);
177 
178         if (thisWidth > width)
179         {
180             width = thisWidth;
181         }
182     }
183 
184     return width;
185 }
186 
StringArrayWidth(const wxArrayString & ary)187 int ConfigDialogCtrlSet::StringArrayWidth(const wxArrayString& ary)
188 {
189     int width = 0;
190 
191     for (unsigned int i = 0; i < ary.size(); i++)
192     {
193         int thisWidth = StringWidth(ary[i]);
194 
195         if (thisWidth > width)
196         {
197             width = thisWidth;
198         }
199     }
200 
201     return width;
202 }
203 
GetParentWindow(BRAIN_CTRL_IDS id)204 wxWindow *ConfigDialogCtrlSet::GetParentWindow(BRAIN_CTRL_IDS id)
205 {
206     return m_pAdvDlg->GetTabLocation(id);
207 }
208 
209 // Base method for adding map elements
AddMapElement(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,wxObject * pElem)210 void ConfigDialogCtrlSet::AddMapElement(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, wxObject *pElem)
211 {
212     CtrlMap[id] = BrainCtrlInfo(id, pElem);
213 }
214 
215 // Simple control
AddCtrl(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,wxControl * pCtrl)216 void ConfigDialogCtrlSet::AddCtrl(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, wxControl *pCtrl)
217 {
218     AddMapElement(CtrlMap, id, pCtrl);
219 }
220 
221 // Control with tooltip
AddCtrl(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,wxControl * pCtrl,const wxString & toolTip)222 void ConfigDialogCtrlSet::AddCtrl(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, wxControl *pCtrl, const wxString& toolTip)
223 {
224     pCtrl->SetToolTip(toolTip);
225     AddMapElement(CtrlMap, id, pCtrl);
226 }
227 
228 // Control group via sizer
AddGroup(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,wxSizer * pSizer)229 void ConfigDialogCtrlSet::AddGroup(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, wxSizer *pSizer)
230 {
231     AddMapElement(CtrlMap, id, pSizer);
232 }
233 
MakeLabeledControl(BRAIN_CTRL_IDS id,const wxString & label,wxWindow * pControl,const wxString & toolTip)234 wxSizer *ConfigDialogCtrlSet::MakeLabeledControl(BRAIN_CTRL_IDS id, const wxString& label, wxWindow *pControl, const wxString& toolTip)
235 {
236     wxStaticText *pLabel = new wxStaticText(GetParentWindow(id), wxID_ANY, label + _(": "));
237     pControl->SetToolTip(toolTip);
238 
239     wxBoxSizer *pSizer = new wxBoxSizer(wxHORIZONTAL);
240     pSizer->Add(pLabel, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
241     pSizer->Add(pControl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
242 
243     return pSizer;
244 }
245 
AddLabeledCtrl(BrainCtrlIdMap & CtrlMap,BRAIN_CTRL_IDS id,const wxString & Label,wxControl * pCtrl,const wxString & toolTip)246 void ConfigDialogCtrlSet::AddLabeledCtrl(BrainCtrlIdMap& CtrlMap, BRAIN_CTRL_IDS id, const wxString& Label, wxControl *pCtrl, const wxString& toolTip)
247 {
248     AddGroup(CtrlMap, id, MakeLabeledControl(id, Label, pCtrl, toolTip));
249 }
250