"Fossies" - the Fresh Open Source Software Archive

Member "rawtherapee-5.7/rtgui/filebrowserentry.cc" (10 Sep 2019, 28190 Bytes) of package /linux/misc/rawtherapee-5.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "filebrowserentry.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.6_vs_5.7.

    1 /*
    2  *  This file is part of RawTherapee.
    3  *
    4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
    5  *
    6  *  RawTherapee is free software: you can redistribute it and/or modify
    7  *  it under the terms of the GNU General Public License as published by
    8  *  the Free Software Foundation, either version 3 of the License, or
    9  *  (at your option) any later version.
   10  *
   11  *  RawTherapee is distributed in the hope that it will be useful,
   12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *  GNU General Public License for more details.
   15  *
   16  *  You should have received a copy of the GNU General Public License
   17  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
   18  */
   19 #include "filebrowserentry.h"
   20 
   21 #include <cstring>
   22 #include <iomanip>
   23 
   24 #include "cursormanager.h"
   25 #include "guiutils.h"
   26 #include "inspector.h"
   27 #include "rtimage.h"
   28 #include "threadutils.h"
   29 #include "thumbbrowserbase.h"
   30 
   31 #include "../rtengine/procparams.h"
   32 
   33 #define CROPRESIZEBORDER 4
   34 
   35 //extern Glib::Threads::Thread* mainThread;
   36 
   37 bool FileBrowserEntry::iconsLoaded(false);
   38 Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::editedIcon;
   39 Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::recentlySavedIcon;
   40 Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::enqueuedIcon;
   41 Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::hdr;
   42 Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::ps;
   43 
   44 FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname)
   45     : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(nullptr), press_x(0), press_y(0), action_x(0), action_y(0), rot_deg(0.0), landscape(true), cropParams(new rtengine::procparams::CropParams), cropgl(nullptr), state(SNormal), crop_custom_ratio(0.f)
   46 {
   47     thumbnail = thm;
   48 
   49     feih = new FileBrowserEntryIdleHelper;
   50     feih->fbentry = this;
   51     feih->destroyed = false;
   52     feih->pending = 0;
   53 
   54     italicstyle = thumbnail->getType() != FT_Raw;
   55     datetimeline = thumbnail->getDateTimeString ();
   56     exifline = thumbnail->getExifString ();
   57 
   58     scale = 1;
   59 
   60     if (!iconsLoaded) {
   61         editedIcon = RTImage::createPixbufFromFile ("tick-small.png");
   62         recentlySavedIcon = RTImage::createPixbufFromFile ("save-small.png");
   63         enqueuedIcon = RTImage::createPixbufFromFile ("gears-small.png");
   64         hdr = RTImage::createPixbufFromFile ("filetype-hdr.png");
   65         ps = RTImage::createPixbufFromFile ("filetype-ps.png");
   66         iconsLoaded = true;
   67     }
   68 
   69     thumbnail->addThumbnailListener (this);
   70 }
   71 
   72 FileBrowserEntry::~FileBrowserEntry ()
   73 {
   74     idle_register.destroy();
   75 
   76     // so jobs arriving now do nothing
   77     if (feih->pending) {
   78         feih->destroyed = true;
   79     } else {
   80         delete feih;
   81         feih = nullptr;
   82     }
   83 
   84     thumbImageUpdater->removeJobs (this);
   85 
   86     if (thumbnail) {
   87         thumbnail->removeThumbnailListener (this);
   88         thumbnail->decreaseRef ();
   89     }
   90 }
   91 
   92 void FileBrowserEntry::refreshThumbnailImage ()
   93 {
   94 
   95     if (!thumbnail) {
   96         return;
   97     }
   98 
   99     thumbImageUpdater->add (this, &updatepriority, false, this);
  100 }
  101 
  102 void FileBrowserEntry::refreshQuickThumbnailImage ()
  103 {
  104 
  105     if (!thumbnail) {
  106         return;
  107     }
  108 
  109     // Only make a (slow) processed preview if the picture has been edited at all
  110     bool upgrade_to_processed = (!options.internalThumbIfUntouched || thumbnail->isPParamsValid());
  111     thumbImageUpdater->add(this, &updatepriority, upgrade_to_processed, this);
  112 }
  113 
  114 void FileBrowserEntry::calcThumbnailSize ()
  115 {
  116 
  117     if (thumbnail) {
  118         thumbnail->getThumbnailSize (prew, preh);
  119     }
  120 }
  121 
  122 std::vector<Glib::RefPtr<Gdk::Pixbuf>> FileBrowserEntry::getIconsOnImageArea ()
  123 {
  124     if (!thumbnail) {
  125         return {};
  126     }
  127 
  128     std::vector<Glib::RefPtr<Gdk::Pixbuf>> ret;
  129 
  130     if (thumbnail->hasProcParams() && editedIcon) {
  131         ret.push_back(editedIcon);
  132     }
  133 
  134     if (thumbnail->isRecentlySaved() && recentlySavedIcon) {
  135         ret.push_back(recentlySavedIcon);
  136     }
  137 
  138     if (thumbnail->isEnqueued () && enqueuedIcon) {
  139         ret.push_back(enqueuedIcon);
  140     }
  141 
  142     return ret;
  143 }
  144 
  145 std::vector<Glib::RefPtr<Gdk::Pixbuf>> FileBrowserEntry::getSpecificityIconsOnImageArea ()
  146 {
  147     if (!thumbnail) {
  148         return {};
  149     }
  150 
  151     std::vector<Glib::RefPtr<Gdk::Pixbuf>> ret;
  152 
  153     if (thumbnail->isHDR() && hdr) {
  154         ret.push_back (hdr);
  155     }
  156 
  157     if (thumbnail->isPixelShift() && ps) {
  158         ret.push_back (ps);
  159     }
  160 
  161     return ret;
  162 }
  163 
  164 void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c)
  165 {
  166     if(scale != 1.0 && cropParams->enabled) { // somewhere in pipeline customBackBufferUpdate is called when scale == 1.0, which is nonsense for a thumb
  167         if (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove) {
  168             drawCrop (c, prex, prey, prew, preh, 0, 0, scale, *cropParams, true, false);
  169         } else {
  170             rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop;
  171             switch (options.cropGuides) {
  172             case Options::CROP_GUIDE_NONE:
  173                 cparams.guide = "None";
  174                 break;
  175             case Options::CROP_GUIDE_FRAME:
  176                 cparams.guide = "Frame";
  177                 break;
  178             default:
  179                 break;
  180             }
  181 
  182             if (cparams.enabled && !thumbnail->isQuick()) { // Quick thumb have arbitrary sizes, so don't apply the crop
  183                 drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cparams, true, false);
  184             }
  185         }
  186     }
  187 }
  188 
  189 void FileBrowserEntry::getIconSize (int& w, int& h) const
  190 {
  191 
  192     w = editedIcon->get_width ();
  193     h = editedIcon->get_height ();
  194 }
  195 
  196 FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet ()
  197 {
  198 
  199     return (static_cast<FileThumbnailButtonSet*>(buttonSet));
  200 }
  201 
  202 void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt)
  203 {
  204 
  205     if ( thumbnail->isQuick() ) {
  206         refreshQuickThumbnailImage ();
  207     } else {
  208         refreshThumbnailImage ();
  209     }
  210 }
  211 
  212 void FileBrowserEntry::updateImage(rtengine::IImage8* img, double scale, const rtengine::procparams::CropParams& cropParams)
  213 {
  214     if (!feih) {
  215         return;
  216     }
  217     redrawRequests++;
  218     feih->pending++;
  219 
  220     idle_register.add(
  221         [this, img, scale, cropParams]() -> bool
  222         {
  223             if (feih->destroyed) {
  224                 if (feih->pending == 1) {
  225                     delete feih;
  226                 } else {
  227                     --feih->pending;
  228                 }
  229 
  230                 img->free();
  231                 return false;
  232             }
  233 
  234             feih->fbentry->_updateImage(img, scale, cropParams);
  235             --feih->pending;
  236 
  237             return false;
  238         },
  239         G_PRIORITY_LOW
  240     );
  241 }
  242 
  243 void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rtengine::procparams::CropParams& cropParams)
  244 {
  245     MYWRITERLOCK(l, lockRW);
  246 
  247     redrawRequests--;
  248     scale = s;
  249     *this->cropParams = cropParams;
  250 
  251     bool newLandscape = img->getWidth() > img->getHeight();
  252     bool rotated = false;
  253 
  254     if (preh == img->getHeight()) {
  255         const bool resize = !preview || prew != img->getWidth();
  256         prew = img->getWidth ();
  257 
  258         // Check if image has been rotated since last time
  259         rotated = preview && newLandscape != landscape;
  260 
  261         if (resize) {
  262             if (preview) {
  263                 delete [] preview;
  264             }
  265             preview = new guint8 [prew * preh * 3];
  266         }
  267         memcpy(preview, img->getData(), prew * preh * 3);
  268         {
  269         GThreadLock lock;
  270         updateBackBuffer ();
  271         }
  272     }
  273 
  274     landscape = newLandscape;
  275 
  276     img->free();
  277 
  278     if (parent) {
  279         if (rotated) {
  280             parent->thumbRearrangementNeeded();
  281         } else if (redrawRequests == 0) {
  282             parent->redrawNeeded(this);
  283         }
  284     }
  285 }
  286 
  287 bool FileBrowserEntry::motionNotify (int x, int y)
  288 {
  289 
  290     const bool b = ThumbBrowserEntryBase::motionNotify(x, y);
  291 
  292     const int ix = x - startx - ofsX;
  293     const int iy = y - starty - ofsY;
  294 
  295     Inspector* inspector = parent->getInspector();
  296 
  297     if (inspector && inspector->isActive() && !parent->isInTabMode()) {
  298         const rtengine::Coord2D coord(getPosInImgSpace(x, y));
  299 
  300         if (coord.x != -1.) {
  301             if (!wasInside) {
  302                 inspector->switchImage(filename);
  303                 wasInside = true;
  304             }
  305             inspector->mouseMove(coord, 0);
  306         } else {
  307             wasInside = false;
  308         }
  309     }
  310 
  311     if (inside(x, y)) {
  312         updateCursor(ix, iy);
  313     }
  314 
  315     if (state == SRotateSelecting) {
  316         action_x = x;
  317         action_y = y;
  318         parent->redrawNeeded (this);
  319     } else if (state == SResizeH1 && cropgl) {
  320         int oy = cropParams->y;
  321         cropParams->y = action_y + (y - press_y) / scale;
  322         cropParams->h += oy - cropParams->y;
  323         cropgl->cropHeight1Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  324         {
  325         MYREADERLOCK(l, lockRW);
  326         updateBackBuffer ();
  327         }
  328         parent->redrawNeeded (this);
  329     } else if (state == SResizeH2 && cropgl) {
  330         cropParams->h = action_y + (y - press_y) / scale;
  331         cropgl->cropHeight2Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  332         {
  333         MYREADERLOCK(l, lockRW);
  334         updateBackBuffer ();
  335         }
  336         parent->redrawNeeded (this);
  337     } else if (state == SResizeW1 && cropgl) {
  338         int ox = cropParams->x;
  339         cropParams->x = action_x + (x - press_x) / scale;
  340         cropParams->w += ox - cropParams->x;
  341         cropgl->cropWidth1Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  342         {
  343         MYREADERLOCK(l, lockRW);
  344         updateBackBuffer ();
  345         }
  346         parent->redrawNeeded (this);
  347     } else if (state == SResizeW2 && cropgl) {
  348         cropParams->w = action_x + (x - press_x) / scale;
  349         cropgl->cropWidth2Resized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  350         {
  351         MYREADERLOCK(l, lockRW);
  352         updateBackBuffer ();
  353         }
  354         parent->redrawNeeded (this);
  355     } else if (state == SResizeTL && cropgl) {
  356         int ox = cropParams->x;
  357         cropParams->x = action_x + (x - press_x) / scale;
  358         cropParams->w += ox - cropParams->x;
  359         int oy = cropParams->y;
  360         cropParams->y = action_y + (y - press_y) / scale;
  361         cropParams->h += oy - cropParams->y;
  362         cropgl->cropTopLeftResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  363         {
  364         MYREADERLOCK(l, lockRW);
  365         updateBackBuffer ();
  366         }
  367         parent->redrawNeeded (this);
  368     } else if (state == SResizeTR && cropgl) {
  369         cropParams->w = action_x + (x - press_x) / scale;
  370         int oy = cropParams->y;
  371         cropParams->y = action_y + (y - press_y) / scale;
  372         cropParams->h += oy - cropParams->y;
  373         cropgl->cropTopRightResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  374         {
  375         MYREADERLOCK(l, lockRW);
  376         updateBackBuffer ();
  377         }
  378         parent->redrawNeeded (this);
  379     } else if (state == SResizeBL && cropgl) {
  380         int ox = cropParams->x;
  381         cropParams->x = action_x + (x - press_x) / scale;
  382         cropParams->w += ox - cropParams->x;
  383         cropParams->h = action_y + (y - press_y) / scale;
  384         cropgl->cropBottomLeftResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  385         {
  386         MYREADERLOCK(l, lockRW);
  387         updateBackBuffer ();
  388         }
  389         parent->redrawNeeded (this);
  390     } else if (state == SResizeBR && cropgl) {
  391         cropParams->w = action_x + (x - press_x) / scale;
  392         cropParams->h = action_y + (y - press_y) / scale;
  393         cropgl->cropBottomRightResized (cropParams->x, cropParams->y, cropParams->w, cropParams->h, crop_custom_ratio);
  394         {
  395         MYREADERLOCK(l, lockRW);
  396         updateBackBuffer ();
  397         }
  398         parent->redrawNeeded (this);
  399     } else if (state == SCropMove && cropgl) {
  400         cropParams->x = action_x + (x - press_x) / scale;
  401         cropParams->y = action_y + (y - press_y) / scale;
  402         cropgl->cropMoved (cropParams->x, cropParams->y, cropParams->w, cropParams->h);
  403         {
  404         MYREADERLOCK(l, lockRW);
  405         updateBackBuffer ();
  406         }
  407         parent->redrawNeeded (this);
  408     } else if (state == SCropSelecting && cropgl) {
  409         int cx1 = press_x, cy1 = press_y;
  410         int cx2 = (ix - prex) / scale, cy2 = (iy - prey) / scale;
  411         cropgl->cropResized (cx1, cy1, cx2, cy2);
  412 
  413         if (cx2 > cx1) {
  414             cropParams->x = cx1;
  415             cropParams->w = cx2 - cx1 + 1;
  416         } else {
  417             cropParams->x = cx2;
  418             cropParams->w = cx1 - cx2 + 1;
  419         }
  420 
  421         if (cy2 > cy1) {
  422             cropParams->y = cy1;
  423             cropParams->h = cy2 - cy1 + 1;
  424         } else {
  425             cropParams->y = cy2;
  426             cropParams->h = cy1 - cy2 + 1;
  427         }
  428 
  429         {
  430         MYREADERLOCK(l, lockRW);
  431         updateBackBuffer ();
  432         }
  433         parent->redrawNeeded (this);
  434     }
  435 
  436     return b;
  437 }
  438 
  439 bool FileBrowserEntry::pressNotify   (int button, int type, int bstate, int x, int y)
  440 {
  441 
  442     bool b = ThumbBrowserEntryBase::pressNotify (button, type, bstate, x, y);
  443 
  444     if (!iatlistener || !iatlistener->getToolBar()) {
  445         return true;
  446     }
  447 
  448     ToolMode tm = iatlistener->getToolBar()->getTool ();
  449     int ix = x - startx - ofsX;
  450     int iy = y - starty - ofsY;
  451 
  452     if (tm == TMNone) {
  453         return b;
  454     }
  455 
  456     crop_custom_ratio = 0.f;
  457 
  458     if (!b && selected && inside (x, y)) {
  459         if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal) {
  460             if ((bstate & GDK_SHIFT_MASK) && cropParams->w > 0 && cropParams->h > 0) {
  461                 crop_custom_ratio = float(cropParams->w) / float(cropParams->h);
  462             }
  463             if (onArea (CropTopLeft, ix, iy)) {
  464                 state = SResizeTL;
  465                 press_x = x;
  466                 action_x = cropParams->x;
  467                 press_y = y;
  468                 action_y = cropParams->y;
  469                 cropgl = iatlistener->startCropEditing (thumbnail);
  470                 b = true;
  471             } else if (onArea (CropTopRight, ix, iy)) {
  472                 state = SResizeTR;
  473                 press_x = x;
  474                 action_x = cropParams->w;
  475                 press_y = y;
  476                 action_y = cropParams->y;
  477                 cropgl = iatlistener->startCropEditing (thumbnail);
  478                 b = true;
  479             } else if (onArea (CropBottomLeft, ix, iy)) {
  480                 state = SResizeBL;
  481                 press_x = x;
  482                 action_x = cropParams->x;
  483                 press_y = y;
  484                 action_y = cropParams->h;
  485                 cropgl = iatlistener->startCropEditing (thumbnail);
  486                 b = true;
  487             } else if (onArea (CropBottomRight, ix, iy)) {
  488                 state = SResizeBR;
  489                 press_x = x;
  490                 action_x = cropParams->w;
  491                 press_y = y;
  492                 action_y = cropParams->h;
  493                 cropgl = iatlistener->startCropEditing (thumbnail);
  494                 b = true;
  495             } else if (onArea (CropTop, ix, iy)) {
  496                 state = SResizeH1;
  497                 press_y = y;
  498                 action_y = cropParams->y;
  499                 cropgl = iatlistener->startCropEditing (thumbnail);
  500                 b = true;
  501             } else if (onArea (CropBottom, ix, iy)) {
  502                 state = SResizeH2;
  503                 press_y = y;
  504                 action_y = cropParams->h;
  505                 cropgl = iatlistener->startCropEditing (thumbnail);
  506                 b = true;
  507             } else if (onArea (CropLeft, ix, iy)) {
  508                 state = SResizeW1;
  509                 press_x = x;
  510                 action_x = cropParams->x;
  511                 cropgl = iatlistener->startCropEditing (thumbnail);
  512                 b = true;
  513             } else if (onArea (CropRight, ix, iy)) {
  514                 state = SResizeW2;
  515                 press_x = x;
  516                 action_x = cropParams->w;
  517                 cropgl = iatlistener->startCropEditing (thumbnail);
  518                 b = true;
  519             } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, ix, iy)) {
  520                 state = SCropMove;
  521                 press_x = x;
  522                 press_y = y;
  523                 action_x = cropParams->x;
  524                 action_y = cropParams->y;
  525                 cropgl = iatlistener->startCropEditing (thumbnail);
  526                 b = true;
  527             } else if (onArea (CropImage, ix, iy)) {
  528                 if (tm == TMStraighten) {
  529                     state = SRotateSelecting;
  530                     press_x = x;
  531                     press_y = y;
  532                     action_x = x;
  533                     action_y = y;
  534                     rot_deg = 0;
  535                     b = true;
  536                 } else if (tm == TMSpotWB) {
  537                     iatlistener->spotWBselected ((ix - prex) / scale, (iy - prey) / scale, thumbnail);
  538                     b = true;
  539                 } else if (tm == TMCropSelect) {
  540                     cropgl = iatlistener->startCropEditing (thumbnail);
  541 
  542                     if (cropgl) {
  543                         state = SCropSelecting;
  544                         press_x = cropParams->x = (ix - prex) / scale;
  545                         press_y = cropParams->y = (iy - prey) / scale;
  546                         cropParams->w = cropParams->h = 1;
  547                         cropgl->cropInit (cropParams->x, cropParams->y, cropParams->w, cropParams->h);
  548                         b = true;
  549                     }
  550                 }
  551             }
  552         }
  553 
  554         updateCursor (ix, iy);
  555     }
  556 
  557     return b;
  558 }
  559 
  560 bool FileBrowserEntry::releaseNotify (int button, int type, int bstate, int x, int y)
  561 {
  562 
  563     bool b = ThumbBrowserEntryBase::releaseNotify (button, type, bstate, x, y);
  564 
  565     int ix = x - startx - ofsX;
  566     int iy = y - starty - ofsY;
  567 
  568     if (!b) {
  569         if (state == SRotateSelecting) {
  570             iatlistener->rotateSelectionReady (rot_deg, thumbnail);
  571 
  572             if (iatlistener->getToolBar()) {
  573                 iatlistener->getToolBar()->setTool (TMHand);
  574             }
  575         } else if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) {
  576             cropgl->cropManipReady ();
  577             cropgl = nullptr;
  578             iatlistener->cropSelectionReady ();
  579 
  580             if (iatlistener->getToolBar()) {
  581                 iatlistener->getToolBar()->setTool (TMHand);
  582             }
  583         }
  584 
  585         state = SNormal;
  586 
  587         if (parent) {
  588             parent->redrawNeeded (this);
  589         }
  590 
  591         updateCursor (ix, iy);
  592     }
  593 
  594     return b;
  595 }
  596 
  597 bool FileBrowserEntry::onArea (CursorArea a, int x, int y)
  598 {
  599 
  600     MYREADERLOCK(l, lockRW);
  601     if (!drawable || !preview) {
  602         return false;
  603     }
  604 
  605     int x1 = (x - prex) / scale;
  606     int y1 = (y - prey) / scale;
  607     int cropResizeBorder = CROPRESIZEBORDER / scale;
  608 
  609     switch (a) {
  610     case CropImage:
  611         return x >= prex && x < prex + prew && y >= prey && y < prey + preh;
  612 
  613     case CropTopLeft:
  614         return cropParams->enabled &&
  615                y1 >= cropParams->y - cropResizeBorder &&
  616                y1 <= cropParams->y + cropResizeBorder &&
  617                x1 >= cropParams->x - cropResizeBorder &&
  618                x1 <= cropParams->x + cropResizeBorder;
  619 
  620     case CropTopRight:
  621         return cropParams->enabled &&
  622                y1 >= cropParams->y - cropResizeBorder &&
  623                y1 <= cropParams->y + cropResizeBorder &&
  624                x1 >= cropParams->x + cropParams->w - 1 - cropResizeBorder &&
  625                x1 <= cropParams->x + cropParams->w - 1 + cropResizeBorder;
  626 
  627     case CropBottomLeft:
  628         return cropParams->enabled &&
  629                y1 >= cropParams->y + cropParams->h - 1 - cropResizeBorder &&
  630                y1 <= cropParams->y + cropParams->h - 1 + cropResizeBorder &&
  631                x1 >= cropParams->x - cropResizeBorder &&
  632                x1 <= cropParams->x + cropResizeBorder;
  633 
  634     case CropBottomRight:
  635         return cropParams->enabled &&
  636                y1 >= cropParams->y + cropParams->h - 1 - cropResizeBorder &&
  637                y1 <= cropParams->y + cropParams->h - 1 + cropResizeBorder &&
  638                x1 >= cropParams->x + cropParams->w - 1 - cropResizeBorder &&
  639                x1 <= cropParams->x + cropParams->w - 1 + cropResizeBorder;
  640 
  641     case CropTop:
  642         return cropParams->enabled &&
  643                x1 > cropParams->x + cropResizeBorder &&
  644                x1 < cropParams->x + cropParams->w - 1 - cropResizeBorder &&
  645                y1 > cropParams->y - cropResizeBorder &&
  646                y1 < cropParams->y + cropResizeBorder;
  647 
  648     case CropBottom:
  649         return cropParams->enabled &&
  650                x1 > cropParams->x + cropResizeBorder &&
  651                x1 < cropParams->x + cropParams->w - 1 - cropResizeBorder &&
  652                y1 > cropParams->y + cropParams->h - 1 - cropResizeBorder &&
  653                y1 < cropParams->y + cropParams->h - 1 + cropResizeBorder;
  654 
  655     case CropLeft:
  656         return cropParams->enabled &&
  657                y1 > cropParams->y + cropResizeBorder &&
  658                y1 < cropParams->y + cropParams->h - 1 - cropResizeBorder &&
  659                x1 > cropParams->x - cropResizeBorder &&
  660                x1 < cropParams->x + cropResizeBorder;
  661 
  662     case CropRight:
  663         return cropParams->enabled &&
  664                y1 > cropParams->y + cropResizeBorder &&
  665                y1 < cropParams->y + cropParams->h - 1 - cropResizeBorder &&
  666                x1 > cropParams->x + cropParams->w - 1 - cropResizeBorder &&
  667                x1 < cropParams->x + cropParams->w - 1 + cropResizeBorder;
  668 
  669     case CropInside:
  670         return cropParams->enabled &&
  671                y1 > cropParams->y &&
  672                y1 < cropParams->y + cropParams->h - 1 &&
  673                x1 > cropParams->x &&
  674                x1 < cropParams->x + cropParams->w - 1;
  675     default: /* do nothing */ ;
  676     }
  677 
  678     return false;
  679 }
  680 
  681 
  682 void FileBrowserEntry::updateCursor (int x, int y)
  683 {
  684 
  685     if (!iatlistener || !iatlistener->getToolBar()) {
  686         return;
  687     }
  688 
  689     CursorShape newCursor = CSUndefined;
  690 
  691     ToolMode tm = iatlistener->getToolBar()->getTool ();
  692     Glib::RefPtr<Gdk::Window> w = parent->getDrawingArea ()->get_window();
  693 
  694     if (!selected) {
  695         newCursor = CSArrow;
  696     } else if (state == SNormal) {
  697         if (tm == TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y))) {
  698             newCursor = CSResizeHeight;
  699         } else if (tm == TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y))) {
  700             newCursor = CSResizeWidth;
  701         } else if (tm == TMHand && (onArea (CropTopLeft, x, y))) {
  702             newCursor = CSResizeTopLeft;
  703         } else if (tm == TMHand && (onArea (CropTopRight, x, y))) {
  704             newCursor = CSResizeTopRight;
  705         } else if (tm == TMHand && (onArea (CropBottomLeft, x, y))) {
  706             newCursor = CSResizeBottomLeft;
  707         } else if (tm == TMHand && (onArea (CropBottomRight, x, y))) {
  708             newCursor = CSResizeBottomRight;
  709         } else if (onArea (CropImage, x, y)) {
  710             if (tm == TMHand) {
  711                 newCursor = CSArrow;
  712             } else if (tm == TMSpotWB) {
  713                 newCursor = CSSpotWB;
  714             } else if (tm == TMCropSelect) {
  715                 newCursor = CSCropSelect;
  716             } else if (tm == TMStraighten) {
  717                 newCursor = CSStraighten;
  718             }
  719         } else {
  720             newCursor = CSArrow;
  721         }
  722     } else if (state == SCropSelecting) {
  723         newCursor = CSCropSelect;
  724     } else if (state == SRotateSelecting) {
  725         newCursor = CSStraighten;
  726     } else if (state == SCropMove) {
  727         newCursor = CSMove;
  728     } else if (state == SResizeW1 || state == SResizeW2) {
  729         newCursor = CSResizeWidth;
  730     } else if (state == SResizeH1 || state == SResizeH2) {
  731         newCursor = CSResizeHeight;
  732     } else if (state == SResizeTL) {
  733         newCursor = CSResizeTopLeft;
  734     } else if (state == SResizeTR) {
  735         newCursor = CSResizeTopRight;
  736     } else if (state == SResizeBL) {
  737         newCursor = CSResizeBottomLeft;
  738     } else if (state == SResizeBR) {
  739         newCursor = CSResizeBottomRight;
  740     }
  741 
  742     if (newCursor != cursor_type) {
  743         cursor_type = newCursor;
  744         CursorManager::setCursorOfMainWindow (w, cursor_type);
  745     }
  746 }
  747 
  748 void FileBrowserEntry::draw (Cairo::RefPtr<Cairo::Context> cc)
  749 {
  750 
  751     ThumbBrowserEntryBase::draw (cc);
  752 
  753     if (state == SRotateSelecting) {
  754         drawStraightenGuide (cc);
  755     }
  756 }
  757 
  758 void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr<Cairo::Context> cr)
  759 {
  760 
  761     if (action_x != press_x || action_y != press_y) {
  762         double arg = (press_x - action_x) / sqrt(double((press_x - action_x) * (press_x - action_x) + (press_y - action_y) * (press_y - action_y)));
  763         double sol1, sol2;
  764         double pi = rtengine::RT_PI;
  765 
  766         if (press_y > action_y) {
  767             sol1 = acos(arg) * 180 / pi;
  768             sol2 = -acos(-arg) * 180 / pi;
  769         } else {
  770             sol1 = acos(-arg) * 180 / pi;
  771             sol2 = -acos(arg) * 180 / pi;
  772         }
  773 
  774         if (fabs(sol1) < fabs(sol2)) {
  775             rot_deg = sol1;
  776         } else {
  777             rot_deg = sol2;
  778         }
  779 
  780         if (rot_deg < -45) {
  781             rot_deg = 90.0 + rot_deg;
  782         } else if (rot_deg > 45) {
  783             rot_deg = - 90.0 + rot_deg;
  784         }
  785     } else {
  786         rot_deg = 0;
  787     }
  788 
  789     Glib::RefPtr<Pango::Context> context = parent->getDrawingArea()->get_pango_context () ;
  790     Pango::FontDescription fontd = context->get_font_description ();
  791     fontd.set_weight (Pango::WEIGHT_BOLD);
  792     fontd.set_size (8 * Pango::SCALE);
  793     context->set_font_description (fontd);
  794     Glib::RefPtr<Pango::Layout> deglayout = parent->getDrawingArea()->create_pango_layout(Glib::ustring::compose ("%1 deg", Glib::ustring::format(std::setprecision(2), rot_deg)));
  795 
  796     int x1 = press_x;
  797     int y1 = press_y;
  798     int y2 = action_y;
  799     int x2 = action_x;
  800 
  801     {
  802     MYREADERLOCK(l, lockRW);
  803     if (x2 < prex + ofsX + startx) {
  804         y2 = y1 - (double)(y1 - y2) * (x1 - (prex + ofsX + startx)) / (x1 - x2);
  805         x2 = prex + ofsX + startx;
  806     } else if (x2 >= prew + prex + ofsX + startx) {
  807         y2 = y1 - (double)(y1 - y2) * (x1 - (prew + prex + ofsX + startx - 1)) / (x1 - x2);
  808         x2 = prew + prex + ofsX + startx - 1;
  809     }
  810 
  811     if (y2 < prey + ofsY + starty) {
  812         x2 = x1 - (double)(x1 - x2) * (y1 - (prey + ofsY + starty)) / (y1 - y2);
  813         y2 = prey + ofsY + starty;
  814     } else if (y2 >= preh + prey + ofsY + starty) {
  815         x2 = x1 - (double)(x1 - x2) * (y1 - (preh + prey + ofsY + starty - 1)) / (y1 - y2);
  816         y2 = preh + prey + ofsY + starty - 1;
  817     }
  818     }
  819 
  820     cr->set_line_width (1.5);
  821     cr->set_source_rgb (1.0, 1.0, 1.0);
  822     cr->move_to (x1, y1);
  823     cr->line_to (x2, y2);
  824     cr->stroke ();
  825     cr->set_source_rgb (0.0, 0.0, 0.0);
  826     std::valarray<double> ds (1);
  827     ds[0] = 4;
  828     cr->set_dash (ds, 0);
  829     cr->move_to (x1, y1);
  830     cr->line_to (x2, y2);
  831     cr->stroke ();
  832 
  833     if (press_x != action_x && press_y != action_y) {
  834         cr->set_source_rgb (0.0, 0.0, 0.0);
  835         cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1);
  836         deglayout->add_to_cairo_context (cr);
  837         cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 - 1);
  838         deglayout->add_to_cairo_context (cr);
  839         cr->move_to ((x1 + x2) / 2 - 1, (y1 + y2) / 2 + 1);
  840         deglayout->add_to_cairo_context (cr);
  841         cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1);
  842         deglayout->add_to_cairo_context (cr);
  843         cr->fill ();
  844         cr->set_source_rgb (1.0, 1.0, 1.0);
  845         cr->move_to ((x1 + x2) / 2, (y1 + y2) / 2);
  846         deglayout->add_to_cairo_context (cr);
  847         cr->fill ();
  848     }
  849 }
  850