1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2019 Jean-Christophe FRISCH <natureh.510@gmail.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 <https://www.gnu.org/licenses/>.
18  */
19 #pragma once
20 
21 #include "editid.h"
22 #include "cursormanager.h"
23 #include "../rtengine/coord.h"
24 
25 class Geometry;
26 class EditDataProvider;
27 
28 /** @file
29  * See editwidgets.h for documentation
30  */
31 
32 /// @brief Method for client tools needing Edit information
33 class EditSubscriber
34 {
35 
36 public:
37 
38 private:
39     EditUniqueID ID; /// this will be used in improcfun to locate the data that has to be stored in the buffer; it must be unique in RT
40     EditType editingType;
41     BufferType bufferType;
42     EditDataProvider *provider;
43 
44 protected:
45     std::vector<Geometry*> visibleGeometry;    /// displayed geometry
46     std::vector<Geometry*> mouseOverGeometry;  /// mouseOver geometry, drawn in a hidden buffer
47     enum class Action {
48         NONE,      ///
49         DRAGGING,  /// set action to this value in the buttonPressed event to start dragging and ask for drag event
50         PICKING    /// set action to this value in the buttonPressed event whenever the user is picking something through a single click. In this case, the pickX events will be called INSTEAD of buttonXReleased !
51     };
52 
53     Action action; /// object mode only, ignored in Pipette mode
54 
55 public:
56     explicit EditSubscriber (EditType editType);
57     virtual ~EditSubscriber () = default;
58 
59     void               setEditProvider(EditDataProvider *provider);
60     EditDataProvider*  getEditProvider ();
61     void               setEditID(EditUniqueID ID, BufferType buffType);
62     bool               isCurrentSubscriber() const;
63     virtual void       subscribe();
64     virtual void       unsubscribe();
65     virtual void       switchOffEditMode();           /// Occurs when the user want to stop the editing mode
66     EditUniqueID       getEditID() const;
67     EditType           getEditingType() const;
68     BufferType         getPipetteBufferType() const;
69     bool               isDragging() const;            /// Returns true if something is being dragged and drag events has to be sent (object mode only)
70     bool               isPicking() const;             /// Returns true if something is being picked
71 
72     /** @brief Get the cursor to be displayed when above handles
73     @param objectID object currently "hovered" */
74     virtual CursorShape getCursor (int objectID) const;
75 
76     /** @brief Triggered when the mouse is moving over an object
77     This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode
78     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
79     @return true if the preview has to be redrawn, false otherwise */
80     virtual bool mouseOver (int modifierKey);
81 
82     /** @brief Triggered when mouse button 1 is pressed, together with the CTRL modifier key if the subscriber is of type ET_PIPETTE
83     Once the key is pressed, RT will enter in drag1 mode on subsequent mouse movements
84     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
85     @return true if the preview has to be redrawn, false otherwise */
86     virtual bool button1Pressed (int modifierKey);
87 
88     /** @brief Triggered when mouse button 1 is released
89     @return true if the preview has to be redrawn, false otherwise */
90     virtual bool button1Released ();
91 
92     /** @brief Triggered when mouse button 2 is pressed (middle button)
93     Once the key is pressed, RT will enter in drag2 mode on subsequent mouse movements
94     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
95     @return true if the preview has to be redrawn, false otherwise */
96     virtual bool button2Pressed (int modifierKey);
97 
98     /** @brief Triggered when mouse button 2 is released (middle button)
99     @return true if the preview has to be redrawn, false otherwise */
100     virtual bool button2Released ();
101 
102     /** @brief Triggered when mouse button 3 is pressed (right button)
103     Once the key is pressed, RT will enter in drag3 mode on subsequent mouse movements
104     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
105     @return true if the preview has to be redrawn, false otherwise */
106     virtual bool button3Pressed (int modifierKey);
107 
108     /** @brief Triggered when mouse button 3 is released (right button)
109     @return true if the preview has to be redrawn, false otherwise */
110     virtual bool button3Released ();
111 
112     /** @brief Triggered when the user is moving while holding down mouse button 1
113     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
114     @return true if the preview has to be redrawn, false otherwise */
115     virtual bool drag1 (int modifierKey);
116 
117     /** @brief Triggered when the user is moving while holding down mouse button 2
118     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
119     @return true if the preview has to be redrawn, false otherwise */
120     virtual bool drag2 (int modifierKey);
121 
122     /** @brief Triggered when the user is moving while holding down mouse button 3
123     @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
124     @return true if the preview has to be redrawn, false otherwise */
125     virtual bool drag3 (int modifierKey);
126 
127     /** @brief Triggered when the user is releasing mouse button 1 while in action==ES_ACTION_PICKING mode
128     No modifier key is provided, since having a different modifier key than on button press will set picked to false.
129     @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
130                   If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
131     @return true if the preview has to be redrawn, false otherwise */
132     virtual bool pick1 (bool picked);
133 
134     /** @brief Triggered when the user is releasing mouse button 2 while in action==ES_ACTION_PICKING mode
135     @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
136                   If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
137     @return true if the preview has to be redrawn, false otherwise */
138     virtual bool pick2 (bool picked);
139 
140     /** @brief Triggered when the user is releasing mouse button 3 while in action==ES_ACTION_PICKING mode
141     @param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
142                   If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
143     @return true if the preview has to be redrawn, false otherwise */
144     virtual bool pick3 (bool picked);
145 
146     /** @brief Get the geometry to be shown to the user */
147     const std::vector<Geometry*>& getVisibleGeometry ();
148 
149     /** @brief Get the geometry to be drawn in the "mouse over" channel, hidden from the user */
150     const std::vector<Geometry*>& getMouseOverGeometry ();
151 };
152 
153 /** @brief Class to handle the furniture of data to the subscribers.
154  *
155  * It is admitted that only one Subscriber can ask data at a time. If the Subscriber is of type ET_PIPETTE, it will have to
156  * trigger the usual event so that the image will be reprocessed to compute the buffer of the current subscriber.
157  */
158 class EditDataProvider
159 {
160 
161 private:
162     EditSubscriber *currSubscriber;
163     int object;            /// ET_OBJECTS mode: Object detected under the cursor, 0 otherwise; ET_PIPETTE mode: 1 if above the image, 0 otherwise
164     float pipetteVal1;     /// Current pipette values
165     float pipetteVal2;     /// Current pipette values; if bufferType==BT_SINGLEPLANE_FLOAT, will be set to 0
166     float pipetteVal3;     /// Current pipette values; if bufferType==BT_SINGLEPLANE_FLOAT, will be set to 0
167 
168 public:
169 
170     rtengine::Coord posScreen;       /// Location of the mouse button press, in preview image space
171     rtengine::Coord posImage;        /// Location of the mouse button press, in the full image space
172     rtengine::Coord deltaScreen;     /// Delta relative to posScreen
173     rtengine::Coord deltaImage;      /// Delta relative to posImage
174     rtengine::Coord deltaPrevScreen; /// Delta relative to the previous mouse location, in preview image space
175     rtengine::Coord deltaPrevImage;  /// Delta relative to the previous mouse location, in the full image space
176 
177     EditDataProvider();
178     virtual ~EditDataProvider() = default;
179 
180     virtual void subscribe(EditSubscriber *subscriber);
181     virtual void unsubscribe();         /// Occurs when the subscriber has been switched off first
182     virtual void switchOffEditMode ();  /// Occurs when the user want to stop the editing mode
183     int getObject() const;
184     void setObject(int newObject);
185     float getPipetteVal1() const;
186     float getPipetteVal2() const;
187     float getPipetteVal3() const;
188     void setPipetteVal1(float newVal);
189     void setPipetteVal2(float newVal);
190     void setPipetteVal3(float newVal);
191     virtual CursorShape getCursor(int objectID) const;
192     int getPipetteRectSize () const;
193     EditSubscriber* getCurrSubscriber() const;
194     virtual void getImageSize (int &w, int&h) = 0;
195 };
196