Re: How to create scales for range widgets?



Vlad Harchev wrote:

>  Could you post your stripped-down source (probably with main function) to
> help us helping you?

It's a bit hard to strip down but I'll try.  The following compiles with:

gcc -g slider_stuff.c `gtk-config --cflags` `gtk-config --libs`

Just start moving the sliders and you'll see what I mean about scales,
values, and special type scales.

---- slider_stuff.c -----

#include <stdio.h>
#include <unistd.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <math.h>

typedef enum {
  NO = 0,
  YES
} Bool;

typedef enum {
   NORMAL=0,
   OPC,
   MAX_ADJ_FLAG
} AdjFlag;

typedef struct {
  double init;
  Bool inited;
  Bool ainit;
  double min;
  double max;
  double value;
  double last_val;
  AdjFlag sflags[MAX_ADJ_FLAG];
  char name[32];   /* The rest used only by sliders */
  int sig_digits;
  double s_incr;
  double p_incr;
  double p_size;
} SLINC_param;

GtkAdjustment *slide_adj[4];
GtkAdjustment *text_adj[4];
SLINC_param slide_params[4];

double octpch(double pch)
{
 int oct = pch;
 return(oct + 8.333333 * (pch - oct));
}

double pchoct(double oct)
{
 double x, result;
 x = (int)oct;
 result = (.12 * (oct - x) + x);
 return result;
}

void cb_set_text (GtkAdjustment *adj, int adj_num)
{
  int i;
  char tstring[10];
  char format[5];
  double val;
  AdjFlag flag;

#ifdef DBUG
  printf("cb_set_text()\n");
#endif
  val = adj->value;

  /* FIXME:  a little hack to retrofit new flag system */
  for (i=0;i<MAX_ADJ_FLAG;i++) {
 flag = slide_params[adj_num].sflags[i];
 if (flag == OPC)
   continue;
  }

  if (flag == OPC) {  /* Need to do special stuff for OPC */

    val = pchoct(val);
    if (val < 10) {
      strcpy(format,"%1.2f");
    }
    else {
      strcpy(format,"%2.2f");
    }
    sprintf(tstring,format,val);
  }
  else {
    if (val > 999) {
      sprintf(tstring,"%4.0f",val);
    }
    else if (val > 99) {
      sprintf(tstring,"%3.0f",val);
    }
    else if (val > 9) {
      sprintf(tstring,"%2.1f",val);
    }
    else if (val >= 0) {
      sprintf(tstring,"%1.2f",val);
    }
    else {
      sprintf(tstring,"%0.3f",val);
    }
  }

  /* Then do the rest */

  gtk_entry_set_text(GTK_ENTRY(text_adj[adj_num]), tstring);

}

double make_incr(double min, double max)
{
  double diff, tdiff, d_incr;
  int i_incr;
  if ((min >= 0) && (max > 0)) {   /* If we're > 0 */
    diff = (max-min);
    if (diff < 20){ /* diff < 20 */
      if (diff > 10) {
  return 1.0;
      }
      else if (diff > 1) {
  return 0.5;
      }
      else if (diff > 0.1) {
  return 0.05;
      }
      else if (diff > 0.01) {
  return 0.005;
      }
 }
 else { /* diff > 20 */
   d_incr = diff/20;
   i_incr = (int)d_incr;
   tdiff = d_incr - (double)i_incr;
   return (d_incr-tdiff);
 }
  }
  else { /* We're < 0 */
 d_incr = diff/20;
 if ((d_incr < 1) && (d_incr > 0.1)) {
   return 0.1;
 }
 else if ((d_incr < 0.1) && (d_incr > 0.01)) {
   return 0.01;
 }
 else if ((d_incr < 0.01) && (d_incr > 0.001)) {
   return 0.001;
 }
  }
  return 0.0;  /* This can never happen ... here to get rid of gcc warning */

}


void scale_set_default_values (GtkScale *scale)
{
  gtk_range_set_update_policy (GTK_RANGE (scale),
          GTK_UPDATE_CONTINUOUS);
  gtk_scale_set_digits (scale, 1);
  gtk_scale_set_value_pos (scale, GTK_POS_LEFT);
  gtk_scale_set_draw_value (scale, FALSE);
}
/* make_slider
-------------------------------------------------------------*/

void make_slider (int adj_no, GtkWidget *box)
{
  GtkWidget *hbox, *vbox, *tvbox, *s_table;
  GtkWidget *label, *tlabel;
  GtkWidget *vscale;
  GtkWidget *vframe, *lframe;
  char tstring[2];
  gfloat i;
  gint j;
  gfloat sincr;
  float steps;
  int t_ival,isteps,maxcell,maxpad,pad;

  int digs;
  double init, min, max, s_incr, p_incr;
  AdjFlag *flags;

  digs = slide_params[adj_no].sig_digits;
  init = slide_params[adj_no].init;
  min = slide_params[adj_no].min;
  max = slide_params[adj_no].max;
  s_incr = slide_params[adj_no].s_incr;
  p_incr = slide_params[adj_no].p_incr;

  flags = slide_params[adj_no].sflags;

/*   if (check_adj_flag(flags,OPC)) { */
/*  min = (gfloat)octpch(min); */
/*  max = (gfloat)octpch(max); */
/*   } */

  /* Don't think we want to do this */
/*   if (check_adj_flag(flags,OPC)) { */
/*  s_incr = (gfloat)opc2real(s_incr); */
/*  p_incr = (gfloat)opc2real(p_incr); */
/*   } */

  /* Create an adjustment corresponding to the slider */
  /*
printf("\ngtk_adjustment_new(%2.2f,%2.2f,%2.2f,%2.2f,%2.2f,%2.2f)\n",init,min,max+p_incr,s_incr,p_incr,p_incr);
*/

  slide_adj[adj_no] = gtk_adjustment_new (init, min, max+p_incr, s_incr,
p_incr, p_incr);
  if (!GTK_IS_ADJUSTMENT(slide_adj[adj_no])) {
    perror("slider param error");
    fflush(stdout);
    exit(1);
  }

  vframe = gtk_frame_new(NULL);
  lframe = gtk_frame_new(NULL);

  /* Create a label */
  label = gtk_label_new(slide_params[adj_no].name);
  /* Vertical box for label, scale+slider, value display */
  vbox = gtk_vbox_new(FALSE,0);

  /* Horizontal box for the slider and scale */
  hbox = gtk_hbox_new(FALSE,0);
  /* Vertical box for the scale #'s */
  tvbox = gtk_vbox_new(TRUE,0);


  /* Create the slider */
  vscale = gtk_vscale_new (GTK_ADJUSTMENT (slide_adj[adj_no]));
  scale_set_default_values (GTK_SCALE (vscale));
  gtk_scale_set_digits (GTK_SCALE (vscale), digs);  /* Accuracy */

  /* Put the label in the vbox ... inside a frame */
  gtk_container_add(GTK_CONTAINER(lframe) , label);
  gtk_widget_show(lframe);
  gtk_box_pack_start (GTK_BOX (vbox), lframe, FALSE, FALSE, 0);

  sincr = 0.0;
  /*  printf("slide_params[%d].flag =
%d\n",adj_no,slide_params[adj_no].flag); */
  if (slide_params[adj_no].sflags[0] ==  NORMAL) {
    /* Create a scale, and put digits into vertical box */
    sincr = make_incr(min,max); /* Create a reasonable increment amount */
    steps = (max-min)/sincr;
 steps = rint(steps);
 isteps = (int)steps;
    max += (sincr/2);
 i=min;
 j=0;
 s_table = gtk_table_new( isteps, 1, FALSE);
    while(i<=max) {
      if (max >= 1000) {
  sprintf(tstring,"%4.0f",i);
      }
      else if (max >= 100) {
  sprintf(tstring,"%3.0f",i);
      }
      else if (max >= 10) {
  sprintf(tstring,"%2.1f",i);
      }
      else if (max >= 0) {
  sprintf(tstring,"%1.2f",i);
      }
      else {
  sprintf(tstring,"%0.3f",i);
      }
      tlabel = gtk_label_new(tstring);
      gtk_widget_show (tlabel);
      gtk_table_attach_defaults (GTK_TABLE (s_table), tlabel, 0, 1, j,j+1);
   j++;
   i += sincr;
    }
 maxcell=j-1;
 if (isteps < 10) {  /* Attempt at scaling */
   pad=1;
   maxpad = (int)rint(steps/2);
   for(j=0;j<maxcell;j++) {
  if (j<3)
    pad += 3;
  if (j>(steps-3))
    pad -= 1;
  gtk_table_set_row_spacing( s_table, j, pad);
   }
 }
  }
  else if (slide_params[adj_no].sflags[0] == OPC) {
 if (max > 4) {
   sincr = 0.06; /* Create a reasonable increment amount */
 }
 else if (max > 1.0) {
   sincr = 0.01;
 }
 else if (max > 0.05) {
   sincr = 0.005;
 }
    steps = (max-min)/sincr;

    steps = (max-min)/sincr;
 steps = rint(steps);
 isteps = (int)steps;
    max += (sincr/2);
 i=min;
 s_table = gtk_table_new( isteps, 1, FALSE);
 j=0;
 i=min;
    while(i<=max) {
      if ((i < 1) && (max < 0.07)) {
  sprintf(tstring,"%1.3f",i);
      }
      else if (i < 10) {
  sprintf(tstring,"%1.2f",i);
      }
   else {
  sprintf(tstring,"%2.2f",i);
   }
      tlabel = gtk_label_new(tstring);
      gtk_widget_show (tlabel);
   gtk_table_attach_defaults (GTK_TABLE (s_table), tlabel, 0, 1, j,j+1);
   i += sincr;
   j++;
   t_ival = (int)i;
   if (i>=((gfloat)t_ival+0.11))
  i = (gfloat)t_ival+1.00;

 }
 maxcell=j-1;
 if (isteps < 0) {  /* Attempt at scaling */
   pad=1;
   maxpad = (int)rint(steps/2);
   for(j=0;j<maxcell;j++) {
  gtk_table_set_row_spacing( s_table, j, pad);
  if (j<3)
    pad += 1;
  if (j>(steps-3))
    pad -= 1;
   }
 }
  }

  /* Put slider and scale into hbox */
  gtk_box_pack_start (GTK_BOX (tvbox), s_table, TRUE, TRUE, 10);
  gtk_box_pack_start (GTK_BOX (hbox), tvbox, TRUE, TRUE, 2);
  gtk_box_pack_start (GTK_BOX (hbox), vscale, TRUE, TRUE, 0);

  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);

  /* Text box for data display */
  text_adj[adj_no] = gtk_entry_new_with_max_length(6);
  gtk_widget_set_events(GTK_WIDGET(text_adj[adj_no]),
      GDK_EXPOSURE_MASK|
                        GDK_KEY_PRESS_MASK|
                        GDK_KEY_RELEASE_MASK);

  gtk_widget_set_usize (GTK_WIDGET(text_adj[adj_no]), (gint) 20, (gint) 20);
  gtk_entry_set_editable(GTK_ENTRY(text_adj[adj_no]), TRUE);

  gtk_signal_connect (GTK_OBJECT(slide_adj[adj_no]), "value_changed",
        GTK_SIGNAL_FUNC(cb_set_text), (gint *)adj_no);

  /* Put it in the vbox */
  gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET(text_adj[adj_no]), FALSE,
FALSE, 0);

  /* A frame around the vbox so it looks nice :-) */
  gtk_container_add(GTK_CONTAINER(vframe) , vbox);
  gtk_widget_show(vframe);
  gtk_box_pack_start (GTK_BOX (box), vframe, TRUE, TRUE, 0);

  gtk_widget_show (label);
  gtk_widget_show (tvbox);
  gtk_widget_show (s_table);
  gtk_widget_show (vscale);
  gtk_widget_show (hbox);
  gtk_widget_show (GTK_WIDGET(text_adj[adj_no]));
  gtk_widget_show (vbox);
}

/* create_sliders
------------------------------------------------------------*/

int main (int argc, char *argv[])
{
  int i,adj_no;
  GtkWidget *window;
  GtkWidget *main_box;

  gtk_init(&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  main_box = gtk_hbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), main_box);
  gtk_widget_show (main_box);

  adj_no = 0;
  slide_params[adj_no].sig_digits = 2;
  slide_params[adj_no].init = 10;
  slide_params[adj_no].min = 0;
  slide_params[adj_no].max = 30;
  slide_params[adj_no].s_incr = 0.01;
  slide_params[adj_no].p_incr = 0.01;
  slide_params[adj_no].sflags[0] = NORMAL;

  make_slider(adj_no,main_box);

  adj_no = 1;

  slide_params[adj_no].sig_digits = 2;
  slide_params[adj_no].init = 2;
  slide_params[adj_no].min = 1;
  slide_params[adj_no].max = 8;
  slide_params[adj_no].s_incr = 0.01;
  slide_params[adj_no].p_incr = 0.01;
  slide_params[adj_no].sflags[1] = OPC;

  make_slider(adj_no,main_box);

  gtk_widget_show (window);

  gtk_main();
}

----- snip -----

DT
--
Technical Director - Virginia Center for Computer Music
http://www.people.virginia.edu/~djt7p






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]