iup-stack/iup/srccontrols/matrix/iupmat_mouse.c

393 lines
10 KiB
C
Raw Normal View History

2023-02-20 16:44:45 +00:00
/** \file
* \brief iupmatrix control
* mouse events
*
* See Copyright Notice in "iup.h"
*/
/**************************************************************************/
/* Functions to handle mouse events */
/**************************************************************************/
#include <stdlib.h>
#include <time.h>
#include "iup.h"
#include "iupcbs.h"
#include <cd.h>
#include "iup_object.h"
#include "iup_attrib.h"
#include "iup_str.h"
#include "iup_stdcontrols.h"
#include "iup_flatscrollbar.h"
#include "iupmat_def.h"
#include "iupmat_colres.h"
#include "iupmat_aux.h"
#include "iupmat_mouse.h"
#include "iupmat_key.h"
#include "iupmat_mark.h"
#include "iupmat_edit.h"
#include "iupmat_draw.h"
#include "iupmat_getset.h"
#include "iupmat_scroll.h"
#define IMAT_DRAG_SCROLL_DELTA 5
static void iMatrixMouseCallMoveCb(Ihandle* ih, int lin, int col)
{
IFnii cb;
if (!ih->data->edit_hide_onfocus && ih->data->editing)
{
cb = (IFnii)IupGetCallback(ih, "EDITMOUSEMOVE_CB");
if (cb)
cb(ih, lin, col);
}
cb = (IFnii)IupGetCallback(ih, "MOUSEMOVE_CB");
if (cb)
cb(ih, lin, col);
}
static int iMatrixMouseCallClickCb(Ihandle* ih, int press, int lin, int col, char* status)
{
IFniis cb;
if (!ih->data->edit_hide_onfocus && ih->data->editing)
{
if (press)
cb = (IFniis)IupGetCallback(ih, "EDITCLICK_CB");
else
cb = (IFniis)IupGetCallback(ih, "EDITRELEASE_CB");
if (cb)
cb(ih, lin, col, status);
}
if (press)
cb = (IFniis)IupGetCallback(ih, "CLICK_CB");
else
cb = (IFniis)IupGetCallback(ih, "RELEASE_CB");
if (cb)
return cb(ih, lin, col, status);
return IUP_DEFAULT;
}
static void iMatrixMouseEdit(Ihandle* ih, int x, int y)
{
if (iupMatrixEditShowXY(ih, x, y))
{
iupMatrixMarkBlockReset(ih);
if (ih->data->datah == ih->data->droph)
IupSetAttribute(ih->data->datah, "SHOWDROPDOWN", "YES");
if (IupGetGlobal("MOTIFVERSION"))
{
/* Sequence of focus_cb in Motif from here:
Matrix-Focus(0) - ok
Edit-KillFocus - weird, must avoid using _IUPMAT_DOUBLECLICK
Since OpenMotif version 2.2.3 this is not necessary anymore. */
if (atoi(IupGetGlobal("MOTIFNUMBER")) < 2203)
iupAttribSet(ih, "_IUPMAT_DOUBLECLICK", "1");
}
}
/* reset mouse flags */
ih->data->button1edit = 0;
}
static int iMatrixIsDropArea(Ihandle* ih, int lin, int col, int x, int y)
{
IFnii dropcheck_cb = (IFnii)IupGetCallback(ih, "DROPCHECK_CB");
if (dropcheck_cb)
{
int ret = dropcheck_cb(ih, lin, col);
if (ret != IUP_IGNORE)
{
int x1, y1, x2, y2;
iupMatrixGetVisibleCellDim(ih, lin, col, &x1, &y1, &x2, &y2);
x2 += x1; /* iupMatrixGetVisibleCellDim returns w and h */
y2 += y1;
if (ret == IUP_DEFAULT)
iupMatrixDrawSetDropFeedbackArea(&x1, &y1, &x2, &y2);
else if (ret == IUP_CONTINUE)
iupMatrixDrawSetToggleFeedbackArea(iupAttribGetBoolean(ih, "TOGGLECENTERED"), &x1, &y1, &x2, &y2);
if (x > x1 && x < x2 &&
y > y1 && y < y2)
{
if (ret == IUP_DEFAULT) /* dropdown */
return 1;
else if (ret == IUP_CONTINUE) /* toggle */
return -1;
}
}
}
return 0;
}
static void iMatrixMouseLeftPress(Ihandle* ih, int lin, int col, int shift, int ctrl, int is_double, int x, int y)
{
if (is_double)
{
iupMatrixMarkBlockReset(ih);
if (lin==0 || col==0)
return;
/* if a double click NOT in the current cell */
if (lin != ih->data->lines.focus_cell || col != ih->data->columns.focus_cell)
{
/* leave the previous cell if the matrix previously had the focus */
if (ih->data->has_focus && iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
return;
ih->data->lines.focus_cell = lin;
ih->data->columns.focus_cell = col;
iupMatrixAuxCallEnterCellCb(ih);
}
ih->data->button1edit = 1; /* prepare for edit */
}
else /* single click */
{
if (shift && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
{
iupMatrixMarkBlockInc(ih, lin, col);
}
else
{
if (lin>0 && col>0 && !(ih->data->noscroll_as_title && (lin < ih->data->lines.num_noscroll || col < ih->data->columns.num_noscroll)))
{
int ret;
if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
return;
ih->data->lines.focus_cell = lin;
ih->data->columns.focus_cell = col;
ret = iMatrixIsDropArea(ih, lin, col, x, y);
/* process mark before EnterCell */
if (!ret && ih->data->mark_mode != IMAT_MARK_NO)
iupMatrixMarkBlockSet(ih, ctrl, lin, col);
iupMatrixAuxCallEnterCellCb(ih);
if (ret == 1) /* dropdown */
{
ih->data->button1edit = 1; /* prepare for edit */
}
else if (ret == -1) /* toggle */
{
int togglevalue;
IFniii togglevalue_cb;
if (iupAttribGetBoolean(ih, "READONLY"))
return;
togglevalue_cb = (IFniii)IupGetCallback(ih, "TOGGLEVALUE_CB");
if (iupAttribGetBoolean(ih, "TOGGLECENTERED"))
{
char* value = iupMatrixGetValueDisplay(ih, lin, col);
togglevalue = !iupStrBoolean(value); /* invert value */
iupMatrixSetValue(ih, lin, col, togglevalue ? "1" : "0", -1);
}
else
{
togglevalue = !iupAttribGetIntId2(ih, "TOGGLEVALUE", lin, col); /* invert value */
iupAttribSetIntId2(ih, "TOGGLEVALUE", lin, col, togglevalue);
}
iupMatrixDrawCells(ih, lin, col, lin, col);
if (togglevalue_cb)
togglevalue_cb(ih, lin, col, togglevalue);
}
}
else
{
/* only process marks here if at titles */
if (ih->data->mark_mode != IMAT_MARK_NO && iupAttribGetBoolean(ih, "MARKATTITLE"))
{
iupMatrixMarkBlockSet(ih, ctrl, lin, col);
if (ih->data->merge_info_count)
{
int merged = iupMatrixGetMerged(ih, lin, col);
if (merged)
{
int endLin, endCol;
iupMatrixGetMergedRect(ih, merged, NULL, &endLin, NULL, &endCol);
if (lin == 0 || (ih->data->noscroll_as_title && lin < ih->data->lines.num_noscroll))
iupMatrixMarkBlockInc(ih, 0, endCol);
else
iupMatrixMarkBlockInc(ih, endLin, 0);
}
}
}
}
}
}
}
int iupMatrixMouseButton_CB(Ihandle* ih, int button, int press, int x, int y, char* status)
{
int lin=-1, col=-1;
if (!iupMatrixIsValid(ih, 0))
return IUP_IGNORE;
if (press)
{
ih->data->button1edit = 0;
/* Sometimes the edit Focus callback is not called when the user clicks in the parent canvas,
so we have to compensate that. */
if (ih->data->edit_hide_onfocus)
{
ih->data->edit_hidden_byfocus = 1;
iupMatrixEditHide(ih);
ih->data->edit_hidden_byfocus = 0;
}
ih->data->has_focus = 1;
}
iupMatrixGetCellFromXY(ih, x, y, &lin, &col);
ih->data->button1press = 0;
if (button == IUP_BUTTON1)
{
if (press)
{
ih->data->button1press = 1;
iupMatrixKeyResetHomeEndCount(ih);
if (iupMatrixColResStart(ih, x, y))
{
iupMatrixMarkBlockReset(ih);
return IUP_DEFAULT; /* Resize of the width a of a column was started */
}
if (lin!=-1 && col!=-1)
iMatrixMouseLeftPress(ih, lin, col, iup_isshift(status), iup_iscontrol(status), iup_isdouble(status), x, y);
}
else
{
if (iupMatrixColResIsResizing(ih)) /* If it was made a column resize, finish it */
iupMatrixColResFinish(ih, x);
if (ih->data->button1edit) /* edit only when releasing the button */
iMatrixMouseEdit(ih, x, y);
}
}
else
iupMatrixMarkBlockReset(ih);
if (lin!=-1 && col!=-1)
{
if (iMatrixMouseCallClickCb(ih, press, lin, col, status) == IUP_IGNORE)
return IUP_DEFAULT;
}
iupMatrixDrawUpdate(ih);
return IUP_DEFAULT;
}
static void iMatrixMouseResetCursor(Ihandle* ih)
{
char *cursor = iupAttribGet(ih, "_IUPMAT_CURSOR");
if (cursor)
{
IupStoreAttribute(ih, "CURSOR", cursor);
iupAttribSet(ih, "_IUPMAT_CURSOR", NULL);
}
}
static void iMatrixMouseSetCursor(Ihandle* ih, const char* name)
{
if (!iupAttribGet(ih, "_IUPMAT_CURSOR"))
iupAttribSetStr(ih, "_IUPMAT_CURSOR", IupGetAttribute(ih, "CURSOR"));
IupSetAttribute(ih, "CURSOR", name);
}
int iupMatrixMouseMove_CB(Ihandle* ih, int x, int y, char *status)
{
int lin, col, has_lincol;
if (!iupMatrixIsValid(ih, 0))
return IUP_DEFAULT;
iupFlatScrollBarMotionUpdate(ih, x, y);
has_lincol = iupMatrixGetCellFromXY(ih, x, y, &lin, &col);
if (iup_isbutton1(status) && ih->data->button1press && ih->data->mark_block && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
{
if ((x < ih->data->columns.dt[0].size || x < IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.first > ih->data->columns.num_noscroll))
iupMATRIX_ScrollLeft(ih);
else if ((x > iupMatrixGetWidth(ih) - IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.last < ih->data->columns.num - 1))
iupMATRIX_ScrollRight(ih);
if ((y < ih->data->lines.dt[0].size || y < IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.first > ih->data->lines.num_noscroll))
iupMATRIX_ScrollUp(ih);
else if ((y > iupMatrixGetHeight(ih) - IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.last < ih->data->lines.num - 1))
iupMATRIX_ScrollDown(ih);
if (has_lincol)
{
iupMatrixMarkBlockInc(ih, lin, col);
if (ih->data->merge_info_count)
{
int merged = iupMatrixGetMerged(ih, lin, col);
if (merged)
{
int endLin, endCol;
iupMatrixGetMergedRect(ih, merged, NULL, &endLin, NULL, &endCol);
if (lin == 0 || (ih->data->noscroll_as_title && lin < ih->data->lines.num_noscroll))
iupMatrixMarkBlockInc(ih, 0, endCol);
else
iupMatrixMarkBlockInc(ih, endLin, 0);
}
}
iupMatrixDrawUpdate(ih);
iMatrixMouseCallMoveCb(ih, lin, col);
}
return IUP_DEFAULT;
}
else if(iupMatrixColResIsResizing(ih)) /* Make a resize in a column size */
iupMatrixColResMove(ih, x);
else if (has_lincol && iMatrixIsDropArea(ih, lin, col, x, y) != 0)
iMatrixMouseSetCursor(ih, "ARROW");
else if (iupMatrixColResCheckChangeCursor(ih, x, y))
iMatrixMouseSetCursor(ih, "RESIZE_W");
else
iMatrixMouseResetCursor(ih);
if (has_lincol)
iMatrixMouseCallMoveCb(ih, lin, col);
return IUP_DEFAULT;
}