1 #include "CtrlLib.h"
2
3 namespace Upp {
4
CtrlsImageLook(Value * look,int i,int n)5 void CtrlsImageLook(Value *look, int i, int n)
6 {
7 while(n--)
8 *look++ = CtrlsImg::Get(i++);
9 }
10
CtrlsImageLook(Value * look,int i,const Image & image,const Color * color,int n)11 void CtrlsImageLook(Value *look, int i, const Image& image, const Color *color, int n)
12 {
13 for(int q = 0; q < n; q++)
14 *look++ = ChLookWith(CtrlsImg::Get(i++), image, *color++);
15 }
16
CtrlsImageLook(Value * look,int i,const Image & image,int n)17 void CtrlsImageLook(Value *look, int i, const Image& image, int n)
18 {
19 for(int q = 0; q < n; q++)
20 *look++ = ChLookWith(CtrlsImg::Get(i++), image);
21 }
22
DeAmp(const char * s)23 String DeAmp(const char *s)
24 {
25 String out;
26 for(; *s; out.Cat(*s++))
27 if(*s == '&')
28 out.Cat('&');
29 return out;
30 }
31
GetSmartTextSize(const char * text,Font font,int cx)32 Size GetSmartTextSize(const char *text, Font font, int cx) {
33 if(*text == '\1') {
34 Size sz;
35 RichText txt = ParseQTF(text + 1);
36 txt.ApplyZoom(GetRichTextStdScreenZoom());
37 sz.cx = min(cx, txt.GetWidth());
38 sz.cy = txt.GetHeight(Zoom(1, 1), sz.cx);
39 return sz;
40 }
41 return GetTLTextSize(ToUnicode(text, CHARSET_DEFAULT), font);
42 }
43
GetSmartTextHeight(const char * s,int cx,Font font)44 int GetSmartTextHeight(const char *s, int cx, Font font) {
45 if(*s == '\1') {
46 Size sz;
47 RichText txt = ParseQTF(s + 1);
48 txt.ApplyZoom(GetRichTextStdScreenZoom());
49 return txt.GetHeight(Zoom(1, 1), cx);
50 }
51 int cy = font.Info().GetHeight();
52 int h = cy;
53 while(*s) {
54 if(*s == '\n')
55 h += cy;
56 s++;
57 }
58 return h;
59 }
60
DrawSmartText(Draw & draw,int x,int y,int cx,const char * text,Font font,Color ink,int accesskey)61 void DrawSmartText(Draw& draw, int x, int y, int cx, const char *text, Font font, Color ink, int accesskey) {
62 if(*text == '\1') {
63 RichText txt = ParseQTF(text + 1, accesskey);
64 txt.ApplyZoom(GetRichTextStdScreenZoom());
65 txt.Paint(Zoom(1, 1), draw, x, y, cx);
66 return;
67 }
68 DrawTLText(draw, x, y, cx, ToUnicode(text, CHARSET_DEFAULT), font, ink, accesskey);
69 }
70
CompareAccessKey(int accesskey,dword key)71 bool CompareAccessKey(int accesskey, dword key)
72 {
73 return accesskey && dword(ToUpper(accesskey & 255) - 'A' + K_ALT_A) == key;
74 }
75
ExtractAccessKey(const char * s,String & label)76 int ExtractAccessKey(const char *s, String& label)
77 {
78 byte akey = 0;
79 int pos = 0;
80 String text;
81 bool qtf = *s == '\1';
82 while(*s)
83 if((*s == '&' && !qtf || *s == '\b') && s[1] && s[1] != '&') {
84 akey = ToAscii(ToUpper(s[1]));
85 pos = text.GetLength() + 1;
86 s++;
87 }
88 else
89 text.Cat(*s++);
90 text.Shrink();
91 label = text;
92 return MAKELONG(akey, pos);
93 }
94
ChooseAccessKey(const char * text,dword used)95 int ChooseAccessKey(const char *text, dword used)
96 {
97 for(const char *s = text; *s; s++) {
98 byte ac = *s;
99 if(ac < 128 && ac >= 'A' && ac <= 'Z' && (Ctrl::AccessKeyBit(ac) & used) == 0)
100 return MAKELONG(ac, s - text + 1);
101 }
102 for(const char *s = text; *s; s++) {
103 dword ac = ToUpper(*s);
104 if(ac < 128 && ac >= 'A' && ac <= 'Z' && ac != 'I' && ac != 'L' && (Ctrl::AccessKeyBit(ac) & used) == 0)
105 return ac;
106 }
107 for(const char *s = text; *s; s++) {
108 dword ac = ToUpper(*s);
109 if(ac < 128 && ac >= 'A' && ac <= 'Z' && (Ctrl::AccessKeyBit(ac) & used) == 0)
110 return ac;
111 }
112 return 0;
113 }
114
DrawLabel()115 DrawLabel::DrawLabel()
116 {
117 push = focus = disabled = false;
118 lspc = rspc = 0;
119 limg_never_hide = false;
120 rimg_never_hide = false;
121 ink = disabledink = Null;
122 align = valign = ALIGN_CENTER;
123 accesskey = 0;
124 accesspos = -1;
125 font = StdFont();
126 nowrap = false;
127 }
128
GetSize(int txtcx) const129 Size DrawLabel::GetSize(int txtcx) const
130 {
131 return GetSize(txtcx, limg.GetSize(), lspc, rimg.GetSize(), rspc);
132 }
133
GetSize(int txtcx,Size sz1,int lspc,Size sz2,int rspc) const134 Size DrawLabel::GetSize(int txtcx, Size sz1, int lspc, Size sz2, int rspc) const
135 {
136 Size isz(0, 0);
137 Size txtsz = *text ? GetSmartTextSize(text, font, nowrap ? INT_MAX/2 : txtcx)
138 : paintrect.GetStdSize();
139
140 if(!IsNull(lspc)) {
141 isz.cx = lspc;
142 isz.cy = sz1.cy;
143 isz.cx += sz1.cx;
144 }
145
146 if(!IsNull(rspc)) {
147 isz.cx += rspc;
148 if(sz2.cy > isz.cy) isz.cy = sz2.cy;
149 isz.cx += sz2.cx;
150 }
151
152 isz.cy = max(txtsz.cy, max(sz1.cy, sz2.cy));
153 isz.cx += txtsz.cx;
154
155 return isz;
156 }
157
DisImage(const Image & m)158 Image DisImage(const Image& m)
159 {
160 Image mm = Grayscale(m, 200);
161 ImageBuffer ib(mm);
162 RGBA *s = ~ib;
163 RGBA *e = s + ib.GetLength();
164 while(s < e)
165 (s++)->a /= 3;
166 Premultiply(ib);
167 return ib;
168 }
169
DisabledImage(const Image & img,bool dis)170 Image DisabledImage(const Image& img, bool dis)
171 {
172 return dis ? MakeImage(img, GUI_GlobalStyle() == GUISTYLE_CLASSIC ? Etched : DisImage)
173 : img;
174 }
175
GetLabelTextColor(const Ctrl * ctrl)176 Color GetLabelTextColor(const Ctrl *ctrl)
177 {
178 if(!IsLabelTextColorMismatch())
179 return SColorLabel();
180 while(ctrl) {
181 if(!ctrl->IsTransparent()) {
182 if(dynamic_cast<const TopWindow *>(ctrl) || dynamic_cast<const TabCtrl *>(ctrl) ||
183 dynamic_cast<const ToolBar *>(ctrl) || dynamic_cast<const MenuBar *>(ctrl) ||
184 dynamic_cast<const StaticRect *>(ctrl) || dynamic_cast<const StaticBarArea *>(ctrl))
185 break;
186 return SColorText();
187 }
188 ctrl = ctrl->GetParent();
189 }
190 return SColorLabel();
191 }
192
Paint(Ctrl * ctrl,Draw & w,const Rect & r,bool visibleaccesskey) const193 Size DrawLabel::Paint(Ctrl *ctrl, Draw& w, const Rect& r, bool visibleaccesskey) const
194 {
195 int lspc = this->lspc;
196 int rspc = this->rspc;
197 Size sz1 = limg.GetSize();
198 Size sz2 = rimg.GetSize();
199 int txtcx = r.GetWidth() - sz1.cx - Nvl(lspc, 0) - sz2.cx - Nvl(rspc, 0);
200 Size txtsz = *text ? GetSmartTextSize(text, font, nowrap ? INT_MAX/2 : txtcx) : paintrect.GetStdSize();
201 if(txtsz.cx) {
202 if(!rimg_never_hide && txtsz.cx + sz1.cx + sz2.cx + Nvl(lspc, 0) + Nvl(rspc, 0) > r.GetWidth()) {
203 sz2.cx = 0;
204 rspc = 0;
205 }
206 if(!limg_never_hide && txtsz.cx + sz1.cx + sz2.cx + Nvl(lspc, 0) + Nvl(rspc, 0) > r.GetWidth()) {
207 sz1.cx = 0;
208 lspc = 0;
209 }
210 }
211 Size isz = GetSize(txtcx, sz1, lspc, sz2, rspc);
212 Point p = r.TopLeft(), ip;
213 if(align == ALIGN_LEFT)
214 p.x = r.left;
215 else
216 if(align == ALIGN_RIGHT)
217 p.x = r.right - isz.cx;
218 else
219 if(align == ALIGN_CENTER)
220 p.x = (r.right + r.left - isz.cx) / 2;
221 if(valign == ALIGN_TOP)
222 p.y = r.top;
223 else
224 if(valign == ALIGN_BOTTOM)
225 p.y = r.bottom - isz.cy;
226 else
227 if(valign == ALIGN_CENTER)
228 p.y = (r.bottom + r.top - txtsz.cy) / 2;
229 Color color = disabled && !IsNull(disabledink) ? disabledink : ink;
230 if(IsNull(color))
231 color = disabled ? SColorDisabled : GetLabelTextColor(ctrl);
232 int ix;
233 if(IsNull(lspc))
234 ix = r.left + push;
235 else {
236 ix = p.x + push;
237 p.x += sz1.cx;
238 p.x += lspc;
239 }
240 int iy = push + (r.top + r.bottom - sz1.cy) / 2;
241
242 if(sz1.cx) {
243 if(IsNull(lcolor))
244 w.DrawImage(ix, iy, DisabledImage(limg, disabled));
245 else
246 w.DrawImage(ix, iy, limg, lcolor);
247 }
248 iy = push + (r.top + r.bottom - sz2.cy) / 2;
249 ix = (IsNull(rspc) ? r.right - sz2.cx : p.x + txtsz.cx + rspc) + push;
250 if(sz2.cx) {
251 if(IsNull(rcolor))
252 w.DrawImage(ix, iy, DisabledImage(rimg, disabled));
253 else
254 w.DrawImage(ix, iy, rimg, rcolor);
255 }
256 paintrect.Paint(w, p.x + push, p.y + push, txtsz.cx, isz.cy, color, Null);
257 if(*text) {
258 if(disabled && *text != '\1')
259 DrawSmartText(w, p.x + push + 1, p.y + push + 1,
260 nowrap ? INT_MAX/2 : txtcx, text, font, SColorPaper);
261 DrawSmartText(w, p.x + push, p.y + push, nowrap ? INT_MAX/2 : txtcx,
262 text, font, color, visibleaccesskey ? accesskey : 0);
263 if(focus)
264 DrawFocus(w, p.x - 2, p.y, txtsz.cx + 5, isz.cy);
265 }
266
267 return isz;
268 }
269
Paint(Ctrl * ctrl,Draw & w,int x,int y,int cx,int cy,bool visibleaccesskey) const270 Size DrawLabel::Paint(Ctrl *ctrl, Draw& w, int x, int y, int cx, int cy, bool visibleaccesskey) const
271 {
272 return Paint(ctrl, w, RectC(x, y, cx, cy), visibleaccesskey);
273 }
274
Paint(Draw & w,const Rect & r,bool visibleaccesskey) const275 Size DrawLabel::Paint(Draw& w, const Rect& r, bool visibleaccesskey) const
276 {
277 return Paint(NULL, w, r, visibleaccesskey);
278 }
279
Paint(Draw & w,int x,int y,int cx,int cy,bool vak) const280 Size DrawLabel::Paint(Draw& w, int x, int y, int cx, int cy, bool vak) const
281 {
282 return Paint(w, RectC(x, y, cx, cy), vak);
283 }
284
LabelUpdate()285 void LabelBase::LabelUpdate() {}
286
SetLeftImage(const Image & img,int spc,bool never_hide)287 LabelBase& LabelBase::SetLeftImage(const Image& img, int spc, bool never_hide) {
288 lbl.limg = img;
289 lbl.lspc = spc;
290 lbl.limg_never_hide = never_hide;
291 LabelUpdate();
292 return *this;
293 }
294
SetRightImage(const Image & img,int spc,bool never_hide)295 LabelBase& LabelBase::SetRightImage(const Image& img, int spc, bool never_hide) {
296 lbl.rimg = img;
297 lbl.rspc = spc;
298 lbl.rimg_never_hide = never_hide;
299 LabelUpdate();
300 return *this;
301 }
302
SetPaintRect(const PaintRect & paintrect)303 LabelBase& LabelBase::SetPaintRect(const PaintRect& paintrect) {
304 lbl.paintrect = paintrect;
305 LabelUpdate();
306 return *this;
307 }
308
309
SetText(const char * text)310 LabelBase& LabelBase::SetText(const char *text) {
311 lbl.text = text;
312 LabelUpdate();
313 return *this;
314 }
315
SetFont(Font font)316 LabelBase& LabelBase::SetFont(Font font) {
317 if(lbl.font != font) {
318 lbl.font = font;
319 LabelUpdate();
320 }
321 return *this;
322 }
323
NoWrap(bool b)324 LabelBase& LabelBase::NoWrap(bool b)
325 {
326 if(lbl.nowrap != b) {
327 lbl.nowrap = b;
328 LabelUpdate();
329 }
330 return *this;
331 }
332
SetInk(Color ink,Color disabledink)333 LabelBase& LabelBase::SetInk(Color ink, Color disabledink) {
334 if(lbl.ink != ink || lbl.disabledink != disabledink) {
335 lbl.ink = ink;
336 lbl.disabledink = disabledink;
337 LabelUpdate();
338 }
339 return *this;
340 }
341
SetAlign(int align)342 LabelBase& LabelBase::SetAlign(int align) {
343 if(lbl.align != align) {
344 lbl.align = align;
345 LabelUpdate();
346 }
347 return *this;
348 }
349
SetVAlign(int valign)350 LabelBase& LabelBase::SetVAlign(int valign) {
351 if(lbl.valign != valign) {
352 lbl.valign = valign;
353 LabelUpdate();
354 }
355 return *this;
356 }
357
PaintLabel(Ctrl * ctrl,Draw & w,const Rect & r,bool disabled,bool push,bool focus,bool vak)358 Size LabelBase::PaintLabel(Ctrl *ctrl, Draw& w, const Rect& r, bool disabled, bool push, bool focus, bool vak)
359 {
360 DrawLabel lbl1 = lbl;
361 lbl1.disabled = disabled;
362 lbl1.push = push;
363 lbl1.focus = focus;
364 return lbl1.Paint(ctrl, w, r, vak);
365 }
366
PaintLabel(Ctrl * ctrl,Draw & w,int x,int y,int cx,int cy,bool disabled,bool push,bool focus,bool vak)367 Size LabelBase::PaintLabel(Ctrl *ctrl, Draw& w, int x, int y, int cx, int cy, bool disabled, bool push, bool focus, bool vak)
368 {
369 return PaintLabel(ctrl, w, RectC(x, y, cx, cy), disabled, push, focus, vak);
370 }
371
PaintLabel(Draw & w,const Rect & r,bool disabled,bool push,bool focus,bool vak)372 Size LabelBase::PaintLabel(Draw& w, const Rect& r, bool disabled, bool push, bool focus, bool vak)
373 {
374 return PaintLabel(NULL, w, r, disabled, push, focus, vak);
375 }
376
377
PaintLabel(Draw & w,int x,int y,int cx,int cy,bool disabled,bool push,bool focus,bool vak)378 Size LabelBase::PaintLabel(Draw& w, int x, int y, int cx, int cy, bool disabled, bool push, bool focus, bool vak)
379 {
380 return PaintLabel(w, RectC(x, y, cx, cy), disabled, push, focus, vak);
381 }
382
GetLabelSize() const383 Size LabelBase::GetLabelSize() const
384 {
385 return lbl.GetSize();
386 }
387
388 void LinkToolTipIn__();
389
~LabelBase()390 LabelBase::~LabelBase() {
391 LinkToolTipIn__();
392 }
393
DrawFocus(Draw & w,int x,int y,int cx,int cy,Color c)394 void DrawFocus(Draw& w, int x, int y, int cx, int cy, Color c) {
395 w.Clipoff(x, y, cx, cy);
396 for(int a = 0; a < cx; a += CtrlImg::focus_h().GetWidth()) {
397 w.DrawImage(a, 0, CtrlImg::focus_h(), c);
398 w.DrawImage(a, cy - DPI(1), CtrlImg::focus_h(), c);
399 }
400 for(int a = 0; a < cy; a += CtrlImg::focus_v().GetHeight()) {
401 w.DrawImage(0, a, CtrlImg::focus_v(), c);
402 w.DrawImage(cx - DPI(1), a, CtrlImg::focus_v(), c);
403 }
404 w.End();
405 }
406
DrawFocus(Draw & w,const Rect & r,Color c)407 void DrawFocus(Draw& w, const Rect& r, Color c) {
408 DrawFocus(w, r.left, r.top, r.Width(), r.Height(), c);
409 }
410
DrawHorzDrop(Draw & w,int x,int y,int cx)411 void DrawHorzDrop(Draw& w, int x, int y, int cx)
412 {
413 w.DrawRect(x, y, cx, 2, SColorHighlight);
414 w.DrawRect(x, y - 2, 1, 6, SColorHighlight);
415 w.DrawRect(x + cx - 1, y - 2, 1, 6, SColorHighlight);
416 w.DrawRect(x + 1, y - 1, 1, 4, SColorHighlight);
417 w.DrawRect(x + cx - 2, y - 1, 1, 4, SColorHighlight);
418 }
419
DrawVertDrop(Draw & w,int x,int y,int cy)420 void DrawVertDrop(Draw& w, int x, int y, int cy)
421 {
422 w.DrawRect(x, y, 2, cy, SColorHighlight);
423 w.DrawRect(x - 2, y, 6, 1, SColorHighlight);
424 w.DrawRect(x - 2, y + cy - 1, 6, 1, SColorHighlight);
425 w.DrawRect(x - 1, y + 1, 4, 1, SColorHighlight);
426 w.DrawRect(x - 1, y + cy - 2, 4, 1, SColorHighlight);
427 }
428
GetDragScroll(Ctrl * ctrl,Point p,Size max)429 Point GetDragScroll(Ctrl *ctrl, Point p, Size max)
430 {
431 if(ctrl->IsReadOnly())
432 return Point(0, 0);
433 Size sz = ctrl->GetSize();
434 Size sd = min(sz / 6, Size(16, 16));
435 Point d(0, 0);
436 if(p.x < sd.cx)
437 d.x = p.x - sd.cx;
438 if(p.x > sz.cx - sd.cx)
439 d.x = p.x - sz.cx + sd.cx;
440 if(p.y < sd.cy)
441 d.y = p.y - sd.cy;
442 if(p.y > sz.cy - sd.cy)
443 d.y = p.y - sz.cy + sd.cy;
444 d.x = minmax(d.x, -max.cx, max.cx);
445 d.y = minmax(d.y, -max.cy, max.cy);
446 return d;
447 }
448
GetDragScroll(Ctrl * ctrl,Point p,int max)449 Point GetDragScroll(Ctrl *ctrl, Point p, int max)
450 {
451 return GetDragScroll(ctrl, p, Size(max, max));
452 }
453
LookMargins(const Rect & r,const Value & ch)454 Rect LookMargins(const Rect& r, const Value& ch)
455 {
456 Rect m = ChMargins(ch);
457 int fcy = GetStdFontCy();
458 if(m.top + m.bottom + fcy > r.GetHeight())
459 m.top = m.bottom = max((r.GetHeight() - fcy) / 2, 0);
460 return m;
461 }
462
FrameLayout(Rect & r)463 void ActiveEdgeFrame::FrameLayout(Rect& r)
464 {
465 Rect m = LookMargins(r, edge[0]);
466 r.left += m.left;
467 r.right -= m.right;
468 r.top += m.top;
469 r.bottom -= m.bottom;
470 }
471
FramePaint(Draw & w,const Rect & r)472 void ActiveEdgeFrame::FramePaint(Draw& w, const Rect& r)
473 {
474 int i = 0;
475 if(ctrl) {
476 i = !ctrl->IsEnabled() || ctrl->IsReadOnly() ? CTRL_DISABLED
477 : button ? push : ctrl->HasFocus() ? CTRL_PRESSED
478 : mousein ? CTRL_HOT
479 : CTRL_NORMAL;
480 }
481 ChPaintEdge(w, r, edge[i]);
482 if(!IsNull(coloredge))
483 ChPaintEdge(w, r, coloredge, color);
484 }
485
FrameAddSize(Size & sz)486 void ActiveEdgeFrame::FrameAddSize(Size& sz)
487 {
488 Rect m = ChMargins(edge[0]);
489 sz.cx += m.left + m.right;
490 sz.cy += m.top + m.bottom;
491 }
492
Set(const Ctrl * ctrl_,const Value * edge_,bool active)493 void ActiveEdgeFrame::Set(const Ctrl *ctrl_, const Value *edge_, bool active)
494 {
495 ctrl = active ? ctrl_ : NULL;
496 edge = edge_;
497 }
498
499 }
500