diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 76bf2794a..3f1fba8e6 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -497,8 +497,11 @@ EditorPanel::EditorPanel (FilePanel* filePanel) // build GUI // build left side panel - leftbox = new Gtk::VBox (); - leftbox->set_size_request (230, 250); + leftbox = new Gtk::Paned (Gtk::ORIENTATION_VERTICAL); + + // make a subbox to allow resizing of the histogram (if it's on the left) + leftsubbox = new Gtk::Box (Gtk::ORIENTATION_VERTICAL); + leftsubbox->set_size_request (230, 250); histogramPanel = nullptr; @@ -507,19 +510,21 @@ EditorPanel::EditorPanel (FilePanel* filePanel) ppframe->set_name ("ProfilePanel"); ppframe->add (*profilep); ppframe->set_label (M ("PROFILEPANEL_LABEL")); - //leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); + //leftsubbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4); navigator = Gtk::manage (new Navigator ()); navigator->previewWindow->set_size_request (-1, 150); - leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 2); + leftsubbox->pack_start (*navigator, Gtk::PACK_SHRINK, 2); history = Gtk::manage (new History ()); - leftbox->pack_start (*history); + leftsubbox->pack_start (*history); - leftbox->show_all (); + leftsubbox->show_all (); + + leftbox->pack2 (*leftsubbox, true, true); // build the middle of the screen - Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ()); + Gtk::Box* editbox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_VERTICAL)); info = Gtk::manage (new Gtk::ToggleButton ()); Gtk::Image* infoimg = Gtk::manage (new RTImage ("info.png")); @@ -590,7 +595,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) tpc->setEditProvider (iareapanel->imageArea); tpc->getToolBar()->setLockablePickerToolListener (iareapanel->imageArea); - Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); + Gtk::Box* toolBarPanel = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL)); toolBarPanel->set_name ("EditorTopPanel"); toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2); @@ -617,10 +622,10 @@ EditorPanel::EditorPanel (FilePanel* filePanel) toolBarPanel->pack_end (*iareapanel->imageArea->previewModePanel, Gtk::PACK_SHRINK, 0); toolBarPanel->pack_end (*vsepz4, Gtk::PACK_SHRINK, 2); - afterBox = Gtk::manage (new Gtk::VBox ()); + afterBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_VERTICAL)); afterBox->pack_start (*iareapanel); - beforeAfterBox = Gtk::manage (new Gtk::HBox()); + beforeAfterBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL)); beforeAfterBox->set_name ("BeforeAfterContainer"); beforeAfterBox->pack_start (*afterBox); @@ -628,12 +633,16 @@ EditorPanel::EditorPanel (FilePanel* filePanel) editbox->pack_start (*beforeAfterBox); // build right side panel - vboxright = new Gtk::VBox (false, 0); - vboxright->set_size_request (300, 250); + vboxright = new Gtk::Paned (Gtk::ORIENTATION_VERTICAL); + + vsubboxright = new Gtk::Box (Gtk::ORIENTATION_VERTICAL, 0); + vsubboxright->set_size_request (300, 250); - vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 2); + vsubboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 2); // main notebook - vboxright->pack_start (*tpc->toolPanelNotebook); + vsubboxright->pack_start (*tpc->toolPanelNotebook); + + vboxright->pack2 (*vsubboxright, true, true); // Save buttons Gtk::Grid *iops = new Gtk::Grid (); @@ -769,8 +778,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) hpanedl->set_position (options.historyPanelWidth); } - - Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned()); + Gtk::Paned *viewpaned = Gtk::manage (new Gtk::Paned (Gtk::ORIENTATION_VERTICAL)); fPanel = filePanel; if (filePanel) { @@ -886,7 +894,9 @@ EditorPanel::~EditorPanel () delete tpc; delete ppframe; + delete leftsubbox; delete leftbox; + delete vsubboxright; delete vboxright; //delete saveAsDialog; @@ -2165,7 +2175,7 @@ void EditorPanel::beforeAfterToggled () tbBeforeLock = Gtk::manage (new Gtk::ToggleButton ()); tbBeforeLock->set_tooltip_markup (M ("MAIN_TOOLTIP_BEFOREAFTERLOCK")); tbBeforeLock->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbBeforeLock_toggled) ); - beforeHeaderBox = Gtk::manage (new Gtk::HBox ()); + beforeHeaderBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL)); beforeHeaderBox->pack_end (*tbBeforeLock, Gtk::PACK_SHRINK, 2); beforeHeaderBox->pack_end (*beforeLabel, Gtk::PACK_SHRINK, 2); beforeHeaderBox->set_size_request (0, HeaderBoxHeight); @@ -2179,7 +2189,7 @@ void EditorPanel::beforeAfterToggled () afterLabel = Gtk::manage (new Gtk::Label ()); afterLabel->set_markup (Glib::ustring ("") + M ("GENERAL_AFTER") + ""); - afterHeaderBox = Gtk::manage (new Gtk::HBox ()); + afterHeaderBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL)); afterHeaderBox->set_size_request (0, HeaderBoxHeight); afterHeaderBox->pack_end (*afterLabel, Gtk::PACK_SHRINK, 2); afterBox->pack_start (*afterHeaderBox, Gtk::PACK_SHRINK, 2); @@ -2321,17 +2331,16 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) if (oldPosition == 0) { // There was no Histogram before, so we create it histogramPanel = Gtk::manage (new HistogramPanel ()); - leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + leftbox->pack1(*histogramPanel, true, false); } else if (oldPosition == 2) { // The histogram was on the right side, so we move it to the left histogramPanel->reference(); removeIfThere (vboxright, histogramPanel, false); - leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + leftbox->pack1(*histogramPanel, true, false); histogramPanel->unreference(); } histogramPanel->reorder (Gtk::POS_LEFT); - leftbox->reorder_child (*histogramPanel, 0); break; case 2: @@ -2341,17 +2350,16 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) if (oldPosition == 0) { // There was no Histogram before, so we create it histogramPanel = Gtk::manage (new HistogramPanel ()); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + vboxright->pack1 (*histogramPanel, true, false); } else if (oldPosition == 1) { // The histogram was on the left side, so we move it to the right histogramPanel->reference(); removeIfThere (leftbox, histogramPanel, false); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + vboxright->pack1 (*histogramPanel, true, false); histogramPanel->unreference(); } histogramPanel->reorder (Gtk::POS_RIGHT); - vboxright->reorder_child (*histogramPanel, 0); break; } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 7876d18e1..054ad0a6b 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -173,8 +173,10 @@ private: Gtk::Image *iShowHideSidePanels; Gtk::Image *iShowHideSidePanels_exit; Gtk::Image *iBeforeLockON, *iBeforeLockOFF; - Gtk::VBox *leftbox; - Gtk::VBox *vboxright; + Gtk::Paned *leftbox; + Gtk::Box *leftsubbox; + Gtk::Paned *vboxright; + Gtk::Box *vsubboxright; Gtk::Button* queueimg; Gtk::Button* saveimgas; @@ -191,13 +193,13 @@ private: PreviewHandler* beforePreviewHandler; // for the before-after view Navigator* navigator; ImageAreaPanel* beforeIarea; // for the before-after view - Gtk::VBox* beforeBox; - Gtk::VBox* afterBox; + Gtk::Box* beforeBox; + Gtk::Box* afterBox; Gtk::Label* beforeLabel; Gtk::Label* afterLabel; - Gtk::HBox* beforeAfterBox; - Gtk::HBox* beforeHeaderBox; - Gtk::HBox* afterHeaderBox; + Gtk::Box* beforeAfterBox; + Gtk::Box* beforeHeaderBox; + Gtk::Box* afterHeaderBox; Gtk::ToggleButton* toggleHistogramProfile; Gtk::Frame* ppframe; diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 9856462b2..65384d75a 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -39,9 +39,9 @@ extern Options options; HistogramPanel::HistogramPanel () { - set_vexpand(false); + set_vexpand(true); set_hexpand(true); - set_valign(Gtk::ALIGN_START); + set_valign(Gtk::ALIGN_FILL); set_halign(Gtk::ALIGN_FILL); set_name("HistogramPanel"); @@ -464,10 +464,10 @@ void HistogramRGBArea::get_preferred_height_for_width_vfunc (int width, int &min { int bHeight = width / 30; - if (bHeight > 10) { - bHeight = 10; // it would be useful to scale this based on display dpi - } else if (bHeight < 5 ) { - bHeight = 5; + if (bHeight > 15) { + bHeight = 15; + } else if (bHeight < 10 ) { + bHeight = 10; } minimum_height = bHeight; @@ -721,19 +721,15 @@ HistogramArea::~HistogramArea () } } -/* Note: best case scenario would be to have the histogram size really flexible - by being able to resize the panel vertically, and the side-bar horizontally. - We would only need to enforce some lower limits then. */ - Gtk::SizeRequestMode HistogramArea::get_request_mode_vfunc () const { - return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; + return Gtk::SIZE_REQUEST_CONSTANT_SIZE; } void HistogramArea::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const { int minimumWidth = 0; - int naturalWidth = 0; // unused? + int naturalWidth = 0; get_preferred_width_vfunc (minimumWidth, naturalWidth); get_preferred_height_for_width_vfunc (minimumWidth, minimum_height, natural_height); } @@ -745,16 +741,8 @@ void HistogramArea::get_preferred_width_vfunc (int &minimum_width, int &natural_ } void HistogramArea::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const -{ - /*int gHeight = width / 2; - - if (gHeight > 150) { - gHeight = 150; - } else if (gHeight < 100) { - gHeight = 100; - }*/ - - int gHeight = width; // aspect ratio 1:1 should fit on most monitors +{ + int gHeight = width * 0.618; if (gHeight < 100) { gHeight = 100; } @@ -763,7 +751,6 @@ void HistogramArea::get_preferred_height_for_width_vfunc (int width, int &minimu natural_height = gHeight; } -//unused? void HistogramArea::get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const { get_preferred_width_vfunc (minimum_width, natural_width); @@ -918,67 +905,53 @@ void HistogramArea::updateBackBuffer () cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); cr->set_line_width (1.0); - cr->set_operator(Cairo::OPERATOR_ADD); + cr->set_operator(Cairo::OPERATOR_SOURCE); int ui = 0, oi = 0; - if (needBlue) { - drawCurve(cr, bhchanged, realhistheight, w, h); - cr->set_source_rgba (0.0, 0.0, 1.0, 0.4); + if (needLuma && !rawMode) { + drawCurve(cr, lhist, realhistheight, w, h); + cr->set_source_rgb (0.65, 0.65, 0.65); cr->fill (); - - drawCurve(cr, bhchanged, realhistheight, w, h); - cr->set_source_rgba (0.0, 0.0, 1.0, 0.9); + + drawMarks(cr, lhist, realhistheight, w, ui, oi); + } + + if (needChroma && !rawMode) { + drawCurve(cr, chist, realhistheight, w, h); + cr->set_source_rgb (0., 0., 0.); cr->stroke (); - drawMarks(cr, bhchanged, realhistheight, w, ui, oi); + drawMarks(cr, chist, realhistheight, w, ui, oi); } - - if (needGreen) { - drawCurve(cr, ghchanged, realhistheight, w, h); - cr->set_source_rgba (0.0, 1.0, 0.0, 0.4); - cr->fill (); - - drawCurve(cr, ghchanged, realhistheight, w, h); - cr->set_source_rgba (0.0, 1.0, 0.0, 0.9); - cr->stroke (); - - drawMarks(cr, ghchanged, realhistheight, w, ui, oi); - } - + if (needRed) { drawCurve(cr, rhchanged, realhistheight, w, h); - cr->set_source_rgba (1.0, 0.0, 0.0, 0.4); - cr->fill (); - - drawCurve(cr, rhchanged, realhistheight, w, h); - cr->set_source_rgba (1.0, 0.0, 0.0, 0.9); + cr->set_source_rgb (1.0, 0.0, 0.0); cr->stroke (); drawMarks(cr, rhchanged, realhistheight, w, ui, oi); } - cr->set_operator(Cairo::OPERATOR_SOURCE); - - if (needLuma && !rawMode) { - drawCurve(cr, lhist, realhistheight, w, h); - cr->set_source_rgb (0.9, 0.9, 0.9); + if (needGreen) { + drawCurve(cr, ghchanged, realhistheight, w, h); + cr->set_source_rgb (0.0, 1.0, 0.0); cr->stroke (); - drawMarks(cr, lhist, realhistheight, w, ui, oi); + drawMarks(cr, ghchanged, realhistheight, w, ui, oi); } - - if (needChroma && !rawMode) { - drawCurve(cr, chist, realhistheight, w, h); - cr->set_source_rgb (0.4, 0.4, 0.4); + + if (needBlue) { + drawCurve(cr, bhchanged, realhistheight, w, h); + cr->set_source_rgb (0.0, 0.0, 1.0); cr->stroke (); - drawMarks(cr, chist, realhistheight, w, ui, oi); + drawMarks(cr, bhchanged, realhistheight, w, ui, oi); } } - cr->set_source_rgba (1., 1., 1., 0.35); + cr->set_source_rgba (1., 1., 1., 0.25); cr->set_line_width (1.0); cr->set_antialias(Cairo::ANTIALIAS_NONE); @@ -988,51 +961,38 @@ void HistogramArea::updateBackBuffer () ch_ds[0] = 4; cr->set_dash (ch_ds, 0); - cr->move_to(w / 4 + 0.5, 1.5); - cr->line_to(w / 4 + 0.5, h - 2); - cr->stroke(); - cr->move_to(2 * w / 4 + 0.5, 1.5); - cr->line_to(2 * w / 4 + 0.5, h - 2); - cr->stroke(); - cr->move_to(3 * w / 4 + 0.5, 1.5); - cr->line_to(3 * w / 4 + 0.5, h - 2); - cr->stroke(); + // determine the number of gridlines based on current h/w + int nrOfHGridPartitions = (int)rtengine::min (16.0, pow (2.0, floor ((h - 100) / 250) + 2)); + int nrOfVGridPartitions = (int)rtengine::min (16.0, pow (2.0, floor ((w - 100) / 250) + 2)); - if (options.histogramDrawMode == 0) - { - cr->move_to(1.5, h / 4 + 0.5); - cr->line_to(w - 2, h / 4 + 0.5); - cr->stroke(); - cr->move_to(1.5, 2 * h / 4 + 0.5); - cr->line_to(w - 2, 2 * h / 4 + 0.5); - cr->stroke(); - cr->move_to(1.5, 3 * h / 4 + 0.5); - cr->line_to(w - 2, 3 * h / 4 + 0.5); - cr->stroke(); + // draw vertical gridlines + if (options.histogramDrawMode < 2) { + for (int i = 1; i < nrOfVGridPartitions; i++) { + cr->move_to (i * w / nrOfVGridPartitions + 0.5, 1.5); + cr->line_to (i * w / nrOfVGridPartitions + 0.5, h - 2); + cr->stroke (); + } + } else { + for (int i = 1; i < nrOfVGridPartitions; i++) { + cr->move_to (scalingFunctionLog (w, i * w / nrOfVGridPartitions) + 0.5, 1.5); + cr->line_to (scalingFunctionLog (w, i * w / nrOfVGridPartitions) + 0.5, h - 2); + cr->stroke (); + } } - if (options.histogramDrawMode == 1) - { - cr->move_to(1.5, h - scalingFunctionLog(h,h / 4 + 0.5)); - cr->line_to(w - 2, h - scalingFunctionLog(h,h / 4 + 0.5)); - cr->stroke(); - cr->move_to(1.5, h - scalingFunctionLog(h,2 * h / 4 + 0.5)); - cr->line_to(w - 2, h - scalingFunctionLog(h,2 * h / 4 + 0.5)); - cr->stroke(); - cr->move_to(1.5, h - scalingFunctionLog(h,3 * h / 4 + 0.5)); - cr->line_to(w - 2, h - scalingFunctionLog(h,3 * h / 4 + 0.5)); - cr->stroke(); - } - if (options.histogramDrawMode == 2) - { - cr->move_to(1.5, scalingFunctionCube(h,h / 4 + 0.5)); - cr->line_to(w - 2, scalingFunctionCube(h,h / 4 + 0.5)); - cr->stroke(); - cr->move_to(1.5, scalingFunctionCube(h,2 * h / 4 + 0.5)); - cr->line_to(w - 2, scalingFunctionCube(h,2 * h / 4 + 0.5)); - cr->stroke(); - cr->move_to(1.5, scalingFunctionCube(h,3 * h / 4 + 0.5)); - cr->line_to(w - 2, scalingFunctionCube(h,3 * h / 4 + 0.5)); - cr->stroke(); + + // draw horizontal gridlines + if (options.histogramDrawMode == 0) { + for (int i = 1; i < nrOfHGridPartitions; i++) { + cr->move_to (1.5, i * h / nrOfHGridPartitions + 0.5); + cr->line_to (w - 2, i * h / nrOfHGridPartitions + 0.5); + cr->stroke (); + } + } else { + for (int i = 1; i < nrOfHGridPartitions; i++) { + cr->move_to (1.5, h - scalingFunctionLog(h, i * h / nrOfHGridPartitions) + 0.5); + cr->line_to (w - 2, h - scalingFunctionLog(h, i * h / nrOfHGridPartitions) + 0.5); + cr->stroke (); + } } cr->unset_dash(); @@ -1056,14 +1016,8 @@ void HistogramArea::on_realize () double HistogramArea::scalingFunctionLog(double vsize, double val) { - double factor = 1.0; // can be tuned if necessary - makes the log 'steeper' - return vsize * log(factor / (factor + val)) / log(factor / vsize); -} - -double HistogramArea::scalingFunctionCube(double vsize, double val) -{ - double factor = 3.0; // can be tuned; higher values compress the middel part of the scale - return (val * (4 * (-1.0 + factor) * val * val - 6.0 * (-1.0 + factor) * val * vsize + (-2.0 + 3.0 * factor) * vsize *vsize))/(factor * vsize * vsize); + double factor = 20.0; // can be tuned if necessary - higher is flatter curve + return vsize * log(factor / (factor + val)) / log(factor / (factor + vsize)); } void HistogramArea::drawCurve(Cairo::RefPtr &cr, @@ -1075,16 +1029,20 @@ void HistogramArea::drawCurve(Cairo::RefPtr &cr, for (int i = 0; i < 256; i++) { double val = data[i] * (double)(vsize - 2) / scale; - if (drawMode == 1) - val = scalingFunctionLog((double)vsize,val); - if (drawMode == 2) - val = scalingFunctionCube((double)vsize,val); - + if (drawMode > 0) { // scale y for single and double log-scale + val = scalingFunctionLog ((double)vsize, val); + } + if (val > vsize - 1) { val = vsize - 1; } + + double iscaled = i; + if (drawMode == 2) { // scale x for double log-scale + iscaled = scalingFunctionLog (256.0, (double)i); + } - double posX = (i / 255.0) * (hsize - 1); + double posX = (iscaled / 255.0) * (hsize - 1); double posY = vsize - 1 - val; cr->line_to (posX, posY); } diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index bc9fca9a4..bb20dadfb 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -100,14 +100,6 @@ private: // Some ... }; - -/*class FullModeListener -{ -public: - virtual ~FullModeListener() {} - virtual void toggle_button_full () {} -};*/ - class DrawModeListener { public: @@ -125,12 +117,12 @@ protected: LUTu lhistRaw, rhistRaw, ghistRaw, bhistRaw; bool valid; - int drawMode; - DrawModeListener *myDrawModeListener; + int drawMode; + DrawModeListener *myDrawModeListener; int oldwidth, oldheight; bool needLuma, needRed, needGreen, needBlue, rawMode, needChroma; - + HistogramAreaIdleHelper* haih; @@ -154,8 +146,7 @@ private: void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const; void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const; void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const; - double scalingFunctionLog(double vsize, double val); - double scalingFunctionCube(double vsize, double val); + double scalingFunctionLog (double vsize, double val); }; class HistogramPanel : public Gtk::Grid, public PointerMotionListener, public DrawModeListener