📄 chart.c
字号:
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 gbooleanauto_recalibrate(GkrellmChart *cp) { if (++cp->auto_recalibrate_delay < 10) return FALSE; cp->maxval_peak = 0; cp->maxval_auto_base = 0; return TRUE; }static gintsetup_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; }voidgkrellm_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); }voidgkrellm_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 voidscroll_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 gbooleanscan_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 voidscan_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); }voidgkrellm_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);#if defined(WIN32) cp->redraw_all = TRUE;#else scroll_chartdata_bitmaps(cp);#endif }/* =================================================================== */static voidchart_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 gintchartdata_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; }voidgkrellm_chart_reuse_text_format(GkrellmChart *cp) { cp->text_format_reuse = TRUE; }voidgkrellm_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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -