File indexing completed on 2024-05-12 03:48:23

0001 /*
0002     File                 : WorksheetElement.h
0003     Project              : LabPlot
0004     Description          : Base class for all Worksheet children.
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2009 Tilman Benkert <thzs@gmx.net>
0007     SPDX-FileCopyrightText: 2012-2022 Alexander Semke <alexander.semke@web.de>
0008     SPDX-FileCopyrightText: 2021 Stefan Gerlach <stefan.gerlach@uni.kn>
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #ifndef WORKSHEETELEMENT_H
0013 #define WORKSHEETELEMENT_H
0014 
0015 #include "backend/core/AbstractAspect.h"
0016 #include "backend/lib/macros.h"
0017 #include <QPainterPath>
0018 
0019 #define D(obj_class) auto* d = static_cast<obj_class##Private*>(d_ptr)
0020 
0021 class CartesianPlot;
0022 class CartesianCoordinateSystem;
0023 class WorksheetElementPrivate;
0024 class KConfig;
0025 
0026 class QAction;
0027 class QGraphicsItem;
0028 class QPen;
0029 
0030 class WorksheetElement : public AbstractAspect {
0031     Q_OBJECT
0032 
0033 public:
0034     WorksheetElement(const QString& name, AspectType type);
0035     ~WorksheetElement() override;
0036 
0037     enum class Orientation { Horizontal, Vertical, Both };
0038     enum class HorizontalPosition { Left, Center, Right, Relative }; // Relative: relative to plot area
0039     enum class VerticalPosition { Top, Center, Bottom, Relative };
0040 
0041     enum class HorizontalAlignment { Left, Center, Right };
0042     enum class VerticalAlignment { Top, Center, Bottom };
0043 
0044     enum class PositionLimit { None, X, Y };
0045 
0046     struct PositionWrapper {
0047         PositionWrapper() {
0048         }
0049         PositionWrapper(QPointF p, HorizontalPosition hor, VerticalPosition vert, PositionLimit limit)
0050             : point(p)
0051             , horizontalPosition(hor)
0052             , verticalPosition(vert)
0053             , positionLimit(limit) {
0054         }
0055 
0056         QPointF point; // range [0 .. 1] for relative position
0057         HorizontalPosition horizontalPosition{HorizontalPosition::Center};
0058         VerticalPosition verticalPosition{VerticalPosition::Center};
0059         PositionLimit positionLimit{PositionLimit::None};
0060     };
0061 
0062     typedef WorksheetElementPrivate Private;
0063 
0064     CLASS_D_ACCESSOR_DECL(PositionWrapper, position, Position)
0065     bool setCoordinateBindingEnabled(bool);
0066     bool coordinateBindingEnabled() const;
0067     BASIC_D_ACCESSOR_DECL(QPointF, positionLogical, PositionLogical)
0068     void setPosition(QPointF);
0069     void setPositionInvalid(bool);
0070     BASIC_D_ACCESSOR_DECL(HorizontalAlignment, horizontalAlignment, HorizontalAlignment)
0071     BASIC_D_ACCESSOR_DECL(VerticalAlignment, verticalAlignment, VerticalAlignment)
0072     BASIC_D_ACCESSOR_DECL(qreal, rotationAngle, RotationAngle)
0073     BASIC_D_ACCESSOR_DECL(qreal, scale, Scale)
0074     BASIC_D_ACCESSOR_DECL(bool, isLocked, Lock)
0075     BASIC_D_ACCESSOR_DECL(bool, isHovered, Hover)
0076 
0077     void finalizeAdd() override;
0078 
0079     virtual QGraphicsItem* graphicsItem() const;
0080     virtual void setParentGraphicsItem(QGraphicsItem* item);
0081     virtual void setZValue(qreal);
0082     virtual void setVisible(bool on);
0083     virtual bool isVisible() const;
0084     virtual bool isFullyVisible() const;
0085     void setSuppressRetransform(bool);
0086 
0087     virtual void setPrinting(bool);
0088     bool isPrinting() const;
0089 
0090     QRectF parentRect() const;
0091     QPointF parentPosToRelativePos(QPointF parentPos, PositionWrapper) const;
0092     QPointF relativePosToParentPos(PositionWrapper) const;
0093 
0094     QPointF align(QPointF, QRectF, HorizontalAlignment, VerticalAlignment, bool positive) const;
0095 
0096     virtual QMenu* createContextMenu() override;
0097     QAction* visibilityAction();
0098     QAction* lockingAction();
0099 
0100     void save(QXmlStreamWriter*) const override;
0101     bool load(XmlStreamReader*, bool) override;
0102     virtual void loadThemeConfig(const KConfig&);
0103     virtual void saveThemeConfig(const KConfig&);
0104 
0105     static QPainterPath shapeFromPath(const QPainterPath&, const QPen&);
0106     virtual void handleResize(double horizontalRatio, double verticalRatio, bool pageResize = false) = 0;
0107 
0108     CartesianPlot* plot() const {
0109         return m_plot;
0110     } // used in the element docks
0111     int coordinateSystemIndex() const {
0112         return m_cSystemIndex;
0113     }
0114     void setCoordinateSystemIndex(int, QUndoCommand* parent = nullptr);
0115     int coordinateSystemCount() const;
0116     QString coordinateSystemInfo(int index) const;
0117 
0118 private:
0119     void init();
0120     QAction* m_visibilityAction{nullptr};
0121     QAction* m_lockingAction{nullptr};
0122 
0123 protected:
0124     WorksheetElement(const QString&, WorksheetElementPrivate* dd, AspectType);
0125     int m_cSystemIndex{0}; // index of coordinate system used from plot
0126     // parent plot if available
0127     // not const because of prepareGeometryChange()
0128     // normally set in finalizeAdd()
0129     CartesianPlot* m_plot{nullptr};
0130     const CartesianCoordinateSystem* cSystem{nullptr}; // current cSystem
0131 
0132 public Q_SLOTS:
0133     virtual void retransform() = 0;
0134 
0135 protected:
0136     WorksheetElementPrivate* const d_ptr;
0137 
0138 private:
0139     Q_DECLARE_PRIVATE(WorksheetElement)
0140     QMenu* m_drawingOrderMenu{nullptr};
0141     QMenu* m_moveBehindMenu{nullptr};
0142     QMenu* m_moveInFrontOfMenu{nullptr};
0143     bool m_printing{false};
0144 
0145 protected Q_SLOTS:
0146     void changeVisibility();
0147     void changeLocking();
0148 
0149 private Q_SLOTS:
0150     void prepareDrawingOrderMenu();
0151     void execMoveBehind(QAction*);
0152     void execMoveInFrontOf(QAction*);
0153 
0154 Q_SIGNALS:
0155     friend class AbstractPlotSetHorizontalPaddingCmd;
0156     friend class AbstractPlotSetVerticalPaddingCmd;
0157     friend class AbstractPlotSetRightPaddingCmd;
0158     friend class AbstractPlotSetBottomPaddingCmd;
0159     friend class AbstractPlotSetSymmetricPaddingCmd;
0160     void positionChanged(const WorksheetElement::PositionWrapper&) const;
0161     void horizontalAlignmentChanged(const WorksheetElement::HorizontalAlignment) const;
0162     void verticalAlignmentChanged(const WorksheetElement::VerticalAlignment) const;
0163     void coordinateBindingEnabledChanged(bool) const;
0164     void positionLogicalChanged(QPointF) const;
0165     void rotationAngleChanged(qreal) const;
0166     void rotationChanged(qreal) const;
0167     void visibleChanged(bool) const;
0168     void lockChanged(bool) const;
0169     void coordinateSystemIndexChanged(int) const;
0170     void changed();
0171     void hoveredChanged(bool) const;
0172 
0173     void objectPositionChanged(); // Position changed, independend of logical or scene, bot are triggering this
0174 
0175     void hovered();
0176     void unhovered();
0177     // needed in the worksheet info element, because execMoveInFrontOf and execMoveBehind
0178     // call also child removed but this is only temporary
0179     void moveBegin(); // called, at the begin of execMoveInFrontOf or execMoveBehind is called
0180     void moveEnd(); // called, at the end of execMoveInFrontOf or execMoveBehind is called
0181 
0182     void plotRangeListChanged();
0183 
0184     friend class WorksheetElementTest;
0185     friend class SetCoordinateSystemIndexCmd;
0186 };
0187 
0188 #endif