Pipette and "On Preview Widgets" branch. See issue 227

The pipette part is already working quite nice but need to be finished. The widgets part needs more work...
This commit is contained in:
Hombre
2014-01-21 23:37:36 +01:00
commit 8b2eac9a3d
1631 changed files with 379231 additions and 0 deletions

482
rtgui/imagearea.cc Normal file
View File

@@ -0,0 +1,482 @@
/*
* 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 "imagearea.h"
#include <ctime>
#include <cmath>
#include "options.h"
#include "multilangmgr.h"
#include <iomanip>
#include "cropwindow.h"
#include "../rtengine/refreshmap.h"
#include "options.h"
ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) {
infotext = "";
cropgl = NULL;
pmlistener = NULL;
pmhlistener = NULL;
focusGrabber = NULL;
mainCropWindow = NULL;
previewHandler = NULL;
lastClosedX = -1;
showClippedH = false;
showClippedS = false;
listener = NULL;
zoomPanel = Gtk::manage (new ZoomPanel (this));
indClippedPanel = Gtk::manage (new IndicateClippedPanel (this));
previewModePanel = Gtk::manage (new PreviewModePanel (this));
signal_style_changed().connect( sigc::mem_fun(*this, &ImageArea::styleChanged) );
signal_size_allocate().connect( sigc::mem_fun(*this, &ImageArea::on_resized) );
dirty = false;
ipc = NULL;
iLinkedImageArea = NULL;
}
ImageArea::~ImageArea () {
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
delete *i;
cropWins.clear ();
if (mainCropWindow)
delete mainCropWindow;
}
void ImageArea::on_realize()
{
Gtk::DrawingArea::on_realize();
#if defined (__APPLE__)
// Workaround: disabling POINTER_MOTION_HINT_MASK as for gtk 2.24.22 the get_pointer() function is buggy for quartz and modifier mask is not updated correctly.
// This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
#else
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
#endif
Cairo::FontOptions cfo;
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
get_pango_context ()->set_cairo_font_options (cfo);
}
void ImageArea::on_resized (Gtk::Allocation& req) {
if (ipc && get_width()>1) { // sometimes on_resize is called in some init state, causing wrong sizes
if (!mainCropWindow) {
mainCropWindow = new CropWindow (this, ipc, false);
mainCropWindow->setDecorated (false);
mainCropWindow->setFitZoomEnabled (true);
mainCropWindow->addCropWindowListener (this);
mainCropWindow->setCropGUIListener (cropgl);
mainCropWindow->setPointerMotionListener (pmlistener);
mainCropWindow->setPointerMotionHListener (pmhlistener);
mainCropWindow->setPosition (0, 0);
mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself
}
else {
mainCropWindow->setSize (get_width(), get_height());
}
parent->syncBeforeAfterViews();
}
}
void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {
if( !ipc_ ){
focusGrabber = NULL;
std::list<CropWindow*>::iterator i = cropWins.begin();
if( i!=cropWins.end() ){
(*i)->getPosition (lastClosedX, lastClosedY);
(*i)->getSize (lastClosedW, lastClosedH);
}
for( ;i!=cropWins.end();i++ ){
delete *i;
}
cropWins.clear();
mainCropWindow->setObservedCropWin (NULL);
}
ipc = ipc_;
}
void ImageArea::setPreviewHandler (PreviewHandler* ph) {
previewHandler = ph;
}
void ImageArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
// TODO: notify all crop windows that the style has been changed
queue_draw ();
}
void ImageArea::setInfoText (Glib::ustring text) {
infotext = text;
Glib::RefPtr<Pango::Context> context = get_pango_context () ;
Pango::FontDescription fontd = context->get_font_description ();
fontd.set_weight (Pango::WEIGHT_BOLD);
fontd.set_size (9*Pango::SCALE);
context->set_font_description (fontd);
ilayout = create_pango_layout("");
ilayout->set_markup(text);
int iw, ih;
ilayout->get_pixel_size (iw, ih);
ipixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, true, 8, iw+8, ih+8);
ipixbuf->fill (128);
}
void ImageArea::infoEnabled (bool e) {
if (options.showInfo!=e) {
options.showInfo = e;
queue_draw ();
}
}
CropWindow* ImageArea::getCropWindow (int x, int y) {
CropWindow* cw = mainCropWindow;
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
if ((*i)->isInside (x, y))
return *i;
return cw;
}
void ImageArea::redraw () {
// dirty prevents multiple updates queued up
if (!dirty) {
dirty = true;
queue_draw ();
}
}
bool ImageArea::on_expose_event(GdkEventExpose* event) {
dirty = false;
if (event->count)
return true;
Glib::RefPtr<Gdk::Window> window = get_window();
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
if (mainCropWindow)
mainCropWindow->expose (cr);
if (options.showInfo==true && infotext!="") {
int fnw, fnh;
ilayout->get_pixel_size (fnw, fnh);
window->draw_pixbuf (get_style()->get_base_gc (Gtk::STATE_NORMAL), ipixbuf, 0, 0, 4, 4, fnw+8, fnh+8, Gdk::RGB_DITHER_NONE, 0, 0);
cr->set_source_rgb (1.0, 1.0, 1.0);
cr->move_to (8, 8);
ilayout->add_to_cairo_context (cr);
cr->fill ();
}
for (std::list<CropWindow*>::reverse_iterator i=cropWins.rbegin(); i!=cropWins.rend(); i++)
(*i)->expose (cr);
return true;
}
bool ImageArea::on_motion_notify_event (GdkEventMotion* event) {
if (focusGrabber)
focusGrabber->pointerMoved (event->x, event->y);
else {
CropWindow* cw = getCropWindow (event->x, event->y);
if (cw)
cw->pointerMoved (event->x, event->y);
}
return true;
}
bool ImageArea::on_button_press_event (GdkEventButton* event) {
if (focusGrabber)
focusGrabber->buttonPress (event->button, event->type, event->state, event->x, event->y);
else {
CropWindow* cw = getCropWindow (event->x, event->y);
if (cw)
cw->buttonPress (event->button, event->type, event->state, event->x, event->y);
}
return true;
}
bool ImageArea::on_scroll_event (GdkEventScroll* event) {
CropWindow* cw = getCropWindow (event->x, event->y);
if (cw) {
int newCenterX = (int)event->x;
int newCenterY = (int)event->y;
if (event->direction==GDK_SCROLL_UP && !cw->isMaxZoom()) {
cw->findCenter (1, newCenterX, newCenterY);
cw->zoomIn (true, newCenterX, newCenterY);
}
else if (!cw->isMinZoom()) {
cw->findCenter (-1, newCenterX, newCenterY);
cw->zoomOut (true, newCenterX, newCenterY);
}
}
return true;
}
bool ImageArea::on_button_release_event (GdkEventButton* event) {
if (focusGrabber)
focusGrabber->buttonRelease (event->button, event->type, event->state, event->x, event->y);
else {
CropWindow* cw = getCropWindow (event->x, event->y);
if (cw) {
cw->buttonRelease (event->button, event->type, event->state, event->x, event->y);
}
}
return true;
}
void ImageArea::grabFocus (CropWindow* cw) {
focusGrabber = cw;
if (cw && cw!=mainCropWindow)
cropWindowSelected (cw);
}
void ImageArea::unGrabFocus () {
focusGrabber = NULL;
}
void ImageArea::addCropWindow () {
if (!mainCropWindow) return; // if called but no image is loaded, it would crash
CropWindow* cw = new CropWindow (this, ipc, true);
cw->zoom11();
cw->setCropGUIListener (cropgl);
cw->setPointerMotionListener (pmlistener);
cw->setPointerMotionHListener (pmhlistener);
cropWins.push_front (cw);
// Position the new crop window in a checkerboard, or used the last position
if (lastClosedX<0) {
int K = 2;
int hBorder = get_width()/K/8;
int vBorder = get_height()/K/8;
int N = cropWins.size()-1;
int layer = N/K/K;
int row = K-1 - (N % (K*K)) / K;
int col = K-1 - (N % (K*K)) % K;
int cropwidth, cropheight;
cropwidth = get_width()/K - hBorder;
cropheight = get_height()/K - vBorder;
if (options.squareDetailWindow){
// force square CropWindow (this is faster as area is smaller)
if (cropwidth<cropheight) cropheight=cropwidth;
if (cropheight<cropwidth) cropwidth=cropheight;
}
cw->setSize (cropwidth,cropheight);
cw->setPosition (col*get_width()/K + hBorder/2 + layer*30, row*get_height()/K + vBorder/2 + layer*30);
}
else {
cw->setPosition (lastClosedX, lastClosedY);
cw->setSize(lastClosedW, lastClosedH);
}
int x0,y0,w,h,wc,hc;
mainCropWindow->getCropRectangle(x0,y0,w,h );
cw->getCropSize(wc,hc);
cw->setCropPosition(x0+w/2-wc/2,y0+h/2-hc/2);
mainCropWindow->setObservedCropWin (cropWins.front());
ipc->startProcessing(M_HIGHQUAL);
// queue_draw ();
}
void ImageArea::cropWindowSelected (CropWindow* cw) {
std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
if (i!=cropWins.end())
cropWins.erase (i);
cropWins.push_front (cw);
mainCropWindow->setObservedCropWin (cropWins.front());
}
void ImageArea::cropWindowClosed (CropWindow* cw) {
focusGrabber = NULL;
cw->getPosition (lastClosedX, lastClosedY);
cw->getSize (lastClosedW, lastClosedH);
std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
if (i!=cropWins.end())
cropWins.erase (i);
delete cw;
if (!cropWins.empty())
mainCropWindow->setObservedCropWin (cropWins.front());
else
mainCropWindow->setObservedCropWin (NULL);
queue_draw ();
}
void ImageArea::straightenReady (double rotDeg) {
if (listener)
listener->rotateSelectionReady (rotDeg);
}
void ImageArea::spotWBSelected (int x, int y) {
if (listener)
listener->spotWBselected (x, y);
}
void ImageArea::getScrollImageSize (int& w, int& h) {
if (mainCropWindow && ipc) {
double z = mainCropWindow->getZoom ();
w = ipc->getFullWidth() * z;
h = ipc->getFullHeight() * z;
}
else
w = h = 0;
}
void ImageArea::getScrollPosition (int& x, int& y) {
if (mainCropWindow) {
int cropX, cropY;
mainCropWindow->getCropPosition (cropX, cropY);
x = cropX*mainCropWindow->getZoom ();
y = cropY*mainCropWindow->getZoom ();
}
else
x = y = 0;
}
void ImageArea::setScrollPosition (int x, int y) {
if (mainCropWindow) {
mainCropWindow->delCropWindowListener (this);
mainCropWindow->setCropPosition (x/mainCropWindow->getZoom (), y/mainCropWindow->getZoom ());
mainCropWindow->addCropWindowListener (this);
}
}
void ImageArea::cropPositionChanged (CropWindow* cw) {
syncBeforeAfterViews ();
}
void ImageArea::cropWindowSizeChanged (CropWindow* cw) {
syncBeforeAfterViews ();
}
void ImageArea::cropZoomChanged (CropWindow* cw) {
if (cw==mainCropWindow) {
parent->zoomChanged ();
syncBeforeAfterViews ();
zoomPanel->refreshZoomLabel ();
}
}
double ImageArea::getZoom () {
if (mainCropWindow)
return mainCropWindow->getZoom ();
else
return 1.0;
}
// Called by imageAreaPanel before/after views
void ImageArea::setZoom (double zoom) {
if (mainCropWindow)
mainCropWindow->setZoom (zoom);
zoomPanel->refreshZoomLabel ();
}
void ImageArea::initialImageArrived (CropWindow* cw) {
if (mainCropWindow)
mainCropWindow->zoomFit ();
}
void ImageArea::syncBeforeAfterViews () {
parent->syncBeforeAfterViews ();
}
void ImageArea::setCropGUIListener (CropGUIListener* l) {
cropgl = l;
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
(*i)->setCropGUIListener (cropgl);
if (mainCropWindow)
mainCropWindow->setCropGUIListener (cropgl);
}
void ImageArea::setPointerMotionListener (PointerMotionListener* pml) {
pmlistener = pml;
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
(*i)->setPointerMotionListener (pml);
if (mainCropWindow)
mainCropWindow->setPointerMotionListener (pml);
}
void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) {
pmhlistener = pml;
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
(*i)->setPointerMotionHListener (pml);
if (mainCropWindow)
mainCropWindow->setPointerMotionHListener (pml);
}
ToolMode ImageArea::getToolMode () {
if (listener && listener->getToolBar())
return listener->getToolBar()->getTool ();
else
return TMHand;
}
void ImageArea::setToolHand () {
if (listener && listener->getToolBar())
listener->getToolBar()->setTool (TMHand);
}
int ImageArea::getSpotWBRectSize () {
if (listener)
return listener->getSpotWBRectSize ();
else
return 1;
}