Bjarne Stroustrup

4thedition

I think it was in late ’70s when I started to use C. The C Programming Language was first published in 1978, and the book, often referred to as K&R, was my greatest favorite.

The_C_Programming_Language,_First_Edition_Cover_(2)

And after some 35 years, I just downloaded this another famous book (Fourth Edition released in 2013), and started reading it on my Kindle.

Drawing Area Widget

gtk3e

The further I do, I get more and more confused..

int main(int argc, char *argv[])
{
  serial_init ();

  Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

  Gtk::Window  win;
  Gtk::Box     bigbox;
  RadioButtons buttons;
  MyArea       area;

  win.set_title("Spinor Lab");
  win.set_default_size(1000,400);
  win.set_border_width(10);

  bigbox.set_orientation(Gtk::ORIENTATION_VERTICAL);
  bigbox.pack_start(buttons, FALSE, FALSE, 0);
  bigbox.pack_start(area   , FALSE, FALSE, 0);

  buttons.show();
  area.show();
  bigbox.show();

  win.add(bigbox);
  return app->run(win);
}
#ifndef GTKMM_EXAMPLE_RADIOBUTTONS_H
#define GTKMM_EXAMPLE_RADIOBUTTONS_H

#include <gtkmm/box.h>
#include <gtkmm/window.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/separator.h>

// class RadioButtons : public Gtk::Window
class RadioButtons : public Gtk::Box
{
public:
  RadioButtons();
  virtual ~RadioButtons();
protected:
  void on_button_clicked ();
  void on_button_clicked9(gint data);
  Gtk::Box         m_Box_Top, m_Box1, m_Box2;
  Gtk::Box         m_Box10       [  8];
  Gtk::RadioButton::Group m_group[  8];
  Gtk::RadioButton m_RadioButton [100];
  Gtk::HSeparator  m_HSeparator;
  Gtk::VSeparator  m_VSeparator  [  7];
  Gtk::Button      m_Button_Quit;
};

#endif //GTKMM_EXAMPLE_RADIOBUTTONS_H

No Data Structures (3)

gtk3c

Maybe this only reveals that I am not object-oriented at all. These codes are quite ugly, I must say.

#include "radiobuttons.h"
#include <iostream>
void myfunc (int);

RadioButtons::RadioButtons() :
  m_Box_Top(Gtk::ORIENTATION_VERTICAL),
  m_Box1   (Gtk::ORIENTATION_HORIZONTAL, 10),
  m_Box2   (Gtk::ORIENTATION_VERTICAL  , 10),
  m_Button_Quit ("Quit")
{
  set_title("Spinor Lab");
  set_border_width(10);

  char label[100][256] = { "CW", "CW-R", "LSB", "USB", "DSP FIL1", "DSP FIL2", "DSP FIL3", "DSP SHARP", "DSP SOFT",
    "IF FIL1", "IF FIL2", "IF FIL3", "PRE-AMP1", "PRE-AMP2", "ATT 20dB", "BOTH OFF", "AGC FAST", "AGC MID", "AGC SLOW",
    "ANT 1", "ANT 2", "BKIN OFF", "BKIN ON", "BKIN FULL"};
  int ngroup = 8;
  int nbuttons[8] = { 4, 3, 2, 3, 4, 3, 2, 3 };

  for(int i=0;i<ngroup;i++) {
    m_Box10[i].set_orientation(Gtk::ORIENTATION_VERTICAL);
    m_Box10[i].set_border_width(3);
  }

  int index = 0;
  for(int i=0;i<ngroup;i++) {
    for(int j=0;j<nbuttons[i];j++) {
      m_RadioButton[index].set_label(label[index]);
      if(j==0) {
        m_RadioButton[index].set_active();
        m_group[i] = m_RadioButton[index].get_group();
      } else {
        m_RadioButton[index].set_group(m_group[i]);
      }
      m_Box10[i].pack_start(m_RadioButton[index], FALSE, FALSE, 0);
      m_RadioButton[index].signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), index));
      index++;
    }
    m_Box1.pack_start(m_Box10[i]);
    if(i != ngroup-1) {
      m_Box1.pack_start(m_VSeparator[i]);
    }
  }

  add(m_Box_Top);

  m_Box1.set_border_width(10);
  m_Box2.set_border_width(10);
  m_Box_Top.pack_start(m_Box1);
  m_Box_Top.pack_start(m_HSeparator);
  m_Box_Top.pack_start(m_Box2);
  m_Box2.pack_start(m_Button_Quit);

  m_Button_Quit.set_can_default();
  m_Button_Quit.grab_default();
  m_Button_Quit.signal_clicked().connect (sigc::            mem_fun(*this, &RadioButtons::on_button_clicked )    );

  show_all_children();
}
#ifndef GTKMM_EXAMPLE_RADIOBUTTONS_H
#define GTKMM_EXAMPLE_RADIOBUTTONS_H

#include <gtkmm/box.h>
#include <gtkmm/window.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/separator.h>

class RadioButtons : public Gtk::Window
{
public:
  RadioButtons();
  virtual ~RadioButtons();
protected:
  void on_button_clicked ();
  void on_button_clicked9(gint data);
  Gtk::Box         m_Box_Top, m_Box1, m_Box2;
  Gtk::Box         m_Box10       [  8];
  Gtk::RadioButton::Group m_group[  8];
  Gtk::RadioButton m_RadioButton [100];
  Gtk::HSeparator  m_HSeparator;
  Gtk::VSeparator  m_VSeparator  [  7];
  Gtk::Button      m_Button_Quit;
};

#endif //GTKMM_EXAMPLE_RADIOBUTTONS_H

No Data Structures (2)

gtk3a

A little bit improved?

#include "radiobuttons.h"
#include <iostream>
void myfunc (int);

RadioButtons::RadioButtons() :
  m_Box_Top(Gtk::ORIENTATION_VERTICAL),
  m_Box1 (Gtk::ORIENTATION_HORIZONTAL, 10),
  m_Box10(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box11(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box12(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box2 (Gtk::ORIENTATION_VERTICAL  , 10),
  m_Button_Quit ("Quit")
{
  set_title("Spinor Lab");
  set_border_width(10);

  static char label[10][256] = { "CW", "CW-R", "LSB", "USB", "DSP FIL1", "DSP FIL2", "DSP FIL3", "DSP SHARP", "DSP SOFT" };

  for(int i=0;i<9;i++) {
    m_RadioButton[i].set_label(label[i]);
  }

  for(int i=0;i<=3;i++) {
    if(i==0) {m_group[0] = m_RadioButton[i].get_group();
    } else {
      m_RadioButton[i].set_group(m_group[0]);
    }
    m_Box10.pack_start(m_RadioButton[i], FALSE, FALSE, 0);
  }

  for(int i=4;i<=6;i++) {
    if(i==4) {m_group[1] = m_RadioButton[i].get_group();
    } else {
      m_RadioButton[i].set_group(m_group[1]);
    }
    m_Box11.pack_start(m_RadioButton[i], FALSE, FALSE, 0);
  }

  for(int i=7;i<=8;i++) {
    if(i==7) {m_group[2] = m_RadioButton[i].get_group();
    } else {
      m_RadioButton[i].set_group(m_group[2]);
    }
    m_Box12.pack_start(m_RadioButton[i], FALSE, FALSE, 0);
  }

  add(m_Box_Top);

  m_Box_Top.pack_start(m_Box1);
  m_Box_Top.pack_start(m_HSeparator);
  m_Box_Top.pack_start(m_Box2);

  m_Box1.set_border_width(10);
  m_Box2.set_border_width(10);

  m_Box1.pack_start(m_Box10);
  m_Box1.pack_start(m_VSeparator[0]);
  m_Box1.pack_start(m_Box11);
  m_Box1.pack_start(m_VSeparator[1]);
  m_Box1.pack_start(m_Box12);
  
  m_RadioButton[0].set_active();

  m_Box2.pack_start(m_Button_Quit);

  m_Button_Quit.set_can_default();
  m_Button_Quit.grab_default();

  m_Button_Quit.signal_clicked().connect (sigc::            mem_fun(*this, &RadioButtons::on_button_clicked )    );
  for(int i=0;i<9;i++) {
    m_RadioButton[i].signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), i));
  }

  show_all_children();
}
void RadioButtons::on_button_clicked9(gint data)
{

  if(m_RadioButton[data].get_active()) {
    std::cout << "button " << data << " is active " << std::endl;
	myfunc(data);
  }
}
#ifndef GTKMM_EXAMPLE_RADIOBUTTONS_H
#define GTKMM_EXAMPLE_RADIOBUTTONS_H

#include <gtkmm/box.h>
#include <gtkmm/window.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/separator.h>

class RadioButtons : public Gtk::Window
{
public:
  RadioButtons();
  virtual ~RadioButtons();
protected:
  void on_button_clicked ();
  void on_button_clicked9(gint data);
  Gtk::Box         m_Box_Top, m_Box1, m_Box10, m_Box11, m_Box12, m_Box2;
  Gtk::RadioButton::Group m_group[ 3];
  Gtk::RadioButton m_RadioButton [10];
  Gtk::HSeparator  m_HSeparator;
  Gtk::VSeparator  m_VSeparator  [ 2];
  Gtk::Button      m_Button_Quit;
};

#endif //GTKMM_EXAMPLE_RADIOBUTTONS_H

No Data Structures

gtk3a

The following code works, but not smart at all, because there are no data structures.

#include "radiobuttons.h"
#include <iostream>
void myfunc (int);

RadioButtons::RadioButtons() :
  m_Box_Top(Gtk::ORIENTATION_VERTICAL),
  m_Box1 (Gtk::ORIENTATION_HORIZONTAL, 10),
  m_Box10(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box11(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box12(Gtk::ORIENTATION_VERTICAL  , 10),
  m_Box2 (Gtk::ORIENTATION_VERTICAL  , 10),
  m_RadioButton1("CW"),
  m_RadioButton2("CW-R"),
  m_RadioButton3("LSB"),
  m_RadioButton4("USB"),
  m_RadioButton5("DSP FIL1"),
  m_RadioButton6("DSP FIL2"),
  m_RadioButton7("DSP FIL3"),
  m_RadioButton8("DSP SHARP"),
  m_RadioButton9("DSP SOFT"),
  m_Button_Quit ("Quit")
{
  set_title("Spinor Lab");
  set_border_width(10);

  Gtk::RadioButton::Group group1 = m_RadioButton1.get_group();
  m_RadioButton2.set_group(group1);
  m_RadioButton3.set_group(group1);
  m_RadioButton4.set_group(group1);

  Gtk::RadioButton::Group group2 = m_RadioButton5.get_group();
  m_RadioButton6.set_group(group2);
  m_RadioButton7.set_group(group2);

  Gtk::RadioButton::Group group3 = m_RadioButton8.get_group();
  m_RadioButton9.set_group(group3);

  add(m_Box_Top);

  m_Box_Top.pack_start(m_Box1);
  m_Box_Top.pack_start(m_Separator1);
  m_Box_Top.pack_start(m_Box2);

  m_Box1.set_border_width(10);
  m_Box2.set_border_width(10);

  m_Box1.pack_start(m_Box10);
  m_Box1.pack_start(m_Separator2);
  m_Box1.pack_start(m_Box11);
  m_Box1.pack_start(m_Separator3);
  m_Box1.pack_start(m_Box12);
  
  m_Box10.pack_start(m_RadioButton1, FALSE, FALSE, 0);
  m_Box10.pack_start(m_RadioButton2, FALSE, FALSE, 0);
  m_Box10.pack_start(m_RadioButton3, FALSE, FALSE, 0);
  m_Box10.pack_start(m_RadioButton4, FALSE, FALSE, 0);

  m_Box11.pack_start(m_RadioButton5, FALSE, FALSE, 0);
  m_Box11.pack_start(m_RadioButton6, FALSE, FALSE, 0);
  m_Box11.pack_start(m_RadioButton7, FALSE, FALSE, 0);

  m_Box12.pack_start(m_RadioButton8, FALSE, FALSE, 0);
  m_Box12.pack_start(m_RadioButton9, FALSE, FALSE, 0);

  m_RadioButton1.set_active();

  m_Box2.pack_start(m_Button_Quit);

  m_Button_Quit.set_can_default();
  m_Button_Quit.grab_default();

  m_Button_Quit.signal_clicked().connect (sigc::            mem_fun(*this, &RadioButtons::on_button_clicked )    );
  m_RadioButton1.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 1));
  m_RadioButton2.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 2));
  m_RadioButton3.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 3));
  m_RadioButton4.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 4));
  m_RadioButton5.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 5));
  m_RadioButton6.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 6));
  m_RadioButton7.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 7));
  m_RadioButton8.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 8));
  m_RadioButton9.signal_clicked().connect(sigc::bind<gint> (mem_fun(*this, &RadioButtons::on_button_clicked9), 9));

  show_all_children();
}
void RadioButtons::on_button_clicked9(gint data)
{
  if(data == 1) {
    if(m_RadioButton1.get_active()) {
      std::cout << "button1 is active " << std::endl;
	  myfunc(1);
	}
  }
  /* this kind of stuff deleted */
}
#ifndef GTKMM_EXAMPLE_RADIOBUTTONS_H
#define GTKMM_EXAMPLE_RADIOBUTTONS_H

#include <gtkmm/box.h>
#include <gtkmm/window.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/separator.h>

class RadioButtons : public Gtk::Window
{
public:
  RadioButtons();
  virtual ~RadioButtons();
protected:
  void on_button_clicked ();
  void on_button_clicked9(gint data);
  Gtk::Box         m_Box_Top, m_Box1, m_Box10, m_Box11, m_Box12, m_Box2;
  Gtk::RadioButton m_RadioButton1, m_RadioButton2, m_RadioButton3, m_RadioButton4;
  Gtk::RadioButton m_RadioButton5, m_RadioButton6, m_RadioButton7;
  Gtk::RadioButton m_RadioButton8, m_RadioButton9;
  Gtk::HSeparator  m_Separator1;
  Gtk::VSeparator  m_Separator2, m_Separator3;
  Gtk::Button      m_Button_Quit;
};

#endif //GTKMM_EXAMPLE_RADIOBUTTONS_H

Wirth’s law

Niklaus_Wirth,_UrGU

Software is getting slower more rapidly than hardware becomes faster.

Algorithms_Data_Structures

This book, written in 1976, emphasizes that algorithms and data structures are inherently related.

radiobuttonsrevisited

So what type of the data structures is best suited for these buttons?

class RadioButtons : public Gtk::Window
{
public:
  RadioButtons();
  virtual ~RadioButtons();

protected:
  void on_button_clicked ();
  void on_button_clicked9(Glib::ustring data);

  Gtk::Box         m_Box_Top, m_Box1, m_Box2; 
  Gtk::RadioButton m_RadioButton1, m_RadioButton2, m_RadioButton3, m_RadioButton4;
  Gtk::Separator   m_Separator;
  Gtk::Button      m_Button_Quit;
};
void RadioButtons::on_button_clicked9(Glib::ustring data)
{
  if(data == "1") {
    if(m_RadioButton1.get_active()) {
      std::cout << "button1 is active " << std::endl;
      myfunc(1);
    }
  }
  if(data == "2") {
    if(m_RadioButton2.get_active()) {
      std::cout << "button2 is active " << std::endl;
      myfunc(2);
    }
  }
  if(data == "3") {
    if(m_RadioButton3.get_active()) {
      std::cout << "button3 is active " << std::endl;
      myfunc(3);
    }
  }
  if(data == "4") {
    if(m_RadioButton4.get_active()) {
      std::cout << "button4 is active " << std::endl;
      myfunc(4);
    }
  }
}
  m_Button_Quit.signal_clicked().connect (sigc::mem_fun(*this, &RadioButtons::on_button_clicked ) );
  m_RadioButton1.signal_clicked().connect(sigc::bind<Glib::ustring>(mem_fun(*this, &RadioButtons::on_button_clicked9), "1" ));
  m_RadioButton2.signal_clicked().connect(sigc::bind<Glib::ustring>(mem_fun(*this, &RadioButtons::on_button_clicked9), "2" ));
  m_RadioButton3.signal_clicked().connect(sigc::bind<Glib::ustring>(mem_fun(*this, &RadioButtons::on_button_clicked9), "3" ));
  m_RadioButton4.signal_clicked().connect(sigc::bind<Glib::ustring>(mem_fun(*this, &RadioButtons::on_button_clicked9), "4" ));

Radio Buttons revisited

radiobuttonsrevisited

Now let’s start at the very beginning.

When you read you begin with A B C, when you write your codes with gtkmm3 you begin with radio buttons.

#include "radiobuttons.h"
#include <iostream>
void myfunc (int);

RadioButtons::RadioButtons() :
  m_Box_Top(Gtk::ORIENTATION_VERTICAL),
  m_Box1(Gtk::ORIENTATION_VERTICAL, 10),
  m_Box2(Gtk::ORIENTATION_VERTICAL, 10),
  m_RadioButton1("CW"),
  m_RadioButton2("CW-R"),
  m_RadioButton3("LSB"),
  m_RadioButton4("USB"),
  m_Button_Quit ("Quit")
{
  set_title("Spinor Lab");
  set_border_width(10);

  Gtk::RadioButton::Group group = m_RadioButton1.get_group();
  m_RadioButton2.set_group(group);
  m_RadioButton3.set_group(group);
  m_RadioButton4.set_group(group);

  add(m_Box_Top);

  m_Box_Top.pack_start(m_Box1);
  m_Box_Top.pack_start(m_Separator);
  m_Box_Top.pack_start(m_Box2);

  m_Box2.set_border_width(10);
  m_Box1.set_border_width(10);

  m_Box1.pack_start(m_RadioButton1);
  m_Box1.pack_start(m_RadioButton2);
  m_Box1.pack_start(m_RadioButton3);
  m_Box1.pack_start(m_RadioButton4);

  m_RadioButton1.set_active();

  m_Box2.pack_start(m_Button_Quit);

  m_Button_Quit.set_can_default();
  m_Button_Quit.grab_default();

  m_Button_Quit.signal_clicked().connect (sigc::mem_fun(*this, &RadioButtons::on_button_clicked ) );
  m_RadioButton1.signal_clicked().connect(sigc::mem_fun(*this, &RadioButtons::on_button_clicked1) );
  m_RadioButton2.signal_clicked().connect(sigc::mem_fun(*this, &RadioButtons::on_button_clicked2) );
  m_RadioButton3.signal_clicked().connect(sigc::mem_fun(*this, &RadioButtons::on_button_clicked3) );
  m_RadioButton4.signal_clicked().connect(sigc::mem_fun(*this, &RadioButtons::on_button_clicked4) );

  show_all_children();
}

void RadioButtons::on_button_clicked1()
{
  if(m_RadioButton1.get_active()) {
    std::cout << "clicked1: active" << std::endl;
	myfunc(1);
  }
}

There is a lot of room for improvement.

void myfunc (int index) {
  std::cout << "myfunc: " << index << std::endl;
  switch (index) {
    case 1: 
      operating_mode = 0x03; 
      dsp_filter     = 0x01; 
      break;  
    case 2: 
      operating_mode = 0x07; 
      dsp_filter     = 0x01; 
      break;  
    case 3: 
      operating_mode = 0x00; 
      dsp_filter     = 0x01; 
      break;  
    case 4: 
      operating_mode = 0x01; 
      dsp_filter     = 0x01; 
      break;  
    }
  set_operating_mode();
}

Migrating from C to C++

buttons

So I am now migrating from C to C++, but this only goes very slowly.

This is a simple test to check if my rig control part of the program still works with C++ environment.

void myfunc( void ); 

Buttons::Buttons()
{
  m_button.add_pixlabel("blueracer2.png", "CW");
  set_title("Spinor Lab");
  set_border_width(10);
  m_button.signal_clicked().connect( sigc::mem_fun(*this, &Buttons::on_button_clicked) );
  add(m_button);
  show_all_children();
}

Buttons::~Buttons()
{
}

void Buttons::on_button_clicked()
{
  std::cout << "The Button was clicked." << std::endl;
  myfunc();
}

gtkmm3

gtkmm3

gtkmm is a C++ wrapper for GTK+.

simple

This looks more readable for you?

Let’s see if I can rewrite my IC-7410 Rig Control Program using gtkmm3.