1 /*
2 * This file is part of RawTherapee.
3 *
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5 *
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "imagearea.h"
20 #include <ctime>
21 #include <cmath>
22 #include "options.h"
23 #include "multilangmgr.h"
24 #include "cropwindow.h"
25 #include "../rtengine/refreshmap.h"
26 #include "options.h"
27
ImageArea(ImageAreaPanel * p)28 ImageArea::ImageArea(ImageAreaPanel* p):
29 parent(p), fullImageWidth(0), fullImageHeight(0),
30 alp_(nullptr)
31 {
32 get_style_context()->add_class("drawingarea");
33
34 infotext = "";
35 cropgl = nullptr;
36 pmlistener = nullptr;
37 pmhlistener = nullptr;
38 focusGrabber = nullptr;
39 flawnOverWindow = nullptr;
40 mainCropWindow = nullptr;
41 previewHandler = nullptr;
42 showClippedH = false;
43 showClippedS = false;
44 listener = nullptr;
45
46 zoomPanel = Gtk::manage (new ZoomPanel (this));
47 indClippedPanel = Gtk::manage (new IndicateClippedPanel (this));
48 previewModePanel = Gtk::manage (new PreviewModePanel (this));
49 previewModePanel->get_style_context()->add_class("narrowbuttonbox");
50
51 add_events(Gdk::LEAVE_NOTIFY_MASK);
52
53 signal_size_allocate().connect( sigc::mem_fun(*this, &ImageArea::on_resized) );
54
55 dirty = false;
56 ipc = nullptr;
57 iLinkedImageArea = nullptr;
58 }
59
~ImageArea()60 ImageArea::~ImageArea ()
61 {
62
63 for (auto cropWin : cropWins) {
64 delete cropWin;
65 }
66
67 cropWins.clear ();
68
69 if (mainCropWindow) {
70 delete mainCropWindow;
71 }
72 }
73
on_realize()74 void ImageArea::on_realize()
75 {
76 Gtk::DrawingArea::on_realize();
77
78 #if defined (__APPLE__)
79 // 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.
80 // This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3
81 add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
82 #else
83 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 | Gdk::SMOOTH_SCROLL_MASK);
84 #endif
85
86 Cairo::FontOptions cfo;
87 cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
88 get_pango_context ()->set_cairo_font_options (cfo);
89 }
90
on_resized(Gtk::Allocation & req)91 void ImageArea::on_resized (Gtk::Allocation& req)
92 {
93 if (ipc && get_width() > 1) { // sometimes on_resize is called in some init state, causing wrong sizes
94 if (!mainCropWindow) {
95 mainCropWindow = new CropWindow (this, false, false);
96 mainCropWindow->setDecorated (false);
97 mainCropWindow->setFitZoomEnabled (true);
98 mainCropWindow->addCropWindowListener (this);
99 mainCropWindow->setCropGUIListener (cropgl);
100 mainCropWindow->setPointerMotionListener (pmlistener);
101 mainCropWindow->setPointerMotionHListener (pmhlistener);
102 mainCropWindow->setPosition (0, 0);
103 mainCropWindow->setSize (get_width(), get_height()); // this execute the refresh itself
104 mainCropWindow->enable(); // start processing !
105 if (alp_) {
106 alp_->setAreaDrawListener(mainCropWindow);
107 }
108 } else {
109 mainCropWindow->setSize (get_width(), get_height()); // this execute the refresh itself
110 }
111
112 parent->syncBeforeAfterViews();
113 }
114 }
115
getImProcCoordinator() const116 rtengine::StagedImageProcessor* ImageArea::getImProcCoordinator() const
117 {
118 return ipc;
119 }
120
setImProcCoordinator(rtengine::StagedImageProcessor * ipc_)121 void ImageArea::setImProcCoordinator(rtengine::StagedImageProcessor* ipc_)
122 {
123 if( !ipc_ ) {
124 focusGrabber = nullptr;
125
126 for (auto cropWin : cropWins) {
127 delete cropWin;
128 }
129
130 cropWins.clear();
131
132 mainCropWindow->deleteColorPickers ();
133 mainCropWindow->setObservedCropWin (nullptr);
134 }
135
136 ipc = ipc_;
137
138 }
139
setPreviewHandler(PreviewHandler * ph)140 void ImageArea::setPreviewHandler (PreviewHandler* ph)
141 {
142
143 previewHandler = ph;
144 }
145
on_style_updated()146 void ImageArea::on_style_updated ()
147 {
148
149 // TODO: notify all crop windows that the style has been changed
150 queue_draw ();
151 }
152
setInfoText(Glib::ustring text)153 void ImageArea::setInfoText (Glib::ustring text)
154 {
155
156 infotext = text;
157
158 Glib::RefPtr<Pango::Context> context = get_pango_context () ;
159 Pango::FontDescription fontd(get_style_context()->get_font());
160
161 // update font
162 fontd.set_weight (Pango::WEIGHT_BOLD);
163 fontd.set_size (10 * Pango::SCALE);
164 context->set_font_description (fontd);
165
166 // create text layout
167 Glib::RefPtr<Pango::Layout> ilayout = create_pango_layout("");
168 ilayout->set_markup(text);
169
170 // get size of the text block
171 int iw, ih;
172 ilayout->get_pixel_size (iw, ih);
173
174 // create BackBuffer
175 iBackBuffer.setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, iw + 16, ih + 16, true);
176 iBackBuffer.setDestPosition(8, 8);
177
178 Cairo::RefPtr<Cairo::Context> cr = iBackBuffer.getContext();
179
180 // cleaning the back buffer (make it full transparent)
181 cr->set_source_rgba (0., 0., 0., 0.);
182 cr->set_operator (Cairo::OPERATOR_CLEAR);
183 cr->paint ();
184 cr->set_operator (Cairo::OPERATOR_OVER);
185
186 // paint transparent black background
187 cr->set_source_rgba (0., 0., 0., 0.5);
188 cr->paint ();
189
190 // paint text
191 cr->set_source_rgb (1.0, 1.0, 1.0);
192 cr->move_to (8, 8);
193 ilayout->add_to_cairo_context (cr);
194 cr->fill ();
195
196 }
197
infoEnabled(bool e)198 void ImageArea::infoEnabled (bool e)
199 {
200
201 if (options.showInfo != e) {
202 options.showInfo = e;
203 queue_draw ();
204 }
205 }
206
getCropWindow(int x,int y)207 CropWindow* ImageArea::getCropWindow (int x, int y)
208 {
209
210 CropWindow* cw = mainCropWindow;
211
212 for (auto cropWin : cropWins) {
213 if (cropWin->isInside (x, y)) {
214 return cropWin;
215 }
216 }
217
218 return cw;
219 }
220
redraw()221 void ImageArea::redraw ()
222 {
223 // dirty prevents multiple updates queued up
224 if (!dirty) {
225 dirty = true;
226 queue_draw ();
227 }
228 }
229
switchPickerVisibility(bool isVisible)230 void ImageArea::switchPickerVisibility (bool isVisible)
231 {
232 redraw();
233 }
234
on_draw(const::Cairo::RefPtr<Cairo::Context> & cr)235 bool ImageArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
236 {
237 dirty = false;
238
239 /* HOMBRE: How do we replace that??
240
241 if (event->count) {
242 return true;
243 }
244
245 */
246
247 if (mainCropWindow) {
248 mainCropWindow->expose (cr);
249 }
250
251 for (std::list<CropWindow*>::reverse_iterator i = cropWins.rbegin(); i != cropWins.rend(); ++i) {
252 (*i)->expose (cr);
253 }
254
255 if (options.showInfo && infotext != "") {
256 iBackBuffer.copySurface(cr);
257 }
258
259
260 return true;
261 }
262
263
on_motion_notify_event(GdkEventMotion * event)264 bool ImageArea::on_motion_notify_event (GdkEventMotion* event)
265 {
266 auto device = gdk_event_get_source_device(reinterpret_cast<GdkEvent *>(event));
267 double pressure = rtengine::RT_NAN;
268 if (device && event->axes) {
269 if (!gdk_device_get_axis(device, event->axes, GDK_AXIS_PRESSURE, &pressure)) {
270 pressure = rtengine::RT_NAN;
271 }
272 }
273
274 if (focusGrabber) {
275 focusGrabber->pointerMoved (event->state, event->x, event->y, pressure);
276 } else {
277 CropWindow* cw = getCropWindow (event->x, event->y);
278
279 if (cw) {
280 if (cw != flawnOverWindow) {
281 if (flawnOverWindow) {
282 flawnOverWindow->flawnOver(false);
283 }
284
285 cw->flawnOver(true);
286 flawnOverWindow = cw;
287 }
288
289 cw->pointerMoved (event->state, event->x, event->y, pressure);
290 } else if (flawnOverWindow) {
291 flawnOverWindow->flawnOver(false);
292 flawnOverWindow = nullptr;
293 }
294 }
295
296 return true;
297 }
298
on_button_press_event(GdkEventButton * event)299 bool ImageArea::on_button_press_event (GdkEventButton* event)
300 {
301 auto device = gdk_event_get_source_device(reinterpret_cast<GdkEvent *>(event));
302 double pressure = rtengine::RT_NAN;
303 if (device && event->axes) {
304 if (!gdk_device_get_axis(device, event->axes, GDK_AXIS_PRESSURE, &pressure)) {
305 pressure = rtengine::RT_NAN;
306 }
307 }
308
309 if (focusGrabber) {
310 focusGrabber->buttonPress(event->button, event->type, event->state, event->x, event->y, pressure);
311 } else {
312 CropWindow* cw = getCropWindow(event->x, event->y);
313
314 if (cw) {
315 cw->buttonPress(event->button, event->type, event->state, event->x, event->y, pressure);
316 }
317 }
318
319 return true;
320 }
321
on_scroll_event(GdkEventScroll * event)322 bool ImageArea::on_scroll_event (GdkEventScroll* event)
323 {
324
325 // printf("ImageArea::on_scroll_event / delta_x=%.5f, delta_y=%.5f, direction=%d, type=%d, send_event=%d\n",
326 // event->delta_x, event->delta_y, (int)event->direction, (int)event->type, event->send_event);
327
328 CropWindow* cw = getCropWindow (event->x, event->y);
329 if (cw) {
330 cw->scroll (event->state, event->direction, event->x, event->y, event->delta_x, event->delta_y);
331 }
332
333 return true;
334 }
335
on_button_release_event(GdkEventButton * event)336 bool ImageArea::on_button_release_event (GdkEventButton* event)
337 {
338
339 if (focusGrabber) {
340 focusGrabber->buttonRelease (event->button, event->type, event->state, event->x, event->y);
341 } else {
342 CropWindow* cw = getCropWindow (event->x, event->y);
343
344 if (cw) {
345 cw->buttonRelease (event->button, event->type, event->state, event->x, event->y);
346 }
347 }
348
349 return true;
350 }
351
on_leave_notify_event(GdkEventCrossing * event)352 bool ImageArea::on_leave_notify_event (GdkEventCrossing* event)
353 {
354 if (flawnOverWindow) {
355 flawnOverWindow->flawnOver(false);
356 flawnOverWindow = nullptr;
357 }
358
359 if (focusGrabber) {
360 focusGrabber->flawnOver(false);
361 focusGrabber->leaveNotify (event);
362 } else {
363 CropWindow* cw = getCropWindow (event->x, event->y);
364
365 if (cw) {
366 cw->flawnOver(false);
367 cw->leaveNotify (event);
368 }
369 }
370
371 return true;
372 }
373
subscribe(EditSubscriber * subscriber)374 void ImageArea::subscribe(EditSubscriber *subscriber)
375 {
376 EditDataProvider::subscribe(subscriber);
377
378 mainCropWindow->setEditSubscriber(subscriber);
379 for (auto cropWin : cropWins) {
380 cropWin->setEditSubscriber(subscriber);
381 }
382
383 if (listener && listener->getToolBar()) {
384 listener->getToolBar()->startEditMode ();
385 }
386
387 if (subscriber && subscriber->getEditingType() == ET_OBJECTS) {
388 // In this case, no need to reprocess the image, so we redraw the image to display the geometry
389 queue_draw();
390 }
391 }
392
unsubscribe()393 void ImageArea::unsubscribe()
394 {
395 bool wasObjectType = false;
396 EditSubscriber* oldSubscriber = EditDataProvider::getCurrSubscriber();
397
398 if (oldSubscriber && oldSubscriber->getEditingType() == ET_OBJECTS) {
399 wasObjectType = true;
400 }
401
402 EditDataProvider::unsubscribe();
403
404 // Ask the Crops to free-up edit mode buffers
405 mainCropWindow->setEditSubscriber(nullptr);
406 for (auto cropWin : cropWins) {
407 cropWin->setEditSubscriber(nullptr);
408 }
409
410 setToolHand();
411
412 if (listener && listener->getToolBar()) {
413 listener->getToolBar()->stopEditMode ();
414 }
415
416 if (wasObjectType) {
417 queue_draw();
418 }
419 }
420
getImageSize(int & w,int & h)421 void ImageArea::getImageSize (int &w, int&h)
422 {
423 if (ipc) {
424 w = ipc->getFullWidth();
425 h = ipc->getFullHeight();
426 } else {
427 w = h = 0;
428 }
429 }
430
grabFocus(CropWindow * cw)431 void ImageArea::grabFocus (CropWindow* cw)
432 {
433
434 focusGrabber = cw;
435
436 if (cw && cw != mainCropWindow) {
437 cropWindowSelected (cw);
438 }
439 }
440
unGrabFocus()441 void ImageArea::unGrabFocus ()
442 {
443
444 focusGrabber = nullptr;
445 }
446
addCropWindow()447 void ImageArea::addCropWindow ()
448 {
449 if (!mainCropWindow) {
450 return; // if called but no image is loaded, it would crash
451 }
452
453 CropWindow* cw = new CropWindow (this, true, true);
454 cw->zoom11(false);
455 cw->setCropGUIListener (cropgl);
456 cw->setPointerMotionListener (pmlistener);
457 cw->setPointerMotionHListener (pmhlistener);
458 int lastWidth = options.detailWindowWidth;
459 int lastHeight = options.detailWindowHeight;
460
461 if (lastWidth < lastHeight) {
462 lastHeight = lastWidth;
463 }
464
465 if (lastHeight < lastWidth) {
466 lastWidth = lastHeight;
467 }
468
469 if(!cropWins.empty()) {
470 CropWindow *lastCrop;
471 lastCrop = cropWins.front();
472
473 if(lastCrop) {
474 lastCrop->getSize(lastWidth, lastHeight);
475 }
476 }
477
478 cropWins.push_front (cw);
479
480 // Position the new crop window this way: start from top right going down to bottom. When bottom is reached, continue top left going down......
481 int N = cropWins.size() - 1;
482 int cropwidth, cropheight;
483
484 if(lastWidth <= 0) { // this is only the case for very first start of RT 4.1 or when options file is deleted
485 cropwidth = 200;
486 cropheight = 200;
487 } else {
488 cropwidth = lastWidth;
489 cropheight = lastHeight;
490 }
491
492 cw->setSize (cropwidth, cropheight);
493 int x, y;
494 int maxRows = get_height() / cropheight;
495
496 if(maxRows == 0) {
497 maxRows = 1;
498 }
499
500 int col = N / maxRows;
501
502 if(col % 2) { // from left side
503 col = col / 2;
504 x = col * cropwidth;
505
506 if(x >= get_width() - 50) {
507 x = get_width() - 50;
508 }
509 } else { // from right side
510 col /= 2;
511 col++;
512 x = get_width() - col * cropwidth;
513
514 if(x <= 0) {
515 x = 0;
516 }
517 }
518
519 y = cropheight * (N % maxRows);
520 cw->setPosition (x, y);
521 cw->setEditSubscriber (getCurrSubscriber());
522 cw->enable(); // start processing!
523
524 {
525 int anchorX = 0;
526 int anchorY = 0;
527 mainCropWindow->getCropAnchorPosition(anchorX, anchorY);
528 cw->setCropAnchorPosition(anchorX, anchorY);
529 }
530
531 mainCropWindow->setObservedCropWin (cropWins.front());
532
533 if(!ipc->getHighQualComputed()) {
534 ipc->startProcessing(M_HIGHQUAL);
535 ipc->setHighQualComputed();
536 }
537 }
538
539
cropWindowSelected(CropWindow * cw)540 void ImageArea::cropWindowSelected (CropWindow* cw)
541 {
542
543 std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
544
545 if (i != cropWins.end()) {
546 cropWins.erase (i);
547 }
548
549 cropWins.push_front (cw);
550 mainCropWindow->setObservedCropWin (cropWins.front());
551 }
552
cropWindowClosed(CropWindow * cw)553 void ImageArea::cropWindowClosed (CropWindow* cw)
554 {
555
556 focusGrabber = nullptr;
557 std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
558
559 if (i != cropWins.end()) {
560 cropWins.erase (i);
561 }
562
563 if (!cropWins.empty()) {
564 mainCropWindow->setObservedCropWin (cropWins.front());
565 } else {
566 mainCropWindow->setObservedCropWin (nullptr);
567 }
568
569 queue_draw ();
570 }
571
straightenReady(double rotDeg)572 void ImageArea::straightenReady (double rotDeg)
573 {
574
575 if (listener) {
576 listener->rotateSelectionReady (rotDeg);
577 }
578 }
579
spotWBSelected(int x,int y)580 void ImageArea::spotWBSelected (int x, int y)
581 {
582
583 if (listener) {
584 listener->spotWBselected (x, y);
585 }
586 }
587
sharpMaskSelected(bool sharpMask)588 void ImageArea::sharpMaskSelected (bool sharpMask)
589 {
590
591 if (listener) {
592 listener->sharpMaskSelected (sharpMask);
593 }
594 }
595
getScrollImageSize(int & w,int & h)596 void ImageArea::getScrollImageSize (int& w, int& h)
597 {
598
599 if (mainCropWindow && ipc) {
600 w = ipc->getFullWidth();
601 h = ipc->getFullHeight();
602 } else {
603 w = h = 0;
604 }
605 }
606
getScrollPosition(int & x,int & y)607 void ImageArea::getScrollPosition (int& x, int& y)
608 {
609
610 if (mainCropWindow) {
611 mainCropWindow->getCropAnchorPosition (x, y);
612 } else {
613 x = y = 0;
614 }
615 }
616
setScrollPosition(int x,int y)617 void ImageArea::setScrollPosition (int x, int y)
618 {
619
620 if (mainCropWindow) {
621 mainCropWindow->delCropWindowListener (this);
622 mainCropWindow->setCropAnchorPosition (x, y);
623 mainCropWindow->addCropWindowListener (this);
624 }
625 }
626
cropPositionChanged(CropWindow * cw)627 void ImageArea::cropPositionChanged (CropWindow* cw)
628 {
629
630 syncBeforeAfterViews ();
631 }
632
cropWindowSizeChanged(CropWindow * cw)633 void ImageArea::cropWindowSizeChanged (CropWindow* cw)
634 {
635
636 syncBeforeAfterViews ();
637 }
638
cropZoomChanged(CropWindow * cw)639 void ImageArea::cropZoomChanged (CropWindow* cw)
640 {
641
642 if (cw == mainCropWindow) {
643 parent->zoomChanged ();
644 syncBeforeAfterViews ();
645 zoomPanel->refreshZoomLabel ();
646 }
647 }
648
getZoom()649 double ImageArea::getZoom ()
650 {
651
652 if (mainCropWindow) {
653 return mainCropWindow->getZoom ();
654 } else {
655 return 1.0;
656 }
657 }
658
659 // Called by imageAreaPanel before/after views
setZoom(double zoom)660 void ImageArea::setZoom (double zoom)
661 {
662
663 if (mainCropWindow) {
664 mainCropWindow->setZoom (zoom);
665 }
666
667 zoomPanel->refreshZoomLabel ();
668 }
669
initialImageArrived()670 void ImageArea::initialImageArrived ()
671 {
672
673 if (mainCropWindow) {
674 int w, h;
675 mainCropWindow->cropHandler.getFullImageSize(w, h);
676 if (options.prevdemo != PD_Sidecar || !options.rememberZoomAndPan || w != fullImageWidth || h != fullImageHeight) {
677 mainCropWindow->zoomFit();
678 } else if (mainCropWindow->cropHandler.cropParams.enabled) {
679 mainCropWindow->zoomFit();
680 }
681 fullImageWidth = w;
682 fullImageHeight = h;
683 }
684 }
685
syncBeforeAfterViews()686 void ImageArea::syncBeforeAfterViews ()
687 {
688 parent->syncBeforeAfterViews ();
689 }
690
setCropGUIListener(CropGUIListener * l)691 void ImageArea::setCropGUIListener (CropGUIListener* l)
692 {
693
694 cropgl = l;
695
696 for (auto cropWin : cropWins) {
697 cropWin->setCropGUIListener (cropgl);
698 }
699
700 if (mainCropWindow) {
701 mainCropWindow->setCropGUIListener (cropgl);
702 }
703 }
704
setPointerMotionListener(PointerMotionListener * pml)705 void ImageArea::setPointerMotionListener (PointerMotionListener* pml)
706 {
707
708 pmlistener = pml;
709
710 for (auto cropWin : cropWins) {
711 cropWin->setPointerMotionListener (pml);
712 }
713
714 if (mainCropWindow) {
715 mainCropWindow->setPointerMotionListener (pml);
716 }
717 }
718
setPointerMotionHListener(PointerMotionListener * pml)719 void ImageArea::setPointerMotionHListener (PointerMotionListener* pml)
720 {
721
722 pmhlistener = pml;
723
724 for (auto cropWin : cropWins) {
725 cropWin->setPointerMotionHListener (pml);
726 }
727
728 if (mainCropWindow) {
729 mainCropWindow->setPointerMotionHListener (pml);
730 }
731 }
732
getToolMode()733 ToolMode ImageArea::getToolMode ()
734 {
735
736 if (listener && listener->getToolBar()) {
737 return listener->getToolBar()->getTool ();
738 } else {
739 return TMHand;
740 }
741 }
742
showColorPickers()743 bool ImageArea::showColorPickers ()
744 {
745
746 if (listener && listener->getToolBar()) {
747 return listener->getToolBar()->showColorPickers ();
748 } else {
749 return false;
750 }
751 }
752
setToolHand()753 void ImageArea::setToolHand ()
754 {
755
756 if (listener && listener->getToolBar()) {
757 listener->getToolBar()->setTool (TMHand);
758 }
759 }
760
getSpotWBRectSize()761 int ImageArea::getSpotWBRectSize ()
762 {
763
764 if (listener) {
765 return listener->getSpotWBRectSize ();
766 } else {
767 return 1;
768 }
769 }
770
get_request_mode_vfunc() const771 Gtk::SizeRequestMode ImageArea::get_request_mode_vfunc () const
772 {
773 return Gtk::SIZE_REQUEST_CONSTANT_SIZE;
774 }
775
get_preferred_height_vfunc(int & minimum_height,int & natural_height) const776 void ImageArea::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const
777 {
778 minimum_height= 50 * RTScalable::getScale();
779 natural_height = 300 * RTScalable::getScale();
780 }
781
get_preferred_width_vfunc(int & minimum_width,int & natural_width) const782 void ImageArea::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const
783 {
784 minimum_width = 100 * RTScalable::getScale();
785 natural_width = 400 * RTScalable::getScale();
786 }
787
get_preferred_height_for_width_vfunc(int width,int & minimum_height,int & natural_height) const788 void ImageArea::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const
789 {
790 get_preferred_height_vfunc(minimum_height, natural_height);
791 }
792
get_preferred_width_for_height_vfunc(int height,int & minimum_width,int & natural_width) const793 void ImageArea::get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const
794 {
795 get_preferred_width_vfunc (minimum_width, natural_width);
796 }
797
798
setAreaDrawListenerProvider(AreaDrawListenerProvider * alp)799 void ImageArea::setAreaDrawListenerProvider(AreaDrawListenerProvider *alp)
800 {
801 alp_ = alp;
802
803 if (mainCropWindow && alp_) {
804 alp_->setAreaDrawListener(mainCropWindow);
805 }
806 }
807