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