1 /*
2  * Copyright (C) 2014-2018 Christopho, Solarus - http://www.solarus-games.org
3  *
4  * Solarus Quest Editor is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Solarus Quest Editor is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #ifndef SOLARUSEDITOR_SPRITE_VIEW_H
18 #define SOLARUSEDITOR_SPRITE_VIEW_H
19 
20 #include <QGraphicsItem>
21 #include <QGraphicsView>
22 #include <QPointer>
23 #include "sprite_model.h"
24 
25 class QAction;
26 
27 namespace SolarusEditor {
28 
29 class SpriteScene;
30 class ViewSettings;
31 
32 /**
33  * @brief Graphical view of the sprite animation image, allowing to manage
34  * directions.
35  */
36 class SpriteView : public QGraphicsView {
37   Q_OBJECT
38 
39 public:
40 
41   SpriteView(QWidget* parent = nullptr);
42 
43   SpriteScene* get_scene();
44 
45   void set_model(SpriteModel* sprite);
46   void set_view_settings(ViewSettings& view_settings);
47 
48 signals:
49 
50   void delete_selected_direction_requested();
51   void add_direction_requested(
52     const QRect& frame, int num_frames, int num_columns);
53   void change_selected_direction_position_requested(const QPoint& position);
54   void duplicate_selected_direction_requested(const QPoint& position);
55   void change_direction_num_frames_columns_requested(
56     int num_frames, int num_columns);
57 
58 public slots:
59 
60   void update_zoom();
61   void zoom_in();
62   void zoom_out();
63   void update_grid_visibility();
64 
65 private slots:
66 
67   void duplicate_selected_direction_requested();
68   void change_num_frames_columns_requested();
69   void change_num_columns_requested();
70   void change_num_frames_requested();
71 
72 protected:
73 
74   void paintEvent(QPaintEvent* event) override;
75 
76   virtual void focusOutEvent(QFocusEvent* event) override;
77   virtual void keyPressEvent(QKeyEvent* event) override;
78   virtual void mousePressEvent(QMouseEvent* event) override;
79   virtual void mouseReleaseEvent(QMouseEvent* event) override;
80   virtual void mouseMoveEvent(QMouseEvent* event) override;
81   virtual void contextMenuEvent(QContextMenuEvent* event) override;
82 
83 private:
84 
85   /**
86    * @brief Possible operation the user is doing on this view.
87    */
88   enum class State {
89     NORMAL,                       /**< Can click on directions. */
90     DRAWING_RECTANGLE,            /**< Drawing a rectangle for a new
91                                    * direction. */
92     MOVING_DIRECTION,             /**< Moving an existing direcion to another
93                                    * place in the PNG image. */
94     CHANGING_NUM_FRAMES_COLUMNS   /**< Changing the number of frames and
95                                    * columns. */
96   };
97 
98   /**
99    * @brief Mode of changing the number of frames and columns operation.
100    */
101   enum class ChangingNumFramesColumnsMode {
102     CHANGE_BOTH,          /**< Changing the number of frames and columns with
103                              * the number of frames fixed to a multiple of the
104                              * number of columns. */
105     CHANGE_NUM_FRAMES,    /**< Changing the number of frames with the number
106                              * of columns fixed. */
107     CHANGE_NUM_COLUMNS    /**< Changing the number of columns with the number
108                              * of frames fixed. */
109   };
110 
111   /**
112    * @brief Direction area item to display several frames.
113    */
114   class DirectionAreaItem : public QGraphicsItem {
115 
116   public:
117 
118     DirectionAreaItem();
119 
120     QSize get_frame_size() const;
121     int get_num_frames() const;
122     int get_num_columns() const;
123 
124     void set_frame_size(const QSize& frame_size);
125     void set_num_frames(int num_frames);
126     void set_num_columns(int num_columns);
127     void set_valid(bool valid);
128 
129     QRect get_direction_all_frames_rect() const;
130 
131     virtual QRectF boundingRect() const override;
132 
133   protected:
134 
135     void paint(
136       QPainter* painter,
137       const QStyleOptionGraphicsItem* option,
138       QWidget* widget = nullptr) override;
139 
140   private:
141 
142     void update_bounding_rect();
143 
144     QSize frame_size;     /**< The size of a frame. */
145     QRect bounding_rect;  /**< The current bounding rect. */
146     int num_frames;       /**< The number of frames. */
147     int num_columns;      /**< The number of columns. */
148     bool is_valid;        /**< Whether the area is valid. */
149 
150   };
151 
152   void show_context_menu(const QPoint& where);
153 
154   QPoint map_to_scene(const QPoint& point, bool snap_to_grid);
155 
156   void change_num_frames_columns(const ChangingNumFramesColumnsMode& mode);
157 
158   void start_state_normal();
159   void start_state_drawing_rectangle(const QPoint& initial_point);
160   void end_state_drawing_rectangle();
161   void start_state_moving_direction(const QPoint& initial_point);
162   void end_state_moving_direction();
163   void start_state_changing_num_frames_columns(
164     const ChangingNumFramesColumnsMode& mode, bool create = false);
165   void update_state_changing_num_frames_columns();
166   void end_state_changing_num_frames_columns();
167   void cancel_state_changing_num_frames_columns();
168   void compute_num_frames_columns(int& num_frames, int& num_columns);
169 
170   QPointer<SpriteModel> model;         /**< The sprite model. */
171   SpriteScene* scene;                  /**< The scene viewed. */
172   QAction* delete_direction_action;    /**< Action of deleting the selected
173                                         * direction. */
174   QAction* duplicate_direction_action; /**< Action of duplicate the selected
175                                         * direction. */
176   QAction*
177     change_num_frames_columns_action;  /**< Action of change the number of
178                                         * frames and columns of the selected
179                                         * direction. */
180   QAction* change_num_frames_action;   /**< Action of change the number of
181                                         * frames of the selected direction. */
182   QAction* change_num_columns_action;  /**< Action of change the number of
183                                         * columns of the selected direction. */
184   State state;                         /**< Current operation done by user. */
185   ChangingNumFramesColumnsMode
186       changing_mode;                   /**< Current mode for changing the number
187                                         * of frames and columns operation. */
188   bool create_multiframe_direction;    /**< Whether a new direction must be
189                                         * created in the
190                                         * CHANGING_NUM_FRAMES_COLUMNS state. */
191   QPoint dragging_start_point;         /**< In states DRAWING_RECTANGLE and
192                                         * MOVING_DIRECTION: point where the
193                                         * dragging started, in scene
194                                         * coordinates.*/
195   QPoint dragging_current_point;       /**< In states DRAWING_RECTANGLE,
196                                         * MOVING_DIRECTION and
197                                         * CHANGING_NUM_FRAMES_COLUMNS: point
198                                         * where the dragging is currently,
199                                         * in scene coordinates. */
200   DirectionAreaItem current_area_item; /**< In states DRAWING_RECTANGLE,
201                                         * MOVING_DIRECTION and
202                                         * CHANGING_NUM_FRAMES_COLUMNS:
203                                         * graphic item of the area drawing
204                                         * by the user. */
205   QPointer<ViewSettings>
206       view_settings;                   /**< How the view is displayed. */
207   double zoom;                         /**< Zoom factor currently applied. */
208 
209 };
210 
211 }
212 
213 #endif
214