summaryrefslogtreecommitdiff
path: root/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp
blob: 867b86e84613a42898166bf2322cb4cf351493bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#pragma once

#include "../../TiledAlgorithm.hpp"
#include "../../../../helpers/math/Direction.hpp"
#include "ScrollTapeController.hpp"
#include "../../../../helpers/signal/Signal.hpp"

#include <optional>
#include <vector>

namespace Layout::Tiled {
    class CScrollingAlgorithm;
    struct SColumnData;
    struct SScrollingData;

    struct SScrollingTargetData {
        SScrollingTargetData(SP<ITarget> t, SP<SColumnData> col) : target(t), column(col) {
            ;
        }

        WP<ITarget>     target;
        WP<SColumnData> column;
        bool            ignoreFullscreenChecks = false;

        CBox            layoutBox;
    };

    struct SColumnData {
        SColumnData(SP<SScrollingData> data) : scrollingData(data) {
            ;
        }

        void   add(SP<ITarget> t);
        void   add(SP<ITarget> t, int after);
        void   add(SP<SScrollingTargetData> w);
        void   add(SP<SScrollingTargetData> w, int after);
        void   remove(SP<ITarget> t);
        bool   has(SP<ITarget> t);
        size_t idx(SP<ITarget> t);

        // index of lowest target that is above y.
        size_t                                idxForHeight(float y);

        bool                                  up(SP<SScrollingTargetData> w);
        bool                                  down(SP<SScrollingTargetData> w);

        SP<SScrollingTargetData>              next(SP<SScrollingTargetData> w);
        SP<SScrollingTargetData>              prev(SP<SScrollingTargetData> w);

        std::vector<SP<SScrollingTargetData>> targetDatas;
        WP<SScrollingData>                    scrollingData;
        WP<SScrollingTargetData>              lastFocusedTarget;

        WP<SColumnData>                       self;

        // Helper methods to access controller-managed data
        float getColumnWidth() const;
        void  setColumnWidth(float width);
        float getTargetSize(size_t idx) const;
        void  setTargetSize(size_t idx, float size);
        float getTargetSize(SP<SScrollingTargetData> target) const;
        void  setTargetSize(SP<SScrollingTargetData> target, float size);
    };

    struct SScrollingData {
        SScrollingData(CScrollingAlgorithm* algo);

        std::vector<SP<SColumnData>> columns;

        UP<CScrollTapeController>    controller;

        SP<SColumnData>              add(std::optional<float> width = std::nullopt);
        SP<SColumnData>              add(int after, std::optional<float> width = std::nullopt);
        int64_t                      idx(SP<SColumnData> c);
        void                         remove(SP<SColumnData> c);
        double                       maxWidth();
        SP<SColumnData>              next(SP<SColumnData> c);
        SP<SColumnData>              prev(SP<SColumnData> c);
        SP<SColumnData>              atCenter();

        bool                         visible(SP<SColumnData> c, bool full = false);
        void                         centerCol(SP<SColumnData> c);
        void                         fitCol(SP<SColumnData> c);
        void                         centerOrFitCol(SP<SColumnData> c);

        void                         recalculate(bool forceInstant = false);

        CScrollingAlgorithm*         algorithm = nullptr;
        WP<SScrollingData>           self;
        std::optional<double>        lockedCameraOffset;
    };

    class CScrollingAlgorithm : public ITiledAlgorithm {
      public:
        CScrollingAlgorithm();
        virtual ~CScrollingAlgorithm();

        virtual void                     newTarget(SP<ITarget> target);
        virtual void                     movedTarget(SP<ITarget> target, std::optional<Vector2D> focalPoint = std::nullopt);
        virtual void                     removeTarget(SP<ITarget> target);

        virtual void                     resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner = CORNER_NONE);
        virtual void                     recalculate(eRecalculateReason reason = RECALCULATE_REASON_UNKNOWN);

        virtual SP<ITarget>              getNextCandidate(SP<ITarget> old);

        virtual Config::ErrorResult      layoutMsg(const std::string_view& sv);
        virtual std::optional<Vector2D>  predictSizeForNewTarget();

        virtual void                     swapTargets(SP<ITarget> a, SP<ITarget> b);
        virtual void                     moveTargetInDirection(SP<ITarget> t, Math::eDirection dir, bool silent);

        virtual eFullscreenRequestResult requestFullscreen(const SFullscreenRequest& request);
        virtual SP<ITarget>              layoutFullscreenTarget() const;
        virtual bool                     layoutFullscreenCoversMonitor() const;

        void                             moveTape(float delta);
        void                             moveTapeNormalized(double delta);
        void                             snapToGrid();
        SP<SColumnData>                  snapToProjectedOffset(double projectedNormalizedOffset);
        void                             focusColumn(SP<SColumnData> column);
        SP<SColumnData>                  getColumnAtViewportCenter();
        SP<SColumnData>                  currentColumn();

        double                           primaryViewportSize();
        double                           normalizedTapeOffset();

        CBox                             usableArea() const;
        SP<SScrollingTargetData>         dataFor(SP<ITarget> t) const;

        enum eInputMode : uint8_t {
            INPUT_MODE_SOFT = 0,
            INPUT_MODE_CLICK,
            INPUT_MODE_HARD
        };

      private:
        SP<SScrollingData>  m_scrollingData;

        CHyprSignalListener m_configCallback;
        CHyprSignalListener m_focusCallback;
        CHyprSignalListener m_mouseButtonCallback;

        struct {
            std::vector<float> configuredWidths;
        } m_config;

        eScrollDirection getDynamicDirection();

        struct SFullscreenScrollState {
            WP<ITarget>          target;
            std::optional<float> restoreColumnWidth;
        };

        void                                syncFullscreenTargets();
        SFullscreenScrollState*             fullscreenStateForTarget(SP<ITarget> target);
        SFullscreenScrollState*             fullscreenStateForData(SP<SScrollingTargetData> target);
        SP<SScrollingTargetData>            fullscreenTargetDataForColumn(SP<SColumnData> col) const;
        bool                                isFullscreenTarget(SP<SScrollingTargetData> target) const;
        float                               fullscreenColumnWidth() const;
        bool                                fullscreenColumnCoversMonitor(SP<SColumnData> col) const;
        void                                updateFullscreenFade(bool coversMonitor);
        void                                clearFullscreenTarget(SP<ITarget> target = nullptr);

        SP<SScrollingTargetData>            findBestNeighbor(SP<SScrollingTargetData> pCurrent, SP<SColumnData> pTargetCol);
        SP<SScrollingTargetData>            closestNode(const Vector2D& posGlobglobgabgalab);

        void                                focusTargetUpdate(SP<ITarget> target);
        void                                moveTargetTo(SP<ITarget> t, Math::eDirection dir, bool silent);
        void                                focusOnInput(SP<ITarget> target, eInputMode input);

        void                                expelTarget(SP<SScrollingTargetData> tdata, SP<SColumnData> srcCol, std::optional<int64_t> insertIdx);

        float                               defaultColumnWidth();

        std::vector<SFullscreenScrollState> m_fullscreenTargets;
        bool                                m_lastFullscreenCover = false;

        friend struct SScrollingData;
    };
};