15 #define GETTEXT_DOMAIN "wesnoth-lib" 31 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__ 32 #define LOG_HEADER LOG_SCOPE_HEADER + ':' 39 static const std::string button_up_names[]
40 {
"_begin",
"_line_up",
"_half_page_up",
"_page_up" };
42 static const std::string button_down_names[]
43 {
"_end",
"_line_down",
"_half_page_down",
"_page_down" };
49 const std::map<std::string, scrollbar_base::scroll_mode>& scroll_lookup()
51 static std::map<std::string, scrollbar_base::scroll_mode> lookup;
73 , vertical_scrollbar_mode_(AUTO_VISIBLE_FIRST_RUN)
74 , horizontal_scrollbar_mode_(AUTO_VISIBLE_FIRST_RUN)
75 , vertical_scrollbar_grid_(nullptr)
76 , horizontal_scrollbar_grid_(nullptr)
77 , vertical_scrollbar_(nullptr)
78 , horizontal_scrollbar_(nullptr)
79 , content_grid_(nullptr)
81 , content_visible_area_()
83 connect_signal<event::SDL_KEY_DOWN>(
86 connect_signal<event::SDL_WHEEL_UP>(
90 connect_signal<event::SDL_WHEEL_DOWN>(
94 connect_signal<event::SDL_WHEEL_LEFT>(
98 connect_signal<event::SDL_WHEEL_RIGHT>(
102 connect_signal<event::SDL_TOUCH_MOTION>(
105 std::placeholders::_2,
106 std::placeholders::_3,
107 std::placeholders::_5,
108 std::placeholders::_6),
117 if(full_initialization) {
163 const unsigned offset =
168 content_grid_->request_reduce_height(maximum_height - offset);
172 if(static_cast<unsigned>(size.
y) <= maximum_height) {
191 if(resized && scrollbar_size.
y > size.
y) {
194 <<
" increased the height to " << scrollbar_size.
y <<
".\n";
198 if(maximum_height > static_cast<unsigned>(scrollbar_size.
y)) {
199 size.
y = maximum_height;
201 size.
y = scrollbar_size.
y;
227 const unsigned offset =
236 if(static_cast<unsigned>(size.
x) <= maximum_width) {
265 <<
" increased the width to " << scrollbar_size.
x <<
".\n";
269 if(maximum_width > static_cast<unsigned>(scrollbar_size.
x)) {
270 size.
x = maximum_width;
272 size.
x = scrollbar_size.
x;
307 vertical_scrollbar.
x + std::max(horizontal_scrollbar.
x, content.
x),
308 horizontal_scrollbar.
y + std::max(vertical_scrollbar.
y, content.
y));
310 DBG_GUI_L <<
LOG_HEADER <<
" vertical_scrollbar " << vertical_scrollbar <<
" horizontal_scrollbar " 311 << horizontal_scrollbar <<
" content " << content <<
" result " << result <<
".\n";
319 const unsigned items,
320 const unsigned visible_items,
323 assert(scrollbar_grid && scrollbar);
335 const bool scrollbar_needed = items > visible_items;
338 if(items <= visible_items && content_grid !=
nullptr 348 unsigned insertion_pos,
unsigned old_item_count,
unsigned old_position,
unsigned visible_items)
350 if(old_position == 0) {
352 }
else if(old_position + visible_items >= old_item_count) {
354 }
else if(insertion_pos <= old_position) {
364 const unsigned items_before,
365 const unsigned items_after,
366 const int insertion_pos,
367 const unsigned visible_items)
369 assert(scrollbar_grid && scrollbar);
371 return set_scrollbar_mode(scrollbar_grid, scrollbar, scrollbar_mode, items_after, visible_items,
nullptr);
379 static_cast<unsigned>(insertion_pos), items_before, previous_item_position, visible_items);
388 ? previous_item_position + items_after - items_before
389 : previous_item_position);
395 const bool scrollbar_needed = items_after > visible_items;
413 const point content_grid_size(std::max(best_size.
x, content_size.x), std::max(best_size.
y, content_size.y));
484 widget*
w = scrollbar_container_implementation::find_at<widget>(*
this,
coordinate, must_be_active);
494 const widget*
w = scrollbar_container_implementation::find_at<const widget>(*
this,
coordinate, must_be_active);
504 return scrollbar_container_implementation::find<widget>(*
this,
id, must_be_active);
509 return scrollbar_container_implementation::find<const widget>(*
this,
id, must_be_active);
533 DBG_GUI_L <<
LOG_HEADER <<
" wanted size " << best_size <<
" available size " << size <<
".\n";
535 if(size ==
point()) {
540 if(best_size.
x <= size.x && best_size.
y <= size.y) {
543 if(content_size.
x > size.x || content_size.
y > size.y) {
557 if(best_size.
x > size.x) {
566 DBG_GUI_L << LOG_HEADER <<
" can't use horizontal scrollbar, request placement.\n";
574 if(best_size.
y > size.y) {
583 DBG_GUI_L << LOG_HEADER <<
" can't use vertical scrollbar, request placement.\n";
599 const int height_modification,
600 const int width_modification_pos,
601 const int height_modification_pos)
603 DBG_GUI_L <<
LOG_HEADER <<
" wanted width modification " << width_modification <<
" wanted height modification " 604 << height_modification <<
".\n";
641 if(width_modification == 0) {
645 const int new_width =
content_grid_->get_width() + width_modification;
653 DBG_GUI_L <<
" width fits in container, test height.\n";
668 DBG_GUI_L <<
" can't use horizontal scrollbar, ask window.\n";
677 DBG_GUI_L <<
" use the horizontal scrollbar, test height.\n";
687 if(height_modification == 0) {
691 const int new_height =
content_grid_->get_height() + height_modification;
700 DBG_GUI_L <<
" height in container, resize allowed.\n";
714 DBG_GUI_L <<
" can't use vertical scrollbar, ask window.\n";
723 DBG_GUI_L <<
" use the vertical scrollbar, resize allowed.\n";
752 for(
const auto&
item : scroll_lookup()) {
771 content_ = build_single_widget_instance<spacer>();
804 content_grid_->draw_children(frame_buffer, x_offset, y_offset);
822 std::vector<widget*> child_call_stack(call_stack);
823 content_grid_->populate_dirty_list(caller, child_call_stack);
844 const int wanted_bottom = rect.y + rect.h;
847 int distance = wanted_bottom - current_bottom;
853 const int wanted_right = rect.x + rect.w;
856 distance = wanted_right - current_right;
879 for(
const auto&
name : button_up_names) {
888 for(
const auto&
name : button_down_names) {
902 for(
const auto&
name : button_up_names) {
911 for(
const auto&
name : button_down_names) {
1086 static const std::string
type =
"scrollbar_container";
1096 const event::ui_event event,
bool& handled,
const SDL_Keycode key, SDL_Keymod modifier)
1193 const point& position,
1194 const point& distance)
1199 bool is_scrollbar_moved =
false;
1205 is_scrollbar_moved =
true;
1213 is_scrollbar_moved =
true;
1217 if (is_scrollbar_moved) {
Define the common log macros for the gui toolkit.
static void set_scrollbar_mode(grid *scrollbar_grid, scrollbar_base *scrollbar, scrollbar_container::scrollbar_mode &scrollbar_mode, const unsigned items, const unsigned visible_items, grid *content_grid)
Defines the exception classes for the layout algorithm.
virtual void child_populate_dirty_list(window &caller, const std::vector< widget *> &call_stack) override
See widget::child_populate_dirty_list.
virtual void place(const point &origin, const point &size) override
See widget::place.
const grid & get_grid() const
Main class to show messages to the user.
lg::log_domain log_gui_layout("gui/layout")
virtual void impl_draw_children(surface &frame_buffer, int x_offset, int y_offset) override
See widget::impl_draw_children.
SDL_Rect intersect_rects(const SDL_Rect &rect1, const SDL_Rect &rect2)
Calculates the intersection of two rectangles.
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
static void adjust_scrollbar_mode(grid *scrollbar_grid, scrollbar_base *scrollbar, scrollbar_container::scrollbar_mode &scrollbar_mode, const unsigned items_before, const unsigned items_after, const int insertion_pos, const unsigned visible_items)
const std::vector< std::string > items
static bool is_inserted_before(unsigned insertion_pos, unsigned old_item_count, unsigned old_position, unsigned visible_items)
The message callbacks hold a reference to a message.
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Request to place the widget.
Exception thrown when the width has been modified during resizing.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
virtual void connect_click_handler(const event::signal_function &signal)=0
Connects a signal handler for a 'click' event.
This file contains the definitions for the gui2::event::message class.
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See widget::set_visible_rectangle.
#define log_scope2(domain, description)
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
A generic container base class.
Contains the SDL_Rect helper code.
virtual void set_origin(const point &origin) override
See widget::set_origin.
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
bool get_need_layout() const
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
void invalidate_layout()
Updates the size of the window.
virtual void layout_children() override
See widget::layout_children.
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
base class of top level items, the only item which needs to store the final canvases to draw on...
static std::deque< std::string > call_stack
ui_event
The event send to the dispatcher.
std::pair< std::string, unsigned > item