File indexing completed on 2024-04-21 04:34:00

0001 /********************************************************************************
0002  * Copyright (C) 2011-2015 by Stephen Allewell                                  *
0003  * steve.allewell@gmail.com                                                     *
0004  *                                                                              *
0005  * This program is free software; you can redistribute it and/or modify         *
0006  * it under the terms of the GNU General Public License as published by         *
0007  * the Free Software Foundation; either version 2 of the License, or            *
0008  * (at your option) any later version.                                          *
0009  ********************************************************************************/
0010 
0011 
0012 /**
0013  * @file
0014  * Header file for the Editor class.
0015  */
0016 
0017 
0018 #ifndef Editor_H
0019 #define Editor_H
0020 
0021 
0022 #include <QMap>
0023 #include <QPainterPath>
0024 #include <QPair>
0025 #include <QPointF>
0026 #include <QUndoStack>
0027 #include <QWidget>
0028 
0029 #include "Commands.h"
0030 
0031 
0032 class QPaintEvent;
0033 
0034 class KCharSelect;
0035 
0036 
0037 /**
0038  * @brief Manages the editor window allowing user interaction with the various tools.
0039  *
0040  * The Editor class is used to edit the new symbols or the symbols from the loaded library.
0041  * It shows a grid of @ref gridElements of @ref elementSize grouped into @ref elementGroup
0042  * number of elements.
0043  *
0044  * The path is a QPainterPath element and is constructed from the various elements created
0045  * by the tools. The constructed QPainterPath is used to draw the path in the editor so it
0046  * is an accurate representation of the final path. The QPainterPath is deconstructed into
0047  * its individual elements and points for editing.
0048  *
0049  * There are additional attributes used to draw the path, filled or unfilled, the fill rule,
0050  * line width, end cap and join styles can be changed to alter the appearance of the path.
0051  *
0052  * The user interacts with the editor using the various tools. For each tool a number of
0053  * points need to be defined, simple tools like move to and line to only require one point
0054  * whereas cubic to requires three to define the two control points and the end point.
0055  *
0056  * Convenience tools are available for rectangles and ellipses but these are broken down
0057  * into lines and curves in the constructed path.
0058  *
0059  * Points that have been added can be moved to adjust the shape by dragging them around.
0060  * The points will snap to the grid intersections if the snap option is enabled. Otherwise
0061  * they can be positioned anywhere.
0062  *
0063  * Tools are available to rotate or flip the symbol which adjusts the points positions and
0064  * reconstructs the QPainterPath.
0065  *
0066  * Guide lines and circles can be displayed if the current position of the mouse on the
0067  * editor aligns with an existing point either horizontally, vertically or at a pre-defined
0068  * angle, or if the point lies on the same circle as the original where its origin is at
0069  * the center of the grid.
0070  */
0071 class Editor : public QWidget
0072 {
0073     Q_OBJECT
0074 
0075 public:
0076     enum ToolMode {MoveTo, LineTo, CubicTo, Rectangle, Ellipse, Character};
0077 
0078     explicit Editor(QWidget *parent = nullptr);
0079     virtual ~Editor();
0080 
0081     QPair<qint16, Symbol> symbol();
0082     void setSymbol(const QPair<qint16, Symbol> &pair);
0083 
0084     QPainterPath moveTo(const QPointF &to);
0085     QPainterPath lineTo(const QPointF &to);
0086     QPainterPath cubicTo(const QPointF &control1, const QPointF &control2, const QPointF &to);
0087     QPainterPath addRectangle(const QPointF &from, const QPointF &to);
0088     QPainterPath addEllipse(const QPointF &from, const QPointF &to);
0089     void removeLast(const QPainterPath &path);
0090     void movePoint(int index, const QPointF &to);
0091     void rotatePointsLeft();
0092     void rotatePointsRight();
0093     void flipPointsHorizontal();
0094     void flipPointsVertical();
0095     void setFilled(bool filled);
0096     void setFillRule(Qt::FillRule rule);
0097     void setCapStyle(Qt::PenCapStyle capStyle);
0098     void setJoinStyle(Qt::PenJoinStyle joinStyle);
0099     void setLineWidth(double width);
0100     QPainterPath setPath(const QPainterPath &path);
0101 
0102     void clear();
0103 
0104     QUndoStack *undoStack();
0105 
0106     void updateStatusMessage();
0107 
0108 public slots:
0109     void selectTool(QAction *action);
0110     void charSelected(const QChar &character);
0111     void enableSnap(bool enabled);
0112     void enableGuides(bool enabled);
0113     void selectFilled(bool enabled);
0114     void selectFillRule(QAction *action);
0115     void selectCapStyle(QAction *action);
0116     void selectJoinStyle(QAction *action);
0117     void increaseLineWidth();
0118     void decreaseLineWidth();
0119 
0120     void rotateLeft();
0121     void rotateRight();
0122     void flipHorizontal();
0123     void flipVertical();
0124     void scalePreferred();
0125 
0126     void readSettings();
0127 
0128 signals:
0129     void message(const QString &text);
0130     void minLineWidth(bool reached);
0131     void maxLineWidth(bool reached);
0132 
0133 protected:
0134     virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
0135     virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
0136     virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
0137 
0138     virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
0139     virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
0140 
0141     virtual void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
0142 
0143 private:
0144     void addPoint(const QPointF &point);
0145     QPointF snapPoint(const QPoint &point) const;
0146     QPair<bool, QPointF> snapToGrid(const QPoint &point) const;
0147     QPair<bool, QPointF> snapToGuide(const QPointF &point) const;
0148     QPointF toSymbol(const QPoint &point) const;
0149     bool node(const QPointF &point) const;
0150     QPair<bool, int> nodeUnderCursor(const QPointF &point) const;
0151     void deconstructPainterPath();
0152     void constructPainterPath();
0153     void constructGuides(const QPointF &to);
0154     void addGuideLine(const QLineF &line);
0155     void addGuideCircle(double radius);
0156     void addSnapPoint(const QPointF &point);
0157     QLineF projected(const QLineF &line) const;
0158 
0159     int     m_size;                                 /**< the overall size of the editor */
0160 
0161     bool    m_snap;                                 /**< true if snap mode is enabled */
0162     bool    m_fill;                                 /**< true if fill mode is enabled */
0163     bool    m_guides;                               /**< true if generating guides is enabled */
0164 
0165     QUndoStack  m_undoStack;                        /**< holds the commands that modify the editor contents allowing for undo */
0166 
0167     ToolMode    m_toolMode;                         /**< the current tool selected */
0168 
0169     QList<QPointF>                      m_points;   /**< the points that have been committed relating to the elements in m_elements */
0170     QList<QPainterPath::ElementType>    m_elements; /**< the basic elements making up the path, move, line and curve */
0171 
0172     QList<QPointF>      m_activePoints;             /**< the points that are being entered for the current command */
0173 
0174     qint16              m_index;                    /**< the index of the symbol as stored in the library, this is 0 for new symbols */
0175     QPainterPath        m_painterPath;              /**< the path from m_symbol currently being edited */
0176     Symbol              m_symbol;                   /**< the symbol containing the QPainterPath and rendering attributes */
0177 
0178     bool                m_dragging;                 /**< true if currently dragging a point around */
0179     QPointF             m_start;                    /**< the start position of a drag operation or the start of a rubber band selection */
0180     QPointF             m_tracking;                 /**< the current position of a drag operation or the position of a rubber band selection */
0181     QRectF              m_rubberBand;               /**< a rubber band rectangle in symbol coordinates, is null when not required */
0182     QPair<bool, int>    m_dragPointIndex;           /**< represents the list and index of the point being moved, true for m_points, false for m_activePoints */
0183 
0184     QVector<qreal>      m_angles;                   /**< the angles allowed for constructing guide lines */
0185     QList<QLineF>       m_guideLines;               /**< the guide lines that have been constructed for a given point */
0186     QList<qreal>        m_guideCircles;             /**< the guide circles that have been constructed for a given point */
0187     QList<QPointF>      m_snapPoints;               /**< points that intersect with guide lines */
0188     QLineF              m_topEdge;                  /**< represents the top edge of the editor from 0,0 to 1,0 */
0189     QLineF              m_bottomEdge;               /**< represents the bottom edge of the editor from 0,1 to 1,1 */
0190     QLineF              m_leftEdge;                 /**< represents the left edge of the editor from 0,1 to 0,1 */
0191     QLineF              m_rightEdge;                /**< represents the right edge of the editor from 1,0 to 1,1 */
0192 
0193     KCharSelect         *m_charSelect;              /**< pointer to KCharSelect dialog used to add characters to paths */
0194 
0195     int     m_gridElements;                         /**< The number of grid elements (Configuration::editor_GridElements) */
0196     int     m_elementSize;                          /**< The size in pixels of an element (Configuration::editor_ElementSize) */
0197     int     m_elementGrouping;                      /**< The number of cells in a group (Configuration::editor_ElementGroup) */
0198     double  m_pointSize;                            /**< The size of a point in pixels (Configuration::editor_PointSize) */
0199     double  m_snapThreshold;                        /**< The distance to check within the range of a point (Configuration::editor_SnapThreshold) */
0200     int     m_borderSize;                           /**< The number of cell elements used for the border (Configuration::editor_BorderSize) */
0201     QColor  m_preferredSizeColor;                   /**< The color of the preferred size square (Configuration::editor_PreferredSizeColor) */
0202     QColor  m_guideLineColor;                       /**< The color of the guide lines (Configuration::editor_GuideLineColor) */
0203 };
0204 
0205 
0206 #endif
0207