1 #include "FloatingWindow.h"
2 #include "plugin/ColorPalette.h"
3 #include "Window.hpp"
4 
FloatingWindow(Widget * group,ColorPalette & palette)5 FloatingWindow::FloatingWindow(Widget *group, ColorPalette &palette)
6     : NanoWidget(group),
7       fPalette(palette)
8 {
9 }
10 
setMoveLimits(DGL::Point<int> origin,DGL::Size<uint> size)11 void FloatingWindow::setMoveLimits(DGL::Point<int> origin, DGL::Size<uint> size)
12 {
13     fLimitOrigin = origin;
14     fLimitSize = size;
15 }
16 
repositionWithinLimits()17 void FloatingWindow::repositionWithinLimits()
18 {
19     setAbsolutePos(restrictWithinLimits(getAbsolutePos()));
20 }
21 
moveAlong(Widget * w)22 void FloatingWindow::moveAlong(Widget *w)
23 {
24     DISTRHO_SAFE_ASSERT_RETURN(w != nullptr, );
25 
26     fMoveAlong.push_back(w);
27 }
28 
setAllVisible(bool visible)29 void FloatingWindow::setAllVisible(bool visible)
30 {
31     setVisible(visible);
32     for (Widget *w : fMoveAlong)
33         w->setVisible(visible);
34 }
35 
onNanoDisplay()36 void FloatingWindow::onNanoDisplay()
37 {
38     ColorPalette &cp = fPalette;
39 
40     double w = getWidth();
41     double h = getHeight();
42 
43     beginPath();
44     roundedRect(0.0, 0.0, w, h, 10.0);
45     fillColor(Colors::fromRGBA8(cp[Colors::floating_window_back]));
46     fill();
47 }
48 
onPositionChanged(const PositionChangedEvent & ev)49 void FloatingWindow::onPositionChanged(const PositionChangedEvent &ev)
50 {
51     int dX = ev.pos.getX() - ev.oldPos.getX();
52     int dY = ev.pos.getY() - ev.oldPos.getY();
53 
54     for (Widget *w : fMoveAlong) {
55         DGL::Point<int> p = w->getAbsolutePos();
56         p.setX(p.getX() + dX);
57         p.setY(p.getY() + dY);
58         w->setAbsolutePos(p);
59     }
60 }
61 
onMouse(const MouseEvent & ev)62 bool FloatingWindow::onMouse(const MouseEvent &ev)
63 {
64     if (ev.press && ev.button == 1) {
65         const int w = getWidth();
66         const int h = getHeight();
67         const int evX = ev.pos.getX();
68         const int evY = ev.pos.getY();
69         const DGL::Point<int> a = getAbsolutePos();
70         const bool inside = evX >= 0 && evX < w && evY >= 0 && evY < h;
71         if (inside) {
72             fIsDragging = true;
73             fDragMouseOrigin = {evX + a.getX(), evY + a.getY()};
74             fDragStartingWindowPos = a;
75             return true;
76         }
77     }
78     else if (!ev.press && ev.button == 1) {
79         if (fIsDragging) {
80             fIsDragging = false;
81             return true;
82         }
83     }
84 
85     return false;
86 }
87 
onMotion(const MotionEvent & ev)88 bool FloatingWindow::onMotion(const MotionEvent &ev)
89 {
90     if (fIsDragging) {
91         DGL::Point<int> orig = fDragMouseOrigin;
92         int curx = ev.pos.getX() + getAbsoluteX();
93         int cury = ev.pos.getY() + getAbsoluteY();
94         int dx = curx - orig.getX();
95         int dy = cury - orig.getY();
96         DGL::Point<int> a = fDragStartingWindowPos;
97         a += DGL::Point<int>(dx, dy);
98         setAbsolutePos(restrictWithinLimits(a));
99         return true;
100     }
101 
102     return false;
103 }
104 
restrictWithinLimits(DGL::Point<int> pos)105 DGL::Point<int> FloatingWindow::restrictWithinLimits(DGL::Point<int> pos)
106 {
107     int x = pos.getX();
108     int y = pos.getY();
109     const uint w = getWidth();
110     const uint h = getHeight();
111     const int lx = fLimitOrigin.getX();
112     const int ly = fLimitOrigin.getY();
113     const uint lw = fLimitSize.getWidth();
114     const uint lh = fLimitSize.getHeight();
115 
116     if (lw == 0 || lh == 0)
117         return pos;
118 
119     x = std::max(lx - (int)(w / 2), std::min(lx + (int)lw - (int)(w / 2), x));
120     y = std::max(ly - (int)(h / 2), std::min(ly + (int)lh - (int)(h / 2), y));
121 
122     return DGL::Point<int>(x, y);
123 }
124