diff options
Diffstat (limited to 'menulist.c')
-rw-r--r-- | menulist.c | 68 |
1 files changed, 55 insertions, 13 deletions
@@ -13,7 +13,7 @@ enum { Menuborder = 2, Vspace = 2, Scrollwidth = 10, - Maxvisitems = 5, + Maxvisitems = 8, }; static char none[] = "none"; @@ -31,7 +31,11 @@ menulist_add(Menulist *ml, int id, char *title) ml->r.min.x = SCRW/2 - ew/2; ml->r.max.x = ml->r.min.x + ew; } - if(ml->nentries > 1) + + if(ml->nentries > Maxvisitems){ + ml->sr.min = subpt(ml->r.min, Pt(Scrollwidth+2*Menuborder,0)); + ml->sr.max = Pt(ml->r.min.x-2*Menuborder, ml->r.max.y); + }else if(ml->nentries > 1) ml->r.max.y += font->height+Vspace; } @@ -55,16 +59,45 @@ menulist_clear(Menulist *ml) ml->r.max = addpt(ml->r.min, Pt(w, font->height+Vspace)); ml->sr = ZR; ml->high = -1; + ml->off = 0; } -static void -menulist_update(Menulist *ml, Mousectl *mc) +static int +menulist_update(Menulist *ml, Mousectl *mc, Channel *drawchan) { - if(ptinrect(mc->xy, ml->r)){ - /* item highlighting and selection */ - }else if(ptinrect(mc->xy, ml->sr)){ - /* scrolling */ + /* redundant from bts.c:/^mouse\(, but it's necessary to avoid overdrawing */ + static Mouse oldm; + static ulong lastlmbms; + int selected; + + selected = -1; + if(ptinrect(mc->xy, Rpt(ml->sr.min, ml->r.max))){ + if(ptinrect(mc->xy, ml->r)){ + /* item highlighting and selection */ + ml->high = ml->off + (mc->xy.y - ml->r.min.y)/(font->height+Vspace); + if(oldm.buttons != mc->buttons && mc->buttons == 1){ + if(mc->msec-lastlmbms < 500) + selected = ml->high; + else + lastlmbms = mc->msec; + } + } + if(mc->buttons != oldm.buttons && ml->nentries > Maxvisitems) + /* scrolling */ + switch(mc->buttons){ + case 1: if(!ptinrect(mc->xy, ml->sr)) break; + case 8: + ml->off = max(0, ml->off - (mc->xy.y - ml->sr.min.y)/(font->height+Vspace)); + break; + case 4: if(!ptinrect(mc->xy, ml->sr)) break; + case 16: + ml->off = min(ml->off + (mc->xy.y - ml->sr.min.y)/(font->height+Vspace), ml->nentries-Maxvisitems); + break; + } } + nbsendp(drawchan, nil); + oldm = mc->Mouse; + return selected; } static void @@ -72,7 +105,7 @@ menulist_draw(Menulist *ml, Image *dst) { static Image *bc; Rectangle tr, er; /* title and per-entry */ - int i; + int i, width; if(ml->filling) return; @@ -81,18 +114,20 @@ menulist_draw(Menulist *ml, Image *dst) bc = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); /* draw title */ + width = stringwidth(font, ml->title); tr.min = subpt(ml->r.min, Pt(0,Menuborder + font->height+Vspace)); tr.max = Pt(ml->r.max.x, ml->r.min.y - Menuborder); draw(dst, tr, display->black, nil, ZP); - string(dst, tr.min, display->white, ZP, font, ml->title); + string(dst, addpt(tr.min, Pt(Dx(tr)/2 - width/2,0)), display->white, ZP, font, ml->title); /* draw content */ border(dst, ml->r, -Menuborder, bc, ZP); er.min = ml->r.min; er.max = Pt(ml->r.max.x, er.min.y + font->height+Vspace); - for(i = 0; i < ml->nentries; i++){ - draw(dst, er, display->white, nil, ZP); - string(dst, er.min, display->black, ZP, font, ml->entries[i].title); + for(i = ml->off; i < ml->nentries && er.min.y < ml->r.max.y; i++){ + width = stringwidth(font, ml->entries[i].title); + draw(dst, er, i == ml->high? display->black: display->white, nil, ZP); + string(dst, addpt(er.min, Pt(Dx(er)/2 - width/2,0)), i == ml->high? display->white: display->black, ZP, font, ml->entries[i].title); er.min.y += font->height+Vspace; er.max.y = er.min.y + font->height+Vspace; } @@ -100,6 +135,13 @@ menulist_draw(Menulist *ml, Image *dst) draw(dst, er, display->white, nil, ZP); string(dst, er.min, display->black, ZP, font, none); } + + /* draw scroll */ + if(ml->nentries > Maxvisitems){ + border(dst, ml->sr, -Menuborder, bc, ZP); + draw(dst, ml->sr, display->black, nil, ZP); + draw(dst, Rpt(addpt(ml->sr.min, Pt(0,ml->off*Dy(ml->sr)/ml->nentries)), Pt(ml->sr.max.x,ml->sr.min.y + (ml->off+Maxvisitems)*Dy(ml->sr)/ml->nentries)), display->white, nil, ZP); + } } Menulist * |