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; }