File indexing completed on 2024-04-21 15:23:40

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