OpenCPN Partial API docs
Loading...
Searching...
No Matches
toolbar.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2010 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24#include <vector>
25
26#include <wx/wxprec.h>
27#ifndef WX_PRECOMP
28#include <wx/wx.h>
29#endif
30
31#include "config.h"
32#include "toolbar.h"
33
35#include "model/config_vars.h"
36#include "model/gui_vars.h"
37#include "model/idents.h"
38#include "model/ocpn_types.h"
39#include "model/svg_utils.h"
40
41#include "chartdb.h"
42#include "chcanv.h"
43#include "compass.h"
44#include "font_mgr.h"
45#include "gui_lib.h"
46#include "navutil.h"
47#include "ocpn_frame.h"
48#include "ocpn_platform.h"
49#include "pluginmanager.h"
50#include "s52plib.h"
51#include "styles.h"
52
53#ifdef __ANDROID__
54#include "androidUTIL.h"
55#endif
56
57#ifdef ocpnUSE_GL
58#include "gl_chart_canvas.h"
59#endif
60
61#ifdef ocpnUSE_GL
62extern GLenum g_texture_rectangle_format;
63#endif
64
66
67class ocpnToolBarTool : public wxToolBarToolBase {
68public:
69 ocpnToolBarTool(ocpnToolBarSimple *tbar, int id, const wxString &label,
70 const wxBitmap &bmpNormal, const wxBitmap &bmpRollover,
71 wxItemKind kind, wxObject *clientData,
72 const wxString &shortHelp, const wxString &longHelp)
73 : wxToolBarToolBase((wxToolBarBase *)tbar, id, label, bmpNormal,
74 bmpRollover, kind, clientData, shortHelp, longHelp) {
75 m_enabled = true;
76 m_toggled = false;
77 rollover = false;
78 bitmapOK = false;
79 m_btooltip_hiviz = false;
80
81 toolname = g_pi_manager->GetToolOwnerCommonName(id);
82 if (toolname == "") {
83 isPluginTool = false;
84 toolname = label;
85 iconName = label;
86
87 } else {
88 isPluginTool = true;
89 pluginNormalIcon = bmpNormal;
90 pluginRolloverIcon = bmpRollover;
91 }
92 }
93
94 ocpnToolBarTool(ocpnToolBarSimple *tbar, int id, const wxBitmap &bmpNormal,
95 const wxBitmap &bmpRollover, wxItemKind kind,
96 wxObject *clientData, const wxString &shortHelp,
97 const wxString &longHelp)
98 : wxToolBarToolBase((wxToolBarBase *)tbar, id, "", bmpNormal, bmpRollover,
99 kind, clientData, shortHelp, longHelp) {
100 m_enabled = true;
101 m_toggled = false;
102 rollover = false;
103 m_btooltip_hiviz = false;
104 isPluginTool = false;
105
106 m_bmpNormal = bmpNormal;
107 bitmapOK = true;
108 }
109
110 void SetSize(const wxSize &size) {
111 m_width = size.x;
112 m_height = size.y;
113 }
114
115 wxCoord GetWidth() const { return m_width; }
116
117 wxCoord GetHeight() const { return m_height; }
118
119 wxString GetToolname() { return toolname; }
120
121 void SetIconName(wxString name) { iconName = name; }
122 wxString GetIconName() { return iconName; }
123
124 void SetTooltipHiviz(bool enable) { m_btooltip_hiviz = enable; }
125
126 wxCoord m_x;
127 wxCoord m_y;
128 wxCoord m_width;
129 wxCoord m_height;
130 wxRect trect;
131 wxString toolname;
132 wxString iconName;
133 wxBitmap pluginNormalIcon;
134 wxBitmap pluginRolloverIcon;
135 const wxBitmap *pluginToggledIcon;
136 bool firstInLine;
137 bool lastInLine;
138 bool rollover;
139 bool bitmapOK;
140 bool isPluginTool;
141 bool b_hilite;
142 bool m_btooltip_hiviz;
143 wxRect last_rect;
144 wxString pluginNormalIconSVG;
145 wxString pluginRolloverIconSVG;
146 wxString pluginToggledIconSVG;
147 wxBitmap m_activeBitmap;
148};
149
150//---------------------------------------------------------------------------------------
151// ocpnFloatingToolbarDialog Implementation
152//---------------------------------------------------------------------------------------
153
154ocpnFloatingToolbarDialog::ocpnFloatingToolbarDialog(wxWindow *parent,
155 wxPoint position,
156 long orient,
157 float size_factor) {
158 m_pparent = parent;
159 m_ptoolbar = NULL;
160
161 m_opacity = 255;
162 m_position = position;
163 m_orient = orient;
164 m_sizefactor = size_factor;
165 m_cornerRadius = 0;
166
167 m_bAutoHideToolbar = false;
168 m_nAutoHideToolbar = 5;
169 m_toolbar_scale_tools_shown = false;
170 m_backcolorString = "GREY3";
171 m_toolShowMask = "XXXXXXXXXXXXXXXX";
172 n_toolbarHideMethod = TOOLBAR_HIDE_TO_GRABBER;
173 b_canToggleOrientation = true;
174 m_enableRolloverBitmaps = true;
175 m_auxOffsetY = 0;
176
177 m_ptoolbar = CreateNewToolbar();
178 if (m_ptoolbar) m_ptoolbar->SetBackgroundColour(GetGlobalColor("GREY3"));
179 m_cs = (ColorScheme)-1;
180
181 m_style = g_StyleManager->GetCurrentStyle();
182 SetULDockPosition(wxPoint(4, 4));
183
184 SetGeometry(false, wxRect());
185
186 // Set initial "Dock" parameters
187 m_dock_x = 0;
188 m_dock_y = 0;
189 m_block = false;
190
191 m_texture = 0;
192
193 m_marginsInvisible = m_style->marginsInvisible;
194
195 m_FloatingToolbarConfigMenu = NULL;
196
197 m_fade_timer.SetOwner(this);
198 this->Connect(wxEVT_TIMER,
199 wxTimerEventHandler(ocpnFloatingToolbarDialog::FadeTimerEvent),
200 NULL, this);
201
202 if (m_bAutoHideToolbar && (m_nAutoHideToolbar > 0))
203 m_fade_timer.Start(m_nAutoHideToolbar * 1000);
204
205 m_bsubmerged = false;
206 m_benableSubmerge = true;
207}
208
209ocpnFloatingToolbarDialog::~ocpnFloatingToolbarDialog() {
210 delete m_FloatingToolbarConfigMenu;
211
212 DestroyToolBar();
213}
214
215void ocpnFloatingToolbarDialog::FadeTimerEvent(wxTimerEvent &event) {
216 if (n_toolbarHideMethod == TOOLBAR_HIDE_TO_FIRST_TOOL) {
217 if (g_bmasterToolbarFull) {
218 if (m_bAutoHideToolbar && (m_nAutoHideToolbar > 0) /*&& !m_bsubmerged*/) {
219 // Double check the mouse position
220 wxPoint mp =
221 gFrame->GetPrimaryCanvas()->ScreenToClient(::wxGetMousePosition());
222 // in the toolbar?
223 wxRect r = GetToolbarRect();
224 if (r.Contains(mp)) return;
225
226 wxCommandEvent event;
227 event.SetId(ID_MASTERTOGGLE);
228 gFrame->OnToolLeftClick(event);
229 }
230 }
231 }
232}
233
234void ocpnFloatingToolbarDialog::AddToolItem(ToolbarItemContainer *item) {
235 m_Items.push_back(item);
236}
237
238int ocpnFloatingToolbarDialog::RebuildToolbar() {
239 ocpnToolBarSimple *tb = GetToolbar();
240 if (!tb) return 0;
241
242 // Iterate over the array of items added,
243 // Creating the toolbar from enabled items.
244 int i_count = 0;
245 for (auto it = m_Items.cbegin(); it != m_Items.cend(); it++) {
246 ToolbarItemContainer *tic = *it;
247 if (!tic) continue;
248
249 bool bEnabled = _toolbarConfigMenuUtil(tic);
250
251 if (bEnabled) {
252 wxToolBarToolBase *tool =
253 tb->AddTool(tic->m_ID, tic->m_label, tic->m_bmpNormal,
254 tic->m_bmpDisabled, tic->m_toolKind, tic->m_tipString);
255 tic->m_tool = tool;
256
257 // Plugin tools may have prescribed their own SVG toolbars as file
258 // locations.
259 if (!tic->m_NormalIconSVG.IsEmpty()) {
260 tb->SetToolBitmapsSVG(tic->m_ID, tic->m_NormalIconSVG,
261 tic->m_RolloverIconSVG, tic->m_ToggledIconSVG);
262 }
263 }
264
265 i_count++;
266 }
267
268 return i_count;
269}
270
271void ocpnFloatingToolbarDialog::SetULDockPosition(wxPoint position) {
272 if (position.x >= 0) m_dock_min_x = position.x;
273 if (position.y >= 0) m_dock_min_y = position.y;
274}
275
276size_t ocpnFloatingToolbarDialog::GetToolCount() {
277 if (m_ptoolbar)
278 return m_ptoolbar->GetToolsCount();
279 else
280 return 0;
281}
282
283void ocpnFloatingToolbarDialog::SetToolShowMask(wxString mask) {}
284
285void ocpnFloatingToolbarDialog::SetToolShowCount(int count) {
286 if (m_ptoolbar) {
287 m_ptoolbar->SetToolShowCount(count);
288 m_ptoolbar->SetDirty(true);
289 }
290}
291
292int ocpnFloatingToolbarDialog::GetToolShowCount() {
293 if (m_ptoolbar)
294 return m_ptoolbar->GetToolShowCount();
295 else
296 return 0;
297}
298
299void ocpnFloatingToolbarDialog::SetBackGroundColorString(wxString colorRef) {
300 m_backcolorString = colorRef;
301 SetColorScheme(m_cs); // Causes a reload of background color
302}
303
304void ocpnFloatingToolbarDialog::OnKeyDown(wxKeyEvent &event) { event.Skip(); }
305
306void ocpnFloatingToolbarDialog::OnKeyUp(wxKeyEvent &event) { event.Skip(); }
307
308void ocpnFloatingToolbarDialog::CreateConfigMenu() {
309 if (m_FloatingToolbarConfigMenu) delete m_FloatingToolbarConfigMenu;
310 m_FloatingToolbarConfigMenu = new wxMenu();
311}
312
313bool ocpnFloatingToolbarDialog::_toolbarConfigMenuUtil(
315 if (m_FloatingToolbarConfigMenu) {
316 wxMenuItem *menuitem;
317
318 if (tic->m_ID == ID_MOB && g_bPermanentMOBIcon) return true;
319
320 if (tic->m_bRequired) return true;
321 if (tic->m_bPlugin) return true;
322
323 // Item ID trickery is needed because the wxCommandEvents for menu item
324 // clicked and toolbar button clicked are 100% identical, so if we use same
325 // id's we can't tell the events apart.
326
327 int idOffset = 100; // Hopefully no more than 100 total icons...
328 int menuItemId = tic->m_ID + idOffset;
329
330 menuitem = m_FloatingToolbarConfigMenu->FindItem(menuItemId);
331
332 if (menuitem) {
333 return menuitem->IsChecked();
334 }
335
336 menuitem = m_FloatingToolbarConfigMenu->AppendCheckItem(menuItemId,
337 tic->m_tipString);
338 size_t n = m_FloatingToolbarConfigMenu->GetMenuItemCount();
339 menuitem->Check(m_configString.Len() >= n
340 ? m_configString.GetChar(n - 1) == 'X'
341 : true);
342 return menuitem->IsChecked();
343 } else
344 return true;
345}
346
347void ocpnFloatingToolbarDialog::EnableTool(int toolid, bool enable) {
348 if (m_ptoolbar) m_ptoolbar->EnableTool(toolid, enable);
349}
350
351void ocpnFloatingToolbarDialog::SetColorScheme(ColorScheme cs) {
352 m_cs = cs;
353 wxColour back_color = GetGlobalColor(m_backcolorString);
354
355 if (m_ptoolbar) {
356 m_ptoolbar->SetToggledBackgroundColour(GetGlobalColor("GREY1"));
357 m_ptoolbar->SetColorScheme(cs);
358 }
359}
360
361wxSize ocpnFloatingToolbarDialog::GetToolSize() {
362 wxSize style_tool_size;
363 if (m_ptoolbar) {
364 style_tool_size = m_style->GetToolSize();
365
366 style_tool_size.x *= m_sizefactor;
367 style_tool_size.y *= m_sizefactor;
368 } else {
369 style_tool_size.x = 32;
370 style_tool_size.y = 32;
371 }
372
373 return style_tool_size;
374}
375
376void ocpnFloatingToolbarDialog::SetGeometry(bool bAvoid, wxRect rectAvoid) {
377 if (m_ptoolbar) {
378 wxSize style_tool_size = m_style->GetToolSize();
379
380 style_tool_size.x *= m_sizefactor;
381 style_tool_size.y *= m_sizefactor;
382
383 m_ptoolbar->SetToolBitmapSize(style_tool_size);
384
385 wxSize tool_size = m_ptoolbar->GetToolBitmapSize();
386 int grabber_width = m_style->GetIcon("grabber").GetWidth();
387
388 int max_rows = 10;
389 int max_cols = 100;
390
391 if (m_pparent) {
392 int avoid_start =
393 m_pparent->GetClientSize().x -
394 (tool_size.x + m_style->GetToolSeparation()) * 2; // default
395 if (bAvoid && !rectAvoid.IsEmpty()) {
396 avoid_start = m_pparent->GetClientSize().x - rectAvoid.width -
397 10; // this is compass window, if shown
398 }
399
400 max_rows = (m_pparent->GetClientSize().y /
401 (tool_size.y + m_style->GetToolSeparation())) -
402 2;
403
404 max_cols = (avoid_start - grabber_width) /
405 (tool_size.x + m_style->GetToolSeparation());
406 max_cols -= 1;
407
408 if (m_orient == wxTB_VERTICAL)
409 max_rows = wxMax(max_rows, 2); // at least two rows
410 else
411 max_cols = wxMax(max_cols, 2); // at least two columns
412 }
413
414 if (m_orient == wxTB_VERTICAL)
415 m_ptoolbar->SetMaxRowsCols(max_rows, 100);
416 else
417 m_ptoolbar->SetMaxRowsCols(100, max_cols);
418 m_ptoolbar->SetSizeFactor(m_sizefactor);
419 }
420}
421
422void ocpnFloatingToolbarDialog::SetDefaultPosition() {
423 if (m_block) return;
424
425 if (m_pparent && m_ptoolbar) {
426 wxSize cs = m_pparent->GetClientSize();
427 if (-1 == m_dock_x)
428 m_position.x = m_dock_min_x;
429 else if (1 == m_dock_x)
430 m_position.x = cs.x - m_ptoolbar->m_maxWidth;
431
432 if (-1 == m_dock_y)
433 m_position.y = m_dock_min_y;
434 else if (1 == m_dock_y)
435 m_position.y = cs.y - m_ptoolbar->m_maxHeight;
436
437 m_position.x = wxMin(cs.x - m_ptoolbar->m_maxWidth, m_position.x);
438 m_position.y = wxMin(cs.y - m_ptoolbar->m_maxHeight, m_position.y);
439
440 m_position.x = wxMax(m_dock_min_x, m_position.x);
441 m_position.y = wxMax(m_dock_min_y, m_position.y);
442
443 m_position.y += m_auxOffsetY;
444
445 g_maintoolbar_x = m_position.x;
446 g_maintoolbar_y = m_position.y;
447
448 // take care of left docked instrument windows and don't blast the main
449 // toolbar on top of them, hinding instruments this positions the main
450 // toolbar directly right of the left docked instruments onto the chart
451 // wxPoint screen_pos = m_pparent->ClientToScreen( m_position );
452 // wxPoint screen_pos =
453 // gFrame->GetPrimaryCanvas()->ClientToScreen(m_position);
454
455 // GTK sometimes has trouble with ClientToScreen() if executed in the
456 // context of an event handler The position of the window is calculated
457 // incorrectly if a deferred Move() has not been processed yet. So work
458 // around this here... Discovered with a Dashboard window left-docked,
459 // toggled on and off by toolbar tool.
460
461 // But this causes another problem. If a toolbar is NOT left docked, it
462 // will walk left by two pixels on each call to Reposition().
463 // TODO
464 }
465}
466
467void ocpnFloatingToolbarDialog::Submerge() {
468 m_bsubmerged = true;
469 // Hide();
470 if (m_ptoolbar) m_ptoolbar->KillTooltip();
471}
472
473void ocpnFloatingToolbarDialog::HideTooltip() {
474#ifndef __ANDROID__
475 if (m_ptoolbar) m_ptoolbar->HideTooltip();
476#endif
477}
478
479void ocpnFloatingToolbarDialog::ShowTooltips() {
480#ifndef __ANDROID__
481 if (m_ptoolbar) m_ptoolbar->EnableTooltips();
482#endif
483}
484
485void ocpnFloatingToolbarDialog::ToggleOrientation() {}
486
487wxRect ocpnFloatingToolbarDialog::GetToolbarRect() {
488 return wxRect(m_position.x, m_position.y, m_ptoolbar->m_maxWidth,
489 m_ptoolbar->m_maxHeight);
490}
491
492wxSize ocpnFloatingToolbarDialog::GetToolbarSize() {
493 return wxSize(m_ptoolbar->m_maxWidth, m_ptoolbar->m_maxHeight);
494}
495
496wxPoint ocpnFloatingToolbarDialog::GetToolbarPosition() {
497 return wxPoint(m_position.x, m_position.y);
498}
499
500bool ocpnFloatingToolbarDialog::MouseEvent(wxMouseEvent &event) {
501 if (g_disable_main_toolbar) return false;
502 if (m_ptoolbar) {
503 bool bproc = m_ptoolbar->OnMouseEvent(event, m_position);
504 if (bproc) m_ptoolbar->CreateBitmap();
505 return bproc;
506 } else
507 return false;
508}
509
510void ocpnFloatingToolbarDialog::RefreshToolbar() {
511 if (m_ptoolbar) {
512 if (m_ptoolbar->IsDirty()) {
513 Realize();
514 gFrame->GetPrimaryCanvas()->Refresh();
515 }
516 }
517}
518
519void ocpnFloatingToolbarDialog::SetAutoHideTimer(int time) {
520 m_nAutoHideToolbar = time;
521 if (m_bAutoHideToolbar) {
522 m_fade_timer.Stop();
523 m_fade_timer.Start(m_nAutoHideToolbar * 1000);
524 }
525}
526
527void ocpnFloatingToolbarDialog::RefreshFadeTimer() {
528 if (m_bAutoHideToolbar && (m_nAutoHideToolbar > 0)) {
529 m_fade_timer.Start(m_nAutoHideToolbar * 1000);
530 }
531}
532
533void ocpnFloatingToolbarDialog::SetToolShortHelp(int id, const wxString &help) {
534 if (m_ptoolbar) m_ptoolbar->SetToolShortHelp(id, help);
535}
536
537void ocpnFloatingToolbarDialog::Realize() {
538 if (m_ptoolbar) {
539 m_ptoolbar->Realize();
540 m_ptoolbar->CreateBitmap();
541 m_toolbar_image.Destroy();
542 }
543}
544
545void ocpnFloatingToolbarDialog::DrawDC(ocpnDC &dc, double displayScale) {
546 if (m_ptoolbar) {
547 m_ptoolbar->CreateBitmap();
548 if (m_ptoolbar->GetBitmap().IsOk()) {
549 dc.DrawBitmap(m_ptoolbar->GetBitmap(), m_position.x, m_position.y, false);
550 m_ptoolbar->SetDirty(false);
551 }
552 }
553}
554
555void ocpnFloatingToolbarDialog::DrawGL(ocpnDC &gldc, double displayScale) {
556 if (g_disable_main_toolbar) return;
557
558#ifdef ocpnUSE_GL
559 if (!m_ptoolbar) return;
560
561 wxColour backColor = GetGlobalColor("GREY3");
562 gldc.SetBrush(wxBrush(backColor));
563 gldc.SetPen(wxPen(backColor));
564
565 wxRect r = GetToolbarRect();
566 int m_end_margin = wxMin(GetToolSize().x, GetToolSize().y) / 8;
567
568 if (m_orient == wxHORIZONTAL)
569 gldc.DrawRoundedRectangle(
570 (r.x - m_end_margin / 2) * displayScale, (r.y - 1) * displayScale,
571 (r.width + m_end_margin) * displayScale, (r.height + 2) * displayScale,
572 (m_end_margin * 1) * displayScale);
573 else
574 gldc.DrawRoundedRectangle(
575 (r.x - 1) * displayScale, (r.y - m_end_margin / 2) * displayScale,
576 (r.width + 2) * displayScale, (r.height + m_end_margin) * displayScale,
577 (m_end_margin * 1.5) * displayScale);
578
579 int width = GetToolbarSize().x;
580 int height = GetToolbarSize().y;
581
582 m_ptoolbar->CreateBitmap(displayScale);
583
584 // Make a GL texture
585 if (!m_texture) {
586 glGenTextures(1, &m_texture);
587
588 glBindTexture(g_texture_rectangle_format, m_texture);
589 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
590 GL_NEAREST);
591 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
592 GL_NEAREST);
593 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_S,
594 GL_CLAMP_TO_EDGE);
595 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_T,
596 GL_CLAMP_TO_EDGE);
597 } else {
598 glBindTexture(g_texture_rectangle_format, m_texture);
599 }
600
601 if (!m_toolbar_image.IsOk()) {
602 // fill texture data
603 m_toolbar_image = m_ptoolbar->GetBitmap().ConvertToImage();
604
605 unsigned char *d = m_toolbar_image.GetData();
606 unsigned char *e = new unsigned char[4 * width * height];
607 for (int y = 0; y < height; y++)
608 for (int x = 0; x < width; x++) {
609 int i = y * width + x;
610 memcpy(e + 4 * i, d + 3 * i, 3);
611 e[4 * i + 3] = 255; // d[3*i + 2] == 255 ? 0:255; //255 - d[3 * i + 2];
612 }
613 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, width, height, 0,
614 GL_RGBA, GL_UNSIGNED_BYTE, e);
615 delete[] e;
616 glDisable(g_texture_rectangle_format);
617 glDisable(GL_BLEND);
618 }
619
620 // Render the texture
621 if (m_texture) {
622 glEnable(g_texture_rectangle_format);
623 glBindTexture(g_texture_rectangle_format, m_texture);
624 glEnable(GL_BLEND);
625
626 int x0 = GetToolbarPosition().x, x1 = x0 + width;
627 int y0 = GetToolbarPosition().y - 0, y1 = y0 + height;
628 x0 *= displayScale;
629 x1 *= displayScale;
630 y0 *= displayScale;
631 y1 *= displayScale;
632
633 float tx, ty;
634 if (GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format)
635 tx = width, ty = height;
636 else
637 tx = ty = 1;
638
639 float coords[8];
640 float uv[8];
641
642 // normal uv
643 uv[0] = 0;
644 uv[1] = 0;
645 uv[2] = tx;
646 uv[3] = 0;
647 uv[4] = tx;
648 uv[5] = ty;
649 uv[6] = 0;
650 uv[7] = ty;
651
652 // pixels
653 coords[0] = x0;
654 coords[1] = y0;
655 coords[2] = x1;
656 coords[3] = y0;
657 coords[4] = x1;
658 coords[5] = y1;
659 coords[6] = x0;
660 coords[7] = y1;
661
662 auto canvas = gFrame->GetPrimaryCanvas();
663 canvas->GetglCanvas()->RenderTextures(gldc, coords, uv, 4,
664 canvas->GetpVP());
665
666 glDisable(g_texture_rectangle_format);
667 glBindTexture(g_texture_rectangle_format, 0);
668 glDisable(GL_BLEND);
669 }
670#endif
671
672 return;
673}
674
675void ocpnFloatingToolbarDialog::OnToolLeftClick(wxCommandEvent &event) {
676 // Since Dialog events don't propagate automatically, we send it explicitly
677 // (instead of relying on event.Skip()). Send events up the window hierarchy
678
679 m_pparent->GetEventHandler()->AddPendingEvent(event);
680#ifndef __WXQT__
681 gFrame->Raise();
682#endif
683}
684
685ocpnToolBarSimple *ocpnFloatingToolbarDialog::GetToolbar() {
686 if (!m_ptoolbar) {
687 m_ptoolbar = CreateNewToolbar();
688 }
689
690 return m_ptoolbar;
691}
692
693ocpnToolBarSimple *ocpnFloatingToolbarDialog::CreateNewToolbar() {
694 long winstyle = wxNO_BORDER | wxTB_FLAT;
695 winstyle |= m_orient;
696
697 m_ptoolbar = new ocpnToolBarSimple(this, -1, wxPoint(-1, -1), wxSize(-1, -1),
698 winstyle, m_orient);
699
700 // m_ptoolbar->SetBackgroundColour(GetGlobalColor("GREY2"));
701 // m_ptoolbar->ClearBackground();
702 m_ptoolbar->SetToggledBackgroundColour(GetGlobalColor("GREY1"));
703 m_ptoolbar->SetColorScheme(m_cs);
704 m_ptoolbar->EnableRolloverBitmaps(GetEnableRolloverBitmaps());
705
706 return m_ptoolbar;
707}
708
709void ocpnFloatingToolbarDialog::DestroyToolBar() {
710 g_toolbarConfig = GetToolConfigString();
711
712 if (m_ptoolbar) {
713 m_ptoolbar->ClearTools();
714 delete m_ptoolbar; //->Destroy();
715 m_ptoolbar = NULL;
716 }
717
718 for (auto it = m_Items.cbegin(); it != m_Items.cend(); it++) {
719 delete *it;
720 }
721 m_Items.clear();
722}
723
724bool ocpnFloatingToolbarDialog::CheckAndAddPlugInTool(ocpnToolBarSimple *tb) {
725 if (!g_pi_manager) return false;
726
727 bool bret = false;
728 int n_tools = tb->GetToolsCount();
729
730 // Walk the PlugIn tool spec array, checking the requested position
731 // If a tool has been requested by a plugin at this position, add it
732 ArrayOfPlugInToolbarTools tool_array =
733 g_pi_manager->GetPluginToolbarToolArray();
734
735 for (unsigned int i = 0; i < tool_array.GetCount(); i++) {
736 PlugInToolbarToolContainer *pttc = tool_array.Item(i);
737 if (pttc->position == n_tools) {
738 wxBitmap *ptool_bmp;
739
740 switch (m_cs) {
741 case GLOBAL_COLOR_SCHEME_DAY:
742 ptool_bmp = pttc->bitmap_day;
743 ;
744 break;
745 case GLOBAL_COLOR_SCHEME_DUSK:
746 ptool_bmp = pttc->bitmap_dusk;
747 break;
748 case GLOBAL_COLOR_SCHEME_NIGHT:
749 ptool_bmp = pttc->bitmap_night;
750 break;
751 default:
752 ptool_bmp = pttc->bitmap_day;
753 ;
754 break;
755 }
756
757 wxToolBarToolBase *tool =
758 tb->AddTool(pttc->id, wxString(pttc->label), *(ptool_bmp),
759 wxString(pttc->shortHelp), pttc->kind);
760
761 tb->SetToolBitmapsSVG(pttc->id, pttc->pluginNormalIconSVG,
762 pttc->pluginRolloverIconSVG,
763 pttc->pluginToggledIconSVG);
764
765 bret = true;
766 }
767 }
768
769 // If we added a tool, call again (recursively) to allow for adding
770 // adjacent tools
771 if (bret)
772 while (CheckAndAddPlugInTool(tb)) { /* nothing to do */
773 }
774
775 return bret;
776}
777
778void ocpnFloatingToolbarDialog::EnableRolloverBitmaps(bool bEnable) {
779 m_enableRolloverBitmaps = bEnable;
780 if (m_ptoolbar) m_ptoolbar->EnableRolloverBitmaps(bEnable);
781}
782
783// ----------------------------------------------------------------------------
784
785// ============================================================================
786// implementation
787// ============================================================================
788// ----------------------------------------------------------------------------
789BEGIN_EVENT_TABLE(ocpnToolBarSimple, wxEvtHandler)
790EVT_TIMER(TOOLTIPON_TIMER, ocpnToolBarSimple::OnToolTipTimerEvent)
791EVT_TIMER(TOOLTIPOFF_TIMER, ocpnToolBarSimple::OnToolTipOffTimerEvent)
792END_EVENT_TABLE()
793
794// ----------------------------------------------------------------------------
795// tool bar tools creation
796// ----------------------------------------------------------------------------
797
798wxToolBarToolBase *ocpnToolBarSimple::CreateTool(
799 int id, const wxString &label, const wxBitmap &bmpNormal,
800 const wxBitmap &bmpDisabled, wxItemKind kind, wxObject *clientData,
801 const wxString &shortHelp, const wxString &longHelp) {
802 if (m_style->NativeToolIconExists(label)) {
803 return new ocpnToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
804 clientData, shortHelp, longHelp);
805 } else {
806 wxString testToolname = g_pi_manager->GetToolOwnerCommonName(id);
807
808 if (testToolname == "") { // Not a PlugIn tool...
809 return new ocpnToolBarTool(this, id, bmpNormal, bmpDisabled, kind,
810 clientData, shortHelp, longHelp);
811 } else {
812 return new ocpnToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
813 clientData, shortHelp, longHelp);
814 }
815 }
816}
817
818// ----------------------------------------------------------------------------
819// ocpnToolBarSimple creation
820// ----------------------------------------------------------------------------
821
822void ocpnToolBarSimple::Init() {
823 m_currentRowsOrColumns = 0;
824
825 m_lastX = m_lastY = 0;
826
827 m_maxWidth = m_maxHeight = 0;
828
829 m_pressedTool = m_currentTool = -1;
830
831 m_xPos = m_yPos = wxDefaultCoord;
832
833 m_style = g_StyleManager->GetCurrentStyle();
834
835 m_defaultWidth = 16;
836 m_defaultHeight = 15;
837
838 m_toggle_bg_color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
839 m_toolOutlineColour.Set("BLACK");
840 m_last_ro_tool = NULL;
841
842 m_btoolbar_is_zooming = false;
843 m_sizefactor = 1.0f;
844
845 m_last_plugin_down_id = -1;
846 m_leftDown = false;
847 m_nShowTools = 0;
848 m_btooltip_show = false;
849#ifndef __ANDROID__
850 EnableTooltips();
851#endif
852 m_tbenableRolloverBitmaps = false;
853}
854
855wxToolBarToolBase *ocpnToolBarSimple::DoAddTool(
856 int id, const wxString &label, const wxBitmap &bitmap,
857 const wxBitmap &bmpDisabled, wxItemKind kind, const wxString &shortHelp,
858 const wxString &longHelp, wxObject *clientData, wxCoord xPos,
859 wxCoord yPos) {
860 // rememeber the position for DoInsertTool()
861 m_xPos = xPos;
862 m_yPos = yPos;
863
864 // InvalidateBestSize();
865 return InsertTool(GetToolsCount(), id, label, bitmap, bmpDisabled, kind,
866 shortHelp, longHelp, clientData);
867}
868
870
871wxToolBarToolBase *ocpnToolBarSimple::AddTool(
872 int toolid, const wxString &label, const wxBitmap &bitmap,
873 const wxBitmap &bmpDisabled, wxItemKind kind, const wxString &shortHelp,
874 const wxString &longHelp, wxObject *data) {
875 // InvalidateBestSize();
876 ocpnToolBarTool *tool = (ocpnToolBarTool *)InsertTool(
877 GetToolsCount(), toolid, label, bitmap, bmpDisabled, kind, shortHelp,
878 longHelp, data);
879 return tool;
880}
881
882wxToolBarToolBase *ocpnToolBarSimple::InsertTool(
883 size_t pos, int id, const wxString &label, const wxBitmap &bitmap,
884 const wxBitmap &bmpDisabled, wxItemKind kind, const wxString &shortHelp,
885 const wxString &longHelp, wxObject *clientData) {
886 wxCHECK_MSG(pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
887 "invalid position in wxToolBar::InsertTool()");
888
889 wxToolBarToolBase *tool = CreateTool(id, label, bitmap, bmpDisabled, kind,
890 clientData, shortHelp, longHelp);
891
892 if (!InsertTool(pos, tool)) {
893 delete tool;
894
895 return NULL;
896 }
897
898 return tool;
899}
900
901wxToolBarToolBase *ocpnToolBarSimple::InsertTool(size_t pos,
902 wxToolBarToolBase *tool) {
903 wxCHECK_MSG(pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
904 "invalid position in wxToolBar::InsertTool()");
905
906 if (!tool || !DoInsertTool(pos, tool)) {
907 return NULL;
908 }
909
910 m_tools.Insert(pos, tool);
911 m_nShowTools++;
912
913 return tool;
914}
915
916bool ocpnToolBarSimple::DoInsertTool(size_t WXUNUSED(pos),
917 wxToolBarToolBase *toolBase) {
918 ocpnToolBarTool *tool = (ocpnToolBarTool *)toolBase;
919
920 // Check if the plugin is inserting same-named tools. Make sure they have
921 // different names, otherwise the style manager cannot differentiate between
922 // them.
923 if (tool->isPluginTool) {
924 for (unsigned int i = 0; i < GetToolsCount(); i++) {
925 if (tool->GetToolname() ==
926 ((ocpnToolBarTool *)m_tools.Item(i)->GetData())->GetToolname()) {
927 tool->toolname << "1";
928 }
929 }
930 }
931
932 tool->m_x = m_xPos;
933 if (tool->m_x == wxDefaultCoord) tool->m_x = m_style->GetLeftMargin();
934
935 tool->m_y = m_yPos;
936 if (tool->m_y == wxDefaultCoord) tool->m_y = m_style->GetTopMargin();
937
938 if (tool->IsButton()) {
939 tool->SetSize(GetToolSize());
940
941 // Calculate reasonable max size in case Layout() not called
942 if ((tool->m_x + tool->GetNormalBitmap().GetWidth() +
943 m_style->GetLeftMargin()) > m_maxWidth)
944 m_maxWidth =
945 (wxCoord)((tool->m_x + tool->GetWidth() + m_style->GetLeftMargin()));
946
947 if ((tool->m_y + tool->GetNormalBitmap().GetHeight() +
948 m_style->GetTopMargin()) > m_maxHeight)
949 m_maxHeight =
950 (wxCoord)((tool->m_y + tool->GetHeight() + m_style->GetTopMargin()));
951 }
952
953 else if (tool->IsControl()) {
954 tool->SetSize(tool->GetControl()->GetSize());
955 }
956
957 tool->b_hilite = false;
958
959 return true;
960}
961
962bool ocpnToolBarSimple::DoDeleteTool(size_t WXUNUSED(pos),
963 wxToolBarToolBase *tool) {
964 // VZ: didn't test whether it works, but why not...
965 tool->Detach();
966
967 if (m_last_ro_tool == tool) m_last_ro_tool = NULL;
968
969 // Refresh(false);
970
971 return true;
972}
973
974bool ocpnToolBarSimple::Create(ocpnFloatingToolbarDialog *parent, wxWindowID id,
975 const wxPoint &pos, const wxSize &size,
976 long style, int orient) {
977 m_parentContainer = parent;
978 m_orient = orient;
979
980 if (IsVertical()) {
981 m_lastX = 7;
982 m_lastY = 3;
983
984 m_maxRows = 32000; // a lot
985 m_maxCols = 1;
986 } else {
987 m_lastX = 3;
988 m_lastY = 7;
989
990 m_maxRows = 1;
991 m_maxCols = 32000; // a lot
992 }
993
994 // SetCursor(*wxSTANDARD_CURSOR);
995
996 m_tooltip_timer.SetOwner(this, TOOLTIPON_TIMER);
997 m_tooltipoff_timer.SetOwner(this, TOOLTIPOFF_TIMER);
998 m_tooltip_off = 3000;
999
1000 m_tbenableRolloverBitmaps = false;
1001
1002 return true;
1003}
1004
1005ocpnToolBarSimple::~ocpnToolBarSimple() {}
1006
1007void ocpnToolBarSimple::EnableTooltips() {
1008#ifndef __ANDROID__
1009 m_btooltip_show = true;
1010#endif
1011}
1012
1013void ocpnToolBarSimple::DisableTooltips() {
1014#ifndef __ANDROID__
1015 ocpnToolBarSimple::m_btooltip_show = false;
1016#endif
1017}
1018
1019void ocpnToolBarSimple::KillTooltip() {
1020 m_btooltip_show = false;
1021
1023 m_tooltip_timer.Stop();
1024
1025 gFrame->Raise();
1026 gFrame->GetFocusCanvas()->TriggerDeferredFocus();
1027}
1028
1029void ocpnToolBarSimple::HideTooltip() {
1030#ifndef __ANDROID__
1032#endif
1033}
1034
1035void ocpnToolBarSimple::SetColorScheme(ColorScheme cs) {
1036#ifndef __ANDROID__
1038#endif
1039 m_toolOutlineColour = GetGlobalColor("UIBDR");
1040
1041 m_currentColorScheme = cs;
1042}
1043
1044bool ocpnToolBarSimple::Realize() {
1045 if (IsVertical())
1046 m_style->SetOrientation(wxTB_VERTICAL);
1047 else
1048 m_style->SetOrientation(wxTB_HORIZONTAL);
1049
1050 wxSize toolSize = wxSize(-1, -1);
1051 int separatorSize = m_style->GetToolSeparation() * m_sizefactor;
1052 int topMargin = m_style->GetTopMargin() * m_sizefactor;
1053 int leftMargin = m_style->GetLeftMargin() * m_sizefactor;
1054
1055 m_currentRowsOrColumns = 0;
1056 m_LineCount = 1;
1057 m_lastX = leftMargin;
1058 m_lastY = topMargin;
1059 m_maxWidth = 0;
1060 m_maxHeight = 0;
1061
1062 ocpnToolBarTool *lastTool = NULL;
1063 bool firstNode = true;
1064 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1065
1066 int iNode = 0;
1067
1068 while (node) {
1069 if (iNode >= m_nShowTools) break;
1070
1071 ocpnToolBarTool *tool = (ocpnToolBarTool *)node->GetData();
1072
1073 // Set the tool size to be the size of the first non-separator tool, usually
1074 // the first one
1075 if (toolSize.x == -1) {
1076 if (!tool->IsSeparator()) {
1077 toolSize.x = tool->m_width;
1078 toolSize.y = tool->m_height;
1079 }
1080 }
1081
1082 tool->firstInLine = firstNode;
1083 tool->lastInLine = false;
1084 firstNode = false;
1085
1086 tool->last_rect.width = 0; // mark it invalid
1087
1088 if (tool->IsSeparator()) {
1089 // if (GetWindowStyleFlag() & wxTB_HORIZONTAL) {
1090 // if (m_currentRowsOrColumns >= m_maxCols)
1091 // m_lastY += separatorSize;
1092 // else
1093 // m_lastX += separatorSize;
1094 //}
1095 // else
1096 {
1097 if (m_currentRowsOrColumns >= m_maxRows)
1098 m_lastX += separatorSize;
1099 else
1100 m_lastY += separatorSize;
1101 }
1102 } else if (tool->IsButton()) {
1103 if (!IsVertical()) {
1104 if (m_currentRowsOrColumns >= m_maxCols) {
1105 tool->firstInLine = true;
1106 if (lastTool && m_LineCount > 1) lastTool->lastInLine = true;
1107 m_LineCount++;
1108 m_currentRowsOrColumns = 0;
1109 m_lastX = leftMargin;
1110 m_lastY += toolSize.y + topMargin;
1111 }
1112 tool->m_x = (wxCoord)m_lastX;
1113 tool->m_y = (wxCoord)m_lastY;
1114
1115 tool->trect = wxRect(tool->m_x, tool->m_y, toolSize.x, toolSize.y);
1116 tool->trect.Inflate(separatorSize / 2, topMargin);
1117
1118 m_lastX += toolSize.x + separatorSize;
1119 } else {
1120 if (m_currentRowsOrColumns >= m_maxRows) {
1121 tool->firstInLine = true;
1122 if (lastTool) lastTool->lastInLine = true;
1123 m_LineCount++;
1124 m_currentRowsOrColumns = 0;
1125 m_lastX += toolSize.x + leftMargin;
1126 m_lastY = topMargin;
1127 }
1128 tool->m_x = (wxCoord)m_lastX;
1129 tool->m_y = (wxCoord)m_lastY;
1130
1131 tool->trect = wxRect(tool->m_x, tool->m_y, toolSize.x, toolSize.y);
1132 tool->trect.Inflate((separatorSize / 2), topMargin);
1133
1134 m_lastY += toolSize.y + separatorSize;
1135 }
1136 m_currentRowsOrColumns++;
1137 }
1138 // else
1139 // if (tool->IsControl()) {
1140 // tool->m_x = (wxCoord)(m_lastX);
1141 // tool->m_y = (wxCoord)(m_lastY - (topMargin / 2));
1142
1143 // tool->trect =
1144 // wxRect(tool->m_x, tool->m_y, tool->GetWidth(), tool->GetHeight());
1145 // tool->trect.Inflate(separatorSize / 2, topMargin);
1146
1147 // wxSize s = tool->GetControl()->GetSize();
1148 // m_lastX += s.x + separatorSize;
1149 //}
1150
1151 if (m_lastX > m_maxWidth) m_maxWidth = m_lastX;
1152 if (m_lastY > m_maxHeight) m_maxHeight = m_lastY;
1153
1154 lastTool = tool;
1155 node = node->GetNext();
1156 iNode++;
1157 }
1158 if (lastTool && (m_LineCount > 1 || IsVertical()))
1159 lastTool->lastInLine = true;
1160
1161 if (!IsVertical()) {
1162 m_maxHeight += toolSize.y;
1163 m_maxHeight += m_style->GetBottomMargin();
1164 } else {
1165 m_maxWidth += toolSize.x;
1166 m_maxWidth += m_style->GetRightMargin() * m_sizefactor;
1167 }
1168
1169 m_bitmap = wxNullBitmap;
1170
1171 return true;
1172}
1173
1174wxBitmap &ocpnToolBarSimple::CreateBitmap(double display_scale) {
1175 if (m_bitmap.IsOk()) return m_bitmap;
1176
1177 // Make the bitmap
1178 int width = m_maxWidth;
1179 int height = m_maxHeight;
1180
1181 wxMemoryDC mdc;
1182 wxBitmap bm(width, height);
1183 mdc.SelectObject(bm);
1184 mdc.SetBackground(wxBrush(GetBackgroundColour()));
1185 mdc.Clear();
1186
1187 // In a loop, draw the tools
1188 for (wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1189 node; node = node->GetNext()) {
1190 wxToolBarToolBase *tool = node->GetData();
1191 ocpnToolBarTool *tools = (ocpnToolBarTool *)tool;
1192 wxRect toolRect = tools->trect;
1193 CreateToolBitmap(tool);
1194
1195 if (tools->m_activeBitmap.IsOk()) {
1196 mdc.DrawBitmap(tools->m_activeBitmap, tools->m_x, tools->m_y, false);
1197 }
1198 int yyp = 5;
1199 }
1200
1201 mdc.SelectObject(wxNullBitmap);
1202
1203 m_bitmap = bm;
1204 return m_bitmap;
1205}
1206
1207void ocpnToolBarSimple::OnToolTipTimerEvent(wxTimerEvent &event) {
1208 if (!gFrame) // In case gFrame was already destroyed, but the toolbar still
1209 // exists (Which should not happen, ever.)
1210 return;
1211
1212 if (m_btooltip_show /*&& IsShown()*/) {
1213 if (m_last_ro_tool) {
1214 wxString s = m_last_ro_tool->GetShortHelp();
1215
1216 if (s.Len()) {
1217 // Calculate tooltip position relative to the tool
1218 wxPoint pos_in_toolbar(m_last_ro_tool->m_x, m_last_ro_tool->m_y);
1219 pos_in_toolbar.x += m_last_ro_tool->m_width + 2;
1220
1221 wxPoint screenPosition =
1222 gFrame->GetPrimaryCanvas()->ClientToScreen(pos_in_toolbar);
1223
1224 // Show tooltip using new system
1226 gFrame->GetPrimaryCanvas(), s, screenPosition,
1227 m_last_ro_tool->m_btooltip_hiviz);
1228
1229#ifndef __WXOSX__
1230 gFrame->Raise();
1231#endif
1232
1233#ifndef __ANDROID__
1234 if (g_btouch) m_tooltipoff_timer.Start(m_tooltip_off, wxTIMER_ONE_SHOT);
1235#endif
1236 }
1237 }
1238 }
1239}
1240
1241void ocpnToolBarSimple::OnToolTipOffTimerEvent(wxTimerEvent &event) {
1242 HideTooltip();
1243}
1244
1245bool ocpnToolBarSimple::OnMouseEvent(wxMouseEvent &event, wxPoint &position) {
1246 wxCoord x, y;
1247 event.GetPosition(&x, &y);
1248
1249 // in the toolbar?
1250 wxRect r = wxRect(position, wxSize(m_maxWidth, m_maxHeight));
1251 if (!r.Contains(x, y)) {
1252 HideTooltip();
1253 return false;
1254 }
1255
1256 m_parentContainer->RefreshFadeTimer();
1257
1258 ocpnToolBarTool *tool =
1259 (ocpnToolBarTool *)FindToolForPosition(x - position.x, y - position.y);
1260 if (tool == NULL) {
1261 m_tooltipoff_timer.Start(m_tooltip_off, wxTIMER_ONE_SHOT);
1262 return true;
1263 } else
1264 m_tooltipoff_timer.Stop();
1265
1266 // tooltips
1267 if (tool && tool->IsButton() /*&& IsShown()*/) {
1268 if (m_btooltip_show) {
1269 if (tool != m_last_ro_tool) {
1271 }
1272
1273#ifndef __ANDROID__
1274 if (!TooltipManager::Get().IsShown()) {
1275 if (!m_tooltip_timer.IsRunning()) {
1276 m_tooltip_timer.Start(m_one_shot, wxTIMER_ONE_SHOT);
1277 }
1278 }
1279#endif
1280 }
1281 }
1282
1283 m_last_ro_tool = tool;
1284
1285 // Left button pressed.
1286 if (event.LeftIsDown()) m_leftDown = true; // trigger on
1287
1288 if (event.LeftDown() && tool->IsEnabled()) {
1289 if (tool->CanBeToggled()) {
1290 tool->Toggle();
1291 tool->bitmapOK = false;
1292 SetDirty(true);
1293 m_bitmap = wxNullBitmap;
1294 }
1295
1296 // Look for PlugIn tools
1297 // If found, make the callback.
1298 if (g_pi_manager) {
1299 ArrayOfPlugInToolbarTools tool_array =
1300 g_pi_manager->GetPluginToolbarToolArray();
1301 for (unsigned int i = 0; i < tool_array.GetCount(); i++) {
1302 PlugInToolbarToolContainer *pttc = tool_array[i];
1303 if (tool->GetId() == pttc->id) {
1304 opencpn_plugin_113 *ppi =
1305 dynamic_cast<opencpn_plugin_113 *>(pttc->m_pplugin);
1306 if (ppi) {
1307 ppi->OnToolbarToolDownCallback(pttc->id);
1308 m_last_plugin_down_id = pttc->id;
1309 }
1310 }
1311 }
1312 }
1313 } else if (event.RightDown()) {
1314 OnRightClick(tool->GetId(), x, y);
1315 }
1316
1317 // Left Button Released. Only this action confirms selection.
1318 // If the button is enabled and it is not a toggle tool and it is
1319 // in the pressed state, then raise the button and call OnLeftClick.
1320 //
1321 // Unfortunately, some touch screen drivers do not send "LeftIsDown" events.
1322 // Nor do they report "LeftIsDown" in any state.
1323 // c.f rPI "official" 7" panel.
1324
1325 // So, for this logic, assume in touch mode that the m_leftDown flag may not
1326 // be set, and process the left-up event anyway.
1327 if (event.LeftUp() && tool->IsEnabled() && (m_leftDown || g_btouch)) {
1328 // Pass the OnLeftClick event to tool
1329 if (!OnLeftClick(tool->GetId(), tool->IsToggled()) &&
1330 tool->CanBeToggled()) {
1331 // If it was a toggle, and OnLeftClick says No Toggle allowed,
1332 // then change it back
1333 tool->Toggle();
1334 tool->bitmapOK = false;
1335 }
1336
1337 DoPluginToolUp();
1338 m_leftDown = false;
1339 return true;
1340 }
1341
1342 return true;
1343}
1344
1345// ----------------------------------------------------------------------------
1346// drawing
1347// ----------------------------------------------------------------------------
1348
1349void ocpnToolBarSimple::CreateToolBitmap(wxToolBarToolBase *toolBase) {
1350 ocpnToolBarTool *tool = (ocpnToolBarTool *)toolBase;
1351
1352 wxBitmap bmp = wxNullBitmap;
1353
1354 bool bNeedClear = !tool->bitmapOK;
1355
1356 if (tool->bitmapOK) {
1357 if (tool->IsEnabled()) {
1358 bmp = tool->GetNormalBitmap();
1359 if (!bmp.IsOk()) {
1360 bmp =
1361 m_style->GetToolIcon(tool->GetToolname(), TOOLICON_NORMAL,
1362 tool->rollover, tool->m_width, tool->m_height);
1363 tool->SetNormalBitmap(bmp);
1364 tool->bitmapOK = true;
1365 }
1366 } else {
1367 bmp = tool->GetDisabledBitmap();
1368 if (!bmp.IsOk()) {
1369 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_DISABLED,
1370 false, tool->m_width, tool->m_height);
1371 tool->SetDisabledBitmap(bmp);
1372 tool->bitmapOK = true;
1373 }
1374 }
1375 } else {
1376 if (tool->isPluginTool) {
1377 int toggleFlag = tool->IsToggled() ? TOOLICON_TOGGLED : TOOLICON_NORMAL;
1378
1379 // First try getting the icon from an SVG definition.
1380 // If it is not found, try to see if it is available in the style
1381 // If not there, we build a new icon from the style BG and the (default)
1382 // plugin icon.
1383
1384 wxString svgFile = tool->pluginNormalIconSVG;
1385 if (toggleFlag) {
1386 if (tool->pluginToggledIconSVG.Length())
1387 svgFile = tool->pluginToggledIconSVG;
1388 }
1389 if (tool->rollover) {
1390 if (tool->pluginRolloverIconSVG.Length())
1391 svgFile = tool->pluginRolloverIconSVG;
1392 }
1393
1394 if (!svgFile.IsEmpty()) { // try SVG
1395#ifdef ocpnUSE_SVG
1396 bmp = LoadSVG(svgFile, tool->m_width, tool->m_height);
1397 if (bmp.IsOk()) {
1398 bmp = m_style->BuildPluginIcon(bmp, toggleFlag, m_sizefactor);
1399 } else
1400 bmp =
1401 m_style->BuildPluginIcon(tool->pluginNormalIcon, TOOLICON_NORMAL);
1402#endif
1403 }
1404
1405 if (!bmp.IsOk() || bmp.IsNull()) {
1406 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1407 bmp = m_style->GetToolIcon(tool->GetToolname(), toggleFlag,
1408 tool->rollover, tool->m_width,
1409 tool->m_height);
1410 } else {
1411 bmp = wxNullBitmap;
1412 }
1413
1414 if (bmp.IsNull()) { // Tool icon not found in style definition
1415 // bmp = m_style->BuildPluginIcon(tool->pluginNormalIcon, toggleFlag);
1416 bmp = tool->pluginNormalIcon;
1417 if (fabs(m_sizefactor - 1.0) > 0.01) {
1418 if (tool->m_width && tool->m_height) {
1419 wxImage scaled_image = bmp.ConvertToImage();
1420 bmp = wxBitmap(scaled_image.Scale(tool->m_width, tool->m_height,
1421 wxIMAGE_QUALITY_HIGH));
1422 }
1423 }
1424 }
1425 }
1426 tool->SetNormalBitmap(bmp);
1427 tool->bitmapOK = true;
1428 } else { // Not a plugin tool
1429 bmp = tool->GetNormalBitmap();
1430 if (tool->IsEnabled()) {
1431 if (tool->IsToggled()) {
1432 if (!tool->bitmapOK) {
1433 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1434 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_TOGGLED,
1435 tool->rollover, tool->m_width,
1436 tool->m_height);
1437 tool->SetNormalBitmap(bmp);
1438 }
1439 }
1440 }
1441
1442 else {
1443 if (!tool->bitmapOK) {
1444 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1445 bmp = m_style->GetToolIcon(tool->GetIconName(), TOOLICON_NORMAL,
1446 tool->rollover, tool->m_width,
1447 tool->m_height);
1448 tool->SetNormalBitmap(bmp);
1449 }
1450 }
1451 }
1452
1453 tool->bitmapOK = true;
1454 } else {
1455 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_DISABLED,
1456 false, tool->m_width, tool->m_height);
1457 tool->SetDisabledBitmap(bmp);
1458 tool->bitmapOK = true;
1459 }
1460 }
1461 }
1462 tool->m_activeBitmap = bmp;
1463}
1464
1465// NB! The current DrawTool code assumes that plugin tools are never disabled
1466// when they are present on the toolbar, since disabled plugins are removed.
1467
1468void ocpnToolBarSimple::DrawTool(wxDC &dc, wxToolBarToolBase *toolBase) {
1469 ocpnToolBarTool *tool = (ocpnToolBarTool *)toolBase;
1470 // PrepareDC(dc);
1471
1472 wxPoint drawAt(tool->m_x, tool->m_y);
1473 wxBitmap bmp = wxNullBitmap;
1474
1475 bool bNeedClear = !tool->bitmapOK;
1476
1477 if (tool->bitmapOK) {
1478 if (tool->IsEnabled()) {
1479 bmp = tool->GetNormalBitmap();
1480 if (!bmp.IsOk()) {
1481 bmp =
1482 m_style->GetToolIcon(tool->GetToolname(), TOOLICON_NORMAL,
1483 tool->rollover, tool->m_width, tool->m_height);
1484 tool->SetNormalBitmap(bmp);
1485 tool->bitmapOK = true;
1486 }
1487 } else {
1488 bmp = tool->GetDisabledBitmap();
1489 if (!bmp.IsOk()) {
1490 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_DISABLED,
1491 false, tool->m_width, tool->m_height);
1492 tool->SetDisabledBitmap(bmp);
1493 tool->bitmapOK = true;
1494 }
1495 }
1496 } else {
1497 if (tool->isPluginTool) {
1498 int toggleFlag = tool->IsToggled() ? TOOLICON_TOGGLED : TOOLICON_NORMAL;
1499
1500 // First try getting the icon from an SVG definition.
1501 // If it is not found, try to see if it is available in the style
1502 // If not there, we build a new icon from the style BG and the (default)
1503 // plugin icon.
1504
1505 wxString svgFile = tool->pluginNormalIconSVG;
1506 if (toggleFlag) {
1507 if (tool->pluginToggledIconSVG.Length())
1508 svgFile = tool->pluginToggledIconSVG;
1509 }
1510 if (tool->rollover) {
1511 if (tool->pluginRolloverIconSVG.Length())
1512 svgFile = tool->pluginRolloverIconSVG;
1513 }
1514
1515 if (!svgFile.IsEmpty()) { // try SVG
1516#ifdef ocpnUSE_SVG
1517 bmp = LoadSVG(svgFile, tool->m_width, tool->m_height);
1518 if (bmp.IsOk()) {
1519 bmp = m_style->BuildPluginIcon(bmp, toggleFlag, m_sizefactor);
1520 } else
1521 bmp =
1522 m_style->BuildPluginIcon(tool->pluginNormalIcon, TOOLICON_NORMAL);
1523#endif
1524 }
1525
1526 if (!bmp.IsOk() || bmp.IsNull()) {
1527 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1528 bmp = m_style->GetToolIcon(tool->GetToolname(), toggleFlag,
1529 tool->rollover, tool->m_width,
1530 tool->m_height);
1531 } else {
1532 bmp = wxNullBitmap;
1533 }
1534
1535 if (bmp.IsNull()) { // Tool icon not found
1536 if (tool->rollover) {
1537 bmp =
1538 m_style->BuildPluginIcon(tool->pluginRolloverIcon, toggleFlag);
1539 if (!bmp.IsOk()) {
1540 bmp =
1541 m_style->BuildPluginIcon(tool->pluginNormalIcon, toggleFlag);
1542 }
1543 } else {
1544 bmp = m_style->BuildPluginIcon(tool->pluginNormalIcon, toggleFlag);
1545 }
1546 if (fabs(m_sizefactor - 1.0) > 0.01) {
1547 if (tool->m_width && tool->m_height) {
1548 wxImage scaled_image = bmp.ConvertToImage();
1549 bmp = wxBitmap(scaled_image.Scale(tool->m_width, tool->m_height,
1550 wxIMAGE_QUALITY_HIGH));
1551 }
1552 }
1553 }
1554 }
1555 tool->SetNormalBitmap(bmp);
1556 tool->bitmapOK = true;
1557 } else { // Not a plugin tool
1558 bmp = tool->GetNormalBitmap();
1559 if (tool->IsEnabled()) {
1560 if (tool->IsToggled()) {
1561 if (!tool->bitmapOK) {
1562 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1563 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_TOGGLED,
1564 tool->rollover, tool->m_width,
1565 tool->m_height);
1566 tool->SetNormalBitmap(bmp);
1567 }
1568 }
1569 }
1570
1571 else {
1572 if (!tool->bitmapOK) {
1573 if (m_style->NativeToolIconExists(tool->GetToolname())) {
1574 bmp = m_style->GetToolIcon(tool->GetIconName(), TOOLICON_NORMAL,
1575 tool->rollover, tool->m_width,
1576 tool->m_height);
1577 tool->SetNormalBitmap(bmp);
1578 }
1579 }
1580 }
1581
1582 tool->bitmapOK = true;
1583 } else {
1584 bmp = m_style->GetToolIcon(tool->GetToolname(), TOOLICON_DISABLED,
1585 false, tool->m_width, tool->m_height);
1586 tool->SetDisabledBitmap(bmp);
1587 tool->bitmapOK = true;
1588 }
1589 }
1590 }
1591
1592 if (tool->firstInLine) {
1593 m_style->DrawToolbarLineStart(bmp, m_sizefactor);
1594 }
1595 if (tool->lastInLine) {
1596 m_style->DrawToolbarLineEnd(bmp, m_sizefactor);
1597 }
1598
1599 if (bmp.GetWidth() != m_style->GetToolSize().x ||
1600 bmp.GetHeight() != m_style->GetToolSize().y) {
1601 // drawAt.x -= ( bmp.GetWidth() - m_style->GetToolSize().x ) / 2;
1602 // drawAt.y -= ( bmp.GetHeight() - m_style->GetToolSize().y ) / 2;
1603 }
1604
1605 // Clear the last drawn tool if necessary
1606 if ((tool->last_rect.width &&
1607 (tool->last_rect.x != drawAt.x || tool->last_rect.y != drawAt.y)) ||
1608 bNeedClear) {
1609 wxBrush bb(GetGlobalColor("GREY3"));
1610 dc.SetBrush(bb);
1611 dc.SetPen(*wxTRANSPARENT_PEN);
1612 dc.DrawRectangle(tool->last_rect.x, tool->last_rect.y,
1613 tool->last_rect.width, tool->last_rect.height);
1614 }
1615
1616 // could cache this in the tool...
1617 // A bit of a hack here. We only scale tools if they are to be magnified
1618 // globally
1619 if (0 /*m_sizefactor > 1.0*/) {
1620 wxImage scaled_image = bmp.ConvertToImage();
1621 wxBitmap sbmp = wxBitmap(scaled_image.Scale(tool->m_width, tool->m_height,
1622 wxIMAGE_QUALITY_HIGH));
1623 dc.DrawBitmap(sbmp, drawAt);
1624 tool->last_rect =
1625 wxRect(drawAt.x, drawAt.y, sbmp.GetWidth(), sbmp.GetHeight());
1626
1627 } else {
1628 dc.DrawBitmap(bmp, drawAt);
1629 tool->last_rect =
1630 wxRect(drawAt.x, drawAt.y, bmp.GetWidth(), bmp.GetHeight());
1631 }
1632}
1633
1634// ----------------------------------------------------------------------------
1635// toolbar geometry
1636// ----------------------------------------------------------------------------
1637
1638wxToolBarToolBase *ocpnToolBarSimple::FindToolForPosition(wxCoord x,
1639 wxCoord y) {
1640 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1641 while (node) {
1642 ocpnToolBarTool *tool = (ocpnToolBarTool *)node->GetData();
1643 if ((x >= tool->m_x) && (y >= tool->m_y) &&
1644 (x < (tool->m_x + tool->GetWidth())) &&
1645 (y < (tool->m_y + tool->GetHeight()))) {
1646 return tool;
1647 }
1648
1649 node = node->GetNext();
1650 }
1651
1652 return (wxToolBarToolBase *)NULL;
1653}
1654
1655void ocpnToolBarSimple::InvalidateBitmaps() {
1656 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1657 while (node) {
1658 ocpnToolBarTool *tool = (ocpnToolBarTool *)node->GetData();
1659 tool->bitmapOK = false;
1660 node = node->GetNext();
1661 }
1662 m_bitmap = wxNullBitmap;
1663}
1664
1665wxRect ocpnToolBarSimple::GetToolRect(int tool_id) {
1666 wxRect rect;
1667 wxToolBarToolBase *tool = FindById(tool_id);
1668 if (tool) {
1669 ocpnToolBarTool *otool = (ocpnToolBarTool *)tool;
1670 if (otool) rect = otool->trect;
1671 }
1672
1673 return rect;
1674}
1675
1676// ----------------------------------------------------------------------------
1677// tool state change handlers
1678// ----------------------------------------------------------------------------
1679
1680void ocpnToolBarSimple::DoEnableTool(wxToolBarToolBase *tool,
1681 bool WXUNUSED(enable)) {
1682 ocpnToolBarTool *t = (ocpnToolBarTool *)tool;
1683 t->bitmapOK = false;
1684}
1685
1686void ocpnToolBarSimple::DoToggleTool(wxToolBarToolBase *tool,
1687 bool WXUNUSED(toggle)) {
1688 ocpnToolBarTool *t = (ocpnToolBarTool *)tool;
1689 t->bitmapOK = false;
1690 SetDirty(true);
1691}
1692
1693// ----------------------------------------------------------------------------
1694// scrolling implementation
1695// ----------------------------------------------------------------------------
1696
1697wxString ocpnToolBarSimple::GetToolShortHelp(int id) const {
1698 wxToolBarToolBase *tool = FindById(id);
1699 wxCHECK_MSG(tool, "", "no such tool");
1700
1701 return tool->GetShortHelp();
1702}
1703
1704wxString ocpnToolBarSimple::GetToolLongHelp(int id) const {
1705 wxToolBarToolBase *tool = FindById(id);
1706 wxCHECK_MSG(tool, "", "no such tool");
1707
1708 return tool->GetLongHelp();
1709}
1710
1711void ocpnToolBarSimple::SetToolShortHelp(int id, const wxString &help) {
1712 wxToolBarToolBase *tool = FindById(id);
1713 if (tool) {
1714 (void)tool->SetShortHelp(help);
1715 }
1716}
1717
1718void ocpnToolBarSimple::SetToolLongHelp(int id, const wxString &help) {
1719 wxToolBarToolBase *tool = FindById(id);
1720 if (tool) {
1721 (void)tool->SetLongHelp(help);
1722 }
1723}
1724
1725int ocpnToolBarSimple::GetToolPos(int id) const {
1726 size_t pos = 0;
1727 wxToolBarToolsList::compatibility_iterator node;
1728
1729 for (node = m_tools.GetFirst(); node; node = node->GetNext()) {
1730 if (node->GetData()->GetId() == id) return pos;
1731
1732 pos++;
1733 }
1734
1735 return wxNOT_FOUND;
1736}
1737bool ocpnToolBarSimple::GetToolState(int id) const {
1738 wxToolBarToolBase *tool = FindById(id);
1739 wxCHECK_MSG(tool, false, "no such tool");
1740
1741 return tool->IsToggled();
1742}
1743
1744bool ocpnToolBarSimple::GetToolEnabled(int id) const {
1745 wxToolBarToolBase *tool = FindById(id);
1746 wxCHECK_MSG(tool, false, "no such tool");
1747
1748 return tool->IsEnabled();
1749}
1750
1751void ocpnToolBarSimple::ToggleTool(int id, bool toggle) {
1752 wxToolBarToolBase *tool = FindById(id);
1753
1754 if (tool && tool->CanBeToggled() && tool->Toggle(toggle)) {
1755 DoToggleTool(tool, toggle);
1756 InvalidateBitmaps();
1757 gFrame->GetPrimaryCanvas()->Refresh(true);
1758 }
1759}
1760
1761wxObject *ocpnToolBarSimple::GetToolClientData(int id) const {
1762 wxToolBarToolBase *tool = FindById(id);
1763 return tool ? tool->GetClientData() : (wxObject *)NULL;
1764}
1765
1766void ocpnToolBarSimple::SetToolClientData(int id, wxObject *clientData) {
1767 wxToolBarToolBase *tool = FindById(id);
1768
1769 wxCHECK_RET(tool, "no such tool in wxToolBar::SetToolClientData");
1770
1771 tool->SetClientData(clientData);
1772}
1773
1774void ocpnToolBarSimple::EnableTool(int id, bool enable) {
1775 wxToolBarToolBase *tool = FindById(id);
1776 if (tool) {
1777 if (tool->Enable(enable)) {
1778 DoEnableTool(tool, enable);
1779 }
1780 }
1781
1782 ocpnFloatingToolbarDialog *parent = m_parentContainer;
1783 if (parent && parent->m_FloatingToolbarConfigMenu) {
1784 wxMenuItem *configItem = parent->m_FloatingToolbarConfigMenu->FindItem(id);
1785 if (configItem) configItem->Check(true);
1786 }
1787}
1788
1789void ocpnToolBarSimple::SetToolTooltipHiViz(int id, bool b_hiviz) {
1790 ocpnToolBarTool *tool = (ocpnToolBarTool *)FindById(id);
1791 if (tool) {
1792 tool->SetTooltipHiviz(b_hiviz);
1793 }
1794}
1795
1796void ocpnToolBarSimple::ClearTools() {
1797 while (GetToolsCount()) {
1798 DeleteToolByPos(0);
1799 }
1800}
1801
1802int ocpnToolBarSimple::GetVisibleToolCount() {
1803 int counter = 0;
1804 wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1805 while (node) {
1806 ocpnToolBarTool *tool = (ocpnToolBarTool *)node->GetData();
1807 counter++;
1808 node = node->GetNext();
1809 }
1810 return counter;
1811}
1812
1813bool ocpnToolBarSimple::DeleteToolByPos(size_t pos) {
1814 wxCHECK_MSG(pos < GetToolsCount(), false,
1815 "invalid position in wxToolBar::DeleteToolByPos()");
1816
1817 wxToolBarToolsList::compatibility_iterator node = m_tools.Item(pos);
1818
1819 if (!DoDeleteTool(pos, node->GetData())) {
1820 return false;
1821 }
1822
1823 delete node->GetData();
1824 m_tools.Erase(node);
1825
1826 return true;
1827}
1828
1829bool ocpnToolBarSimple::DeleteTool(int id) {
1830 size_t pos = 0;
1831 wxToolBarToolsList::compatibility_iterator node;
1832 for (node = m_tools.GetFirst(); node; node = node->GetNext()) {
1833 if (node->GetData()->GetId() == id) break;
1834
1835 pos++;
1836 }
1837
1838 if (!node || !DoDeleteTool(pos, node->GetData())) {
1839 return false;
1840 }
1841
1842 delete node->GetData();
1843 m_tools.Erase(node);
1844
1845 return true;
1846}
1847
1848wxToolBarToolBase *ocpnToolBarSimple::AddSeparator() {
1849 return InsertSeparator(GetToolsCount());
1850}
1851
1852wxToolBarToolBase *ocpnToolBarSimple::InsertSeparator(size_t pos) {
1853 wxCHECK_MSG(pos <= GetToolsCount(), (wxToolBarToolBase *)NULL,
1854 "invalid position in wxToolBar::InsertSeparator()");
1855
1856 wxToolBarToolBase *tool =
1857 CreateTool(wxID_SEPARATOR, "", wxNullBitmap, wxNullBitmap,
1858 wxITEM_SEPARATOR, (wxObject *)NULL, "", "");
1859
1860 if (!tool || !DoInsertTool(pos, tool)) {
1861 delete tool;
1862
1863 return NULL;
1864 }
1865
1866 m_tools.Insert(pos, tool);
1867 m_nShowTools++;
1868
1869 return tool;
1870}
1871
1872wxToolBarToolBase *ocpnToolBarSimple::RemoveTool(int id) {
1873 size_t pos = 0;
1874 wxToolBarToolsList::compatibility_iterator node;
1875 for (node = m_tools.GetFirst(); node; node = node->GetNext()) {
1876 if (node->GetData()->GetId() == id) break;
1877
1878 pos++;
1879 }
1880
1881 if (!node) {
1882 // don't give any error messages - sometimes we might call RemoveTool()
1883 // without knowing whether the tool is or not in the toolbar
1884 return (wxToolBarToolBase *)NULL;
1885 }
1886
1887 wxToolBarToolBase *tool = node->GetData();
1888 if (!DoDeleteTool(pos, tool)) {
1889 return (wxToolBarToolBase *)NULL;
1890 }
1891
1892 m_tools.Erase(node);
1893
1894 return tool;
1895}
1896
1897wxControl *ocpnToolBarSimple::FindControl(int id) {
1898 for (wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1899 node; node = node->GetNext()) {
1900 const wxToolBarToolBase *const tool = node->GetData();
1901 if (tool->IsControl()) {
1902 wxControl *const control = tool->GetControl();
1903
1904 if (!control) {
1905 wxFAIL_MSG("NULL control in toolbar?");
1906 } else if (control->GetId() == id) {
1907 // found
1908 return control;
1909 }
1910 }
1911 }
1912
1913 return NULL;
1914}
1915
1916wxToolBarToolBase *ocpnToolBarSimple::FindById(int id) const {
1917 wxToolBarToolBase *tool = (wxToolBarToolBase *)NULL;
1918
1919 for (wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
1920 node; node = node->GetNext()) {
1921 tool = node->GetData();
1922 if (tool->GetId() == id) {
1923 // found
1924 break;
1925 }
1926
1927 tool = NULL;
1928 }
1929
1930 return tool;
1931}
1932
1933// ----------------------------------------------------------------------------
1934// event processing
1935// ----------------------------------------------------------------------------
1936
1937// Only allow toggle if returns true
1938
1939bool ocpnToolBarSimple::OnLeftClick(int id, bool toggleDown) {
1940 wxCommandEvent event(wxEVT_COMMAND_TOOL_CLICKED, id);
1941 // event.SetEventObject(this);
1942
1943 // we use SetInt() to make wxCommandEvent::IsChecked() return toggleDown
1944 event.SetInt((int)toggleDown);
1945
1946 // and SetExtraLong() for backwards compatibility
1947 event.SetExtraLong((long)toggleDown);
1948
1949 gFrame->GetEventHandler()->AddPendingEvent(event);
1950
1951 return true;
1952}
1953
1954// Call when right button down.
1955void ocpnToolBarSimple::OnRightClick(int id, long WXUNUSED(x),
1956 long WXUNUSED(y)) {
1957 HideTooltip();
1958
1959 if (m_parentContainer) {
1960 if (m_parentContainer->m_FloatingToolbarConfigMenu) {
1962 new ToolbarChoicesDialog(NULL, m_parentContainer, -1, "OpenCPN",
1963 wxDefaultPosition, wxSize(100, 100));
1964 int rc = dlg->ShowModal();
1965 delete dlg;
1966
1967 if (rc == wxID_OK) {
1968 wxCommandEvent event(wxEVT_COMMAND_TOOL_RCLICKED, id);
1969 event.SetEventObject(this);
1970 event.SetInt(id);
1971
1972 gFrame->GetEventHandler()->AddPendingEvent(event);
1973 }
1974 }
1975 }
1976}
1977
1978void ocpnToolBarSimple::DoPluginToolUp() {
1979 // Look for PlugIn tools
1980 // If found, make the callback.
1981 if (!g_pi_manager) return;
1982
1983 ArrayOfPlugInToolbarTools tool_array =
1984 g_pi_manager->GetPluginToolbarToolArray();
1985 for (unsigned int i = 0; i < tool_array.GetCount(); i++) {
1986 PlugInToolbarToolContainer *pttc = tool_array[i];
1987 if (m_last_plugin_down_id == pttc->id) {
1988 opencpn_plugin_113 *ppi =
1989 dynamic_cast<opencpn_plugin_113 *>(pttc->m_pplugin);
1990 if (ppi) ppi->OnToolbarToolUpCallback(pttc->id);
1991 }
1992 }
1993
1994 m_last_plugin_down_id = -1;
1995}
1996
1997void ocpnToolBarSimple::SetToolNormalBitmapEx(wxToolBarToolBase *tool,
1998 const wxString &iconName) {
1999 if (tool) {
2000 ocpnToolBarTool *otool = (ocpnToolBarTool *)tool;
2001 if (otool) {
2002 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
2003
2004 wxBitmap bmp = style->GetToolIcon(iconName, TOOLICON_NORMAL, false,
2005 otool->m_width, otool->m_height);
2006 tool->SetNormalBitmap(bmp);
2007 otool->SetIconName(iconName);
2008 }
2009 }
2010}
2011
2012void ocpnToolBarSimple::SetToolNormalBitmapSVG(wxToolBarToolBase *tool,
2013 wxString fileSVG) {
2014 if (tool) {
2015 ocpnToolBarTool *otool = (ocpnToolBarTool *)tool;
2016 if (otool) {
2017 otool->pluginNormalIconSVG = fileSVG;
2018 }
2019 }
2020}
2021
2022void ocpnToolBarSimple::SetToolBitmaps(int id, wxBitmap *bmp,
2023 wxBitmap *bmpRollover) {
2024 ocpnToolBarTool *tool = (ocpnToolBarTool *)FindById(id);
2025 if (tool) {
2026 if (tool->isPluginTool) {
2027 if (bmp->GetWidth() != tool->GetWidth()) {
2028 if (bmp->IsOk()) {
2029 wxImage ibmp = bmp->ConvertToImage();
2030 ibmp.Rescale(tool->GetWidth(), tool->GetHeight(),
2031 wxIMAGE_QUALITY_HIGH);
2032 wxBitmap sbmp = wxBitmap(ibmp);
2033 tool->pluginNormalIcon = sbmp;
2034 }
2035 } else {
2036 tool->pluginNormalIcon = *bmp;
2037 }
2038
2039 if (bmpRollover->GetWidth() != tool->GetWidth()) {
2040 if (bmpRollover->IsOk()) {
2041 wxImage ibmp = bmpRollover->ConvertToImage();
2042 ibmp.Rescale(tool->GetWidth(), tool->GetHeight(),
2043 wxIMAGE_QUALITY_HIGH);
2044 wxBitmap sbmp = wxBitmap(ibmp);
2045 tool->pluginRolloverIcon = sbmp;
2046 }
2047 } else {
2048 tool->pluginRolloverIcon = *bmpRollover;
2049 }
2050 tool->bitmapOK = false;
2051
2052 } else {
2053 tool->SetNormalBitmap(*bmp);
2054 tool->bitmapOK = true;
2055 }
2056 InvalidateBitmaps();
2057 }
2058}
2059
2060void ocpnToolBarSimple::SetToolBitmapsSVG(int id, wxString fileSVGNormal,
2061 wxString fileSVGRollover,
2062 wxString fileSVGToggled) {
2063 ocpnToolBarTool *tool = (ocpnToolBarTool *)FindById(id);
2064 if (tool) {
2065 tool->pluginNormalIconSVG = fileSVGNormal;
2066 tool->pluginRolloverIconSVG = fileSVGRollover;
2067 tool->pluginToggledIconSVG = fileSVGToggled;
2068 tool->bitmapOK = false;
2069 InvalidateBitmaps();
2070 }
2071}
2072
2073//-------------------------------------------------------------------------------------
2074
2075ToolbarMOBDialog::ToolbarMOBDialog(wxWindow *parent)
2076 : wxDialog(parent, wxID_ANY, _("OpenCPN Alert"), wxDefaultPosition,
2077 wxSize(250, 230)) {
2078 wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
2079
2080 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2081 topSizer->Add(sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
2082
2083 choices.push_back(
2084 new wxRadioButton(this, 0, _("No, I don't want to hide it."),
2085 wxDefaultPosition, wxDefaultSize, wxRB_GROUP));
2086
2087 choices.push_back(new wxRadioButton(
2088 this, 1, _("No, and permanently remove the option to hide it."),
2089 wxDefaultPosition));
2090
2091 choices.push_back(
2092 new wxRadioButton(this, 2, _("Yes, hide it."), wxDefaultPosition));
2093
2094 wxStdDialogButtonSizer *buttonSizer =
2095 CreateStdDialogButtonSizer(wxOK | wxCANCEL);
2096
2097 wxStaticText *textCtrl =
2098 new wxStaticText(this, wxID_ANY,
2099 _("The Man Over Board button could be an important "
2100 "safety feature.\nAre you sure you want to hide it?"));
2101
2102 sizer->Add(textCtrl, 0, wxEXPAND | wxALL, 5);
2103 sizer->Add(choices[0], 0, wxEXPAND | wxALL, 5);
2104 sizer->Add(choices[1], 0, wxEXPAND | wxALL, 5);
2105 sizer->Add(choices[2], 0, wxEXPAND | wxALL, 5);
2106 sizer->Add(buttonSizer, 0, wxEXPAND | wxTOP, 5);
2107
2108 topSizer->SetSizeHints(this);
2109 SetSizer(topSizer);
2110}
2111
2112int ToolbarMOBDialog::GetSelection() {
2113 for (unsigned int i = 0; i < choices.size(); i++) {
2114 if (choices[i]->GetValue()) return choices[i]->GetId();
2115 }
2116 return 0;
2117}
2118
2122BEGIN_EVENT_TABLE(ToolbarChoicesDialog, wxDialog)
2123END_EVENT_TABLE()
2124
2125
2130
2133 wxWindowID id,
2134 const wxString &caption,
2135 const wxPoint &pos,
2136 const wxSize &size, long style) {
2137 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
2138 wxDialog::Create(parent, id, caption, pos, size, wstyle);
2139
2140 m_configMenu = NULL;
2141 m_ToolbarDialogAncestor = sponsor;
2142
2143 if (m_ToolbarDialogAncestor)
2144 m_configMenu = m_ToolbarDialogAncestor->m_FloatingToolbarConfigMenu;
2145
2147 GetSizer()->Fit(this);
2148
2149 RecalculateSize();
2150}
2151
2152ToolbarChoicesDialog::~ToolbarChoicesDialog() {}
2153
2159 wxBoxSizer *itemBoxSizer1 = new wxBoxSizer(wxVERTICAL);
2160 SetSizer(itemBoxSizer1);
2161
2162 wxScrolledWindow *itemDialog1 = new wxScrolledWindow(
2163 this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxHSCROLL | wxVSCROLL);
2164 itemDialog1->SetScrollRate(2, 2);
2165
2166#ifdef __ANDROID__
2167
2168 // Set Dialog Font by custom crafted Qt Stylesheet.
2169 wxFont *qFont = GetOCPNScaledFont(_("Dialog"));
2170
2171 wxString wqs = getFontQtStylesheet(qFont);
2172 wxCharBuffer sbuf = wqs.ToUTF8();
2173 QString qsb = QString(sbuf.data());
2174
2175 QString qsbq = getQtStyleSheet(); // basic scrollbars, etc
2176
2177 this->GetHandle()->setStyleSheet(qsb + qsbq); // Concatenated style sheets
2178
2179#endif
2180 itemBoxSizer1->Add(itemDialog1, 2, wxEXPAND | wxALL, 0);
2181
2182 wxBoxSizer *itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
2183 itemDialog1->SetSizer(itemBoxSizer2);
2184
2185 wxStaticBox *itemStaticBoxSizer3Static =
2186 new wxStaticBox(itemDialog1, wxID_ANY, _("Choose Toolbar Icons"));
2187 wxStaticBoxSizer *itemStaticBoxSizer3 =
2188 new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxVERTICAL);
2189 itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxEXPAND | wxALL, 5);
2190
2191 int nitems = 0;
2192 int max_width = -1;
2193 if (m_configMenu) {
2194 nitems = m_configMenu->GetMenuItemCount();
2195
2196 cboxes.clear();
2197 for (int i = 0; i < nitems; i++) {
2198 if (i + ID_ZOOMIN == ID_MOB && g_bPermanentMOBIcon) continue;
2199 wxMenuItem *item = m_configMenu->FindItemByPosition(i);
2200
2201 wxString label = item->GetItemLabel();
2202 int l = label.Len();
2203 max_width = wxMax(max_width, l);
2204
2205 wxString windowName = "";
2206 if (item->GetId() == ID_MOB + 100) windowName = "MOBCheck";
2207
2208 wxCheckBox *cb =
2209 new wxCheckBox(itemDialog1, -1, label, wxDefaultPosition,
2210 wxDefaultSize, 0, wxDefaultValidator, windowName);
2211 // wxCheckBox *cb = new wxCheckBox(itemDialog1, -1, label);
2212 itemStaticBoxSizer3->Add(cb, 0, wxALL | wxEXPAND, 2);
2213 cb->SetValue(item->IsChecked());
2214
2215 cboxes.push_back(cb);
2216 }
2217 }
2218
2219 itemBoxSizer1->SetMinSize((max_width + 20) * GetCharWidth(),
2220 (nitems + 4) * GetCharHeight() * 2);
2221
2222 wxBoxSizer *itemBoxSizerBottom = new wxBoxSizer(wxHORIZONTAL);
2223 itemBoxSizer1->Add(itemBoxSizerBottom, 0, wxALL | wxEXPAND, 5);
2224
2225 wxBoxSizer *itemBoxSizerAux = new wxBoxSizer(wxHORIZONTAL);
2226 itemBoxSizerBottom->Add(itemBoxSizerAux, 1, wxALL, 3);
2227
2228 wxBoxSizer *itemBoxSizer16 = new wxBoxSizer(wxHORIZONTAL);
2229 itemBoxSizerBottom->Add(itemBoxSizer16, 0, wxALL, 3);
2230
2231 m_CancelButton =
2232 new wxButton(this, -1, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0);
2233 itemBoxSizer16->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
2234
2235 m_OKButton =
2236 new wxButton(this, -1, _("OK"), wxDefaultPosition, wxDefaultSize, 0);
2237 itemBoxSizer16->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 1);
2238 m_OKButton->SetDefault();
2239
2240 m_CancelButton->Connect(
2241 wxEVT_COMMAND_BUTTON_CLICKED,
2242 wxCommandEventHandler(ToolbarChoicesDialog::OnCancelClick), NULL, this);
2243 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2244 wxCommandEventHandler(ToolbarChoicesDialog::OnOkClick),
2245 NULL, this);
2246
2247 SetColorScheme((ColorScheme)0);
2248}
2249
2250void ToolbarChoicesDialog::SetColorScheme(ColorScheme cs) { DimeControl(this); }
2251
2252void ToolbarChoicesDialog::OnCancelClick(wxCommandEvent &event) {
2253 EndModal(wxID_CANCEL);
2254}
2255
2256void ToolbarChoicesDialog::OnOkClick(wxCommandEvent &event) {
2257 unsigned int ncheck = 0;
2258
2259 wxString toolbarConfigSave = m_ToolbarDialogAncestor->GetToolConfigString();
2260 wxString new_toolbarConfig = toolbarConfigSave;
2261
2262 for (unsigned int i = 0; i < cboxes.size(); i++) {
2263 wxCheckBox *cb = cboxes[i];
2264 wxString cbName = cb->GetName(); // Special flag passed into checkbox ctor
2265 // to find the "MOB" item
2266 if (cbName.IsSameAs("MOBCheck") && !cb->IsChecked()) {
2267 // Ask if really want to disable MOB button
2268 ToolbarMOBDialog mdlg(this);
2269 int dialog_ret = mdlg.ShowModal();
2270 int answer = mdlg.GetSelection();
2271 if (dialog_ret == wxID_OK) {
2272 if (answer == 1) {
2273 g_bPermanentMOBIcon = true;
2274 cb->SetValue(true);
2275 } else if (answer == 0) {
2276 cb->SetValue(true);
2277 }
2278 } else { // wxID_CANCEL
2279 new_toolbarConfig = toolbarConfigSave;
2280 return;
2281 }
2282 }
2283 if (m_configMenu) {
2284 wxMenuItem *item = m_configMenu->FindItemByPosition(i);
2285 if (new_toolbarConfig.Len() > i) {
2286 new_toolbarConfig.SetChar(i, cb->IsChecked() ? 'X' : '.');
2287 } else {
2288 new_toolbarConfig.Append(cb->IsChecked() ? 'X' : '.');
2289 }
2290 item->Check(cb->IsChecked());
2291 if (cb->IsChecked()) ncheck++;
2292 }
2293 }
2294
2295#if 0
2296 // We always must have one Tool enabled. Make it the Options tool....
2297 if( 0 == ncheck){
2298 new_toolbarConfig.SetChar( ID_SETTINGS -ID_ZOOMIN , 'X' );
2299
2300 int idOffset = ID_PLUGIN_BASE - ID_ZOOMIN + 100;
2301
2302 if(m_configMenu){
2303 wxMenuItem *item = m_configMenu->FindItem(ID_SETTINGS + idOffset);
2304 if(item)
2305 item->Check( true );
2306 }
2307 }
2308#endif
2309 m_ToolbarDialogAncestor->SetToolConfigString(new_toolbarConfig);
2310
2311 EndModal(wxID_OK);
2312}
2313
2314void ToolbarChoicesDialog::RecalculateSize() {
2315 wxSize esize = GetSize();
2316
2317 if (GetParent()) {
2318 wxSize dsize = GetParent()->GetClientSize();
2319 esize.y = wxMin(esize.y, dsize.y - (4 * GetCharHeight()));
2320 esize.x = wxMin(esize.x, dsize.x - (2 * GetCharHeight()));
2321 SetSize(esize);
2322 Centre();
2323
2324 } else {
2325 wxSize fsize = g_Platform->getDisplaySize();
2326 fsize.y = wxMin(esize.y, fsize.y - (4 * GetCharHeight()));
2327 fsize.x = wxMin(esize.x, fsize.x - (2 * GetCharHeight()));
2328 SetSize(fsize);
2329 CentreOnScreen();
2330#ifdef __ANDROID__
2331 Move(GetPosition().x, 10);
2332#endif
2333 }
2334}
Global state for AIS decoder.
Charts database management
Generic Chart canvas base.
wxSize getDisplaySize()
Get the display size in logical pixels.
ToolbarChoicesDialog()
Constructors.
Definition toolbar.cpp:2129
Container for toolbar item properties.
Definition toolbar.h:45
void SetColorScheme(ColorScheme cs)
Set color scheme for all tooltips.
Definition tooltip.cpp:373
static TooltipManager & Get()
Get the singleton instance.
Definition tooltip.cpp:308
void HideTooltip()
Hide the current tooltip.
Definition tooltip.cpp:362
void ShowTooltipAtPosition(wxWindow *parent, const wxString &text, const wxPoint &position, bool hiviz=false)
Show tooltip at specified position in absolute screen coordinates (physical pixels).
Definition tooltip.cpp:315
Device context class that can use either wxDC or OpenGL for drawing.
Definition ocpndc.h:60
Floating toolbar dialog for OpenCPN.
Definition toolbar.h:390
Generic toolbar implementation in pure wxWidgets adapted from wxToolBarSimple (deprecated).
Definition toolbar.h:108
virtual void OnToolbarToolDownCallback(int id)
Handles toolbar button press.
virtual void OnToolbarToolUpCallback(int id)
Handles toolbar button release.
Global variables stored in configuration file.
Font list manager.
OpenGL chart rendering canvas.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:59
General purpose GUI support.
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
GUI constant definitions.
Utility functions.
OpenCPN top window.
OpenCPN Platform specific support utilities.
Navigation data types.
PlugInManager * g_pi_manager
Global instance.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
Chart Symbols.
wxBitmap LoadSVG(const wxString filename, const unsigned int width, const unsigned int height, wxBitmap *default_bitmap, bool use_cache)
Load SVG file and return it's bitmap representation of requested size In case file can't be loaded an...
Definition svg_utils.cpp:59
SVG utilities.
ocpnFloatingToolbarDialog * g_MainToolbar
Global instance.
Definition toolbar.cpp:65
OpenCPN Toolbar.