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