-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhelpmenu.cpp
More file actions
327 lines (257 loc) · 13.9 KB
/
Copy pathhelpmenu.cpp
File metadata and controls
327 lines (257 loc) · 13.9 KB
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#include "helpmenu.h"
#include "text_renderer.h"
HelpMenu::HelpMenu(Widget* parent) : Widget(parent) {
id = icu::UnicodeString::fromUTF8("HelpMenu");
closebutton = new Button(this, icu::UnicodeString::fromUTF8("X"), [&](Widget* b, int x, int y, int w, int h, int width, int height){
b->t_x = t_x+t_w-width;
b->t_y = t_y;
b->t_w = width;
b->t_h = height;
}, [&](Widget*){
App::RemoveWidgetFromParent(this);
App::reclear = 2;
});
closebutton->text_special = 1;
closebutton->window_button = true;
closebutton->rounded = true;
closebutton->background_color = nullptr;
closebutton->background_color_hover = App::theme.del_diff;
closebutton->border_color = nullptr;
closebutton->border_color_hover = nullptr;
tb = new Tabs(this);
tb->POSITIONER = [&](Widget* t) {
tb->t_y = t_y+closebutton->t_h;
tb->t_x = t_x+2;
tb->t_w = t_w-2;
};
tb->tab_clicked_callback = [&](TabInfo info){
setToIndex(info.id);
};
tb->can_add_new = false;
tb->has_close_button = false;
helpInformation = {
{
icu::UnicodeString::fromUTF8("General"),
icu::UnicodeString::fromUTF8(R":(CodeWizard2 V):" + App::vnumstr + R":(
CodeWizard2 is a performant code editor/ide written in C++. CodeWizard is designed to be extendable to a number of languages and configurations. Highlighting is provided using the same syntax highlighting system that VSCode uses (but written completely in C++ by yours truly,) and supports the Language Server Protocol. Note that the LSP support is not perfect, and doesn't support everything available. But, it's been tested with gopls, rust analyzer, clangd, and of course pypls (my multi-purpose LSP.)
CodeWizard was created by Adam Mather.):"),
},{
icu::UnicodeString::fromUTF8("Using CodeWizard"),
icu::UnicodeString::fromUTF8(R":( CodeWizard is an extremely opinionated editor. Namely, most actions are handled via keyboard key combos, mouse support is limited, and it's designed to work in the way I will use it.
Opening Files/Folders:
● CodeWizard maintains an active folder. All operations will be executed from this folder, including command palette actions. To change the active folder, use Ctrl+Shift+O.
● Once in the correct folder (or even when not), one can open specific files in the editor interface (see widgets tab to learn how CodeWizard handles widgets.) To open a file, you can use the Ctrl+O command, or use the command palette to open a file in the current directory. To open the command palette without clicking, use Ctrl+Shift+P.
● Use Ctrl+W to close the current file (or click on the close button on the file tab.)
Running Programs:
● Assuming the language you're using has been configured (see 'Languages' section) you can run any files in that language using the F5 key. It will use the command specified for that language.
● Project specific settings can be created to run code with a specific command for a given folder. You can create the project specific settings by creating a settings menu and navigating to 'Project Specific'. Then, it will provide you with a JSON file that you can edit to control that project's build command and language server starting commands.
Quirks:
● The biggest will be the use of tabs instead of four space increments. Deal with it 😉 it's better.
):"),
},{
icu::UnicodeString::fromUTF8("Widgets"),
icu::UnicodeString::fromUTF8(R":( Widgets are the gas on which CodeWizard runs. The most important widgets are the: editor, settings menu, file tree, and terminal widgets. The editor is where all code editing happens, including a tab bar (by default). The file tree is a tree constructed to match the files in your actively selected directory (see Using CodeWizard.) The terminal widget will take over the execution for your code if it's open, otherwise CodeWizard will open a Microsoft Command Prompt and run your code there. And of course the settings menu is where some of CodeWizard's settings are managed.
To open a new widget, click the '+' button in the top left of the screen, hover over where you want the new widget, and click again. (This will not work while in the help menu.)
Similarly, to close, use the '-' button in the top left, hovering over the pane you want removed.
):"),
},{
icu::UnicodeString::fromUTF8("Settings"),
icu::UnicodeString::fromUTF8(R":( The majority of settings are accessible via the settings widget (see 'Widgets'.) This includes editor appearance, toggling features (file tabs, etc,) and AI settings (see AI).
However, CodeWizard also stores language settings in a json file located in C:\Users\<username>\AppData\Local\CodeWizard\languages.json. This file is where you can add syntax highlighting and language servers for specific languages. By default CodeWizard comes setup for some languages, including Python, C++, Go, R, Java, JavaScript, HTML, and Rust.
Project specific settings are described in 'Using CodeWizard', under 'Running Programs'.
):"),
},{
icu::UnicodeString::fromUTF8("Languages"),
icu::UnicodeString::fromUTF8(R":( Languages in CodeWizard are extensible and all configured in the languages settings (see 'Settings')
CodeWizard requires a few things:
● The name of the language, the line comment strings for the language (ex '//' for C++, '#' for Python)
● The filetypes (ex '.py', '.cpp', etc)
● The lsp command (if unsure use "%INSTALL_DIR%\\pypls.exe" for my pypls LSP. That maps to "C:\Users\<username>\AppData\Local\CodeWizard\pypls.exe")
● And the build command for the language (ex: 'cd /d %FILE_LOCATION% && python %FILE_NAME%' to navigate to the current file directory, and run it with python)
In these settings, the following are available as variables in your build commands: %FILE_LOCATION%, %FILE_NAME%, %FILE_NAME_NO_EXT%, and %INSTALL_DIR%
):"),
},{
icu::UnicodeString::fromUTF8("KeyMaps"),
icu::UnicodeString::fromUTF8(R":(General:
● Ctrl+Shift+O ----- Open Folder
● Ctrl+O ----------- Open File
● Ctrl+S ----------- Save (CodeWizard saves automatically every 4 seconds)
● Ctrl+Shift+P ----- Bring focus to the command palette
● Ctrl+Shift+U ----- Bring focus to the command palette, and begins a project search (any command palette search starting with '&')
● Ctrl+W ----------- Close the current file
● Ctrl+N ----------- New empty file
● Ctrl+< ----------- Jump to corresponding opening bracket
● Ctrl+> ----------- Jump to corresponding closing bracket
● Tab -------------- When selecting text, indent one tab
● Shift+Tab -------- When selecting text, unindent one tab
● Ctrl+] ----------- When selecting text, indent one tab
● Ctrl+[ ----------- When selecting text, unindent one tab
● Alt+3 ------------ Comment selected region
● Alt+4 ------------ Uncomment selected region
● Ctrl+/ ----------- Toggle comment on selected region
● F5 --------------- Run code (see 'Using CodeWizard')
● Ctrl+F ----------- Open the find/replace menu
● Ctrl+Shift+Tab --- Next file tab
Macro Recording:
● F12 -------------- To start a macro recording
● F12 -------------- Again to finish recording
● F11 -------------- To replay the macro
CodeWizard also has an optional modal experience which is designed to help you code faster. Enable it in the settings. Essentially every text edit will then have two modes, insert, and normal. While in insert you can type normally. When in normal mode you can execute commands to move around the text faster.
From Within Insert Mode:
● All normal commands
● Esc -------------- To exit insert mode, and enter normal mode
From Within Normal Mode:
● All normal commands
● 'i' -------------- To re-enter insert mode and exit normal mode
● 'n' -------------- To re-enter insert mode and exit normal mode, but one character to the right
● 'h' -------------- Move left one char
● 'l' -------------- Move right one char
● 'j' -------------- Move down one line
● 'k' -------------- Move up one line
● 'a' -------------- Move to the end of the line
● 'o' -------------- Create a new line below the current line
● 'w' -------------- Move back one word (same as ctrl+[left arrow])
● 'e' -------------- Move forward one word (same as ctrl+[right arrow])
● 'b' -------------- Also move back one word
● 's' -------------- Select the word under the cursor.
● Shift+'s' -------- Extend the selection with the word under the cursor
● '>' -------------- Jump to corresponding closing bracket
● '<' -------------- Jump to corresponding opening bracket
● 'f' -------------- Open the find/replace menu
● 'c' -------------- Copy text in selection
● 'v' -------------- Paste at cursor position
● 'x' -------------- Cut text in selection
● 'r' -------------- Rename variable under cursor (only works with supported LSPs currently pypls does not support this)
Note that for most movement shortcuts ('h', 'j', 'k', 'l', '<', '>', 'a', 'w', 'e', 'b') you can also hold shift to extend the selected cursor text.
Hold alt while clicking or pressing an arrow (or one of hjkl keys) to add another cursor. When you're done with them press esc.):"),
},{
icu::UnicodeString::fromUTF8("AI"),
icu::UnicodeString::fromUTF8(R":( CodeWizard has support for AI. Specifically, after setting an AI provider, model, and key in the settings, press Alt+A to trigger an insertion at your current cursor position. Or you can then open an AI chat widget to chat with your chosen model in a window.
For the settings you must get a provider (openrouter or lmstudio for example), a key for the provider (if required), the number of lines to send to the model for completions. If you choose 'Load AI Model On Start' it will send a request to your provider on startup (ONLY DO THIS IF YOU'RE RUNNING AN OFFLINE MODEL). The non-chat completions are not supported by most providers, but lmstudio supports them.):"),
},{
icu::UnicodeString::fromUTF8("Math/Graph Windows"),
icu::UnicodeString::fromUTF8(R":(Math Window:
● The math window allows for multi step equasions. Variables are accepted as so: `x = 12` or `test = 12` and so on.
● The _ variable is reserved for the previous line's value. For instance:
```
3*4 # 12
_+1 # returns 13
```
● Exponents use the ^ symbol, like: `5*10^4` or `5.2^-3`, etc.
● Bedmas order is followed.
Graphing Window:
● The graphing window allows you to view data on an xy plane. By providing the x and y values like this: `x1, x2, x3`, `y1, y2, y3`, you can view data in either a scatter or line graph.
● Furthermore, the data can be averaged with a simple moving average, but only the line graphs will be affected.
● Next, you can both type in values directly, or load them from a file (or load all files in a folder). We support these formats:
● Y only, one line:
```
y1, y2, y3, y4
```
● Y only, multi line:
```
y1
y2
y3
y4
```
● X and Y, two lines
```
x1, x2, x3, x4
y1, y2, y3, y4
```
● X and Y, multi line:
```
x1, y1
x2, y2
x3, y3
x4, y4
```
):"),
}
};
for (int i = 0; i < helpInformation.size(); i++) {
auto ti = TabInfo();
ti.id = i;
ti.title = helpInformation[i][0];
tb->addTab(ti);
scrolled_to.push_back(0.0);
}
tb->selected_id = 0;
label = new Label(this);
label->setFullText(icu::UnicodeString::fromUTF8("Widgets"));
label->POSITIONER = [&](Widget* l) {
l->t_x = t_x;
l->t_y = tb->t_h+tb->t_y - scrolled_to[tb->selected_id];
l->t_w = t_w;
l->t_h = label->should_be_h;
};
label->border = false;
setToIndex(0);
}
void HelpMenu::setToIndex(int index) {
label->setFullText(helpInformation[index][1]);
}
void HelpMenu::render() {
App::DrawRect(t_x, t_y+closebutton->t_h-App::text_padding, t_w, App::text_padding, App::theme.main_background_color); // this fixes the corners on the bottom to be flat. In a kinda dumb way, but it will work. Probably
App::DrawRoundedRect(t_x, t_y, t_w, closebutton->t_h, App::text_padding, App::theme.main_background_color);
App::DrawRoundedRect(t_x, t_y+closebutton->t_h, t_w, t_h-closebutton->t_h, App::text_padding, App::theme.darker_background_color);
int vert_padding = (closebutton->t_h-TextRenderer::get_text_height())/2;
TextRenderer::draw_text(t_x+vert_padding, t_y+vert_padding, icu::UnicodeString::fromUTF8("CodeWizard2 Help Menu"), App::theme.main_text_color);
closebutton->render();
App::runWithSKIZ(tb->t_x, tb->t_y, tb->t_w, tb->t_h, [&](){
tb->render();
});
App::runWithSKIZ(t_x, tb->t_y+tb->t_h, t_w, t_h-tb->t_h-closebutton->t_h, [&](){
label->render();
});
App::DrawRect(t_x, tb->t_y+tb->t_h, t_w, 1, App::theme.border);
App::DrawRoundBorder(t_x, t_y, t_w, t_h, App::theme.active_color, 5, App::text_padding);
}
void HelpMenu::position(int x, int y, int w, int h) {
t_x = x+w*.1;
t_y = y+h*.1;
t_w = w*.8;
t_h = h*.8;
Widget::position(t_x, t_y, t_w, t_h);
on_scroll_event(0, 0);
}
bool HelpMenu::on_key_event(int key, int scancode, int action, int mods) {
Widget::on_key_event(key, scancode, action, mods);
return true;
}
bool HelpMenu::on_char_event(unsigned int codepoint) {
Widget::on_char_event(codepoint);
return true;
}
bool HelpMenu::on_mouse_button_event(int button, int action, int mods) {
int my = App::mouseY;
if (my <= App::tb->t_h) {
return false;
}
if (action == GLFW_PRESS && !cursor_in_this) {
App::RemoveWidgetFromParent(this);
App::reclear = 2;
return true;
}
Widget::on_mouse_button_event(button, action, mods);
return true;
}
bool HelpMenu::on_mouse_move_event() {
int my = App::mouseY;
if (my <= App::tb->t_h) {
return false;
}
Widget::on_mouse_move_event();
return true;
}
bool HelpMenu::on_scroll_event(double xchange, double ychange) {
if (tb->on_scroll_event(xchange, ychange) || !cursor_in_this) { return true; }
scrolled_to[tb->selected_id] += ychange*6.0*(double)TextRenderer::get_text_height();
int maxScroll = std::max(0, label->t_h-((t_h+t_y)-(tb->t_h+tb->t_y)));
if (scrolled_to[tb->selected_id] < 0) {
scrolled_to[tb->selected_id] = 0;
}else if (scrolled_to[tb->selected_id] > maxScroll) {
scrolled_to[tb->selected_id] = maxScroll;
}
return true;
}