iup-stack/iup/srcplot/iup_plot_ctrl.cpp

3131 lines
94 KiB
C++
Raw Normal View History

2023-02-20 16:44:45 +00:00
/*
* IupPlot element
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "iupPlot.h"
#include "iup_plot.h"
#include "iupkey.h"
#include "iupgl.h"
#include <cdgl.h>
#include <cdiup.h>
#include <cdprint.h>
#include <cdsvg.h>
#include <cdirgb.h>
#include <cdemf.h>
#include <cdwmf.h>
#include <cdcgm.h>
#include <cdclipbd.h>
#include <cdps.h>
#include "iup_class.h"
#include "iup_register.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_assert.h"
#include "iup_predialogs.h"
#include "iup_linefile.h"
#include "iup_image.h"
#include "iup_plot_ctrl.h"
static int iPlotSelectFile(Ihandle* parent, char* filename, const char* title, const char* extfilter)
{
Ihandle* filedlg = IupFileDlg();
IupSetStrAttribute(filedlg, "DIALOGTYPE", "SAVE");
IupSetStrAttribute(filedlg, "EXTFILTER", extfilter);
IupSetStrAttribute(filedlg, "TITLE", title);
IupSetStrAttribute(filedlg, "FILE", filename);
IupSetAttributeHandle(filedlg, "PARENTDIALOG", parent);
IupPopup(filedlg, IUP_CENTERPARENT, IUP_CENTERPARENT);
if (IupGetInt(filedlg, "STATUS") != -1)
{
char* value = IupGetAttribute(filedlg, "VALUE");
strcpy(filename, value);
IupDestroy(filedlg);
return 1;
}
IupDestroy(filedlg);
return 0;
}
static int iPlotCopyAsMetafile_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char StrData[100];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
sprintf(StrData, "%dx%d", w, h);
cdCanvas* cd_canvas;
if (ih->data->graphics_mode == IUP_PLOT_NATIVEPLUS)
{
int old_plus = cdUseContextPlus(1);
cd_canvas = cdCreateCanvas(CD_CLIPBOARD, StrData);
cdUseContextPlus(old_plus);
}
else
cd_canvas = cdCreateCanvas(CD_CLIPBOARD, StrData);
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
return IUP_DEFAULT;
}
static int iPlotCopyAsImage_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char StrData[100];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
double res = IupGetDouble(NULL, "SCREENDPI") / 25.4;
int plane_size = w*h;
unsigned char* data = (unsigned char*)malloc(plane_size * 4);
if (!data)
return IUP_DEFAULT;
sprintf(StrData, "%dx%d %p %p %p %p -r%g -a", w, h, data, data + plane_size, data + 2 * plane_size, data + 3 * plane_size, res);
cdCanvas* cd_canvas = cdCreateCanvas(CD_IMAGERGB, StrData);
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
Ihandle *clipboard = IupClipboard();
IupSetAttribute(clipboard, "IMAGE", NULL);
IupSetAttribute(clipboard, "NATIVEIMAGE", (char*)iupdrvImageCreateImageRaw(w, h, 32, NULL, 0, data));
IupDestroy(clipboard);
free(data);
return IUP_DEFAULT;
}
static int iPlotExportEPS_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char filename[10240] = "*.eps";
if (iPlotSelectFile(IupGetDialog(ih), filename, "_@IUP_EXPORT", "Encapsulated Postscript (EPS)|*.eps|All Files|*.*|"))
{
char StrData[10240];
int dpi = IupGetInt(NULL, "SCREENDPI");
sprintf(StrData, "%s -e -s%d", filename, dpi);
cdCanvas* cd_canvas = cdCreateCanvas(CD_PS, StrData);
if (cd_canvas)
{
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
}
else
IupMessageError(IupGetDialog(ih), "IUP_ERRORFILESAVE");
}
return IUP_DEFAULT;
}
static int iPlotExportSVG_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char filename[10240] = "*.svg";
if (iPlotSelectFile(IupGetDialog(ih), filename, "_@IUP_EXPORT", "Scalable Vector Graphics (SVG)|*.svg|All Files|*.*|"))
{
char StrData[10240];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
double res = (double)IupGetInt(NULL, "SCREENDPI") / 25.4;
double w_mm = ((double)w) / res;
double h_mm = ((double)h) / res;
sprintf(StrData, "%s %gx%g %g", filename, w_mm, h_mm, res);
cdCanvas* cd_canvas = cdCreateCanvas(CD_SVG, StrData);
if (cd_canvas)
{
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
}
else
IupMessageError(IupGetDialog(ih), "IUP_ERRORFILESAVE");
}
return IUP_DEFAULT;
}
static int iPlotExportCGM_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char filename[10240] = "*.cgm";
if (iPlotSelectFile(IupGetDialog(ih), filename, "_@IUP_EXPORT", "Computer Graphics Metafile (CGM)|*.cgm|All Files|*.*|"))
{
char StrData[10240];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
double res = (double)IupGetInt(NULL, "SCREENDPI") / 25.4;
double w_mm = ((double)w) / res;
double h_mm = ((double)h) / res;
sprintf(StrData, "%s %gx%g %g", filename, w_mm, h_mm, res);
cdCanvas* cd_canvas = cdCreateCanvas(CD_CGM, StrData);
if (cd_canvas)
{
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
}
else
IupMessageError(IupGetDialog(ih), "IUP_ERRORFILESAVE");
}
return IUP_DEFAULT;
}
#ifdef WIN32
static int iPlotExportEMF_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char filename[10240] = "*.emf";
if (iPlotSelectFile(IupGetDialog(ih), filename, "_@IUP_EXPORT", "Windows Enhanced Metafile (EMF)|*.emf|All Files|*.*|"))
{
char StrData[10240];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
sprintf(StrData, "%s %dx%d", filename, w, h);
cdCanvas* cd_canvas;
if (ih->data->graphics_mode == IUP_PLOT_NATIVEPLUS)
{
int old_plus = cdUseContextPlus(1);
cd_canvas = cdCreateCanvas(CD_EMF, StrData);
cdUseContextPlus(old_plus);
}
else
cd_canvas = cdCreateCanvas(CD_EMF, StrData);
if (cd_canvas)
{
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
}
else
IupMessageError(IupGetDialog(ih), "IUP_ERRORFILESAVE");
}
return IUP_DEFAULT;
}
static int iPlotExportWMF_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
char filename[10240] = "*.wmf";
if (iPlotSelectFile(IupGetDialog(ih), filename, "_@IUP_EXPORT", "Windows Metafile (WMF)|*.wmf|All Files|*.*|"))
{
char StrData[10240];
int w, h;
IupGetIntInt(ih, "DRAWSIZE", &w, &h);
sprintf(StrData, "%s %dx%d", filename, w, h);
cdCanvas* cd_canvas = cdCreateCanvas(CD_WMF, StrData);
if (cd_canvas)
{
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
}
else
IupMessageError(IupGetDialog(ih), "IUP_ERRORFILESAVE");
}
return IUP_DEFAULT;
}
#endif
static int iPlotPrint_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
cdCanvas* cd_canvas;
if (ih->data->graphics_mode == IUP_PLOT_NATIVEPLUS)
{
int old_plus = cdUseContextPlus(1);
cd_canvas = cdCreateCanvas(CD_PRINTER, (void*)"Plot -d");
cdUseContextPlus(old_plus);
}
else
cd_canvas = cdCreateCanvas(CD_PRINTER, (void*)"Plot -d");
IupPlotPaintTo(ih, cd_canvas);
cdKillCanvas(cd_canvas);
return IUP_DEFAULT;
}
static double iPlotDataSetValuesMatrixNumericGetValue_CB(Ihandle *ih_matrix, int lin, int col)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_matrix, "PLOT");
int plot_current = iupAttribGetInt(ih_matrix, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_matrix, "_IUP_DS");
// make sure we are changing the right plot
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
if (IupGetInt(ih, "DS_STRXDATA"))
{
if (col == 1)
return 0;
else
{
char* str_x;
double y;
IupPlotGetSampleStr(ih, ds, lin - 1, (const char**)&str_x, &y);
return y;
}
}
double x, y;
IupPlotGetSample(ih, ds, lin - 1, &x, &y);
if (col == 1)
return x;
else
return y;
}
static char* iPlotDataSetValuesMatrixValue_CB(Ihandle *ih_matrix, int lin, int col)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_matrix, "PLOT");
int plot_current = iupAttribGetInt(ih_matrix, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_matrix, "_IUP_DS");
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
if (lin == 0 && col == 0)
return "";
if (lin == 0)
return (col == 1) ? IupGetAttribute(ih, "AXS_XLABEL") : IupGetAttribute(ih, "AXS_YLABEL");
if (col == 1 && IupGetInt(ih, "DS_STRXDATA"))
{
char* str_x;
double y;
IupPlotGetSampleStr(ih, ds, lin - 1, (const char**)&str_x, &y);
return str_x;
}
if (col == 0)
{
static char str[30];
sprintf(str, "%d", lin - 1);
return str;
}
return NULL;
}
static int iPlotDataSetValuesMatrixNumericSetValue_CB(Ihandle* ih_matrix, int lin, int col, double new_value)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_matrix, "PLOT");
int plot_current = iupAttribGetInt(ih_matrix, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_matrix, "_IUP_DS");
int sample_index = lin - 1;
double x, y;
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
if (col == 2 && IupGetInt(ih, "DS_STRXDATA"))
{
char* str_x;
IupPlotGetSampleStr(ih, ds, sample_index, (const char**)&str_x, &y);
x = sample_index;
IupPlotSetSampleStr(ih, ds, sample_index, str_x, new_value);
}
else
{
IupPlotGetSample(ih, ds, sample_index, &x, &y);
if (col == 1)
IupPlotSetSample(ih, ds, sample_index, new_value, y);
else
IupPlotSetSample(ih, ds, sample_index, x, new_value);
}
IFniidd editsample_cb = (IFniidd)IupGetCallback(ih, "EDITSAMPLE_CB");
if (editsample_cb)
editsample_cb(ih, ds, sample_index, x, y);
return IUP_DEFAULT;
}
static int iPlotDataSetValuesMatrixValueEdit_CB(Ihandle* ih_matrix, int lin, int col, char* new_value)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_matrix, "PLOT");
int plot_current = iupAttribGetInt(ih_matrix, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_matrix, "_IUP_DS");
int sample_index = lin - 1;
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
if (col == 1 && IupGetInt(ih, "DS_STRXDATA"))
{
char* str_x;
double x, y;
IupPlotGetSampleStr(ih, ds, sample_index, (const char**)&str_x, &y);
x = sample_index;
IupPlotSetSampleStr(ih, ds, sample_index, new_value, y);
IFniidd editsample_cb = (IFniidd)IupGetCallback(ih, "EDITSAMPLE_CB");
if (editsample_cb)
editsample_cb(ih, ds, sample_index, x, y);
}
return IUP_DEFAULT;
}
static int iPlotDataSetValuesMatrixResize_CB(Ihandle *ih, int, int)
{
IupSetAttribute(ih, "RASTERWIDTH1", NULL);
IupSetAttribute(ih, "RASTERWIDTH2", NULL);
IupSetAttribute(ih, "FITTOSIZE", "COLUMNS");
return IUP_DEFAULT;
}
static int iPlotDataSetValuesButton_CB(Ihandle*)
{
return IUP_CLOSE;
}
static int iPlotDataSetValues_CB(Ihandle* ih_item)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_item, "PLOT");
Ihandle* ih_menu = IupGetParent(ih_item);
int plot_current = iupAttribGetInt(ih_menu, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_menu, "_IUP_DS");
Ihandle *matrix = IupCreate("matrixex"); /* IupControlsOpen must have been called somewhere */
if (!matrix)
return IUP_DEFAULT;
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
char* ds_name = IupGetAttribute(ih, "DS_NAME");
Ihandle* label = IupLabel(ds_name);
Ihandle *button = IupButton("Close", NULL);
Ihandle *vbox = IupVbox(label, matrix, button, NULL);
IupSetAttribute(vbox, "ALIGNMENT", "ACENTER");
IupSetAttribute(vbox, "MARGIN", "10x10");
IupSetAttribute(vbox, "GAP", "10");
Ihandle* dlg = IupDialog(vbox);
Ihandle *parent = IupGetDialog(ih);
IupSetStrAttribute(dlg, "TITLE", "_@IUP_DATASETVALUESDLG");
IupSetAttribute(dlg, "MINBOX", "NO");
IupSetAttribute(dlg, "MAXBOX", "NO");
IupSetAttribute(dlg, "SHRINK", "YES");
IupSetAttributeHandle(dlg, "DEFAULTESC", button);
IupSetAttributeHandle(dlg, "DEFAULTENTER", button);
IupSetAttributeHandle(dlg, "PARENTDIALOG", parent);
if (IupGetAttribute(parent, "ICON"))
IupSetStrAttribute(dlg, "ICON", IupGetAttribute(parent, "ICON"));
else
IupSetStrAttribute(dlg, "ICON", IupGetGlobal("ICON"));
IupSetStrAttribute(button, "PADDING", IupGetGlobal("DEFAULTBUTTONPADDING"));
IupSetAttribute(matrix, "USETITLESIZE", "YES");
IupSetAttribute(matrix, "MARKMODE", "CELL");
IupSetAttribute(matrix, "MARKMULTIPLE", "Yes");
IupSetAttribute(matrix, "SCROLLBAR", "VERTICAL");
int count = IupGetInt(ih, "DS_COUNT");
IupSetAttribute(matrix, "NUMCOL", "2");
IupSetInt(matrix, "NUMLIN", count);
IupSetAttribute(matrix, "NUMCOL_VISIBLE", "2");
if (count > 10)
IupSetAttribute(matrix, "NUMLIN_VISIBLE", "10");
else
IupSetInt(matrix, "NUMLIN_VISIBLE", count);
if (!IupGetInt(ih, "DS_STRXDATA"))
{
IupSetAttribute(matrix, "NUMERICQUANTITY1", "NONE");
IupSetStrAttribute(matrix, "NUMERICFORMAT1", IupGetAttribute(ih, "AXS_XTICKFORMAT"));
IupSetAttribute(matrix, "MASK*:1", IUP_MASK_FLOAT);
}
IupSetAttribute(matrix, "NUMERICQUANTITY2", "NONE");
IupSetStrAttribute(matrix, "NUMERICFORMAT2", IupGetAttribute(ih, "AXS_YTICKFORMAT"));
IupSetAttribute(matrix, "MASK*:2", IUP_MASK_FLOAT);
IupSetCallback(matrix, "NUMERICGETVALUE_CB", (Icallback)iPlotDataSetValuesMatrixNumericGetValue_CB);
IupSetCallback(matrix, "RESIZEMATRIX_CB", (Icallback)iPlotDataSetValuesMatrixResize_CB);
IupSetCallback(matrix, "VALUE_CB", (Icallback)iPlotDataSetValuesMatrixValue_CB);
if (IupGetInt(ih, "EDITABLEVALUES"))
{
IupSetCallback(matrix, "NUMERICSETVALUE_CB", (Icallback)iPlotDataSetValuesMatrixNumericSetValue_CB);
IupSetCallback(matrix, "VALUE_EDIT_CB", (Icallback)iPlotDataSetValuesMatrixValueEdit_CB);
}
IupSetCallback(button, "ACTION", (Icallback)iPlotDataSetValuesButton_CB);
IupSetAttribute(matrix, "PLOT", (char*)ih);
iupAttribSetInt(matrix, "_IUP_PLOT_CURRENT", plot_current);
iupAttribSetInt(matrix, "_IUP_DS", ds);
IupPopup(dlg, IUP_CENTERPARENT, IUP_CENTERPARENT);
if (IupGetInt(ih, "EDITABLEVALUES"))
IupSetAttribute(ih, "REDRAW", NULL);
IupDestroy(dlg);
return IUP_DEFAULT;
}
static int iPlotKeyPress_CB(Ihandle* ih, int c, int press);
static void iPlotRedrawInteract(Ihandle *ih);
static int iPlotZoomIn_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
return iPlotKeyPress_CB(ih, K_plus, 1);
}
static int iPlotZoomOut_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
return iPlotKeyPress_CB(ih, K_minus, 1);
}
static int iPlotZoomReset_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
return iPlotKeyPress_CB(ih, K_period, 1);
}
static int iPlotShowLegend_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
if (ih->data->current_plot->mLegend.mShow)
ih->data->current_plot->mLegend.mShow = false;
else
ih->data->current_plot->mLegend.mShow = true;
ih->data->current_plot->mRedraw = true;
iPlotRedrawInteract(ih);
return IUP_DEFAULT;
}
static int iPlotShowGrid_CB(Ihandle* self)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(self, "PLOT");
if (ih->data->current_plot->mGrid.mShowX || ih->data->current_plot->mGrid.mShowY)
{
ih->data->current_plot->mGrid.mShowY = false;
ih->data->current_plot->mGrid.mShowX = false;
}
else
{
ih->data->current_plot->mGrid.mShowX = true;
ih->data->current_plot->mGrid.mShowY = true;
}
ih->data->current_plot->mRedraw = true;
iPlotRedrawInteract(ih);
return IUP_DEFAULT;
}
static int iPlotGetListIndex(const char** list, const char* value)
{
int i = 0;
while (list[i])
{
if (iupStrEqualNoCase(list[i], value))
return i;
i++;
}
return 0;
}
struct iPlotAttribParam
{
const char* name;
Icallback check;
const char* label;
const char* type;
const char* extra;
const char* tip;
const char** list;
};
static const char* iplot_linestyle_list[] = { "CONTINUOUS", "DASHED", "DOTTED", "DASH_DOT", "DASH_DOT_DOT", NULL };
static const char* iplot_fontstyle_list[] = { "", "BOLD", "ITALIC", "BOLDITALIC", NULL };
static const char* iplot_legendpos_list[] = { "TOPRIGHT", "TOPLEFT", "BOTTOMRIGHT", "BOTTOMLEFT", "BOTTOMCENTER", "XY", NULL };
static const char* iplot_grid_list[] = { "NO", "YES", "HORIZONTAL", "VERTICAL", NULL };
static const char* iplot_scale_list[] = { "LIN", "LOG10", "LOG2", "LOGN", NULL };
static const char* iplot_axispos_list[] = { "START", "CROSSORIGIN", "END", NULL };
static const char* iplot_linestyle_extra = { "|_@IUP_CONTINUOUS|_@IUP_DASHED|_@IUP_DOTTED|_@IUP_DASH_DOT|_@IUP_DASH_DOT_DOT|" };
static const char* iplot_fontstyle_extra = { "|_@IUP_PLAIN|_@IUP_BOLD|_@IUP_ITALIC|_@IUP_BOLDITALIC|" };
static const char* iplot_legendpos_extra = { "|_@IUP_TOPRIGHT|_@IUP_TOPLEFT|_@IUP_BOTTOMRIGHT|_@IUP_BOTTOMLEFT|_@IUP_BOTTOMCENTER|_@IUP_XY|" };
static const char* iplot_grid_extra = { "|_@IUP_NO|_@IUP_YES|_@IUP_HORIZONTAL|_@IUP_VERTICAL|" };
static const char* iplot_scale_extra = { "|_@IUP_LINEAR|_@IUP_LOG10|_@IUP_LOG2|_@IUP_LOGN|" };
static const char* iplot_axispos_extra = { "|_@IUP_START|_@IUP_CROSSORIGIN|_@IUP_END|" };
static int iPlotCheckBool(Ihandle* param)
{
return iupAttribGetBoolean(param, "VALUE");
}
static int iPlotCheckAuto(Ihandle* param)
{
return !iupAttribGetBoolean(param, "VALUE");
}
static int iPlotCheckAuto2(Ihandle* param)
{
iupAttribSetInt(param, "CHILDCOUNT", 2);
return !iupAttribGetBoolean(param, "VALUE");
}
static int iPlotCheckAutoXY(Ihandle* param) // Simply to be able to distinguish from other iPlotCheckAuto
{
return !iupAttribGetBoolean(param, "VALUE");
}
static int iPlotCheckLegendXY(Ihandle* param)
{
int index = iupAttribGetInt(param, "VALUE");
return iupStrEqualNoCase(iplot_legendpos_list[index], "XY");
}
static iPlotAttribParam iplot_background_attribs[] = {
{ "", NULL, "_@IUP_MARGIN", "t", NULL, NULL, NULL },
{ "MARGINLEFTAUTO", iPlotCheckAuto, "_@IUP_LEFT", "b", "[ ,Auto]", "", NULL },
{ "MARGINLEFT", NULL, "\t_@IUP_VALUE", "i", "", "", NULL },
{ "MARGINRIGHTAUTO", iPlotCheckAuto, "_@IUP_RIGHT", "b", "", "", NULL },
{ "MARGINRIGHT", NULL, "\t_@IUP_VALUE", "i", "", "", NULL },
{ "MARGINTOPAUTO", iPlotCheckAuto, "_@IUP_TOP", "b", "[ ,Auto]", "", NULL },
{ "MARGINTOP", NULL, "\t_@IUP_VALUE", "i", "", "", NULL },
{ "MARGINBOTTOMAUTO", iPlotCheckAuto, "_@IUP_BOTTOM", "b", "[ ,Auto]", "", NULL },
{ "MARGINBOTTOM", NULL, "\t_@IUP_VALUE", "i", "", "", NULL },
{ "", NULL, "", "t", NULL, NULL, NULL },
{ "PADDING", NULL, "_@IUP_PADDING", "s", "[+/-]?/d+[x][+/-]?/d+", "{_@IUP_INTERNALMARGIN}", NULL },
{ "BACKCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_title_attribs[] = {
{ "TITLE", NULL, "_@IUP_TEXT", "s", "", "", NULL },
{ "TITLECOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "TITLEFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "TITLEFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ "TITLEPOSAUTO", iPlotCheckAutoXY, "_@IUP_POSITION", "b", "[ ,Auto]", "", NULL },
{ "TITLEPOSXY", NULL, "\t_@IUP_POSXY", "s", "[+/-]?/d+[,][+/-]?/d+", "{(pixels)}", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_legend_attribs[] = {
{ "LEGEND", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "LEGENDFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "LEGENDFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ "LEGENDPOS", iPlotCheckLegendXY, "_@IUP_POSITION", "l", iplot_legendpos_extra, "", iplot_legendpos_list },
{ "LEGENDPOSXY", NULL, "\t_@IUP_POSXY", "s", "[+/-]?/d+[,][+/-]?/d+", "{(pixels)}", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_legendbox_attribs[] = {
{ "LEGENDBOX", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "LEGENDBOXCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "LEGENDBOXBACKCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "LEGENDBOXLINESTYLE", NULL, "_@IUP_LINESTYLE", "l", iplot_linestyle_extra, "", iplot_linestyle_list },
{ "LEGENDBOXLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_grid_attribs[] = {
{ "GRID", NULL, "_@IUP_SHOW", "l", iplot_grid_extra, "", iplot_grid_list },
{ "GRIDCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "GRIDLINESTYLE", NULL, "_@IUP_LINESTYLE", "l", iplot_linestyle_extra, "", iplot_linestyle_list },
{ "GRIDLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_gridminor_attribs[] = {
{ "GRIDMINOR", NULL, "_@IUP_SHOW", "l", iplot_grid_extra, "", iplot_grid_list },
{ "GRIDMINORCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "GRIDMINORLINESTYLE", NULL, "_@IUP_LINESTYLE", "l", iplot_linestyle_extra, "", iplot_linestyle_list },
{ "GRIDMINORLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_box_attribs[] = {
{ "BOX", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "BOXCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "BOXLINESTYLE", NULL, "_@IUP_LINESTYLE", "l", iplot_linestyle_extra, "", iplot_linestyle_list },
{ "BOXLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisX_attribs[] = {
{ "AXS_X", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_XARROW", NULL, "_@IUP_SHOWARROW", "b", "", "", NULL },
{ "AXS_XCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "AXS_XLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ "", NULL, "", "t", NULL, NULL, NULL },
{ "AXS_XAUTOMIN", iPlotCheckAuto, "_@IUP_MIN", "b", "[ ,Auto]", "", NULL },
{ "AXS_XMIN", NULL, "\t_@IUP_VALUE", "R", "", "", NULL },
{ "AXS_XAUTOMAX", iPlotCheckAuto, "_@IUP_MAX", "b", "[ ,Auto]", "", NULL },
{ "AXS_XMAX", NULL, "\t_@IUP_VALUE", "R", "", "", NULL },
{ "AXS_XSCALE", NULL, "_@IUP_SCALE", "l", iplot_scale_extra, "", iplot_scale_list },
{ "AXS_XREVERSE", NULL, "_@IUP_REVERSE", "b", "", "", NULL },
{ "AXS_XPOSITION", NULL, "_@IUP_POSITION", "l", iplot_axispos_extra, "", iplot_axispos_list },
{ "AXS_XREVERSETICKSLABEL", NULL, "_@IUP_REVERSETICKSLABEL", "b", "", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisY_attribs[] = {
{ "AXS_Y", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_YARROW", NULL, "_@IUP_SHOWARROW", "b", "", "", NULL },
{ "AXS_YCOLOR", NULL, "_@IUP_COLOR", "c", "", "", NULL },
{ "AXS_YLINEWIDTH", NULL, "_@IUP_LINEWIDTH", "i", "[1,,]", "", NULL },
{ "", NULL, "", "t", NULL, NULL, NULL },
{ "AXS_YAUTOMIN", iPlotCheckAuto, "_@IUP_MIN", "b", "[ ,Auto]", "", NULL },
{ "AXS_YMIN", NULL, "\t_@IUP_VALUE", "R", "", "", NULL },
{ "AXS_YAUTOMAX", iPlotCheckAuto, "_@IUP_MAX", "b", "[ ,Auto]", "", NULL },
{ "AXS_YMAX", NULL, "\t_@IUP_VALUE", "R", "", "", NULL },
{ "AXS_YSCALE", NULL, "_@IUP_SCALE", "l", iplot_scale_extra, "", iplot_scale_list },
{ "AXS_YREVERSE", NULL, "_@IUP_REVERSE", "b", "", "", NULL },
{ "AXS_YPOSITION", NULL, "_@IUP_POSITION", "l", iplot_axispos_extra, "", iplot_axispos_list },
{ "AXS_YREVERSETICKSLABEL", NULL, "_@IUP_REVERSETICKSLABEL", "b", "", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisXlabel_attribs[] = {
{ "AXS_XLABEL", NULL, "_@IUP_TEXT", "s", "", "", NULL },
{ "AXS_XLABELCENTERED", NULL, "_@IUP_CENTERED", "b", "", "", NULL },
{ "AXS_XLABELSPACING", NULL, "_@IUP_SPACING", "i", "[-1,,]", "", NULL },
{ "AXS_XFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "AXS_XFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisYlabel_attribs[] = {
{ "AXS_YLABEL", NULL, "_@IUP_TEXT", "s", "", "", NULL },
{ "AXS_YLABELCENTERED", NULL, "_@IUP_CENTERED", "b", "", "", NULL },
{ "AXS_YLABELSPACING", NULL, "_@IUP_SPACING", "i", "[-1,,]", "", NULL },
{ "AXS_YFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "AXS_YFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisXticks_attribs[] = {
{ "AXS_XTICK", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_XTICKAUTO", iPlotCheckAuto2, "_@IUP_SPACING", "b", "[ ,Auto]", "", NULL },
{ "AXS_XTICKMAJORSPAN", NULL, "\t_@IUP_MAJORSPAN", "R", "", "", NULL },
{ "AXS_XTICKMINORDIVISION", NULL, "\t_@IUP_MINORDIVISION", "i", "[1,,]", "", NULL },
{ "AXS_XTICKSIZEAUTO", iPlotCheckAuto2, "_@IUP_SIZE", "b", "[ ,Auto]", "", NULL },
{ "AXS_XTICKMAJORSIZE", NULL, "\t_@IUP_MAJOR", "i", "[1,,]", "", NULL },
{ "AXS_XTICKMINORSIZE", NULL, "\t_@IUP_MINOR", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisYticks_attribs[] = {
{ "AXS_YTICK", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_YTICKAUTO", iPlotCheckAuto2, "_@IUP_SPACING", "b", "[ ,Auto]", "", NULL },
{ "AXS_YTICKMAJORSPAN", NULL, "\t_@IUP_MAJORSPAN", "R", "", "", NULL },
{ "AXS_YTICKMINORDIVISION", NULL, "\t_@IUP_MINORDIVISION", "i", "[1,,]", "", NULL },
{ "AXS_YTICKSIZEAUTO", iPlotCheckAuto2, "_@IUP_SIZE", "b", "[ ,Auto]", "", NULL },
{ "AXS_YTICKMAJORSIZE", NULL, "\t_@IUP_MAJOR", "i", "[1,,]", "", NULL },
{ "AXS_YTICKMINORSIZE", NULL, "\t_@IUP_MINOR", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisXticksnumber_attribs[] = {
{ "AXS_XTICKNUMBER", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_XTICKROTATENUMBER", iPlotCheckBool, "_@IUP_ROTATE", "b", "", "", NULL },
{ "AXS_XTICKROTATENUMBERANGLE", NULL, "\t_@IUP_ANGLE", "A", "", "", NULL },
{ "AXS_XTICKFORMATAUTO", iPlotCheckAuto, "_@IUP_FORMAT", "b", "[ ,Auto]", "", NULL },
{ "AXS_XTICKFORMATPRECISION", NULL, "\t_@IUP_DECIMALS", "i", "[0,,]", "", NULL },
{ "AXS_XTICKFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "AXS_XTICKFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static iPlotAttribParam iplot_axisYticksnumber_attribs[] = {
{ "AXS_YTICKNUMBER", NULL, "_@IUP_SHOW", "b", "", "", NULL },
{ "AXS_YTICKROTATENUMBER", iPlotCheckBool, "_@IUP_ROTATE", "b", "", "", NULL },
{ "AXS_YTICKROTATENUMBERANGLE", NULL, "\t_@IUP_ANGLE", "A", "", "", NULL },
{ "AXS_YTICKFORMATAUTO", iPlotCheckAuto, "_@IUP_FORMAT", "b", "[ ,Auto]", "", NULL },
{ "AXS_YTICKFORMATPRECISION", NULL, "\t_@IUP_DECIMALS", "i", "[0,,]", "", NULL },
{ "AXS_YTICKFONTSTYLE", NULL, "_@IUP_FONTSTYLE", "l", iplot_fontstyle_extra, "", iplot_fontstyle_list },
{ "AXS_YTICKFONTSIZE", NULL, "_@IUP_FONTSIZE", "i", "[1,,]", "", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static void iPlotSetParamDouble(Ihandle* control, const char* name, double num)
{
char value[80];
char format[30];
int prec = IupGetInt(NULL, "DEFAULTPRECISION");
sprintf(format, "%%.%df", prec);
iupStrPrintfDoubleLocale(value, format, num, IupGetGlobal("DEFAULTDECIMALSYMBOL"));
IupStoreAttribute(control, name, value);
}
static void iPlotSetParamValue(Ihandle* param, const char* value)
{
Ihandle* control = (Ihandle*)IupGetAttribute(param, "CONTROL");
Ihandle* auxcontrol = (Ihandle*)IupGetAttribute(param, "AUXCONTROL");
if (value && iupStrEqualNoCase(IupGetAttribute(param, "TYPE"), "LIST"))
{
const char** list = (const char**)IupGetAttribute(param, "PLOT_ATTRIBLIST");
int index = iPlotGetListIndex(list, value);
IupSetInt(param, "VALUE", index);
if (control) IupSetInt(control, "VALUE", index + 1);
// No Aux here
}
else
{
IupSetStrAttribute(param, "VALUE", value);
if (control)
{
if (iupStrEqualNoCase(iupAttribGet(param, "TYPE"), "REAL"))
{
double num = IupGetDouble(param, "VALUE");
iPlotSetParamDouble(control, "VALUE", num);
}
else
IupSetStrAttribute(control, "VALUE", value);
}
if (auxcontrol) IupSetStrAttribute(auxcontrol, "VALUE", value);
}
}
static const char* iPlotGetParamValue(Ihandle* param)
{
char* value = IupGetAttribute(param, "VALUE");
if (!value || value[0] == 0)
return NULL; /* reset to default */
else
{
if (iupStrEqualNoCase(IupGetAttribute(param, "TYPE"), "LIST"))
{
const char** list = (const char**)IupGetAttribute(param, "PLOT_ATTRIBLIST");
int index;
iupStrToInt(value, &index);
return list[index];
}
return value;
}
}
static void iPlotPropertiesCheckUpdateXY(Ihandle* ih, Ihandle* parambox, Ihandle* param, int param_index)
{
Icallback check = IupGetCallback(param, "PLOT_ATTRIBCHECK_CB");
if (check == iPlotCheckAutoXY ||
check == iPlotCheckLegendXY)
{
int active = check(param);
if (!active)
{
/* if not active is automatically calculated every draw, must update param */
param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", param_index + 1);
char* name = IupGetAttribute(param, "PLOT_ATTRIB");
// From Plot
char* value = IupGetAttribute(ih, name);
// To Param
iPlotSetParamValue(param, value);
}
}
}
static void iPlotPropertiesCheckParam(Ihandle* parambox, Ihandle* param, int param_index)
{
Icallback check = IupGetCallback(param, "PLOT_ATTRIBCHECK_CB");
if (check)
{
/* disable or enable the next childcount params */
int active = check(param);
int count = iupAttribGetInt(param, "CHILDCOUNT");
if (count == 0) count = 1;
while (count)
{
param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", param_index + count);
Ihandle* control = (Ihandle*)IupGetAttribute(param, "CONTROL");
IupSetInt(IupGetParent(control), "ACTIVE", active);
count--;
}
}
}
static void iPlotPropertiesInit(Ihandle* parambox)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(parambox, "PLOT");
Ihandle* zbox = IupGetParent(parambox);
int plot_current = iupAttribGetInt(zbox, "_IUP_PLOT_CURRENT");
// make sure we are accessing the right plot
IupSetInt(ih, "PLOT_CURRENT", plot_current);
int i, count = IupGetInt(parambox, "PARAMCOUNT");
for (i = 0; i < count; i++)
{
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", i);
char* name = IupGetAttribute(param, "PLOT_ATTRIB");
// From Plot
char* value = IupGetAttribute(ih, name);
// To Param
iPlotSetParamValue(param, value);
iPlotPropertiesCheckParam(parambox, param, i);
}
IupSetAttribute(parambox, "PLOT_CHANGED", NULL);
IupSetAttribute(ih, "REDRAW", NULL);
}
static void iPlotPropertiesResetChanges(Ihandle* parambox)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(parambox, "PLOT");
Ihandle* zbox = IupGetParent(parambox);
int plot_current = iupAttribGetInt(zbox, "_IUP_PLOT_CURRENT");
// make sure we are changing the right plot
IupSetInt(ih, "PLOT_CURRENT", plot_current);
int i, count = IupGetInt(parambox, "PARAMCOUNT");
for (i = count - 1; i >= 0; i--) // backwards to avoid dependencies
{
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", i);
char* name = IupGetAttribute(param, "PLOT_ATTRIB");
// From Original Value
const char* value = IupGetAttribute(param, "RESET_VALUE");
// To Param
iPlotSetParamValue(param, value);
iPlotPropertiesCheckParam(parambox, param, i);
// From Param
value = iPlotGetParamValue(param);
// To Plot
IupSetStrAttribute(ih, name, value);
}
IupSetAttribute(parambox, "PLOT_CHANGED", NULL);
IupSetAttribute(ih, "REDRAW", NULL);
Icallback cb = IupGetCallback(ih, "PROPERTIESCHANGED_CB");
if (cb)
cb(ih);
}
static void iPlotPropertiesApplyChanges(Ihandle* parambox)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(parambox, "PLOT");
Ihandle* zbox = IupGetParent(parambox);
IFnss validate_cb = (IFnss)IupGetCallback(ih, "PROPERTIESVALIDATE_CB");
int plot_current = iupAttribGetInt(zbox, "_IUP_PLOT_CURRENT");
// make sure we are changing the right plot
IupSetInt(ih, "PLOT_CURRENT", plot_current);
int i, count = IupGetInt(parambox, "PARAMCOUNT");
for (i = count - 1; i >= 0; i--) // backwards to avoid dependencies
{
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", i);
char* name = IupGetAttribute(param, "PLOT_ATTRIB");
// From Param
const char* value = iPlotGetParamValue(param);
if (validate_cb && validate_cb(ih, name, (char*)value) == IUP_IGNORE)
continue;
else
{
// To Plot
IupSetAttribute(ih, name, value);
}
}
IupSetAttribute(parambox, "PLOT_CHANGED", NULL);
IupSetAttribute(ih, "REDRAW", NULL);
for (i = 0; i < count; i++)
{
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", i);
iPlotPropertiesCheckUpdateXY(ih, parambox, param, i);
}
Icallback cb = IupGetCallback(ih, "PROPERTIESCHANGED_CB");
if (cb)
cb(ih);
}
static void iPlotPropertiesCheckChanges(Ihandle* parambox)
{
if (IupGetInt(parambox, "PLOT_CHANGED"))
{
Ihandle* dlg = IupMessageDlg();
IupSetAttributeHandle(dlg, "PARENTDIALOG", IupGetDialog(parambox));
IupSetAttribute(dlg, "DIALOGTYPE", "WARNING");
IupSetAttribute(dlg, "BUTTONS", "YESNO");
IupSetStrAttribute(dlg, "TITLE", "_@IUP_ATTENTION");
IupSetStrAttribute(dlg, "VALUE", "_@IUP_CHANGESNOTAPPLIEDAPPLY");
IupPopup(dlg, IUP_CENTERPARENT, IUP_CENTERPARENT);
int ret = IupGetInt(dlg, "BUTTONRESPONSE");
IupDestroy(dlg);
if (ret == 1)
iPlotPropertiesApplyChanges(parambox);
else
IupSetAttribute(parambox, "PLOT_CHANGED", NULL);
}
}
static int iPlotPropertiesTreeSelection_CB(Ihandle *ih_tree, int id, int status)
{
if (status == 0)
{
Ihandle* zbox = IupGetBrother(ih_tree);
Ihandle* parambox = (Ihandle*)IupGetAttribute(zbox, "VALUE_HANDLE");
iPlotPropertiesCheckChanges(parambox);
}
if (status == 1)
{
Ihandle* zbox = IupGetBrother(ih_tree);
IupSetInt(zbox, "VALUEPOS", id);
Ihandle* parambox = (Ihandle*)IupGetAttribute(zbox, "VALUE_HANDLE");
iPlotPropertiesInit(parambox);
}
return IUP_DEFAULT;
}
static int iPlotPropertiesParam_CB(Ihandle* parambox, int param_index, void*)
{
if (param_index == IUP_GETPARAM_BUTTON1)
{
iPlotPropertiesApplyChanges(parambox);
return 0;
}
if (param_index == IUP_GETPARAM_BUTTON2)
{
iPlotPropertiesResetChanges(parambox);
return 0;
}
if (param_index == IUP_GETPARAM_BUTTON3)
{
iPlotPropertiesCheckChanges(parambox);
IupExitLoop();
return 0;
}
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", param_index);
iPlotPropertiesCheckParam(parambox, param, param_index);
IupSetAttribute(parambox, "PLOT_CHANGED", "1");
return 1;
}
static int iPlotPropertiesClose_CB(Ihandle* dlg)
{
Ihandle* zbox = IupGetChild(dlg, 1);
Ihandle* parambox = (Ihandle*)IupGetAttribute(zbox, "VALUE_HANDLE");
iPlotPropertiesCheckChanges(parambox);
return IUP_CLOSE;
}
static void iPlotPropertiesAddParamBox(Ihandle* ih, Ihandle* zbox, iPlotAttribParam* attribs)
{
Ihandle* params[50];
int count = 0;
char format[10240];
while (attribs[count].name)
{
sprintf(format, "%s%%%s%s%s\n", attribs[count].label, attribs[count].type, attribs[count].extra, attribs[count].tip);
params[count] = IupParam(format);
if (attribs[count].name[0] != 0)
{
IupSetStrAttribute(params[count], "PLOT_ATTRIB", attribs[count].name);
IupSetAttribute(params[count], "PLOT_ATTRIBLIST", (char*)(attribs[count].list));
IupSetCallback(params[count], "PLOT_ATTRIBCHECK_CB", attribs[count].check);
// From Plot
char* value = IupGetAttribute(ih, attribs[count].name);
// To Param
iPlotSetParamValue(params[count], value);
IupSetStrAttribute(params[count], "RESET_VALUE", value);
}
count++;
}
params[count] = IupParam("%u[,,_@IUP_CLOSE]");
count++;
params[count] = NULL;
Ihandle* parambox = IupParamBoxv(params);
IupSetCallback(parambox, "PARAM_CB", (Icallback)iPlotPropertiesParam_CB);
IupAppend(zbox, parambox);
count = IupGetInt(parambox, "PARAMCOUNT");
for (int i = 0; i < count; i++)
{
Ihandle* param = (Ihandle*)IupGetAttributeId(parambox, "PARAM", i);
iPlotPropertiesCheckParam(parambox, param, i);
}
}
static int iPlotProperties_CB(Ihandle* ih_item)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_item, "PLOT");
Ihandle* parent = IupGetDialog(ih);
Ihandle* ih_menu = IupGetParent(ih_item);
int plot_current = iupAttribGetInt(ih_menu, "_IUP_PLOT_CURRENT");
IupSetInt(ih, "PLOT_CURRENT", plot_current);
Ihandle* tree = IupTree();
IupSetAttribute(tree, "ADDROOT", "NO");
IupSetCallback(tree, "SELECTION_CB", (Icallback)iPlotPropertiesTreeSelection_CB);
IupSetAttribute(tree, "EXPAND", "VERTICAL");
IupSetAttribute(tree, "SIZE", "100x140");
IupSetAttribute(tree, "IMAGELEAF", "IMGPAPER");
Ihandle* zbox = IupZbox(NULL);
iPlotPropertiesAddParamBox(ih, zbox, iplot_background_attribs); /* 0 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_title_attribs); /* 1 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_legend_attribs); /* 2 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_legendbox_attribs); /* 3 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_box_attribs); /* 4 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_grid_attribs); /* 5 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_gridminor_attribs); /* 6 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisX_attribs); /* 7 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisXlabel_attribs); /* 8 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisXticks_attribs); /* 9 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisXticksnumber_attribs); /* 10 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisY_attribs); /* 11 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisYlabel_attribs); /* 12 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisYticks_attribs); /* 13 */
iPlotPropertiesAddParamBox(ih, zbox, iplot_axisYticksnumber_attribs); /* 14 */
IupSetAttribute(zbox, "PLOT", (char*)ih);
iupAttribSetInt(zbox, "_IUP_PLOT_CURRENT", plot_current);
Ihandle* dlg = IupDialog(IupHbox(tree, zbox, NULL));
IupSetAttributeHandle(dlg, "PARENTDIALOG", parent);
IupSetStrAttribute(dlg, "TITLE", "_@IUP_PROPERTIESDLG");
IupSetCallback(dlg, "K_ESC", iPlotPropertiesClose_CB);
IupSetCallback(dlg, "CLOSE_CB", (Icallback)iPlotPropertiesClose_CB);
IupSetAttribute(dlg, "MINBOX", "NO");
IupSetAttribute(dlg, "MAXBOX", "NO");
if (IupGetAttribute(parent, "ICON"))
IupSetStrAttribute(dlg, "ICON", IupGetAttribute(parent, "ICON"));
else
IupSetStrAttribute(dlg, "ICON", IupGetGlobal("ICON"));
IupMap(dlg);
IupSetStrAttribute(tree, "ADDLEAF-1", "_@IUP_BACKGROUND"); /* 0 */
IupSetStrAttribute(tree, "ADDLEAF0", "_@IUP_TITLE"); /* 1 */
IupSetStrAttribute(tree, "ADDBRANCH1", "_@IUP_LEGEND"); /* 2 */
IupSetStrAttribute(tree, "ADDLEAF2", "_@IUP_LEGENDBOX"); /* 3 */
IupSetStrAttribute(tree, "INSERTLEAF2", "_@IUP_BOX"); /* 4 */
IupSetStrAttribute(tree, "ADDBRANCH4", "_@IUP_GRID"); /* 5 */
IupSetStrAttribute(tree, "ADDLEAF5", "_@IUP_GRIDMINOR"); /* 6 */
IupSetStrAttribute(tree, "INSERTBRANCH5", "_@IUP_XAXIS"); /* 7 */
IupSetStrAttribute(tree, "ADDLEAF7", "_@IUP_AXISLABEL"); /* 8 */
IupSetStrAttribute(tree, "ADDLEAF8", "_@IUP_AXISTICKS"); /* 9 */
IupSetStrAttribute(tree, "ADDLEAF9", "_@IUP_AXISTICKSNUMBER"); /* 10 */
IupSetStrAttribute(tree, "INSERTBRANCH7", "_@IUP_YAXIS"); /* 11 */
IupSetStrAttribute(tree, "ADDLEAF11", "_@IUP_AXISLABEL"); /* 12 */
IupSetStrAttribute(tree, "ADDLEAF12", "_@IUP_AXISTICKS"); /* 13 */
IupSetStrAttribute(tree, "ADDLEAF13", "_@IUP_AXISTICKSNUMBER"); /* 14 */
IupPopup(dlg, IUP_CENTERPARENT, IUP_CENTERPARENT);
IupSetAttribute(ih, "REDRAW", NULL);
IupDestroy(dlg);
return IUP_DEFAULT;
}
static int iPlotDataSetPropertiesParam_cb(Ihandle* param_dialog, int param_index, void* user_data)
{
if (param_index == IUP_GETPARAM_MAP)
{
Ihandle* ih = (Ihandle*)user_data;
IupSetAttributeHandle(param_dialog, "PARENTDIALOG", IupGetDialog(ih));
}
else if (param_index == IUP_GETPARAM_BUTTON1)
{
Ihandle* ih = (Ihandle*)user_data;
IFnni cb = (IFnni)IupGetCallback(ih, "DSPROPERTIESVALIDATE_CB");
int ds = IupGetInt(ih, "_IUP_DS");
if (cb && cb(ih, param_dialog, ds) == IUP_IGNORE)
return 0;
}
return 1;
}
static int iPlotDataSetProperties_CB(Ihandle* ih_item)
{
Ihandle* ih = (Ihandle*)IupGetAttribute(ih_item, "PLOT");
Ihandle* ih_menu = IupGetParent(ih_item);
int plot_current = iupAttribGetInt(ih_menu, "_IUP_PLOT_CURRENT");
int ds = iupAttribGetInt(ih_menu, "_IUP_DS");
char name[100];
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
IupSetInt(ih, "_IUP_DS", ds);
char* ds_name = IupGetAttribute(ih, "DS_NAME");
strcpy(name, ds_name);
const char* ds_color = IupGetAttribute(ih, "DS_COLOR");
char color[30];
strcpy(color, ds_color);
const char* ds_mode = IupGetAttribute(ih, "DS_MODE");
const char* mode_list[] = { "LINE", "MARK", "MARKLINE", "AREA", "BAR", "STEM", "MARKSTEM", "HORIZONTALBAR", "MULTIBAR", "STEP", "ERRORBAR", "PIE", NULL };
int mode = iPlotGetListIndex(mode_list, ds_mode);
const char* ds_linestyle = IupGetAttribute(ih, "DS_LINESTYLE");
int linestyle = iPlotGetListIndex(iplot_linestyle_list, ds_linestyle);
int linewidth = IupGetInt(ih, "DS_LINEWIDTH");
const char* ds_markstyle = IupGetAttribute(ih, "DS_MARKSTYLE");
const char* markstyle_list[] = { "PLUS", "STAR", "CIRCLE", "X", "BOX", "DIAMOND", "HOLLOW_CIRCLE", "HOLLOW_BOX", "HOLLOW_DIAMOND", NULL };
int markstyle = iPlotGetListIndex(markstyle_list, ds_markstyle);
int marksize = IupGetInt(ih, "DS_MARKSIZE");
int barOutline = IupGetInt(ih, "DS_BAROUTLINE");
const char* ds_barOutlineColor = IupGetAttribute(ih, "DS_BAROUTLINECOLOR");
char barOutlineColor[30];
strcpy(barOutlineColor, ds_barOutlineColor);
int barSpacing = IupGetInt(ih, "DS_BARSPACING");
int areaTransparency = IupGetInt(ih, "DS_AREATRANSPARENCY");
double pieRadius = IupGetDouble(ih, "DS_PIERADIUS");
double pieStartAngle = IupGetDouble(ih, "DS_PIESTARTANGLE");
int pieContour = IupGetInt(ih, "DS_PIECONTOUR");
double pieHole = IupGetDouble(ih, "DS_PIEHOLE");
const char* pieSliceLabel = IupGetAttribute(ih, "DS_PIESLICELABEL");
const char* pieSliceLabel_list[] = { "NONE", "X", "Y", "PERCENT", NULL };
int pieSliceLabel_index = iPlotGetListIndex(pieSliceLabel_list, pieSliceLabel);
double pieSliceLabelPos = IupGetDouble(ih, "DS_PIESLICELABELPOS");
char format[1024] =
"_@IUP_NAME%s\n"
"_@IUP_COLOR%c\n"
"_@IUP_MODE%l|_@IUP_LINES|_@IUP_MARKS|_@IUP_MARKSLINES|_@IUP_AREA|_@IUP_BARS|_@IUP_STEMS|_@IUP_MARKSSTEMS|_@IUP_HORIZONTALBARS|_@IUP_MULTIBARS|_@IUP_STEPS|_@IUP_ERRORBARS|_@IUP_PIE|\n"
"_@IUP_LINESTYLE%l|_@IUP_CONTINUOUS|_@IUP_DASHED|_@IUP_DOTTED|_@IUP_DASH_DOT|_@IUP_DASH_DOT_DOT|\n"
"_@IUP_LINEWIDTH%i[1,,]\n"
"_@IUP_MARKSTYLE%l|_@IUP_PLUS|_@IUP_STAR|_@IUP_CIRCLE|_@IUP_X|_@IUP_BOX|_@IUP_DIAMOND|_@IUP_HOLLOW_CIRCLE|_@IUP_HOLLOW_BOX|_@IUP_HOLLOW_DIAMOND|\n"
"_@IUP_MARKSIZE%i[1,,]\n"
"_@IUP_BARSPACING%i[0,100]\n"
"_@IUP_BAROUTLINE%b[false,true]\n"
"_@IUP_BAROUTLINECOLOR%c\n"
"_@IUP_AREATRANSPARENCY%i[0,255]\n"
"_@IUP_PIERADIUS%R[0,,]\n"
"_@IUP_PIESTARTANGLE%R[0,360,]\n"
"_@IUP_PIECONTOUR%b[false,true]\n"
"_@IUP_PIEHOLE%R[0,1,]\n"
"_@IUP_PIESLICELABEL%l|_@IUP_NONE|X|Y|_@IUP_PERCENT|\n"
"_@IUP_PIESLICELABELPOS%R[0,1,]\n";
if (!IupGetParam("_@IUP_DATASETPROPERTIESDLG", iPlotDataSetPropertiesParam_cb, ih, format,
name, color, &mode, &linestyle, &linewidth, &markstyle, &marksize,
&barSpacing, &barOutline, barOutlineColor,
&areaTransparency,
&pieRadius, &pieStartAngle, &pieContour, &pieHole, &pieSliceLabel_index, &pieSliceLabelPos,
NULL))
return IUP_DEFAULT;
// make sure we are changing the right plot
IupSetInt(ih, "PLOT_CURRENT", plot_current);
IupSetInt(ih, "CURRENT", ds);
IupSetAttribute(ih, "_IUP_DS", NULL);
IupSetStrAttribute(ih, "DS_NAME", name);
IupSetStrAttribute(ih, "DS_COLOR", color);
ds_mode = mode_list[mode];
IupSetStrAttribute(ih, "DS_MODE", ds_mode);
ds_linestyle = iplot_linestyle_list[linestyle];
IupSetStrAttribute(ih, "DS_LINESTYLE", ds_linestyle);
IupSetInt(ih, "DS_LINEWIDTH", linewidth);
ds_markstyle = markstyle_list[markstyle];
IupSetStrAttribute(ih, "DS_MARKSTYLE", ds_markstyle);
IupSetInt(ih, "DS_MARKSIZE", marksize);
if (barOutline == 1)
IupSetAttribute(ih, "DS_BAROUTLINE", "Yes");
else
IupSetAttribute(ih, "DS_BAROUTLINE", "No");
IupSetInt(ih, "DS_BARSPACING", barSpacing);
IupSetStrAttribute(ih, "DS_BAROUTLINECOLOR", barOutlineColor);
IupSetInt(ih, "DS_AREATRANSPARENCY", areaTransparency);
IupSetDouble(ih, "DS_PIERADIUS", pieRadius);
IupSetDouble(ih, "DS_PIESTARTANGLE", pieStartAngle);
IupSetInt(ih, "DS_PIECONTOUR", pieContour);
IupSetDouble(ih, "DS_PIEHOLE", pieHole);
pieSliceLabel = pieSliceLabel_list[pieSliceLabel_index];
IupSetStrAttribute(ih, "DS_PIESLICELABEL", pieSliceLabel);
IupSetDouble(ih, "DS_PIESLICELABELPOS", pieSliceLabelPos);
IupSetAttribute(ih, "REDRAW", NULL);
IFni cb = (IFni)IupGetCallback(ih, "DSPROPERTIESCHANGED_CB");
if (cb)
cb(ih, ds);
return IUP_DEFAULT;
}
static Ihandle* iPlotCreateMenuContext(Ihandle* ih, int x, int y)
{
Ihandle* menu = IupMenu(
IupSetCallbacks(IupItem("_@IUP_ZOOMINAC", NULL), "ACTION", iPlotZoomIn_CB, NULL),
IupSetCallbacks(IupItem("_@IUP_ZOOMOUTAC", NULL), "ACTION", iPlotZoomOut_CB, NULL),
IupSetCallbacks(IupItem("_@IUP_RESETZOOMAC", NULL), "ACTION", iPlotZoomReset_CB, NULL),
IupSeparator(),
IupSetCallbacks(IupItem("_@IUP_SHOWHIDELEGEND", NULL), "ACTION", iPlotShowLegend_CB, NULL),
IupSetCallbacks(IupItem("_@IUP_SHOWHIDEGRID", NULL), "ACTION", iPlotShowGrid_CB, NULL),
IupSeparator(),
IupSubmenu("_@IUP_COPY",
IupMenu(
IupSetCallbacks(IupItem("Metafile", NULL), "ACTION", iPlotCopyAsMetafile_CB, NULL),
IupSetCallbacks(IupItem("Image", NULL), "ACTION", iPlotCopyAsImage_CB, NULL),
NULL)),
IupSubmenu("_@IUP_EXPORT",
IupMenu(
IupSetCallbacks(IupItem("SVG...", NULL), "ACTION", iPlotExportSVG_CB, NULL),
IupSetCallbacks(IupItem("EPS...", NULL), "ACTION", iPlotExportEPS_CB, NULL),
IupSetCallbacks(IupItem("CGM...", NULL), "ACTION", iPlotExportCGM_CB, NULL),
#ifdef WIN32
IupSetCallbacks(IupItem("EMF...", NULL), "ACTION", iPlotExportEMF_CB, NULL),
IupSetCallbacks(IupItem("WMF...", NULL), "ACTION", iPlotExportWMF_CB, NULL),
#endif
NULL)),
IupSeparator(),
IupSetCallbacks(IupItem("_@IUP_PRINTDLG", NULL), "ACTION", iPlotPrint_CB, NULL),
NULL);
if (IupGetInt(ih, "MENUITEMPROPERTIES") || IupGetInt(ih, "MENUITEMVALUES"))
{
Ihandle* itemProp = NULL, *itemVal = NULL;
IupAppend(menu, IupSeparator());
if (iupRegisterFindClass("matrixex") && !iupStrEqualNoCase(iupAttribGet(ih, "MENUITEMVALUES"), "HIDE"))
IupAppend(menu, IupSetCallbacks(itemVal = IupItem("_@IUP_DATASETVALUESDLG", NULL), "ACTION", iPlotDataSetValues_CB, NULL));
if (IupGetInt(ih, "MENUITEMPROPERTIES"))
{
IupAppend(menu, IupSetCallbacks(itemProp = IupItem("_@IUP_DATASETPROPERTIESDLG", NULL), "ACTION", iPlotDataSetProperties_CB, NULL));
IupAppend(menu, IupSetCallbacks(IupItem("_@IUP_PROPERTIESDLG", NULL), "ACTION", iPlotProperties_CB, NULL));
}
int ds = IupGetInt(ih, "CURRENT");
int sample1, sample2;
double rx1, ry1, rx2, ry2;
const char* ds_name;
const char* strX;
if (ih->data->current_plot->FindDataSetSample((double)x, (double)y, ds, ds_name, sample1, rx1, ry1, strX) ||
((ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_CURVE || ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_BOTH) && ih->data->current_plot->FindDataSetSegment((double)x, (double)y, ds, ds_name, sample1, rx1, ry1, sample2, rx2, ry2)))
{
// save plot info because it may have changed by the time the callback is called
iupAttribSetInt(menu, "_IUP_DS", ds);
if (itemProp) IupSetAttribute(itemProp, "ACTIVE", "YES");
if (itemVal) IupSetAttribute(itemVal, "ACTIVE", "YES");
}
else
{
if (itemProp) IupSetAttribute(itemProp, "ACTIVE", "NO");
if (itemVal) IupSetAttribute(itemVal, "ACTIVE", "NO");
}
// save plot info because it may have changed by the time the callback is called
iupAttribSetInt(menu, "_IUP_PLOT_CURRENT", ih->data->current_plot_index);
}
IupSetAttribute(menu, "PLOT", (char*)ih);
return menu;
}
void iupPlotShowMenuContext(Ihandle* ih, int screen_x, int screen_y, int x, int y)
{
Ihandle* menu = iPlotCreateMenuContext(ih, x, y);
IFnnii menucontext_cb;
menucontext_cb = (IFnnii)IupGetCallback(ih, "MENUCONTEXT_CB");
if (menucontext_cb)
menucontext_cb(ih, menu, x, y);
IupPopup(menu, screen_x, screen_y);
menucontext_cb = (IFnnii)IupGetCallback(ih, "MENUCONTEXTCLOSE_CB");
if (menucontext_cb)
menucontext_cb(ih, menu, x, y);
IupDestroy(menu);
}
void iupPlotSetPlotCurrent(Ihandle* ih, int p)
{
ih->data->current_plot_index = p;
ih->data->current_plot = ih->data->plot_list[ih->data->current_plot_index];
}
void iupPlotRedraw(Ihandle* ih, int flush, int only_current, int reset_redraw)
{
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
{
IupGLMakeCurrent(ih);
// in OpenGL mode must:
flush = 1; // always flush
only_current = 0; // redraw all plots
reset_redraw = 1; // always render
}
if (ih->data->sync_view || ih->data->merge_view)
only_current = 0; // draw all plots
cdCanvasActivate(ih->data->cd_canvas);
if (only_current)
{
if (reset_redraw)
ih->data->current_plot->mRedraw = true;
ih->data->current_plot->PrepareRender(ih->data->cd_canvas);
ih->data->current_plot->Render(ih->data->cd_canvas);
}
else
{
int old_current = ih->data->current_plot_index;
int p;
for (p = 0; p < ih->data->plot_list_count; p++)
{
iupPlotSetPlotCurrent(ih, p);
if (reset_redraw)
ih->data->current_plot->mRedraw = true;
ih->data->current_plot->PrepareRender(ih->data->cd_canvas);
ih->data->current_plot->mBack.mTransparent = false;
}
if (ih->data->merge_view)
{
iupPlotSetPlotCurrent(ih, 0);
iupPlot* plot0 = ih->data->current_plot;
/* compute the margin that all plots can fit */
for (p = 1; p < ih->data->plot_list_count; p++)
{
iupPlotSetPlotCurrent(ih, p);
if (ih->data->current_plot->mBack.mMargin.mLeft > plot0->mBack.mMargin.mLeft)
plot0->mBack.mMargin.mLeft = ih->data->current_plot->mBack.mMargin.mLeft;
if (ih->data->current_plot->mBack.mMargin.mRight > plot0->mBack.mMargin.mRight)
plot0->mBack.mMargin.mRight = ih->data->current_plot->mBack.mMargin.mRight;
if (ih->data->current_plot->mBack.mMargin.mTop > plot0->mBack.mMargin.mTop)
plot0->mBack.mMargin.mTop = ih->data->current_plot->mBack.mMargin.mTop;
if (ih->data->current_plot->mBack.mMargin.mBottom > plot0->mBack.mMargin.mBottom)
plot0->mBack.mMargin.mBottom = ih->data->current_plot->mBack.mMargin.mBottom;
if (ih->data->current_plot->mRedraw)
plot0->mRedraw = true;
}
/* all the plots get the same margin */
for (p = 1; p < ih->data->plot_list_count; p++)
{
iupPlotSetPlotCurrent(ih, p);
ih->data->current_plot->mBack.mMargin.mLeft = plot0->mBack.mMargin.mLeft;
ih->data->current_plot->mBack.mMargin.mRight = plot0->mBack.mMargin.mRight;
ih->data->current_plot->mBack.mMargin.mTop = plot0->mBack.mMargin.mTop;
ih->data->current_plot->mBack.mMargin.mBottom = plot0->mBack.mMargin.mBottom;
ih->data->current_plot->mBack.mTransparent = true;
if (plot0->mRedraw)
ih->data->current_plot->mRedraw = true;
}
}
for (p = 0; p < ih->data->plot_list_count; p++)
{
iupPlotSetPlotCurrent(ih, p);
ih->data->current_plot->Render(ih->data->cd_canvas);
}
iupPlotSetPlotCurrent(ih, old_current);
}
// Do the flush once
if (flush)
cdCanvasFlush(ih->data->cd_canvas);
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
IupGLSwapBuffers(ih);
}
static int iPlotAction_CB(Ihandle* ih)
{
// in the redraw callback
int flush = 1, // always flush
only_current = 0, // redraw all plots
reset_redraw = 0; // render only if necessary
iupPlotRedraw(ih, flush, only_current, reset_redraw);
return IUP_DEFAULT;
}
void iupPlotUpdateViewports(Ihandle* ih)
{
int w, h;
cdCanvasActivate(ih->data->cd_canvas);
cdCanvasGetSize(ih->data->cd_canvas, &w, &h, NULL, NULL);
int numcol = ih->data->numcol;
if (numcol > ih->data->plot_list_count) numcol = ih->data->plot_list_count;
int numlin = ih->data->plot_list_count / numcol;
int pw = w / numcol;
int ph = h / numlin;
for (int p = 0; p < ih->data->plot_list_count; p++)
{
int lin = p / numcol;
int col = p % numcol;
int px = col * pw;
int py = lin * ph;
if (ih->data->merge_view) /* ignore computed values */
{
px = 0;
py = 0;
pw = w;
ph = h;
}
ih->data->plot_list[p]->SetViewport(px, py, pw, ph);
}
}
static int iPlotResize_CB(Ihandle* ih, int width, int height)
{
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
{
IupGLMakeCurrent(ih);
double res = IupGetDouble(NULL, "SCREENDPI") / 25.4;
cdCanvasSetfAttribute(ih->data->cd_canvas, "SIZE", "%dx%d %g", width, height, res);
}
iupPlotUpdateViewports(ih);
return IUP_DEFAULT;
}
static void iPlotRedrawInteract(Ihandle *ih)
{
// when interacting
int flush = 0, // flush if necessary
only_current = 1,
reset_redraw = 0; // render only if necessary
if (ih->data->current_plot->mRedraw)
flush = 1;
iupPlotRedraw(ih, flush, only_current, reset_redraw);
}
void iupPlotResetZoom(Ihandle *ih, int redraw)
{
ih->data->current_plot->ResetZoom();
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
ih->data->plot_list[p]->ResetZoom();
}
}
if (redraw)
iPlotRedrawInteract(ih);
}
static void iPlotPanStart(Ihandle *ih)
{
ih->data->current_plot->PanStart();
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
ih->data->plot_list[p]->PanStart();
}
}
}
static void iPlotPan(Ihandle *ih, int x1, int y1, int x2, int y2)
{
double rx1, ry1, rx2, ry2;
ih->data->current_plot->TransformBack(x1, y1, rx1, ry1);
ih->data->current_plot->TransformBack(x2, y2, rx2, ry2);
double offsetX = rx2 - rx1;
double offsetY = ry2 - ry1;
ih->data->current_plot->Pan(offsetX, offsetY);
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
{
ih->data->plot_list[p]->TransformBack(x1, y1, rx1, ry1);
ih->data->plot_list[p]->TransformBack(x2, y2, rx2, ry2);
offsetX = rx2 - rx1;
offsetY = ry2 - ry1;
ih->data->plot_list[p]->Pan(offsetX, offsetY);
}
}
}
iPlotRedrawInteract(ih);
}
static void iPlotZoom(Ihandle *ih, int x, int y, float delta)
{
double rx, ry;
ih->data->current_plot->TransformBack(x, y, rx, ry);
if (delta > 0)
ih->data->current_plot->ZoomIn(rx, ry);
else
ih->data->current_plot->ZoomOut(rx, ry);
if (ih->data->sync_view)
{
for (int p = 0; p<ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
{
ih->data->plot_list[p]->TransformBack(x, y, rx, ry);
if (delta > 0)
ih->data->plot_list[p]->ZoomIn(rx, ry);
else
ih->data->plot_list[p]->ZoomOut(rx, ry);
}
}
}
iPlotRedrawInteract(ih);
}
void iupPlotSetZoom(Ihandle *ih, int dir)
{
if (dir > 0)
{
int x = ih->data->current_plot->mViewport.mWidth / 2;
int y = ih->data->current_plot->mViewport.mHeight / 2;
iPlotZoom(ih, x, y, 1);
}
else if (dir < 0)
{
int x = ih->data->current_plot->mViewport.mWidth / 2;
int y = ih->data->current_plot->mViewport.mHeight / 2;
iPlotZoom(ih, x, y, -1);
}
else
iupPlotResetZoom(ih, 1);
}
static void iPlotZoomTo(Ihandle *ih, int x1, int y1, int x2, int y2)
{
double rx1, ry1, rx2, ry2;
ih->data->current_plot->TransformBack(x1, y1, rx1, ry1);
ih->data->current_plot->TransformBack(x2, y2, rx2, ry2);
ih->data->current_plot->ZoomTo(rx1, rx2, ry1, ry2);
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
{
ih->data->plot_list[p]->TransformBack(x1, y1, rx1, ry1);
ih->data->plot_list[p]->TransformBack(x2, y2, rx2, ry2);
ih->data->plot_list[p]->ZoomTo(rx1, rx2, ry1, ry2);
}
}
}
iPlotRedrawInteract(ih);
}
static void iPlotScroll(Ihandle *ih, float delta, bool full_page, bool vertical)
{
ih->data->current_plot->Scroll(delta, full_page, vertical);
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
ih->data->plot_list[p]->Scroll(delta, full_page, vertical);
}
}
iPlotRedrawInteract(ih);
}
static void iPlotScrollTo(Ihandle *ih, int x, int y)
{
double rx, ry;
ih->data->current_plot->TransformBack(x, y, rx, ry);
ih->data->current_plot->ScrollTo(rx, ry);
if (ih->data->sync_view)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p] != ih->data->current_plot)
{
ih->data->plot_list[p]->TransformBack(x, y, rx, ry);
ih->data->plot_list[p]->ScrollTo(rx, ry);
}
}
}
iPlotRedrawInteract(ih);
}
static int iPlotFindPlot(Ihandle* ih, int x, int &y, char* status)
{
int w, h;
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
IupGLMakeCurrent(ih);
cdCanvasActivate(ih->data->cd_canvas);
cdCanvasGetSize(ih->data->cd_canvas, &w, &h, NULL, NULL);
// Notice that this change is returned to the callback
cdCanvasOrigin(ih->data->cd_canvas, 0, 0);
y = cdCanvasInvertYAxis(ih->data->cd_canvas, y);
if (ih->data->plot_list_count == 1)
return 0;
if (ih->data->merge_view)
{
if (ih->data->plot_list_count > 1 && iup_isshift(status))
return 1;
if (ih->data->plot_list_count > 2 && iup_iscontrol(status))
return 2;
if (ih->data->plot_list_count > 3 && iup_isalt(status))
return 3;
return 0;
}
int numcol = ih->data->numcol;
if (numcol > ih->data->plot_list_count) numcol = ih->data->plot_list_count;
int numlin = ih->data->plot_list_count / numcol;
int pw = w / numcol;
int ph = h / numlin;
int lin = y / ph;
int col = x / pw;
int index = lin * numcol + col;
if (index < ih->data->plot_list_count)
return index;
return -1;
}
static int iPlotButton_CB(Ihandle* ih, int button, int press, int x, int y, char* status)
{
int screen_x = x, screen_y = y;
int index = iPlotFindPlot(ih, x, y, status);
if (index < 0)
{
iPlotRedrawInteract(ih);
return IUP_DEFAULT;
}
iupPlotSetPlotCurrent(ih, index);
if (ih->data->current_plot->mDataSetListCount == 0)
return IUP_DEFAULT;
x -= ih->data->current_plot->mViewport.mX;
y -= ih->data->current_plot->mViewport.mY;
IFniidds cb = (IFniidds)IupGetCallback(ih, "PLOTBUTTON_CB");
if (cb)
{
cdCanvasOrigin(ih->data->cd_canvas, ih->data->current_plot->mViewport.mX, ih->data->current_plot->mViewport.mY);
double rx, ry;
ih->data->current_plot->TransformBack(x, y, rx, ry);
if (cb(ih, button, press, rx, ry, status) == IUP_IGNORE)
return IUP_DEFAULT;
}
ih->data->last_pos_moving = 0;
if (press)
{
ih->data->last_click_x = x;
ih->data->last_click_y = y;
ih->data->last_click_plot = index;
if (button == IUP_BUTTON1)
{
if (!iup_iscontrol(status))
{
if (iup_isdouble(status))
iupPlotResetZoom(ih, 1);
else
{
if (!ih->data->current_plot->mTitle.mAutoPos &&
ih->data->current_plot->CheckInsideTitle(ih->data->cd_canvas, x, y))
{
ih->data->last_pos_x = ih->data->current_plot->mTitle.mPosX;
ih->data->last_pos_y = ih->data->current_plot->mTitle.mPosY;
ih->data->last_pos_moving = 1;
}
else if (ih->data->current_plot->mLegend.mPosition == IUP_PLOT_XY &&
ih->data->current_plot->CheckInsideLegend(x, y))
{
ih->data->last_pos_x = ih->data->current_plot->mLegend.mPos.mX;
ih->data->last_pos_y = ih->data->current_plot->mLegend.mPos.mY;
ih->data->last_pos_moving = 2;
}
else
iPlotPanStart(ih);
}
}
}
else if (button == IUP_BUTTON2)
{
if (!iup_iscontrol(status))
iPlotScrollTo(ih, x, y);
}
else if (button == IUP_BUTTON3 && !iup_iscontrol(status) && !iup_isshift(status) && IupGetInt(ih, "MENUCONTEXT"))
{
int sx, sy;
IupGetIntInt(ih, "SCREENPOSITION", &sx, &sy);
screen_x += sx;
screen_y += sy;
iupPlotShowMenuContext(ih, screen_x, screen_y, x, y);
}
}
else
{
if (iup_iscontrol(status))
{
if (ih->data->last_click_x == x && ih->data->last_click_y == y && ih->data->last_click_plot == index)
{
float delta = 0;
if (button == IUP_BUTTON1)
delta = 1.0;
else if (button == IUP_BUTTON3)
delta = -1.0;
if (delta)
iPlotZoom(ih, x, y, delta);
}
else if (button == IUP_BUTTON1 && ih->data->last_click_x != x && ih->data->last_click_y != y && ih->data->last_click_plot == index)
{
iPlotZoomTo(ih, ih->data->last_click_x, ih->data->last_click_y, x, y);
}
}
else if (button == IUP_BUTTON1 && iup_isshift(status))
{
double rx1, ry1, rx2, ry2;
ih->data->current_plot->TransformBack(ih->data->last_click_x, ih->data->last_click_y, rx1, ry1);
ih->data->current_plot->TransformBack(x, y, rx2, ry2);
ih->data->current_plot->SelectDataSetSamples(rx1, rx2, ry1, ry2);
iPlotRedrawInteract(ih);
}
if (!iup_iscontrol(status) && ih->data->last_click_x == x && ih->data->last_click_y == y && ih->data->last_click_plot == index)
{
int ds, sample1, sample2;
double rx1, ry1, rx2, ry2;
const char* ds_name;
const char* strX;
IFniiddi clicksample_cb = (IFniiddi)IupGetCallback(ih, "CLICKSAMPLE_CB");
IFniiddiddi clicksegment_cb = (IFniiddiddi)IupGetCallback(ih, "CLICKSEGMENT_CB");
if (clicksample_cb && ih->data->current_plot->FindDataSetSample((double)x, (double)y, ds, ds_name, sample1, rx1, ry1, strX))
clicksample_cb(ih, ds, sample1, rx1, ry1, button);
else if (clicksegment_cb && ih->data->current_plot->FindDataSetSegment((double)x, (double)y, ds, ds_name, sample1, rx1, ry1, sample2, rx2, ry2))
clicksegment_cb(ih, ds, sample1, rx1, ry1, sample2, rx2, ry2, button);
}
}
return IUP_DEFAULT;
}
static int iPlotMotion_CB(Ihandle* ih, int x, int y, char *status)
{
if (iupStrEqualNoCase(IupGetAttribute(ih, "CURSOR"), "HAND"))
IupSetAttribute(ih, "CURSOR", NULL);
int index = iPlotFindPlot(ih, x, y, status);
if (index < 0)
return IUP_DEFAULT;
iupPlotSetPlotCurrent(ih, index);
if (ih->data->current_plot->mDataSetListCount == 0)
return IUP_DEFAULT;
x -= ih->data->current_plot->mViewport.mX;
y -= ih->data->current_plot->mViewport.mY;
//////////// PLOTMOTION_CB
IFndds cb = (IFndds)IupGetCallback(ih, "PLOTMOTION_CB");
if (cb)
{
cdCanvasOrigin(ih->data->cd_canvas, ih->data->current_plot->mViewport.mX, ih->data->current_plot->mViewport.mY);
double rx, ry;
ih->data->current_plot->TransformBack(x, y, rx, ry);
if (cb(ih, rx, ry, status) == IUP_IGNORE)
return IUP_DEFAULT;
}
/////////////// CURSOR
if (!ih->data->current_plot->mTitle.mAutoPos &&
ih->data->current_plot->CheckInsideTitle(ih->data->cd_canvas, x, y))
IupSetAttribute(ih, "CURSOR", "HAND");
else if (ih->data->current_plot->mLegend.mPosition == IUP_PLOT_XY &&
ih->data->current_plot->CheckInsideLegend(x, y))
IupSetAttribute(ih, "CURSOR", "HAND");
/////////////// SELECTION, TITLE MOVE and LEGEND MOVE
if (iup_isbutton1(status) && ih->data->last_click_plot == index)
{
if (iup_iscontrol(status) || iup_isshift(status))
{
ih->data->current_plot->mRedraw = true;
ih->data->current_plot->mShowSelectionBand = true;
ih->data->current_plot->mSelectionBand.mX = ih->data->last_click_x < x ? ih->data->last_click_x : x;
ih->data->current_plot->mSelectionBand.mY = ih->data->last_click_y < y ? ih->data->last_click_y : y;
ih->data->current_plot->mSelectionBand.mWidth = abs(ih->data->last_click_x - x) + 1;
ih->data->current_plot->mSelectionBand.mHeight = abs(ih->data->last_click_y - y) + 1;
iPlotRedrawInteract(ih);
ih->data->current_plot->mShowSelectionBand = false;
return IUP_DEFAULT;
}
else
{
if (ih->data->last_click_x != x || ih->data->last_click_y != y)
{
if (!ih->data->current_plot->mTitle.mAutoPos && ih->data->last_pos_moving == 1)
{
ih->data->current_plot->mTitle.mPosX = ih->data->last_pos_x + (x - ih->data->last_click_x);
ih->data->current_plot->mTitle.mPosY = ih->data->last_pos_y + (y - ih->data->last_click_y);
ih->data->current_plot->mRedraw = true;
iPlotRedrawInteract(ih);
return IUP_DEFAULT;
}
if (ih->data->current_plot->mLegend.mPosition == IUP_PLOT_XY && ih->data->last_pos_moving == 2)
{
ih->data->current_plot->mLegend.mPos.mX = ih->data->last_pos_x + (x - ih->data->last_click_x);
ih->data->current_plot->mLegend.mPos.mY = ih->data->last_pos_y + (y - ih->data->last_click_y);
ih->data->current_plot->mRedraw = true;
iPlotRedrawInteract(ih);
return IUP_DEFAULT;
}
iPlotPan(ih, ih->data->last_click_x, ih->data->last_click_y, x, y);
return IUP_DEFAULT;
}
}
}
/////////////// SAMPLE TIPS and HIGHLIGHT
bool changed = false;
bool found = false;
bool redraw = false;
int ds, sample, sample1, sample2;
double rx, ry, rx1, ry1, rx2, ry2;
const char* ds_name;
const char* strX;
if (ih->data->current_plot->FindDataSetSample((double)x, (double)y, ds, ds_name, sample, rx, ry, strX))
{
found = true;
if (ih->data->last_cursor_plot != index ||
ih->data->last_cursor_ds != ds ||
ih->data->last_cursor_sample != sample)
{
char* tipformat = iupAttribGetStr(ih, "TIPFORMAT");
char str_Y[100];
iupStrPrintfDoubleLocale(str_Y, ih->data->current_plot->mAxisY.mTipFormatString, ry, IupGetGlobal("DEFAULTDECIMALSYMBOL"));
if (strX)
IupSetfAttribute(ih, "TIP", tipformat, ds_name, strX, str_Y);
else
{
char str_X[100];
iupStrPrintfDoubleLocale(str_X, ih->data->current_plot->mAxisX.mTipFormatString, rx, IupGetGlobal("DEFAULTDECIMALSYMBOL"));
IupSetfAttribute(ih, "TIP", tipformat, ds_name, str_X, str_Y);
}
IupSetAttribute(ih, "TIPVISIBLE", "Yes");
ih->data->last_cursor_plot = index;
ih->data->last_cursor_ds = ds;
ih->data->last_cursor_sample = sample;
changed = true;
}
}
else
{
if (ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_CURVE || ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_BOTH)
{
if (ih->data->current_plot->FindDataSetSegment((double)x, (double)y, ds, ds_name, sample1, rx1, ry1, sample2, rx2, ry2))
{
found = true;
if (ih->data->last_cursor_plot != index ||
ih->data->last_cursor_ds != ds ||
ih->data->last_cursor_sample != -1)
{
ih->data->last_cursor_plot = index;
ih->data->last_cursor_ds = ds;
ih->data->last_cursor_sample = -1;
changed = true;
}
}
}
}
if (ih->data->last_cursor_plot != -1 &&
ih->data->last_cursor_ds != -1)
{
if ((!found || changed) && ih->data->current_plot->mHighlightMode != IUP_PLOT_HIGHLIGHT_NONE)
{
redraw = true;
ih->data->plot_list[ih->data->last_cursor_plot]->ClearHighlight();
}
if (!found)
{
ih->data->last_cursor_plot = -1;
ih->data->last_cursor_ds = -1;
ih->data->last_cursor_sample = -1;
IupSetAttribute(ih, "TIP", NULL);
IupSetAttribute(ih, "TIPVISIBLE", "Yes");
}
else if (changed)
{
if (ih->data->current_plot->mHighlightMode != IUP_PLOT_HIGHLIGHT_NONE)
{
redraw = true;
if (ih->data->last_cursor_sample != -1)
{
// priority for sample highlight when sample is found
if (ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_SAMPLE ||
ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_BOTH)
ih->data->current_plot->mDataSetList[ih->data->last_cursor_ds]->mHighlightedSample = ih->data->last_cursor_sample;
// highlight a curve
if (ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_CURVE)
ih->data->current_plot->mDataSetList[ih->data->last_cursor_ds]->mHighlightedCurve = true;
}
else
{
// highlight a curve
if (ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_CURVE ||
ih->data->current_plot->mHighlightMode == IUP_PLOT_HIGHLIGHT_BOTH)
ih->data->current_plot->mDataSetList[ih->data->last_cursor_ds]->mHighlightedCurve = true;
}
}
}
}
if (ih->data->show_cross_hair)
{
redraw = true;
if (ih->data->show_cross_hair == IUP_PLOT_CROSSHAIR_HORIZ)
{
ih->data->current_plot->mCrossHairH = true;
ih->data->current_plot->mCrossHairX = x;
}
else
{
ih->data->current_plot->mCrossHairV = true;
ih->data->current_plot->mCrossHairY = y;
}
}
if (redraw)
{
ih->data->current_plot->mRedraw = true;
iPlotRedrawInteract(ih);
}
return IUP_DEFAULT;
}
static int iPlotWheel_CB(Ihandle *ih, float delta, int x, int y, char* status)
{
int index = iPlotFindPlot(ih, x, y, status);
if (index < 0)
return IUP_DEFAULT;
iupPlotSetPlotCurrent(ih, index);
if (ih->data->current_plot->mDataSetListCount == 0)
return IUP_DEFAULT;
x -= ih->data->current_plot->mViewport.mX;
y -= ih->data->current_plot->mViewport.mY;
if (iup_iscontrol(status))
iPlotZoom(ih, x, y, delta);
else
{
bool vertical = true;
if (iup_isshift(status))
vertical = false;
iPlotScroll(ih, delta, false, vertical);
}
return IUP_DEFAULT;
}
static int iPlotKeyPress_CB(Ihandle* ih, int c, int press)
{
if (!press)
return IUP_DEFAULT;
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
IupGLMakeCurrent(ih);
if (c == K_cH || c == K_cV)
{
int new_show_cross_hair = IUP_PLOT_CROSSHAIR_HORIZ;
if (c == K_cV) new_show_cross_hair = IUP_PLOT_CROSSHAIR_VERT;
if (ih->data->show_cross_hair == new_show_cross_hair)
ih->data->show_cross_hair = IUP_PLOT_CROSSHAIR_NONE;
else
ih->data->show_cross_hair = new_show_cross_hair;
for (int p = 0; p < ih->data->plot_list_count; p++)
{
if (ih->data->plot_list[p]->mCrossHairH)
{
ih->data->plot_list[p]->mRedraw = true;
ih->data->plot_list[p]->mCrossHairH = false;
}
if (ih->data->plot_list[p]->mCrossHairV)
{
ih->data->plot_list[p]->mRedraw = true;
ih->data->plot_list[p]->mCrossHairV = false;
}
}
if (ih->data->show_cross_hair != IUP_PLOT_CROSSHAIR_NONE) // was shown, leave it there as reference
iPlotRedrawInteract(ih);
return IUP_IGNORE; /* ignore processed keys */
}
if (ih->data->current_plot->mDataSetListCount == 0)
return IUP_DEFAULT;
if (c == K_plus)
{
int x = ih->data->current_plot->mViewport.mWidth / 2;
int y = ih->data->current_plot->mViewport.mHeight / 2;
iPlotZoom(ih, x, y, 1);
return IUP_IGNORE; /* ignore processed keys */
}
else if (c == K_minus)
{
int x = ih->data->current_plot->mViewport.mWidth / 2;
int y = ih->data->current_plot->mViewport.mHeight / 2;
iPlotZoom(ih, x, y, -1);
return IUP_IGNORE; /* ignore processed keys */
}
else if (c == K_period)
{
iupPlotResetZoom(ih, 1);
return IUP_IGNORE; /* ignore processed keys */
}
else if (c == K_LEFT || c == K_RIGHT)
{
float delta = 1.0f;
if (c == K_LEFT) delta = -1.0f;
iPlotScroll(ih, delta, false, false);
return IUP_IGNORE; /* ignore processed keys */
}
else if (c == K_UP || c == K_DOWN || c == K_PGUP || c == K_PGDN)
{
float delta = 1.0f;
if (c == K_DOWN || c == K_PGDN) delta = -1.0f;
bool full_page = false;
if (c == K_PGUP || c == K_PGDN) full_page = true;
iPlotScroll(ih, delta, full_page, true);
return IUP_IGNORE; /* ignore processed keys */
}
else if (c == K_DEL)
{
if (!ih->data->read_only)
{
ih->data->current_plot->DeleteSelectedDataSetSamples();
iPlotRedrawInteract(ih);
return IUP_IGNORE; /* ignore processed keys */
}
}
else if (c == K_ESC)
{
ih->data->current_plot->ClearDataSetSelection();
iPlotRedrawInteract(ih);
return IUP_IGNORE; /* ignore processed keys */
}
return IUP_DEFAULT;
}
/************************************************************************************/
void IupPlotBegin(Ihandle* ih, int strXdata)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
if (theDataSet)
delete theDataSet;
theDataSet = new iupPlotDataSet(strXdata ? true : false);
iupAttribSet(ih, "_IUP_PLOT_DATASET", (char*)theDataSet);
}
void IupPlotAdd(Ihandle* ih, double x, double y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
theDataSet->AddSample(x, y);
}
void IupPlotAddStr(Ihandle* ih, const char* x, double y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
theDataSet->AddSample(x, y);
}
void IupPlotAddSegment(Ihandle* ih, double x, double y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
theDataSet->AddSampleSegment(x, y, true);
}
int IupPlotEnd(Ihandle* ih)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return -1;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return -1;
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
if (!theDataSet)
return -1;
ih->data->current_plot->AddDataSet(theDataSet);
iupAttribSet(ih, "_IUP_PLOT_DATASET", NULL);
ih->data->current_plot->mRedraw = true;
return ih->data->current_plot->mCurrentDataSet;
}
void IupPlotInsert(Ihandle* ih, int inIndex, int inSampleIndex, double inX, double inY)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->InsertSample(inSampleIndex, inX, inY);
}
void IupPlotInsertStr(Ihandle* ih, int inIndex, int inSampleIndex, const char* inX, double inY)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->InsertSample(inSampleIndex, inX, inY);
}
void IupPlotInsertSegment(Ihandle* ih, int inIndex, int inSampleIndex, double inX, double inY)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->InsertSampleSegment(inSampleIndex, inX, inY, true);
}
void IupPlotAddSamples(Ihandle* ih, int inIndex, double *x, double *y, int count)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
for (int i = 0; i < count; i++)
theDataSet->AddSample(x[i], y[i]);
}
void IupPlotAddStrSamples(Ihandle* ih, int inIndex, const char** x, double* y, int count)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
for (int i = 0; i < count; i++)
theDataSet->AddSample(x[i], y[i]);
}
void IupPlotInsertStrSamples(Ihandle* ih, int inIndex, int inSampleIndex, const char** inX, double* inY, int count)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
for (int i = 0; i < count; i++)
theDataSet->InsertSample(inSampleIndex + i, inX[i], inY[i]);
}
void IupPlotInsertSamples(Ihandle* ih, int inIndex, int inSampleIndex, double *inX, double *inY, int count)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
for (int i = 0; i < count; i++)
theDataSet->InsertSample(inSampleIndex + i, inX[i], inY[i]);
}
void IupPlotGetSample(Ihandle* ih, int inIndex, int inSampleIndex, double *x, double *y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->GetSample(inSampleIndex, x, y);
}
void IupPlotGetSampleStr(Ihandle* ih, int inIndex, int inSampleIndex, const char* *x, double *y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->GetSample(inSampleIndex, x, y);
}
int IupPlotGetSampleSelection(Ihandle* ih, int inIndex, int inSampleIndex)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return -1;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return -1;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return -1;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
int theCount = theDataSet->GetCount();
if (inSampleIndex < 0 || inSampleIndex >= theCount)
return -1;
return theDataSet->GetSampleSelection(inSampleIndex);
}
double IupPlotGetSampleExtra(Ihandle* ih, int inIndex, int inSampleIndex)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return -1;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return -1;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return -1;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
int theCount = theDataSet->GetCount();
if (inSampleIndex < 0 || inSampleIndex >= theCount)
return -1;
return theDataSet->GetSampleExtra(inSampleIndex);
}
void IupPlotSetSample(Ihandle* ih, int inIndex, int inSampleIndex, double x, double y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->SetSample(inSampleIndex, x, y);
}
void IupPlotSetSampleStr(Ihandle* ih, int inIndex, int inSampleIndex, const char* x, double y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
theDataSet->SetSample(inSampleIndex, x, y);
}
void IupPlotSetSampleSelection(Ihandle* ih, int inIndex, int inSampleIndex, int inSelected)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
int theCount = theDataSet->GetCount();
if (inSampleIndex < 0 || inSampleIndex >= theCount)
return;
return theDataSet->SetSampleSelection(inSampleIndex, inSelected ? true : false);
}
void IupPlotSetSampleExtra(Ihandle* ih, int inIndex, int inSampleIndex, double inExtra)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (inIndex < 0 || inIndex >= ih->data->current_plot->mDataSetListCount)
return;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[inIndex];
int theCount = theDataSet->GetCount();
if (inSampleIndex < 0 || inSampleIndex >= theCount)
return;
return theDataSet->SetSampleExtra(inSampleIndex, inExtra);
}
void IupPlotTransform(Ihandle* ih, double x, double y, double *cnv_x, double *cnv_y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (cnv_x) *cnv_x = ih->data->current_plot->mAxisX.mTrafo->Transform(x);
if (cnv_y) *cnv_y = ih->data->current_plot->mAxisY.mTrafo->Transform(y);
}
void IupPlotTransformTo(Ihandle* ih, double cnv_x, double cnv_y, double *x, double *y)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (x) *x = ih->data->current_plot->mAxisX.mTrafo->TransformBack(cnv_x);
if (y) *y = ih->data->current_plot->mAxisY.mTrafo->TransformBack(cnv_y);
}
void IupPlotPaintTo(Ihandle* ih, cdCanvas* cnv)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return;
if (!cnv)
return;
cdCanvas *old_cd_canvas = ih->data->cd_canvas;
ih->data->cd_canvas = (cdCanvas*)cnv;
iupPlotUpdateViewports(ih);
// when drawing to an external canvas
int flush = 0, // never flush
only_current = 0, // draw all plots
reset_redraw = 1; // always render
iupPlotRedraw(ih, flush, only_current, reset_redraw);
ih->data->cd_canvas = old_cd_canvas;
iupPlotUpdateViewports(ih);
}
static const char* iPlotSkipValue(const char* line_buffer)
{
// fix next separator
char ch = *line_buffer;
while (ch != ' ' && ch != '\t' && ch != ';' && ch != 0)
{
line_buffer++;
ch = *line_buffer;
}
// skip separators
while ((ch == ' ' || ch == '\t' || ch == ';') && ch != 0)
{
line_buffer++;
ch = *line_buffer;
}
return line_buffer;
}
static int iPlotCountDataSets(const char* line_buffer)
{
int ds_count = 0;
while (*line_buffer != 0)
{
line_buffer = iPlotSkipValue(line_buffer);
ds_count++;
}
return ds_count;
}
static int iPlotAddToDataSets(Ihandle* ih, const char* line_buffer, int ds_start, int ds_count)
{
double x = 0;
double value;
for (int ds = 0; ds < ds_count; ds++)
{
int ret = sscanf(line_buffer, "%lf", &value);
if (!ret)
return 0;
line_buffer = iPlotSkipValue(line_buffer);
if (ds == 0)
x = value;
else
{
double y = value;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[ds_start + ds - 1];
theDataSet->AddSample(x, y);
}
}
return 1;
}
static int iPlotAddToDataSetsStrX(Ihandle* ih, const char* line_buffer, int ds_start, int ds_count)
{
char x[100] = "";
double value = 0;
for (int ds = 0; ds < ds_count; ds++)
{
if (ds == 0)
{
int ret = sscanf(line_buffer, "%s", x);
if (!ret)
return 0;
}
else
{
int ret = sscanf(line_buffer, "%lf", &value);
if (!ret)
return 0;
}
line_buffer = iPlotSkipValue(line_buffer);
if (ds != 0)
{
double y = value;
iupPlotDataSet* theDataSet = ih->data->current_plot->mDataSetList[ds_start + ds - 1];
theDataSet->AddSample(x, y);
}
}
return 1;
}
static int iPlotLoadDataFile(Ihandle* ih, IlineFile* line_file, int strXdata)
{
int first_line = 1;
int ds_count = 0;
int ds, ds_start = ih->data->current_plot->mDataSetListCount;
do
{
int line_len = iupLineFileReadLine(line_file);
if (line_len == -1)
return 0;
const char* line_buffer = iupLineFileGetBuffer(line_file);
int i = 0;
while (line_buffer[i] == ' ') /* ignore spaces at start */
i++;
if (line_buffer[i] == 0) /* skip empty line */
continue;
if (line_buffer[i] == '#') /* "#" signifies a comment line when used as the first non-space character on a line */
continue;
if (first_line)
{
ds_count = iPlotCountDataSets(line_buffer);
if (ds_count < 2) // must have at least X and Y1, could have Y2, Y3, ...
return 0;
for (ds = 0; ds < ds_count - 1; ds++)
{
iupPlotDataSet* theDataSet = new iupPlotDataSet(strXdata ? true : false);
ih->data->current_plot->AddDataSet(theDataSet);
}
first_line = 0;
}
if (strXdata)
{
if (!iPlotAddToDataSetsStrX(ih, line_buffer + i, ds_start, ds_count))
return 0;
}
else
{
if (!iPlotAddToDataSets(ih, line_buffer + i, ds_start, ds_count))
return 0;
}
} while (!iupLineFileEOF(line_file));
return 1;
}
int IupPlotLoadData(Ihandle* ih, const char* filename, int strXdata)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return 0;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return 0;
if (!filename)
return 0;
IlineFile* line_file = iupLineFileOpen(filename);
if (!line_file)
return 0;
int error = iPlotLoadDataFile(ih, line_file, strXdata);
iupLineFileClose(line_file);
return error;
}
int IupPlotFindSample(Ihandle* ih, double cnv_x, double cnv_y, int *ds_index, int *sample_index)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return 0;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return 0;
int ds, sample;
double rx, ry;
const char* ds_name;
const char* strX;
if (ih->data->current_plot->FindDataSetSample(cnv_x, cnv_y, ds, ds_name, sample, rx, ry, strX))
{
if (ds_index) *ds_index = ds;
if (sample_index) *sample_index = sample;
return 1;
}
return 0;
}
int IupPlotFindSegment(Ihandle* ih, double cnv_x, double cnv_y, int *ds_index, int *sample_index1, int *sample_index2)
{
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return 0;
if (ih->iclass->nativetype != IUP_TYPECANVAS ||
!IupClassMatch(ih, "plot"))
return 0;
int ds, sample1, sample2;
double rx1, ry1;
double rx2, ry2;
const char* ds_name;
if (ih->data->current_plot->FindDataSetSegment(cnv_x, cnv_y, ds, ds_name, sample1, rx1, ry1, sample2, rx2, ry2))
{
if (ds_index) *ds_index = ds;
if (sample_index1) *sample_index1 = sample1;
if (sample_index2) *sample_index2 = sample2;
return 1;
}
return 0;
}
/************************************************************************************/
static int iPlotMapMethod(Ihandle* ih)
{
if (ih->data->graphics_mode == IUP_PLOT_OPENGL)
{
IupGLMakeCurrent(ih);
double res = IupGetDouble(NULL, "SCREENDPI") / 25.4;
ih->data->cd_canvas = cdCreateCanvasf(CD_GL, "10x10 %g", res);
}
else if (ih->data->graphics_mode == IUP_PLOT_IMAGERGB)
ih->data->cd_canvas = cdCreateCanvas(CD_IUPDBUFFERRGB, ih);
else if (ih->data->graphics_mode == IUP_PLOT_NATIVEPLUS)
{
int old_plus = cdUseContextPlus(1);
ih->data->cd_canvas = cdCreateCanvas(CD_IUPDBUFFER, ih);
cdUseContextPlus(old_plus);
}
else
ih->data->cd_canvas = cdCreateCanvas(CD_IUPDBUFFER, ih);
if (!ih->data->cd_canvas)
return IUP_ERROR;
for (int p = 0; p < ih->data->plot_list_count; p++)
ih->data->plot_list[p]->mRedraw = true;
iupPlotUpdateViewports(ih);
return IUP_NOERROR;
}
static void iPlotUnMapMethod(Ihandle* ih)
{
if (ih->data->cd_canvas != NULL)
{
cdKillCanvas(ih->data->cd_canvas);
ih->data->cd_canvas = NULL;
}
}
static void iPlotDestroyMethod(Ihandle* ih)
{
for (int p = 0; p < ih->data->plot_list_count; p++)
delete ih->data->plot_list[p];
iupPlotDataSet* theDataSet = (iupPlotDataSet*)iupAttribGet(ih, "_IUP_PLOT_DATASET");
if (theDataSet)
delete theDataSet;
}
static int iPlotCreateMethod(Ihandle* ih, void **params)
{
(void)params;
/* free the data allocated by IupCanvas */
free(ih->data);
ih->data = iupALLOCCTRLDATA();
ih->data->read_only = 1;
ih->data->plot_list_count = 1;
ih->data->numcol = 1;
ih->data->last_cursor_ds = -1;
ih->data->last_cursor_sample = -1;
ih->data->last_cursor_plot = -1;
ih->data->last_click_plot = -1;
ih->data->graphics_mode = IUP_PLOT_NATIVEPLUS;
ih->data->plot_list[0] = new iupPlot(ih, 0, 0); // font style/size will be initialized by font initialization
ih->data->current_plot = ih->data->plot_list[ih->data->current_plot_index];
/* IupCanvas callbacks */
IupSetCallback(ih, "ACTION", (Icallback)iPlotAction_CB);
IupSetCallback(ih, "RESIZE_CB", (Icallback)iPlotResize_CB);
IupSetCallback(ih, "BUTTON_CB", (Icallback)iPlotButton_CB);
IupSetCallback(ih, "MOTION_CB", (Icallback)iPlotMotion_CB);
IupSetCallback(ih, "WHEEL_CB", (Icallback)iPlotWheel_CB);
IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iPlotKeyPress_CB);
return IUP_NOERROR;
}
#include "iup_lng_english_plot.h"
#include "iup_lng_portuguese_plot.h"
#include "iup_lng_portuguese_plot_utf8.h"
#include "iup_lng_spanish_plot.h"
#include "iup_lng_spanish_plot_utf8.h"
static void iPlotSetClassUpdate(Iclass* ic)
{
Ihandle* lng = NULL;
(void)ic;
if (iupStrEqualNoCase(IupGetGlobal("LANGUAGE"), "ENGLISH"))
{
lng = iup_load_lng_english_plot();
}
else if (iupStrEqualNoCase(IupGetGlobal("LANGUAGE"), "PORTUGUESE"))
{
if (IupGetInt(NULL, "UTF8MODE"))
lng = iup_load_lng_portuguese_plot_utf8();
else
lng = iup_load_lng_portuguese_plot();
}
else if (iupStrEqualNoCase(IupGetGlobal("LANGUAGE"), "SPANISH"))
{
if (IupGetInt(NULL, "UTF8MODE"))
lng = iup_load_lng_spanish_plot_utf8();
else
lng = iup_load_lng_spanish_plot();
}
if (lng)
{
IupSetLanguagePack(lng);
IupDestroy(lng);
}
}
static Iclass* iPlotNewClass(void)
{
Iclass* ic = iupClassNew(iupRegisterFindClass("glcanvas"));
ic->name = (char*)"plot";
ic->format = NULL; /* none */
ic->nativetype = IUP_TYPECANVAS;
ic->childtype = IUP_CHILDNONE;
ic->is_interactive = 1;
/* Class functions */
ic->New = iPlotNewClass;
ic->Create = iPlotCreateMethod;
ic->Destroy = iPlotDestroyMethod;
ic->Map = iPlotMapMethod;
ic->UnMap = iPlotUnMapMethod;
/* IupPlot Callbacks */
iupClassRegisterCallback(ic, "POSTDRAW_CB", "C");
iupClassRegisterCallback(ic, "PREDRAW_CB", "C");
iupClassRegisterCallback(ic, "CLICKSAMPLE_CB", "iiddi");
iupClassRegisterCallback(ic, "CLICKSEGMENT_CB", "iiddiddi");
iupClassRegisterCallback(ic, "DRAWSAMPLE_CB", "iiddi");
iupClassRegisterCallback(ic, "PLOTMOTION_CB", "dds");
iupClassRegisterCallback(ic, "PLOTBUTTON_CB", "iidds");
iupClassRegisterCallback(ic, "EDITSAMPLE_CB", "iidd");
iupClassRegisterCallback(ic, "DELETE_CB", "iidd");
iupClassRegisterCallback(ic, "DELETEBEGIN_CB", "");
iupClassRegisterCallback(ic, "DELETEEND_CB", "");
iupClassRegisterCallback(ic, "SELECT_CB", "iiddi");
iupClassRegisterCallback(ic, "SELECTBEGIN_CB", "");
iupClassRegisterCallback(ic, "SELECTEND_CB", "");
iupClassRegisterCallback(ic, "MENUCONTEXT_CB", "nii");
iupClassRegisterCallback(ic, "MENUCONTEXTCLOSE_CB", "nii");
iupClassRegisterCallback(ic, "PROPERTIESCHANGED_CB", "");
iupClassRegisterCallback(ic, "PROPERTIESVALIDATE_CB", "ss");
iupClassRegisterCallback(ic, "DSPROPERTIESCHANGED_CB", "i");
iupClassRegisterCallback(ic, "DSPROPERTIESVALIDATE_CB", "nni");
iupClassRegisterCallback(ic, "XTICKFORMATNUMBER_CB", "ssds");
iupClassRegisterCallback(ic, "YTICKFORMATNUMBER_CB", "ssds");
iupPlotRegisterAttributes(ic);
iupClassRegisterAttribute(ic, "CLASSUPDATE", NULL, (IattribSetFunc)iPlotSetClassUpdate, NULL, NULL, IUPAF_WRITEONLY | IUPAF_NO_INHERIT);
iPlotSetClassUpdate(ic);
return ic;
}
Ihandle* IupPlot(void)
{
return IupCreate("plot");
}
void IupPlotOpen(void)
{
if (!IupIsOpened())
return;
IupGLCanvasOpen();
#ifdef USE_CONTEXTPLUS
cdInitContextPlus();
#endif
if (!IupGetGlobal("_IUP_PLOT_OPEN"))
{
iupRegisterClass(iPlotNewClass());
IupSetGlobal("_IUP_PLOT_OPEN", "1");
}
}