"Fossies" - the Fresh Open Source Software Archive

Member "procmeter3-3.6+svn387/gtk3/widgets/PMBar.c" (7 Jan 2012, 16000 Bytes) of package /linux/misc/procmeter3-3.6+svn387.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "PMBar.c" see the Fossies "Dox" file reference documentation.

    1 /***************************************
    2   ProcMeter Bar Widget Source file (for ProcMeter3 3.6).
    3   ******************/ /******************
    4   Written by Andrew M. Bishop
    5 
    6   This file Copyright 1996-2012 Andrew M. Bishop
    7   It may be distributed under the GNU Public License, version 2, or
    8   any higher version.  See section COPYING of the GNU Public license
    9   for conditions under which this file may be redistributed.
   10   ***************************************/
   11 
   12 
   13 #include <stdlib.h>
   14 #include <string.h>
   15 
   16 #include "PMGeneric.h"
   17 #include "PMBar.h"
   18 
   19 #include "procmeter.h"
   20 
   21 static void procmeterbar_class_init(ProcMeterBarClass *class);
   22 static void procmeterbar_init(ProcMeterBar *pmw);
   23 static void destroy(GtkWidget *widget);
   24 static void realize(GtkWidget *widget);
   25 static void get_preferred_width(GtkWidget *widget,gint *minimal_width,gint *natural_width);
   26 static void get_preferred_height(GtkWidget *widget,gint *minimal_height,gint *natural_height);
   27 static void size_allocate(GtkWidget *widget,GtkAllocation *allocation);
   28 static gboolean draw(GtkWidget *widget,cairo_t *cr);
   29 
   30 static void BarResize(ProcMeterBar *pmw);
   31 static void BarUpdate(ProcMeterBar *pmw,gboolean all);
   32 
   33 static char *empty_string="";
   34 
   35 static ProcMeterGenericClass *parent_class=NULL;
   36 
   37 
   38 /*++++++++++++++++++++++++++++++++++++++
   39   Returns the type of a Widget.
   40 
   41   guint gtk_procmeterbar_get_type Returns a unique pointer to the Widget type.
   42   ++++++++++++++++++++++++++++++++++++++*/
   43 
   44 guint gtk_procmeterbar_get_type(void)
   45 {
   46  static guint pmw_type = 0;
   47 
   48  if(!pmw_type)
   49    {
   50     GTypeInfo pmw_info={sizeof(ProcMeterBarClass),
   51                         NULL,
   52                         NULL,
   53                         (GClassInitFunc) procmeterbar_class_init,
   54                         NULL,
   55                         NULL,
   56                         sizeof(ProcMeterBar),
   57                         0,
   58                         (GInstanceInitFunc) procmeterbar_init,
   59                         NULL};
   60 
   61     pmw_type=g_type_register_static(gtk_procmetergeneric_get_type(),"ProcMeterBar",&pmw_info,0);
   62    }
   63 
   64  return(pmw_type);
   65 }
   66 
   67 
   68 /*++++++++++++++++++++++++++++++++++++++
   69   Initialise the Widget class
   70 
   71   ProcMeterBarClass *class The class of widget to initialise.
   72   ++++++++++++++++++++++++++++++++++++++*/
   73 
   74 static void procmeterbar_class_init(ProcMeterBarClass *class)
   75 {
   76  GtkWidgetClass *widget_class;
   77 
   78  g_return_if_fail(class!=NULL);
   79 
   80  widget_class=(GtkWidgetClass*)class;
   81 
   82  class->resize=BarResize;
   83  class->update=BarUpdate;
   84 
   85  parent_class=g_type_class_ref(gtk_procmetergeneric_get_type());
   86 
   87  widget_class->destroy=destroy;
   88  widget_class->realize=realize;
   89  widget_class->draw=draw;
   90  widget_class->get_preferred_width=get_preferred_width;
   91  widget_class->get_preferred_height=get_preferred_height;
   92  widget_class->size_allocate=size_allocate;
   93 }
   94 
   95 
   96 /*++++++++++++++++++++++++++++++++++++++
   97   Initialise an instance of the Widget
   98 
   99   ProcMeterBar *pmw The Widget to initialise.
  100   ++++++++++++++++++++++++++++++++++++++*/
  101 
  102 static void procmeterbar_init(ProcMeterBar *pmw)
  103 {
  104  int i;
  105 
  106  g_return_if_fail(pmw!=NULL);
  107 
  108  /* The grid parts. */
  109 
  110  pmw->grid_units=empty_string;
  111 
  112  gtk_style_context_get_color(gtk_widget_get_style_context(&pmw->generic.widget),GTK_STATE_FLAG_NORMAL,&pmw->grid_color);
  113 
  114  pmw->grid_drawn=1;
  115  pmw->grid_min=1;
  116 
  117  pmw->grid_max=0;
  118 
  119  pmw->grid_num=pmw->grid_min;
  120 
  121  /* The data parts. */
  122 
  123  for(i=0;i<sizeof(pmw->data)/sizeof(pmw->data[0]);i++)
  124     pmw->data[i]=0;
  125 
  126  pmw->data_index=0;
  127 
  128  pmw->data_sum=0;
  129 
  130  /* The rest of the sizing. */
  131 
  132  BarResize(pmw);
  133 }
  134 
  135 
  136 /*++++++++++++++++++++++++++++++++++++++
  137   Create a new Widget.
  138 
  139   GtkWidget* gtk_procmeterbar_new Returns the new widgets.
  140   ++++++++++++++++++++++++++++++++++++++*/
  141 
  142 GtkWidget* gtk_procmeterbar_new(void)
  143 {
  144  ProcMeterBar *pmw;
  145 
  146  pmw=g_object_new(gtk_procmeterbar_get_type(),NULL);
  147 
  148  return(GTK_WIDGET(pmw));
  149 }
  150 
  151 
  152 /*++++++++++++++++++++++++++++++++++++++
  153   Destroy a Widget
  154 
  155   GtkWidget *widget The widget to destroy.
  156   ++++++++++++++++++++++++++++++++++++++*/
  157 
  158 static void destroy(GtkWidget *widget)
  159 {
  160  ProcMeterBar *pmw;
  161 
  162  g_return_if_fail(widget!=NULL);
  163  g_return_if_fail(GTK_IS_PROCMETERBAR(widget));
  164 
  165  pmw=GTK_PROCMETERBAR(widget);
  166 
  167  if(pmw->grid_units!=empty_string)
  168    {
  169     free(pmw->grid_units);
  170     pmw->grid_units=empty_string;
  171    }
  172 
  173  if(GTK_WIDGET_CLASS(parent_class)->destroy)
  174     (*GTK_WIDGET_CLASS(parent_class)->destroy)(widget);
  175 }
  176 
  177 
  178 /*++++++++++++++++++++++++++++++++++++++
  179   Realize a widget.
  180 
  181   GtkWidget *widget The widget to realize.
  182   ++++++++++++++++++++++++++++++++++++++*/
  183 
  184 static void realize(GtkWidget *widget)
  185 {
  186  ProcMeterBar *pmw;
  187  GdkWindowAttr attributes;
  188  GtkAllocation allocation;
  189  gint attributes_mask;
  190 
  191  g_return_if_fail(widget!=NULL);
  192  g_return_if_fail(GTK_IS_PROCMETERBAR(widget));
  193 
  194  gtk_widget_set_realized(widget,TRUE);
  195  pmw=GTK_PROCMETERBAR(widget);
  196 
  197  gtk_widget_get_allocation(widget,&allocation);
  198 
  199  attributes.x=allocation.x;
  200  attributes.y=allocation.y;
  201  attributes.width=allocation.width;
  202  attributes.height=allocation.height;
  203  attributes.wclass=GDK_INPUT_OUTPUT;
  204  attributes.window_type=GDK_WINDOW_CHILD;
  205  attributes.event_mask=gtk_widget_get_events(widget)|GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK;
  206  attributes.visual=gtk_widget_get_visual(widget);
  207 
  208  attributes_mask=GDK_WA_X|GDK_WA_Y|GDK_WA_VISUAL;
  209  gtk_widget_set_window(widget,gdk_window_new(gtk_widget_get_parent_window(widget),&attributes,attributes_mask));
  210 
  211  gdk_window_set_user_data(gtk_widget_get_window(widget),widget);
  212 
  213  BarUpdate(pmw,TRUE);
  214 }
  215 
  216 
  217 /*++++++++++++++++++++++++++++++++++++++
  218   Return the preferred width of the widget
  219 
  220   GtkWidget *widget The widget whose width is requested.
  221 
  222   gint *minimal_width Returns the minimal width.
  223 
  224   gint *natural_width Returns the preferred width.
  225   ++++++++++++++++++++++++++++++++++++++*/
  226 
  227 static void get_preferred_width(GtkWidget *widget,gint *minimal_width,gint *natural_width)
  228 {
  229  g_return_if_fail(widget!=NULL);
  230  g_return_if_fail(GTK_IS_PROCMETERBAR(widget));
  231  g_return_if_fail(minimal_width!=NULL);
  232  g_return_if_fail(natural_width!=NULL);
  233 
  234  *minimal_width=*natural_width=50; /* arbitrary */
  235 }
  236 
  237 
  238 /*++++++++++++++++++++++++++++++++++++++
  239   Return the preferred height of the widget
  240 
  241   GtkWidget *widget The widget whose height is requested.
  242 
  243   gint *minimal_height Returns the minimal height.
  244 
  245   gint *natural_height Returns the preferred height.
  246   ++++++++++++++++++++++++++++++++++++++*/
  247 
  248 static void get_preferred_height(GtkWidget *widget,gint *minimal_height,gint *natural_height)
  249 {
  250  ProcMeterBar *pmw;
  251 
  252  g_return_if_fail(widget!=NULL);
  253  g_return_if_fail(GTK_IS_PROCMETERBAR(widget));
  254  g_return_if_fail(minimal_height!=NULL);
  255  g_return_if_fail(natural_height!=NULL);
  256 
  257  pmw=GTK_PROCMETERBAR(widget);
  258 
  259  *minimal_height=*natural_height=20+pmw->generic.label_height;
  260 }
  261 
  262 
  263 /*++++++++++++++++++++++++++++++++++++++
  264   Change to the size that has been specified by the container.
  265 
  266   GtkWidget *widget The widget that has been resized.
  267 
  268   GtkAllocation *allocation The size information.
  269   ++++++++++++++++++++++++++++++++++++++*/
  270 
  271 static void size_allocate(GtkWidget *widget,GtkAllocation *allocation)
  272 {
  273  g_return_if_fail(widget!=NULL);
  274  g_return_if_fail(GTK_IS_PROCMETERBAR(widget));
  275  g_return_if_fail(allocation!=NULL);
  276 
  277  gtk_widget_set_allocation(widget,allocation);
  278  if(gtk_widget_get_realized(widget))
  279    {
  280     ProcMeterBar *pmw=GTK_PROCMETERBAR(widget);
  281 
  282     gdk_window_move_resize(gtk_widget_get_window(widget),
  283                            allocation->x,allocation->y,
  284                            allocation->width,allocation->height);
  285 
  286     BarResize(pmw);
  287    }
  288 }
  289 
  290 
  291 /*++++++++++++++++++++++++++++++++++++++
  292   Redisplay the ProcMeter Bar Widget.
  293 
  294   gboolean draw Returns false
  295 
  296   GtkWidget *widget The Widget to redisplay.
  297 
  298   cairo_t *cr A cairo object describing the position to draw.
  299   ++++++++++++++++++++++++++++++++++++++*/
  300 
  301 static gboolean draw(GtkWidget *widget,cairo_t *cr)
  302 {
  303  ProcMeterBar *pmw;
  304 
  305  g_return_val_if_fail(widget!=NULL,FALSE);
  306  g_return_val_if_fail(GTK_IS_PROCMETERBAR(widget),FALSE);
  307 
  308  pmw=GTK_PROCMETERBAR(widget);
  309 
  310  BarUpdate(pmw,TRUE);
  311 
  312  return(FALSE);
  313 }
  314 
  315 
  316 /*++++++++++++++++++++++++++++++++++++++
  317   Perform all of the sizing on the Widget when it is created/resized.
  318 
  319   ProcMeterBar *pmw The Widget to resize.
  320   ++++++++++++++++++++++++++++++++++++++*/
  321 
  322 static void BarResize(ProcMeterBar *pmw)
  323 {
  324  int allocation_width;
  325  cairo_t *cr;
  326  PangoLayout *layout;
  327  int width,height;
  328 
  329  g_return_if_fail(pmw!=NULL);
  330 
  331  if(parent_class->resize)
  332     parent_class->resize(&pmw->generic);
  333 
  334  pmw->generic.label_x=2;
  335 
  336  /* The grid parts. */
  337 
  338  allocation_width=gtk_widget_get_allocated_width(&pmw->generic.widget);
  339 
  340  cr=gdk_cairo_create(gtk_widget_get_root_window(&pmw->generic.widget));
  341 
  342  layout=pango_cairo_create_layout(cr);
  343  if(pmw->generic.label_font)
  344     pango_layout_set_font_description(layout,pmw->generic.label_font);
  345  else
  346     pango_layout_set_font_description(layout,gtk_style_context_get_font(gtk_widget_get_style_context(&pmw->generic.widget),GTK_STATE_FLAG_NORMAL));
  347 
  348  pango_layout_set_text(layout,pmw->grid_units,-1);
  349  pango_layout_get_pixel_size(layout,&width,&height);
  350 
  351  cairo_destroy(cr);
  352 
  353  pmw->grid_units_x=allocation_width-width-2;
  354 
  355  pmw->grid_maxvis=allocation_width/3;
  356 
  357  if(pmw->generic.label_pos==ProcMeterLabelTop)
  358     pmw->generic.body_start=pmw->generic.label_height;
  359  else
  360     pmw->generic.body_start=0;
  361 
  362  if(pmw->grid_num>pmw->grid_maxvis && pmw->grid_drawn)
  363     pmw->grid_drawn=-1;
  364  if(pmw->grid_num<=pmw->grid_maxvis && pmw->grid_drawn)
  365     pmw->grid_drawn=1;
  366 }
  367 
  368 
  369 /*++++++++++++++++++++++++++++++++++++++
  370   Update the display.
  371 
  372   ProcMeterBar *pmw The Widget to update.
  373 
  374   gboolean all Indicates if it all is to be updated including the generic parts.
  375   ++++++++++++++++++++++++++++++++++++++*/
  376 
  377 static void BarUpdate(ProcMeterBar *pmw,gboolean all)
  378 {
  379  g_return_if_fail(pmw!=NULL);
  380 
  381  if(gtk_widget_get_visible(&pmw->generic.widget))
  382    {
  383     int allocation_width;
  384     cairo_t *cr;
  385     int i;
  386     int scale=PROCMETER_GRAPH_SCALE*pmw->grid_num;
  387     gshort pos;
  388     gshort top_average_bottom,bottom_average_top,average_size;
  389 
  390     cr=gdk_cairo_create(gtk_widget_get_window(&pmw->generic.widget));
  391     cairo_set_line_width(cr,1.0);
  392 
  393     allocation_width=gtk_widget_get_allocated_width(&pmw->generic.widget);
  394 
  395     if(all)
  396       {
  397        if(parent_class->update)
  398           parent_class->update(&pmw->generic);
  399 
  400        if(pmw->generic.label_pos!=ProcMeterLabelNone)
  401          {
  402           PangoLayout *layout;
  403 
  404           cairo_set_source_rgb(cr,pmw->generic.label_color.red,pmw->generic.label_color.green,pmw->generic.label_color.blue);
  405 
  406           layout=pango_cairo_create_layout(cr);
  407           if(pmw->generic.label_font)
  408              pango_layout_set_font_description(layout,pmw->generic.label_font);
  409           else
  410              pango_layout_set_font_description(layout,gtk_style_context_get_font(gtk_widget_get_style_context(&pmw->generic.widget),GTK_STATE_FLAG_NORMAL));
  411 
  412           cairo_move_to(cr,pmw->grid_units_x,pmw->generic.label_y);
  413           pango_layout_set_text(layout,pmw->grid_units,-1);
  414           pango_cairo_show_layout(cr,layout);
  415          }
  416       }
  417     else
  418       {
  419        cairo_set_source_rgb(cr,pmw->generic.body_bg_color.red,pmw->generic.body_bg_color.green,pmw->generic.body_bg_color.blue);
  420 
  421        cairo_rectangle(cr,0,pmw->generic.body_start,allocation_width,pmw->generic.body_height);
  422        cairo_fill(cr);
  423       }
  424 
  425     pos=pmw->data_sum*allocation_width/(scale*2);
  426 
  427     top_average_bottom=pmw->generic.body_start+2*(pmw->generic.body_height>>3);
  428     bottom_average_top=pmw->generic.body_start+pmw->generic.body_height-2*(pmw->generic.body_height>>3);
  429     average_size=pmw->generic.body_height>>3;
  430 
  431     cairo_set_source_rgb(cr,pmw->generic.body_fg_color.red,pmw->generic.body_fg_color.green,pmw->generic.body_fg_color.blue);
  432 
  433     cairo_rectangle(cr,pos-average_size,top_average_bottom-average_size,average_size,average_size);
  434     cairo_fill(cr);
  435 
  436     cairo_rectangle(cr,pos-average_size,bottom_average_top             ,average_size,average_size);
  437     cairo_fill(cr);
  438 
  439     pos=pmw->data[pmw->data_index]*allocation_width/scale;
  440 
  441     cairo_rectangle(cr,0,top_average_bottom+1,pos,bottom_average_top-top_average_bottom-2);
  442     cairo_fill(cr);
  443 
  444     cairo_set_source_rgb(cr,pmw->grid_color.red,pmw->grid_color.green,pmw->grid_color.blue);
  445 
  446     if(pmw->grid_drawn==1)
  447        for(i=1;i<pmw->grid_num;i++)
  448          {
  449           pos=i*allocation_width/pmw->grid_num;
  450           cairo_move_to(cr,pos+0.5,pmw->generic.body_start);
  451           cairo_line_to(cr,pos+0.5,pmw->generic.body_height+pmw->generic.body_start);
  452           cairo_stroke(cr);
  453          }
  454     else
  455        if(pmw->grid_drawn==-1)
  456          {
  457           pos=pmw->grid_maxvis*allocation_width/pmw->grid_num;
  458           cairo_move_to(cr,pos+0.5,pmw->generic.body_start);
  459           cairo_line_to(cr,pos+0.5,pmw->generic.body_height+pmw->generic.body_start);
  460           cairo_stroke(cr);
  461          }
  462 
  463     cairo_destroy(cr);
  464    }
  465 }
  466 
  467 
  468 /*++++++++++++++++++++++++++++++++++++++
  469   Set the grid colour of the Widget.
  470 
  471   ProcMeterBar *pmw The widget to set.
  472 
  473   GdkRGBA *grid_color The grid.
  474   ++++++++++++++++++++++++++++++++++++++*/
  475 
  476 void ProcMeterBarSetGridColour(ProcMeterBar *pmw,GdkRGBA *grid_color)
  477 {
  478  pmw->grid_color=*grid_color;
  479 
  480  BarUpdate(pmw,TRUE);
  481 }
  482 
  483 
  484 /*++++++++++++++++++++++++++++++++++++++
  485   Set the minimum number of grid lines in the Widget.
  486 
  487   ProcMeterBar *pmw The Widget to set.
  488 
  489   gint grid_min The minimum number of lines.
  490   ++++++++++++++++++++++++++++++++++++++*/
  491 
  492 void ProcMeterBarSetGridMin(ProcMeterBar *pmw,gint grid_min)
  493 {
  494  if(grid_min<0)
  495    {
  496     pmw->grid_min=-grid_min;
  497     pmw->grid_drawn=0;
  498    }
  499  else if(grid_min>0)
  500    {
  501     pmw->grid_min=grid_min;
  502     pmw->grid_drawn=1;
  503    }
  504  else /* if(grid_min==0) */
  505    {
  506     pmw->grid_min=1;
  507     pmw->grid_drawn=1;
  508    }
  509 
  510  if(grid_min>pmw->grid_max && pmw->grid_max)
  511     pmw->grid_min=pmw->grid_max;
  512 
  513  if(pmw->grid_min>=pmw->grid_num)
  514     pmw->grid_num=pmw->grid_min;
  515 
  516  BarResize(pmw);
  517 
  518  BarUpdate(pmw,TRUE);
  519 }
  520 
  521 
  522 /*++++++++++++++++++++++++++++++++++++++
  523   Set the maximum number of grid lines in the Widget.
  524 
  525   ProcMeterBar *pmw The Widget to set.
  526 
  527   gint grid_max The maximum number of lines.
  528   ++++++++++++++++++++++++++++++++++++++*/
  529 
  530 void ProcMeterBarSetGridMax(ProcMeterBar *pmw,gint grid_max)
  531 {
  532  if(grid_max<0)
  533     pmw->grid_max=0;
  534  else
  535     pmw->grid_max=grid_max;
  536 
  537  if(grid_max && grid_max<pmw->grid_min)
  538     pmw->grid_max=pmw->grid_min;
  539 
  540  BarResize(pmw);
  541 
  542  BarUpdate(pmw,TRUE);
  543 }
  544 
  545 
  546 /*++++++++++++++++++++++++++++++++++++++
  547   Set the grid units for the widget
  548 
  549   ProcMeterBar *pmw The widget to set.
  550 
  551   gchar *units The grid units.
  552   ++++++++++++++++++++++++++++++++++++++*/
  553 
  554 void ProcMeterBarSetGridUnits(ProcMeterBar *pmw,gchar *units)
  555 {
  556  if(pmw->grid_units!=empty_string)
  557     free(pmw->grid_units);
  558  pmw->grid_units=(char*)malloc(strlen(units)+1);
  559  strcpy(pmw->grid_units,units);
  560 
  561  BarResize(pmw);
  562 
  563  BarUpdate(pmw,TRUE);
  564 }
  565 
  566 
  567 /*++++++++++++++++++++++++++++++++++++++
  568   Add a data point to the ProcMeter Bar Widget.
  569 
  570   ProcMeterBar *pmw The ProcMeter Bar Widget.
  571 
  572   gushort datum The data point to add.
  573   ++++++++++++++++++++++++++++++++++++++*/
  574 
  575 void ProcMeterBarAddDatum(ProcMeterBar *pmw,gushort datum)
  576 {
  577  int new_grid_num;
  578  gushort old_datum;
  579 
  580  pmw->data_index++;
  581  if(pmw->data_index==8)
  582     pmw->data_index=0;
  583 
  584  old_datum=pmw->data[pmw->data_index];
  585  pmw->data[pmw->data_index]=datum;
  586 
  587  pmw->data_sum=(pmw->data_sum>>1)+datum-(old_datum>>8);
  588 
  589  if((pmw->data_sum/2)>datum)
  590     new_grid_num=((pmw->data_sum/2)+(PROCMETER_GRAPH_SCALE-1))/PROCMETER_GRAPH_SCALE;
  591  else
  592     new_grid_num=(datum+(PROCMETER_GRAPH_SCALE-1))/PROCMETER_GRAPH_SCALE;
  593 
  594  if(new_grid_num<pmw->grid_min)
  595     new_grid_num=pmw->grid_min;
  596  if(pmw->grid_max && new_grid_num>pmw->grid_max)
  597     new_grid_num=pmw->grid_max;
  598 
  599  if(new_grid_num!=pmw->grid_num)
  600    {
  601     pmw->grid_num=new_grid_num;
  602 
  603     if(pmw->grid_num>pmw->grid_maxvis && pmw->grid_drawn)
  604        pmw->grid_drawn=-1;
  605     if(pmw->grid_num<=pmw->grid_maxvis && pmw->grid_drawn)
  606        pmw->grid_drawn=1;
  607    }
  608 
  609  BarUpdate(pmw,FALSE);
  610 }