/** ** rawdl2.c ---- Mini GUI for MGRX, raw data list 2 ** ** Copyright (C) 2020 Mariano Alvarez Fernandez ** [e-mail: malfer at telefonica dot net] ** ** This file is part of the GRX graphics library. ** ** The GRX graphics library is free software; you can redistribute it ** and/or modify it under some conditions; see the "copying.grx" file ** for details. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** **/ #include #include #include #include "grguip.h" typedef struct _guiRawDataList2 { GUIRDL2Intf *f; // interfaz int sreg; // selected reg int vreg; // max num of regs visible (gen) int freg; // first reg in screen (gen) int dx, dy; // latest displacement requested to paint int ewidth, eheight; // effective dimensions (without scb) (gen) GUIScrollbar *vscb; // vertical scrollbar (can be NULL) int selected; // the whole rdl has the focus int pressed; // left mouse pressed } GUIRawDataList2; static int check_freg(GUIRawDataList2 *rdl2); static void paint_selected_box(GUIRawDataList2 *rdl2, int blt); static void show_rdl2_item(GUIRawDataList2 *rdl2, int ind); /***************************/ GUIRawDataList2 * GUIRDL2Create(GUIRDL2Intf *f, int sreg) { GUIRawDataList2 *rdl2; int xscb; rdl2 = malloc(sizeof(GUIRawDataList2)); if (rdl2 == NULL) return NULL; rdl2->f = f; rdl2->dx = 0; rdl2->dy = 0; rdl2->selected = 0; rdl2->pressed = 0; rdl2->vscb = NULL; rdl2->sreg = sreg; rdl2->freg = 0; rdl2->vreg = (rdl2->f->height - 6) / rdl2->f->regheight; if (rdl2->vreg >= rdl2->f->nreg) { rdl2->vreg = rdl2->f->nreg; rdl2->ewidth = rdl2->f->width; rdl2->eheight = rdl2->f->height; } else { xscb = rdl2->f->x + rdl2->f->width - GUI_SB_DEFAULT_THICK - 2; rdl2->vscb = GUIScrollbarCreate(GUI_TSB_VERTICAL, xscb, rdl2->f->y+2, GUI_SB_DEFAULT_THICK, rdl2->f->height-4); if (rdl2->vscb == NULL) { free(rdl2); return NULL; } // we know freg = 0, so only check sreg >= vreg if (rdl2->sreg >= rdl2->vreg) rdl2->freg = rdl2->sreg - rdl2->vreg + 1; GUIScrollbarSetLimits(rdl2->vscb, 0, rdl2->f->nreg-1, rdl2->freg, rdl2->freg+rdl2->vreg-1); rdl2->ewidth = rdl2->f->width - GUI_SB_DEFAULT_THICK - 1; rdl2->eheight = rdl2->f->height; } return rdl2; } /***************************/ void GUIRDL2Destroy(GUIRawDataList2 *rdl2) { if (rdl2->vscb) free(rdl2->vscb); free(rdl2); } /***************************/ void GUIRDL2SetSreg(GUIRawDataList2 *rdl2, int sreg) { rdl2->sreg = sreg; if (rdl2->sreg < rdl2->freg) rdl2->freg = rdl2->sreg; if (rdl2->sreg >= rdl2->vreg+rdl2->freg) rdl2->freg = rdl2->sreg - rdl2->vreg + 1; } /***************************/ int GUIRDL2GetSreg(GUIRawDataList2 *rdl2) { return rdl2->sreg; } /***************************/ void GUIRDL2Paint(GUIRawDataList2 *rdl2, int dx, int dy, int blt) { int x, y, i; rdl2->dx = dx; rdl2->dy = dy; x = rdl2->f->x + rdl2->dx; y = rdl2->f->y + rdl2->dy; GrBox(x, y, x+rdl2->f->width-1, y+rdl2->f->height-1, _objectlcolor); GrFilledBox(x+1, y+1, x+rdl2->f->width-2, y+rdl2->f->height-2, rdl2->f->bg); if (rdl2->selected) { paint_selected_box(rdl2, 0); } for (i=0; ivreg; i++) show_rdl2_item(rdl2, i); if (rdl2->vscb) { GUIScrollbarSetLimits(rdl2->vscb, 0, rdl2->f->nreg-1, rdl2->freg, rdl2->freg+rdl2->vreg-1); GUIScrollbarPaint(rdl2->vscb, rdl2->dx, rdl2->dy, 0); } if (blt) GUIDBCurCtxBltRectToScreen(x, y, x+rdl2->f->width-1, y+rdl2->f->height-1); } /***************************/ void GUIRDL2SetSelected(GUIRawDataList2 *rdl2, int selected, int paint, int blt) { rdl2->selected = selected; if (paint) paint_selected_box(rdl2, blt); } /***************************/ static int check_freg(GUIRawDataList2 *rdl2) { if (rdl2->sreg < rdl2->freg) { rdl2->freg = rdl2->sreg; return -1; } if (rdl2->sreg >= rdl2->vreg+rdl2->freg) { rdl2->freg = rdl2->sreg - rdl2->vreg + 1; return 1; } return 0; } /***************************/ static void paint_selected_box(GUIRawDataList2 *rdl2, int blt) { GrLineOption glo; int x, y; x = rdl2->f->x + rdl2->dx; y = rdl2->f->y + rdl2->dy; if (rdl2->selected) { glo.lno_color = rdl2->f->fg; glo.lno_width = 1; glo.lno_pattlen = 2; glo.lno_dashpat = (unsigned char *)"\2\1"; GrCustomBox(x+2, y+2, x+rdl2->ewidth-3, y+rdl2->eheight-3, &glo); } else { GrBox(x+2, y+2, x+rdl2->ewidth-3, y+rdl2->eheight-3, rdl2->f->bg); } if (blt) GUIDBCurCtxBltRectToScreen(x+2, y+2, x+rdl2->ewidth-3, y+rdl2->eheight-3); } /***************************/ static void show_rdl2_item(GUIRawDataList2 *rdl2, int ind) { int x, y, selected = 0; if (ind >= rdl2->vreg) return; if (ind < 0) return; if (ind+rdl2->freg == rdl2->sreg) selected = 1; x = rdl2->f->x + rdl2->dx + 3; y = rdl2->f->y + rdl2->dy + 3 + ind * rdl2->f->regheight; GrFilledBox(x, y, x+rdl2->ewidth-7, y+rdl2->f->regheight-1, selected ? rdl2->f->fg : rdl2->f->bg); GrSetClipBox(x+1, y, x+rdl2->ewidth-8, y+rdl2->f->regheight-1); (rdl2->f->paint_reg)(x+1, y, ind+rdl2->freg, selected, rdl2->f->fg, rdl2->f->bg); GrResetClipBox(); } /***************************/ int GUIRDL2ProcessEvent(GUIRawDataList2 *rdl2, GrEvent *ev) // returns 1=event consumed, 0=not consumed, 2=element selected by user { long c; int ind, old, pos; int change = 0; int move = 0; int res = 0; int j, x, y; ind = rdl2->sreg - rdl2->freg; switch (ev->type) { case GREV_MOUSE : c = ev->p1; x = ev->p2 - rdl2->dx; y = ev->p3 - rdl2->dy; switch (c) { case GRMOUSE_LB_PRESSED : if (GrCheckCoordInto(x, y, rdl2->f->x, rdl2->f->y, rdl2->ewidth, rdl2->eheight)) { rdl2->pressed = 1; pos = (y - rdl2->f->y -3) / rdl2->f->regheight; if ((pos >= 0) && (pos < rdl2->vreg)) { if (ind != pos) { old = ind; ind = pos; rdl2->sreg = rdl2->freg + ind; change = 1; } res = 1; } } else if (rdl2->vscb) { return GUIScrollbarProcessEvent(rdl2->vscb, ev); } break; case GRMOUSE_LB_RELEASED : if (rdl2->pressed) { rdl2->pressed = 0; pos = (y - rdl2->f->y -3) / rdl2->f->regheight; if (pos == ind) return 2; res = 1; } else if (rdl2->vscb) { return GUIScrollbarProcessEvent(rdl2->vscb, ev); } break; case GRMOUSE_B4_RELEASED : if (rdl2->freg > 0) { rdl2->freg--; change = move = 1; } res = 1; break; case GRMOUSE_B5_RELEASED : if (rdl2->freg < rdl2->f->nreg-rdl2->vreg) { rdl2->freg++; change = move = 1; } res = 1; break; } break; case GREV_MMOVE : y = ev->p3 - rdl2->dy; if (rdl2->pressed) { if (ev->p1 & GRMOUSE_LB_STATUS) { pos = (y - rdl2->f->y -3) / rdl2->f->regheight; if ((pos >= 0) && (pos < rdl2->vreg)) { if (ind != pos) { old = ind; ind = pos; change = 1; rdl2->sreg = rdl2->freg + ind; } } } res = 1; } else if (rdl2->vscb) { return GUIScrollbarProcessEvent(rdl2->vscb, ev); } break; case GREV_KEY : c = ev->p1; switch (c) { case GrKey_Up : if (rdl2->sreg > 0) { rdl2->sreg--; old = ind; ind = rdl2->sreg - rdl2->freg; change = 1; if (check_freg(rdl2) != 0) move = 1; } res = 1; break; case GrKey_Down : if (rdl2->sreg < rdl2->f->nreg-1) { rdl2->sreg++; old = ind; ind = rdl2->sreg - rdl2->freg; change = 1; if (check_freg(rdl2) != 0) move = 1; } res = 1; break; case GrKey_PageUp : if (check_freg(rdl2) != 0) { change = move = 1; } else if (rdl2->freg == 0) { if (rdl2->sreg > 0) { rdl2->sreg = 0; old = ind; ind = rdl2->sreg - rdl2->freg; change = 1; } } else if (rdl2->freg > 0) { rdl2->freg -= rdl2->vreg - 1; rdl2->sreg -= rdl2->vreg - 1; if (rdl2->freg < 0) rdl2->freg = 0; if (rdl2->sreg < 0) rdl2->sreg = 0; change = move = 1; } res = 1; break; case GrKey_PageDown : if (check_freg(rdl2) != 0) { change = move = 1; } else if (rdl2->freg == rdl2->f->nreg - rdl2->vreg) { if (rdl2->sreg < rdl2->f->nreg-1) { rdl2->sreg = rdl2->f->nreg - 1; old = ind; ind = rdl2->sreg - rdl2->freg; change = 1; } } else if (rdl2->freg < rdl2->f->nreg - rdl2->vreg) { rdl2->freg += rdl2->vreg - 1; rdl2->sreg += rdl2->vreg - 1; if (rdl2->freg > rdl2->f->nreg-rdl2->vreg) rdl2->freg = rdl2->f->nreg - rdl2->vreg; if (rdl2->sreg >= rdl2->f->nreg) rdl2->sreg = rdl2->f->nreg - 1; change = move = 1; } res = 1; break; case GrKey_Return : if (check_freg(rdl2) != 0) { change = move = 1; } res = 2; } break; case GREV_NULL : if (rdl2->vscb) { return GUIScrollbarProcessEvent(rdl2->vscb, ev); } break; case GREV_SCBVERT: if (rdl2->vscb && GUIScrollbarGetAid(rdl2->vscb) == ev->p2) { if (rdl2->freg != ev->p1) { rdl2->freg = ev->p1; change = 1; move = 1; } res = 1; } break; } if (change) { if (move) { for(j=0; jvreg; j++) show_rdl2_item(rdl2, j); if (rdl2->vscb) { GUIScrollbarSetLimits(rdl2->vscb, 0, rdl2->f->nreg-1, rdl2->freg, rdl2->freg+rdl2->vreg-1); GUIScrollbarPaint(rdl2->vscb, rdl2->dx, rdl2->dy, 0); } } else { show_rdl2_item(rdl2, old); show_rdl2_item(rdl2, ind); } x = rdl2->f->x + rdl2->dx; y = rdl2->f->y + rdl2->dy; GUIDBCurCtxBltRectToScreen(x, y, x+rdl2->f->width-1, y+rdl2->f->height-1); } return res; }