-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimpleBar.hpp
More file actions
162 lines (126 loc) · 4.72 KB
/
simpleBar.hpp
File metadata and controls
162 lines (126 loc) · 4.72 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* A widget similar to a Gtk::ProgressBar, but that uses a very simple
* theme-independent drawing function and that can change colour when
* its value is set above a given threshold
*/
#ifndef SIMPLEBAR_HPP_
#define SIMPLEBAR_HPP_
#include <gtkmm/widget.h>
#include <glibmm/dispatcher.h>
#include <gdkmm/general.h>
#include <gdkmm/color.h>
#include <atomic>
#include <limits>
#include <cstring>
#include "attributes.hpp"
class SimpleBar : public Gtk::Widget {
private:
Glib::RefPtr<Gdk::Window> window;
double value;
double threshold;
Gdk::Color belowColour;
Gdk::Color aboveColour;
int width;
int height;
Glib::Dispatcher dispatch;
std::atomic<unsigned> queued_value;
FLATTEN void set_queued_value() { value = (double)queued_value / (double)std::numeric_limits<unsigned>::max(); queue_draw(); }
protected:
virtual void get_preferred_width_vfunc(int& minimum_width, int& natural_width) const {
minimum_width = width;
natural_width = (width > 150) ? width : 150;
}
virtual void get_preferred_height_vfunc(int& minimum_height, int& natural_height) const {
minimum_height = height;
natural_height = (height > 25) ? height : 25;
}
virtual void get_preferred_width_for_height_vfunc(int, int& minimum_width, int& natural_width) const {
// no preferred aspect ratio
minimum_width = width;
natural_width = (width > 150) ? width : 150;
}
virtual void get_preferred_height_for_width_vfunc(int, int& minimum_height, int& natural_height) const {
// no preferred aspect ratio
minimum_height = height;
natural_height = (height > 25) ? height : 25;
}
virtual void on_size_allocate(Gtk::Allocation& allocation) {
set_allocation(allocation);
if (window) {
window->move_resize(allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height());
}
}
virtual void on_realize() {
set_realized();
if (!window) {
GdkWindowAttr attr;
std::memset(&attr, 0, sizeof(GdkWindowAttr));
Gtk::Allocation alloc = get_allocation();
attr.x = alloc.get_x();
attr.y = alloc.get_y();
attr.width = alloc.get_width();
attr.height = alloc.get_height();
attr.event_mask = get_events() | Gdk::EXPOSURE_MASK;
attr.window_type = GDK_WINDOW_CHILD;
attr.wclass = GDK_INPUT_OUTPUT;
window = Gdk::Window::create(get_parent_window(), &attr, GDK_WA_X | GDK_WA_Y);
set_window(window);
window->set_user_data(gobj());
}
}
virtual void on_unrealize() {
window.reset();
Gtk::Widget::on_unrealize();
}
virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& pen) {
const double w = (double)get_allocation().get_width();
const double h = (double)get_allocation().get_height();
const double x = 0.5 + (w - 1.0) * value;
const Gdk::Color &colour = (value > threshold) ? aboveColour : belowColour;
pen->set_source_rgb(colour.get_red_p(), colour.get_green_p(), colour.get_blue_p());
pen->move_to(0.5, 0.5);
pen->line_to(x, 0.5);
pen->line_to(x, h - 0.5);
pen->line_to(0.5, h - 0.5);
pen->fill();
pen->set_source_rgb(0.0, 0.0, 0.0);
pen->set_line_width(1.0);
pen->move_to(0.5, 0.5);
pen->line_to(w - 0.5, 0.5);
pen->line_to(w - 0.5, h - 0.5);
pen->line_to(0.5, h - 0.5);
pen->close_path();
pen->stroke();
return true;
}
public:
SimpleBar() : Glib::ObjectBase("SimpleBar"), Gtk::Widget(), value(0), threshold(0), width(3), height(3) {
set_has_window(true);
aboveColour.set_rgb_p(0.0, 1.0, 0.0);
belowColour.set_rgb_p(1.0, 0.0, 0.0);
dispatch.connect(sigc::mem_fun(*this, &SimpleBar::set_queued_value));
}
INLINE ~SimpleBar() {}
INLINE void set_minimum_width(int w) { width = (w > 3) ? w : 3; }
INLINE void set_minimum_height(int h) { height = (h > 3) ? h : 3; }
INLINE void set_minimum_size(int w, int h) { width = (w > 3) ? w : 3; height = (h > 3) ? h : 3; }
INLINE void set_colour_below_threshold(const Gdk::Color &c) { belowColour = c; }
INLINE void set_colour_above_threshold(const Gdk::Color &c) { aboveColour = c; }
INLINE void set_colours(const Gdk::Color &below, const Gdk::Color &above) { belowColour = below; aboveColour = above; }
INLINE void set_value(double v) { value = (v > 0.0) ? ((v < 1.0) ? v : 1.0) : 0.0; queue_draw(); }
INLINE void set_value_async(double v) {
if (v <= 0.0) {
queued_value = 0;
} else if (v >= 1.0) {
queued_value = std::numeric_limits<unsigned>::max();
} else {
queued_value = (unsigned)(v * (double)std::numeric_limits<unsigned>::max());
}
dispatch.emit();
}
USERET INLINE double get_value() const { return value; }
INLINE void set_threshold(double t) { threshold = (t > 0.0) ? ((t < 1.0) ? t : 1.0) : 0.0; queue_draw(); }
USERET INLINE double get_threshold() const { return threshold; }
USERET INLINE bool get_above_threshold() const { return(value > threshold); }
};
#endif /* SIMPLEBAR_HPP_ */