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 | |
---|
14 | using namespace Gtk; |
---|
15 | |
---|
16 | |
---|
17 | /* { name, stock_id, label, acclerator, tooltip, callback } */ |
---|
18 | GtkActionEntry 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 | |
---|
34 | PaperTapeZoom::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 | |
---|
43 | void 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 | |
---|
133 | void 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 | |
---|
140 | void 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 | |
---|
152 | void 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 | |
---|
162 | void 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 | |
---|
176 | void 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 | |
---|
188 | void 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 | |
---|
196 | void 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 | |
---|
207 | void 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 | |
---|
218 | void PaperTapeZoom::set_flip(PaperTapeFlip flip, bool relative) { |
---|
219 | // not implemented yet |
---|
220 | } |
---|
221 | |
---|
222 | Glib::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 | |
---|
236 | void 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 | |
---|
274 | void PaperTapeZoom::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, &PaperTapeZoom::on_auto_zoom_resize) |
---|
280 | ); |
---|
281 | |
---|
282 | |
---|
283 | |
---|
284 | } |
---|
285 | |
---|
286 | void PaperTapeZoom::disable_auto_zoom() { |
---|
287 | if(auto_zoom_enabled) { |
---|
288 | auto_zoom_resize_con.disconnect(); |
---|
289 | auto_zoom_enabled = false; |
---|
290 | } |
---|
291 | } |
---|
292 | |
---|
293 | bool PaperTapeZoom::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 | return true; |
---|
298 | } |
---|
299 | |
---|
300 | |
---|
301 | /* |
---|
302 | void 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 | */ |
---|