1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
|
#############################################################################
##
#W brgrids.g GAP 4 package `browse' Thomas Breuer
##
## This file contains some <C>SpecialGrid</C> functions.
##
#T TB, May 2007:
#T extended version of `NCurses.Grid',
#T supports ``indicating continuation'' and attributes for lines;
#T the optional components `tend', `bend', `lend', `rend' are `true'
#T if the shown grid is not continued at the top, bottom, left, and right,
#T respectively (this is also the default), and `false' otherwise;
#T the argument `attrs', if given, must be an integer
#T describing the attributes for the lines.
NCurses.GridExt:= function( win, args, attrs )
local size, trow, brow, lcol, rcol, rowinds, colinds,
tend, bend, lend, rend,
tvis, bvis, ht, lvis, rvis, wdth, ld, lmr, i, j;
size := NCurses.getmaxyx(win);
if size = false then return false; fi;
trow:= args.trow;
brow:= args.brow;
lcol:= args.lcol;
rcol:= args.rcol;
rowinds:= args.rowinds;
colinds:= args.colinds;
tend:= not IsBound( args.tend ) or args.tend = true;
bend:= not IsBound( args.bend ) or args.bend = true;
lend:= not IsBound( args.lend ) or args.lend = true;
rend:= not IsBound( args.rend ) or args.rend = true;
if not ForAll([trow, brow, lcol, rcol], IsInt) then return false; fi;
if not ForAll(rowinds, IsInt) then return false; fi;
if not ForAll(colinds, IsInt) then return false; fi;
# find viewable rows and cols
rowinds := Filtered(rowinds, i-> i >= 0 and i >= trow and
i <= size[1]-1 and i <= brow);
colinds := Filtered(colinds, i-> i >= 0 and i >= lcol and
i <= size[2]-1 and i <= rcol);
if IsEmpty( rowinds ) and IsEmpty( colinds ) then
return false;
fi;
tvis := Maximum(trow, 0);
bvis := Minimum(brow, size[1]);
ht := bvis - tvis + 1;
lvis := Maximum(lcol, 0);
rvis := Minimum(rcol, size[2]);
wdth := rvis - lvis + 1;
# Set attributes for the lines.
NCurses.wattrset( win, attrs );
# draw vlines
ld := NCurses.lineDraw;
for i in colinds do
NCurses.wmove(win, tvis, i);
NCurses.wvline(win, ld.VLINE, ht);
od;
# draw hlines and handle crossings
for i in rowinds do
NCurses.wmove(win, i, lvis);
NCurses.whline(win, ld.HLINE, wdth);
if i = trow and tend then
lmr := [ld.ULCORNER, ld.TTEE, ld.URCORNER];
elif i = brow and bend then
lmr := [ld.LLCORNER, ld.BTEE, ld.LRCORNER];
else
lmr := [ld.LTEE, ld.PLUS, ld.RTEE];
fi;
for j in colinds do
NCurses.wmove(win, i, j);
if j = lcol and lend then
NCurses.waddch(win, lmr[1]);
elif j = rcol and rend then
NCurses.waddch(win, lmr[3]);
else
NCurses.waddch(win, lmr[2]);
fi;
od;
od;
# Reset the attributes.
NCurses.wattrset( win, NCurses.attrs.NORMAL );
return true;
end;
#############################################################################
##
#F BrowseData.SpecialGridLineDraw( <t>, <data> )
##
## When this special grid is used in a browse table,
## nonempty row separators are overwritten with horizontal rows
## that consist of the special character <C>NCurses.lineDraw.HLINE</C>,
## non-blank characters in column separators are overwritten with vertical
## rows that consist of the special character <C>NCurses.lineDraw.VLINE</C>,
## and <Q>crossings</Q> of horizontal and vertical lines are handled as in
## <Ref Func="NCurses.Grid"/>.
## <P/>
## In categorized browse tables, each set of table rows shown under
## a category row gets a grid of its own,
## and the separators below category rows are regarded as the top rows of
## these grids.
## So this special grid requires nonempty category separators if nonempty
## row separators occur.
## (Note that below a row separator, first the category rows and their
## separators appear, and then the data rows and their separators.
## If there is a nonempty row separator above the first data row
## then it is overwritten by whitespace.)
##
BrowseData.SpecialGridLineDraw:= function( t, data )
local win, entry, top, i;
win:= t.dynamic.window;
# Clear category separators, since they may exceed the last column.
for entry in data.catSeparators do
NCurses.wmove( win, entry[1], entry[2] );
NCurses.waddstr( win, ListWithIdenticalEntries( entry[3], ' ' ) );
od;
# Replace the row and column separators in all four tables by the lines.
for entry in data.gridsInfo do
NCurses.GridExt( win, entry, NCurses.attrs.NORMAL );
od;
# Overwrite a row separator above the first data row
# if the table has a category for the first data row.
top:= t.dynamic.topleft[1];
if IsOddInt( top )
and t.dynamic.topleft[3] = 1
and BrowseData.LengthCell( t, top, "vert" ) <> 0 then
for i in [ top+1, top+3 .. Length( t.dynamic.indexRow ) - 1 ] do
if BrowseData.LengthCell( t, i, "vert" ) <> 0 then
if i in t.dynamic.categories[1] then
NCurses.wmove( win, data.topmargin + data.headerLength
+ BrowseData.HeightLabelsColTable( t ),
data.leftmargin );
NCurses.waddstr( win, ListWithIdenticalEntries(
NCurses.getmaxyx( win )[2] - data.leftmargin, ' ' ) );
fi;
break;
fi;
od;
fi;
# Print those category separators that do not overwrite grid top lines.
#T force printing of category separators involving attributes!
for entry in data.catSeparators do
if ForAll( data.gridsInfo, x -> entry[1] <> x.trow ) then
NCurses.wmove( win, entry[1], entry[2] );
NCurses.whline( win, NCurses.lineDraw.HLINE, entry[3] );
fi;
od;
end;
#############################################################################
##
#F BrowseData.SpecialGridLineDrawPlus( <t>, <data> )
##
## This function is used for example in the `Browse' method for matrices.
##
## It draws the crossing of the two lines that separate the row and column
## labels from the main table.
## Note that the grids drawn by `BrowseData.SpecialGridLineDraw' belong to
## one of the four subtables of a browse table, and it is not supported
## that lines separate these tables.
##
BrowseData.SpecialGridLineDrawPlus:= function( t, data )
local win;
BrowseData.SpecialGridLineDraw( t, data );
win:= t.dynamic.window;
NCurses.wmove( win, data.gridsInfo[1].rowinds[1],
data.gridsInfo[1].colinds[1] );
NCurses.waddch( win, NCurses.lineDraw.PLUS );
end;
#############################################################################
##
#F BrowseData.SpecialGridTreeStyle( <t>, <data> )
##
## *NOTE*:
## This function does not yet support category separators
## and cells of height larger than 1.
## (And there is the general problem that when one expands all categories at
## the end of the table, the programmatically hidden rows are taken into
## account and then lead to unmotivated empty rows.)
## (Scrolling by cells seems to be not appropriate for this application,
## scrolling by characters would be better.)
##
BrowseData.SpecialGridTreeStyle:= function( t, data )
local categories, catpos, win, i, fromrow, maxdepth, previousrow, scr,
ymin, ymax, y, prevdatarow, pos, entry, level, currlevel, pos2,
kmin, j, k, lastcategorypos, height, l;
categories:= t.dynamic.categories;
catpos:= categories[1];
if IsEmpty( catpos ) or 2 < catpos[1] then
# `BrowseData.SpecialGridTreeStyle' expects category rows,
# starting in the first row.
return;
fi;
win:= t.dynamic.window;
i:= t.dynamic.topleft[1];
fromrow:= t.dynamic.topleft[3];
maxdepth:= Length( t.work.sepCol[1] );
# The `i'-th entry in `previousrow' is the position of the previous
# level `i' category if there is one on the screen, and zero otherwise.
previousrow:= 0 * [ 0 .. maxdepth ];
# Process the current line.
scr:= BrowseData.HeightWidthWindow( t );
ymin:= data.topmargin + BrowseData.HeightLabelsColTable( t )
+ data.headerLength + 1;
ymax:= scr[1] - data.bottommargin - data.footerLength;
y:= ymin;
prevdatarow:= fail;
while y <= ymax+1 and IsBound( t.dynamic.indexRow[i] ) do
# We consider row `ymax+1' but we do not print there.
if i mod 2 = 0 then
# Deal with categories, omitting the first `fromrow - 1' rows.
pos:= PositionSorted( catpos, i );
#T Why is there no variant with a <from> argument?
while pos <= Length( catpos ) and catpos[ pos ] = i do
entry:= categories[2][ pos ];
if entry.isUnderCollapsedCategory or entry.isRejectedCategory then
# This category and all of higher level are hidden.
break;
fi;
level:= entry.level;
# Deal with the category line.
if 1 < fromrow then
# The beginning of the cell is above the screen.
fromrow:= fromrow - 1;
else
# (We print no path to level 1 rows.)
if 1 < level then
if not IsBound( currlevel ) then
# The current level is that of the previous category row.
pos2:= pos;
while 1 < pos2 and catpos[ pos2 ] = i do
pos2:= pos2 - 1;
od;
currlevel:= categories[2][ pos2 ].level;
fi;
# Print the grid part for this level above the current line.
if currlevel < level then
# Fill the level `currlevel' column above the current line.
if ymin < y and previousrow[ currlevel ] + 1 < y then
NCurses.wmove( win, y-2, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*currlevel-2, ' ' ) );
NCurses.wmove( win, y-2, 2*currlevel-2 );
NCurses.waddch( win, NCurses.lineDraw.LTEE );
fi;
elif currlevel = level then
# Fill the level `currlevel' column above the current line.
if previousrow[ currlevel ] = 0 then
kmin:= ymin;
NCurses.wmove( win, kmin-1, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*currlevel-4, ' ' ) );
NCurses.wmove( win, kmin - 1, 2*currlevel-4 );
NCurses.waddch( win, NCurses.lineDraw.VLINE );
else
kmin:= previousrow[ currlevel ];
NCurses.wmove( win, kmin-1, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*currlevel-4, ' ' ) );
NCurses.wmove( win, kmin - 1, 2*currlevel-4 );
NCurses.waddch( win, NCurses.lineDraw.LTEE );
fi;
NCurses.wmove( win, kmin, 2 * ( currlevel-2 ) );
NCurses.wvline( win, NCurses.lineDraw.VLINE, y - kmin - 1 );
else
# Fill the column for level `level' above the current line.
if previousrow[ level ] = 0 then
kmin:= ymin;
else
kmin:= previousrow[ level ];
fi;
NCurses.wmove( win, kmin-1, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*level-4, ' ' ) );
NCurses.wmove( win, kmin - 1, 2*level-4 );
if previousrow[ level ] = 0 then
NCurses.waddch( win, NCurses.lineDraw.VLINE );
else
NCurses.waddch( win, NCurses.lineDraw.LTEE );
fi;
NCurses.wmove( win, kmin, 2 * ( level-2 ) );
NCurses.wvline( win, NCurses.lineDraw.VLINE, y - kmin - 1 );
fi;
if y <= ymax then
NCurses.wmove( win, y-1, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*level-4, ' ' ) );
NCurses.wmove( win, y-1, 2*level-4 );
NCurses.waddch( win, NCurses.lineDraw.LLCORNER );
fi;
fi;
previousrow[ level ]:= y;
currlevel:= level;
lastcategorypos:= pos;
y:= y + 1;
fi;
pos:= pos + 1;
od;
fi;
# Deal with the data rows.
#T what about fromrow?
height:= BrowseData.HeightRow( t, i );
if 0 < height then
if i mod 2 = 0 then
if not IsBound( currlevel ) then
# The first shown row is a data row.
# Determine the level of the category row above the first line.
pos:= PositionSorted( catpos, i );
if IsBound( catpos[ pos ] ) and catpos[ pos ] = i then
if BrowseData.HeightCategories( t, i ) < fromrow then
# Take the last category row for `i'.
while IsBound( catpos[ pos ] ) and catpos[ pos ] = i do
pos:= pos + 1;
od;
else
# Take the last category row for `i' above the first line,
# together with its category separator below.
while IsBound( catpos[ pos ] )
and BrowseData.HeightCategories( t, i,
categories[2][ pos ].level ) < fromrow do
pos:= pos + 1;
od;
fi;
fi;
if 1 < pos then
pos:= pos-1;
fi;
currlevel:= categories[2][ pos ].level;
lastcategorypos:= pos;
fi;
# Fill the column for level `currlevel' above the current line.
if prevdatarow = y-1 then
NCurses.wmove( win, y-2, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*currlevel-2, ' ' ) );
NCurses.wmove( win, y-2, 2*currlevel-2 );
NCurses.waddch( win, NCurses.lineDraw.LTEE );
fi;
if y <= ymax then
NCurses.wmove( win, y-1, 0 );
NCurses.waddstr( win, ListWithIdenticalEntries(
2*currlevel-2, ' ' ) );
NCurses.wmove( win, y-1, 2*currlevel-2 );
NCurses.waddch( win, NCurses.lineDraw.LLCORNER );
fi;
prevdatarow:= y;
#T fill with LTEE only in the first line of a cell, otherwise with VLINE
# Draw a horizontal line in row `y'.
if y <= ymax then
NCurses.wmove( win, y-1, 2 * currlevel - 1 );
NCurses.whline( win, NCurses.lineDraw.HLINE,
2 * ( maxdepth - currlevel ) );
fi;
fi;
y:= y + height - fromrow + 1;
fi;
i:= i + 1;
fromrow:= 1;
od;
# Draw the missing vertical lines from and to outside categories:
# If there is an unhidden category of level $k$ below and above
# the next category of level less than $k$
# then either replace the `LLCORNER' in column $k-1$ by an `LTEE' and
# draw a `VLINE' below until the end of the window,
# or in the case that there is no `LLCORNER' in column $k-1$
# draw a `VLINE' through the whole window.
for k in [ 2 .. Length( previousrow ) ] do
if previousrow[k] >= previousrow[ k-1 ] then
for pos2 in [ lastcategorypos + 1 .. Length( catpos ) ] do
if categories[2][ pos2 ].level = k
and not categories[2][ pos2 ].isRejectedCategory then
if previousrow[k] = 0 then
NCurses.wmove( win, ymin - 1, 2 * ( k-2 ) );
NCurses.wvline( win, NCurses.lineDraw.VLINE,
ymax - ymin + 1 );
elif previousrow[k] <= ymax then
NCurses.wmove( win, previousrow[k]-1, 2 * ( k-2 ) );
NCurses.waddch( win, NCurses.lineDraw.LTEE );
NCurses.wmove( win, previousrow[k], 2 * ( k-2 ) );
NCurses.wvline( win, NCurses.lineDraw.VLINE,
ymax - previousrow[k] );
fi;
break;
elif categories[2][ pos2 ].level < k
and not categories[2][ pos2 ].isRejectedCategory then
break;
fi;
od;
fi;
od;
end;
#############################################################################
##
#E
|