1 /* GKrellM 2 | Copyright (C) 1999-2019 Bill Wilson 3 | 4 | Author: Bill Wilson billw@gkrellm.net 5 | Latest versions might be found at: http://gkrellm.net 6 | 7 | 8 | GKrellM is free software: you can redistribute it and/or modify it 9 | under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | GKrellM is distributed in the hope that it will be useful, but WITHOUT 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 | License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see http://www.gnu.org/licenses/ 20 | 21 | 22 | Additional permission under GNU GPL version 3 section 7 23 | 24 | If you modify this program, or any covered work, by linking or 25 | combining it with the OpenSSL project's OpenSSL library (or a 26 | modified version of that library), containing parts covered by 27 | the terms of the OpenSSL or SSLeay licenses, you are granted 28 | additional permission to convey the resulting work. 29 | Corresponding Source for a non-source form of such a combination 30 | shall include the source code for the parts of OpenSSL used as well 31 | as that of the covered work. 32 */ 33 34 #include "gkrellm.h" 35 #include "gkrellm-private.h" 36 37 #include <math.h> 38 39 40 static void set_grid_resolution_spin_button(GkrellmChart *, gint); 41 42 43 /* For grid images of height 2 pixels, make room at bottom of chartdata 44 | window so both pixel lines will show. 45 */ 46 #define GRID_HEIGHT_Y_OFFSET_ADJUST(cp) \ 47 (( gdk_pixbuf_get_height((cp)->bg_grid_piximage->pixbuf) < 2) ? 0 : 1) 48 49 /* Map internal y values with origin at lower left to X screen coordinates 50 | which have origin at upper left. 51 */ 52 #define Y_SCREEN_MAP(cp,y) ((cp)->h - (y) - 1) 53 54 55 #define MIN_CHARTHEIGHT 5 56 #define MAX_CHARTHEIGHT 200 57 58 static GList *chart_list; 59 60 // #define DEBUG1 61 // #define DEBUG2 62 // #define DEBUG3 63 64 /* ----------------------------------------------------------------------- */ 65 66 static gint 67 computed_index(GkrellmChart *cp, gint i) 68 { 69 gint x; 70 71 x = (cp->position + i + 1) % cp->w; 72 return x; 73 } 74 75 GList * 76 gkrellm_get_chart_list() 77 { 78 return chart_list; 79 } 80 81 gint 82 gkrellm_get_chart_scalemax(GkrellmChart *cp) 83 { 84 if (!cp) 85 return 0; 86 return cp->scale_max; 87 } 88 89 gint 90 gkrellm_get_current_chartdata(GkrellmChartdata *cd) 91 { 92 if (!cd) 93 return 0; 94 return cd->data[cd->chart->position]; 95 } 96 97 gint 98 gkrellm_get_chartdata_data(GkrellmChartdata *cd, gint index) 99 { 100 gint x; 101 102 if (!cd) 103 return 0; 104 x = computed_index(cd->chart, index); 105 return cd->data[x]; 106 } 107 108 void 109 gkrellm_clear_chart(GkrellmChart *cp) 110 { 111 if (!cp) 112 return; 113 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 114 0, 0, 0, 0, cp->w, cp->h); 115 gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 116 0, 0, 0, 0, cp->w, cp->h); 117 if (cp->drawing_area->window) 118 gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap, 119 0, 0, 0, 0, cp->w, cp->h); 120 } 121 122 void 123 gkrellm_clear_chart_pixmap(GkrellmChart *cp) 124 { 125 if (!cp) 126 return; 127 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 128 0, 0, 0, 0, cp->w, cp->h); 129 gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, cp->bg_src_pixmap, 130 0, 0, 0, 0, cp->w, cp->h); 131 } 132 133 void 134 gkrellm_clean_bg_src_pixmap(GkrellmChart *cp) 135 { 136 if (!cp) 137 return; 138 if (!gkrellm_winop_draw_rootpixmap_onto_transparent_chart(cp)) 139 gdk_draw_drawable(cp->bg_src_pixmap, _GK.draw1_GC, 140 cp->bg_clean_pixmap, 0, 0, 0, 0, cp->w, cp->h); 141 cp->bg_sequence_id += 1; 142 } 143 144 void 145 gkrellm_draw_chart_grid_line(GkrellmChart *cp, GdkPixmap *pixmap, gint y) 146 { 147 gint h; 148 149 if (!cp) 150 return; 151 gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h); 152 gdk_draw_drawable(pixmap, _GK.draw1_GC, 153 cp->bg_grid_pixmap, 0, 0, cp->x, y, cp->w, h); 154 } 155 156 void 157 gkrellm_draw_chart_to_screen(GkrellmChart *cp) 158 { 159 /* Draw the expose pixmap onto the screen. 160 */ 161 if (cp && cp->drawing_area->window) 162 gdk_draw_drawable(cp->drawing_area->window, _GK.draw1_GC, cp->pixmap, 163 0, 0, 0, 0, cp->w, cp->h); 164 } 165 166 static void 167 default_draw_chart_function(GkrellmChart *cp) 168 { 169 if (!cp) 170 return; 171 gkrellm_draw_chartdata(cp); 172 gkrellm_draw_chart_to_screen(cp); 173 } 174 175 void 176 gkrellm_set_draw_chart_function(GkrellmChart *cp, void (*func)(), gpointer data) 177 { 178 if (!cp) 179 return; 180 cp->draw_chart = func; 181 cp->draw_chart_data = data; 182 } 183 184 void 185 gkrellm_scale_chartdata(GkrellmChartdata *cd, gint multiplier, gint divisor) 186 { 187 gint i; 188 189 if (!cd || !cd->data || divisor < 1) 190 return; 191 for (i = 0; i < cd->chart->w; ++i) 192 cd->data[i] = cd->data[i] * multiplier / divisor; 193 cd->previous = cd->previous * multiplier / divisor; 194 } 195 196 void 197 gkrellm_offset_chartdata(GkrellmChartdata *cd, gint offset) 198 { 199 gint i; 200 201 if (!cd || !cd->data) 202 return; 203 for (i = 0; i < cd->chart->w; ++i) 204 cd->data[i] = cd->data[i] + offset; 205 cd->previous = cd->previous + offset; 206 } 207 208 void 209 gkrellm_reset_chart(GkrellmChart *cp) 210 { 211 GList *list; 212 GkrellmChartdata *cd; 213 gint i; 214 215 cp->scale_max = 0; 216 cp->maxval = 0; 217 cp->redraw_all = TRUE; 218 cp->position = cp->w - 1; 219 cp->primed = FALSE; 220 221 for (list = cp->cd_list; list; list = list->next) 222 { 223 cd = (GkrellmChartdata *) list->data; 224 cd->maxval = 0; 225 cd->previous = 0; 226 if (cd->data) 227 for (i = 0; i < cp->w; ++i) 228 cd->data[i] = 0; 229 } 230 } 231 232 void 233 gkrellm_reset_and_draw_chart(GkrellmChart *cp) 234 { 235 if (!cp) 236 return; 237 gkrellm_reset_chart(cp); 238 if (cp->draw_chart) 239 (*(cp->draw_chart))(cp->draw_chart_data); 240 } 241 242 void 243 gkrellm_monotonic_chartdata(GkrellmChartdata *cd, gboolean value) 244 { 245 if (cd) 246 cd->monotonic = value; 247 } 248 249 void 250 gkrellm_set_chartdata_draw_style(GkrellmChartdata *cd, gint dstyle) 251 { 252 if (cd) 253 cd->draw_style = dstyle; 254 } 255 256 void 257 gkrellm_set_chartdata_draw_style_default(GkrellmChartdata *cd, gint dstyle) 258 { 259 if (cd && cd->chart->config && !cd->chart->config->config_loaded) 260 cd->draw_style = dstyle; 261 } 262 263 void 264 gkrellm_set_chartdata_flags(GkrellmChartdata *cd, gint flags) 265 { 266 if (cd) 267 cd->flags = flags; 268 } 269 270 static void 271 gk_draw_vertical_line(GdkDrawable *drawable, GdkGC *gc, gint x, gint y1, gint y2) 272 { 273 if (y1 == y2) 274 gdk_draw_point(drawable, gc, x, y1); 275 else 276 gdk_draw_line(drawable, gc, x, y1, x, y2); 277 } 278 279 280 static gint 281 chartdata_ycoord(GkrellmChart *cp, GkrellmChartdata *cd, gint yd) 282 { 283 glong y; 284 guint64 Y; 285 286 if (cp->scale_max <= 0) 287 cp->scale_max = 1; 288 289 if (yd > 2000000000 / MAX_CHARTHEIGHT) 290 { 291 Y = (guint64) yd * (guint64) cd->h; 292 y = Y / cp->scale_max; 293 } 294 else 295 y = ((glong) yd * cd->h / cp->scale_max); 296 297 if (y < 0) 298 y = 0; 299 if (y >= cd->h) 300 y = cd->h - 1; 301 if (cd->inverted) 302 y = cd->h - y - 1; 303 y += cd->y; 304 return Y_SCREEN_MAP(cp, y); 305 } 306 307 static void 308 draw_layer_grid_lines(GkrellmChart *cp) 309 { 310 GList *list; 311 GkrellmChartdata *cd; 312 gint y, y0, h, grid_res, lines; 313 gint active_split, current_split; 314 gboolean do_next_split, done_once_per_split, tmp; 315 316 gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, 317 cp->bg_src_pixmap, 0, 0, 0, 0, cp->w, cp->h); 318 do_next_split = TRUE; 319 for (active_split = 0; do_next_split; ++active_split) 320 { 321 do_next_split = FALSE; 322 done_once_per_split = FALSE; 323 current_split = 0; 324 for (list = cp->cd_list; list; list = list->next) 325 { 326 cd = (GkrellmChartdata *) list->data; 327 if (cd->hide) 328 continue; 329 current_split += cd->split_chart; 330 if (active_split != current_split) 331 { 332 if (current_split > active_split) 333 do_next_split = TRUE; 334 continue; 335 } 336 gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC, 337 *(cd->layer.src_pixmap), 0, 0, 0, 0, cp->w, cp->h); 338 339 grid_res = cp->config->grid_resolution; 340 lines = cp->scale_max / grid_res; 341 if (lines && cd->h / lines > 2) /* No grids if h is too small */ 342 { 343 for (y = 0; y <= cp->scale_max; y += grid_res) 344 { 345 if ( _GK.bg_grid_mode == GRID_MODE_RESTRAINED 346 && ((y == 0 && cp->y == 0) || y == cp->scale_max) 347 ) 348 continue; 349 tmp = cd->inverted; /* Draw grid lines in one direction*/ 350 cd->inverted = FALSE; /* else, may not line up by 1 pixel*/ 351 y0 = chartdata_ycoord(cp, cd, y); 352 cd->inverted = tmp; 353 gdk_drawable_get_size(cd->layer.grid_pixmap, NULL, &h); 354 gdk_draw_drawable(cd->layer.pixmap, _GK.draw1_GC, 355 cd->layer.grid_pixmap, 0, 0, cp->x, y0, cp->w, h); 356 357 if (!done_once_per_split) 358 { 359 gdk_drawable_get_size(cp->bg_grid_pixmap, NULL, &h); 360 gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, 361 cp->bg_grid_pixmap, 0, 0, cp->x, y0, cp->w, h); 362 } 363 } 364 } 365 if (current_split > 0 && !done_once_per_split) 366 { 367 y = cd->y - 1; /* Get separator y value */ 368 y -= GRID_HEIGHT_Y_OFFSET_ADJUST(cp); 369 if (y >= 0) 370 { 371 gdk_draw_drawable(cp->bg_pixmap, _GK.draw1_GC, 372 _GK.bg_separator_pixmap, 373 0, 0, cp->x, Y_SCREEN_MAP(cp, y), 374 cp->w, _GK.bg_separator_height); 375 } 376 } 377 done_once_per_split = TRUE; 378 } 379 } 380 } 381 382 /* Return TRUE as long as there is a next split with impulse data needing 383 | to be drawn. 384 */ 385 static gboolean 386 draw_chartdata_impulses(GkrellmChart *cp, GList *cd_list, 387 gint i0, gint active_split) 388 { 389 GList *list; 390 GkrellmChartdata *cd; 391 gint n, x, y, y0, y1, yN, yI; 392 gint current_split; 393 gboolean need_next_split = FALSE; 394 395 if (!cd_list) 396 return FALSE; 397 for (n = i0; n < cp->w; ++n) 398 { 399 x = computed_index(cp, n); 400 y0 = y1 = -1; 401 yN = yI = 0; 402 current_split = 0; 403 for (list = cp->cd_list; list; list= list->next) 404 { 405 cd = (GkrellmChartdata *) list->data; 406 if (cd->hide) 407 continue; 408 current_split += cd->split_chart; 409 if ( cd->draw_style != CHARTDATA_IMPULSE 410 || current_split != active_split 411 ) 412 { 413 if ( current_split > active_split 414 && cd->draw_style == CHARTDATA_IMPULSE 415 ) 416 need_next_split = TRUE; 417 continue; 418 } 419 if (cd->inverted) 420 { 421 if (y1 < 0) 422 y1 = chartdata_ycoord(cp, cd, 0); 423 yI += cd->data[x]; 424 y = chartdata_ycoord(cp, cd, yI); 425 if (cd->data[x] > 0) 426 gk_draw_vertical_line(cd->data_bitmap, _GK.bit1_GC, n, y1, y); 427 y1 = y; 428 } 429 else 430 { 431 if (y0 < 0) 432 y0 = chartdata_ycoord(cp, cd, 0); 433 yN += cd->data[x]; 434 y = chartdata_ycoord(cp, cd, yN); 435 if (cd->data[x] > 0) 436 gk_draw_vertical_line(cd->data_bitmap, _GK.bit1_GC, n, y0, y); 437 y0 = y; 438 } 439 } 440 } 441 /* Push the grided pixmaps through the data bitmaps onto the expose pixmap 442 */ 443 current_split = 0; 444 for (list = cp->cd_list; list; list = list->next) 445 { 446 cd = (GkrellmChartdata *) list->data; 447 if (cd->hide) 448 continue; 449 current_split += cd->split_chart; 450 if (cd->draw_style == CHARTDATA_LINE || current_split != active_split) 451 continue; 452 if (cd->maxval > 0) 453 { 454 y0 = chartdata_ycoord(cp, cd, 0); 455 y1 = chartdata_ycoord(cp, cd, cd->maxval); 456 gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap); 457 if (cd->inverted) 458 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 459 0, y0, 0, y0, cp->w, y1 - y0 + 1); 460 else 461 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 462 0, y1, 0, y1, cp->w, y0 - y1 + 1); 463 } 464 } 465 return need_next_split; 466 } 467 468 static gint 469 fix_y(gint yn, gint yp, gint ypp) 470 { 471 gint y; 472 473 if (yp > ypp && yn < yp) 474 { 475 y = (yp + yn) / 2; 476 if (y < ypp) 477 y = ypp; 478 } 479 else if (yp < ypp && yn > yp) 480 { 481 y = (yp + yn) / 2; 482 if (y > ypp) 483 y = ypp; 484 } 485 else 486 y = yp; 487 return y; 488 } 489 490 static void 491 draw_chartdata_lines(GkrellmChart *cp, GkrellmChartdata *cd, gint i0) 492 { 493 gint n, x, xp, y, y0, y1; 494 495 y0 = chartdata_ycoord(cp, cd, 0); 496 for (n = i0; n < cp->w; ++n) 497 { 498 x = computed_index(cp, n); 499 y1 = chartdata_ycoord(cp, cd, cd->data[x]); 500 if (n == 0) 501 cd->y_p = y1; 502 else if (!cd->y_p_valid && i0 == cp->w - 1) 503 { 504 if ((xp = x - 1) < 0) 505 xp = cp->w - 1; 506 cd->y_p = cd->y_pp = chartdata_ycoord(cp, cd, cd->data[xp]); 507 } 508 y = fix_y(y1, cd->y_p, cd->y_pp); 509 cd->y_pp = y; 510 cd->y_p = y1; 511 cd->y_p_valid = FALSE; /* Need a store_chartdata to make it valid */ 512 if (cd->data[x] > 0 || (cd->inverted ? (y > y0) : (y < y0))) 513 { 514 gk_draw_vertical_line(cd->data_bitmap, _GK.bit1_GC, cp->x + n, y, y1); 515 } 516 } 517 /* Push the grided pixmap through the data bitmap onto the expose pixmap 518 */ 519 if (cd->maxval > 0) 520 { 521 y0 = chartdata_ycoord(cp, cd, 0); 522 y1 = chartdata_ycoord(cp, cd, cd->maxval); 523 gdk_gc_set_clip_mask(_GK.draw1_GC, cd->data_bitmap); 524 if (cd->inverted) 525 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 526 0, y0, 0, y0, cp->w, y1 - y0 + 1); 527 else 528 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cd->layer.pixmap, 529 0, y1, 0, y1, cp->w, y0 - y1 + 1); 530 } 531 } 532 533 /* See the README for description of auto grid resolution behavior. 534 */ 535 static void 536 set_auto_grid_resolution(GkrellmChart *cp, gint maxval) 537 { 538 GkrellmChartconfig *cf = cp->config; 539 gint grids, grid_res, maxval_base; 540 541 if (maxval <= cp->maxval_auto_base) 542 maxval = cp->maxval_auto_base; 543 else 544 { 545 if (maxval > cp->maxval_peak) 546 cp->maxval_peak = maxval; 547 maxval_base = maxval / FULL_SCALE_GRIDS; 548 if (maxval_base > cp->maxval_auto_base) 549 cp->maxval_auto_base = maxval_base; 550 } 551 cp->maxval_auto = maxval; 552 553 grids = cf->fixed_grids; 554 if (grids == 0) /* Auto grids mode */ 555 grid_res = gkrellm_125_sequence(cp->maxval_auto_base, cf->sequence_125, 556 cf->low, cf->high, TRUE, FALSE); 557 else 558 { 559 if (cf->auto_resolution_stick) 560 maxval = cp->maxval_peak; 561 grid_res = gkrellm_125_sequence(maxval / grids, cf->sequence_125, 562 cf->low, cf->high, TRUE, TRUE); 563 } 564 if (grid_res != cf->grid_resolution) 565 { 566 cf->grid_resolution = grid_res; 567 set_grid_resolution_spin_button(cp, grid_res); 568 if (cf->cb_grid_resolution && !cf->cb_block) 569 (*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data); 570 cp->redraw_all = TRUE; 571 } 572 cp->auto_recalibrate_delay = 0; 573 } 574 575 static gboolean 576 auto_recalibrate(GkrellmChart *cp) 577 { 578 if (++cp->auto_recalibrate_delay < 10) 579 return FALSE; 580 cp->maxval_peak = 0; 581 cp->maxval_auto_base = 0; 582 return TRUE; 583 } 584 585 static gint 586 setup_chart_scalemax(GkrellmChart *cp) 587 { 588 GkrellmChartconfig *cf = cp->config; 589 glong scalemax; 590 gint grid_res, i0; 591 592 /* maxval may change at any gkrellm_store_chartdata(), so at each chart 593 | draw compute a scalemax and compare to last cp->scale_max. 594 | Redraw grided background if different. 595 */ 596 if (cf->auto_grid_resolution) 597 { 598 if ( cp->maxval != cp->maxval_auto 599 && ( cp->maxval > cp->maxval_auto 600 || cp->maxval_auto != cp->maxval_auto_base 601 ) 602 ) 603 set_auto_grid_resolution(cp, cp->maxval); 604 else if ( !cf->auto_resolution_stick 605 && cp->maxval < cp->maxval_auto_base / FULL_SCALE_GRIDS 606 ) 607 { 608 if (auto_recalibrate(cp)) 609 set_auto_grid_resolution(cp, cp->maxval); 610 } 611 else 612 cp->auto_recalibrate_delay = 0; 613 } 614 grid_res = cf->grid_resolution; 615 if (cf->fixed_grids) 616 scalemax = grid_res * cf->fixed_grids; 617 else /* Auto scale to cp->maxval */ 618 { 619 if (cp->maxval == 0) 620 scalemax = grid_res; 621 else 622 scalemax = ((cp->maxval - 1) / grid_res + 1) * grid_res; 623 if (cp->previous_total && scalemax > grid_res * FULL_SCALE_GRIDS) 624 scalemax = grid_res * FULL_SCALE_GRIDS; 625 } 626 if (scalemax != cp->scale_max || cp->redraw_all) 627 { 628 cp->redraw_all = FALSE; 629 i0 = 0; /* Will draw all data on chart */ 630 cp->scale_max = scalemax; 631 draw_layer_grid_lines(cp); 632 } 633 else 634 i0 = cp->w - 1; /* Will draw the last data point only */ 635 return i0; 636 } 637 638 void 639 gkrellm_draw_chartdata(GkrellmChart *cp) 640 { 641 GList *list; 642 GkrellmChartdata *cd; 643 gint i0, active_split, current_split; 644 gboolean have_impulse_splits = FALSE; 645 646 if (!cp) 647 return; 648 i0 = setup_chart_scalemax(cp); 649 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_pixmap, 650 0, 0, 0, 0, cp->w, cp->h); 651 652 current_split = active_split = 0; 653 for (list = cp->cd_list; list; list = list->next) 654 { 655 cd = (GkrellmChartdata *) list->data; 656 if (cd->hide) 657 continue; 658 current_split += cd->split_chart; 659 if (!have_impulse_splits && cd->draw_style == CHARTDATA_IMPULSE) 660 { 661 have_impulse_splits = TRUE; 662 active_split = current_split; 663 } 664 /* Clear the area of the data bitmaps that data will be drawn into 665 */ 666 gdk_draw_rectangle(cd->data_bitmap, _GK.bit0_GC, TRUE, 667 i0, 0, cd->w - i0, cp->h); 668 } 669 670 for ( ; have_impulse_splits; ++active_split) 671 have_impulse_splits = draw_chartdata_impulses(cp, cp->cd_list, 672 i0, active_split); 673 674 for (list = cp->cd_list; list; list = list->next) 675 { 676 cd = (GkrellmChartdata *) list->data; 677 if (cd->draw_style == CHARTDATA_LINE && !cd->hide) 678 draw_chartdata_lines(cp, cd, i0); 679 } 680 gdk_gc_set_clip_mask(_GK.draw1_GC, NULL); 681 } 682 683 void 684 gkrellm_alloc_chartdata(GkrellmChart *cp) 685 { 686 GList *list; 687 GkrellmChartdata *cd; 688 size_t w; 689 690 if (!cp) 691 return; 692 w = (size_t) cp->w; 693 for (list = cp->cd_list; list; list = list->next) 694 { 695 cd = (GkrellmChartdata *) list->data; 696 if (cd->w == w && cd->data) 697 continue; 698 cd->w = w; 699 if (cd->data) 700 g_free(cd->data); 701 cd->data = (gulong *) g_new0(gulong, w); 702 cd->maxval = 0; 703 cp->position = cp->w - 1; 704 cp->tail = cp->position; 705 } 706 cp->alloc_width = w; 707 cp->maxval = 0; 708 cp->scale_max = 0; 709 cp->redraw_all = TRUE; 710 } 711 712 static void 713 scroll_chartdata_bitmaps(GkrellmChart *cp) 714 { 715 GList *list; 716 GkrellmChartdata *cd; 717 718 for (list = cp->cd_list; list; list = list->next) 719 { 720 cd = (GkrellmChartdata *) list->data; 721 if (cd->hide) 722 continue; 723 gdk_draw_drawable(cd->data_bitmap, _GK.bit1_GC, cd->data_bitmap, 724 1, 0, 0, 0, cp->w - 1, cp->h); 725 } 726 } 727 728 static gboolean 729 scan_for_impulse_maxval(GkrellmChart *cp, gint active_split) 730 { 731 GList *list; 732 GkrellmChartdata *cd; 733 gint N, I; 734 gint i, current_split; 735 gboolean need_next_split = FALSE; 736 737 for (i = 0; i < cp->w; ++i) 738 { 739 /* N is normal and I inverted cumulative impulse data/split 740 */ 741 N = I = 0; 742 current_split = 0; 743 for (list = cp->cd_list; list; list = list->next) 744 { 745 cd = (GkrellmChartdata *) list->data; 746 if (cd->hide) 747 continue; 748 current_split += cd->split_chart; 749 if ( cd->draw_style != CHARTDATA_IMPULSE 750 || current_split != active_split 751 ) 752 { 753 if ( current_split > active_split 754 && cd->draw_style == CHARTDATA_IMPULSE 755 ) 756 need_next_split = TRUE; 757 continue; 758 } 759 if (cd->inverted) 760 { 761 I += cd->data[i]; 762 if (I > cd->maxval) 763 cd->maxval = I; 764 } 765 else 766 { 767 N += cd->data[i]; 768 if (N > cd->maxval) 769 cd->maxval = N; 770 } 771 if (N + I > cp->maxval) 772 cp->maxval = N + I; 773 } 774 } 775 return need_next_split; 776 } 777 778 static void 779 scan_for_maxval(GkrellmChart *cp) 780 { 781 GList *list; 782 GkrellmChartdata *cd; 783 gint i, current_split, active_split; 784 gboolean have_impulse_splits = FALSE; 785 786 cp->maxval = 0; 787 current_split = 0; 788 active_split = 0; 789 for (list = cp->cd_list; list; list = list->next) 790 { 791 cd = (GkrellmChartdata *) list->data; 792 if (cd->hide) 793 continue; 794 cd->maxval = 0; 795 current_split += cd->split_chart; 796 if (cd->draw_style == CHARTDATA_LINE) 797 for (i = 0; i < cp->w; ++i) 798 { 799 if (cd->data[i] > cd->maxval) 800 cd->maxval = cd->data[i]; 801 if (cd->maxval > cp->maxval) 802 cp->maxval = cd->maxval; 803 } 804 if (!have_impulse_splits && cd->draw_style == CHARTDATA_IMPULSE) 805 { 806 have_impulse_splits = TRUE; 807 active_split = current_split; 808 } 809 } 810 for ( ; have_impulse_splits; ++active_split) 811 have_impulse_splits = scan_for_impulse_maxval(cp, active_split); 812 } 813 814 void 815 gkrellm_store_chartdata(GkrellmChart *cp, gulong total, ...) 816 { 817 va_list args; 818 819 if (!cp) 820 return; 821 va_start(args, total); 822 gkrellm_store_chartdatav(cp, total, args); 823 va_end(args); 824 } 825 826 void 827 gkrellm_store_chartdatav(GkrellmChart *cp, gulong total, va_list args) 828 { 829 GList *list; 830 GkrellmChartdata *cd; 831 gulong range, total_diff; 832 gint n, N_discard, I_discard, N, I; 833 gint active_split, current_split; 834 gboolean need_scan = FALSE; 835 836 if (!cp) 837 return; 838 for (list = cp->cd_list; list; list = list->next) 839 { 840 cd = (GkrellmChartdata *) list->data; 841 //FIXME: missing check for number of passed varargs passed in "args" 842 cd->current = va_arg(args, gulong); 843 if (!cd->monotonic) 844 { 845 cd->previous = 0; 846 cp->previous_total = 0; /* All or none if total is used */ 847 } 848 /* Prime the pump. Also handle data wrap around or reset to zero. 849 */ 850 cd->wrap = 0; 851 if (!cp->primed) 852 cd->previous = cd->current; 853 else if (cd->current < cd->previous) 854 { 855 cd->wrap = (gulong) -1 - cd->previous; 856 cd->previous = 0; 857 } 858 } 859 if (total < cp->previous_total || !cp->primed) 860 cp->previous_total = total; /* Wrap around, this store won't scale */ 861 total_diff = total - cp->previous_total; 862 cp->previous_total = total; 863 864 /* Increment position in circular buffer and remember the data 865 | value to be thrown out. 866 */ 867 cp->position = (cp->position + 1) % cp->w; 868 cp->tail = (cp->tail + 1) % cp->w; 869 n = cp->position; 870 active_split = current_split = 0; 871 N_discard = I_discard = 0; 872 873 /* N is normal and I inverted cumulative impulse data/split 874 */ 875 N = I = 0; 876 for (list = cp->cd_list; list; list = list->next) 877 { 878 cd = (GkrellmChartdata *) list->data; 879 cd->discard = cd->data[cp->tail]; 880 cd->data[n] = (gulong)(cd->current - cd->previous) + cd->wrap; 881 cd->previous = cd->current; 882 883 /* If using totals, scale the stored data to range between 0 and the 884 | max chart value. Max chart value is number of grids * grid res. 885 | No. of grids is 5 in auto grid mode. For plotting data as a %. 886 */ 887 if (total_diff > 0) 888 { 889 range = (cp->config->fixed_grids ? cp->config->fixed_grids 890 : FULL_SCALE_GRIDS) * cp->config->grid_resolution; 891 if (range != total_diff) 892 cd->data[n] = cd->data[n] * range / total_diff; 893 } 894 if (cd->hide || need_scan) 895 continue; 896 897 /* Compare discarded data to new data (accounting for stacked impulse 898 | data) and decide if a new maxval must be set (new data > maxval) 899 | or if a complete rescan of the data is needed to find a new 900 | maxval (a discard > a new). 901 */ 902 current_split += cd->split_chart; 903 if (cd->draw_style == CHARTDATA_IMPULSE) 904 { 905 if (current_split != active_split) 906 { 907 active_split = current_split; 908 N_discard = I_discard = 0; 909 N = I = 0; 910 } 911 if (cd->inverted) 912 { 913 I_discard += cd->discard; 914 I += cd->data[n]; 915 if (I_discard && I_discard >= cd->maxval) 916 need_scan = TRUE; 917 else if (I > cd->maxval) 918 cd->maxval = I; 919 } 920 else 921 { 922 N_discard += cd->discard; 923 N += cd->data[n]; 924 if (N_discard && N_discard >= cd->maxval) 925 need_scan = TRUE; 926 else if (N > cd->maxval) 927 cd->maxval = N; 928 } 929 if (N_discard + I_discard >= cd->maxval) 930 need_scan = TRUE; 931 else if (N + I > cp->maxval) 932 cp->maxval = N + I; 933 } 934 else if (cd->draw_style == CHARTDATA_LINE) 935 { 936 cd->y_p_valid = TRUE; 937 if (cd->discard && cd->discard >= cd->maxval) 938 need_scan = TRUE; 939 else 940 { 941 if (cd->data[n] > cd->maxval) 942 cd->maxval = cd->data[n]; 943 if (cd->maxval > cp->maxval) 944 cp->maxval = cd->maxval; 945 } 946 } 947 } 948 cp->primed = TRUE; 949 if (need_scan || cp->redraw_all) 950 scan_for_maxval(cp); 951 scroll_chartdata_bitmaps(cp); 952 } 953 954 955 956 /* =================================================================== */ 957 958 static void 959 chart_destroy_text_run_list(GkrellmChart *cp) 960 { 961 GList *list; 962 963 if (!cp || !cp->text_run_list) 964 return; 965 for (list = cp->text_run_list; list; list = list->next) 966 g_free(((GkrellmTextRun *) list->data)->text); 967 gkrellm_free_glist_and_data(&cp->text_run_list); 968 } 969 970 static gint 971 chartdata_text_y(GkrellmChart *cp, char key, gint height, 972 gint y_ink, gint shadow) 973 { 974 GList *list; 975 GkrellmChartdata *cd; 976 gint n, y; 977 978 n = key - '0'; 979 y = -100; 980 if (n >= 0) 981 { 982 list = g_list_nth(cp->cd_list, n / 2); 983 if (list) 984 { 985 cd = (GkrellmChartdata *) list->data; 986 if (!cd->hide) 987 { 988 if (n & 1) /* Justify 2 pixels from top of ChartData view */ 989 { 990 y = cd->y + cd->h + y_ink - 3; 991 } 992 else /* Justify to bottom of ChartData view */ 993 { 994 y = cd->y + height + y_ink + shadow - 1; 995 } 996 y = Y_SCREEN_MAP(cp, y); 997 } 998 } 999 } 1000 return y; 1001 } 1002 1003 void 1004 gkrellm_chart_reuse_text_format(GkrellmChart *cp) 1005 { 1006 cp->text_format_reuse = TRUE; 1007 } 1008 1009 void 1010 gkrellm_draw_chart_text(GkrellmChart *cp, gint style_id, gchar *str) 1011 { 1012 GList *list; 1013 GkrellmTextRun *tr; 1014 GkrellmTextstyle *ts, *ts_default, *ts_alt; 1015 gchar c, *s, *t; 1016 gint h, text_length, field_width, fw; 1017 gint offset; 1018 gint xx, x, y, center, shadow; 1019 gboolean right, set_fw, fw_right; 1020 1021 if (!cp || !str) 1022 return; 1023 1024 /* Assume text_format will be changed at each call unless caller has said 1025 | we can reuse it or the whole string compares equal. 1026 */ 1027 if ( !cp->text_format_reuse 1028 && !gkrellm_dup_string(&cp->text_format_string, str) 1029 ) 1030 cp->text_format_reuse = TRUE; 1031 1032 if (_GK.debug_level & DEBUG_CHART_TEXT) 1033 { 1034 g_debug("\n"); 1035 if (!cp->text_format_reuse) 1036 g_debug("draw_chart_text: [%s]\n", str); 1037 } 1038 1039 if ( !cp->text_format_reuse 1040 || cp->text_run_sequence_id != cp->bg_sequence_id 1041 ) 1042 chart_destroy_text_run_list(cp); 1043 cp->text_run_sequence_id = cp->bg_sequence_id; 1044 cp->text_format_reuse = FALSE; 1045 1046 ts_default = gkrellm_chart_textstyle(style_id); 1047 ts_alt = gkrellm_chart_alt_textstyle(style_id); 1048 1049 x = xx = 2; 1050 if (!cp->text_run_list) 1051 gkrellm_text_extents(ts_default->font, _("Ag8"), 3, NULL, 1052 &cp->h_text, &cp->baseline_ref, &cp->y_ink); 1053 1054 y = 2 - cp->y_ink; 1055 h = fw = 0; 1056 tr = NULL; 1057 for (list = cp->text_run_list, s = str; *s; s += text_length) 1058 { 1059 if (!list) 1060 { 1061 tr = g_new0(GkrellmTextRun, 1); 1062 cp->text_run_list = g_list_append(cp->text_run_list, tr); 1063 } 1064 else 1065 { 1066 tr = (GkrellmTextRun *) list->data; 1067 list = list->next; 1068 tr->cache_valid = TRUE; 1069 } 1070 c = '\0'; 1071 center = 0; 1072 right = FALSE; 1073 set_fw = FALSE; 1074 fw_right = FALSE; 1075 ts = ts_default; 1076 field_width = 0; 1077 shadow = ts_default->effect ? 1 : 0; 1078 while (*s == '\\') 1079 { 1080 if ((c = *(++s)) != '\0') 1081 ++s; 1082 if (c == 'n') 1083 { 1084 y += cp->h_text + 1; 1085 x = xx; 1086 } 1087 else if (c == 'c') 1088 center = 1; 1089 else if (c == 'C') 1090 center = 2; 1091 else if (c == 'N') 1092 { 1093 x = xx; /* A conditional newline. If previous string */ 1094 if (h > 2) /* was spaces, no nl. A space has nonzero a */ 1095 y += cp->h_text + 1; 1096 } 1097 else if (c == 'b') 1098 { 1099 y = cp->h - cp->h_text - cp->y_ink - 1; 1100 x = xx; 1101 } 1102 else if (c == 't') 1103 { 1104 y = 2 - cp->y_ink; 1105 x = xx; 1106 } 1107 else if (c == 'r') 1108 right = TRUE; 1109 else if (c == 'p') 1110 { 1111 y -= cp->h_text + 1; 1112 x = xx; 1113 } 1114 else if (c == 'w') 1115 set_fw = TRUE; 1116 else if (c == 'a') 1117 field_width = fw; 1118 else if (c == 'e') 1119 { 1120 field_width = fw; 1121 fw_right = TRUE; 1122 } 1123 else if (c == 'f') 1124 { 1125 ts = ts_alt; 1126 shadow = ts_alt->effect ? 1 : 0; 1127 } 1128 else if (c == 'x' && isdigit((unsigned char)*s)) 1129 xx = *s++ - '0'; 1130 else if (c == 'y' && isdigit((unsigned char)*s)) 1131 y = *s++ - '0'; 1132 else if (c == 'D') 1133 { 1134 y = chartdata_text_y(cp, *s++, cp->h_text, cp->y_ink, shadow); 1135 x = xx; 1136 } 1137 } 1138 t = strchr(s, (gint) '\\'); 1139 if (t) 1140 text_length = t - s; 1141 else 1142 text_length = strlen(s); 1143 1144 if (y == -100) /* asked for a chartdata that is hidden */ 1145 continue; 1146 1147 if ( !tr->cache_valid || !tr->text 1148 || strncmp(tr->text, s, text_length) 1149 || strlen(tr->text) != text_length 1150 ) 1151 { 1152 gkrellm_text_extents(ts->font, s, text_length, 1153 &tr->w, &tr->h, &tr->baseline, &tr->y_ink); 1154 tr->cache_valid = FALSE; 1155 g_free(tr->text); 1156 tr->text = g_strndup(s, text_length); 1157 } 1158 h = tr->h; 1159 1160 if (set_fw) 1161 { 1162 fw = tr->w + shadow; 1163 continue; 1164 } 1165 if (center == 1) 1166 x = (cp->w - tr->w) / 2; 1167 else if (center == 2) 1168 x = cp->w / 2; 1169 else if (fw_right) 1170 x = x + fw - tr->w - shadow; 1171 else if (right) 1172 x = cp->w - tr->w - 2 - shadow; 1173 if (text_length > 1 || (text_length == 1 && *s != ' ')) 1174 { 1175 if (x != tr->x || y != tr->y) 1176 tr->cache_valid = FALSE; 1177 tr->x = x; 1178 tr->y = y; 1179 1180 if (_GK.debug_level & DEBUG_CHART_TEXT) 1181 { 1182 gchar buf[128]; 1183 1184 strncpy(buf, s, text_length); 1185 buf[text_length] = '\0'; 1186 g_debug("draw_chart_text: [%s] ", buf); 1187 } 1188 1189 offset = cp->baseline_ref - tr->baseline; /* align baselines */ 1190 if (_GK.chart_text_no_fill) 1191 gkrellm_draw_text(cp->pixmap, ts, x, y + offset, s, 1192 text_length); 1193 else /* Default text draw effect is fill solid and can use cache */ 1194 { 1195 if (!tr->cache_valid) 1196 { 1197 if (_GK.debug_level & DEBUG_CHART_TEXT) 1198 g_debug("pango "); 1199 gdk_draw_drawable(cp->bg_text_pixmap, _GK.draw1_GC, 1200 cp->bg_pixmap, 1201 x - 1, y + tr->y_ink + offset - 1, 1202 x - 1, y + tr->y_ink + offset - 1, 1203 tr->w + shadow + 2, tr->h + shadow + 1); 1204 gkrellm_draw_text(cp->bg_text_pixmap, ts, x, y + offset, s, 1205 text_length); 1206 } 1207 if (_GK.debug_level & DEBUG_CHART_TEXT) 1208 g_debug("x=%d y=%d w=%d h=%d\n", 1209 x - 1, y + tr->y_ink + offset - 1, 1210 tr->w + shadow + 2, tr->h + shadow + 1); 1211 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_text_pixmap, 1212 x - 1, y + tr->y_ink + offset - 1, 1213 x - 1, y + tr->y_ink + offset - 1, 1214 tr->w + shadow + 2, tr->h + shadow + 1); 1215 } 1216 } 1217 if (field_width && !fw_right) 1218 x += (field_width > tr->w) ? field_width : tr->w; 1219 else 1220 x += tr->w + shadow; 1221 } 1222 } 1223 1224 gint 1225 gkrellm_draw_chart_label(GkrellmChart *cp, GkrellmTextstyle *ts, 1226 gint x, gint y, gchar *s) 1227 { 1228 gint w, h, y_ink; 1229 1230 if (!cp || !ts || !s) 1231 return x; 1232 1233 gkrellm_text_extents(ts->font, s, strlen(s), &w, &h, NULL, &y_ink); 1234 1235 gdk_draw_drawable(cp->pixmap, _GK.draw1_GC, cp->bg_pixmap, 1236 x, y, x, y, w + ts->effect, h + ts->effect); 1237 gkrellm_draw_string(cp->pixmap, ts, x, y - y_ink, s); 1238 1239 return x + w + ts->effect; 1240 } 1241 1242 void 1243 gkrellm_destroy_chartdata_list(GList **cd_list_head) 1244 { 1245 GList *list; 1246 GkrellmChartdata *cd; 1247 1248 if (!cd_list_head) 1249 return; 1250 for (list = *cd_list_head; list; list = list->next) 1251 { 1252 cd = (GkrellmChartdata *) list->data; 1253 if (cd->label) 1254 g_free(cd->label); 1255 if (cd->data) 1256 g_free(cd->data); 1257 if (cd->data_bitmap) 1258 g_object_unref(G_OBJECT(cd->data_bitmap)); 1259 if (cd->layer.pixmap) 1260 g_object_unref(G_OBJECT(cd->layer.pixmap)); 1261 /* cd->layer.src_pixmap & cd->layer.grid_pixmap must be handled by 1262 | creating monitor. 1263 */ 1264 } 1265 gkrellm_free_glist_and_data(cd_list_head); 1266 } 1267 1268 1269 static void 1270 free_chart_pixmaps(GkrellmChart *cp) 1271 { 1272 GList *list; 1273 GkrellmChartdata *cd; 1274 1275 for (list = cp->cd_list; list; list = list->next) 1276 { 1277 cd = (GkrellmChartdata *) list->data; 1278 gkrellm_free_bitmap(&cd->data_bitmap); 1279 gkrellm_free_pixmap(&cd->layer.pixmap); 1280 /* cd->layer.src_pixmap & cd->layer.grid_pixmap must be handled by 1281 | creating monitor. 1282 */ 1283 } 1284 /* If new theme or size, the cd_list will not be destroyed so I can 1285 | reuse the data arrays. Pixmaps will be recreated. 1286 */ 1287 cp->cd_list_index = 0; 1288 1289 gkrellm_free_pixmap(&cp->bg_pixmap); 1290 gkrellm_free_pixmap(&cp->bg_text_pixmap); 1291 gkrellm_free_pixmap(&cp->bg_src_pixmap); 1292 gkrellm_free_pixmap(&cp->bg_grid_pixmap); 1293 1294 gkrellm_free_pixmap(&cp->bg_clean_pixmap); 1295 gkrellm_free_bitmap(&cp->bg_mask); 1296 1297 gkrellm_free_pixmap(&cp->pixmap); 1298 1299 gkrellm_free_pixmap(&cp->top_spacer.clean_pixmap); 1300 gkrellm_free_pixmap(&cp->top_spacer.pixmap); 1301 gkrellm_free_bitmap(&cp->top_spacer.mask); 1302 gkrellm_free_pixmap(&cp->bottom_spacer.clean_pixmap); 1303 gkrellm_free_pixmap(&cp->bottom_spacer.pixmap); 1304 gkrellm_free_bitmap(&cp->bottom_spacer.mask); 1305 } 1306 1307 static void 1308 destroy_chart_data(GkrellmChart *cp) 1309 { 1310 GList *list; 1311 GkrellmChartdata *cd; 1312 1313 free_chart_pixmaps(cp); 1314 chart_destroy_text_run_list(cp); 1315 for (list = cp->cd_list; list; list = list->next) 1316 { 1317 cd = (GkrellmChartdata *) list->data; 1318 if (cd->label) 1319 g_free(cd->label); 1320 if (cd->data) 1321 g_free(cd->data); 1322 cd->label = NULL; 1323 cd->data = NULL; 1324 } 1325 /* Don't free the cd_list. It is in the GkrellmChartconfig struct. 1326 */ 1327 } 1328 1329 /* Destroy everything inside a chart except leave cp->config alone since 1330 | the config is managed by each monitor. 1331 */ 1332 void 1333 gkrellm_chart_destroy(GkrellmChart *cp) 1334 { 1335 gint h_spacers = 0; 1336 1337 if (!cp) 1338 return; 1339 1340 if (cp->top_spacer.image) 1341 h_spacers = cp->top_spacer.height; 1342 if (cp->bottom_spacer.image) 1343 h_spacers += cp->bottom_spacer.height; 1344 1345 gkrellm_freeze_side_frame_packing(); 1346 if (cp->panel) 1347 gkrellm_panel_destroy(cp->panel); 1348 destroy_chart_data(cp); 1349 gtk_widget_destroy(cp->box); 1350 chart_list = g_list_remove(chart_list, cp); 1351 gkrellm_chartconfig_window_destroy(cp); 1352 if (cp->shown) 1353 gkrellm_monitor_height_adjust(-(cp->h + h_spacers)); 1354 g_free(cp); 1355 gkrellm_thaw_side_frame_packing(); 1356 } 1357 1358 void 1359 gkrellm_chartconfig_destroy(GkrellmChartconfig **cf) 1360 { 1361 if (!cf || !*cf) 1362 return; 1363 gkrellm_destroy_chartdata_list((*cf)->chart_cd_list); 1364 g_free(*cf); 1365 *cf = NULL; 1366 } 1367 1368 void 1369 gkrellm_chart_bg_piximage_override(GkrellmChart *cp, 1370 GkrellmPiximage *bg_piximage, GkrellmPiximage *bg_grid_piximage) 1371 { 1372 if (!cp || !bg_piximage || !bg_grid_piximage) 1373 return; 1374 cp->bg_piximage = bg_piximage; 1375 cp->bg_grid_piximage = bg_grid_piximage; 1376 cp->bg_piximage_override = TRUE; 1377 } 1378 1379 1380 static void 1381 set_chartdata_split_heights(GkrellmChart *cp) 1382 { 1383 GList *list, *list1; 1384 GkrellmChartdata *cd, *cd1; 1385 gint splits; 1386 gint i, y0, h_avail, h_free, y_offset; 1387 1388 for (i = 0, splits = 0, list = cp->cd_list; list; list = list->next) 1389 { 1390 cd = (GkrellmChartdata *) list->data; 1391 if (cd->hide) 1392 continue; 1393 if (++i > 1 && cd->split_chart) /* Can't split before the first one */ 1394 ++splits; 1395 cd->split_share = 1.0; 1396 for (list1 = list->next; list1; list1 = list1->next) 1397 { 1398 cd1 = (GkrellmChartdata *) list1->data; 1399 if (!cd1->split_chart || cd1->hide) 1400 continue; 1401 cd->split_share = cd1->split_fraction; 1402 break; 1403 } 1404 } 1405 y_offset = GRID_HEIGHT_Y_OFFSET_ADJUST(cp); 1406 y0 = cp->y + y_offset; 1407 h_avail = cp->h - cp->y - ((splits + 1) * y_offset) 1408 - splits * _GK.bg_separator_height; 1409 h_free = h_avail; 1410 for (list = cp->cd_list; list; list = list->next) 1411 { 1412 cd = (GkrellmChartdata *) list->data; 1413 if (cd->hide) 1414 continue; 1415 cd->y = y0; 1416 for (list1 = list->next; list1; list1 = list1->next) 1417 if (!((GkrellmChartdata *) list1->data)->hide) 1418 break; 1419 if (!list1) 1420 cd->h = h_free; 1421 else 1422 cd->h = (gint) (cd->split_share * (gfloat) h_free); 1423 if (cd->h < 1) 1424 cd->h = 1; 1425 if (list1 && ((GkrellmChartdata *) list1->data)->split_chart) 1426 { 1427 y0 += cd->h + _GK.bg_separator_height + y_offset; 1428 h_free -= cd->h; 1429 } 1430 } 1431 } 1432 1433 GkrellmChartdata * 1434 gkrellm_add_default_chartdata(GkrellmChart *cp, gchar *label) 1435 { 1436 GdkPixmap **src_pixmap, *grid_pixmap; 1437 1438 if (!cp) 1439 return NULL; 1440 if (cp->cd_list_index & 1) 1441 { 1442 src_pixmap = &_GK.data_in_pixmap; 1443 grid_pixmap = _GK.data_in_grid_pixmap; 1444 } 1445 else 1446 { 1447 src_pixmap = &_GK.data_out_pixmap; 1448 grid_pixmap = _GK.data_out_grid_pixmap; 1449 } 1450 return gkrellm_add_chartdata(cp, src_pixmap, grid_pixmap, label); 1451 } 1452 1453 /* Need a GdkPixmap ** because the src pixmap can change (re-rendered at 1454 | size or theme changes). 1455 */ 1456 GkrellmChartdata * 1457 gkrellm_add_chartdata(GkrellmChart *cp, GdkPixmap **src_pixmap, 1458 GdkPixmap *grid_pixmap, gchar *label) 1459 { 1460 GtkWidget *top_win = gkrellm_get_top_window(); 1461 GList *list; 1462 GkrellmChartdata *cd; 1463 1464 if (!cp || !src_pixmap || !grid_pixmap || !label) 1465 return NULL; 1466 1467 /* To handle theme and vert size changes without losing data, reuse the 1468 | GkrellmChartdata structs in the cd_list. 1469 */ 1470 list = g_list_nth(cp->cd_list, cp->cd_list_index++); 1471 if (!list) 1472 { 1473 cd = g_new0(GkrellmChartdata, 1); 1474 cp->cd_list = g_list_append(cp->cd_list, cd); 1475 cp->config->cd_list = cp->cd_list; 1476 cd->split_fraction = 0.5; 1477 } 1478 else 1479 cd = (GkrellmChartdata *) list->data; 1480 cd->chart = cp; 1481 gkrellm_dup_string(&cd->label, label); 1482 cd->monotonic = TRUE; 1483 cd->data_bitmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, 1); 1484 cd->layer.pixmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, -1); 1485 cd->layer.src_pixmap = src_pixmap; 1486 cd->layer.grid_pixmap = grid_pixmap; 1487 1488 set_chartdata_split_heights(cp); 1489 return cd; 1490 } 1491 1492 void 1493 gkrellm_render_data_grid_pixmap(GkrellmPiximage *im, GdkPixmap **pixmap, 1494 GdkColor *color) 1495 { 1496 GtkWidget *top_win = gkrellm_get_top_window(); 1497 gint w, w_pixmap = 0, h = 0; 1498 1499 w = gkrellm_chart_width(); 1500 if (*pixmap) 1501 gdk_drawable_get_size(*pixmap, &w_pixmap, NULL); 1502 if (!*pixmap || w != w_pixmap) 1503 { 1504 if (im) 1505 { 1506 if ((h = gdk_pixbuf_get_height(im->pixbuf)) > 2) 1507 h = 2; 1508 gkrellm_scale_piximage_to_pixmap(im, pixmap, NULL, w, h); 1509 } 1510 else 1511 { 1512 gkrellm_free_pixmap(pixmap); 1513 *pixmap = gdk_pixmap_new(top_win->window, w, 1, -1); 1514 if (color) 1515 gdk_gc_set_foreground(_GK.draw1_GC, color); 1516 else 1517 gdk_gc_set_foreground(_GK.draw1_GC, &_GK.in_color_grid); 1518 gdk_draw_rectangle(*pixmap, _GK.draw1_GC, TRUE, 0, 0, w, 1); 1519 } 1520 } 1521 } 1522 1523 void 1524 gkrellm_render_data_pixmap(GkrellmPiximage *im, GdkPixmap **pixmap, 1525 GdkColor *color, gint h) 1526 { 1527 GtkWidget *top_win = gkrellm_get_top_window(); 1528 gint w, w_pixmap = 0, h_pixmap = 0; 1529 1530 w = gkrellm_chart_width(); 1531 if (*pixmap) 1532 gdk_drawable_get_size(*pixmap, &w_pixmap, &h_pixmap); 1533 1534 if (!*pixmap || w != w_pixmap || h != h_pixmap) 1535 { 1536 if (!gkrellm_scale_piximage_to_pixmap(im, pixmap, NULL, w, h)) 1537 { 1538 *pixmap = gdk_pixmap_new(top_win->window, w, h, -1); 1539 if (color) 1540 gdk_gc_set_foreground(_GK.draw1_GC, color); 1541 else 1542 gdk_gc_set_foreground(_GK.draw1_GC, &_GK.in_color_grid); 1543 gdk_draw_rectangle(*pixmap, _GK.draw1_GC, TRUE, 0,0,w,h); 1544 } 1545 } 1546 } 1547 1548 static void 1549 render_default_data_pixmaps(GkrellmChart *cp) 1550 { 1551 GList *list; 1552 GdkPixmap *pixmap; 1553 gint w, h, w_pixmap = 0; 1554 1555 gkrellm_render_data_grid_pixmap(_GK.data_in_grid_piximage, 1556 &_GK.data_in_grid_pixmap, &_GK.in_color_grid); 1557 gkrellm_render_data_grid_pixmap(_GK.data_out_grid_piximage, 1558 &_GK.data_out_grid_pixmap, &_GK.out_color_grid); 1559 1560 w = gkrellm_chart_width(); 1561 pixmap = _GK.bg_separator_pixmap; 1562 if (pixmap) 1563 gdk_drawable_get_size(pixmap, &w_pixmap, NULL); 1564 if (!pixmap || w_pixmap != w) 1565 { 1566 if ((h = _GK.bg_separator_height) < 1 || h > 5) 1567 h = 2; 1568 if (_GK.bg_separator_piximage) 1569 gkrellm_scale_piximage_to_pixmap(_GK.bg_separator_piximage, 1570 &_GK.bg_separator_pixmap, NULL, w, h); 1571 else 1572 { 1573 GkrellmPiximage *im; 1574 1575 im = gkrellm_bg_panel_piximage(DEFAULT_STYLE_ID); 1576 gkrellm_scale_pixbuf_to_pixmap(im->pixbuf, &_GK.bg_separator_pixmap, 1577 NULL, w, h); 1578 } 1579 } 1580 1581 h = 2; 1582 for (list = chart_list; list; list = list->next) 1583 { 1584 cp = (GkrellmChart *) list->data; 1585 if (cp->h > h) 1586 h = cp->h; 1587 } 1588 gkrellm_render_data_pixmap(_GK.data_in_piximage, 1589 &_GK.data_in_pixmap, &_GK.in_color, h); 1590 gkrellm_render_data_pixmap(_GK.data_out_piximage, 1591 &_GK.data_out_pixmap, &_GK.out_color, h); 1592 } 1593 1594 void 1595 gkrellm_chart_setup(void) 1596 { 1597 gkrellm_free_pixmap(&_GK.data_in_pixmap); 1598 gkrellm_free_pixmap(&_GK.data_in_grid_pixmap); 1599 gkrellm_free_pixmap(&_GK.data_out_pixmap); 1600 gkrellm_free_pixmap(&_GK.data_out_grid_pixmap); 1601 gkrellm_free_pixmap(&_GK.bg_separator_pixmap); 1602 } 1603 1604 #if 0 1605 static gint 1606 compare_chartlist(gconstpointer a, gconstpointer b) 1607 { 1608 GkrellmChart *cp_a = (GkrellmChart *) a; 1609 GkrellmChart *cp_b = (GkrellmChart *) b; 1610 gint result; 1611 1612 if (cp_a->style_id < cp_b->style_id) 1613 result = -1; 1614 else (if cp_a->style_id > cp_b->style_id) 1615 result = 1; 1616 else 1617 result = 0; 1618 return result; 1619 } 1620 #endif 1621 1622 static void 1623 insert_in_chartlist(GkrellmChart *cp) 1624 { 1625 GList *list; 1626 GkrellmChart *cp_x; 1627 gint position = 0; 1628 1629 for (list = chart_list; list; list = list->next, ++position) 1630 { 1631 cp_x = (GkrellmChart *) list->data; 1632 if (cp_x->style_id > cp->style_id) 1633 { 1634 chart_list = g_list_insert(chart_list, cp, position); 1635 return; 1636 } 1637 } 1638 chart_list = g_list_append(chart_list, cp); 1639 } 1640 1641 void 1642 gkrellm_chart_hide(GkrellmChart *cp, gboolean hide_panel) 1643 { 1644 gint h_spacers = 0; 1645 1646 if (!cp || !cp->shown) 1647 return; 1648 1649 if (cp->top_spacer.image) 1650 h_spacers = cp->top_spacer.height; 1651 if (cp->bottom_spacer.image) 1652 h_spacers += cp->bottom_spacer.height; 1653 1654 gtk_widget_hide(cp->box); 1655 gkrellm_freeze_side_frame_packing(); 1656 if (hide_panel) 1657 gkrellm_panel_hide(cp->panel); 1658 gkrellm_monitor_height_adjust(- (cp->h + h_spacers)); 1659 cp->shown = FALSE; 1660 gkrellm_thaw_side_frame_packing(); 1661 } 1662 1663 void 1664 gkrellm_chart_show(GkrellmChart *cp, gboolean show_panel) 1665 { 1666 gint h_spacers = 0; 1667 1668 if (!cp || cp->shown) 1669 return; 1670 1671 if (cp->top_spacer.image) 1672 h_spacers = cp->top_spacer.height; 1673 if (cp->bottom_spacer.image) 1674 h_spacers += cp->bottom_spacer.height; 1675 1676 gtk_widget_show(cp->box); 1677 gkrellm_freeze_side_frame_packing(); 1678 if (show_panel) 1679 gkrellm_panel_show(cp->panel); 1680 cp->shown = TRUE; 1681 gkrellm_monitor_height_adjust(cp->h + h_spacers); 1682 gkrellm_thaw_side_frame_packing(); 1683 } 1684 1685 gboolean 1686 gkrellm_is_chart_visible(GkrellmChart *cp) 1687 { 1688 if (!cp) 1689 return FALSE; 1690 return cp->shown; 1691 } 1692 1693 gboolean 1694 gkrellm_chart_enable_visibility(GkrellmChart *cp, gboolean new_vis, 1695 gboolean *current_vis) 1696 { 1697 gboolean changed = FALSE; 1698 1699 if (new_vis && ! *current_vis) 1700 { 1701 gkrellm_chart_show(cp, TRUE); 1702 *current_vis = TRUE; 1703 changed = TRUE; 1704 } 1705 if (!new_vis && *current_vis) 1706 { 1707 gkrellm_chart_hide(cp, TRUE); 1708 *current_vis = FALSE; 1709 changed = TRUE; 1710 } 1711 return changed; 1712 } 1713 1714 void 1715 gkrellm_set_chart_height_default(GkrellmChart *cp, gint h) 1716 { 1717 if (!cp || (cp->config && cp->config->config_loaded)) 1718 return; 1719 1720 if (h < MIN_CHARTHEIGHT) 1721 h = MIN_CHARTHEIGHT; 1722 if (h > MAX_CHARTHEIGHT) 1723 h = MAX_CHARTHEIGHT; 1724 cp->h = h; 1725 } 1726 1727 static void 1728 render_chart_margin_spacers(GkrellmChart *cp) 1729 { 1730 GkrellmMargin *m; 1731 GkrellmSpacer *ts, *bs; 1732 1733 ts = &cp->top_spacer; 1734 bs = &cp->bottom_spacer; 1735 if (ts->image) 1736 gtk_container_remove(GTK_CONTAINER(ts->vbox), ts->image); 1737 if (bs->image) 1738 gtk_container_remove(GTK_CONTAINER(bs->vbox), bs->image); 1739 ts->image = bs->image = NULL; 1740 m = gkrellm_get_style_margins(cp->style); 1741 ts->piximage = cp->bg_piximage; 1742 ts->height = m->top; 1743 bs->piximage = cp->bg_piximage; 1744 bs->height = m->bottom; 1745 1746 if (!gkrellm_render_spacer(ts, 0, m->top, 1747 _GK.frame_left_chart_overlap, _GK.frame_right_chart_overlap)) 1748 gtk_widget_hide(ts->vbox); 1749 1750 if (!gkrellm_render_spacer(bs, 1751 gdk_pixbuf_get_height(cp->bg_piximage->pixbuf) - m->bottom, 1752 m->bottom, 1753 _GK.frame_left_chart_overlap, _GK.frame_right_chart_overlap)) 1754 gtk_widget_hide(bs->vbox); 1755 } 1756 1757 #if 0 1758 static gboolean 1759 cb_chart_map_event(GtkWidget *widget, GdkEvent *event, GkrellmChart *cp) 1760 { 1761 gdk_window_get_position(cp->drawing_area->window, NULL, &cp->y_mapped); 1762 if (_GK.frame_left_chart_overlap > 0 || _GK.frame_right_chart_overlap > 0) 1763 _GK.need_frame_packing = TRUE; 1764 return FALSE; 1765 } 1766 #endif 1767 1768 static gboolean 1769 cb_chart_size_allocate(GtkWidget *widget, GtkAllocation *size, 1770 GkrellmChart *cp) 1771 { 1772 gdk_window_get_position(cp->drawing_area->window, NULL, &cp->y_mapped); 1773 if (_GK.frame_left_chart_overlap > 0 || _GK.frame_right_chart_overlap > 0) 1774 _GK.need_frame_packing = TRUE; 1775 return FALSE; 1776 } 1777 1778 static void 1779 render_chart_pixmaps(GkrellmChart *cp) 1780 { 1781 GkrellmPiximage piximage; 1782 GkrellmMargin *m; 1783 gint h, w; 1784 1785 m = gkrellm_get_style_margins(cp->style); 1786 w = gdk_pixbuf_get_width(cp->bg_piximage->pixbuf) 1787 - _GK.frame_left_chart_overlap - _GK.frame_right_chart_overlap; 1788 h = gdk_pixbuf_get_height(cp->bg_piximage->pixbuf) - m->top - m->bottom; 1789 1790 if ( ( m->top > 0 || m->bottom > 0 1791 || _GK.frame_left_chart_overlap > 0 1792 || _GK.frame_right_chart_overlap > 0 1793 ) 1794 && w > 0 && h > 0 1795 ) 1796 { 1797 piximage.pixbuf = gdk_pixbuf_new_subpixbuf(cp->bg_piximage->pixbuf, 1798 _GK.frame_left_chart_overlap, m->top, w, h); 1799 piximage.border = cp->bg_piximage->border; 1800 gkrellm_border_adjust(&piximage.border, 1801 -_GK.frame_left_chart_overlap, -_GK.frame_right_chart_overlap, 1802 -m->top, -m->bottom); 1803 gkrellm_scale_piximage_to_pixmap(&piximage, &cp->bg_clean_pixmap, 1804 &cp->bg_mask, cp->w, cp->h); 1805 g_object_unref(G_OBJECT(piximage.pixbuf)); 1806 } 1807 else 1808 gkrellm_scale_piximage_to_pixmap(cp->bg_piximage, 1809 &cp->bg_clean_pixmap, &cp->bg_mask, cp->w, cp->h); 1810 1811 gkrellm_clone_pixmap(&cp->pixmap, &cp->bg_clean_pixmap); 1812 gkrellm_clone_pixmap(&cp->bg_pixmap, &cp->bg_clean_pixmap); 1813 gkrellm_clone_pixmap(&cp->bg_src_pixmap, &cp->bg_clean_pixmap); 1814 gkrellm_clone_pixmap(&cp->bg_text_pixmap, &cp->bg_clean_pixmap); 1815 } 1816 1817 void 1818 gkrellm_chart_create(GtkWidget *vbox, GkrellmMonitor *mon, GkrellmChart *cp, 1819 GkrellmChartconfig **config) 1820 { 1821 GkrellmMargin *m; 1822 GkrellmChartconfig *cf; 1823 gint h, style_id; 1824 1825 if (!vbox || !mon || !cp || !config) 1826 return; 1827 if (mon->privat->style_type == CHART_PANEL_TYPE) 1828 style_id = mon->privat->style_id; 1829 else 1830 style_id = DEFAULT_STYLE_ID; 1831 cp->style = gkrellm_chart_style(style_id); 1832 m = gkrellm_get_style_margins(cp->style); 1833 cp->monitor = (gpointer) mon; 1834 if (!cp->bg_piximage_override) 1835 { 1836 cp->bg_piximage = gkrellm_bg_chart_piximage(style_id); 1837 cp->bg_grid_piximage = gkrellm_bg_grid_piximage(style_id); 1838 } 1839 cp->bg_piximage_override = FALSE; 1840 cp->x = 0; 1841 /* cp->y = 0; */ 1842 cp->w = _GK.chart_width; 1843 if (!*config) 1844 { 1845 *config = gkrellm_chartconfig_new0(); 1846 (*config)->auto_grid_resolution = TRUE; /* the default */ 1847 (*config)->h = cp->h; /* In case default */ 1848 } 1849 cf = cp->config = *config; 1850 if (cf->h < 5) 1851 cf->h = 40; 1852 cp->h = cf->h; 1853 if (cf->grid_resolution < 1) 1854 cf->grid_resolution = 1; 1855 cp->cd_list = cp->config->cd_list; 1856 cp->config->chart_cd_list = &cp->cd_list; 1857 1858 if (!cp->box) 1859 { 1860 cp->box = gtk_vbox_new(FALSE, 0); /* not a hbox anymore !! */ 1861 gtk_box_pack_start(GTK_BOX(vbox), cp->box, FALSE, FALSE, 0); 1862 1863 cp->top_spacer.vbox = gtk_vbox_new(FALSE, 0); 1864 gtk_box_pack_start(GTK_BOX(cp->box), cp->top_spacer.vbox, 1865 FALSE, FALSE, 0); 1866 cp->drawing_area = gtk_drawing_area_new(); 1867 gtk_widget_set_events(cp->drawing_area, GDK_EXPOSURE_MASK 1868 | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK 1869 | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK 1870 | GDK_POINTER_MOTION_MASK); 1871 gtk_box_pack_start(GTK_BOX(cp->box), cp->drawing_area, 1872 FALSE, FALSE, 0); 1873 cp->bottom_spacer.vbox = gtk_vbox_new(FALSE, 0); 1874 gtk_box_pack_start(GTK_BOX(cp->box), cp->bottom_spacer.vbox, 1875 FALSE, FALSE, 0); 1876 1877 gtk_widget_show(cp->drawing_area); 1878 gtk_widget_show(cp->box); 1879 cp->shown = TRUE; 1880 gtk_widget_realize(cp->box); 1881 gtk_widget_realize(cp->drawing_area); 1882 cp->style_id = style_id; 1883 insert_in_chartlist(cp); 1884 cp->y_mapped = -1; 1885 // g_signal_connect(G_OBJECT (cp->drawing_area), "map_event", 1886 // G_CALLBACK(cb_chart_map_event), cp); 1887 g_signal_connect(G_OBJECT (cp->drawing_area), "size_allocate", 1888 G_CALLBACK(cb_chart_size_allocate), cp); 1889 } 1890 else 1891 free_chart_pixmaps(cp); 1892 1893 gtk_widget_set_size_request(cp->drawing_area, cp->w, cp->h); 1894 1895 cp->bg_sequence_id += 1; 1896 1897 render_chart_pixmaps(cp); 1898 render_chart_margin_spacers(cp); 1899 1900 h = gdk_pixbuf_get_height(cp->bg_grid_piximage->pixbuf); 1901 if (h > 2) 1902 h = 2; 1903 gkrellm_scale_piximage_to_pixmap(cp->bg_grid_piximage, 1904 &cp->bg_grid_pixmap, NULL, cp->w, h); 1905 1906 cp->transparency = cp->style->transparency; 1907 _GK.any_transparency |= cp->transparency; 1908 1909 gkrellm_set_draw_chart_function(cp, default_draw_chart_function, cp); 1910 cp->redraw_all = TRUE; 1911 render_default_data_pixmaps(cp); 1912 if (cp->shown) 1913 { 1914 gkrellm_monitor_height_adjust(cp->h + m->top + m->bottom); 1915 gkrellm_pack_side_frames(); 1916 } 1917 } 1918 1919 void 1920 gkrellm_refresh_chart(GkrellmChart *cp) 1921 { 1922 if (!cp) 1923 return; 1924 cp->redraw_all = TRUE; 1925 cp->maxval_auto = -1; 1926 if (cp->draw_chart) 1927 (*(cp->draw_chart))(cp->draw_chart_data); 1928 } 1929 1930 void 1931 gkrellm_rescale_chart(GkrellmChart *cp) 1932 { 1933 if (!cp) 1934 return; 1935 scan_for_maxval(cp); 1936 gkrellm_refresh_chart(cp); 1937 } 1938 1939 /* =================================================================== */ 1940 1941 1942 static gint map_125_table[] = 1943 { 1944 1, 2, 5, 1945 10, 20, 50, 1946 100, 200, 500, 1947 1000, 2000, 5000, 1948 10000, 20000, 50000, 1949 100000, 200000, 500000, 1950 1000000, 2000000, 5000000, 1951 10000000, 20000000, 50000000, 1952 100000000, 200000000, 500000000 1953 }; 1954 1955 static gint map_12357_table[] = 1956 { 1957 1, 2, 3, 5, 7, 1958 10, 15, 20, 30, 50, 70, 1959 100, 150, 200, 300, 500, 700, 1960 1000, 1500, 2000, 3000, 5000, 7000, 1961 10000, 15000, 20000, 30000, 50000, 70000, 1962 100000, 150000, 200000, 300000, 500000, 700000, 1963 1000000, 1500000, 2000000, 3000000, 5000000, 7000000, 1964 10000000, 15000000, 20000000, 30000000, 50000000, 70000000, 1965 100000000, 150000000, 200000000, 300000000, 500000000, 700000000 1966 }; 1967 1968 gint 1969 gkrellm_125_sequence(gint value, gboolean use125, 1970 gint low, gint high, 1971 gboolean snap_to_table, gboolean roundup) 1972 { 1973 gint i, table_size; 1974 gint *table; 1975 1976 if (use125) 1977 { 1978 table = map_125_table; 1979 table_size = sizeof(map_125_table) / sizeof(gint); 1980 } 1981 else 1982 { 1983 table = map_12357_table; 1984 table_size = sizeof(map_12357_table) / sizeof(gint); 1985 } 1986 if (value < low) 1987 value = low; 1988 if (value > high) 1989 value = high; 1990 if (value < table[0]) 1991 return table[0]; 1992 if (value > table[table_size - 1]) 1993 return table[table_size - 1]; 1994 if (!snap_to_table && !roundup) 1995 { 1996 for (i = 0; i < table_size; ++i) 1997 { 1998 /*g_debug(" mapping[%d] value=%d table=%d\n", i, value, table[i]); */ 1999 if (value == table[i]) 2000 return table[i]; 2001 else if (value == table[i] - 1) 2002 return table[i - 1]; 2003 else if (value == table[i] + 1) 2004 return table[i + 1]; 2005 } 2006 } 2007 else if (snap_to_table && !roundup) 2008 { 2009 for (i = table_size - 1; i >= 0; --i) 2010 { 2011 if (value >= table[i]) 2012 { 2013 value = table[i]; 2014 break; 2015 } 2016 } 2017 } 2018 else if (snap_to_table && roundup) 2019 { 2020 for (i = 0; i < table_size; ++i) 2021 { 2022 if (value <= table[i]) 2023 { 2024 value = table[i]; 2025 break; 2026 } 2027 } 2028 } 2029 return value; 2030 } 2031 2032 static void 2033 set_grid_resolution_spin_button(GkrellmChart *cp, gint res) 2034 { 2035 GtkSpinButton *spin; 2036 2037 if (!cp || !cp->config_window || !cp->config->grid_resolution_spin_button) 2038 return; 2039 spin = GTK_SPIN_BUTTON(cp->config->grid_resolution_spin_button); 2040 gtk_spin_button_set_value(spin, (gfloat) res); 2041 } 2042 2043 static void 2044 cb_chart_grid_resolution(GtkWidget *adjustment, GkrellmChart *cp) 2045 { 2046 GtkSpinButton *spin; 2047 GkrellmChartconfig *cf; 2048 gint res; 2049 gfloat fres; 2050 2051 _GK.config_modified = TRUE; 2052 cf = cp->config; 2053 spin = GTK_SPIN_BUTTON(cf->grid_resolution_spin_button); 2054 if (cf->map_sequence) 2055 { 2056 res = gtk_spin_button_get_value_as_int(spin); 2057 if (res != cf->grid_resolution) 2058 { 2059 res = gkrellm_125_sequence(res, cf->sequence_125, 2060 cf->low, cf->high, FALSE, FALSE); 2061 cf->grid_resolution = res; 2062 gtk_spin_button_set_value(spin, (gfloat) res); 2063 if (cf->cb_grid_resolution && !cf->cb_block) 2064 (*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data); 2065 gkrellm_refresh_chart(cp); 2066 } 2067 } 2068 else 2069 { 2070 fres = gtk_spin_button_get_value(spin); 2071 if (cf->spin_factor > 0.0) 2072 fres *= cf->spin_factor; 2073 cf->grid_resolution = (gint) fres; 2074 if (cf->grid_resolution < 1) 2075 cf->grid_resolution = 1; 2076 if (cf->cb_grid_resolution && !cf->cb_block) 2077 (*cf->cb_grid_resolution)(cf, cf->cb_grid_resolution_data); 2078 gkrellm_refresh_chart(cp); 2079 } 2080 } 2081 2082 2083 /* ---- GkrellmChartconfig functions ---- */ 2084 void 2085 gkrellm_chartconfig_callback_block(GkrellmChartconfig *cf, gboolean block) 2086 { 2087 if (!cf) 2088 return; 2089 cf->cb_block = block; 2090 } 2091 2092 void 2093 gkrellm_set_chartconfig_grid_resolution(GkrellmChartconfig *cf, gint res) 2094 { 2095 if (!cf || res <= 0) 2096 return; 2097 cf->grid_resolution = res; 2098 } 2099 2100 gint 2101 gkrellm_get_chartconfig_grid_resolution(GkrellmChartconfig *cf) 2102 { 2103 if (!cf) 2104 return 0; 2105 return cf->grid_resolution; 2106 } 2107 2108 void 2109 gkrellm_chartconfig_grid_resolution_connect(GkrellmChartconfig *cf, 2110 void (*func)(gpointer), gpointer data) 2111 { 2112 if (!cf) 2113 return; 2114 cf->cb_grid_resolution = func; 2115 cf->cb_grid_resolution_data = data; 2116 } 2117 2118 void 2119 gkrellm_set_chartconfig_flags(GkrellmChartconfig *cf, gint flags) 2120 { 2121 if (!cf) 2122 return; 2123 cf->flags = flags; 2124 } 2125 2126 void 2127 gkrellm_chartconfig_grid_resolution_adjustment(GkrellmChartconfig *cf, 2128 gboolean map_sequence, gfloat spin_factor, 2129 gfloat low, gfloat high, gfloat step0, gfloat step1, gint digits, 2130 gint width) 2131 { 2132 if (!cf) 2133 return; 2134 cf->map_sequence = map_sequence; 2135 if ((cf->width = width) == 0) 2136 cf->width = 70 + log(high / 100000) * 5; 2137 if (map_sequence) 2138 { 2139 cf->low = 1; 2140 cf->low = (gfloat) gkrellm_125_sequence((gint) low, cf->sequence_125, 2141 low, high, TRUE, FALSE); 2142 cf->high = (gfloat) gkrellm_125_sequence((gint) high, 2143 cf->sequence_125, low, high, TRUE, TRUE); 2144 cf->step0 = 1.0; 2145 cf->step1 = 1.0; 2146 cf->digits = 0; 2147 } 2148 else 2149 { 2150 cf->low = low; 2151 cf->high = high; 2152 cf->step0 = step0; 2153 cf->step1 = step1; 2154 cf->digits = digits; 2155 cf->spin_factor = spin_factor; 2156 } 2157 if (cf->spin_factor < 1.0) 2158 cf->spin_factor = 1.0; 2159 cf->adjustment_is_set = TRUE; 2160 } 2161 2162 void 2163 gkrellm_chartconfig_grid_resolution_label(GkrellmChartconfig *cf, gchar *label) 2164 { 2165 if (!cf) 2166 return; 2167 gkrellm_dup_string(&cf->grid_resolution_label, label); 2168 } 2169 2170 void 2171 gkrellm_set_chartconfig_auto_grid_resolution(GkrellmChartconfig *cf, gboolean ato) 2172 { 2173 if (cf) 2174 cf->auto_grid_resolution = ato; 2175 } 2176 2177 void 2178 gkrellm_set_chartconfig_auto_resolution_stick(GkrellmChartconfig *cf, gboolean stick) 2179 { 2180 if (cf) 2181 cf->auto_resolution_stick = stick; 2182 } 2183 2184 void 2185 gkrellm_set_chartconfig_sequence_125(GkrellmChartconfig *cf, gboolean seq) 2186 { 2187 if (cf) 2188 cf->sequence_125 = seq; 2189 } 2190 2191 void 2192 gkrellm_set_chartconfig_fixed_grids(GkrellmChartconfig *cf, gint fixed_grids) 2193 { 2194 if (!cf || fixed_grids < 0 || fixed_grids > 5) 2195 return; 2196 cf->fixed_grids = fixed_grids; 2197 } 2198 2199 gint 2200 gkrellm_get_chartconfig_fixed_grids(GkrellmChartconfig *cf) 2201 { 2202 if (!cf) 2203 return 0; 2204 return cf->fixed_grids; 2205 } 2206 2207 void 2208 gkrellm_chartconfig_fixed_grids_connect(GkrellmChartconfig *cf, 2209 void (*func)(gpointer), gpointer data) 2210 { 2211 if (!cf) 2212 return; 2213 cf->cb_fixed_grids = func; 2214 cf->cb_fixed_grids_data = data; 2215 } 2216 2217 gint 2218 gkrellm_get_chartconfig_height(GkrellmChartconfig *cf) 2219 { 2220 if (!cf) 2221 return 0; 2222 return cf->h; 2223 } 2224 2225 void 2226 gkrellm_chartconfig_height_connect(GkrellmChartconfig *cf, 2227 void (*func)(gpointer), gpointer data) 2228 { 2229 if (!cf) 2230 return; 2231 cf->cb_height = func; 2232 cf->cb_height_data = data; 2233 } 2234 2235 void 2236 gkrellm_set_chart_height(GkrellmChart *cp, gint h) 2237 { 2238 GtkWidget *top_win = gkrellm_get_top_window(); 2239 GtkSpinButton *spin; 2240 GList *list; 2241 GkrellmChartdata *cd; 2242 GkrellmChartconfig *cf; 2243 gint dy; 2244 2245 if (!cp || cp->h == h) 2246 return; 2247 dy = h - cp->h; 2248 cp->h = h; 2249 cp->config->h = h; 2250 render_default_data_pixmaps(cp); 2251 for (list = cp->cd_list; list; list = list->next) 2252 { 2253 cd = (GkrellmChartdata *) list->data; 2254 g_object_unref(G_OBJECT(cd->data_bitmap)); 2255 g_object_unref(G_OBJECT(cd->layer.pixmap)); 2256 cd->data_bitmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, 1); 2257 cd->layer.pixmap = gdk_pixmap_new(top_win->window, cp->w, cp->h, -1); 2258 } 2259 cp->bg_sequence_id += 1; 2260 render_chart_pixmaps(cp); 2261 2262 cf = cp->config; 2263 if (cf->cb_height && !cf->cb_block) 2264 (*cf->cb_height)(cf, cf->cb_height_data); 2265 gtk_widget_set_size_request(cp->drawing_area, cp->w, cp->h); 2266 set_chartdata_split_heights(cp); 2267 if (cp->shown) 2268 { 2269 gkrellm_monitor_height_adjust(dy); 2270 gkrellm_pack_side_frames(); 2271 gkrellm_refresh_chart(cp); 2272 } 2273 if (cp->config_window) 2274 { 2275 spin = GTK_SPIN_BUTTON(cf->height_spin_button); 2276 if (h != gtk_spin_button_get_value_as_int(spin)) 2277 gtk_spin_button_set_value(spin, (gfloat) h); 2278 } 2279 } 2280 2281 gboolean 2282 gkrellm_get_chartdata_hide(GkrellmChartdata *cd) 2283 { 2284 if (cd && cd->hide) 2285 return TRUE; 2286 return FALSE; 2287 } 2288 2289 2290 /* =================================================================== */ 2291 2292 static void 2293 chart_config_window_close(GtkWidget *widget, GkrellmChart *cp) 2294 { 2295 if (cp->config_window) 2296 gtk_widget_destroy(cp->config_window); 2297 cp->config_window = NULL; 2298 } 2299 2300 void 2301 gkrellm_chartconfig_window_destroy(GkrellmChart *cp) 2302 { 2303 chart_config_window_close(NULL, cp); 2304 } 2305 2306 static gint 2307 chart_config_window_delete_event(GtkWidget *widget, GdkEvent *ev, 2308 gpointer data) 2309 { 2310 chart_config_window_close(widget, data); 2311 return FALSE; 2312 } 2313 2314 static void 2315 set_resolution_menubar_items_sensitivity(GkrellmChartconfig *cf) 2316 { 2317 GtkWidget *w; 2318 2319 if (!cf->auto_resolution_ui_manager) 2320 return; 2321 2322 w = gtk_ui_manager_get_widget(cf->auto_resolution_ui_manager, 2323 "/menubar/Control/AutoModeStickPeak"); 2324 GTK_CHECK_MENU_ITEM(w)->active = cf->auto_resolution_stick; 2325 2326 w = gtk_ui_manager_get_widget(cf->auto_resolution_ui_manager, 2327 "/menubar/Control/AutoModeRecalibrate"); 2328 if (cf->auto_grid_resolution) 2329 gtk_widget_set_sensitive(w, TRUE); 2330 else 2331 gtk_widget_set_sensitive(w, FALSE); 2332 } 2333 2334 static void 2335 cb_chart_height(GtkWidget *adjustment, GkrellmChart *cp) 2336 { 2337 GtkSpinButton *spin; 2338 gint h; 2339 2340 _GK.config_modified = TRUE; 2341 spin = GTK_SPIN_BUTTON(cp->config->height_spin_button); 2342 h = gtk_spin_button_get_value_as_int(spin); 2343 gkrellm_set_chart_height(cp, h); 2344 } 2345 2346 static void 2347 cb_chart_fixed_grids(GtkWidget *adjustment, GkrellmChart *cp) 2348 { 2349 GtkSpinButton *spin; 2350 GkrellmChartconfig *cf = cp->config; 2351 2352 _GK.config_modified = TRUE; 2353 spin = GTK_SPIN_BUTTON(cf->fixed_grids_spin_button); 2354 cf->fixed_grids = gtk_spin_button_get_value_as_int(spin); 2355 if (cf->auto_grid_resolution) 2356 set_auto_grid_resolution(cp, cp->maxval_auto); 2357 if (cf->cb_fixed_grids && !cf->cb_block) 2358 (*cf->cb_fixed_grids)(cf, cf->cb_fixed_grids_data); 2359 2360 set_resolution_menubar_items_sensitivity(cf); 2361 2362 gkrellm_refresh_chart(cp); 2363 } 2364 2365 static void 2366 cb_line_draw_style(GtkWidget *widget, GkrellmChartdata *cd) 2367 { 2368 _GK.config_modified = TRUE; 2369 cd->draw_style = GTK_TOGGLE_BUTTON(widget)->active; 2370 gkrellm_rescale_chart(cd->chart); 2371 } 2372 2373 static void 2374 cb_auto_resolution(GtkWidget *widget, GkrellmChart *cp) 2375 { 2376 GtkWidget *button; 2377 GkrellmChartconfig *cf = cp->config; 2378 2379 _GK.config_modified = TRUE; 2380 cf->auto_grid_resolution = GTK_TOGGLE_BUTTON(widget)->active; 2381 2382 set_resolution_menubar_items_sensitivity(cf); 2383 button = cf->grid_resolution_spin_button; 2384 if (cf->auto_grid_resolution) 2385 gtk_widget_set_sensitive(button, FALSE); 2386 else 2387 gtk_widget_set_sensitive(button, TRUE); 2388 gkrellm_rescale_chart(cp); 2389 } 2390 2391 static void 2392 cb_inverted_draw_mode(GtkWidget *widget, GkrellmChartdata *cd) 2393 { 2394 _GK.config_modified = TRUE; 2395 cd->inverted = GTK_TOGGLE_BUTTON(widget)->active; 2396 gkrellm_rescale_chart(cd->chart); 2397 } 2398 2399 static void 2400 cb_hide(GtkWidget *widget, GkrellmChartdata *cd) 2401 { 2402 _GK.config_modified = TRUE; 2403 cd->hide = GTK_TOGGLE_BUTTON(widget)->active; 2404 set_chartdata_split_heights(cd->chart); 2405 gkrellm_rescale_chart(cd->chart); 2406 } 2407 2408 static void 2409 cb_split_mode(GtkWidget *widget, GkrellmChartdata *cd) 2410 { 2411 _GK.config_modified = TRUE; 2412 cd->split_chart = GTK_TOGGLE_BUTTON(widget)->active; 2413 gtk_widget_set_sensitive(cd->split_fraction_spin_button, cd->split_chart); 2414 set_chartdata_split_heights(cd->chart); 2415 gkrellm_rescale_chart(cd->chart); 2416 } 2417 2418 static void 2419 cb_split_fraction(GtkWidget *adjustment, GkrellmChartdata *cd) 2420 { 2421 GtkSpinButton *spin; 2422 2423 _GK.config_modified = TRUE; 2424 spin = GTK_SPIN_BUTTON(cd->split_fraction_spin_button); 2425 cd->split_fraction = gtk_spin_button_get_value(spin); 2426 set_chartdata_split_heights(cd->chart); 2427 gkrellm_rescale_chart(cd->chart); 2428 } 2429 2430 2431 /* =================================================================== */ 2432 2433 static void 2434 cb_seq_control(GtkRadioAction *action, GtkRadioAction *current, GkrellmChart *cp ) 2435 { 2436 GkrellmChartconfig *cf = cp->config; 2437 2438 if (cf->sequence_125 == gtk_radio_action_get_current_value(action)) 2439 return; 2440 cf->sequence_125 = gtk_radio_action_get_current_value(action); 2441 2442 cf->grid_resolution = gkrellm_125_sequence(cf->grid_resolution, 2443 cf->sequence_125, cf->low, cf->high, TRUE, FALSE); 2444 set_grid_resolution_spin_button(cp, cf->grid_resolution); 2445 } 2446 2447 static void 2448 cb_auto_stick_control(GtkToggleAction *action, GkrellmChart *cp ) 2449 { 2450 GkrellmChartconfig *cf = cp->config; 2451 2452 cf->auto_resolution_stick = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); 2453 cp->maxval_auto_base = 0; 2454 gkrellm_refresh_chart(cp); 2455 } 2456 2457 static void 2458 cb_auto_res_control(GtkAction *action, GkrellmChart *cp ) 2459 { 2460 cp->maxval_auto_base = 0; 2461 cp->maxval_peak = 0; 2462 gkrellm_refresh_chart(cp); 2463 } 2464 2465 static const char *auto_res_control_items = "\ 2466 <ui>\ 2467 <menubar>\ 2468 <menu name=\"Control\" action=\"ControlAction\">\ 2469 <separator/>\ 2470 <menuitem name=\"AutoModeRecalibrate\" action=\"AutoModeRecalibrateAction\"/>\ 2471 <menuitem name=\"AutoModeStickPeak\" action=\"AutoModeStickPeakAction\"/>\ 2472 <menu name=\"SequenceMenu\" action=\"SequenceMenuAction\">\ 2473 <menuitem name=\"Seq125\" action=\"Seq125Action\"/>\ 2474 <menuitem name=\"Seq1357\" action=\"Seq1357Action\"/>\ 2475 </menu>\ 2476 <separator/>\ 2477 </menu>\ 2478 </menubar>\ 2479 </ui>\ 2480 "; 2481 2482 static GtkActionEntry auto_res_control_entries[] = 2483 { 2484 { "ControlAction", NULL, N_("Control"), 2485 NULL, NULL, G_CALLBACK(NULL) }, 2486 { "SequenceMenuAction", NULL, N_("Sequence..."), 2487 NULL, NULL, G_CALLBACK(NULL) }, 2488 { "AutoModeRecalibrateAction", NULL, N_("Auto mode recalibrate"), 2489 NULL, NULL, G_CALLBACK(cb_auto_res_control) }, 2490 }; 2491 static guint n_auto_res_control_entries = G_N_ELEMENTS (auto_res_control_entries); 2492 2493 static GtkToggleActionEntry auto_res_control_toggle_entries[] = 2494 { 2495 { "AutoModeStickPeakAction", NULL, N_("Auto mode sticks at peak value"), 2496 NULL, NULL, G_CALLBACK(cb_auto_stick_control), FALSE }, 2497 }; 2498 static guint n_auto_res_control_toggle_entries = G_N_ELEMENTS (auto_res_control_toggle_entries); 2499 2500 static GtkRadioActionEntry auto_res_control_radio_entries[] = 2501 { 2502 { "Seq125Action", NULL, N_("1 2 5"), 2503 NULL, NULL, 1 }, 2504 { "Seq1357Action", NULL, N_("1 1.5 2 3 5 7"), 2505 NULL, NULL, 0 }, 2506 }; 2507 static guint n_auto_res_control_radio_entries = G_N_ELEMENTS (auto_res_control_radio_entries); 2508 2509 static void 2510 auto_resolution_control_menubar(GtkWidget **menubar, GkrellmChart *cp) 2511 { 2512 GtkUIManager *ui_manager; 2513 GtkActionGroup *action_group; 2514 GkrellmChartconfig *cf = cp->config; 2515 GError *error; 2516 2517 action_group = gtk_action_group_new ("ControlActions"); 2518 gtk_action_group_add_actions (action_group, auto_res_control_entries, 2519 n_auto_res_control_entries, cp); 2520 gtk_action_group_add_toggle_actions (action_group, auto_res_control_toggle_entries, 2521 n_auto_res_control_toggle_entries, cp); 2522 gtk_action_group_add_radio_actions (action_group, auto_res_control_radio_entries, 2523 n_auto_res_control_radio_entries, 2524 !!cf->sequence_125, G_CALLBACK(cb_seq_control), 2525 cp); 2526 ui_manager = gtk_ui_manager_new (); 2527 error = NULL; 2528 gtk_ui_manager_add_ui_from_string (ui_manager, auto_res_control_items, 2529 strlen(auto_res_control_items), &error); 2530 if (error) 2531 { 2532 g_message ("building menus failed: %s", error->message); 2533 g_error_free (error); 2534 return; 2535 } 2536 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); 2537 cf->auto_resolution_ui_manager = ui_manager; 2538 set_resolution_menubar_items_sensitivity(cf); 2539 2540 if (menubar) 2541 *menubar = gtk_ui_manager_get_widget(ui_manager, "/menubar"); 2542 } 2543 2544 void 2545 gkrellm_chartconfig_window_create(GkrellmChart *cp) 2546 { 2547 GtkWidget *main_vbox, *vbox, *vbox1, *vbox2, *hbox; 2548 GtkWidget *button; 2549 GList *list; 2550 GkrellmChartconfig *cf; 2551 GkrellmChartdata *cd; 2552 GkrellmPanel *p; 2553 gchar *s; 2554 2555 if (!cp || _GK.no_config) 2556 return; 2557 if (cp->config_window) 2558 { 2559 gtk_window_present(GTK_WINDOW(cp->config_window)); 2560 return; 2561 } 2562 cp->config_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 2563 g_signal_connect(G_OBJECT(cp->config_window), "delete_event", 2564 G_CALLBACK(chart_config_window_delete_event), cp); 2565 2566 p = cp->panel; 2567 cf = cp->config; 2568 if (p && p->label) 2569 s = p->label->string; 2570 else 2571 s = NULL; 2572 gtk_window_set_title(GTK_WINDOW(cp->config_window), 2573 _("GKrellM Chart Config")); 2574 gtk_window_set_wmclass(GTK_WINDOW(cp->config_window), 2575 "Gkrellm_conf", "Gkrellm"); 2576 2577 main_vbox = gtk_vbox_new(FALSE, 0); 2578 gtk_container_set_border_width(GTK_CONTAINER(cp->config_window), 4); 2579 gtk_container_add(GTK_CONTAINER(cp->config_window), main_vbox); 2580 vbox = gkrellm_gtk_framed_vbox(main_vbox, s, 4, FALSE, 4, 3); 2581 2582 hbox = gtk_hbox_new(TRUE, 0); 2583 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 2584 for (list = cp->cd_list; list; list = list->next) 2585 { 2586 cd = (GkrellmChartdata *) list->data; 2587 if ((cd->flags & CHARTDATA_NO_CONFIG) == CHARTDATA_NO_CONFIG) 2588 continue; 2589 vbox1 = gkrellm_gtk_framed_vbox(hbox, cd->label, 2, TRUE, 2, 2); 2590 2591 if (!(cd->flags & CHARTDATA_NO_CONFIG_DRAW_STYLE)) 2592 { 2593 gkrellm_gtk_check_button(vbox1, &button, cd->draw_style, FALSE, 0, 2594 _("Line style")); 2595 g_signal_connect(G_OBJECT(button), "toggled", 2596 G_CALLBACK(cb_line_draw_style), cd); 2597 } 2598 if (!(cd->flags & CHARTDATA_NO_CONFIG_INVERTED)) 2599 { 2600 gkrellm_gtk_check_button(vbox1, &button, cd->inverted, FALSE, 0, 2601 _("Inverted")); 2602 g_signal_connect(G_OBJECT(button), "toggled", 2603 G_CALLBACK(cb_inverted_draw_mode), cd); 2604 } 2605 if (list != cp->cd_list && !(cd->flags & CHARTDATA_NO_CONFIG_SPLIT)) 2606 { 2607 vbox2 = gkrellm_gtk_framed_vbox(vbox1, NULL, 2, FALSE, 2, 2); 2608 gkrellm_gtk_check_button(vbox2, &button, cd->split_chart, FALSE, 0, 2609 _("Split view")); 2610 g_signal_connect(G_OBJECT(button), "toggled", 2611 G_CALLBACK(cb_split_mode), cd); 2612 gkrellm_gtk_spin_button(vbox2, &button, cd->split_fraction, 2613 0.05, 0.95, 0.01, 0.05, 2, 55, 2614 cb_split_fraction, cd, FALSE, ""); 2615 gtk_widget_set_sensitive(button, cd->split_chart); 2616 cd->split_fraction_spin_button = button; 2617 } 2618 if (cd->flags & CHARTDATA_ALLOW_HIDE) 2619 { 2620 gkrellm_gtk_check_button(vbox1, &button, cd->hide, FALSE, 0, 2621 _("Hide")); 2622 g_signal_connect(G_OBJECT(button), "toggled", 2623 G_CALLBACK(cb_hide), cd); 2624 } 2625 } 2626 2627 cf->auto_resolution_control_menubar = NULL; 2628 cf->auto_resolution_ui_manager = NULL; 2629 cf->grid_resolution_spin_button = NULL; 2630 cf->fixed_grids_spin_button = NULL; 2631 2632 if (cf->adjustment_is_set) 2633 { 2634 gfloat value; 2635 2636 vbox1 = gkrellm_gtk_framed_vbox(vbox, _("Resolution per Grid"), 2637 2, FALSE, 2, 2); 2638 if (cf->map_sequence) 2639 value = (gfloat) cf->grid_resolution; 2640 else 2641 value = cf->grid_resolution / cf->spin_factor; 2642 gkrellm_gtk_spin_button(vbox1, &button, value, 2643 cf->low, cf->high, cf->step0, cf->step1, cf->digits, cf->width, 2644 cb_chart_grid_resolution, cp, FALSE, cf->grid_resolution_label); 2645 cf->grid_resolution_spin_button = button; 2646 if (cp->config->auto_grid_resolution) 2647 gtk_widget_set_sensitive(button, FALSE); 2648 2649 if (!(cp->config->flags & NO_CONFIG_AUTO_GRID_RESOLUTION)) 2650 { 2651 hbox = gtk_hbox_new (FALSE, 0); 2652 gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); 2653 gtk_container_add(GTK_CONTAINER(vbox1), hbox); 2654 gkrellm_gtk_check_button(hbox, &button, 2655 cp->config->auto_grid_resolution, TRUE, 0, 2656 _("Auto")); 2657 g_signal_connect(G_OBJECT(button), "toggled", 2658 G_CALLBACK(cb_auto_resolution), cp); 2659 2660 auto_resolution_control_menubar( 2661 &cf->auto_resolution_control_menubar, cp); 2662 gtk_box_pack_start(GTK_BOX(hbox), 2663 cf->auto_resolution_control_menubar, FALSE, TRUE, 10); 2664 } 2665 } 2666 if (!(cp->config->flags & NO_CONFIG_FIXED_GRIDS)) 2667 { 2668 vbox1 = gkrellm_gtk_framed_vbox(vbox, _("Number of Grids"), 2, FALSE, 2669 2, 2); 2670 gkrellm_gtk_spin_button(vbox1, &button, (gfloat) cf->fixed_grids, 2671 0, 5, 1.0, 1.0, 0, 50, 2672 cb_chart_fixed_grids, cp, FALSE, 2673 _("0: Auto 1-5: Constant")); 2674 cf->fixed_grids_spin_button = button; 2675 } 2676 2677 vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 2, FALSE, 2, 2); 2678 gkrellm_gtk_spin_button(vbox1, &button, (gfloat) cp->h, 2679 (gfloat) _GK.chart_height_min, (gfloat) _GK.chart_height_max, 2680 5.0, 10.0, 0, 50, 2681 cb_chart_height, cp, FALSE, 2682 _("Chart height")); 2683 cf->height_spin_button = button; 2684 2685 hbox = gtk_hbutton_box_new(); 2686 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END); 2687 gtk_box_set_spacing(GTK_BOX(hbox), 5); 2688 gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0); 2689 2690 button = gtk_button_new_from_stock(GTK_STOCK_OK); 2691 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); 2692 g_signal_connect(G_OBJECT(button), "clicked", 2693 G_CALLBACK(chart_config_window_close), cp); 2694 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 15); 2695 gtk_widget_grab_default(button); 2696 2697 gtk_widget_show_all(cp->config_window); 2698 } 2699 2700 void 2701 gkrellm_save_chartconfig(FILE *f, GkrellmChartconfig *cf, gchar *mon_keyword, 2702 gchar *name) 2703 { 2704 GList *list; 2705 GkrellmChartdata *cd; 2706 2707 if (!f || !cf || !mon_keyword) 2708 return; 2709 if (name) 2710 fprintf(f, "%s %s %s ", mon_keyword, GKRELLM_CHARTCONFIG_KEYWORD,name); 2711 else 2712 fprintf(f, "%s %s ", mon_keyword, GKRELLM_CHARTCONFIG_KEYWORD); 2713 fprintf(f, "%d %d %d %d %d %d", cf->h, cf->grid_resolution, 2714 cf->fixed_grids, cf->auto_grid_resolution, 2715 cf->auto_resolution_stick, cf->sequence_125); 2716 for (list = cf->cd_list; list; list = list->next) 2717 { 2718 cd = (GkrellmChartdata *) list->data; 2719 fprintf(f, " : %d %d %d %d %.0f", 2720 cd->draw_style, cd->inverted, cd->hide, 2721 cd->split_chart, cd->split_fraction * GKRELLM_FLOAT_FACTOR); 2722 } 2723 fprintf(f, "\n"); 2724 } 2725 2726 void 2727 gkrellm_load_chartconfig(GkrellmChartconfig **config, gchar *string, 2728 gint max_cd) 2729 { 2730 GList *list; 2731 GkrellmChartdata *cd; 2732 GkrellmChartconfig *cf; 2733 gchar *s; 2734 gint index = 0; 2735 2736 if (!config || !string) 2737 return; 2738 if (!*config) 2739 { 2740 *config = gkrellm_chartconfig_new0(); 2741 (*config)->auto_grid_resolution = TRUE; /* the default */ 2742 } 2743 cf = *config; 2744 sscanf(string, "%d %d %d %d %d %d", &cf->h, &cf->grid_resolution, 2745 &cf->fixed_grids, &cf->auto_grid_resolution, 2746 &cf->auto_resolution_stick, &cf->sequence_125); 2747 for (s = strchr(string, (int) ':'); s ; s = strchr(s, (int) ':')) 2748 { 2749 ++s; 2750 list = g_list_nth(cf->cd_list, index++); 2751 if (!list) 2752 { 2753 cd = g_new0(GkrellmChartdata, 1); 2754 cd->split_fraction = 0.5; 2755 cf->cd_list = g_list_append(cf->cd_list, cd); 2756 } 2757 else 2758 cd = (GkrellmChartdata *) list->data; 2759 sscanf(s, "%d %d %d %d %f", 2760 &cd->draw_style, &cd->inverted, &cd->hide, 2761 &cd->split_chart, &cd->split_fraction); 2762 cd->split_fraction /= _GK.float_factor; 2763 if (cd->split_fraction <= 0.01 || cd->split_fraction >= 0.99) 2764 cd->split_fraction = 0.5; 2765 2766 cf->config_loaded = TRUE; 2767 if (max_cd && index >= max_cd) 2768 break; 2769 } 2770 } 2771 2772 void 2773 debug_dump_chart_list() 2774 { 2775 GList *list, *cdlist; 2776 GkrellmChart *cp; 2777 GkrellmPanel *p; 2778 GkrellmChartdata *cd; 2779 2780 g_debug("\n"); 2781 for (list = gkrellm_get_chart_list(); list; list = list->next) 2782 { 2783 cp = (GkrellmChart *) list->data; 2784 p = cp->panel; 2785 if (p && p->label && p->label->string) 2786 g_debug("%s [%d]: ", p->label->string, cp->style_id); 2787 else 2788 g_debug("(null) [%d]: ", cp->style_id); 2789 for (cdlist = cp->cd_list; cdlist; cdlist = cdlist->next) 2790 { 2791 cd = (GkrellmChartdata *) cdlist->data; 2792 g_debug("%s %p->data ", cd->label, cd->data); 2793 } 2794 g_debug("\n"); 2795 } 2796 } 2797