neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
scrollable_widget.ipp
Go to the documentation of this file.
1// scrollable_widget.inl
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2015, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <neogfx/neogfx.hpp>
24
25namespace neogfx
26{
27 template <typename Base>
29 {
30 service<i_scrollbar_container_updater>().unqueue(*this);
31 }
32
33 template <typename Base>
35 {
36 return iScrollbarStyle;
37 }
38
39 template <typename Base>
41 {
42 return units_converter{ *this }.from_device_units(point(static_cast<coordinate>(horizontal_scrollbar().position()), static_cast<coordinate>(vertical_scrollbar().position())));
43 }
44
45 template <typename Base>
47 {
48 (void)aChild;
49 /* todo */
50 }
51
52 template <typename Base>
54 {
55 base_type::layout_items_started();
56 }
57
58 template <typename Base>
60 {
61 base_type::layout_items_completed();
62 if (!base_type::as_widget().layout_items_in_progress() && !iIgnoreScrollbarUpdates && !iMovingWidgets)
63 {
64 scoped_property_transition_suppression sts1{ iVerticalScrollbar.Position };
65 scoped_property_transition_suppression sts2{ iHorizontalScrollbar.Position };
66 update_scrollbar_visibility();
67 }
68 }
69
70 template <typename Base>
72 {
73 base_type::resized();
74 if (!base_type::as_widget().layout_items_in_progress() && !iIgnoreScrollbarUpdates)
75 {
76 scoped_property_transition_suppression sts1{ iVerticalScrollbar.Position };
77 scoped_property_transition_suppression sts2{ iHorizontalScrollbar.Position };
78 update_scrollbar_visibility();
79 }
80 }
81
82 template <typename Base>
83 rect scrollable_widget<Base>::client_rect(bool aExtendIntoPadding) const
84 {
85 rect result = base_type::client_rect(aExtendIntoPadding);
86 if (vertical_scrollbar().visible())
87 {
88 if (vertical_scrollbar().type() == scrollbar_style::Normal)
89 result.cx -= vertical_scrollbar().width();
90 else if (vertical_scrollbar().type() == scrollbar_style::Menu)
91 {
92 result.y += vertical_scrollbar().width();
93 result.cy -= vertical_scrollbar().width() * 2.0;
94 }
95 else if (vertical_scrollbar().type() == scrollbar_style::Scroller)
96 result.cy -= vertical_scrollbar().width() * 2.0;
97 }
98 if (horizontal_scrollbar().visible())
99 {
100 if (horizontal_scrollbar().type() == scrollbar_style::Normal)
101 result.cy -= horizontal_scrollbar().width();
102 else if (vertical_scrollbar().type() == scrollbar_style::Menu)
103 {
104 result.x += horizontal_scrollbar().width();
105 result.cx -= horizontal_scrollbar().width() * 2.0;
106 }
107 else if (vertical_scrollbar().type() == scrollbar_style::Scroller)
108 result.cx -= horizontal_scrollbar().width() * 2.0;
109 }
110 return result;
111 }
112
113 template <typename Base>
115 {
116 if (vertical_scrollbar().visible() &&
117 ((vertical_scrollbar().element_at(aPosition) != scrollbar_element::None) ||
118 (vertical_scrollbar().type() == scrollbar_style::Normal && scrollbar_geometry(vertical_scrollbar()).contains(aPosition))))
120 else if (horizontal_scrollbar().visible() &&
121 ((horizontal_scrollbar().element_at(aPosition) != scrollbar_element::None) ||
122 (horizontal_scrollbar().type() == scrollbar_style::Normal && scrollbar_geometry(horizontal_scrollbar()).contains(aPosition))))
124 else
125 return base_type::part(aPosition);
126 }
128 template <typename Base>
131 base_type::paint_non_client_after(aGc);
132 if (vertical_scrollbar().visible() && !vertical_scrollbar().auto_hidden())
133 vertical_scrollbar().render(aGc);
134 if (horizontal_scrollbar().visible() && !horizontal_scrollbar().auto_hidden())
135 horizontal_scrollbar().render(aGc);
136 if (vertical_scrollbar().visible() && horizontal_scrollbar().visible() &&
137 !vertical_scrollbar().auto_hidden() && !horizontal_scrollbar().auto_hidden() &&
138 vertical_scrollbar().type() == horizontal_scrollbar().type() && vertical_scrollbar().type() == scrollbar_style::Normal)
140 auto const spareSquare = rect{
141 point{ scrollbar_geometry(horizontal_scrollbar()).right(), scrollbar_geometry(vertical_scrollbar()).bottom() },
142 size{ scrollbar_geometry(vertical_scrollbar()).width(), scrollbar_geometry(horizontal_scrollbar()).height() } };
143 aGc.fill_rect(spareSquare, scrollbar_color(vertical_scrollbar()));
146
147 template <typename Base>
148 bool scrollable_widget<Base>::mouse_wheel_scrolled(mouse_wheel aWheel, const point& aPosition, delta aDelta, key_modifiers_e aKeyModifiers)
150 scoped_property_transition_suppression sts1{ iVerticalScrollbar.Position };
151 scoped_property_transition_suppression sts2{ iHorizontalScrollbar.Position };
152 bool handledVertical = false;
153 bool handledHorizontal = false;
155 mouse_wheel horizontalSense = mouse_wheel::Horizontal;
156 if (service<i_keyboard>().is_key_pressed(ScanCode_LSHIFT) || service<i_keyboard>().is_key_pressed(ScanCode_RSHIFT))
157 std::swap(verticalSense, horizontalSense);
158 auto const maxSteps = 6.0; // todo: configurable
159 auto const maxDeltaY = std::max(vertical_scrollbar().page() - vertical_scrollbar().step(), vertical_scrollbar().step());
160 auto const maxDeltaX = std::max(horizontal_scrollbar().page() - horizontal_scrollbar().step(), horizontal_scrollbar().step());
161 if ((aWheel & verticalSense) != mouse_wheel::None && vertical_scrollbar().visible())
162 handledVertical = vertical_scrollbar().set_position(
163 vertical_scrollbar().position() +
164 std::min(std::max(((verticalSense == mouse_wheel::Vertical ? aDelta.dy : aDelta.dx) >= 0.0 ? -maxSteps : maxSteps) * vertical_scrollbar().step(), -maxDeltaY), maxDeltaY));
165 if ((aWheel & horizontalSense) != mouse_wheel::None && horizontal_scrollbar().visible())
166 handledHorizontal = horizontal_scrollbar().set_position(
167 horizontal_scrollbar().position() +
168 std::min(std::max(((horizontalSense == mouse_wheel::Horizontal ? aDelta.dx : aDelta.dx) >= 0.0 ? -maxSteps : maxSteps) * horizontal_scrollbar().step(), -maxDeltaX), maxDeltaX));
169 mouse_wheel passOn = static_cast<mouse_wheel>(
170 aWheel & ((handledVertical ? ~verticalSense : verticalSense) | (handledHorizontal ? ~horizontalSense : horizontalSense)));
171 if (passOn != mouse_wheel::None)
172 return base_type::mouse_wheel_scrolled(passOn, aPosition, aDelta, aKeyModifiers);
173 else
174 return true;
175 }
176
177 template <typename Base>
179 {
180 if (aButton == mouse_button::Middle)
181 {
182 bool handled = false;
183 if (vertical_scrollbar().visible())
184 {
185 vertical_scrollbar().track();
186 handled = true;
187 }
188 if (horizontal_scrollbar().visible())
189 {
190 horizontal_scrollbar().track();
191 handled = true;
192 }
193 if (handled)
194 base_type::as_widget().set_capture();
195 else
196 base_type::mouse_button_pressed(aButton, aPosition, aKeyModifiers);
197 }
198 else
199 {
200 base_type::mouse_button_pressed(aButton, aPosition, aKeyModifiers);
201 if (aButton == mouse_button::Left)
202 {
203 if (vertical_scrollbar().clicked_element() == scrollbar_element::None && horizontal_scrollbar().clicked_element() == scrollbar_element::None)
204 {
205 if (vertical_scrollbar().visible() && vertical_scrollbar().element_at(aPosition) != scrollbar_element::None)
206 {
207 base_type::as_widget().update(true);
208 vertical_scrollbar().click_element(vertical_scrollbar().element_at(aPosition));
209 }
210 else if (horizontal_scrollbar().visible() && horizontal_scrollbar().element_at(aPosition) != scrollbar_element::None)
211 {
212 base_type::as_widget().update(true);
213 horizontal_scrollbar().click_element(horizontal_scrollbar().element_at(aPosition));
214 }
215 }
216 }
217 }
218 }
219
220 template <typename Base>
222 {
223 base_type::mouse_button_double_clicked(aButton, aPosition, aKeyModifiers);
224 if (aButton == mouse_button::Left)
225 {
226 if (vertical_scrollbar().clicked_element() == scrollbar_element::None && horizontal_scrollbar().clicked_element() == scrollbar_element::None)
227 {
228 if (vertical_scrollbar().visible() && vertical_scrollbar().element_at(aPosition) != scrollbar_element::None)
229 {
230 base_type::as_widget().update(true);
231 vertical_scrollbar().click_element(vertical_scrollbar().element_at(aPosition));
232 }
233 else if (horizontal_scrollbar().visible() && horizontal_scrollbar().element_at(aPosition) != scrollbar_element::None)
234 {
235 base_type::as_widget().update(true);
236 horizontal_scrollbar().click_element(horizontal_scrollbar().element_at(aPosition));
237 }
238 }
239 }
240 }
241
242 template <typename Base>
244 {
245 base_type::mouse_button_released(aButton, aPosition);
246 if (aButton == mouse_button::Left)
247 {
248 if (vertical_scrollbar().clicked_element() != scrollbar_element::None)
249 {
250 base_type::as_widget().update(true);
251 vertical_scrollbar().unclick_element();
252 }
253 else if (horizontal_scrollbar().clicked_element() != scrollbar_element::None)
254 {
255 base_type::as_widget().update(true);
256 horizontal_scrollbar().unclick_element();
257 }
258 }
259 else if (aButton == mouse_button::Middle)
260 {
261 vertical_scrollbar().untrack();
262 horizontal_scrollbar().untrack();
263 }
264 }
265
266 template <typename Base>
267 void scrollable_widget<Base>::mouse_moved(const point& aPosition, key_modifiers_e aKeyModifiers)
268 {
269 base_type::mouse_moved(aPosition, aKeyModifiers);
270 vertical_scrollbar().update(aPosition);
271 horizontal_scrollbar().update(aPosition);
272 }
273
274 template <typename Base>
276 {
277 base_type::mouse_entered(aPosition);
278 vertical_scrollbar().update();
279 horizontal_scrollbar().update();
280 }
281
282 template <typename Base>
284 {
285 base_type::mouse_left();
286 vertical_scrollbar().update();
287 horizontal_scrollbar().update();
288 }
289
290 template <typename Base>
292 {
293 bool handled = true;
294 switch (aScanCode)
295 {
296 case ScanCode_LEFT:
297 horizontal_scrollbar().set_position(horizontal_scrollbar().position() - horizontal_scrollbar().step());
298 break;
299 case ScanCode_RIGHT:
300 horizontal_scrollbar().set_position(horizontal_scrollbar().position() + horizontal_scrollbar().step());
301 break;
302 case ScanCode_UP:
303 vertical_scrollbar().set_position(vertical_scrollbar().position() - vertical_scrollbar().step());
304 break;
305 case ScanCode_DOWN:
306 vertical_scrollbar().set_position(vertical_scrollbar().position() + vertical_scrollbar().step());
307 break;
308 case ScanCode_PAGEUP:
309 vertical_scrollbar().set_position(vertical_scrollbar().position() - vertical_scrollbar().page());
310 break;
312 vertical_scrollbar().set_position(vertical_scrollbar().position() + vertical_scrollbar().page());
313 break;
314 case ScanCode_HOME:
315 if (horizontal_scrollbar().visible() && !(aKeyModifiers & KeyModifier_CTRL))
316 horizontal_scrollbar().set_position(horizontal_scrollbar().minimum());
317 else
318 vertical_scrollbar().set_position(vertical_scrollbar().minimum());
319 break;
320 case ScanCode_END:
321 if (horizontal_scrollbar().visible() && !(aKeyModifiers & KeyModifier_CTRL))
322 horizontal_scrollbar().set_position(horizontal_scrollbar().maximum());
323 else
324 vertical_scrollbar().set_position(vertical_scrollbar().maximum());
325 break;
326 default:
327 handled = base_type::key_pressed(aScanCode, aKeyCode, aKeyModifiers);
328 break;
329 }
330 return handled;
331 }
332
333 template <typename Base>
335 {
336 return iVerticalScrollbar;
337 }
338
339 template <typename Base>
341 {
342 return iVerticalScrollbar;
343 }
344
345 template <typename Base>
347 {
348 return iHorizontalScrollbar;
349 }
350
351 template <typename Base>
353 {
354 return iHorizontalScrollbar;
355 }
356
357 template <typename Base>
359 {
360 if (base_type::device_metrics_available())
361 {
362 vertical_scrollbar().set_step(std::ceil(1.0_cm));
363 horizontal_scrollbar().set_step(std::ceil(1.0_cm));
364 }
365 }
366
367 template <typename Base>
369 {
370 auto async_update = [&]()
371 {
372 if (!iScrollbarUpdater && !iSuppressScrollbarVisibilityUpdates)
373 iScrollbarUpdater.emplace(*this, [this](widget_timer&)
374 {
375 update_scrollbar_visibility();
376 }, std::chrono::seconds{});
377 };
378 iSink += base_type::ChildAdded([&, async_update](i_widget& aWidget)
379 {
380 async_update();
381 });
382 iSink += base_type::ChildRemoved([&, async_update](i_widget& aWidget)
383 {
384 async_update();
385 });
386 init_scrollbars();
387 }
388
389 template <typename Base>
394
395 template <typename Base>
400
401 template <typename Base>
403 {
404 scoped_units su{ *this, units::Pixels };
405
406 auto const cr = client_rect();
407
408 rect result = cr;
409
410 if (iUpdatingScrollbarVisibility)
411 {
412 auto& self = base_type::as_widget();
413
414 optional_point min;
415 optional_point max;
416
417 for (auto& c : self.children())
418 {
419 if (c->hidden() || c->extents().cx == 0.0 || c->extents().cy == 0.0)
420 continue;
421 if (!min)
422 min.emplace(std::numeric_limits<scalar>::infinity(), std::numeric_limits<scalar>::infinity());
423 if (!max)
424 max.emplace(-std::numeric_limits<scalar>::infinity(), -std::numeric_limits<scalar>::infinity());
425 point const childTopLeftPos{ point{ units_converter{ *c }.to_device_units(c->position()) } };
426 point const childBottomRightPos{ point{ units_converter{ *c }.to_device_units(c->position() + units_converter{ *c }.to_device_units(c->extents())) - point{ 1.0, 1.0 } } };
428 {
429 min->x = std::min(min->x, childTopLeftPos.x);
430 max->x = std::max(max->x, childBottomRightPos.x);
431 }
433 {
434 min->y = std::min(min->y, childTopLeftPos.y);
435 max->y = std::max(max->y, childBottomRightPos.y);
436 }
437 }
438
439 if (!min)
440 min = cr.top_left();
441 if (!max)
442 max = cr.top_left();
443
444 if (self.has_layout())
445 {
446 auto const& ourLayout = self.layout();
448 max->x += ourLayout.internal_spacing().right;
450 max->y += ourLayout.internal_spacing().bottom;
451 }
452
453 if (max->x > cr.right() - 1.0 - self.internal_spacing().right)
454 max->x += self.internal_spacing().right;
455 if (max->y > cr.bottom() - 1.0 - self.internal_spacing().bottom)
456 max->y += self.internal_spacing().bottom;
457
458 min = min->min(cr.top_left());
459 max = max->max(cr.bottom_right()) - point{ 1.0, 1.0 };
460
461 result = rect{ *min, *max };
462 }
463 else
464 {
465 if (horizontal_scrollbar().visible())
466 {
467 result.x = horizontal_scrollbar().minimum();
468 result.cx = horizontal_scrollbar().maximum() - result.x;
469 }
470 if (vertical_scrollbar().visible())
471 {
472 result.y = vertical_scrollbar().minimum();
473 result.cy = vertical_scrollbar().maximum() - result.y;
474 }
475 }
476
477 return to_units(*this, su.saved_units(), result);
478 }
479 template <typename Base>
481 {
482 return client_rect().extents();
483 }
484
485 template <typename Base>
487 {
488 auto const sbrect = client_rect();
489 switch (aScrollbar.orientation())
490 {
492 if (aScrollbar.type() == scrollbar_style::Normal)
493 return rect{ sbrect.top_right(), size{ aScrollbar.width(), sbrect.cy } };
494 else if (aScrollbar.type() == scrollbar_style::Scroller)
495 return rect{ sbrect.bottom_left(), size{ sbrect.width(), aScrollbar.width() * 2.0 } };
496 else if (aScrollbar.type() == scrollbar_style::Menu)
497 return sbrect + point{ 0.0, -aScrollbar.width() } + size{ 0.0, aScrollbar.width() * 2.0 };
498 return rect{};
500 if (aScrollbar.type() == scrollbar_style::Normal)
501 return rect{ sbrect.bottom_left(), size{ sbrect.cx , aScrollbar.width() } };
502 else if (aScrollbar.type() == scrollbar_style::Scroller)
503 return rect{ sbrect.top_right(), size{ aScrollbar.width() * 2.0, sbrect.height() } };
504 else if (aScrollbar.type() == scrollbar_style::Menu)
505 return sbrect + point{ -aScrollbar.width(), 0.0 } + size{ aScrollbar.width() * 2.0, 0.0 };
506 return rect{};
507 default:
508 return rect{};
509 }
510 }
511
512 template <typename Base>
514 {
515 if (!iIgnoreScrollbarUpdates)
516 {
517 point scrollPosition = scroll_position();
518 if (iOldScrollPosition != scrollPosition)
519 {
520 neolib::scoped_flag sf{ iMovingWidgets };
521 for (auto& c : base_type::as_widget().children())
522 {
523 point delta = -(scrollPosition - iOldScrollPosition);
525 delta.y = 0.0;
527 delta.x = 0.0;
528 c->move(c->position() + delta);
529 }
531 {
532 iOldScrollPosition.y = scrollPosition.y;
533 }
534 else if (aScrollbar.orientation() == scrollbar_orientation::Horizontal)
535 {
536 iOldScrollPosition.x = scrollPosition.x;
537 }
538 }
539 }
540 base_type::as_widget().update(true);
541 }
542
543 template <typename Base>
545 {
546 return base_type::as_widget().palette_color(color_role::Foreground);
547 }
548
549 template <typename Base>
551 {
552 return *this;
553 }
554
555 template <typename Base>
557 {
558 return *this;
559 }
560
561 template <typename Base>
563 {
564 return true;
565 }
566
567 template <typename Base>
569 {
570 if (!base_type::device_metrics_available())
571 return;
572
573 if (iUpdatingScrollbarVisibility)
574 return;
575
576#ifdef NEOGFX_DEBUG
577 if (debug::layoutItem == this)
578 service<debug::logger>() << neolib::logger::severity::Debug << "widget:layout_items: update_scrollbar_visibility..." << endl;
579#endif
580
581 neolib::scoped_flag sf{ iUpdatingScrollbarVisibility };
582
583 scoped_units su{ *this, units::Pixels };
584
585 if (use_scrollbar_container_updater())
586 {
587 auto& updater = service<i_scrollbar_container_updater>();
588 if (!updater.processing())
589 {
590 neolib::scoped_counter<uint32_t> sc(iIgnoreScrollbarUpdates);
591 update_scrollbar_visibility(UsvStageInit);
592 updater.queue(*this);
593 return;
594 }
595 else if (&updater.current() != this)
596 {
597 return;
598 }
599 }
600
601 iScrollbarUpdater = {};
603 vertical_scrollbar().lock(0.0);
605 horizontal_scrollbar().lock(0.0);
606 {
607 neolib::scoped_counter<uint32_t> sc(iIgnoreScrollbarUpdates);
608 update_scrollbar_visibility(UsvStageInit);
609 auto const& cr = base_type::as_widget().client_rect();
610 if (cr.cx > vertical_scrollbar().width() &&
611 cr.cy > horizontal_scrollbar().width())
612 {
613 update_scrollbar_visibility(UsvStageCheckVertical1);
614 update_scrollbar_visibility(UsvStageCheckHorizontal);
615 update_scrollbar_visibility(UsvStageCheckVertical2);
616 }
617 update_scrollbar_visibility(UsvStageDone);
618 }
620 vertical_scrollbar().unlock();
622 horizontal_scrollbar().unlock();
623
624 scrollbar_updated(vertical_scrollbar(), i_scrollbar::update_reason_e::Updated);
625 scrollbar_updated(horizontal_scrollbar(), i_scrollbar::update_reason_e::Updated);
626
627#ifdef NEOGFX_DEBUG
628 if (debug::layoutItem == this)
629 {
630 auto const scrollArea = scroll_area();
631 auto const scrollPage = scroll_page();
632 service<debug::logger>() << neolib::logger::severity::Debug << "widget:layout_items: update_scrollbar_visibility: scroll_area: " << scrollArea << ", scroll_page: " << scrollPage << endl;
633 }
634#endif
635 }
636
637 template <typename Base>
639 {
640 bool updatePage = false;
641
642 switch (aStage)
643 {
644 case UsvStageInit:
645 if (vertical_scrollbar().visible())
646 {
647 vertical_scrollbar().hide();
648 updatePage = true;
649 }
650 if (horizontal_scrollbar().visible())
651 {
652 horizontal_scrollbar().hide();
653 updatePage = true;
654 }
655 break;
656 case UsvStageCheckVertical1:
657 case UsvStageCheckVertical2:
658 if (scroll_area().cy > scroll_page().cy)
659 {
660 if (!vertical_scrollbar().visible())
661 {
662 vertical_scrollbar().show();
663 updatePage = true;
664 }
665 }
666 break;
667 case UsvStageCheckHorizontal:
668 if (scroll_area().cx > scroll_page().cx)
669 {
670 if (!horizontal_scrollbar().visible())
671 {
672 horizontal_scrollbar().show();
673 updatePage = true;
674 }
675 break;
676 }
677 break;
678 case UsvStageDone:
679 {
680 auto const& sa = units_converter{ *this }.to_device_units(scroll_area());
681 auto const& sp = units_converter{ *this }.to_device_units(scroll_page());
682 neolib::scoped_counter<uint32_t> sc(iIgnoreScrollbarUpdates);
683 vertical_scrollbar().set_minimum(sa.top());
684 vertical_scrollbar().set_maximum(sa.bottom());
685 vertical_scrollbar().set_page(sp.cy);
686 horizontal_scrollbar().set_minimum(sa.left());
687 horizontal_scrollbar().set_maximum(sa.right());
688 horizontal_scrollbar().set_page(sp.cx);
689 iOldScrollPosition = scroll_position();
690 }
691 break;
692 default:
693 break;
694 }
695
696 if (updatePage)
697 scroll_page_updated();
698
699 return updatePage;
700 }
701
702 template <typename Base>
704 {
705 base_type::as_widget().layout_items();
706 }
707}
coordinate_type dy
coordinate_type dx
coordinate_type x
coordinate_type y
point_type top_right() const
point_type bottom_left() const
dimension_type cy
dimension_type cx
void fill_rect(const rect &aRect, const brush &aFill) const
virtual dimension width() const =0
virtual scrollbar_orientation orientation() const =0
virtual scrollbar_style type() const =0
widget_part part(point const &aPosition) const override
rect scroll_area() const override
bool mouse_wheel_scrolled(mouse_wheel aWheel, point const &aPosition, delta aDelta, key_modifiers_e aKeyModifiers) override
bool key_pressed(scan_code_e aScanCode, key_code_e aKeyCode, key_modifiers_e aKeyModifiers) override
rect scrollbar_geometry(i_scrollbar const &aScrollbar) const override
void mouse_entered(point const &aPosition) override
size scroll_page() const override
virtual bool use_scrollbar_container_updater() const
virtual neogfx::scrolling_disposition scrolling_disposition() const
neogfx::scrollbar_style scrollbar_style() const
void mouse_button_released(mouse_button aButton, point const &aPosition) override
void layout_items_completed() override
virtual scrollbar const & vertical_scrollbar() const
rect client_rect(bool aExtendIntoPadding=true) const override
void scrollbar_updated(i_scrollbar const &aScrollbar, i_scrollbar::update_reason_e aReason) override
void update_scrollbar_visibility() override
void mouse_button_pressed(mouse_button aButton, point const &aPosition, key_modifiers_e aKeyModifiers) override
void paint_non_client_after(i_graphics_context &aGc) const override
i_widget const & as_widget() const override
void mouse_button_double_clicked(mouse_button aButton, point const &aPosition, key_modifiers_e aKeyModifiers) override
virtual scrollbar const & horizontal_scrollbar() const
void scroll_to(i_widget &aChild)
void mouse_moved(point const &aPosition, key_modifiers_e aKeyModifiers) override
color scrollbar_color(i_scrollbar const &aScrollbar) const override
void set_step(value_type aStep) override
vector2 to_device_units(const vector2 &aValue) const
vector2 from_device_units(const vector2 &aValue) const
reference & emplace(Args &&... args)
Definition optional.hpp:166
@ KeyModifier_CTRL
T to_units(i_units_context const &aSourceUnitsContext, units aNewUnits, const T &aValue)
Definition units.hpp:426
bool contains(item_selection const &aSelection, item_presentation_model_index aIndex)
mouse_wheel
Definition i_mouse.hpp:42
basic_delta< coordinate > delta
default_geometry_value_type coordinate
@ ScanCode_RSHIFT
@ ScanCode_RIGHT
@ ScanCode_DOWN
@ ScanCode_LSHIFT
@ ScanCode_HOME
@ ScanCode_PAGEDOWN
@ ScanCode_PAGEUP
@ ScanCode_LEFT
mouse_button
Definition i_mouse.hpp:31
basic_point< coordinate > point
@ Foreground
Definition i_palette.hpp:34
basic_scoped_units< units > scoped_units
Definition units.hpp:927
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
Definition plf_hive.h:4776