CtrlLib: Coco MultiButton

git-svn-id: svn://ultimatepp.org/upp/trunk@12281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-09-17 10:01:04 +00:00
parent 6deb92c93e
commit 85ef74e429
10 changed files with 143 additions and 17 deletions

View file

@ -63,7 +63,7 @@ CGGlyph GetCharGlyph(CTFontRef ctfont, int chr)
return glyph_index;
}
GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr, bool bold_synth)
GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr, bool bold_synth, CGRect *bounds = NULL)
{
GlyphInfo gi;
gi.lspc = gi.rspc = 0;
@ -79,6 +79,10 @@ GlyphInfo GetGlyphInfoSys(CTFontRef ctfont, int chr, bool bold_synth)
gi.glyphi = glyph_index;
if(bold_synth)
gi.width++;
if(bounds)
CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontOrientationHorizontal,
&glyph_index, bounds, 1);
}
}
return gi;
@ -101,10 +105,33 @@ CommonFontInfo GetFontInfoSys(Font font)
DDUMP(CTFontGetUnderlinePosition(ctfont));
DDUMP(MakeRect(CTFontGetBoundingBox(ctfont)));
DDUMPHEX(CTFontGetSymbolicTraits(ctfont));
DDUMP(font);
CGRect cr = CTFontGetBoundingBox(ctfont);
DDUMP(cr.origin.y);
DDUMP(cr.size.height);
DDUMP(cr.origin.y + cr.size.height);
#endif
fi.descent = ceil(CTFontGetDescent(ctfont));
fi.ascent = ceil(CTFontGetAscent(ctfont));
fi.external = ceil(CTFontGetLeading(ctfont));
// Some MacOS fonts have really weird ascent/descents (namely stadard GUI font...)
// let us fix it by testing typical charactes bounding boxes
static WString descent_test = "yjgp";
CGRect bb;
for(int i = 0; i < descent_test.GetCount(); i++)
if(GetGlyphInfoSys(ctfont, descent_test[i], synth && font.IsBold(), &bb).IsNormal())
fi.descent = max(fi.descent, (int)ceil(-bb.origin.y));
int ascent = fi.ascent;
static WString ascent_test = "ÀÁÂÃÄË";
for(int i = 0; i < ascent_test.GetCount(); i++)
if(GetGlyphInfoSys(ctfont, ascent_test[i], synth && font.IsBold(), &bb).IsNormal())
ascent = max(ascent, (int)ceil(bb.origin.y + bb.size.height));
fi.ascent = ascent;
fi.internal = 0;
fi.overhang = 0;
fi.maxwidth = GetGlyphInfoSys(ctfont, 'W', synth && font.IsBold()).width; // TODO?
@ -138,7 +165,7 @@ Vector<FaceInfo> GetAllFacesSys()
{
Index<String> facename;
facename.Add("Arial"); // TODO: This should be default GUI font
facename.Add("Arial"); // This is default GUI font, changed afterward
facename.Add("Times New Roman");
facename.Add("Arial");
facename.Add("Courier New");

View file

@ -1,5 +1,8 @@
sooner:
- Assist popup has vertically missaligned text
- initial focus in uword
- clang install
- Information etc.. Images
- Ctrl gets stuck
- fix package organiser link options (joining link options missing space)

View file

@ -85,7 +85,7 @@ void CocoButton(Button::Style& s, int type, int value)
s.look[i] = h[i];
Image gg = CreateImage(h[i].GetSize(), SColorFace());
Over(gg, h[i]);
s.textcolor[i] = i == CTRL_DISABLED ? SColorDisabled()
s.monocolor[i] = s.textcolor[i] = i == CTRL_DISABLED ? SColorDisabled()
: Grayscale(AvgColor(gg, h[i].GetSize().cy / 3)) > 160 ? SColorText()
: White();
}
@ -103,6 +103,25 @@ Color CocoColor(int k, Color bg = SColorFace())
return AvgColor(Coco_ThemeImage(bg, 16, 16, 0, COCO_NSCOLOR, k));
}
Color GetInkColor(const Image& m)
{
int x = m.GetSize().cx / 2;
bool dark = !IsDark(SColorText());
int best = 1000;
Color bestc = SColorText();
for(int y = 0; y < m.GetHeight(); y++) {
Color c = m[y][x];
int g = Grayscale(c);
if(dark)
g = 255 - g;
if(g < best) {
best = g;
bestc = c;
}
}
return bestc;
}
void ChHostSkin()
{
CtrlImg::Reset();
@ -115,6 +134,8 @@ void ChHostSkin()
DUMP(Coco_Metric(0)); // kThemeMetricScrollBarWidth
DUMP(Coco_Metric(7)); // kThemeMetricFocusRectOutset
DUMP(Coco_Metric(19)); // kThemeMetricPushButtonHeight
int button_height = Coco_Metric(19); // kThemeMetricPushButtonHeight
SwapOKCancel_Write(true);
@ -185,6 +206,7 @@ void ChHostSkin()
Image thumb = Coco_ThemeImage(s.barsize, 50, 0, COCO_SCROLLTHUMB, 0, status);
Rect bounds = FindBounds(thumb);
thumb = Crop(thumb, Rect(0, bounds.top, thumb.GetWidth(), bounds.bottom));
thumb = AddMargins(thumb, 0, 1, 0, 1, RGBAZero());
s.vthumb[status] = Hot3(thumb);
s.hupper[status] = s.hlower[status] =
@ -192,9 +214,45 @@ void ChHostSkin()
thumb = Coco_ThemeImage(50, s.barsize, 0, COCO_SCROLLTHUMB, 1, status);
bounds = FindBounds(thumb);
thumb = Crop(thumb, Rect(bounds.left, 0, bounds.right, thumb.GetHeight()));
thumb = AddMargins(thumb, 1, 0, 1, 0 , RGBAZero());
s.hthumb[status] = Hot3(thumb);
}
}
ColoredOverride(CtrlsImg::Iml(), CtrlsImg::Iml());
{
Color e = GetInkColor(Coco_ThemeImage(SColorFace(), 100, 50, 10, COCO_COMBOBOX));
CtrlsImg::Set(CtrlsImg::I_EFE,
WithHotSpots(AddMargins(CreateImage(Size(1, 1), SColorPaper()), 1, 1, 1, 1, e),
1, 1, 0, 0));
CtrlsImg::Set(CtrlsImg::I_VE,
WithHotSpots(AddMargins(CreateImage(Size(3, 3), SColorPaper()), 1, 1, 1, 1, e),
2, 2, 0, 0));
MultiButton::Style& s = MultiButton::StyleDefault().Write();
// s.trivialsep = true;
// s.edge[0] = Null;
s.clipedge = true;
s.border = s.trivialborder = 0;
for(int i = CTRL_NORMAL; i <= CTRL_DISABLED; i++) {
Image m = Coco_ThemeImage(150, button_height + 1, 0, COCO_BUTTON, 1, i); // TODO: ChWithOffset...
Size isz = m.GetSize();
int x3 = isz.cx / 3;
s.left[i] = Hot3(Crop(m, 0, 0, x3, isz.cy));
s.trivial[i] = s.look[i] = s.right[i] = Hot3(Crop(m, 2 * x3, 0, isz.cx - 2 * x3, isz.cy));
m = Crop(m, x3, 0, x3, isz.cy);
s.lmiddle[i] = Hot3(AddMargins(m, 1, 0, 0, 0, SColorPaper()));
s.rmiddle[i] = Hot3(AddMargins(m, 0, 0, 1, 0, SColorPaper()));
s.monocolor[i] = s.fmonocolor[i] = Button::StyleOk().monocolor[i];
// Win32Look(s.look[i], XP_COMBOBOX, 4, i + 1);
}
}
// DDUMP(Coco_ThemeColor(1));

View file

@ -7,6 +7,7 @@ enum ChCocoControlTypes {
COCO_RADIOBUTTON,
COCO_BEVELBUTTON,
COCO_ROUNDEDBUTTON,
COCO_COMBOBOX,
COCO_SCROLLTHUMB,
COCO_SCROLLTRACK,
COCO_BRUSH,

View file

@ -94,6 +94,7 @@ void Coco_ThemePaint(void *cgcontext, const Upp::Rect& r, int type, int value, i
COCO_RADIOBUTTON, (int)kThemeRadioButton,
COCO_BEVELBUTTON, (int)kThemeBevelButtonMedium,
COCO_ROUNDEDBUTTON, (int)kThemeRoundedBevelButton,
COCO_COMBOBOX, (int)kThemeComboBox,
(int)kThemePushButtonNormal);
#ifdef _DEBUG
if(type < 0)

View file

@ -234,7 +234,7 @@ bool MultiButton::GetPos(SubButton& b, int& lx, int& rx, int& x, int& cx, int px
if(b.visible) {
cx = Nvl(b.cx, style->stdwidth + tsz.cx);
if(IsNull(b.cx) && tsz.cx > 0 && !IsNull(b.img))
cx += LB_IMAGE + LB_MARGIN;
cx += DPI(LB_IMAGE + LB_MARGIN);
}
else
cx = 0;
@ -263,6 +263,18 @@ void MultiButton::GetPos(int ii, int& x, int& cx)
}
}
void MultiButton::GetLR(int& lx, int& rx)
{
int border;
Metrics(border, lx, rx);
int x = 0;
int cx = 0;
for(int i = 0; i < button.GetCount(); i++) {
SubButton& b = button[i];
GetPos(b, lx, rx, x, cx);
}
}
int MultiButton::ChState(int i)
{
bool frm = Frame();
@ -343,8 +355,16 @@ Rect MultiButton::Paint0(Draw& w, bool getcr)
int border, lx, rx;
bool frm = Metrics(border, lx, rx);
int mst = ChState(MAIN);
if(frm && !nobg && !getcr)
if(frm && !nobg && !getcr) {
if(style->clipedge) {
int l, r;
GetLR(l, r);
w.Clip(l, 0, r - l, sz.cy);
}
ChPaint(w, sz, style->edge[style->activeedge ? mst : 0]);
if(style->clipedge)
w.End();
}
bool left = false;
bool right = false;
for(int i = 0; i < button.GetCount(); i++) {
@ -394,22 +414,24 @@ Rect MultiButton::Paint0(Draw& w, bool getcr)
Image m = tsz.cx > 0 ? b.img : (Image)Nvl(b.img, CtrlsImg::DA());
Size isz = m.GetSize();
Point p = (st == CTRL_PRESSED) * style->pressoffset;
p.x += x + (cx - isz.cx - tsz.cx - (tsz.cx > 0 && isz.cx > 0 ? LB_IMAGE : 0)) / 2;
p.x += x + (cx - isz.cx - tsz.cx - (tsz.cx > 0 && isz.cx > 0 ? DPI(LB_IMAGE) : 0)) / 2;
p.y += (sz.cy - isz.cy) / 2;
if(b.left) {
if(!left) p.x += style->loff;
}
else
if(!right) p.x += style->roff;
Color ink = frm ? style->fmonocolor[st] : style->monocolor[st];
if(b.monoimg || IsNull(b.img))
w.DrawImage(p.x, p.y, m, frm ? style->fmonocolor[st] : style->monocolor[st]);
w.DrawImage(p.x, p.y, m, ink);
else
w.DrawImage(p.x, p.y, m);
if(tsz.cx > 0) {
if(isz.cx > 0)
p.x += isz.cx + LB_IMAGE;
w.DrawText(p.x, (sz.cy - tsz.cy) / 2, b.label);
p.x += isz.cx + DPI(LB_IMAGE);
w.DrawText(p.x, (sz.cy - tsz.cy) / 2, b.label, StdFont(), ink);
}
}
(b.left ? left : right) = true;

View file

@ -21,26 +21,27 @@ public:
Value edge[4];
bool activeedge;
Value look[4];
Value left[4];
Value lmiddle[4];
Value right[4];
Value rmiddle[4];
Value left[4]; // leftmost button on the left side
Value lmiddle[4]; // other buttons on the left size
Value right[4]; // rightmost button on the right side
Value rmiddle[4]; // other buttons on the right size
Value simple[4];
int border;
Value trivial[4];
int trivialborder;
Color monocolor[4];
Color fmonocolor[4];
Point pressoffset;
Color monocolor[4]; // color of mono images and text in nonframe situation
Color fmonocolor[4]; // color of mono images and text in frame situation
Point pressoffset; // offset of images and text if button is pressed
Value sep1, sep2;
int sepm;
int stdwidth;
int stdwidth; // standard width of button
bool trivialsep;
bool usetrivial;
Rect margin;
int overpaint;
int loff, roff;
Color error;
bool clipedge; // Clip border edge so that it does not paint area where are buttons
};
class SubButton {
@ -109,6 +110,7 @@ private:
int FindButton(int px);
void Margins(int& l, int& r);
Rect ContentRect();
void GetLR(int& lx, int& rx);
bool GetPos(SubButton& b, int& lx, int& rx, int& x, int& cx, int px = -1);
void GetPos(int ii, int& x, int& cx);
int ChState(int i);

View file

@ -24,6 +24,7 @@ struct CommonFontInfo {
bool fixedpitch;
bool scaleable;
bool ttf;
int aux;
char path[256]; // optional
};

View file

@ -166,6 +166,15 @@ Image Crop(const Image& img, const Rect& rc)
return WithResolution(tgt, img);
}
Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color)
{
Size sz = img.GetSize();
ImageBuffer ib(sz.cx + left + right, sz.cy + top + bottom);
Fill(ib, color, ib.GetLength());
Copy(ib, Point(left, top), img, img.GetSize());
return ib;
}
Image Crop(const Image& img, int x, int y, int cx, int cy)
{
return Crop(img, RectC(x, y, cx, cy));

View file

@ -24,6 +24,8 @@ void Crop(RasterEncoder& tgt, Raster& img, const Rect& rc);
Image Crop(const Image& img, const Rect& rc);
Image Crop(const Image& img, int x, int y, int cx, int cy);
Image AddMargins(const Image& img, int left, int top, int right, int bottom, RGBA color);
Rect FindBounds(const Image& m, RGBA bg = RGBAZero());
Image AutoCrop(const Image& m, RGBA bg = RGBAZero());
void AutoCrop(Image *m, int count, RGBA bg = RGBAZero());