/* * This file is part of RawTherapee. * * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include #include #include bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference) { Glib::ListHandle list = cont->get_children (); Glib::ListHandle::iterator i = list.begin (); for (; i!=list.end() && *i!=w; i++); if (i!=list.end()) { if (increference) w->reference (); cont->remove (*w); return true; } else return false; } void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) { if (options.thumbInterp==0) rtengine::nearestInterp (src, sw, sh, dst, dw, dh); else if (options.thumbInterp==1) rtengine::bilinearInterp (src, sw, sh, dst, dw, dh); } Glib::ustring removeExtension (const Glib::ustring& filename) { Glib::ustring bname = Glib::path_get_basename(filename); int lastdot = bname.find_last_of ('.'); if (lastdot!=bname.npos) return filename.substr (0, filename.size()-(bname.size()-lastdot)); else return filename; } Glib::ustring getExtension (const Glib::ustring& filename) { Glib::ustring bname = Glib::path_get_basename(filename); int lastdot = bname.find_last_of ('.'); if (lastdot!=bname.npos) return filename.substr (filename.size()-(bname.size()-lastdot)+1, filename.npos); else return ""; } void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams) { cr->set_line_width (0.); cr->rectangle (imx, imy, imw, imh); cr->clip (); double c1x = (cparams.x-startx)*scale; double c1y = (cparams.y-starty)*scale; double c2x = (cparams.x+cparams.w-1-startx)*scale; double c2y = (cparams.y+cparams.h-1-starty)*scale; cr->set_source_rgba (options.cutOverlayBrush[0], options.cutOverlayBrush[1], options.cutOverlayBrush[2], options.cutOverlayBrush[3]); cr->rectangle (imx, imy, imw, c1y); cr->rectangle (imx, imy+c2y, imw, imh-c2y); cr->rectangle (imx, imy+c1y, c1x, c2y-c1y+1); cr->rectangle (imx+c2x, imy+c1y, imw-c2x, c2y-c1y+1); cr->fill (); // rectangle around the cropped area and guides if (cparams.guide!="None") { double rectx1 = c1x + imx + 0.5; double recty1 = c1y + imy + 0.5; double rectx2 = c2x + imx + 0.5; double recty2 = c2y + imy + 0.5; cr->set_line_width (1.0); cr->set_source_rgb (1.0, 1.0, 1.0); cr->move_to (rectx1, recty1); cr->line_to (rectx2, recty1); cr->line_to (rectx2, recty2); cr->line_to (rectx1, recty2); cr->line_to (rectx1, recty1); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); cr->move_to (rectx1, recty1); cr->line_to (rectx2, recty1); cr->line_to (rectx2, recty2); cr->line_to (rectx1, recty2); cr->line_to (rectx1, recty1); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); if (cparams.guide!="Rule of diagonals") { // draw guide lines std::vector horiz_ratios; std::vector vert_ratios; if (cparams.guide=="Rule of thirds") { horiz_ratios.push_back (1.0/3.0); horiz_ratios.push_back (2.0/3.0); vert_ratios.push_back (1.0/3.0); vert_ratios.push_back (2.0/3.0); } else if (cparams.guide=="Harmonic means 1") { horiz_ratios.push_back (1.0-0.618); vert_ratios.push_back (1.0-0.618); } else if (cparams.guide=="Harmonic means 2") { horiz_ratios.push_back (0.618); vert_ratios.push_back (1.0-0.618); } else if (cparams.guide=="Harmonic means 3") { horiz_ratios.push_back (1.0-0.618); vert_ratios.push_back (0.618); } else if (cparams.guide=="Harmonic means 4") { horiz_ratios.push_back (0.618); vert_ratios.push_back (0.618); } else if (cparams.guide=="Grid") { // To have even distribution, normalize it a bit const int longSideNumLines=10; int w=rectx2-rectx1, h=recty2-recty1, shortSideNumLines; if (w>longSideNumLines && h>longSideNumLines) { if (w>h) { for (int i=1;iset_source_rgb (1.0, 1.0, 1.0); cr->move_to (rectx1, recty1 + (recty2-recty1) * horiz_ratios[i]); cr->line_to (rectx2, recty1 + (recty2-recty1) * horiz_ratios[i]); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); cr->move_to (rectx1, recty1 + (recty2-recty1) * horiz_ratios[i]); cr->line_to (rectx2, recty1 + (recty2-recty1) * horiz_ratios[i]); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); } // Verticals for (int i=0; iset_source_rgb (1.0, 1.0, 1.0); cr->move_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty1); cr->line_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty2); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); cr->move_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty1); cr->line_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty2); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); } } else { int corners_from[4][2]; int corners_to[4][2]; int mindim = MIN (rectx2-rectx1+1, recty2-recty1+1); corners_from[0][0] = rectx1; corners_from[0][1] = recty1; corners_to[0][0] = rectx1 + mindim; corners_to[0][1] = recty1 + mindim; corners_from[1][0] = rectx1; corners_from[1][1] = recty2; corners_to[1][0] = rectx1 + mindim; corners_to[1][1] = recty2 - mindim; corners_from[2][0] = rectx2; corners_from[2][1] = recty1; corners_to[2][0] = rectx2 - mindim; corners_to[2][1] = recty1 + mindim; corners_from[3][0] = rectx2; corners_from[3][1] = recty2; corners_to[3][0] = rectx2 - mindim; corners_to[3][1] = recty2 - mindim; for (int i=0; i<4; i++) { cr->set_source_rgb (1.0, 1.0, 1.0); cr->move_to (corners_from[i][0], corners_from[i][1]); cr->line_to (corners_to[i][0], corners_to[i][1]); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); cr->move_to (corners_from[i][0], corners_from[i][1]); cr->line_to (corners_to[i][0], corners_to[i][1]); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); } } } cr->reset_clip (); } /* * * Derived class of some widgets to properly handle the scroll wheel ; * the user has to use the Shift key to be able to change the widget's value, * otherwise the mouse wheel will scroll the editor's tabs content. * */ MyScrolledWindow::MyScrolledWindow () { set_size_request(-1,30); } bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) { if (!options.hideTPVScrollbar) { Gtk::ScrolledWindow::on_scroll_event (event); return true; } Gtk::Adjustment *adjust = get_vadjustment(); Gtk::VScrollbar *scroll = get_vscrollbar(); if (adjust && scroll) { double upper = adjust->get_upper(); double lower = adjust->get_lower(); double value = adjust->get_value(); double step = adjust->get_step_increment(); double value2 = 0.; if (event->direction == GDK_SCROLL_DOWN) { value2 = value+step; if (value2 > upper) value2 = upper; if (value2 != value) { scroll->set_value(value2); } } else { value2 = value-step; if (value2 < lower) value2 = lower; if (value2 != value) { scroll->set_value(value2); } } } return true; } MyComboBoxText::MyComboBoxText () { set_size_request(40, -1); } bool MyComboBoxText::on_scroll_event (GdkEventScroll* event) { // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::ComboBoxText::on_scroll_event(event); return true; } // ... otherwise the scroll event is sent back to an upper level return false; } MyComboBox::MyComboBox () { set_size_request(40, -1); } bool MyComboBox::on_scroll_event (GdkEventScroll* event) { // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::ComboBox::on_scroll_event(event); return true; } // ... otherwise the scroll event is sent back to an upper level return false; } MySpinButton::MySpinButton () { set_size_request(50, -1); Gtk::Border border; border.bottom = 0; border.top = 0; border.left = 0; border.right = 0; set_inner_border(border); } bool MySpinButton::on_scroll_event (GdkEventScroll* event) { // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::SpinButton::on_scroll_event(event); return true; } // ... otherwise the scroll event is sent back to an upper level return false; } bool MyHScale::on_scroll_event (GdkEventScroll* event) { // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::HScale::on_scroll_event(event); return true; } // ... otherwise the scroll event is sent back to an upper level return false; } MyFileChooserButton::MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action) : Gtk::FileChooserButton(title, action) { set_size_request(20, -1); }; // For an unknown reason (a bug ?), it doesn't work when action = FILE_CHOOSER_ACTION_SELECT_FOLDER ! bool MyFileChooserButton::on_scroll_event (GdkEventScroll* event) { // If Shift is pressed, the widget is modified if (event->state & GDK_SHIFT_MASK) { Gtk::FileChooserButton::on_scroll_event(event); return true; } // ... otherwise the scroll event is sent back to an upper level return false; } TextOrIcon::TextOrIcon (Glib::ustring fname, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type) { imgIcon = 0; label = 0; filename = fname; labelText = labelTx; tooltipText = tooltipTx; switchTo(type); } TextOrIcon::~TextOrIcon () { if (imgIcon) delete imgIcon; if (label) delete label; } void TextOrIcon::switchTo(TOITypes type) { switch (type) { case (TOI_ICON): if (!imgIcon) { removeIfThere(this, label, false); delete label; label = 0; imgIcon = new Gtk::Image (filename); pack_start(*imgIcon, Gtk::PACK_SHRINK, 0); set_tooltip_markup ("" + labelText + "\n" + tooltipText); } // do nothing if imgIcon exist, which mean that it is currently being displayed break; case(TOI_TEXT): default: if (!label) { removeIfThere(this, imgIcon, false); delete imgIcon; imgIcon = 0; label = new Gtk::Label (labelText, Gtk::ALIGN_CENTER); pack_start(*label, Gtk::PACK_EXPAND_WIDGET, 0); set_tooltip_markup (tooltipText); } // do nothing if label exist, which mean that it is currently being displayed break; } show_all(); }