aboutsummaryrefslogtreecommitdiff
path: root/src/application.hpp
blob: 0c34532815c77322586d81daf0c49b5329c86273 (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
#pragma once

#include "system_headers.hpp"
#include <memory>
#include <optional>
#include <functional>
#include <typeindex>
#include <type_traits>

#include "base.hpp"
#include "any_map.h"

namespace cru 
{
    class Application;

    namespace ui
    {
        class WindowClass;
        class WindowManager;

        namespace animations::details
        {
            class AnimationManager;
        }
    }

    namespace graph
    {
        class GraphManager;
    }

    class TimerManager;

    struct CaretInfo
    {
        std::chrono::milliseconds caret_blink_duration;
        float half_caret_width;
    };

    class GodWindow : public Object
    {
    public:
        explicit GodWindow(Application* application);
        GodWindow(const GodWindow& other) = delete;
        GodWindow(GodWindow&& other) = delete;
        GodWindow& operator=(const GodWindow& other) = delete;
        GodWindow& operator=(GodWindow&& other) = delete;
        ~GodWindow() override;

        HWND GetHandle() const
        {
            return hwnd_;
        }

        std::optional<LRESULT> HandleGodWindowMessage(HWND hwnd, int msg, WPARAM w_param, LPARAM l_param);

    private:
        Application* application_;
        std::unique_ptr<ui::WindowClass> god_window_class_;
        HWND hwnd_;
    };

    class Application : public Object
    {
    public:
        static Application* GetInstance();
    private:
        static Application* instance_;

    public:
        explicit Application(HINSTANCE h_instance);
        Application(const Application&) = delete;
        Application(Application&&) = delete;
        Application& operator = (const Application&) = delete;
        Application& operator = (Application&&) = delete;
        ~Application() override;

    public:
        int Run();
        void Quit(int quit_code);


        HINSTANCE GetInstanceHandle() const
        {
            return h_instance_;
        }

        GodWindow* GetGodWindow() const
        {
            return god_window_.get();
        }

        // Resolve a singleton.
        // All singletons will be delete in reverse order of resolve.
        template<typename T, typename = std::enable_if_t<std::is_base_of_v<Object, T>>>
        T* ResolveSingleton(const std::function<T*(Application*)>& creator)
        {
            const auto& index = std::type_index{typeid(T)};
            const auto find_result = singleton_map_.find(index);
            if (find_result != singleton_map_.cend())
                return static_cast<T*>(find_result->second);

            auto singleton = creator(this);
            singleton_map_.emplace(index, static_cast<Object*>(singleton));
            singleton_list_.push_back(singleton);
            return singleton;
        }


        CaretInfo GetCaretInfo() const
        {
            return caret_info_;
        }

        const AnyMap* GetPredefineResourceMap() const
        {
            return &predefine_resource_map_;
        }

    private:
        HINSTANCE h_instance_;

        std::unique_ptr<GodWindow> god_window_;

        std::unordered_map<std::type_index, Object*> singleton_map_;
        std::list<Object*> singleton_list_; // used for reverse destroy.

        CaretInfo caret_info_;

        AnyMap predefine_resource_map_{};
    };


    void InvokeLater(const std::function<void()>& action);
}