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