123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- implement Columnm;
- include "common.m";
- sys : Sys;
- utils : Utils;
- drawm : Draw;
- acme : Acme;
- graph : Graph;
- gui : Gui;
- dat : Dat;
- textm : Textm;
- rowm : Rowm;
- filem : Filem;
- windowm : Windowm;
- FALSE, TRUE, XXX : import Dat;
- Border : import Dat;
- mouse, colbutton : import dat;
- Point, Rect, Image : import drawm;
- draw : import graph;
- min, max, abs, error, clearmouse : import utils;
- black, white, mainwin : import gui;
- Text : import textm;
- Row : import rowm;
- Window : import windowm;
- File : import filem;
- Columntag : import Textm;
- BACK : import Framem;
- tagcols, textcols : import acme;
- init(mods : ref Dat->Mods)
- {
- sys = mods.sys;
- dat = mods.dat;
- utils = mods.utils;
- drawm = mods.draw;
- acme = mods.acme;
- graph = mods.graph;
- gui = mods.gui;
- textm = mods.textm;
- rowm = mods.rowm;
- filem = mods.filem;
- windowm = mods.windowm;
- }
- Column.init(c : self ref Column, r : Rect)
- {
- r1 : Rect;
- t : ref Text;
- dummy : ref File = nil;
- draw(mainwin, r, white, nil, (0, 0));
- c.r = r;
- c.row = nil;
- c.w = nil;
- c.nw = 0;
- c.tag = textm->newtext();
- t = c.tag;
- t.w = nil;
- t.col = c;
- r1 = r;
- r1.max.y = r1.min.y + (graph->font).height;
- t.init(dummy.addtext(t), r1, dat->reffont, tagcols);
- t.what = Columntag;
- r1.min.y = r1.max.y;
- r1.max.y += Border;
- draw(mainwin, r1, black, nil, (0, 0));
- t.insert(0, "New Cut Paste Snarf Sort Zerox Delcol ", 38, TRUE, 0);
- t.setselect(t.file.buf.nc, t.file.buf.nc);
- draw(mainwin, t.scrollr, colbutton, nil, colbutton.r.min);
- c.safe = TRUE;
- }
- Column.add(c : self ref Column, w : ref Window, clone : ref Window, y : int) : ref Window
- {
- r, r1 : Rect;
- v : ref Window;
- i, t : int;
- v = nil;
- r = c.r;
- r.min.y = c.tag.frame.r.max.y+Border;
- if(y<r.min.y && c.nw>0){ # steal half of last window by default
- v = c.w[c.nw-1];
- y = v.body.frame.r.min.y+v.body.frame.r.dy()/2;
- }
- # look for window we'll land on
- for(i=0; i<c.nw; i++){
- v = c.w[i];
- if(y < v.r.max.y)
- break;
- }
- if(c.nw > 0){
- if(i < c.nw)
- i++; # new window will go after v
- #
- # if v's too small, grow it first.
- #
-
- if(!c.safe || v.body.frame.maxlines<=3){
- c.grow(v, 1, 1);
- y = v.body.frame.r.min.y+v.body.frame.r.dy()/2;
- }
- r = v.r;
- if(i == c.nw)
- t = c.r.max.y;
- else
- t = c.w[i].r.min.y-Border;
- r.max.y = t;
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- r1 = r;
- y = min(y, t-(v.tag.frame.font.height+v.body.frame.font.height+Border+1));
- r1.max.y = min(y, v.body.frame.r.min.y+v.body.frame.nlines*v.body.frame.font.height);
- r1.min.y = v.reshape(r1, FALSE);
- r1.max.y = r1.min.y+Border;
- draw(mainwin, r1, black, nil, (0, 0));
- r.min.y = r1.max.y;
- }
- if(w == nil){
- w = ref Window;
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- w.col = c;
- w.init(clone, r);
- }else{
- w.col = c;
- w.reshape(r, FALSE);
- }
- w.tag.col = c;
- w.tag.row = c.row;
- w.body.col = c;
- w.body.row = c.row;
- ocw := c.w;
- c.w = array[c.nw+1] of ref Window;
- c.w[0:] = ocw[0:i];
- c.w[i+1:] = ocw[i:c.nw];
- ocw = nil;
- c.nw++;
- c.w[i] = w;
- utils->savemouse(w);
- # near but not on the button
- graph->cursorset(w.tag.scrollr.max.add(Point(3, 3)));
- dat->barttext = w.body;
- c.safe = TRUE;
- return w;
- }
- Column.close(c : self ref Column, w : ref Window, dofree : int)
- {
- r : Rect;
- i : int;
- # w is locked
- if(!c.safe)
- c.grow(w, 1, 1);
- for(i=0; i<c.nw; i++)
- if(c.w[i] == w)
- break;
- if (i == c.nw)
- error("can't find window");
- r = w.r;
- w.tag.col = nil;
- w.body.col = nil;
- w.col = nil;
- utils->restoremouse(w);
- if(dofree){
- w.delete();
- w.close();
- }
- ocw := c.w;
- c.w = array[c.nw-1] of ref Window;
- c.w[0:] = ocw[0:i];
- c.w[i:] = ocw[i+1:c.nw];
- ocw = nil;
- c.nw--;
- if(c.nw == 0){
- draw(mainwin, r, white, nil, (0, 0));
- return;
- }
- if(i == c.nw){ # extend last window down
- w = c.w[i-1];
- r.min.y = w.r.min.y;
- r.max.y = c.r.max.y;
- }else{ # extend next window up
- w = c.w[i];
- r.max.y = w.r.max.y;
- }
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- if(c.safe)
- w.reshape(r, FALSE);
- }
- Column.closeall(c : self ref Column)
- {
- i : int;
- w : ref Window;
- if(c == dat->activecol)
- dat->activecol = nil;
- c.tag.close();
- for(i=0; i<c.nw; i++){
- w = c.w[i];
- w.close();
- }
- c.nw = 0;
- c.w = nil;
- c = nil;
- clearmouse();
- }
- Column.mousebut(c : self ref Column)
- {
- graph->cursorset(c.tag.scrollr.min.add(c.tag.scrollr.max).div(2));
- }
- Column.reshape(c : self ref Column, r : Rect)
- {
- i : int;
- r1, r2 : Rect;
- w : ref Window;
- clearmouse();
- r1 = r;
- r1.max.y = r1.min.y + c.tag.frame.font.height;
- c.tag.reshape(r1);
- draw(mainwin, c.tag.scrollr, colbutton, nil, colbutton.r.min);
- r1.min.y = r1.max.y;
- r1.max.y += Border;
- draw(mainwin, r1, black, nil, (0, 0));
- r1.max.y = r.max.y;
- for(i=0; i<c.nw; i++){
- w = c.w[i];
- w.maxlines = 0;
- if(i == c.nw-1)
- r1.max.y = r.max.y;
- else
- r1.max.y = r1.min.y+(w.r.dy()+Border)*r.dy()/c.r.dy();
- r2 = r1;
- r2.max.y = r2.min.y+Border;
- draw(mainwin, r2, black, nil, (0, 0));
- r1.min.y = r2.max.y;
- r1.min.y = w.reshape(r1, FALSE);
- }
- c.r = r;
- }
- colcmp(a : ref Window, b : ref Window) : int
- {
- r1, r2 : string;
- r1 = a.body.file.name;
- r2 = b.body.file.name;
- if (r1 < r2)
- return -1;
- if (r1 > r2)
- return 1;
- return 0;
- }
- qsort(a : array of ref Window, n : int)
- {
- i, j : int;
- t : ref Window;
- while(n > 1) {
- i = n>>1;
- t = a[0]; a[0] = a[i]; a[i] = t;
- i = 0;
- j = n;
- for(;;) {
- do
- i++;
- while(i < n && colcmp(a[i], a[0]) < 0);
- do
- j--;
- while(j > 0 && colcmp(a[j], a[0]) > 0);
- if(j < i)
- break;
- t = a[i]; a[i] = a[j]; a[j] = t;
- }
- t = a[0]; a[0] = a[j]; a[j] = t;
- n = n-j-1;
- if(j >= n) {
- qsort(a, j);
- a = a[j+1:];
- } else {
- qsort(a[j+1:], n);
- n = j;
- }
- }
- }
- Column.sort(c : self ref Column)
- {
- i, y : int;
- r, r1 : Rect;
- rp : array of Rect;
- w : ref Window;
- wp : array of ref Window;
- if(c.nw == 0)
- return;
- clearmouse();
- rp = array[c.nw] of Rect;
- wp = array[c.nw] of ref Window;
- wp[0:] = c.w[0:c.nw];
- qsort(wp, c.nw);
- for(i=0; i<c.nw; i++)
- rp[i] = wp[i].r;
- r = c.r;
- r.min.y = c.tag.frame.r.max.y;
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- y = r.min.y;
- for(i=0; i<c.nw; i++){
- w = wp[i];
- r.min.y = y;
- if(i == c.nw-1)
- r.max.y = c.r.max.y;
- else
- r.max.y = r.min.y+w.r.dy()+Border;
- r1 = r;
- r1.max.y = r1.min.y+Border;
- draw(mainwin, r1, black, nil, (0, 0));
- r.min.y = r1.max.y;
- y = w.reshape(r, FALSE);
- }
- rp = nil;
- c.w = wp;
- }
- Column.grow(c : self ref Column, w : ref Window, but : int, mv : int)
- {
- r, cr : Rect;
- i, j, k, l, y1, y2, tot, nnl, onl, dnl, h : int;
- nl, ny : array of int;
- v : ref Window;
- for(i=0; i<c.nw; i++)
- if(c.w[i] == w)
- break;
- if (i == c.nw)
- error("can't find window");
- cr = c.r;
- if(but < 0){ # make sure window fills its own space properly
- r = w.r;
- if(i == c.nw-1)
- r.max.y = cr.max.y;
- else
- r.max.y = c.w[i+1].r.min.y;
- w.reshape(r, FALSE);
- return;
- }
- cr.min.y = c.w[0].r.min.y;
- if(but == 3){ # full size
- if(i != 0){
- v = c.w[0];
- c.w[0] = w;
- c.w[i] = v;
- }
- draw(mainwin, cr, textcols[BACK], nil, (0, 0));
- w.reshape(cr, FALSE);
- for(i=1; i<c.nw; i++)
- c.w[i].body.frame.maxlines = 0;
- c.safe = FALSE;
- return;
- }
- # store old #lines for each window
- onl = w.body.frame.maxlines;
- nl = array[c.nw] of int;
- ny = array[c.nw] of int;
- tot = 0;
- for(j=0; j<c.nw; j++){
- l = c.w[j].body.frame.maxlines;
- nl[j] = l;
- tot += l;
- }
- # approximate new #lines for this window
- if(but == 2){ # as big as can be
- for (j = 0; j < c.nw; j++)
- nl[j] = 0;
- nl[i] = tot;
- }
- else {
- nnl = min(onl + max(min(5, w.maxlines), onl/2), tot);
- if(nnl < w.maxlines)
- nnl = (w.maxlines+nnl)/2;
- if(nnl == 0)
- nnl = 2;
- dnl = nnl - onl;
- # compute new #lines for each window
- for(k=1; k<c.nw; k++){
- # prune from later window
- j = i+k;
- if(j<c.nw && nl[j]){
- l = min(dnl, max(1, nl[j]/2));
- nl[j] -= l;
- nl[i] += l;
- dnl -= l;
- }
- # prune from earlier window
- j = i-k;
- if(j>=0 && nl[j]){
- l = min(dnl, max(1, nl[j]/2));
- nl[j] -= l;
- nl[i] += l;
- dnl -= l;
- }
- }
- }
- # pack everyone above
- y1 = cr.min.y;
- for(j=0; j<i; j++){
- v = c.w[j];
- r = v.r;
- r.min.y = y1;
- r.max.y = y1+v.tag.all.dy();
- if(nl[j])
- r.max.y += 1 + nl[j]*v.body.frame.font.height;
- if(!c.safe || !v.r.eq(r)){
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- v.reshape(r, c.safe);
- }
- r.min.y = v.r.max.y;
- r.max.y += Border;
- draw(mainwin, r, black, nil, (0, 0));
- y1 = r.max.y;
- }
- # scan to see new size of everyone below
- y2 = c.r.max.y;
- for(j=c.nw-1; j>i; j--){
- v = c.w[j];
- r = v.r;
- r.min.y = y2-v.tag.all.dy();
- if(nl[j])
- r.min.y -= 1 + nl[j]*v.body.frame.font.height;
- r.min.y -= Border;
- ny[j] = r.min.y;
- y2 = r.min.y;
- }
- # compute new size of window
- r = w.r;
- r.min.y = y1;
- r.max.y = r.min.y+w.tag.all.dy();
- h = w.body.frame.font.height;
- if(y2-r.max.y >= 1+h+Border){
- r.max.y += 1;
- r.max.y += h*((y2-r.max.y)/h);
- }
- # draw window
- if(!c.safe || !w.r.eq(r)){
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- w.reshape(r, c.safe);
- }
- if(i < c.nw-1){
- r.min.y = r.max.y;
- r.max.y += Border;
- draw(mainwin, r, black, nil, (0, 0));
- for(j=i+1; j<c.nw; j++)
- ny[j] -= (y2-r.max.y);
- }
- # pack everyone below
- y1 = r.max.y;
- for(j=i+1; j<c.nw; j++){
- v = c.w[j];
- r = v.r;
- r.min.y = y1;
- r.max.y = y1+v.tag.all.dy();
- if(nl[j])
- r.max.y += 1 + nl[j]*v.body.frame.font.height;
- if(!c.safe || !v.r.eq(r)){
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- v.reshape(r, c.safe);
- }
- if(j < c.nw-1){ # no border on last window
- r.min.y = v.r.max.y;
- r.max.y += Border;
- draw(mainwin, r, black, nil, (0, 0));
- }
- y1 = r.max.y;
- }
- r = w.r;
- r.min.y = y1;
- r.max.y = c.r.max.y;
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- nl = nil;
- ny = nil;
- c.safe = TRUE;
- if (mv)
- w.mousebut();
- }
- Column.dragwin(c : self ref Column, w : ref Window, but : int)
- {
- r : Rect;
- i, b : int;
- p, op : Point;
- v : ref Window;
- nc : ref Column;
- clearmouse();
- graph->cursorswitch(dat->boxcursor);
- b = mouse.buttons;
- op = mouse.xy;
- while(mouse.buttons == b)
- acme->frgetmouse();
- graph->cursorswitch(dat->arrowcursor);
- if(mouse.buttons){
- while(mouse.buttons)
- acme->frgetmouse();
- return;
- }
- for(i=0; i<c.nw; i++)
- if(c.w[i] == w)
- break;
- if (i == c.nw)
- error("can't find window");
- p = mouse.xy;
- if(abs(p.x-op.x)<5 && abs(p.y-op.y)<5){
- c.grow(w, but, 1);
- w.mousebut();
- return;
- }
- # is it a flick to the right?
- if(abs(p.y-op.y)<10 && p.x>op.x+30 && c.row.whichcol(p) == c)
- p.x += w.r.dx(); # yes: toss to next column
- nc = c.row.whichcol(p);
- if(nc!=nil && nc!=c){
- c.close(w, FALSE);
- nc.add(w, nil, p.y);
- w.mousebut();
- return;
- }
- if(i==0 && c.nw==1)
- return; # can't do it
- if((i>0 && p.y<c.w[i-1].r.min.y) || (i<c.nw-1 && p.y>w.r.max.y)
- || (i==0 && p.y>w.r.max.y)){
- # shuffle
- c.close(w, FALSE);
- c.add(w, nil, p.y);
- w.mousebut();
- return;
- }
- if(i == 0)
- return;
- v = c.w[i-1];
- if(p.y < v.tag.all.max.y)
- p.y = v.tag.all.max.y;
- if(p.y > w.r.max.y-w.tag.all.dy()-Border)
- p.y = w.r.max.y-w.tag.all.dy()-Border;
- r = v.r;
- r.max.y = p.y;
- if(r.max.y > v.body.frame.r.min.y){
- r.max.y -= (r.max.y-v.body.frame.r.min.y)%v.body.frame.font.height;
- if(v.body.frame.r.min.y == v.body.frame.r.max.y)
- r.max.y++;
- }
- if(!r.eq(v.r)){
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- v.reshape(r, c.safe);
- }
- r.min.y = v.r.max.y;
- r.max.y = r.min.y+Border;
- draw(mainwin, r, black, nil, (0, 0));
- r.min.y = r.max.y;
- if(i == c.nw-1)
- r.max.y = c.r.max.y;
- else
- r.max.y = c.w[i+1].r.min.y-Border;
- # r.max.y = w.r.max.y;
- if(!r.eq(w.r)){
- draw(mainwin, r, textcols[BACK], nil, (0, 0));
- w.reshape(r, c.safe);
- }
- c.safe = TRUE;
- w.mousebut();
- }
- Column.which(c : self ref Column, p : Point) : ref Text
- {
- i : int;
- w : ref Window;
- if(!p.in(c.r))
- return nil;
- if(p.in(c.tag.all))
- return c.tag;
- for(i=0; i<c.nw; i++){
- w = c.w[i];
- if(p.in(w.r)){
- if(p.in(w.tag.all))
- return w.tag;
- return w.body;
- }
- }
- return nil;
- }
- Column.clean(c : self ref Column, exiting : int) : int
- {
- clean : int;
- i : int;
- clean = TRUE;
- for(i=0; i<c.nw; i++)
- clean &= c.w[i].clean(TRUE, exiting);
- return clean;
- }
|