Merge branch 'feature-keyboard-accelerator' into develop
This commit is contained in:
@@ -379,7 +379,7 @@ namespace nana{ namespace drawerbase
|
||||
}//end namespace drawerbase
|
||||
|
||||
//button
|
||||
//@brief: Defaine a button widget and it provides the interfaces to be operational
|
||||
//@brief: Define a button widget and it provides the interfaces to be operational
|
||||
button::button(){}
|
||||
|
||||
button::button(window wd, bool visible)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Form Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/form.hpp>
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@@ -94,6 +95,11 @@ namespace nana
|
||||
{
|
||||
API::wait_for(handle());
|
||||
}
|
||||
|
||||
void form::keyboard_accelerator(const accel_key& key, const std::function<void()>& fn)
|
||||
{
|
||||
nana::detail::bedrock::instance().keyboard_accelerator(this->native_handle(), key, fn);
|
||||
}
|
||||
//end class form
|
||||
|
||||
//class nested_form
|
||||
|
||||
@@ -208,8 +208,8 @@ namespace nana{
|
||||
outter[field_title] << impl_->caption;
|
||||
outter.collocate();
|
||||
|
||||
impl_->caption.transparent(true);
|
||||
color pbg = API::bgcolor(this->parent());
|
||||
|
||||
impl_->caption.bgcolor(pbg.blend(colors::black, 0.025));
|
||||
|
||||
this->bgcolor(pbg.blend(colors::black, 0.05));
|
||||
@@ -222,10 +222,27 @@ namespace nana{
|
||||
auto gap_px = impl_->gap - 1;
|
||||
|
||||
graph.rectangle(true, API::bgcolor(this->parent()));
|
||||
graph.round_rectangle(rectangle(point(gap_px, impl_->caption_dimension.height / 2),
|
||||
nana::size(graph.width() - 2 * gap_px, graph.height() - impl_->caption_dimension.height / 2 - gap_px)
|
||||
|
||||
auto const top_round_line = static_cast<int>(impl_->caption_dimension.height) / 2;
|
||||
|
||||
graph.round_rectangle(rectangle(point(gap_px, top_round_line),
|
||||
nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px)
|
||||
),
|
||||
3, 3, colors::gray_border, true, this->bgcolor());
|
||||
|
||||
auto opt_r = API::window_rectangle(impl_->caption);
|
||||
if (opt_r)
|
||||
{
|
||||
rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width, static_cast<unsigned>(top_round_line - opt_r->y) } };
|
||||
|
||||
grad_r.y += top_round_line*2 / 3;
|
||||
grad_r.x -= 2;
|
||||
grad_r.width += 4;
|
||||
|
||||
graph.gradual_rectangle(grad_r,
|
||||
API::bgcolor(this->parent()), this->bgcolor(), true
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A List Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -1273,6 +1273,7 @@ namespace nana
|
||||
}
|
||||
|
||||
//Backward
|
||||
n = -n;
|
||||
dpos = pos;
|
||||
if (good(dpos.cat))
|
||||
{
|
||||
@@ -1519,8 +1520,6 @@ namespace nana
|
||||
template<typename Pred>
|
||||
std::vector<std::pair<index_pair, bool>> select_display_range_if(const index_pair& fr_abs, index_pair to_dpl, bool deselect_others, Pred pred)
|
||||
{
|
||||
const index_pairs already_selected = (deselect_others ? this->pick_items(true) : index_pairs{});
|
||||
|
||||
if (to_dpl.empty())
|
||||
{
|
||||
if (fr_abs.empty())
|
||||
@@ -1533,6 +1532,11 @@ namespace nana
|
||||
if (fr_dpl > to_dpl)
|
||||
std::swap(fr_dpl, to_dpl);
|
||||
|
||||
if (to_dpl.is_category() && this->size_item(to_dpl.cat) > 0)
|
||||
to_dpl.item = this->size_item(to_dpl.cat) - 1;
|
||||
|
||||
const index_pairs already_selected = (deselect_others ? this->pick_items(true) : index_pairs{});
|
||||
|
||||
const auto begin = fr_dpl;
|
||||
const auto last = to_dpl;
|
||||
|
||||
@@ -1586,7 +1590,7 @@ namespace nana
|
||||
return pairs;
|
||||
}
|
||||
|
||||
bool select_for_all(bool sel, const index_pair& except = index_pair{npos, npos})
|
||||
bool select_for_all(bool sel, const index_pair& except_abs = index_pair{npos, npos})
|
||||
{
|
||||
bool changed = false;
|
||||
index_pair pos;
|
||||
@@ -1595,7 +1599,7 @@ namespace nana
|
||||
pos.item = 0;
|
||||
for(auto & m : cat.items)
|
||||
{
|
||||
if (except != pos)
|
||||
if (except_abs != pos)
|
||||
{
|
||||
if (m.flags.selected != sel)
|
||||
{
|
||||
@@ -1618,7 +1622,7 @@ namespace nana
|
||||
}
|
||||
|
||||
/// return absolute positions, no relative to display
|
||||
index_pairs pick_items(bool for_selection) const
|
||||
index_pairs pick_items(bool for_selection, bool find_first = false) const
|
||||
{
|
||||
index_pairs results;
|
||||
index_pair id;
|
||||
@@ -1629,7 +1633,11 @@ namespace nana
|
||||
for (auto & m : cat.items)
|
||||
{
|
||||
if (for_selection ? m.flags.selected : m.flags.checked)
|
||||
{
|
||||
results.push_back(id); // absolute positions, no relative to display
|
||||
if (find_first)
|
||||
return results;
|
||||
}
|
||||
++id.item;
|
||||
}
|
||||
++id.cat;
|
||||
@@ -1978,6 +1986,15 @@ namespace nana
|
||||
};
|
||||
}
|
||||
|
||||
bool cs_status(index_pair abs_pos, bool for_selection) const
|
||||
{
|
||||
if (abs_pos.is_category())
|
||||
return lister.cat_status(abs_pos.cat, for_selection);
|
||||
|
||||
auto & flags = lister.get(abs_pos.cat)->items.at(abs_pos.item).flags;
|
||||
return (for_selection ? flags.selected : flags.checked);
|
||||
}
|
||||
|
||||
void resize_disp_area()
|
||||
{
|
||||
auto head_px = this->header_visible_px();
|
||||
@@ -3416,6 +3433,8 @@ namespace nana
|
||||
rect.y - static_cast<int>(origin.y % item_height_px)
|
||||
};
|
||||
|
||||
essence_->inline_buffered_table.swap(essence_->inline_table);
|
||||
|
||||
// The first display is empty when the listbox is empty.
|
||||
if (!first_disp.empty())
|
||||
{
|
||||
@@ -3438,8 +3457,6 @@ namespace nana
|
||||
|
||||
auto idx = first_disp;
|
||||
|
||||
essence_->inline_buffered_table.swap(essence_->inline_table);
|
||||
|
||||
for (auto & cat : lister.cat_container())
|
||||
for (auto & ind : cat.indicators)
|
||||
{
|
||||
@@ -3509,10 +3526,10 @@ namespace nana
|
||||
++idx.item;
|
||||
}
|
||||
}
|
||||
|
||||
essence_->inline_buffered_table.clear();
|
||||
}
|
||||
|
||||
essence_->inline_buffered_table.clear();
|
||||
|
||||
if (item_coord.y < rect.bottom())
|
||||
{
|
||||
rectangle bground_r{ rect.x, item_coord.y, rect.width, static_cast<unsigned>(rect.bottom() - item_coord.y) };
|
||||
@@ -4117,17 +4134,16 @@ namespace nana
|
||||
essence_->content_view->sync(false);
|
||||
}
|
||||
|
||||
bool sel = true;
|
||||
bool new_selected_status = true;
|
||||
|
||||
//no single selected
|
||||
if (!lister.single_status(true))
|
||||
if (!lister.single_status(true)) //multiply selection enabled
|
||||
{
|
||||
if (arg.shift)
|
||||
{
|
||||
//Set the first item as the begin of selected item if there
|
||||
//is not a latest selected item.(#154 reported by RenaudAlpes)
|
||||
if (lister.latest_selected_abs.empty() || lister.latest_selected_abs.is_category())
|
||||
lister.latest_selected_abs.set_both(0);
|
||||
if (lister.latest_selected_abs.empty())
|
||||
lister.latest_selected_abs = lister.first();
|
||||
|
||||
auto before = lister.latest_selected_abs;
|
||||
|
||||
@@ -4141,7 +4157,7 @@ namespace nana
|
||||
else if (arg.ctrl)
|
||||
{
|
||||
essence_->mouse_selection.reverse_selection = true;
|
||||
sel = !item_proxy(essence_, abs_item_pos).selected();
|
||||
new_selected_status = !essence_->cs_status(abs_item_pos, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4150,12 +4166,12 @@ namespace nana
|
||||
//Unselects all selected items if the current item is not selected before selecting.
|
||||
auto selected = lister.pick_items(true);
|
||||
if (selected.cend() == std::find(selected.cbegin(), selected.cend(), item_pos))
|
||||
lister.select_for_all(false, item_pos);
|
||||
lister.select_for_all(false, abs_item_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Unselects all selected items except current item if right button clicked.
|
||||
lister.select_for_all(false, item_pos); //cancel all selections
|
||||
lister.select_for_all(false, abs_item_pos); //cancel all selections
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4164,14 +4180,14 @@ namespace nana
|
||||
//Clicking on a category is ignored when single selection is enabled.
|
||||
//Fixed by Greentwip(issue #121)
|
||||
if (item_ptr)
|
||||
sel = !item_proxy(essence_, abs_item_pos).selected();
|
||||
new_selected_status = !item_proxy(essence_, abs_item_pos).selected();
|
||||
}
|
||||
|
||||
if(item_ptr)
|
||||
{
|
||||
if (item_ptr->flags.selected != sel)
|
||||
if (item_ptr->flags.selected != new_selected_status)
|
||||
{
|
||||
if (sel)
|
||||
if (new_selected_status)
|
||||
{
|
||||
//Deselects the previously selected item.
|
||||
lister.cancel_others_if_single_enabled(true, abs_item_pos);
|
||||
@@ -4180,13 +4196,15 @@ namespace nana
|
||||
else if (essence_->lister.latest_selected_abs == abs_item_pos)
|
||||
essence_->lister.latest_selected_abs.set_both(npos);
|
||||
|
||||
item_ptr->flags.selected = sel;
|
||||
item_ptr->flags.selected = new_selected_status;
|
||||
lister.emit_cs(abs_item_pos, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lister.cat_status(item_pos.cat, true, true);
|
||||
//A category was clicked. Sets all child items to be selected only if multiply selection is enabled.
|
||||
if(!lister.single_status(true))
|
||||
lister.cat_status(item_pos.cat, true, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4336,8 +4354,9 @@ namespace nana
|
||||
|
||||
void trigger::key_press(graph_reference graph, const arg_keyboard& arg)
|
||||
{
|
||||
auto & list = essence_->lister;
|
||||
// Exit if list is empty
|
||||
if (essence_->lister.first().empty())
|
||||
if (list.first().empty())
|
||||
return;
|
||||
|
||||
bool upward = false;
|
||||
@@ -4347,12 +4366,12 @@ namespace nana
|
||||
case keyboard::os_arrow_up:
|
||||
upward = true;
|
||||
case keyboard::os_arrow_down:
|
||||
essence_->lister.move_select(upward, !arg.shift, true);
|
||||
list.move_select(upward, !arg.shift, true);
|
||||
break;
|
||||
case L' ':
|
||||
{
|
||||
index_pairs s;
|
||||
bool ck = ! essence_->lister.item_selected_all_checked(s);
|
||||
bool ck = ! list.item_selected_all_checked(s);
|
||||
for(auto i : s)
|
||||
item_proxy(essence_, i).check(ck);
|
||||
}
|
||||
@@ -4361,30 +4380,69 @@ namespace nana
|
||||
upward = true;
|
||||
case keyboard::os_pagedown:
|
||||
{
|
||||
//Turns page, then returns if no change occurs
|
||||
if (!essence_->content_view->turn_page(!upward, false))
|
||||
return;
|
||||
auto const item_px = essence_->item_height();
|
||||
auto picked_items = list.pick_items(true, true);
|
||||
index_pair init_idx = (picked_items.empty() ? list.first() : picked_items[0]);
|
||||
|
||||
essence_->lister.select_for_all(false);
|
||||
|
||||
auto idx = essence_->first_display();
|
||||
//Get the pixels between the init item and top edge or bottom edge
|
||||
auto logic_top = static_cast<int>(list.distance(list.first(), init_idx) * item_px);
|
||||
|
||||
if (!upward)
|
||||
idx = essence_->lister.advance(idx, static_cast<int>(essence_->count_of_exposed(false)) - 1);
|
||||
auto const screen_top = essence_->content_view->origin().y;
|
||||
auto const screen_bottom = screen_top + essence_->content_view->view_area().height;
|
||||
index_pair target_idx;
|
||||
|
||||
if (!idx.is_category())
|
||||
item_proxy::from_display(essence_, idx).select(true);
|
||||
else if (!essence_->lister.single_status(true)) //not selected
|
||||
essence_->lister.cat_status(idx.cat, true, true);
|
||||
//Check if it scrolls in current screen window
|
||||
//condition: top of target item is not less than top edge of content view and
|
||||
//the bottom of target item is not greater than bottom edge of content view.
|
||||
if ((screen_top + item_px <= logic_top) && (logic_top + item_px + item_px <= screen_bottom))
|
||||
{
|
||||
int offset = (static_cast<int>(upward ? screen_top : screen_bottom - item_px) - logic_top) / static_cast<int>(item_px);
|
||||
target_idx = list.advance(init_idx, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
//turn page
|
||||
auto page_item_count = (std::max)(1, static_cast<int>(essence_->count_of_exposed(false)));
|
||||
|
||||
break;
|
||||
auto origin = essence_->content_view->origin();
|
||||
if (upward)
|
||||
{
|
||||
target_idx = list.advance(init_idx, -page_item_count);
|
||||
if (target_idx.empty())
|
||||
target_idx = list.first();
|
||||
|
||||
origin.y = list.distance(list.first(), target_idx) * item_px;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_idx = list.advance(init_idx, page_item_count);
|
||||
if (target_idx.empty())
|
||||
target_idx = list.last();
|
||||
|
||||
origin.y = list.distance(list.first(), target_idx) * item_px + item_px;
|
||||
if (origin.y >= (screen_bottom - screen_top))
|
||||
origin.y -= (screen_bottom - screen_top);
|
||||
else
|
||||
origin.y = 0;
|
||||
}
|
||||
|
||||
essence_->content_view->move_origin(origin - essence_->content_view->origin());
|
||||
}
|
||||
|
||||
if (!target_idx.is_category())
|
||||
item_proxy::from_display(essence_, target_idx).select(true);
|
||||
else if (!list.single_status(true)) //not selected
|
||||
list.cat_status(target_idx.cat, true, true);
|
||||
}
|
||||
break;
|
||||
case keyboard::os_home:
|
||||
case keyboard::os_end:
|
||||
{
|
||||
essence_->lister.select_for_all(false);
|
||||
list.select_for_all(false);
|
||||
|
||||
auto pos = (keyboard::os_home == arg.key ? essence_->lister.first() : essence_->lister.last());
|
||||
auto pos = (keyboard::os_home == arg.key ? list.first() : list.last());
|
||||
if (!pos.empty())
|
||||
{
|
||||
//When the pos indicates an empty category, then search forwards/backwards(depending on arg.key whether it is Home or End) for a non empty category.
|
||||
@@ -4393,9 +4451,9 @@ namespace nana
|
||||
{
|
||||
if (keyboard::os_home == arg.key)
|
||||
{
|
||||
while (0 == essence_->lister.size_item(pos.cat))
|
||||
while (0 == list.size_item(pos.cat))
|
||||
{
|
||||
if (++pos.cat >= essence_->lister.cat_container().size())
|
||||
if (++pos.cat >= list.cat_container().size())
|
||||
{
|
||||
pos = index_pair{ npos, npos };
|
||||
break;
|
||||
@@ -4404,7 +4462,7 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
while (0 == essence_->lister.size_item(pos.cat))
|
||||
while (0 == list.size_item(pos.cat))
|
||||
{
|
||||
if (pos.cat-- == 0)
|
||||
{
|
||||
@@ -4416,7 +4474,7 @@ namespace nana
|
||||
|
||||
if (!pos.empty())
|
||||
{
|
||||
if (essence_->lister.expand(pos.cat))
|
||||
if (list.expand(pos.cat))
|
||||
pos.item = 0;
|
||||
}
|
||||
}
|
||||
@@ -4425,8 +4483,8 @@ namespace nana
|
||||
{
|
||||
if (pos.is_category())
|
||||
{
|
||||
if (!essence_->lister.single_status(true)) //multiple selection is not enabled
|
||||
essence_->lister.cat_status(pos.cat, true, true);
|
||||
if (!list.single_status(true)) //multiple selection is not enabled
|
||||
list.cat_status(pos.cat, true, true);
|
||||
}
|
||||
else
|
||||
item_proxy::from_display(essence_, pos).select(true);
|
||||
@@ -4662,12 +4720,12 @@ namespace nana
|
||||
|
||||
bool item_proxy::operator==(const std::string& s) const
|
||||
{
|
||||
return (text(pos_.item) == s);
|
||||
return (text(0) == s);
|
||||
}
|
||||
|
||||
bool item_proxy::operator==(const std::wstring& s) const
|
||||
{
|
||||
return (text(pos_.item) == to_utf8(s));
|
||||
return (text(0) == to_utf8(s));
|
||||
}
|
||||
|
||||
item_proxy & item_proxy::operator=(const item_proxy& rhs)
|
||||
@@ -5158,7 +5216,8 @@ namespace nana
|
||||
cat_->make_sort_order();
|
||||
ess_->lister.sort();
|
||||
|
||||
ess_->update(true);
|
||||
//Don't ignore the auto-draw flag for performance enhancement.
|
||||
ess_->update();
|
||||
}
|
||||
}
|
||||
//end class cat_proxy
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Progress Indicator Implementation
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -96,7 +96,11 @@ namespace nana
|
||||
{
|
||||
if (widget_)
|
||||
{
|
||||
auto value_px = (widget_->size().width - border_px * 2) * value_ / max_;
|
||||
auto value_px = (widget_->size().width - border_px * 2);
|
||||
|
||||
//avoid overflow
|
||||
if (value_ < max_)
|
||||
value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_)));
|
||||
|
||||
if (value_px != value_px_)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Scroll Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -20,9 +20,15 @@ namespace nana
|
||||
namespace scroll
|
||||
{
|
||||
//struct metrics_type
|
||||
metrics_type::metrics_type()
|
||||
:peak(1), range(1), step(1), value(0),
|
||||
what(buttons::none), pressed(false), scroll_length(0), scroll_pos(0)
|
||||
metrics_type::metrics_type():
|
||||
peak(1),
|
||||
range(1),
|
||||
step(1),
|
||||
value(0),
|
||||
what(buttons::none),
|
||||
pressed(false),
|
||||
scroll_length(0),
|
||||
scroll_pos(0)
|
||||
{}
|
||||
//end struct metrics_type
|
||||
|
||||
|
||||
Reference in New Issue
Block a user