BugFix Color dialog ends properly

Changed multithreading mechanism to use color value from color dialog, avoiding to rely on the testing of future value.
This commit is contained in:
Bruno Herbelin
2024-12-21 19:55:00 +01:00
parent 22d9c41357
commit fc91a74d05
5 changed files with 72 additions and 69 deletions

View File

@@ -591,33 +591,18 @@ void DialogToolkit::ErrorDialog(const char* message)
// Color Picker Dialog common functions
//
bool DialogToolkit::ColorPickerDialog::busy_ = false;
DialogToolkit::ColorPickerDialog::ColorPickerDialog()
DialogToolkit::ColorPickerDialog::ColorPickerDialog(): busy_(false)
{
rgb_ = std::make_tuple(0.f, 0.f, 0.f);
}
bool DialogToolkit::ColorPickerDialog::closed()
void DialogToolkit::ColorPickerDialog::openColorDialog( std::function<void (std::tuple<float, float, float>)> func )
{
if ( !promises_.empty() ) {
// check that file dialog thread finished
if (promises_.back().wait_for(timeout) == std::future_status::ready ) {
// get the filename from this file dialog
rgb_ = promises_.back().get();
// done with this file dialog
promises_.pop_back();
busy_ = false;
return true;
}
}
return false;
}
DialogToolkit::ColorPickerDialog::instance().busy_ = true;
std::tuple<float, float, float> openColorDialog( std::tuple<float, float, float> rgb)
{
// default return value to given value (so Cancel does nothing)
std::tuple<float, float, float> ret = rgb;
bool changed = false;
std::tuple<float, float, float> rgb = DialogToolkit::ColorPickerDialog::instance().RGB();
#if USE_TINYFILEDIALOG
@@ -631,11 +616,12 @@ std::tuple<float, float, float> openColorDialog( std::tuple<float, float, float>
if ( NULL != tinyfd_colorChooser("Choose or pick a color", NULL, prev_color, ret_color) )
{
ret = { (float) ret_color[0] / 255.f, (float) ret_color[1] / 255.f, (float) ret_color[2] / 255.f};
changed = true;
}
#else
if (!gtk_init()) {
return ret;
return;
}
GtkWidget *dialog = gtk_color_chooser_dialog_new( "Choose or pick a color", NULL);
@@ -662,7 +648,8 @@ std::tuple<float, float, float> openColorDialog( std::tuple<float, float, float>
if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_OK ) {
gtk_color_chooser_get_rgba( GTK_COLOR_CHOOSER(dialog), &color );
ret = { color.red, color.green, color.blue};
rgb = { color.red, color.green, color.blue};
changed = true;
}
// remember position
@@ -674,14 +661,16 @@ std::tuple<float, float, float> openColorDialog( std::tuple<float, float, float>
#endif
return ret;
// call the function with the selected color
if (changed)
func(rgb);
DialogToolkit::ColorPickerDialog::instance().busy_ = false;
}
void DialogToolkit::ColorPickerDialog::open()
void DialogToolkit::ColorPickerDialog::open(std::function<void(std::tuple<float, float, float>)> func)
{
if ( !DialogToolkit::ColorPickerDialog::busy_ && promises_.empty() ) {
promises_.emplace_back( std::async(std::launch::async, openColorDialog, rgb_) );
busy_ = true;
}
if (!busy_)
// launch thread to get color from dialog
std::thread( openColorDialog, func ).detach();
}

View File

@@ -98,19 +98,30 @@ class ColorPickerDialog
{
protected:
std::tuple<float, float, float> rgb_;
std::vector< std::future< std::tuple<float, float, float> > > promises_;
static bool busy_;
std::atomic<bool> busy_;
// private function to open dialog
static void openColorDialog( std::function<void(std::tuple<float, float, float>)> func);
// Private Constructor
ColorPickerDialog();
ColorPickerDialog(ColorPickerDialog const& copy) = delete;
ColorPickerDialog& operator=(ColorPickerDialog const& copy) = delete;
public:
ColorPickerDialog();
void open();
bool closed();
static ColorPickerDialog& instance()
{
// The only instance
static ColorPickerDialog _instance;
return _instance;
}
void open( std::function<void(std::tuple<float, float, float>)> func);
inline bool busy() { return busy_; }
inline void setRGB(std::tuple<float, float, float> rgb) { rgb_ = rgb; }
inline std::tuple<float, float, float> RGB() const { return rgb_; }
static bool busy() { return busy_; }
};

View File

@@ -424,9 +424,6 @@ void DisplaysView::adaptGridToWindow(int w)
void DisplaysView::draw()
{
// White ballance color button
static DialogToolkit::ColorPickerDialog whitebalancedialog;
// draw all windows
int i = 0;
for (; i < Settings::application.num_output_windows; ++i) {
@@ -626,14 +623,24 @@ void DisplaysView::draw()
Settings::application.windows[1+current_window_].whitebalance.y,
Settings::application.windows[1+current_window_].whitebalance.z, 1.f),
ImGuiColorEditFlags_NoAlpha)) {
if ( DialogToolkit::ColorPickerDialog::busy()) {
if ( DialogToolkit::ColorPickerDialog::instance().busy()) {
Log::Warning("Close previously openned color picker.");
}
else {
whitebalancedialog.setRGB( std::make_tuple(Settings::application.windows[1+current_window_].whitebalance.x,
// prepare the color picker to start with white balance color
DialogToolkit::ColorPickerDialog::instance().setRGB( std::make_tuple(Settings::application.windows[1+current_window_].whitebalance.x,
Settings::application.windows[1+current_window_].whitebalance.y,
Settings::application.windows[1+current_window_].whitebalance.z) );
whitebalancedialog.open();
// declare function to be called
int w = 1+current_window_;
auto applyColor = [w](std::tuple<float, float, float> c) {
Settings::application.windows[w].whitebalance.x = std::get<0>(c);
Settings::application.windows[w].whitebalance.y = std::get<1>(c);
Settings::application.windows[w].whitebalance.z = std::get<2>(c);
};
// open dialog (starts a thread that will call the 'applyColor' function
DialogToolkit::ColorPickerDialog::instance().open( applyColor );
}
}
ImGui::PopFont();
@@ -700,14 +707,6 @@ void DisplaysView::draw()
}
ImGui::PopFont();
// get picked color if dialog finished
if (whitebalancedialog.closed()){
std::tuple<float, float, float> c = whitebalancedialog.RGB();
Settings::application.windows[1+current_window_].whitebalance.x = std::get<0>(c);
Settings::application.windows[1+current_window_].whitebalance.y = std::get<1>(c);
Settings::application.windows[1+current_window_].whitebalance.z = std::get<2>(c);
}
// display popup menu
if (show_window_menu_ && current_window_ > -1) {
ImGui::OpenPopup( "DisplaysOutputContextMenu" );

View File

@@ -1203,8 +1203,6 @@ void ImGuiVisitor::visit (AlphaFilter& f)
if ( m == AlphaFilter::ALPHA_CHROMAKEY || m == AlphaFilter::ALPHA_FILL)
{
static DialogToolkit::ColorPickerDialog colordialog;
// read color from filter
float color[3] = {filter_parameters["Red"], filter_parameters["Green"], filter_parameters["Blue"]};
@@ -1227,12 +1225,30 @@ void ImGuiVisitor::visit (AlphaFilter& f)
ImGui::SameLine(0, IMGUI_SAME_LINE);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::Button( ICON_FA_EYE_DROPPER " Open selector", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ){
if ( DialogToolkit::ColorPickerDialog::busy()) {
if ( DialogToolkit::ColorPickerDialog::instance().busy()) {
Log::Warning("Close previously openned color picker.");
}
else {
colordialog.setRGB( std::make_tuple(color[0], color[1], color[2]) );
colordialog.open();
// prepare the color picker to start with filter's color
DialogToolkit::ColorPickerDialog::instance().setRGB( std::make_tuple(color[0], color[1], color[2]) );
// declare function to be called
std::string msg = oss.str();
auto applyColor = [&f, msg]( std::tuple<float, float, float> c) {
f.setProgramParameter("Red", std::get<0>(c));
f.setProgramParameter("Green", std::get<1>(c));
f.setProgramParameter("Blue", std::get<2>(c));
char buf[1024];
ImFormatString(buf, IM_ARRAYSIZE(buf), "%scolor #%02X%02X%02X",
msg.c_str(),
ImClamp((int)ceil(255.f * std::get<0>(c)),0,255),
ImClamp((int)ceil(255.f * std::get<1>(c)),0,255),
ImClamp((int)ceil(255.f * std::get<2>(c)),0,255));
Action::manager().store(buf);
};
// open dialog (starts a thread that will callthe 'applyColor' function
DialogToolkit::ColorPickerDialog::instance().open( applyColor );
}
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
@@ -1244,18 +1260,6 @@ void ImGuiVisitor::visit (AlphaFilter& f)
Action::manager().store(oss.str());
}
// get picked color if dialog finished
if (colordialog.closed()){
std::tuple<float, float, float> c = colordialog.RGB();
f.setProgramParameter("Red", std::get<0>(c));
f.setProgramParameter("Green", std::get<1>(c));
f.setProgramParameter("Blue", std::get<2>(c));
char buf[64];
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp((int)ceil(255.f * std::get<0>(c)),0,255),
ImClamp((int)ceil(255.f * std::get<1>(c)),0,255), ImClamp((int)ceil(255.f * std::get<2>(c)),0,255));
oss << " Color " << buf;
Action::manager().store(oss.str());
}
}
// Luminance extra parameter
else {

View File

@@ -790,7 +790,7 @@ bool UserInterface::saveOrSaveAs(bool force_versioning)
bool UserInterface::TryClose()
{
// cannot close if a file dialog is pending
if (DialogToolkit::FileDialog::busy() || DialogToolkit::ColorPickerDialog::busy())
if (DialogToolkit::FileDialog::busy() || DialogToolkit::ColorPickerDialog::instance().busy())
return false;
// always stop all recordings and pending actions
@@ -902,7 +902,7 @@ void UserInterface::NewFrame()
}
// overlay to ensure file color dialog is closed after use
if (DialogToolkit::ColorPickerDialog::busy()){
if (DialogToolkit::ColorPickerDialog::instance().busy()){
if (!ImGui::IsPopupOpen("##ColorBusy"))
ImGui::OpenPopup("##ColorBusy");
if (ImGui::BeginPopup("##ColorBusy")) {