2740 lines
67 KiB
C
2740 lines
67 KiB
C
/* GKrellM
|
|
| Copyright (C) 1999-2007 Bill Wilson
|
|
|
|
|
| Author: Bill Wilson billw@gkrellm.net
|
|
| Latest versions might be found at: http://gkrellm.net
|
|
|
|
|
|
|
|
| GKrellM 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 3 of the License, or
|
|
| (at your option) any later version.
|
|
|
|
|
| GKrellM 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 this program. If not, see http://www.gnu.org/licenses/
|
|
*/
|
|
|
|
#include "gkrellm.h"
|
|
#include "gkrellm-private.h"
|
|
|
|
#include <math.h>
|
|
|
|
|
|
static void set_grid_resolution_spin_button(GkrellmChart *, gint);
|
|
|
|
|
|
/* For grid images of height 2 pixels, make room at bottom of chartdata
|
|
| window so both pixel lines will show.
|
|
*/
|
|
#define GRID_HEIGHT_Y_OFFSET_ADJUST(cp) \
|
|
(( gdk_pixbuf_get_height((cp)->bg_grid_piximage->pixbuf) < 2) ? 0 : 1)
|
|
|
|
/* Map internal y values with origin at lower left to X screen coordinates
|
|
| which have origin at upper left.
|
|
*/
|
|
#define Y_SCREEN_MAP(cp,y) ((cp)->h - (y) - 1)
|
|
|
|
|
|
#define MIN_CHARTHEIGHT 5
|
|
#define MAX_CHARTHEIGHT 200
|
|
|
|
static GList *chart_list;
|
|
|
|
// #define DEBUG1
|
|
// #define DEBUG2
|
|
// #define DEBUG3
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
static gint
|
|
computed_index(GkrellmChart *cp, gint i)
|
|
{
|
|
gint x;
|
|
|
|
x = (cp->position + i + 1) % cp->w;
|
|
return x;
|
|
}
|
|
|
|
GList *
|
|
gkrellm_get_chart_list()
|
|
{
|
|
return chart_list;
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_chart_scalemax(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return 0;
|
|
return cp->scale_max;
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_current_chartdata(GkrellmChartdata *cd)
|
|
{
|
|
if (!cd)
|
|
return 0;
|
|
return cd->data[cd->chart->position];
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_chartdata_data(GkrellmChartdata *cd, gint index)
|
|
{
|
|
gint x;
|
|
|
|
if (!cd)
|
|
return 0;
|
|
x = computed_index(cd->chart, index);
|
|
return cd->data[x];
|
|
}
|
|
|
|
void
|
|
gkrellm_clear_chart(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
if (cp->drawing_area->window)
|
|
gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
}
|
|
|
|
void
|
|
gkrellm_clear_chart_pixmap(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
}
|
|
|
|
void
|
|
gkrellm_clean_bg_src_pixmap(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
if (!gkrellm_winop_draw_rootpixmap_onto_transparent_chart(cp))
|
|
gdk_draw_drawable(cp->bg_src_pixmap, _GK.draw1_GC,
|
|
cp->bg_clean_pixmap, 0, 0, 0, 0, cp->w, cp->h);
|
|
cp->bg_sequence_id += 1;
|
|
}
|
|
|
|
void
|
|
gkrellm_draw_chart_grid_line(GkrellmChart *cp, GdkPixmap *pixmap, gint y)
|
|
{
|
|
gint h;
|
|
|
|
if (!cp)
|
|
return;
|
|
gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h);
|
|
gdk_draw_drawable(pixmap, _GK.draw1_GC,
|
|
cp->bg_grid_pixmap, 0, 0, cp->x, y, cp->w, h);
|
|
}
|
|
|
|
void
|
|
gkrellm_draw_chart_to_screen(GkrellmChart *cp)
|
|
{
|
|
/* Draw the expose pixmap onto the screen.
|
|
*/
|
|
if (cp && cp->drawing_area->window)
|
|
gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
}
|
|
|
|
static void
|
|
default_draw_chart_function(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
gkrellm_draw_chartdata(cp);
|
|
gkrellm_draw_chart_to_screen(cp);
|
|
}
|
|
|
|
void
|
|
gkrellm_set_draw_chart_function(GkrellmChart *cp, void (*func)(), gpointer data)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
cp->draw_chart = func;
|
|
cp->draw_chart_data = data;
|
|
}
|
|
|
|
void
|
|
gkrellm_scale_chartdata(GkrellmChartdata *cd, gint multiplier, gint divisor)
|
|
{
|
|
gint i;
|
|
|
|
if (!cd || !cd->data || divisor < 1)
|
|
return;
|
|
for (i = 0; i < cd->chart->w; ++i)
|
|
cd->data[i] = cd->data[i] * multiplier / divisor;
|
|
cd->previous = cd->previous * multiplier / divisor;
|
|
}
|
|
|
|
void
|
|
gkrellm_offset_chartdata(GkrellmChartdata *cd, gint offset)
|
|
{
|
|
gint i;
|
|
|
|
if (!cd || !cd->data)
|
|
return;
|
|
for (i = 0; i < cd->chart->w; ++i)
|
|
cd->data[i] = cd->data[i] + offset;
|
|
cd->previous = cd->previous + offset;
|
|
}
|
|
|
|
void
|
|
gkrellm_reset_chart(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint i;
|
|
|
|
cp->scale_max = 0;
|
|
cp->maxval = 0;
|
|
cp->redraw_all = TRUE;
|
|
cp->position = cp->w - 1;
|
|
cp->primed = FALSE;
|
|
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
cd->maxval = 0;
|
|
cd->previous = 0;
|
|
if (cd->data)
|
|
for (i = 0; i < cp->w; ++i)
|
|
cd->data[i] = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
gkrellm_reset_and_draw_chart(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
gkrellm_reset_chart(cp);
|
|
if (cp->draw_chart)
|
|
(*(cp->draw_chart))(cp->draw_chart_data);
|
|
}
|
|
|
|
void
|
|
gkrellm_monotonic_chartdata(GkrellmChartdata *cd, gboolean value)
|
|
{
|
|
if (cd)
|
|
cd->monotonic = value;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartdata_draw_style(GkrellmChartdata *cd, gint dstyle)
|
|
{
|
|
if (cd)
|
|
cd->draw_style = dstyle;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartdata_draw_style_default(GkrellmChartdata *cd, gint dstyle)
|
|
{
|
|
if (cd && cd->chart->config && !cd->chart->config->config_loaded)
|
|
cd->draw_style = dstyle;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartdata_flags(GkrellmChartdata *cd, gint flags)
|
|
{
|
|
if (cd)
|
|
cd->flags = flags;
|
|
}
|
|
|
|
static gint
|
|
chartdata_ycoord(GkrellmChart *cp, GkrellmChartdata *cd, gint yd)
|
|
{
|
|
glong y;
|
|
guint64 Y;
|
|
|
|
if (cp->scale_max <= 0)
|
|
cp->scale_max = 1;
|
|
|
|
if (yd > 2000000000 / MAX_CHARTHEIGHT)
|
|
{
|
|
Y = (guint64) yd * (guint64) cd->h;
|
|
y = Y / cp->scale_max;
|
|
}
|
|
else
|
|
y = ((glong) yd * cd->h / cp->scale_max);
|
|
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y >= cd->h)
|
|
y = cd->h - 1;
|
|
if (cd->inverted)
|
|
y = cd->h - y - 1;
|
|
y += cd->y;
|
|
return Y_SCREEN_MAP(cp, y);
|
|
}
|
|
|
|
static void
|
|
draw_layer_grid_lines(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint y, y0, h, grid_res, lines;
|
|
gint active_split, current_split;
|
|
gboolean do_next_split, done_once_per_split, tmp;
|
|
|
|
gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC,
|
|
cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h);
|
|
do_next_split = TRUE;
|
|
for (active_split = 0; do_next_split; ++active_split)
|
|
{
|
|
do_next_split = FALSE;
|
|
done_once_per_split = FALSE;
|
|
current_split = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
current_split += cd->split_chart;
|
|
if (active_split != current_split)
|
|
{
|
|
if (current_split > active_split)
|
|
do_next_split = TRUE;
|
|
continue;
|
|
}
|
|
gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC,
|
|
*(cd->layer.src_pixmap), 0, 0, 0, 0, cp->w, cp->h);
|
|
|
|
grid_res = cp->config->grid_resolution;
|
|
lines = cp->scale_max / grid_res;
|
|
if (lines && cd->h / lines > 2) /* No grids if h is too small */
|
|
{
|
|
for (y = 0; y <= cp->scale_max; y += grid_res)
|
|
{
|
|
if ( _GK.bg_grid_mode == GRID_MODE_RESTRAINED
|
|
&& ((y == 0 && cp->y == 0) || y == cp->scale_max)
|
|
)
|
|
continue;
|
|
tmp = cd->inverted; /* Draw grid lines in one direction*/
|
|
cd->inverted = FALSE; /* else, may not line up by 1 pixel*/
|
|
y0 = chartdata_ycoord(cp, cd, y);
|
|
cd->inverted = tmp;
|
|
gdk_drawable_get_size(cd->layer.grid_pixmap, NULL, &h);
|
|
gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC,
|
|
cd->layer.grid_pixmap, 0, 0, cp->x, y0, cp->w, h);
|
|
|
|
if (!done_once_per_split)
|
|
{
|
|
gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h);
|
|
gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC,
|
|
cp->bg_grid_pixmap, 0, 0, cp->x, y0, cp->w, h);
|
|
}
|
|
}
|
|
}
|
|
if (current_split > 0 && !done_once_per_split)
|
|
{
|
|
y = cd->y - 1; /* Get separator y value */
|
|
y -= GRID_HEIGHT_Y_OFFSET_ADJUST(cp);
|
|
if (y >= 0)
|
|
{
|
|
gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC,
|
|
_GK.bg_separator_pixmap,
|
|
0, 0, cp->x, Y_SCREEN_MAP(cp, y),
|
|
cp->w, _GK.bg_separator_height);
|
|
}
|
|
}
|
|
done_once_per_split = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return TRUE as long as there is a next split with impulse data needing
|
|
| to be drawn.
|
|
*/
|
|
static gboolean
|
|
draw_chartdata_impulses(GkrellmChart *cp, GList *cd_list,
|
|
gint i0, gint active_split)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint n, x, y, y0, y1, yN, yI;
|
|
gint current_split;
|
|
gboolean need_next_split = FALSE;
|
|
|
|
if (!cd_list)
|
|
return FALSE;
|
|
for (n = i0; n < cp->w; ++n)
|
|
{
|
|
x = computed_index(cp, n);
|
|
y0 = y1 = -1;
|
|
yN = yI = 0;
|
|
current_split = 0;
|
|
for (list = cp->cd_list; list; list= list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
current_split += cd->split_chart;
|
|
if ( cd->draw_style != CHARTDATA_IMPULSE
|
|
|| current_split != active_split
|
|
)
|
|
{
|
|
if ( current_split > active_split
|
|
&& cd->draw_style == CHARTDATA_IMPULSE
|
|
)
|
|
need_next_split = TRUE;
|
|
continue;
|
|
}
|
|
if (cd->inverted)
|
|
{
|
|
if (y1 < 0)
|
|
y1 = chartdata_ycoord(cp, cd, 0);
|
|
yI += cd->data[x];
|
|
y = chartdata_ycoord(cp, cd, yI);
|
|
if (cd->data[x] > 0)
|
|
gdk_draw_line(cd->data_bitmap, _GK.bit1_GC, n, y1, n, y);
|
|
y1 = y;
|
|
}
|
|
else
|
|
{
|
|
if (y0 < 0)
|
|
y0 = chartdata_ycoord(cp, cd, 0);
|
|
yN += cd->data[x];
|
|
y = chartdata_ycoord(cp, cd, yN);
|
|
if (cd->data[x] > 0)
|
|
gdk_draw_line(cd->data_bitmap, _GK.bit1_GC, n, y0, n, y);
|
|
y0 = y;
|
|
}
|
|
}
|
|
}
|
|
/* Push the grided pixmaps through the data bitmaps onto the expose pixmap
|
|
*/
|
|
current_split = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
current_split += cd->split_chart;
|
|
if (cd->draw_style == CHARTDATA_LINE || current_split != active_split)
|
|
continue;
|
|
if (cd->maxval > 0)
|
|
{
|
|
y0 = chartdata_ycoord(cp, cd, 0);
|
|
y1 = chartdata_ycoord(cp, cd, cd->maxval);
|
|
gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap);
|
|
if (cd->inverted)
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap,
|
|
0, y0, 0, y0, cp->w, y1 - y0 + 1);
|
|
else
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap,
|
|
0, y1, 0, y1, cp->w, y0 - y1 + 1);
|
|
}
|
|
}
|
|
return need_next_split;
|
|
}
|
|
|
|
static gint
|
|
fix_y(gint yn, gint yp, gint ypp)
|
|
{
|
|
gint y;
|
|
|
|
if (yp > ypp && yn < yp)
|
|
{
|
|
y = (yp + yn) / 2;
|
|
if (y < ypp)
|
|
y = ypp;
|
|
}
|
|
else if (yp < ypp && yn > yp)
|
|
{
|
|
y = (yp + yn) / 2;
|
|
if (y > ypp)
|
|
y = ypp;
|
|
}
|
|
else
|
|
y = yp;
|
|
return y;
|
|
}
|
|
|
|
static void
|
|
draw_chartdata_lines(GkrellmChart *cp, GkrellmChartdata *cd, gint i0)
|
|
{
|
|
gint n, x, xp, y, y0, y1;
|
|
|
|
y0 = chartdata_ycoord(cp, cd, 0);
|
|
for (n = i0; n < cp->w; ++n)
|
|
{
|
|
x = computed_index(cp, n);
|
|
y1 = chartdata_ycoord(cp, cd, cd->data[x]);
|
|
if (n == 0)
|
|
cd->y_p = y1;
|
|
else if (!cd->y_p_valid && i0 == cp->w - 1)
|
|
{
|
|
if ((xp = x - 1) < 0)
|
|
xp = cp->w - 1;
|
|
cd->y_p = cd->y_pp = chartdata_ycoord(cp, cd, cd->data[xp]);
|
|
}
|
|
y = fix_y(y1, cd->y_p, cd->y_pp);
|
|
cd->y_pp = y;
|
|
cd->y_p = y1;
|
|
cd->y_p_valid = FALSE; /* Need a store_chartdata to make it valid */
|
|
if (cd->data[x] > 0 || (cd->inverted ? (y > y0) : (y < y0)))
|
|
{
|
|
if (y == y1)
|
|
gdk_draw_point(cd->data_bitmap, _GK.bit1_GC, cp->x + n, y1);
|
|
else
|
|
gdk_draw_line(cd->data_bitmap, _GK.bit1_GC,
|
|
cp->x + n, y, cp->x + n, y1);
|
|
}
|
|
}
|
|
/* Push the grided pixmap through the data bitmap onto the expose pixmap
|
|
*/
|
|
if (cd->maxval > 0)
|
|
{
|
|
y0 = chartdata_ycoord(cp, cd, 0);
|
|
y1 = chartdata_ycoord(cp, cd, cd->maxval);
|
|
gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap);
|
|
if (cd->inverted)
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap,
|
|
0, y0, 0, y0, cp->w, y1 - y0 + 1);
|
|
else
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap,
|
|
0, y1, 0, y1, cp->w, y0 - y1 + 1);
|
|
}
|
|
}
|
|
|
|
/* See the README for description of auto grid resolution behavior.
|
|
*/
|
|
static void
|
|
set_auto_grid_resolution(GkrellmChart *cp, gint maxval)
|
|
{
|
|
GkrellmChartconfig *cf = cp->config;
|
|
gint grids, grid_res, maxval_base;
|
|
|
|
if (maxval <= cp->maxval_auto_base)
|
|
maxval = cp->maxval_auto_base;
|
|
else
|
|
{
|
|
if (maxval > cp->maxval_peak)
|
|
cp->maxval_peak = maxval;
|
|
maxval_base = maxval / FULL_SCALE_GRIDS;
|
|
if (maxval_base > cp->maxval_auto_base)
|
|
cp->maxval_auto_base = maxval_base;
|
|
}
|
|
cp->maxval_auto = maxval;
|
|
|
|
grids = cf->fixed_grids;
|
|
if (grids == 0) /* Auto grids mode */
|
|
grid_res = gkrellm_125_sequence(cp->maxval_auto_base, cf->sequence_125,
|
|
cf->low, cf->high, TRUE, FALSE);
|
|
else
|
|
{
|
|
if (cf->auto_resolution_stick)
|
|
maxval = cp->maxval_peak;
|
|
grid_res = gkrellm_125_sequence(maxval / grids, cf->sequence_125,
|
|
cf->low, cf->high, TRUE, TRUE);
|
|
}
|
|
if (grid_res != cf->grid_resolution)
|
|
{
|
|
cf->grid_resolution = grid_res;
|
|
set_grid_resolution_spin_button(cp, grid_res);
|
|
if (cf->cb_grid_resolution && !cf->cb_block)
|
|
(*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data);
|
|
cp->redraw_all = TRUE;
|
|
}
|
|
cp->auto_recalibrate_delay = 0;
|
|
}
|
|
|
|
static gboolean
|
|
auto_recalibrate(GkrellmChart *cp)
|
|
{
|
|
if (++cp->auto_recalibrate_delay < 10)
|
|
return FALSE;
|
|
cp->maxval_peak = 0;
|
|
cp->maxval_auto_base = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
static gint
|
|
setup_chart_scalemax(GkrellmChart *cp)
|
|
{
|
|
GkrellmChartconfig *cf = cp->config;
|
|
glong scalemax;
|
|
gint grid_res, i0;
|
|
|
|
/* maxval may change at any gkrellm_store_chartdata(), so at each chart
|
|
| draw compute a scalemax and compare to last cp->scale_max.
|
|
| Redraw grided background if different.
|
|
*/
|
|
if (cf->auto_grid_resolution)
|
|
{
|
|
if ( cp->maxval != cp->maxval_auto
|
|
&& ( cp->maxval > cp->maxval_auto
|
|
|| cp->maxval_auto != cp->maxval_auto_base
|
|
)
|
|
)
|
|
set_auto_grid_resolution(cp, cp->maxval);
|
|
else if ( !cf->auto_resolution_stick
|
|
&& cp->maxval < cp->maxval_auto_base / FULL_SCALE_GRIDS
|
|
)
|
|
{
|
|
if (auto_recalibrate(cp))
|
|
set_auto_grid_resolution(cp, cp->maxval);
|
|
}
|
|
else
|
|
cp->auto_recalibrate_delay = 0;
|
|
}
|
|
grid_res = cf->grid_resolution;
|
|
if (cf->fixed_grids)
|
|
scalemax = grid_res * cf->fixed_grids;
|
|
else /* Auto scale to cp->maxval */
|
|
{
|
|
if (cp->maxval == 0)
|
|
scalemax = grid_res;
|
|
else
|
|
scalemax = ((cp->maxval - 1) / grid_res + 1) * grid_res;
|
|
if (cp->previous_total && scalemax > grid_res * FULL_SCALE_GRIDS)
|
|
scalemax = grid_res * FULL_SCALE_GRIDS;
|
|
}
|
|
if (scalemax != cp->scale_max || cp->redraw_all)
|
|
{
|
|
cp->redraw_all = FALSE;
|
|
i0 = 0; /* Will draw all data on chart */
|
|
cp->scale_max = scalemax;
|
|
draw_layer_grid_lines(cp);
|
|
}
|
|
else
|
|
i0 = cp->w - 1; /* Will draw the last data point only */
|
|
return i0;
|
|
}
|
|
|
|
void
|
|
gkrellm_draw_chartdata(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint i0, active_split, current_split;
|
|
gboolean have_impulse_splits = FALSE;
|
|
|
|
if (!cp)
|
|
return;
|
|
i0 = setup_chart_scalemax(cp);
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_pixmap,
|
|
0, 0, 0, 0, cp->w, cp->h);
|
|
|
|
current_split = active_split = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
current_split += cd->split_chart;
|
|
if (!have_impulse_splits && cd->draw_style == CHARTDATA_IMPULSE)
|
|
{
|
|
have_impulse_splits = TRUE;
|
|
active_split = current_split;
|
|
}
|
|
/* Clear the area of the data bitmaps that data will be drawn into
|
|
*/
|
|
gdk_draw_rectangle(cd->data_bitmap, _GK.bit0_GC, TRUE,
|
|
i0, 0, cd->w - i0, cp->h);
|
|
}
|
|
|
|
for ( ; have_impulse_splits; ++active_split)
|
|
have_impulse_splits = draw_chartdata_impulses(cp, cp->cd_list,
|
|
i0, active_split);
|
|
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->draw_style == CHARTDATA_LINE && !cd->hide)
|
|
draw_chartdata_lines(cp, cd, i0);
|
|
}
|
|
gdk_gc_set_clip_mask(_GK.draw1_GC, NULL);
|
|
}
|
|
|
|
void
|
|
gkrellm_alloc_chartdata(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
size_t w;
|
|
|
|
if (!cp)
|
|
return;
|
|
w = (size_t) cp->w;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->w == w && cd->data)
|
|
continue;
|
|
cd->w = w;
|
|
if (cd->data)
|
|
g_free(cd->data);
|
|
cd->data = (gint *) g_new0(gint, w);
|
|
cd->maxval = 0;
|
|
cp->position = cp->w - 1;
|
|
cp->tail = cp->position;
|
|
}
|
|
cp->alloc_width = w;
|
|
cp->maxval = 0;
|
|
cp->scale_max = 0;
|
|
cp->redraw_all = TRUE;
|
|
}
|
|
|
|
static void
|
|
scroll_chartdata_bitmaps(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
gdk_draw_drawable(cd->data_bitmap, _GK.bit1_GC, cd->data_bitmap,
|
|
1, 0, 0, 0, cp->w - 1, cp->h);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
scan_for_impulse_maxval(GkrellmChart *cp, gint active_split)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint N, I;
|
|
gint i, current_split;
|
|
gboolean need_next_split = FALSE;
|
|
|
|
for (i = 0; i < cp->w; ++i)
|
|
{
|
|
/* N is normal and I inverted cumulative impulse data/split
|
|
*/
|
|
N = I = 0;
|
|
current_split = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
current_split += cd->split_chart;
|
|
if ( cd->draw_style != CHARTDATA_IMPULSE
|
|
|| current_split != active_split
|
|
)
|
|
{
|
|
if ( current_split > active_split
|
|
&& cd->draw_style == CHARTDATA_IMPULSE
|
|
)
|
|
need_next_split = TRUE;
|
|
continue;
|
|
}
|
|
if (cd->inverted)
|
|
{
|
|
I += cd->data[i];
|
|
if (I > cd->maxval)
|
|
cd->maxval = I;
|
|
}
|
|
else
|
|
{
|
|
N += cd->data[i];
|
|
if (N > cd->maxval)
|
|
cd->maxval = N;
|
|
}
|
|
if (N + I > cp->maxval)
|
|
cp->maxval = N + I;
|
|
}
|
|
}
|
|
return need_next_split;
|
|
}
|
|
|
|
static void
|
|
scan_for_maxval(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint i, current_split, active_split;
|
|
gboolean have_impulse_splits = FALSE;
|
|
|
|
cp->maxval = 0;
|
|
current_split = 0;
|
|
active_split = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
cd->maxval = 0;
|
|
current_split += cd->split_chart;
|
|
if (cd->draw_style == CHARTDATA_LINE)
|
|
for (i = 0; i < cp->w; ++i)
|
|
{
|
|
if (cd->data[i] > cd->maxval)
|
|
cd->maxval = cd->data[i];
|
|
if (cd->maxval > cp->maxval)
|
|
cp->maxval = cd->maxval;
|
|
}
|
|
if (!have_impulse_splits && cd->draw_style == CHARTDATA_IMPULSE)
|
|
{
|
|
have_impulse_splits = TRUE;
|
|
active_split = current_split;
|
|
}
|
|
}
|
|
for ( ; have_impulse_splits; ++active_split)
|
|
have_impulse_splits = scan_for_impulse_maxval(cp, active_split);
|
|
}
|
|
|
|
void
|
|
gkrellm_store_chartdata(GkrellmChart *cp, gulong total, ...)
|
|
{
|
|
va_list args;
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gulong range, total_diff;
|
|
gint n, N_discard, I_discard, N, I;
|
|
gint active_split, current_split;
|
|
gboolean need_scan = FALSE;
|
|
|
|
if (!cp)
|
|
return;
|
|
va_start(args, total);
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
cd->current = va_arg(args, gulong);
|
|
if (!cd->monotonic)
|
|
{
|
|
cd->previous = 0;
|
|
cp->previous_total = 0; /* All or none if total is used */
|
|
}
|
|
/* Prime the pump. Also handle data wrap around or reset to zero.
|
|
*/
|
|
if (cd->current < cd->previous || !cp->primed)
|
|
cd->previous = cd->current;
|
|
}
|
|
va_end(args);
|
|
if (total < cp->previous_total || !cp->primed)
|
|
cp->previous_total = total; /* Wrap around, this store won't scale */
|
|
total_diff = total - cp->previous_total;
|
|
cp->previous_total = total;
|
|
|
|
/* Increment position in circular buffer and remember the data
|
|
| value to be thrown out.
|
|
*/
|
|
cp->position = (cp->position + 1) % cp->w;
|
|
cp->tail = (cp->tail + 1) % cp->w;
|
|
n = cp->position;
|
|
active_split = current_split = 0;
|
|
N_discard = I_discard = 0;
|
|
|
|
/* N is normal and I inverted cumulative impulse data/split
|
|
*/
|
|
N = I = 0;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
cd->discard = cd->data[cp->tail];
|
|
cd->data[n] = (gint)(cd->current - cd->previous);
|
|
cd->previous = cd->current;
|
|
|
|
/* If using totals, scale the stored data to range between 0 and the
|
|
| max chart value. Max chart value is number of grids * grid res.
|
|
| No. of grids is 5 in auto grid mode. For plotting data as a %.
|
|
*/
|
|
if (total_diff > 0)
|
|
{
|
|
range = (cp->config->fixed_grids ? cp->config->fixed_grids
|
|
: FULL_SCALE_GRIDS) * cp->config->grid_resolution;
|
|
if (range != total_diff)
|
|
cd->data[n] = cd->data[n] * range / total_diff;
|
|
}
|
|
if (cd->hide || need_scan)
|
|
continue;
|
|
|
|
/* Compare discarded data to new data (accounting for stacked impulse
|
|
| data) and decide if a new maxval must be set (new data > maxval)
|
|
| or if a complete rescan of the data is needed to find a new
|
|
| maxval (a discard > a new).
|
|
*/
|
|
current_split += cd->split_chart;
|
|
if (cd->draw_style == CHARTDATA_IMPULSE)
|
|
{
|
|
if (current_split != active_split)
|
|
{
|
|
active_split = current_split;
|
|
N_discard = I_discard = 0;
|
|
N = I = 0;
|
|
}
|
|
if (cd->inverted)
|
|
{
|
|
I_discard += cd->discard;
|
|
I += cd->data[n];
|
|
if (I_discard && I_discard >= cd->maxval)
|
|
need_scan = TRUE;
|
|
else if (I > cd->maxval)
|
|
cd->maxval = I;
|
|
}
|
|
else
|
|
{
|
|
N_discard += cd->discard;
|
|
N += cd->data[n];
|
|
if (N_discard && N_discard >= cd->maxval)
|
|
need_scan = TRUE;
|
|
else if (N > cd->maxval)
|
|
cd->maxval = N;
|
|
}
|
|
if (N_discard + I_discard >= cd->maxval)
|
|
need_scan = TRUE;
|
|
else if (N + I > cp->maxval)
|
|
cp->maxval = N + I;
|
|
}
|
|
else if (cd->draw_style == CHARTDATA_LINE)
|
|
{
|
|
cd->y_p_valid = TRUE;
|
|
if (cd->discard && cd->discard >= cd->maxval)
|
|
need_scan = TRUE;
|
|
else
|
|
{
|
|
if (cd->data[n] > cd->maxval)
|
|
cd->maxval = cd->data[n];
|
|
if (cd->maxval > cp->maxval)
|
|
cp->maxval = cd->maxval;
|
|
}
|
|
}
|
|
}
|
|
cp->primed = TRUE;
|
|
if (need_scan || cp->redraw_all)
|
|
scan_for_maxval(cp);
|
|
scroll_chartdata_bitmaps(cp);
|
|
}
|
|
|
|
|
|
|
|
/* =================================================================== */
|
|
|
|
static void
|
|
chart_destroy_text_run_list(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
|
|
if (!cp || !cp->text_run_list)
|
|
return;
|
|
for (list = cp->text_run_list; list; list = list->next)
|
|
g_free(((GkrellmTextRun *) list->data)->text);
|
|
gkrellm_free_glist_and_data(&cp->text_run_list);
|
|
}
|
|
|
|
static gint
|
|
chartdata_text_y(GkrellmChart *cp, char key, gint height,
|
|
gint y_ink, gint shadow)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
gint n, y;
|
|
|
|
n = key - '0';
|
|
y = -100;
|
|
if (n >= 0)
|
|
{
|
|
list = g_list_nth(cp->cd_list, n / 2);
|
|
if (list)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (!cd->hide)
|
|
{
|
|
if (n & 1) /* Justify 2 pixels from top of ChartData view */
|
|
{
|
|
y = cd->y + cd->h + y_ink - 3;
|
|
}
|
|
else /* Justify to bottom of ChartData view */
|
|
{
|
|
y = cd->y + height + y_ink + shadow - 1;
|
|
}
|
|
y = Y_SCREEN_MAP(cp, y);
|
|
}
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_reuse_text_format(GkrellmChart *cp)
|
|
{
|
|
cp->text_format_reuse = TRUE;
|
|
}
|
|
|
|
void
|
|
gkrellm_draw_chart_text(GkrellmChart *cp, gint style_id, gchar *str)
|
|
{
|
|
GList *list;
|
|
GkrellmTextRun *tr;
|
|
GkrellmTextstyle *ts, *ts_default, *ts_alt;
|
|
gchar c, *s, *t;
|
|
gint h, text_length, field_width, fw;
|
|
gint offset;
|
|
gint xx, x, y, center, shadow;
|
|
gboolean right, set_fw, fw_right;
|
|
|
|
if (!cp || !str)
|
|
return;
|
|
|
|
/* Assume text_format will be changed at each call unless caller has said
|
|
| we can reuse it or the whole string compares equal.
|
|
*/
|
|
if ( !cp->text_format_reuse
|
|
&& !gkrellm_dup_string(&cp->text_format_string, str)
|
|
)
|
|
cp->text_format_reuse = TRUE;
|
|
|
|
if (_GK.debug_level & DEBUG_CHART_TEXT)
|
|
{
|
|
printf("\n");
|
|
if (!cp->text_format_reuse)
|
|
printf("draw_chart_text: [%s]\n", str);
|
|
}
|
|
|
|
if ( !cp->text_format_reuse
|
|
|| cp->text_run_sequence_id != cp->bg_sequence_id
|
|
)
|
|
chart_destroy_text_run_list(cp);
|
|
cp->text_run_sequence_id = cp->bg_sequence_id;
|
|
cp->text_format_reuse = FALSE;
|
|
|
|
ts_default = gkrellm_chart_textstyle(style_id);
|
|
ts_alt = gkrellm_chart_alt_textstyle(style_id);
|
|
|
|
x = xx = 2;
|
|
if (!cp->text_run_list)
|
|
gkrellm_text_extents(ts_default->font, _("Ag8"), 3, NULL,
|
|
&cp->h_text, &cp->baseline_ref, &cp->y_ink);
|
|
|
|
y = 2 - cp->y_ink;
|
|
h = fw = 0;
|
|
tr = NULL;
|
|
for (list = cp->text_run_list, s = str; *s; s += text_length)
|
|
{
|
|
if (!list)
|
|
{
|
|
tr = g_new0(GkrellmTextRun, 1);
|
|
cp->text_run_list = g_list_append(cp->text_run_list, tr);
|
|
}
|
|
else
|
|
{
|
|
tr = (GkrellmTextRun *) list->data;
|
|
list = list->next;
|
|
tr->cache_valid = TRUE;
|
|
}
|
|
c = '\0';
|
|
center = 0;
|
|
right = FALSE;
|
|
set_fw = FALSE;
|
|
fw_right = FALSE;
|
|
ts = ts_default;
|
|
field_width = 0;
|
|
shadow = ts_default->effect ? 1 : 0;
|
|
while (*s == '\\')
|
|
{
|
|
if ((c = *(++s)) != '\0')
|
|
++s;
|
|
if (c == 'n')
|
|
{
|
|
y += cp->h_text + 1;
|
|
x = xx;
|
|
}
|
|
else if (c == 'c')
|
|
center = 1;
|
|
else if (c == 'C')
|
|
center = 2;
|
|
else if (c == 'N')
|
|
{
|
|
x = xx; /* A conditional newline. If previous string */
|
|
if (h > 2) /* was spaces, no nl. A space has nonzero a */
|
|
y += cp->h_text + 1;
|
|
}
|
|
else if (c == 'b')
|
|
{
|
|
y = cp->h - cp->h_text - cp->y_ink - 1;
|
|
x = xx;
|
|
}
|
|
else if (c == 't')
|
|
{
|
|
y = 2 - cp->y_ink;
|
|
x = xx;
|
|
}
|
|
else if (c == 'r')
|
|
right = TRUE;
|
|
else if (c == 'p')
|
|
{
|
|
y -= cp->h_text + 1;
|
|
x = xx;
|
|
}
|
|
else if (c == 'w')
|
|
set_fw = TRUE;
|
|
else if (c == 'a')
|
|
field_width = fw;
|
|
else if (c == 'e')
|
|
{
|
|
field_width = fw;
|
|
fw_right = TRUE;
|
|
}
|
|
else if (c == 'f')
|
|
{
|
|
ts = ts_alt;
|
|
shadow = ts_alt->effect ? 1 : 0;
|
|
}
|
|
else if (c == 'x' && isdigit((unsigned char)*s))
|
|
xx = *s++ - '0';
|
|
else if (c == 'y' && isdigit((unsigned char)*s))
|
|
y = *s++ - '0';
|
|
else if (c == 'D')
|
|
{
|
|
y = chartdata_text_y(cp, *s++, cp->h_text, cp->y_ink, shadow);
|
|
x = xx;
|
|
}
|
|
}
|
|
t = strchr(s, (gint) '\\');
|
|
if (t)
|
|
text_length = t - s;
|
|
else
|
|
text_length = strlen(s);
|
|
|
|
if (y == -100) /* asked for a chartdata that is hidden */
|
|
continue;
|
|
|
|
if ( !tr->cache_valid || !tr->text
|
|
|| strncmp(tr->text, s, text_length)
|
|
|| strlen(tr->text) != text_length
|
|
)
|
|
{
|
|
gkrellm_text_extents(ts->font, s, text_length,
|
|
&tr->w, &tr->h, &tr->baseline, &tr->y_ink);
|
|
tr->cache_valid = FALSE;
|
|
g_free(tr->text);
|
|
tr->text = g_strndup(s, text_length);
|
|
}
|
|
h = tr->h;
|
|
|
|
if (set_fw)
|
|
{
|
|
fw = tr->w + shadow;
|
|
continue;
|
|
}
|
|
if (center == 1)
|
|
x = (cp->w - tr->w) / 2;
|
|
else if (center == 2)
|
|
x = cp->w / 2;
|
|
else if (fw_right)
|
|
x = x + fw - tr->w - shadow;
|
|
else if (right)
|
|
x = cp->w - tr->w - 2 - shadow;
|
|
if (text_length > 1 || (text_length == 1 && *s != ' '))
|
|
{
|
|
if (x != tr->x || y != tr->y)
|
|
tr->cache_valid = FALSE;
|
|
tr->x = x;
|
|
tr->y = y;
|
|
|
|
if (_GK.debug_level & DEBUG_CHART_TEXT)
|
|
{
|
|
gchar buf[128];
|
|
|
|
strncpy(buf, s, text_length);
|
|
buf[text_length] = '\0';
|
|
printf("draw_chart_text: [%s] ", buf);
|
|
}
|
|
|
|
offset = cp->baseline_ref - tr->baseline; /* align baselines */
|
|
if (_GK.chart_text_no_fill)
|
|
gkrellm_draw_text(cp->pixmap, ts, x, y + offset, s,
|
|
text_length);
|
|
else /* Default text draw effect is fill solid and can use cache */
|
|
{
|
|
if (!tr->cache_valid)
|
|
{
|
|
if (_GK.debug_level & DEBUG_CHART_TEXT)
|
|
printf("pango ");
|
|
gdk_draw_drawable(cp->bg_text_pixmap, _GK.draw1_GC,
|
|
cp->bg_pixmap,
|
|
x - 1, y + tr->y_ink + offset - 1,
|
|
x - 1, y + tr->y_ink + offset - 1,
|
|
tr->w + shadow + 2, tr->h + shadow + 1);
|
|
gkrellm_draw_text(cp->bg_text_pixmap, ts, x, y + offset, s,
|
|
text_length);
|
|
}
|
|
if (_GK.debug_level & DEBUG_CHART_TEXT)
|
|
printf("x=%d y=%d w=%d h=%d\n",
|
|
x - 1, y + tr->y_ink + offset - 1,
|
|
tr->w + shadow + 2, tr->h + shadow + 1);
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_text_pixmap,
|
|
x - 1, y + tr->y_ink + offset - 1,
|
|
x - 1, y + tr->y_ink + offset - 1,
|
|
tr->w + shadow + 2, tr->h + shadow + 1);
|
|
}
|
|
}
|
|
if (field_width && !fw_right)
|
|
x += (field_width > tr->w) ? field_width : tr->w;
|
|
else
|
|
x += tr->w + shadow;
|
|
}
|
|
}
|
|
|
|
gint
|
|
gkrellm_draw_chart_label(GkrellmChart *cp, GkrellmTextstyle *ts,
|
|
gint x, gint y, gchar *s)
|
|
{
|
|
gint w, h, y_ink;
|
|
|
|
if (!cp || !ts || !s)
|
|
return x;
|
|
|
|
gkrellm_text_extents(ts->font, s, strlen(s), &w, &h, NULL, &y_ink);
|
|
|
|
gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_pixmap,
|
|
x, y, x, y, w + ts->effect, h + ts->effect);
|
|
gkrellm_draw_string(cp->pixmap, ts, x, y - y_ink, s);
|
|
|
|
return x + w + ts->effect;
|
|
}
|
|
|
|
void
|
|
gkrellm_destroy_chartdata_list(GList **cd_list_head)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
if (!cd_list_head)
|
|
return;
|
|
for (list = *cd_list_head; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->label)
|
|
g_free(cd->label);
|
|
if (cd->data)
|
|
g_free(cd->data);
|
|
if (cd->data_bitmap)
|
|
g_object_unref(G_OBJECT(cd->data_bitmap));
|
|
if (cd->layer.pixmap)
|
|
g_object_unref(G_OBJECT(cd->layer.pixmap));
|
|
/* cd->layer.src_pixmap & cd->layer.grid_pixmap must be handled by
|
|
| creating monitor.
|
|
*/
|
|
}
|
|
gkrellm_free_glist_and_data(cd_list_head);
|
|
}
|
|
|
|
|
|
static void
|
|
free_chart_pixmaps(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
gkrellm_free_bitmap(&cd->data_bitmap);
|
|
gkrellm_free_pixmap(&cd->layer.pixmap);
|
|
/* cd->layer.src_pixmap & cd->layer.grid_pixmap must be handled by
|
|
| creating monitor.
|
|
*/
|
|
}
|
|
/* If new theme or size, the cd_list will not be destroyed so I can
|
|
| reuse the data arrays. Pixmaps will be recreated.
|
|
*/
|
|
cp->cd_list_index = 0;
|
|
|
|
gkrellm_free_pixmap(&cp->bg_pixmap);
|
|
gkrellm_free_pixmap(&cp->bg_text_pixmap);
|
|
gkrellm_free_pixmap(&cp->bg_src_pixmap);
|
|
gkrellm_free_pixmap(&cp->bg_grid_pixmap);
|
|
|
|
gkrellm_free_pixmap(&cp->bg_clean_pixmap);
|
|
gkrellm_free_bitmap(&cp->bg_mask);
|
|
|
|
gkrellm_free_pixmap(&cp->pixmap);
|
|
|
|
gkrellm_free_pixmap(&cp->top_spacer.clean_pixmap);
|
|
gkrellm_free_pixmap(&cp->top_spacer.pixmap);
|
|
gkrellm_free_bitmap(&cp->top_spacer.mask);
|
|
gkrellm_free_pixmap(&cp->bottom_spacer.clean_pixmap);
|
|
gkrellm_free_pixmap(&cp->bottom_spacer.pixmap);
|
|
gkrellm_free_bitmap(&cp->bottom_spacer.mask);
|
|
}
|
|
|
|
static void
|
|
destroy_chart_data(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
free_chart_pixmaps(cp);
|
|
chart_destroy_text_run_list(cp);
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->label)
|
|
g_free(cd->label);
|
|
if (cd->data)
|
|
g_free(cd->data);
|
|
cd->label = NULL;
|
|
cd->data = NULL;
|
|
}
|
|
/* Don't free the cd_list. It is in the GkrellmChartconfig struct.
|
|
*/
|
|
}
|
|
|
|
/* Destroy everything inside a chart except leave cp->config alone since
|
|
| the config is managed by each monitor.
|
|
*/
|
|
void
|
|
gkrellm_chart_destroy(GkrellmChart *cp)
|
|
{
|
|
gint h_spacers = 0;
|
|
|
|
if (!cp)
|
|
return;
|
|
|
|
if (cp->top_spacer.image)
|
|
h_spacers = cp->top_spacer.height;
|
|
if (cp->bottom_spacer.image)
|
|
h_spacers += cp->bottom_spacer.height;
|
|
|
|
gkrellm_freeze_side_frame_packing();
|
|
if (cp->panel)
|
|
gkrellm_panel_destroy(cp->panel);
|
|
destroy_chart_data(cp);
|
|
gtk_widget_destroy(cp->box);
|
|
chart_list = g_list_remove(chart_list, cp);
|
|
gkrellm_chartconfig_window_destroy(cp);
|
|
if (cp->shown)
|
|
gkrellm_monitor_height_adjust(-(cp->h + h_spacers));
|
|
g_free(cp);
|
|
gkrellm_thaw_side_frame_packing();
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_destroy(GkrellmChartconfig **cf)
|
|
{
|
|
if (!cf || !*cf)
|
|
return;
|
|
gkrellm_destroy_chartdata_list((*cf)->chart_cd_list);
|
|
g_free(*cf);
|
|
*cf = NULL;
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_bg_piximage_override(GkrellmChart *cp,
|
|
GkrellmPiximage *bg_piximage, GkrellmPiximage *bg_grid_piximage)
|
|
{
|
|
if (!cp || !bg_piximage || !bg_grid_piximage)
|
|
return;
|
|
cp->bg_piximage = bg_piximage;
|
|
cp->bg_grid_piximage = bg_grid_piximage;
|
|
cp->bg_piximage_override = TRUE;
|
|
}
|
|
|
|
|
|
static void
|
|
set_chartdata_split_heights(GkrellmChart *cp)
|
|
{
|
|
GList *list, *list1;
|
|
GkrellmChartdata *cd, *cd1;
|
|
gint splits;
|
|
gint i, y0, h_avail, h_free, y_offset;
|
|
|
|
for (i = 0, splits = 0, list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
if (++i > 1 && cd->split_chart) /* Can't split before the first one */
|
|
++splits;
|
|
cd->split_share = 1.0;
|
|
for (list1 = list->next; list1; list1 = list1->next)
|
|
{
|
|
cd1 = (GkrellmChartdata *) list1->data;
|
|
if (!cd1->split_chart || cd1->hide)
|
|
continue;
|
|
cd->split_share = cd1->split_fraction;
|
|
break;
|
|
}
|
|
}
|
|
y_offset = GRID_HEIGHT_Y_OFFSET_ADJUST(cp);
|
|
y0 = cp->y + y_offset;
|
|
h_avail = cp->h - cp->y - ((splits + 1) * y_offset)
|
|
- splits * _GK.bg_separator_height;
|
|
h_free = h_avail;
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if (cd->hide)
|
|
continue;
|
|
cd->y = y0;
|
|
for (list1 = list->next; list1; list1 = list1->next)
|
|
if (!((GkrellmChartdata *) list1->data)->hide)
|
|
break;
|
|
if (!list1)
|
|
cd->h = h_free;
|
|
else
|
|
cd->h = (gint) (cd->split_share * (gfloat) h_free);
|
|
if (cd->h < 1)
|
|
cd->h = 1;
|
|
if (list1 && ((GkrellmChartdata *) list1->data)->split_chart)
|
|
{
|
|
y0 += cd->h + _GK.bg_separator_height + y_offset;
|
|
h_free -= cd->h;
|
|
}
|
|
}
|
|
}
|
|
|
|
GkrellmChartdata *
|
|
gkrellm_add_default_chartdata(GkrellmChart *cp, gchar *label)
|
|
{
|
|
GdkPixmap **src_pixmap, *grid_pixmap;
|
|
|
|
if (!cp)
|
|
return NULL;
|
|
if (cp->cd_list_index & 1)
|
|
{
|
|
src_pixmap = &_GK.data_in_pixmap;
|
|
grid_pixmap = _GK.data_in_grid_pixmap;
|
|
}
|
|
else
|
|
{
|
|
src_pixmap = &_GK.data_out_pixmap;
|
|
grid_pixmap = _GK.data_out_grid_pixmap;
|
|
}
|
|
return gkrellm_add_chartdata(cp, src_pixmap, grid_pixmap, label);
|
|
}
|
|
|
|
/* Need a GdkPixmap ** because the src pixmap can change (re-rendered at
|
|
| size or theme changes).
|
|
*/
|
|
GkrellmChartdata *
|
|
gkrellm_add_chartdata(GkrellmChart *cp, GdkPixmap **src_pixmap,
|
|
GdkPixmap *grid_pixmap, gchar *label)
|
|
{
|
|
GtkWidget *top_win = gkrellm_get_top_window();
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
if (!cp || !src_pixmap || !grid_pixmap || !label)
|
|
return NULL;
|
|
|
|
/* To handle theme and vert size changes without loosing data, reuse the
|
|
| GkrellmChartdata structs in the cd_list.
|
|
*/
|
|
list = g_list_nth(cp->cd_list, cp->cd_list_index++);
|
|
if (!list)
|
|
{
|
|
cd = g_new0(GkrellmChartdata, 1);
|
|
cp->cd_list = g_list_append(cp->cd_list, cd);
|
|
cp->config->cd_list = cp->cd_list;
|
|
cd->split_fraction = 0.5;
|
|
}
|
|
else
|
|
cd = (GkrellmChartdata *) list->data;
|
|
cd->chart = cp;
|
|
gkrellm_dup_string(&cd->label, label);
|
|
cd->monotonic = TRUE;
|
|
cd->data_bitmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, 1);
|
|
cd->layer.pixmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, -1);
|
|
cd->layer.src_pixmap = src_pixmap;
|
|
cd->layer.grid_pixmap = grid_pixmap;
|
|
|
|
set_chartdata_split_heights(cp);
|
|
return cd;
|
|
}
|
|
|
|
void
|
|
gkrellm_render_data_grid_pixmap(GkrellmPiximage *im, GdkPixmap **pixmap,
|
|
GdkColor *color)
|
|
{
|
|
GtkWidget *top_win = gkrellm_get_top_window();
|
|
gint w, w_pixmap = 0, h = 0;
|
|
|
|
w = gkrellm_chart_width();
|
|
if (*pixmap)
|
|
gdk_drawable_get_size(*pixmap, &w_pixmap, NULL);
|
|
if (!*pixmap || w != w_pixmap)
|
|
{
|
|
if (im)
|
|
{
|
|
if ((h = gdk_pixbuf_get_height(im->pixbuf)) > 2)
|
|
h = 2;
|
|
gkrellm_scale_piximage_to_pixmap(im, pixmap, NULL, w, h);
|
|
}
|
|
else
|
|
{
|
|
gkrellm_free_pixmap(pixmap);
|
|
*pixmap = gdk_pixmap_new(top_win->window, w, 1, -1);
|
|
if (color)
|
|
gdk_gc_set_foreground(_GK.draw1_GC, color);
|
|
else
|
|
gdk_gc_set_foreground(_GK.draw1_GC, &_GK.in_color_grid);
|
|
gdk_draw_rectangle(*pixmap, _GK.draw1_GC, TRUE, 0, 0, w, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gkrellm_render_data_pixmap(GkrellmPiximage *im, GdkPixmap **pixmap,
|
|
GdkColor *color, gint h)
|
|
{
|
|
GtkWidget *top_win = gkrellm_get_top_window();
|
|
gint w, w_pixmap = 0, h_pixmap = 0;
|
|
|
|
w = gkrellm_chart_width();
|
|
if (*pixmap)
|
|
gdk_drawable_get_size(*pixmap, &w_pixmap, &h_pixmap);
|
|
|
|
if (!*pixmap || w != w_pixmap || h != h_pixmap)
|
|
{
|
|
if (!gkrellm_scale_piximage_to_pixmap(im, pixmap, NULL, w, h))
|
|
{
|
|
*pixmap = gdk_pixmap_new(top_win->window, w, h, -1);
|
|
if (color)
|
|
gdk_gc_set_foreground(_GK.draw1_GC, color);
|
|
else
|
|
gdk_gc_set_foreground(_GK.draw1_GC, &_GK.in_color_grid);
|
|
gdk_draw_rectangle(*pixmap, _GK.draw1_GC, TRUE, 0,0,w,h);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
render_default_data_pixmaps(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GdkPixmap *pixmap;
|
|
gint w, h, w_pixmap = 0;
|
|
|
|
gkrellm_render_data_grid_pixmap(_GK.data_in_grid_piximage,
|
|
&_GK.data_in_grid_pixmap, &_GK.in_color_grid);
|
|
gkrellm_render_data_grid_pixmap(_GK.data_out_grid_piximage,
|
|
&_GK.data_out_grid_pixmap, &_GK.out_color_grid);
|
|
|
|
w = gkrellm_chart_width();
|
|
pixmap = _GK.bg_separator_pixmap;
|
|
if (pixmap)
|
|
gdk_drawable_get_size(pixmap, &w_pixmap, NULL);
|
|
if (!pixmap || w_pixmap != w)
|
|
{
|
|
if ((h = _GK.bg_separator_height) < 1 || h > 5)
|
|
h = 2;
|
|
if (_GK.bg_separator_piximage)
|
|
gkrellm_scale_piximage_to_pixmap(_GK.bg_separator_piximage,
|
|
&_GK.bg_separator_pixmap, NULL, w, h);
|
|
else
|
|
{
|
|
GkrellmPiximage *im;
|
|
|
|
im = gkrellm_bg_panel_piximage(DEFAULT_STYLE_ID);
|
|
gkrellm_scale_pixbuf_to_pixmap(im->pixbuf, &_GK.bg_separator_pixmap,
|
|
NULL, w, h);
|
|
}
|
|
}
|
|
|
|
h = 2;
|
|
for (list = chart_list; list; list = list->next)
|
|
{
|
|
cp = (GkrellmChart *) list->data;
|
|
if (cp->h > h)
|
|
h = cp->h;
|
|
}
|
|
gkrellm_render_data_pixmap(_GK.data_in_piximage,
|
|
&_GK.data_in_pixmap, &_GK.in_color, h);
|
|
gkrellm_render_data_pixmap(_GK.data_out_piximage,
|
|
&_GK.data_out_pixmap, &_GK.out_color, h);
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_setup(void)
|
|
{
|
|
gkrellm_free_pixmap(&_GK.data_in_pixmap);
|
|
gkrellm_free_pixmap(&_GK.data_in_grid_pixmap);
|
|
gkrellm_free_pixmap(&_GK.data_out_pixmap);
|
|
gkrellm_free_pixmap(&_GK.data_out_grid_pixmap);
|
|
gkrellm_free_pixmap(&_GK.bg_separator_pixmap);
|
|
}
|
|
|
|
#if 0
|
|
static gint
|
|
compare_chartlist(gconstpointer a, gconstpointer b)
|
|
{
|
|
GkrellmChart *cp_a = (GkrellmChart *) a;
|
|
GkrellmChart *cp_b = (GkrellmChart *) b;
|
|
gint result;
|
|
|
|
if (cp_a->style_id < cp_b->style_id)
|
|
result = -1;
|
|
else (if cp_a->style_id > cp_b->style_id)
|
|
result = 1;
|
|
else
|
|
result = 0;
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
insert_in_chartlist(GkrellmChart *cp)
|
|
{
|
|
GList *list;
|
|
GkrellmChart *cp_x;
|
|
gint position = 0;
|
|
|
|
for (list = chart_list; list; list = list->next, ++position)
|
|
{
|
|
cp_x = (GkrellmChart *) list->data;
|
|
if (cp_x->style_id > cp->style_id)
|
|
{
|
|
chart_list = g_list_insert(chart_list, cp, position);
|
|
return;
|
|
}
|
|
}
|
|
chart_list = g_list_append(chart_list, cp);
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_hide(GkrellmChart *cp, gboolean hide_panel)
|
|
{
|
|
gint h_spacers = 0;
|
|
|
|
if (!cp || !cp->shown)
|
|
return;
|
|
|
|
if (cp->top_spacer.image)
|
|
h_spacers = cp->top_spacer.height;
|
|
if (cp->bottom_spacer.image)
|
|
h_spacers += cp->bottom_spacer.height;
|
|
|
|
gtk_widget_hide(cp->box);
|
|
gkrellm_freeze_side_frame_packing();
|
|
if (hide_panel)
|
|
gkrellm_panel_hide(cp->panel);
|
|
gkrellm_monitor_height_adjust(- (cp->h + h_spacers));
|
|
cp->shown = FALSE;
|
|
gkrellm_thaw_side_frame_packing();
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_show(GkrellmChart *cp, gboolean show_panel)
|
|
{
|
|
gint h_spacers = 0;
|
|
|
|
if (!cp || cp->shown)
|
|
return;
|
|
|
|
if (cp->top_spacer.image)
|
|
h_spacers = cp->top_spacer.height;
|
|
if (cp->bottom_spacer.image)
|
|
h_spacers += cp->bottom_spacer.height;
|
|
|
|
gtk_widget_show(cp->box);
|
|
gkrellm_freeze_side_frame_packing();
|
|
if (show_panel)
|
|
gkrellm_panel_show(cp->panel);
|
|
cp->shown = TRUE;
|
|
gkrellm_monitor_height_adjust(cp->h + h_spacers);
|
|
gkrellm_thaw_side_frame_packing();
|
|
}
|
|
|
|
gboolean
|
|
gkrellm_is_chart_visible(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return FALSE;
|
|
return cp->shown;
|
|
}
|
|
|
|
gboolean
|
|
gkrellm_chart_enable_visibility(GkrellmChart *cp, gboolean new_vis,
|
|
gboolean *current_vis)
|
|
{
|
|
gboolean changed = FALSE;
|
|
|
|
if (new_vis && ! *current_vis)
|
|
{
|
|
gkrellm_chart_show(cp, TRUE);
|
|
*current_vis = TRUE;
|
|
changed = TRUE;
|
|
}
|
|
if (!new_vis && *current_vis)
|
|
{
|
|
gkrellm_chart_hide(cp, TRUE);
|
|
*current_vis = FALSE;
|
|
changed = TRUE;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chart_height_default(GkrellmChart *cp, gint h)
|
|
{
|
|
if (!cp || (cp->config && cp->config->config_loaded))
|
|
return;
|
|
|
|
if (h < MIN_CHARTHEIGHT)
|
|
h = MIN_CHARTHEIGHT;
|
|
if (h > MAX_CHARTHEIGHT)
|
|
h = MAX_CHARTHEIGHT;
|
|
cp->h = h;
|
|
}
|
|
|
|
static void
|
|
render_chart_margin_spacers(GkrellmChart *cp)
|
|
{
|
|
GkrellmMargin *m;
|
|
GkrellmSpacer *ts, *bs;
|
|
|
|
ts = &cp->top_spacer;
|
|
bs = &cp->bottom_spacer;
|
|
if (ts->image)
|
|
gtk_container_remove(GTK_CONTAINER(ts->vbox), ts->image);
|
|
if (bs->image)
|
|
gtk_container_remove(GTK_CONTAINER(bs->vbox), bs->image);
|
|
ts->image = bs->image = NULL;
|
|
m = gkrellm_get_style_margins(cp->style);
|
|
ts->piximage = cp->bg_piximage;
|
|
ts->height = m->top;
|
|
bs->piximage = cp->bg_piximage;
|
|
bs->height = m->bottom;
|
|
|
|
if (!gkrellm_render_spacer(ts, 0, m->top,
|
|
_GK.frame_left_chart_overlap, _GK.frame_right_chart_overlap))
|
|
gtk_widget_hide(ts->vbox);
|
|
|
|
if (!gkrellm_render_spacer(bs,
|
|
gdk_pixbuf_get_height(cp->bg_piximage->pixbuf) - m->bottom,
|
|
m->bottom,
|
|
_GK.frame_left_chart_overlap, _GK.frame_right_chart_overlap))
|
|
gtk_widget_hide(bs->vbox);
|
|
}
|
|
|
|
#if 0
|
|
static gboolean
|
|
cb_chart_map_event(GtkWidget *widget, GdkEvent *event, GkrellmChart *cp)
|
|
{
|
|
gdk_window_get_position(cp->drawing_area->window, NULL, &cp->y_mapped);
|
|
if (_GK.frame_left_chart_overlap > 0 || _GK.frame_right_chart_overlap > 0)
|
|
_GK.need_frame_packing = TRUE;
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
static gboolean
|
|
cb_chart_size_allocate(GtkWidget *widget, GtkAllocation *size,
|
|
GkrellmChart *cp)
|
|
{
|
|
gdk_window_get_position(cp->drawing_area->window, NULL, &cp->y_mapped);
|
|
if (_GK.frame_left_chart_overlap > 0 || _GK.frame_right_chart_overlap > 0)
|
|
_GK.need_frame_packing = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
render_chart_pixmaps(GkrellmChart *cp)
|
|
{
|
|
GkrellmPiximage piximage;
|
|
GkrellmMargin *m;
|
|
gint h, w;
|
|
|
|
m = gkrellm_get_style_margins(cp->style);
|
|
w = gdk_pixbuf_get_width(cp->bg_piximage->pixbuf)
|
|
- _GK.frame_left_chart_overlap - _GK.frame_right_chart_overlap;
|
|
h = gdk_pixbuf_get_height(cp->bg_piximage->pixbuf) - m->top - m->bottom;
|
|
|
|
if ( ( m->top > 0 || m->bottom > 0
|
|
|| _GK.frame_left_chart_overlap > 0
|
|
|| _GK.frame_right_chart_overlap > 0
|
|
)
|
|
&& w > 0 && h > 0
|
|
)
|
|
{
|
|
piximage.pixbuf = gdk_pixbuf_new_subpixbuf(cp->bg_piximage->pixbuf,
|
|
_GK.frame_left_chart_overlap, m->top, w, h);
|
|
piximage.border = cp->bg_piximage->border;
|
|
gkrellm_border_adjust(&piximage.border,
|
|
-_GK.frame_left_chart_overlap, -_GK.frame_right_chart_overlap,
|
|
-m->top, -m->bottom);
|
|
gkrellm_scale_piximage_to_pixmap(&piximage, &cp->bg_clean_pixmap,
|
|
&cp->bg_mask, cp->w, cp->h);
|
|
g_object_unref(G_OBJECT(piximage.pixbuf));
|
|
}
|
|
else
|
|
gkrellm_scale_piximage_to_pixmap(cp->bg_piximage,
|
|
&cp->bg_clean_pixmap, &cp->bg_mask, cp->w, cp->h);
|
|
|
|
gkrellm_clone_pixmap(&cp->pixmap, &cp->bg_clean_pixmap);
|
|
gkrellm_clone_pixmap(&cp->bg_pixmap, &cp->bg_clean_pixmap);
|
|
gkrellm_clone_pixmap(&cp->bg_src_pixmap, &cp->bg_clean_pixmap);
|
|
gkrellm_clone_pixmap(&cp->bg_text_pixmap, &cp->bg_clean_pixmap);
|
|
}
|
|
|
|
void
|
|
gkrellm_chart_create(GtkWidget *vbox, GkrellmMonitor *mon, GkrellmChart *cp,
|
|
GkrellmChartconfig **config)
|
|
{
|
|
GkrellmMargin *m;
|
|
GkrellmChartconfig *cf;
|
|
gint h, style_id;
|
|
|
|
if (!vbox || !mon || !cp || !config)
|
|
return;
|
|
if (mon->privat->style_type == CHART_PANEL_TYPE)
|
|
style_id = mon->privat->style_id;
|
|
else
|
|
style_id = DEFAULT_STYLE_ID;
|
|
cp->style = gkrellm_chart_style(style_id);
|
|
m = gkrellm_get_style_margins(cp->style);
|
|
cp->monitor = (gpointer) mon;
|
|
if (!cp->bg_piximage_override)
|
|
{
|
|
cp->bg_piximage = gkrellm_bg_chart_piximage(style_id);
|
|
cp->bg_grid_piximage = gkrellm_bg_grid_piximage(style_id);
|
|
}
|
|
cp->bg_piximage_override = FALSE;
|
|
cp->x = 0;
|
|
/* cp->y = 0; */
|
|
cp->w = _GK.chart_width;
|
|
if (!*config)
|
|
{
|
|
*config = gkrellm_chartconfig_new0();
|
|
(*config)->auto_grid_resolution = TRUE; /* the default */
|
|
(*config)->h = cp->h; /* In case default */
|
|
}
|
|
cf = cp->config = *config;
|
|
if (cf->h < 5)
|
|
cf->h = 40;
|
|
cp->h = cf->h;
|
|
if (cf->grid_resolution < 1)
|
|
cf->grid_resolution = 1;
|
|
cp->cd_list = cp->config->cd_list;
|
|
cp->config->chart_cd_list = &cp->cd_list;
|
|
|
|
if (!cp->box)
|
|
{
|
|
cp->box = gtk_vbox_new(FALSE, 0); /* not a hbox anymore !! */
|
|
gtk_box_pack_start(GTK_BOX(vbox), cp->box, FALSE, FALSE, 0);
|
|
|
|
cp->top_spacer.vbox = gtk_vbox_new(FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(cp->box), cp->top_spacer.vbox,
|
|
FALSE, FALSE, 0);
|
|
cp->drawing_area = gtk_drawing_area_new();
|
|
gtk_widget_set_events(cp->drawing_area, GDK_EXPOSURE_MASK
|
|
| GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
|
|
| GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK
|
|
| GDK_POINTER_MOTION_MASK);
|
|
gtk_box_pack_start(GTK_BOX(cp->box), cp->drawing_area,
|
|
FALSE, FALSE, 0);
|
|
cp->bottom_spacer.vbox = gtk_vbox_new(FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(cp->box), cp->bottom_spacer.vbox,
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show(cp->drawing_area);
|
|
gtk_widget_show(cp->box);
|
|
cp->shown = TRUE;
|
|
gtk_widget_realize(cp->box);
|
|
gtk_widget_realize(cp->drawing_area);
|
|
cp->style_id = style_id;
|
|
insert_in_chartlist(cp);
|
|
cp->y_mapped = -1;
|
|
// g_signal_connect(G_OBJECT (cp->drawing_area), "map_event",
|
|
// G_CALLBACK(cb_chart_map_event), cp);
|
|
g_signal_connect(G_OBJECT (cp->drawing_area), "size_allocate",
|
|
G_CALLBACK(cb_chart_size_allocate), cp);
|
|
}
|
|
else
|
|
free_chart_pixmaps(cp);
|
|
|
|
gtk_widget_set_size_request(cp->drawing_area, cp->w, cp->h);
|
|
|
|
cp->bg_sequence_id += 1;
|
|
|
|
render_chart_pixmaps(cp);
|
|
render_chart_margin_spacers(cp);
|
|
|
|
h = gdk_pixbuf_get_height(cp->bg_grid_piximage->pixbuf);
|
|
if (h > 2)
|
|
h = 2;
|
|
gkrellm_scale_piximage_to_pixmap(cp->bg_grid_piximage,
|
|
&cp->bg_grid_pixmap, NULL, cp->w, h);
|
|
|
|
cp->transparency = cp->style->transparency;
|
|
_GK.any_transparency |= cp->transparency;
|
|
|
|
gkrellm_set_draw_chart_function(cp, default_draw_chart_function, cp);
|
|
cp->redraw_all = TRUE;
|
|
render_default_data_pixmaps(cp);
|
|
if (cp->shown)
|
|
{
|
|
gkrellm_monitor_height_adjust(cp->h + m->top + m->bottom);
|
|
gkrellm_pack_side_frames();
|
|
}
|
|
}
|
|
|
|
void
|
|
gkrellm_refresh_chart(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
cp->redraw_all = TRUE;
|
|
cp->maxval_auto = -1;
|
|
if (cp->draw_chart)
|
|
(*(cp->draw_chart))(cp->draw_chart_data);
|
|
}
|
|
|
|
void
|
|
gkrellm_rescale_chart(GkrellmChart *cp)
|
|
{
|
|
if (!cp)
|
|
return;
|
|
scan_for_maxval(cp);
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
|
|
/* =================================================================== */
|
|
|
|
|
|
static gint map_125_table[] =
|
|
{
|
|
1, 2, 5,
|
|
10, 20, 50,
|
|
100, 200, 500,
|
|
1000, 2000, 5000,
|
|
10000, 20000, 50000,
|
|
100000, 200000, 500000,
|
|
1000000, 2000000, 5000000,
|
|
10000000, 20000000, 50000000,
|
|
100000000, 200000000, 500000000
|
|
};
|
|
|
|
static gint map_12357_table[] =
|
|
{
|
|
1, 2, 3, 5, 7,
|
|
10, 15, 20, 30, 50, 70,
|
|
100, 150, 200, 300, 500, 700,
|
|
1000, 1500, 2000, 3000, 5000, 7000,
|
|
10000, 15000, 20000, 30000, 50000, 70000,
|
|
100000, 150000, 200000, 300000, 500000, 700000,
|
|
1000000, 1500000, 2000000, 3000000, 5000000, 7000000,
|
|
10000000, 15000000, 20000000, 30000000, 50000000, 70000000,
|
|
100000000, 150000000, 200000000, 300000000, 500000000, 700000000
|
|
};
|
|
|
|
gint
|
|
gkrellm_125_sequence(gint value, gboolean use125,
|
|
gint low, gint high,
|
|
gboolean snap_to_table, gboolean roundup)
|
|
{
|
|
gint i, table_size;
|
|
gint *table;
|
|
|
|
if (use125)
|
|
{
|
|
table = map_125_table;
|
|
table_size = sizeof(map_125_table) / sizeof(gint);
|
|
}
|
|
else
|
|
{
|
|
table = map_12357_table;
|
|
table_size = sizeof(map_12357_table) / sizeof(gint);
|
|
}
|
|
if (value < low)
|
|
value = low;
|
|
if (value > high)
|
|
value = high;
|
|
if (value < table[0])
|
|
return table[0];
|
|
if (value > table[table_size - 1])
|
|
return table[table_size - 1];
|
|
if (!snap_to_table && !roundup)
|
|
{
|
|
for (i = 0; i < table_size; ++i)
|
|
{
|
|
/*printf(" mapping[%d] value=%d table=%d\n", i, value, table[i]); */
|
|
if (value == table[i])
|
|
return table[i];
|
|
else if (value == table[i] - 1)
|
|
return table[i - 1];
|
|
else if (value == table[i] + 1)
|
|
return table[i + 1];
|
|
}
|
|
}
|
|
else if (snap_to_table && !roundup)
|
|
{
|
|
for (i = table_size - 1; i >= 0; --i)
|
|
{
|
|
if (value >= table[i])
|
|
{
|
|
value = table[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (snap_to_table && roundup)
|
|
{
|
|
for (i = 0; i < table_size; ++i)
|
|
{
|
|
if (value <= table[i])
|
|
{
|
|
value = table[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static void
|
|
set_grid_resolution_spin_button(GkrellmChart *cp, gint res)
|
|
{
|
|
GtkSpinButton *spin;
|
|
|
|
if (!cp || !cp->config_window || !cp->config->grid_resolution_spin_button)
|
|
return;
|
|
spin = GTK_SPIN_BUTTON(cp->config->grid_resolution_spin_button);
|
|
gtk_spin_button_set_value(spin, (gfloat) res);
|
|
}
|
|
|
|
static void
|
|
cb_chart_grid_resolution(GtkWidget *adjustment, GkrellmChart *cp)
|
|
{
|
|
GtkSpinButton *spin;
|
|
GkrellmChartconfig *cf;
|
|
gint res;
|
|
gfloat fres;
|
|
|
|
cf = cp->config;
|
|
spin = GTK_SPIN_BUTTON(cf->grid_resolution_spin_button);
|
|
if (cf->map_sequence)
|
|
{
|
|
res = gtk_spin_button_get_value_as_int(spin);
|
|
if (res != cf->grid_resolution)
|
|
{
|
|
res = gkrellm_125_sequence(res, cf->sequence_125,
|
|
cf->low, cf->high, FALSE, FALSE);
|
|
cf->grid_resolution = res;
|
|
gtk_spin_button_set_value(spin, (gfloat) res);
|
|
if (cf->cb_grid_resolution && !cf->cb_block)
|
|
(*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data);
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fres = gtk_spin_button_get_value(spin);
|
|
if (cf->spin_factor > 0.0)
|
|
fres *= cf->spin_factor;
|
|
cf->grid_resolution = (gint) fres;
|
|
if (cf->grid_resolution < 1)
|
|
cf->grid_resolution = 1;
|
|
if (cf->cb_grid_resolution && !cf->cb_block)
|
|
(*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data);
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
}
|
|
|
|
|
|
/* ---- GkrellmChartconfig functions ---- */
|
|
void
|
|
gkrellm_chartconfig_callback_block(GkrellmChartconfig *cf, gboolean block)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->cb_block = block;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_grid_resolution(GkrellmChartconfig *cf, gint res)
|
|
{
|
|
if (!cf || res <= 0)
|
|
return;
|
|
cf->grid_resolution = res;
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_chartconfig_grid_resolution(GkrellmChartconfig *cf)
|
|
{
|
|
if (!cf)
|
|
return 0;
|
|
return cf->grid_resolution;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_grid_resolution_connect(GkrellmChartconfig *cf,
|
|
void (*func)(gpointer), gpointer data)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->cb_grid_resolution = func;
|
|
cf->cb_grid_resolution_data = data;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_flags(GkrellmChartconfig *cf, gint flags)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->flags = flags;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_grid_resolution_adjustment(GkrellmChartconfig *cf,
|
|
gboolean map_sequence, gfloat spin_factor,
|
|
gfloat low, gfloat high, gfloat step0, gfloat step1, gint digits,
|
|
gint width)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->map_sequence = map_sequence;
|
|
if ((cf->width = width) == 0)
|
|
cf->width = 70 + log(high / 100000) * 5;
|
|
if (map_sequence)
|
|
{
|
|
cf->low = 1;
|
|
cf->low = (gfloat) gkrellm_125_sequence((gint) low, cf->sequence_125,
|
|
low, high, TRUE, FALSE);
|
|
cf->high = (gfloat) gkrellm_125_sequence((gint) high,
|
|
cf->sequence_125, low, high, TRUE, TRUE);
|
|
cf->step0 = 1.0;
|
|
cf->step1 = 1.0;
|
|
cf->digits = 0;
|
|
}
|
|
else
|
|
{
|
|
cf->low = low;
|
|
cf->high = high;
|
|
cf->step0 = step0;
|
|
cf->step1 = step1;
|
|
cf->digits = digits;
|
|
cf->spin_factor = spin_factor;
|
|
}
|
|
if (cf->spin_factor < 1.0)
|
|
cf->spin_factor = 1.0;
|
|
cf->adjustment_is_set = TRUE;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_grid_resolution_label(GkrellmChartconfig *cf, gchar *label)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
gkrellm_dup_string(&cf->grid_resolution_label, label);
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_auto_grid_resolution(GkrellmChartconfig *cf, gboolean ato)
|
|
{
|
|
if (cf)
|
|
cf->auto_grid_resolution = ato;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_auto_resolution_stick(GkrellmChartconfig *cf, gboolean stick)
|
|
{
|
|
if (cf)
|
|
cf->auto_resolution_stick = stick;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_sequence_125(GkrellmChartconfig *cf, gboolean seq)
|
|
{
|
|
if (cf)
|
|
cf->sequence_125 = seq;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chartconfig_fixed_grids(GkrellmChartconfig *cf, gint fixed_grids)
|
|
{
|
|
if (!cf || fixed_grids < 0 || fixed_grids > 5)
|
|
return;
|
|
cf->fixed_grids = fixed_grids;
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_chartconfig_fixed_grids(GkrellmChartconfig *cf)
|
|
{
|
|
if (!cf)
|
|
return 0;
|
|
return cf->fixed_grids;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_fixed_grids_connect(GkrellmChartconfig *cf,
|
|
void (*func)(gpointer), gpointer data)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->cb_fixed_grids = func;
|
|
cf->cb_fixed_grids_data = data;
|
|
}
|
|
|
|
gint
|
|
gkrellm_get_chartconfig_height(GkrellmChartconfig *cf)
|
|
{
|
|
if (!cf)
|
|
return 0;
|
|
return cf->h;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_height_connect(GkrellmChartconfig *cf,
|
|
void (*func)(gpointer), gpointer data)
|
|
{
|
|
if (!cf)
|
|
return;
|
|
cf->cb_height = func;
|
|
cf->cb_height_data = data;
|
|
}
|
|
|
|
void
|
|
gkrellm_set_chart_height(GkrellmChart *cp, gint h)
|
|
{
|
|
GtkWidget *top_win = gkrellm_get_top_window();
|
|
GtkSpinButton *spin;
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
GkrellmChartconfig *cf;
|
|
gint dy;
|
|
|
|
if (!cp || cp->h == h)
|
|
return;
|
|
dy = h - cp->h;
|
|
cp->h = h;
|
|
cp->config->h = h;
|
|
render_default_data_pixmaps(cp);
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
g_object_unref(G_OBJECT(cd->data_bitmap));
|
|
g_object_unref(G_OBJECT(cd->layer.pixmap));
|
|
cd->data_bitmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, 1);
|
|
cd->layer.pixmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, -1);
|
|
}
|
|
cp->bg_sequence_id += 1;
|
|
render_chart_pixmaps(cp);
|
|
|
|
cf = cp->config;
|
|
if (cf->cb_height && !cf->cb_block)
|
|
(*cf->cb_height)(cf, cf->cb_height_data);
|
|
gtk_widget_set_size_request(cp->drawing_area, cp->w, cp->h);
|
|
set_chartdata_split_heights(cp);
|
|
if (cp->shown)
|
|
{
|
|
gkrellm_monitor_height_adjust(dy);
|
|
gkrellm_pack_side_frames();
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
if (cp->config_window)
|
|
{
|
|
spin = GTK_SPIN_BUTTON(cf->height_spin_button);
|
|
if (h != gtk_spin_button_get_value_as_int(spin))
|
|
gtk_spin_button_set_value(spin, (gfloat) h);
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gkrellm_get_chartdata_hide(GkrellmChartdata *cd)
|
|
{
|
|
if (cd && cd->hide)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* =================================================================== */
|
|
|
|
static void
|
|
chart_config_window_close(GtkWidget *widget, GkrellmChart *cp)
|
|
{
|
|
if (cp->config_window)
|
|
gtk_widget_destroy(cp->config_window);
|
|
cp->config_window = NULL;
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_window_destroy(GkrellmChart *cp)
|
|
{
|
|
chart_config_window_close(NULL, cp);
|
|
}
|
|
|
|
static gint
|
|
chart_config_window_delete_event(GtkWidget *widget, GdkEvent *ev,
|
|
gpointer data)
|
|
{
|
|
chart_config_window_close(widget, data);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
set_resolution_menubar_items_sensitivity(GkrellmChartconfig *cf)
|
|
{
|
|
GtkWidget *w;
|
|
|
|
if (!cf->auto_resolution_item_factory)
|
|
return;
|
|
|
|
w = gtk_item_factory_get_widget(cf->auto_resolution_item_factory,
|
|
_("/Control/Auto mode sticks at peak value"));
|
|
GTK_CHECK_MENU_ITEM(w)->active = cf->auto_resolution_stick;
|
|
|
|
w = gtk_item_factory_get_widget(cf->auto_resolution_item_factory,
|
|
_("/Control/Auto mode recalibrate"));
|
|
if (cf->auto_grid_resolution)
|
|
gtk_widget_set_sensitive(w, TRUE);
|
|
else
|
|
gtk_widget_set_sensitive(w, FALSE);
|
|
}
|
|
|
|
static void
|
|
cb_chart_height(GtkWidget *adjustment, GkrellmChart *cp)
|
|
{
|
|
GtkSpinButton *spin;
|
|
gint h;
|
|
|
|
_GK.config_modified = TRUE;
|
|
spin = GTK_SPIN_BUTTON(cp->config->height_spin_button);
|
|
h = gtk_spin_button_get_value_as_int(spin);
|
|
gkrellm_set_chart_height(cp, h);
|
|
}
|
|
|
|
static void
|
|
cb_chart_fixed_grids(GtkWidget *adjustment, GkrellmChart *cp)
|
|
{
|
|
GtkSpinButton *spin;
|
|
GkrellmChartconfig *cf = cp->config;
|
|
|
|
_GK.config_modified = TRUE;
|
|
spin = GTK_SPIN_BUTTON(cf->fixed_grids_spin_button);
|
|
cf->fixed_grids = gtk_spin_button_get_value_as_int(spin);
|
|
if (cf->auto_grid_resolution)
|
|
set_auto_grid_resolution(cp, cp->maxval_auto);
|
|
if (cf->cb_fixed_grids && !cf->cb_block)
|
|
(*cf->cb_fixed_grids)(cf, cf->cb_fixed_grids_data);
|
|
|
|
set_resolution_menubar_items_sensitivity(cf);
|
|
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
|
|
static void
|
|
cb_line_draw_style(GtkWidget *widget, GkrellmChartdata *cd)
|
|
{
|
|
_GK.config_modified = TRUE;
|
|
cd->draw_style = GTK_TOGGLE_BUTTON(widget)->active;
|
|
gkrellm_rescale_chart(cd->chart);
|
|
}
|
|
|
|
static void
|
|
cb_auto_resolution(GtkWidget *widget, GkrellmChart *cp)
|
|
{
|
|
GtkWidget *button;
|
|
GkrellmChartconfig *cf = cp->config;
|
|
|
|
_GK.config_modified = TRUE;
|
|
cf->auto_grid_resolution = GTK_TOGGLE_BUTTON(widget)->active;
|
|
|
|
set_resolution_menubar_items_sensitivity(cf);
|
|
button = cf->grid_resolution_spin_button;
|
|
if (cf->auto_grid_resolution)
|
|
gtk_widget_set_sensitive(button, FALSE);
|
|
else
|
|
gtk_widget_set_sensitive(button, TRUE);
|
|
gkrellm_rescale_chart(cp);
|
|
}
|
|
|
|
static void
|
|
cb_inverted_draw_mode(GtkWidget *widget, GkrellmChartdata *cd)
|
|
{
|
|
_GK.config_modified = TRUE;
|
|
cd->inverted = GTK_TOGGLE_BUTTON(widget)->active;
|
|
gkrellm_rescale_chart(cd->chart);
|
|
}
|
|
|
|
static void
|
|
cb_hide(GtkWidget *widget, GkrellmChartdata *cd)
|
|
{
|
|
_GK.config_modified = TRUE;
|
|
cd->hide = GTK_TOGGLE_BUTTON(widget)->active;
|
|
set_chartdata_split_heights(cd->chart);
|
|
gkrellm_rescale_chart(cd->chart);
|
|
}
|
|
|
|
static void
|
|
cb_split_mode(GtkWidget *widget, GkrellmChartdata *cd)
|
|
{
|
|
_GK.config_modified = TRUE;
|
|
cd->split_chart = GTK_TOGGLE_BUTTON(widget)->active;
|
|
gtk_widget_set_sensitive(cd->split_fraction_spin_button, cd->split_chart);
|
|
set_chartdata_split_heights(cd->chart);
|
|
gkrellm_rescale_chart(cd->chart);
|
|
}
|
|
|
|
static void
|
|
cb_split_fraction(GtkWidget *adjustment, GkrellmChartdata *cd)
|
|
{
|
|
GtkSpinButton *spin;
|
|
|
|
_GK.config_modified = TRUE;
|
|
spin = GTK_SPIN_BUTTON(cd->split_fraction_spin_button);
|
|
cd->split_fraction = gtk_spin_button_get_value(spin);
|
|
set_chartdata_split_heights(cd->chart);
|
|
gkrellm_rescale_chart(cd->chart);
|
|
}
|
|
|
|
|
|
/* =================================================================== */
|
|
|
|
static void
|
|
cb_auto_res_control(GkrellmChart *cp, guint option, GtkWidget* widget)
|
|
{
|
|
GkrellmChartconfig *cf;
|
|
gint grid_res;
|
|
gboolean active;
|
|
|
|
cf = cp->config;
|
|
switch (option)
|
|
{
|
|
case 0:
|
|
cp->maxval_auto_base = 0;
|
|
cp->maxval_peak = 0;
|
|
break;
|
|
case 1:
|
|
active = GTK_CHECK_MENU_ITEM(widget)->active;
|
|
cf->auto_resolution_stick = active;
|
|
cp->maxval_auto_base = 0;
|
|
break;
|
|
case 2:
|
|
active = GTK_CHECK_MENU_ITEM(widget)->active;
|
|
if (cf->sequence_125 && active)
|
|
return;
|
|
cf->sequence_125 = active;
|
|
break;
|
|
case 3:
|
|
active = GTK_CHECK_MENU_ITEM(widget)->active;
|
|
if (!cf->sequence_125 && active)
|
|
return;
|
|
cf->sequence_125 = !active;
|
|
|
|
grid_res = gkrellm_125_sequence(cf->grid_resolution,
|
|
cf->sequence_125, cf->low, cf->high, TRUE, FALSE);
|
|
cf->grid_resolution = grid_res;
|
|
set_grid_resolution_spin_button(cp, grid_res);
|
|
break;
|
|
}
|
|
gkrellm_refresh_chart(cp);
|
|
}
|
|
|
|
|
|
static GtkItemFactoryEntry auto_res_control_items[] =
|
|
{
|
|
{N_("/Control"), NULL, NULL, 0, "<LastBranch>" },
|
|
{N_("/Control/-"), NULL, NULL, 0, "<Separator>"},
|
|
{N_("/Control/Auto mode recalibrate"),
|
|
NULL, cb_auto_res_control, 0, "<Item>"},
|
|
{N_("/Control/Auto mode sticks at peak value"),
|
|
NULL, cb_auto_res_control, 1, "<ToggleItem>"},
|
|
{N_("/Control/-"), NULL, NULL, 0, "<Separator>"},
|
|
{N_("/Control/Sequence.../1 2 5"),
|
|
NULL, cb_auto_res_control, 2, "<RadioItem>"},
|
|
{N_("/Control/Sequence.../1 1.5 2 3 5 7"),
|
|
NULL, cb_auto_res_control, 3,
|
|
N_("/Control/Sequence.../1 2 5")},
|
|
{N_("/Control/-"), NULL, NULL, 0, "<Separator>"},
|
|
};
|
|
|
|
static void
|
|
auto_resolution_control_menubar(GtkWidget **menubar, GkrellmChart *cp)
|
|
{
|
|
GtkItemFactory *item_factory;
|
|
GkrellmChartconfig *cf = cp->config;
|
|
gint i, n;
|
|
static gboolean translated;
|
|
|
|
n = sizeof(auto_res_control_items) / sizeof(GtkItemFactoryEntry);
|
|
item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", NULL);
|
|
if (!translated)
|
|
{
|
|
for(i = 0; i < n; i++)
|
|
auto_res_control_items[i].path = _(auto_res_control_items[i].path);
|
|
auto_res_control_items[6].item_type =
|
|
_(auto_res_control_items[6].item_type);
|
|
translated = TRUE;
|
|
}
|
|
gtk_item_factory_create_items(item_factory, n, auto_res_control_items, cp);
|
|
cf->auto_resolution_item_factory = item_factory;
|
|
set_resolution_menubar_items_sensitivity(cf);
|
|
|
|
GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(item_factory,
|
|
_("/Control/Sequence.../1 2 5")))->active = cf->sequence_125;
|
|
GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(item_factory,
|
|
_("/Control/Sequence.../1 1.5 2 3 5 7")))->active = !cf->sequence_125;
|
|
|
|
if (menubar)
|
|
*menubar = gtk_item_factory_get_widget(item_factory, "<main>");
|
|
}
|
|
|
|
void
|
|
gkrellm_chartconfig_window_create(GkrellmChart *cp)
|
|
{
|
|
GtkWidget *main_vbox, *vbox, *vbox1, *vbox2, *hbox;
|
|
GtkWidget *button;
|
|
GList *list;
|
|
GkrellmChartconfig *cf;
|
|
GkrellmChartdata *cd;
|
|
GkrellmPanel *p;
|
|
gchar *s;
|
|
|
|
if (!cp || _GK.no_config)
|
|
return;
|
|
if (cp->config_window)
|
|
{
|
|
gtk_window_present(GTK_WINDOW(cp->config_window));
|
|
return;
|
|
}
|
|
cp->config_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
g_signal_connect(G_OBJECT(cp->config_window), "delete_event",
|
|
G_CALLBACK(chart_config_window_delete_event), cp);
|
|
|
|
p = cp->panel;
|
|
cf = cp->config;
|
|
if (p && p->label)
|
|
s = p->label->string;
|
|
else
|
|
s = NULL;
|
|
gtk_window_set_title(GTK_WINDOW(cp->config_window),
|
|
_("GKrellM Chart Config"));
|
|
gtk_window_set_wmclass(GTK_WINDOW(cp->config_window),
|
|
"Gkrellm_conf", "Gkrellm");
|
|
|
|
main_vbox = gtk_vbox_new(FALSE, 0);
|
|
gtk_container_set_border_width(GTK_CONTAINER(cp->config_window), 4);
|
|
gtk_container_add(GTK_CONTAINER(cp->config_window), main_vbox);
|
|
vbox = gkrellm_gtk_framed_vbox(main_vbox, s, 4, FALSE, 4, 3);
|
|
|
|
hbox = gtk_hbox_new(TRUE, 0);
|
|
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
|
|
for (list = cp->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
if ((cd->flags & CHARTDATA_NO_CONFIG) == CHARTDATA_NO_CONFIG)
|
|
continue;
|
|
vbox1 = gkrellm_gtk_framed_vbox(hbox, cd->label, 2, TRUE, 2, 2);
|
|
|
|
if (!(cd->flags & CHARTDATA_NO_CONFIG_DRAW_STYLE))
|
|
{
|
|
gkrellm_gtk_check_button(vbox1, &button, cd->draw_style, FALSE, 0,
|
|
_("Line style"));
|
|
g_signal_connect(G_OBJECT(button), "toggled",
|
|
G_CALLBACK(cb_line_draw_style), cd);
|
|
}
|
|
if (!(cd->flags & CHARTDATA_NO_CONFIG_INVERTED))
|
|
{
|
|
gkrellm_gtk_check_button(vbox1, &button, cd->inverted, FALSE, 0,
|
|
_("Inverted"));
|
|
g_signal_connect(G_OBJECT(button), "toggled",
|
|
G_CALLBACK(cb_inverted_draw_mode), cd);
|
|
}
|
|
if (list != cp->cd_list && !(cd->flags & CHARTDATA_NO_CONFIG_SPLIT))
|
|
{
|
|
vbox2 = gkrellm_gtk_framed_vbox(vbox1, NULL, 2, FALSE, 2, 2);
|
|
gkrellm_gtk_check_button(vbox2, &button, cd->split_chart, FALSE, 0,
|
|
_("Split view"));
|
|
g_signal_connect(G_OBJECT(button), "toggled",
|
|
G_CALLBACK(cb_split_mode), cd);
|
|
gkrellm_gtk_spin_button(vbox2, &button, cd->split_fraction,
|
|
0.05, 0.95, 0.01, 0.05, 2, 55,
|
|
cb_split_fraction, cd, FALSE, "");
|
|
gtk_widget_set_sensitive(button, cd->split_chart);
|
|
cd->split_fraction_spin_button = button;
|
|
}
|
|
if (cd->flags & CHARTDATA_ALLOW_HIDE)
|
|
{
|
|
gkrellm_gtk_check_button(vbox1, &button, cd->hide, FALSE, 0,
|
|
_("Hide"));
|
|
g_signal_connect(G_OBJECT(button), "toggled",
|
|
G_CALLBACK(cb_hide), cd);
|
|
}
|
|
}
|
|
|
|
cf->auto_resolution_control_menubar = NULL;
|
|
cf->auto_resolution_item_factory = NULL;
|
|
cf->grid_resolution_spin_button = NULL;
|
|
cf->fixed_grids_spin_button = NULL;
|
|
|
|
if (cf->adjustment_is_set)
|
|
{
|
|
gfloat value;
|
|
|
|
vbox1 = gkrellm_gtk_framed_vbox(vbox, _("Resolution per Grid"),
|
|
2, FALSE, 2, 2);
|
|
if (cf->map_sequence)
|
|
value = (gfloat) cf->grid_resolution;
|
|
else
|
|
value = cf->grid_resolution / cf->spin_factor;
|
|
gkrellm_gtk_spin_button(vbox1, &button, value,
|
|
cf->low, cf->high, cf->step0, cf->step1, cf->digits, cf->width,
|
|
cb_chart_grid_resolution, cp, FALSE, cf->grid_resolution_label);
|
|
cf->grid_resolution_spin_button = button;
|
|
if (cp->config->auto_grid_resolution)
|
|
gtk_widget_set_sensitive(button, FALSE);
|
|
|
|
if (!(cp->config->flags & NO_CONFIG_AUTO_GRID_RESOLUTION))
|
|
{
|
|
hbox = gtk_hbox_new (FALSE, 0);
|
|
gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
|
|
gtk_container_add(GTK_CONTAINER(vbox1), hbox);
|
|
gkrellm_gtk_check_button(hbox, &button,
|
|
cp->config->auto_grid_resolution, TRUE, 0,
|
|
_("Auto"));
|
|
g_signal_connect(G_OBJECT(button), "toggled",
|
|
G_CALLBACK(cb_auto_resolution), cp);
|
|
|
|
auto_resolution_control_menubar(
|
|
&cf->auto_resolution_control_menubar, cp);
|
|
gtk_box_pack_start(GTK_BOX(hbox),
|
|
cf->auto_resolution_control_menubar, FALSE, TRUE, 10);
|
|
}
|
|
}
|
|
if (!(cp->config->flags & NO_CONFIG_FIXED_GRIDS))
|
|
{
|
|
vbox1 = gkrellm_gtk_framed_vbox(vbox, _("Number of Grids"), 2, FALSE,
|
|
2, 2);
|
|
gkrellm_gtk_spin_button(vbox1, &button, (gfloat) cf->fixed_grids,
|
|
0, 5, 1.0, 1.0, 0, 50,
|
|
cb_chart_fixed_grids, cp, FALSE,
|
|
_("0: Auto 1-5: Constant"));
|
|
cf->fixed_grids_spin_button = button;
|
|
}
|
|
|
|
vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 2, FALSE, 2, 2);
|
|
gkrellm_gtk_spin_button(vbox1, &button, (gfloat) cp->h,
|
|
(gfloat) _GK.chart_height_min, (gfloat) _GK.chart_height_max,
|
|
5.0, 10.0, 0, 50,
|
|
cb_chart_height, cp, FALSE,
|
|
_("Chart height"));
|
|
cf->height_spin_button = button;
|
|
|
|
hbox = gtk_hbutton_box_new();
|
|
gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
|
|
gtk_box_set_spacing(GTK_BOX(hbox), 5);
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
button = gtk_button_new_from_stock(GTK_STOCK_OK);
|
|
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
|
|
g_signal_connect(G_OBJECT(button), "clicked",
|
|
G_CALLBACK(chart_config_window_close), cp);
|
|
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 15);
|
|
gtk_widget_grab_default(button);
|
|
|
|
gtk_widget_show_all(cp->config_window);
|
|
}
|
|
|
|
void
|
|
gkrellm_save_chartconfig(FILE *f, GkrellmChartconfig *cf, gchar *mon_keyword,
|
|
gchar *name)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
|
|
if (!f || !cf || !mon_keyword)
|
|
return;
|
|
if (name)
|
|
fprintf(f, "%s %s %s ", mon_keyword, GKRELLM_CHARTCONFIG_KEYWORD,name);
|
|
else
|
|
fprintf(f, "%s %s ", mon_keyword, GKRELLM_CHARTCONFIG_KEYWORD);
|
|
fprintf(f, "%d %d %d %d %d %d", cf->h, cf->grid_resolution,
|
|
cf->fixed_grids, cf->auto_grid_resolution,
|
|
cf->auto_resolution_stick, cf->sequence_125);
|
|
for (list = cf->cd_list; list; list = list->next)
|
|
{
|
|
cd = (GkrellmChartdata *) list->data;
|
|
fprintf(f, " : %d %d %d %d %.0f",
|
|
cd->draw_style, cd->inverted, cd->hide,
|
|
cd->split_chart, cd->split_fraction * GKRELLM_FLOAT_FACTOR);
|
|
}
|
|
fprintf(f, "\n");
|
|
}
|
|
|
|
void
|
|
gkrellm_load_chartconfig(GkrellmChartconfig **config, gchar *string,
|
|
gint max_cd)
|
|
{
|
|
GList *list;
|
|
GkrellmChartdata *cd;
|
|
GkrellmChartconfig *cf;
|
|
gchar *s;
|
|
gint index = 0;
|
|
|
|
if (!config || !string)
|
|
return;
|
|
if (!*config)
|
|
{
|
|
*config = gkrellm_chartconfig_new0();
|
|
(*config)->auto_grid_resolution = TRUE; /* the default */
|
|
}
|
|
cf = *config;
|
|
sscanf(string, "%d %d %d %d %d %d", &cf->h, &cf->grid_resolution,
|
|
&cf->fixed_grids, &cf->auto_grid_resolution,
|
|
&cf->auto_resolution_stick, &cf->sequence_125);
|
|
for (s = strchr(string, (int) ':'); s ; s = strchr(s, (int) ':'))
|
|
{
|
|
++s;
|
|
list = g_list_nth(cf->cd_list, index++);
|
|
if (!list)
|
|
{
|
|
cd = g_new0(GkrellmChartdata, 1);
|
|
cd->split_fraction = 0.5;
|
|
cf->cd_list = g_list_append(cf->cd_list, cd);
|
|
}
|
|
else
|
|
cd = (GkrellmChartdata *) list->data;
|
|
sscanf(s, "%d %d %d %d %f",
|
|
&cd->draw_style, &cd->inverted, &cd->hide,
|
|
&cd->split_chart, &cd->split_fraction);
|
|
cd->split_fraction /= _GK.float_factor;
|
|
if (cd->split_fraction <= 0.01 || cd->split_fraction >= 0.99)
|
|
cd->split_fraction = 0.5;
|
|
|
|
cf->config_loaded = TRUE;
|
|
if (max_cd && index >= max_cd)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
debug_dump_chart_list()
|
|
{
|
|
GList *list, *cdlist;
|
|
GkrellmChart *cp;
|
|
GkrellmPanel *p;
|
|
GkrellmChartdata *cd;
|
|
|
|
printf("\n");
|
|
for (list = gkrellm_get_chart_list(); list; list = list->next)
|
|
{
|
|
cp = (GkrellmChart *) list->data;
|
|
p = cp->panel;
|
|
if (p && p->label && p->label->string)
|
|
printf("%s [%d]: ", p->label->string, cp->style_id);
|
|
else
|
|
printf("(null) [%d]: ", cp->style_id);
|
|
for (cdlist = cp->cd_list; cdlist; cdlist = cdlist->next)
|
|
{
|
|
cd = (GkrellmChartdata *) cdlist->data;
|
|
printf("%s %p->data ", cd->label, cd->data);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|