1 #include "CtrlCore.h"
2
3 namespace Upp {
4
5 #define LLOG(x) // DLOG(x)
6 #define LDUMP(x) // DDUMP(x)
7 #define LTIMESTOP(x) // DTIMESTOP(x)
8
Run()9 void LocalLoop::Run()
10 {
11 ASSERT(master);
12 master->AddChild(this);
13 SizePos();
14 Ptr<Ctrl> focus = GetFocusCtrl();
15 SetCapture();
16 SetFocus();
17 LLOG("LocalLoop::Run");
18 EventLoop(this);
19 LLOG("LocalLoop Finished");
20 Remove();
21 if(focus)
22 focus->SetFocus();
23 }
24
CancelMode()25 void LocalLoop::CancelMode()
26 {
27 EndLoop();
28 }
29
sPaintView(Draw & w,Ctrl & m)30 static void sPaintView(Draw& w, Ctrl& m)
31 {
32 m.Paint(w);
33 for(Ctrl *q = m.GetFirstChild(); q; q = q->GetNext()) {
34 Rect r = q->GetRect();
35 if(q->IsShown() && q->InView() && w.IsPainting(r)) {
36 w.Offset(r.TopLeft());
37 sPaintView(w, *q);
38 w.End();
39 }
40 }
41 }
42
RectTracker(Ctrl & master)43 RectTracker::RectTracker(Ctrl& master)
44 {
45 op = GetMousePos();
46 SetMaster(master);
47 if(master.IsVisible()) {
48 LTIMESTOP("--- snapshot");
49 LDUMP(master.GetSize());
50 ImageDraw iw(master.GetSize());
51 sPaintView(iw, master);
52 master_image = iw;
53 }
54 Clip(Rect(0, 0, 100000, 100000));
55 width = 1;
56 minsize = Size(0, 0);
57 maxsize = Size(100000, 100000);
58 maxrect = Rect(-100000, -100000, 100000, 100000);
59 keepratio = false;
60 cursorimage = Image::Arrow();
61 color = Black();
62 pattern = DRAWDRAGRECT_NORMAL;
63 animation = 0;
64 rounder = NULL;
65 }
66
LeftUp(Point,dword)67 void RectTracker::LeftUp(Point, dword)
68 {
69 EndLoop();
70 }
71
RightUp(Point,dword)72 void RectTracker::RightUp(Point, dword)
73 {
74 EndLoop();
75 }
76
CursorImage(Point,dword)77 Image RectTracker::CursorImage(Point, dword)
78 {
79 if(animation)
80 Refresh();
81 return cursorimage;
82 }
83
RefreshRect(const Rect & old,const Rect & r)84 void RectTracker::RefreshRect(const Rect& old, const Rect& r)
85 {
86 if(r.Normalized() == r && (tx >= 0 || ty >= 0)) {
87 auto Ref = [&](const Rect& r) {
88 Refresh(r.left, r.top, r.Width(), width);
89 Refresh(r.left, r.top, width, r.GetHeight());
90 Refresh(r.left, r.bottom - width, r.Width(), width);
91 Refresh(r.right - width, r.top, width, r.GetHeight());
92 };
93 Ref(old);
94 Ref(r);
95 }
96 else
97 Refresh();
98 }
99
DrawRect(Draw & w,Rect r)100 void RectTracker::DrawRect(Draw& w, Rect r)
101 {
102 DrawDragFrame(w, r, width, pattern, color, animation ? (msecs() / animation) % 8 : 0);
103 }
104
Paint(Draw & w)105 void RectTracker::Paint(Draw& w)
106 {
107 {
108 LTIMESTOP("DrawImage");
109 w.DrawImage(0, 0, master_image);
110 }
111 w.Clip(clip & GetMaster().GetSize());
112 Rect r = rect;
113 if(tx < 0 && ty < 0) {
114 if(width > 1 || pattern == DRAWDRAGRECT_SOLID)
115 w.DrawLine(r.TopLeft(), r.BottomRight(), width, color);
116 else {
117 Color color2 = IsDark(color) ? White() : Black();
118 w.DrawLine(r.TopLeft(), r.BottomRight(), 1, color2);
119 w.DrawLine(r.TopLeft(), r.BottomRight(), pattern == DRAWDRAGRECT_DASHED ? PEN_DASH : PEN_DOT, color);
120 }
121 }
122 else {
123 if(ty < 0)
124 r.left = r.right - 1;
125 else
126 if(tx < 0)
127 r.top = r.bottom - 1;
128 else
129 r.Normalize();
130 DrawRect(w, r);
131 }
132 w.End();
133 }
134
Track(const Rect & r,int _tx,int _ty)135 Rect RectTracker::Track(const Rect& r, int _tx, int _ty)
136 {
137 rect = r;
138 tx = _tx;
139 ty = _ty;
140 org = rect;
141 o = rect;
142 Run();
143 return rect;
144 }
145
TrackHorzLine(int x0,int y0,int cx,int line)146 int RectTracker::TrackHorzLine(int x0, int y0, int cx, int line)
147 {
148 return Track(RectC(x0, y0, cx, line + 1), -1, ALIGN_BOTTOM).bottom - 1;
149 }
150
TrackVertLine(int x0,int y0,int cy,int line)151 int RectTracker::TrackVertLine(int x0, int y0, int cy, int line)
152 {
153 return Track(RectC(x0, y0, line + 1, cy), ALIGN_RIGHT, -1).right - 1;
154 }
155
TrackLine(int x0,int y0)156 Point RectTracker::TrackLine(int x0, int y0)
157 {
158 return Track(Rect(x0, y0, x0, y0), -1, -1).BottomRight();
159 }
160
Round(const Rect & r)161 Rect RectTracker::Round(const Rect& r)
162 {
163 Rect h = r;
164 if(round)
165 round(h);
166 return rounder ? rounder->Round(h) : h;
167 }
168
MouseMove(Point mp,dword)169 void RectTracker::MouseMove(Point mp, dword)
170 {
171 Point p = GetMousePos();
172 rect = org;
173 if(tx < 0 && ty < 0) { // free line mode
174 rect.right = mp.x;
175 rect.bottom = mp.y;
176 }
177 else
178 if(tx == ALIGN_CENTER && ty == ALIGN_CENTER) { // move rectangle
179 int x = org.left - op.x + p.x;
180 int y = org.top - op.y + p.y;
181 if(x + org.Width() > maxrect.right)
182 x = maxrect.right - org.Width();
183 if(x < maxrect.left)
184 x = maxrect.left;
185 if(y + org.Height() > maxrect.bottom)
186 y = maxrect.bottom - org.Height();
187 if(y < maxrect.top)
188 y = maxrect.top;
189 rect = RectC(x, y, org.Width(), org.Height());
190 }
191 else {
192 if(tx == ALIGN_LEFT) {
193 rect.left = max(org.left - op.x + p.x, maxrect.left);
194 rect.left = minmax(rect.left, rect.right - maxsize.cx, rect.right - minsize.cx);
195 }
196 if(tx == ALIGN_RIGHT) {
197 rect.right = min(org.right - op.x + p.x, maxrect.right);
198 rect.right = minmax(rect.right, rect.left + minsize.cx, rect.left + maxsize.cx);
199 }
200 if(ty == ALIGN_TOP) {
201 rect.top = max(org.top - op.y + p.y, maxrect.top);
202 rect.top = minmax(rect.top, rect.bottom - maxsize.cy, rect.bottom - minsize.cy);
203 }
204 if(ty == ALIGN_BOTTOM) {
205 rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
206 rect.bottom = minmax(rect.bottom, rect.top + minsize.cy, rect.top + maxsize.cy);
207 }
208 if(tx == ALIGN_NULL) {
209 rect.right = min(org.right - op.x + p.x, maxrect.right);
210 if (rect.right < rect.left) {
211 Swap(rect.right, rect.left);
212 rect.InflateHorz(1);
213 }
214 }
215 if(ty == ALIGN_NULL) {
216 rect.bottom = min(org.bottom - op.y + p.y, maxrect.bottom);
217 if (rect.bottom < rect.top) {
218 Swap(rect.bottom, rect.top);
219 rect.InflateVert(1);
220 }
221 }
222 if(keepratio) {
223 int cy = org.Width() ? rect.Width() * org.Height() / org.Width() : 0;
224 int cx = org.Height() ? rect.Height() * org.Width() / org.Height() : 0;
225 if(tx == ALIGN_BOTTOM && ty == ALIGN_RIGHT) {
226 Size sz = rect.Size();
227 if(cx > sz.cx)
228 rect.right = rect.left + cx;
229 else
230 rect.bottom = rect.top + cy;
231 }
232 else
233 if(tx == ALIGN_RIGHT)
234 rect.bottom = rect.top + cy;
235 else
236 if(ty == ALIGN_BOTTOM)
237 rect.right = rect.left + cx;
238 }
239 }
240 if(rect != o) {
241 rect = Round(rect);
242 if(rect != o) {
243 RefreshRect(rect, o);
244 sync(rect);
245 o = rect;
246 }
247 }
248 }
249
250 class PointLooper : public LocalLoop {
251 const Vector<Image>& ani;
252 int ani_ms;
253 bool result;
254
255 public:
256 virtual void LeftUp(Point, dword);
257 virtual Image CursorImage(Point p, dword keyflags);
258 virtual bool Key(dword key, int);
259
operator bool() const260 operator bool() const { return result; }
261
PointLooper(Ctrl & ctrl,const Vector<Image> & ani,int ani_ms)262 PointLooper(Ctrl& ctrl, const Vector<Image>& ani, int ani_ms)
263 : ani(ani), ani_ms(ani_ms) { SetMaster(ctrl); }
264 };
265
LeftUp(Point,dword)266 void PointLooper::LeftUp(Point, dword)
267 {
268 result = true;
269 EndLoop();
270 }
271
CursorImage(Point p,dword keyflags)272 Image PointLooper::CursorImage(Point p, dword keyflags)
273 {
274 return ani[int(GetTimeClick() / ani_ms % ani.GetCount())];
275 }
276
Key(dword key,int)277 bool PointLooper::Key(dword key, int)
278 {
279 if(key == K_ESCAPE) {
280 result = false;
281 EndLoop();
282 }
283 return true;
284 }
285
PointLoop(Ctrl & ctrl,const Vector<Image> & ani,int ani_ms)286 bool PointLoop(Ctrl& ctrl, const Vector<Image>& ani, int ani_ms)
287 {
288 PointLooper p(ctrl, ani, ani_ms);
289 p.Run();
290 return p;
291 }
292
PointLoop(Ctrl & ctrl,const Image & img)293 bool PointLoop(Ctrl& ctrl, const Image& img)
294 {
295 Vector<Image> m;
296 m.Add(img);
297 return PointLoop(ctrl, m, 1);
298 }
299
300 }
301