source: projects/visualisator/gtkpapertapeview.cc @ 19

Last change on this file since 19 was 19, checked in by sven, 16 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.0 KB
Line 
1#include <cairomm/context.h>
2#include <iostream>
3#include <cstdio>
4#include <gtkmm/colorbutton.h>
5
6#include "gtkpapertapeview.h"
7#include "gtkpapertapeexporter.h"
8
9#include <cairo/cairo-xlib.h>
10using namespace Gtk;
11
12PaperTapeView::PaperTapeView(PaperTape* controller)
13:
14        just_hovered_row(LOCHSTREIFEN_NO_ROW),
15        just_hovered_track(LOCHSTREIFEN_NO_TRACK),
16        controller(controller)
17{
18        this->lochstreifen = lochstreifen_new();
19        make_colors();
20       
21        current_width_scaling = 200;
22        lochstreifen_set_scaling_by_width(lochstreifen, 200);
23       
24        // catch events for callback functions
25        add_events(Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
26       
27        // the controller connects the on_data_change for us.
28        controller->model->data_changed.connect(sigc::mem_fun(*this, &PaperTapeView::on_data_change));
29       
30        // init zoom (don't forget to delete)
31        zoom = new PaperTapeZoom(0.0, Gdk::Screen::get_default()->get_resolution());
32        zoom->signal_changed().connect(sigc::mem_fun(*this, &PaperTapeView::on_zoom_change));
33       
34        //set_double_buffered(false);
35        //get_window()->set_debug_updates(true);
36}
37
38void PaperTapeView::on_data_change(byte_t* new_data, int new_data_len) {
39        // daten haben sich geaendert. Neue Daten als Parameter
40        // Die Daten verblieben bei dem Model, welches das hier aufruft.
41       
42        std::cout << "data change signal called, newl len " << new_data_len << "\n";
43
44        lochstreifen_set_data(lochstreifen, new_data_len, new_data);
45       
46        set_size_request(
47                lochstreifen_get_target_width(lochstreifen),
48                lochstreifen_get_target_height(lochstreifen)
49        );
50}
51
52void PaperTapeView::on_zoom_change() {
53        // yeah, zoom has changed.
54        // erhm, this is a bit stupid:
55        cairo_matrix_init(&lochstreifen->matrix,
56                zoom->xx, zoom->xy, zoom->yx, zoom->yy, zoom->x0, zoom->y0
57        );
58        lochstreifen_check_matrix(lochstreifen);       
59        set_size_request(
60                lochstreifen_get_target_width(lochstreifen),
61                lochstreifen_get_target_height(lochstreifen)
62        );
63        queue_draw();
64}
65
66bool PaperTapeView::on_expose_event(GdkEventExpose *event) {
67        // besser: Erst das tatsaechliche cairo_t* objekt kriegen beim drawen!
68        Cairo::RefPtr<Cairo::Context> cr = this->get_window()->create_cairo_context();
69        cr->save(); // this is said to be good style
70       
71        // --gtk-debug=updates
72        // for debugging!
73       
74        std::cout << "expose("<< event->count <<"): " << event->area.x << "|" << event->area.y << " " <<
75                event->area.width << "x" << event->area.height << "\n";
76
77        //get_window()->clear_area(event->area.x, event->area.y, event->area.width, event->area.height);
78        //gdk_window_clear_area(event->window, event->area.x, event->area.y, event->area.width, event->area.height);
79        //gdk_window_clear(event->window);
80       
81        int x, y, width, height;
82       
83        gdk_window_get_position(gdk_window_get_parent(event->window), &x, &y);
84        gdk_drawable_get_size(GDK_DRAWABLE(event->window), &width, &height);
85        std::cout << "GdkWin: " << x << "|" << y << " " << width << "x" << height << "\n";
86        //gdk_window_get_geometry(gdk_window_get_parent(event->window), &x, &y, &width, &height, NULL);
87        //std::cout << x << "|" << y << " " << width << "x" << height << "\n";
88       
89        // Get the CAIRO WIDTH/HEIGHT
90        width = cairo_xlib_surface_get_width( cairo_get_target(cr->cobj()) );
91        height = cairo_xlib_surface_get_height( cairo_get_target(cr->cobj()) );
92        std::cout << "csurface: " << width << "x" << height << "\n";
93       
94        // clipping! :-)
95        lochstreifen_set_clip(lochstreifen,
96                event->area.x, event->area.y,
97                event->area.width, event->area.height);
98       
99        lochstreifen_draw(lochstreifen, cr->cobj());
100        cr->restore();
101       
102//      cr->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
103//      cr->paint();
104       
105       
106        return true;
107}
108
109bool PaperTapeView::on_scroll_event(GdkEventScroll* event) {
110        std::cout << "Mouse Scrolling.\n";
111
112        return true;
113}
114
115void PaperTapeView::queue_draw_bit(row_t& row, track_t& track) {
116        cairo_rectangle_t repaint;
117        // paint only in valid range:
118        if(row != LOCHSTREIFEN_NO_ROW && track != LOCHSTREIFEN_NO_TRACK) {
119                if(lochstreifen_get_target_rect_from_bit(lochstreifen, row, track, &repaint)
120                   == LOCHSTREIFEN_SUCCESS) {
121                        std::cout << "Redrawing! row " << row << " track " << track << ": ";
122                        std::cout << repaint.x << "|" << repaint.y << " " << repaint.width << "x" << repaint.height << "\n";
123                        queue_draw_rect(repaint);
124                }
125                else
126                        std::cout << "ERROR Repainting the bit " << row << "," << track << " failed!\n";
127        }
128}
129
130void PaperTapeView::queue_draw_row(row_t& row) {
131        cairo_rectangle_t repaint;
132        // paint only in valid range
133        if(row != LOCHSTREIFEN_NO_ROW) {
134                if(lochstreifen_get_target_rect_from_row(lochstreifen, row, &repaint)
135                   == LOCHSTREIFEN_SUCCESS)
136                        queue_draw_rect(repaint);
137                else   
138                        std::cout << "ERROR Repainting row " << row << " failed!\n";
139        }
140}
141
142bool PaperTapeView::on_motion_notify_event(GdkEventMotion* event) {
143        row_t new_row;
144        track_t new_track;
145        lochstreifen_get_target_bit_from_point(lochstreifen, &new_row, &new_track, event->x, event->y);
146
147        // repaint bits, if neccessary
148        if(new_track != just_hovered_track) {
149                // we have changed the track, queue a redraw for the old one
150                queue_draw_bit(just_hovered_row, just_hovered_track);
151       
152                // set the new one. If NO_TRACK or NO_ROW, this is the "no highlight"
153                // state, internally
154                lochstreifen_set_highlight_bit(lochstreifen, new_row, new_track);
155                std::cout << "Queue new draw row " << new_row << " bit " << new_track << "\n";
156                // redraw the new one. If NO_TRACK or NO_ROW, it won't be paint.
157                queue_draw_bit(new_row, new_track);
158               
159                // buffer hovered track for next mouse event
160                just_hovered_track = new_track;
161        } // bit
162       
163        // repaint the old row, if neccessary
164        if(new_row != just_hovered_row) {
165                // we have changed the row, repaint the old one (remove the highlight)
166                queue_draw_row(just_hovered_row);
167       
168                // if new_row is NO_ROW, this will simply remove the highlight
169                lochstreifen_set_highlight_row(lochstreifen, new_row);
170                // this will only repaint if it's a vaild row
171                queue_draw_row(new_row);
172
173                // buffer hovered row for next mouse event
174                just_hovered_row = new_row;
175        } // row
176
177        return true;
178}
179
180bool PaperTapeView::on_button_press_event(GdkEventButton* event) {
181        // mouse button pressed. (we could make another color ;-)
182        if(just_hovered_track != LOCHSTREIFEN_NO_TRACK) {
183                // we are on a bit, and the mouse button was pressed.
184                std::cout << "You are about to change byte " << just_hovered_row << ", bit " << just_hovered_track << "\n";
185               
186                // make a cool surface:
187                cairo_pattern_destroy(lochstreifen->highlight_bit_color);
188                lochstreifen->highlight_bit_color = cairo_pattern_create_rgb(0., 1., 0.);
189               
190                queue_draw_bit(just_hovered_row, just_hovered_track);
191        } else if(just_hovered_row != LOCHSTREIFEN_NO_ROW) {
192                // mouse pressed on a row, but not on Button
193                std::cout << "Begin selection\n";
194        }
195
196        return true;
197}
198
199bool PaperTapeView::on_button_release_event(GdkEventButton* event) {
200        // mouse button released.
201        if(just_hovered_track != LOCHSTREIFEN_NO_TRACK) {
202                // that's it. CHANGE THE DATA!
203                std::cout << "Triggered. Have toggled byte " << just_hovered_row << ", bit " << just_hovered_track << "\n";
204                controller->model->toggle_bit(just_hovered_row, just_hovered_track);
205        }
206
207        // reset pattern
208        cairo_pattern_destroy(lochstreifen->highlight_bit_color);
209        lochstreifen->highlight_bit_color = LOCHSTREIFEN_DEFAULT_HIGHLIGHT_BIT_COLOR;
210       
211        queue_draw_bit(just_hovered_row, just_hovered_track);
212
213        return true;
214}
215
216
217void PaperTapeView::export_image() {
218        std::cout << "Creating object:\n";
219        PaperTapeExporter program(*controller->parent_window, lochstreifen);
220        std::cout << "STARTING EXPORT\n";
221        if(program.run_export()) {
222                std::cout << "Export handled nicely\n";
223        }
224}
225
226Glib::RefPtr<ActionGroup> PaperTapeView::get_color_action_group() {
227        Glib::RefPtr<ActionGroup> group = ActionGroup::create("GtkPaperTapeViewColors");
228        // iterate the Colors
229        for(std::map<std::string,  Glib::RefPtr<PaperTapeColor> >::iterator i = colors.begin();
230            i != colors.end(); i++) {
231                std::cout << "Adding actions for " << i->first << "\n";
232                group->add(i->second);
233                if(i->second->is_switchable())
234                        group->add(i->second->get_toggle_action());
235        }
236
237/*
238        for(unsigned int i = 0; i < colors.size(); i++) {
239                group->add(colors[i]->get_color_action());
240                if(colors[i]->is_switchable())
241                        group->add(colors[i]->get_toggle_action());
242        }
243*/
244        return group;
245}
246
247void PaperTapeView::make_colors() {
248        // Make the color vector thing, for faster iteration
249        add_color("outer_background",
250                &lochstreifen->outer_background_color,
251                "Select background color",
252                "Color of the <b>background</b>",
253                "Display background"
254        );
255        add_color("papertape_background",
256                &lochstreifen->papertape_background_color,
257                "Select color of papertape",
258                "Color of the <b>papertape</b>",
259                "Display papertape sheet"
260        );
261        add_color("one_code_hole",
262                &lochstreifen->one_code_hole_color,
263                "Select color of punched holes (logical 1)",
264                "Color of <b>punched holes</b>\n(logical 1)",
265                "Display punched code holes"
266        );
267        add_color("zero_code_hole",
268                &lochstreifen->zero_code_hole_color,
269                "Select color of zero holes (logical 0)",
270                "Color of <b>zero holes</b>\n(logical 0)",
271                "Display zero code holes"
272        );
273        add_color("feed_hole",
274                &lochstreifen->feed_hole_color,
275                "Select color of feed holes",
276                "Color of <b>feed holes</b>",
277                "Display feed holes"
278        );
279        add_color("highlight_region",
280                &lochstreifen->highlight_region_color,
281                "Select color of highlighted regions (selections)",
282                "Color of <b>selections</b>"
283        );
284        add_color("highlight_row",
285                &lochstreifen->highlight_row_color,
286                "Select color of highlighted byte (hovered byte)",
287                "Color of <b>hovered bytes</b>"
288        );
289        add_color("highlight_bit",
290                &lochstreifen->highlight_bit_color,
291                "Select color of highlighted bit (hovered bit)",
292                "Color of <b>hovered bit</b>"
293        );
294}
295
296void PaperTapeView::add_color(const Glib::ustring& name, cairo_pattern_t** target, const Glib::ustring& dialog_title,
297   const Glib::ustring& menu_label, const Glib::ustring& toggle_label) {
298        colors[name] = PaperTapeColor::create(this, target,
299                name, dialog_title, menu_label, toggle_label);
300        colors[name]->signal_color_changed().connect(sigc::mem_fun(*this, &PaperTapeView::on_color_change));
301}
302
303void PaperTapeView::on_color_change(PaperTapeColor* name) {
304        std::cout << "PaperTapeView: Got a changed color!\n";
305        queue_draw();
306}
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