/* * Proview Open Source Process Control. * Copyright (C) 2005-2017 SSAB EMEA AB. * * This file is part of Proview. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Proview. If not, see <http://www.gnu.org/licenses/> * * Linking Proview statically or dynamically with other modules is * making a combined work based on Proview. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. * * In addition, as a special exception, the copyright holders of * Proview give you permission to, from the build function in the * Proview Configurator, combine Proview with modules generated by the * Proview PLC Editor to a PLC program, regardless of the license * terms of these modules. You may copy and distribute the resulting * combined work under the terms of your choice, provided that every * copy of the combined work is accompanied by a complete copy of * the source code of Proview (the version used to produce the * combined work), being distributed under the terms of the GNU * General Public License plus this exception. **/ #include "glow_std.h" #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <math.h> #include <float.h> #include "rt_load.h" #include "flow.h" #include "flow_browctx.h" #include "flow_browapi.h" #include "glow.h" #include "glow_curvectx.h" #include "glow_growctx.h" #include "glow_curveapi.h" #include "glow_msg.h" #include "rt_gdh.h" #include "rt_gdh_msg.h" #include "co_cdh.h" #include "co_time.h" #include "co_dcli.h" #include "cow_wow.h" #include "co_lng.h" #include "co_cnf.h" #include "glow_growctx.h" #include "glow_growapi.h" #include "ge_curve.h" #include "ge_msg.h" #define MARK_WIDTH 2.0 void GeCurve::activate_exit() { if ( close_cb) (close_cb)( parent_ctx); else delete this; } void GeCurve::activate_configure() { configure_curves(); configure_axes(); } void GeCurve::activate_new() { if ( new_cb) (new_cb)( parent_ctx); } void GeCurve::activate_save() { if ( save_cb) (save_cb)( parent_ctx); } void GeCurve::activate_open() { if ( open_cb) (open_cb)( parent_ctx); } void GeCurve::activate_snapshot() { if ( snapshot_cb) (snapshot_cb)( parent_ctx); } void GeCurve::activate_export() { double ll_x, ll_y, ur_x, ur_y; pwr_tTime to = pwr_cNTime; pwr_tTime from = pwr_cNTime; double from_time, to_time; pwr_tFileName filename; // Get default file from proview.cnf if ( layout_mask & curve_mEnable_ExportTime) { if ( !cnf_get_value( "curveExportFile", filename, sizeof(filename))) strcpy( filename, "~/history_$date.txt"); } else { if ( !cnf_get_value( "curveExportFile", filename, sizeof(filename))) strcpy( filename, "~/fast_$date.txt"); } grow_MeasureWindow( growcurve_ctx, &ll_x, &ll_y, &ur_x, &ur_y); if ( !cd->x_reverse) { from_time = cd->x_min_value_axis[0] + ll_x * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; to_time = cd->x_min_value_axis[0] + ur_x * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; } else { from_time = cd->x_min_value_axis[0] + (200.0 - ll_x) * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; to_time = cd->x_min_value_axis[0] + (200.0 - ur_x) * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; } from.tv_sec = (pwr_tInt64) from_time; to.tv_sec = (pwr_tInt64) to_time; open_export( &from, &to, 1000, filename); } void GeCurve::activate_print() { pwr_tFileName fname; pwr_tCmd cmd; dcli_translate_filename( fname, "$pwrp_tmp/curve.ps"); print( fname); sprintf( cmd, "$pwr_exe/rt_print.sh %s 1", fname); system(cmd); } void GeCurve::activate_background() { if ( curve_color == background_dark) { curve_color = background_bright; curve_border = border_bright; } else { curve_color = background_dark; curve_border = border_dark; } grow_SetObjectFillColor( curve_object, curve_color); grow_SetObjectBorderColor( curve_object, curve_border); cd->select_color( curve_color == background_dark); configure_curves(); } void GeCurve::activate_filledcurves( int set) { if ( set) { grow_SetTrendFillCurve( curve_object, 1); configure_curves(); } else { grow_SetTrendFillCurve( curve_object, 0); configure_curves(); } grow_NavRedraw( growcurve_ctx); } void GeCurve::activate_curvetype( int type) { grow_SetCurveType( curve_object, (glow_eCurveType)type); configure_curves(); grow_NavRedraw( growcurve_ctx); } void GeCurve::activate_help() { if ( help_cb) (help_cb)( parent_ctx); } void GeCurve::activate_edit() { set_times_sensitivity( 1); } void GeCurve::activate_period( time_ePeriod period) { pwr_tTime from; pwr_tTime to; pwr_tTime center; double ll_x, ll_y, ur_x, ur_y; int low, high; if ( center_from_window) { // Get the center time measure_window( &ll_x, &ll_y, &ur_x, &ur_y); low = int( cd->x_min_value_axis[0] + ll_x / 200 * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0])); high = int( cd->x_min_value_axis[0] + ur_x / 200 * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0])); center_from_window = 0; } else { // Get period from current time intervall pwr_tStatus sts; pwr_tTime t_low, t_high; sts = get_times( &t_low, &t_high); if ( EVEN(sts)) { // No previous valid time time_Period( period, &from, &to, 0, 1); set_times_sensitivity( 0); set_times( &from, &to); return; } high = t_high.tv_sec; low = t_low.tv_sec; } center.tv_sec = low + (high - low)/2; center.tv_nsec = 0; time_Period( period, &from, &to, ¢er, 1); set_times_sensitivity( 0); set_times( &from, &to); } void GeCurve::activate_period_markers() { set_times_sensitivity( 0); set_times_markers(); } void GeCurve::set_times_markers() { if ( time_Acomp( &last_mark1_time, &last_mark2_time) == -1) set_times( &last_mark1_time, &last_mark2_time); else set_times( &last_mark2_time, &last_mark1_time); } void GeCurve::update_times_markers() { double x; double ll_x, ll_y, ur_x, ur_y; char str[40]; double time; double values[CURVE_MAX_COLS]; // Mark 1 grow_MeasureNode( curve_markobject1, &ll_x, &ll_y, &ur_x, &ur_y); x = (ll_x + ur_x) / 2; last_mark1_x = x; x_to_points( x, &time, values); for ( int i = 0; i < cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( mark1_annot[i], 0, str, strlen(str)); } if ( !(strcmp( cd->x_format[0], "%10t") == 0 || strcmp( cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( mark1_annot[cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); last_mark1_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( mark1_annot[cd->cols], 0, str, strlen(str)); } // Mark 2 grow_MeasureNode( curve_markobject2, &ll_x, &ll_y, &ur_x, &ur_y); x = (ll_x + ur_x) / 2; last_mark2_x = x; x_to_points( x, &time, values); for ( int i = 0; i < cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( mark2_annot[i], 0, str, strlen(str)); } if ( !(strcmp( cd->x_format[0], "%10t") == 0 || strcmp( cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( mark2_annot[cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); last_mark1_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( mark2_annot[cd->cols], 0, str, strlen(str)); } if ( current_period == ge_ePeriod_Markers) set_times_markers(); } void GeCurve::activate_minmax_ok( double min_value, double max_value) { int i = minmax_idx; if ( minmax_idx < cd->cols) cd->scale( cd->y_axis_type[i], cd->y_value_type[i], min_value, max_value, &cd->y_min_value_axis[i], &cd->y_max_value_axis[i], &cd->y_trend_lines[i], &cd->y_axis_lines[i], &cd->y_axis_linelongq[i], &cd->y_axis_valueq[i], cd->y_format[i], &cd->y_axis_width[i], 1, 1); else { double axis_width; i = 0; cd->scale( cd->x_axis_type[i], cd->x_value_type[i], min_value, max_value, &cd->x_min_value_axis[i], &cd->x_max_value_axis[i], &cd->x_trend_lines[i], &cd->x_axis_lines[i], &cd->x_axis_linelongq[i], &cd->x_axis_valueq[i], cd->x_format[i], &axis_width, 1, 1); if ( cd->type == curve_eDataType_MultiTrend) { for ( i = 1; i < cd->cols; i++) { cd->x_min_value_axis[i] = cd->x_min_value_axis[0]; cd->x_max_value_axis[i] = cd->x_max_value_axis[0]; } } } // cd->min_value_axis[minmax_idx] = min_value; // cd->max_value_axis[minmax_idx] = max_value; configure_curves(); configure_axes(); } void GeCurve::activate_minmax_save( double min_value, double max_value) { FILE *fp; int i = minmax_idx; fp = fopen( minmax_filename(cd->y_name[i]), "w"); if ( !fp) return; fprintf( fp, "%lf %lf\n", min_value, max_value); fclose( fp); } int GeCurve::get_saved_minmax( char *name, double *min_value, double *max_value) { FILE *fp; fp = fopen( minmax_filename( name), "r"); if ( !fp) return 0; fscanf( fp, "%lf %lf\n", min_value, max_value); fclose( fp); return 1; } char *GeCurve::minmax_filename( char *aname) { static pwr_tFileName fname; pwr_tAName attrname; strcpy( attrname, aname); cdh_ToLower( attrname, attrname); for ( char *s = attrname; *s; s++) { if ( *s == '-') *s = '_'; if ( *s == '.') *s = '_'; } strcpy( fname, "$HOME/pwr_curve_"); strcat( fname, attrname); strcat( fname, ".dat"); dcli_translate_filename( fname, fname); return fname; } // // Callbacks from growcurve // int GeCurve::growcurve_cb( GlowCtx *ctx, glow_tEvent event) { GeCurve *curve; grow_GetCtxUserData( (GrowCtx *)ctx, (void **) &curve); switch ( event->event) { case glow_eEvent_MB1Click: { // Move mark slider to this position double ll_x, ll_y, ur_x, ur_y; char str[40]; double time; double values[CURVE_MAX_COLS]; if ( curve->selected_mark == 0 || curve->selected_mark == 1) { grow_MeasureNode( curve->curve_markobject1, &ll_x, &ll_y, &ur_x, &ur_y); grow_MoveNode( curve->curve_markobject1, event->any.x - (ur_x - ll_x)/2, ll_y); grow_Redraw( curve->growcurve_ctx); curve->last_mark1_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->mark1_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->mark1_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); curve->last_mark1_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->mark1_annot[curve->cd->cols], 0, str, strlen(str)); if ( curve->current_period == ge_ePeriod_Markers) curve->set_times_markers(); } } else if ( curve->selected_mark == 2) { grow_MeasureNode( curve->curve_markobject2, &ll_x, &ll_y, &ur_x, &ur_y); grow_MoveNode( curve->curve_markobject2, event->any.x - (ur_x - ll_x)/2, ll_y); grow_Redraw( curve->growcurve_ctx); curve->last_mark2_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->mark2_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); curve->last_mark2_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); if ( curve->current_period == ge_ePeriod_Markers) curve->set_times_markers(); } } break; } case glow_eEvent_MB1ClickCtrl: { // Move mark slider to this position double ll_x, ll_y, ur_x, ur_y; char str[40]; double time; double values[CURVE_MAX_COLS]; grow_MeasureNode( curve->curve_markobject2, &ll_x, &ll_y, &ur_x, &ur_y); grow_MoveNode( curve->curve_markobject2, event->any.x - (ur_x - ll_x)/2, ll_y); grow_Redraw( curve->growcurve_ctx); curve->last_mark2_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->mark2_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); curve->last_mark2_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); if ( curve->current_period == ge_ePeriod_Markers) curve->set_times_markers(); } break; } case glow_eEvent_SliderMoveStart: { if ( event->object.object_type == glow_eObjectType_NoObject) grow_SetMoveRestrictions( (GrowCtx *)ctx, glow_eMoveRestriction_Disable, 0, 0, NULL); else { if ( event->object.object == curve->curve_markobject1) grow_SetMoveRestrictions( (GrowCtx *)ctx, glow_eMoveRestriction_HorizontalSlider, 200 - MARK_WIDTH/2, -MARK_WIDTH/2, curve->curve_markobject1); else if ( event->object.object == curve->curve_markobject2) grow_SetMoveRestrictions( (GrowCtx *)ctx, glow_eMoveRestriction_HorizontalSlider, 200 - MARK_WIDTH/2, -MARK_WIDTH/2, curve->curve_markobject2); } break; } case glow_eEvent_SliderMoved: { char str[40]; double ll_x, ll_y, ur_x, ur_y; double time; double values[CURVE_MAX_COLS]; if ( event->object.object == curve->curve_markobject1) { grow_MeasureNode( curve->curve_markobject1, &ll_x, &ll_y, &ur_x, &ur_y); curve->last_mark1_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->mark1_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->mark1_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); curve->last_mark1_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->mark1_annot[curve->cd->cols], 0, str, strlen(str)); if ( curve->current_period == ge_ePeriod_Markers) curve->set_times_markers(); } } else if ( event->object.object == curve->curve_markobject2) { grow_MeasureNode( curve->curve_markobject2, &ll_x, &ll_y, &ur_x, &ur_y); curve->last_mark2_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->mark2_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); curve->last_mark2_time = t; time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->mark2_annot[curve->cd->cols], 0, str, strlen(str)); if ( curve->current_period == ge_ePeriod_Markers) curve->set_times_markers(); } } break; } case glow_eEvent_CursorMotion: { char str[40]; double time; double values[CURVE_MAX_COLS]; if ( curve->cd->cols == 0) return 1; curve->last_cursor_x = event->any.x; curve->x_to_points( event->any.x, &time, values); for ( int i = 0; i < curve->cd->cols; i++) { sprintf( str, "%7.2f", values[i]); grow_SetAnnotation( curve->cursor_annot[i], 0, str, strlen(str)); } if ( !(strcmp( curve->cd->x_format[0], "%10t") == 0 || strcmp( curve->cd->x_format[0], "%11t") == 0)) { sprintf( str, "%7.2f", time); grow_SetAnnotation( curve->cursor_annot[curve->cd->cols], 0, str, strlen(str)); } else { // Time is a date pwr_tTime t; time_Float64ToD( (pwr_tDeltaTime *) &t, time); time_AtoAscii( &t, time_eFormat_DateAndTime, str, sizeof(str)); grow_SetAnnotation( curve->cursor_annot[curve->cd->cols], 0, str, strlen(str)); } break; } case glow_eEvent_Key_Left: curve_Scroll( curve->growcurve_ctx, 0.1); break; case glow_eEvent_Key_Right: curve_Scroll( curve->growcurve_ctx, -0.1); break; case glow_eEvent_Key_Up: curve_Zoom( curve->growcurve_ctx, 1.5); break; case glow_eEvent_Key_Down: curve_Zoom( curve->growcurve_ctx, 0.75); break; case glow_eEvent_ScrollUp: curve_Scroll( curve->growcurve_ctx, 0.05); break; case glow_eEvent_ScrollDown: curve_Scroll( curve->growcurve_ctx, -0.05); break; default: ; } return 1; } int GeCurve::init_growcurve_cb( GlowCtx *fctx, void *client_data) { grow_sAttributes grow_attr; unsigned long mask; char path[2][80] = {"$pwrp_exe/", "$pwr_exe/"}; GeCurve *curve = (GeCurve *) client_data; curve->growcurve_ctx = (CurveCtx *) fctx; mask = 0; mask |= grow_eAttr_grid_on; grow_attr.grid_on = 0; mask |= grow_eAttr_double_buffer_on; grow_attr.default_hot_mode = glow_eHotMode_TraceAction; mask |= grow_eAttr_default_hot_mode; grow_attr.double_buffer_on = 1; if ( curve->initial_right_position) { mask |= grow_eAttr_initial_position; grow_attr.initial_position = glow_eDirection_Right; } mask |= grow_eAttr_color_theme; strcpy( grow_attr.color_theme, "$default"); grow_SetAttributes( curve->growcurve_ctx, &grow_attr, mask); grow_SetCtxUserData( curve->growcurve_ctx, curve); grow_SetMoveRestrictions( curve->growcurve_ctx, glow_eMoveRestriction_Disable, 0, 0, NULL); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_MB1Click, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_MB1ClickCtrl, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_CursorMotion, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_SliderMoved, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_SliderMoveStart, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_MB1Press, glow_eEventType_MoveNode, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_Key_Left, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_Key_Right, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_Key_Up, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_Key_Down, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_ScrollUp, glow_eEventType_CallBack, growcurve_cb); grow_EnableEvent( (GrowCtx *)curve->growcurve_ctx, glow_eEvent_ScrollDown, glow_eEventType_CallBack, growcurve_cb); grow_SetPath( curve->growcurve_ctx, 2, (char *)path); grow_ReadCustomColorFile( curve->growcurve_ctx, 0); grow_SetBackgroundColor( curve->growcurve_ctx, glow_eCtColor_Background); grow_CreateGrowCurve( curve->growcurve_ctx, "curve", NULL, 0, 0, 200, 30, curve->curve_border, 2, glow_mDisplayLevel_1, 1, 1, curve->curve_color, curve, &curve->curve_object); grow_SetObjectOriginalFillColor( curve->curve_object, glow_eCtColor_DiagramFillcolor); grow_SetObjectOriginalBorderColor( curve->curve_object, glow_eCtColor_DiagramBordercolor); grow_CreateGrowAxis( curve->growcurve_ctx, "y_axis", 0, 30, 200, 31.85, glow_eDrawType_Line, 1, 5, glow_eDrawType_TextHelvetica, curve, &curve->curve_axisobject); grow_SetObjectOriginalBorderColor( curve->curve_axisobject, glow_eCtColor_AxisBordercolor); grow_SetObjectOriginalTextColor( curve->curve_axisobject, glow_eCtColor_BackgroundTextAndLines); grow_tNodeClass nc; grow_CreateNodeClass( curve->growcurve_ctx, "MarkNc", glow_eNodeGroup_Common, &nc); grow_AddLine( nc, "", 0, 0, 0, 32, glow_eDrawType_Color34, 1, 0, NULL); grow_AddRect( nc, "", -MARK_WIDTH/2, 30.1, MARK_WIDTH, 1.8, glow_eDrawType_LineGray, 1, 0, glow_mDisplayLevel_1, 0, 0, 1, glow_eDrawType_Color33, NULL); glow_sPoint p1[3] = { {-0.1, 30.3}, {-MARK_WIDTH/2+0.1, 31},{-0.1, 31.85}}; grow_AddPolyLine( nc, "", p1, 3, glow_eDrawType_Line, 1, 0, 1, 0, 1, glow_eDrawType_Color38, 1, 0); glow_sPoint p2[3] = { {0.1, 30.3}, { MARK_WIDTH/2-0.1, 31},{ 0.1, 31.7}}; grow_AddPolyLine( nc, "", p2, 3, glow_eDrawType_Line, 1, 0, 1, 0, 1, glow_eDrawType_Color38, 1, 0); grow_CreateGrowSlider( curve->growcurve_ctx, "", nc, 1, 0, NULL, &curve->curve_markobject2); grow_SetSliderInfo( curve->curve_markobject2, glow_eDirection_Right, 200, 0, 200, 0); grow_CreateGrowSlider( curve->growcurve_ctx, "", nc, 1, 0, NULL, &curve->curve_markobject1); grow_SetSliderInfo( curve->curve_markobject1, glow_eDirection_Right, 200, 0, 200, 0); // grow_SetMode( curve->growcurve_ctx, grow_eMode_Edit); curve->configure_curves(); if ( curve->deferred_configure_axes) curve->configure_axes(); return 1; } // // Callbacks from growaxis // int GeCurve::growaxis_cb( GlowCtx *ctx, glow_tEvent event) { GeCurve *curve; grow_GetCtxUserData( (GrowCtx *)ctx, (void **) &curve); switch ( event->event) { case glow_eEvent_MB1Click: { if ( event->object.object_type != glow_eObjectType_NoObject) { for ( int i = 0; i < curve->cd->cols; i++) { if ( event->object.object == curve->axis_object[i]) { grow_SetTrendLines( curve->curve_object, curve->cd->x_trend_lines[0] - 2, 2 * curve->cd->y_trend_lines[i] - 3); grow_Redraw( curve->growcurve_ctx); grow_SetAxisConf( curve->axis_lineobject, 0, 10, 2 * curve->cd->y_trend_lines[i] - 1, 1, 10, 0, "%2.0f"); grow_Redraw( curve->growaxis_ctx); break; } } } break; } case glow_eEvent_MB1DoubleClick: { if ( event->object.object_type != glow_eObjectType_NoObject) { for ( int i = 0; i < curve->cd->cols; i++) { if ( event->object.object == curve->axis_object[i]) { curve->open_minmax( i); break; } } } break; } case glow_eEvent_Resized: { if ( curve->axis_displayed) curve->resize(); break; } default: ; } return 1; } // // Callbacks from grownames // int GeCurve::grownames_cb( GlowCtx *ctx, glow_tEvent event) { GeCurve *curve; grow_GetCtxUserData( (GrowCtx *)ctx, (void **) &curve); switch ( event->event) { case glow_eEvent_MB1Click: { glow_eDrawType color; if ( event->object.object_type != glow_eObjectType_NoObject) { for ( int i = 0; i < curve->cd->cols; i++) { if ( event->object.object == curve->hide_rect[i] ) { if ( curve->hide[i]) { // Check max number of curves int num = 0; for ( int j = 0; j < curve->cd->cols; j++) { if ( !curve->hide[j]) num++; } if ( num >= TREND_MAX_CURVES - 1) { curve->wow->DisplayError( "Error", " Max number of curves exceeded "); break; } } curve->hide[i] = !curve->hide[i]; if ( curve->hide[i]) color = glow_eCtColor_Background; else color = glow_eCtColor_BackgroundTextAndLines; grow_SetObjectBorderColor( curve->hide_l1[i], color); grow_SetObjectBorderColor( curve->hide_l2[i], color); if ( curve->auto_refresh) { curve->configure_curves(); curve->configure_axes(); } break; } } for ( int i = 0; i < curve->cd->cols + 1; i++) { if ( event->object.object == curve->scale_rect[i] ) { curve->open_minmax( i); break; } } if ( event->object.object == curve->mark1_rect || event->object.object == curve->mark1_text) { if ( curve->selected_mark == 1) { grow_SetObjectFillColor( curve->mark1_rect, glow_eCtColor_AreaDelimiter); curve->selected_mark = 0; } else { grow_SetObjectFillColor( curve->mark1_rect, glow_eCtColor_ButtonActiveFillcolor); grow_SetObjectFillColor( curve->mark2_rect, glow_eCtColor_AreaDelimiter); curve->selected_mark = 1; } } if ( event->object.object == curve->mark2_rect || event->object.object == curve->mark2_text) { if ( curve->selected_mark == 2) { grow_SetObjectFillColor( curve->mark2_rect, glow_eCtColor_AreaDelimiter); curve->selected_mark = 0; } else { grow_SetObjectFillColor( curve->mark1_rect, glow_eCtColor_AreaDelimiter); grow_SetObjectFillColor( curve->mark2_rect, glow_eCtColor_ButtonActiveFillcolor); curve->selected_mark = 2; } } } break; } case glow_eEvent_HotRequest: return 0; case glow_eEvent_Resized: { break; } default: ; } return 1; } int GeCurve::init_growaxis_cb( GlowCtx *fctx, void *client_data) { grow_sAttributes grow_attr; unsigned long mask; GeCurve *curve = (GeCurve *) client_data; curve->growaxis_ctx = (GrowCtx *) fctx; mask = 0; // Double buffer is used to avoid pulldown menu at print mask |= grow_eAttr_double_buffer_on; grow_attr.double_buffer_on = 1; mask |= grow_eAttr_grid_on; grow_attr.grid_on = 0; mask |= grow_eAttr_hot_mode; grow_attr.hot_mode = glow_eHotMode_TraceAction; grow_SetAttributes( curve->growaxis_ctx, &grow_attr, mask); grow_SetCtxUserData( curve->growaxis_ctx, curve); grow_EnableEvent( (GrowCtx *)curve->growaxis_ctx, glow_eEvent_MB1Click, glow_eEventType_CallBack, growaxis_cb); grow_EnableEvent( (GrowCtx *)curve->growaxis_ctx, glow_eEvent_MB1DoubleClick, glow_eEventType_CallBack, growaxis_cb); grow_EnableEvent( (GrowCtx *)curve->growaxis_ctx, glow_eEvent_Resized, glow_eEventType_CallBack, growaxis_cb); if ( curve->growcurve_ctx) curve->configure_axes(); else curve->deferred_configure_axes = 1; return 1; } int GeCurve::init_grownames_cb( GlowCtx *fctx, void *client_data) { GeCurve *curve = (GeCurve *) client_data; curve->grownames_ctx = (GrowCtx *) fctx; grow_sAttributes grow_attr; unsigned long mask; if ( Lng::translatefile_coding() == lng_eCoding_UTF_8) grow_SetTextCoding( (GrowCtx *)curve->grownames_ctx, glow_eTextCoding_UTF_8); mask = 0; // Double buffer is used for print mask |= grow_eAttr_double_buffer_on; grow_attr.double_buffer_on = 1; mask |= grow_eAttr_grid_on; grow_attr.grid_on = 0; mask |= grow_eAttr_hot_mode; grow_attr.hot_mode = glow_eHotMode_TraceAction; mask |= grow_eAttr_color_theme; strcpy( grow_attr.color_theme, "$default"); grow_SetAttributes( curve->grownames_ctx, &grow_attr, mask); grow_SetCtxUserData( curve->grownames_ctx, curve); grow_EnableEvent( (GrowCtx *)curve->grownames_ctx, glow_eEvent_MB1Click, glow_eEventType_CallBack, grownames_cb); grow_EnableEvent( (GrowCtx *)curve->grownames_ctx, glow_eEvent_Resized, glow_eEventType_CallBack, grownames_cb); grow_EnableEvent( (GrowCtx *)curve->grownames_ctx, glow_eEvent_HotRequest, glow_eEventType_CallBack, grownames_cb); curve->config_names(); return 1; } int GeCurve::config_names() { if ( !cd) return 0; grow_tObject t1; glow_eDrawType color; double x, y; grow_sAttributes grow_attr; unsigned long mask; char path[2][80] = {"$pwrp_exe/", "$pwr_exe/"}; int date = (strcmp( cd->x_format[0], "%10t") == 0 || strcmp( cd->x_format[0], "%11t") == 0) ? 1 : 0; int time_size; if ( date) time_size = 9; else time_size = 3; // Create nodeclass for mark values grow_New( grownames_ctx); mask = grow_eAttr_color_theme; strcpy( grow_attr.color_theme, "$default"); grow_SetAttributes( grownames_ctx, &grow_attr, mask); grow_SetPath( grownames_ctx, 2, (char *)path); grow_ReadCustomColorFile( grownames_ctx, 0); grow_SetBackgroundColor( grownames_ctx, glow_eCtColor_Background); grow_tNodeClass nc; grow_CreateNodeClass( grownames_ctx, "MarkVal", glow_eNodeGroup_Common, &nc); grow_AddRect( nc, "", 0, 0, time_size, 0.75, glow_eCtColor_Background, 1, 0, glow_mDisplayLevel_1, 0, 0, 0, glow_eDrawType_Line, NULL); grow_AddAnnot( nc, 0.2, 0.7, 0, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eAnnotType_OneLine, 0, glow_mDisplayLevel_1, NULL); // Draw header grow_tObject o1; // grow_CreateGrowLine( grownames_ctx, "", 0, 0.75, 60, 0.75, // glow_eDrawType_Color34, 2, 0, NULL, &o1); y = 0; grow_CreateGrowRect( grownames_ctx, "", 0, y, 60, y + 0.9, glow_eDrawType_Line, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, glow_eCtColor_AreaDelimiter, NULL, &o1); x = 0.8; grow_CreateGrowText( grownames_ctx, "", Lng::translate("View"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); x += 1.8; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Cursor"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); x += time_size + 0.2; grow_CreateGrowRect( grownames_ctx, "", x - 0.4, 0, time_size, 0.75, glow_eCtColor_IndicatorBorderColor, 1, 0, glow_mDisplayLevel_1, 1, 1, 1, glow_eCtColor_AreaDelimiter, NULL, &mark1_rect); grow_SetObjectShadowWidth( mark1_rect, 10); grow_CreateGrowText( grownames_ctx, "", Lng::translate("Mark 1"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &mark1_text); // TODO x += time_size + 0.2; grow_CreateGrowRect( grownames_ctx, "", x - 0.4, 0, time_size, 0.75, glow_eCtColor_IndicatorBorderColor, 1, 0, glow_mDisplayLevel_1, 1, 1, 1, glow_eCtColor_AreaDelimiter, NULL, &mark2_rect); grow_SetObjectShadowWidth( mark2_rect, 10); grow_CreateGrowText( grownames_ctx, "", Lng::translate("Mark 2"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &mark2_text); x += time_size + 0.2; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Unit"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); x += 2; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Scale"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); if ( options & curve_mOptions_ShowDescrFirst) { x += 3; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Description"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); x += 14; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Attribute"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); } else { x += 3; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Attribute"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); x += 14; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Description"), x, y + 0.6, glow_eDrawType_TextHelvetica, glow_eCtColor_AreaDelimiterTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &o1); } y += 1; for ( int i = 0; i < cd->cols; i++) { // Draw shadowed frame grow_CreateGrowLine( grownames_ctx, "", 0, y + 1, 60, y + 1, glow_eCtColor_LineDelimiter, 1, 0, NULL, &o1); // Draw color rectangle grow_CreateGrowRect( grownames_ctx, "", 0.25, y + 0.3, 0.75, 0.5, glow_eCtColor_IndicatorBorderColor, 1, 0, glow_mDisplayLevel_1, 1, 1, 0, cd->color[i], NULL, &name_rect[i]); if ( hide[i]) color = glow_eCtColor_Background; else color = glow_eCtColor_BackgroundTextAndLines; // Draw checkbox for hide grow_CreateGrowLine( grownames_ctx, "", 1.4, y + 0.45, 1.52, y + 0.75, color, 2, 0, NULL, &hide_l1[i]); grow_CreateGrowLine( grownames_ctx, "", 1.50, y + 0.75, 1.77, y + 0.35, color, 2, 0, NULL, &hide_l2[i]); grow_CreateGrowRect( grownames_ctx, "", 1.3, y + 0.3, 0.5, 0.5, color, 1, 0, glow_mDisplayLevel_1, 0, 1, 0, glow_eCtColor_Background, NULL, &hide_rect[i]); // Draw nodes for mark and cursor values x = 2.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y + 0.05, NULL, &cursor_annot[i]); x += time_size + 0.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y + 0.05, NULL, &mark1_annot[i]); // TODO x += time_size + 0.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y + 0.05, NULL, &mark2_annot[i]); // Draw unit x += time_size + 0.6; if ( strcmp( cd->y_unit[i], "") == 0) strcpy( cd->y_unit[i], " "); grow_CreateGrowText( grownames_ctx, "", cd->y_unit[i], x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); // Draw button for scale x += 2; grow_CreateGrowRect( grownames_ctx, "", x, y + 0.1, 1.2, 0.7, glow_eCtColor_ButtonBordercolor, 1, 0, glow_mDisplayLevel_1, 1, 1, 1, glow_eCtColor_ButtonFillcolor, NULL, &scale_rect[i]); grow_SetObjectShadowWidth( scale_rect[i], 20); // Draw attribute name if ( options & curve_mOptions_ShowDescrFirst) { double w, h, descent; x += 3; if ( strcmp( cd->y_description[i], "") != 0) { grow_CreateGrowText( grownames_ctx, "", cd->y_description[i], x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); grow_GetTextExtent( grownames_ctx, cd->y_name[i], strlen(cd->y_name[i]), glow_eDrawType_TextHelvetica, 3, glow_eFont_LucidaSans, &w, &h, &descent); if ( w < 13) x += 14; else x += w + 1; } else x += 14; grow_CreateGrowText( grownames_ctx, "", cd->y_name[i], x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); } else { x += 3; grow_CreateGrowText( grownames_ctx, "", cd->y_name[i], x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); if ( strcmp( cd->y_description[i], "") != 0) { double w, h, descent; grow_GetTextExtent( grownames_ctx, cd->y_name[i], strlen(cd->y_name[i]), glow_eDrawType_TextHelvetica, 3, glow_eFont_LucidaSans, &w, &h, &descent); if ( w < 13) x += 14; else x += w + 1; grow_CreateGrowText( grownames_ctx, "", cd->y_description[i], x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); } } grow_SetAnnotation( cursor_annot[i], 0, "0", 1); grow_SetAnnotation( mark1_annot[i], 0, "0", 1); grow_SetAnnotation( mark2_annot[i], 0, "0", 1); y += 1; } // Draw nodes for time values // Draw shadowed frame grow_CreateGrowLine( grownames_ctx, "", 0, y + 1, 60, y + 1, glow_eCtColor_LineDelimiter, 1, 0, NULL, &o1); x = 2.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y + 0.05, NULL, &cursor_annot[cd->cols]); x += time_size + 0.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y +0.05, NULL, &mark1_annot[cd->cols]); // TODO x += time_size + 0.2; grow_CreateGrowNode( grownames_ctx, "", nc, x, y + 0.05, NULL, &mark2_annot[cd->cols]); // Draw unit x += time_size + 0.6; grow_CreateGrowText( grownames_ctx, "", "s", x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); // Draw button for scale x += 2; grow_CreateGrowRect( grownames_ctx, "", x, y + 0.1, 1.2, 0.7, glow_eCtColor_ButtonBordercolor, 1, 0, glow_mDisplayLevel_1, 1, 1, 1, glow_eCtColor_ButtonFillcolor, NULL, &scale_rect[cd->cols]); grow_SetObjectShadowWidth( scale_rect[cd->cols], 20); // Draw attribute name x += 3; grow_CreateGrowText( grownames_ctx, "", Lng::translate("Time axis"), x, y + 0.75, glow_eDrawType_TextHelvetica, glow_eCtColor_BackgroundTextAndLines, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); grow_SetAnnotation( cursor_annot[cd->cols], 0, "0", 1); grow_SetAnnotation( mark1_annot[cd->cols], 0, "0", 1); grow_SetAnnotation( mark2_annot[cd->cols], 0, "0", 1); return 1; } void GeCurve::scroll( double value) { curve_Scroll( growcurve_ctx, value); } void GeCurve::print( char *filename) { double x; int w1, w2, h1, h2; glow_eDrawType c1, c2, c3; grow_GetBackgroundColor( growaxis_ctx, &c1); grow_GetBackgroundColor( growcurve_ctx, &c2); grow_GetBackgroundColor( grownames_ctx, &c3); grow_SetBackgroundColor( growaxis_ctx, glow_eDrawType_Color4); grow_SetBackgroundColor( growcurve_ctx, glow_eDrawType_Color4); grow_SetBackgroundColor( grownames_ctx, glow_eDrawType_Color4); grow_Redraw( growaxis_ctx); grow_Redraw( growcurve_ctx); grow_Redraw( grownames_ctx); grow_GetWindowSize( growaxis_ctx, &w1, &h1); grow_GetWindowSize( growcurve_ctx, &w2, &h2); if ( w1 + w2 == 0) return; x = double(w1) / (w1 + w2); grow_Print( growaxis_ctx, filename, 0.0, x, 0); grow_Print( growcurve_ctx, filename, x, 1.0, 0); grow_Print( grownames_ctx, filename, 0, 0, 1); grow_SetBackgroundColor( growaxis_ctx, c1); grow_SetBackgroundColor( growcurve_ctx, c2); grow_SetBackgroundColor( grownames_ctx, c3); grow_Redraw( growaxis_ctx); grow_Redraw( growcurve_ctx); grow_Redraw( grownames_ctx); } int GeCurve::configure_axes() { double x = 0; int i, idx; grow_sAttributes grow_attr; unsigned long mask; char path[2][80] = {"$pwrp_exe/", "$pwr_exe/"}; if ( !cd) return 0; grow_SetNodraw( growaxis_ctx); grow_New( growaxis_ctx); mask = grow_eAttr_color_theme; strcpy( grow_attr.color_theme, "$default"); grow_SetAttributes( growaxis_ctx, &grow_attr, mask); grow_SetPath( growaxis_ctx, 2, (char *)path); grow_ReadCustomColorFile( growaxis_ctx, 0); grow_SetBackgroundColor( growaxis_ctx, glow_eCtColor_Background); memset( axis_object, 0, sizeof( axis_object)); for ( i = 0; i < cd->cols; i++) { if ( cd->y_value_type[i] != pwr_eType_Boolean && !hide[i]) { grow_CreateGrowRect( growaxis_ctx, "", x, 0, cd->y_axis_width[i], 30, glow_eDrawType_Line, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, cd->axiscolor[i], NULL, &axis_rect[i]); x += cd->y_axis_width[i]; } } // Draw horizontal lines with same interval as the trend object // Get number of horizontal lines from first not hidden float idx = 0; for ( i = 0; i < cd->cols; i++) { if ( cd->y_value_type[i] != pwr_eType_Boolean && !hide[i]) { idx = i; break; } } grow_CreateGrowAxis( growaxis_ctx, "", -2, 0, x + 1, 30, border_bright, 1, 0, glow_eDrawType_TextHelvetica, NULL, &axis_lineobject); grow_SetAxisConf( axis_lineobject, 0, 10, 2 * cd->y_trend_lines[idx] - 1, 1, 10, 0, "%1.0f"); x = 0; for ( i = 0; i < cd->cols; i++) { if ( cd->y_value_type[i] != pwr_eType_Boolean && !hide[i]) { grow_CreateGrowAxis( growaxis_ctx, "", x, 0, x + cd->y_axis_width[i], 30, glow_eDrawType_Line, 1, 6, glow_eDrawType_TextHelvetica, NULL, &axis_object[i]); grow_SetAxisConf( axis_object[i], cd->y_max_value_axis[i], cd->y_min_value_axis[i], 2 * cd->y_trend_lines[i] - 1, 2, 2, 0, cd->y_format[i]); x += cd->y_axis_width[i]; } } axis_window_width = MAX( x, 1); double zoom_x, zoom_y; int width; curve_GetZoom( growcurve_ctx, &zoom_x, &zoom_y); grow_ZoomY( growaxis_ctx, zoom_y); grow_ZoomX( growaxis_ctx, zoom_y); if ( axis_displayed) { width = int( zoom_y * axis_window_width); axis_set_width( width); } grow_ResetNodraw( growaxis_ctx); grow_Redraw( growaxis_ctx); update_times_markers(); return 1; } int GeCurve::configure_curves() { int i, j, idx; glow_sCurveData gcd; int max_index, min_index; double minval, maxval; if ( !cd) return 0; if ( cd->type == curve_eDataType_LogFile || cd->type == curve_eDataType_DsTrend) { gcd.type = glow_eCurveDataType_CommonX; // Get max and min index in x max_index = -1; min_index = -1; if ( cd->x_min_value_axis[0] > cd->x_min_value[0] || cd->x_max_value_axis[0] < cd->x_max_value[0]) { for ( i = 0; i < cd->rows[0]; i++) { if ( min_index == -1 && cd->x_data[0][i] >= cd->x_min_value_axis[0] ) min_index = i; if ( max_index == -1 && cd->x_data[0][i] >= cd->x_max_value_axis[0] ) max_index = i - 1; } if ( min_index == -1) min_index = 0; if ( max_index == -1) max_index = cd->rows[0] - 1; } else { max_index = cd->rows[0] - 1; min_index = 0; } idx = 0; for ( i = 0; i < cd->cols; i++) { if ( !hide[i]) { gcd.y_max_value[idx] = cd->y_max_value_axis[i]; gcd.y_min_value[idx] = cd->y_min_value_axis[i]; gcd.y_data[idx] = &cd->y_data[i][min_index]; gcd.color[idx] = cd->color[i]; gcd.fillcolor[idx] = cd->fillcolor[i]; gcd.curve_type[idx] = glow_eCurveType_Inherit; if ( cd->y_value_type[i] == pwr_eType_Boolean) gcd.curve_type[idx] = glow_eCurveType_DigSquare; else gcd.curve_type[idx] = glow_eCurveType_Inherit; idx++; if ( idx == TREND_MAX_CURVES - 1) break; } } gcd.x_data[0] = &cd->x_data[0][min_index]; gcd.x_max_value[0] = cd->x_max_value_axis[0]; gcd.x_min_value[0] = cd->x_min_value_axis[0]; gcd.curves = idx; gcd.rows[0] = max_index - min_index + 1; gcd.x_reverse = cd->x_reverse; // Get number of horizontal lines from first not hidden float idx = 1; for ( i = 0; i < cd->cols; i++) { if ( cd->y_value_type[i] != pwr_eType_Boolean && !hide[i]) { idx = i; break; } } grow_SetTrendLines( curve_object, // int(cd->max_value_axis[0] - cd->min_value_axis[0] - 1), cd->x_trend_lines[0] - 2, 2 * cd->y_trend_lines[idx] - 3); if ( cd->x_reverse) { minval = cd->x_max_value_axis[0]; maxval = cd->x_min_value_axis[0]; } else { minval = cd->x_min_value_axis[0]; maxval = cd->x_max_value_axis[0]; } grow_SetAxisConf( curve_axisobject, minval, maxval, // 10 * int( cd->max_value_axis[0] - cd->min_value_axis[0]) + 1, cd->x_axis_lines[0], cd->x_axis_linelongq[0], cd->x_axis_valueq[0], 270, cd->x_format[0]); grow_CurveConfigure( curve_object, &gcd); } else if ( cd->type == curve_eDataType_MultiTrend) { gcd.type = glow_eCurveDataType_SeparateX; idx = 0; for ( i = 0; i < cd->cols; i++) { if ( !hide[i]) { // Get max and min index in x max_index = -1; min_index = -1; if ( cd->x_min_value_axis[i] > cd->x_min_value[i] || cd->x_max_value_axis[i] < cd->x_max_value[i]) { for ( j = 0; j < cd->rows[i]; j++) { if ( min_index == -1 && cd->x_data[i][j] >= cd->x_min_value_axis[i] ) min_index = j; if ( max_index == -1 && cd->x_data[i][j] >= cd->x_max_value_axis[i] ) max_index = j - 1; } if ( min_index == -1) min_index = 0; if ( max_index == -1) max_index = cd->rows[i] - 1; } else { max_index = cd->rows[i] - 1; min_index = 0; } gcd.y_max_value[idx] = cd->y_max_value_axis[i]; gcd.y_min_value[idx] = cd->y_min_value_axis[i]; gcd.y_data[idx] = &cd->y_data[i][min_index]; gcd.color[idx] = cd->color[i]; gcd.fillcolor[idx] = cd->fillcolor[i]; if ( cd->y_value_type[i] == pwr_eType_Boolean) gcd.curve_type[idx] = glow_eCurveType_DigSquare; else gcd.curve_type[idx] = glow_eCurveType_Inherit; gcd.x_data[idx] = &cd->x_data[i][min_index]; gcd.x_max_value[idx] = cd->x_max_value_axis[i]; gcd.x_min_value[idx] = cd->x_min_value_axis[i]; gcd.rows[idx] = max_index - min_index + 1; idx++; if ( idx == TREND_MAX_CURVES - 1) break; } } gcd.curves = idx; gcd.x_reverse = cd->x_reverse; // Get number of horizontal lines from first not hidden float idx = 1; for ( i = 0; i < cd->cols; i++) { if ( cd->y_value_type[i] != pwr_eType_Boolean && !hide[i]) { idx = i; break; } } grow_SetTrendLines( curve_object, // int(cd->max_value_axis[0] - cd->min_value_axis[0] - 1), cd->x_trend_lines[0] - 2, 2 * cd->y_trend_lines[idx] - 3); if ( cd->x_reverse) { minval = cd->x_max_value_axis[0]; maxval = cd->x_min_value_axis[0]; } else { minval = cd->x_min_value_axis[0]; maxval = cd->x_max_value_axis[0]; } grow_SetAxisConf( curve_axisobject, minval, maxval, // 10 * int( cd->max_value_axis[0] - cd->min_value_axis[0]) + 1, cd->x_axis_lines[0], cd->x_axis_linelongq[0], cd->x_axis_valueq[0], 270, cd->x_format[0]); grow_CurveConfigure( curve_object, &gcd); } return 1; } void GeCurve::redraw() { grow_Redraw( growcurve_ctx); } void GeCurve::points_added( unsigned int no_of_points) { int i, idx; glow_sCurveData gcd; int max_index, min_index; gcd.type = glow_eCurveDataType_CommonX; // Get max and min index in x */ max_index = -1; min_index = -1; if ( cd->x_min_value_axis[0] > cd->x_min_value[0] || cd->x_max_value_axis[0] < cd->x_max_value[0]) { for ( i = 0; i < cd->rows[0]; i++) { if ( min_index == -1 && cd->x_data[0][i] >= cd->x_min_value_axis[0] ) min_index = i; if ( max_index == -1 && cd->x_data[0][i] >= cd->x_max_value_axis[0] ) max_index = i - 1; } if ( min_index == -1) min_index = 0; if ( max_index == -1) max_index = cd->rows[0] - 1; } else { max_index = cd->rows[0] - 1; min_index = 0; } idx = 0; for ( i = 0; i < cd->cols; i++) { if ( !hide[i]) { gcd.y_max_value[idx] = cd->y_max_value_axis[i]; gcd.y_min_value[idx] = cd->y_min_value_axis[i]; gcd.y_data[idx] = &cd->y_data[i][min_index]; gcd.color[idx] = cd->color[i]; gcd.fillcolor[idx] = cd->fillcolor[i]; idx++; if ( idx == TREND_MAX_CURVES - 1) break; } } gcd.x_max_value[0] = cd->x_max_value_axis[0]; gcd.x_min_value[0] = cd->x_min_value_axis[0]; gcd.x_data[0] = &cd->x_data[0][min_index]; gcd.curves = idx; gcd.rows[0] = max_index - min_index + 1; gcd.x_reverse = cd->x_reverse; grow_CurveAddPoints( curve_object, &gcd, no_of_points); // Simulate cursormotion and slidermoved event to update markvalues glow_sEvent e; e.any.event = glow_eEvent_CursorMotion; e.any.x = last_cursor_x; growcurve_cb( growcurve_ctx, &e); e.any.event = glow_eEvent_SliderMoved; e.any.x = last_mark1_x; e.object.object = curve_markobject1; growcurve_cb( growcurve_ctx, &e); e.any.event = glow_eEvent_SliderMoved; e.any.x = last_mark2_x; e.object.object = curve_markobject2; growcurve_cb( growcurve_ctx, &e); } int GeCurve::read_file( char *filename) { FILE *fp; char line[10000]; char item_str[CURVE_MAX_COLS][80]; int nr; int rows = 0; pwr_tFileName fname; int i, j; int skip_line; dcli_translate_filename( fname, filename); fp = fopen( fname, "r"); if ( !fp) return 0; // Attribute names in first line if ( !dcli_read_line( line, sizeof(line), fp)) { fclose( fp); return 0; } nr = dcli_parse( line, " ", "", (char *)item_str, sizeof( item_str) / sizeof( item_str[0]), sizeof( item_str[0]), 0); if ( nr == 0) { fclose( fp); return 0; } //printf( "line: %s\n", line); //for ( i = 0; i < nr; i++) // printf( "item: %s\n", item_str[i]); while( dcli_read_line( line, sizeof(line), fp)) { rows++; } fclose( fp); // printf( "Rows: %d\n", rows); cd = new GeCurveData( curve_eDataType_LogFile); cd->x_reverse = 0; cd->cols = nr - 1; for ( i = 0; i < nr; i++) { cd->rows[i] = rows; if ( i == 0) { strcpy( cd->x_name, item_str[i]); cd->x_data[i] = (double *) malloc( rows * sizeof( double)); cd->x_axis_type[i] = curve_eAxis_x; } else { strcpy( cd->y_name[i-1], item_str[i]); cd->y_data[i-1] = (double *) malloc( rows * sizeof( double)); cd->y_axis_type[i-1] = curve_eAxis_y; } } fp = fopen( fname, "r"); dcli_read_line( line, sizeof(line), fp); j = 0; while( dcli_read_line( line, sizeof(line), fp)) { dcli_parse( line, " ", "", (char *)item_str, sizeof( item_str) / sizeof( item_str[0]), sizeof( item_str[0]), 0); skip_line = 0; for ( i = 0; i < cd->cols + 1; i++) { if ( i == 0) nr = sscanf( item_str[i], "%lf", &cd->x_data[i][j]); else nr = sscanf( item_str[i], "%lf", &cd->y_data[i-1][j]); if ( nr != 1) { if ( i == 0) { printf( "Unreadble line %d\n", j); skip_line = 1; cd->rows[0]--; break; } else cd->y_data[i-1][j] = 0; } } if ( skip_line) continue; j++; } fclose( fp); return 1; } void GeCurve::set_time( pwr_tTime time) { char time_str[40]; char full_title[500]; time_AtoAscii( &time, time_eFormat_DateAndTime, time_str, sizeof(time_str)); sprintf( full_title, "%s %s", title, time_str); write_title( full_title); } void GeCurve::set_title( char *str) { strcpy( title, str); write_title( str); } void GeCurve::measure_window( double *ll_x, double *ll_y, double *ur_x, double *ur_y) { grow_MeasureWindow( growcurve_ctx, ll_x, ll_y, ur_x, ur_y); } void GeCurve::set_curvedata( GeCurveData *curve_data) { if ( cd) delete cd; cd = curve_data; } GeCurve::~GeCurve() { } GeCurve::GeCurve( void *gc_parent_ctx, char *curve_name, char *filename, GeCurveData *curve_data, int pos_right, int gc_width, int gc_height, unsigned int gc_options, int gc_color_theme) : parent_ctx(gc_parent_ctx), growcurve_ctx(0), background_dark(glow_eCtColor_DiagramFillcolor), background_bright(glow_eDrawType_Color21), border_dark(glow_eCtColor_DiagramBordercolor), border_bright(glow_eDrawType_Color22), cd(0), axis_window_width(0), auto_refresh(1), axis_displayed(1), minmax_idx(0), close_cb(0), help_cb(0), increase_period_cb(0), decrease_period_cb(0), reload_cb(0), prev_period_cb(0), next_period_cb(0), add_cb(0), madd_cb(0), remove_cb(0), export_cb(0), new_cb(0), save_cb(0), open_cb(0), snapshot_cb(0), initial_right_position(pos_right), last_cursor_x(0), last_mark1_x(0), last_mark2_x(0), last_mark1_time(pwr_cNTime), last_mark2_time(pwr_cNTime), deferred_configure_axes(0), center_from_window(0), options(gc_options), layout_mask(0), color_theme(gc_color_theme), current_period(time_ePeriod_OneHour), fill_curves(0) { pwr_tStatus sts; memset( hide, 0, sizeof(hide)); memset( name_rect, 0, sizeof(name_rect)); memset( hide_rect, 0, sizeof(hide_rect)); memset( scale_rect, 0, sizeof(scale_rect)); memset( hide_l1, 0, sizeof(hide_l1)); memset( hide_l2, 0, sizeof(hide_l2)); memset( cursor_annot, 0, sizeof(cursor_annot)); memset( mark1_annot, 0, sizeof(mark1_annot)); memset( mark2_annot, 0, sizeof(mark2_annot)); curve_color = background_dark; curve_border = border_dark; for ( int i = TREND_MAX_CURVES; i < CURVE_MAX_COLS; i++) hide[i] = 1; if ( filename) { sts = read_file( filename); if ( EVEN(sts)) return; cd->get_borders(); cd->get_default_axis(); cd->select_color( curve_color == background_dark); } else if ( curve_data) { cd = curve_data; cd->select_color( curve_color == background_dark); } char color_theme_file[80]; sprintf( color_theme_file, "pwr_colortheme%d", color_theme); grow_SetDefaultColorTheme( color_theme_file); } GeCurveData::GeCurveData( curve_eDataType datatype) : type(datatype), cols(0), x_reverse(0), time_format(curve_eTimeFormat_Float) { memset( x_data, 0, sizeof(x_data)); memset( y_data, 0, sizeof(y_data)); for ( int i = 0; i < CURVE_MAX_COLS; i++) { strcpy( y_unit[i], ""); strcpy( y_format[i], ""); strcpy( y_name[i], ""); strcpy( y_description[i], ""); rows[i] = 0; y_max_value[i] = 0; y_min_value[i] = 0; y_min_value_axis[i] = 0; y_max_value_axis[i] = 0; y_trend_lines[i] = 0; y_axis_lines[i] = 0; y_axis_linelongq[i] = 0; y_axis_valueq[i] = 0; y_axis_width[i] = 0; strcpy( x_unit[i], ""); strcpy( x_format[i], ""); x_max_value[i] = 0; x_min_value[i] = 0; x_min_value_axis[i] = 0; x_max_value_axis[i] = 0; x_trend_lines[i] = 0; x_axis_lines[i] = 0; x_axis_linelongq[i] = 0; x_axis_valueq[i] = 0; } strcpy( x_name, ""); } GeCurveData::~GeCurveData() { for ( int i = 0; i < cols; i++) { free( (char *) y_data[i]); if ( x_data[i]) free( (char *) x_data[i]); } } void GeCurveData::get_borders() { for ( int i = 0; i < cols; i++) { y_max_value[i] = 1e-37; y_min_value[i] = 1e37; y_value_type[i] = pwr_eType_Boolean; for ( int j = 0; j < rows[i]; j++) { if ( y_data[i][j] < y_min_value[i]) y_min_value[i] = y_data[i][j]; if ( y_data[i][j] > y_max_value[i]) y_max_value[i] = y_data[i][j]; if ( y_value_type[i] == pwr_eType_Boolean && !( y_data[i][j] == 1 || y_data[i][j] == 0)) { y_value_type[i] = pwr_eType_Float64; // printf( "Not Boolean %s: %f\n", name[i], data[i][j]); } } } if ( type == curve_eDataType_MultiTrend) { for ( int i = 0; i < cols; i++) { x_max_value[i] = 1e-37; x_min_value[i] = 1e37; x_value_type[i] = pwr_eType_Float64; for ( int j = 0; j < rows[i]; j++) { if ( x_data[i][j] < x_min_value[i]) x_min_value[i] = x_data[i][j]; if ( x_data[i][j] > x_max_value[i]) x_max_value[i] = x_data[i][j]; } } } else { for ( int i = 0; i < 1; i++) { x_max_value[i] = 1e-37; x_min_value[i] = 1e37; x_value_type[i] = pwr_eType_Float64; for ( int j = 0; j < rows[0]; j++) { if ( x_data[i][j] < x_min_value[i]) x_min_value[i] = x_data[i][j]; if ( x_data[i][j] > x_max_value[i]) x_max_value[i] = x_data[i][j]; } } } } void GeCurveData::get_default_axis() { double min_value, max_value; for ( int i = 0; i < cols; i++) { if ( GeCurve::get_saved_minmax( y_name[i], &min_value, &max_value)) scale( y_axis_type[i], y_value_type[i], min_value, max_value, &y_min_value_axis[i], &y_max_value_axis[i], &y_trend_lines[i], &y_axis_lines[i], &y_axis_linelongq[i], &y_axis_valueq[i], y_format[i], &y_axis_width[i], 0, 0); else scale( y_axis_type[i], y_value_type[i], y_min_value[i], y_max_value[i], &y_min_value_axis[i], &y_max_value_axis[i], &y_trend_lines[i], &y_axis_lines[i], &y_axis_linelongq[i], &y_axis_valueq[i], y_format[i], &y_axis_width[i], 0, 0); } int i = 0; double axis_width; if ( type != curve_eDataType_MultiTrend) { scale( x_axis_type[i], x_value_type[i], x_min_value[i], x_max_value[i], &x_min_value_axis[i], &x_max_value_axis[i], &x_trend_lines[i], &x_axis_lines[i], &x_axis_linelongq[i], &x_axis_valueq[i], x_format[i], &axis_width, 0, 0); } else { double min_value = 1e37; double max_value = -1e37; for ( i = 0; i < cols; i++) { if ( x_min_value[i] < min_value) min_value = x_min_value[i]; if ( x_max_value[i] > max_value) max_value = x_max_value[i]; } scale( x_axis_type[0], x_value_type[0], min_value, max_value, &x_min_value_axis[0], &x_max_value_axis[0], &x_trend_lines[0], &x_axis_lines[0], &x_axis_linelongq[0], &x_axis_valueq[0], x_format[0], &axis_width, 0, 0); for ( i = 1; i < cols; i++) { x_min_value_axis[i] = x_min_value_axis[0]; x_max_value_axis[i] = x_max_value_axis[0]; } } } void GeCurveData::select_color( bool dark_bg) { int j; for ( int i = 0; i < cols; i++) { j = i % 9; switch( j) { case 0: // Orange if ( dark_bg) color[i] = glow_eDrawType_Color144; else color[i] = glow_eDrawType_Color146; axiscolor[i] = glow_eDrawType_Color135; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color137; else fillcolor[i] = glow_eDrawType_Color133; break; case 1: // YellowGreen if ( dark_bg) color[i] = glow_eDrawType_Color85; else color[i] = glow_eDrawType_Color87; axiscolor[i] = glow_eDrawType_Color75; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color67; else fillcolor[i] = glow_eDrawType_Color64; break; case 2: // Yellow if ( dark_bg) color[i] = glow_eDrawType_Color115; else color[i] = glow_eDrawType_Color117; axiscolor[i] = glow_eDrawType_Color105; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color107; else fillcolor[i] = glow_eDrawType_Color104; break; case 3: // Blue color[i] = glow_eDrawType_Color235; axiscolor[i] = glow_eDrawType_Color225; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color227; else fillcolor[i] = glow_eDrawType_Color214; break; case 4: // Violet color[i] = glow_eDrawType_Color205; axiscolor[i] = glow_eDrawType_Color195; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color197; else fillcolor[i] = glow_eDrawType_Color184; break; case 5: // Red color[i] = glow_eDrawType_Color175; axiscolor[i] = glow_eDrawType_Color165; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color167; else fillcolor[i] = glow_eDrawType_Color154; break; case 6: // Green color[i] = glow_eDrawType_Color295; axiscolor[i] = glow_eDrawType_Color285; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color287; else fillcolor[i] = glow_eDrawType_Color274; break; case 7: // Gray color[i] = glow_eDrawType_Color35; axiscolor[i] = glow_eDrawType_Color35; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color37; else fillcolor[i] = glow_eDrawType_Color34; break; case 8: // Seablue color[i] = glow_eDrawType_Color265; axiscolor[i] = glow_eDrawType_Color255; if ( dark_bg) fillcolor[i] = glow_eDrawType_Color257; else fillcolor[i] = glow_eDrawType_Color254; break; } } } void GeCurveData::scale( int axis_type, int value_type, double min_value, double max_value, double *min_value_axis, double *max_value_axis, int *trend_lines, int *axis_lines, int *axis_linelongq, int *axis_valueq, char *format, double *axis_width, int not_zero, int allow_odd) { double value, maxval, minval; int i_value; int n, max_n, min_n; int min_lines, max_lines; int min_zero, max_zero; int format_int, format_dec; int trendlinequot = 2; int axlinequot = 2; int axvaluequot = 2; time_format = curve_eTimeFormat_Float; // Scale 0 - 10 for boolean if ( value_type == pwr_eType_Boolean) { maxval = 10; minval = 0; i_value = 10; max_lines = i_value; min_lines = 0; n = 0; } else { n = 0; if ( (type == curve_eDataType_LogFile || type == curve_eDataType_DsTrend || type == curve_eDataType_MultiTrend) && axis_type == curve_eAxis_x) { // Time axis if ( max_value - min_value < 300) { i_value = int(max_value + 0.99); maxval = i_value; max_lines = i_value; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value - 0.99); minval = i_value; min_lines = i_value; } else if ( max_value - min_value < 1000) { i_value = int(max_value/10) * 10 + 10; maxval = i_value; max_lines = i_value / 10; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/10) * 10 - 10; minval = i_value; min_lines = i_value / 10; } else if ( max_value - min_value < 3000) { i_value = int(max_value/50) * 50 + 50; maxval = i_value; max_lines = i_value / 50; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/50) * 50 - 50; minval = i_value; min_lines = i_value / 50; } else if ( max_value - min_value < 10000) { i_value = int(max_value/100) * 100 + 100; maxval = i_value; max_lines = i_value / 100; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/100) * 100 - 100; minval = i_value; min_lines = i_value / 100; } else if ( max_value - min_value < 30000) { i_value = int(max_value/600) * 600 + 600; maxval = i_value; max_lines = i_value / 60; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/60) * 60 - 60; minval = i_value; min_lines = i_value / 60; time_format = curve_eTimeFormat_HourMinute; trendlinequot = 2; axlinequot = 10; axvaluequot = 10; } else if ( max_value - min_value < 60000) { i_value = int(max_value/600) * 600 + 600; maxval = i_value; max_lines = i_value / 600; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/600) * 600 - 600; minval = i_value; min_lines = i_value / 600; axlinequot = 6; axvaluequot = 2; time_format = curve_eTimeFormat_HourMinute; } else if ( max_value - min_value < 140000) { i_value = int(max_value/600) * 600 + 600; maxval = i_value; max_lines = i_value / 600; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/600) * 600 - 600; minval = i_value; min_lines = i_value / 600; axlinequot = 6; axvaluequot = 12; time_format = curve_eTimeFormat_HourMinute; } else { i_value = int(max_value/3600) * 3600 + 3600; maxval = i_value; max_lines = i_value / 3600; if ( fabs( min_value) < DBL_EPSILON) i_value = 0; else i_value = int(min_value/3600) * 3600 - 3600; minval = i_value; min_lines = i_value / 3600; axlinequot = 2 * int((max_value - min_value)/140000); axvaluequot = 2 * int((max_value - min_value)/140000); time_format = curve_eTimeFormat_DayHour; } } else { min_zero = 0; max_zero = 0; // Power for max_value if ( (max_value < DBL_EPSILON && !not_zero) || fabs(max_value) < DBL_EPSILON) { maxval = 0; max_lines = 0; max_n = 0; max_zero = 1; } else { value = fabs(max_value); n = 0; if ( value >= 1) { while ( value / 10 > 1) { value = value / 10; n++; } max_n = n; } else { while ( value * 10 < 10) { value = value * 10; n++; } max_n = -n; } } // Power for min_value if ( (min_value > -DBL_EPSILON && !not_zero) || fabs(min_value) < DBL_EPSILON) { minval = 0; min_lines = 0; min_n = 0; min_zero = 1; } else { value = fabs(min_value); n = 0; if ( value >= 1) { while ( value / 10 > 1) { value = value / 10; n++; } min_n = n; } else { while ( value * 10 < 10) { value = value * 10; n++; } min_n = -n; } } if ( min_zero) { // Use power for max_value i_value = int( max_value * pow(10, -max_n)) + 1; if ( fabs(double(i_value-1) - max_value * pow(10, -n)) < 1e-10) i_value--; if ( ODD(i_value) && i_value != 5 && !allow_odd) i_value += 1; maxval = double(i_value) * pow( 10, max_n); max_lines = i_value; n = max_n; } else if ( max_zero) { // Use power for min_value i_value = int( min_value * pow(10, -min_n)) + ((min_value < 0) ? -1 : 1); if ( fabs(double(i_value+1) - min_value * pow(10, -n)) < 1e-10) i_value++; if ( ODD(i_value) && i_value != 5 && !allow_odd) i_value += 1; minval = double(i_value) * pow( 10, min_n); min_lines = i_value; n = min_n; } else { // Use largest power of min and max if ( max_n > min_n) n = max_n; else n = min_n; if ( max_value > 0) { i_value = int( max_value * pow(10, -n)) + 1; if ( fabs(double(i_value-1) - max_value * pow(10, -n)) < 1e-10) i_value--; } else i_value = int( max_value * pow(10, -n)); if ( ODD(i_value) && i_value != 5 && !allow_odd) i_value += 1; maxval = double(i_value) * pow( 10, n); max_lines = i_value; if ( min_value < 0) { i_value = int( min_value * pow(10, -n)) - 1; if ( fabs(double(i_value+1) - min_value * pow(10, -n)) < 1e-10) i_value++; } else i_value = int( min_value * pow(10, -n)); if ( ODD(i_value) && i_value != 5 && !allow_odd) i_value -= 1; minval = double(i_value) * pow( 10, n); min_lines = i_value; } } } *max_value_axis = maxval; *min_value_axis = minval; *trend_lines = ABS(max_lines - min_lines) + 1; *axis_lines = (*trend_lines - 1) * trendlinequot + 1; *axis_linelongq = axlinequot; *axis_valueq = axvaluequot; switch ( time_format) { case curve_eTimeFormat_Float: // Float format format_int = ABS(n) + 1; if ( n > 0) format_dec = 0; else { format_dec = ABS(n); format_int++; } if ( minval < 0) format_int++; sprintf( format, "%%%d.%df", format_int, format_dec); *axis_width = 0.65 * format_int + 0.4; break; case curve_eTimeFormat_HourMinute: // Hour and minute format format_int = ABS(n) + 1; strcpy( format, "%2t"); *axis_width = 0.65 * format_int + 0.4; break; case curve_eTimeFormat_DayHour: // Days and hour format format_int = ABS(n) + 1; strcpy( format, "%3t"); *axis_width = 0.65 * format_int + 0.4; break; } //printf( "%f %f %f %f %3d %5s %4.1f\n", // min_value, max_value, // *min_value_axis, *max_value_axis, *trend_lines, format, *axis_width); return; } void GeCurve::x_to_points( double x, double *t, double *values) { int row; double time; if ( cd->type != curve_eDataType_MultiTrend) { // Time is a date if ( !cd->x_reverse) time = cd->x_min_value_axis[0] + x * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; else time = cd->x_min_value_axis[0] + (200.0 - x) * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; // Approximate row row = int ((time - cd->x_min_value[0]) / (cd->x_max_value[0] - cd->x_min_value[0]) * (cd->rows[0] - 1) + 0.5); if ( row > cd->rows[0] - 1) row = cd->rows[0] - 1; else if ( row < 0) row = 0; else { // Find exact row double b1, b2; int r = row; for (int i = 0;; i++) { if ( r == 0) { b2 = (cd->x_data[0][row] + cd->x_data[0][r+1]) / 2; if ( time < b2) break; r++; } else if ( r == cd->rows[0] - 1) { b1 = (cd->x_data[0][r] + cd->x_data[0][r-1]) / 2; if ( time >= b1) break; r--; } else { b1 = (cd->x_data[0][r] + cd->x_data[0][r-1]) / 2; b2 = (cd->x_data[0][r] + cd->x_data[0][r+1]) / 2; if ( b1 <= time && time < b2) break; if ( b1 <= time) r++; else r--; } if ( i > cd->rows[0]) { // Corrupt data, se original row r = row; break; } } row = r; } for ( int i = 0; i < cd->cols; i++) values[i] = cd->y_data[i][row]; *t = cd->x_data[0][row]; } else { // Time is a date if ( !cd->x_reverse) time = cd->x_min_value_axis[0] + x * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; else time = cd->x_min_value_axis[0] + (200.0 - x) * (cd->x_max_value_axis[0] - cd->x_min_value_axis[0]) / 200; // Approximate row for ( int j = 0; j < cd->cols; j++) { row = int ((time - cd->x_min_value[j]) / (cd->x_max_value[j] - cd->x_min_value[j]) * (cd->rows[j] - 1) + 0.5); if ( row > cd->rows[j] - 1) row = cd->rows[j] - 1; else if ( row < 0) row = 0; else { // Find exact row double b1, b2; int r = row; for (int i = 0;; i++) { if ( r == 0) { b2 = (cd->x_data[j][row] + cd->x_data[j][r+1]) / 2; if ( time < b2) break; r++; } else if ( r == cd->rows[j] - 1) { b1 = (cd->x_data[j][r] + cd->x_data[0][r-1]) / 2; if ( time >= b1) break; r--; } else { b1 = (cd->x_data[j][r] + cd->x_data[j][r-1]) / 2; b2 = (cd->x_data[j][r] + cd->x_data[j][r+1]) / 2; if ( b1 <= time && time < b2) break; if ( b1 <= time) r++; else r--; } if ( i > cd->rows[j]) { // Corrupt data, se original row r = row; break; } } row = r; } values[j] = cd->y_data[j][row]; if ( j == 0) *t = cd->x_data[j][row]; } } } void GeCurve::update_color_theme( int ct) { char color_theme_file[80]; int sts; sprintf( color_theme_file, "pwr_colortheme%d", ct); sts = grow_ReadCustomColorFile( grownames_ctx, color_theme_file); if ( EVEN(sts)) return; sts = grow_ReadCustomColorFile( growcurve_ctx, color_theme_file); if ( EVEN(sts)) return; sts = grow_ReadCustomColorFile( growaxis_ctx, color_theme_file); if ( EVEN(sts)) return; grow_SetDefaultColorTheme( color_theme_file); color_theme = ct; }