static void GScrollBarFit(GScrollBar *gsb) { int minheight; gsb->sbborder = GBoxBorderWidth(gsb->g.base,gsb->g.box); gsb->thumbborder = GBoxBorderWidth(gsb->g.base,gsb->thumbbox); gsb->arrowsize = gsb->sbborder + 2*GDrawPointsToPixels(gsb->g.base,2) + GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width)/2- 2*GDrawPointsToPixels(gsb->g.base,1); minheight = 2*(gsb->thumbborder+gsb->arrowsize) + GDrawPointsToPixels(gsb->g.base,2); if ( gsb->g.vert ) { if ( gsb->g.r.width==0 ) gsb->g.r.width = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width); if ( gsb->g.r.height< minheight ) gsb->g.r.height = minheight; gsb->g.inner.x = gsb->g.r.x+gsb->sbborder; gsb->g.inner.width = gsb->g.r.width - 2*gsb->sbborder; gsb->g.inner.y = gsb->g.r.y+gsb->arrowsize; gsb->g.inner.height = gsb->g.r.height - 2*gsb->arrowsize; } else { if ( gsb->g.r.height==0 ) gsb->g.r.height = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width); if ( gsb->g.r.width< minheight ) gsb->g.r.width = minheight; gsb->g.inner.x = gsb->g.r.x+gsb->arrowsize; gsb->g.inner.width = gsb->g.r.width - 2*gsb->arrowsize; gsb->g.inner.y = gsb->g.r.y+gsb->sbborder; gsb->g.inner.height = gsb->g.r.height - 2*gsb->sbborder; } }
/* row is at least as wide as the row above it */ static void GTabSetFigureWidths(GTabSet *gts) { int bp = GBoxBorderWidth(gts->g.base,gts->g.box) + GDrawPointsToPixels(gts->g.base,5); int i, rd; int oldwidth=0, width; /* set all row widths to default values */ for ( i=0; i<gts->tabcnt; ++i ) { gts->tabs[i].width = gts->tabs[i].tw + 2*bp; } /* r is real row, rd is drawn pos */ /* rd is 0 at the top of the ggadget */ /* r is 0 when it contains tabs[0], (the index in the rowstarts array) */ if ( ( gts->filllines && gts->rcnt>1 ) || (gts->fill1line && gts->rcnt==1) ) { for ( rd = 0; rd<gts->rcnt; ++rd ) { int r = (rd+gts->rcnt-1-gts->active_row)%gts->rcnt; int totwidth = gts->g.r.width-2*GBoxBorderWidth(gts->g.base,gts->g.box) - (gts->rcnt-1-rd)*gts->offset_per_row; width = GTabSetGetLineWidth(gts,r); GTabSetDistributePixels(gts,r,totwidth-width); } } else { for ( rd = 0; rd<gts->rcnt; ++rd ) { /* r is real row, rd is drawn pos */ int r = (rd+gts->rcnt-1-gts->active_row)%gts->rcnt; width = GTabSetGetLineWidth(gts,r) + (gts->rcnt-1-rd)*gts->offset_per_row; if ( rd==0 ) oldwidth = width; else if ( oldwidth>width ) GTabSetDistributePixels(gts,r,oldwidth-width); else oldwidth = width; } } }
static void gscrollbar_get_desired_size(GGadget *g, GRect *outer, GRect *inner) { int bp = GBoxBorderWidth(g->base,g->box); GScrollBar *gsb = (GScrollBar *) g; int width, height; int minheight, sbw; sbw = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width); minheight = 2*(gsb->thumbborder+gsb->arrowsize) + GDrawPointsToPixels(gsb->g.base,2); if ( g->vert ) { width = sbw; height = minheight; } else { width = minheight; height = sbw; } if ( inner!=NULL ) { inner->x = inner->y = 0; inner->width = width; inner->height = height; } if ( outer!=NULL ) { outer->x = outer->y = 0; outer->width = width+2*bp; outer->height = height+2*bp; } }
static void GGroupGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) { if ( outer!=NULL ) { int bp = GBoxBorderWidth(g->base,g->box); outer->x = outer->y = 0; outer->width = outer->height = 2*bp+2; if ( g->desired_width>0 ) outer->width = g->desired_width; if ( g->desired_height>0 ) outer->height = g->desired_height; } if ( inner!=NULL ) { inner->x = inner->y = 0; inner->width = inner->height = 1; } }
static void GLineFit(GGadget *g) { int bp = GBoxBorderWidth(g->base,g->box); if ( g->r.width==0 && !g->vert ) { GRect size; GDrawGetSize(g->base,&size); g->r.width = size.width - g->r.x - GDrawPointsToPixels(g->base,_GGadget_Skip); } if ( g->r.height==0 && !g->vert ) g->r.height = bp; if ( g->r.width==0 && g->vert ) g->r.width = bp; g->inner = g->r; g->inner.width = g->inner.height = 0; }
static int GTabSetRCnt(GTabSet *gts, int totwidth) { int i, off, r, width; int bp = GBoxBorderWidth(gts->g.base,gts->g.box) + GDrawPointsToPixels(gts->g.base,5); width = totwidth; for ( i = off = r = 0; i<gts->tabcnt; ++i ) { if ( off!=0 && width-(gts->tabs[i].tw+2*bp)< 0 ) { off = 0; ++r; width = totwidth; } width -= gts->tabs[i].width; gts->tabs[i].x = off; off ++; } return( r+1 ); }
static void GGroupFit(GGadget *g) { int bp = GBoxBorderWidth(g->base,g->box); if ( g->r.width==0 || g->r.height==0 ) g->opengroup = true; g->inner = g->r; g->inner.x += bp; if ( g->prevlabel ) g->inner.y += (g->prev->r.height-bp)/2 + bp; else g->inner.y += bp; if ( g->r.width != 0 ) g->inner.width = g->r.width - 2*bp; if ( g->r.height != 0 ) g->inner.height = g->r.y + g->r.height - bp - g->inner.y; }
static int ggroup_expose(GWindow pixmap, GGadget *g, GEvent *event) { GRect old1, border; if ( g->state == gs_invisible ) return( false ); GDrawPushClip(pixmap,&g->r,&old1); /* Background should be transpearant */ /*GBoxDrawBackground(pixmap,&g->r,g->box, g->state,false);*/ border = g->r; if ( g->prevlabel ) { int off = (g->prev->r.height-GBoxBorderWidth(g->base,g->box))/2; border.y += off; border.height -= off; } GBoxDrawBorder(pixmap,&border,g->box,g->state,false); GDrawPopClip(pixmap,&old1); return( true ); }
static int gtabset_mouse(GGadget *g, GEvent *event) { GTabSet *gts = (GTabSet *) g; if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused )) return( false ); if ( gts->nested_mouse!=NULL ) if ( (gts->nested_mouse)(g,event)) return( true ); if ( event->type == et_crossing ) { return( true ); } else if ( event->type == et_mousemove ) { return( true ); } else { int i, sel= -1, l; if ( event->u.mouse.y < gts->g.r.y || ( !gts->vertical && event->u.mouse.y >= gts->g.inner.y ) || ( gts->vertical && event->u.mouse.x >= gts->g.inner.x )) return( false ); else if ( gts->vertical ) { int y = g->r.y + GBoxBorderWidth(g->base,g->box) + 5; sel = (event->u.mouse.y-y)/gts->fh + gts->offtop; if ( sel<0 || sel>=gts->tabcnt ) return(false); } else if ( gts->scrolled ) { if ( gts->haslarrow && event->u.mouse.x<gts->tabs[gts->toff].x ) sel = -2; /* left arrow */ else { for ( i=gts->toff; i<gts->tabcnt && event->u.mouse.x>=gts->tabs[i].x+gts->tabs[i].width; ++i ); if ( gts->hasrarrow && gts->tabs[i].x==0x7fff && event->u.mouse.x>=gts->tabs[i-1].x+gts->tabs[i-1].width ) sel = -3; else sel = i; } } else { l = (event->u.mouse.y-gts->g.r.y)/gts->rowh; /* screen row */ if ( l>=gts->rcnt ) l = gts->rcnt-1; /* can happen on single line tabsets (there's extra space then) */ l = (gts->rcnt-1-l+gts->active_row)%gts->rcnt; /* internal row number */ if ( event->u.mouse.x<gts->tabs[gts->rowstarts[l]].x ) sel = -1; else if ( event->u.mouse.x>=gts->tabs[gts->rowstarts[l+1]-1].x+gts->tabs[gts->rowstarts[l+1]-1].width ) sel = -1; else { for ( i=gts->rowstarts[l]; i<gts->rowstarts[l+1] && event->u.mouse.x>=gts->tabs[i].x+gts->tabs[i].width; ++i ); sel = i; } } if ( event->type==et_mousedown ) { gts->pressed = true; gts->pressed_sel = sel; } else { if ( gts->pressed && gts->pressed_sel == sel ) GTabSetChangeSel(gts,sel,true); gts->pressed = false; gts->pressed_sel = -1; } } return( true ); }
/* between those rows, and then the widths of each tab */ static void GTabSet_Remetric(GTabSet *gts) { int bbp = GBoxBorderWidth(gts->g.base,gts->g.box); int bp = bbp + GDrawPointsToPixels(gts->g.base,5); int r, r2, width, i; int as, ds, ld; int ni = GDrawPointsToPixels(gts->g.base,NEST_INDENT), in; GDrawSetFont(gts->g.base,gts->font); GDrawWindowFontMetrics(gts->g.base,gts->font,&as,&ds,&ld); gts->as = as; gts->fh = as+ds; gts->rowh = as+ds + bbp+GDrawPointsToPixels(gts->g.base,3); gts->ds = ds + bbp+GDrawPointsToPixels(gts->g.base,1); gts->arrow_size = as+ds; gts->arrow_width = gts->arrow_size + 2*GBoxBorderWidth(gts->g.base,gts->g.box); gts->vert_list_width = 0; for ( i=0; i<gts->tabcnt; ++i ) { gts->tabs[i].tw = GDrawGetTextWidth(gts->g.base,gts->tabs[i].name,-1); gts->tabs[i].width = gts->tabs[i].tw + 2*bp; in = gts->tabs[i].nesting*ni; if ( gts->tabs[i].tw+in > gts->vert_list_width ) gts->vert_list_width = gts->tabs[i].tw+in; } if ( gts->vsb ) { gts->vert_list_width += gts->vsb->r.width; if ( gts->g.inner.height>26 ) { int bp = GBoxBorderWidth(gts->g.base,gts->g.box); GScrollBarSetBounds(gts->vsb,0,gts->tabcnt,(gts->g.r.height-2*bp-6)/gts->fh); } } gts->vert_list_width += 8; if ( gts->vertical ) { /* Nothing much to do */ } else if ( gts->scrolled ) { free(gts->rowstarts); gts->rowstarts = malloc(2*sizeof(16)); gts->rowstarts[0] = 0; gts->rowstarts[1] = gts->tabcnt; gts->rcnt = 1; } else { width = gts->g.r.width-2*GBoxBorderWidth(gts->g.base,gts->g.box); r = GTabSetRCnt(gts,width); if ( gts->offset_per_row!=0 && r>1 ) while ( (r2 = GTabSetRCnt(gts,width-(r-1)*gts->offset_per_row))!=r ) r = r2; free(gts->rowstarts); gts->rowstarts = malloc((r+1)*sizeof(int16)); gts->rcnt = r; gts->rowstarts[r] = gts->tabcnt; for ( i=r=0; i<gts->tabcnt; ++i ) { if ( gts->tabs[i].x==0 ) gts->rowstarts[r++] = i; } /* if there is a single tab on the last line and there are more on */ /* the previous line, then things look nicer if we move one of the */ /* tabs from the previous line onto the last line */ /* Providing it fits, of course */ if ( gts->rowstarts[r]-gts->rowstarts[r-1]==1 && r>1 && gts->rowstarts[r-1]-gts->rowstarts[r-2]>1 && gts->tabs[i-1].width+gts->tabs[i-2].width < width-(r-1)*gts->offset_per_row ) --gts->rowstarts[r-1]; GTabSetFigureWidths(gts); } }
static int gtabset_expose(GWindow pixmap, GGadget *g, GEvent *event) { GTabSet *gts = (GTabSet *) g; int x,y,i,rd, dsel; GRect old1, bounds; int bw = GBoxBorderWidth(pixmap,g->box); int yoff = ( gts->rcnt==1 ? bw : 0 ); Color fg; int ni = GDrawPointsToPixels(pixmap,NEST_INDENT); if ( g->state == gs_invisible ) return( false ); GDrawPushClip(pixmap,&g->r,&old1); GBoxDrawBackground(pixmap,&g->r,g->box,g->state,false); bounds = g->r; if ( !gts->vertical ) { /* make room for tabs */ bounds.y += gts->rcnt*gts->rowh+yoff-1; bounds.height -= gts->rcnt*gts->rowh+yoff-1; /* draw border around horizontal tabs only */ GBoxDrawBorder(pixmap,&bounds,g->box,g->state,false); } else if ( g->state==gs_enabled ) { /* background for labels */ GRect old2, vertListRect = g->r; vertListRect.width = gts->vert_list_width+bw-1; GDrawPushClip(pixmap,&vertListRect,&old2); GBoxDrawBackground(pixmap,&g->r,g->box,gs_pressedactive,false); GDrawPopClip(pixmap,&old2); } GDrawSetFont(pixmap,gts->font); if ( gts->vertical ) { x = g->r.x + bw + 3; y = g->r.y + bw + 3; for ( i=gts->offtop; i<gts->tabcnt; ++i ) { fg = gts->tabs[i].disabled?gts->g.box->disabled_foreground:gts->g.box->main_foreground; if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)); if ( i==gts->sel ) { GRect r; r.x = x; r.y = y; r.width = gts->vert_list_width-10; r.height = gts->fh; GDrawFillRect(pixmap,&r,gts->g.box->active_border); } GDrawDrawText(pixmap,x+gts->tabs[i].nesting*ni,y + gts->as,gts->tabs[i].name,-1,fg); y += gts->fh; } fg = gts->g.box->main_foreground; if ( fg==COLOR_DEFAULT ) fg = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)); GDrawDrawLine(pixmap,x + gts->vert_list_width-4, g->r.y + bw, x + gts->vert_list_width-4, g->r.y + g->r.height - (bw+1), fg); if ( gts->vsb != NULL ) gts->vsb->funcs->handle_expose(pixmap,gts->vsb,event); } else { gts->haslarrow = gts->hasrarrow = false; if ( gts->scrolled ) { x = g->r.x + GBoxBorderWidth(pixmap,gts->g.box); y = g->r.y+yoff; dsel = 0; if ( gts->toff!=0 ) x = DrawLeftArrowTab(pixmap,gts,x,y); for ( i=gts->toff; (i==gts->tabcnt-1 && x+gts->tabs[i].width < g->r.width) || (i<gts->tabcnt-1 && x+gts->tabs[i].width < g->r.width-gts->arrow_width ) ; ++i ) { if ( i!=gts->sel ) x = DrawTab(pixmap,gts,i,x,y); else { gts->tabs[i].x = x; x += gts->tabs[i].width; dsel = 1; } } if ( i!=gts->tabcnt ) { int p = gts->g.inner.x+gts->g.inner.width - gts->arrow_width; if ( p>x ) x=p; x = DrawRightArrowTab(pixmap,gts,x,y); gts->tabs[i].x = 0x7fff; } /* This one draws on top of the others, must come last */ if ( dsel ) DrawTab(pixmap,gts,gts->sel,gts->tabs[gts->sel].x, g->r.y + (gts->rcnt-1) * gts->rowh + yoff ); } else { /* r is real row, rd is drawn pos */ /* rd is 0 at the top of the ggadget */ /* r is 0 when it contains tabs[0], (the index in the rowstarts array) */ for ( rd = 0; rd<gts->rcnt; ++rd ) { int r = (gts->rcnt-1-rd+gts->active_row)%gts->rcnt; y = g->r.y + rd * gts->rowh + yoff; x = g->r.x + (gts->rcnt-1-rd) * gts->offset_per_row + GBoxBorderWidth(pixmap,gts->g.box); for ( i = gts->rowstarts[r]; i<gts->rowstarts[r+1]; ++i ) if ( i==gts->sel ) { gts->tabs[i].x = x; x += gts->tabs[i].width; } else x = DrawTab(pixmap,gts,i,x,y); } /* This one draws on top of the others, must come last */ DrawTab(pixmap,gts,gts->sel,gts->tabs[gts->sel].x, g->r.y + (gts->rcnt-1) * gts->rowh + yoff ); } } if ( gts->nested_expose ) (gts->nested_expose)(pixmap,g,event); GDrawPopClip(pixmap,&old1); return( true ); }