|
|
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
|