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"
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 "ocpn_platform.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() { 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() {
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() {
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.
AIS target definitions.
Generic Chart canvas base.
Dialog for displaying AIS target alerts.
float GetVPScale()
Return the ViewPort scale factor, in physical pixels per meter.
Definition chcanv.h:472
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:440
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Get a font object for a UI element.
Definition font_mgr.cpp:191
Main application frame.
Definition ocpn_frame.h:139
Provides platform-specific support utilities for OpenCPN.
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.
MySQL based storage for routes, tracks, etc.
Utility functions.
OpenCPN top window.
OpenCPN Platform specific support utilities.
Navigation data types.
Waypoint or mark abstraction.
Manage routes dialog.
Select * pSelect
Global instance.
Definition select.cpp:36
Selected route, segment, waypoint, etc.