Add DelayedCall and integrate it into navigator and histogram

- Rename `delayedconnection.h` to `delayed.h`
- Align `delayed_helper::apply()` with `std::apply()`
This commit is contained in:
Flössie
2020-08-08 11:18:56 +02:00
parent b7738afe22
commit f353df3d05
6 changed files with 203 additions and 91 deletions

View File

@@ -19,7 +19,7 @@
#pragma once
#include "editedstate.h"
#include "delayedconnection.h"
#include "delayed.h"
#include "guiutils.h"
class Adjuster;

View File

@@ -20,13 +20,136 @@
#pragma once
#include <cstddef>
#include <functional>
#include <tuple>
#include <glibmm/main.h>
#include <glibmm/signalproxy.h>
#include "../rtengine/noncopyable.h"
namespace delayed_helper
{
// C++14
// See https://gist.github.com/ntessore/dc17769676fb3c6daa1f
template<std::size_t... Is>
struct index_sequence
{
};
template<std::size_t N, std::size_t... Is>
struct make_index_sequence :
make_index_sequence<N-1, N-1, Is...>
{
};
template<std::size_t... Is>
struct make_index_sequence<0, Is...> :
index_sequence<Is...>
{
};
// C++17
// See https://aherrmann.github.io/programming/2016/02/28/unpacking-tuples-in-cpp14/
template<typename F, typename T, size_t... Is>
constexpr void apply_impl(F f, T t, index_sequence<Is...>)
{
f(std::get<Is>(t)...);
}
template <typename T, typename F>
constexpr void apply(F f, T t)
{
apply_impl(f, t, make_index_sequence<std::tuple_size<T>{}>{});
}
}
template<typename... Ts>
class DelayedConnection final
class DelayedCall final :
public rtengine::NonCopyable
{
public:
DelayedCall(std::function<void (Ts...)> _function, unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) :
function(_function),
min_delay_ms(_min_delay_ms),
max_delay_ms(_max_delay_ms)
{
}
DelayedCall(unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) :
DelayedCall({}, _min_delay_ms, _max_delay_ms)
{
}
void setFunction(std::function<void (Ts...)> function)
{
this->function = function;
}
void operator ()(Ts... ts)
{
if (!function) {
return;
}
if (!min_delay_ms) {
function(ts...);
return;
}
params = std::make_tuple(ts...);
min_timeout.disconnect();
min_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedCall::onMinTimeout), min_delay_ms);
if (max_delay_ms && !max_timeout.connected()) {
max_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &DelayedCall::onMaxTimeout), max_delay_ms);
}
}
void cancel()
{
min_timeout.disconnect();
max_timeout.disconnect();
}
private:
bool onMinTimeout()
{
max_timeout.disconnect();
if (function) {
delayed_helper::apply(function, params);
}
return false;
}
bool onMaxTimeout()
{
min_timeout.disconnect();
if (function) {
delayed_helper::apply(function, params);
}
return false;
}
std::function<void (Ts...)> function;
unsigned int min_delay_ms;
unsigned int max_delay_ms;
sigc::connection min_timeout;
sigc::connection max_timeout;
std::tuple<Ts...> params;
};
template<typename... Ts>
class DelayedConnection final :
public rtengine::NonCopyable
{
public:
DelayedConnection(unsigned int _min_delay_ms, unsigned int _max_delay_ms = 0) :
@@ -45,15 +168,11 @@ public:
void block(bool value = true)
{
signal.block(value);
min_timeout.block(value);
max_timeout.block(value);
}
void unblock()
{
signal.unblock();
min_timeout.unblock();
max_timeout.unblock();
}
void cancel()
@@ -96,52 +215,17 @@ private:
bool onMinTimeout()
{
max_timeout.disconnect();
apply(params, slot);
delayed_helper::apply(slot, params);
return false;
}
bool onMaxTimeout()
{
min_timeout.disconnect();
apply(params, slot);
delayed_helper::apply(slot, params);
return false;
}
// C++14
// See https://gist.github.com/ntessore/dc17769676fb3c6daa1f
template<std::size_t... Is>
struct index_sequence
{
};
template<std::size_t N, std::size_t... Is>
struct make_index_sequence :
make_index_sequence<N-1, N-1, Is...>
{
};
template<std::size_t... Is>
struct make_index_sequence<0, Is...> :
index_sequence<Is...>
{
};
// C++17
// See https://aherrmann.github.io/programming/2016/02/28/unpacking-tuples-in-cpp14/
template<typename T, class F, size_t... Is>
constexpr void apply_impl(T t, F f, index_sequence<Is...>)
{
f(std::get<Is>(t)...);
}
template <class T, class F>
constexpr void apply(T t, F f)
{
apply_impl(t, f, make_index_sequence<std::tuple_size<T>{}>{});
}
unsigned int min_delay_ms;
unsigned int max_delay_ms;

View File

@@ -32,7 +32,22 @@ using namespace rtengine;
//
//
// HistogramPanel
HistogramPanel::HistogramPanel ()
HistogramPanel::HistogramPanel() :
pointer_moved_delayed_call(
[this](bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int r, int g, int b)
{
if (!validPos) {
// do something to un-show vertical bars
histogramRGBArea->updateBackBuffer(-1, -1, -1);
} else {
// do something to show vertical bars
histogramRGBArea->updateBackBuffer(r, g, b, profile, profileW);
}
histogramRGBArea->queue_draw ();
},
50,
100
)
{
setExpandAlignProperties(this, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
set_name("HistogramPanel");
@@ -192,6 +207,8 @@ HistogramPanel::HistogramPanel ()
HistogramPanel::~HistogramPanel ()
{
pointer_moved_delayed_call.cancel();
delete redImage;
delete greenImage;
delete blueImage;
@@ -311,15 +328,7 @@ void HistogramPanel::setHistRGBInvalid ()
void HistogramPanel::pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw)
{
if (!validPos) {
// do something to un-show vertical bars
histogramRGBArea->updateBackBuffer(-1, -1, -1);
} else {
// do something to show vertical bars
histogramRGBArea->updateBackBuffer(r, g, b, profile, profileW);
}
histogramRGBArea->queue_draw ();
pointer_moved_delayed_call(validPos, profile, profileW, r, g, b);
}
/*
@@ -372,7 +381,6 @@ HistogramRGBArea::HistogramRGBArea () :
needLuma(options.histogramLuma), needChroma(options.histogramChroma), rawMode(options.histogramRAW),
showMode(options.histogramBar), barDisplayed(options.histogramBar), parent(nullptr)
{
get_style_context()->add_class("drawingarea");
set_name("HistogramRGBArea");

View File

@@ -24,6 +24,7 @@
#include <cairomm/cairomm.h>
#include "delayed.h"
#include "guiutils.h"
#include "pointermotionlistener.h"
@@ -180,6 +181,8 @@ private:
class HistogramPanel final : public Gtk::Grid, public PointerMotionListener, public DrawModeListener, public rtengine::NonCopyable
{
private:
DelayedCall<bool, Glib::ustring, Glib::ustring, int, int, int> pointer_moved_delayed_call;
protected:

View File

@@ -26,8 +26,50 @@
using namespace rtengine;
Navigator::Navigator () : currentRGBUnit(options.navRGBUnit), currentHSVUnit(options.navHSVUnit)
Navigator::Navigator() :
pointer_moved_delayed_call(50, 100),
currentRGBUnit(options.navRGBUnit),
currentHSVUnit(options.navHSVUnit)
{
pointer_moved_delayed_call.setFunction(
[this](bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b, bool isRaw)
{
if (!validPos) {
setInvalid (x, y);
} else {
Glib::ustring s1, s2, s3;
position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y));
getRGBText (r, g, b, s1, s2, s3, isRaw);
R->set_text (s1);
G->set_text (s2);
B->set_text (s3);
if (isRaw) {
H->set_text ("--");
S->set_text ("--");
V->set_text ("--");
LAB_L->set_text ("--");
LAB_A->set_text ("--");
LAB_B->set_text ("--");
} else {
float h, s, v;
float LAB_a, LAB_b, LAB_l;
Color::rgb2hsv01(r / 255.f, g / 255.f, b / 255.f, h, s, v);
getHSVText (h, s, v, s1, s2, s3);
H->set_text (s1);
S->set_text (s2);
V->set_text (s3);
Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works?
getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3);
LAB_L->set_text (s1);
LAB_A->set_text (s2);
LAB_B->set_text (s3);
}
}
}
);
set_label (M("MAIN_MSG_NAVIGATOR"));
Gtk::VBox* mbox = Gtk::manage (new Gtk::VBox ());
@@ -202,6 +244,11 @@ Navigator::Navigator () : currentRGBUnit(options.navRGBUnit), currentHSVUnit(opt
show_all ();
}
Navigator::~Navigator()
{
pointer_moved_delayed_call.cancel();
}
void Navigator::setInvalid (int fullWidth, int fullHeight)
{
if (fullWidth > 0 && fullHeight > 0) {
@@ -278,41 +325,7 @@ void Navigator::getLABText (float l, float a, float b, Glib::ustring &sL, Glib::
// if !validPos then x/y contain the full image size
void Navigator::pointerMoved (bool validPos, const Glib::ustring &profile, const Glib::ustring &profileW, int x, int y, int r, int g, int b, bool isRaw)
{
if (!validPos) {
setInvalid (x, y);
} else {
Glib::ustring s1, s2, s3;
position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y));
getRGBText (r, g, b, s1, s2, s3, isRaw);
R->set_text (s1);
G->set_text (s2);
B->set_text (s3);
if (isRaw) {
H->set_text ("--");
S->set_text ("--");
V->set_text ("--");
LAB_L->set_text ("--");
LAB_A->set_text ("--");
LAB_B->set_text ("--");
} else {
float h, s, v;
float LAB_a, LAB_b, LAB_l;
Color::rgb2hsv01(r / 255.f, g / 255.f, b / 255.f, h, s, v);
getHSVText (h, s, v, s1, s2, s3);
H->set_text (s1);
S->set_text (s2);
V->set_text (s3);
Color::rgb2lab01(profile, profileW, r / 255.f, g / 255.f, b / 255.f, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works?
getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3);
LAB_L->set_text (s1);
LAB_A->set_text (s2);
LAB_B->set_text (s3);
}
}
pointer_moved_delayed_call(validPos, profile, profileW, x, y, r, g, b, isRaw);
}
void Navigator::cycleUnitsRGB (GdkEventButton *event) {

View File

@@ -20,6 +20,7 @@
#include <gtkmm.h>
#include "delayed.h"
#include "options.h"
#include "pointermotionlistener.h"
@@ -33,6 +34,8 @@ class Navigator final :
typedef const double (*TMatrix)[3];
private:
DelayedCall<bool, Glib::ustring, Glib::ustring, int, int, int, int, int, bool> pointer_moved_delayed_call;
Options::NavigatorUnit currentRGBUnit;
Options::NavigatorUnit currentHSVUnit;
void cycleUnitsRGB (GdkEventButton *event);
@@ -53,7 +56,8 @@ protected:
public:
PreviewWindow* previewWindow;
Navigator ();
Navigator();
~Navigator() override;
// pointermotionlistener interface
// void pointerMoved (bool validPos, int x, int y, int r, int g, int b);