components-window.cpp 10.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
// Copyright (c) 2020 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include "application.hpp"
#include "dialog.hpp"
#include "editor.hpp"
#include "internal.hpp"

namespace irt {

static component_id add_empty_component(component_editor& ed) noexcept
{
14
15
    auto ret = undefined<component_id>();

16
    if (ed.mod.components.can_alloc()) {
17
        auto& new_compo = ed.mod.components.alloc();
18
19
20
21
        new_compo.name.assign("New component");
        new_compo.type  = component_type::memory;
        new_compo.state = component_status::modified;

22
23
24
25
26
27
28
29
30
        ret = ed.mod.components.get_id(new_compo);
    } else {
        auto* app   = container_of(&ed, &application::c_editor);
        auto& notif = app->notifications.alloc(notification_type::error);
        notif.title = "Can not allocate new container";
        format(notif.message,
               "Components allocated: {}\nTree nodes allocated: {}",
               ed.mod.components.size(),
               ed.mod.tree_nodes.size());
31
32
    }

33
    return ret;
34
35
}

36
37
static void show_component_popup_menu(irt::component_editor& ed,
                                      component*             compo) noexcept
38
{
39
40
41
42
43
44
    if (ImGui::BeginPopupContextItem()) {
        if (ImGui::MenuItem("New")) {
            // log_w.log(7, "adding a new component");
            auto id = add_empty_component(ed);
            ed.open_as_main(id);
        }
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
        if (compo) {
            if (ImGui::MenuItem("Copy")) {
                if (ed.mod.components.can_alloc()) {
                    auto& new_c = ed.mod.components.alloc();
                    new_c.type  = component_type::memory;
                    new_c.name  = compo->name;
                    new_c.state = component_status::modified;
                    ed.mod.copy(*compo, new_c);
                } else {
                    // log_w.log(3, "Can not alloc a new component");
                }
            }

            if (compo->type == component_type::memory) {
                if (ImGui::MenuItem("Delete")) {
                    ed.mod.components.free(*compo);
                    compo = nullptr;
                }
            }

            if (compo && compo->type == component_type::file) {
                if (ImGui::MenuItem("Delete file")) {
                    ed.mod.components.free(*compo);
                    compo = nullptr;
                }
            }

            ImGui::EndPopup();
        }
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
static void show_component(component_editor& ed,
                           dir_path&         dir,
                           file_path&        file,
                           component&        c,
                           irt::tree_node*   head) noexcept
{
    const auto id       = ed.mod.components.get_id(c);
    const bool selected = head ? id == head->id : false;

    if (ImGui::Selectable(file.path.c_str(), selected))
        ed.open_as_main(id);

    if (ImGui::BeginPopupContextItem()) {
        if (ImGui::MenuItem("New")) {
            // log_w.log(7, "adding a new component");
            auto id = add_empty_component(ed);
            ed.open_as_main(id);
        }

        if (ImGui::MenuItem("Copy")) {
            if (ed.mod.components.can_alloc()) {
                auto& new_c = ed.mod.components.alloc();
                new_c.type  = component_type::memory;
                new_c.name  = c.name;
                new_c.state = component_status::modified;
                ed.mod.copy(c, new_c);
            } else {
                // log_w.log(3, "Can not alloc a new component");
            }
        }

        if (ImGui::MenuItem("Delete file")) {
            ed.mod.free(c);
        }

        ImGui::EndPopup();
114
115
116
117
118
119
120
121
    }

    if (c.state == component_status::modified) {
        ImGui::SameLine();
        ImGui::TextUnformatted("(modified)");
    }
}

122
123
static void show_notsaved_components(irt::component_editor& ed,
                                     irt::tree_node*        head) noexcept
124
125
126
{
    component* compo = nullptr;
    while (ed.mod.components.next(compo)) {
127
128
129
        const auto is_notsaved = match(compo->type, component_type::memory);

        if (is_notsaved) {
130
131
132
133
            const auto id       = ed.mod.components.get_id(*compo);
            const bool selected = head ? id == head->id : false;

            if (ImGui::Selectable(compo->name.c_str(), selected))
134
135
                ed.open_as_main(id);

136
            show_component_popup_menu(ed, compo);
137
138
139
140
        }
    }
}

141
142
static void show_internal_components(irt::component_editor& ed,
                                     irt::tree_node*        head) noexcept
143
144
145
{
    component* compo = nullptr;
    while (ed.mod.components.next(compo)) {
146
147
148
149
        const auto is_internal =
          !match(compo->type, component_type::file, component_type::memory);

        if (is_internal) {
150
151
152
153
            const auto id       = ed.mod.components.get_id(*compo);
            const bool selected = head ? id == head->id : false;

            if (ImGui::Selectable(compo->name.c_str(), selected))
154
155
                ed.open_as_main(id);

156
            show_component_popup_menu(ed, compo);
157
158
159
160
        }
    }
}

161
void application::show_components_window() noexcept
162
163
164
{
    constexpr ImGuiTreeNodeFlags flags =
      ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen;
165
    component* selected = nullptr;
166

167
168
    auto*        tree = c_editor.mod.tree_nodes.try_to_get(c_editor.mod.head);
    component_id head_id = tree ? tree->id : undefined<component_id>();
169

170
    if (ImGui::CollapsingHeader("Component library", flags)) {
171
        if (ImGui::TreeNodeEx("Internal")) {
172
            show_internal_components(c_editor, tree);
173
174
175
            ImGui::TreePop();
        }

176
        for (auto id : c_editor.mod.component_repertories) {
177
            static small_string<32> s; //! @TODO remove this variable
178
            small_string<32>*       select;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
179

180
            auto& reg_dir = c_editor.mod.registred_paths.get(id);
181
            if (reg_dir.name.empty()) {
182
                format(s, "{}", ordinal(id));
Gauthier Quesnel's avatar
Gauthier Quesnel committed
183
184
                select = &s;
            } else {
185
                select = &reg_dir.name;
Gauthier Quesnel's avatar
Gauthier Quesnel committed
186
            }
187

188
189
            ImGui::PushID(&reg_dir);
            if (ImGui::TreeNodeEx(select->c_str())) {
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
                int i = 0;
                while (i != reg_dir.children.ssize()) {
                    if (auto* dir = c_editor.mod.dir_paths.try_to_get(
                          reg_dir.children[i]);
                        dir) {
                        if (ImGui::TreeNodeEx(dir->path.c_str())) {
                            int j = 0;
                            while (j < dir->children.ssize()) {
                                if (auto* file =
                                      c_editor.mod.file_paths.try_to_get(
                                        dir->children[j]);
                                    file) {
                                    if (auto* compo =
                                          c_editor.mod.components.try_to_get(
                                            file->component);
                                        compo)
                                        show_component(
                                          c_editor, *dir, *file, *compo, tree);
                                    ++j;
                                } else {
                                    dir->children.swap_pop_back(j);
                                }
                            }
                            ImGui::TreePop();
214
                        }
215
216
217
                        ++i;
                    } else {
                        reg_dir.children.swap_pop_back(i);
218
219
                    }
                }
220
221
                ImGui::TreePop();
            }
Gauthier Quesnel's avatar
Gauthier Quesnel committed
222
            ImGui::PopID();
223
224
        }

225
        if (ImGui::TreeNodeEx("Not saved")) {
226
            show_notsaved_components(c_editor, tree);
227
228
229
230
231
232
233
            ImGui::TreePop();
        }
    }

    ImGui::Separator();

    if (ImGui::CollapsingHeader("Selected children", flags)) {
234
235
        auto* tree =
          c_editor.mod.tree_nodes.try_to_get(c_editor.selected_component);
236
        if (tree) {
237
            component* compo = c_editor.mod.components.try_to_get(tree->id);
238
            if (compo) {
239
                for (int i = 0, e = c_editor.selected_nodes.size(); i != e;
240
241
242
                     ++i) {
                    auto* child = compo->children.try_to_get(
                      static_cast<u32>(c_editor.selected_nodes[i]));
243
244
245
246
247
248
                    if (!child)
                        continue;

                    if (ImGui::TreeNodeEx(child,
                                          ImGuiTreeNodeFlags_DefaultOpen,
                                          "%d",
249
                                          c_editor.selected_nodes[i])) {
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
                        bool is_modified = false;
                        ImGui::Text("position %f %f",
                                    static_cast<double>(child->x),
                                    static_cast<double>(child->y));
                        if (ImGui::Checkbox("configurable",
                                            &child->configurable))
                            is_modified = true;
                        if (ImGui::Checkbox("observables", &child->observable))
                            is_modified = true;
                        if (ImGui::InputSmallString("name", child->name))
                            is_modified = true;

                        if (is_modified)
                            compo->state = component_status::modified;

                        if (child->type == child_type::model) {
                            auto  child_id = enum_cast<model_id>(child->id);
                            auto* mdl      = compo->models.try_to_get(child_id);

                            if (mdl)
                                ImGui::Text(
                                  "type: %s",
                                  dynamics_type_names[ordinal(mdl->type)]);
                        } else {
                            auto  compo_id = enum_cast<component_id>(child->id);
275
276
                            auto* compo =
                              c_editor.mod.components.try_to_get(compo_id);
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

                            if (compo)
                                ImGui::Text(
                                  "type: %s",
                                  component_type_names[ordinal(compo->type)]);
                        }

                        ImGui::TreePop();
                    }
                }
            }
        }
    }
}

Gauthier Quesnel's avatar
Gauthier Quesnel committed
292
} // namespace irt