summaryrefslogtreecommitdiff
path: root/Userland/Applications/Spreadsheet/Cell.h
blob: 6159b9ec2d69e390c550e92acb9d8c2d27847ba7 (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
/*
 * Copyright (c) 2020, the SerenityOS developers.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include "CellType/Type.h"
#include "ConditionalFormatting.h"
#include "Forward.h"
#include "JSIntegration.h"
#include "Position.h"
#include <AK/String.h>
#include <AK/Types.h>
#include <AK/WeakPtr.h>
#include <LibGUI/Command.h>

namespace Spreadsheet {

struct Cell : public Weakable<Cell> {
    enum Kind {
        LiteralString,
        Formula,
    };

    Cell(String data, Position position, WeakPtr<Sheet> sheet)
        : m_dirty(false)
        , m_data(move(data))
        , m_kind(LiteralString)
        , m_sheet(sheet)
        , m_position(move(position))
    {
    }

    Cell(String source, JS::Value&& cell_value, Position position, WeakPtr<Sheet> sheet)
        : m_dirty(false)
        , m_data(move(source))
        , m_evaluated_data(move(cell_value))
        , m_kind(Formula)
        , m_sheet(sheet)
        , m_position(move(position))
    {
    }

    void reference_from(Cell*);

    void set_data(String new_data);
    void set_data(JS::Value new_data);
    bool dirty() const { return m_dirty; }
    void clear_dirty() { m_dirty = false; }

    void set_thrown_value(JS::Value value) { m_thrown_value = value; }
    Optional<JS::Value> thrown_value() const
    {
        if (m_thrown_value.is_empty())
            return {};
        return m_thrown_value;
    }

    String const& data() const { return m_data; }
    const JS::Value& evaluated_data() const { return m_evaluated_data; }
    Kind kind() const { return m_kind; }
    Vector<WeakPtr<Cell>> const& referencing_cells() const { return m_referencing_cells; }

    void set_type(StringView name);
    void set_type(CellType const*);
    void set_type_metadata(CellTypeMetadata&&);

    Position const& position() const { return m_position; }
    void set_position(Position position, Badge<Sheet>)
    {
        if (position != m_position) {
            m_dirty = true;
            m_position = move(position);
        }
    }

    Format const& evaluated_formats() const { return m_evaluated_formats; }
    Format& evaluated_formats() { return m_evaluated_formats; }
    Vector<ConditionalFormat> const& conditional_formats() const { return m_conditional_formats; }
    void set_conditional_formats(Vector<ConditionalFormat>&& fmts)
    {
        m_dirty = true;
        m_conditional_formats = move(fmts);
    }

    JS::ThrowCompletionOr<String> typed_display() const;
    JS::ThrowCompletionOr<JS::Value> typed_js_data() const;

    CellType const& type() const;
    CellTypeMetadata const& type_metadata() const { return m_type_metadata; }
    CellTypeMetadata& type_metadata() { return m_type_metadata; }

    String source() const;

    JS::Value js_data();

    void update();
    void update_data(Badge<Sheet>);

    Sheet const& sheet() const { return *m_sheet; }
    Sheet& sheet() { return *m_sheet; }

    void copy_from(Cell const&);

private:
    bool m_dirty { false };
    bool m_evaluated_externally { false };
    String m_data;
    JS::Value m_evaluated_data;
    JS::Value m_thrown_value;
    Kind m_kind { LiteralString };
    WeakPtr<Sheet> m_sheet;
    Vector<WeakPtr<Cell>> m_referencing_cells;
    CellType const* m_type { nullptr };
    CellTypeMetadata m_type_metadata;
    Position m_position;

    Vector<ConditionalFormat> m_conditional_formats;
    Format m_evaluated_formats;
};

class CellUndoCommand : public GUI::Command {
public:
    CellUndoCommand(Cell&, String const&);

    virtual void undo() override;
    virtual void redo() override;

private:
    Cell& m_cell;
    String m_current_data;
    String m_previous_data;
};

}