/* timeline-ruler.cpp - Implementation of the time ruler widget Copyright (C) Lumiera.org 2008, Joel Holdsworth This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************/ #include #include "timeline-ruler.hpp" #include "../../window-manager.hpp" extern "C" { #include "../../../lib/time.h" } using namespace Gtk; using namespace Cairo; using namespace std; using namespace lumiera::gui; using namespace lumiera::gui::widgets; using namespace lumiera::gui::widgets::timeline; namespace lumiera { namespace gui { namespace widgets { namespace timeline { TimelineRuler::TimelineRuler() : Glib::ObjectBase("TimelineRuler"), timeOffset(0), timeScale(1), mouseChevronTime(0), annotationHorzMargin(0), annotationVertMargin(0), majorTickHeight(0), minorLongTickHeight(0), minorShortTickHeight(0), minDivisionWidth(100), mouseChevronSize(0) { // Install style properties register_styles(); } void TimelineRuler::set_time_offset(gavl_time_t time_offset) { timeOffset = time_offset; rulerImage.clear(); queue_draw(); } void TimelineRuler::set_time_scale(int64_t time_scale) { REQUIRE(time_scale > 0); timeScale = time_scale; rulerImage.clear(); queue_draw(); } void TimelineRuler::set_mouse_chevron_time(gavl_time_t time) { mouseChevronTime = time; queue_draw(); } void TimelineRuler::on_realize() { Widget::on_realize(); // Set event notifications add_events(Gdk::POINTER_MOTION_MASK); // Load styles read_styles(); } bool TimelineRuler::on_expose_event(GdkEventExpose* event) { REQUIRE(event != NULL); // This is where we draw on the window Glib::RefPtr window = get_window(); if(!window) return false; // Prepare to render via cairo const Allocation allocation = get_allocation(); Cairo::RefPtr cairo = window->create_cairo_context(); REQUIRE(cairo); // Draw the ruler if(!rulerImage) { // We have no cached rendering - it must be redrawn // but do we need ro allocate a new image? if(!rulerImage || rulerImage->get_width() != allocation.get_width() || rulerImage->get_height() != allocation.get_height()) rulerImage = ImageSurface::create(FORMAT_RGB24, allocation.get_width(), allocation.get_height()); ENSURE(rulerImage); Cairo::RefPtr image_cairo = Context::create(rulerImage); ENSURE(image_cairo); draw_ruler(image_cairo, allocation); } // Draw the cached ruler image cairo->set_source(rulerImage, 0, 0); cairo->paint(); // Draw the mouse chevron draw_mouse_chevron(cairo, allocation); return true; } bool TimelineRuler::on_motion_notify_event(GdkEventMotion *event) { REQUIRE(event != NULL); set_mouse_chevron_time(event->x * timeScale + timeOffset); return true; } void TimelineRuler::on_size_request (Gtk::Requisition *requisition) { REQUIRE(requisition != NULL); // Initialize the output parameter *requisition = Gtk::Requisition(); requisition->width = 0; get_style_property("height", requisition->height); } void TimelineRuler::on_size_allocate(Gtk::Allocation& allocation) { Widget::on_size_allocate(allocation); rulerImage.clear(); // The widget has changed size - redraw } void TimelineRuler::draw_ruler(Cairo::RefPtr cairo, Gdk::Rectangle ruler_rect) { REQUIRE(cairo); REQUIRE(ruler_rect.get_width() > 0); REQUIRE(ruler_rect.get_height() > 0); // Preparation steps const int height = ruler_rect.get_height(); Glib::RefPtr pango_layout = create_pango_layout(""); Glib::RefPtr