summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGUI/TreeViewModel.h
blob: 664b59ccf0a65f56a5cbc81a4337cc5a96e60683 (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
/*
 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
#include <AK/RefPtr.h>
#include <AK/StdLibExtras.h>
#include <AK/String.h>
#include <AK/WeakPtr.h>
#include <LibGUI/Model.h>

namespace GUI {

class TreeViewModel final : public Model {
public:
    static NonnullRefPtr<TreeViewModel> create()
    {
        return adopt_ref(*new TreeViewModel());
    }

    virtual ~TreeViewModel() override = default;

    virtual int row_count(ModelIndex const& = {}) const override;
    virtual int column_count(ModelIndex const& = {}) const override { return 1; }
    virtual Variant data(ModelIndex const&, ModelRole role) const override;
    virtual ModelIndex parent_index(ModelIndex const&) const override;
    virtual ModelIndex index(int row, int column, ModelIndex const& parent = {}) const override;

    class Node
        : public RefCounted<Node>
        , public Weakable<Node> {
    public:
        Node(String text, Optional<Icon> icon, Node* parent_node = nullptr)
            : m_text(move(text))
            , m_icon(move(icon))
            , m_parent_node(parent_node)
        {
        }

        virtual ~Node() = default;

        template<typename NodeType = Node, typename... Args>
        NonnullRefPtr<NodeType> add_node(String text, Optional<Icon> icon, Args&&... args) requires(IsBaseOf<Node, NodeType>)
        {
            auto node = adopt_ref(*new NodeType(move(text), move(icon), this, forward<Args>(args)...));
            m_child_nodes.append(*static_cast<Node const*>(node.ptr()));
            return node;
        }

        String const& text() const { return m_text; }
        Optional<Icon> const& icon() const { return m_icon; }

        Node const* parent_node() const { return m_parent_node; }
        Node* parent_node() { return m_parent_node; }

        NonnullRefPtrVector<Node> const& child_nodes() const { return m_child_nodes; }
        NonnullRefPtrVector<Node>& child_nodes() { return m_child_nodes; }

    private:
        String m_text;
        Optional<Icon> m_icon;
        WeakPtr<Node> m_parent_node;
        NonnullRefPtrVector<Node> m_child_nodes;
    };

    NonnullRefPtrVector<Node> const& nodes() const { return m_nodes; }
    NonnullRefPtrVector<Node>& nodes() { return m_nodes; }

    template<typename NodeType = Node, typename... Args>
    NonnullRefPtr<NodeType> add_node(String text, Optional<Icon> icon, Args&&... args) requires(IsBaseOf<Node, NodeType>)
    {
        auto node = adopt_ref(*new NodeType(move(text), move(icon), nullptr, forward<Args>(args)...));
        m_nodes.append(*static_cast<Node const*>(node.ptr()));
        return node;
    }

    Optional<ModelIndex> index_for_node(Node const&, ModelIndex const& parent = {}) const;

private:
    TreeViewModel() = default;

    NonnullRefPtrVector<Node> m_nodes;
};

}