1 /* 2 */ 3 4 /* 5 6 Copyright (C) 2014 Ferrero Andrea 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 22 */ 23 24 /* 25 26 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/ 27 28 */ 29 30 #ifndef IMAGE_EDITOR_H 31 #define IMAGE_EDITOR_H 32 33 #include <string> 34 35 #include <gtkmm.h> 36 37 #include "../base/photoflow.hh" 38 39 #include "imagearea.hh" 40 #include "histogram.hh" 41 #include "sampler.hh" 42 #include "image_info.hh" 43 #include "snapshotswidget.hh" 44 #include "layerwidget.hh" 45 #include "tablabelwidget.hh" 46 #include "softproofdialog.hh" 47 #include "widgets/statusindicator.hh" 48 49 50 namespace PF { 51 52 53 class PreviewScrolledWindow: public Gtk::ScrolledWindow 54 { 55 public: 56 void on_map(); 57 bool on_configure_event(GdkEventConfigure*event); 58 }; 59 60 61 62 // The image_size_updater is a special pipeline sink that stores 63 // the dimensions of the full-res image which corresponds to 64 // the output being displayed in the preview area. 65 // It is used to compute the correct scaling factor when 66 // the preview image is shown in zoom-to-fit mode. 67 class ImageSizeUpdater: public PipelineSink 68 { 69 int sticky_layer_id; 70 71 VipsImage* image; 72 int image_width, image_height; 73 public: 74 ImageSizeUpdater( Pipeline* p ); 75 get_sticky_layer()76 int get_sticky_layer() { return sticky_layer_id; } set_sticky_layer(int id)77 void set_sticky_layer( int id ) { sticky_layer_id = id; } 78 get_image()79 VipsImage* get_image() { return image; } get_image_width()80 int get_image_width() { return image_width; } get_image_height()81 int get_image_height() { return image_height; } 82 83 void update( VipsRect* area ); 84 }; 85 86 87 class MainWindow; 88 89 90 class ImageEditor: public Gtk::HBox 91 { 92 std::string filename; 93 Image* image; 94 bool image_opened; 95 96 Layer* sticky_layer; 97 Layer* edited_layer; 98 int selected_layer_id; 99 std::list<PF::Layer*> edited_layer_children; 100 101 ImageSizeUpdater* image_size_updater; 102 103 Gtk::VBox imageBox; 104 ImageArea* imageArea; 105 Gtk::EventBox imageArea_eventBox; 106 107 108 Histogram* histogram; 109 SamplerGroup* samplers; 110 ImageInfo* image_info; 111 SnapshotsWidget* snapshots; 112 113 114 // Boxes for aligning the image area inside the scrolled window. 115 // The image area gets inserted into an HBox which in turn 116 // is inserted into a VBox, in both cases with PACK_EXPAND_PADDING. 117 // The VBox is the inserted into an EventBox which provides 118 // the black background. 119 Gtk::VBox imageArea_vbox; 120 Gtk::HBox imageArea_hbox; 121 Gtk::EventBox imageArea_eventBox2; 122 PreviewScrolledWindow imageArea_scrolledWindow; 123 124 Gtk::VBox imageArea_scrolledWindow_box; 125 //Gtk::HPaned main_panel; 126 Gtk::HBox* main_panel; 127 LayerWidget layersWidget; 128 Gtk::VBox layersWidget_box; 129 Gtk::Widget* aux_controls; 130 Gtk::VBox aux_controlsBox; 131 Gtk::HBox controlsBox; 132 Gtk::VBox controlsBox2; 133 134 Gtk::Frame soft_proof_frame; 135 Gtk::VBox soft_proof_box; 136 Gtk::CheckButton soft_proof_enable_button; 137 SoftProofDialog* softproof_dialog; 138 139 StatusIndicatorWidget status_indicator; 140 Gtk::Image img_zoom_in, img_zoom_out, img_zoom_fit; 141 Gtk::Button buttonZoomIn, buttonZoomOut, buttonZoom100, buttonZoomFit; 142 Gtk::Image img_shadows_warning, img_highlights_warning; 143 Gtk::ToggleButton button_shadows_warning, button_highlights_warning; 144 Gtk::VBox radioBox; 145 Gtk::RadioButton buttonShowMerged, buttonShowActive; 146 Gtk::VBox controls_group_vbox; 147 Gtk::ScrolledWindow controls_group_scrolled_window; 148 Gtk::HBox image_controls_box, image_controls_box2; 149 150 HTabLabelWidget* tab_label_widget; 151 152 Gtk::HBox file_buttons_box; 153 154 Glib::ustring last_exported_file; 155 156 157 bool fit_image; 158 bool fit_image_needed; 159 160 bool hide_background_layer; 161 162 int preview_drag_start_x, preview_drag_start_y, adjustment_drag_start_x, adjustment_drag_start_y; 163 164 Glib::Dispatcher signal_image_modified, signal_image_updated; 165 166 void expand_layer( PF::Layer* layer, std::list<PF::Layer*>& list ); 167 void get_child_layers( Layer* layer, std::list<PF::Layer*>& container, 168 std::list<Layer*>& children ); 169 void get_child_layers(); 170 171 public: 172 ImageEditor( std::string filename ); 173 ~ImageEditor(); 174 175 void dispose(); 176 get_image()177 Image* get_image() { return image; } get_image_area()178 ImageArea* get_image_area() { return imageArea; } 179 get_layer_widget()180 LayerWidget& get_layer_widget() { return layersWidget; } 181 set_tab_label_widget(HTabLabelWidget * l)182 void set_tab_label_widget( HTabLabelWidget* l ) { tab_label_widget = l; } 183 184 void update_controls(); 185 void set_aux_controls( Gtk::Widget* aux ); get_aux_controls()186 Gtk::Widget* get_aux_controls() { return aux_controls; } 187 get_file_buttons_box()188 Gtk::HBox& get_file_buttons_box() { return file_buttons_box; } 189 get_edited_layer()190 int get_edited_layer() { 191 //std::cout<<"ImageEditor::get_edited_layer(): edited_layer="<<edited_layer; 192 //if(edited_layer) std::cout<<"(\""<<edited_layer->get_name()<<"\", "<<edited_layer->get_id()<<")"<<std::endl; 193 return( (edited_layer) ? edited_layer->get_id() : -1 ); 194 } 195 void set_edited_layer( int id ); get_sticky_layer()196 int get_sticky_layer() { return (sticky_layer) ? sticky_layer->get_id() : -1; } 197 void set_sticky_layer( int id ); 198 void set_selected_layer( int id ); get_selected_layer()199 int get_selected_layer() { return selected_layer_id; } 200 201 void set_display_mask( bool val ); 202 203 set_hide_background_layer(bool flag)204 void set_hide_background_layer( bool flag ) { hide_background_layer = flag; } get_hide_background_layer()205 bool get_hide_background_layer() { return hide_background_layer; } 206 207 void open_image(); 208 void build_image(); 209 210 void on_image_modified(); 211 void on_image_modified_async(); 212 213 void on_image_updated(); 214 void on_image_updated_async(); 215 216 void on_map(); 217 void on_realize(); 218 set_status(std::string label,int status)219 void set_status( std::string label, int status ) 220 { 221 //std::cout<<"ImageEditor::set_status("<<label<<", "<<status<<") called"<<std::endl; 222 status_indicator.set_status( label, status ); 223 } set_status_ready()224 void set_status_ready() { set_status(_("ready"), 0); } set_status_caching()225 void set_status_caching() { set_status(_("caching"), 1); } set_status_processing()226 void set_status_processing() { set_status(_("processing"), 2); } set_status_updating()227 void set_status_updating() { set_status(_("updating"), 3); } set_status_exporting()228 void set_status_exporting() { set_status(_("exporting"), 2); } 229 230 // Handlers for the mouse events inside the image area 231 bool my_button_press_event( GdkEventButton* button ); 232 bool my_button_release_event( GdkEventButton* button ); 233 bool my_motion_notify_event( GdkEventMotion* button ); 234 bool on_key_press_event(GdkEventKey* event); 235 236 // Handler for the widget size change 237 //bool on_preview_configure_event( GdkEventConfigure* event ); 238 void on_my_size_allocate(Gtk::Allocation& allocation); 239 get_zoom_factor()240 float get_zoom_factor() 241 { 242 PF::Pipeline* pipeline = image->get_pipeline(1); 243 if( !pipeline ) return 1.0f; 244 unsigned int level = pipeline->get_level(); 245 float fact = 1.0f; 246 for( unsigned int i = 0; i < level; i++ ) 247 fact /= 2.0f; 248 #ifndef NDEBUG 249 std::cout<<"get_zoom_factor(): level="<<level<<" fact="<<fact<<std::endl; 250 #endif 251 return fact; 252 } 253 254 void screen2image( gdouble& x, gdouble& y, gdouble& w, gdouble& h ); 255 void image2layer( gdouble& x, gdouble& y, gdouble& w, gdouble& h ); screen2layer(gdouble & x,gdouble & y,gdouble & w,gdouble & h)256 void screen2layer( gdouble& x, gdouble& y, gdouble& w, gdouble& h ) 257 { 258 screen2image( x, y, w, h ); 259 image2layer( x, y, w, h ); 260 } 261 262 void image2screen( gdouble& x, gdouble& y, gdouble& w, gdouble& h ); 263 void layer2image( gdouble& x, gdouble& y, gdouble& w, gdouble& h ); layer2screen(gdouble & x,gdouble & y,gdouble & w,gdouble & h)264 void layer2screen( gdouble& x, gdouble& y, gdouble& w, gdouble& h ) 265 { 266 layer2image( x, y, w, h ); 267 image2screen( x, y, w, h ); 268 } 269 270 void toggle_highlights_warning(); 271 void toggle_shadows_warning(); 272 273 void on_soft_proof_toggled(); soft_proof_disable()274 void soft_proof_disable() 275 { 276 soft_proof_enable_button.set_active(false); 277 } 278 279 void zoom_in(); 280 void zoom_out(); 281 bool zoom_fit(); 282 void zoom_actual_size(); 283 284 // Functions called when switching in and out of the current editor in the 285 // main window's notebook 286 void enter(); 287 void exit(); 288 get_last_exported_file()289 Glib::ustring get_last_exported_file() { return last_exported_file; } set_last_exported_file(Glib::ustring name)290 void set_last_exported_file( Glib::ustring name ) { last_exported_file = name; } 291 }; 292 293 } 294 295 #endif 296