/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include "previewwindow.h" #include "guiutils.h" #include "imagearea.h" #include "cursormanager.h" PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL), imageArea(NULL), imgX(0), imgY(0), imgW(0), imgH(0), zoom(0.0), isMoving(false), needsUpdate(false) { rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); } void PreviewWindow::on_realize () { Gtk::DrawingArea::on_realize (); add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); } void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { if (mainCropWin) { int cropX, cropY, cropW, cropH; mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); // translate it to screen coordinates x = imgX + round(cropX*zoom); y = imgY + round(cropY*zoom); w = round(cropW * zoom); h = round(cropH * zoom); } } void PreviewWindow::updatePreviewImage () { int W = get_width(), H = get_height(); Glib::RefPtr wind = get_window(); if( ! wind ) { needsUpdate = true; return; } backBuffer = Gdk::Pixmap::create (wind, W, H, -1); backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); if (previewHandler) { Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); if (resPixbuf) { imgW = resPixbuf->get_width(); imgH = resPixbuf->get_height(); imgX = (W-imgW)/2; imgY = (H-imgH)/2; backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); Cairo::RefPtr cr = backBuffer->create_cairo_context(); if (previewHandler->getCropParams().enabled) drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams(), true, false); } } } void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { previewHandler = ph; if (previewHandler) previewHandler->addPreviewImageListener (this); } void PreviewWindow::on_resized (Gtk::Allocation& req) { updatePreviewImage (); queue_draw (); } bool PreviewWindow::on_expose_event (GdkEventExpose* event) { if (backBuffer) { Glib::RefPtr window = get_window(); int bufferW, bufferH; backBuffer->get_size (bufferW, bufferH); if (!mainCropWin && imageArea) { mainCropWin = imageArea->getMainCropWindow (); if (mainCropWin) mainCropWin->addCropWindowListener (this); } if ((get_width()!=bufferW && get_height()!=bufferH) || needsUpdate) { needsUpdate = false; updatePreviewImage (); } window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); if (mainCropWin && zoom > 0.0) { if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { Cairo::RefPtr cr = get_window()->create_cairo_context(); int x, y, w, h; getObservedFrameArea (x, y, w, h); double rectX = x + 0.5; double rectY = y + 0.5; double rectW = std::min(w, (int)(imgW - (x-imgX) - 1)); double rectH = std::min(h, (int)(imgH - (y-imgY) - 1)); // draw a black "shadow" line cr->set_source_rgba (0.0, 0.0, 0.0, 0.65); cr->set_line_width (1); cr->rectangle (rectX+1., rectY+1, rectW, rectH); cr->stroke (); // draw a "frame" line. Color of frame line can be set in preferences cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); cr->rectangle (rectX, rectY, rectW, rectH); cr->stroke (); } } } return true; } void PreviewWindow::previewImageChanged () { updatePreviewImage (); queue_draw (); } void PreviewWindow::setImageArea (ImageArea* ia) { imageArea = ia; mainCropWin = ia->getMainCropWindow (); if (mainCropWin) mainCropWin->addCropWindowListener (this); } void PreviewWindow::cropPositionChanged (CropWindow* w) { queue_draw (); } void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { queue_draw (); } void PreviewWindow::cropZoomChanged (CropWindow* w) { queue_draw (); } bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { if (!mainCropWin) return true; if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { int x, y, w, h; getObservedFrameArea (x, y, w, h); bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; if (isMoving) mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); else if (inside && !moreInside) cursorManager.setCursor (get_window(), CSClosedHand); else cursorManager.setCursor (get_window(), CSArrow); } return true; } bool PreviewWindow::on_button_press_event (GdkEventButton* event) { if (!mainCropWin) return true; if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { int x, y, w, h; getObservedFrameArea (x, y, w, h); bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; if (!isMoving) { isMoving = true; if (!inside || moreInside) { mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); press_x = x+w/2; press_y = y+h/2; } else { press_x = event->x; press_y = event->y; } cursorManager.setCursor (get_window(), CSClosedHand); } } return true; } bool PreviewWindow::on_button_release_event (GdkEventButton* event) { if (!mainCropWin) return true; if (isMoving) { isMoving = false; cursorManager.setCursor (get_window(), CSArrow); mainCropWin->remoteMoveReady (); } return true; }