Guest User

Gergely Kontra

a guest
Apr 29th, 2008
214
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env ruby
  2.  
  3. require 'gtk2'
  4. require 'rational'
  5.  
  6. =begin
  7. A drawing area, which can be panned and zoomed.
  8. (requires rational)
  9. Panning is done with middle mouse drag, zooming is with the scrollwheel.
  10. To zoom only into x or y axis, hold down the shift or ctrl keys respectively.
  11. You must create the following method:
  12. expose_event event, cairo, coordinates
  13. where
  14. event is the expose event
  15. cairo is the cairo context
  16. coordinates is an array with the [xstart, ystart, xend, yend] coordinates
  17. =end
  18. class DragZoomDrawingArea < Gtk::DrawingArea
  19.     type_register
  20.  
  21.     def initialize
  22.         super
  23.  
  24.         @xscale = @yscale = 1.to_r
  25.         @xoffset = @yoffset = 0.to_r
  26.         @xscalestep = @yscalestep = 2.to_r
  27.         @drag_sig_handlers = []
  28.  
  29.         signal_connect('expose-event') {|widget, event|
  30.             cairo = window.create_cairo_context
  31.             cairo.scale(@xscale, @yscale)
  32.             cairo.translate(@xoffset, @yoffset)
  33.  
  34.             alloc = allocation
  35.             width, height = alloc.width, alloc.height
  36.  
  37.             xstart = (0.to_r - @xoffset) / @xscale
  38.             xend = (width.to_r - @xoffset) / @xscale
  39.  
  40.             ystart = (0.to_r - @yoffset) / @yscale
  41.             yend = (height.to_r - @yoffset) / @yscale
  42.  
  43.             expose_event widget, event, cairo, [xstart, ystart, xend, yend]
  44.             true
  45.         }
  46.  
  47.         signal_connect('scroll-event') {|widget, event|
  48.             do_xscale = do_yscale = true
  49.  
  50.             if event.state & Gdk::Window::ModifierType::SHIFT_MASK != 0
  51.                 do_yscale = false
  52.             end
  53.             if event.state & Gdk::Window::ModifierType::CONTROL_MASK != 0
  54.                 do_xscale = false
  55.             end
  56.  
  57.             xscale_old, yscale_old = @xscale, @yscale
  58.             case event.direction
  59.             when Gdk::EventScroll::DOWN
  60.                 @xscale /= @xscalestep if do_xscale
  61.                 @yscale /= @yscalestep if do_yscale
  62.             when Gdk::EventScroll::UP
  63.                 @xscale *= @xscalestep if do_xscale
  64.                 @yscale *= @yscalestep if do_yscale
  65.             end
  66.  
  67.             @xoffset = event.x.to_i.to_r / @xscale - (event.x.to_i / xscale_old - @xoffset)
  68.             @yoffset = event.y.to_i.to_r / @yscale - (event.y.to_i / yscale_old - @yoffset)
  69.             queue_draw
  70.         }
  71.  
  72.         @motion_cb = proc {|widget, event|
  73.             deltax, deltay = event.x.to_i.to_r - @startx.to_i, event.y.to_i.to_r - @starty.to_i
  74.             @xoffset += deltax / @xscale
  75.             @yoffset += deltay / @yscale
  76.             @startx, @starty = event.x, event.y
  77.             queue_draw
  78.         }
  79.  
  80.         signal_connect('button-press-event') {|widget, event|
  81.             if(event.button == 2)
  82.                 @startx, @starty = event.x, event.y
  83.                 @drag_sig_handlers << signal_connect('motion-notify-event', &@motion_cb)
  84.             end
  85.         }
  86.  
  87.         signal_connect('button-release-event') {|widget, event|
  88.             if(event.button == 2)
  89.                 @drag_sig_handlers.reject!{|s| signal_handler_disconnect(s); true}
  90.             end
  91.         }
  92.  
  93.         add_events(Gdk::Event::SCROLL_MASK |
  94.             Gdk::Event::BUTTON_PRESS_MASK |
  95.             Gdk::Event::BUTTON_RELEASE_MASK |
  96.             Gdk::Event::POINTER_MOTION_MASK)
  97.     end
  98. end
  99.  
  100. class MyWindow < Gtk::Window
  101.     def initialize
  102.         super('interactive graph')
  103.         set_size_request(500,500)
  104.         signal_connect("delete-event") { Gtk.main_quit;true }
  105.  
  106.  
  107.         drawing_area = DragZoomDrawingArea.new
  108.         def drawing_area.expose_event widget, event, cairo, disp
  109.             cairo.set_source_rgb(1,0,0)
  110.             cairo.rectangle(100, 100, 50, 50)
  111.             cairo.stroke
  112.         end
  113.         add(drawing_area)
  114.         show_all
  115.     end
  116. end
  117.  
  118. app = MyWindow.new
  119.  
  120. Gtk.main
  121.  
  122.  
RAW Paste Data