summaryrefslogtreecommitdiff
path: root/Userland/DevTools/HackStudio/HackStudioWidget.h
blob: d54b3754726fa470f0f7ef19024a1547cfb69cf1 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/*
 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
 * Copyright (c) 2020-2022, Itamar S. <itamar8910@gmail.com>
 * Copyright (c) 2020-2021, the SerenityOS developers.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include "ClassViewWidget.h"
#include "Debugger/DebugInfoWidget.h"
#include "Debugger/DisassemblyWidget.h"
#include "EditorWrapper.h"
#include "FindInFilesWidget.h"
#include "GMLPreviewWidget.h"
#include "Git/DiffViewer.h"
#include "Git/GitWidget.h"
#include "Locator.h"
#include "Project.h"
#include "ProjectBuilder.h"
#include "ProjectFile.h"
#include "TerminalWrapper.h"
#include "ToDoEntriesWidget.h"
#include <LibCoredump/Inspector.h>
#include <LibGUI/ActionGroup.h>
#include <LibGUI/Button.h>
#include <LibGUI/Scrollbar.h>
#include <LibGUI/Splitter.h>
#include <LibGUI/Widget.h>
#include <LibGfx/Font/Font.h>
#include <LibThreading/Thread.h>

namespace HackStudio {

class HackStudioWidget : public GUI::Widget {
    C_OBJECT_ABSTRACT(HackStudioWidget)

public:
    static ErrorOr<NonnullRefPtr<HackStudioWidget>> create(DeprecatedString path_to_project);
    virtual ~HackStudioWidget() override;

    bool open_file(DeprecatedString const& filename, size_t line = 0, size_t column = 0);
    void close_file_in_all_editors(DeprecatedString const& filename);

    void update_actions();
    Project& project();
    GUI::TextEditor& current_editor();
    GUI::TextEditor const& current_editor() const;
    EditorWrapper& current_editor_wrapper();
    EditorWrapper const& current_editor_wrapper() const;
    void set_current_editor_wrapper(RefPtr<EditorWrapper>);
    void set_current_editor_tab_widget(RefPtr<GUI::TabWidget>);

    GUI::TabWidget& current_editor_tab_widget();
    GUI::TabWidget const& current_editor_tab_widget() const;

    DeprecatedString const& active_file() const { return m_current_editor_wrapper->filename(); }
    ErrorOr<void> initialize_menubar(GUI::Window&);

    Locator& locator()
    {
        VERIFY(m_locator);
        return *m_locator;
    }

    enum class ContinueDecision {
        No,
        Yes
    };
    ContinueDecision warn_unsaved_changes(DeprecatedString const& prompt);

    enum class Mode {
        Code,
        Coredump
    };

    void open_coredump(DeprecatedString const& coredump_path);
    void debug_process(pid_t pid);
    void for_each_open_file(Function<void(ProjectFile const&)>);
    bool semantic_syntax_highlighting_is_enabled() const;

    static Vector<DeprecatedString> read_recent_projects();

    void update_current_editor_title();
    void update_window_title();

private:
    static constexpr size_t recent_projects_history_size = 15;

    static DeprecatedString get_full_path_of_serenity_source(DeprecatedString const& file);
    DeprecatedString get_absolute_path(DeprecatedString const&) const;
    Vector<DeprecatedString> selected_file_paths() const;

    void open_project(DeprecatedString const& root_path);

    enum class EditMode {
        Text,
        Diff,
    };

    void set_edit_mode(EditMode);

    ErrorOr<NonnullRefPtr<GUI::Menu>> create_project_tree_view_context_menu();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_new_file_action(DeprecatedString const& label, DeprecatedString const& icon, DeprecatedString const& extension);
    ErrorOr<NonnullRefPtr<GUI::Action>> create_new_directory_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_open_selected_action();
    NonnullRefPtr<GUI::Action> create_delete_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_new_project_action();
    NonnullRefPtr<GUI::Action> create_switch_to_next_editor_tab_widget_action();
    NonnullRefPtr<GUI::Action> create_switch_to_next_editor_action();
    NonnullRefPtr<GUI::Action> create_switch_to_previous_editor_action();
    NonnullRefPtr<GUI::Action> create_remove_current_editor_tab_widget_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_remove_current_editor_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_open_action();
    NonnullRefPtr<GUI::Action> create_save_action();
    NonnullRefPtr<GUI::Action> create_save_as_action();
    NonnullRefPtr<GUI::Action> create_show_in_file_manager_action();
    NonnullRefPtr<GUI::Action> create_copy_relative_path_action();
    NonnullRefPtr<GUI::Action> create_copy_full_path_action();
    NonnullRefPtr<GUI::Action> create_add_editor_tab_widget_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_add_editor_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_add_terminal_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_remove_current_terminal_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_debug_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_build_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_run_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_stop_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_toggle_syntax_highlighting_mode_action();
    ErrorOr<NonnullRefPtr<GUI::Action>> create_open_project_configuration_action();
    ErrorOr<void> create_location_history_actions();

    void add_new_editor_tab_widget(GUI::Widget& parent);
    void add_new_editor(GUI::TabWidget& parent);
    RefPtr<EditorWrapper> get_editor_of_file(DeprecatedString const& filename);
    DeprecatedString get_project_executable_path() const;

    void on_action_tab_change();
    void reveal_action_tab(GUI::Widget&);
    void initialize_debugger();
    void update_statusbar();

    void handle_external_file_deletion(DeprecatedString const& filepath);
    void stop_debugger_if_running();
    void close_current_project();

    void create_open_files_view(GUI::Widget& parent);
    void create_toolbar(GUI::Widget& parent);
    ErrorOr<void> create_action_tab(GUI::Widget& parent);
    ErrorOr<void> create_file_menu(GUI::Window&);
    void update_recent_projects_submenu();
    ErrorOr<void> create_edit_menu(GUI::Window&);
    void create_build_menu(GUI::Window&);
    ErrorOr<void> create_view_menu(GUI::Window&);
    void create_help_menu(GUI::Window&);
    void create_project_tab(GUI::Widget& parent);
    void configure_project_tree_view();

    void run();
    void build();

    void hide_action_tabs();
    bool any_document_is_dirty() const;

    void update_gml_preview();
    void update_tree_view();
    void update_toolbar_actions();
    void on_cursor_change();
    void file_renamed(DeprecatedString const& old_name, DeprecatedString const& new_name);

    struct ProjectLocation {
        DeprecatedString filename;
        size_t line { 0 };
        size_t column { 0 };
    };

    ProjectLocation current_project_location() const;
    void update_history_actions();

    Vector<NonnullRefPtr<EditorWrapper>> m_all_editor_wrappers;
    RefPtr<EditorWrapper> m_current_editor_wrapper;
    Vector<NonnullRefPtr<GUI::TabWidget>> m_all_editor_tab_widgets;
    RefPtr<GUI::TabWidget> m_current_editor_tab_widget;

    HashMap<DeprecatedString, NonnullRefPtr<ProjectFile>> m_open_files;
    RefPtr<Core::FileWatcher> m_file_watcher;
    Vector<DeprecatedString> m_open_files_vector; // NOTE: This contains the keys from m_open_files and m_file_watchers

    OwnPtr<Project> m_project;

    Vector<ProjectLocation> m_locations_history;
    // This index is the boundary between the "Go Back" and "Go Forward" locations.
    // It always points at one past the current location in the list.
    size_t m_locations_history_end_index { 0 };
    bool m_locations_history_disabled { false };

    RefPtr<GUI::TreeView> m_project_tree_view;
    RefPtr<GUI::ListView> m_open_files_view;
    RefPtr<GUI::VerticalSplitter> m_right_hand_splitter;
    RefPtr<GUI::StackWidget> m_right_hand_stack;
    RefPtr<GUI::Splitter> m_editors_splitter;
    RefPtr<DiffViewer> m_diff_viewer;
    RefPtr<GitWidget> m_git_widget;
    RefPtr<GMLPreviewWidget> m_gml_preview_widget;
    RefPtr<ClassViewWidget> m_class_view;
    RefPtr<GUI::Menu> m_project_tree_view_context_menu;
    RefPtr<GUI::Statusbar> m_statusbar;
    RefPtr<GUI::TabWidget> m_action_tab_widget;
    RefPtr<GUI::TabWidget> m_project_tab;
    RefPtr<TerminalWrapper> m_terminal_wrapper;
    RefPtr<Locator> m_locator;
    RefPtr<FindInFilesWidget> m_find_in_files_widget;
    RefPtr<ToDoEntriesWidget> m_todo_entries_widget;
    RefPtr<DebugInfoWidget> m_debug_info_widget;
    RefPtr<DisassemblyWidget> m_disassembly_widget;
    RefPtr<Threading::Thread> m_debugger_thread;
    RefPtr<EditorWrapper> m_current_editor_in_execution;
    RefPtr<GUI::Menu> m_recent_projects_submenu { nullptr };

    Vector<NonnullRefPtr<GUI::Action>> m_new_file_actions;
    RefPtr<GUI::Action> m_new_plain_file_action;

    RefPtr<GUI::Action> m_new_directory_action;
    RefPtr<GUI::Action> m_open_selected_action;
    RefPtr<GUI::Action> m_show_in_file_manager_action;
    RefPtr<GUI::Action> m_copy_relative_path_action;
    RefPtr<GUI::Action> m_copy_full_path_action;
    RefPtr<GUI::Action> m_delete_action;
    RefPtr<GUI::Action> m_tree_view_rename_action;
    RefPtr<GUI::Action> m_new_project_action;
    RefPtr<GUI::Action> m_switch_to_next_editor_tab_widget;
    RefPtr<GUI::Action> m_switch_to_next_editor;
    RefPtr<GUI::Action> m_switch_to_previous_editor;
    RefPtr<GUI::Action> m_remove_current_editor_tab_widget_action;
    RefPtr<GUI::Action> m_remove_current_editor_action;
    RefPtr<GUI::Action> m_open_action;
    RefPtr<GUI::Action> m_save_action;
    RefPtr<GUI::Action> m_save_as_action;
    RefPtr<GUI::Action> m_add_editor_action;
    RefPtr<GUI::Action> m_add_editor_tab_widget_action;
    RefPtr<GUI::Action> m_add_terminal_action;
    RefPtr<GUI::Action> m_remove_current_terminal_action;
    RefPtr<GUI::Action> m_stop_action;
    RefPtr<GUI::Action> m_debug_action;
    RefPtr<GUI::Action> m_build_action;
    RefPtr<GUI::Action> m_run_action;
    RefPtr<GUI::Action> m_locations_history_back_action;
    RefPtr<GUI::Action> m_locations_history_forward_action;
    RefPtr<GUI::Action> m_toggle_semantic_highlighting_action;
    RefPtr<GUI::Action> m_open_project_configuration_action;

    RefPtr<Gfx::Font const> read_editor_font_from_config();
    void change_editor_font(RefPtr<Gfx::Font const>);
    RefPtr<Gfx::Font const> m_editor_font;
    RefPtr<GUI::Action> m_editor_font_action;

    GUI::TextEditor::WrappingMode m_wrapping_mode { GUI::TextEditor::NoWrap };
    GUI::ActionGroup m_wrapping_mode_actions;
    RefPtr<GUI::Action> m_no_wrapping_action;
    RefPtr<GUI::Action> m_wrap_anywhere_action;
    RefPtr<GUI::Action> m_wrap_at_words_action;

    RefPtr<GUI::Button> m_cut_button;
    RefPtr<GUI::Button> m_paste_button;
    RefPtr<GUI::Button> m_copy_button;

    Mode m_mode { Mode::Code };
    OwnPtr<Coredump::Inspector> m_coredump_inspector;
    OwnPtr<ProjectBuilder> m_project_builder;
};
}