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