mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
575 lines
No EOL
12 KiB
C++
575 lines
No EOL
12 KiB
C++
#include "GridCtrl.h"
|
|
|
|
namespace Upp {
|
|
|
|
int GridCtrl::GetMouseCol(Point &p, bool relative, bool fixed, bool full)
|
|
{
|
|
if(!full && p.x < fixed_width)
|
|
return -1;
|
|
|
|
int dx = 0;
|
|
|
|
if(relative)
|
|
dx += sbx;
|
|
|
|
int first_col = fixed ? 0 : max(firstVisCol, fixed_cols);
|
|
int last_col = max(lastVisCol, fixed_cols - 1);
|
|
|
|
if(!fixed && last_col >= total_cols)
|
|
return -1;
|
|
|
|
for(int i = first_col; i <= last_col; i++)
|
|
{
|
|
if(p.x >= hitems[i].nLeft(dx) &&
|
|
p.x < hitems[i].nRight(dx))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int GridCtrl::GetMouseRow(Point &p, bool relative, bool fixed, bool full)
|
|
{
|
|
if(!full && p.y < fixed_height)
|
|
return -1;
|
|
|
|
int dy = 0;
|
|
|
|
if(relative)
|
|
dy += sby;
|
|
|
|
int first_row = fixed ? 0 : max(firstVisRow, fixed_rows);
|
|
int last_row = max(lastVisRow, fixed_rows - 1);
|
|
|
|
if(!fixed && last_row >= total_rows)
|
|
return -1;
|
|
|
|
for(int i = first_row; i <= last_row; i++)
|
|
{
|
|
if(p.y >= vitems[i].nTop(dy) &&
|
|
p.y < vitems[i].nBottom(dy))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
Point GridCtrl::GetPos(Point p)
|
|
{
|
|
return Point(GetMouseCol(p, true, false), GetMouseRow(p, true, false));
|
|
}
|
|
|
|
void GridCtrl::LeftDown(Point p, dword keyflags)
|
|
{
|
|
//popup.Close();
|
|
SetCapture();
|
|
leftpnt = p;
|
|
just_clicked = true;
|
|
|
|
fixed_top_click = p.x >= fixed_width && p.y < fixed_height;
|
|
fixed_left_click = p.x < fixed_width && p.y >= fixed_height;
|
|
fixed_click = fixed_top_click || fixed_left_click;
|
|
top_click = p.y < fixed_height;
|
|
|
|
resizing = curResizeCol || curResizeRow;
|
|
|
|
if(resizing)
|
|
{
|
|
popup.Close();
|
|
|
|
splitCol = curSplitCol;
|
|
splitRow = curSplitRow;
|
|
resizeCol = curResizeCol;
|
|
resizeRow = curResizeRow;
|
|
|
|
Split(GS_DOWN);
|
|
return;
|
|
}
|
|
else if(fixed_click)
|
|
{
|
|
moveCol = oldMoveCol = GetMouseCol(p, fixed_top_click, 1);
|
|
moveRow = oldMoveRow = GetMouseRow(p, fixed_left_click, 1);
|
|
return;
|
|
}
|
|
|
|
SetFocus();
|
|
|
|
if(IsEmpty() || IsReadOnly())
|
|
return;
|
|
|
|
bool is_shift = keyflags & K_SHIFT;
|
|
bool is_ctrl = keyflags & K_CTRL;
|
|
|
|
Point oldcur = curpos;
|
|
|
|
CurState cs = SetCursor0(p, CU_MOUSE | CU_HIDECTRLS);
|
|
bool state_change = cs.IsValid() && !cs.IsNew() && (is_ctrl || is_shift);
|
|
|
|
if(!cs.IsAccepted() && !state_change)
|
|
return;
|
|
|
|
anchor = curpos;
|
|
|
|
if(cs || state_change) {
|
|
moveCol = curpos.x;
|
|
moveRow = curpos.y;
|
|
|
|
if((keyflags & K_CTRL) && multi_select) {
|
|
SelectRange(curpos, curpos, !IsSelect(curpos.y, curpos.x, false), select_row);
|
|
}
|
|
else {
|
|
ClearSelection();
|
|
if((keyflags & K_SHIFT) && multi_select && IsValidCursor(oldcur)) {
|
|
if(oldcur.y >= 0 && oldcur.x >= 0)
|
|
SetCursor0(oldcur, CU_HIDECTRLS);
|
|
Refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef LOG_CALLBACKS
|
|
//LGR(2, "WhenLeftClick()");
|
|
#endif
|
|
|
|
WhenLeftClick();
|
|
|
|
if(editing && one_click_edit && cs.IsValid() ) //&& IsRowEditable() ?
|
|
StartEdit();
|
|
else
|
|
RebuildToolBar();
|
|
|
|
SetCapture();
|
|
}
|
|
|
|
void GridCtrl::MouseMove(Point p, dword keyflags)
|
|
{
|
|
mouse_move = true;
|
|
|
|
if(resizing)
|
|
{
|
|
int si, lp, mp, off;
|
|
RectItems *its;
|
|
static int sub = 0;
|
|
|
|
if(resizeCol)
|
|
{
|
|
mp = p.x;
|
|
lp = leftpnt.x;
|
|
si = splitCol;
|
|
its = &hitems;
|
|
bool top = fixed_top_click || (!fixed_left_click && full_col_resizing);
|
|
off = top ? sbx : 0;
|
|
}
|
|
else
|
|
{
|
|
mp = p.y;
|
|
lp = leftpnt.y;
|
|
si = splitRow;
|
|
its = &vitems;
|
|
bool left = fixed_left_click || (!fixed_top_click && full_row_resizing);
|
|
off = left ? sby : 0;
|
|
}
|
|
|
|
int right = (*its)[si].nRight(off);
|
|
|
|
if(just_clicked)
|
|
{
|
|
sub = right - lp;
|
|
just_clicked = false;
|
|
}
|
|
|
|
if(SetDiffItemSize(resizeCol, *its, si, mp - right + sub))
|
|
{
|
|
Split(GS_MOVE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if(fixed_click)
|
|
{
|
|
if((fixed_top_click && !moving_cols) ||
|
|
(fixed_left_click && !moving_rows) ||
|
|
moveCol < 0 || moveRow < 0)
|
|
return;
|
|
|
|
if(!moving_header)
|
|
{
|
|
int diffx = p.x - leftpnt.x;
|
|
int diffy = p.y - leftpnt.y;
|
|
if(abs(diffx) < 5 && abs(diffy) < 5)
|
|
return;
|
|
|
|
p -= Point(diffx, diffy);
|
|
|
|
moving_header = true;
|
|
int idx = hitems[moveCol].id;
|
|
int idy = vitems[moveRow].id;
|
|
pophdr.val = idy > 0 ? GetConvertedColumn(moveCol, items[idy][idx].val) : items[idy][idx].val;
|
|
|
|
if(fixed_top_click)
|
|
{
|
|
pophdr.sortmode = hitems[moveCol].sortmode;
|
|
pophdr.sortcol = hitems[moveCol].sortcol;
|
|
pophdr.sortcnt = sortOrder.GetCount();
|
|
|
|
UpdateHighlighting(GS_POPUP, p);
|
|
}
|
|
else
|
|
{
|
|
pophdr.sortmode = 0;
|
|
pophdr.sortcol = -1;
|
|
pophdr.sortcnt = 0;
|
|
}
|
|
|
|
dx = hitems[moveCol].nLeft(fixed_top_click ? sbx : 0) - p.x;
|
|
dy = vitems[moveRow].nTop(fixed_left_click ? sby : 0) - p.y;
|
|
}
|
|
|
|
|
|
Point pt = p + GetScreenRect().TopLeft() + GetBarOffset();
|
|
|
|
pophdr.display = display;
|
|
pophdr.chameleon = chameleon;
|
|
pophdr.PopUp(this, pt.x + dx, pt.y + dy, hitems[moveCol].nWidth(), vitems[moveRow].nHeight());
|
|
|
|
if(fixed_top_click && curSplitCol != oldMoveCol)
|
|
{
|
|
moving_allowed = CanMoveCol(moveCol, curSplitCol);
|
|
RefreshTop();
|
|
//Refresh(oldMoveCol >= 0 ? hitems[oldMoveCol].nRight(sbx) : 0, 0, hitems[curSplitCol].nRight(sbx), fixed_height);
|
|
oldMoveCol = curSplitCol;
|
|
}
|
|
|
|
if(fixed_left_click && curSplitRow != oldMoveRow)
|
|
{
|
|
Refresh(0, 0, fixed_width, fixed_height);
|
|
RefreshLeft();
|
|
oldMoveRow = curSplitRow;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(leftpnt != p && p.y < fixed_height)
|
|
{
|
|
UpdateHighlighting(GS_MOVE, p);
|
|
}
|
|
|
|
if(live_cursor && popup.IsOpen())
|
|
{
|
|
LG(2, "MouseMove:LiveCursor");
|
|
if(IsMouseBody(p))
|
|
SetCursor0(p, CU_MOUSE | CU_HIGHLIGHT);
|
|
else
|
|
SetCursor0(-1, -1, CU_HIGHLIGHT);
|
|
}
|
|
|
|
if(HasCapture())
|
|
{
|
|
if(!moving_body)
|
|
{
|
|
anchor = GetPos(p);
|
|
Refresh();
|
|
return;
|
|
/* if(keyflags & K_SHIFT)
|
|
{
|
|
if(SetCursor0(p, CU_MOUSE))
|
|
DoShiftSelect();
|
|
return;
|
|
}
|
|
|
|
bool select = true;
|
|
if(select_row && !multi_select)
|
|
select = false;
|
|
|
|
if(select && (keyflags & K_CTRL))
|
|
{
|
|
if(SetCursor0(p, CU_MOUSE))
|
|
// DoCtrlSelect();
|
|
return;
|
|
}*/
|
|
}
|
|
|
|
if(moveCol < 0 || moveRow < 0)
|
|
return;
|
|
|
|
if(!dragging)
|
|
return;
|
|
|
|
if(!moving_body)
|
|
{
|
|
popup.Close();
|
|
|
|
if(!top_click && valid_cursor &&
|
|
p.x < total_width &&
|
|
p.y < total_height &&
|
|
(abs(p.y - leftpnt.y) > 5 ||
|
|
abs(p.x - leftpnt.x) > 5))
|
|
moving_body = true;
|
|
|
|
oldMoveRow = -1;
|
|
}
|
|
else
|
|
{
|
|
Point pt = p + GetScreenRect().TopLeft();
|
|
|
|
int row = curSplitRow - fixed_rows + 2;
|
|
if(select_row)
|
|
{
|
|
int count = max(1, selected_rows);
|
|
|
|
if(vitems[curpos.y].IsSelect())
|
|
popup.val = Format(t_("Moving selection (%d %s) before row %d"), count, count == 1 ? t_("row") : t_("rows"), row);
|
|
else
|
|
popup.val = Format(t_("Moving row %d before row %d"), curpos.y - fixed_rows + 1, row);
|
|
}
|
|
else
|
|
{
|
|
int count = max(1, selected_items);
|
|
popup.val = Format(t_("Moving %d %s before row %d"), count, count == 1 ? t_("cell") : t_("cells"), row);
|
|
}
|
|
|
|
int px = pt.x + 15;
|
|
int py = pt.y + GD_ROW_HEIGHT;
|
|
|
|
popup.gd = display;
|
|
popup.gd->row = 0;
|
|
popup.gd->col = 0;
|
|
popup.fg = SColorText;
|
|
popup.bg = SColorPaper;
|
|
popup.fnt = StdFont();
|
|
popup.style = 0;
|
|
popup.PopUp(this, px, py, GetTextSize((String) popup.val, StdFont()).cx + 10, GD_ROW_HEIGHT);
|
|
SetFocus();
|
|
|
|
if(curSplitRow != oldMoveRow || scrollLeftRight)
|
|
{
|
|
int dy = sby;
|
|
if(oldMoveRow >= 0)
|
|
Refresh(Rect(0, vitems[oldMoveRow].nBottom(dy) - 5, GetSize().cx, vitems[oldMoveRow].nBottom(dy) + 5));
|
|
else
|
|
Refresh(Rect(0, 0, GetSize().cx, 5));
|
|
if(curSplitRow >= 0)
|
|
Refresh(Rect(0, vitems[curSplitRow].nBottom(dy) - 5, GetSize().cx, vitems[curSplitRow].nBottom(dy) + 5));
|
|
else
|
|
Refresh(Rect(0, 0, GetSize().cx, 5));
|
|
|
|
oldMoveRow = curSplitRow;
|
|
popup.Refresh();
|
|
|
|
scrollLeftRight = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
SyncPopup();
|
|
}
|
|
|
|
void GridCtrl::LeftUp(Point p, dword keyflags)
|
|
{
|
|
LG(0, "LeftUp");
|
|
|
|
ReleaseCapture();
|
|
Refresh();
|
|
|
|
fixed_click = false;
|
|
|
|
UpdateHighlighting(resizing ? GS_MOVE : GS_UP, p);
|
|
|
|
if(moving_header)
|
|
{
|
|
LG(0, "moving_header");
|
|
pophdr.Close();
|
|
|
|
moving_header = false;
|
|
if(fixed_top_click)
|
|
MoveCol(moveCol, curSplitCol);
|
|
else
|
|
MoveRow(moveRow, curSplitRow);
|
|
|
|
if(focused_ctrl)
|
|
focused_ctrl->SetFocus();
|
|
|
|
fixed_top_click = false;
|
|
fixed_left_click = false;
|
|
|
|
return;
|
|
}
|
|
|
|
if(resizing)
|
|
{
|
|
Split(GS_UP);
|
|
resizeCol = resizeRow = resizing = false;
|
|
return;
|
|
}
|
|
|
|
if(fixed_top_click && sorting && Distance(leftpnt, p) < 3)
|
|
{
|
|
int i = GetMouseRow(leftpnt, false, true);
|
|
int j = GetMouseCol(leftpnt, true, false);
|
|
|
|
if(j >= fixed_cols && i == 0 && hitems[i].sortable)
|
|
{
|
|
int newSortCol = hitems[j].id;
|
|
|
|
if(sorting_multicol && (keyflags & K_CTRL))
|
|
{
|
|
int colidx = InMultisort(newSortCol);
|
|
|
|
if(colidx < 0)
|
|
sortOrder.Add(newSortCol);
|
|
|
|
int cnt = sortOrder.GetCount();
|
|
|
|
hitems[j].ChangeSortMode(newSortCol == sortOrder[cnt - 1]);
|
|
|
|
if(colidx >= 0)
|
|
{
|
|
if(hitems[j].sortmode == 0)
|
|
{
|
|
sortOrder.Remove(colidx);
|
|
cnt--;
|
|
}
|
|
|
|
if(WhenSort)
|
|
WhenSort();
|
|
else
|
|
{
|
|
if(hitems[j].sortmode > 0 && colidx == cnt - 1)
|
|
GSort();
|
|
else
|
|
Multisort();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hitems[j].sortcol = cnt;
|
|
if(WhenSort)
|
|
WhenSort();
|
|
else
|
|
GSort();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(sortCol >= 0 && sortCol != newSortCol)
|
|
{
|
|
int idx = GetIdCol(sortCol, true);
|
|
hitems[idx].sortmode = 0;
|
|
}
|
|
|
|
ClearMultisort(1);
|
|
hitems[j].ChangeSortMode();
|
|
hitems[j].sortcol = 1;
|
|
|
|
if(hitems[j].sortmode == 0)
|
|
sortCol = -1;
|
|
else
|
|
sortCol = newSortCol;
|
|
|
|
sortOrder.Add(newSortCol);
|
|
|
|
if(WhenSort)
|
|
WhenSort();
|
|
else
|
|
GSort(newSortCol, hitems[j].sortmode, fixed_rows);
|
|
}
|
|
|
|
UpdateCursor();
|
|
Repaint(false, true);
|
|
|
|
if(WhenSorted)
|
|
WhenSorted();
|
|
}
|
|
}
|
|
|
|
if(moving_body)
|
|
{
|
|
popup.Close();
|
|
moving_body = false;
|
|
MoveRows(curSplitRow + 1, !vitems[curpos.y].IsSelect());
|
|
return;
|
|
}
|
|
|
|
if(IsValidCursor(anchor) && IsValidCursor(curpos) && multi_select)
|
|
SelectRange(Rect(anchor, curpos), true, select_row);
|
|
|
|
anchor = curpos;
|
|
}
|
|
|
|
void GridCtrl::LeftDouble(Point p, dword keyflags)
|
|
{
|
|
LG(0, "LeftDouble");
|
|
|
|
if(full_col_resizing && curSplitCol >= 0)
|
|
return;
|
|
|
|
if(full_row_resizing && curSplitRow >= 0)
|
|
return;
|
|
|
|
if(IsEmpty() || !IsMouseBody(p) || IsReadOnly())
|
|
return;
|
|
|
|
if(keyflags & K_SHIFT || keyflags & K_CTRL)
|
|
return;
|
|
|
|
if(!valid_cursor)
|
|
return;
|
|
|
|
if(editing)
|
|
StartEdit();
|
|
|
|
if(!IsCtrl(curpos))
|
|
{
|
|
popup.Close();
|
|
#ifdef LOG_CALLBACKS
|
|
LGR(2, "WhenLeftDouble()");
|
|
#endif
|
|
WhenLeftDouble();
|
|
}
|
|
}
|
|
|
|
void GridCtrl::LeftRepeat(Point p, dword keyflags)
|
|
{
|
|
if(!moving_header && !resizeCol && !resizeRow)
|
|
MouseAccel(p, resize_col_mode == 0, resize_row_mode == 0, keyflags);
|
|
}
|
|
|
|
void GridCtrl::RightDown(Point p, dword keyflags)
|
|
{
|
|
if(IsReadOnly())
|
|
return;
|
|
|
|
if(total_rows > fixed_rows)
|
|
{
|
|
if(!EndEdit())
|
|
return;
|
|
|
|
SetCursor0(p, CU_MOUSE);
|
|
}
|
|
|
|
RebuildToolBar();
|
|
SetFocus(); //jak nie bedzie menu to fokous zostanie na danym wierszu
|
|
MenuBar::Execute(WhenMenuBar);
|
|
anchor = curpos;
|
|
}
|
|
|
|
void GridCtrl::MouseLeave()
|
|
{
|
|
if(live_cursor)
|
|
{
|
|
LG(2, "MouseLeave:LiveCursor");
|
|
SetCursor0(-1, -1, CU_HIGHLIGHT);
|
|
}
|
|
UpdateHighlighting(GS_BORDER, Point(0, 0));
|
|
oldSplitCol = -1;
|
|
oldSplitRow = -1;
|
|
//popup.Close();
|
|
}
|
|
|
|
void GridCtrl::MouseWheel(Point p, int zdelta, dword keyflags)
|
|
{
|
|
if(resize_row_mode == 0)
|
|
{
|
|
sby.Set(sby - zdelta / 4);
|
|
}
|
|
}
|
|
|
|
}; |