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

1693 lines
52 KiB
C
Executable File

/** \file
* \brief iupmatrix control
* draw functions
*
* See Copyright Notice in "iup.h"
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "iup.h"
#include "iupcbs.h"
#include <cd.h>
#include <cd_old.h>
#include "iup_object.h"
#include "iup_attrib.h"
#include "iup_str.h"
#include "iup_drv.h"
#include "iup_drvfont.h"
#include "iup_stdcontrols.h"
#include "iup_image.h"
#include "iup_controls.h"
#include "iup_cdutil.h"
#include "iupmat_def.h"
#include "iupmat_cd.h"
#include "iupmat_draw.h"
#include "iupmat_aux.h"
#include "iupmat_getset.h"
#include "iupmat_mark.h"
#define IMAT_FEEDBACK_SIZE 16
static unsigned char imatrix_toggleoff_alpha[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
};
static unsigned char imatrix_toggleon_alpha[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 89, 252, 89, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 84, 239, 106, 239, 84, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 84, 239, 60, 0, 60, 239, 84, 0, 0, 0, 0, 0, 255,
255, 0, 84, 239, 60, 0, 0, 0, 60, 239, 84, 0, 0, 0, 0, 255,
255, 16, 227, 60, 0, 0, 0, 0, 0, 60, 239, 84, 0, 0, 0, 255,
255, 0, 8, 0, 0, 0, 0, 0, 0, 0, 60, 239, 84, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 239, 84, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 227, 16, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
};
static unsigned char imatrix_dropdown_alpha[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE] =
{
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 128, 128, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 128, 255, 255, 128, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 128, 255, 255, 255, 255, 128, 000, 000, 000, 000, 000,
000, 000, 000, 000, 128, 255, 255, 255, 255, 255, 255, 128, 000, 000, 000, 000,
000, 000, 000, 128, 255, 255, 255, 255, 255, 255, 255, 255, 128, 000, 000, 000,
000, 000, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 000, 000,
000, 000, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000
};
static unsigned char imatrix_sortup_alpha[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0,
0, 0, 32, 239, 60, 0, 0, 0, 0, 0, 0, 0, 60, 239, 32, 0,
0, 0, 0, 84, 239, 60, 0, 0, 0, 0, 0, 60, 239, 84, 0, 0,
0, 0, 0, 0, 84, 239, 60, 0, 0, 0, 60, 239, 84, 0, 0, 0,
0, 0, 8, 0, 0, 84, 239, 60, 0, 60, 239, 84, 0, 0, 8, 0,
0, 0, 32, 32, 0, 0, 84, 239, 106, 239, 84, 0, 0, 32, 32, 0,
0, 0, 32, 239, 60, 0, 0, 89, 252, 89, 0, 0, 60, 239, 32, 0,
0, 0, 0, 84, 239, 60, 0, 0, 31, 0, 0, 60, 239, 84, 0, 0,
0, 0, 0, 0, 84, 239, 60, 0, 0, 0, 60, 239, 84, 0, 0, 0,
0, 0, 0, 0, 0, 84, 239, 60, 0, 60, 239, 84, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 84, 239, 106, 239, 84, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 89, 252, 89, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static unsigned char imatrix_sortdown_alpha[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 89, 252, 89, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 84, 239, 106, 239, 84, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 84, 239, 60, 0, 60, 239, 84, 0, 0, 0, 0,
0, 0, 0, 0, 84, 239, 60, 0, 0, 0, 60, 239, 84, 0, 0, 0,
0, 0, 0, 84, 239, 60, 0, 0, 31, 0, 0, 60, 239, 84, 0, 0,
0, 0, 32, 239, 60, 0, 0, 89, 252, 89, 0, 0, 60, 239, 32, 0,
0, 0, 32, 32, 0, 0, 84, 239, 106, 239, 84, 0, 0, 32, 32, 0,
0, 0, 8, 0, 0, 84, 239, 60, 0, 60, 239, 84, 0, 0, 8, 0,
0, 0, 0, 0, 84, 239, 60, 0, 0, 0, 60, 239, 84, 0, 0, 0,
0, 0, 0, 84, 239, 60, 0, 0, 0, 0, 0, 60, 239, 84, 0, 0,
0, 0, 32, 239, 60, 0, 0, 0, 0, 0, 0, 0, 60, 239, 32, 0,
0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
/**************************************************************************/
/* Private functions */
/**************************************************************************/
static void iMatrixDrawSetCellClipping(Ihandle* ih, int x1, int x2, int y1, int y2)
{
int old_clip = cdCanvasClip(ih->data->cd_canvas, CD_QUERY);
if (old_clip == CD_CLIPAREA)
{
cdCanvasGetClipArea(ih->data->cd_canvas, &(ih->data->clip_x1), &(ih->data->clip_x2), &(ih->data->clip_y1), &(ih->data->clip_y2));
y1 = iupMATRIX_INVERTYAXIS(ih, y1);
y2 = iupMATRIX_INVERTYAXIS(ih, y2);
if (x1 > x2) { int tmp = x1; x1 = x2; x2 = tmp; }
if (y1 > y2) { int tmp = y1; y1 = y2; y2 = tmp; }
if (x1 < ih->data->clip_x1) x1 = ih->data->clip_x1;
if (x2 > ih->data->clip_x2) x2 = ih->data->clip_x2;
if (y1 < ih->data->clip_y1) y1 = ih->data->clip_y1;
if (y2 > ih->data->clip_y2) y2 = ih->data->clip_y2;
if (x1 > x2) x2 = x1;
if (y1 > y2) y2 = y1;
cdCanvasClipArea(ih->data->cd_canvas, x1, x2, y1, y2);
cdCanvasClip(ih->data->cd_canvas, CD_CLIPAREA);
}
}
static void iMatrixDrawResetCellClipping(Ihandle* ih)
{
int old_clip = cdCanvasClip(ih->data->cd_canvas, CD_QUERY);
if (old_clip == CD_CLIPAREA)
cdCanvasClipArea(ih->data->cd_canvas, ih->data->clip_x1, ih->data->clip_x2, ih->data->clip_y1, ih->data->clip_y2);
}
static int iMatrixDrawCallDrawCB(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, IFniiiiiiC draw_cb)
{
int ret;
iMatrixDrawSetCellClipping(ih, x1, x2, y1, y2);
ret = draw_cb(ih, lin, col, x1, x2, iupMATRIX_INVERTYAXIS(ih, y1), iupMATRIX_INVERTYAXIS(ih, y2), ih->data->cd_canvas);
iMatrixDrawResetCellClipping(ih);
if (ret == IUP_DEFAULT)
return 0;
return 1;
}
/* Change the CD foreground color, for the selected color to draw a cell with
its FOREGROUND COLOR. This involves checking if there is a color attribute
that cell. If no, uses a color attribute for the line, else if no for the
column, else if no for the entire matrix. Finally, if not find any of
these, use the default color.
-> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
top cell of the matrix; lin and col values = 0 represents the
title lines and columns.
-> marked - indicate if a cell is marked. If yes, its color is attenuated.
*/
static unsigned long iMatrixDrawSetFgColor(Ihandle* ih, int lin, int col, int marked, int active)
{
unsigned char r = 0, g = 0, b = 0;
iupMatrixGetFgRGB(ih, lin, col, &r, &g, &b, marked, active);
return cdCanvasForeground(ih->data->cd_canvas, cdEncodeColor(r, g, b));
}
/* Change the CD foreground color, for the selected color to draw a cell with
its BACKGROUND COLOR. This involves checking if there is a color attribute
that cell. If no, uses a color attribute for the line, else if no for the
column, else if no for the entire matrix. Finally, if not find any of
these, use the default color.
-> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
top cell of the matrix; lin and col values = 0 represents the
title lines and columns.
-> marked - indicate if a cell is marked. If yes, its color is attenuated.
*/
static unsigned long iMatrixDrawSetBgColor(Ihandle* ih, int lin, int col, int marked, int active)
{
unsigned char r = 255, g = 255, b = 255;
iupMatrixGetBgRGB(ih, lin, col, &r, &g, &b, marked, active);
return cdCanvasForeground(ih->data->cd_canvas, cdEncodeColor(r, g, b));
}
static unsigned long iMatrixDrawSetTypeColor(Ihandle* ih, const char* color, int marked, int active)
{
unsigned char r = 0, g = 0, b = 0;
iupMatrixGetTypeRGB(ih, color, &r, &g, &b, marked, active);
return cdCanvasForeground(ih->data->cd_canvas, cdEncodeColor(r, g, b));
}
static int iMatrixDrawFrameVertLineTitleHighlight(Ihandle* ih, int lin, int col, int x, int y1, int y2, long framecolor)
{
if (ih->data->flat)
return 1;
if (col > 0)
{
int transp = iupMatrixGetFrameVertColor(ih, lin, col - 1, &framecolor, 0); /* framecolor is ignored here */
if (transp)
return 1;
}
cdCanvasForeground(ih->data->cd_canvas, CD_WHITE);
iupMATRIX_LINE(ih, x, y1, x, y2);
return 0;
}
static int iMatrixDrawFrameHorizLineTitleHighlight(Ihandle* ih, int lin, int col, int x1, int x2, int y, long framecolor)
{
if (ih->data->flat)
return 1;
if (lin > 0)
{
int transp = iupMatrixGetFrameHorizColor(ih, lin - 1, col, &framecolor, 0); /* framecolor is ignored here */
if (transp)
return 1;
}
cdCanvasForeground(ih->data->cd_canvas, CD_WHITE);
iupMATRIX_LINE(ih, x1, y, x2, y);
return 0;
}
static int iMatrixDrawFrameHorizLineCell(Ihandle* ih, int lin, int col, int x1, int x2, int y, long framecolor)
{
int transp = iupMatrixGetFrameHorizColor(ih, lin, col, &framecolor, 0);
if (transp)
return 1;
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_LINE(ih, x1, y, x2, y); /* horizontal line */
return 0;
}
static int iMatrixDrawFrameHorizLineTitle(Ihandle* ih, int col, int x1, int x2, int y, long framecolor)
{
int transp = iupMatrixGetFrameHorizColor(ih, 0, col, &framecolor, 1);
if (transp)
return 1;
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_LINE(ih, x1, y, x2, y); /* horizontal line */
return 0;
}
static int iMatrixDrawFrameVertLineTitle(Ihandle* ih, int lin, int x, int y1, int y2, long framecolor)
{
int transp = iupMatrixGetFrameVertColor(ih, lin, 0, &framecolor, 1);
if (transp)
return 1;
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_LINE(ih, x, y1, x, y2); /* vertical line */
return 0;
}
static int iMatrixDrawFrameVertLineCell(Ihandle* ih, int lin, int col, int x, int y1, int y2, long framecolor)
{
int transp = iupMatrixGetFrameVertColor(ih, lin, col, &framecolor, 0);
if (transp)
return 1;
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_LINE(ih, x, y1, x, y2); /* vertical line */
return 0;
}
static void iMatrixDrawFrameRectTitle(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, int framehighlight)
{
/* avoid drawing over the frame of the next cell */
x2 -= IMAT_FRAME_W / 2;
y2 -= IMAT_FRAME_H / 2;
/********************* VERTICAL *************************/
/* right vertical line */
iMatrixDrawFrameVertLineCell(ih, lin, col, x2, y1, y2, framecolor);
if (col == 0)
{
/* left vertical line */
iMatrixDrawFrameVertLineTitle(ih, lin, x1, y1, y2, framecolor);
x1++;
}
else if (col == 1 && ih->data->columns.dt[0].size == 0)
{
/* If does not have line titles then draw the left vertical line */
iMatrixDrawFrameVertLineCell(ih, lin, col - 1, x1, y1, y2, framecolor);
x1++;
}
/* Titles have a bright vertical line near the frame, at left */
if (framehighlight)
iMatrixDrawFrameVertLineTitleHighlight(ih, lin, col, x1, y1 + 1, y2 - 1, framecolor);
/********************* HORIZONTAL *************************/
/* bottom horizontal line */
iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2, y2, framecolor);
if (lin == 0)
{
/* top horizontal line */
iMatrixDrawFrameHorizLineTitle(ih, col, x1, x2, y1, framecolor);
y1++;
}
else if (lin == 1 && ih->data->lines.dt[0].size == 0)
{
/* If does not have column titles then draw the top horizontal line */
iMatrixDrawFrameHorizLineCell(ih, lin - 1, col, x1, x2 - 1, y1, framecolor);
y1++;
}
/* Titles have a bright horizontal line near the frame, at top */
if (framehighlight)
iMatrixDrawFrameHorizLineTitleHighlight(ih, lin, col, x1, x2 - 1, y1, framecolor);
}
static void iMatrixDrawFrameRectCell(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor)
{
int transp;
if (col == 1 && ih->data->columns.dt[0].size == 0)
{
/* If does not have line titles then draw the >> left line << of the cell frame */
iMatrixDrawFrameVertLineCell(ih, lin, col - 1, x1, y1, y2 - 1, framecolor);
}
if (lin == 1 && ih->data->lines.dt[0].size == 0)
{
/* If does not have column titles then draw the >> top line << of the cell frame */
iMatrixDrawFrameHorizLineCell(ih, lin - 1, col, x1, x2 - 1, y1, framecolor);
}
/* bottom line */
transp = iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2 - 1, y2 - 1, framecolor);
/* right line */
iMatrixDrawFrameVertLineCell(ih, lin, col, x2 - 1, y1, transp ? y2 - 1 : y2 - 2, framecolor);
}
static void iMatrixDrawFeedbackImage(Ihandle* ih, int x1, int x2, int y1, int y2, int lin, int col, int active, int marked, const char*name, unsigned char* alpha)
{
int x, y;
Ihandle* image = IupImageGetHandle(name);
if (image)
{
long bgcolor;
int image_width = IupGetInt(image, "WIDTH");
int image_height = IupGetInt(image, "HEIGHT");
unsigned char r = 255, g = 255, b = 255;
iupMatrixGetBgRGB(ih, lin, col, &r, &g, &b, marked, active);
bgcolor = cdEncodeColor(r, g, b);
y = (y2 + y1 + image_height) / 2;
x = (x2 + x1 - image_width) / 2;
cdIupDrawImage(ih->data->cd_canvas, image, x, iupMATRIX_INVERTYAXIS(ih, y), 0, 0, !active, bgcolor);
}
else
{
static unsigned char red[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE];
static unsigned char green[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE];
static unsigned char blue[IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE];
static unsigned char last_r = 0, last_g = 0, last_b = 0;
static int init = 1;
unsigned char r = 0, g = 0, b = 0;
iupMatrixGetFgRGB(ih, lin, col, &r, &g, &b, marked, active);
if (init || last_r != r || last_g != g || last_b != b)
{
int count = IMAT_FEEDBACK_SIZE * IMAT_FEEDBACK_SIZE;
memset(red, r, count);
memset(green, g, count);
memset(blue, b, count);
last_r = r;
last_g = g;
last_b = b;
init = 0;
}
y = (y2 + y1 + IMAT_FEEDBACK_SIZE) / 2;
x = (x2 + x1 - IMAT_FEEDBACK_SIZE) / 2;
cdCanvasPutImageRectRGBA(ih->data->cd_canvas, IMAT_FEEDBACK_SIZE, IMAT_FEEDBACK_SIZE, red, green, blue, alpha, x, iupMATRIX_INVERTYAXIS(ih, y), IMAT_FEEDBACK_SIZE, IMAT_FEEDBACK_SIZE, 0, 0, 0, 0);
}
}
static int iMatrixDrawSortSign(Ihandle* ih, int x2, int y1, int y2, int col, int active)
{
int x1;
char* sort = iupAttribGetId(ih, "SORTSIGN", col);
if (!sort || iupStrEqualNoCase(sort, "NO"))
return 0;
/* feedback area */
iupMatrixDrawSetDropFeedbackArea(&x1, &y1, &x2, &y2);
if (iupStrEqualNoCase(sort, "DOWN"))
iMatrixDrawFeedbackImage(ih, x1, x2, y1, y2, 0, col, active, 0, iupAttribGet(ih, "SORTIMAGEDOWN"), imatrix_sortdown_alpha);
else
iMatrixDrawFeedbackImage(ih, x1, x2, y1, y2, 0, col, active, 0, iupAttribGet(ih, "SORTIMAGEUP"), imatrix_sortup_alpha);
return 1;
}
static void iMatrixDrawDropdownButton(Ihandle* ih, int x2, int y1, int y2, int lin, int col, int marked, int active)
{
int x1;
/* feedback area */
iupMatrixDrawSetDropFeedbackArea(&x1, &y1, &x2, &y2);
iMatrixDrawFeedbackImage(ih, x1, x2, y1, y2, lin, col, active, marked, iupAttribGet(ih, "DROPIMAGE"), imatrix_dropdown_alpha);
}
static void iMatrixDrawToggle(Ihandle* ih, int x1, int x2, int y1, int y2, int lin, int col, int marked, int active, int toggle_centered)
{
int togglevalue = 0;
/* toggle area */
iupMatrixDrawSetToggleFeedbackArea(toggle_centered, &x1, &y1, &x2, &y2);
if (toggle_centered)
{
char* value = iupMatrixGetValueDisplay(ih, lin, col);
togglevalue = iupStrBoolean(value);
}
else
togglevalue = iupAttribGetIntId2(ih, "TOGGLEVALUE", lin, col);
/* toggle check */
if (togglevalue)
iMatrixDrawFeedbackImage(ih, x1, x2, y1, y2, lin, col, active, marked, iupAttribGet(ih, "TOGGLEIMAGEON"), imatrix_toggleon_alpha);
else
iMatrixDrawFeedbackImage(ih, x1, x2, y1, y2, lin, col, active, marked, iupAttribGet(ih, "TOGGLEIMAGEOFF"), imatrix_toggleoff_alpha);
}
static void iMatrixDrawBackground(Ihandle* ih, int x1, int x2, int y1, int y2, int marked, int active, int lin, int col)
{
/* avoid drawing over the frame of the next cell */
x2 -= IMAT_FRAME_W / 2;
y2 -= IMAT_FRAME_H / 2;
iMatrixDrawSetBgColor(ih, lin, col, marked, active);
iupMATRIX_BOX(ih, x1, x2, y1, y2);
}
static void iMatrixDrawText(Ihandle* ih, int x1, int x2, int y1, int y2, int col_alignment, int lin_alignment, int marked, int active, int lin, int col, const char* text)
{
int text_alignment;
int charheight, x, y, hidden_text_marks = 0;
iupdrvFontGetCharSize(ih, NULL, &charheight);
if (lin == 0 || ih->data->hidden_text_marks)
{
int text_w;
iupdrvFontGetMultiLineStringSize(ih, text, &text_w, NULL);
if (text_w > x2 - x1 + 1 - IMAT_PADDING_W - IMAT_FRAME_W)
{
if (lin == 0)
col_alignment = IMAT_ALIGN_START;
if (ih->data->hidden_text_marks)
hidden_text_marks = 1;
}
}
/* Set the color used to draw the text */
iMatrixDrawSetFgColor(ih, lin, col, marked, active);
IupCdSetFont(ih, ih->data->cd_canvas, iupMatrixGetFont(ih, lin, col));
/* Set the clip area to the cell region informed, the text maybe greater than the cell */
if (hidden_text_marks)
{
int crop = iupdrvFontGetStringWidth(ih, "...") + 2;
iMatrixDrawSetCellClipping(ih, x1, x2 - crop, y1, y2);
}
else
{
iMatrixDrawSetCellClipping(ih, x1, x2, y1, y2);
}
/* Create an space between text and cell frame */
x1 += IMAT_PADDING_W / 2; x2 -= IMAT_PADDING_W / 2;
y1 += IMAT_PADDING_H / 2; y2 -= IMAT_PADDING_H / 2;
iupMatrixGetCellAlign(ih, lin, col, &col_alignment, &lin_alignment);
if (lin_alignment == IMAT_ALIGN_CENTER)
{
y = iupROUND((y1 + y2) / 2.0);
if (col_alignment == IMAT_ALIGN_CENTER)
{
x = iupROUND((x1 + x2) / 2.0);
text_alignment = CD_CENTER;
}
else if (col_alignment == IMAT_ALIGN_START)
{
x = x1;
text_alignment = CD_WEST;
}
else /* RIGHT */
{
x = x2;
text_alignment = CD_EAST;
}
}
else if (lin_alignment == IMAT_ALIGN_START)
{
y = y1;
if (col_alignment == IMAT_ALIGN_CENTER)
{
x = iupROUND((x1 + x2) / 2.0);
text_alignment = CD_NORTH;
}
else if (col_alignment == IMAT_ALIGN_START)
{
x = x1;
text_alignment = CD_NORTH_WEST;
}
else /* RIGHT */
{
x = x2;
text_alignment = CD_NORTH_EAST;
}
}
else /* lin_alignment == IMAT_ALIGN_END */
{
y = y2;
if (col_alignment == IMAT_ALIGN_CENTER)
{
x = iupROUND((x1 + x2) / 2.0);
text_alignment = CD_SOUTH;
}
else if (col_alignment == IMAT_ALIGN_START)
{
x = x1;
text_alignment = CD_SOUTH_WEST;
}
else /* RIGHT */
{
x = x2;
text_alignment = CD_SOUTH_EAST;
}
}
cdCanvasTextAlignment(ih->data->cd_canvas, text_alignment);
iupMATRIX_TEXT(ih, x, y, text);
iMatrixDrawResetCellClipping(ih);
if (hidden_text_marks)
{
cdCanvasTextAlignment(ih->data->cd_canvas, CD_EAST);
y = (int)((y1 + y2) / 2.0 - 0.5);
x = x2 + IMAT_PADDING_W / 2;
iupMATRIX_TEXT(ih, x, y, "...");
}
}
static void iMatrixDrawColor(Ihandle* ih, int x1, int x2, int y1, int y2, int marked, int active, const char* color, long framecolor)
{
x1 += IMAT_PADDING_W / 2 + IMAT_FRAME_H / 2;
x2 -= IMAT_PADDING_W / 2 + IMAT_FRAME_W / 2;
y1 += IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
y2 -= IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
if (!iupAttribGetBoolean(ih, "TYPECOLORINACTIVE"))
active = 1; /* draw as active */
/* Fill the box with the color */
iMatrixDrawSetTypeColor(ih, color, marked, active);
iupMATRIX_BOX(ih, x1, x2, y1, y2);
/* Draw the frame */
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_RECT(ih, x1, x2, y1, y2);
}
static void iMatrixDrawFill(Ihandle* ih, int x1, int x2, int y1, int y2, int marked, int active, int lin, int col, const char* value, long framecolor)
{
int empty, fill = 0;
iupStrToInt(value, &fill);
if (fill < 0) fill = 0;
if (fill > 100) fill = 100;
/* Create an space between text and cell frame */
x1 += IMAT_PADDING_W / 2; x2 -= IMAT_PADDING_W / 2;
y1 += IMAT_PADDING_H / 2; y2 -= IMAT_PADDING_H / 2;
empty = ((x2 - x1)*(100 - fill)) / 100;
/* Fill the box with the color */
iMatrixDrawSetFgColor(ih, lin, col, marked, active);
iupMATRIX_BOX(ih, x1, x2 - empty, y1, y2);
if (ih->data->show_fill_value)
{
int y = (int)((y1 + y2) / 2.0 - 0.5);
int empty1 = ((x2 - x1)*fill) / 100;
char text[50];
sprintf(text, "%d%%", fill);
IupCdSetFont(ih, ih->data->cd_canvas, iupMatrixGetFont(ih, lin, col));
cdCanvasTextAlignment(ih->data->cd_canvas, CD_CENTER);
iMatrixDrawSetCellClipping(ih, x1 + empty1, x2, y1, y2);
iupMATRIX_TEXT(ih, (x1 + x2) / 2, y, text);
iMatrixDrawResetCellClipping(ih);
iMatrixDrawSetBgColor(ih, lin, col, marked, active);
iMatrixDrawSetCellClipping(ih, x1, x2 - empty, y1, y2);
iupMATRIX_TEXT(ih, (x1 + x2) / 2, y, text);
iMatrixDrawResetCellClipping(ih);
}
/* Draw the frame */
cdCanvasForeground(ih->data->cd_canvas, framecolor);
iupMATRIX_RECT(ih, x1, x2, y1, y2);
}
static void iMatrixDrawImage(Ihandle* ih, int x1, int x2, int y1, int y2, int col_alignment, int lin_alignment, int marked, int active, int lin, int col, const char* name)
{
Ihandle* image;
iMatrixDrawSetCellClipping(ih, x1, x2, y1, y2);
/* Create an space between image and cell frame */
x1 += IMAT_PADDING_W / 2; x2 -= IMAT_PADDING_W / 2;
y1 += IMAT_PADDING_H / 2; y2 -= IMAT_PADDING_H / 2;
image = IupImageGetHandle(name);
if (image)
{
long bgcolor;
int x, y;
int image_width = IupGetInt(image, "WIDTH");
int image_height = IupGetInt(image, "HEIGHT");
unsigned char r = 255, g = 255, b = 255;
iupMatrixGetBgRGB(ih, lin, col, &r, &g, &b, marked, active);
bgcolor = cdEncodeColor(r, g, b);
if (lin_alignment == IMAT_ALIGN_CENTER)
y = (y2 + y1 + image_height) / 2;
else if (lin_alignment == IMAT_ALIGN_START)
y = y1;
else /* BOTTOM */
y = y2 + image_height;
if (col_alignment == IMAT_ALIGN_CENTER)
x = (x2 + x1 - image_width) / 2;
else if (col_alignment == IMAT_ALIGN_START)
x = x1;
else /* RIGHT */
x = x2 - image_width;
cdIupDrawImage(ih->data->cd_canvas, image, x, iupMATRIX_INVERTYAXIS(ih, y), 0, 0, !active, bgcolor);
}
iMatrixDrawResetCellClipping(ih);
}
/* Put the cell contents in the screen, using the specified color and Alignment.
-> y1, y2 : vertical limits of the cell
-> x1, x2 : horizontal limits of the complete cell
-> col_alignment : Alignment type (horizontal) assigned to the text. The options are:
[IMAT_ALIGN_CENTER,IMAT_ALIGN_START,IMAT_ALIGN_END]
-> marked : mark state
-> lin, col - cell coordinates */
static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, int col_alignment, int lin_alignment, int marked, int active, int lin, int col, IFniiiiiiC draw_cb, long framecolor)
{
char *value;
/* avoid drawing over the frame of the next cell */
x2 -= IMAT_FRAME_W / 2;
y2 -= IMAT_FRAME_H / 2;
/* avoid drawing over the frame of the cell */
x2 -= IMAT_FRAME_W / 2;
y2 -= IMAT_FRAME_H / 2;
if (lin == 0 || col == 0)
{
/* avoid drawing over the frame of the cell */
x1 += IMAT_FRAME_W / 2;
y1 += IMAT_FRAME_H / 2;
if (col == 0) x1 += IMAT_FRAME_W / 2;
if (lin == 0) y1 += IMAT_FRAME_H / 2;
}
else if ((col == 1 && ih->data->columns.dt[0].size == 0) || (lin == 1 && ih->data->lines.dt[0].size == 0))
{
/* avoid drawing over the frame of the cell */
x1 += IMAT_FRAME_W / 2;
y1 += IMAT_FRAME_H / 2;
}
if (draw_cb && !iMatrixDrawCallDrawCB(ih, lin, col, x1, x2, y1, y2, draw_cb))
return;
value = iupMatrixGetValueDisplay(ih, lin, col);
/* Put the text */
if (value && *value)
{
int type = iupMatrixGetType(ih, lin, col);
if (type == IMAT_TYPE_TEXT)
iMatrixDrawText(ih, x1, x2, y1, y2, col_alignment, lin_alignment, marked, active, lin, col, value);
else if (type == IMAT_TYPE_COLOR)
iMatrixDrawColor(ih, x1, x2, y1, y2, marked, active, value, framecolor);
else if (type == IMAT_TYPE_FILL)
iMatrixDrawFill(ih, x1, x2, y1, y2, marked, active, lin, col, value, framecolor);
else if (type == IMAT_TYPE_IMAGE)
iMatrixDrawImage(ih, x1, x2, y1, y2, col_alignment, lin_alignment, marked, active, lin, col, value);
}
}
static void iMatrixDrawTitleCorner(Ihandle* ih)
{
if (ih->data->lines.dt[0].size && ih->data->columns.dt[0].size)
{
long framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
int active = iupdrvIsActive(ih);
IFniiiiiiC draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
int col_alignment = iupMatrixGetColAlignmentLin0(ih);
int lin_alignment = iupMatrixGetLinAlignment(ih, 0);
int framehighlight = iupAttribGetInt(ih, "FRAMETITLEHIGHLIGHT");
iMatrixDrawBackground(ih, 0, ih->data->columns.dt[0].size, 0, ih->data->lines.dt[0].size, 0, active, 0, 0);
iMatrixDrawFrameRectTitle(ih, 0, 0, 0, ih->data->columns.dt[0].size, 0, ih->data->lines.dt[0].size, framecolor, framehighlight);
iMatrixDrawCellValue(ih, 0, ih->data->columns.dt[0].size, 0, ih->data->lines.dt[0].size, col_alignment, lin_alignment, 0, active, 0, 0, draw_cb, framecolor);
}
}
static void iMatrixDrawFocus(Ihandle* ih)
{
int x1, y1, x2, y2, dx, dy;
if (iupAttribGetBoolean(ih, "HIDEFOCUS"))
return;
/* there are no cells that can get the focus */
if (ih->data->columns.num <= 1 || ih->data->lines.num <= 1)
return;
if (!iupMatrixAuxIsCellVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
return;
iupMatrixGetVisibleCellDim(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, &x1, &y1, &dx, &dy);
x2 = x1 + dx - 1;
y2 = y1 + dy - 1;
if (ih->data->noscroll_as_title && (ih->data->columns.focus_cell < ih->data->columns.num_noscroll || ih->data->lines.focus_cell < ih->data->lines.num_noscroll))
{
x1++;
y1++;
}
else
{
if (ih->data->columns.focus_cell == 1 && ih->data->columns.dt[0].size == 0)
x1++;
if (ih->data->lines.focus_cell == 1 && ih->data->lines.dt[0].size == 0)
y1++;
}
cdIupDrawFocusRect(ih->data->cd_canvas, x1, iupMATRIX_INVERTYAXIS(ih, y1), x2, iupMATRIX_INVERTYAXIS(ih, y2));
}
static void iMatrixDrawColRes(Ihandle* ih)
{
cdCanvasForeground(ih->data->cd_canvas, ih->data->colres_color);
cdCanvasLine(ih->data->cd_canvas, ih->data->colres_x, ih->data->colres_y1,
ih->data->colres_x, ih->data->colres_y2);
}
/**************************************************************************/
/* Exported functions */
/**************************************************************************/
void iupMatrixDrawSetDropFeedbackArea(int *x1, int *y1, int *x2, int *y2)
{
*x2 -= IMAT_PADDING_W / 2 + IMAT_FRAME_W / 2;
*x1 = *x2 - IMAT_FEEDBACK_SIZE - IMAT_PADDING_W / 2;
*y1 += IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
*y2 -= IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
}
void iupMatrixDrawSetToggleFeedbackArea(int toggle_centered, int *x1, int *y1, int *x2, int *y2)
{
if (toggle_centered)
{
*x1 = (*x2 + *x1) / 2 - IMAT_FEEDBACK_SIZE / 2;
*x2 = *x1 + IMAT_FEEDBACK_SIZE;
}
else
{
*x2 -= IMAT_PADDING_W / 2 + IMAT_FRAME_W / 2;
*x1 = *x2 - IMAT_FEEDBACK_SIZE - IMAT_PADDING_W / 2;
}
*y1 += IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
*y2 -= IMAT_PADDING_H / 2 + IMAT_FRAME_H / 2;
}
static int iMatrixAdjustVisibleColToMergedCells(Ihandle *ih, int *col1, int lin1, int lin2)
{
int lin, adjusted = 0, merged;
int startCol;
int new_col1 = *col1;
/* check merged cells at col1 */
for (lin = lin1; lin <= lin2; lin++)
{
merged = iupMatrixGetMerged(ih, lin, *col1);
if (merged)
{
iupMatrixGetMergedRect(ih, merged, NULL, NULL, &startCol, NULL);
if (startCol < new_col1)
{
new_col1 = startCol;
adjusted = 1;
}
}
}
if (adjusted)
*col1 = new_col1;
return adjusted;
}
static int iMatrixAdjustVisibleLinToMergedCells(Ihandle *ih, int *lin1, int col1, int col2)
{
int col, adjusted = 0, merged;
int startLin;
int new_lin1 = *lin1;
/* check merged cells at lin1 */
for (col = col1; col <= col2; col++)
{
merged = iupMatrixGetMerged(ih, *lin1, col);
if (merged)
{
iupMatrixGetMergedRect(ih, merged, &startLin, NULL, NULL, NULL);
if (startLin < new_lin1)
{
new_lin1 = startLin;
adjusted = 1;
}
}
}
if (adjusted)
*lin1 = new_lin1;
return adjusted;
}
/* Draw the line titles, visible, between lin and lastlin, include it.
Line titles marked will be draw with the appropriate feedback.
-> lin1 - First line to have its title drawn
-> lin2 - Last line to have its title drawn */
static void iMatrixDrawTitleLines(Ihandle* ih, int lin1, int lin2)
{
int x1, y1, x2, y2, first_lin, adjust_merged_lin = 0;
int lin, col_alignment, active, framehighlight;
long framecolor;
IFniiiiiiC draw_cb;
/* here col==0 always */
if (!ih->data->columns.dt[0].size)
return;
if (ih->data->merge_info_count)
adjust_merged_lin = iMatrixAdjustVisibleLinToMergedCells(ih, &lin1, 0, 0);
if (ih->data->lines.num_noscroll > 1 && lin1 == 1 && lin2 == ih->data->lines.num_noscroll - 1)
{
first_lin = 0;
y1 = 0;
}
else
{
if (lin1 > ih->data->lines.last ||
lin2 < ih->data->lines.first)
return;
if (!adjust_merged_lin && lin1 < ih->data->lines.first)
lin1 = ih->data->lines.first;
if (lin2 > ih->data->lines.last)
lin2 = ih->data->lines.last;
first_lin = ih->data->lines.first;
y1 = 0;
for (lin = 0; lin < ih->data->lines.num_noscroll; lin++)
y1 += ih->data->lines.dt[lin].size;
}
/* Start the position of the line title */
x1 = 0;
x2 = ih->data->columns.dt[0].size;
iupMATRIX_CLIPAREA(ih, x1, x2, y1, iupMatrixGetHeight(ih) - 1);
cdCanvasClip(ih->data->cd_canvas, CD_CLIPAREA);
/* Find the initial position of the first line */
if (first_lin == ih->data->lines.first)
y1 -= ih->data->lines.first_offset;
for (lin = first_lin; lin < lin1; lin++)
y1 += ih->data->lines.dt[lin].size;
if (adjust_merged_lin)
{
for (lin = first_lin; lin > lin1; lin--)
y1 -= ih->data->lines.dt[lin].size;
}
framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
framehighlight = iupAttribGetInt(ih, "FRAMETITLEHIGHLIGHT");
active = iupdrvIsActive(ih);
draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
col_alignment = iupMatrixGetColAlignment(ih, 0);
/* Draw the titles */
for (lin = lin1; lin <= lin2; lin++)
{
int merged;
/* If it is a hidden line (size = 0), don't draw the title */
if (ih->data->lines.dt[lin].size == 0)
continue;
merged = 0;
if (ih->data->merge_info_count)
merged = iupMatrixGetMerged(ih, lin, 0);
y2 = y1 + ih->data->lines.dt[lin].size;
if (merged)
{
int startLin, endLin, startCol, endCol;
iupMatrixGetMergedRect(ih, merged, &startLin, &endLin, &startCol, &endCol);
if (lin == startLin && 0 == startCol) /* merged start */
{
int i;
for (i = startLin + 1; i <= endLin; i++)
y2 += ih->data->lines.dt[i].size;
}
else
continue; /* ignore internal merged */
}
/* If it doesn't have title, the loop just calculate the final position */
if (ih->data->columns.dt[0].size)
{
int marked = iupMatrixLineIsMarked(ih, lin);
int lin_alignment = iupMatrixGetLinAlignment(ih, lin);
iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, 0);
iMatrixDrawFrameRectTitle(ih, lin, 0, x1, x2, y1, y2, framecolor, framehighlight);
iMatrixDrawCellValue(ih, x1, x2, y1, y2, col_alignment, lin_alignment, marked, active, lin, 0, draw_cb, framecolor);
}
y1 = y2;
}
cdCanvasClip(ih->data->cd_canvas, CD_CLIPOFF);
}
/* Draw the column titles, visible, between col and lastcol, include it.
Column titles marked will be draw with the appropriate feedback.
-> col1 - First column to have its title drawn
-> col2 - Last column to have its title drawn */
static void iMatrixDrawTitleColumns(Ihandle* ih, int col1, int col2)
{
int x1, y1, x2, y2, first_col, adjust_merged_col = 0;
int col, active, col_alignment, lin_alignment, framehighlight;
long framecolor;
IFniiiiiiC draw_cb;
/* here lin==0 always */
if (!ih->data->lines.dt[0].size)
return;
if (ih->data->merge_info_count)
adjust_merged_col = iMatrixAdjustVisibleColToMergedCells(ih, &col1, 0, 0);
if (ih->data->columns.num_noscroll > 1 && col1 == 1 && col2 == ih->data->columns.num_noscroll - 1)
{
first_col = 0;
x1 = 0;
}
else
{
if (col1 > ih->data->columns.last ||
col2 < ih->data->columns.first)
return;
if (!adjust_merged_col && col1 < ih->data->columns.first)
col1 = ih->data->columns.first;
if (col2 > ih->data->columns.last)
col2 = ih->data->columns.last;
first_col = ih->data->columns.first;
x1 = 0;
for (col = 0; col < ih->data->columns.num_noscroll; col++)
x1 += ih->data->columns.dt[col].size;
}
/* Start the position of the first column title */
y1 = 0;
y2 = ih->data->lines.dt[0].size;
iupMATRIX_CLIPAREA(ih, x1, iupMatrixGetWidth(ih) - 1, y1, y2);
cdCanvasClip(ih->data->cd_canvas, CD_CLIPAREA);
/* Find the initial position of the first column */
if (first_col == ih->data->columns.first)
x1 -= ih->data->columns.first_offset;
for (col = first_col; col < col1; col++)
x1 += ih->data->columns.dt[col].size;
if (adjust_merged_col)
{
for (col = first_col; col > col1; col--)
x1 -= ih->data->columns.dt[col].size;
}
framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
framehighlight = iupAttribGetInt(ih, "FRAMETITLEHIGHLIGHT");
active = iupdrvIsActive(ih);
draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
col_alignment = iupMatrixGetColAlignmentLin0(ih);
lin_alignment = iupMatrixGetLinAlignment(ih, 0);
/* Draw the titles */
for (col = col1; col <= col2; col++)
{
int merged;
/* If it is hidden column (size = 0), do not draw the title */
if (ih->data->columns.dt[col].size == 0)
continue;
merged = 0;
if (ih->data->merge_info_count)
merged = iupMatrixGetMerged(ih, 0, col);
x2 = x1 + ih->data->columns.dt[col].size;
if (merged)
{
int startLin, endLin, startCol, endCol;
iupMatrixGetMergedRect(ih, merged, &startLin, &endLin, &startCol, &endCol);
if (0 == startLin && col == startCol) /* merged start */
{
int i;
for (i = startCol + 1; i <= endCol; i++)
x2 += ih->data->columns.dt[i].size;
}
else
continue; /* ignore internal merged */
}
/* If it doesn't have title, the loop just calculate the final position */
if (ih->data->lines.dt[0].size)
{
int sort = 0;
int marked = iupMatrixColumnIsMarked(ih, col);
iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, 0, col);
iMatrixDrawFrameRectTitle(ih, 0, col, x1, x2, y1, y2, framecolor, framehighlight);
if (iMatrixDrawSortSign(ih, x2, y1, y2, col, active))
sort = IMAT_PADDING_W / 2 + IMAT_FEEDBACK_SIZE + IMAT_PADDING_W / 2; /* same space is used by the sort sign */
iMatrixDrawCellValue(ih, x1, x2 - sort, y1, y2, col_alignment, lin_alignment, marked, active, 0, col, draw_cb, framecolor);
}
x1 = x2;
}
cdCanvasClip(ih->data->cd_canvas, CD_CLIPOFF);
}
/* Redraw a block of cells of the matrix. Handle marked cells, change
automatically the background color of them.
- lin1, col1 : cell coordinates that mark the left top corner of the area to be redrawn
- lin2, col2 : cell coordinates that mark the right bottom corner of the area to be redrawn */
static void iMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
{
int x1, y1, x2, y2, old_x2, old_y1, old_y2, toggle_centered;
int col_alignment, lin, col, active, first_col, first_lin;
int i, adjust_merged_col = 0, adjust_merged_lin = 0;
long framecolor, framehighlight;
IFnii mark_cb;
IFnii dropcheck_cb;
IFniiiiiiC draw_cb;
if (ih->data->merge_info_count)
{
adjust_merged_lin = iMatrixAdjustVisibleLinToMergedCells(ih, &lin1, col1, col2);
adjust_merged_col = iMatrixAdjustVisibleColToMergedCells(ih, &col1, lin1, lin2);
}
x2 = iupMatrixGetWidth(ih) - 1;
y2 = iupMatrixGetHeight(ih) - 1;
old_x2 = x2;
old_y1 = 0;
old_y2 = y2;
if (ih->data->lines.num <= 1 ||
ih->data->columns.num <= 1)
return;
if (ih->data->columns.num_noscroll > 1 && col1 == 1 && col2 == ih->data->columns.num_noscroll - 1)
{
first_col = 0;
x1 = 0;
}
else
{
if (col1 > ih->data->columns.last ||
col2 < ih->data->columns.first)
return;
if (!adjust_merged_col && col1 < ih->data->columns.first)
col1 = ih->data->columns.first;
if (col2 > ih->data->columns.last)
col2 = ih->data->columns.last;
first_col = ih->data->columns.first;
x1 = 0;
for (col = 0; col< ih->data->columns.num_noscroll; col++)
x1 += ih->data->columns.dt[col].size;
}
if (ih->data->lines.num_noscroll>1 && lin1 == 1 && lin2 == ih->data->lines.num_noscroll - 1)
{
first_lin = 0;
y1 = 0;
}
else
{
if (lin1 > ih->data->lines.last ||
lin2 < ih->data->lines.first)
return;
if (!adjust_merged_lin && lin1 < ih->data->lines.first)
lin1 = ih->data->lines.first;
if (lin2 > ih->data->lines.last)
lin2 = ih->data->lines.last;
first_lin = ih->data->lines.first;
y1 = 0;
for (lin = 0; lin < ih->data->lines.num_noscroll; lin++)
y1 += ih->data->lines.dt[lin].size;
}
iupMATRIX_CLIPAREA(ih, x1, x2, y1, y2);
cdCanvasClip(ih->data->cd_canvas, CD_CLIPOFF); /* wait for background */
/* Find the initial position of the first column */
if (first_col == ih->data->columns.first)
x1 -= ih->data->columns.first_offset;
for (col = first_col; col < col1; col++)
x1 += ih->data->columns.dt[col].size;
if (adjust_merged_col)
{
for (col = first_col-1; col >= col1; col--)
x1 -= ih->data->columns.dt[col].size;
}
/* Find the initial position of the first line */
if (first_lin == ih->data->lines.first)
y1 -= ih->data->lines.first_offset;
for (lin = first_lin; lin < lin1; lin++)
y1 += ih->data->lines.dt[lin].size;
if (adjust_merged_lin)
{
for (lin = first_lin-1; lin >= lin1; lin--)
y1 -= ih->data->lines.dt[lin].size;
}
/* Find the final position of the last column */
x2 = x1;
for (; col <= col2; col++)
x2 += ih->data->columns.dt[col].size;
/* Find the final position of the last line */
y2 = y1;
for (; lin <= lin2; lin++)
y2 += ih->data->lines.dt[lin].size;
if ((col2 == ih->data->columns.num - 1) && (old_x2 > x2))
{
long emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
cdCanvasForeground(ih->data->cd_canvas, emptyarea_color);
/* If it was drawn until the last column and remains space in the right of it,
then delete this area with the the background color. */
iupMATRIX_BOX(ih, x2, old_x2, old_y1, old_y2);
}
if ((lin2 == ih->data->lines.num - 1) && (old_y2 > y2))
{
long emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
cdCanvasForeground(ih->data->cd_canvas, emptyarea_color);
/* If it was drawn until the last line visible and remains space below it,
then delete this area with the the background color. */
iupMATRIX_BOX(ih, 0, old_x2, y2, old_y2);
}
/* after the background */
cdCanvasClip(ih->data->cd_canvas, CD_CLIPAREA);
/***** Draw the cell values and frame */
old_y1 = y1;
framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
framehighlight = iupAttribGetInt(ih, "FRAMETITLEHIGHLIGHT");
active = iupdrvIsActive(ih);
mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
dropcheck_cb = (IFnii)IupGetCallback(ih, "DROPCHECK_CB");
draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
toggle_centered = iupAttribGetBoolean(ih, "TOGGLECENTERED");
for (col = col1; col <= col2; col++) /* For all the columns in the region */
{
int last_x2, last_y2;
if (ih->data->columns.dt[col].size == 0)
continue;
col_alignment = iupMatrixGetColAlignment(ih, col);
x2 = x1 + ih->data->columns.dt[col].size;
last_x2 = x2;
for (lin = lin1; lin <= lin2; lin++) /* For all lines in the region */
{
int drop = 0;
int marked = 0;
int lin_alignment;
int merged;
if (ih->data->lines.dt[lin].size == 0)
continue;
merged = 0;
if (ih->data->merge_info_count)
merged = iupMatrixGetMerged(ih, lin, col);
y2 = y1 + ih->data->lines.dt[lin].size;
last_y2 = y2;
if (merged)
{
int startLin, endLin, startCol, endCol;
iupMatrixGetMergedRect(ih, merged, &startLin, &endLin, &startCol, &endCol);
if (lin == startLin && col == startCol) /* merged start */
{
for (i = startLin + 1; i <= endLin; i++)
y2 += ih->data->lines.dt[i].size;
for (i = startCol + 1; i <= endCol; i++)
x2 += ih->data->columns.dt[i].size;
}
else
{
x2 = last_x2;
y1 = last_y2;
continue; /* ignore internal merged */
}
}
lin_alignment = iupMatrixGetLinAlignment(ih, lin);
/* If the cell is marked, then draw it with attenuation color */
marked = iupMatrixGetMark(ih, lin, col, mark_cb);
if (ih->data->noscroll_as_title && (lin < ih->data->lines.num_noscroll || col < ih->data->columns.num_noscroll))
{
iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, 0);
iMatrixDrawFrameRectTitle(ih, lin, col, x1, x2, y1, y2, framecolor, framehighlight);
}
else
{
iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, col);
iMatrixDrawFrameRectCell(ih, lin, col, x1, x2, y1, y2, framecolor);
if (dropcheck_cb)
{
int ret = dropcheck_cb(ih, lin, col);
if (ret == IUP_DEFAULT)
{
iMatrixDrawDropdownButton(ih, x2, y1, y2, lin, col, marked, active);
drop = IMAT_PADDING_W / 2 + IMAT_FEEDBACK_SIZE + IMAT_PADDING_W / 2;
}
else if (ret == IUP_CONTINUE)
{
iMatrixDrawToggle(ih, x1, x2, y1, y2, lin, col, marked, active, toggle_centered);
if (toggle_centered)
{
y1 = last_y2;
continue; /* do not draw the cell contents */
}
drop = IMAT_PADDING_W / 2 + IMAT_FEEDBACK_SIZE + IMAT_PADDING_W / 2;
}
}
}
/* draw the cell contents */
iMatrixDrawCellValue(ih, x1, x2 - drop, y1, y2, col_alignment, lin_alignment, marked, active, lin, col, draw_cb, framecolor);
x2 = last_x2;
y1 = last_y2;
}
x1 = last_x2;
y1 = old_y1; /* must reset also y */
}
cdCanvasClip(ih->data->cd_canvas, CD_CLIPOFF);
}
static void iMatrixDrawMatrix(Ihandle* ih)
{
iupMatrixPrepareDrawData(ih);
/* fill the background because there will be empty cells */
if ((ih->data->lines.num == 1) || (ih->data->columns.num == 1))
{
cdCanvasBackground(ih->data->cd_canvas, cdIupConvertColor(ih->data->bgcolor_parent));
cdCanvasClear(ih->data->cd_canvas);
}
/* Draw the corner between line and column titles, if necessary */
iMatrixDrawTitleCorner(ih);
/* If there are columns, then draw their titles */
if (ih->data->columns.num_noscroll > 1)
iMatrixDrawTitleColumns(ih, 1, ih->data->columns.num_noscroll - 1);
iMatrixDrawTitleColumns(ih, ih->data->columns.first, ih->data->columns.last);
/* If there are lines, then draw their titles */
if (ih->data->lines.num_noscroll > 1)
iMatrixDrawTitleLines(ih, 1, ih->data->lines.num_noscroll - 1);
iMatrixDrawTitleLines(ih, ih->data->lines.first, ih->data->lines.last);
/* If there are ordinary cells, then draw them */
if (ih->data->columns.num_noscroll > 1 && ih->data->lines.num_noscroll > 1)
iMatrixDrawCells(ih, 1, 1, ih->data->lines.num_noscroll - 1, ih->data->columns.num_noscroll - 1);
if (ih->data->columns.num_noscroll > 1)
iMatrixDrawCells(ih, ih->data->lines.first, 1, ih->data->lines.last, ih->data->columns.num_noscroll - 1);
if (ih->data->lines.num_noscroll > 1)
iMatrixDrawCells(ih, 1, ih->data->columns.first, ih->data->lines.num_noscroll - 1, ih->data->columns.last);
iMatrixDrawCells(ih, ih->data->lines.first, ih->data->columns.first, ih->data->lines.last, ih->data->columns.last);
if (iupAttribGetBoolean(ih, "FRAMEBORDER"))
{
long framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
cdCanvasForeground(ih->data->cd_canvas, framecolor);
/* if vertical scrollbar is visible */
if (!iupAttribGetBoolean(ih, "YHIDDEN"))
{
int posy = IupGetInt(ih, "POSY");
int dy = IupGetInt(ih, "DY");
int ymax = IupGetInt(ih, "YMAX");
int height = iupMatrixGetHeight(ih);
int width = iupMatrixGetWidth(ih);
if (width > ih->data->columns.total_size)
width = ih->data->columns.total_size;
/* if scrollbar at top, top line is not necessary */
if (posy > 0)
iupMATRIX_LINE(ih, 0, 0, width - 1, 0); /* top horizontal line */
/* if scrollbar at bottom, bottom line is not necessary */
if (posy < ymax - dy)
iupMATRIX_LINE(ih, 0, height - 1, width - 1, height - 1); /* bottom horizontal line */
}
/* if horizontal scrollbar is visible */
if (!iupAttribGetBoolean(ih, "XHIDDEN"))
{
int posx = IupGetInt(ih, "POSX");
int dx = IupGetInt(ih, "DX");
int xmax = IupGetInt(ih, "XMAX");
int width = iupMatrixGetWidth(ih);
int height = iupMatrixGetHeight(ih);
if (height > ih->data->lines.total_size)
height = ih->data->lines.total_size;
/* if scrollbar at left, left line is not necessary */
if (posx > 0)
iupMATRIX_LINE(ih, 0, 0, 0, height - 1); /* left vertical line */
/* if scrollbar at right, right line is not necessary */
if (posx < xmax - dx)
iupMATRIX_LINE(ih, width - 1, 0, width - 1, height - 1); /* right vertical line */
}
}
}
void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
{
#ifdef USE_OLD_DRAW
iMatrixDrawCells(ih, lin1, col1, lin2, col2);
#else
(void)ih;
(void)lin1;
(void)col1;
(void)lin2;
(void)col2;
#endif
}
void iupMatrixDrawTitleColumns(Ihandle* ih, int col1, int col2)
{
#ifdef USE_OLD_DRAW
iMatrixDrawTitleColumns(ih, col1, col2);
#else
(void)ih;
(void)col1;
(void)col2;
#endif
}
void iupMatrixDrawTitleLines(Ihandle* ih, int lin1, int lin2)
{
#ifdef USE_OLD_DRAW
iMatrixDrawTitleLines(ih, lin1, lin2);
#else
(void)ih;
(void)lin1;
(void)lin2;
#endif
}
void iupMatrixDraw(Ihandle* ih, int update)
{
#ifdef USE_OLD_DRAW
cdCanvasActivate(ih->data->cd_canvas);
if (ih->data->need_calcsize)
iupMatrixAuxCalcSizes(ih);
iMatrixDrawMatrix(ih);
ih->data->need_redraw = 0;
#endif
if (update)
iupMatrixDrawUpdate(ih);
}
void iupMatrixDrawUpdate(Ihandle* ih)
{
#ifdef USE_OLD_DRAW
cdCanvasFlush(ih->data->cd_canvas);
if (ih->data->has_focus)
iMatrixDrawFocus(ih);
if (ih->data->colres_feedback)
iMatrixDrawColRes(ih);
if (!ih->data->edit_hide_onfocus && ih->data->editing)
IupUpdate(ih->data->datah);
#else
iupdrvRedrawNow(ih);
#endif
}
/*
static int iMatrixDrawHasFlatScrollBar(Ihandle* ih)
{
char* value = iupAttribGetStr(ih, "FLATSCROLLBAR");
if (value && !iupStrEqualNoCase(value, "NO"))
return 1;
else
return 0;
}
*/
#ifndef USE_OLD_DRAW
void iupMatrixDrawCB(Ihandle* ih)
{
/* called only from the ACTION callback */
if (ih->data->need_calcsize)
{
int sb_resize = iupMatrixAuxCalcSizes(ih); /* does not use cd_canvas, can be done before Activate, */
if (sb_resize) /* but it can trigger a resize+redraw event */
{
/* if (!iMatrixDrawHasFlatScrollBar(ih)) */
{
/* TODO: this is not working in all situations, so it is disabled. */
/* return; */
}
}
}
cdCanvasActivate(ih->data->cd_canvas);
iMatrixDrawMatrix(ih);
ih->data->need_redraw = 0;
if (ih->data->has_focus)
iMatrixDrawFocus(ih);
if (ih->data->colres_feedback)
iMatrixDrawColRes(ih);
cdCanvasFlush(ih->data->cd_canvas);
cdCanvasDeactivate(ih->data->cd_canvas);
if (!ih->data->edit_hide_onfocus && ih->data->editing)
IupUpdate(ih->data->datah);
}
#endif
int iupMatrixDrawSetRedrawAttrib(Ihandle* ih, const char* value)
{
#ifdef USE_OLD_DRAW
int type;
if (value == NULL)
type = 0;
else if (value[0] == 'L' || value[0] == 'l')
type = IMAT_PROCESS_LIN;
else if (value[0] == 'C' || value[0] == 'c')
type = IMAT_PROCESS_COL;
else
type = 0;
if (type) /* lines or columns, including their titles */
{
int min = 0, max = 0;
value++;
/* compatibility code */
if (strchr(value, ':') != NULL)
{
if (iupStrToIntInt(value, &min, &max, ':') != 2)
max = min;
}
else
{
if (iupStrToIntInt(value, &min, &max, '-') != 2)
max = min;
}
if (min > max)
return 0;
cdCanvasActivate(ih->data->cd_canvas);
iupMatrixPrepareDrawData(ih);
if (ih->data->need_calcsize)
iupMatrixAuxCalcSizes(ih);
/* ignore empty area, draw only cells */
iMatrixDrawTitleCorner(ih);
if (type == IMAT_PROCESS_LIN)
{
if (min == 0)
{
if (ih->data->columns.num_noscroll > 1)
iMatrixDrawTitleColumns(ih, 1, ih->data->columns.num_noscroll - 1);
iMatrixDrawTitleColumns(ih, ih->data->columns.first, ih->data->columns.last);
}
iMatrixDrawTitleLines(ih, min, max);
if (ih->data->columns.num_noscroll > 1)
iMatrixDrawCells(ih, min, 1, max, ih->data->columns.num_noscroll - 1);
iMatrixDrawCells(ih, min, ih->data->columns.first, max, ih->data->columns.last);
}
else
{
if (min == 0)
{
if (ih->data->lines.num_noscroll > 1)
iMatrixDrawTitleLines(ih, 1, ih->data->lines.num_noscroll - 1);
iMatrixDrawTitleLines(ih, ih->data->lines.first, ih->data->lines.last);
}
iMatrixDrawTitleColumns(ih, min, max);
if (ih->data->lines.num_noscroll > 1)
iMatrixDrawCells(ih, 1, min, ih->data->lines.num_noscroll - 1, max);
iMatrixDrawCells(ih, ih->data->lines.first, min, ih->data->lines.last, max);
}
}
else
{
cdCanvasActivate(ih->data->cd_canvas);
/* Force CalcSize */
iupMatrixAuxCalcSizes(ih);
iMatrixDrawMatrix(ih);
}
ih->data->need_redraw = 0;
iupMatrixDrawUpdate(ih);
#else
IupRedraw(ih, 0); /* redraw now */
(void)value;
#endif
return 0;
}