blob: c0603989ad40edb6d3feb427711ab6a71512c50a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef SEEN_INKSCAPE_UI_WIDGET_SCROLLPROTECTED_H
#define SEEN_INKSCAPE_UI_WIDGET_SCROLLPROTECTED_H
/* Authors:
* Thomas Holder
* Anshudhar Kumar Singh <anshudhar2001@gmail.com>
*
* Copyright (C) 2020-2021 Authors
*
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
#include <gtkmm.h>
#include "scroll-utils.h"
namespace Inkscape {
namespace UI {
namespace Widget {
/**
* A class decorator which blocks the scroll event if the widget does not have
* focus and any ancestor is a scrollable window, and SHIFT is not pressed.
*
* For custom scroll event handlers, derived classes must implement
* on_safe_scroll_event instead of on_scroll_event. Directly connecting to
* signal_scroll_event() will bypass the scroll protection.
*
* @tparam Base A subclass of Gtk::Widget
*/
template <typename Base>
class ScrollProtected : public Base
{
public:
using Base::Base;
using typename Base::BaseObjectType;
ScrollProtected()
: Base()
{}
ScrollProtected(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade)
: Base(cobject){};
~ScrollProtected() override{};
protected:
/**
* Event handler for "safe" scroll events which are only triggered if:
* - the widget has focus
* - or the widget has no scrolled window ancestor
* - or the Shift key is pressed
*/
virtual bool on_safe_scroll_event(GdkEventScroll *event)
{ //
return Base::on_scroll_event(event);
}
bool on_scroll_event(GdkEventScroll *event) final
{
if (!scrolling_allowed(this, event)) {
return false;
}
return on_safe_scroll_event(event);
}
};
/**
* A class decorator for scroll widgets like scrolled window to transfer scroll to
* any ancestor which is is a scrollable window when scroll reached end.
*
* For custom scroll event handlers, derived classes must implement
* on_safe_scroll_event instead of on_scroll_event. Directly connecting to
* signal_scroll_event() will bypass the scroll protection.
*
* @tparam Base A subclass of Gtk::Widget
*/
template <typename Base>
class ScrollTransfer : public Base
{
public:
using Base::Base;
using typename Base::BaseObjectType;
ScrollTransfer()
: Base()
{}
ScrollTransfer(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade)
: Base(cobject){};
~ScrollTransfer() override{};
protected:
/**
* Event handler for "safe" scroll events
*/
virtual bool on_safe_scroll_event(GdkEventScroll *event)
{ //
return Base::on_scroll_event(event);
}
bool on_scroll_event(GdkEventScroll *event) final
{
auto scrollable = dynamic_cast<Gtk::Widget *>(Inkscape::UI::Widget::get_scrollable_ancestor(this));
auto adj = this->get_vadjustment();
auto before = adj->get_value();
bool result = on_safe_scroll_event(event);
auto after = adj->get_value();
if (scrollable && before == after) {
return false;
}
return result;
}
};
} // namespace Widget
} // namespace UI
} // namespace Inkscape
#endif
// vim: filetype=cpp:expandtab:shiftwidth=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
|