RadarPanel::~RadarPanel() { wxAuiPaneInfo& pane = m_aui_mgr->GetPane(this); bool wasFloating = pane.IsFloating(); if (!wasFloating) { pane.Float(); m_aui_mgr->Update(); pane = m_aui_mgr->GetPane(this); } wxPoint pos = pane.floating_pos; LOG_DIALOG(wxT("%s saved position %d,%d"), m_aui_name.c_str(), pos.x, pos.y); m_pi->m_settings.window_pos[m_ri->m_radar] = pos; if (!wasFloating) { pane.Dock(); m_aui_mgr->Update(); pane = m_aui_mgr->GetPane(this); } m_pi->m_perspective[m_ri->m_radar] = m_aui_mgr->SavePaneInfo(pane); if (m_ri->m_radar_canvas) { m_sizer->Detach(m_ri->m_radar_canvas); delete m_ri->m_radar_canvas; m_ri->m_radar_canvas = 0; } m_aui_mgr->DetachPane(this); m_aui_mgr->Update(); LOG_DIALOG(wxT("BR24radar_pi: %s panel removed"), m_ri->m_name.c_str()); }
bool RadarPanel::Create() { m_aui_mgr = GetFrameAuiManager(); m_aui_name = wxString::Format(wxT("BR24radar_pi-%d"), m_ri->m_radar); wxAuiPaneInfo pane = wxAuiPaneInfo() .Name(m_aui_name) .Caption(m_ri->m_name) .CaptionVisible(true) // Show caption even when docked .TopDockable(false) .BottomDockable(false) .RightDockable(true) .LeftDockable(true) .CloseButton(true) .Gripper(false); m_sizer = new wxBoxSizer(wxHORIZONTAL); m_text = new wxStaticText(this, 0, wxT(""), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_sizer->Add(m_text, 0, wxEXPAND | wxALL, 0); SetSizer(m_sizer); DimeWindow(this); Fit(); Layout(); // SetMinSize(GetBestSize()); m_best_size = wxGetDisplaySize(); m_best_size.x /= 2; m_best_size.y /= 2; pane.MinSize(256, 256); pane.BestSize(m_best_size); pane.FloatingSize(512, 512); pane.FloatingPosition(m_pi->m_settings.window_pos[m_ri->m_radar]); pane.Float(); pane.dock_proportion = 100000; // Secret sauce to get panels to use entire bar m_aui_mgr->AddPane(this, pane); m_aui_mgr->Update(); m_aui_mgr->Connect(wxEVT_AUI_PANE_CLOSE, wxAuiManagerEventHandler(RadarPanel::close), NULL, this); m_dock_size = 0; if (m_pi->m_perspective[m_ri->m_radar].length()) { // Do this first and it doesn't work if the pane starts docked. LOG_DIALOG(wxT("BR24radar_pi: Restoring panel %s to AUI control manager: %s"), m_aui_name.c_str(), m_pi->m_perspective[m_ri->m_radar].c_str()); m_aui_mgr->LoadPaneInfo(m_pi->m_perspective[m_ri->m_radar], pane); m_aui_mgr->Update(); } else { LOG_DIALOG(wxT("BR24radar_pi: Added panel %s to AUI control manager"), m_aui_name.c_str()); } return true; }
void RadarPanel::close(wxAuiManagerEvent& event) { event.Skip(); wxAuiPaneInfo* pane = event.GetPane(); if (pane->window == this) { m_pi->m_settings.show_radar[m_ri->m_radar] = 0; LOG_DIALOG(wxT("BR24radar_pi: RadarPanel::close: show_radar[%d]=%d"), m_ri->m_radar, 0); m_pi->NotifyRadarWindowViz(); } else { LOG_DIALOG(wxT("BR24radar_pi: RadarPanel::close: ignore close of window %s in window %s"), pane->name.c_str(), m_aui_name.c_str()); } }
void RadarCanvas::OnSize(wxSizeEvent &evt) { wxSize parentSize = m_parent->GetSize(); LOG_DIALOG(wxT("BR24radar_pi: %s resize OpenGL canvas to %d, %d"), m_ri->m_name.c_str(), parentSize.x, parentSize.y); Refresh(false); if (GetSize() != parentSize) { SetSize(parentSize); } }
void RadarCanvas::RenderCursor(int w, int h) { double distance; double bearing; if (m_ri->m_mouse_vrm != 0.0) { distance = m_ri->m_mouse_vrm * 1852.; bearing = m_ri->m_mouse_ebl; } else { if ((m_ri->m_mouse_lat == 0.0 && m_ri->m_mouse_lon == 0.0) || !m_pi->m_bpos_set) { return; } // Can't compute this upfront, ownship may move... distance = local_distance(m_pi->m_ownship_lat, m_pi->m_ownship_lon, m_ri->m_mouse_lat, m_ri->m_mouse_lon) * 1852.; bearing = local_bearing(m_pi->m_ownship_lat, m_pi->m_ownship_lon, m_ri->m_mouse_lat, m_ri->m_mouse_lon); if (!m_ri->IsDisplayNorthUp()) { bearing -= m_pi->m_hdt; } // LOG_DIALOG(wxT("BR24radar_pi: Chart Mouse vrm=%f ebl=%f"), distance / 1852.0, bearing); } double full_range = wxMax(w, h) / 2.0; int display_range = m_ri->GetDisplayRange(); double range = distance * full_range / display_range; #define CURSOR_SCALE 1 double center_x = w / 2.0; double center_y = h / 2.0; double angle = deg2rad(bearing); double x = center_x + sin(angle) * range - CURSOR_WIDTH * CURSOR_SCALE / 2; double y = center_y - cos(angle) * range - CURSOR_WIDTH * CURSOR_SCALE / 2; // LOG_DIALOG(wxT("BR24radar_pi: draw cursor angle=%.1f bearing=%.1f"), rad2deg(angle), bearing); if (!m_cursor_texture) { glGenTextures(1, &m_cursor_texture); glBindTexture(GL_TEXTURE_2D, m_cursor_texture); FillCursorTexture(); LOG_DIALOG(wxT("BR24radar_pi: generated cursor texture # %u"), m_cursor_texture); } glColor3f(1.0f, 1.0f, 1.0f); glBindTexture(GL_TEXTURE_2D, m_cursor_texture); glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2i(x, y); glTexCoord2i(1, 0); glVertex2i(x + CURSOR_SCALE * CURSOR_WIDTH, y); glTexCoord2i(1, 1); glVertex2i(x + CURSOR_SCALE * CURSOR_WIDTH, y + CURSOR_SCALE * CURSOR_HEIGHT); glTexCoord2i(0, 1); glVertex2i(x, y + CURSOR_SCALE * CURSOR_HEIGHT); glEnd(); }
void RadarCanvas::OnMouseClick(wxMouseEvent &event) { int x, y, w, h; event.GetPosition(&x, &y); GetClientSize(&w, &h); int center_x = w / 2; int center_y = h / 2; LOG_DIALOG(wxT("BR24radar_pi: %s Mouse clicked at %d, %d"), m_ri->m_name.c_str(), x, y); if (x >= w - m_menu_size.x && y < m_menu_size.y) { m_pi->ShowRadarControl(m_ri->m_radar, true); } else if ((x >= center_x - m_zoom_size.x / 2) && (x <= center_x + m_zoom_size.x / 2) && (y > h - m_zoom_size.y + MENU_ROUNDING)) { if (x > center_x) { m_ri->AdjustRange(+1); } else { m_ri->AdjustRange(-1); } } else { double delta_x = x - center_x; double delta_y = y - center_y; double distance = sqrt(delta_x * delta_x + delta_y * delta_y); int display_range = m_ri->GetDisplayRange(); double angle = fmod(rad2deg(atan2(delta_y, delta_x)) + 720. + 90., 360.0); double full_range = wxMax(w, h) / 2.0; double range = distance / (1852.0 * full_range / display_range); LOG_VERBOSE(wxT("BR24radar_pi: cursor in PPI at angle=%.1f range=%f heading=%.1f"), angle, range); m_ri->SetMouseVrmEbl(range, angle); } event.Skip(); }
void RadarPanel::ShowFrame(bool visible) { LOG_DIALOG(wxT("BR24radar_pi %s: set visible %d"), m_ri->m_name.c_str(), visible); wxAuiPaneInfo& pane = m_aui_mgr->GetPane(this); if (!m_pi->m_opengl_mode && m_ri->m_radar_canvas) { m_sizer->Detach(m_ri->m_radar_canvas); delete m_ri->m_radar_canvas; m_ri->m_radar_canvas = 0; m_text->SetLabel(_("OpenGL mode required")); m_sizer->Show(m_text); DimeWindow(this); Fit(); Layout(); } if (visible) { if (m_pi->m_opengl_mode && !m_ri->m_radar_canvas) { LOG_DIALOG(wxT("BR24radar_pi %s: creating OpenGL canvas"), m_ri->m_name.c_str()); m_ri->m_radar_canvas = new RadarCanvas(m_pi, m_ri, this, GetSize()); if (!m_ri->m_radar_canvas) { m_text->SetLabel(_("Unable to create OpenGL canvas")); m_sizer->Show(m_text); } else { m_sizer->Hide(m_text); m_sizer->Add(m_ri->m_radar_canvas, 0, wxEXPAND | wxALL, 0); Fit(); Layout(); } } } if (visible) { m_pi->m_settings.show_radar[m_ri->m_radar] = 1; LOG_DIALOG(wxT("BR24radar_pi: RadarPanel::ShowFrame: show_radar[%d]=%d"), m_ri->m_radar, 1); } // What should have been a simple 'pane.Show(visible)' has devolved into a terrible hack. // When the entire dock row disappears because we're removing the last pane from it then the // next time we restore the dock gets its original size again. This is not want customers want. // So we store the size of the dock just before hiding the pane. This is done via parsing of the // perspective string, as there is no other way to access the dock information through wxAUI. if (!visible) { m_dock_size = 0; if (pane.IsDocked()) { m_dock = wxString::Format(wxT("|dock_size(%d,%d,%d)="), pane.dock_direction, pane.dock_layer, pane.dock_row); wxString perspective = m_aui_mgr->SavePerspective(); int p = perspective.Find(m_dock); if (p != wxNOT_FOUND) { perspective = perspective.Mid(p + m_dock.length()); perspective = perspective.BeforeFirst(wxT('|')); m_dock_size = wxAtoi(perspective); LOG_DIALOG(wxT("BR24radar_pi: %s: replaced=%s, saved dock_size = %d"), m_ri->m_name.c_str(), perspective.c_str(), m_dock_size); } } } else { pane.Position(m_ri->m_radar); } pane.Show(visible); m_aui_mgr->Update(); // causes recursive calls on OS X when not in OpenGL mode if (visible && (m_dock_size > 0)) { // Now the reverse: take the new perspective string and replace the dock size of the dock that our pane is in and // reset it to the width it was before the hide. wxString perspective = m_aui_mgr->SavePerspective(); int p = perspective.Find(m_dock); if (p != wxNOT_FOUND) { wxString newPerspective = perspective.Left(p); newPerspective << m_dock; newPerspective << m_dock_size; perspective = perspective.Mid(p + m_dock.length()); newPerspective << wxT("|"); newPerspective << perspective.AfterFirst(wxT('|')); m_aui_mgr->LoadPerspective(newPerspective); LOG_DIALOG(wxT("BR24radar_pi: %s: new perspective %s"), m_ri->m_name.c_str(), newPerspective.c_str()); } } }
void RadarCanvas::OnMove(wxMoveEvent &evt) { wxPoint pos = m_parent->GetPosition(); LOG_DIALOG(wxT("BR24radar_pi: %s move OpenGL canvas to %d, %d"), m_ri->m_name.c_str(), pos.x, pos.y); }
void RadarCanvas::Render(wxPaintEvent &evt) { int w, h; if (!IsShown() || !m_pi->m_initialized) { return; } GetClientSize(&w, &h); wxPaintDC(this); // only to be used in paint events. use wxClientDC to paint // outside the paint event if (!m_pi->m_opengl_mode) { LOG_DIALOG(wxT("BR24radar_pi: %s cannot render non-OpenGL mode"), m_ri->m_name.c_str()); return; } if (!m_pi->m_opencpn_gl_context && !m_pi->m_opencpn_gl_context_broken) { LOG_DIALOG(wxT("BR24radar_pi: %s skip render as no context known yet"), m_ri->m_name.c_str()); return; } LOG_DIALOG(wxT("BR24radar_pi: %s render OpenGL canvas %d by %d "), m_ri->m_name.c_str(), w, h); SetCurrent(*m_context); glPushMatrix(); glPushAttrib(GL_ALL_ATTRIB_BITS); wxFont font = GetOCPNGUIScaledFont_PlugIn(_T("StatusBar")); m_FontNormal.Build(font); wxFont bigFont = GetOCPNGUIScaledFont_PlugIn(_T("Dialog")); bigFont.SetPointSize(bigFont.GetPointSize() + 2); bigFont.SetWeight(wxFONTWEIGHT_BOLD); m_FontBig.Build(bigFont); bigFont.SetPointSize(bigFont.GetPointSize() + 2); bigFont.SetWeight(wxFONTWEIGHT_NORMAL); m_FontMenu.Build(bigFont); bigFont.SetPointSize(bigFont.GetPointSize() + 10); bigFont.SetWeight(wxFONTWEIGHT_BOLD); m_FontMenuBold.Build(bigFont); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the canvas glEnable(GL_TEXTURE_2D); // Enable textures glEnable(GL_COLOR_MATERIAL); glEnable(GL_BLEND); // glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); // Next two operations on the project matrix stack glLoadIdentity(); // Reset projection matrix stack glOrtho(0, w, h, 0, -1, 1); glMatrixMode(GL_MODELVIEW); // Reset matrick stack target back to GL_MODELVIEW RenderRangeRingsAndHeading(w, h); Render_EBL_VRM(w, h); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); // Next two operations on the project matrix stack glLoadIdentity(); // Reset projection matrix stack if (w >= h) { glScaled(1.0, (float)-w / h, 1.0); } else { glScaled((float)h / w, -1.0, 1.0); } glMatrixMode(GL_MODELVIEW); // Reset matrick stack target back to GL_MODELVIEW m_ri->RenderRadarImage(wxPoint(0, 0), 1.0, 0.0, false); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); // Next two operations on the project matrix stack glLoadIdentity(); // Reset projection matrix stack glOrtho(0, w, h, 0, -1, 1); glMatrixMode(GL_MODELVIEW); // Reset matrick stack target back to GL_MODELVIEW glEnable(GL_TEXTURE_2D); RenderTexts(w, h); RenderCursor(w, h); #ifdef NEVER glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); // Next two operations on the project matrix stack glLoadIdentity(); // Reset projection matrix stack glMatrixMode(GL_MODELVIEW); // Reset matrick stack target back to GL_MODELVIEW #endif glPopAttrib(); glPopMatrix(); glFlush(); glFinish(); SwapBuffers(); if (m_pi->m_opencpn_gl_context) { SetCurrent(*m_pi->m_opencpn_gl_context); } else { SetCurrent(*m_zero_context); // Make sure OpenCPN -at least- doesn't overwrite our context info } }