OpenCPN Partial API docs
Loading...
Searching...
No Matches
user_colors_dlg.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2025 Alec Leamas *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
23#include <functional>
24#include <iostream>
25
26#include <wx/button.h>
27#include <wx/clrpicker.h>
28#include <wx/frame.h>
29#include <wx/panel.h>
30#include <wx/sizer.h>
31#include <wx/statline.h>
32#include <wx/stattext.h>
33
34#include "model/config_vars.h"
35#include "model/gui_events.h"
36#include "model/navmsg_filter.h"
37
38#include "user_colors_dlg.h"
39#include "tty_scroll.h"
40
41static constexpr const char* const kDialogName = "DataMonitorColors";
42
43const static NavmsgStatus kOkStatus =
44 NavmsgStatus(NavmsgStatus::Direction::kHandled);
45const static NavmsgStatus kNotOkStatus =
46 NavmsgStatus(NavmsgStatus::State::kMalformed);
47const static NavmsgStatus kNoOutputStatus =
48 NavmsgStatus(NavmsgStatus::Accepted::kFilteredNoOutput);
49const static NavmsgStatus kDroppedStatus =
50 NavmsgStatus(NavmsgStatus::Accepted::kFilteredDropped);
51const static NavmsgStatus kOutputStatus =
52 NavmsgStatus(NavmsgStatus::Direction::kOutput);
53const static NavmsgStatus kInputStatus =
54 NavmsgStatus(NavmsgStatus::Direction::kInput);
55
57class UserColoursDlg : public wxFrame {
58public:
59 explicit UserColoursDlg(wxWindow* parent)
60 : wxFrame(parent, wxID_ANY, _("Data Monitor: colours setup")),
61 m_top_panel(nullptr) {
62 wxWindow::SetName(kDialogName);
63 auto on_apply = [&] { m_top_panel->Apply(); };
64 auto on_ok = [&] {
65 m_top_panel->Apply();
66 Destroy();
67 };
68 auto on_cancel = [&] {
69 m_top_panel->Cancel();
70 Destroy();
71 };
72 auto vbox = new wxBoxSizer(wxVERTICAL);
73 auto buttons = new ButtonSizer(this, on_ok, on_apply, on_cancel);
74 m_top_panel = new TopPanel(this);
75 vbox->Add(m_top_panel, wxSizerFlags(1).Border().Expand());
76 vbox->Add(new wxStaticLine(this, wxID_ANY), wxSizerFlags(0).Expand());
77 vbox->Add(buttons, wxSizerFlags(0).Expand().Border());
78 SetSizer(vbox);
79 wxWindow::Fit();
80 }
81
82private:
83 using ButtonHandler = std::function<void()>;
84
86 class StoredConfig {
87 public:
88 StoredConfig() { Load(); }
89
90 void Load() {
91 dm_dropped = g_dm_dropped;
92 dm_filtered = g_dm_filtered;
93 dm_input = g_dm_input;
94 dm_not_ok = g_dm_not_ok;
95 dm_ok = g_dm_ok;
96 dm_output = g_dm_output;
97 }
98
99 void Unload() {
100 g_dm_dropped = WorkValue(dm_dropped, kDroppedStatus);
101 g_dm_filtered = WorkValue(dm_filtered, kNoOutputStatus);
102 g_dm_input = WorkValue(dm_input, kInputStatus);
103 g_dm_not_ok = WorkValue(dm_not_ok, kNotOkStatus);
104 g_dm_ok = WorkValue(dm_ok, kOkStatus);
105 g_dm_output = WorkValue(dm_output, kOutputStatus);
106 }
107
108 private:
109 unsigned dm_dropped;
110 unsigned dm_filtered;
111 unsigned dm_input;
112 unsigned dm_not_ok;
113 unsigned dm_ok;
114 unsigned dm_output;
115
116 UserColorsByState default_colors;
117
118 unsigned WorkValue(unsigned stored_value, NavmsgStatus ns) {
119 if (stored_value == kUndefinedColor) return default_colors(ns).GetRGB();
120 return stored_value;
121 }
122 };
123
125 class TopPanel : public wxPanel {
126 public:
127 explicit TopPanel(wxWindow* parent) : wxPanel(parent) {
128 auto grid = new wxGridSizer(2);
129
130 m_msg_ok_pick = AddGridRow(grid, _("Input - OK"), kOkStatus);
131 m_msg_not_ok_pick = AddGridRow(grid, _("Errors"), kNotOkStatus);
132 m_msg_filtered_pick =
133 AddGridRow(grid, _("Filtered, no output"), kNoOutputStatus);
134 m_msg_dropped_pick =
135 AddGridRow(grid, _("Filtered, dropped"), kDroppedStatus);
136 m_msg_output_pick = AddGridRow(grid, _("Output"), kOutputStatus);
137 m_msg_input_pick = AddGridRow(grid, _("Input event"), kInputStatus);
138
139 auto reset_btn = new wxButton(this, wxID_UNDO, _("Restore defaults"));
140 reset_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
141 [&](wxCommandEvent&) { Reset(); });
142 grid->Add(reset_btn);
143
144 SetSizer(grid);
145 }
146
148 void Apply() const {
149 g_dm_ok = m_msg_ok_pick->GetRgb();
150 g_dm_not_ok = m_msg_not_ok_pick->GetRgb();
151 g_dm_filtered = m_msg_filtered_pick->GetRgb();
152 g_dm_dropped = m_msg_dropped_pick->GetRgb();
153 g_dm_output = m_msg_output_pick->GetRgb();
154 g_dm_input = m_msg_input_pick->GetRgb();
155 GuiEvents::GetInstance().on_dm_colors_change.Notify();
156 }
157
159 void Cancel() {
160 m_stored_config.Unload();
161 m_msg_ok_pick->SetColor(g_dm_ok);
162 m_msg_not_ok_pick->SetColor(g_dm_not_ok);
163 m_msg_filtered_pick->SetColor(g_dm_filtered);
164 m_msg_dropped_pick->SetColor(g_dm_dropped);
165 m_msg_output_pick->SetColor(g_dm_output);
166 m_msg_input_pick->SetColor(g_dm_input);
167 }
168
170 void Reset() {
171 m_msg_ok_pick->SetColour(m_std_colors(kOkStatus));
172 m_msg_not_ok_pick->SetColour(m_std_colors(kNotOkStatus));
173 m_msg_filtered_pick->SetColour(m_std_colors(kNoOutputStatus));
174 m_msg_dropped_pick->SetColour(m_std_colors(kDroppedStatus));
175 m_msg_output_pick->SetColour(m_std_colors(kOutputStatus));
176 m_msg_input_pick->SetColour(m_std_colors(kInputStatus));
177 m_stored_config.Load();
178 }
179
180 private:
182 class ColorPicker : public wxColourPickerCtrl {
183 public:
184 ColorPicker(wxWindow* parent, const wxColour& c)
185 : wxColourPickerCtrl(parent, wxID_ANY, c) {}
186
187 void SetColor(unsigned rgb) { SetColour(wxColour(rgb)); }
188
189 [[nodiscard]] unsigned GetRgb() const {
190 return static_cast<unsigned>(GetColour().GetRGB());
191 }
192 };
193
194 ColorPicker* m_msg_ok_pick;
195 ColorPicker* m_msg_not_ok_pick;
196 ColorPicker* m_msg_filtered_pick;
197 ColorPicker* m_msg_dropped_pick;
198 ColorPicker* m_msg_output_pick;
199 ColorPicker* m_msg_input_pick;
200
201 UserColorsByState m_colors;
202 StdColorsByState m_std_colors;
203 StoredConfig m_stored_config;
204
205 ColorPicker* AddGridRow(wxGridSizer* grid, const char* label,
206 NavmsgStatus ns) {
207 grid->Add(new wxStaticText(this, wxID_ANY, label));
208 auto picker = new ColorPicker(this, m_colors(ns));
209 grid->Add(picker);
210 return picker;
211 }
212 };
213
215 class ButtonSizer : public wxStdDialogButtonSizer {
216 public:
217 ButtonSizer(wxWindow* parent, ButtonHandler on_ok, ButtonHandler on_apply,
218 ButtonHandler on_cancel)
219 : wxStdDialogButtonSizer(),
220 m_on_ok(std::move(on_ok)),
221 m_on_apply(std::move(on_apply)),
222 m_on_cancel(std::move(on_cancel)) {
223 auto ok_btn = new wxButton(parent, wxID_OK);
224 ok_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
225 [&](wxCommandEvent& ev) { m_on_ok(); });
226 AddButton(ok_btn);
227 auto cancel_btn = new wxButton(parent, wxID_CANCEL);
228 cancel_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
229 [&](wxCommandEvent& ev) { m_on_cancel(); });
230 AddButton(cancel_btn);
231 auto apply_btn = new wxButton(parent, wxID_APPLY);
232 apply_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
233 [&](wxCommandEvent& ev) { m_on_apply(); });
234 AddButton(apply_btn);
235 Realize();
236 }
237
238 protected:
239 ButtonHandler m_on_ok;
240 ButtonHandler m_on_apply;
241 ButtonHandler m_on_cancel;
242 };
243
244private:
245 TopPanel* m_top_panel;
246};
247
248wxFrame* UserColorsDlg(wxWindow* parent) {
249 auto current_dlg = wxWindow::FindWindowByName(kDialogName);
250 if (current_dlg) {
251 current_dlg->Raise();
252 return nullptr;
253 } else {
254 auto dialog = new UserColoursDlg(parent);
255 dialog->Show();
256 return dialog;
257 }
258}
void Notify() override
Notify all listeners, no data supplied.
EventVar on_dm_colors_change
Notified without arguments when the global variables housing the Data Monitor user defined colors are...
Definition gui_events.h:62
Representation of message status as determined by the multiplexer.
The standard colors handler functor.
Definition tty_scroll.h:61
Dialog top frame.
Global variables stored in configuration file.
Misc GUI event vars, a singleton.
Data monitor filter definitions.
Scrolled tty like window for logging.
wxFrame * UserColorsDlg(wxWindow *parent)
Run the Data Monitor dialog for user defined colors.