mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
519 lines
No EOL
12 KiB
C++
519 lines
No EOL
12 KiB
C++
#include "GridCtrl.h"
|
|
|
|
namespace Upp {
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
void GridCtrl::Paint(Draw &w)
|
|
{
|
|
[[maybe_unused]] static int paintcnt = 0;
|
|
|
|
Font stdfont(StdFont());
|
|
|
|
Size sz = GetSize();
|
|
Rect rc = Rect(sz); //w.GetClip() - it always returns view rect now. bug??
|
|
|
|
if(!ready)
|
|
{
|
|
w.DrawRect(rc, SColorPaper);
|
|
return;
|
|
}
|
|
|
|
int i, j, cx, cy, x, y;
|
|
bool skip;
|
|
Rect r;
|
|
|
|
LLOG("---- Paint " << ++paintcnt);
|
|
|
|
if(total_cols <= 1 || total_rows == 0)
|
|
{
|
|
LLOG("---- Paint " << paintcnt << " Empty.");
|
|
w.DrawRect(sz, SColorPaper);
|
|
return;
|
|
}
|
|
|
|
if(UpdateCols() || UpdateRows())
|
|
UpdateSizes();
|
|
|
|
if(firstCol < 0) firstCol = GetFirstVisCol(fixed_width);
|
|
if(firstRow < 0) firstRow = GetFirstVisRow(fixed_height);
|
|
|
|
LLOG("firstCol " << firstCol);
|
|
LLOG("firstRow " << firstRow);
|
|
|
|
int en = IsShowEnabled() ? 0 : GD::READONLY;
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
if(fixed_width > 0 && fixed_height > 0)
|
|
{
|
|
w.Clip(0, 0, fixed_width, fixed_height);
|
|
dword style = chameleon ? GD::CHAMELEON : 0;
|
|
|
|
display->PaintFixed(w, 1, 1, 0, 0, fixed_width, fixed_height,
|
|
Value(""),
|
|
style, stdfont, false, false,
|
|
0, -1, 0,
|
|
true);
|
|
w.End();
|
|
}
|
|
|
|
r.Set(fixed_width, 0, sz.cx, summary_row ? sz.cy : fixed_height);
|
|
|
|
if(w.IsPainting(r) && total_cols > 1)
|
|
{
|
|
LLOG("Top header");
|
|
w.Clip(r);
|
|
|
|
x = hitems[total_cols - 1].nRight(sbx);
|
|
int rx = x;
|
|
|
|
int firstcol = indicator ? 0 : (fixed_cols > 1 ? 1 : firstVisCol);
|
|
if(firstCol < 0) firstCol = 0;
|
|
int jfc = chameleon ? 0 : firstCol;
|
|
|
|
for(i = 0; i < fixed_rows; i++)
|
|
{
|
|
for(j = jfc; j < total_cols; j++)
|
|
{
|
|
ItemRect& hi = hitems[j];
|
|
|
|
if(hi.hidden)
|
|
continue;
|
|
|
|
int jj = j;
|
|
Item &it = GetItemSize(i, j, x, y, cx, cy, skip, true, false);
|
|
if(skip)
|
|
continue;
|
|
|
|
if(x >= rc.right)
|
|
break;
|
|
|
|
if(w.IsPainting(x, y, cx, cy))
|
|
{
|
|
GridDisplay * gd = it.display ? it.display : display;
|
|
|
|
dword style = hi.style | hi.halign;
|
|
if(i > 0) style &= ~GD::HIGHLIGHT;
|
|
if(chameleon)
|
|
style |= GD::CHAMELEON;
|
|
|
|
Font fnt(stdfont);
|
|
gd->SetLeftImage(hi.img);
|
|
gd->ReverseSortIcon(reverse_sort_icon);
|
|
gd->PaintFixed(w, jj == firstcol, i == 0, x, y, cx, cy,
|
|
i == 0 ? it.val : GetConvertedColumn(hi.id, it.val),
|
|
style | en, IsNull(hi.hfnt) ? fnt : hi.hfnt, false, false,
|
|
i == 0 ? hi.sortmode : 0,
|
|
hi.sortcol,
|
|
sortOrder.GetCount(),
|
|
true);
|
|
|
|
it.rcx = gd->real_size.cx;
|
|
it.rcy = gd->real_size.cy;
|
|
}
|
|
|
|
if(summary_row && i == 0)
|
|
{
|
|
cy = GD_HDR_HEIGHT;
|
|
y = sz.cy - cy;
|
|
|
|
if(w.IsPainting(x, y, cx, cy))
|
|
{
|
|
Item &it = summary[hi.id];
|
|
GridDisplay * gd = it.display ? it.display : display;
|
|
|
|
dword style = en | hi.halign;
|
|
if(chameleon)
|
|
style |= GD::CHAMELEON;
|
|
|
|
String s;
|
|
if(hi.sop != SOP_NONE && !hi.sopfrm.IsEmpty() && !IsNull(it.val))
|
|
s = Format(hi.sopfrm, it.val);
|
|
else
|
|
s = IsString(it.val) ? it.val : StdConvert().Format(it.val);
|
|
gd->SetLeftImage(Null);
|
|
//gd->PaintFixed(w, jj == firstcol, i == 0, x, y, cx, cy, s,
|
|
// style | en, stdfont, false, false, 0, -1, 0, true);
|
|
Color fg = Black;
|
|
Color bg = Blend(Blue, White, 240);
|
|
w.DrawRect(x, y, cx, 1, Gray);
|
|
Font fnt(stdfont);
|
|
|
|
if(style & GD::READONLY)
|
|
{
|
|
bg = Blend(bg, SGray(), 40);
|
|
fg = Blend(fg, SGray(), 200);
|
|
}
|
|
|
|
gd->Paint(w, x, y + 1, cx, cy - 1, s, style, fg, bg, fnt.Bold(), false, 0, 0);
|
|
|
|
it.rcx = gd->real_size.cx;
|
|
it.rcy = gd->real_size.cy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(rx < sz.cx || chameleon)
|
|
{
|
|
int cx = sz.cx - rx + 1;
|
|
dword style = 0;
|
|
if(chameleon)
|
|
{
|
|
cx = max(10, cx);
|
|
style = GD::CHAMELEON;
|
|
}
|
|
display->PaintFixed(w, 0, 1, rx, 0, cx, fixed_height,
|
|
Value(""),
|
|
style, stdfont, false, false,
|
|
0, -1, 0,
|
|
true);
|
|
if(summary_row)
|
|
{
|
|
Color fg = Black;
|
|
Color bg = Blend(Blue, White, 240);
|
|
w.DrawRect(rx, y, cx, 1, Gray);
|
|
|
|
if(style & GD::READONLY)
|
|
{
|
|
bg = Blend(bg, SGray(), 40);
|
|
fg = Blend(fg, SGray(), 200);
|
|
}
|
|
display->Paint(w, rx, y + 1, cx, GD_HDR_HEIGHT - 1, Value(""), style, fg, bg, stdfont, false, 0, 0);
|
|
}
|
|
}
|
|
|
|
w.End();
|
|
}
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
bool can_paint = firstCol >= 0 && firstRow >= 0;
|
|
r.Set(0, fixed_height, fixed_width, sz.cy);
|
|
|
|
if(can_paint && w.IsPainting(r))
|
|
{
|
|
LLOG("Left header");
|
|
w.Clip(r);
|
|
y = vitems[total_rows - 1].nBottom(sby);
|
|
|
|
if(y < sz.cy)
|
|
w.DrawRect(Rect(0, y, fixed_width, sz.cy - summary_height), SColorPaper);
|
|
|
|
for(i = 0; i < fixed_cols; i++)
|
|
{
|
|
bool firstx = (i == !indicator);
|
|
bool indicator = (i == 0);
|
|
int id = hitems[i].id;
|
|
|
|
for(j = firstRow; j < total_rows; j++)
|
|
{
|
|
ItemRect& vi = vitems[j];
|
|
|
|
if(vi.hidden)
|
|
continue;
|
|
|
|
Item &it = GetItemSize(j, i, x, y, cx, cy, skip, false, true);
|
|
|
|
if(skip)
|
|
continue;
|
|
|
|
if(y >= rc.bottom)
|
|
break;
|
|
|
|
if(w.IsPainting(x, y, cx, cy))
|
|
{
|
|
GridDisplay * gd = it.display ? it.display : display;
|
|
|
|
dword style = vi.style;
|
|
if(i > 0) style &= ~GD::HIGHLIGHT;
|
|
if(chameleon)
|
|
style |= GD::CHAMELEON;
|
|
|
|
Font fnt(stdfont);
|
|
gd->PaintFixed(w, firstx, j == 0, x, y, cx, cy,
|
|
GetConvertedColumn(id, it.val),
|
|
style | en, IsNull(vi.hfnt) ? fnt : vi.hfnt,
|
|
indicator, false, 0, -1, 0, false);
|
|
|
|
it.rcx = gd->real_size.cx;
|
|
it.rcy = gd->real_size.cy;
|
|
}
|
|
}
|
|
|
|
if(summary_row)
|
|
{
|
|
j = 0;
|
|
cy = GD_HDR_HEIGHT;
|
|
y = sz.cy - cy;
|
|
if(w.IsPainting(x, y, cx, cy))
|
|
{
|
|
Item& it = summary[hitems[i].id];
|
|
GridDisplay * gd = it.display ? it.display : display;
|
|
|
|
dword style = vitems[j].style;
|
|
if(chameleon)
|
|
style |= GD::CHAMELEON;
|
|
|
|
// gd->PaintFixed(w, firstx, true, x, y, cx, cy,
|
|
// GetConvertedColumn(id, it.val),
|
|
// style | en, stdfont,
|
|
// false, false, 0, -1, 0, false);
|
|
//
|
|
Color fg = Black;
|
|
Color bg = Blend(Blue, White, 240);
|
|
w.DrawRect(x, y, cx, 1, Gray);
|
|
Font fnt(stdfont);
|
|
gd->Paint(w, x, y + 1, cx, cy - 1, GetConvertedColumn(id, it.val), style | en, fg, bg, fnt.Bold(), false, 0, 0);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
w.End();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
// Draw the "active" (non-fixed) cells:
|
|
|
|
r.Set(fixed_width, fixed_height, sz.cx, sz.cy - summary_height);
|
|
|
|
if(can_paint && w.IsPainting(r))
|
|
{
|
|
LLOG("Body");
|
|
w.Clip(r);
|
|
|
|
x = hitems[total_cols - 1].nRight(sbx);
|
|
y = vitems[total_rows - 1].nBottom(sby);
|
|
|
|
if(x < sz.cx) w.DrawRect(Rect(max(x, rc.left), max(fixed_height, rc.top), sz.cx, sz.cy), SColorPaper);
|
|
if(y < sz.cy) w.DrawRect(Rect(max(fixed_width, rc.left), max(y, rc.top), sz.cx, sz.cy), SColorPaper);
|
|
|
|
bool hasfocus = HasFocus() || holder.HasFocusDeep();
|
|
|
|
for(i = max(firstRow, fixed_rows); i < total_rows; i++)
|
|
{
|
|
ItemRect& vi = vitems[i];
|
|
if(vi.hidden) continue;
|
|
|
|
bool even = coloring_mode == 2 ? (i - vi.n - fixed_rows) & 1 : false;
|
|
|
|
for(j = max(firstCol, fixed_cols); j < total_cols; j++)
|
|
{
|
|
const ItemRect& hi = hitems[j];
|
|
|
|
if(hi.hidden)
|
|
continue;
|
|
|
|
Item &it = GetItemSize(i, j, x, y, cx, cy, skip);
|
|
if(skip)
|
|
continue;
|
|
|
|
if(y >= rc.bottom)
|
|
goto end_paint;
|
|
|
|
if(x >= rc.right)
|
|
break;
|
|
|
|
if(!w.IsPainting(0, y, sz.cx, cy))
|
|
break;
|
|
|
|
if(w.IsPainting(x, y, cx, cy))
|
|
{
|
|
bool iscur = draw_focus ? (i == curpos.y && j == curpos.x) : false;
|
|
|
|
if(coloring_mode == 1)
|
|
even = (j - hi.n - fixed_cols) & 1;
|
|
|
|
int id = hi.id;
|
|
|
|
dword style = en | (select_row ? vi.style : it.style) | hi.balign;
|
|
dword istyle = it.style;
|
|
|
|
if(hitems[j].wrap)
|
|
style |= GD::WRAP;
|
|
if(ctrlpos.y == i && edits[id].ctrl && edits[id].ctrl->IsShown())
|
|
style |= GD::NOTEXT;
|
|
if(it.ctrl)
|
|
style |= GD::NOTEXT;
|
|
|
|
if(coloring_mode > 0)
|
|
style |= (even ? GD::EVEN : GD::ODD);
|
|
if(hasfocus)
|
|
style |= GD::FOCUS;
|
|
|
|
if(IsValidCursor(anchor) && anchor != curpos && multi_select) { // mouse selection in progress
|
|
Rect r(anchor, curpos);
|
|
r.Normalize();
|
|
r.SetSize(r.GetSize() + 1);
|
|
if(select_row) {
|
|
r.left = 0;
|
|
r.right = INT_MAX;
|
|
}
|
|
if(r.Contains(Point(j, i)))
|
|
style |= GD::SELECT;
|
|
}
|
|
|
|
Color cfg;
|
|
Color cbg;
|
|
|
|
Font fnt = StdFont();
|
|
GridDisplay* gd;
|
|
Value val = GetItemValue(it, id, hi, vi);
|
|
GetItemAttrs(it, val, i, j, vi, hi, style, gd, cfg, cbg, fnt);
|
|
|
|
Color fg = SColorText;
|
|
Color bg = SColorPaper;
|
|
|
|
bool custom = true;
|
|
|
|
if(style & GD::CURSOR)
|
|
{
|
|
if(style & GD::FOCUS)
|
|
{
|
|
fg = iscur ? Blend(bg_focus, Black, 230) : fg_focus;
|
|
bg = iscur ? Blend(bg_focus, White, 230) : bg_focus;
|
|
}
|
|
else
|
|
{
|
|
bg = Blend(SColorDisabled, bg);
|
|
}
|
|
custom = false;
|
|
}
|
|
else if(style & GD::LIVE)
|
|
{
|
|
fg = fg_live;
|
|
bg = bg_live;
|
|
custom = false;
|
|
}
|
|
else if(istyle & GD::FOUND)
|
|
{
|
|
fg = fg_found;
|
|
bg = bg_found;
|
|
custom = false;
|
|
}
|
|
else if(style & GD::SELECT)
|
|
{
|
|
fg = fg_select;
|
|
bg = bg_select;
|
|
custom = false;
|
|
}
|
|
else if(style & GD::EVEN)
|
|
{
|
|
fg = fg_even;
|
|
bg = bg_even;
|
|
}
|
|
else if(style & GD::ODD)
|
|
{
|
|
fg = fg_odd;
|
|
bg = bg_odd;
|
|
}
|
|
|
|
if(custom)
|
|
{
|
|
if(!IsNull(cfg)) fg = cfg;
|
|
if(!IsNull(cbg)) bg = cbg;
|
|
}
|
|
|
|
if(style & GD::READONLY)
|
|
{
|
|
bg = Blend(bg, SGray(), 40);
|
|
fg = Blend(fg, SGray(), 200);
|
|
}
|
|
|
|
gd->SetBgImage(vi.img);
|
|
gd->col = j - fixed_rows;
|
|
gd->row = i - fixed_cols;
|
|
gd->parent = this;
|
|
|
|
val = GetAttrTextVal(val);
|
|
|
|
gd->Paint(w, x, y, cx, cy,
|
|
val, style,
|
|
fg, bg, fnt, it.style & GD::FOUND, it.fs, it.fe);
|
|
|
|
it.rcx = gd->real_size.cx;
|
|
it.rcy = gd->real_size.cy;
|
|
|
|
if(vert_grid)
|
|
{
|
|
bool skip = false;
|
|
if(!draw_last_vert_line && j == total_cols - 1)
|
|
skip = true;
|
|
|
|
if(!skip)
|
|
w.DrawRect(x + cx - 1, y, 1, cy, fg_grid);
|
|
}
|
|
if(horz_grid)
|
|
{
|
|
bool skip = false;
|
|
if(!draw_last_horz_line && i == total_rows - 1)
|
|
skip = true;
|
|
|
|
if(!skip)
|
|
w.DrawRect(x, y + cy - 1, cx, 1, fg_grid);
|
|
}
|
|
|
|
if(iscur && draw_focus)
|
|
Upp::DrawFocus(w, x, y, cx, cy);
|
|
}
|
|
}
|
|
}
|
|
|
|
end_paint:
|
|
|
|
w.End();
|
|
|
|
lastCol = j - 1;
|
|
lastRow = i - 1;
|
|
}
|
|
|
|
|
|
if(moving_header && fixed_top_click && curSplitCol >= 0)
|
|
{
|
|
r.Set(fixed_width, 0, sz.cx, fixed_height);
|
|
w.Clip(r);
|
|
bool lastcol = curSplitCol == lastVisCol;
|
|
|
|
int cp = curSplitCol;
|
|
if(!lastcol)
|
|
while(++cp < total_cols && hitems[cp].hidden);
|
|
|
|
int cx = hitems[cp].nWidth() / 2;
|
|
int x = lastcol ? hitems[curSplitCol].nLeft(sbx) + cx
|
|
: hitems[curSplitCol].nRight(sbx) - 1;
|
|
DrawFatFrame(w, x, 0, cx, vitems[fixed_rows - 1].nBottom(), moving_allowed ? LtBlue : Red, 2);
|
|
w.End();
|
|
}
|
|
|
|
if(moving_header && fixed_left_click)
|
|
{
|
|
int dy = curSplitRow == lastVisRow ? -2 : -1;
|
|
int y = curSplitRow >= 0 ? vitems[curSplitRow].nBottom(sby) + dy : 0;
|
|
if(y >= fixed_height - 1)
|
|
DrawVertDragLine(w, y, hitems[fixed_cols - 1].nRight(), 0, moving_allowed ? LtBlue : Red);
|
|
}
|
|
|
|
if(moving_body)
|
|
{
|
|
int dy = curSplitRow == lastVisRow ? -2 : -1;
|
|
int y = curSplitRow >= 0 ? vitems[curSplitRow].nBottom(sby) + dy : 0;
|
|
if(y >= fixed_height - 1)
|
|
DrawVertDragLine(w, y, sz.cx, fixed_width - 1, LtBlue);
|
|
}
|
|
|
|
if(search_display && !search_string.IsEmpty())
|
|
{
|
|
Size tsz = GetTextSize(search_string, StdFont());
|
|
w.DrawRect(Rect(0, sz.cy - tsz.cy - 4, tsz.cx + 4, sz.cy), SRed);
|
|
w.DrawText(2, sz.cy - tsz.cy - 2, search_string, StdFont(), SYellow);
|
|
}
|
|
|
|
if(!can_paint)
|
|
w.DrawRect(Rect(0, total_cols > 1 ? fixed_height : 0, sz.cx, sz.cy), SColorPaper);
|
|
if(++paint_flag > 100)
|
|
paint_flag = 0;
|
|
|
|
LLOG("---- Paint " << paintcnt);
|
|
}
|
|
|
|
}; |