require 'erb'
require 'rabbit/dependency-canvas'
require 'rabbit/renderer/display/drawing-area-view-only'
require 'rabbit/renderer/display/hook-handler'
require 'rabbit/renderer/display/key-handler'
require 'rabbit/renderer/display/button-handler'
require 'rabbit/renderer/display/scroll-handler'
require 'rabbit/renderer/display/menu'
module Rabbit
class InfoWindow
include ERB::Util
include Renderer::Display::HookHandler
include Renderer::Display::KeyHandler
include Renderer::Display::ButtonHandler
include Renderer::Display::ScrollHandler
include Renderer::Display::Menu
def initialize(canvas)
@canvas = canvas
@window = nil
@timer_started = false
init_hook_handler
init_key_handler
init_button_handler
init_scroll_handler
end
def show(width=nil, height=nil)
init_gui(width, height)
@window.show_all
update_source
toggle_index_mode if @canvas.index_mode?
adjust_slide
end
def hide
return unless showing?
detach_menu(@window)
detach_key(@window)
each do |canvas|
canvas.detach
end
@window.signal_handler_disconnect(@window_destroy_id)
@window.destroy
@window = @window_destroy_id = nil
@canvas_widgets = @outer_box = nil
@timer_started = false
@previous_canvas = @current_canvas = @next_canvas = nil
end
def showing?
!@window.nil?
end
def moved(index)
return unless showing?
check_timer
update_note_text if on_note_mode?
adjust_slide(index)
end
def index_mode_on
return unless showing?
toggle_index_mode
end
def index_mode_off
return unless showing?
toggle_index_mode
end
private
def init_gui(width, height)
init_canvas
init_window(width, height)
end
def init_canvas
@current_canvas = make_canvas
@previous_canvas = make_canvas
@next_canvas = make_canvas
end
def make_canvas
DependencyCanvas.new(@canvas, @canvas.logger,
Renderer::Display::DrawingAreaViewOnly)
end
def init_window(width, height)
@window = Gtk::Window.new
@window_destroy_id = @window.signal_connect("destroy") do
@canvas.activate("ToggleInfoWindow")
end
@window.title = _("%s: Information window") % @canvas.title
@window.set_default_size(width, height) if width and height
if on_note_mode?
init_widgets_on_note_mode(width, height)
else
init_widgets(width, height)
end
init_menu
attach_key(@window)
attach_menu(@window)
event_mask = Gdk::Event::BUTTON_PRESS_MASK
event_mask |= Gdk::Event::BUTTON_RELEASE_MASK
event_mask |= Gdk::Event::BUTTON1_MOTION_MASK
event_mask |= Gdk::Event::BUTTON2_MOTION_MASK
event_mask |= Gdk::Event::BUTTON3_MOTION_MASK
@window.add_events(event_mask)
set_button_event(@window)
set_scroll_event(@window)
@window.add(@outer_box)
end
def init_widgets(width, height)
init_timer_label(width * (1.0 / 3.0), height * (1.0 / 3.0))
@outer_box = Gtk::VBox.new
current_box = Gtk::HBox.new
@current_canvas.attach_to(nil, @window, current_box) do |container, widget|
widget.set_size_request(width * (2.0 / 3.0), height * (2.0 / 3.0))
container.pack_start(widget, true, false)
end
@outer_box.pack_start(current_box, true, false)
bottom_box = Gtk::HBox.new
@previous_canvas.attach_to(nil, @window, bottom_box) do |container, widget|
widget.set_size_request(width * (1.0 / 3.0), height * (1.0 / 3.0))
container.pack_start(widget, false, false)
end
bottom_box.pack_start(@timer_label, true, false)
@next_canvas.attach_to(nil, @window, bottom_box) do |container, widget|
widget.set_size_request(width * (1.0 / 3.0), height * (1.0 / 3.0))
container.pack_end(widget, false, false)
end
@outer_box.pack_end(bottom_box, false, false)
@outer_box.show
end
def init_widgets_on_note_mode(width, height)
init_timer_label(width * (1.0 / 5.0), height * (2.0 / 5.0))
init_note_text(width * (5.0 / 5.0), height * (3.0 / 5.0))
@outer_box = Gtk::VBox.new
current_box = Gtk::HBox.new
current_box.pack_start(@timer_label, false, false)
@previous_canvas.attach_to(nil, @window, current_box) do |container, widget|
widget.set_size_request(width * (1.0 / 5.0), height * (2.0 / 5.0))
container.pack_start(widget, true, true, 10)
end
@current_canvas.attach_to(nil, @window, current_box) do |container, widget|
widget.set_size_request(width * (2.0 / 5.0), height * (2.0 / 5.0))
container.pack_start(widget, true, true)
end
@next_canvas.attach_to(nil, @window, current_box) do |container, widget|
widget.set_size_request(width * (1.0 / 5.0), height * (2.0 / 5.0))
container.pack_end(widget, true, true, 10)
end
@outer_box.pack_start(current_box, false, false)
bottom_box = Gtk::HBox.new
bottom_box.pack_start(@note_label, false, true, 20)
@outer_box.pack_start(bottom_box, true, false)
@outer_box.show
end
def init_canvas_widgets
@canvas_widgets = Gtk::HBox.new
@current_canvas.attach_to(nil, @window, @canvas_widgets)
@next_canvas.attach_to(nil, @window, @canvas_widgets)
end
def init_timer_label(width, height)
@timer_label = Gtk::Label.new
@timer_label.justify = :center
@timer_label.markup = markupped_timer_label(width, height)
@timer_started = false
check_timer
end
def init_note_text(width, height)
@note_label = Gtk::Label.new
@note_label.justify = :left
@note_label.wrap = true
@note_label.markup = markupped_note_text(width, height)
@note_label.set_size_request(width, height)
end
def update_note_text
@note_label.markup = markupped_note_text
end
def check_timer
return if @timer_started
Gtk.timeout_add(1000) do
@timer_label.markup = markupped_timer_label if showing?
@timer_started = (showing? and @canvas.rest_time)
end
end
def markupped_timer_label(width=nil, height=nil)
width ||= @window.size[0] * (1.0 / 3.0)
height ||= @window.size[1] * (1.0 / 3.0)
attrs = {}
font_size = on_note_mode? ? 100 : 200
attrs["font_desc"] = ((height * font_size) / Pango::SCALE).to_s
rest_time = @canvas.rest_time
attrs["foreground"] = "red" if rest_time and rest_time < 0
"#{h timer_label}"
end
def timer_label
rest_time = @canvas.rest_time || @canvas.allotted_time
if rest_time
"%s%02d:%02d" % Utils.split_number_to_minute_and_second(rest_time)
else
_("unlimited")
end
end
def markupped_note_text(width=nil, height=nil)
height ||= @window.size[1] * (3.0 / 5.0)
if @canvas.current_slide["note"]
text = @canvas.current_slide["note"].gsub(/\\n/, "\n")
else
text = ""
end
attrs = {}
attrs["font_desc"] = ((height * 40) / Pango::SCALE).to_s
"#{text}"
end
def update_source
each do |canvas|
source = Source::Memory.new("UTF-8", @canvas.logger)
@canvas.source_force_modified(true) do |original_source|
source.source = original_source.read
source.base = original_source.base
end
canvas.parse(source)
end
end
def adjust_slide(base_index=nil)
base_index ||= @canvas.current_index
@previous_canvas.move_to_if_can([base_index - 1, 0].max)
@current_canvas.move_to_if_can(base_index)
@next_canvas.move_to_if_can([base_index + 1, @canvas.slide_size - 1].min)
end
def toggle_index_mode
each do |canvas|
canvas.toggle_index_mode
end
end
def each(&block)
[@previous_canvas, @current_canvas, @next_canvas].each(&block)
end
def on_note_mode?
@canvas.slides.any? {|slide| slide["note"]}
end
end
end