# Copyright (c) 2016 Ruby-GNOME2 Project Team
# This program is licenced under the same licence as Ruby-GNOME2.
#
=begin
= Drawing Area
GtkDrawingArea is a blank area where you can draw custom displays
of various kinds.
This demo has two drawing areas. The checkerboard area shows
how you can just draw something; all you have to do is write
a signal handler for "draw", as shown here.
The "scribble" area is a bit more advanced, and shows how to handle
events such as button presses and mouse motion. Click the mouse
and drag in the scribble area to draw squiggles. Resize the window
to clear the area.
=end
class DrawingareaDemo
def initialize(main_window)
@window = Gtk::Window.new(:toplevel)
@window.screen = main_window.screen
@window.title = "Drawing Area"
initialize_vbox
create_the_checkerboard_area
create_the_scribble_area
end
def run
if !@window.visible?
@window.show_all
else
@window.destroy
end
@window
end
private
def initialize_vbox
@vbox = Gtk::Box.new(:vertical, 8)
@vbox.margin = 16
@window.add(@vbox)
end
def create_da_in_frame(text)
label = Gtk::Label.new
label.set_markup(text, :use_underline => true)
@vbox.pack_start(label, :expand => false, :fill => false, :padding => 0)
frame = Gtk::Frame.new
frame.shadow_type = :in
@vbox.pack_start(frame, :expand => true, :fill => true, :padding => 0)
da = Gtk::DrawingArea.new
da.set_size_request(100, 100)
frame.add(da)
da
end
def checkerboard_draw(da, cr)
check_size = 10
spacing = 2
# At the start of a draw handler, a clip region has been set on
# the Cairo context, and the contents have been cleared to the
# widget's background color. The docs for
# gdk_window_begin_paint_region() give more details on how this
# works.
ycount = 0
xcount = 0
i = spacing
while i < da.allocated_width
j = spacing
ycount = xcount % 2 # start with even/odd depending on row
while j < da.allocated_height
if ycount % 2 == 0
cr.set_source_rgb(0.45777, 0, 0.45777)
else
cr.set_source_rgb(1, 1, 1)
end
# if we are outside the clip, this will do nothing
cr.rectangle(i, j, check_size, check_size)
cr.fill
j += check_size + spacing
ycount += 1
end
i += check_size + spacing
xcount += 1
end
end
def create_the_checkerboard_area
da = create_da_in_frame("Checkerboard pattern")
da.signal_connect "draw" do |widget, cr|
checkerboard_draw(widget, cr)
end
end
def scribble_configure_event(da)
@surface.destroy if @surface
@surface = da.window.create_similar_surface(Cairo::CONTENT_COLOR,
da.allocated_width,
da.allocated_height)
# initialize the surface to white
cr = Cairo::Context.new(@surface)
cr.set_source_rgb(1, 1, 1)
cr.paint
cr.destroy
# we have handled the configure event, no need to further processing
true
end
def scribble_draw(cr)
# Redraw the screen from the surface
cr.set_source(@surface, 0, 0)
cr.paint
false
end
def draw_brush(widget, x, y)
cr = Cairo::Context.new(@surface)
cr.rectangle(x - 3, y - 3, 6, 6)
cr.fill
cr.destroy
widget.queue_draw_area(x - 3, y - 3, 6, 6)
end
def scribble_button_press_event(da, event)
return false unless @surface
draw_brush(da, event.x, event.y) if event.button == Gdk::BUTTON_PRIMARY
true
end
def scribble_motion_notify_event(da, event)
return false unless @surface
_window, x, y, state = event.window.get_device_position(event.device)
if (state & Gdk::EventMask::BUTTON_PRESS_MASK.to_i).nonzero?
draw_brush(da, x, y)
end
true
end
def create_the_scribble_area
da = create_da_in_frame("Scribble area")
da.signal_connect "draw" do |_widget, cr|
scribble_draw(cr)
end
da.signal_connect "configure-event" do |widget|
scribble_configure_event(widget)
end
da.signal_connect "motion-notify-event" do |widget, event|
scribble_motion_notify_event(widget, event)
end
da.signal_connect "button-press-event" do |widget, event|
scribble_button_press_event(widget, event)
end
# da.events |= (Gdk::EventMask::LEAVE_NOTIFY_MASK |
# Gdk::EventMask::BUTTON_PRESS_MASK |
# Gdk::EventMask::POINTER_MOTION_MASK |
# Gdk::EventMask::POINTER_MOTION_HINT_MASK)
da.add_events([:leave_notify_mask, :button_press_mask,
:pointer_motion_mask, :pointer_motion_hint_mask])
end
end