Blame synfig-studio/src/gui/timemodel.h

6eb56a
/* === S Y N F I G ========================================================= */
6eb56a
/*!	\file timemodel.h
6eb56a
**	\brief TimeModel Header
6eb56a
**
6eb56a
**	$Id$
6eb56a
**
6eb56a
**	\legal
6eb56a
**	Copyright (c) 2004 Adrian Bentley
6eb56a
**	......... ... 2018 Ivan Mahonin
6eb56a
**
6eb56a
**	This package is free software; you can redistribute it and/or
6eb56a
**	modify it under the terms of the GNU General Public License as
6eb56a
**	published by the Free Software Foundation; either version 2 of
6eb56a
**	the License, or (at your option) any later version.
6eb56a
**
6eb56a
**	This package is distributed in the hope that it will be useful,
6eb56a
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
6eb56a
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6eb56a
**	General Public License for more details.
6eb56a
**	\endlegal
6eb56a
*/
6eb56a
/* ========================================================================= */
6eb56a
6eb56a
/* === S T A R T =========================================================== */
6eb56a
6eb56a
#ifndef __SYNFIG_TIMEMODEL_H
6eb56a
#define __SYNFIG_TIMEMODEL_H
6eb56a
6eb56a
/* === H E A D E R S ======================================================= */
6eb56a
6eb56a
#include <list></list>
6eb56a
6eb56a
#include <gtkmm adjustment.h=""></gtkmm>
6eb56a
6eb56a
#include <etl handle=""></etl>
6eb56a
6eb56a
#include <synfig real.h=""></synfig>
6eb56a
#include <synfig time.h=""></synfig>
6eb56a
6eb56a
/* === M A C R O S ========================================================= */
6eb56a
6eb56a
/* === T Y P E D E F S ===================================================== */
6eb56a
6eb56a
/* === C L A S S E S & S T R U C T S ======================================= */
6eb56a
6eb56a
namespace studio {
6eb56a
6eb56a
//! Sets up an adjustment that controls
6eb56a
//!  - full time track
6eb56a
//!  - visible part of time track (when it zoomed/scrolled)
6eb56a
//!  - playing bounds at time track
6eb56a
class TimeModel: public etl::shared_object, public sigc::trackable
6eb56a
{
6eb56a
private:
c35ed2
	bool in_sync;
c35ed2
6eb56a
	float fps;
6eb56a
	bool play_bounds_enabled;
6eb56a
	bool play_repeat;
6eb56a
	synfig::Time time;
6eb56a
	synfig::Time play_time;
6eb56a
	synfig::Time lower;
6eb56a
	synfig::Time upper;
6eb56a
	synfig::Time visible_lower;
6eb56a
	synfig::Time visible_upper;
6eb56a
	synfig::Time play_bounds_lower;
6eb56a
	synfig::Time play_bounds_upper;
6eb56a
6eb56a
	Glib::RefPtr<gtk::adjustment> full_time_adjustment_;</gtk::adjustment>
6eb56a
	Glib::RefPtr<gtk::adjustment> scroll_time_adjustment_;</gtk::adjustment>
6eb56a
	Glib::RefPtr<gtk::adjustment> play_bounds_adjustment_;</gtk::adjustment>
6eb56a
6dfc9f
	sigc::signal<void> signal_bounds_changed_;</void>
6eb56a
	sigc::signal<void> signal_visible_changed_;</void>
6eb56a
	sigc::signal<void> signal_play_bounds_changed_;</void>
6eb56a
	sigc::signal<void> signal_time_changed_;</void>
6eb56a
	sigc::signal<void> signal_play_time_changed_;</void>
6dfc9f
	sigc::signal<void> signal_changed_;</void>
6eb56a
6eb56a
	void on_changed(Glib::RefPtr<gtk::adjustment> *source);</gtk::adjustment>
6eb56a
	void on_value_changed(Glib::RefPtr<gtk::adjustment> *source);</gtk::adjustment>
6eb56a
6eb56a
	//! put internal values to adjustments and emit the adjustments signals if need
6eb56a
	void sync();
6eb56a
6eb56a
	// all parameters will be edited infide functions so pass them by copy instead of const reference
6eb56a
	bool set_time_silent(synfig::Time time, bool *is_play_time_changed);
6eb56a
	bool set_bounds_silent(synfig::Time lower, synfig::Time upper, float fps);
6eb56a
	bool set_visible_bounds_silent(synfig::Time lower, synfig::Time upper);
6eb56a
	bool set_play_bounds_silent(synfig::Time lower, synfig::Time upper, bool enabled, bool repeat);
6eb56a
6eb56a
public:
6eb56a
	TimeModel();
6eb56a
6eb56a
	float get_frame_rate() const { return fps; }
6eb56a
	synfig::Time round_time(const synfig::Time &time) const
6eb56a
		{ return get_frame_rate() ? time.round(get_frame_rate()) : time; }
6eb56a
6eb56a
	const synfig::Time& get_time() const { return time; }
6eb56a
	const synfig::Time& get_play_time() const { return play_time; } //!< time clamped by playing bounds
6eb56a
	void set_time(const synfig::Time &time) {
6eb56a
		bool is_play_time_changed = false;
6eb56a
		if (set_time_silent(time, &is_play_time_changed)) time_changed();
6eb56a
		if (is_play_time_changed) play_time_changed();
6eb56a
	}
6eb56a
6eb56a
	bool almost_equal(const synfig::Time &a, const synfig::Time &b, const synfig::Time &range = synfig::Time()) const;
6eb56a
	bool almost_equal_to_current(const synfig::Time &time, const synfig::Time &range = synfig::Time()) const
6eb56a
		{ return almost_equal(get_time(), time, range); }
6eb56a
6eb56a
	const synfig::Time& get_lower() const { return lower; }
6eb56a
	const synfig::Time& get_upper() const { return upper; }
6eb56a
	void set_bounds(const synfig::Time &lower, const synfig::Time &upper, float fps)
6dfc9f
		{ if (set_bounds_silent(lower, upper, fps)) bounds_changed(); }
6eb56a
6eb56a
	const synfig::Time& get_visible_lower() const { return visible_lower; }
6eb56a
	const synfig::Time& get_visible_upper() const { return visible_upper; }
6eb56a
	void set_visible_bounds(const synfig::Time &lower, const synfig::Time &upper)
6eb56a
		{ if (set_visible_bounds_silent(lower, upper)) visible_changed(); }
6eb56a
6eb56a
	synfig::Real get_zoom() const;
6eb56a
	void set_zoom(synfig::Real x, const synfig::Time ¢er);
6eb56a
	void zoom(synfig::Real x, const synfig::Time ¢er); //!< relative zoom in/out
6eb56a
b440da
	synfig::Time get_frame_duration() const; //!< duration of one frame
6eb56a
	synfig::Time get_page_increment() const; //!< depends on visible duration
b440da
	synfig::Time get_step_increment() const
b440da
		{ return get_frame_duration(); }
6eb56a
	synfig::Time get_page_size() const //!< visible duration
6eb56a
		{ return get_visible_upper() - get_visible_lower(); }
6eb56a
	synfig::Time get_size() const //!< full duration
6eb56a
		{ return round_time(get_upper() - get_lower()); }
6eb56a
6eb56a
	synfig::Time get_visible_center() const
6eb56a
		{ return (get_visible_lower() + get_visible_upper())*0.5; }
6eb56a
	void set_zoom(synfig::Real x)
6eb56a
		{ set_zoom(x, get_visible_center()); }
6eb56a
	void zoom(synfig::Real x) //!< relative zoom in/out
6eb56a
		{ zoom(x, get_visible_center()); }
6eb56a
6eb56a
	void move_to(const synfig::Time &time) //!< absolute scroll
6eb56a
		{ set_visible_bounds(time, time + get_page_size()); }
6eb56a
	void move_by(const synfig::Time &time) //!< relative scroll
6eb56a
		{ move_to(get_visible_lower() + time); }
6eb56a
6eb56a
	bool get_play_bounds_enabled() const { return play_bounds_enabled; }
6eb56a
	bool get_play_repeat() const { return play_repeat;}
6eb56a
	const synfig::Time& get_play_bounds_lower() const { return play_bounds_lower; }
6eb56a
	const synfig::Time& get_play_bounds_upper() const { return play_bounds_upper; }
6eb56a
	void set_play_bounds_enabled(bool enabled);
6eb56a
	void set_play_repeat(bool repeat);
6eb56a
	void set_play_bounds_lower(const synfig::Time &lower); //!< upper bound will be fixed to be >= (lower + two frames)
6eb56a
	void set_play_bounds_upper(const synfig::Time &upper); //!< lower bound will be fixed to be <= (upper - two frames)
6eb56a
	void set_play_bounds(const synfig::Time &lower, const synfig::Time &upper, bool enabled, bool repeat) //!< duration will be fixed to be >= two frames
6eb56a
		{ if (set_play_bounds_silent(lower, upper, enabled, repeat)) play_bounds_changed(); }
6eb56a
	void set_play_bounds(const synfig::Time &lower, const synfig::Time &upper, bool enabled)
6eb56a
		{ set_play_bounds(lower, upper, enabled, get_play_repeat()); }
6eb56a
	void set_play_bounds(const synfig::Time &lower, const synfig::Time &upper)
6eb56a
		{ set_play_bounds(lower, upper, get_play_bounds_enabled()); }
6eb56a
	void set_play_bounds_lower_to_current()
6eb56a
		{ set_play_bounds_lower(get_time()); }
6eb56a
	void set_play_bounds_upper_to_current()
6eb56a
		{ set_play_bounds_upper(get_time()); }
6eb56a
6eb56a
	//! returns play_time if play bounds is enabled, in other case returns time
6eb56a
	const synfig::Time& get_actual_play_time() const
6eb56a
		{ return get_play_bounds_enabled() ? get_play_time() : get_time(); }
6eb56a
	//! returns play_bounds_lower if play bounds is enabled, in other case returns lower
6eb56a
	const synfig::Time& get_actual_play_bounds_lower() const
6eb56a
		{ return get_play_bounds_enabled() ? get_play_bounds_lower() : get_lower(); }
6eb56a
	//! returns play_bounds_upper if play bounds is enabled, in other case returns upper
6eb56a
	const synfig::Time& get_actual_play_bounds_upper() const
6eb56a
		{ return get_play_bounds_enabled() ? get_play_bounds_upper() : get_upper(); }
6eb56a
6eb56a
	const Glib::RefPtr<gtk::adjustment>& full_time_adjustment()    { return full_time_adjustment_; }</gtk::adjustment>
6eb56a
	const Glib::RefPtr<gtk::adjustment>& scroll_time_adjustment()  { return scroll_time_adjustment_; }</gtk::adjustment>
6eb56a
	const Glib::RefPtr<gtk::adjustment>& play_bounds_adjustment()  { return play_bounds_adjustment_; }</gtk::adjustment>
6eb56a
6dfc9f
	sigc::signal<void> signal_bounds_changed()      { return signal_bounds_changed_; }      // raises on bounds changed</void>
6dfc9f
	sigc::signal<void> signal_visible_changed()     { return signal_visible_changed_; }     // raises on visible bounds changed</void>
6dfc9f
	sigc::signal<void> signal_play_bounds_changed() { return signal_play_bounds_changed_; } // raises on play bounsd changed</void>
6dfc9f
	sigc::signal<void> signal_time_changed()        { return signal_time_changed_; }        // raises on current time changed</void>
6dfc9f
	sigc::signal<void> signal_play_time_changed()   { return signal_play_time_changed_; }   // raises on play time changed</void>
6dfc9f
6dfc9f
	sigc::signal<void> signal_changed()             { return signal_changed_; }             // raises on any change</void>
6dfc9f
6dfc9f
	void bounds_changed() {
6dfc9f
		sync();
6dfc9f
		signal_bounds_changed()();
6dfc9f
		visible_changed();
6dfc9f
		play_bounds_changed();
6dfc9f
		time_changed();
6dfc9f
		signal_changed()();
6dfc9f
	}
6dfc9f
6dfc9f
	void visible_changed() {
6dfc9f
		sync();
6dfc9f
		signal_visible_changed()();
6dfc9f
		signal_changed()();
6dfc9f
	}
6dfc9f
6dfc9f
	void play_bounds_changed() {
6dfc9f
		sync();
6dfc9f
		signal_play_bounds_changed()();
6dfc9f
		play_time_changed();
6dfc9f
		signal_changed()();
6dfc9f
	}
6dfc9f
6dfc9f
	void time_changed() {
6dfc9f
		sync();
6dfc9f
		signal_time_changed()();
6dfc9f
		signal_changed()();
6dfc9f
	}
6dfc9f
6dfc9f
	void play_time_changed() {
6dfc9f
		sync();
6dfc9f
		signal_play_time_changed()();
6dfc9f
		signal_changed()();
6dfc9f
	}
6dfc9f
6dfc9f
	void all_changed()
6dfc9f
		{ bounds_changed(); }
6eb56a
};
6eb56a
6eb56a
}; // END of namespace studio
6eb56a
6eb56a
/* === E N D =============================================================== */
6eb56a
6eb56a
#endif