OpenCPN Partial API docs
Loading...
Searching...
No Matches
ais_target_alert_dlg.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2010 by David S. Register *
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
24#include <wx/wxprec.h>
25
26#include "gl_headers.h"
27
28#ifndef WX_PRECOMP
29#include <wx/wx.h>
30#endif // precompiled headers
31
32#include <wx/html/htmlwin.h>
33
34#include "model/ais_decoder.h"
37#include "model/gui_vars.h"
38#include "model/navobj_db.h"
39#include "model/ocpn_types.h"
40#include "model/ocpn_types.h"
41#include "model/route_point.h"
42#include "model/select.h"
43
45#include "chcanv.h"
46#include "font_mgr.h"
47#include "navutil.h"
48#include "ocpn_platform.h"
49#include "routemanagerdialog.h"
50#include "top_frame.h"
51#include "user_colors.h"
52
53#ifdef __ANDROID__
54#include <QDebug>
55#include "androidUTIL.h"
56#endif
57
58IMPLEMENT_CLASS(OCPN_AlertDialog, wxDialog)
59
60BEGIN_EVENT_TABLE(OCPN_AlertDialog, wxDialog)
61END_EVENT_TABLE()
62
64
65OCPN_AlertDialog::~OCPN_AlertDialog() {}
66
67void OCPN_AlertDialog::Init() { m_pparent = NULL; }
68
69bool OCPN_AlertDialog::Create(wxWindow *parent, wxWindowID id,
70 const wxString &caption, const wxPoint &pos,
71 const wxSize &size, long style)
72
73{
74 long wstyle = wxDEFAULT_FRAME_STYLE;
75
76 wxSize size_min = size;
77 size_min.IncTo(wxSize(500, 600));
78 if (!wxDialog::Create(parent, id, caption, pos, size_min, wstyle))
79 return false;
80
81 m_pparent = parent;
82
83 if (!g_bopengl && CanSetTransparent()) SetTransparent(192);
84
85 return true;
86}
87
88//---------------------------------------------------------------------------------------------------------------------
89//
90// AIS Target Alert Dialog implementation
91//
92//---------------------------------------------------------------------------------------------------------------------
93
94IMPLEMENT_CLASS(AISTargetAlertDialog, wxDialog)
95
96BEGIN_EVENT_TABLE(AISTargetAlertDialog, wxDialog)
97EVT_CLOSE(AISTargetAlertDialog::OnClose)
98EVT_BUTTON(ID_ACKNOWLEDGE, AISTargetAlertDialog::OnIdAckClick)
99EVT_BUTTON(ID_SILENCE, AISTargetAlertDialog::OnIdSilenceClick)
100EVT_BUTTON(ID_JUMPTO, AISTargetAlertDialog::OnIdJumptoClick)
101EVT_BUTTON(ID_WPT_CREATE, AISTargetAlertDialog::OnIdCreateWPClick)
102EVT_MOVE(AISTargetAlertDialog::OnMove)
103EVT_SIZE(AISTargetAlertDialog::OnSize)
104END_EVENT_TABLE()
105
107
108AISTargetAlertDialog::~AISTargetAlertDialog() {}
109
110void AISTargetAlertDialog::Init() {
111 m_target_mmsi = 0;
112 m_max_nline = 20;
113 m_adj_height = 0;
114 m_bsizeSet = false;
115 m_pParent = 0;
116}
117
118bool AISTargetAlertDialog::Create(int target_mmsi, wxWindow *parent,
119 AisDecoder *pdecoder, bool b_jumpto,
120 bool b_createWP, bool b_ack, wxWindowID id,
121 const wxString &caption, const wxPoint &pos,
122 const wxSize &size, long style)
123
124{
125 OCPN_AlertDialog::Create(parent, id, caption, pos, size, style);
126 m_bjumpto = b_jumpto;
127 m_back = b_ack;
128 m_bcreateWP = b_createWP;
129
130 m_target_mmsi = target_mmsi;
131 m_pdecoder = pdecoder;
132 m_pParent = parent;
133
134 wxFont *dFont = FontMgr::Get().GetFont(_("AISTargetAlert"), 0);
135 int font_size = wxMax(8, dFont->GetPointSize());
136 wxString face = dFont->GetFaceName();
137#ifdef __WXGTK__
138 face = "Monospace";
139#endif
140 wxFont *fp_font = FontMgr::Get().FindOrCreateFont(
141 font_size, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, dFont->GetWeight(),
142 false, face);
143
144 SetFont(*fp_font);
145
146 CreateControls();
147 if (!g_bopengl && CanSetTransparent()) SetTransparent(192);
148 DimeControl(this);
149 wxColor bg = GetBackgroundColour();
150 m_pAlertTextCtl->SetBackgroundColour(bg);
151 SetBackgroundColour(bg);
152
153 return true;
154}
155
156void AISTargetAlertDialog::CreateControls() {
157 wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
158 SetSizer(topSizer);
159 long style = wxHW_SCROLLBAR_AUTO;
160 if (g_btouch) style |= wxHW_NO_SELECTION;
161
162 m_pAlertTextCtl =
163 new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
164#ifdef __ANDROID__
165 m_pAlertTextCtl->GetHandle()->setStyleSheet(getQtStyleSheet());
166#endif
167
168 m_pAlertTextCtl->SetBorders(5);
169 m_pAlertTextCtl->SetScrollRate(1, 1);
170
171 topSizer->Add(m_pAlertTextCtl, 1, wxALL | wxEXPAND, 5);
172
173 // A flex sizer to contain Ack and more buttons
174 wxFlexGridSizer *AckBox = new wxFlexGridSizer(2);
175 topSizer->Add(AckBox, 0, wxALL, 5);
176
177 // The Silence button
178 if (g_bAIS_CPA_Alert_Audio) {
179 wxButton *silence = new wxButton(this, ID_SILENCE, _("&Silence Alert"),
180 wxDefaultPosition, wxDefaultSize, 0);
181 AckBox->Add(silence, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
182 }
183
184 if (m_bjumpto) {
185 wxButton *jumpto = new wxButton(this, ID_JUMPTO, _("&Jump To"),
186 wxDefaultPosition, wxDefaultSize, 0);
187 AckBox->Add(jumpto, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
188 }
189
190 if (m_bcreateWP) {
191 wxButton *createWptBtn =
192 new wxButton(this, ID_WPT_CREATE, _("Create Waypoint"),
193 wxDefaultPosition, wxDefaultSize, 0);
194 AckBox->Add(createWptBtn, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
195 }
196 // The Ack button
197 // Also used to close a DSC Alert
198 wxString acktext = _("&Acknowledge");
199 bool show_ack_button = false;
200 if (m_bjumpto && m_bcreateWP) { // DSC Alert only
201 acktext = _("&Close Alert");
202 show_ack_button = true;
203 }
204 if (m_back || show_ack_button) {
205 wxButton *ack = new wxButton(this, ID_ACKNOWLEDGE, acktext,
206 wxDefaultPosition, wxDefaultSize, 0);
207 AckBox->Add(ack, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
208 }
209
210 UpdateText();
211
212 RecalculateSize();
213}
214
215bool AISTargetAlertDialog::GetAlertText() {
216 // Search the parent AisDecoder's target list for specified mmsi
217 if (m_pdecoder) {
218 auto td_found = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
219
220 if (td_found) {
221 m_alert_text = td_found->BuildQueryResult();
222 return true;
223 } else
224 return false;
225 } else
226 return false;
227}
228
229void AISTargetAlertDialog::UpdateText() {
230 if (GetAlertText()) {
231 // Capture current scroll position
232 int x, y;
233 m_pAlertTextCtl->GetViewStart(&x, &y);
234
235 wxFont *dFont = FontMgr::Get().GetFont(_("AISTargetAlert"), 0);
236 wxString face = dFont->GetFaceName();
237 int sizes[7];
238 for (int i = -2; i < 5; i++) {
239 sizes[i + 2] = dFont->GetPointSize() + i + (i > 0 ? i : 0);
240 }
241
242 wxString html;
243 wxColor bg = GetBackgroundColour();
244 wxColor fg = GetForegroundColour();
245
246 html.Printf(
247 "<html><body bgcolor=#%02x%02x%02x><font "
248 "color=#%02x%02x%02x><center>",
249 bg.Red(), bg.Green(), bg.Blue(), fg.Red(), fg.Green(), fg.Blue());
250
251 html << m_alert_text;
252 html << "</center></font></body></html>";
253
254 m_pAlertTextCtl->SetFonts(face, face, sizes);
255 m_pAlertTextCtl->SetPage(html);
256
257 RecalculateSize();
258
259 // Restore scroll position
260 m_pAlertTextCtl->Scroll(x, y);
261 }
262
263 SetColorScheme();
264 if (!g_bopengl && CanSetTransparent()) SetTransparent(192);
265}
266
267void AISTargetAlertDialog::RecalculateSize() {
268 // Count the lines in the currently displayed text string
269 unsigned int i = 0;
270 int nline = 0;
271 while (i < m_alert_text.Length()) {
272 if (m_alert_text[i] == '\n') nline++;
273 i++;
274 }
275
276 if (nline > m_max_nline) m_max_nline = nline;
277
278 wxSize esize;
279 esize.x = GetCharWidth() * 45;
280 esize.y = GetCharHeight() * (m_max_nline + 4);
281 // SetSize(esize);
282
283 int height = m_pAlertTextCtl->GetInternalRepresentation()->GetHeight();
284 int adj_height = height + (GetCharHeight() * 6);
285 m_adj_height = wxMax(m_adj_height, adj_height);
286
287 esize.y = wxMin(esize.y, m_adj_height);
288
289 Fit(); // Sets the horizontal size OK, with respect to the buttons
290
291 // If there is only one button shown, the resulting Fit() size may be too
292 // narrow. Adjust it, considering the size of the rendered HTML text content.
293 int textWidth = m_pAlertTextCtl->GetInternalRepresentation()->GetWidth();
294 wxSize gSize = GetClientSize();
295 int adjustedWidth = wxMax(GetClientSize().x, textWidth + GetCharHeight() * 2);
296 SetClientSize(adjustedWidth, esize.y);
297
298 // Constrain the vertical size to be no larger than parent window height
299 if (m_pParent) {
300 wxSize wsize = m_pParent->GetSize();
301 SetSize(-1, wxMin(esize.y, wsize.y));
302 }
303
304 g_Platform->PositionAISAlert(this);
305}
306
307void AISTargetAlertDialog::SetColorScheme() {
308 DimeControl(this);
309 wxColor bg = GetBackgroundColour();
310 m_pAlertTextCtl->SetBackgroundColour(bg);
311 SetBackgroundColour(
312 bg); // This looks like non-sense, but is needed for __WXGTK__
313 // to get colours to propagate down the control's family tree.
314
315#ifdef __WXQT__
316 // wxQT has some trouble clearing the background of HTML window...
317 wxBitmap tbm(GetSize().x, GetSize().y, -1);
318 wxMemoryDC tdc(tbm);
319 // wxColour cback = GetGlobalColor( "YELO1" );
320 tdc.SetBackground(bg);
321 tdc.Clear();
322 m_pAlertTextCtl->SetBackgroundImage(tbm);
323#endif
324}
325
326void AISTargetAlertDialog::OnClose(wxCloseEvent &event) {
327 // Acknowledge any existing Alert, and dismiss the dialog
328 if (m_pdecoder) {
329 auto td = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
330 if (td) {
331 if (AIS_ALERT_SET == td->n_alert_state) {
332 td->m_ack_time = wxDateTime::Now();
333 td->b_in_ack_timeout = true;
334 }
335 if (td->b_isDSCtarget) {
336 td->b_isDSCtarget = false;
337 if (td->n_alert_state) {
338 td->n_alert_state = AIS_NO_ALERT;
339 }
340 }
341 }
342 }
343
344 Destroy();
345 g_pais_alert_dialog_active = NULL;
346}
347
348void AISTargetAlertDialog::OnIdAckClick(wxCommandEvent &event) {
349 // Acknowledge the Alert, and dismiss the dialog
350 if (m_pdecoder) {
351 auto td = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
352 if (td) {
353 if (AIS_ALERT_SET == td->n_alert_state) {
354 td->m_ack_time = wxDateTime::Now();
355 td->b_in_ack_timeout = true;
356 }
357 if (td->b_isDSCtarget) {
358 td->b_isDSCtarget = false;
359 if (td->n_alert_state) {
360 td->n_alert_state = AIS_NO_ALERT;
361 }
362 }
363 }
364 }
365 Destroy();
366 g_pais_alert_dialog_active = NULL;
367}
368void AISTargetAlertDialog::OnIdCreateWPClick(wxCommandEvent &event) {
369 if (m_pdecoder) {
370 auto td = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
371 if (td) {
372 RoutePoint *pWP = new RoutePoint(td->Lat, td->Lon, g_default_wp_icon,
373 wxEmptyString, wxEmptyString);
374 pWP->m_bIsolatedMark = true; // This is an isolated mark
375 pSelect->AddSelectableRoutePoint(td->Lat, td->Lon, pWP);
376 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
377
379 pRouteManagerDialog->UpdateWptListCtrl();
380 if (top_frame::Get()->GetAbstractPrimaryCanvas()) {
381 top_frame::Get()->BeforeUndoableAction(Undo_CreateWaypoint, pWP,
382 Undo_HasParent, NULL);
383 top_frame::Get()->AfterUndoableAction(NULL);
384 top_frame::Get()->InvalidateAllGL();
385 }
386 Refresh(false);
387 }
388 }
389}
390
391void AISTargetAlertDialog::OnIdSilenceClick(wxCommandEvent &event) {
392 // Set the suppress audio flag
393 if (m_pdecoder) {
394 auto td = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
395 if (td) td->b_suppress_audio = true;
396 }
397}
398
399void AISTargetAlertDialog::OnIdJumptoClick(wxCommandEvent &event) {
400 if (m_pdecoder) {
401 auto td = m_pdecoder->Get_Target_Data_From_MMSI(Get_Dialog_MMSI());
402 if (td) {
403 top_frame::Get()->JumpToPosition(
404 top_frame::Get()->GetAbstractFocusCanvas(), td->Lat, td->Lon);
405 }
406 }
407}
408
409void AISTargetAlertDialog::OnMove(wxMoveEvent &event) {
410 // Record the dialog position
411 g_ais_alert_dialog_x = GetPosition().x;
412 g_ais_alert_dialog_y = GetPosition().y;
413
414 event.Skip();
415}
416
417void AISTargetAlertDialog::OnSize(wxSizeEvent &event) {
418 // Record the dialog size
419 wxSize p = event.GetSize();
420 g_ais_alert_dialog_sx = p.x;
421 g_ais_alert_dialog_sy = p.y;
422
423 event.Skip();
424}
Class AisDecoder and helpers.
Global state for AIS decoder.
Class AISTargetAlertDialog and helpers.
AIS target definitions.
Generic Chart canvas base.
Dialog for displaying AIS target alerts.
wxFont * FindOrCreateFont(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
Creates or finds a matching font in the font cache.
Definition font_mgr.cpp:442
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Get a font object for a UI element.
Definition font_mgr.cpp:193
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
Font list manager.
Platform independent GL includes.
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
MySQL based storage for routes, tracks, etc.
Utility functions.
OpenCPN Platform specific support utilities.
Navigation data types.
Waypoint or mark abstraction.
RouteManagerDialog * pRouteManagerDialog
Global instance.
Manage routes dialog.
Select * pSelect
Global instance.
Definition select.cpp:36
Selected route, segment, waypoint, etc.
Abstract gFrame/MyFrame interface.