1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "ViewPreferencePane.h"
21 
22 #include "StringUtils.h"
23 #include "PreferenceManager.h"
24 #include "Preferences.h"
25 #include "View/BorderLine.h"
26 #include "View/TitleBar.h"
27 #include "View/ViewConstants.h"
28 #include "View/wxUtils.h"
29 
30 #include "Renderer/GL.h"
31 
32 #include <wx/checkbox.h>
33 #include <wx/choice.h>
34 #include <wx/clrpicker.h>
35 #include <wx/gbsizer.h>
36 #include <wx/sizer.h>
37 #include <wx/slider.h>
38 #include <wx/stattext.h>
39 
40 namespace TrenchBroom {
41     namespace View {
42         struct TextureMode {
43             int minFilter;
44             int magFilter;
45             String name;
46 
TextureModeTrenchBroom::View::TextureMode47             TextureMode(const int i_minFilter, const int i_magFilter, const String& i_name) :
48             minFilter(i_minFilter),
49             magFilter(i_magFilter),
50             name(i_name) {}
51         };
52 
53         static const size_t NumTextureModes = 6;
54         static const TextureMode TextureModes[] = {
55             TextureMode(GL_NEAREST,                 GL_NEAREST, "Nearest"),
56             TextureMode(GL_NEAREST_MIPMAP_NEAREST,  GL_NEAREST, "Nearest (mipmapped)"),
57             TextureMode(GL_NEAREST_MIPMAP_LINEAR,   GL_NEAREST, "Nearest (mipmaps, interpolated)"),
58             TextureMode(GL_LINEAR,                  GL_LINEAR,  "Linear"),
59             TextureMode(GL_LINEAR_MIPMAP_NEAREST,   GL_LINEAR,  "Linear (mipmapped)"),
60             TextureMode(GL_LINEAR_MIPMAP_LINEAR,    GL_LINEAR,  "Linear (mipmapped, interpolated")
61         };
62 
63         static const size_t NumFrameLayouts = 4;
64 
ViewPreferencePane(wxWindow * parent)65         ViewPreferencePane::ViewPreferencePane(wxWindow* parent) :
66         PreferencePane(parent) {
67             createGui();
68             bindEvents();
69         }
70 
71 
OnLayoutChanged(wxCommandEvent & event)72         void ViewPreferencePane::OnLayoutChanged(wxCommandEvent& event) {
73             if (IsBeingDeleted()) return;
74 
75             const int selection = m_layoutChoice->GetSelection();
76             assert(selection >= 0 && selection < static_cast<int>(NumFrameLayouts));
77 
78             PreferenceManager& prefs = PreferenceManager::instance();
79             prefs.set(Preferences::MapViewLayout, selection);
80         }
81 
OnBrightnessChanged(wxScrollEvent & event)82         void ViewPreferencePane::OnBrightnessChanged(wxScrollEvent& event) {
83             if (IsBeingDeleted()) return;
84 
85             const int value = m_brightnessSlider->GetValue();
86 
87             PreferenceManager& prefs = PreferenceManager::instance();
88             prefs.set(Preferences::Brightness, value / 40.0f);
89         }
90 
OnGridAlphaChanged(wxScrollEvent & event)91         void ViewPreferencePane::OnGridAlphaChanged(wxScrollEvent& event) {
92             if (IsBeingDeleted()) return;
93 
94             const int value = m_gridAlphaSlider->GetValue();
95 
96             PreferenceManager& prefs = PreferenceManager::instance();
97             const int max = m_gridAlphaSlider->GetMax();
98             const float floatValue = static_cast<float>(value) / static_cast<float>(max);
99             prefs.set(Preferences::GridAlpha, floatValue);
100         }
101 
OnBackgroundColorChanged(wxColourPickerEvent & event)102         void ViewPreferencePane::OnBackgroundColorChanged(wxColourPickerEvent& event) {
103             if (IsBeingDeleted()) return;
104 
105             const Color value(fromWxColor(event.GetColour()), 1.0f);
106 
107             PreferenceManager& prefs = PreferenceManager::instance();
108             prefs.set(Preferences::BackgroundColor, value);
109         }
110 
OnShowAxesChanged(wxCommandEvent & event)111         void ViewPreferencePane::OnShowAxesChanged(wxCommandEvent& event) {
112             if (IsBeingDeleted()) return;
113 
114             const bool value = event.IsChecked();
115 
116             PreferenceManager& prefs = PreferenceManager::instance();
117             prefs.set(Preferences::ShowAxes, value);
118         }
119 
OnTextureModeChanged(wxCommandEvent & event)120         void ViewPreferencePane::OnTextureModeChanged(wxCommandEvent& event) {
121             if (IsBeingDeleted()) return;
122 
123             const int selection = m_textureModeChoice->GetSelection();
124             assert(selection >= 0);
125 
126             const size_t index = static_cast<size_t>(selection);
127             assert(index < NumTextureModes);
128             const int minFilter = TextureModes[index].minFilter;
129             const int magFilter = TextureModes[index].magFilter;
130 
131             PreferenceManager& prefs = PreferenceManager::instance();
132             prefs.set(Preferences::TextureMinFilter, minFilter);
133             prefs.set(Preferences::TextureMagFilter, magFilter);
134         }
135 
OnTextureBrowserIconSizeChanged(wxCommandEvent & event)136         void ViewPreferencePane::OnTextureBrowserIconSizeChanged(wxCommandEvent& event) {
137             if (IsBeingDeleted()) return;
138 
139             PreferenceManager& prefs = PreferenceManager::instance();
140 
141             const int selection = m_textureBrowserIconSizeChoice->GetSelection();
142             switch (selection) {
143                 case 0:
144                     prefs.set(Preferences::TextureBrowserIconSize, 0.25f);
145                     break;
146                 case 1:
147                     prefs.set(Preferences::TextureBrowserIconSize, 0.5f);
148                     break;
149                 case 2:
150                     prefs.set(Preferences::TextureBrowserIconSize, 1.0f);
151                     break;
152                 case 3:
153                     prefs.set(Preferences::TextureBrowserIconSize, 1.5f);
154                     break;
155                 case 4:
156                     prefs.set(Preferences::TextureBrowserIconSize, 2.0f);
157                     break;
158                 case 5:
159                     prefs.set(Preferences::TextureBrowserIconSize, 2.5f);
160                     break;
161                 case 6:
162                     prefs.set(Preferences::TextureBrowserIconSize, 3.0f);
163                     break;
164             }
165         }
166 
createGui()167         void ViewPreferencePane::createGui() {
168             wxWindow* viewPreferences = createViewPreferences();
169 
170             wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
171             sizer->AddSpacer(LayoutConstants::NarrowVMargin);
172             sizer->Add(viewPreferences, 1, wxEXPAND);
173             sizer->AddSpacer(LayoutConstants::WideVMargin);
174 
175             SetMinSize(sizer->GetMinSize());
176             SetSizer(sizer);
177 
178             SetBackgroundColour(*wxWHITE);
179         }
180 
createViewPreferences()181         wxWindow* ViewPreferencePane::createViewPreferences() {
182             wxPanel* viewBox = new wxPanel(this);
183             viewBox->SetBackgroundColour(*wxWHITE);
184 
185             wxStaticText* viewPrefsHeader = new wxStaticText(viewBox, wxID_ANY, "Map Views");
186             viewPrefsHeader->SetFont(viewPrefsHeader->GetFont().Bold());
187 
188             wxString layoutNames[NumFrameLayouts];
189             layoutNames[0] = "One Pane";
190             layoutNames[1] = "Two Panes";
191             layoutNames[2] = "Three Panes";
192             layoutNames[3] = "Four Panes";
193 
194             wxStaticText* layoutLabel = new wxStaticText(viewBox, wxID_ANY, "Layout");
195             m_layoutChoice = new wxChoice(viewBox, wxID_ANY, wxDefaultPosition, wxDefaultSize, NumFrameLayouts, layoutNames);
196 
197             wxStaticText* brightnessLabel = new wxStaticText(viewBox, wxID_ANY, "Brightness");
198             m_brightnessSlider = new wxSlider(viewBox, wxID_ANY, 50, 1, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_BOTTOM);
199             wxStaticText* gridLabel = new wxStaticText(viewBox, wxID_ANY, "Grid");
200             m_gridAlphaSlider = new wxSlider(viewBox, wxID_ANY, 50, 1, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_BOTTOM);
201 
202             wxStaticText* backgroundColorLabel = new wxStaticText(viewBox, wxID_ANY, "Background Color");
203             m_backgroundColorPicker = new wxColourPickerCtrl(viewBox, wxID_ANY);
204 
205             wxStaticText* axesLabel = new wxStaticText(viewBox, wxID_ANY, "Coordinate System");
206             m_showAxes = new wxCheckBox(viewBox, wxID_ANY, "Show Axes");
207 
208             wxString textureModeNames[NumTextureModes];
209             for (size_t i = 0; i < NumTextureModes; ++i)
210                 textureModeNames[i] = TextureModes[i].name;
211             wxStaticText* textureModeLabel = new wxStaticText(viewBox, wxID_ANY, "Texture Mode");
212             m_textureModeChoice = new wxChoice(viewBox, wxID_ANY, wxDefaultPosition, wxDefaultSize, NumTextureModes, textureModeNames);
213 
214             wxStaticText* textureBrowserPrefsHeader = new wxStaticText(viewBox, wxID_ANY, "Texture Browser");
215             textureBrowserPrefsHeader->SetFont(textureBrowserPrefsHeader->GetFont().Bold());
216 
217             wxStaticText* textureBrowserIconSizeLabel = new wxStaticText(viewBox, wxID_ANY, "Icon Size");
218             wxString iconSizes[7] = {"25%", "50%", "100%", "150%", "200%", "250%", "300%"};
219             m_textureBrowserIconSizeChoice = new wxChoice(viewBox, wxID_ANY, wxDefaultPosition, wxDefaultSize, 7, iconSizes);
220             m_textureBrowserIconSizeChoice->SetToolTip("Sets the icon size in the texture browser.");
221 
222 
223             const int HMargin           = LayoutConstants::WideHMargin;
224             const int LMargin           = LayoutConstants::WideVMargin;
225             const int HeaderFlags       = wxLEFT;
226             const int LabelFlags        = wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxLEFT;
227             const int SliderFlags       = wxEXPAND | wxRIGHT;
228             const int ChoiceFlags       = wxRIGHT;
229             const int CheckBoxFlags     = wxLeft;
230             const int ColorPickerFlags  = wxRIGHT;
231             const int LineFlags         = wxEXPAND | wxTOP;
232 
233             int r = 0;
234 
235             wxGridBagSizer* sizer = new wxGridBagSizer(LayoutConstants::NarrowVMargin, LayoutConstants::WideHMargin);
236             sizer->Add(viewPrefsHeader,                     wxGBPosition( r, 0), wxGBSpan(1,2), HeaderFlags, HMargin);
237             ++r;
238 
239             sizer->Add(layoutLabel,                         wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
240             sizer->Add(m_layoutChoice,                      wxGBPosition( r, 1), wxDefaultSpan, ChoiceFlags, HMargin);
241             ++r;
242 
243             sizer->Add(brightnessLabel,                     wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
244             sizer->Add(m_brightnessSlider,                  wxGBPosition( r, 1), wxDefaultSpan, SliderFlags, HMargin);
245             ++r;
246 
247             sizer->Add(gridLabel,                           wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
248             sizer->Add(m_gridAlphaSlider,                   wxGBPosition( r, 1), wxDefaultSpan, SliderFlags, HMargin);
249             ++r;
250 
251             sizer->Add(axesLabel,                           wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
252             sizer->Add(m_showAxes,                          wxGBPosition( r, 1), wxDefaultSpan, CheckBoxFlags, HMargin);
253             ++r;
254 
255             sizer->Add(backgroundColorLabel,                wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
256             sizer->Add(m_backgroundColorPicker,             wxGBPosition( r, 1), wxDefaultSpan, ColorPickerFlags, HMargin);
257             ++r;
258 
259             sizer->Add(textureModeLabel,                    wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
260             sizer->Add(m_textureModeChoice,                 wxGBPosition( r, 1), wxDefaultSpan, ChoiceFlags, HMargin);
261             ++r;
262 
263             sizer->Add(0, LayoutConstants::ChoiceSizeDelta, wxGBPosition( r, 0), wxGBSpan(1,2));
264             ++r;
265 
266             sizer->Add(new BorderLine(viewBox),             wxGBPosition( r, 0), wxGBSpan(1,2), LineFlags, LMargin);
267             ++r;
268 
269             sizer->Add(textureBrowserPrefsHeader,           wxGBPosition( r, 0), wxGBSpan(1,2), HeaderFlags, HMargin);
270             ++r;
271 
272             sizer->Add(textureBrowserIconSizeLabel,         wxGBPosition( r, 0), wxDefaultSpan, LabelFlags, HMargin);
273             sizer->Add(m_textureBrowserIconSizeChoice,      wxGBPosition( r, 1), wxDefaultSpan, ChoiceFlags, HMargin);
274             ++r;
275 
276             sizer->Add(0, LayoutConstants::ChoiceSizeDelta, wxGBPosition( r, 0), wxGBSpan(1,2));
277 
278             sizer->AddGrowableCol(1);
279             sizer->SetMinSize(500, wxDefaultCoord);
280             viewBox->SetSizer(sizer);
281             return viewBox;
282         }
283 
bindEvents()284         void ViewPreferencePane::bindEvents() {
285             m_layoutChoice->Bind(wxEVT_CHOICE, &ViewPreferencePane::OnLayoutChanged, this);
286 
287             bindSliderEvents(m_brightnessSlider, &ViewPreferencePane::OnBrightnessChanged, this);
288             bindSliderEvents(m_gridAlphaSlider, &ViewPreferencePane::OnGridAlphaChanged, this);
289 
290             m_backgroundColorPicker->Bind(wxEVT_COLOURPICKER_CHANGED, &ViewPreferencePane::OnBackgroundColorChanged, this);
291             m_showAxes->Bind(wxEVT_CHECKBOX, &ViewPreferencePane::OnShowAxesChanged, this);
292 
293             m_textureModeChoice->Bind(wxEVT_CHOICE, &ViewPreferencePane::OnTextureModeChanged, this);
294             m_textureBrowserIconSizeChoice->Bind(wxEVT_CHOICE, &ViewPreferencePane::OnTextureBrowserIconSizeChanged, this);
295         }
296 
doCanResetToDefaults()297         bool ViewPreferencePane::doCanResetToDefaults() {
298             return true;
299         }
300 
doResetToDefaults()301         void ViewPreferencePane::doResetToDefaults() {
302             PreferenceManager& prefs = PreferenceManager::instance();
303             prefs.resetToDefault(Preferences::Brightness);
304             prefs.resetToDefault(Preferences::GridAlpha);
305             prefs.resetToDefault(Preferences::BackgroundColor);
306             prefs.resetToDefault(Preferences::ShowAxes);
307             prefs.resetToDefault(Preferences::TextureMinFilter);
308             prefs.resetToDefault(Preferences::TextureMagFilter);
309             prefs.resetToDefault(Preferences::TextureBrowserIconSize);
310         }
311 
doUpdateControls()312         void ViewPreferencePane::doUpdateControls() {
313             m_layoutChoice->SetSelection(pref(Preferences::MapViewLayout));
314 
315             m_brightnessSlider->SetValue(static_cast<int>(pref(Preferences::Brightness) * 40.0f));
316             m_gridAlphaSlider->SetValue(static_cast<int>(pref(Preferences::GridAlpha) * m_gridAlphaSlider->GetMax()));
317 
318             m_backgroundColorPicker->SetColour(toWxColor(pref(Preferences::BackgroundColor)));
319             m_showAxes->SetValue(pref(Preferences::ShowAxes));
320 
321             const size_t textureModeIndex = findTextureMode(pref(Preferences::TextureMinFilter), pref(Preferences::TextureMagFilter));
322             assert(textureModeIndex < NumTextureModes);
323             m_textureModeChoice->SetSelection(static_cast<int>(textureModeIndex));
324 
325             const float textureBrowserIconSize = pref(Preferences::TextureBrowserIconSize);
326             if (textureBrowserIconSize == 0.25f)
327                 m_textureBrowserIconSizeChoice->SetSelection(0);
328             else if (textureBrowserIconSize == 0.5f)
329                 m_textureBrowserIconSizeChoice->SetSelection(1);
330             else if (textureBrowserIconSize == 1.5f)
331                 m_textureBrowserIconSizeChoice->SetSelection(3);
332             else if (textureBrowserIconSize == 2.0f)
333                 m_textureBrowserIconSizeChoice->SetSelection(4);
334             else if (textureBrowserIconSize == 2.5f)
335                 m_textureBrowserIconSizeChoice->SetSelection(5);
336             else if (textureBrowserIconSize == 3.0f)
337                 m_textureBrowserIconSizeChoice->SetSelection(6);
338             else
339                 m_textureBrowserIconSizeChoice->SetSelection(2);
340         }
341 
doValidate()342         bool ViewPreferencePane::doValidate() {
343             return true;
344         }
345 
findTextureMode(const int minFilter,const int magFilter) const346         size_t ViewPreferencePane::findTextureMode(const int minFilter, const int magFilter) const {
347             for (size_t i = 0; i < NumTextureModes; ++i)
348                 if (TextureModes[i].minFilter == minFilter &&
349                     TextureModes[i].magFilter == magFilter)
350                     return i;
351             return NumTextureModes;
352         }
353 	}
354 }
355