1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2014 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
17 //
18 #if defined(__GNUG__) && !defined(__APPLE__)
19 #pragma implementation "DlgHiddenColumns.cpp"
20 #endif
21
22 #include "stdwx.h"
23 #include "util.h"
24 #include "DlgHiddenColumns.h"
25 #include "BOINCGUIApp.h"
26 #include "Events.h"
27 #include "error_numbers.h"
28 #include "gui_rpc_client.h"
29 #include "SkinManager.h"
30 #include "MainDocument.h"
31 #include "AdvancedFrame.h"
32 #include "BOINCBaseView.h"
33 #include "BOINCListCtrl.h"
34
35 #define DLGDIAGNOSTICS_INITIAL_WIDTH ADJUSTFORXDPI(480)
36 #define DLGDIAGNOSTICS_INITIAL_HEIGHT ADJUSTFORYDPI(480)
37 #define DLGDIAGNOSTICS_MIN_WIDTH ADJUSTFORXDPI(400)
38 #define DLGDIAGNOSTICS_MIN_HEIGHT ADJUSTFORYDPI(400)
39
IMPLEMENT_DYNAMIC_CLASS(CDlgHiddenColumns,wxDialog)40 IMPLEMENT_DYNAMIC_CLASS(CDlgHiddenColumns, wxDialog)
41
42 BEGIN_EVENT_TABLE(CDlgHiddenColumns, wxDialog)
43 EVT_SIZE(CDlgHiddenColumns::OnSize)
44 EVT_BUTTON(wxID_OK,CDlgHiddenColumns::OnOK)
45 EVT_BUTTON(ID_DEFAULTSBTN,CDlgHiddenColumns::OnSetDefaults)
46 EVT_CHECKBOX(wxID_ANY, CDlgHiddenColumns::OnCheckboxClick )
47
48
49 END_EVENT_TABLE()
50
51 /* Constructor */
52 CDlgHiddenColumns::CDlgHiddenColumns(wxWindow* parent) :
53 wxDialog( parent, ID_ANYDIALOG, wxEmptyString, wxDefaultPosition,
54 wxSize( DLGDIAGNOSTICS_INITIAL_WIDTH,DLGDIAGNOSTICS_INITIAL_HEIGHT ),
55 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER
56 ) {
57
58 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
59 wxASSERT(pSkinAdvanced);
60 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
61
62 wxString title;
63 title.Printf(
64 _("%s Column Selection"),
65 pSkinAdvanced->GetApplicationShortName().c_str()
66 );
67
68 SetTitle(title);
69
70 SetSizeHints(DLGDIAGNOSTICS_MIN_WIDTH, DLGDIAGNOSTICS_MIN_HEIGHT);
71 SetExtraStyle( GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY );
72
73 wxBoxSizer* bSizer1 = new wxBoxSizer( wxVERTICAL );
74 m_headingSizer = new wxGridSizer( 1 );
75
76 m_headingText.Printf(
77 _("Select which columns %s should show."),
78 pSkinAdvanced->GetApplicationShortName().c_str()
79 );
80
81 m_heading = new wxStaticText(this, wxID_ANY, m_headingText);
82
83 m_headingSizer->Add(m_heading, 1, wxLEFT | wxRIGHT, 25);
84
85 bSizer1->AddSpacer(7);
86 bSizer1->Add( m_headingSizer, 0, wxEXPAND | wxALL, 5 );
87 bSizer1->AddSpacer(7);
88
89 m_scrolledWindow = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
90 m_scrolledWindow->SetScrollRate( 5, 5 );
91
92 m_scrolledSizer = new wxBoxSizer(wxVERTICAL);
93
94 CreateCheckboxes();
95
96 bSizer1->Add( m_scrolledWindow, 1, wxEXPAND | wxALL, 5 );
97
98 wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
99
100 m_btnOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
101 m_btnOK->SetToolTip( _("Save all values and close the dialog") );
102 buttonSizer->Add( m_btnOK, 0, wxALL, 5 );
103
104 wxButton* btnDefaults = new wxButton( this, ID_DEFAULTSBTN, _("Defaults"), wxDefaultPosition, wxDefaultSize, 0 );
105 btnDefaults->SetToolTip( _("Restore default settings") );
106 buttonSizer->Add( btnDefaults, 0, wxALL, 5 );
107
108 wxButton* btnCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
109 btnCancel->SetToolTip( _("Close the dialog without saving") );
110 buttonSizer->Add( btnCancel, 0, wxALL, 5 );
111
112 btnCancel->SetDefault();
113 bSizer1->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 15 );
114
115 SetSizer( bSizer1 );
116
117 RestoreState();
118 Layout();
119 Center( wxBOTH );
120
121 #if defined(__WXMSW__) || defined(__WXGTK__)
122 SetDoubleBuffered(true);
123 #endif
124 }
125
126 // destructor
~CDlgHiddenColumns()127 CDlgHiddenColumns::~CDlgHiddenColumns() {
128 unsigned int i, count;
129
130 SaveState();
131
132 count = m_checkbox_list.size();
133 for (i=0; i<count; ++i) {
134 std::vector <wxCheckBox*> *checkbox_list = m_checkbox_list[i];
135 checkbox_list->clear();
136 delete checkbox_list;
137 }
138 m_checkbox_list.clear();
139 m_pBOINCBaseView.clear();
140 }
141
142
CreateCheckboxes()143 void CDlgHiddenColumns::CreateCheckboxes() {
144 int i, stdCount, actualCount;
145 bool val;
146 CAdvancedFrame* pFrame = (CAdvancedFrame*)GetParent();
147 wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame));
148
149 wxNotebook* pNotebook = pFrame->GetNotebook();
150 wxASSERT(pNotebook);
151
152 actualCount = m_checkbox_list.size();
153 for (i=0; i<actualCount; ++i) {
154 std::vector <wxCheckBox*> *checkbox_list = m_checkbox_list[i];
155 checkbox_list->clear();
156 delete checkbox_list;
157 }
158 m_checkbox_list.clear();
159
160 wxWindow* pwndNotebookPage = NULL;
161 CBOINCBaseView* pView = NULL;
162 long iIndex;
163 long iPageCount;
164
165 iPageCount = (long)pNotebook->GetPageCount();
166
167 for (iIndex = 0; iIndex < iPageCount; iIndex++) {
168 pwndNotebookPage = pNotebook->GetPage(iIndex);
169 wxASSERT(wxDynamicCast(pwndNotebookPage, CBOINCBaseView));
170
171 pView = wxDynamicCast(pwndNotebookPage, CBOINCBaseView);
172 wxASSERT(pView);
173
174 CBOINCListCtrl* listPane = pView->GetListCtrl();
175 if (!listPane) continue;
176
177 m_pBOINCBaseView.push_back(pView);
178
179 std::vector <wxCheckBox*> *checkbox_list = new std::vector <wxCheckBox*>;
180
181 wxStaticBox* tabStaticBox = new wxStaticBox(m_scrolledWindow, -1, pView->GetViewDisplayName());
182 wxStaticBoxSizer* tabStaticBoxSizer = new wxStaticBoxSizer( tabStaticBox, wxVERTICAL );
183 wxGridSizer* checkboxSizer = new wxGridSizer(2, wxSize(0,3));
184
185 CBOINCListCtrl* listCtrl = pView->GetListCtrl();
186 wxInt32 iShownColumnCount = listCtrl->GetColumnCount();
187 wxArrayInt aOrder(iShownColumnCount);
188
189 #ifdef wxHAS_LISTCTRL_COLUMN_ORDER
190 aOrder = listCtrl->GetColumnsOrder();
191 #else
192 for (i = 0; i < iShownColumnCount; ++i) {
193 aOrder[i] = i;
194 }
195 #endif
196
197 stdCount = pView->m_aStdColNameOrder->GetCount();
198
199 #ifdef wxHAS_LISTCTRL_COLUMN_ORDER
200 // Create checkboxes for shown columns in current column order
201 for (i=0; i<iShownColumnCount; ++i) {
202 wxString columnLabel = pView->m_aStdColNameOrder->Item(pView->m_iColumnIndexToColumnID[aOrder[i]]);
203 wxCheckBox* ckbox = new wxCheckBox(tabStaticBox, wxID_ANY, columnLabel);
204 checkboxSizer->Add(ckbox, 0, wxLEFT, 25);
205 val = false;
206 ckbox->SetValue(true);
207 checkbox_list->push_back(ckbox);
208 }
209
210 // Create checkboxes for hidden columns
211 for (i=0; i<stdCount; ++i) {
212 bool found = false;
213 for (int j = 0; j < iShownColumnCount; ++j) {
214 if (pView->m_iColumnIndexToColumnID[aOrder[j]] == i) {
215 found = true;
216 break;
217 }
218 }
219 if (found) continue;
220
221 wxString columnLabel = pView->m_aStdColNameOrder->Item(i);
222 wxCheckBox* ckbox = new wxCheckBox(tabStaticBox, wxID_ANY, columnLabel);
223 checkboxSizer->Add(ckbox, 0, wxLEFT, 25);
224 ckbox->SetValue(false);
225 checkbox_list->push_back(ckbox);
226 }
227 #else
228 for (i=0; i<stdCount; ++i) {
229 wxString columnLabel = pView->m_aStdColNameOrder->Item(i);
230 wxCheckBox* ckbox = new wxCheckBox(tabStaticBox, wxID_ANY, columnLabel);
231 checkboxSizer->Add(ckbox, 0, wxLEFT, 25);
232 val = false;
233 if (pView->m_iColumnIDToColumnIndex[i] >= 0) val = true;
234 ckbox->SetValue(val);
235 checkbox_list->push_back(ckbox);
236 }
237 #endif
238
239 m_checkbox_list.push_back(checkbox_list);
240
241 tabStaticBoxSizer->Add(checkboxSizer, 0, wxEXPAND, 1 );
242 m_scrolledSizer->Add(tabStaticBoxSizer, 0, wxEXPAND, 1 );
243 }
244 m_scrolledWindow->SetSizer( m_scrolledSizer );
245 m_scrolledWindow->Layout();
246 m_scrolledSizer->Fit( m_scrolledWindow );
247 }
248
249
250 /* saves dialog size and (on Mac) position */
SaveState()251 bool CDlgHiddenColumns::SaveState() {
252 wxConfigBase* pConfig = wxConfigBase::Get(FALSE);
253
254 wxASSERT(pConfig);
255 if (!pConfig) return false;
256
257 pConfig->SetPath("/DlgHiddenColumns/");
258 pConfig->Write(wxT("Width"), GetSize().GetWidth());
259 pConfig->Write(wxT("Height"), GetSize().GetHeight());
260
261 pConfig->Flush();
262
263 return true;
264 }
265
266 /* restores former dialog size and (on Mac) position */
RestoreState()267 bool CDlgHiddenColumns::RestoreState() {
268 wxConfigBase* pConfig = wxConfigBase::Get(FALSE);
269 int iWidth, iHeight;
270
271 wxASSERT(pConfig);
272 if (!pConfig) return false;
273
274 pConfig->SetPath("/DlgHiddenColumns/");
275
276 pConfig->Read(wxT("Width"), &iWidth, DLGDIAGNOSTICS_INITIAL_WIDTH);
277 pConfig->Read(wxT("Height"), &iHeight, DLGDIAGNOSTICS_INITIAL_HEIGHT);
278
279 // Guard against a rare situation where registry values are zero
280 if ((iWidth < 50) && (iWidth != wxDefaultCoord)) iWidth = DLGDIAGNOSTICS_INITIAL_WIDTH;
281 if ((iHeight < 50) && (iHeight != wxDefaultCoord)) iHeight = DLGDIAGNOSTICS_INITIAL_HEIGHT;
282
283 // Set size to saved values or defaults if no saved values
284 SetSize(std::max(iWidth, DLGDIAGNOSTICS_MIN_WIDTH), std::max(iHeight, DLGDIAGNOSTICS_MIN_HEIGHT));
285
286 return true;
287 }
288
289
OnSize(wxSizeEvent & event)290 void CDlgHiddenColumns::OnSize(wxSizeEvent& event) {
291 m_heading->SetLabel(m_headingText);
292 m_heading->Wrap(m_headingSizer->GetSize().GetWidth()-50);
293 m_headingSizer->Fit(m_heading);
294 Layout();
295 SaveState();
296 Refresh();
297
298 event.Skip();
299 }
300
301
OnCheckboxClick(wxCommandEvent & event)302 void CDlgHiddenColumns::OnCheckboxClick(wxCommandEvent& event){
303 bool bAllOffInGroup, bEnableOK = true;
304
305 size_t actualCount = m_checkbox_list.size();
306 for (size_t i=0; i<actualCount; ++i) {
307 std::vector <wxCheckBox*> *checkbox_list = m_checkbox_list[i];
308 bAllOffInGroup = true;
309 for (size_t j=0; j<checkbox_list->size(); ++j) {
310 wxCheckBox* ckbox = (*checkbox_list)[j];
311 if (ckbox->GetValue()) {
312 bAllOffInGroup = false;
313 break;
314 }
315 }
316 if (bAllOffInGroup) {
317 bEnableOK = false;
318 break;
319 }
320 }
321 m_btnOK->Enable(bEnableOK);
322
323 event.Skip();
324 }
325
326
OnOK(wxCommandEvent & event)327 void CDlgHiddenColumns::OnOK(wxCommandEvent& event) {
328 size_t actualCount = m_checkbox_list.size();
329 wxASSERT (m_pBOINCBaseView.size() == actualCount);
330
331 for (size_t i=0; i<actualCount; ++i) {
332 CBOINCBaseView* pView = m_pBOINCBaseView[i];
333 std::vector <wxCheckBox*> *checkbox_list = m_checkbox_list[i];
334 wxArrayString orderArray;
335 for (size_t j=0; j<checkbox_list->size(); ++j) {
336 wxCheckBox* ckbox = (*checkbox_list)[j];
337 if (ckbox->GetValue()) {
338 wxString name = ckbox->GetLabel();
339 orderArray.Add(name);
340 }
341 }
342
343 CBOINCListCtrl* listPane = pView->GetListCtrl();
344 listPane->SetListColumnOrder(orderArray);
345
346 // Write the new column configuration to the registry
347 wxConfigBase* pConfig = wxConfigBase::Get(false);
348 pConfig->SetPath(wxT("/") + pView->GetViewName());
349 listPane->OnSaveState(pConfig);
350 }
351
352 event.Skip();
353 }
354
355
OnSetDefaults(wxCommandEvent &)356 void CDlgHiddenColumns::OnSetDefaults(wxCommandEvent& ) {
357 wxMessageDialog* dlg = new wxMessageDialog(this, _("Are you sure you want to reset all list columns to the default configurations?"),
358 _("Confirm defaults"), wxOK|wxCANCEL|wxCENTRE, wxDefaultPosition);
359
360 if (dlg->ShowModal() != wxID_OK) return;
361
362 int count = m_pBOINCBaseView.size();
363 for (int i=0; i<count; ++i) {
364 CBOINCBaseView* pView = m_pBOINCBaseView[i];
365 CBOINCListCtrl* listPane = pView->GetListCtrl();
366
367 listPane->SetListColumnOrder(*(pView->m_aStdColNameOrder));
368 listPane->SetDefaultColumnDisplay();
369
370 // Write the new column configuration to the registry
371 wxConfigBase* pConfig = wxConfigBase::Get(false);
372 pConfig->SetPath(wxT("/") + pView->GetViewName());
373 listPane->OnSaveState(pConfig);
374 }
375
376 EndModal(0);
377 }
378