Still not really comfortable (2)

This is better.

I did not notice the difference between the two; sigc::ptr_fun() generates a slot for a standalone function or static method. sigc::mem_fun() generates a slot for a member method of a particular instance.

So it’s another RTFM as it always happens to me.

/* MyWindow.cpp */

#include "MyWindow.h"
#include "MyArea.h"
#include <gtkmm.h>

MyWindow::MyWindow() : m_box(Gtk::ORIENTATION_VERTICAL), m_buttons(Gtk::ORIENTATION_HORIZONTAL),
		m_button1("_reset", true), m_button2("_shrink", true), m_button3("_left", true),
		m_button4("righ_t", true), m_button5("_up"    , true), m_button6("_down", true) {
	set_title("Test test...");
	set_default_size(300, 329);
	set_border_width(10);
	add(m_box);
	m_box.pack_start(m_buttons, false, true);
	m_buttons.pack_start(m_button1, true, true);
	m_buttons.pack_start(m_button2, true, true);
	m_buttons.pack_start(m_button3, true, true);
	m_buttons.pack_start(m_button4, true, true);
	m_buttons.pack_start(m_button5, true, true);
	m_buttons.pack_start(m_button6, true, true);
	m_button1.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_reset ));
	m_button2.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_shrink));
	m_button3.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_left  ));
	m_button4.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_right ));
	m_button5.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_up    ));
	m_button6.signal_clicked().connect(sigc::mem_fun(m_area, &MyArea::area_down  ));
	m_box.pack_start(m_area);
	show_all_children();
}

MyWindow::~MyWindow() {
}

Still not really comfortable

notcomfortable

It works, but I am not satisfied.

/* main.cpp */
#include "MyWindow.h"
#include <gtkmm/application.h>

int main(int argc, char** argv)
{
   Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
   MyWindow win;
   return app->run(win);
}
/* MyWindow.h */

#ifndef MYWINDOW_H_
#define MYWINDOW_H_

#include "MyArea.h"
#include <gtkmm/window.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>

class MyWindow : public Gtk::Window {
public:
	MyWindow();
	virtual ~MyWindow();
protected:
	void on_button1_clicked();
	void on_button2_clicked();
	void on_button3_clicked();
	void on_button4_clicked();
	void on_button5_clicked();
	void on_button6_clicked();
private:
	Gtk::Box    m_box;
	Gtk::Box    m_buttons;
	Gtk::Button m_button1;
	Gtk::Button m_button2;
	Gtk::Button m_button3;
	Gtk::Button m_button4;
	Gtk::Button m_button5;
	Gtk::Button m_button6;
	MyArea      m_area;
};

#endif /* MYWINDOW_H_ */
/* MyWindow.cpp */

#include "MyWindow.h"
#include "MyArea.h"

MyWindow::MyWindow() : m_box(Gtk::ORIENTATION_VERTICAL), m_buttons(Gtk::ORIENTATION_HORIZONTAL),
		m_button1("reset"), m_button2("shrink"), m_button3("left"), m_button4("right"), m_button5("up"), m_button6("down") {
	set_title("Not comfortable...");
	set_default_size(300, 329);
	add(m_box);
	m_box.pack_start(m_buttons, false, true);
	m_buttons.pack_start(m_button1, true, true);
	m_buttons.pack_start(m_button2, true, true);
	m_buttons.pack_start(m_button3, true, true);
	m_buttons.pack_start(m_button4, true, true);
	m_buttons.pack_start(m_button5, true, true);
	m_buttons.pack_start(m_button6, true, true);
	m_button1.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button1_clicked));
	m_button1.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button1_clicked));
	m_button1.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button1_clicked));
	m_button2.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button2_clicked));
	m_button3.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button3_clicked));
	m_button4.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button4_clicked));
	m_button5.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button5_clicked));
	m_button6.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_button6_clicked));
	m_box.pack_start(m_area);
	show_all_children();
}

MyWindow::~MyWindow() {
}

void MyWindow::on_button1_clicked() {
	m_area.area_reset();
}

void MyWindow::on_button2_clicked() {
	m_area.area_shrink();
}

void MyWindow::on_button3_clicked() {
	m_area.area_left();
}

void MyWindow::on_button4_clicked() {
	m_area.area_right();
}

void MyWindow::on_button5_clicked() {
	m_area.area_up();
}

void MyWindow::on_button6_clicked() {
	m_area.area_down();
}
/* MyArea.h */

#ifndef MYAREA_H_
#define MYAREA_H_

#include <gtkmm/drawingarea.h>

class MyArea : public Gtk::DrawingArea
{
public:
  MyArea();
  virtual ~MyArea();
  void area_reset();
  void area_shrink();
  void area_left();
  void area_right();
  void area_up();
  void area_down();
protected:
  virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
  virtual bool on_button_press_event  ( GdkEventButton* event );
  virtual bool on_button_release_event( GdkEventButton* event );
private:
  double x_min;
  double x_max;
  double y_min;
  double y_max;
  double x_press;
  double y_press;
  double x_release;
  double y_release;
};

#endif /* MYAREA_H_ */
/* MyArea.cpp */

#include "MyArea.h"
#include <complex>
#include <iostream>
using namespace std;

MyArea::MyArea() : x_min {-1.5}, x_max { 0.5}, y_min {-1.0}, y_max { 1.0},
				   x_press {0.0}, y_press {0.0}, x_release {0.0}, y_release {0.0}
{
	add_events( Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK );
}

MyArea::~MyArea() {
}

void MyArea::area_reset() {
	x_min = -1.5;
	x_max =  0.5;
	y_min = -1.0;
	y_max =  1.0;
	get_window()->invalidate(true);
}

void MyArea::area_shrink() {
	double xc = (x_min + x_max) / 2.0;
	double yc = (y_min + y_max) / 2.0;
	double xs = (x_max - xc) / 0.67;
	double ys = (y_max - yc) / 0.67;
	x_min = xc - xs;
	x_max = xc + xs;
	y_min = yc - ys;
	y_max = yc + ys;
	get_window()->invalidate(true);
}

void MyArea::area_left() {
	double xc = (x_min + x_max) / 2.0;
	double xs = (x_max - xc) * 0.67;
	x_min += xs;
	x_max += xs;
	get_window()->invalidate(true);
}

void MyArea::area_right() {
	double xc = (x_min + x_max) / 2.0;
	double xs = (x_max - xc) * 0.67;
	x_min -= xs;
	x_max -= xs;
	get_window()->invalidate(true);
}

void MyArea::area_up() {
	double yc = (y_min + y_max) / 2.0;
	double ys = (y_max - yc) * 0.67;
	y_min += ys;
	y_max += ys;
	get_window()->invalidate(true);
}

void MyArea::area_down() {
	double yc = (y_min + y_max) / 2.0;
	double ys = (y_max - yc) * 0.67;
	y_min -= ys;
	y_max -= ys;
	get_window()->invalidate(true);
}

bool MyArea::on_button_press_event( GdkEventButton* event )
{
    std::cout << "pressed:  " << event->x << " : " << event->y << std::endl;
    x_press = event->x;
    y_press = event->y;
    return true;
}

bool MyArea::on_button_release_event( GdkEventButton* event )
{
    std::cout << "released: " << event->x << " : " << event->y << std::endl;
    x_release = event->x;
    y_release = event->y;
	get_window()->invalidate(true);
    return true;
}

bool MyArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
  Gtk::Allocation allocation = get_allocation();
  const int width  = allocation.get_width();
  const int height = allocation.get_height();
  if(x_press != x_release && y_press != y_release) {
	  double x_min_new = x_min + (x_max - x_min) * ( x_press   / (double) width );
	  double x_max_new = x_min + (x_max - x_min) * ( x_release / (double) width );
	  x_min = x_min_new;
	  x_max = x_max_new;
	  double y_min_new = y_min + (y_max - y_min) * ( y_press   / (double) height );
	  double y_max_new = y_min + (y_max - y_min) * ( y_release / (double) height );
	  y_min = y_min_new;
	  y_max = y_max_new;
	  x_press = y_press = x_release = y_release = 0.0;
  }
  cout << "MyArea: width = " << width << ", height = " << height
       << ", (" << x_min << ", " << y_min << ") ----> (" << x_max << ", " << y_max << ") \n";

  cr->set_line_width(1.0);

  double large = 100.0;
  int    kmax  =  50;

  for(int i=0;i<width;i++) {
	  for(int j=0;j<height;j++) {
		  double x=x_min+(x_max-x_min)*(double)i/(double)width;
		  double y=y_min+(y_max-y_min)*(double)j/(double)height;
		  complex<double> z=0.0;
		  complex<double> w=complex<double>(x,y);
		  int count=0;
		  for(int k=0;k<kmax;k++) {
			  z=z*z+w;
			  if(abs(z)>large) {
				  count = k;
				  break;
			  }
		  }
		  if(count) {
			  cr->set_source_rgba(0.9,(count%10)/10.0,0.3,1.0);
		  } else {
			  cr->set_source_rgba(0.0,0.2,0.7,1.0);
		  }
		  cr->rectangle((double)i, (double)j, 1.0, 1.0);
		  cr->stroke();
	  }
  }
  return true;
}