fix bug that dropdown list of combox may excess screen

This commit is contained in:
Jinhao 2017-10-20 04:19:35 +08:00
parent 24bbfc6493
commit 94ab3b9f78
3 changed files with 82 additions and 44 deletions

View File

@ -38,9 +38,9 @@ namespace nana
{
std::vector<std::shared_ptr<item_interface>> items;
std::size_t max_items{10}; // the number of items display.
mutable std::size_t index{::nana::npos}; // the result of the selection.
mutable bool have_selected;
std::size_t max_items{ 10 }; // the number of items display.
mutable std::size_t index{ ::nana::npos }; // the result of the selection.
mutable bool have_selected{ false };
};
class item_renderer

View File

@ -14,6 +14,7 @@
#include <nana/gui/widgets/scroll.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/screen.hpp>
namespace nana
{
@ -198,16 +199,14 @@ namespace nana
return widget_;
}
void attach(widget* wd, nana::paint::graphics* graph)
void attach(widget& wd, nana::paint::graphics& graph)
{
if(wd)
{
widget_ = wd;
wd->events().mouse_wheel.connect_unignorable([this](const arg_wheel& arg){
scroll_items(arg.upwards);
});
}
if(graph) graph_ = graph;
widget_ = &wd;
wd.events().mouse_wheel.connect_unignorable([this](const arg_wheel& arg){
scroll_items(arg.upwards);
});
graph_ = &graph;
}
void detach()
@ -219,9 +218,46 @@ namespace nana
{
if(module_)
{
std::size_t items = (module_->max_items <= module_->items.size() ? module_->max_items : module_->items.size());
std::size_t h = items * state_.renderer->item_pixels(*graph_);
widget_->size(size{ widget_->size().width, static_cast<unsigned>(h + 4) });
auto const items = (module_->max_items <= module_->items.size() ? module_->max_items : module_->items.size());
rectangle list_r{
0, 0,
widget_->size().width,
static_cast<unsigned>(items * state_.renderer->item_pixels(*graph_)) + 4
};
//Test if the listbox excesses the screen
screen scr;
auto & disp = scr.from_window(*widget_);
auto disp_r = disp.area();
point pos;
API::calc_screen_point(*widget_, pos);
list_r.position(pos);
if (widget_->size().width >= disp_r.width)
{
pos.x = 0;
list_r.width = disp_r.width;
}
else if (list_r.right() > disp_r.right())
pos.x = disp_r.right() - static_cast<int>(list_r.width);
if (list_r.height >= disp_r.height)
{
pos.y = 0;
list_r.height = disp_r.height;
}
else if (list_r.bottom() > disp_r.bottom())
pos.y = disp_r.bottom() - static_cast<int>(list_r.height);
API::calc_window_point(API::get_owner_window(*widget_), pos);
list_r.position(pos);
widget_->move(list_r);
}
}
@ -312,36 +348,37 @@ namespace nana
void _m_open_scrollbar(widget_reference wd, bool v)
{
if(v)
if (!v)
{
if(scrollbar_.empty() && module_)
{
scrollbar_.create(wd, rectangle(static_cast<int>(wd.size().width - 18), 2, 16, wd.size().height - 4));
scrollbar_.amount(module_->items.size());
scrollbar_.range(module_->max_items);
scrollbar_.value(state_.offset_y);
auto & events = scrollbar_.events();
events.mouse_wheel.connect([this](const arg_wheel& arg)
{
scroll_items(arg.upwards);
});
auto fn = [this](const arg_mouse& arg)
{
if (arg.is_left_button() && (scrollbar_.value() != state_.offset_y))
{
state_.offset_y = static_cast<unsigned>(scrollbar_.value());
draw();
API::update_window(*widget_);
}
};
events.mouse_move.connect(fn);
events.mouse_up.connect(fn);
}
}
else
scrollbar_.close();
return;
}
if(scrollbar_.empty() && module_)
{
scrollbar_.create(wd, rectangle(static_cast<int>(wd.size().width - 18), 2, 16, wd.size().height - 4));
scrollbar_.amount(module_->items.size());
scrollbar_.range(module_->max_items);
scrollbar_.value(state_.offset_y);
auto & events = scrollbar_.events();
events.mouse_wheel.connect([this](const arg_wheel& arg)
{
scroll_items(arg.upwards);
});
auto fn = [this](const arg_mouse& arg)
{
if (arg.is_left_button() && (scrollbar_.value() != state_.offset_y))
{
state_.offset_y = static_cast<unsigned>(scrollbar_.value());
draw();
API::update_window(*widget_);
}
};
events.mouse_move.connect(fn);
events.mouse_up.connect(fn);
}
}
private:
widget * widget_{nullptr};
@ -393,7 +430,7 @@ namespace nana
void trigger::attached(widget_reference widget, graph_reference graph)
{
drawer_->attach(&widget, &graph);
drawer_->attach(widget, graph);
}
void trigger::detached()

View File

@ -4168,6 +4168,7 @@ namespace nana
{
if (sel)
{
//Deselects the previously selected item.
lister.cancel_others_if_single_enabled(true, abs_item_pos);
essence_->lister.latest_selected_abs = abs_item_pos;
}