#include #include #include "StepCtrl.hpp" #include "Label.hpp" wxDEFINE_EVENT( EVT_STEP_CHANGING, wxCommandEvent ); wxDEFINE_EVENT( EVT_STEP_CHANGED, wxCommandEvent ); BEGIN_EVENT_TABLE(StepCtrl, StepCtrlBase) EVT_LEFT_DOWN(StepCtrl::mouseDown) EVT_MOTION(StepCtrl::mouseMove) EVT_LEFT_UP(StepCtrl::mouseUp) EVT_MOUSE_CAPTURE_LOST(StepCtrl::mouseCaptureLost) END_EVENT_TABLE() StepCtrlBase::StepCtrlBase(wxWindow * parent, wxWindowID id, const wxPoint & pos, const wxSize & size, long style) : StaticBox(parent, id, pos, size, style) , font_tip(Label::Body_14) , clr_bar(0xACACAC) , clr_step(0xACACAC) //, clr_text(std::make_pair(0x00AE42, (int) StateColor::Checked), , clr_text(std::make_pair(0x215F9A, (int) StateColor::Checked), std::make_pair(0x6B6B6B, (int) StateColor::Normal)) , clr_tip(0x828280) { SetFont(Label::Body_14); border_color = StateColor(*wxLIGHT_GREY); StaticBox::radius = 0; //wxString reason; //IsTransparentBackgroundSupported(&reason); } StepCtrlBase::~StepCtrlBase() { } int StepCtrlBase::GetSelection() const { return step; } void StepCtrlBase::SelectItem(int item) { if (item == step || item < -1 || item >= steps.size() || !sendStepCtrlEvent(true)) return; step = item; sendStepCtrlEvent(); Refresh(); } void StepCtrlBase::Idle() { step = -1; sendStepCtrlEvent(); Refresh(); } bool StepCtrlBase::SetTipFont(wxFont const& font) { font_tip = font; return true; } void StepCtrlBase::SetHint(wxString hint) { this->hint = hint; } int StepCtrlBase::AppendItem(const wxString &item, wxString const & tip) { steps.push_back(item); tips.push_back(tip); return steps.size() - 1; } void StepCtrlBase::DeleteAllItems() { steps.clear(); tips.clear(); if (step >= 0) { step = -1; sendStepCtrlEvent(); } } unsigned int StepCtrlBase::GetCount() const { return steps.size(); } wxString StepCtrlBase::GetItemText(unsigned int item) const { return item < steps.size() ? steps[item] : wxString{}; } int StepCtrlBase::GetItemUseText(wxString txt) const { for(int i = 0; i < steps.size(); i++){ if (steps[i] == txt) { return i; } else { continue; } } return 0; } void StepCtrlBase::SetItemText(unsigned int item, wxString const &value) { if (item >= steps.size()) return; steps[item] = value; } bool StepCtrlBase::sendStepCtrlEvent(bool changing) { wxCommandEvent event(changing ? EVT_STEP_CHANGING : EVT_STEP_CHANGED, GetId()); event.SetEventObject(this); event.SetInt(step); GetEventHandler()->ProcessEvent(event); return true; } /* StepCtrl */ StepCtrl::StepCtrl(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) : StepCtrlBase(parent, id, pos, size, style) , bmp_thumb(this, "step_thumb", 36) { StaticBox::border_width = 3; radius = radius * bmp_thumb.GetBmpHeight() / 36; bar_width = bar_width * bmp_thumb.GetBmpHeight() / 36; } void StepCtrl::Rescale() { bmp_thumb.msw_rescale(); radius = radius * bmp_thumb.GetBmpHeight() / 36; bar_width = bar_width * bmp_thumb.GetBmpHeight() / 36; } void StepCtrl::mouseDown(wxMouseEvent &event) { wxPoint pt; event.GetPosition(&pt.x, &pt.y); wxSize size = GetSize(); int itemWidth = size.x / steps.size(); wxRect rcBar = {0, (size.y - 60) / 2, size.x, 60}; int circleX = itemWidth / 2 + itemWidth * step; wxRect rcThumb = {{circleX, size.y / 2}, bmp_thumb.GetBmpSize()}; rcThumb.x -= rcThumb.width / 2; rcThumb.y -= rcThumb.height / 2; if (rcThumb.Contains(pt)) { pos_thumb = wxPoint{circleX, size.y / 2}; drag_offset = pos_thumb - pt; if (!HasCapture()) CaptureMouse(); } else if (rcBar.Contains(pt)) { if (pt.x < circleX) { if (step > 0) SelectItem(step - 1); } else { if (step < steps.size() - 1) SelectItem(step + 1); } } } void StepCtrl::mouseMove(wxMouseEvent &event) { if (pos_thumb == wxPoint{0, 0}) return; wxPoint pt; event.GetPosition(&pt.x, &pt.y); pos_thumb.x = pt.x + drag_offset.x; wxSize size = GetSize(); int itemWidth = size.x / steps.size(); int index = pos_thumb.x / itemWidth; if (index < 0) index = 0; else if (index >= steps.size()) index = steps.size() - 1; if (index != pos_thumb.y) { pos_thumb.y = index; Refresh(); } } void StepCtrl::mouseUp(wxMouseEvent &event) { if (pos_thumb == wxPoint{0, 0}) return; wxSize size = GetSize(); int itemWidth = size.x / steps.size(); int index = pos_thumb.x / itemWidth; if (index < 0) index = 0; else if (index >= steps.size()) index = steps.size() - 1; pos_thumb = {0, 0}; SelectItem(index); if (HasCapture()) ReleaseMouse(); } void StepCtrl::mouseCaptureLost(wxMouseCaptureLostEvent &event) { wxMouseEvent evt; mouseUp(evt); } void StepCtrl::doRender(wxDC &dc) { if (steps.empty()) return; StaticBox::doRender(dc); wxSize size = GetSize(); int states = state_handler.states(); int itemWidth = size.x / steps.size(); wxRect rcBar = {itemWidth / 2, (size.y - bar_width) / 2, size.x - itemWidth, bar_width}; dc.SetPen(wxPen(clr_bar.colorForStates(states))); dc.SetBrush(wxBrush(clr_bar.colorForStates(states))); dc.DrawRectangle(rcBar); int circleX = itemWidth / 2; int circleY = size.y / 2; dc.SetPen(wxPen(clr_step.colorForStates(states))); dc.SetBrush(wxBrush(clr_step.colorForStates(states))); if (!hint.empty()) { dc.SetFont(font_tip); dc.SetTextForeground(clr_tip.colorForStates(states)); wxSize sz = dc.GetTextExtent(hint); dc.DrawText(hint, dc.GetCharWidth(), circleY - FromDIP(20) - sz.y); } for (int i = 0; i < steps.size(); ++i) { bool check = (pos_thumb == wxPoint{0, 0} ? step : pos_thumb.y) == i; dc.DrawEllipse(circleX - radius, circleY - radius, radius * 2, radius * 2); dc.SetFont(GetFont()); dc.SetTextForeground(clr_text.colorForStates(states | (check ? StateColor::Checked : 0))); wxSize sz = dc.GetTextExtent(steps[i]); dc.DrawText(steps[i], circleX - sz.x / 2, circleY + 20); if (check) { dc.SetFont(font_tip); dc.SetTextForeground(clr_tip.colorForStates(states)); wxSize sz = dc.GetTextExtent(tips[i]); dc.DrawText(tips[i], circleX - sz.x / 2, circleY - 20 - sz.y); sz = bmp_thumb.GetBmpSize(); dc.DrawBitmap(bmp_thumb.bmp(), circleX - sz.x / 2, circleY - sz.y / 2); } circleX += itemWidth; } } /* StepIndicator */ StepIndicator::StepIndicator(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) : StepCtrlBase(parent, id, pos, size, style) , bmp_ok(this, "step_ok", 12) { SetFont(Label::Body_12); font_tip = Label::Body_10; clr_bar = 0xE1E1E1; clr_step = StateColor( std::make_pair(0xACACAC, (int) StateColor::Disabled), //std::make_pair(0x00AE42, 0)); std::make_pair(0x215F9A, 0)); clr_text = StateColor( std::make_pair(0xACACAC, (int) StateColor::Disabled), std::make_pair(0x323A3D, (int) StateColor::Checked), std::make_pair(0x6B6B6B, 0)); clr_tip = *wxWHITE; StaticBox::border_width = 0; radius = bmp_ok.GetBmpHeight() / 2; bar_width = bmp_ok.GetBmpHeight() / 20; if (bar_width < 2) bar_width = 2; } void StepIndicator::Rescale() { bmp_ok.msw_rescale(); radius = bmp_ok.GetBmpHeight() / 2; bar_width = bmp_ok.GetBmpHeight() / 20; if (bar_width < 2) bar_width = 2; } void StepIndicator::SelectNext() { SelectItem(step + 1); } void StepIndicator::doRender(wxDC &dc) { if (steps.empty()) return; StaticBox::doRender(dc); wxSize size = GetSize(); int states = state_handler.states(); if (!IsEnabled()) { states = clr_step.Disabled; } int textWidth = size.x - radius * 5; dc.SetFont(GetFont()); wxString firstLine; if (step == 0) dc.SetFont(GetFont().Bold()); wxSize firstLineSize = Label::split_lines(dc, textWidth, steps.front(), firstLine); wxString lastLine; if (step == steps.size() - 1) dc.SetFont(GetFont().Bold()); wxSize lastLineSize = Label::split_lines(dc, textWidth, steps.back(), lastLine); int firstPadding = std::max(0, firstLineSize.y / 2 - radius); int lastPadding = std::max(0, lastLineSize.y / 2 - radius); wxRect rcBar = {radius * 2 - bar_width / 2, radius * 2 + firstPadding, bar_width, size.y - radius * 6 - firstPadding - lastPadding}; int itemWidth = steps.size() == 1 ? size.y : rcBar.height / (steps.size() - 1); // Draw thin bar stick dc.SetPen(wxPen(clr_bar.colorForStates(states))); dc.SetBrush(wxBrush(clr_bar.colorForStates(states))); dc.DrawRectangle(rcBar); int circleX = radius * 2; int circleY = radius * 3 + firstPadding; dc.SetPen(wxPen(clr_step.colorForStates(states))); dc.SetBrush(wxBrush(clr_step.colorForStates(states))); for (int i = 0; i < steps.size(); ++i) { bool disabled = step > i; bool checked = step == i; // Draw circle point & texts in it dc.DrawEllipse(circleX - radius, circleY - radius, radius * 2, radius * 2); // Draw content ( icon or text ) in circle if (disabled) { wxSize sz = bmp_ok.GetBmpSize(); dc.DrawBitmap(bmp_ok.bmp(), circleX - radius, circleY - radius); } else { dc.SetFont(font_tip); dc.SetTextForeground(clr_tip.colorForStates(states)); auto tip = tips[i]; if (tip.IsEmpty()) tip.append(1, wchar_t(L'0' + i + 1)); wxSize sz = dc.GetTextExtent(tip); dc.DrawText(tip, circleX - sz.x / 2, circleY - sz.y / 2 + 1); } // Draw step text dc.SetTextForeground(clr_text.colorForStates(states | (disabled ? StateColor::Disabled : checked ? StateColor::Checked : 0))); dc.SetFont(checked ? GetFont().Bold() : GetFont()); wxString text; wxSize textSize; if (i == 0) { text = firstLine; textSize = firstLineSize; } else if (i == steps.size() - 1) { text = lastLine; textSize = lastLineSize; } else { textSize = Label::split_lines(dc, textWidth, steps[i], text); } dc.DrawText(text, circleX + radius * 3, circleY - (textSize.y / 2)); circleY += itemWidth; } }