First patch of the LockableColorPicker tool.
Still Work In Progress, but can be used without too much hassle.
BIN
rtdata/images/Dark/actions/colorPickers-hide.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
rtdata/images/Dark/actions/colorPickers-show.png
Normal file
After Width: | Height: | Size: 833 B |
BIN
rtdata/images/Dark/actions/gtk-color-picker-add.png
Normal file
After Width: | Height: | Size: 851 B |
BIN
rtdata/images/Light/actions/colorPickers-hide.png
Normal file
After Width: | Height: | Size: 645 B |
BIN
rtdata/images/Light/actions/colorPickers-show.png
Normal file
After Width: | Height: | Size: 796 B |
BIN
rtdata/images/Light/actions/gtk-color-picker-add.png
Normal file
After Width: | Height: | Size: 810 B |
@ -988,7 +988,8 @@ PREFERENCES_REMEMBERZOOMPAN;Se souvenir de niveau de zoom et de la position de l
|
||||
PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Retient le niveau de zoom et la position de l'image courante lors de l'ouverture d'une nouvelle image.\n\nCette option ne fonctionne que dans le mode "Éditeur unique" et quand "Méthode de dématriçage utilisé pour l'aperçu à un zoom <100%" is set to "Idem PP3".
|
||||
PREFERENCES_RGBDTL_LABEL;Nombre maximum d'unités de calcul pour la Réduction du bruit
|
||||
PREFERENCES_RGBDTL_TOOLTIP;La réduction du bruit nécessite un minimum d'à peu près 128Mo de RAM pour une image de 10MPix ou 512Mo pour une image de 40MPix, ainsi que 128Mo de RAM supplémentaire par unité de calcul. Plus il y aura d'unités de calcul travaillant en parallèle, plus ce sera rapide. Laissez la valeur à "0" pour utiliser automatiquement autant d'unités de calcul que possible.
|
||||
PREFERENCES_SELECTFONT;Police de caractère
|
||||
PREFERENCES_SELECTFONT;Police générale
|
||||
PREFERENCES_SELECTFONT_COLPICKER;Police des pipette à couleur
|
||||
PREFERENCES_SELECTLANG;Choix de la langue
|
||||
PREFERENCES_SELECTTHEME;Choisissez un thème
|
||||
PREFERENCES_SERIALIZE_TIFF_READ;Réglage de lecture des images TIFF
|
||||
@ -1089,6 +1090,7 @@ THRESHOLDSELECTOR_HINT;Maintenez la touche <b>Shift</b> appuyée pour déplacer
|
||||
THRESHOLDSELECTOR_T;Haut
|
||||
THRESHOLDSELECTOR_TL;Haut-Gauche
|
||||
THRESHOLDSELECTOR_TR;Haut-droite
|
||||
TOOLBAR_TOOLTIP_COLORPICKER;Ancre de Vérification Couleur\n\nLorque activé:\nCliquez la zone d'image avec le bouton gauche de la souris pour ajouter une ancre\nDéplacez-le en le "tirant" avec le bouton gauche de la souris\nSupprimez une ancre en cliquant dessus avec le bouton droit de la souris\nSupprimez toutes les ancres avec Shift + click avec le bouton droit\nCliquez avec le bouton droit de la souris en dehors de toute ancre pour revenir au mode Déplacement
|
||||
TOOLBAR_TOOLTIP_CROP;Sélection du recadrage\nRaccourci: <b>c</b>\nDéplacez le recadrage en utilisant Shift + Glisser
|
||||
TOOLBAR_TOOLTIP_HAND;Outil de navigation\nRaccourci: <b>h</b>
|
||||
TOOLBAR_TOOLTIP_STRAIGHTEN;Sélection de la ligne d'horizon\nRaccourci: <b>s</b>\n\nIndiquez la verticale ou l'horizontale en dessinant une ligne à travers l'image de prévisualisation. L'angle de rotation sera affiché près de la ligne guide. Le centre de rotation est le centre géométrique de l'image.
|
||||
|
@ -1037,7 +1037,8 @@ PREFERENCES_REMEMBERZOOMPAN;Remember zoom % and pan offset
|
||||
PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3".
|
||||
PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels
|
||||
PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements.
|
||||
PREFERENCES_SELECTFONT;Select font
|
||||
PREFERENCES_SELECTFONT;Select global font
|
||||
PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font
|
||||
PREFERENCES_SELECTLANG;Select language
|
||||
PREFERENCES_SELECTTHEME;Select theme
|
||||
PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings
|
||||
@ -1140,6 +1141,7 @@ THRESHOLDSELECTOR_HINT;Hold the <b>Shift</b> key to move individual control poin
|
||||
THRESHOLDSELECTOR_T;Top
|
||||
THRESHOLDSELECTOR_TL;Top-left
|
||||
THRESHOLDSELECTOR_TR;Top-right
|
||||
TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool
|
||||
TOOLBAR_TOOLTIP_CROP;<b>Crop</b> selection.\nShortcut: <b>c</b>\nMove the crop area using <b>Shift-mouse drag</b>
|
||||
TOOLBAR_TOOLTIP_HAND;Hand tool.\nShortcut: <b>h</b>
|
||||
TOOLBAR_TOOLTIP_STRAIGHTEN;<b>Straighten</b> / <b>fine rotation</b>.\nShortcut: <b>s</b>\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Center of rotation is the geometrical center of the image.
|
||||
|
@ -48,7 +48,10 @@ struct Coord
|
||||
Coord& operator+= (const Coord& other);
|
||||
Coord& operator-= (const Coord& other);
|
||||
Coord& operator*= (const double scale);
|
||||
|
||||
bool operator< (const Coord& rhs) const;
|
||||
bool operator> (const Coord& rhs) const;
|
||||
bool operator<=(const Coord& rhs) const;
|
||||
bool operator>=(const Coord& rhs) const;
|
||||
};
|
||||
|
||||
bool operator== (const Coord& lhs, const Coord& rhs);
|
||||
@ -130,6 +133,26 @@ inline Coord& Coord::operator*= (const double scale)
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool Coord::operator< (const Coord& rhs) const
|
||||
{
|
||||
return x < rhs.x && y < rhs.y;
|
||||
}
|
||||
|
||||
inline bool Coord::operator> (const Coord& rhs) const
|
||||
{
|
||||
return x > rhs.x && y > rhs.y;
|
||||
}
|
||||
|
||||
inline bool Coord::operator<=(const Coord& rhs) const
|
||||
{
|
||||
return x <= rhs.x && y <= rhs.y;
|
||||
}
|
||||
|
||||
inline bool Coord::operator>=(const Coord& rhs) const
|
||||
{
|
||||
return x >= rhs.x && y >= rhs.y;
|
||||
}
|
||||
|
||||
inline bool operator== (const Coord& lhs, const Coord& rhs)
|
||||
{
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
|
@ -8,7 +8,7 @@ set (BASESOURCEFILES
|
||||
coarsepanel.cc cacorrection.cc chmixer.cc blackwhite.cc
|
||||
resize.cc icmpanel.cc crop.cc shadowshighlights.cc
|
||||
impulsedenoise.cc dirpyrdenoise.cc epd.cc
|
||||
exifpanel.cc toolpanel.cc lensprofile.cc
|
||||
exifpanel.cc toolpanel.cc lensprofile.cc lockablecolorpicker.cc
|
||||
sharpening.cc vibrance.cc rgbcurves.cc colortoning.cc
|
||||
whitebalance.cc vignetting.cc gradient.cc pcvignette.cc rotate.cc distortion.cc
|
||||
crophandler.cc dirbrowser.cc
|
||||
|
@ -42,6 +42,10 @@ BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolP
|
||||
toolPanels.erase (ipi);
|
||||
}
|
||||
|
||||
if (toolBar) {
|
||||
toolBar->setBatchMode ();
|
||||
}
|
||||
|
||||
toolPanelNotebook->remove_page (*metadataPanel);
|
||||
metadataPanel = 0;
|
||||
toiM = 0;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <cstring>
|
||||
#include "guiutils.h"
|
||||
#include "cropwindow.h"
|
||||
#include "imagearea.h"
|
||||
#include "../rtengine/dcrop.h"
|
||||
#include "../rtengine/refreshmap.h"
|
||||
#include "../rtengine/rt_math.h"
|
||||
@ -188,6 +189,15 @@ void CropHandler::setZoom (int z, int centerx, int centery)
|
||||
}
|
||||
}
|
||||
|
||||
float CropHandler::getZoomFactor ()
|
||||
{
|
||||
if (zoom >= 1000) {
|
||||
return zoom / 1000;
|
||||
} else {
|
||||
return 1.f / (float)zoom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CropHandler::setWSize (int w, int h)
|
||||
{
|
||||
@ -465,6 +475,63 @@ bool CropHandler::getEnabled ()
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void CropHandler::colorPick (rtengine::Coord pickerPos, float &r, float &g, float &b, LockableColorPicker::PickerSize size)
|
||||
{
|
||||
|
||||
int xSize = (int)size;
|
||||
int ySize = (int)size;
|
||||
int pixbufW = cropPixbuf->get_width();
|
||||
rtengine::Coord topLeftPos(pickerPos.x - xSize/2, pickerPos.y - ySize/2);
|
||||
|
||||
if (topLeftPos.x > pixbufW || topLeftPos.y > pixbufW || topLeftPos.x + xSize < 0 || topLeftPos.y + ySize < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the position of the center of the picker
|
||||
int radius = (int)size / 2;
|
||||
|
||||
// X/Width clip
|
||||
if (topLeftPos.x < 0) {
|
||||
xSize += topLeftPos.x;
|
||||
topLeftPos.x = 0;
|
||||
}
|
||||
if (topLeftPos.x + xSize > pixbufW) {
|
||||
xSize = pixbufW - topLeftPos.x;
|
||||
}
|
||||
// Y/Height clip
|
||||
if (topLeftPos.y < 0) {
|
||||
ySize += topLeftPos.y;
|
||||
topLeftPos.y = 0;
|
||||
}
|
||||
if (topLeftPos.y + ySize > cropimg_height) {
|
||||
ySize = cropimg_height - topLeftPos.y;
|
||||
}
|
||||
|
||||
// Accumulating the data
|
||||
std::uint32_t r2=0, g2=0, b2=0;
|
||||
std::uint32_t count = 0;
|
||||
const guint8* data = cropPixbuf->get_pixels();
|
||||
for (int j = topLeftPos.y ; j < topLeftPos.y + ySize ; ++j) {
|
||||
const guint8* data2 = data + cropPixbuf->get_rowstride()*j;
|
||||
for (int i = topLeftPos.x ; i < topLeftPos.x + xSize ; ++i) {
|
||||
const guint8* data3 = data2 + i*3;
|
||||
rtengine::Coord currPos(i, j);
|
||||
rtengine::Coord delta = pickerPos - currPos;
|
||||
rtengine::PolarCoord p(delta);
|
||||
if (p.radius <= radius) {
|
||||
r2 += *data3;
|
||||
g2 += *(data3+1);
|
||||
b2 += *(data3+2);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Averaging
|
||||
r = (float)r2 / (float)count / 255.f;
|
||||
g = (float)g2 / (float)count / 255.f;
|
||||
b = (float)b2 / (float)count / 255.f;
|
||||
}
|
||||
|
||||
void CropHandler::getSize (int& w, int& h)
|
||||
{
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../rtengine/rtengine.h"
|
||||
#include "threadutils.h"
|
||||
#include "edit.h"
|
||||
#include "lockablecolorpicker.h"
|
||||
#include <gtkmm.h>
|
||||
|
||||
class CropDisplayHandler
|
||||
@ -94,23 +95,26 @@ public:
|
||||
}
|
||||
void setEditSubscriber (EditSubscriber* newSubscriber);
|
||||
|
||||
void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow);
|
||||
void setZoom (int z, int centerx = -1, int centery = -1);
|
||||
double getFitZoom ();
|
||||
void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow);
|
||||
void setZoom (int z, int centerx = -1, int centery = -1);
|
||||
float getZoomFactor ();
|
||||
double getFitZoom ();
|
||||
double getFitCropZoom();
|
||||
void setWSize (int w, int h);
|
||||
void getWSize (int& w, int &h);
|
||||
void setWSize (int w, int h);
|
||||
void getWSize (int& w, int &h);
|
||||
void getAnchorPosition (int& x, int& y);
|
||||
void setAnchorPosition (int x, int y, bool update = true);
|
||||
void moveAnchor (int deltaX, int deltaY, bool update = true);
|
||||
void centerAnchor (bool update = true);
|
||||
void getPosition (int& x, int& y);
|
||||
void getSize (int& w, int& h);
|
||||
void moveAnchor (int deltaX, int deltaY, bool update = true);
|
||||
void centerAnchor (bool update = true);
|
||||
void getPosition (int& x, int& y);
|
||||
void getSize (int& w, int& h);
|
||||
void getFullImageSize (int& w, int& h);
|
||||
|
||||
void setEnabled (bool e);
|
||||
bool getEnabled ();
|
||||
|
||||
void colorPick (rtengine::Coord pickerPos, float &r, float &g, float &b, LockableColorPicker::PickerSize size);
|
||||
|
||||
rtengine::DetailedCrop* getCrop()
|
||||
{
|
||||
return crop;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "cursormanager.h"
|
||||
#include "options.h"
|
||||
#include "imagearea.h"
|
||||
#include "lockablecolorpicker.h"
|
||||
|
||||
using namespace rtengine;
|
||||
|
||||
@ -67,7 +68,7 @@ ZoomStep zoomSteps[] = {
|
||||
|
||||
CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow)
|
||||
: ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false),
|
||||
fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), cropLabel(Glib::ustring("100%")),
|
||||
fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")),
|
||||
backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3),
|
||||
upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0),
|
||||
imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(NULL),
|
||||
@ -112,6 +113,13 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_,
|
||||
cropHandler.newImage (ipc_, isDetailWindow);
|
||||
}
|
||||
|
||||
CropWindow::~CropWindow ()
|
||||
{
|
||||
for (auto colorPicker : colorPickers) {
|
||||
delete colorPicker;
|
||||
}
|
||||
}
|
||||
|
||||
void CropWindow::enable()
|
||||
{
|
||||
cropHandler.setEnabled (true);
|
||||
@ -308,7 +316,25 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
|
||||
press_y = height;
|
||||
} else {
|
||||
if (onArea (CropImage, x, y)) { // events inside of the image domain
|
||||
if (onArea (CropTopLeft, x, y)) {
|
||||
if (iarea->getToolMode () == TMColorPicker) {
|
||||
if (hoveredPicker) {
|
||||
// Color Picker drag starts
|
||||
state = SDragPicker;
|
||||
} else {
|
||||
// Add a new Color Picker
|
||||
int x2, y2;
|
||||
screenCoordToImage(x, y, x2, y2);
|
||||
LockableColorPicker *newPicker = new LockableColorPicker(x2, y2, LockableColorPicker::PickerSize::S15, 0., 0., 0., this);
|
||||
colorPickers.push_back(newPicker);
|
||||
hoveredPicker = newPicker;
|
||||
state = SDragPicker;
|
||||
press_x = x;
|
||||
press_y = y;
|
||||
action_x = 0;
|
||||
action_y = 0;
|
||||
needRedraw = true;
|
||||
}
|
||||
} else if (onArea (CropTopLeft, x, y)) {
|
||||
state = SResizeTL;
|
||||
press_x = x;
|
||||
action_x = cropHandler.cropParams.x;
|
||||
@ -430,6 +456,9 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
|
||||
action_x = 0;
|
||||
action_y = 0;
|
||||
}
|
||||
} else if (iarea->getToolMode () == TMColorPicker && hoveredPicker) {
|
||||
// Color Picker drag starts
|
||||
state = SDragPicker;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,6 +502,32 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
|
||||
action_y = 0;
|
||||
}
|
||||
}
|
||||
else if (iarea->getToolMode () == TMColorPicker && type == GDK_BUTTON_PRESS && state == SNormal) {
|
||||
if (hoveredPicker) {
|
||||
if((bstate & GDK_CONTROL_MASK) && (bstate & GDK_SHIFT_MASK)) {
|
||||
// Deleting all pickers !
|
||||
for (auto colorPicker : colorPickers) {
|
||||
delete colorPicker;
|
||||
}
|
||||
colorPickers.clear();
|
||||
hoveredPicker = nullptr;
|
||||
state = SDeletePicker;
|
||||
needRedraw = true;
|
||||
} else if (!(bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) {
|
||||
// Deleting the hovered picker
|
||||
for (std::vector<LockableColorPicker*>::iterator i = colorPickers.begin(); i != colorPickers.end(); i++) {
|
||||
if (*i == hoveredPicker) {
|
||||
colorPickers.erase(i);
|
||||
delete hoveredPicker;
|
||||
hoveredPicker = nullptr;
|
||||
state = SDeletePicker;
|
||||
needRedraw = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needRedraw) {
|
||||
@ -602,6 +657,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
|
||||
} else {
|
||||
iarea->object = 0;
|
||||
}
|
||||
} else if (state == SDeletePicker) {
|
||||
needRedraw = true;
|
||||
} else if (state == SNormal && iarea->getToolMode() == TMColorPicker && !hoveredPicker && button == 3) {
|
||||
iarea->setToolHand ();
|
||||
}
|
||||
|
||||
if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) {
|
||||
@ -620,7 +679,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
|
||||
return;
|
||||
}
|
||||
|
||||
if (state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) {
|
||||
if (state != SDeletePicker && state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) {
|
||||
iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f;
|
||||
|
||||
needRedraw = iarea->object == 1;
|
||||
@ -778,6 +837,33 @@ void CropWindow::pointerMoved (int bstate, int x, int y)
|
||||
action_x = new_action_x;
|
||||
action_y = new_action_y;
|
||||
iarea->redraw ();
|
||||
} else if (state == SDragPicker) {
|
||||
Coord imgPos, cropPos;
|
||||
action_x = x - press_x;
|
||||
action_x = y - press_y;
|
||||
screenCoordToImage (x, y, imgPos.x, imgPos.y);
|
||||
if (imgPos.x < 0) {
|
||||
imgPos.x = 0;
|
||||
}else if (imgPos.x >= ipc->getFullWidth()) {
|
||||
imgPos.x = ipc->getFullWidth()-1;
|
||||
}
|
||||
if (imgPos.y < 0) {
|
||||
imgPos.y = 0;
|
||||
}else if (imgPos.y >= ipc->getFullHeight()) {
|
||||
imgPos.y = ipc->getFullHeight()-1;
|
||||
}
|
||||
imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y);
|
||||
float r=0.f, g=0.f, b=0.f;
|
||||
bool isValid = isHoveredPickerFullyInside (cropPos);
|
||||
hoveredPicker->setValidity (isValid);
|
||||
if (isValid) {
|
||||
cropHandler.colorPick(cropPos, r, g, b, hoveredPicker->getSize());
|
||||
}
|
||||
hoveredPicker->setPosition (imgPos, r, g, b);
|
||||
iarea->redraw ();
|
||||
} else if (state == SNormal && iarea->getToolMode () == TMColorPicker && onArea(ColorPicker, x, y)) {
|
||||
// TODO: we could set the hovered picker as Highlighted here
|
||||
// Keep this if statement, the onArea will find out the hoveredPicker and will be used to update the cursor
|
||||
} else if (editSubscriber) {
|
||||
rtengine::Crop* crop = static_cast<rtengine::Crop*>(cropHandler.getCrop());
|
||||
|
||||
@ -931,6 +1017,16 @@ bool CropWindow::onArea (CursorArea a, int x, int y)
|
||||
case CropImage:
|
||||
return x >= xpos + imgX + imgAreaX && y >= ypos + imgY + imgAreaY && x < xpos + imgX + imgAreaX + imgW && y < ypos + imgY + imgAreaY + imgH;
|
||||
|
||||
case ColorPicker:
|
||||
for (auto colorPicker : colorPickers) {
|
||||
if (colorPicker->isOver(x, y)) {
|
||||
hoveredPicker = colorPicker;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
hoveredPicker = nullptr;
|
||||
return false;
|
||||
|
||||
case CropBorder:
|
||||
return
|
||||
(x >= xpos + imgAreaX && y >= ypos + imgAreaY && x < xpos + imgAreaX + imgAreaW && y < ypos + imgAreaY + imgAreaH) &&
|
||||
@ -1048,6 +1144,8 @@ void CropWindow::updateCursor (int x, int y)
|
||||
cursorManager.setCursor (iarea->get_window(), CSMove);
|
||||
} else if (onArea (CropResize, x, y)) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal);
|
||||
} else if (tm == TMColorPicker && hoveredPicker) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSMove);
|
||||
} else if (tm == TMHand && (onArea (CropTopLeft, x, y))) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSResizeTopLeft);
|
||||
} else if (tm == TMHand && (onArea (CropTopRight, x, y))) {
|
||||
@ -1083,6 +1181,8 @@ void CropWindow::updateCursor (int x, int y)
|
||||
cursorManager.setCursor (iarea->get_window(), CSCropSelect);
|
||||
} else if (tm == TMStraighten) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSStraighten);
|
||||
} else if (tm == TMColorPicker) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSAddColPicker);
|
||||
}
|
||||
} else {
|
||||
int objectID = -1;
|
||||
@ -1121,6 +1221,8 @@ void CropWindow::updateCursor (int x, int y)
|
||||
cursorManager.setCursor (iarea->get_window(), CSResizeBottomRight);
|
||||
} else if (state == SCropWinResize) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal);
|
||||
} else if (state == SDragPicker) {
|
||||
cursorManager.setCursor (iarea->get_window(), CSMove2D);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1674,6 +1776,12 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr)
|
||||
}
|
||||
}
|
||||
|
||||
if ((state == SNormal || state == SDragPicker) && iarea->showColorPickers()) {
|
||||
for (auto colorPicker : colorPickers) {
|
||||
colorPicker->draw(cr);
|
||||
}
|
||||
}
|
||||
|
||||
//t2.set ();
|
||||
// printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3));
|
||||
}
|
||||
@ -1924,6 +2032,25 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery)
|
||||
iarea->redraw ();
|
||||
}
|
||||
|
||||
bool CropWindow::isHoveredPickerFullyInside (const rtengine::Coord &pos)
|
||||
{
|
||||
|
||||
return true;
|
||||
if (!cropHandler.cropPixbuf) {
|
||||
return false;
|
||||
}
|
||||
rtengine::Coord cropPos;
|
||||
rtengine::Coord pickerPos, cropPickerPos;
|
||||
hoveredPicker->getImagePosition(pickerPos);
|
||||
rtengine::Coord minPos(0, 0);
|
||||
rtengine::Coord maxPos(cropHandler.cropPixbuf->get_width(), cropHandler.cropPixbuf->get_height());
|
||||
rtengine::Coord halfPickerSize((int)hoveredPicker->getSize()/2, (int)hoveredPicker->getSize()/2);
|
||||
imageCoordToCropImage (pickerPos.x, pickerPos.y, cropPickerPos.x, cropPickerPos.y);
|
||||
rtengine::Coord pickerMinPos = cropPickerPos - halfPickerSize;
|
||||
rtengine::Coord pickerMaxPos = cropPickerPos + halfPickerSize;
|
||||
return pickerMinPos >= minPos && pickerMaxPos <= maxPos;
|
||||
}
|
||||
|
||||
void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy)
|
||||
{
|
||||
|
||||
@ -1945,8 +2072,8 @@ void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy)
|
||||
|
||||
int cropX, cropY;
|
||||
cropHandler.getPosition (cropX, cropY);
|
||||
imgx = cropX + (phyx - xpos - imgX) / zoomSteps[cropZoom].zoom;
|
||||
imgy = cropY + (phyy - ypos - imgY) / zoomSteps[cropZoom].zoom;
|
||||
imgx = cropX + (phyx - xpos - imgX - imgAreaX) / zoomSteps[cropZoom].zoom;
|
||||
imgy = cropY + (phyy - ypos - imgY - imgAreaY) / zoomSteps[cropZoom].zoom;
|
||||
}
|
||||
|
||||
void CropWindow::screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy)
|
||||
@ -1983,6 +2110,14 @@ void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phy
|
||||
phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder();
|
||||
}
|
||||
|
||||
void CropWindow::imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy)
|
||||
{
|
||||
int cropX, cropY;
|
||||
cropHandler.getPosition (cropX, cropY);
|
||||
phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom;
|
||||
phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom;
|
||||
}
|
||||
|
||||
int CropWindow::scaleValueToImage (int value)
|
||||
{
|
||||
return int(double(value) / zoomSteps[cropZoom].zoom);
|
||||
@ -2220,6 +2355,14 @@ void CropWindow::drawObservedFrame (Cairo::RefPtr<Cairo::Context> cr, int rw, in
|
||||
void CropWindow::cropImageUpdated ()
|
||||
{
|
||||
|
||||
for (auto colorPicker : colorPickers) {
|
||||
Coord imgPos, cropPos;
|
||||
colorPicker->getImagePosition(imgPos);
|
||||
imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y);
|
||||
float r=0.f, g=0.f, b=0.f;
|
||||
cropHandler.colorPick(cropPos, r, g, b, colorPicker->getSize());
|
||||
colorPicker->setRGB (r, g, b);
|
||||
}
|
||||
iarea->redraw ();
|
||||
}
|
||||
|
||||
@ -2281,7 +2424,7 @@ void CropWindow::delCropWindowListener (CropWindowListener* l)
|
||||
}
|
||||
}
|
||||
|
||||
EditDataProvider* CropWindow::getImageArea()
|
||||
ImageArea* CropWindow::getImageArea()
|
||||
{
|
||||
return iarea;
|
||||
}
|
||||
|
@ -59,6 +59,10 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed
|
||||
bool fitZoom;
|
||||
bool isLowUpdatePriority;
|
||||
|
||||
// color pickers
|
||||
std::vector<LockableColorPicker*> colorPickers;
|
||||
LockableColorPicker* hoveredPicker;
|
||||
|
||||
// decoration
|
||||
LWButton *bZoomIn, *bZoomOut, *bZoom100, /**bZoomFit,*/ *bClose;
|
||||
LWButtonSet buttonSet;
|
||||
@ -101,12 +105,15 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed
|
||||
void drawObservedFrame (Cairo::RefPtr<Cairo::Context> cr, int rw = 0, int rh = 0);
|
||||
void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1);
|
||||
|
||||
bool isHoveredPickerFullyInside(const rtengine::Coord &pos);
|
||||
|
||||
// Used by the mainCropWindow only
|
||||
void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0);
|
||||
|
||||
public:
|
||||
CropHandler cropHandler;
|
||||
CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow);
|
||||
~CropWindow ();
|
||||
|
||||
void setDecorated (bool decorated)
|
||||
{
|
||||
@ -127,6 +134,7 @@ public:
|
||||
void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy);
|
||||
void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy);
|
||||
void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy);
|
||||
void imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy);
|
||||
int scaleValueToImage (int value);
|
||||
float scaleValueToImage (float value);
|
||||
double scaleValueToImage (double value);
|
||||
@ -208,7 +216,7 @@ public:
|
||||
void remoteMove (int deltaX, int deltaY);
|
||||
void remoteMoveReady ();
|
||||
|
||||
EditDataProvider* getImageArea();
|
||||
ImageArea* getImageArea();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -44,6 +44,7 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin)
|
||||
Glib::RefPtr<Gdk::Pixbuf> hand = RTImage::createFromFile ("cross.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> close_hand = RTImage::createFromFile ("closedhand.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> wbpick = RTImage::createFromFile ("gtk-color-picker-small.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> cpick = RTImage::createFromFile ("gtk-color-picker-add.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> empty = RTImage::createFromFile ("empty.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> move2D = RTImage::createFromFile ("move-2D.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> move1DH = RTImage::createFromFile ("move-1D-h.png");
|
||||
@ -52,7 +53,8 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin)
|
||||
|
||||
cHand = hand ? new Gdk::Cursor (cAdd->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cClosedHand = close_hand ? new Gdk::Cursor (cAdd->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cWB = wbpick ? new Gdk::Cursor (cAdd->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW);
|
||||
cWB = wbpick ? new Gdk::Cursor (cAdd->get_display(), wbpick, 3, 15) : new Gdk::Cursor (Gdk::ARROW);
|
||||
cAddPicker = cpick ? new Gdk::Cursor (cAdd->get_display(), cpick, 3, 18) : new Gdk::Cursor (Gdk::ARROW);
|
||||
cHidden = empty ? new Gdk::Cursor (cAdd->get_display(), empty, 12, 12) : new Gdk::Cursor (Gdk::FLEUR);
|
||||
cMove2D = move2D ? new Gdk::Cursor (cAdd->get_display(), move2D, 11, 11) : new Gdk::Cursor (Gdk::FLEUR);
|
||||
cMove1DH = move1DH ? new Gdk::Cursor (cAdd->get_display(), move1DH, 11, 11) : new Gdk::Cursor (Gdk::FLEUR);
|
||||
@ -100,6 +102,8 @@ void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape sha
|
||||
window->set_cursor (*cMoveRotate);
|
||||
} else if (shape == CSSpotWB) {
|
||||
window->set_cursor (*cWB);
|
||||
} else if (shape == CSAddColPicker) {
|
||||
window->set_cursor (*cAddPicker);
|
||||
} else if (shape == CSCropSelect) {
|
||||
window->set_cursor (*cHand);
|
||||
} else if (shape == CSMoveLeft) {
|
||||
|
@ -26,7 +26,7 @@ enum CursorShape {
|
||||
CSMoveRight, CSResizeWidth, CSResizeHeight, CSResizeDiagonal,
|
||||
CSResizeTopLeft, CSResizeTopRight, CSResizeBottomLeft, CSResizeBottomRight,
|
||||
CSMove2D, CSMove1DH, CSMove1DV, CSMoveRotate,
|
||||
CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSWait, CSEmpty
|
||||
CSSpotWB, CSAddColPicker, CSCropSelect, CSStraighten, CSPlus, CSWait, CSEmpty
|
||||
};
|
||||
|
||||
class CursorManager
|
||||
@ -51,6 +51,7 @@ protected:
|
||||
Gdk::Cursor* cHand;
|
||||
Gdk::Cursor* cClosedHand;
|
||||
Gdk::Cursor* cWB;
|
||||
Gdk::Cursor* cAddPicker;
|
||||
Gdk::Cursor* cHidden;
|
||||
Gdk::Cursor* cMove2D;
|
||||
Gdk::Cursor* cMove1DH;
|
||||
|
@ -59,7 +59,7 @@ std::vector<Glib::ustring> listSubDirs (const Glib::RefPtr<Gio::File>& dir, bool
|
||||
} catch (const Glib::Exception& exception) {
|
||||
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cerr << "Failed to list subdirectories of \"" << dir << "\": " << exception.what () << std::endl;
|
||||
std::cerr << "Failed to list subdirectories of \"" << dir->get_basename() << "\": " << exception.what () << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -208,10 +208,12 @@ public:
|
||||
virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) = 0;
|
||||
/// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords
|
||||
virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) = 0;
|
||||
/// Convert the image coords to the crop's canvas coords
|
||||
/// Convert the image coords to the crop's canvas coords (full image + padding)
|
||||
virtual void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) = 0;
|
||||
/// Convert the image coords to the edit buffer coords
|
||||
/// Convert the image coords to the edit buffer coords (includes borders)
|
||||
virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) = 0;
|
||||
/// Convert the image coords to the displayed image coords (no borders here)
|
||||
virtual void imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy) = 0;
|
||||
/// Convert a size value from the preview's scale to the image's scale
|
||||
virtual int scaleValueToImage (int value) = 0;
|
||||
/// Convert a size value from the preview's scale to the image's scale
|
||||
|
@ -21,9 +21,9 @@
|
||||
|
||||
enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR,
|
||||
SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove,
|
||||
SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3
|
||||
SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3, SDragPicker, SDeletePicker
|
||||
};
|
||||
enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft,
|
||||
enum CursorArea {CropWinButtons, CropToolBar, CropImage, ColorPicker, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft,
|
||||
CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved
|
||||
};
|
||||
|
||||
|
@ -313,6 +313,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
|
||||
|
||||
iareapanel = new ImageAreaPanel ();
|
||||
tpc->setEditProvider(iareapanel->imageArea);
|
||||
tpc->getToolBar()->setLockablePickerToolListener(iareapanel->imageArea);
|
||||
|
||||
Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ());
|
||||
toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1);
|
||||
|
@ -52,7 +52,6 @@ FilePanel::FilePanel () : parent(NULL)
|
||||
dirpaned->pack1 (*placespaned, false, true);
|
||||
|
||||
tpc = new BatchToolPanelCoordinator (this);
|
||||
tpc->removeWbTool();
|
||||
fileCatalog = Gtk::manage ( new FileCatalog (tpc->coarse, tpc->getToolBar(), this) );
|
||||
ribbonPane = Gtk::manage ( new Gtk::Paned() );
|
||||
ribbonPane->add(*fileCatalog);
|
||||
|
@ -1080,11 +1080,35 @@ void TextOrIcon::switchTo(TOITypes type)
|
||||
|
||||
BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0, 0), dirty(true) {}
|
||||
|
||||
void BackBuffer::setDestPosition(int x, int y)
|
||||
{
|
||||
// values will be clamped when used...
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
void BackBuffer::setSrcOffset(int x, int y)
|
||||
{
|
||||
// values will be clamped when used...
|
||||
offset.x = x;
|
||||
offset.y = y;
|
||||
offset.set(x, y);
|
||||
}
|
||||
|
||||
void BackBuffer::setSrcOffset(const rtengine::Coord &newOffset)
|
||||
{
|
||||
// values will be clamped when used...
|
||||
offset = newOffset;
|
||||
}
|
||||
|
||||
void BackBuffer::getSrcOffset(int &x, int &y)
|
||||
{
|
||||
// values will be clamped when used...
|
||||
offset.get(x, y);
|
||||
}
|
||||
|
||||
void BackBuffer::getSrcOffset(rtengine::Coord &offset)
|
||||
{
|
||||
// values will be clamped when used...
|
||||
offset = this->offset;
|
||||
}
|
||||
|
||||
// Note: newW & newH must be > 0
|
||||
@ -1092,12 +1116,16 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, in
|
||||
{
|
||||
assert(newW && newH);
|
||||
|
||||
bool newSize = w != newW || h != newH;
|
||||
bool newSize = (newW > 0 && w != newW) || (newH > 0 && h != newH);
|
||||
|
||||
x = newX;
|
||||
y = newY;
|
||||
w = newW;
|
||||
h = newH;
|
||||
if (newH > 0) {
|
||||
w = newW;
|
||||
}
|
||||
if (newH > 0) {
|
||||
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 && window) {
|
||||
@ -1113,14 +1141,18 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, in
|
||||
// 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);
|
||||
assert(newW && newH);
|
||||
|
||||
bool newSize = w != newW || h != newH;
|
||||
bool newSize = (newW > 0 && w != newW) || (newH > 0 && h != newH);
|
||||
|
||||
x = newX;
|
||||
y = newY;
|
||||
w = newW;
|
||||
h = newH;
|
||||
if (newH > 0) {
|
||||
w = newW;
|
||||
}
|
||||
if (newH > 0) {
|
||||
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) {
|
||||
@ -1136,7 +1168,7 @@ bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int
|
||||
/*
|
||||
* Copy the backbuffer to a Gdk::Window
|
||||
*/
|
||||
void BackBuffer::copySurface(Glib::RefPtr<Gdk::Window> window, GdkRectangle *rectangle)
|
||||
void BackBuffer::copySurface(Glib::RefPtr<Gdk::Window> &window, GdkRectangle *rectangle)
|
||||
{
|
||||
if (surface && window) {
|
||||
// TODO: look out if window can be different on each call, and if not, store a reference to the window
|
||||
@ -1190,7 +1222,7 @@ void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle
|
||||
/*
|
||||
* Copy the BackBuffer to another Cairo::Surface
|
||||
*/
|
||||
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle)
|
||||
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> &destSurface, GdkRectangle *rectangle)
|
||||
{
|
||||
if (surface && destSurface) {
|
||||
// compute the source offset
|
||||
@ -1212,3 +1244,23 @@ void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, Gdk
|
||||
}
|
||||
}
|
||||
|
||||
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::Context> &context, GdkRectangle *rectangle)
|
||||
{
|
||||
if (surface && context) {
|
||||
// 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
|
||||
context->set_source(surface, x - offsetX, y - offsetY);
|
||||
context->set_line_width(0.);
|
||||
|
||||
if (rectangle) {
|
||||
context->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height);
|
||||
} else {
|
||||
context->rectangle(x, y, w, h);
|
||||
}
|
||||
|
||||
context->fill();
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include "../rtengine/rtengine.h"
|
||||
#include "../rtengine/coord.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
@ -382,33 +383,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle point coordinates
|
||||
*/
|
||||
template <class T>
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
T x, y;
|
||||
Point()
|
||||
{
|
||||
x = T(0);
|
||||
y = T(0);
|
||||
}
|
||||
|
||||
Point(T coordX, T coordY)
|
||||
{
|
||||
x = coordX;
|
||||
y = coordY;
|
||||
}
|
||||
|
||||
void setCoords(T coordX, T coordY)
|
||||
{
|
||||
x = coordX;
|
||||
y = coordY;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle backbuffers as automatically as possible
|
||||
*/
|
||||
@ -417,7 +391,7 @@ class BackBuffer
|
||||
|
||||
protected:
|
||||
int x, y, w, h; // Rectangle where the colored bar has to be drawn
|
||||
Point<int> offset; // Offset of the source region to draw, relative to the top left corner
|
||||
rtengine::Coord 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
|
||||
|
||||
@ -426,13 +400,19 @@ public:
|
||||
|
||||
// set the destination drawing rectangle; return true if the dimensions are different
|
||||
// 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);
|
||||
bool setDrawRectangle(Glib::RefPtr<Gdk::Window> window, int newX, int newY, int newW=-1, int newH=-1, bool updateBackBufferSize = true);
|
||||
bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW=-1, int newH=-1, bool updateBackBufferSize = true);
|
||||
// set the destination drawing location, do not modify other parameters like size and offset. Use setDrawRectangle to set all parameters at the same time
|
||||
void setDestPosition(int x, int y);
|
||||
void setSrcOffset(int x, int y);
|
||||
void setSrcOffset(const rtengine::Coord &newOffset);
|
||||
void getSrcOffset(int &x, int &y);
|
||||
void getSrcOffset(rtengine::Coord &offset);
|
||||
|
||||
void copySurface(Glib::RefPtr<Gdk::Window> window, GdkRectangle *rectangle = NULL);
|
||||
void copySurface(Glib::RefPtr<Gdk::Window> &window, GdkRectangle *rectangle = NULL);
|
||||
void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle = NULL);
|
||||
void copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle = NULL);
|
||||
void copySurface(Cairo::RefPtr<Cairo::ImageSurface> &destSurface, GdkRectangle *rectangle = NULL);
|
||||
void copySurface(Cairo::RefPtr<Cairo::Context> &context, GdkRectangle *rectangle = NULL);
|
||||
|
||||
void setDirty(bool isDirty)
|
||||
{
|
||||
|
@ -178,7 +178,6 @@ CropWindow* ImageArea::getCropWindow (int x, int y)
|
||||
return cw;
|
||||
}
|
||||
|
||||
|
||||
void ImageArea::redraw ()
|
||||
{
|
||||
// dirty prevents multiple updates queued up
|
||||
@ -188,6 +187,11 @@ void ImageArea::redraw ()
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::switchPickerVisibility (bool isVisible)
|
||||
{
|
||||
redraw();
|
||||
}
|
||||
|
||||
bool ImageArea::on_expose_event(GdkEventExpose* event)
|
||||
{
|
||||
dirty = false;
|
||||
@ -690,6 +694,16 @@ ToolMode ImageArea::getToolMode ()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageArea::showColorPickers ()
|
||||
{
|
||||
|
||||
if (listener && listener->getToolBar()) {
|
||||
return listener->getToolBar()->showColorPickers ();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::setToolHand ()
|
||||
{
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "edit.h"
|
||||
|
||||
class ImageAreaPanel;
|
||||
class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider
|
||||
class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider, public LockablePickerToolListener
|
||||
{
|
||||
|
||||
friend class ZoomPanel;
|
||||
@ -122,6 +122,7 @@ public:
|
||||
void cropWindowSelected (CropWindow* cw);
|
||||
void cropWindowClosed (CropWindow* cw);
|
||||
ToolMode getToolMode ();
|
||||
bool showColorPickers ();
|
||||
void setToolHand ();
|
||||
void straightenReady (double rotDeg);
|
||||
void spotWBSelected (int x, int y);
|
||||
@ -143,6 +144,9 @@ public:
|
||||
void cropZoomChanged (CropWindow* cw);
|
||||
void initialImageArrived (CropWindow* cw) ;
|
||||
|
||||
// LockablePickerToolListener interface
|
||||
void switchPickerVisibility (bool isVisible);
|
||||
|
||||
CropWindow* getMainCropWindow ()
|
||||
{
|
||||
return mainCropWindow;
|
||||
|
@ -27,6 +27,7 @@ class ImageAreaToolListener
|
||||
{
|
||||
|
||||
public:
|
||||
virtual ~ImageAreaToolListener() {}
|
||||
virtual void spotWBselected (int x, int y, Thumbnail* thm = NULL) {}
|
||||
virtual int getSpotWBRectSize ()
|
||||
{
|
||||
@ -38,7 +39,6 @@ public:
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
virtual void removeWbTool() = 0;
|
||||
virtual CropGUIListener* startCropEditing (Thumbnail* thm = NULL)
|
||||
{
|
||||
return NULL;
|
||||
|
332
rtgui/lockablecolorpicker.cc
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* 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 "lockablecolorpicker.h"
|
||||
#include "options.h"
|
||||
#include "../rtengine/color.h"
|
||||
#include "../rtengine/rt_math.h"
|
||||
#include "imagearea.h"
|
||||
#include "multilangmgr.h"
|
||||
|
||||
extern Options options;
|
||||
|
||||
LockableColorPicker::LockableColorPicker (CropWindow* cropWindow)
|
||||
: cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(0, 0), size(PickerSize::S20),
|
||||
isValid(false), r(0.f), g(0.f), b(0.f), h(0.f), s(0.f), v(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
LockableColorPicker::LockableColorPicker (int x, int y, PickerSize size, const float R, const float G, const float B, CropWindow* cropWindow)
|
||||
: cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(x, y), size(size),
|
||||
isValid(false), r(R), g(G), b(B)
|
||||
{
|
||||
float h_, s_, v_;
|
||||
rtengine::Color::rgb2hsv((float)r*65535.f, (float)g*65535.f, (float)b*65535.f, h_, s_, v_);
|
||||
h = (int)(h_*255.f);
|
||||
s = (int)(s_*255.f);
|
||||
v = (int)(v_*255.f);
|
||||
}
|
||||
|
||||
void LockableColorPicker::updateBackBuffer ()
|
||||
{
|
||||
int newW, newH;
|
||||
|
||||
// -------------------- setting some key constants ---------------------
|
||||
const float circlePadding = 3.f;
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
if (isValid) {
|
||||
Gtk::DrawingArea *iArea = cropWindow->getImageArea();
|
||||
Cairo::RefPtr<Cairo::Context> bbcr = BackBuffer::getContext();
|
||||
|
||||
Glib::RefPtr<Pango::Context> pangoContext = iArea->get_pango_context ();
|
||||
Pango::FontDescription fontd(options.colorPickerFont);
|
||||
pangoContext->set_font_description (fontd);
|
||||
|
||||
// for drawing text
|
||||
bbcr->set_line_width (0.);
|
||||
|
||||
Glib::RefPtr<Pango::Layout> layout[3][2];
|
||||
|
||||
switch (displayedValues) {
|
||||
case ColorPickerType::RGB:
|
||||
layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_R") + " ");
|
||||
layout[0][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(r*255.f)));
|
||||
layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_G") + " ");
|
||||
layout[1][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(g*255.f)));
|
||||
layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_B") + " ");
|
||||
layout[2][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(b*255.f)));
|
||||
break;
|
||||
case ColorPickerType::HSV:
|
||||
default:
|
||||
layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_H") + " ");
|
||||
layout[0][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(h*255.f)));
|
||||
layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_S") + " ");
|
||||
layout[1][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(s*255.f)));
|
||||
layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_V") + " ");
|
||||
layout[2][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(v*255.f)));
|
||||
}
|
||||
|
||||
int w00, w01, w10, w11, w20, w21, h00, h01, h10, h11, h20, h21;
|
||||
layout[0][0]->get_pixel_size(w00, h00);
|
||||
layout[1][0]->get_pixel_size(w10, h10);
|
||||
layout[2][0]->get_pixel_size(w20, h20);
|
||||
layout[0][1]->get_pixel_size(w01, h01);
|
||||
layout[1][1]->get_pixel_size(w11, h11);
|
||||
layout[2][1]->get_pixel_size(w21, h21);
|
||||
int maxWCol0 = rtengine::max(w00, w10, w20);
|
||||
int maxWCol1 = rtengine::max(w01, w11, w21);
|
||||
int maxHRow0 = rtengine::max(h00, h01);
|
||||
int maxHRow1 = rtengine::max(h10, h11);
|
||||
int maxHRow2 = rtengine::max(h20, h21);
|
||||
|
||||
// -------------------- setting some key constants ---------------------
|
||||
const int textPadding = 2;
|
||||
const int textWidth = maxWCol0 + maxWCol1 + textPadding;
|
||||
const int textHeight = maxHRow0 + maxHRow1 + maxHRow2 + 2*textPadding;
|
||||
const double opacity = 0.75;
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
newW = rtengine::max<int>((int)size + 2 * circlePadding, textWidth + 2 * textPadding);
|
||||
newH = (int)size + 2 * circlePadding + textHeight + 2 * textPadding;
|
||||
|
||||
setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, newW, newH, true);
|
||||
|
||||
float center = (float)size/2.f + circlePadding;
|
||||
|
||||
// black background of the whole color picker
|
||||
bbcr->set_line_width (0.);
|
||||
bbcr->arc_negative (center, center, center, 0.f, (float)M_PI);
|
||||
bbcr->line_to (0, 2.f * center + textHeight + 2*textPadding);
|
||||
bbcr->line_to (textWidth + 2*textPadding, 2.f * center + textHeight + 2*textPadding);
|
||||
bbcr->line_to (textWidth + 2*textPadding, 2.f * center);
|
||||
bbcr->line_to (2.f * center, 2.f * center);
|
||||
bbcr->close_path();
|
||||
bbcr->set_source_rgba (0., 0., 0., opacity);
|
||||
bbcr->set_line_join (Cairo::LINE_JOIN_BEVEL);
|
||||
bbcr->set_line_cap (Cairo::LINE_CAP_SQUARE);
|
||||
bbcr->fill ();
|
||||
|
||||
// light grey circle around the color mark
|
||||
bbcr->arc (center, center, center - circlePadding / 2.f - 0.5f, 0.f, 2.f * (float)M_PI);
|
||||
bbcr->set_source_rgb (0.7, 0.7, 0.7);
|
||||
bbcr->set_line_width (circlePadding-2.f);
|
||||
bbcr->stroke ();
|
||||
|
||||
// spot disc with picked color
|
||||
bbcr->arc (center, center, center - circlePadding - 0.5f, 0.f, 2.f * (float)M_PI);
|
||||
bbcr->set_source_rgb (r, g, b); // <- set the picker color here
|
||||
bbcr->set_line_width (0.);
|
||||
bbcr->fill();
|
||||
|
||||
// adding the font
|
||||
bbcr->set_line_width (0.);
|
||||
bbcr->set_line_join (Cairo::LINE_JOIN_ROUND);
|
||||
bbcr->set_line_cap (Cairo::LINE_CAP_ROUND);
|
||||
bbcr->set_source_rgb (1., 1., 1.);
|
||||
double txtOffsetX = textPadding;
|
||||
double txtOffsetY = (double)size + 2.f * circlePadding + textPadding;
|
||||
switch (iArea->get_direction()) {
|
||||
case Gtk::TEXT_DIR_RTL:
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY);
|
||||
layout[0][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY);
|
||||
layout[0][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + textPadding);
|
||||
layout[1][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY + maxHRow0 + textPadding);
|
||||
layout[1][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding);
|
||||
layout[2][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding);
|
||||
layout[2][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
break;
|
||||
default:
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY);
|
||||
layout[0][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY);
|
||||
layout[0][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + textPadding);
|
||||
layout[1][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY + maxHRow0 + textPadding);
|
||||
layout[1][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
|
||||
bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding);
|
||||
layout[2][0]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding);
|
||||
layout[2][1]->add_to_cairo_context (bbcr);
|
||||
bbcr->fill ();
|
||||
}
|
||||
|
||||
anchorOffset.set (center, center);
|
||||
|
||||
} else {
|
||||
newH = newW = (int)size + 2 * circlePadding;
|
||||
|
||||
setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, newW, newH, true);
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> bbcr = BackBuffer::getContext();
|
||||
|
||||
float center = (float)size/2.f + circlePadding;
|
||||
bbcr->arc (center, center, center - circlePadding/2.f, 0.f, 2.f * (float)M_PI);
|
||||
bbcr->set_source_rgb (0., 0., 0.);
|
||||
bbcr->set_line_width(circlePadding);
|
||||
bbcr->stroke_preserve();
|
||||
bbcr->set_source_rgb (1., 1., 1.);
|
||||
bbcr->set_line_width(circlePadding-2.f);
|
||||
bbcr->stroke ();
|
||||
|
||||
anchorOffset.set (center, center);
|
||||
|
||||
}
|
||||
|
||||
setDirty (false);
|
||||
}
|
||||
|
||||
void LockableColorPicker::draw (Cairo::RefPtr<Cairo::Context> &cr)
|
||||
{
|
||||
if (isDirty()) {
|
||||
updateBackBuffer();
|
||||
}
|
||||
int px, py;
|
||||
cropWindow->imageCoordToScreen(position.x, position.y, px, py);
|
||||
setDestPosition(px - anchorOffset.x, py - anchorOffset.y);
|
||||
|
||||
copySurface(cr);
|
||||
}
|
||||
|
||||
void LockableColorPicker::setPosition (const rtengine::Coord &newPos, const float R, const float G, const float B)
|
||||
{
|
||||
// we're not checking bounds here, this will be done at rendering time
|
||||
position = newPos;
|
||||
|
||||
r = R;
|
||||
g = G;
|
||||
b = B;
|
||||
|
||||
float h_, s_, v_;
|
||||
rtengine::Color::rgb2hsv((float)r*65535.f, (float)g*65535.f, (float)b*65535.f, h_, s_, v_);
|
||||
h = (float)h_;
|
||||
s = (float)s_;
|
||||
v = (float)v_;
|
||||
|
||||
if (isValid) {
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LockableColorPicker::setRGB (const float R, const float G, const float B)
|
||||
{
|
||||
if (r==R && g==G && b==B) {
|
||||
return;
|
||||
}
|
||||
|
||||
r = R;
|
||||
g = G;
|
||||
b = B;
|
||||
|
||||
float h_, s_, v_;
|
||||
rtengine::Color::rgb2hsv((float)r*65535.f, (float)g*65535.f, (float)b*65535.f, h_, s_, v_);
|
||||
h = (float)h_;
|
||||
s = (float)s_;
|
||||
v = (float)v_;
|
||||
|
||||
if (isValid) {
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LockableColorPicker::getImagePosition (rtengine::Coord &imgPos)
|
||||
{
|
||||
imgPos = position;
|
||||
}
|
||||
|
||||
void LockableColorPicker::getScreenPosition (rtengine::Coord &screenPos)
|
||||
{
|
||||
if (cropWindow) {
|
||||
cropWindow->imageCoordToScreen(position.x, position.y, screenPos.x, screenPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
bool LockableColorPicker::isOver (int x, int y)
|
||||
{
|
||||
if (!cropWindow) {
|
||||
return false;
|
||||
}
|
||||
rtengine::Coord pickerScreenPos;
|
||||
cropWindow->imageCoordToScreen(position.x, position.y, pickerScreenPos.x, pickerScreenPos.y);
|
||||
|
||||
rtengine::Coord mousePos(x, y);
|
||||
rtengine::Coord wh(getWidth(), getHeight());
|
||||
rtengine::Coord tl(pickerScreenPos - anchorOffset);
|
||||
rtengine::Coord br(tl + wh);
|
||||
return mousePos >= tl && mousePos <= br;
|
||||
}
|
||||
|
||||
void LockableColorPicker::setValidity (bool isValid)
|
||||
{
|
||||
if (this->isValid != isValid) {
|
||||
setDirty(true);
|
||||
}
|
||||
this->isValid = isValid;
|
||||
}
|
||||
|
||||
void LockableColorPicker::setSize (PickerSize newSize)
|
||||
{
|
||||
if (size != newSize)
|
||||
{
|
||||
size = newSize;
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
LockableColorPicker::PickerSize LockableColorPicker::getSize ()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
void LockableColorPicker::incSize ()
|
||||
{
|
||||
if (size < PickerSize::S30) {
|
||||
size = (PickerSize)((int)size + 5);
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LockableColorPicker::decSize ()
|
||||
{
|
||||
if (size > PickerSize::S5) {
|
||||
size = (PickerSize)((int)size - 5);
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
85
rtgui/lockablecolorpicker.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 __COLORPICKER__
|
||||
#define __COLORPICKER__
|
||||
|
||||
|
||||
#include "../rtengine/coord.h"
|
||||
#include "guiutils.h"
|
||||
#include "edit.h"
|
||||
|
||||
class CropWindow;
|
||||
|
||||
class LockablePickerToolListener {
|
||||
public:
|
||||
virtual ~LockablePickerToolListener () {}
|
||||
|
||||
/// Callback on Color Picker's visibility switch
|
||||
virtual void switchPickerVisibility (bool isVisible) {}
|
||||
};
|
||||
|
||||
class LockableColorPicker : BackBuffer
|
||||
{
|
||||
public:
|
||||
enum class PickerSize {
|
||||
S5=5,
|
||||
S10=10,
|
||||
S15=15,
|
||||
S20=20,
|
||||
S25=25,
|
||||
S30=30
|
||||
};
|
||||
private:
|
||||
enum class ColorPickerType {
|
||||
RGB,
|
||||
HSV
|
||||
};
|
||||
CropWindow* cropWindow; // the color picker is displayed in a single cropWindow, the one that the user has clicked in
|
||||
ColorPickerType displayedValues;
|
||||
rtengine::Coord position; // Coordinate in image space
|
||||
rtengine::Coord anchorOffset;
|
||||
PickerSize size;
|
||||
bool isValid;
|
||||
float r, g, b; // red green blue in [0;1] range
|
||||
float h, s, v; // hue saturation value in [0;1] range
|
||||
|
||||
void updateBackBuffer ();
|
||||
|
||||
public:
|
||||
|
||||
LockableColorPicker (CropWindow* cropWindow);
|
||||
LockableColorPicker (int x, int y, PickerSize size, const float R, const float G, const float B, CropWindow* cropWindow);
|
||||
|
||||
void draw (Cairo::RefPtr<Cairo::Context> &cr);
|
||||
|
||||
// Used to update the RGB color, the HSV values will be updated accordingly
|
||||
void setPosition (const rtengine::Coord &newPos, const float R, const float G, const float B);
|
||||
void setRGB (const float R, const float G, const float B);
|
||||
void getImagePosition (rtengine::Coord &imgPos);
|
||||
void getScreenPosition (rtengine::Coord &screenPos);
|
||||
PickerSize getSize ();
|
||||
bool isOver (int x, int y);
|
||||
void setValidity (bool isValid);
|
||||
void setSize (PickerSize newSize);
|
||||
void incSize ();
|
||||
void decSize ();
|
||||
};
|
||||
|
||||
#endif
|
@ -292,6 +292,7 @@ void Options::setDefaults ()
|
||||
{
|
||||
|
||||
font = "sans, 8";
|
||||
colorPickerFont = "sans, 8";
|
||||
windowWidth = 1200;
|
||||
windowHeight = 680;
|
||||
windowX = 0;
|
||||
@ -1246,6 +1247,10 @@ int Options::readFromFile (Glib::ustring fname)
|
||||
font = keyFile.get_string ("GUI", "Font");
|
||||
}
|
||||
|
||||
if (keyFile.has_key ("GUI", "ColorPickerFont")) {
|
||||
colorPickerFont = keyFile.get_string ("GUI", "ColorPickerFont");
|
||||
}
|
||||
|
||||
if (keyFile.has_key ("GUI", "WindowWidth")) {
|
||||
windowWidth = keyFile.get_integer ("GUI", "WindowWidth");
|
||||
}
|
||||
@ -1973,6 +1978,7 @@ int Options::saveToFile (Glib::ustring fname)
|
||||
keyFile.set_integer ("Profiles", "CustomProfileBuilderKeys", CPBKeys);
|
||||
|
||||
keyFile.set_string ("GUI", "Font", font);
|
||||
keyFile.set_string ("GUI", "ColorPickerFont", colorPickerFont);
|
||||
keyFile.set_integer ("GUI", "WindowWidth", windowWidth);
|
||||
keyFile.set_integer ("GUI", "WindowHeight", windowHeight);
|
||||
keyFile.set_integer ("GUI", "WindowX", windowX);
|
||||
|
@ -120,6 +120,7 @@ public:
|
||||
bool editorFilmStripOpened;
|
||||
int historyPanelWidth;
|
||||
Glib::ustring font;
|
||||
Glib::ustring colorPickerFont;
|
||||
int windowWidth;
|
||||
int windowHeight;
|
||||
int windowX;
|
||||
|
@ -931,14 +931,21 @@ Gtk::Widget* Preferences::getGeneralPanel ()
|
||||
hbtheme->pack_start (*fontbutton);
|
||||
vbftheme->pack_start(*hbtheme, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
Gtk::Label* cpfontlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTFONT_COLPICKER") + ":") );
|
||||
colorPickerFontButton = Gtk::manage( new Gtk::FontButton ());
|
||||
colorPickerFontButton->set_use_size(true);
|
||||
colorPickerFontButton->set_font_name(options.colorPickerFont);
|
||||
|
||||
|
||||
Gtk::HBox* hbcolorchooser = Gtk::manage( new Gtk::HBox () );
|
||||
hbcolorchooser->set_spacing(4);
|
||||
|
||||
hbcolorchooser->pack_start (*cutOverlayLabel, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_start (*butCropCol, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_end (*butNavGuideCol, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_end (*navGuideLabel, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_start (*butNavGuideCol, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_start (*navGuideLabel, Gtk::PACK_SHRINK, 0);
|
||||
hbcolorchooser->pack_start (*cpfontlab, Gtk::PACK_EXPAND_WIDGET, 0);
|
||||
hbcolorchooser->pack_start (*colorPickerFontButton, Gtk::PACK_SHRINK, 0);
|
||||
vbftheme->pack_start(*hbcolorchooser, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
|
||||
@ -1414,6 +1421,7 @@ void Preferences::storePreferences ()
|
||||
moptions.navGuideBrush[3] = butNavGuideCol->get_alpha() / 65535.0;
|
||||
|
||||
moptions.font = fontbutton->get_font_name();
|
||||
moptions.colorPickerFont = colorPickerFontButton->get_font_name();
|
||||
#ifdef WIN32
|
||||
moptions.gimpDir = gimpDir->get_filename ();
|
||||
moptions.psDir = psDir->get_filename ();
|
||||
@ -1629,6 +1637,7 @@ void Preferences::fillPreferences ()
|
||||
butNavGuideCol->set_alpha ( (unsigned short)(moptions.navGuideBrush[3] * 65535.0));
|
||||
|
||||
fontbutton->set_font_name(moptions.font);
|
||||
colorPickerFontButton->set_font_name(moptions.colorPickerFont);
|
||||
showDateTime->set_active (moptions.fbShowDateTime);
|
||||
showBasicExif->set_active (moptions.fbShowBasicExif);
|
||||
showExpComp->set_active (moptions.fbShowExpComp);
|
||||
|
@ -131,6 +131,7 @@ protected:
|
||||
Gtk::HBox* hbtheme;
|
||||
Gtk::CheckButton* chUseSystemTheme;
|
||||
Gtk::FontButton* fontbutton;
|
||||
Gtk::FontButton* colorPickerFontButton;
|
||||
Gtk::ColorButton* butCropCol;
|
||||
Gtk::ColorButton* butNavGuideCol;
|
||||
|
||||
|
156
rtgui/toolbar.cc
@ -20,7 +20,7 @@
|
||||
#include "multilangmgr.h"
|
||||
#include "guiutils.h"
|
||||
|
||||
ToolBar::ToolBar () : listener (NULL)
|
||||
ToolBar::ToolBar () : showColPickers(true), listener (NULL)
|
||||
{
|
||||
|
||||
editingMode = false;
|
||||
@ -47,6 +47,19 @@ ToolBar::ToolBar () : listener (NULL)
|
||||
|
||||
pack_start (*wbTool);
|
||||
|
||||
showcolpickersimg = Gtk::manage (new RTImage ("colorPickers-show.png"));
|
||||
showcolpickersimg->reference();
|
||||
hidecolpickersimg = Gtk::manage (new RTImage ("colorPickers-hide.png"));
|
||||
hidecolpickersimg->reference();
|
||||
|
||||
colPickerTool = Gtk::manage (new Gtk::ToggleButton ());
|
||||
colPickerTool->add (*showcolpickersimg);
|
||||
showcolpickersimg->show ();
|
||||
colPickerTool->set_relief(Gtk::RELIEF_NONE);
|
||||
colPickerTool->show ();
|
||||
|
||||
pack_start (*colPickerTool);
|
||||
|
||||
cropTool = Gtk::manage (new Gtk::ToggleButton ());
|
||||
Gtk::Image* cropimg = Gtk::manage (new RTImage ("crop.png"));
|
||||
cropTool->add (*cropimg);
|
||||
@ -71,11 +84,13 @@ ToolBar::ToolBar () : listener (NULL)
|
||||
|
||||
handConn = handTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::hand_pressed));
|
||||
wbConn = wbTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::wb_pressed));
|
||||
cpConn = colPickerTool->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &ToolBar::colPicker_pressed));
|
||||
cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed));
|
||||
straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed));
|
||||
|
||||
handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND"));
|
||||
wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB"));
|
||||
colPickerTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_COLORPICKER"));
|
||||
cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP"));
|
||||
straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN"));
|
||||
}
|
||||
@ -84,6 +99,8 @@ ToolBar::~ToolBar ()
|
||||
{
|
||||
handimg->unreference();
|
||||
editinghandimg->unreference();
|
||||
showcolpickersimg->unreference();
|
||||
hidecolpickersimg->unreference();
|
||||
|
||||
}
|
||||
//
|
||||
@ -98,6 +115,9 @@ void ToolBar::setTool (ToolMode tool)
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
}
|
||||
if (colPickerTool) {
|
||||
cpConn.block (true);
|
||||
}
|
||||
|
||||
straConn.block (true);
|
||||
|
||||
@ -111,6 +131,9 @@ void ToolBar::setTool (ToolMode tool)
|
||||
|
||||
cropTool->set_active (false);
|
||||
straTool->set_active (false);
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active (false);
|
||||
}
|
||||
|
||||
if (tool == TMHand) {
|
||||
handTool->set_active (true);
|
||||
@ -123,6 +146,10 @@ void ToolBar::setTool (ToolMode tool)
|
||||
cropTool->set_active (true);
|
||||
} else if (tool == TMStraighten) {
|
||||
straTool->set_active (true);
|
||||
} else if (tool == TMColorPicker) {
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active (true);
|
||||
}
|
||||
}
|
||||
|
||||
current = tool;
|
||||
@ -133,6 +160,9 @@ void ToolBar::setTool (ToolMode tool)
|
||||
if (wbTool) {
|
||||
wbConn.block (false);
|
||||
}
|
||||
if (colPickerTool) {
|
||||
cpConn.block (false);
|
||||
}
|
||||
|
||||
straConn.block (false);
|
||||
|
||||
@ -181,6 +211,9 @@ void ToolBar::hand_pressed ()
|
||||
|
||||
handConn.block (true);
|
||||
cropConn.block (true);
|
||||
if (colPickerTool) {
|
||||
cpConn.block (true);
|
||||
}
|
||||
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
@ -189,6 +222,9 @@ void ToolBar::hand_pressed ()
|
||||
straConn.block (true);
|
||||
|
||||
if (current != TMHand) {
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active(false);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbTool->set_active (false);
|
||||
}
|
||||
@ -209,7 +245,9 @@ void ToolBar::hand_pressed ()
|
||||
handTool->set_active (true);
|
||||
handConn.block (false);
|
||||
cropConn.block (false);
|
||||
|
||||
if (colPickerTool) {
|
||||
cpConn.block (false);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbConn.block (false);
|
||||
}
|
||||
@ -226,7 +264,9 @@ void ToolBar::wb_pressed ()
|
||||
|
||||
handConn.block (true);
|
||||
cropConn.block (true);
|
||||
|
||||
if (colPickerTool) {
|
||||
cpConn.block (true);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
}
|
||||
@ -237,6 +277,9 @@ void ToolBar::wb_pressed ()
|
||||
handTool->set_active (false);
|
||||
cropTool->set_active (false);
|
||||
straTool->set_active (false);
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active(false);
|
||||
}
|
||||
current = TMSpotWB;
|
||||
}
|
||||
|
||||
@ -246,7 +289,9 @@ void ToolBar::wb_pressed ()
|
||||
|
||||
handConn.block (false);
|
||||
cropConn.block (false);
|
||||
|
||||
if (colPickerTool) {
|
||||
cpConn.block (false);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbConn.block (false);
|
||||
}
|
||||
@ -258,11 +303,92 @@ void ToolBar::wb_pressed ()
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBar::colPicker_pressed (GdkEventButton* event)
|
||||
{
|
||||
|
||||
if (event->button == 1) {
|
||||
handConn.block (true);
|
||||
cropConn.block (true);
|
||||
cpConn.block (true);
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
}
|
||||
|
||||
straConn.block (true);
|
||||
|
||||
cropTool->set_active (false);
|
||||
if (wbTool) {
|
||||
wbTool->set_active (false);
|
||||
}
|
||||
straTool->set_active (false);
|
||||
|
||||
if (current != TMColorPicker) {
|
||||
// Disabling all other tools, enabling the Picker tool and entering the "visible pickers" mode
|
||||
handTool->set_active (false);
|
||||
showColorPickers(true);
|
||||
current = TMColorPicker;
|
||||
} else {
|
||||
// Disabling the picker tool, enabling the Hand tool and keeping the "visible pickers" mode
|
||||
handTool->set_active (true);
|
||||
colPickerTool->set_active (false);
|
||||
current = TMHand;
|
||||
}
|
||||
|
||||
handConn.block (false);
|
||||
cropConn.block (false);
|
||||
cpConn.block (false);
|
||||
wbConn.block (false);
|
||||
straConn.block (false);
|
||||
|
||||
if (listener) {
|
||||
listener->toolSelected (current);
|
||||
}
|
||||
} else if (event->button == 3) {
|
||||
if (current == TMColorPicker) {
|
||||
// Disabling the Picker tool and entering into the "invisible pickers" mode
|
||||
cpConn.block (true);
|
||||
handConn.block (true);
|
||||
handTool->set_active (true);
|
||||
colPickerTool->set_active (false);
|
||||
current = TMHand;
|
||||
showColorPickers(false);
|
||||
cpConn.block (false);
|
||||
handConn.block (false);
|
||||
} else {
|
||||
// The Picker tool is already disabled, entering into the "invisible pickers" mode
|
||||
switchColorPickersVisibility();
|
||||
}
|
||||
if (pickerListener) {
|
||||
pickerListener->switchPickerVisibility (showColPickers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolBar::showColorPickers(bool showCP)
|
||||
{
|
||||
if (showColPickers != showCP) {
|
||||
// Inverting the state
|
||||
colPickerTool->set_image(showCP ? *showcolpickersimg : *hidecolpickersimg);
|
||||
showColPickers = showCP;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToolBar::switchColorPickersVisibility()
|
||||
{
|
||||
// Inverting the state
|
||||
showColPickers = !showColPickers;
|
||||
colPickerTool->set_image(showColPickers ? *showcolpickersimg : *hidecolpickersimg);
|
||||
}
|
||||
|
||||
void ToolBar::crop_pressed ()
|
||||
{
|
||||
|
||||
handConn.block (true);
|
||||
cropConn.block (true);
|
||||
cpConn.block(true);
|
||||
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
@ -272,7 +398,9 @@ void ToolBar::crop_pressed ()
|
||||
|
||||
if (current != TMCropSelect) {
|
||||
handTool->set_active (false);
|
||||
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active(false);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbTool->set_active (false);
|
||||
}
|
||||
@ -284,6 +412,7 @@ void ToolBar::crop_pressed ()
|
||||
cropTool->set_active (true);
|
||||
handConn.block (false);
|
||||
cropConn.block (false);
|
||||
cpConn.block(false);
|
||||
wbConn.block (false);
|
||||
straConn.block (false);
|
||||
|
||||
@ -297,6 +426,9 @@ void ToolBar::stra_pressed ()
|
||||
|
||||
handConn.block (true);
|
||||
cropConn.block (true);
|
||||
if (colPickerTool) {
|
||||
cpConn.block (true);
|
||||
}
|
||||
|
||||
if (wbTool) {
|
||||
wbConn.block (true);
|
||||
@ -306,7 +438,9 @@ void ToolBar::stra_pressed ()
|
||||
|
||||
if (current != TMStraighten) {
|
||||
handTool->set_active (false);
|
||||
|
||||
if (colPickerTool) {
|
||||
colPickerTool->set_active(false);
|
||||
}
|
||||
if (wbTool) {
|
||||
wbTool->set_active (false);
|
||||
}
|
||||
@ -318,6 +452,7 @@ void ToolBar::stra_pressed ()
|
||||
straTool->set_active (true);
|
||||
handConn.block (false);
|
||||
cropConn.block (false);
|
||||
cpConn.block (false);
|
||||
|
||||
if (wbTool) {
|
||||
wbConn.block (false);
|
||||
@ -371,12 +506,17 @@ bool ToolBar::handleShortcutKey (GdkEventKey* event)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToolBar::removeWbTool()
|
||||
void ToolBar::setBatchMode()
|
||||
{
|
||||
if (wbTool) {
|
||||
wbConn.disconnect();
|
||||
removeIfThere(this, wbTool, false);
|
||||
wbTool = NULL;
|
||||
wbTool = nullptr;
|
||||
}
|
||||
if (colPickerTool) {
|
||||
cpConn.disconnect();
|
||||
removeIfThere(this, colPickerTool, false);
|
||||
colPickerTool = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <gtkmm.h>
|
||||
#include "toolenum.h"
|
||||
#include "rtimage.h"
|
||||
#include "lockablecolorpicker.h"
|
||||
|
||||
class ToolBarListener
|
||||
{
|
||||
@ -40,17 +41,31 @@ class ToolBar : public Gtk::HBox
|
||||
private:
|
||||
RTImage* handimg;
|
||||
RTImage* editinghandimg;
|
||||
RTImage* showcolpickersimg;
|
||||
RTImage* hidecolpickersimg;
|
||||
bool showColPickers;
|
||||
|
||||
void hand_pressed ();
|
||||
void wb_pressed ();
|
||||
void colPicker_pressed (GdkEventButton* event);
|
||||
void crop_pressed ();
|
||||
void stra_pressed ();
|
||||
bool showColorPickers(bool showCP);
|
||||
void switchColorPickersVisibility();
|
||||
|
||||
protected:
|
||||
Gtk::ToggleButton* handTool;
|
||||
Gtk::ToggleButton* wbTool;
|
||||
Gtk::ToggleButton* colPickerTool;
|
||||
Gtk::ToggleButton* cropTool;
|
||||
Gtk::ToggleButton* straTool;
|
||||
ToolBarListener* listener;
|
||||
LockablePickerToolListener* pickerListener;
|
||||
ToolMode current;
|
||||
bool editingMode; // true if the cursor is being used to remotely edit tool's values
|
||||
sigc::connection handConn;
|
||||
sigc::connection wbConn;
|
||||
sigc::connection cpConn;
|
||||
sigc::connection cropConn;
|
||||
sigc::connection straConn;
|
||||
|
||||
@ -64,21 +79,25 @@ public:
|
||||
return current;
|
||||
}
|
||||
|
||||
bool showColorPickers() {
|
||||
return showColPickers;
|
||||
}
|
||||
|
||||
void setToolBarListener (ToolBarListener* tpl)
|
||||
{
|
||||
listener = tpl;
|
||||
}
|
||||
|
||||
void setLockablePickerToolListener (LockablePickerToolListener* lptl)
|
||||
{
|
||||
pickerListener = lptl;
|
||||
}
|
||||
|
||||
void startEditMode();
|
||||
void stopEditMode();
|
||||
|
||||
void hand_pressed ();
|
||||
void wb_pressed ();
|
||||
void crop_pressed ();
|
||||
void stra_pressed ();
|
||||
|
||||
bool handleShortcutKey (GdkEventKey* event);
|
||||
void removeWbTool();
|
||||
void setBatchMode();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,6 @@
|
||||
#ifndef _TOOLENUM_
|
||||
#define _TOOLENUM_
|
||||
|
||||
enum ToolMode {TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3};
|
||||
enum ToolMode {TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4};
|
||||
|
||||
#endif
|
||||
|
@ -294,12 +294,6 @@ public:
|
||||
{
|
||||
return toolBar;
|
||||
}
|
||||
void removeWbTool()
|
||||
{
|
||||
if (toolBar) {
|
||||
toolBar->removeWbTool();
|
||||
}
|
||||
}
|
||||
int getSpotWBRectSize ();
|
||||
CropGUIListener* startCropEditing (Thumbnail* thm = NULL)
|
||||
{
|
||||
|
1
tools/source_icons/scalable/colorPickers-hide.file
Normal file
@ -0,0 +1 @@
|
||||
colorPickers-hide.png,w22,actions
|
4301
tools/source_icons/scalable/colorPickers-hide.svg
Normal file
After Width: | Height: | Size: 141 KiB |
1
tools/source_icons/scalable/colorPickers-show.file
Normal file
@ -0,0 +1 @@
|
||||
colorPickers-show.png,w22,actions
|
4372
tools/source_icons/scalable/colorPickers-show.svg
Normal file
After Width: | Height: | Size: 147 KiB |
1
tools/source_icons/scalable/gtk-color-picker-add.file
Normal file
@ -0,0 +1 @@
|
||||
gtk-color-picker-add.png,w22,actions
|
4839
tools/source_icons/scalable/gtk-color-picker-add.svg
Normal file
After Width: | Height: | Size: 178 KiB |