diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libtk/frame.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libtk/frame.c')
| -rw-r--r-- | libtk/frame.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/libtk/frame.c b/libtk/frame.c new file mode 100644 index 00000000..fdd39b16 --- /dev/null +++ b/libtk/frame.c @@ -0,0 +1,277 @@ +#include <lib9.h> +#include <kernel.h> +#include "draw.h" +#include "tk.h" +#include "frame.h" + +char* +tkframe(TkTop *t, char *arg, char **ret) +{ + Tk *tk; + char *e; + TkOptab tko[2]; + TkName *names; + + tk = tknewobj(t, TKframe, sizeof(Tk)); + if(tk == nil) + return TkNomem; + + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = nil; + names = nil; + + e = tkparse(t, arg, tko, &names); + if(e != nil) { + tkfreeobj(tk); + return e; + } + tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); + + e = tkaddchild(t, tk, &names); + + tkfreename(names); + if(e != nil) { + tkfreeobj(tk); + return e; + } + tk->name->link = nil; + + return tkvalue(ret, "%s", tk->name->name); +} + +/* + * Also used for windows, menus, separators + */ +void +tkfreeframe(Tk *tk) +{ + TkWin *tkw; + + if((tk->flag & Tkwindow) == 0) + return; + + if(tk->type == TKmenu) { + tkw = TKobj(TkWin, tk); + free(tkw->postcmd); + free(tkw->cascade); + free(tkw->cbname); + } + + tkunmap(tk); /* XXX do this only if (tk->flag&Tkswept)==0 ?? */ +} + +char* +tkdrawframe(Tk *tk, Point orig) +{ + int bw; + Point p; + Image *i; + Tk *f; + Rectangle r, slaver; /* dribbling, whipping or just square? */ + + i = tkimageof(tk); + if(i == nil) + return nil; + + p.x = orig.x + tk->act.x + tk->borderwidth; + p.y = orig.y + tk->act.y + tk->borderwidth; + + draw(i, rectaddpt(tk->dirty, p), tkgc(tk->env, TkCbackgnd), nil, ZP); + + /* + * doesn't matter about drawing TKseparator + * oblivious of dirty rect, as it never has any children to sully anyway + */ + if(tk->type == TKseparator) { + r = rectaddpt(tkrect(tk, 1), p); + r.min.x += 4; + r.max.x -= 4; + r.min.y += (Dy(r) - 2)/2; + r.max.y = r.min.y+1; + draw(i, r, tkgc(tk->env, TkCbackgnddark), nil, ZP); + r.min.y += 1; + r.max.y += 1; + draw(i, r, tkgc(tk->env, TkCbackgndlght), nil, ZP); + return nil; + } + + /* + * make sure all the slaves inside the area we've just drawn + * refresh themselves properly. + */ + for(f = tk->slave; f; f = f->next) { + bw = f->borderwidth; + slaver.min.x = f->act.x; + slaver.min.y = f->act.y; + slaver.max.x = slaver.min.x + f->act.width + 2*bw; + slaver.max.y = slaver.min.y + f->act.height + 2*bw; + if (rectclip(&slaver, tk->dirty)) { + f->flag |= Tkrefresh; + slaver = rectsubpt(slaver, Pt(f->act.x + bw, f->act.y + bw)); + combinerect(&f->dirty, slaver); + } + } + p.x -= tk->borderwidth; + p.y -= tk->borderwidth; + + if (!rectinrect(tk->dirty, tkrect(tk, 0))) + tkdrawrelief(i, tk, p, TkCbackgnd, tk->relief); + return nil; +} + +/* Frame commands */ + +static char* +tkframecget(Tk *tk, char *arg, char **val) +{ + TkOptab tko[3]; + + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = nil; + if(tk->flag & Tkwindow){ + tko[1].ptr = TKobj(TkWin, tk); + tko[1].optab = tktop; + tko[2].ptr = nil; + } + + return tkgencget(tko, arg, val, tk->env->top); +} + +static char* +tkframeconf(Tk *tk, char *arg, char **val) +{ + char *e; + TkGeom g; + int bd; + Point oldp; + TkOptab tko[3]; + TkWin *tkw; + + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = nil; + tkw = nil; + if(tk->flag & Tkwindow) { + tkw = TKobj(TkWin, tk); + tko[1].ptr = tkw; + tko[1].optab = tktop; + tko[2].ptr = nil; + oldp = tkw->act; + } + + if(*arg == '\0') + return tkconflist(tko, val); + + if(tkw != nil){ + /* + * see whether only -x or -y is being configured, + * in which case just move the window; don't redraw + * everything + */ + e = tkparse(tk->env->top, arg, &tko[1], nil); + if(e == nil){ + if(!eqpt(oldp, tkw->req)) + tkmovewin(tk, tkw->req); + return nil; + } + } + + g = tk->req; + bd = tk->borderwidth; + e = tkparse(tk->env->top, arg, tko, nil); + tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); + tk->req.x = tk->act.x; + tk->req.y = tk->act.y; + tkgeomchg(tk, &g, bd); + if(tkw != nil && !eqpt(oldp, tkw->act)) + tkmovewin(tk, tkw->req); + + tk->dirty = tkrect(tk, 1); + + return e; +} + +static char* +tkframesuspend(Tk *tk, char *arg, char **val) +{ + USED(arg); + USED(val); + if((tk->flag & Tkwindow) == 0) + return TkNotwm; + tk->flag |= Tksuspended; + return nil; +} + +static char* +tkframemap(Tk *tk, char *arg, char **val) +{ + USED(arg); + USED(val); + if(tk->flag & Tkwindow) + return tkmap(tk); + return TkNotwm; +} + +static char* +tkframeunmap(Tk *tk, char *arg, char **val) +{ + USED(arg); + USED(val); + if(tk->flag & Tkwindow) { + tkunmap(tk); + return nil; + } + return TkNotwm; +} + +static void +tkframefocusorder(Tk *tk) +{ + int i, n; + Tk *sub; + TkWinfo *inf; + + n = 0; + for (sub = tk->slave; sub != nil; sub = sub->next) + n++; + + if (n == 0) + return; + + inf = malloc(sizeof(*inf) * n); + if (inf == nil) + return; + i = 0; + for (sub = tk->slave; sub != nil; sub = sub->next) { + inf[i].w = sub; + inf[i].r = rectaddpt(tkrect(sub, 1), Pt(sub->act.x, sub->act.y)); + i++; + } + tksortfocusorder(inf, n); + for (i = 0; i < n; i++) + tkappendfocusorder(inf[i].w); + free(inf); +} + +static +TkCmdtab tkframecmd[] = +{ + "cget", tkframecget, + "configure", tkframeconf, + "map", tkframemap, + "unmap", tkframeunmap, + "suspend", tkframesuspend, + nil +}; + +TkMethod framemethod = { + "frame", + tkframecmd, + tkfreeframe, + tkdrawframe, + nil, + nil, + tkframefocusorder +}; |
