Custom control : Action buttons are "alive" now

- show tooltips for buttons
- LBtnClick invokes revert functions for the field
This commit is contained in:
YuSanka 2020-10-26 19:38:09 +01:00 committed by Oleksandra Yushchenko
parent e93e80166b
commit 4f5efc99fb
7 changed files with 161 additions and 55 deletions

View file

@ -39,12 +39,12 @@ OG_CustomCtrl::OG_CustomCtrl( wxWindow* parent,
this->Bind(wxEVT_PAINT, &OG_CustomCtrl::OnPaint, this);
this->Bind(wxEVT_MOTION, &OG_CustomCtrl::OnMotion, this);
this->Bind(wxEVT_LEFT_DOWN, &OG_CustomCtrl::OnLeftDown, this);
this->Bind(wxEVT_LEFT_UP, &OG_CustomCtrl::OnLeftUp, this);
}
void OG_CustomCtrl::init_ctrl_lines()
{
for (const Line& line : opt_group->get_lines())
const std::vector<Line>& og_lines = opt_group->get_lines();
for (const Line& line : og_lines)
{
if (line.full_width && (
// description line
@ -64,13 +64,13 @@ void OG_CustomCtrl::init_ctrl_lines()
line.get_extra_widgets().size() == 0)
{
height = m_bmp_blinking_sz.GetHeight() + m_v_gap;
ctrl_lines.emplace_back(CtrlLine{ height, this, line, true });
ctrl_lines.emplace_back(CtrlLine(height, this, line, true));
}
else if (opt_group->label_width != 0 && !line.label.IsEmpty())
{
wxSize label_sz = GetTextExtent(line.label);
height = label_sz.y * (label_sz.GetWidth() > int(opt_group->label_width * m_em_unit) ? 2 : 1) + m_v_gap;
ctrl_lines.emplace_back(CtrlLine{ height, this, line });
ctrl_lines.emplace_back(CtrlLine(height, this, line));
}
else
int i = 0;
@ -106,10 +106,12 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
if (opt_group->label_width != 0 && !label.IsEmpty())
h_pos += opt_group->label_width * m_em_unit + m_h_gap;
if (line.widget)
break;
int blinking_button_width = m_bmp_blinking_sz.GetWidth() + m_h_gap;
int action_buttons_width = 3 * (m_bmp_blinking_sz.GetWidth() + m_h_gap);
if (line.widget) {
h_pos += blinking_button_width;
break;
}
// If we have a single option with no sidetext
const std::vector<Option>& option_set = line.get_options();
@ -117,7 +119,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
option_set.front().opt.label.empty() &&
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0)
{
h_pos += action_buttons_width;
h_pos += 3 * blinking_button_width;
break;
}
@ -135,7 +137,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
dc.SetFont(m_font);
h_pos += dc.GetMultiLineTextExtent(label).x + m_h_gap;
}
h_pos += action_buttons_width;
h_pos += 3 * blinking_button_width;
if (field == field_in)
break;
@ -169,11 +171,15 @@ void OG_CustomCtrl::OnPaint(wxPaintEvent&)
SetBackgroundColour(GetParent()->GetBackgroundColour());
#endif // _WIN32
// case, when custom controll is destroyed but doesn't deleted from the evet loop
if(!this->opt_group->custom_ctrl)
return;
wxPaintDC dc(this);
dc.SetFont(m_font);
wxCoord v_pos = 0;
for (auto line : ctrl_lines) {
for (CtrlLine& line : ctrl_lines) {
if (!line.is_visible)
continue;
line.render(dc, v_pos);
@ -181,11 +187,41 @@ void OG_CustomCtrl::OnPaint(wxPaintEvent&)
}
}
static bool is_point_in_rect(const wxPoint& pt, const wxRect& rect)
{
return rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() &&
rect.GetTop() <= pt.y && pt.y <= rect.GetBottom();
}
void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
{
bool action = false;
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
wxString tooltip;
for (const CtrlLine& line : ctrl_lines) {
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
tooltip = *field->undo_tooltip();
break;
}
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
tooltip = *field->undo_to_sys_tooltip();
break;
}
if (!tooltip.IsEmpty())
break;
}
// Set tooltips with information for each icon
this->SetToolTip(tooltip);
Refresh();
Update();
event.Skip();
@ -193,20 +229,29 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event)
{
if (HasCapture())
return;
this->CaptureMouse();
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
event.Skip();
}
for (const CtrlLine& line : ctrl_lines) {
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
field->on_back_to_initial_value();
event.Skip();
return;
}
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
field->on_back_to_sys_value();
event.Skip();
return;
}
}
void OG_CustomCtrl::OnLeftUp(wxMouseEvent& event)
{
if (HasCapture())
return;
this->CaptureMouse();
event.Skip();
}
bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode)
@ -275,6 +320,27 @@ void OG_CustomCtrl::sys_color_changed()
msw_rescale();
}
OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height,
OG_CustomCtrl* ctrl,
const Line& og_line,
bool draw_just_act_buttons /* = false*/):
height(height),
ctrl(ctrl),
og_line(og_line),
draw_just_act_buttons(draw_just_act_buttons)
{
if (og_line.widget) {
rects_blinking.emplace_back(wxRect());
return;
}
for (size_t i = 0; i < og_line.get_options().size(); i++) {
rects_blinking.emplace_back(wxRect());
rects_undo_icon.emplace_back(wxRect());
rects_undo_to_sys_icon.emplace_back(wxRect());
}
}
void OG_CustomCtrl::CtrlLine::correct_items_positions()
{
if (draw_just_act_buttons || !is_visible)
@ -377,9 +443,11 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label + ":", text_clr, ctrl->opt_group->label_width * ctrl->m_em_unit);
}
// If there's a widget, build it and add the result to the sizer.
if (og_line.widget != nullptr)
// If there's a widget, build it and set result to the correct position.
if (og_line.widget != nullptr) {
draw_blinking_bmp(dc, wxPoint(h_pos, v_pos));
return;
}
// If we're here, we have more than one option or a single option with sidetext
// so we need a horizontal sizer to arrange these things
@ -389,11 +457,12 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
option_set.front().opt.label.empty() &&
option_set.front().side_widget == nullptr && og_line.get_extra_widgets().size() == 0)
{
if (field)
if (field && field->undo_to_sys_bitmap())
draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp());
return;
}
size_t bmp_rect_id = 0;
for (auto opt : option_set) {
field = ctrl->opt_group->get_field(opt.opt_id);
ConfigOptionDef option = opt.opt;
@ -407,8 +476,8 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit);
}
if (field) {
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp());
if (field && field->undo_to_sys_bitmap()) {
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), bmp_rect_id++);
if (field->getSizer())
{
auto children = field->getSizer()->GetChildren();
@ -490,28 +559,38 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr
return pos.x + width + ctrl->m_h_gap;
}
wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo)
wxPoint OG_CustomCtrl::CtrlLine::draw_blinking_bmp(wxDC& dc, wxPoint pos, size_t rect_id)
{
wxBitmap bmp_blinking = create_scaled_bitmap("search_blink", ctrl);
// wxBitmap bmp_blinking = create_scaled_bitmap("search_blink", ctrl);
wxBitmap bmp_blinking = create_scaled_bitmap("empty", ctrl);
wxCoord h_pos = pos.x;
wxCoord pos_y = pos.y + lround((height - bmp_blinking.GetHeight()) / 2);
wxCoord v_pos = pos.y + lround((height - bmp_blinking.GetHeight()) / 2);
dc.DrawBitmap(bmp_blinking, h_pos, pos_y);
dc.DrawBitmap(bmp_blinking, h_pos, v_pos);
int bmp_dim = bmp_blinking.GetWidth();
m_rect_blinking = wxRect(h_pos, pos_y, bmp_dim, bmp_dim);
rects_blinking[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim);
h_pos += bmp_dim + ctrl->m_h_gap;
dc.DrawBitmap(bmp_undo_to_sys, h_pos, pos_y);
return wxPoint(h_pos, v_pos);
}
bmp_dim = bmp_undo_to_sys.GetWidth();
m_rect_undo_to_sys_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim);
wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, size_t rect_id)
{
pos = draw_blinking_bmp(dc, pos, rect_id);
wxCoord h_pos = pos.x;
wxCoord v_pos = pos.y;
dc.DrawBitmap(bmp_undo_to_sys, h_pos, v_pos);
int bmp_dim = bmp_undo_to_sys.GetWidth();
rects_undo_to_sys_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim);
h_pos += bmp_dim + ctrl->m_h_gap;
dc.DrawBitmap(bmp_undo, h_pos, pos_y);
dc.DrawBitmap(bmp_undo, h_pos, v_pos);
bmp_dim = bmp_undo.GetWidth();
m_rect_undo_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim);
rects_undo_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim);
h_pos += bmp_dim + ctrl->m_h_gap;