114 const unsigned m_size;
115 const fs::path m_svg_dir;
119 static unsigned GetSize(
const wxWindow* parent) {
120 double size = parent->GetCharHeight() * (IsWindows() ? 1.3 : 1.0);
121#if wxCHECK_VERSION(3, 1, 2)
124 size *=
static_cast<double>(parent->ToDIP(100)) / 100.;
128 double pixel_per_mm =
130 size = std::max(size, 7.0 * pixel_per_mm);
132 return static_cast<unsigned>(size);
135 [[nodiscard]] wxBitmap LoadIcon(
const std::string& filename)
const {
136 fs::path path = m_svg_dir / filename;
137 return LoadSVG(path.string(), m_size, m_size);
140 [[nodiscard]] wxBitmap IconApplyColorScheme(
const wxBitmap& proto)
const {
141 if (!proto.IsOk())
return wxNullBitmap;
142 if ((m_cs != GLOBAL_COLOR_SCHEME_DAY) &&
143 (m_cs != GLOBAL_COLOR_SCHEME_RGB)) {
145 const wxImage image = proto.ConvertToImage();
146 unsigned char* data = image.GetData();
147 unsigned char* p_idata = data;
148 for (
int i = 0; i < image.GetSize().y; i++) {
149 for (
int j = 0; j < image.GetSize().x; j++) {
150 unsigned char v = *p_idata;
167 explicit StdIcons(
const wxWindow* parent)
168 : m_size(GetSize(parent)),
169 m_svg_dir(fs::path(g_Platform->GetSharedDataDir().ToStdString()) /
170 "uidata" /
"MUI_flat"),
171 m_cs(GLOBAL_COLOR_SCHEME_RGB),
172 trash_bin_proto(LoadIcon(
"trash_bin.svg")),
173 settings_proto(LoadIcon(
"setting_gear.svg")),
174 filled_circle_proto(LoadIcon(
"circle-on.svg")),
175 open_circle_proto(LoadIcon(
"circle-off.svg")),
176 exclaim_mark_proto(LoadIcon(
"exclaim_mark.svg")),
177 x_mult_proto(LoadIcon(
"X_mult.svg")),
178 check_mark_proto(LoadIcon(
"check_mark.svg")) {
179 trash_bin = trash_bin_proto;
180 settings = settings_proto;
181 filled_circle = filled_circle_proto;
182 open_circle = open_circle_proto;
183 exclaim_mark = exclaim_mark_proto;
184 x_mult = x_mult_proto;
185 check_mark = check_mark_proto;
188 void SetColorScheme(
const ColorScheme cs) {
191 trash_bin = IconApplyColorScheme(trash_bin_proto);
192 settings = IconApplyColorScheme(settings_proto);
193 filled_circle = IconApplyColorScheme(filled_circle_proto);
194 open_circle = IconApplyColorScheme(open_circle_proto);
195 exclaim_mark = IconApplyColorScheme(exclaim_mark_proto);
196 x_mult = IconApplyColorScheme(x_mult_proto);
197 check_mark = IconApplyColorScheme(check_mark_proto);
201 const wxBitmap trash_bin_proto;
202 const wxBitmap settings_proto;
203 const wxBitmap filled_circle_proto;
204 const wxBitmap open_circle_proto;
205 const wxBitmap exclaim_mark_proto;
206 const wxBitmap x_mult_proto;
207 const wxBitmap check_mark_proto;
211 wxBitmap filled_circle;
212 wxBitmap open_circle;
213 wxBitmap exclaim_mark;
346 const std::vector<ConnectionParams*>& connections,
350 : wxGrid(parent, wxID_ANY),
351 m_connections(connections),
352 m_header_column_widths({0, 0, 0, 0, 0, 0, 0}),
353 m_last_tooltip_cell(100),
354 m_cs(GLOBAL_COLOR_SCHEME_DAY),
355 m_on_conn_delete(on_conn_update),
357 m_on_edit_conn(on_edit_conn) {
358 ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_NEVER);
359 SetTable(
new wxGridStringTable(),
false);
360 GetTable()->AppendCols(8);
363 SetDefaultRowSize(wxWindow::GetCharHeight() * 2);
364 SetColLabelSize(wxWindow::GetCharHeight() * 2);
366 static const std::array<wxString, 7> headers = {
367 "", _(
"Protocol") +
" ", _(
"In/Out"), _(
"Data port"), _(
"Status"),
"",
370 for (
auto hdr = headers.begin(); hdr != headers.end(); hdr++, ic++) {
371 SetColLabelValue(
static_cast<int>(hdr - headers.begin()), *hdr);
372 unsigned col_width = hdr->Length() * wxWindow::GetCharWidth();
373 col_width = wxMax(col_width, 6 * wxWindow::GetCharWidth());
374 m_header_column_widths[ic] =
static_cast<int>(col_width);
375 SetColSize(ic,
static_cast<int>(col_width));
379 SetLabelBackgroundColour(GetGlobalColor(
"DILG1"));
380 SetLabelTextColour(GetGlobalColor(
"DILG3"));
383 SetColAttributes(parent);
386 DisableDragColSize();
387 DisableDragRowSize();
388 wxWindow::Show(GetNumberRows() > 0);
390 GetGridWindow()->Bind(wxEVT_MOTION, [&](wxMouseEvent& ev) {
394 GetGridWindow()->Bind(wxEVT_MOUSEWHEEL,
395 [&](
const wxMouseEvent& ev) {
OnWheel(ev); });
397 Bind(wxEVT_GRID_LABEL_LEFT_CLICK,
398 [&](wxGridEvent& ev) { HandleSort(ev.GetCol()); });
399 Bind(wxEVT_GRID_CELL_LEFT_CLICK,
400 [&](wxGridEvent& ev) { OnClickCell(ev.GetRow(), ev.GetCol()); });
401 Bind(wxEVT_PAINT, [&](wxPaintEvent& ev) {
402 SetColAttributes(
dynamic_cast<const wxWindow*
>(ev.GetEventObject()));
405 conn_change_lstnr.
Init(
407 [&](
ObservedEvt&) { OnConnectionChange(m_connections); });
409 void SetColorScheme(
const ColorScheme cs) {
411 m_icons.SetColorScheme(cs);
415 wxSize GetEstimatedSize()
const {
417 for (
auto s : m_header_column_widths) rs += s;
418 return {
static_cast<int>(rs), -1};
424 dynamic_cast<wxScrolledWindow*
>(FindWindowByName(TopScrollWindowName));
425 assert(w &&
"No TopScroll window found");
428 w->GetViewStart(&xpos, &ypos);
431 w->GetScrollPixelsPerUnit(&x, &y);
433 const int dir = ev.GetWheelRotation();
434 w->Scroll(-1, ypos - dir / y / 4);
438 void ReloadGrid(
const std::vector<ConnectionParams*>& connections) {
440 m_renderer_status_vector.clear();
442 for (
auto it = connections.begin(); it != connections.end(); ++it) {
443 const auto row =
static_cast<int>(it - connections.begin());
445 SetCellValue(row, 0, (*it)->bEnabled ?
"1" :
"");
447 m_tooltips[row][0] = _(
"Enabled, click to disable");
449 m_tooltips[row][0] = _(
"Disabled, click to enable");
450 std::string protocol = NavAddr::BusToString((*it)->GetCommProtocol());
451 SetCellValue(row, 1, protocol);
452 SetCellValue(row, 2, (*it)->GetIOTypeValueStr());
453 SetCellValue(row, 3, (*it)->GetStrippedDSPort());
454 m_tooltips[row][3] = (*it)->UserComment;
456 m_tooltips[row][5] = _(
"Edit connection");
458 m_tooltips[row][6] = _(
"Delete connection");
459 SetCellValue(row, 7, (*it)->GetKey());
462 stat_renderer->status = ConnState::Disabled;
463 m_renderer_status_vector.push_back(stat_renderer);
464 SetCellRenderer(row, 4, stat_renderer);
466 wxString sp(protocol);
467 unsigned size = sp.Length() * wxWindow::GetCharWidth();
468 m_header_column_widths[1] = std::max(m_header_column_widths[1], size);
469 size = (*it)->GetIOTypeValueStr().Length() * wxWindow::GetCharWidth();
470 m_header_column_widths[2] = std::max(m_header_column_widths[2], size);
471 sp = wxString((*it)->GetStrippedDSPort());
472 size = sp.Length() * wxWindow::GetCharWidth();
473 m_header_column_widths[3] = std::max(m_header_column_widths[3], size);
476 OnConnectionChange(m_connections);
480 for (
auto val : m_header_column_widths) {
481 SetColSize(ic,
static_cast<int>(val));
492 : m_conns(connections) {}
497 if (row1 == -1 && row2 == -1)
return false;
498 if (row1 == -1)
return false;
499 if (row2 == -1)
return true;
500 const int v1 = m_conns->GetCellValue(row1, 4)[0];
501 const int v2 = m_conns->GetCellValue(row2, 4)[0];
514 auto found = find_if(
515 m_connections.begin(), m_connections.end(),
517 if (found == m_connections.end())
return -1;
518 return static_cast<int>(found - m_connections.begin());
527 auto found = find_if(m_connections.begin(), m_connections.end(),
529 return GetCellValue(row, 7) == p->GetKey();
531 return found != m_connections.end() ? *found :
nullptr;
538 void EnsureRows(
size_t rows) {
539 for (
unsigned i = m_tooltips.size(); i <= rows; i++)
540 m_tooltips.emplace_back(std::vector<std::string>(7));
541 for (
unsigned i = GetNumberRows(); i <= rows; i++) AppendRows(1,
false);
545 void SetColAttributes(
const wxWindow* parent) {
548 SetDefaultCellBackgroundColour(GetGlobalColor(
"DILG1"));
550 auto enable_attr =
new wxGridCellAttr();
551 enable_attr->SetAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
554 enable_attr->SetRenderer(
557 enable_attr->SetRenderer(
new wxGridCellBoolRenderer());
559 enable_attr->SetEditor(
new wxGridCellBoolEditor());
560 if (IsWindows()) enable_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
561 SetColAttr(0, enable_attr);
563 auto protocol_attr =
new wxGridCellAttr();
564 protocol_attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTRE);
565 protocol_attr->SetReadOnly(
true);
567 protocol_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
568 SetColAttr(1, protocol_attr);
570 auto in_out_attr =
new wxGridCellAttr();
571 in_out_attr->SetAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
572 in_out_attr->SetReadOnly(
true);
573 if (IsWindows()) in_out_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
574 SetColAttr(2, in_out_attr);
576 auto port_attr =
new wxGridCellAttr();
577 port_attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTRE);
578 port_attr->SetReadOnly(
true);
579 if (IsWindows()) port_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
580 SetColAttr(3, port_attr);
582 auto status_attr =
new wxGridCellAttr();
583 status_attr->SetAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
584 status_attr->SetReadOnly(
true);
585 status_attr->SetFont(parent->GetFont().Scale(1.3));
586 if (IsWindows()) status_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
587 SetColAttr(4, status_attr);
589 auto edit_attr =
new wxGridCellAttr();
590 edit_attr->SetAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
591 edit_attr->SetFont(parent->GetFont().Scale(1.3));
592 edit_attr->SetReadOnly(
true);
593 if (IsWindows()) edit_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
594 SetColAttr(5, edit_attr);
596 auto delete_attr =
new wxGridCellAttr();
597 delete_attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTRE);
598 delete_attr->SetFont(parent->GetFont().Scale(1.3));
599 delete_attr->SetTextColour(*wxRED);
600 delete_attr->SetReadOnly(
true);
601 if (IsWindows()) delete_attr->SetBackgroundColour(GetGlobalColor(
"DILG1"));
602 SetColAttr(6, delete_attr);
606 void OnClickCell(
int row,
int col) {
611 }
else if (col == 6) {
617 void OnMouseMove(
const wxMouseEvent& ev) {
618 const wxPoint pt = ev.GetPosition();
619 int row = YToRow(pt.y);
620 int col = XToCol(pt.x);
621 if (col < 0 || col >= 7 || row < 0 || row >= GetNumberRows())
return;
622 if (row * 7 + col == m_last_tooltip_cell)
return;
623 m_last_tooltip_cell = row * 7 + col;
624 GetGridWindow()->SetToolTip(m_tooltips[row][col]);
628 void OnConnectionChange(
const std::vector<ConnectionParams*>& connections) {
629 bool refresh_needed =
false;
630 for (
auto it = connections.begin(); it != connections.end(); ++it) {
631 ConnState state = m_conn_states.GetDriverState(
632 (*it)->GetCommProtocol(), (*it)->GetStrippedDSPort());
633 if (!(*it)->bEnabled) state = ConnState::Disabled;
634 auto row =
static_cast<int>(it - connections.begin());
636 if (
static_cast<int>(m_renderer_status_vector.size()) < row + 1)
continue;
638 case ConnState::Disabled:
639 if (m_renderer_status_vector[row]->status != ConnState::Disabled) {
640 m_renderer_status_vector[row]->SetBitmap(m_icons.filled_circle);
641 m_renderer_status_vector[row]->status = ConnState::Disabled;
642 refresh_needed =
true;
644 m_tooltips[row][4] = _(
"Disabled");
646 case ConnState::NoStats:
647 if (m_renderer_status_vector[row]->status != ConnState::NoStats) {
648 m_renderer_status_vector[row]->SetBitmap(m_icons.open_circle);
649 m_renderer_status_vector[row]->status = ConnState::NoStats;
650 refresh_needed =
true;
652 m_tooltips[row][4] = _(
"No driver statistics available");
654 case ConnState::NoData:
655 if (m_renderer_status_vector[row]->status != ConnState::NoData) {
656 m_renderer_status_vector[row]->SetBitmap(m_icons.exclaim_mark);
657 m_renderer_status_vector[row]->status = ConnState::NoData;
658 refresh_needed =
true;
660 m_tooltips[row][4] = _(
"No data flowing through connection");
662 case ConnState::Unavailable:
663 if (m_renderer_status_vector[row]->status != ConnState::Unavailable) {
664 m_renderer_status_vector[row]->SetBitmap(m_icons.x_mult);
665 m_renderer_status_vector[row]->status = ConnState::Unavailable;
666 refresh_needed =
true;
668 m_tooltips[row][4] = _(
"The device is unavailable");
671 if (m_renderer_status_vector[row]->status != ConnState::Ok) {
672 m_renderer_status_vector[row]->SetBitmap(m_icons.check_mark);
673 m_renderer_status_vector[row]->status = ConnState::Ok;
674 refresh_needed =
true;
676 m_tooltips[row][4] = _(
"Data is flowing");
680 if (refresh_needed) ForceRefresh();
684 void SetSortingColumn(
int col) {
685 if (GetSortingColumn() != wxNOT_FOUND) {
686 int old_col = GetSortingColumn();
687 auto label = GetColLabelValue(old_col);
688 if (label[0] == UtfArrowDown()[0])
689 SetColLabelValue(old_col, label.substr(2));
691 auto label = GetColLabelValue(col);
692 if (label[0] != UtfArrowDown()[0])
693 SetColLabelValue(col, UtfArrowDown() +
" " + label);
694 wxGrid::SetSortingColumn(col);
699 void HandleSort(
int col) {
701 auto& params = TheConnectionParams();
703 std::sort(params.begin(), params.end(),
ConnCompare(col));
705 std::sort(params.begin(), params.end(), ConnStateCompare(
this));
707 SetSortingColumn(col);
711 void HandleEnable(
int row) {
714 cp->bEnabled = !cp->bEnabled;
715 cp->b_IsSetup = FALSE;
716 SetCellValue(row, 0, cp->bEnabled ?
"1" :
"");
718 m_tooltips[row][0] = _(
"Enabled, click to disable");
720 m_tooltips[row][0] = _(
"Disabled, click to enable");
722 stats.driver_iface = cp->GetStrippedDSPort();
723 stats.driver_bus = cp->GetCommProtocol();
724 m_conn_states.HandleDriverStats(stats);
725 StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
727 cp->b_IsSetup =
true;
729 SetCellValue(row, 4, UtfFilledCircle());
736 void HandleEdit(
int row) {
738 Show(GetNumberRows() > 0);
739 m_on_edit_conn(cp,
true);
744 void HandleDelete(
int row) {
746 auto found = std::find(m_connections.begin(), m_connections.end(), cp);
747 if (found != m_connections.end()) {
748 std::stringstream ss;
749 ss << _(
"Ok to delete connection on ") << (*found)->GetStrippedDSPort();
750 int rcode = OCPNMessageBox(
this, ss.str(), _(
"Delete connection?"),
752 if (rcode != wxID_OK && rcode != wxID_YES)
return;
753 delete (*found)->m_optionsPanel;
754 StopAndRemoveCommDriver((*found)->GetStrippedDSPort(),
755 (*found)->GetCommProtocol());
756 TheConnectionParams().erase(found);
757 if (GetNumberRows() >
static_cast<int>(m_connections.size()))
758 DeleteRows(GetNumberRows() - 1);
759 m_on_conn_delete.
Notify();
764 std::vector<std::vector<std::string>> m_tooltips;
766 const std::vector<ConnectionParams*>& m_connections;
767 std::array<unsigned, 7> m_header_column_widths;
768 int m_last_tooltip_cell;
772 std::vector<BitmapCellRenderer*> m_renderer_status_vector;
883 : wxPanel(parent, wxID_ANY) {
884 auto sizer =
new wxStaticBoxSizer(wxVERTICAL,
this,
"");
885 sizer->Add(
new BearingsCheckbox(
this), wxSizerFlags().Expand());
886 sizer->Add(
new ExtraRmbRmcLine(
this), wxSizerFlags().Expand());
887 sizer->Add(
new NmeaFilterRow(
this), wxSizerFlags().Expand());
888 sizer->Add(
new TalkerIdRow(
this), wxSizerFlags().Expand());
889 sizer->Add(
new NetmaskRow(
this), wxSizerFlags().Expand());
891 wxWindow::SetMaxSize(max_size);
896 class BearingsCheckbox :
public wxCheckBox,
public ApplyCancel {
898 explicit BearingsCheckbox(wxWindow* parent)
899 : wxCheckBox(parent, wxID_ANY,
900 _(
"Use magnetic bearing in output sentence APB")) {
901 wxCheckBox::SetValue(g_bMagneticAPB);
904 void Apply()
override { g_bMagneticAPB = GetValue(); }
905 void Cancel()
override { SetValue(g_bMagneticAPB); }
908 class ExtraRmbRmcLine :
public wxPanel {
909 class RmbRmcCheckbox :
public wxCheckBox,
public ApplyCancel {
911 explicit RmbRmcCheckbox(wxWindow* parent)
912 : wxCheckBox(parent, wxID_ANY,
913 _(
"Always send RMB and RMC NMEA0183 data")) {
914 wxCheckBox::SetValue(g_always_send_rmb_rmc);
917 void Apply()
override { g_always_send_rmb_rmc = GetValue(); }
918 void Cancel()
override { SetValue(g_always_send_rmb_rmc); }
922 explicit ExtraRmbRmcLine(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
923 auto hbox =
new wxBoxSizer(wxHORIZONTAL);
924 hbox->Add(
new RmbRmcCheckbox(
this), wxSizerFlags().Expand());
925 hbox->Add(1, 1, 1, wxEXPAND);
926 hbox->Add(
new InfoButton(
this, g_btouch, kInfoHeader, kInfo),
927 wxSizerFlags().Border());
933 class ExtraRmbRmcCheckbox final :
public wxCheckBox,
public ApplyCancel {
935 explicit ExtraRmbRmcCheckbox(wxWindow* parent)
936 : wxCheckBox(parent, wxID_ANY,
937 _(
"Always send RMB and RMC NMEA0183 data")) {
938 wxCheckBox::SetValue(g_always_send_rmb_rmc);
941 void Apply()
override { g_always_send_rmb_rmc = GetValue(); }
942 void Cancel()
override { SetValue(g_always_send_rmb_rmc); }
946 class NmeaFilterRow :
public wxPanel,
public ApplyCancel {
947 wxCheckBox* checkbox;
948 wxTextCtrl* filter_period;
951 explicit NmeaFilterRow(wxWindow* parent) : wxPanel(parent) {
952 auto hbox =
new wxBoxSizer(wxHORIZONTAL);
953 checkbox =
new wxCheckBox(
955 _(
"Filter NMEA course and speed data. Filter period: "));
956 checkbox->SetValue(g_bfilter_cogsog);
957 hbox->Add(checkbox, wxSizerFlags().Align(wxALIGN_CENTRE));
959 new wxTextCtrl(
this, wxID_ANY,
"", wxDefaultPosition,
960 wxSize(50, 3 * wxWindow::GetCharWidth()), 0);
961 filter_period->SetValue(std::to_string(g_COGFilterSec));
962 hbox->Add(filter_period, wxSizerFlags().Border());
964 NmeaFilterRow::Cancel();
967 void Apply()
override {
968 std::stringstream ss;
969 ss << filter_period->GetValue();
970 ss >> g_COGFilterSec;
971 g_bfilter_cogsog = checkbox->GetValue();
974 void Cancel()
override {
975 std::stringstream ss;
976 ss << g_COGFilterSec;
977 filter_period->SetValue(ss.str());
978 checkbox->SetValue(g_bfilter_cogsog);
983 class TalkerIdRow :
public wxPanel,
public ApplyCancel {
984 wxTextCtrl* text_ctrl;
987 explicit TalkerIdRow(wxWindow* parent) : wxPanel(parent) {
988 auto hbox =
new wxBoxSizer(wxHORIZONTAL);
989 hbox->Add(
new wxStaticText(
this, wxID_ANY, _(
"NMEA 0183 Talker Id: ")),
990 wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL).Border());
991 text_ctrl =
new wxTextCtrl(
992 this, wxID_ANY,
"", wxDefaultPosition,
993 wxSize(4 * wxWindow::GetCharWidth(), 3 * wxWindow::GetCharWidth()));
994 text_ctrl->SetToolTip(
995 _(
"Enter a two-letter talker ID to override the default ID in NMEA "
996 "sentences generated by OpenCPN (e.g., GP, HC, EC). This affects "
997 "only sentences created by OpenCPN, not those forwarded from other "
999 text_ctrl->SetValue(g_TalkerIdText);
1000 hbox->Add(text_ctrl, wxSizerFlags().Border());
1002 TalkerIdRow::Cancel();
1005 void Apply()
override { g_TalkerIdText = text_ctrl->GetValue(); }
1006 void Cancel()
override { text_ctrl->SetValue(g_TalkerIdText); }
1010 class NetmaskRow :
public wxPanel,
public ApplyCancel {
1012 explicit NetmaskRow(wxWindow* parent)
1014 m_spin_ctrl(
new wxSpinCtrl(
this, wxID_ANY)),
1015 m_text(
new wxStaticText(
this, wxID_ANY,
"")) {
1016 m_spin_ctrl->SetRange(8, 32);
1017 auto hbox =
new wxBoxSizer(wxHORIZONTAL);
1018 auto flags = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL).Border();
1019 hbox->Add(
new wxStaticText(
this, wxID_ANY, _(
"Netmask: ")), flags);
1020 hbox->Add(m_text, flags);
1021 hbox->Add(
new wxStaticText(
this, wxID_ANY, _(
"length (bits): ")), flags);
1022 hbox->Add(m_spin_ctrl, flags);
1024 NetmaskRow::Cancel();
1026 Bind(wxEVT_SPINCTRL, [&](wxSpinEvent&) {
1027 m_text->SetLabel(BitsToDottedMask(m_spin_ctrl->GetValue()));
1032 void Apply()
override { g_netmask_bits = m_spin_ctrl->GetValue(); }
1034 void Cancel()
override {
1035 m_spin_ctrl->SetValue(g_netmask_bits);
1036 m_text->SetLabel(BitsToDottedMask(m_spin_ctrl->GetValue()));
1041 wxSpinCtrl* m_spin_ctrl;
1042 wxStaticText* m_text;
1049 TopPanel(wxWindow* parent,
const std::vector<ConnectionParams*>& connections,
1053 : wxPanel(parent, wxID_ANY),
1054 m_evt_add_connection(evt_add_connection),
1055 m_connections(connections) {
1056 auto vbox =
new wxBoxSizer(wxVERTICAL);
1057 auto conn_grid =
new Connections(
this, m_connections, m_evt_add_connection,
1059 wxSize panel_max_size(conn_grid->GetEstimatedSize());
1060 vbox->AddSpacer(wxWindow::GetCharHeight());
1061 auto conn_flags = wxSizerFlags().Border();
1062 if (IsAndroid()) conn_flags = wxSizerFlags().Border().Expand();
1063 vbox->Add(conn_grid, conn_flags);
1065 wxSizerFlags().Border());
1066 vbox->Add(0, wxWindow::GetCharHeight());
1068 wxSizerFlags().Border(wxLEFT | wxDOWN | wxRIGHT).Expand();
1069 m_general_panel =
new GeneralPanel(
this, panel_max_size);
1070 vbox->Add(m_general_panel, panel_flags);
1072 auto advanced_panel =
new AdvancedPanel(
this, panel_max_size);
1073 m_advanced_panel = advanced_panel;
1074 auto on_toggle = [&, advanced_panel, vbox](
bool show) {
1076 advanced_panel->Show(show);
1077 vbox->SetSizeHints(
this);
1080 vbox->Add(
new ShowAdvanced(
this, on_toggle), panel_flags);
1081 vbox->Add(advanced_panel, panel_flags.ReserveSpaceEvenIfHidden());
1084 vbox->SetSizeHints(
this);
1089 auto on_evt_update_connections = [&, conn_grid](
ObservedEvt&) {
1090 conn_grid->ReloadGrid(TheConnectionParams());
1091 conn_grid->Show(conn_grid->GetNumberRows() > 0);
1094 m_add_connection_lstnr.
Init(m_evt_add_connection,
1095 on_evt_update_connections);
1096 m_conn_grid = conn_grid;
1099 void SetColorScheme(
const ColorScheme cs)
const {
1100 m_conn_grid->SetColorScheme(cs);
1101 m_general_panel->SetColorScheme(cs);
1103 [[nodiscard]]
Connections* GetConnectionsGrid()
const {
return m_conn_grid; }
1108 const std::vector<ConnectionParams*>& m_connections;
1118 TopScroll(wxWindow* parent,
const std::vector<ConnectionParams*>& connections,
1120 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1121 wxVSCROLL | wxHSCROLL, TopScrollWindowName) {
1122 ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_ALWAYS);
1123 auto vbox =
new wxBoxSizer(wxVERTICAL);
1134 new TopPanel(
this, connections, evt_add_connection, on_edit_connection);
1135 vbox->Add(top_panel, wxSizerFlags(1).Expand());
1139 HandleEditFinish(p, new_mode, ok_cancel);
1143 m_edit_panel->SetPropsLabel(_(
"Edit Selected Connection"));
1144 wxWindow*
options = FindWindowByName(
"Options");
1145 assert(
options &&
"Null Options window!");
1150 m_edit_panel->SetSize(
1151 wxSize(
options->GetSize().x,
options->GetSize().y * fraction / 10));
1152 vbox->Add(m_edit_panel, wxSizerFlags(0).Expand());
1153 m_edit_panel->Hide();
1155 SetScrollRate(0, 10);
1156 if (IsAndroid()) SetScrollRate(1, 1);
1158 SetScrollRate(0, 10);
1159 if (IsAndroid()) SetScrollRate(1, 1);
1162 void SetColorScheme(ColorScheme cs)
const {
1163 if (top_panel) top_panel->SetColorScheme(cs);
1167 m_edit_panel->SetPropsLabel(_(
"Edit Selected Connection"));
1168 m_edit_panel->SetNewMode(
false);
1169 m_edit_panel->PreloadControls(p);
1170 m_edit_panel->AddOKCancelButtons();
1175 m_edit_panel->SetPropsLabel(_(
"Configure new connection"));
1176 m_edit_panel->SetDefaultConnectionParams();
1177 m_edit_panel->SetNewMode(
true);
1178 m_edit_panel->AddOKCancelButtons();
1182 void SwitchToEditor() {
1185 DimeControl(m_edit_panel);
1186 m_edit_panel->Show();
1187 g_options->ShowOKButtons(
false);
1192 void SwitchToGrid() {
1193 g_options->ShowOKButtons(
true);
1194 m_edit_panel->Hide();
1196 top_panel->GetConnectionsGrid()->
ReloadGrid(TheConnectionParams());
1210 delete cp_orig->m_optionsPanel;
1211 StopAndRemoveCommDriver(cp_orig->GetStrippedDSPort(),
1212 cp_orig->GetCommProtocol());
1214 assert(index != -1 &&
"Cannot look up connection index");
1215 TheConnectionParams()[index] = cp_edited;
1216 cp_edited->b_IsSetup =
false;
1221 if (cp->GetValidPort()) {
1222 cp->b_IsSetup =
false;
1223 TheConnectionParams().push_back(cp);
1226 _(
"Unable to create a connection as configured. "
1227 "Connected port or address was missing.");
1228 auto& noteman = NotificationManager::GetInstance();
1229 noteman.AddNotification(NotificationSeverity::kWarning,
1230 msg.ToStdString(), 60);
1233 UpdateDatastreams();
1234 top_panel->m_evt_add_connection.
Notify();
1238 UpdateDatastreams();