summaryrefslogtreecommitdiff
path: root/src/layout/algorithm/tiled/scrolling/ScrollingAlgorithm.hpp
blob: 109aa99ebe00ea73309731dc5b5fd16dc78bab39 (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
#pragma once

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

#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);

        void                                  up(SP<SScrollingTargetData> w);
        void                                  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();
        SP<SColumnData>              add(int after);
        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);
        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();

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

        virtual std::expected<void, std::string> 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);

        CBox                                     usableArea();

      private:
        SP<SScrollingData>  m_scrollingData;

        CHyprSignalListener m_configCallback;
        CHyprSignalListener m_focusCallback;
        CHyprSignalListener m_mouseButtonCallback;

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

        eScrollDirection         getDynamicDirection();

        SP<SScrollingTargetData> findBestNeighbor(SP<SScrollingTargetData> pCurrent, SP<SColumnData> pTargetCol);
        SP<SScrollingTargetData> dataFor(SP<ITarget> t);
        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, bool hardInput);

        friend struct SScrollingData;
    };
};