diff --git a/src/DialogToolkit.cpp b/src/DialogToolkit.cpp index 9e61084..18ae53f 100644 --- a/src/DialogToolkit.cpp +++ b/src/DialogToolkit.cpp @@ -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)> 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 openColorDialog( std::tuple rgb) -{ // default return value to given value (so Cancel does nothing) - std::tuple ret = rgb; + bool changed = false; + std::tuple rgb = DialogToolkit::ColorPickerDialog::instance().RGB(); #if USE_TINYFILEDIALOG @@ -631,11 +616,12 @@ std::tuple openColorDialog( std::tuple 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 openColorDialog( std::tuple 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 openColorDialog( std::tuple #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)> 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(); } - diff --git a/src/DialogToolkit.h b/src/DialogToolkit.h index cf0e0b1..79670fd 100644 --- a/src/DialogToolkit.h +++ b/src/DialogToolkit.h @@ -98,19 +98,30 @@ class ColorPickerDialog { protected: std::tuple rgb_; - std::vector< std::future< std::tuple > > promises_; - static bool busy_; + std::atomic busy_; + + // private function to open dialog + static void openColorDialog( std::function)> 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)> func); + + inline bool busy() { return busy_; } inline void setRGB(std::tuple rgb) { rgb_ = rgb; } inline std::tuple RGB() const { return rgb_; } - - static bool busy() { return busy_; } }; diff --git a/src/DisplaysView.cpp b/src/DisplaysView.cpp index 93adca9..a83ee3e 100644 --- a/src/DisplaysView.cpp +++ b/src/DisplaysView.cpp @@ -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 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 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" ); diff --git a/src/ImGuiVisitor.cpp b/src/ImGuiVisitor.cpp index 1d03f31..c7d2b26 100644 --- a/src/ImGuiVisitor.cpp +++ b/src/ImGuiVisitor.cpp @@ -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 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 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 { diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 7dadf03..5dcbb59 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -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")) {