/* * nudge_lock.cpp * PHD Guiding * * Created by Andy Galasso * Copyright (c) 2014 Andy Galasso * All rights reserved. * * This source code is distributed under the following "BSD" license * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of Craig Stark, Stark Labs nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "phd.h" #include "nudge_lock.h" #include "comet_tool.h" #include <wx/valnum.h> struct NudgeLockDialog : public wxDialog { wxCheckBox *stayOnTop; wxButton *upButton, *downButton, *leftButton, *rightButton; wxSlider *nudgeAmountSlider; wxCheckBox *stickyLockPos; wxStaticText *nudgeAmountText; wxTextCtrl *lockPosCtrlX, *lockPosCtrlY; wxButton *updateLockPosButton; wxButton *saveLockPosButton; wxButton *restoreLockPosButton; bool lockPosIsValid; double lockPosX, lockPosY; NudgeLockDialog(); ~NudgeLockDialog(); void OnStayOnTopClicked(wxCommandEvent& evt); void OnButton(wxCommandEvent& evt); void OnNudgeAmountSlider(wxCommandEvent& evt); void OnStickyChecked(wxCommandEvent& evt); void OnSetLockPosClicked(wxCommandEvent& evt); void OnSaveLockPosClicked(wxCommandEvent& evt); void OnRestoreLockPosClicked(wxCommandEvent& evt); void OnAppStateNotify(wxCommandEvent& evt); void OnClose(wxCloseEvent& evt); void UpdateSliderLabel(); void UpdateLockPosCtrls(); DECLARE_EVENT_TABLE() }; enum { ID_UP_BTN = 1001, ID_DOWN_BTN, ID_LEFT_BTN, ID_RIGHT_BTN, ID_STAY_ON_TOP, ID_NUDGE_AMOUNT, ID_STICKY, ID_SET_LOCK_POS, ID_SAVE_LOCK_POS, ID_RESTORE_LOCK_POS, }; wxBEGIN_EVENT_TABLE(NudgeLockDialog, wxDialog) EVT_CHECKBOX(ID_STAY_ON_TOP, NudgeLockDialog::OnStayOnTopClicked) EVT_BUTTON(ID_UP_BTN, NudgeLockDialog::OnButton) EVT_BUTTON(ID_DOWN_BTN, NudgeLockDialog::OnButton) EVT_BUTTON(ID_LEFT_BTN, NudgeLockDialog::OnButton) EVT_BUTTON(ID_RIGHT_BTN, NudgeLockDialog::OnButton) EVT_SLIDER(ID_NUDGE_AMOUNT, NudgeLockDialog::OnNudgeAmountSlider) EVT_CHECKBOX(ID_STICKY, NudgeLockDialog::OnStickyChecked) EVT_BUTTON(ID_SET_LOCK_POS, NudgeLockDialog::OnSetLockPosClicked) EVT_BUTTON(ID_SAVE_LOCK_POS, NudgeLockDialog::OnSaveLockPosClicked) EVT_BUTTON(ID_RESTORE_LOCK_POS, NudgeLockDialog::OnRestoreLockPosClicked) EVT_COMMAND(wxID_ANY, APPSTATE_NOTIFY_EVENT, NudgeLockDialog::OnAppStateNotify) EVT_CLOSE(NudgeLockDialog::OnClose) wxEND_EVENT_TABLE() static double NudgeIncrements[] = { 0.01, 0.03, 0.1, 0.3, 1, 3, 10, }; static int IncrIdx(double incr) { for (unsigned int i = 0; i < WXSIZEOF(NudgeIncrements); i++) { if (fabs(incr - NudgeIncrements[i]) < 0.0001) return i; } return 0; } NudgeLockDialog::NudgeLockDialog() : wxDialog(pFrame, wxID_ANY, _("Adjust Lock Position"), wxPoint(-1,-1), wxSize(300,300)) { stayOnTop = new wxCheckBox(this, ID_STAY_ON_TOP, _("Always on top")); stayOnTop->SetToolTip(_("Keep this window on top of all others")); upButton = new wxButton(this, ID_UP_BTN, _("Up")); downButton = new wxButton(this, ID_DOWN_BTN, _("Down")); leftButton = new wxButton(this, ID_LEFT_BTN, _("Left")); rightButton = new wxButton(this, ID_RIGHT_BTN, _("Right")); wxGridSizer *sz1 = new wxGridSizer(3, 3, 0, 0); sz1->AddStretchSpacer(); sz1->Add(upButton, wxSizerFlags().Expand().Border(wxALL,1)); sz1->AddStretchSpacer(); sz1->Add(leftButton, wxSizerFlags().Expand().Border(wxALL,1)); sz1->AddStretchSpacer(); sz1->Add(rightButton, wxSizerFlags().Expand().Border(wxALL,1)); sz1->AddStretchSpacer(); sz1->Add(downButton, wxSizerFlags().Expand().Border(wxALL,1)); wxBoxSizer *sz0 = new wxBoxSizer(wxHORIZONTAL); sz0->AddStretchSpacer(); sz0->Add(sz1); sz0->AddStretchSpacer(); wxSizer *sz2 = new wxBoxSizer(wxHORIZONTAL); sz2->Add(new wxStaticText(this, wxID_ANY, _("Step")), wxSizerFlags().Right().Border(wxALL, 5).Align(wxALIGN_CENTER_VERTICAL)); double incr = pConfig->Global.GetDouble("/NudgeLock/Amount", NudgeIncrements[2]); int idx = IncrIdx(incr); nudgeAmountSlider = new wxSlider(this, ID_NUDGE_AMOUNT, idx, 0, WXSIZEOF(NudgeIncrements) - 1, wxDefaultPosition, wxSize(100, -1)); nudgeAmountSlider->SetToolTip(_("Adjust how far the lock position moves when you click the Up/Down/Left/Right buttons")); sz2->Add(nudgeAmountSlider, wxSizerFlags().Expand().Border(wxALL, 0)); nudgeAmountText = new wxStaticText(this, wxID_ANY, _T("1.234")); sz2->Add(nudgeAmountText, wxSizerFlags().Border(wxLEFT, 5).Align(wxALIGN_CENTER_VERTICAL)); stickyLockPos = new wxCheckBox(this, ID_STICKY, _("Sticky Lock Position")); stickyLockPos->SetToolTip(_("Sticky lock position will not follow the star when guiding is stopped and restarted, or after calibration completes")); sz2->Add(0, 0, 1, wxEXPAND, 5); sz2->Add(stickyLockPos, wxSizerFlags().Border(wxALL, 5).Align(wxALIGN_CENTER_VERTICAL)); wxSizer *sz3 = new wxBoxSizer(wxHORIZONTAL); sz3->Add(new wxStaticText(this, wxID_ANY, _("Lock Pos:")), wxSizerFlags().Right().Border(wxALL, 5).Align(wxALIGN_CENTER_VERTICAL)); wxFloatingPointValidator<double> valX(2, &lockPosX, wxNUM_VAL_ZERO_AS_BLANK); valX.SetMin(0.0); lockPosCtrlX = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, StringSize(this, _T("12345.67"), 10), 0, valX); lockPosCtrlX->SetToolTip(_("Lock position X coordinate")); sz3->Add(lockPosCtrlX, wxSizerFlags().Border(wxALL, 0).Align(wxALIGN_CENTER_VERTICAL)); wxFloatingPointValidator<double> valY(2, &lockPosY, wxNUM_VAL_ZERO_AS_BLANK); valY.SetMin(0.0); lockPosCtrlY = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, StringSize(this, _T("12345.67"), 10), 0, valY); lockPosCtrlY->SetToolTip(_("Lock position Y coordinate")); sz3->Add(lockPosCtrlY, wxSizerFlags().Border(wxLEFT, 5).Align(wxALIGN_CENTER_VERTICAL)); wxSize s1 = StringSize(this, _("Set"), 10); wxSize s2 = StringSize(this, _("Save"), 10); wxSize s3 = StringSize(this, _("Restore"), 10); size_t longest = wxMax(s1.GetX(), s2.GetX()); longest = wxMax(longest, s3.GetX()); wxSize btnsize(longest, -1); updateLockPosButton = new wxButton(this, ID_SET_LOCK_POS, _("Set"), wxDefaultPosition, btnsize); updateLockPosButton->SetToolTip(_("Set the lock position to the entered coordinates")); sz3->Add(updateLockPosButton, wxSizerFlags().Border(wxALL, 5).Align(wxALIGN_CENTER_VERTICAL)); saveLockPosButton = new wxButton(this, ID_SAVE_LOCK_POS, _("Save"), wxDefaultPosition, btnsize); saveLockPosButton->SetToolTip(_("Save the current lock position so it can be restored later")); sz3->Add(saveLockPosButton, wxSizerFlags().Border(wxALL, 5).Align(wxALIGN_CENTER_VERTICAL)); restoreLockPosButton = new wxButton(this, ID_RESTORE_LOCK_POS, _("Restore"), wxDefaultPosition, btnsize); restoreLockPosButton->SetToolTip(_("Restore the saved lock position")); sz3->Add(restoreLockPosButton, wxSizerFlags().Border(wxRIGHT, 5).Align(wxALIGN_CENTER_VERTICAL)); wxBoxSizer *outerSizer = new wxBoxSizer(wxVERTICAL); outerSizer->Add(stayOnTop, wxSizerFlags().Border(wxALL, 5)); outerSizer->AddSpacer(5); outerSizer->Add(sz0, wxSizerFlags().Border(wxALL,3).Expand()); outerSizer->Add(sz2, wxSizerFlags().Border(wxALL,3).Expand()); outerSizer->Add(sz3, wxSizerFlags().Border(wxALL,3)); UpdateSliderLabel(); UpdateLockPosCtrls(); outerSizer->SetSizeHints(this); SetSizerAndFit(outerSizer); int xpos = pConfig->Global.GetInt("/NudgeLock/pos.x", -1); int ypos = pConfig->Global.GetInt("/NudgeLock/pos.y", -1); MyFrame::PlaceWindowOnScreen(this, xpos, ypos); } NudgeLockDialog::~NudgeLockDialog(void) { pFrame->pNudgeLock = 0; } void NudgeLockDialog::UpdateSliderLabel() { int idx = nudgeAmountSlider->GetValue(); double val = NudgeIncrements[idx]; nudgeAmountText->SetLabel(wxString::Format("%.2f px", val)); } void NudgeLockDialog::UpdateLockPosCtrls() { const PHD_Point& pos = pFrame->pGuider->LockPosition(); lockPosIsValid = pos.IsValid(); if (lockPosIsValid) { lockPosX = pos.X; lockPosY = pos.Y; } else { lockPosX = 0.0; lockPosY = 0.0; } TransferDataToWindow(); lockPosCtrlX->Enable(lockPosIsValid); lockPosCtrlY->Enable(lockPosIsValid); updateLockPosButton->Enable(lockPosIsValid); saveLockPosButton->Enable(lockPosIsValid); restoreLockPosButton->Enable(lockPosIsValid); stickyLockPos->SetValue(pFrame->pGuider->LockPosIsSticky()); } static bool UpdateLockPos(const PHD_Point& newPos) { if (pFrame->pGuider->IsValidLockPosition(newPos)) { pFrame->pGuider->SetLockPosition(newPos); pFrame->Refresh(); CometTool::NotifyUpdateLockPos(); return true; } return false; } static void DoMove(double dx, double dy) { PHD_Point newPos = pFrame->pGuider->LockPosition(); newPos.X += dx; newPos.Y += dy; UpdateLockPos(newPos); } void NudgeLockDialog::OnStayOnTopClicked(wxCommandEvent& evt) { long style = GetWindowStyle(); if (evt.IsChecked()) SetWindowStyle(style | wxSTAY_ON_TOP); else SetWindowStyle(style & ~wxSTAY_ON_TOP); } void NudgeLockDialog::OnButton(wxCommandEvent &evt) { if (!lockPosIsValid) return; int idx = nudgeAmountSlider->GetValue(); double incr = NudgeIncrements[idx]; switch (evt.GetId()) { case ID_UP_BTN: DoMove(0.0, -incr); break; case ID_DOWN_BTN: DoMove(0.0, +incr); break; case ID_RIGHT_BTN: DoMove(+incr, 0.0); break; case ID_LEFT_BTN: DoMove(-incr, 0.0); break; } } void NudgeLockDialog::OnNudgeAmountSlider(wxCommandEvent& evt) { UpdateSliderLabel(); int idx = nudgeAmountSlider->GetValue(); double val = NudgeIncrements[idx]; pConfig->Global.SetDouble("/NudgeLock/Amount", val); } void NudgeLockDialog::OnStickyChecked(wxCommandEvent& evt) { bool sticky = evt.IsChecked(); pFrame->pGuider->SetLockPosIsSticky(sticky); pConfig->Global.SetBoolean("/StickyLockPosition", sticky); pFrame->tools_menu->FindItem(EEGG_STICKY_LOCK)->Check(sticky); } void NudgeLockDialog::OnSetLockPosClicked(wxCommandEvent& evt) { TransferDataFromWindow(); PHD_Point newPos(lockPosX, lockPosY); if (!UpdateLockPos(newPos)) { UpdateLockPosCtrls(); } } void NudgeLockDialog::OnSaveLockPosClicked(wxCommandEvent& evt) { const PHD_Point& pos = pFrame->pGuider->LockPosition(); if (pos.IsValid()) { pConfig->Profile.SetDouble("/NudgeLock/SavedLockPosX", pos.X); pConfig->Profile.SetDouble("/NudgeLock/SavedLockPosY", pos.Y); } } void NudgeLockDialog::OnRestoreLockPosClicked(wxCommandEvent& evt) { double x = pConfig->Profile.GetDouble("/NudgeLock/SavedLockPosX", -1.0); double y = pConfig->Profile.GetDouble("/NudgeLock/SavedLockPosY", -1.0); if (x < 0.0 || y < 0.0) return; if (ConfirmDialog::Confirm(wxString::Format(_("Set lock position to saved value (%.2f,%.2f)?"), x, y), "/RestoreSavedLockPosOK", _("Restore saved Lock Pos"))) { UpdateLockPos(PHD_Point(x, y)); } } void NudgeLockDialog::OnAppStateNotify(wxCommandEvent& evt) { UpdateLockPosCtrls(); } void NudgeLockDialog::OnClose(wxCloseEvent& evt) { // save the window position int x, y; GetPosition(&x, &y); pConfig->Global.SetInt("/NudgeLock/pos.x", x); pConfig->Global.SetInt("/NudgeLock/pos.y", y); evt.Skip(); } wxWindow *NudgeLockTool::CreateNudgeLockToolWindow() { return new NudgeLockDialog(); } void NudgeLockTool::UpdateNudgeLockControls() { // notify nudge lock tool to update its controls if (pFrame && pFrame->pNudgeLock) { wxCommandEvent event(APPSTATE_NOTIFY_EVENT, pFrame->GetId()); event.SetEventObject(pFrame); wxPostEvent(pFrame->pNudgeLock, event); } }