summaryrefslogtreecommitdiff
path: root/iup/srccontrols/matrix/iupmat_scroll.c
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/srccontrols/matrix/iupmat_scroll.c
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/srccontrols/matrix/iupmat_scroll.c')
-rwxr-xr-xiup/srccontrols/matrix/iupmat_scroll.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/iup/srccontrols/matrix/iupmat_scroll.c b/iup/srccontrols/matrix/iupmat_scroll.c
new file mode 100755
index 0000000..24bbef2
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_scroll.c
@@ -0,0 +1,495 @@
+/** \file
+ * \brief iupmatrix control
+ * scrolling
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_focus.h"
+#include "iupmat_aux.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+/* Macros used by "dir" parameter of the iMatrixScrollLine and iMatrixScrollColumn functions */
+#define IMAT_SCROLL_LEFT 0
+#define IMAT_SCROLL_RIGHT 1
+#define IMAT_SCROLL_UP 2
+#define IMAT_SCROLL_DOWN 3
+
+
+/**************************************************************************/
+/* Private functions */
+/**************************************************************************/
+
+
+static int iMatrixScrollIsFullVisibleLast(ImatLinColData *p)
+{
+ int i, sum = 0;
+
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+
+ if (sum > p->visible_size)
+ return 0;
+ else
+ return 1;
+}
+
+/* Scroll columns/lines in the left/top side of the matriz until the last column/line is FULLY visible.
+ -> m : Define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL] */
+static void iMatrixScrollToVisible(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (index < p->first)
+ {
+ p->first = index;
+ return;
+ }
+ else if (index > p->last)
+ {
+ /* Increment the first column/line until the index is visible */
+ while(index > p->last && p->last != (p->num - 1))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+
+ if (index == p->last)
+ {
+ /* must increment util the last is fully visible */
+ while(index == p->last && p->last != (p->num - 1) && !iMatrixScrollIsFullVisibleLast(p))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+}
+
+/* Callback to report to the user which visualization area of
+ the matrix changed. */
+static void iMatrixScrollCallScrollTopCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "SCROLLTOP_CB");
+ if (cb)
+ cb(ih, ih->data->lines.first, ih->data->columns.first);
+}
+
+static int iMatrixScrollGetNextNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index < p->num && p->sizes[index] == 0)
+ index++;
+
+ if (index > p->num-1)
+ {
+ if (p->num == 1)
+ return 1;
+ else
+ return p->num-1;
+ }
+ else
+ return index;
+}
+
+static int iMatrixScrollGetPrevNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index > 0 && p->sizes[index] == 0)
+ index--;
+
+ if (index < 1)
+ return 1;
+ else
+ return index;
+}
+
+static void iMatrixScrollSetFocusScrollToVisible(Ihandle* ih, int m, int index)
+{
+ if (m == IMAT_PROCESS_COL)
+ iupMatrixFocusSet(ih, ih->data->lines.focus_cell, index);
+ else
+ iupMatrixFocusSet(ih, index, ih->data->columns.focus_cell);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+}
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+
+/* Move using the cells of matrix.
+ Receive as a parameter a pointer to a function that will make the work,
+ in fact. This is done to avoid a test to each of the manipulation cursor
+ functions, verifying if it is necessary to call or not the scroll
+ callback. This is only done here.
+ -> func - pointer to the function that will make the movement
+ -> mode - parameter passed to func, specify if the movement request is of
+ the scrollbar or the keyboard
+ -> pos - parameter passed to func, that will be the handle position function
+ of the scrollbar, returning the scrollbar thumb position...
+ if func is other function, this parameter will be ignored
+ -> m - parameter passed to func, specify which is the mode of operation:
+ lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iupMatrixEditForceHidden(ih);
+
+ func(ih, mode, pos, m);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 0);
+ }
+}
+
+void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, col);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, lin);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 1);
+ }
+}
+
+/* This function is called when the "home" key is pressed.
+ In the first time, go to the beginning of the line.
+ In the second time, go to the beginning of the page.
+ In the third time, go to the beginning of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollHome(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->homekeycount == 0) /* go to the beginning of the line */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.first);
+ }
+ else if(ih->data->homekeycount == 1) /* go to the beginning of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->homekeycount == 2) /* go to the beginning of the matrix 1:1 */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ ih->data->lines.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_LIN, 1);
+
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called when the "end" key is pressed.
+ In the first time, go to the end of the line.
+ In the second time, go to the end of the page.
+ In the third time, go to the end of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollEnd(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->endkeycount == 0) /* go to the end of the line */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, last_col);
+ }
+ else if(ih->data->endkeycount == 1) /* go to the end of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.last, ih->data->columns.last);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->endkeycount == 2) /* go to the end of the matrix */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ int last_lin = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_LIN, ih->data->lines.num-1);
+
+ iupMatrixFocusSet(ih, last_lin, last_col);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called to move a cell to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first-1);
+ }
+}
+
+/* This function is called to move a cell to the right or down.
+ -> mode : indicate if the command from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, m, p->focus_cell+1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetNextNonEmpty(ih, m, p->first+1);
+ }
+}
+
+/* This function is called to move a page to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgLeft) or columns (PgUp) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell - (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first - (p->last - p->first));
+ }
+}
+
+/* This function is called to move a page to the right or down.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgDown) or columns (PgRight) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, p->focus_cell + (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first + (p->last - p->first));
+ }
+}
+
+void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ int oldlin = ih->data->lines.focus_cell;
+ int oldcol = ih->data->columns.focus_cell;
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ /* try the normal processing of next cell down */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN);
+
+ if(ih->data->lines.focus_cell == oldlin && ih->data->columns.focus_cell == oldcol)
+ {
+ /* If focus was not changed, it was because it is in the last line of the column.
+ Go to the next column of the same line. */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL);
+ }
+}
+
+/* This function is called when a drag is performed in the scrollbar.
+ -> x : scrollbar thumb position, value between 0 and 1
+ -> mode : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPos(Ihandle* ih, int mode, float pos, int m)
+{
+ int scroll_pos, index, vp;
+ float d;
+ ImatLinColData* p;
+ (void)mode;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ p = &(ih->data->lines);
+ d = IupGetFloat(ih, "DY");
+ }
+ else
+ {
+ p = &(ih->data->columns);
+ d = IupGetFloat(ih, "DX");
+ }
+
+ if (p->num == 1)
+ {
+ p->first = 1;
+ return;
+ }
+
+ scroll_pos = (int)(pos * p->total_size + 0.5);
+
+ vp = 0;
+ for(index = 1; index < p->num; index++)
+ {
+ vp += p->sizes[index];
+ if (vp > scroll_pos)
+ break;
+ }
+
+ if (index == p->num)
+ {
+ if (p->num == 1)
+ index = 1;
+ else
+ index = p->num-1;
+ }
+
+ p->first = index;
+}
+
+int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y)
+{
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ switch(action)
+ {
+ case IUP_SBUP : iupMatrixScrollUp(ih); break;
+ case IUP_SBDN : iupMatrixScrollDown(ih); break;
+ case IUP_SBPGUP : iupMatrixScrollPgUp(ih); break;
+ case IUP_SBPGDN : iupMatrixScrollPgDown(ih); break;
+ case IUP_SBRIGHT : iupMatrixScrollRight(ih); break;
+ case IUP_SBLEFT : iupMatrixScrollLeft(ih); break;
+ case IUP_SBPGRIGHT : iupMatrixScrollPgRight(ih); break;
+ case IUP_SBPGLEFT : iupMatrixScrollPgLeft(ih); break;
+ case IUP_SBPOSV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBPOSH : iupMatrixScrollPosHor(ih,x); break;
+ case IUP_SBDRAGV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBDRAGH : iupMatrixScrollPosHor(ih,x); break;
+ }
+
+ iupMatrixDrawUpdate(ih);
+
+ return IUP_DEFAULT;
+}