25 #include <imgui-filebrowser/imfilebrowser.h>
32 std::vector<jevois::EditorItem> && fixeditems, std::string
const & scanpath,
33 std::string
const & prefix, std::set<std::string> && extensions) :
34 TextEditor(), itsHelper(helper), itsId(imguiid), itsItems(fixeditems), itsNumFixedItems(fixeditems.size()),
35 itsScanPath(scanpath), itsPrefix(prefix), itsExtensions(extensions),
36 itsBrowser(new
ImGui::FileBrowser(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir))
38 TextEditor::SetSaveCallback([
this]() {
saveFile(); itsWantAction =
true; } );
40 itsBrowser->SetTitle(
"Select a file to open or create...");
41 itsBrowser->SetPwd(JEVOIS_SHARE_PATH);
53 itsItems.resize(itsNumFixedItems);
56 for (
auto const & dent : std::filesystem::recursive_directory_iterator(itsScanPath))
58 if (dent.is_regular_file())
60 std::filesystem::path
const path = dent.path();
63 if (itsExtensions.find(path.extension()) == itsExtensions.end())
continue;
65 std::string
const filepath = path.string();
69 EditorSaveAction::Reload });
74 itsItems.emplace_back(
EditorItem {
"**",
"Browse / Create file...", EditorSaveAction::Reload });
77 auto m = itsHelper->engine()->module();
78 int i = 0;
bool not_found =
true;
80 for (
auto const & item : itsItems)
82 (m && m->absolutePath(item.filename) == itsFilename))
97 itsOverrideReloadModule = IsEdited();
105 char const * items[itsItems.size()];
106 for (
int i = 0;
EditorItem const & c : itsItems) items[i++] = c.displayname.c_str();
109 if (ImGui::Combo((
"##"+itsId+
"editorcombo").c_str(), &itsNewItem, items, itsItems.size())) itsWantLoad =
true;
112 if (itsWantLoad && itsWantAction ==
false)
116 static int discard_edits_default = 0;
117 int ret = itsHelper->modal(
"Discard edits?",
"File was edited. Discard all edits? This cannot be undone.",
118 &discard_edits_default,
"Discard",
"Save");
121 case 1: itsWantAction =
false; itsOkToLoad =
true;
break;
122 case 2: saveFile(); itsWantAction =
true;
break;
136 switch (itsCurrentAction)
138 case jevois::EditorSaveAction::None:
139 itsWantAction =
false;
142 case jevois::EditorSaveAction::Reload:
146 if (itsOverrideReloadModule)
148 itsOverrideReloadModule =
false;
149 itsWantAction =
false;
150 itsOkToLoad = itsWantLoad;
155 static int reload_default = 0;
156 int ret = itsHelper->modal(
"Reload Module?",
"Reload Machine Vision Module for changes to take effect?",
157 &reload_default,
"Reload",
"Later");
161 itsHelper->engine()->requestSetFormat(-1);
162 itsWantAction =
false;
163 itsOkToLoad = itsWantLoad;
167 itsWantAction =
false;
168 itsOkToLoad = itsWantLoad;
176 case jevois::EditorSaveAction::Reboot:
178 int ret = itsHelper->modal(
"Restart?",
"Restart JeVois-Pro for changes to take effect?",
179 nullptr,
"Restart",
"Later");
183 itsHelper->engine()->reboot();
184 itsWantAction =
false;
188 itsWantAction =
false;
196 case jevois::EditorSaveAction::RefreshMappings:
198 itsHelper->engine()->reloadVideoMappings();
199 itsWantAction =
false;
209 if (itsItems[itsNewItem].filename ==
"**")
211 ImGui::PushStyleColor(ImGuiCol_PopupBg, 0xf0ffe0e0);
213 if (itsBrowser->IsOpened() ==
false) itsBrowser->Open();
214 itsBrowser->Display();
215 if (itsBrowser->HasSelected())
217 std::filesystem::path
const fn = itsBrowser->GetSelected();
219 if (std::filesystem::exists(fn))
220 loadFile(fn,
"Could not load " + fn.string());
224 itsBrowser->ClearSelected();
227 itsItems.emplace_back(
EditorItem { fn,
"File " + fn.string(), EditorSaveAction::Reload });
231 itsCurrentItem = itsItems.size() - 1;
232 itsCurrentAction = itsItems[itsCurrentItem].action;
233 itsNewItem = itsCurrentItem;
237 if (itsBrowser->IsOpened() ==
false)
240 itsNewItem = itsCurrentItem;
243 ImGui::PopStyleColor();
249 itsCurrentItem = itsNewItem;
250 itsCurrentAction = itsItems[itsCurrentItem].action;
253 if (itsItems[itsCurrentItem].filename ==
"*")
256 jevois::VideoMapping
const & vm = itsHelper->engine()->getCurrentVideoMapping();
257 loadFile(vm.srcpath(),
"Could not open Module's source code");
259 else if (items[itsCurrentItem][0] !=
'/')
262 auto m = itsHelper->engine()->module();
263 if (m) loadFile(m->absolutePath(itsItems[itsCurrentItem].filename),
"");
264 else loadFile(itsItems[itsCurrentItem].filename,
"");
266 else loadFile(itsItems[itsCurrentItem].filename,
"");
271 bool const ro = IsReadOnly();
273 if (ImGui::Button(
"...")) ImGui::OpenPopup(
"editor_actions");
274 if (ImGui::BeginPopup(
"editor_actions"))
276 constexpr
int ok = ImGuiSelectableFlags_None;
277 constexpr
int disa = ImGuiSelectableFlags_Disabled;
279 if (ImGui::Selectable(
"Save [Ctrl-S]",
false, !ro && IsEdited() ? ok : disa))
280 { saveFile(); itsWantAction =
true; }
284 if (ImGui::Selectable(
"Undo [Ctrl-Z]",
false, !ro && CanUndo() ? ok : disa)) Undo();
285 if (ImGui::Selectable(
"Redo [Ctrl-Y]",
false, !ro && CanRedo() ? ok : disa)) Redo();
289 if (ImGui::Selectable(
"Copy [Ctrl-C]",
false, HasSelection() ? ok : disa)) Copy();
290 if (ImGui::Selectable(
"Cut [Ctrl-X]",
false, !ro && HasSelection() ? ok : disa)) Cut();
291 if (ImGui::Selectable(
"Delete [Del]",
false, !ro && HasSelection() ? ok : disa)) Delete();
292 if (ImGui::Selectable(
"Paste [Ctrl-V]",
false, !ro && ImGui::GetClipboardText()!=
nullptr ? ok : disa)) Paste();
296 ImGui::Selectable(
"More shortcuts...",
false, disa);
297 if (ImGui::IsItemHovered())
298 ImGui::SetTooltip(
"[Ctrl-A] Select all\n"
299 "[PgUp/PgDn] Move one page up/down\n"
300 "[Home] Move to start of line\n"
301 "[End] Move to end of line\n"
302 "[Ctrl-Home] Move to start of file\n"
303 "[Ctrl-End] Move to end of file\n"
304 "[Ctrl-Left/Right] Move left/right one word\n"
305 "[Ins] Toggle overwrite mode\n"
306 "[Alt-Bksp] Undo (same as [Ctrl-Z])\n"
307 "[Ctrl-Ins] Copy (same as [Ctrl-C])\n"
308 "[Shift-Ins] Paste (same as [Ctrl-V])\n"
309 "[Shift-Del] Cut (same as [Ctrl-X])\n"
310 "[Shift-Cursor] Select while moving cursor (up, down, left, right, home, end)\n"
311 "[Mouse-Drag] Select with mouse\n"
321 ImGui::TextUnformatted(
" "); ImGui::SameLine();
322 if (ImGui::Button(
"Save")) { saveFile(); itsWantAction =
true; }
328 auto cpos = GetCursorPosition();
330 ImGui::Text(
"%6d/%-6d %6d lines | %s | %s | %s", cpos.mLine + 1, cpos.mColumn + 1, GetTotalLines(),
331 IsOverwrite() ?
"Ovr" :
"Ins",
332 IsEdited() ?
"*" :
" ",
333 GetLanguageDefinition().mName.c_str());
335 Render(
"JeVois-Pro Editor");
341 LINFO(
"Loading " << fn <<
" ...");
347 std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
351 std::filesystem::path
const ext = fn.extension();
354 { SetLanguageDefinition(TextEditor::LanguageDefinition::Python()); SetReadOnly(
false); }
355 else if (ext ==
".C" || ext ==
".H" || ext ==
".cpp" || ext ==
".hpp")
356 { SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus()); SetReadOnly(
true); }
357 else if ( ext ==
".c" || ext ==
".h")
358 { SetLanguageDefinition(TextEditor::LanguageDefinition::C()); SetReadOnly(
true); }
360 { SetLanguageDefinition(TextEditor::LanguageDefinition::JeVoisCfg()); SetReadOnly(
false); }
366 if (failtxt.empty()) {
LINFO(
"File " << fn <<
" not found -- CREATING NEW"); SetReadOnly(
false); }
367 else {
LINFO(
"File " << fn <<
" not found."); SetReadOnly(
true); }
377 LINFO(
"Saving " << itsFilename <<
" ...");
378 std::ofstream os(itsFilename);
379 if (os.is_open() ==
false) { itsHelper->reportError(
"Cannot write " + itsFilename.string());
return; }
381 std::string
const txt = GetText();