-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathLayoutStrategy.cc
More file actions
122 lines (101 loc) · 4.14 KB
/
LayoutStrategy.cc
File metadata and controls
122 lines (101 loc) · 4.14 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
#include <cmath>
#include "LayoutStrategy.h"
#define BAR_HEIGHT_FACTOR 0.5
LayoutStrategy::~LayoutStrategy() {}
WaveLayout::WaveLayout(int widget_size_, int num_anim_, float zoom_factor_,
float jump_factor_)
: widget_size(widget_size_), widget_dist(5), bar_margin(5),
num_animated(num_anim_), zoom_factor(zoom_factor_),
jump_factor(jump_factor_), position(), bounds(),
dock_bounds(widget_growth() / 2.0, bar_y(), widget_unit(), bar_height()) {
}
WaveLayout::~WaveLayout() {
for (auto &elem : bounds)
delete elem;
for (auto &elem : position)
delete elem;
}
const Rect &WaveLayout::addWidget() {
dock_bounds.width += widget_unit();
auto p = new Point((widget_growth() + widget_dist) / 2.0 +
widget_unit() * (bounds.size() + 0.5),
bar_y() + (int)(widget_size * BAR_HEIGHT_FACTOR / 2.0));
position.push_back(p);
bounds.push_back(new Rect(p->x, p->y, widget_size, widget_size));
return *bounds.back();
}
void WaveLayout::unfocus() {
for (size_t i = 0; i < position.size(); i++) {
Rect &w = *bounds[i];
w.x = position[i]->x;
w.y = position[i]->y;
w.width = w.height = widget_size;
}
dock_bounds.x = widget_growth() / 2.0;
dock_bounds.width = widget_unit() * (bounds.size() + 1);
}
void WaveLayout::focus(const Point &p) {
const float x = (p.x - (widget_growth() + widget_unit() + widget_dist) / 2.0);
const size_t focused = x / widget_unit();
float rx = x - widget_unit() / 2.0; // widget-space relative x
const float wu_na = widget_unit() * num_animated;
for (size_t i = 0; i < bounds.size(); i++, rx -= widget_unit()) {
Rect &w = *bounds[i];
if (std::abs(rx) > wu_na / 2) {
w.width = w.height = widget_size;
w.x = position[i]->x + widget_growth() / (i < focused ? -2.0 : 2.0);
w.y = position[i]->y;
} else {
w.width = w.height =
widget_size *
(1.0 + (zoom_factor - 1.0) * std::cos(rx * M_PI / wu_na));
w.x = position[i]->x - (w.width - widget_size) / 2.0 -
rx * widget_growth() / wu_na;
w.y = position[i]->y - jump_factor * (w.height - widget_size);
}
}
dock_bounds.x = 0;
dock_bounds.width = widget_growth() + widget_unit() * (bounds.size() + 1);
}
int WaveLayout::widgetAt(const Point &p) const {
for (auto widget = bounds.begin(); widget != bounds.end(); widget++) {
if (p.x >= (*widget)->x && p.x < (*widget)->x + (*widget)->width)
return std::distance(bounds.begin(), widget);
}
return -1;
}
bool WaveLayout::atHoverZone(const Point &p) const {
const float x = (p.x - (widget_growth() + widget_unit() + widget_dist) / 2.0);
return (x >= 0.0 && x < bounds.size() * widget_unit() - widget_dist);
}
Size WaveLayout::frameSize() const {
return Size(widget_growth() + widget_unit() * (bounds.size() + 1),
bar_height() + 2 * bar_margin + (int)(_upgrowth() + _dngrowth()));
}
const Rect &WaveLayout::dockLayout() const { return dock_bounds; }
///// WaveLayout private helpers ///// TODO: memoize
int WaveLayout::widget_unit() const { return widget_size + widget_dist; }
int WaveLayout::widget_growth() const {
// computed by taking the size of evenly distributed widgets (num_animated)
// inside a cos-function wrapper: shifted and scaled so that scale ranges
// from -pi/2 to pi/2 holding num_animated widgets with spacing (widget_unit)
float wo = 0.0;
for (float i = 0.0; i < num_animated; i += 1.0)
wo += std::sin(M_PI * (i + 0.5) / (float)num_animated);
return widget_unit() * (zoom_factor < 1.0 ? 0.0 : zoom_factor - 1.0) * wo;
}
int WaveLayout::bar_height() const {
return widget_size * (1 + BAR_HEIGHT_FACTOR);
}
int WaveLayout::bar_y() const { return bar_margin + (int)_upgrowth(); }
float WaveLayout::_upgrowth() const {
const float ug = widget_size * ((zoom_factor - 1.0) * jump_factor -
BAR_HEIGHT_FACTOR / 2.0);
return (ug > 0.0 ? ug : 0.0);
}
float WaveLayout::_dngrowth() const {
const float dg = widget_size * ((zoom_factor - 1.0) * (1.0 - jump_factor) -
BAR_HEIGHT_FACTOR / 2.0);
return (dg > 0.0 ? dg : 0.0);
}
/* vim: set sw=2 sts=2 : */