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