Partly solving issue 1490: "Comparator Tab / Light Table / Inspector" with the addition of an "Inspect" tab to the File Browser panel.
This commit is contained in:
@@ -14,7 +14,7 @@ set (BASESOURCEFILES
|
||||
crophandler.cc dirbrowser.cc
|
||||
curveeditor.cc curveeditorgroup.cc diagonalcurveeditorsubgroup.cc flatcurveeditorsubgroup.cc
|
||||
filecatalog.cc extprog.cc
|
||||
previewloader.cc rtimage.cc
|
||||
previewloader.cc rtimage.cc inspector.cc
|
||||
histogrampanel.cc history.cc imagearea.cc
|
||||
imageareapanel.cc iptcpanel.cc labcurve.cc main.cc
|
||||
multilangmgr.cc mycurve.cc myflatcurve.cc mydiagonalcurve.cc options.cc
|
||||
|
||||
@@ -179,12 +179,15 @@ BatchQueuePanel::BatchQueuePanel () {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BatchQueuePanel::updateTab (int qsize)
|
||||
// it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ingored and computed automatically
|
||||
void BatchQueuePanel::updateTab (int qsize, int forceOrientation)
|
||||
{
|
||||
Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent());
|
||||
|
||||
if (options.mainNBVertical) {
|
||||
if (forceOrientation > 0)
|
||||
qsize = batchQueue->getEntries().size();
|
||||
|
||||
if ((forceOrientation==0 && options.mainNBVertical) || (forceOrientation==2)) {
|
||||
Gtk::VBox* vbb = Gtk::manage (new Gtk::VBox ());
|
||||
Gtk::Label* l;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class BatchQueuePanel : public Gtk::VBox,
|
||||
void pathFolderChanged ();
|
||||
void pathFolderButtonPressed ();
|
||||
void formatChanged (Glib::ustring f);
|
||||
void updateTab (int qsize);
|
||||
void updateTab (int qsize, int forceOrientation=0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical
|
||||
|
||||
bool handleShortcutKey (GdkEventKey* event);
|
||||
};
|
||||
|
||||
@@ -26,9 +26,9 @@ ColoredBar::ColoredBar (eRTOrientation orient) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Redraw the bar to a Cairo::Surface
|
||||
* Redraw the bar to a Cairo::ImageSurface
|
||||
*/
|
||||
void ColoredBar::expose(Cairo::RefPtr<Cairo::Surface> destSurface) {
|
||||
void ColoredBar::expose(Cairo::RefPtr<Cairo::ImageSurface> destSurface) {
|
||||
// look out if the Surface has to be redrawn
|
||||
if (!surfaceCreated() || !destSurface)
|
||||
return;
|
||||
|
||||
@@ -39,7 +39,7 @@ class ColoredBar : public BackBuffer, public ColorCaller {
|
||||
ColoredBar (eRTOrientation orient);
|
||||
|
||||
void expose(Glib::RefPtr<Gdk::Window> destWindow);
|
||||
void expose(Cairo::RefPtr<Cairo::Surface> destSurface);
|
||||
void expose(Cairo::RefPtr<Cairo::ImageSurface> destSurface);
|
||||
void expose(BackBuffer *backBuffer);
|
||||
|
||||
bool canGetColors();
|
||||
|
||||
163
rtgui/coord.h
Normal file
163
rtgui/coord.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _COORD_H_
|
||||
#define _COORD_H_
|
||||
|
||||
class PolarCoord;
|
||||
|
||||
// Do not confuse with rtengine::Coord2D, Coord is for the GUI
|
||||
class Coord {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Coord() : x(-1), y(-1) {}
|
||||
Coord(int x, int y) : x(x), y(y) {}
|
||||
|
||||
void set (int x, int y) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void setFromPolar(PolarCoord polar);
|
||||
|
||||
/// @brief Clip the coord to stay in the width x height bounds
|
||||
/// @return true if the x or y coordinate has changed
|
||||
bool clip(int width, int height) {
|
||||
int trimmedX = rtengine::LIM<int>(x, 0, width);
|
||||
int trimmedY = rtengine::LIM<int>(y, 0, height);
|
||||
bool retval = trimmedX!=x || trimmedY!=y;
|
||||
x = trimmedX;
|
||||
y = trimmedY;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void operator+=(const Coord & rhs) {
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
}
|
||||
void operator-=(const Coord & rhs) {
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
}
|
||||
void operator*=(double scale) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
Coord operator+(Coord & rhs) {
|
||||
Coord result(x+rhs.x, y+rhs.y);
|
||||
return result;
|
||||
}
|
||||
Coord operator-(Coord & rhs) {
|
||||
Coord result(x-rhs.x, y-rhs.y);
|
||||
return result;
|
||||
}
|
||||
Coord operator*(double scale) {
|
||||
Coord result(x*scale, y*scale);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class PolarCoord {
|
||||
public:
|
||||
double radius;
|
||||
double angle; // degree
|
||||
|
||||
PolarCoord() : radius(1.), angle(0.) {}
|
||||
PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
|
||||
|
||||
void set (double radius, double angle) {
|
||||
this->radius = radius;
|
||||
this->angle = angle;
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord start, Coord end) {
|
||||
Coord delta(end.x-start.x, end.y-start.y);
|
||||
setFromCartesian(delta);
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord delta) {
|
||||
if (!delta.x && !delta.y) {
|
||||
// null vector, we set to a default value
|
||||
radius = 1.;
|
||||
angle = 0.;
|
||||
return;
|
||||
}
|
||||
double x_ = double(delta.x);
|
||||
double y_ = double(delta.y);
|
||||
radius = sqrt(x_*x_+y_*y_);
|
||||
if (delta.x>0.) {
|
||||
if (delta.y>=0.)
|
||||
angle = atan(y_/x_)/(2*M_PI)*360.;
|
||||
else if (delta.y<0.)
|
||||
angle = (atan(y_/x_)+2*M_PI)/(2*M_PI)*360.;
|
||||
}
|
||||
else if (delta.x<0.)
|
||||
angle = (atan(y_/x_)+M_PI)/(2*M_PI)*360.;
|
||||
else if (delta.x==0.) {
|
||||
if (delta.y>0.)
|
||||
angle = 90.;
|
||||
else
|
||||
angle = 270.;
|
||||
}
|
||||
}
|
||||
|
||||
void operator+=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator-=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator*=(double scale) {
|
||||
radius *= scale;
|
||||
}
|
||||
PolarCoord operator+(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
PolarCoord operator-(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
Coord operator*(double scale) {
|
||||
Coord result(radius*scale, angle);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
141
rtgui/edit.h
141
rtgui/edit.h
@@ -24,6 +24,7 @@
|
||||
#include "editid.h"
|
||||
#include "cursormanager.h"
|
||||
#include "../rtengine/rt_math.h"
|
||||
#include "coord.h"
|
||||
|
||||
class EditDataProvider;
|
||||
|
||||
@@ -60,146 +61,6 @@ class EditBuffer;
|
||||
*
|
||||
*/
|
||||
|
||||
class PolarCoord;
|
||||
|
||||
// Do not confuse with rtengine::Coord2D, this one is for the GUI
|
||||
class Coord {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Coord() : x(-1), y(-1) {}
|
||||
Coord(int x, int y) : x(x), y(y) {}
|
||||
|
||||
void set (int x, int y) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void setFromPolar(PolarCoord polar);
|
||||
|
||||
/// @brief Clip the coord to stay in the width x height bounds
|
||||
/// @return true if the x or y coordinate has changed
|
||||
bool clip(int width, int height) {
|
||||
int trimmedX = rtengine::LIM<int>(x, 0, width);
|
||||
int trimmedY = rtengine::LIM<int>(y, 0, height);
|
||||
bool retval = trimmedX!=x || trimmedY!=y;
|
||||
x = trimmedX;
|
||||
y = trimmedY;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void operator+=(const Coord & rhs) {
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
}
|
||||
void operator-=(const Coord & rhs) {
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
}
|
||||
void operator*=(double scale) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
Coord operator+(Coord & rhs) {
|
||||
Coord result(x+rhs.x, y+rhs.y);
|
||||
return result;
|
||||
}
|
||||
Coord operator-(Coord & rhs) {
|
||||
Coord result(x-rhs.x, y-rhs.y);
|
||||
return result;
|
||||
}
|
||||
Coord operator*(double scale) {
|
||||
Coord result(x*scale, y*scale);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class PolarCoord {
|
||||
public:
|
||||
double radius;
|
||||
double angle; // degree
|
||||
|
||||
PolarCoord() : radius(1.), angle(0.) {}
|
||||
PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
|
||||
|
||||
void set (double radius, double angle) {
|
||||
this->radius = radius;
|
||||
this->angle = angle;
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord start, Coord end) {
|
||||
Coord delta(end.x-start.x, end.y-start.y);
|
||||
setFromCartesian(delta);
|
||||
}
|
||||
|
||||
void setFromCartesian(Coord delta) {
|
||||
if (!delta.x && !delta.y) {
|
||||
// null vector, we set to a default value
|
||||
radius = 1.;
|
||||
angle = 0.;
|
||||
return;
|
||||
}
|
||||
double x_ = double(delta.x);
|
||||
double y_ = double(delta.y);
|
||||
radius = sqrt(x_*x_+y_*y_);
|
||||
if (delta.x>0.) {
|
||||
if (delta.y>=0.)
|
||||
angle = atan(y_/x_)/(2*M_PI)*360.;
|
||||
else if (delta.y<0.)
|
||||
angle = (atan(y_/x_)+2*M_PI)/(2*M_PI)*360.;
|
||||
}
|
||||
else if (delta.x<0.)
|
||||
angle = (atan(y_/x_)+M_PI)/(2*M_PI)*360.;
|
||||
else if (delta.x==0.) {
|
||||
if (delta.y>0.)
|
||||
angle = 90.;
|
||||
else
|
||||
angle = 270.;
|
||||
}
|
||||
}
|
||||
|
||||
void operator+=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator-=(const PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
setFromCartesian(thisCoord);
|
||||
}
|
||||
void operator*=(double scale) {
|
||||
radius *= scale;
|
||||
}
|
||||
PolarCoord operator+(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord += rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
PolarCoord operator-(PolarCoord & rhs) {
|
||||
Coord thisCoord, rhsCoord;
|
||||
thisCoord.setFromPolar(*this);
|
||||
rhsCoord.setFromPolar(rhs);
|
||||
thisCoord -= rhsCoord;
|
||||
PolarCoord result;
|
||||
result.setFromCartesian(thisCoord);
|
||||
return result;
|
||||
}
|
||||
Coord operator*(double scale) {
|
||||
Coord result(radius*scale, angle);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** @brief Coordinate system where the widgets will be drawn
|
||||
*
|
||||
|
||||
@@ -45,6 +45,7 @@ class FileBrowserListener {
|
||||
virtual void copyMoveRequested (std::vector<FileBrowserEntry*> tbe, bool moveRequested) {}
|
||||
virtual void selectionChanged (std::vector<Thumbnail*> tbe) {}
|
||||
virtual void clearFromCacheRequested(std::vector<FileBrowserEntry*> tbe, bool leavenotrace) {}
|
||||
virtual bool isInTabMode () { return false; }
|
||||
};
|
||||
|
||||
struct FileBrowserIdleHelper {
|
||||
@@ -166,6 +167,8 @@ class FileBrowser : public ThumbBrowserBase,
|
||||
void saveThumbnailHeight (int height);
|
||||
int getThumbnailHeight ();
|
||||
|
||||
bool isInTabMode() { return tbl ? tbl->isInTabMode() : false; }
|
||||
|
||||
void openNextImage ();
|
||||
void openPrevImage ();
|
||||
void copyProfile ();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "inspector.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@@ -34,7 +35,7 @@ Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::recentlySavedIcon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::enqueuedIcon;
|
||||
|
||||
FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname)
|
||||
: ThumbBrowserEntryBase (fname), iatlistener(NULL), cropgl(NULL), state(SNormal) {
|
||||
: ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(NULL), cropgl(NULL), state(SNormal) {
|
||||
thumbnail=thm;
|
||||
|
||||
feih = new FileBrowserEntryIdleHelper;
|
||||
@@ -261,6 +262,25 @@ bool FileBrowserEntry::motionNotify (int x, int y) {
|
||||
int ix = x - startx - ofsX;
|
||||
int iy = y - starty - ofsY;
|
||||
|
||||
Inspector* inspector = parent->getInspector();
|
||||
if (inspector && inspector->isActive() && !parent->isInTabMode()) {
|
||||
rtengine::Coord2D coord(-1.,-1.);
|
||||
getPosInImgSpace(x, y, coord);
|
||||
if (coord.x != -1.) {
|
||||
if (!wasInside) {
|
||||
inspector->switchImage(filename);
|
||||
}
|
||||
wasInside = true;
|
||||
inspector->mouseMove(coord, 0);
|
||||
}
|
||||
else {
|
||||
if (wasInside) {
|
||||
wasInside = false;
|
||||
rtengine::Coord2D coord(-1,-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inside (x,y))
|
||||
updateCursor (ix, iy);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ class FileBrowserEntry : public ThumbBrowserEntryBase,
|
||||
|
||||
double scale;
|
||||
static bool iconsLoaded;
|
||||
bool wasInside;
|
||||
ImageAreaToolListener* iatlistener;
|
||||
int press_x, press_y, action_x, action_y;
|
||||
double rot_deg;
|
||||
|
||||
@@ -60,7 +60,7 @@ class FilePanel;
|
||||
class FileCatalog : public Gtk::VBox,
|
||||
public DirSelectionListener,
|
||||
public PreviewLoaderListener,
|
||||
public FilterPanelListener,
|
||||
public FilterPanelListener,
|
||||
public FileBrowserListener,
|
||||
public ExportPanelListener
|
||||
#ifdef WIN32
|
||||
@@ -181,6 +181,10 @@ class FileCatalog : public Gtk::VBox,
|
||||
void previewsFinishedUI ();
|
||||
void _refreshProgressBar ();
|
||||
|
||||
void setInspector(Inspector* inspector) { if (fileBrowser) fileBrowser->setInspector(inspector); }
|
||||
void disableInspector() { if (fileBrowser) fileBrowser->disableInspector(); }
|
||||
void enableInspector() { if (fileBrowser) fileBrowser->enableInspector(); }
|
||||
|
||||
// filterpanel interface
|
||||
void exifFilterChanged ();
|
||||
|
||||
@@ -245,6 +249,8 @@ class FileCatalog : public Gtk::VBox,
|
||||
|
||||
bool handleShortcutKey (GdkEventKey* event);
|
||||
|
||||
bool isInTabMode() { return inTabMode; }
|
||||
|
||||
bool CheckSidePanelsVisibility();
|
||||
void toggleSidePanels();
|
||||
void toggleLeftPanel();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "filepanel.h"
|
||||
#include "rtwindow.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "inspector.h"
|
||||
|
||||
int FilePanelInitUI (void* data) {
|
||||
(static_cast<FilePanel*>(data))->init ();
|
||||
@@ -68,6 +69,7 @@ FilePanel::FilePanel () : parent(NULL) {
|
||||
rightBox = Gtk::manage ( new Gtk::HBox () );
|
||||
rightBox->set_size_request(50,100);
|
||||
rightNotebook = Gtk::manage ( new Gtk::Notebook () );
|
||||
rightNotebook->signal_switch_page().connect_notify( sigc::mem_fun(*this, &FilePanel::on_NB_switch_page) );
|
||||
//Gtk::VBox* taggingBox = Gtk::manage ( new Gtk::VBox () );
|
||||
|
||||
history = Gtk::manage ( new History (false) );
|
||||
@@ -80,6 +82,9 @@ FilePanel::FilePanel () : parent(NULL) {
|
||||
sFilterPanel->add (*filterPanel);
|
||||
sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
inspectorPanel = new Inspector();
|
||||
fileCatalog->setInspector(inspectorPanel);
|
||||
|
||||
Gtk::ScrolledWindow* sExportPanel = Gtk::manage ( new Gtk::ScrolledWindow() );
|
||||
exportPanel = Gtk::manage ( new ExportPanel () );
|
||||
sExportPanel->add (*exportPanel);
|
||||
@@ -96,6 +101,8 @@ FilePanel::FilePanel () : parent(NULL) {
|
||||
|
||||
Gtk::Label* devLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_DEVELOP")) );
|
||||
devLab->set_angle (90);
|
||||
Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) );
|
||||
inspectLab->set_angle (90);
|
||||
Gtk::Label* filtLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_FILTER")) );
|
||||
filtLab->set_angle (90);
|
||||
//Gtk::Label* tagLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_TAGGING")) );
|
||||
@@ -108,6 +115,7 @@ FilePanel::FilePanel () : parent(NULL) {
|
||||
tpcPaned->pack2 (*history, true, true);
|
||||
|
||||
rightNotebook->append_page (*tpcPaned, *devLab);
|
||||
rightNotebook->append_page (*inspectorPanel, *inspectLab);
|
||||
rightNotebook->append_page (*sFilterPanel, *filtLab);
|
||||
//rightNotebook->append_page (*taggingBox, *tagLab); commented out: currently the tab is empty ...
|
||||
rightNotebook->append_page (*sExportPanel, *exportLab);
|
||||
@@ -125,6 +133,11 @@ FilePanel::FilePanel () : parent(NULL) {
|
||||
show_all ();
|
||||
}
|
||||
|
||||
FilePanel::~FilePanel () {
|
||||
if (inspectorPanel)
|
||||
delete inspectorPanel;
|
||||
}
|
||||
|
||||
void FilePanel::setAspect () {
|
||||
int winW, winH;
|
||||
parent->get_size(winW, winH);
|
||||
@@ -160,7 +173,18 @@ void FilePanel::init () {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FilePanel::on_NB_switch_page(GtkNotebookPage* page, guint page_num) {
|
||||
if (page_num == 1) {
|
||||
// switching the inspector "on"
|
||||
fileCatalog->enableInspector();
|
||||
}
|
||||
else {
|
||||
// switching the inspector "off"
|
||||
fileCatalog->disableInspector();
|
||||
}
|
||||
}
|
||||
|
||||
bool FilePanel::fileSelected (Thumbnail* thm) {
|
||||
|
||||
|
||||
@@ -44,11 +44,12 @@ class FilePanel : public Gtk::HPaned,
|
||||
RecentBrowser* recentBrowser;
|
||||
// FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it
|
||||
|
||||
Inspector* inspectorPanel;
|
||||
Gtk::VPaned* tpcPaned;
|
||||
BatchToolPanelCoordinator* tpc;
|
||||
History* history;
|
||||
//FilterPanel* filterPanel;
|
||||
RTWindow* parent;
|
||||
//FilterPanel* filterPanel;
|
||||
RTWindow* parent;
|
||||
Gtk::Notebook* rightNotebook;
|
||||
|
||||
struct pendingLoad {
|
||||
@@ -56,12 +57,16 @@ class FilePanel : public Gtk::HPaned,
|
||||
ProgressConnector<rtengine::InitialImage*> *pc;
|
||||
Thumbnail *thm;
|
||||
};
|
||||
MyMutex pendingLoadMutex;
|
||||
MyMutex pendingLoadMutex;
|
||||
std::vector<struct pendingLoad*> pendingLoads;
|
||||
|
||||
int error;
|
||||
|
||||
void on_NB_switch_page(GtkNotebookPage* page, guint page_num);
|
||||
|
||||
public:
|
||||
FilePanel ();
|
||||
~FilePanel ();
|
||||
|
||||
Gtk::Paned* placespaned;
|
||||
Gtk::HPaned* dirpaned;
|
||||
@@ -80,10 +85,10 @@ class FilePanel : public Gtk::HPaned,
|
||||
void open (const Glib::ustring& d); // open a file or a directory
|
||||
void refreshEditedState (const std::set<Glib::ustring>& efiles) { fileCatalog->refreshEditedState (efiles); }
|
||||
void loadingThumbs(Glib::ustring str, double rate);
|
||||
|
||||
// call this before closeing rt: it saves file browser relating things into options
|
||||
|
||||
// call this before closing RT: it saves file browser's related things into options
|
||||
void saveOptions ();
|
||||
|
||||
|
||||
// interface fileselectionlistener
|
||||
bool fileSelected (Thumbnail* thm);
|
||||
bool addBatchQueueJobs ( std::vector<BatchQueueEntry*> &entries );
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "guiutils.h"
|
||||
#include "options.h"
|
||||
#include "../rtengine/rt_math.h"
|
||||
#include "../rtengine/utils.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "rtimage.h"
|
||||
@@ -540,12 +541,18 @@ void TextOrIcon::switchTo(TOITypes type) {
|
||||
show_all();
|
||||
}
|
||||
|
||||
BackBuffer::BackBuffer() {
|
||||
x = y = w = h = 0;
|
||||
dirty = true;
|
||||
BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0,0), dirty(true) {}
|
||||
|
||||
void BackBuffer::setSrcOffset(int x, int y) {
|
||||
// values will be clamped when used...
|
||||
offset.x = x;
|
||||
offset.y = y;
|
||||
}
|
||||
|
||||
bool BackBuffer::setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, int newY, int newW, int newH) {
|
||||
// Note: newW & newH must be > 0
|
||||
bool BackBuffer::setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, int newY, int newW, int newH, bool updateBackBufferSize) {
|
||||
assert(newW && newH);
|
||||
|
||||
bool newSize = w!=newW || h!=newH;
|
||||
|
||||
x = newX;
|
||||
@@ -554,17 +561,31 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, in
|
||||
h = newH;
|
||||
|
||||
// WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!?
|
||||
if (newSize && window) {
|
||||
if (updateBackBufferSize && newSize && window) {
|
||||
// allocate a new Surface
|
||||
if (newW>0 && newH>0) {
|
||||
surface = window->create_similar_surface(Cairo::CONTENT_COLOR, w, h);
|
||||
}
|
||||
else {
|
||||
// at least one dimension is null, so we delete the Surface
|
||||
surface.clear();
|
||||
// and we reset all dimensions
|
||||
x = y = w = h = 0;
|
||||
}
|
||||
surface.clear(); // ... don't know if this is necessary?
|
||||
surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h);
|
||||
dirty = true;
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
|
||||
// Note: newW & newH must be > 0
|
||||
bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize) {
|
||||
assert(!newW && !newH);
|
||||
|
||||
bool newSize = w!=newW || h!=newH;
|
||||
|
||||
x = newX;
|
||||
y = newY;
|
||||
w = newW;
|
||||
h = newH;
|
||||
|
||||
// WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!?
|
||||
if (updateBackBufferSize && newSize) {
|
||||
// allocate a new Surface
|
||||
surface.clear(); // ... don't know if this is necessary?
|
||||
surface = Cairo::ImageSurface::create(format, w, h);
|
||||
dirty = true;
|
||||
}
|
||||
return dirty;
|
||||
@@ -579,9 +600,13 @@ void BackBuffer::copySurface(Glib::RefPtr<Gdk::Window> window, GdkRectangle *rec
|
||||
Cairo::RefPtr<Cairo::Context> crSrc = window->create_cairo_context();
|
||||
Cairo::RefPtr<Cairo::Surface> destSurface = crSrc->get_target();
|
||||
|
||||
// compute the source offset
|
||||
int offsetX = rtengine::LIM<int>(offset.x,0, surface->get_width());
|
||||
int offsetY = rtengine::LIM<int>(offset.y,0, surface->get_height());
|
||||
|
||||
// now copy the off-screen Surface to the destination Surface
|
||||
Cairo::RefPtr<Cairo::Context> crDest = Cairo::Context::create(destSurface);
|
||||
crDest->set_source(surface, x, y);
|
||||
crDest->set_source(surface, x-offsetX, y-offsetY);
|
||||
crDest->set_line_width(0.);
|
||||
if (rectangle)
|
||||
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
|
||||
@@ -596,9 +621,13 @@ void BackBuffer::copySurface(Glib::RefPtr<Gdk::Window> window, GdkRectangle *rec
|
||||
*/
|
||||
void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle) {
|
||||
if (surface && destBackBuffer) {
|
||||
// compute the source offset
|
||||
int offsetX = rtengine::LIM<int>(offset.x,0, surface->get_width());
|
||||
int offsetY = rtengine::LIM<int>(offset.y,0, surface->get_height());
|
||||
|
||||
// now copy the off-screen Surface to the destination Surface
|
||||
Cairo::RefPtr<Cairo::Context> crDest = Cairo::Context::create(destBackBuffer->getSurface());
|
||||
crDest->set_source(surface, x, y);
|
||||
crDest->set_source(surface, x-offsetX, y-offsetY);
|
||||
crDest->set_line_width(0.);
|
||||
if (rectangle)
|
||||
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
|
||||
@@ -611,11 +640,15 @@ void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle
|
||||
/*
|
||||
* Copy the BackBuffer to another Cairo::Surface
|
||||
*/
|
||||
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::Surface> destSurface, GdkRectangle *rectangle) {
|
||||
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle) {
|
||||
if (surface && destSurface) {
|
||||
// compute the source offset
|
||||
int offsetX = rtengine::LIM<int>(offset.x,0, surface->get_width());
|
||||
int offsetY = rtengine::LIM<int>(offset.y,0, surface->get_height());
|
||||
|
||||
// now copy the off-screen Surface to the destination Surface
|
||||
Cairo::RefPtr<Cairo::Context> crDest = Cairo::Context::create(destSurface);
|
||||
crDest->set_source(surface, x, y);
|
||||
crDest->set_source(surface, x-offsetX, y-offsetY);
|
||||
crDest->set_line_width(0.);
|
||||
if (rectangle)
|
||||
crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
|
||||
|
||||
@@ -265,29 +265,34 @@ class BackBuffer {
|
||||
|
||||
protected:
|
||||
int x, y, w, h; // Rectangle where the colored bar has to be drawn
|
||||
Cairo::RefPtr<Cairo::Surface> surface;
|
||||
Point<int> offset; // Offset of the source region to draw, relative to the top left corner
|
||||
Cairo::RefPtr<Cairo::ImageSurface> surface;
|
||||
bool dirty; // mean that the Surface has to be (re)allocated
|
||||
|
||||
public:
|
||||
BackBuffer();
|
||||
|
||||
// set the destination drawing rectangle; return true if the dimensions are different
|
||||
bool setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, int newY, int newW, int newH);
|
||||
// Note: newW & newH must be > 0
|
||||
bool setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true);
|
||||
bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true);
|
||||
void setSrcOffset(int x, int y);
|
||||
|
||||
void copySurface(Glib::RefPtr<Gdk::Window> window, GdkRectangle *rectangle=NULL);
|
||||
void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle=NULL);
|
||||
void copySurface(Cairo::RefPtr<Cairo::Surface> destSurface, GdkRectangle *rectangle=NULL);
|
||||
void copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle=NULL);
|
||||
|
||||
void setDirty(bool isDirty) { dirty = isDirty; if (!dirty && !surface) dirty = true; }
|
||||
bool isDirty() { return dirty; }
|
||||
// you have to check if the surface is created thanks to surfaceCreated before starting to draw on it
|
||||
bool surfaceCreated() { return surface; }
|
||||
Cairo::RefPtr<Cairo::Surface> getSurface() { return surface; }
|
||||
void deleteSurface() { surface.clear(); dirty=true; }
|
||||
Cairo::RefPtr<Cairo::ImageSurface> getSurface() { return surface; }
|
||||
void setSurface(Cairo::RefPtr<Cairo::ImageSurface> surf) { surface = surf; }
|
||||
void deleteSurface() { if (surface) surface.clear(); dirty=true; }
|
||||
// will let you get a Cairo::Context for Cairo drawing operations
|
||||
Cairo::RefPtr<Cairo::Context> getContext() { return Cairo::Context::create(surface); }
|
||||
int getWidth() { return w; }
|
||||
int getHeight() { return h; }
|
||||
int getWidth() { return surface ? surface->get_width() : 0; }
|
||||
int getHeight() { return surface ? surface->get_height() : 0; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
262
rtgui/inspector.cc
Normal file
262
rtgui/inspector.cc
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "inspector.h"
|
||||
#include "guiutils.h"
|
||||
#include <gtkmm.h>
|
||||
#include "cursormanager.h"
|
||||
#include "guiutils.h"
|
||||
#include "options.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "../rtengine/previewimage.h"
|
||||
|
||||
extern Options options;
|
||||
|
||||
InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform(0), fromRaw(false) {
|
||||
if (!imagePath.empty() && safe_file_test(imagePath, Glib::FILE_TEST_EXISTS) && !safe_file_test(imagePath, Glib::FILE_TEST_IS_DIR)) {
|
||||
imgPath = imagePath;
|
||||
|
||||
// generate thumbnail image
|
||||
Glib::ustring ext = getExtension (imagePath);
|
||||
if (ext=="") {
|
||||
imgPath.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
rtengine::PreviewImage pi(imagePath, ext, rtengine::PreviewImage::PIM_EmbeddedOrRaw);
|
||||
Cairo::RefPtr<Cairo::ImageSurface> imageSurface = pi.getImage();
|
||||
|
||||
if (imageSurface) {
|
||||
imgBuffer.setSurface(imageSurface);
|
||||
fromRaw = true;
|
||||
}
|
||||
else {
|
||||
imgPath.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
InspectorBuffer::~InspectorBuffer() {
|
||||
}
|
||||
*/
|
||||
|
||||
int InspectorBuffer::infoFromImage (const Glib::ustring& fname) {
|
||||
|
||||
rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, NULL);
|
||||
if (!idata)
|
||||
return 0;
|
||||
|
||||
int deg = 0;
|
||||
if (idata->hasExif()) {
|
||||
if (idata->getOrientation()=="Rotate 90 CW" ) deg = 90;
|
||||
else if (idata->getOrientation()=="Rotate 180" ) deg = 180;
|
||||
else if (idata->getOrientation()=="Rotate 270 CW") deg = 270;
|
||||
}
|
||||
delete idata;
|
||||
return deg;
|
||||
}
|
||||
|
||||
Inspector::Inspector () : currImage(NULL), zoom(0.0), active(false) {}
|
||||
|
||||
Inspector::~Inspector() {
|
||||
deleteBuffers();
|
||||
}
|
||||
|
||||
bool Inspector::on_expose_event (GdkEventExpose* event) {
|
||||
|
||||
Glib::RefPtr<Gdk::Window> win = get_window();
|
||||
if (!win)
|
||||
return false;
|
||||
|
||||
if (!active) {
|
||||
active = true;
|
||||
}
|
||||
|
||||
|
||||
// cleanup the region
|
||||
|
||||
|
||||
if (currImage && currImage->imgBuffer.surfaceCreated()) {
|
||||
// this will eventually create/update the off-screen pixmap
|
||||
|
||||
// compute the displayed area
|
||||
Coord availableSize;
|
||||
Coord topLeft;
|
||||
Coord displayedSize;
|
||||
Coord dest(0, 0);
|
||||
win->get_size(availableSize.x, availableSize.y);
|
||||
int imW = currImage->imgBuffer.getWidth();
|
||||
int imH = currImage->imgBuffer.getHeight();
|
||||
|
||||
if (imW < availableSize.x) {
|
||||
// center the image in the available space along X
|
||||
topLeft.x = 0;
|
||||
displayedSize.x = availableSize.x;
|
||||
dest.x = (availableSize.x - imW) / 2;
|
||||
}
|
||||
else {
|
||||
// partial image display
|
||||
// double clamp
|
||||
topLeft.x = center.x + availableSize.x/2;
|
||||
topLeft.x = rtengine::min<int>(topLeft.x, imW);
|
||||
topLeft.x -= availableSize.x;
|
||||
topLeft.x = rtengine::max<int>(topLeft.x, 0);
|
||||
}
|
||||
|
||||
if (imH < availableSize.y) {
|
||||
// center the image in the available space along Y
|
||||
topLeft.y = 0;
|
||||
displayedSize.y = availableSize.y;
|
||||
dest.y = (availableSize.y - imH) / 2;
|
||||
}
|
||||
else {
|
||||
// partial image display
|
||||
// double clamp
|
||||
topLeft.y = center.y + availableSize.y/2;
|
||||
topLeft.y = rtengine::min<int>(topLeft.y, imH);
|
||||
topLeft.y -= availableSize.y;
|
||||
topLeft.y = rtengine::max<int>(topLeft.y, 0);
|
||||
}
|
||||
|
||||
//printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y);
|
||||
|
||||
// define the destination area
|
||||
currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min<int>(availableSize.x-dest.x, imW), rtengine::min<int>(availableSize.y-dest.y,imH), false);
|
||||
currImage->imgBuffer.setSrcOffset(topLeft.x, topLeft.y);
|
||||
|
||||
if (!currImage->imgBuffer.surfaceCreated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draw!
|
||||
|
||||
Gdk::Color c;
|
||||
Cairo::RefPtr<Cairo::Context> cr = win->create_cairo_context();
|
||||
Glib::RefPtr<Gtk::Style> style = get_style();
|
||||
|
||||
// draw the background
|
||||
c = style->get_bg (Gtk::STATE_NORMAL);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->set_line_width (0);
|
||||
cr->rectangle (0, 0, availableSize.x, availableSize.y);
|
||||
cr->fill ();
|
||||
|
||||
currImage->imgBuffer.copySurface(win);
|
||||
|
||||
// draw the frame
|
||||
c = style->get_fg (Gtk::STATE_NORMAL);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->set_line_width (1);
|
||||
cr->rectangle (0.5, 0.5, availableSize.x-1, availableSize.y-1);
|
||||
cr->stroke ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Inspector::mouseMove (rtengine::Coord2D pos, int transform) {
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
if (currImage)
|
||||
center.set(int(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth())), int(rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight())));
|
||||
else
|
||||
center.set(0,0);
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
void Inspector::switchImage (const Glib::ustring &fullPath) {
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
// we first check the size of the list, it may have been changed in Preference
|
||||
if (images.size() > size_t(options.maxInspectorBuffers)) {
|
||||
// deleting the last entries
|
||||
for (size_t i=images.size()-1; i>size_t(options.maxInspectorBuffers-1); --i) {
|
||||
delete images.at(i);
|
||||
images.at(i) = NULL;
|
||||
}
|
||||
// resizing down
|
||||
images.resize(options.maxInspectorBuffers);
|
||||
}
|
||||
|
||||
if (fullPath.empty()) {
|
||||
currImage = NULL;
|
||||
queue_draw();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
bool found = false;
|
||||
for (size_t i=0; i<images.size(); ++i) {
|
||||
if (images.at(i) != NULL && images.at(i)->imgPath==fullPath) {
|
||||
currImage = images.at(i);
|
||||
|
||||
// rolling the list 1 step to the beginning
|
||||
for (size_t j=i; j<images.size()-1; ++j) {
|
||||
images.at(j) = images.at(j+1);
|
||||
}
|
||||
images.at(images.size()-1) = currImage; // move the last used image to the tail
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (images.size() == size_t(options.maxInspectorBuffers)) {
|
||||
// The list is full, delete the first entry
|
||||
delete images.at(0);
|
||||
images.erase(images.begin());
|
||||
}
|
||||
// Loading a new image
|
||||
InspectorBuffer *iBuffer = new InspectorBuffer(fullPath);
|
||||
// and add it to the tail
|
||||
if (!iBuffer->imgPath.empty()) {
|
||||
images.push_back(iBuffer);
|
||||
currImage = images.at(images.size()-1);
|
||||
}
|
||||
else {
|
||||
currImage = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Inspector::deleteBuffers () {
|
||||
for (size_t i=0; i<images.size(); ++i) {
|
||||
if (images.at(i) != NULL) {
|
||||
delete images.at(i);
|
||||
images.at(i) = NULL;
|
||||
}
|
||||
}
|
||||
images.resize(0);
|
||||
currImage = NULL;
|
||||
}
|
||||
|
||||
void Inspector::flushBuffers () {
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
deleteBuffers();
|
||||
}
|
||||
|
||||
void Inspector::setActive(bool state) {
|
||||
if (!state) {
|
||||
flushBuffers();
|
||||
}
|
||||
active = state;
|
||||
}
|
||||
|
||||
86
rtgui/inspector.h
Normal file
86
rtgui/inspector.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _INSPECTOR_
|
||||
#define _INSPECTOR_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include "guiutils.h"
|
||||
#include "coord.h"
|
||||
|
||||
class InspectorBuffer {
|
||||
private:
|
||||
int infoFromImage (const Glib::ustring& fname);
|
||||
|
||||
public:
|
||||
BackBuffer imgBuffer;
|
||||
Glib::ustring imgPath;
|
||||
int currTransform; // coarse rotation from RT, not from shot orientation
|
||||
bool fromRaw;
|
||||
|
||||
InspectorBuffer(const Glib::ustring &imgagePath);
|
||||
//~InspectorBuffer();
|
||||
};
|
||||
|
||||
class Inspector : public Gtk::DrawingArea {
|
||||
|
||||
private:
|
||||
Coord center;
|
||||
std::vector<InspectorBuffer*> images;
|
||||
InspectorBuffer* currImage;
|
||||
double zoom;
|
||||
bool active;
|
||||
|
||||
bool on_expose_event (GdkEventExpose* event);
|
||||
void deleteBuffers();
|
||||
|
||||
public:
|
||||
Inspector();
|
||||
~Inspector();
|
||||
|
||||
/** @brief Mouse movement to a new position
|
||||
* @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image
|
||||
* @param transform H/V flip and coarse rotation transformation
|
||||
*/
|
||||
void mouseMove (rtengine::Coord2D pos, int transform);
|
||||
|
||||
/** @brief A new image is being flown over
|
||||
* @param fullPath Full path of the image that is being hovered inspect, or an empty string if out of any image.
|
||||
*/
|
||||
void switchImage (const Glib::ustring &fullPath);
|
||||
|
||||
/** @brief Set the new coarse rotation transformation
|
||||
* @param transform A semi-bitfield coarse transformation using #defines from iimage.h
|
||||
*/
|
||||
void setTransformation (int transform);
|
||||
|
||||
/** @brief Use this method to flush all image buffer whenever the Inspector panel is hidden
|
||||
*/
|
||||
void flushBuffers ();
|
||||
|
||||
/** @brief Set the inspector on/off
|
||||
* @param state true if to activate the Inspector, false to disable it and flush the buffers
|
||||
*/
|
||||
void setActive(bool state);
|
||||
|
||||
/** @brief Get the on/off state
|
||||
*/
|
||||
bool isActive() { return active; };
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -360,11 +360,12 @@ void Options::setDefaults () {
|
||||
|
||||
rgbDenoiseThreadLimit = 0;
|
||||
#if defined( _OPENMP ) && defined( __x86_64__ )
|
||||
clutCacheSize = omp_get_num_procs();
|
||||
clutCacheSize = omp_get_num_procs();
|
||||
#else
|
||||
clutCacheSize = 1;
|
||||
clutCacheSize = 1;
|
||||
#endif
|
||||
filledProfile = false;
|
||||
filledProfile = false;
|
||||
maxInspectorBuffers = 2; // a rather conservative value for low specced systems...
|
||||
|
||||
showProfileSelector = true;
|
||||
FileBrowserToolbarSingleRow = false;
|
||||
@@ -735,17 +736,18 @@ if (keyFile.has_group ("Clipping Indication")) {
|
||||
}
|
||||
|
||||
if (keyFile.has_group ("Performance")) {
|
||||
if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit");
|
||||
if( keyFile.has_key ("Performance", "NRauto")) rtSettings.nrauto = keyFile.get_double("Performance", "NRauto");
|
||||
if( keyFile.has_key ("Performance", "NRautomax")) rtSettings.nrautomax = keyFile.get_double("Performance", "NRautomax");
|
||||
if( keyFile.has_key ("Performance", "NRhigh")) rtSettings.nrhigh = keyFile.get_double("Performance", "NRhigh");
|
||||
if( keyFile.has_key ("Performance", "NRWavlevel")) rtSettings.nrwavlevel = keyFile.get_integer("Performance", "NRWavlevel");
|
||||
if (keyFile.has_key ("Performance", "LevNR")) rtSettings.leveldnv = keyFile.get_integer("Performance", "LevNR");
|
||||
if (keyFile.has_key ("Performance", "LevNRTI")) rtSettings.leveldnti = keyFile.get_integer("Performance", "LevNRTI");
|
||||
if (keyFile.has_key ("Performance", "LevNRAUT")) rtSettings.leveldnaut = keyFile.get_integer("Performance", "LevNRAUT");
|
||||
if (keyFile.has_key ("Performance", "LevNRLISS")) rtSettings.leveldnliss = keyFile.get_integer("Performance", "LevNRLISS");
|
||||
if (keyFile.has_key ("Performance", "SIMPLNRAUT")) rtSettings.leveldnautsimpl = keyFile.get_integer("Performance", "SIMPLNRAUT");
|
||||
if (keyFile.has_key ("Performance", "ClutCacheSize")) clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize");
|
||||
if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit");
|
||||
if( keyFile.has_key ("Performance", "NRauto")) rtSettings.nrauto = keyFile.get_double ("Performance", "NRauto");
|
||||
if( keyFile.has_key ("Performance", "NRautomax")) rtSettings.nrautomax = keyFile.get_double ("Performance", "NRautomax");
|
||||
if( keyFile.has_key ("Performance", "NRhigh")) rtSettings.nrhigh = keyFile.get_double ("Performance", "NRhigh");
|
||||
if( keyFile.has_key ("Performance", "NRWavlevel")) rtSettings.nrwavlevel = keyFile.get_integer ("Performance", "NRWavlevel");
|
||||
if (keyFile.has_key ("Performance", "LevNR")) rtSettings.leveldnv = keyFile.get_integer ("Performance", "LevNR");
|
||||
if (keyFile.has_key ("Performance", "LevNRTI")) rtSettings.leveldnti = keyFile.get_integer ("Performance", "LevNRTI");
|
||||
if (keyFile.has_key ("Performance", "LevNRAUT")) rtSettings.leveldnaut = keyFile.get_integer ("Performance", "LevNRAUT");
|
||||
if (keyFile.has_key ("Performance", "LevNRLISS")) rtSettings.leveldnliss = keyFile.get_integer ("Performance", "LevNRLISS");
|
||||
if (keyFile.has_key ("Performance", "SIMPLNRAUT")) rtSettings.leveldnautsimpl = keyFile.get_integer ("Performance", "SIMPLNRAUT");
|
||||
if (keyFile.has_key ("Performance", "ClutCacheSize")) clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize");
|
||||
if (keyFile.has_key ("Performance", "MaxInspectorBuffers")) maxInspectorBuffers = keyFile.get_integer ("Performance", "MaxInspectorBuffers");
|
||||
}
|
||||
|
||||
if (keyFile.has_group ("GUI")) {
|
||||
@@ -811,12 +813,12 @@ if (keyFile.has_group ("Color Management")) {
|
||||
|
||||
if (keyFile.has_key ("Color Management", "Intent")) rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent");
|
||||
if (keyFile.has_key ("Color Management", "CRI")) rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI");
|
||||
if (keyFile.has_key ("Color Management", "DenoiseLabgamma"))rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma");
|
||||
if (keyFile.has_key ("Color Management", "DenoiseLabgamma"))rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma");
|
||||
if (keyFile.has_key ("Color Management", "view")) rtSettings.viewingdevice = keyFile.get_integer("Color Management", "view");
|
||||
if (keyFile.has_key ("Color Management", "grey")) rtSettings.viewingdevicegrey = keyFile.get_integer("Color Management", "grey");
|
||||
if (keyFile.has_key ("Color Management", "greySc")) rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc");
|
||||
if (keyFile.has_key ("Color Management", "greySc")) rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc");
|
||||
if (keyFile.has_key ("Color Management", "CBDLArtif")) rtSettings.artifact_cbdl = keyFile.get_double("Color Management", "CBDLArtif");
|
||||
if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0");
|
||||
if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0");
|
||||
if (keyFile.has_key ("Color Management", "CBDLlevel123")) rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123");
|
||||
// if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab");
|
||||
// if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction");
|
||||
@@ -1017,17 +1019,18 @@ int Options::saveToFile (Glib::ustring fname) {
|
||||
keyFile.set_integer ("Clipping Indication", "ShadowThreshold", shadowThreshold);
|
||||
keyFile.set_boolean ("Clipping Indication", "BlinkClipped", blinkClipped);
|
||||
|
||||
keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit);
|
||||
keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit);
|
||||
keyFile.set_double ("Performance", "NRauto", rtSettings.nrauto);
|
||||
keyFile.set_double ("Performance", "NRautomax", rtSettings.nrautomax);
|
||||
keyFile.set_double ("Performance", "NRhigh", rtSettings.nrhigh);
|
||||
keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel);
|
||||
keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv);
|
||||
keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti);
|
||||
keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut);
|
||||
keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss);
|
||||
keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl);
|
||||
keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel);
|
||||
keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv);
|
||||
keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti);
|
||||
keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut);
|
||||
keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss);
|
||||
keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl);
|
||||
keyFile.set_integer ("Performance", "ClutCacheSize", clutCacheSize);
|
||||
keyFile.set_integer ("Performance", "MaxInspectorBuffers", maxInspectorBuffers);
|
||||
|
||||
keyFile.set_string ("Output", "Format", saveFormat.format);
|
||||
keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality);
|
||||
@@ -1128,8 +1131,8 @@ int Options::saveToFile (Glib::ustring fname) {
|
||||
keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut);
|
||||
keyFile.set_integer ("Color Management", "Intent", rtSettings.colorimetricIntent);
|
||||
keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice);
|
||||
keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
|
||||
keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
|
||||
keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
|
||||
keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
|
||||
|
||||
keyFile.set_string ("Color Management", "AdobeRGB", rtSettings.adobe);
|
||||
keyFile.set_string ("Color Management", "ProPhoto", rtSettings.prophoto);
|
||||
|
||||
@@ -219,7 +219,8 @@ class Options {
|
||||
|
||||
// Performance options
|
||||
int rgbDenoiseThreadLimit; // maximum number of threads for the denoising tool ; 0 = use the maximum available
|
||||
int clutCacheSize;
|
||||
int maxInspectorBuffers; // maximum number of buffers (i.e. images) for the Inspector feature
|
||||
int clutCacheSize;
|
||||
bool filledProfile; // Used as reminder for the ProfilePanel "mode"
|
||||
|
||||
bool menuGroupRank;
|
||||
|
||||
@@ -493,14 +493,14 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
|
||||
}
|
||||
|
||||
Gtk::Widget* Preferences::getPerformancePanel () {
|
||||
Gtk::VBox* mvbsd = Gtk::manage( new Gtk::VBox () );
|
||||
Gtk::VBox* vbdenoise = Gtk::manage( new Gtk::VBox () );
|
||||
|
||||
Gtk::Frame* fdenoise = Gtk::manage( new Gtk::Frame (M("PREFERENCES_NOISE")) );
|
||||
|
||||
Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () );
|
||||
Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () );
|
||||
mainContainer->set_border_width (4);
|
||||
|
||||
mainContainer->set_spacing(4);
|
||||
|
||||
mainContainer->set_spacing(4);
|
||||
|
||||
Gtk::HBox* threadLimitHB = Gtk::manage( new Gtk::HBox () );
|
||||
threadLimitHB->set_border_width(4);
|
||||
@@ -579,9 +579,13 @@ Gtk::Widget* Preferences::getPerformancePanel () {
|
||||
colon->attach (*dnwavlab, 0, 1, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
colon->attach (*dnwavlev, 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
|
||||
colon->attach (*restartNeeded7, 2, 3, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
|
||||
mainContainer->pack_start (*colon, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
|
||||
vbdenoise->pack_start (*colon, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
vbdenoise->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4);
|
||||
fdenoise->add (*vbdenoise);
|
||||
mainContainer->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
/* Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB")+":", Gtk::ALIGN_LEFT));
|
||||
|
||||
dnti = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
@@ -591,14 +595,9 @@ Gtk::Widget* Preferences::getPerformancePanel () {
|
||||
colon2->attach (*dntilab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
colon2->attach (*dnti, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
|
||||
colon2->attach (*restartNeeded4, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
mainContainer->pack_start (*colon2, Gtk::PACK_SHRINK, 4);
|
||||
vbdenoise->pack_start (*colon2, Gtk::PACK_SHRINK, 4);
|
||||
*/
|
||||
|
||||
mainContainer->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4);
|
||||
fdenoise->add (*mainContainer);
|
||||
mvbsd->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
|
||||
|
||||
Gtk::Frame* fclut = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CLUTSCACHE")) );
|
||||
|
||||
Gtk::HBox* clutCacheSizeHB = Gtk::manage( new Gtk::HBox () );
|
||||
@@ -619,14 +618,29 @@ Gtk::Widget* Preferences::getPerformancePanel () {
|
||||
|
||||
clutCacheSizeHB->pack_start (*CLUTLl, Gtk::PACK_SHRINK, 0);
|
||||
clutCacheSizeHB->pack_end (*clutCacheSizeSB, Gtk::PACK_SHRINK, 0);
|
||||
fclut->add (*clutCacheSizeHB);
|
||||
|
||||
|
||||
mvbsd->pack_start (*fclut, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
// return mainContainer;
|
||||
return mvbsd;
|
||||
|
||||
fclut->add (*clutCacheSizeHB);
|
||||
mainContainer->pack_start (*fclut, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
Gtk::Frame* finspect = Gtk::manage( new Gtk::Frame (M("PREFERENCES_INSPECT_LABEL")) );
|
||||
|
||||
Gtk::HBox* maxIBuffersHB = Gtk::manage( new Gtk::HBox () );
|
||||
maxIBuffersHB->set_border_width(4);
|
||||
maxIBuffersHB->set_spacing(4);
|
||||
maxIBuffersHB->set_tooltip_text(M("PREFERENCES_INSPECT_MAXBUFFERS_TOOLTIP"));
|
||||
Gtk::Label* maxIBufferLbl = Gtk::manage( new Gtk::Label (M("PREFERENCES_INSPECT_MAXBUFFERS_LABEL") + ":", Gtk::ALIGN_LEFT));
|
||||
maxInspectorBuffersSB = Gtk::manage( new Gtk::SpinButton () );
|
||||
maxInspectorBuffersSB->set_digits (0);
|
||||
maxInspectorBuffersSB->set_increments (1, 5);
|
||||
maxInspectorBuffersSB->set_max_length(2);
|
||||
maxInspectorBuffersSB->set_range (1, 12); // ... we have to set a limit, 12 seem to be enough even for systems with tons of RAM
|
||||
maxIBuffersHB->pack_start (*maxIBufferLbl, Gtk::PACK_SHRINK, 0);
|
||||
maxIBuffersHB->pack_end (*maxInspectorBuffersSB, Gtk::PACK_SHRINK, 0);
|
||||
finspect->add(*maxIBuffersHB);
|
||||
|
||||
mainContainer->pack_start(*finspect, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
return mainContainer;
|
||||
}
|
||||
|
||||
Gtk::Widget* Preferences::getColorManagementPanel () {
|
||||
@@ -1405,8 +1419,9 @@ void Preferences::storePreferences () {
|
||||
moptions.overwriteOutputFile = chOverwriteOutputFile->get_active ();
|
||||
moptions.UseIconNoText = ckbUseIconNoText->get_active();
|
||||
|
||||
moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
|
||||
moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
|
||||
moptions.clutCacheSize = clutCacheSizeSB->get_value_as_int();
|
||||
moptions.maxInspectorBuffers = maxInspectorBuffersSB->get_value_as_int();
|
||||
|
||||
// Sounds only on Windows and Linux
|
||||
#if defined(WIN32) || defined(__linux__)
|
||||
@@ -1552,7 +1567,9 @@ void Preferences::fillPreferences () {
|
||||
ckbUseIconNoText->set_active(moptions.UseIconNoText);
|
||||
|
||||
rgbDenoiseTreadLimitSB->set_value(moptions.rgbDenoiseThreadLimit);
|
||||
clutCacheSizeSB->set_value(moptions.clutCacheSize);
|
||||
clutCacheSizeSB->set_value(moptions.clutCacheSize);
|
||||
maxInspectorBuffersSB->set_value(moptions.maxInspectorBuffers);
|
||||
|
||||
//darkFrameDir->set_filename( moptions.rtSettings.darkFramesPath );
|
||||
//updateDFinfos();
|
||||
darkFrameDir->set_current_folder( moptions.rtSettings.darkFramesPath );
|
||||
|
||||
@@ -125,6 +125,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener {
|
||||
|
||||
Gtk::SpinButton* rgbDenoiseTreadLimitSB;
|
||||
Gtk::SpinButton* clutCacheSizeSB;
|
||||
Gtk::SpinButton* maxInspectorBuffersSB;
|
||||
|
||||
Gtk::CheckButton* ckbmenuGroupRank;
|
||||
Gtk::CheckButton* ckbmenuGroupLabel;
|
||||
|
||||
@@ -75,9 +75,9 @@ RTWindow::RTWindow ()
|
||||
:mainNB(NULL)
|
||||
,bpanel(NULL)
|
||||
,splash(NULL)
|
||||
,btn_fullscreen(NULL)
|
||||
,epanel(NULL)
|
||||
,fpanel(NULL)
|
||||
,btn_fullscreen(NULL)
|
||||
{
|
||||
|
||||
cacheMgr->init ();
|
||||
@@ -284,6 +284,8 @@ RTWindow::~RTWindow()
|
||||
#if defined(__APPLE__)
|
||||
g_object_unref (osxApp);
|
||||
#endif
|
||||
if (fpanel)
|
||||
delete fpanel;
|
||||
}
|
||||
|
||||
void RTWindow::findVerNumbers(int* numbers, Glib::ustring versionStr) {
|
||||
@@ -705,6 +707,7 @@ void RTWindow::MoveFileBrowserToEditor()
|
||||
{
|
||||
FileCatalog *fCatalog = fpanel->fileCatalog;
|
||||
fpanel->ribbonPane->remove(*fCatalog);
|
||||
fCatalog->disableInspector();
|
||||
epanel->catalogPane->add(*fCatalog);
|
||||
epanel->showTopPanel(options.editorFilmStripOpened);
|
||||
fCatalog->enableTabMode(true);
|
||||
@@ -783,4 +786,4 @@ bool RTWindow::isEditorPanel(Widget* panel) {
|
||||
|
||||
bool RTWindow::isEditorPanel(guint pageNum) {
|
||||
return isEditorPanel(mainNB->get_nth_page(pageNum));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
using namespace std;
|
||||
|
||||
ThumbBrowserBase::ThumbBrowserBase ()
|
||||
: lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1) {
|
||||
: lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1), inspector(NULL), isInspectorActive(false) {
|
||||
location = THLOC_FILEBROWSER;
|
||||
inW = -1; inH = -1;
|
||||
|
||||
@@ -546,6 +546,15 @@ void ThumbBrowserBase::arrangeFiles () {
|
||||
}
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::disableInspector() {
|
||||
if (inspector)
|
||||
inspector->setActive(false);
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::enableInspector() {
|
||||
if (inspector)
|
||||
inspector->setActive(true);
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::Internal::on_realize() {
|
||||
// Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <set>
|
||||
#include "options.h"
|
||||
#include "guiutils.h"
|
||||
#include "inspector.h"
|
||||
|
||||
/*
|
||||
* Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space
|
||||
@@ -48,7 +49,7 @@ class ThumbBrowserBase : public Gtk::VBox {
|
||||
bool on_key_press_event (GdkEventKey* event);
|
||||
bool on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Gtk::Tooltip>& tooltip);
|
||||
void setPosition (int x, int y);
|
||||
|
||||
|
||||
void setDirty () { dirty = true; }
|
||||
bool isDirty () { return dirty; }
|
||||
};
|
||||
@@ -72,12 +73,20 @@ class ThumbBrowserBase : public Gtk::VBox {
|
||||
|
||||
int inW, inH;
|
||||
|
||||
Inspector *inspector;
|
||||
bool isInspectorActive;
|
||||
|
||||
|
||||
void resizeThumbnailArea (int w, int h);
|
||||
void internalAreaResized (Gtk::Allocation& req);
|
||||
void buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh);
|
||||
|
||||
public:
|
||||
|
||||
void setInspector(Inspector* inspector) { this->inspector = inspector; }
|
||||
Inspector* getInspector() { return inspector; }
|
||||
void disableInspector();
|
||||
void enableInspector();
|
||||
enum Arrangement {TB_Horizontal, TB_Vertical};
|
||||
void configScrollBars ();
|
||||
void scrollChanged ();
|
||||
@@ -89,6 +98,8 @@ class ThumbBrowserBase : public Gtk::VBox {
|
||||
void selectFirst (bool enlarge);
|
||||
void selectLast (bool enlarge);
|
||||
|
||||
virtual bool isInTabMode() { return false; }
|
||||
|
||||
eLocation getLocation() { return location; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -459,7 +459,20 @@ void ThumbBrowserEntryBase::setOffset (int x, int y) {
|
||||
bool ThumbBrowserEntryBase::inside (int x, int y) {
|
||||
|
||||
return x>ofsX+startx && x<ofsX+startx+exp_width && y>ofsY+starty && y<ofsY+starty+exp_height;
|
||||
}
|
||||
}
|
||||
|
||||
void ThumbBrowserEntryBase::getPosInImgSpace (int x, int y, rtengine::Coord2D &coord) {
|
||||
|
||||
coord.x = coord.y = -1.;
|
||||
if (preview) {
|
||||
x -= ofsX+startx;
|
||||
y -= ofsY+starty;
|
||||
if (x>=prex && x<=prex+prew && y>=prey && y<=prey+preh) {
|
||||
coord.x = double(x-prex)/double(prew);
|
||||
coord.y = double(y-prey)/double(preh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) {
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ protected:
|
||||
int getY () const { return ofsY+starty; }
|
||||
|
||||
bool inside (int x, int y);
|
||||
void getPosInImgSpace (int x, int y, rtengine::Coord2D &coord);
|
||||
bool insideWindow (int x, int y, int w, int h);
|
||||
void setPosition (int x, int y, int w, int h);
|
||||
void setOffset (int x, int y);
|
||||
|
||||
Reference in New Issue
Block a user