source: projects/visualisator/gtkpapertapezoom.cc @ 19

Last change on this file since 19 was 19, checked in by sven, 11 years ago

The Gtk::PaperTape gtkmm implementation of the GtkPaperTape widget. Now
quite more object oriented, using a MVC approach. There's much still to
do.

I commit these files now because I won't be able to work at the project
in the next week(s). Afterwards I plan to make more use of the
versioning features, commiting on a more regular basis.

-- Sven @ workstation

File size: 10.1 KB
Line 
1#include "gtkpapertapezoom.h"
2#include <gtkmm/actiongroup.h>
3#include <gtkmm/table.h>
4#include <gtkmm/label.h>
5#include <gtkmm/frame.h>
6#include <gtkmm/checkbutton.h>
7#include <gtkmm/box.h>
8#include <gtk/gtk.h>
9#include <cairo.h>
10#include <gtkmm/stock.h>
11#include <iostream>
12#include <cstdio>
13
14using namespace Gtk;
15
16
17/* { name, stock_id, label, acclerator, tooltip, callback } */
18GtkActionEntry PaperTapeZoom::ui_action_entries[] = {
19        { "ZoomIn", GTK_STOCK_ZOOM_IN },
20        { "ZoomOut", GTK_STOCK_ZOOM_OUT },
21        { "Zoom100", GTK_STOCK_ZOOM_100 },
22        { "Zoom50", NULL, "Zoom to 50%" },
23        { "Zoom200", NULL, "Zoom to 200%" },
24        { "ZoomWidth", GTK_STOCK_ZOOM_FIT, "Fit to screen", NULL, "Zoom that the papertape width fills the screen" },
25        { "ZoomLength", GTK_STOCK_ZOOM_FIT, "Fit all to screen ", NULL, "Zoom that the complete papertape fills in the screen" },
26        { "ZoomDialog", GTK_STOCK_PROPERTIES, "Show dialog...", "<ctrl>z", "Set Zoom level and input own Affine Translation Matrix" },
27
28        { "Rotate90CW", GTK_STOCK_ORIENTATION_LANDSCAPE, "Rotate clockwise" },
29        { "Rotate90CCW", GTK_STOCK_ORIENTATION_REVERSE_LANDSCAPE, "Rotate anticlockwise" },
30        { "FlipHoriz", GTK_STOCK_ORIENTATION_PORTRAIT, "Flip horizontally" },
31        { "FlipVert", GTK_STOCK_ORIENTATION_REVERSE_PORTRAIT, "Flip verticall" }
32};
33
34PaperTapeZoom::PaperTapeZoom(double default_rotation, double default_zoom_factor, PaperTapeFlip default_flip) {
35        // init values
36        this->rotation = default_rotation;
37        this->flip = default_flip;
38        this->zoom_factor = default_zoom_factor;
39        this->manually = false;
40        set_default(default_rotation, default_zoom_factor, default_flip);
41}
42
43void PaperTapeZoom::show_dialog() {
44        if(!matrix_dialog) {
45                // set up the matrix_dialog.
46                matrix_dialog = new Dialog("Set papertape view");
47                // Frame.
48                Frame* matrix_frame = manage(new Frame());
49                CheckButton* matrix_manually = manage(new CheckButton("Set Affine Translation Matrix manually"));
50                matrix_manually->set_active(this->manually);
51                // connect matrix_manually button
52                matrix_manually->signal_toggled().connect(
53                        sigc::bind(sigc::mem_fun(*this, &PaperTapeZoom::on_toggle_manually), matrix_manually)
54                );
55                matrix_frame->set_label_widget(*matrix_manually);
56               
57                Table* table = manage(new Table(2, 6));
58                Label* l;
59                l = manage(new Label("x__n = "));
60                table->attach(*l, 0, 1, 0, 1);
61                matrix_entries[&xx] = manage(new SpinButton());
62                table->attach(*matrix_entries[&xx], 1, 2, 0, 1);
63                l = manage(new Label("* x + "));
64                table->attach(*l, 2, 3, 0, 1);
65                matrix_entries[&xy] = manage(new SpinButton());
66                table->attach(*matrix_entries[&xy], 3, 4, 0, 1);
67                l = manage(new Label("* y + "));
68                table->attach(*l, 4, 5, 0, 1);
69                matrix_entries[&x0] = manage(new SpinButton());
70                table->attach(*matrix_entries[&x0], 5, 6, 0, 1);
71                l = manage(new Label("y__n = "));
72                table->attach(*l, 0, 1, 1, 2);
73                matrix_entries[&yx] = manage(new SpinButton());
74                table->attach(*matrix_entries[&yx], 1, 2, 1, 2);
75                l = manage(new Label("* x + "));
76                table->attach(*l, 2, 3, 1, 2);
77                matrix_entries[&yy] = manage(new SpinButton());
78                table->attach(*matrix_entries[&yy], 3, 4, 1, 2);
79                l = manage(new Label("* y + "));
80                table->attach(*l, 4, 5, 1, 2);
81                matrix_entries[&y0] = manage(new SpinButton());
82                table->attach(*matrix_entries[&y0], 5, 6, 1, 2);
83               
84                // connect signals
85                for(std::map<double*, SpinButton*>::iterator i = matrix_entries.begin();
86                    i != matrix_entries.end(); i++) {
87                        i->second->set_sensitive(this->manually);
88                        i->second->set_range(-G_MAXDOUBLE, G_MAXDOUBLE); // ;-)
89                        i->second->set_increments(5.0, 10.0);
90                        i->second->set_value( * (i->first) );
91                        i->second->signal_value_changed().connect(
92                                sigc::bind(
93                                        sigc::mem_fun(*this, &PaperTapeZoom::on_change_field),
94                                        i->first
95                                )
96                        );
97                } // for entries
98
99               
100                matrix_frame->add(*table);
101                matrix_dialog->get_vbox()->add(*matrix_frame);
102               
103                // add buttons
104                //matrix_dialog->add_button(GTK_STOCK_UNDO, 1);
105                Button* reset = manage(new Button(Stock::UNDO));
106                matrix_dialog->get_action_area()->add(*reset);
107                matrix_dialog->get_action_area()->set_child_secondary(*reset);
108                reset->signal_clicked().connect(sigc::mem_fun(*this, &PaperTapeZoom::reset));
109
110                //matrix_dialog->add_button(Stock::APPLY, 2);
111                // directly apply! :-)
112               
113                // we could use this, but we could not conncet own signals, so:
114                //matrix_dialog->add_button(Stock::CLOSE, 3);
115                Button *close = manage(new Button(Stock::CLOSE));
116                matrix_dialog->get_action_area()->add(*close);
117                close->signal_clicked().connect(sigc::mem_fun(*matrix_dialog, &Window::hide));
118               
119                // update the entry things whenever the zoom is changed
120                this->signal_changed().connect(sigc::mem_fun(*this, &PaperTapeZoom::update_dialog_on_zoom_changes));
121               
122                //matrix_dialog->add(*main_box);
123                matrix_dialog->set_focus(*close);
124                matrix_dialog->show_all();
125        } else {
126                // Window already created: Show it and/or bring it to front
127                matrix_dialog->show();
128                matrix_dialog->grab_focus(); // try it...
129                matrix_dialog->raise(); // bring it to front
130        }
131}
132
133void PaperTapeZoom::update_dialog_on_zoom_changes() {
134        for(std::map<double*, SpinButton*>::iterator i = matrix_entries.begin();
135            i != matrix_entries.end(); i++) {
136                i->second->set_value( * (i->first) );
137        } // for entries
138}
139
140void PaperTapeZoom::reset() {
141        if(this->is_controlled_manually()) {
142                *this = default_matrix; /*xx = default_matrix.xx; xy = default_matrix.xy; x0 = default_matrix.x0;
143                yx = default_matrix.yx; yy = default_matrix.yy; y0 = default_matrix.y0;*/
144                zoom_changed.emit();
145        } else {
146                zoom_factor = 1.0;
147                rotation = 0.0;
148                calc_matrix();
149        }
150}
151
152void PaperTapeZoom::on_toggle_manually(CheckButton* manually_toggle) {
153        this->manually = manually_toggle->get_active();
154        // turn input widgets on/off
155        for(std::map<double*, SpinButton*>::iterator i = matrix_entries.begin();
156            i != matrix_entries.end(); i++) {
157                i->second->set_sensitive(manually);
158        }
159        // + turn other widgets on/off, like action widgets
160}
161
162void PaperTapeZoom::on_change_field(double* field) {
163        // only for internal use
164        if(!field) {
165                std::cout << "Bad NUll Pointer at on_change_field.\n";
166                return;
167        }
168        if(matrix_entries[field]) {
169                std::cout << "UPDATE FIELD\n";
170                *field = matrix_entries[field]->get_value();
171                zoom_changed.emit();
172        } else
173                std::cout << "BAD: FIELD NOT SUPPORTED (PaperTapeZoom::change_field)\n";
174}
175
176void PaperTapeZoom::calc_matrix() {
177        // take the buffer things and calculate a new matrix, FROM
178        // DEFAULT MATRIX.
179        if(!this->is_controlled_manually()) {
180                *this = default_matrix;
181                cairo_matrix_scale(this, zoom_factor, zoom_factor);
182                cairo_matrix_rotate(this, rotation);
183
184                zoom_changed.emit();
185        }
186}
187
188void PaperTapeZoom::set_default(double rotation, double zoom_factor, PaperTapeFlip flip) {
189        // change default matrix.
190        cairo_matrix_init_identity(&this->default_matrix);
191        cairo_matrix_scale(&this->default_matrix, zoom_factor, zoom_factor);
192        cairo_matrix_rotate(&this->default_matrix, rotation);
193        // flip?
194}
195
196void PaperTapeZoom::set_rotate(double radians, bool relative) {
197        if(!is_controlled_manually()) {
198                this->rotation = relative ? (this->rotation + radians) : radians;
199                this->calc_matrix();
200        } else {
201                // change user matrix
202                cairo_matrix_rotate(this, radians);
203                zoom_changed.emit();
204        }
205}
206
207void PaperTapeZoom::set_zoom(double zoom_factor, bool relative) {
208        if(!is_controlled_manually()) {
209                this->zoom_factor = relative ? (this->zoom_factor * zoom_factor) : zoom_factor;
210                this->calc_matrix();
211        } else {
212                // change user matrix
213                cairo_matrix_scale(this, zoom_factor, zoom_factor);
214                zoom_changed.emit();
215        }
216}
217
218void PaperTapeZoom::set_flip(PaperTapeFlip flip, bool relative) {
219        // not implemented yet
220}
221
222Glib::RefPtr<ActionGroup> PaperTapeZoom::get_action_group() {
223        Glib::RefPtr<ActionGroup> group = ActionGroup::create("GtkPaperTapeZoom");
224       
225        gtk_action_group_add_actions(
226                        group->gobj(),
227                        ui_action_entries,
228                        G_N_ELEMENTS(ui_action_entries),
229                        NULL);
230
231        group->signal_post_activate().connect(sigc::mem_fun(*this, &PaperTapeZoom::transform_action));
232
233        return group;
234}
235
236void PaperTapeZoom::transform_action(const Glib::RefPtr<Action>& action) {
237        Glib::ustring name = action->get_name();
238       
239        if(name == "ZoomIn") {
240                set_zoom(1.1, true);
241        } else if(name == "ZoomOut") {
242                set_zoom(0.9, true);
243        } else if(name == "Zoom100") {
244                set_zoom(1.0, false);
245        } else if(name == "Zoom50") {
246                set_zoom(0.5, false);
247        } else if(name == "Zoom200") {
248                set_zoom(2.0, false);
249        } else if(name == "ZoomWidth") {
250                signal_set_auto_zoom.emit(true);
251               
252                //set_auto_zoom(ZOOM_LOCHSTREIFEN_WIDTH);
253                // get width of lochstreifen (well, "1")
254                // get height of view Viewport
255                // calc length
256                // add signal to fetch size changements
257        } else if(name == "ZoomLength") {
258                set_auto_zoom(ZOOM_LOCHSTREIFEN_LENGTH);
259        } else if(name == "ZoomDialog") {
260                show_dialog();
261        } else if(name == "Rotate90CW") {
262                set_rotate(G_PI, true);
263        } else if(name == "Rotate90CCW") {
264                set_rotate(-G_PI, true);
265        } else if(name == "FlipHoriz") {
266                //set_flip();
267        } else if(name == "FlipVert") {
268                // same here...
269        } else {
270                std::cout << "PaperTapeZoom: Action " << name << " not supported!\n";
271        }
272}
273
274void set_auto_zoom(PaperTapeView& view, PaperTapeAutoZoomType type) {
275        this->auto_zoom_enabled = true;
276
277        // connect resize signal
278        auto_zoom_resize_con = view.signal_configure_event().connect(
279                sigc::mem_fun(*this, on_auto_zoom_resize);
280        );
281
282       
283       
284}
285
286void disable_auto_zoom() {
287        if(auto_zoom_enabled) {
288                auto_zoom_resize_con.disconnect();
289                auto_zoom_enabled = false;
290        }
291}
292
293bool on_auto_zoom_resize(GdkEventConfigure* event) {
294        // depending on orientation, use event->width and event->height
295       
296        // We could use LOCHSTREIFEN logic here!
297       
298}
299
300
301/*
302void PaperTapeView::transform(PaperTapeTransformation how) {
303        switch(how) {
304                case ZOOM_IN:
305                case ZOOM_OUT:
306                {
307                        //current_width_scaling += 10 * ((how == ZOOM_IN) ? 1 : -1);
308                        double f((how == ZOOM_IN) ? 1.1 : (0.9));
309                       
310                        std::cout << "View: scaling up/down: " << f << "\n";
311
312                        cairo_matrix_scale(&lochstreifen->matrix, f, f);
313                        lochstreifen_check_matrix(lochstreifen);
314                        zoom_changed.emit();
315                        break;
316                }
317                case ZOOM_REAL:
318                {
319                        // get the DPI, our factor
320                        double f = Gdk::Screen::get_default().get_resolution();
321                        cairo_matrix_init_scale(&lochstreifen->matrix, f, f);
322                        lochstreifen_check_matrix(lochstreifen);
323                        zoom_changed.emit();
324                }
325                case SET_ZOOM:
326                {
327                        // display the matrix enter dialog
328                }
329        }
330}
331*/
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License