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

491f32
/* === S Y N F I G ========================================================= */
491f32
/*!	\file helpers.h
491f32
**	\brief Helpers Header
491f32
**
491f32
**	$Id$
491f32
**
491f32
**	\legal
491f32
**	......... ... 2018 Ivan Mahonin
491f32
**
491f32
**	This package is free software; you can redistribute it and/or
491f32
**	modify it under the terms of the GNU General Public License as
491f32
**	published by the Free Software Foundation; either version 2 of
491f32
**	the License, or (at your option) any later version.
491f32
**
491f32
**	This package is distributed in the hope that it will be useful,
491f32
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
491f32
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
491f32
**	General Public License for more details.
491f32
**	\endlegal
491f32
*/
491f32
/* ========================================================================= */
491f32
491f32
/* === S T A R T =========================================================== */
491f32
491f32
#ifndef __SYNFIG_HELPERS_H
491f32
#define __SYNFIG_HELPERS_H
491f32
491f32
/* === H E A D E R S ======================================================= */
491f32
491f32
#include <cassert></cassert>
491f32
491f32
#include <gtkmm adjustment.h=""></gtkmm>
491f32
aeb01c
#include <etl handle=""></etl>
491f32
#include <synfig real.h=""></synfig>
491f32
491f32
/* === M A C R O S ========================================================= */
491f32
491f32
/* === T Y P E D E F S ===================================================== */
491f32
491f32
/* === C L A S S E S & S T R U C T S ======================================= */
491f32
491f32
namespace studio {
491f32
aeb01c
aeb01c
class BoolLock {
aeb01c
private:
aeb01c
	bool &lock;
aeb01c
public:
aeb01c
	explicit BoolLock(bool &lock): lock(lock) { assert(!lock); lock = true; }
aeb01c
	~BoolLock() { lock = false; }
aeb01c
};
aeb01c
aeb01c
491f32
//! Temoraly freezes all notifications from Glib object
491f32
//! All notifications will raised immediately when FreezeNotify is destroyed
491f32
//! see: Glib::ObjectBase::freeze_notify(), Glib::ObjectBase::thaw_notify()
491f32
class FreezeNotify {
491f32
private:
491f32
	Glib::ObjectBase *obj;
491f32
	Glib::RefPtr<glib::objectbase> obj_ref;</glib::objectbase>
491f32
491f32
	// disable copying
491f32
	FreezeNotify(const FreezeNotify&): obj() { }
491f32
	FreezeNotify& operator=(const FreezeNotify&) { return *this; }
491f32
public:
491f32
	explicit FreezeNotify(Glib::ObjectBase &obj):
491f32
		obj(&obj)
491f32
		{ if (this->obj) this->obj->freeze_notify(); }
491f32
	explicit FreezeNotify(Glib::ObjectBase *obj):
491f32
		obj(obj)
491f32
		{ if (this->obj) this->obj->freeze_notify(); }
491f32
	explicit FreezeNotify(const Glib::RefPtr<glib::objectbase> &obj_ref):</glib::objectbase>
491f32
		obj(), obj_ref(obj_ref)
491f32
		{ if (this->obj_ref) this->obj_ref->freeze_notify(); }
491f32
	~FreezeNotify() {
491f32
		if (obj) obj->thaw_notify();
491f32
		if (obj_ref) obj_ref->thaw_notify();
491f32
	}
491f32
};
491f32
491f32
aeb01c
class AdjustmentGroup: public etl::shared_object {
aeb01c
public:
aeb01c
	typedef etl::handle<adjustmentgroup> Handle;</adjustmentgroup>
aeb01c
aeb01c
	struct Item {
aeb01c
		Glib::RefPtr<gtk::adjustment> adjustment;</gtk::adjustment>
aeb01c
		double origSize;
aeb01c
		sigc::connection connection_changed;
aeb01c
		sigc::connection connection_value_changed;
aeb01c
aeb01c
		Item(): origSize() { }
aeb01c
	};
aeb01c
	typedef std::list<item> List;</item>
aeb01c
aeb01c
private:
aeb01c
	List items;
aeb01c
	bool lock;
aeb01c
	sigc::connection connection_timeout;
aeb01c
aeb01c
	void changed(Glib::RefPtr<gtk::adjustment> adjustment);</gtk::adjustment>
aeb01c
	void set(double position, double size);
aeb01c
aeb01c
public:
aeb01c
	AdjustmentGroup();
aeb01c
	~AdjustmentGroup();
aeb01c
aeb01c
	void add(Glib::RefPtr<gtk::adjustment> adjustment);</gtk::adjustment>
aeb01c
	void remove(Glib::RefPtr<gtk::adjustment> adjustment);</gtk::adjustment>
aeb01c
};
aeb01c
aeb01c
491f32
class ConfigureAdjustment {
491f32
public:
491f32
	Glib::RefPtr<gtk::adjustment> adjustment;</gtk::adjustment>
491f32
	double value;
491f32
	double lower;
491f32
	double upper;
491f32
	double step_increment;
491f32
	double page_increment;
491f32
	double page_size;
491f32
491f32
	double precision;
491f32
a64bc0
private:
a64bc0
	// for compatibility with old gtk
a64bc0
	void emit_changed();
a64bc0
	void emit_value_changed();
a64bc0
a64bc0
public:
491f32
	explicit ConfigureAdjustment(const Glib::RefPtr<gtk::adjustment> &adjustment = Glib::RefPtr<gtk::adjustment>()):</gtk::adjustment></gtk::adjustment>
491f32
		adjustment(adjustment),
491f32
		value(),
491f32
		lower(),
491f32
		upper(),
491f32
		step_increment(),
491f32
		page_increment(),
491f32
		page_size(),
491f32
		precision()
491f32
		{ reset(); }
491f32
491f32
	~ConfigureAdjustment()
491f32
		{ cancel(); }
491f32
491f32
	bool is_equal(double a, double b)
491f32
		{ return fabs(b-a) <= precision; }
491f32
491f32
	ConfigureAdjustment& reset(const Glib::RefPtr<gtk::adjustment> &adjustment, double precision) {</gtk::adjustment>
491f32
		set_adjustment(adjustment);
491f32
		if (this->adjustment) {
491f32
			value          = this->adjustment->get_value();
491f32
			lower          = this->adjustment->get_lower();
491f32
			upper          = this->adjustment->get_upper();
491f32
			step_increment = this->adjustment->get_step_increment();
491f32
			page_increment = this->adjustment->get_page_increment();
491f32
			page_size      = this->adjustment->get_page_size();
491f32
		} else {
491f32
			value          = 0.0;
491f32
			lower          = 0.0;
491f32
			upper          = 0.0;
491f32
			step_increment = 0.0;
491f32
			page_increment = 0.0;
491f32
			page_size      = 0.0;
491f32
		}
491f32
		this->precision = precision;
491f32
		return *this;
491f32
	}
491f32
	ConfigureAdjustment& reset(double precision)
491f32
		{ return reset(adjustment, precision); }
491f32
	ConfigureAdjustment& reset()
491f32
		{ return reset(precision); }
491f32
491f32
	ConfigureAdjustment& set_adjustment(const Glib::RefPtr<gtk::adjustment> &x)</gtk::adjustment>
491f32
		{ if (&x != &adjustment) adjustment = x; return *this; }
491f32
	ConfigureAdjustment& set_precision(double x)
491f32
		{ precision = x; return *this; }
491f32
	ConfigureAdjustment& set_precision_high()
491f32
		{ precision = synfig::real_high_precision<double>(); return *this; }</double>
491f32
	ConfigureAdjustment& set_precision_normal()
491f32
		{ precision = synfig::real_precision<double>(); return *this; }</double>
491f32
	ConfigureAdjustment& set_precision_low()
491f32
		{ precision = synfig::real_low_precision<double>(); return *this; }</double>
491f32
491f32
	ConfigureAdjustment& set_value(double x)
491f32
		{ value = x; return *this; }
491f32
	ConfigureAdjustment& set_lower(double x)
491f32
		{ lower = x; return *this; }
491f32
	ConfigureAdjustment& set_upper(double x)
491f32
		{ upper = x; return *this; }
491f32
	ConfigureAdjustment& set_step_increment(double x)
491f32
		{ step_increment = x; return *this; }
491f32
	ConfigureAdjustment& set_page_increment(double x)
491f32
		{ page_increment = x; return *this; }
491f32
	ConfigureAdjustment& set_page_size(double x)
491f32
		{ page_size = x; return *this; }
491f32
aeb01c
	ConfigureAdjustment& adj_value(double x)
aeb01c
		{ value += x; return *this; }
aeb01c
	ConfigureAdjustment& adj_value_step(double x)
aeb01c
		{ value += x*step_increment; return *this; }
aeb01c
	ConfigureAdjustment& adj_value_page(double x)
aeb01c
		{ value += x*page_increment; return *this; }
aeb01c
491f32
	void finish() {
491f32
		assert(adjustment);
491f32
		if (!adjustment) return;
aeb01c
		double value = std::max(lower, std::min(upper - page_size, this->value));
491f32
		if ( !is_equal(lower,          adjustment->get_lower())
491f32
		  || !is_equal(upper,          adjustment->get_upper())
491f32
		  || !is_equal(step_increment, adjustment->get_step_increment())
491f32
		  || !is_equal(page_increment, adjustment->get_page_increment())
491f32
		  || !is_equal(page_size,      adjustment->get_page_size()) )
a64bc0
		{
491f32
			adjustment->configure(value, lower, upper, step_increment, page_increment, page_size);
a64bc0
			emit_changed();
a64bc0
		} else
a64bc0
		if (!is_equal(value, adjustment->get_value())) {
491f32
			adjustment->set_value(value);
a64bc0
			emit_value_changed();
a64bc0
		}
491f32
		adjustment.reset();
491f32
	}
491f32
491f32
	void cancel()
491f32
		{ adjustment.reset(); }
491f32
};
491f32
491f32
inline void configure_adjustment(
491f32
	const Glib::RefPtr<gtk::adjustment> &adjustment,</gtk::adjustment>
491f32
	double value,
491f32
	double lower,
491f32
	double upper,
491f32
	double step_increment,
491f32
	double page_increment,
491f32
	double page_size,
491f32
	double precision = 0.0 )
491f32
{
491f32
	ConfigureAdjustment(adjustment)
491f32
		.set_value(value)
491f32
		.set_lower(lower)
491f32
		.set_upper(upper)
491f32
		.set_step_increment(step_increment)
491f32
		.set_page_increment(page_increment)
491f32
		.set_page_size(page_size)
491f32
		.set_precision(precision)
491f32
		.finish();
491f32
}
491f32
491f32
491f32
}; // END of namespace studio
491f32
491f32
/* === E N D =============================================================== */
491f32
491f32
#endif