The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
scrollbar_container.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
20 #include "gui/core/log.hpp"
23 #include "gui/widgets/spacer.hpp"
24 #include "gui/widgets/window.hpp"
25 #include "sdl/rect.hpp"
26 
27 #include "utils/functional.hpp"
28 
29 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
30 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
31 
32 namespace gui2
33 {
34 
35 namespace
36 {
37 
38 static const std::string button_up_names[]
39  = { "_begin", "_line_up", "_half_page_up", "_page_up" };
40 
41 static const std::string button_down_names[]
42  = { "_end", "_line_down", "_half_page_down", "_page_down" };
43 
44 /**
45  * Returns a map with the names of all buttons and the scrollbar jump they're
46  * supposed to execute.
47  */
48 const std::map<std::string, tscrollbar_::tscroll>& scroll_lookup()
49 {
50  static std::map<std::string, tscrollbar_::tscroll> lookup;
51  if(lookup.empty()) {
52  lookup["_begin"] = tscrollbar_::BEGIN;
53  lookup["_line_up"] = tscrollbar_::ITEM_BACKWARDS;
54  lookup["_half_page_up"] = tscrollbar_::HALF_JUMP_BACKWARDS;
55  lookup["_page_up"] = tscrollbar_::JUMP_BACKWARDS;
56 
57  lookup["_end"] = tscrollbar_::END;
58  lookup["_line_down"] = tscrollbar_::ITEM_FORWARD;
59  lookup["_half_page_down"] = tscrollbar_::HALF_JUMP_FORWARD;
60  lookup["_page_down"] = tscrollbar_::JUMP_FORWARD;
61  }
62 
63  return lookup;
64 }
65 
66 } // namespace
67 
68 tscrollbar_container::tscrollbar_container(const unsigned canvas_count)
69  : tcontainer_(canvas_count)
70  , state_(ENABLED)
71  , vertical_scrollbar_mode_(auto_visible_first_run)
72  , horizontal_scrollbar_mode_(auto_visible_first_run)
73  , vertical_scrollbar_grid_(nullptr)
74  , horizontal_scrollbar_grid_(nullptr)
75  , vertical_scrollbar_(nullptr)
76  , horizontal_scrollbar_(nullptr)
77  , content_grid_(nullptr)
78  , content_(nullptr)
79  , content_visible_area_()
80 {
81  connect_signal<event::SDL_KEY_DOWN>(
83  this,
84  _2,
85  _3,
86  _5,
87  _6));
88 
89 
90  connect_signal<event::SDL_WHEEL_UP>(
92  this,
93  _2,
94  _3),
96 
97  connect_signal<event::SDL_WHEEL_DOWN>(
99  this,
100  _2,
101  _3),
103 
104  connect_signal<event::SDL_WHEEL_LEFT>(
106  this,
107  _2,
108  _3),
110 
111  connect_signal<event::SDL_WHEEL_RIGHT>(
113  this,
114  _2,
115  _3),
117 }
118 
119 void tscrollbar_container::layout_initialise(const bool full_initialisation)
120 {
121  // Inherited.
122  tcontainer_::layout_initialise(full_initialisation);
123 
124  if(full_initialisation) {
125 
126  assert(vertical_scrollbar_grid_);
127  switch(vertical_scrollbar_mode_) {
128  case always_visible:
131  break;
132 
133  case auto_visible:
136  break;
137 
138  default:
141  }
142 
145  case always_visible:
148  break;
149 
150  case auto_visible:
153  break;
154 
155  default:
158  }
159  }
160 
161  assert(content_grid_);
162  content_grid_->layout_initialise(full_initialisation);
163 }
164 
165 void tscrollbar_container::request_reduce_height(const unsigned maximum_height)
166 {
167  DBG_GUI_L << LOG_HEADER << " requested height " << maximum_height << ".\n";
168  /*
169  * First ask the content to reduce it's height. This seems to work for now,
170  * but maybe some sizing hints will be required later.
171  */
172  /** @todo Evaluate whether sizing hints are required. */
173  assert(content_grid_);
174  const unsigned offset
179  : 0;
180 
181  content_grid_->request_reduce_height(maximum_height - offset);
182 
183  // Did we manage to achieve the wanted size?
185  if(static_cast<unsigned>(size.y) <= maximum_height) {
186  DBG_GUI_L << LOG_HEADER << " child honored request, height " << size.y
187  << ".\n";
188  return;
189  }
190 
192  DBG_GUI_L << LOG_HEADER << " request failed due to scrollbar mode.\n";
193  return;
194  }
195 
196  assert(vertical_scrollbar_grid_);
197  const bool resized = vertical_scrollbar_grid_->get_visible()
199 
200  // Always set the bar visible, is a nop is already visible.
202 
203  const tpoint scrollbar_size = vertical_scrollbar_grid_->get_best_size();
204 
205  // If showing the scrollbar increased the height, hide and abort.
206  if(resized && scrollbar_size.y > size.y) {
208  DBG_GUI_L << LOG_HEADER << " request failed, showing the scrollbar"
209  << " increased the height to " << scrollbar_size.y << ".\n";
210  return;
211  }
212 
213  if(maximum_height > static_cast<unsigned>(scrollbar_size.y)) {
214  size.y = maximum_height;
215  } else {
216  size.y = scrollbar_size.y;
217  }
218 
219  // FIXME adjust for the step size of the scrollbar
220 
221  set_layout_size(size);
222  DBG_GUI_L << LOG_HEADER << " resize resulted in " << size.y << ".\n";
223 
224  if(resized) {
226  << " resize modified the width, throw notification.\n";
227 
229  }
230 }
231 
232 void tscrollbar_container::request_reduce_width(const unsigned maximum_width)
233 {
234  DBG_GUI_L << LOG_HEADER << " requested width " << maximum_width << ".\n";
235 
236  // First ask our content, it might be able to wrap which looks better as
237  // a scrollbar.
238  assert(content_grid_);
239  const unsigned offset
244  : 0;
245 
246  content_grid_->request_reduce_width(maximum_width - offset);
247 
248  // Did we manage to achieve the wanted size?
250  if(static_cast<unsigned>(size.x) <= maximum_width) {
251  DBG_GUI_L << LOG_HEADER << " child honored request, width " << size.x
252  << ".\n";
253  return;
254  }
255 
257  DBG_GUI_L << LOG_HEADER << " request failed due to scrollbar mode.\n";
258  return;
259  }
260 
261  // Always set the bar visible, is a nop when it's already visible.
264  size = get_best_size();
265 
266  tpoint scrollbar_size = horizontal_scrollbar_grid_->get_best_size();
267 
268  /*
269  * If the vertical bar is not invisible it's size needs to be added to the
270  * minimum size.
271  */
274 
275  scrollbar_size.x += vertical_scrollbar_grid_->get_best_size().x;
276  }
277 
278  // If showing the scrollbar increased the width, hide and abort.
279  if(horizontal_scrollbar_mode_ == auto_visible_first_run && scrollbar_size.x
280  > size.x) {
281 
283  DBG_GUI_L << LOG_HEADER << " request failed, showing the scrollbar"
284  << " increased the width to " << scrollbar_size.x << ".\n";
285  return;
286  }
287 
288  if(maximum_width > static_cast<unsigned>(scrollbar_size.x)) {
289  size.x = maximum_width;
290  } else {
291  size.x = scrollbar_size.x;
292  }
293 
294  // FIXME adjust for the step size of the scrollbar
295 
296  set_layout_size(size);
297  DBG_GUI_L << LOG_HEADER << " resize resulted in " << size.x << ".\n";
298 }
299 
301 {
302  return content_grid_ ? content_grid_->can_wrap() : false;
303 }
304 
306 {
308 
309  /***** get vertical scrollbar size *****/
310  const tpoint vertical_scrollbar
313  ? tpoint(0, 0)
315 
316  /***** get horizontal scrollbar size *****/
317  const tpoint horizontal_scrollbar
320  ? tpoint(0, 0)
322 
323  /***** get content size *****/
324  assert(content_grid_);
325  const tpoint content = content_grid_->get_best_size();
326 
327  const tpoint result(
328  vertical_scrollbar.x + std::max(horizontal_scrollbar.x, content.x),
329  horizontal_scrollbar.y + std::max(vertical_scrollbar.y, content.y));
330 
331  DBG_GUI_L << LOG_HEADER << " vertical_scrollbar " << vertical_scrollbar
332  << " horizontal_scrollbar " << horizontal_scrollbar << " content "
333  << content << " result " << result << ".\n";
334 
335  return result;
336 }
337 
338 static void
339 set_scrollbar_mode(tgrid* scrollbar_grid,
340  tscrollbar_* scrollbar,
342  const unsigned items,
343  const unsigned visible_items)
344 {
345  assert(scrollbar_grid && scrollbar);
346 
347  if(scrollbar_mode == tscrollbar_container::always_invisible) {
348  scrollbar_grid->set_visible(twidget::tvisible::invisible);
349  return;
350  }
351 
352  scrollbar->set_item_count(items);
353  scrollbar->set_item_position(0);
354  scrollbar->set_visible_items(visible_items);
355 
356  if(scrollbar_mode == tscrollbar_container::auto_visible) {
357 
358  const bool scrollbar_needed = items > visible_items;
359 
360  scrollbar_grid->set_visible(scrollbar_needed
363  }
364 }
365 static bool is_inserted_before(unsigned insertion_pos, unsigned old_item_count, unsigned old_position, unsigned visible_items)
366 {
367  if(old_position == 0)
368  return false;
369  else if(old_position + visible_items >= old_item_count)
370  return true;
371  else if(insertion_pos <= old_position)
372  return true;
373  else
374  return false;
375 }
376 
377 static void
378 adjust_scrollbar_mode(tgrid* scrollbar_grid,
379  tscrollbar_* scrollbar,
381  const unsigned items_before,
382  const unsigned items_after,
383  const int insertion_pos,
384  const unsigned visible_items)
385 {
386  assert(scrollbar_grid && scrollbar);
387  if(items_before != scrollbar->get_item_count()) {
388  return set_scrollbar_mode(scrollbar_grid, scrollbar, scrollbar_mode, items_after, visible_items);
389  }
390  //TODO: does this also work well in case the items were removed?
391  const unsigned previous_item_position = scrollbar->get_item_position();
392  //Casts insertion_pos to an unsigned so negative values are interpreted as 'at end'
393  const bool inserted_before_visible_area = is_inserted_before(static_cast<unsigned>(insertion_pos), items_before, previous_item_position, visible_items);
394 
395  if(scrollbar_mode == tscrollbar_container::always_invisible) {
396  scrollbar_grid->set_visible(twidget::tvisible::invisible);
397  return;
398  }
399 
400  scrollbar->set_item_count(items_after);
401  scrollbar->set_item_position(inserted_before_visible_area ? previous_item_position + items_after - items_before : previous_item_position);
402  //scrollbar->set_item_position(0);
403  scrollbar->set_visible_items(visible_items);
404 
405  if(scrollbar_mode == tscrollbar_container::auto_visible) {
406 
407  const bool scrollbar_needed = items_after > visible_items;
408 
409  scrollbar_grid->set_visible(scrollbar_needed
412  }
413 }
414 
415 void tscrollbar_container::place(const tpoint& origin, const tpoint& size)
416 {
417  // Inherited.
418  tcontainer_::place(origin, size);
419 
420  // Set content size
421  assert(content_ && content_grid_);
422 
423  const tpoint content_origin = content_->get_origin();
424 
425  const tpoint best_size = content_grid_->get_best_size();
426  const tpoint content_size(content_->get_width(), content_->get_height());
427 
428  const tpoint content_grid_size(std::max(best_size.x, content_size.x),
429  std::max(best_size.y, content_size.y));
430 
431  set_content_size(content_origin, content_grid_size);
432 
433  // Set vertical scrollbar
438  content_->get_height());
439 
440  // Set horizontal scrollbar
445  content_->get_width());
446 
447  // Update the buttons.
449 
450  // Now set the visible part of the content.
453 }
454 
456 {
457  // Inherited.
458  tcontainer_::set_origin(origin);
459 
460  // Set content size
461  assert(content_ && content_grid_);
462 
463  const tpoint content_origin = content_->get_origin();
464 
465  content_grid_->set_origin(content_origin);
466 
467  // Changing the origin also invalidates the visible area.
469 }
470 
471 void tscrollbar_container::set_visible_rectangle(const SDL_Rect& rectangle)
472 {
473  // Inherited.
475 
476  // Now get the visible part of the content.
479 
481 }
482 
484 {
485  return state_ != DISABLED;
486 }
487 
489 {
490  return state_;
491 }
492 
494  const bool must_be_active)
495 {
496  return tscrollbar_container_implementation::find_at<twidget>(
497  *this, coordinate, must_be_active);
498 }
499 
501  const bool must_be_active) const
502 {
503  return tscrollbar_container_implementation::find_at<const twidget>(
504  *this, coordinate, must_be_active);
505 }
506 
508  const bool must_be_active)
509 {
510  return tscrollbar_container_implementation::find<twidget>(
511  *this, id, must_be_active);
512 }
513 
515  const bool must_be_active) const
516 {
517  return tscrollbar_container_implementation::find<const twidget>(
518  *this, id, must_be_active);
519 }
520 
522 {
523  assert(content_grid_);
526 }
527 
528 bool tscrollbar_container::content_resize_request(const bool force_sizing)
529 {
530  /**
531  * @todo Try to handle auto_visible_first_run here as well.
532  *
533  * Handling it here makes the code a bit more complex but allows to not
534  * reserve space for scrollbars, which will look nicer in the MP lobby.
535  * But the extra complexity is no 1.8 material.
536  */
537 
538  assert(content_ && content_grid_);
539 
542 
543  DBG_GUI_L << LOG_HEADER << " wanted size " << best_size
544  << " available size " << size << ".\n";
545 
546  if(size == tpoint(0, 0)) {
547  DBG_GUI_L << LOG_HEADER << " initial setup not done, bailing out.\n";
548  return false;
549  }
550 
551  if(best_size.x <= size.x && best_size.y <= size.y) {
552  const tpoint content_size = content_grid_->get_size();
553  if(content_size.x > size.x || content_size.y > size.y) {
554  DBG_GUI_L << LOG_HEADER << " will fit, only needs a resize.\n";
555  goto resize;
556  }
557  if(force_sizing) {
558  DBG_GUI_L << LOG_HEADER << " fits, but resize forced.\n";
559  goto resize;
560  }
561  DBG_GUI_L << LOG_HEADER << " fits, nothing to do.\n";
562  return true;
563  }
564 
565  if(best_size.x > size.x) {
566  DBG_GUI_L << LOG_HEADER << " content too wide.\n";
571 
572  DBG_GUI_L << LOG_HEADER
573  << " can't use horizontal scrollbar, ask window.\n";
574  twindow* window = get_window();
575  assert(window);
576  window->invalidate_layout();
577  return false;
578  }
579  }
580 
581  if(best_size.y > size.y) {
582  DBG_GUI_L << LOG_HEADER << " content too high.\n";
587 
588  DBG_GUI_L << LOG_HEADER
589  << " can't use vertical scrollbar, ask window.\n";
590  twindow* window = get_window();
591  assert(window);
592  window->invalidate_layout();
593  return false;
594  }
595  }
596 
597 resize:
598  DBG_GUI_L << LOG_HEADER << " handle resizing.\n";
599  place(get_origin(), get_size());
600  return true;
601 }
602 
603 bool tscrollbar_container::content_resize_request(const int width_modification,
604  const int height_modification,
605  const int width_modification_pos,
606  const int height_modification_pos)
607 {
608  DBG_GUI_L << LOG_HEADER << " wanted width modification "
609  << width_modification << " wanted height modification "
610  << height_modification << ".\n";
611 
612  if(get_size() == tpoint(0, 0)) {
613  DBG_GUI_L << LOG_HEADER << " initial setup not done, bailing out.\n";
614  return false;
615  }
616 
617  twindow* window = get_window();
618  assert(window);
619  if(window->get_need_layout()) {
621  << " window already needs a layout phase, bailing out.\n";
622  return false;
623  }
624 
625  assert(content_ && content_grid_);
626 
627  const bool result = content_resize_width(width_modification, width_modification_pos)
628  && content_resize_height(height_modification, height_modification_pos);
629  scrollbar_moved();
630  if(result) {
631  /*
632  * The subroutines set the new size of the scrollbar but don't
633  * update the button status.
634  */
636  }
637 
638  DBG_GUI_L << LOG_HEADER << " result " << result << ".\n";
639  return result;
640 }
641 
642 bool tscrollbar_container::content_resize_width(const int width_modification, const int width_modification_pos)
643 {
644  if(width_modification == 0) {
645  return true;
646  }
647 
648  const int new_width = content_grid_->get_width() + width_modification;
649  DBG_GUI_L << LOG_HEADER << " current width " << content_grid_->get_width()
650  << " wanted width " << new_width;
651 
652  assert(new_width > 0);
653 
654  if(static_cast<unsigned>(new_width) <= content_->get_width()) {
655  DBG_GUI_L << " width fits in container, test height.\n";
660  content_grid_->get_width() + width_modification,
661  width_modification_pos,
662  content_->get_width());
663  return true;
664  }
665 
671 
672  DBG_GUI_L << " can't use horizontal scrollbar, ask window.\n";
673  twindow* window = get_window();
674  assert(window);
675  window->invalidate_layout();
676  return false;
677  }
678 
679  DBG_GUI_L << " use the horizontal scrollbar, test height.\n";
684  content_grid_->get_width() + width_modification,
685  width_modification_pos,
686  content_->get_width());
687 
688  return true;
689 }
690 
691 bool tscrollbar_container::content_resize_height(const int height_modification, const int height_modification_pos)
692 {
693  if(height_modification == 0) {
694  return true;
695  }
696 
697  const int new_height = content_grid_->get_height() + height_modification;
698 
699  DBG_GUI_L << LOG_HEADER << " current height " << content_grid_->get_height()
700  << " wanted height " << new_height;
701 
702  assert(new_height > 0);
703 
704  if(static_cast<unsigned>(new_height) <= content_->get_height()) {
705  DBG_GUI_L << " height in container, resize allowed.\n";
710  new_height,
711  height_modification_pos,
712  content_->get_height());
713  return true;
714  }
715 
721 
722  DBG_GUI_L << " can't use vertical scrollbar, ask window.\n";
723  twindow* window = get_window();
724  assert(window);
725  window->invalidate_layout();
726  return false;
727  }
728 
729  DBG_GUI_L << " use the vertical scrollbar, resize allowed.\n";
734  new_height,
735  height_modification_pos,
736  content_->get_height());
737 
738  return true;
739 }
740 
742 {
743  /***** Setup vertical scrollbar *****/
744 
746  = find_widget<tgrid>(this, "_vertical_scrollbar_grid", false, true);
747 
748  vertical_scrollbar_ = find_widget<tscrollbar_>(
749  vertical_scrollbar_grid_, "_vertical_scrollbar", false, true);
750 
752  *vertical_scrollbar_,
754 
755  /***** Setup horizontal scrollbar *****/
756  horizontal_scrollbar_grid_ = find_widget<tgrid>(
757  this, "_horizontal_scrollbar_grid", false, true);
758 
759  horizontal_scrollbar_ = find_widget<tscrollbar_>(
760  horizontal_scrollbar_grid_, "_horizontal_scrollbar", false, true);
761 
763  *horizontal_scrollbar_,
765  this));
766 
767  /***** Setup the scrollbar buttons *****/
768  for(const auto & item : scroll_lookup())
769  {
770 
771  // Vertical.
772  tclickable_* button = find_widget<tclickable_>(
773  vertical_scrollbar_grid_, item.first, false, false);
774 
775  if(button) {
776  button->connect_click_handler(std::bind(
778  this,
779  item.second));
780  }
781 
782  // Horizontal.
783  button = find_widget<tclickable_>(
784  horizontal_scrollbar_grid_, item.first, false, false);
785 
786  if(button) {
787  button->connect_click_handler(std::bind(
789  this,
790  item.second));
791  }
792  }
793 
794  /***** Setup the content *****/
795  content_ = new tspacer();
796  content_->set_definition("default");
797 
798  content_grid_ = dynamic_cast<tgrid*>(
799  grid().swap_child("_content_grid", content_, true));
800  assert(content_grid_);
801 
802  content_grid_->set_parent(this);
803 
804  /***** Let our subclasses initialize themselves. *****/
806 }
807 
809  const tscrollbar_mode scrollbar_mode)
810 {
811  if(vertical_scrollbar_mode_ != scrollbar_mode) {
812  vertical_scrollbar_mode_ = scrollbar_mode;
813  }
814 }
815 
817  const tscrollbar_mode scrollbar_mode)
818 {
819  if(horizontal_scrollbar_mode_ != scrollbar_mode) {
820  horizontal_scrollbar_mode_ = scrollbar_mode;
821  }
822 }
823 
825  int x_offset,
826  int y_offset)
827 {
830 
831  // Inherited.
832  tcontainer_::impl_draw_children(frame_buffer, x_offset, y_offset);
833 
834  content_grid_->draw_children(frame_buffer, x_offset, y_offset);
835 }
836 
838 {
839  // Inherited.
841 
842  assert(content_grid_);
844 }
845 
847  twindow& caller, const std::vector<twidget*>& call_stack)
848 {
849  // Inherited.
850  tcontainer_::child_populate_dirty_list(caller, call_stack);
851 
852  assert(content_grid_);
853  std::vector<twidget*> child_call_stack(call_stack);
854  content_grid_->populate_dirty_list(caller, child_call_stack);
855 }
856 
858  const tpoint& size)
859 {
860  content_grid_->place(origin, size);
861 }
862 
863 void tscrollbar_container::show_content_rect(const SDL_Rect& rect)
864 {
865  assert(content_);
867 
868  // Set the bottom right location first if it doesn't fit the top left
869  // will look good. First calculate the left and top position depending on
870  // the current position.
871 
872  const int left_position = horizontal_scrollbar_->get_item_position()
873  + (rect.x - content_->get_x());
874  const int top_position = vertical_scrollbar_->get_item_position()
875  + (rect.y - content_->get_y());
876 
877  // bottom.
878  const int wanted_bottom = rect.y + rect.h;
879  const int current_bottom = content_->get_y() + content_->get_height();
880  int distance = wanted_bottom - current_bottom;
881  if(distance > 0) {
883  vertical_scrollbar_->get_item_position() + distance);
884  }
885 
886  // right.
887  const int wanted_right = rect.x + rect.w;
888  const int current_right = content_->get_x() + content_->get_width();
889  distance = wanted_right - current_right;
890  if(distance > 0) {
893  }
894 
895  // top.
896  if(top_position
897  < static_cast<int>(vertical_scrollbar_->get_item_position())) {
898 
899  vertical_scrollbar_->set_item_position(top_position);
900  }
901 
902  // left.
903  if(left_position
904  < static_cast<int>(horizontal_scrollbar_->get_item_position())) {
905 
907  }
908 
909  // Update.
910  scrollbar_moved();
911 }
912 
914 {
915  if(true) { /** @todo scrollbar visibility. */
916  /***** set scroll up button status *****/
917  for(const auto & name : button_up_names)
918  {
919  tcontrol* button = find_widget<tcontrol>(
920  vertical_scrollbar_grid_, name, false, false);
921 
922  if(button) {
924  }
925  }
926 
927  /***** set scroll down status *****/
928  for(const auto & name : button_down_names)
929  {
930  tcontrol* button = find_widget<tcontrol>(
931  vertical_scrollbar_grid_, name, false, false);
932 
933  if(button) {
935  }
936  }
937 
938  /***** Set the status if the scrollbars *****/
941  }
942 
943  if(true) { /** @todo scrollbar visibility. */
944  /***** Set scroll left button status *****/
945  for(const auto & name : button_up_names)
946  {
947  tcontrol* button = find_widget<tcontrol>(
948  horizontal_scrollbar_grid_, name, false, false);
949 
950  if(button) {
952  }
953  }
954 
955  /***** Set scroll right button status *****/
956  for(const auto & name : button_down_names)
957  {
958  tcontrol* button = find_widget<tcontrol>(
959  horizontal_scrollbar_grid_, name, false, false);
960 
961  if(button) {
963  }
964  }
965 
966  /***** Set the status if the scrollbars *****/
969  }
970 }
971 
973 {
974  assert(vertical_scrollbar_);
975 
976  return vertical_scrollbar_->at_end();
977 }
978 
980 {
981  assert(vertical_scrollbar_);
982 
984 }
985 
987  const unsigned position)
988 {
989  assert(vertical_scrollbar_);
990 
992  scrollbar_moved();
993 }
994 
996  const tscrollbar_::tscroll scroll)
997 {
998  assert(vertical_scrollbar_);
999 
1000  vertical_scrollbar_->scroll(scroll);
1001  scrollbar_moved();
1002 }
1003 
1005  const tscrollbar_::tscroll scroll)
1006 {
1007  assert(horizontal_scrollbar_);
1008 
1009  horizontal_scrollbar_->scroll(scroll);
1010  scrollbar_moved();
1011 }
1012 
1013 void tscrollbar_container::handle_key_home(SDLMod /*modifier*/, bool& handled)
1014 {
1016 
1019  scrollbar_moved();
1020 
1021  handled = true;
1022 }
1023 
1024 void tscrollbar_container::handle_key_end(SDLMod /*modifier*/, bool& handled)
1025 {
1026  assert(vertical_scrollbar_);
1027 
1029  scrollbar_moved();
1030 
1031  handled = true;
1032 }
1033 
1035  bool& handled)
1036 {
1037  assert(vertical_scrollbar_);
1038 
1040  scrollbar_moved();
1041 
1042  handled = true;
1043 }
1044 
1046  bool& handled)
1047 
1048 {
1049  assert(vertical_scrollbar_);
1050 
1052  scrollbar_moved();
1053 
1054  handled = true;
1055 }
1056 
1058  bool& handled)
1059 {
1060  assert(vertical_scrollbar_);
1061 
1063  scrollbar_moved();
1064 
1065  handled = true;
1066 }
1067 
1069  bool& handled)
1070 {
1071  assert(vertical_scrollbar_);
1072 
1074  scrollbar_moved();
1075 
1076  handled = true;
1077 }
1078 
1080  bool& handled)
1081 {
1082  assert(horizontal_scrollbar_);
1083 
1085  scrollbar_moved();
1086 
1087  handled = true;
1088 }
1089 
1091  bool& handled)
1092 {
1093  assert(horizontal_scrollbar_);
1094 
1096  scrollbar_moved();
1097 
1098  handled = true;
1099 }
1100 
1102 {
1103  // Init.
1104  assert(content_ && content_grid_);
1106 
1107  /*** Update the content location. ***/
1108  const int x_offset = horizontal_scrollbar_mode_ == always_invisible
1109  ? 0
1112 
1113  const int y_offset = vertical_scrollbar_mode_ == always_invisible
1114  ? 0
1117 
1118  const tpoint content_origin = tpoint(content_->get_x() - x_offset,
1119  content_->get_y() - y_offset);
1120 
1121  content_grid_->set_origin(content_origin);
1123  content_grid_->set_is_dirty(true);
1124 
1125  // Update scrollbar.
1127 }
1128 
1130 {
1131  static const std::string type = "scrollbar_container";
1132  return type;
1133 }
1134 
1135 void
1137  bool& handled,
1138  const SDLKey key,
1139  SDLMod modifier)
1140 {
1141  DBG_GUI_E << LOG_HEADER << event << ".\n";
1142 
1143  switch(key) {
1144  case SDLK_HOME:
1145  handle_key_home(modifier, handled);
1146  break;
1147 
1148  case SDLK_END:
1149  handle_key_end(modifier, handled);
1150  break;
1151 
1152 
1153  case SDLK_PAGEUP:
1154  handle_key_page_up(modifier, handled);
1155  break;
1156 
1157  case SDLK_PAGEDOWN:
1158  handle_key_page_down(modifier, handled);
1159  break;
1160 
1161 
1162  case SDLK_UP:
1163  handle_key_up_arrow(modifier, handled);
1164  break;
1165 
1166  case SDLK_DOWN:
1167  handle_key_down_arrow(modifier, handled);
1168  break;
1169 
1170  case SDLK_LEFT:
1171  handle_key_left_arrow(modifier, handled);
1172  break;
1173 
1174  case SDLK_RIGHT:
1175  handle_key_right_arrow(modifier, handled);
1176  break;
1177  default:
1178  /* ignore */
1179  break;
1180  }
1181 }
1182 
1183 void
1185  bool& handled)
1186 {
1187  DBG_GUI_E << LOG_HEADER << event << ".\n";
1188 
1190 
1193  scrollbar_moved();
1194  handled = true;
1195  }
1196 }
1197 
1198 void
1200  bool& handled)
1201 {
1202  DBG_GUI_E << LOG_HEADER << event << ".\n";
1203 
1205 
1208  scrollbar_moved();
1209  handled = true;
1210  }
1211 }
1212 
1213 void
1215  bool& handled)
1216 {
1217  DBG_GUI_E << LOG_HEADER << event << ".\n";
1218 
1220 
1224  scrollbar_moved();
1225  handled = true;
1226  }
1227 }
1228 
1229 void
1231  bool& handled)
1232 {
1233  DBG_GUI_E << LOG_HEADER << event << ".\n";
1234 
1236 
1240  scrollbar_moved();
1241  handled = true;
1242  }
1243 }
1244 
1245 } // namespace gui2
Define the common log macros for the gui toolkit.
Like auto_visible, but when not needed upon the initial layout phase, the bars are not shown and no s...
void set_vertical_scrollbar_item_position(const unsigned position)
Move the vertical scrollbar to a position.
unsigned get_width() const
Definition: widget.cpp:294
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See twidget::set_visible_rectangle.
virtual void layout_initialise(const bool full_initialisation) override
See twidget::layout_initialise.
Definition: container.cpp:33
SDL_Rect intersect_rects(SDL_Rect const &rect1, SDL_Rect const &rect2)
Calculates the intersection of two rectangles.
Definition: rect.cpp:58
Defines the exception classes for the layout algorithm.
virtual void request_reduce_height(const unsigned maximum_height) override
See twidget::request_reduce_height.
void set_item_count(const unsigned item_count)
Definition: scrollbar.hpp:116
twidget * find(const std::string &id, const bool must_be_active) override
See twidget::find.
#define SDLMod
Definition: compat.hpp:30
Go the visibile items towards the begin.
Definition: scrollbar.hpp:60
const tgrid & grid() const
Definition: container.hpp:229
#define DBG_GUI_L
Definition: log.hpp:58
tspacer * content_
Dummy spacer to hold the contents location.
void set_parent(twidget *parent)
Definition: widget.cpp:150
virtual bool get_active() const override
See tcontrol::get_active.
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See twidget::set_visible_rectangle.
Definition: container.cpp:132
virtual void layout_initialise(const bool full_initialisation) override
See twidget::layout_initialise.
virtual void layout_children() override
See twidget::layout_children.
Definition: grid.cpp:575
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
virtual const std::string & get_control_type() const override
See tcontrol::get_control_type.
virtual void impl_draw_children(surface &frame_buffer, int x_offset, int y_offset) override
See twidget::impl_draw_children.
Definition: container.cpp:140
virtual void child_populate_dirty_list(twindow &caller, const std::vector< twidget * > &call_stack) override
See twidget::child_populate_dirty_list.
void connect_signal_notify_modified(tdispatcher &dispatcher, const tsignal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.hpp:725
Base container class.
Definition: grid.hpp:29
virtual void handle_key_end(SDLMod modifier, bool &handled)
End key pressed.
This file contains the window object, this object is a top level container which has the event manage...
tvisible::scoped_enum get_visible() const
Definition: widget.cpp:471
static void adjust_scrollbar_mode(tgrid *scrollbar_grid, tscrollbar_ *scrollbar, tscrollbar_container::tscrollbar_mode &scrollbar_mode, const unsigned items_before, const unsigned items_after, const int insertion_pos, const unsigned visible_items)
void scroll_vertical_scrollbar(const tscrollbar_::tscroll scroll)
Scrolls the vertical scrollbar.
#define LOG_SCOPE_HEADER
tpoint get_size() const
Returns the size of the widget.
Definition: widget.cpp:274
lg::log_domain log_gui_layout("gui/layout")
Definition: log.hpp:57
Go to the end position.
Definition: scrollbar.hpp:61
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Definition: grid.cpp:435
virtual twidget * find_at(const tpoint &coordinate, const bool must_be_active) override
See twidget::find_at.
tpoint recalculate_best_size()
Recalculates the best size.
Definition: grid.cpp:371
bool disable_click_dismiss() const override
See twidget::disable_click_dismiss.
Definition: grid.cpp:638
Base class for a scroll bar.
Definition: scrollbar.hpp:41
int get_y() const
Definition: widget.cpp:289
const std::vector< std::string > items
void scroll_horizontal_scrollbar(const tscrollbar_::tscroll scroll)
Scrolls the horizontal scrollbar.
void signal_handler_sdl_key_down(const event::tevent event, bool &handled, const SDLKey key, SDLMod modifier)
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
Definition: grid.cpp:542
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
Definition: container.cpp:122
Go one item towards the begin.
Definition: scrollbar.hpp:57
static bool is_inserted_before(unsigned insertion_pos, unsigned old_item_count, unsigned old_position, unsigned visible_items)
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:435
virtual void set_origin(const tpoint &origin) override
See twidget::set_origin.
virtual bool can_wrap() const override
See twidget::can_wrap.
unsigned get_vertical_scrollbar_item_position() const
Returns current position of the vertical scrollbar.
tpoint get_best_size() const
Gets the best size for the widget.
Definition: widget.cpp:188
#define SDLKey
Definition: compat.hpp:29
bool all_items_visible() const
Are all items visible?
Definition: scrollbar.hpp:93
virtual void set_active(const bool active) override
See tcontrol::set_active.
Definition: scrollbar.cpp:110
The scrollbar is never shown even not when needed.
unsigned get_item_count() const
Definition: scrollbar.hpp:121
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
virtual void impl_draw_children(surface &frame_buffer, int x_offset, int y_offset) override
See twidget::impl_draw_children.
virtual void handle_key_home(SDLMod modifier, bool &handled)
Home key pressed.
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
GLintptr offset
Definition: glew.h:1650
tscrollbar_ * vertical_scrollbar_
These are valid after finalize_setup().
The user set the widget invisible, that means:
Definition: widget.hpp:103
void signal_handler_sdl_wheel_up(const event::tevent event, bool &handled)
virtual void handle_key_down_arrow(SDLMod modifier, bool &handled)
Down arrow key pressed.
tgrid * vertical_scrollbar_grid_
These are valid after finalize_setup().
bool content_resize_request(const bool force_sizing=false)
Notification if the content of a child needs a resize.
virtual void request_reduce_height(const unsigned maximum_height) override
See twidget::request_reduce_height.
Definition: grid.cpp:313
virtual void set_active(const bool active)=0
Sets the control's state.
#define LOG_HEADER
GLuint64EXT * result
Definition: glew.h:10727
bool disable_click_dismiss() const override
See twidget::disable_click_dismiss.
Definition: container.cpp:203
void set_vertical_scrollbar_mode(const tscrollbar_mode scrollbar_mode)
SDL_Rect content_visible_area_
Cache for the visible area for the content.
void set_scrollbar_button_status()
Sets the status of the scrollbar buttons.
virtual tpoint calculate_best_size() const override
See twidget::calculate_best_size.
int y
y coordinate.
Definition: point.hpp:34
void set_layout_size(const tpoint &size)
Definition: widget.cpp:304
unsigned get_item_position() const
Definition: scrollbar.hpp:131
void populate_dirty_list(twindow &caller, std::vector< twidget * > &call_stack)
Adds a widget to the dirty list if it is dirty.
Definition: widget.cpp:386
tscrollbar_container(const unsigned canvas_count)
virtual void request_reduce_width(const unsigned maximum_width) override
See twidget::request_reduce_width.
bool disable_click_dismiss() const override
See twidget::disable_click_dismiss.
An empty widget.
Definition: spacer.hpp:38
void signal_handler_sdl_wheel_down(const event::tevent event, bool &handled)
void draw_children(surface &frame_buffer, int x_offset, int y_offset)
Draws the children of a widget.
Definition: widget.cpp:356
void show_content_rect(const SDL_Rect &rect)
Shows a certain part of the content.
The user sets the widget hidden, that means:
Definition: widget.hpp:91
virtual void request_reduce_width(const unsigned maximum_width) override
See twidget::request_reduce_width.
Definition: grid.cpp:237
int get_x() const
Definition: widget.cpp:284
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Definition: container.cpp:76
#define log_scope2(domain, description)
Definition: log.hpp:186
tscrollbar_mode
The way to handle the showing or hiding of the scrollbar.
Exception thrown when the width has been modified during resizing.
bool content_resize_width(const int width_modification, const int width_modification_pos)
Helper for content_resize_request.
tevent
The event send to the dispatcher.
Definition: handler.hpp:54
virtual void connect_click_handler(const event::tsignal_function &signal)=0
Connects a signal handler for a 'click' event.
Go half the visible items towards the begin.
Definition: scrollbar.hpp:58
void finalize_setup()
The builder needs to call us so we do our setup.
int x
x coordinate.
Definition: point.hpp:31
virtual void set_visible_rectangle(const SDL_Rect &rectangle) override
See twidget::set_visible_rectangle.
Definition: grid.cpp:560
virtual void layout_children() override
See twidget::layout_children.
Definition: container.cpp:150
Small concept class.
Definition: clickable.hpp:39
The user sets the widget visible, that means:
Definition: widget.hpp:79
tgrid * content_grid_
The grid that holds the content.
virtual void set_content_size(const tpoint &origin, const tpoint &size)
Sets the size of the content grid.
void signal_handler_sdl_wheel_left(const event::tevent event, bool &handled)
virtual void child_populate_dirty_list(twindow &caller, const std::vector< twidget * > &call_stack) override
See twidget::child_populate_dirty_list.
Definition: container.cpp:156
#define DBG_GUI_E
Definition: log.hpp:35
void set_visible_items(const unsigned visible_items)
Definition: scrollbar.hpp:140
tpoint get_origin() const
Returns the screen origin of the widget.
Definition: widget.cpp:269
bool at_end() const
Is the positioner at the and of the scrollbar?
Definition: scrollbar.hpp:87
bool get_need_layout() const
Definition: window.hpp:444
tscrollbar_mode vertical_scrollbar_mode_
The mode of how to show the scrollbar.
virtual bool can_wrap() const override
See twidget::can_wrap.
Definition: grid.cpp:422
unsigned get_height() const
Definition: widget.cpp:299
const std::string & id() const
Definition: widget.cpp:109
twidget * swap_child(const std::string &id, twidget *widget, const bool recurse, twidget *new_parent=nullptr)
Exchanges a child in the grid.
Definition: grid.cpp:99
Holds a 2D point.
Definition: point.hpp:24
void set_horizontal_scrollbar_mode(const tscrollbar_mode scrollbar_mode)
virtual void layout_children() override
See twidget::layout_children.
Go to begin position.
Definition: scrollbar.hpp:56
The scrollbar is always shown, whether needed or not.
bool content_resize_height(const int height_modification, const int width_modification_pos)
Helper for content_resize_request.
virtual void handle_key_up_arrow(SDLMod modifier, bool &handled)
Up arrow key pressed.
Helper for header for the scrollbar_container.
virtual void handle_key_right_arrow(SDLMod modifier, bool &handled)
Right arrow key pressed.
tscrollbar_mode horizontal_scrollbar_mode_
Base class for all visible items.
Definition: control.hpp:34
GLuint const GLchar * name
Definition: glew.h:1782
A generic container base class.
Definition: container.hpp:32
GLsizeiptr size
Definition: glew.h:1649
void signal_handler_sdl_wheel_right(const event::tevent event, bool &handled)
virtual void place(const tpoint &origin, const tpoint &size) override
See twidget::place.
Contains the SDL_Rect helper code.
void scroll(const tscroll scroll)
Sets the item position.
Definition: scrollbar.cpp:54
static void set_scrollbar_mode(tgrid *scrollbar_grid, tscrollbar_ *scrollbar, tscrollbar_container::tscrollbar_mode &scrollbar_mode, const unsigned items, const unsigned visible_items)
cl_event event
Definition: glew.h:3070
Base class for all widgets.
Definition: widget.hpp:49
void set_item_position(const unsigned item_position)
Note the position isn't guaranteed to be the wanted position the step size is honored.
Definition: scrollbar.cpp:127
virtual unsigned get_state() const override
See tcontrol::get_state.
void scrollbar_moved()
Helper function which needs to be called after the scollbar moved.
virtual void layout_initialise(const bool full_initialisation) override
See twidget::layout_initialise.
Definition: grid.cpp:191
The scrollbar is shown when the number of items is larger as the visible items.
bool at_begin() const
Is the positioner at the beginning of the scrollbar?
Definition: scrollbar.hpp:77
void set_definition(const std::string &definition)
Sets the definition.
Definition: control.cpp:318
Go one item towards the end.
Definition: scrollbar.hpp:62
twindow * get_window()
Get the parent window.
Definition: widget.cpp:116
void vertical_scrollbar_moved()
Callback when the scrollbar moves (NOTE maybe only one callback needed).
SDL_Rect get_rectangle() const
Gets the bounding rectangle of the widget on the screen.
Definition: widget.cpp:279
unsigned get_step_size() const
Definition: scrollbar.hpp:146
void set_visible(const tvisible::scoped_enum visible)
Definition: widget.cpp:445
virtual void handle_key_left_arrow(SDLMod modifier, bool &handled)
Left arrow key pressed.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
tstate state_
Current state of the widget.
Go half the visible items towards the end.
Definition: scrollbar.hpp:63
virtual void finalize_subclass()
Function for the subclasses to do their setup.
void invalidate_layout()
Updates the size of the window.
Definition: window.cpp:941
virtual void handle_key_page_up(SDLMod modifier, bool &handled)
Page up key pressed.
virtual void handle_key_page_down(SDLMod modifier, bool &handled)
Page down key pressed.
tscroll
scroll 'step size'.
Definition: scrollbar.hpp:55