diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml
index 0a5a9b0..c8db854 100644
--- a/android-project/app/src/main/AndroidManifest.xml
+++ b/android-project/app/src/main/AndroidManifest.xml
@@ -28,6 +28,7 @@
android:name="android.hardware.type.pc"
android:required="false" />
+
diff --git a/include/Helpers/StringHelpers.cpp b/include/Helpers/StringHelpers.cpp
index b99114e..882141b 100644
--- a/include/Helpers/StringHelpers.cpp
+++ b/include/Helpers/StringHelpers.cpp
@@ -2,9 +2,7 @@
#include
#include
#include
-#include
-#include
-#include
+#include
#include
#include
@@ -162,3 +160,14 @@ std::string sdl_time_to_nice_access_time(const SDL_DateTime& t, SDL_DateFormat d
}
return "";
}
+
+std::vector glob_path_as_string_list(const std::filesystem::path& folder, const char* globStr, SDL_GlobFlags globFlags, const std::function& pathToStr) {
+ int globCount;
+ char** filesInPath = SDL_GlobDirectory(folder.c_str(), globStr, globFlags, &globCount);
+ if(!filesInPath)
+ throw std::runtime_error("[glob_path_as_string_list] SDL_GlobDirectory failed");
+ std::vector toRet(globCount);
+ for(int i = 0; i < globCount; i++)
+ toRet[i] = pathToStr(std::filesystem::path(filesInPath[i]));
+ return toRet;
+}
diff --git a/include/Helpers/StringHelpers.hpp b/include/Helpers/StringHelpers.hpp
index b0552c6..2813894 100644
--- a/include/Helpers/StringHelpers.hpp
+++ b/include/Helpers/StringHelpers.hpp
@@ -1,8 +1,10 @@
#pragma once
+#include
#include
#include
#include
#include
+#include
#include
std::vector split_string_by_token(std::string str, std::string token);
@@ -15,3 +17,4 @@ bool is_valid_http_url(const std::string& str);
std::string remove_carriage_returns_from_str(std::string s);
std::string ensure_string_unique(const std::vector& stringList, std::string str);
std::string sdl_time_to_nice_access_time(const SDL_DateTime& t, SDL_DateFormat dF, SDL_TimeFormat tF);
+std::vector glob_path_as_string_list(const std::filesystem::path& folder, const char* globStr, SDL_GlobFlags globFlags, const std::function& pathToStr);
diff --git a/src/CustomEvents.hpp b/src/CustomEvents.hpp
index 2f2d45a..1a24d2a 100644
--- a/src/CustomEvents.hpp
+++ b/src/CustomEvents.hpp
@@ -48,6 +48,7 @@ namespace CustomEvents {
struct OpenInfiniPaintFileEvent {
static uint32_t EVENT_NUM;
bool isClient;
+ std::optional filePathEmptyAutoSaveDir;
std::optional filePathSource;
std::string netSource;
std::string serverLocalID;
diff --git a/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp b/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp
index 8c91d8e..f8bb43b 100644
--- a/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp
+++ b/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp
@@ -194,22 +194,22 @@ void window_gap_side_bar(GUIManager& gui, const char* id, const WindowFillSideBa
switch(dir) {
case WindowFillSideBarConfig::Direction::TOP:
CLAY_AUTO_ID({
- .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(gui.io.safeWindowRect.min.y())}}
+ .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(gui.io.safeWindowRect.min.y())}}
}) {}
break;
case WindowFillSideBarConfig::Direction::BOTTOM:
CLAY_AUTO_ID({
- .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(gui.io.windowSize.y() - gui.io.safeWindowRect.max.y())}}
+ .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(gui.io.windowSize.y() - gui.io.safeWindowRect.max.y())}}
}) {}
break;
case WindowFillSideBarConfig::Direction::LEFT:
CLAY_AUTO_ID({
- .layout = {.sizing = {.width = CLAY_SIZING_FIXED(gui.io.safeWindowRect.min.x()), .height = CLAY_SIZING_GROW(0)}}
+ .layout = {.sizing = {.width = CLAY_SIZING_FIT(gui.io.safeWindowRect.min.x()), .height = CLAY_SIZING_GROW(0)}}
}) {}
break;
case WindowFillSideBarConfig::Direction::RIGHT:
CLAY_AUTO_ID({
- .layout = {.sizing = {.width = CLAY_SIZING_FIXED(gui.io.windowSize.x() - gui.io.safeWindowRect.max.x()), .height = CLAY_SIZING_GROW(0)}}
+ .layout = {.sizing = {.width = CLAY_SIZING_FIT(gui.io.windowSize.x() - gui.io.safeWindowRect.max.x()), .height = CLAY_SIZING_GROW(0)}}
}) {}
break;
}
diff --git a/src/Screens/FileSelectScreen.cpp b/src/Screens/FileSelectScreen.cpp
index 37c037f..eef1f54 100644
--- a/src/Screens/FileSelectScreen.cpp
+++ b/src/Screens/FileSelectScreen.cpp
@@ -28,6 +28,9 @@ FileSelectScreen::FileSelectScreen(MainProgram& m): Screen(m) {
trashPath = main.conf.configPath / "trash";
trashInfoPath = main.conf.configPath / "trashInfo.json";
+ SDL_CreateDirectory(savePath.string().c_str());
+ SDL_CreateDirectory(trashPath.string().c_str());
+
try {
nlohmann::json j(nlohmann::json::parse(read_file_to_string(trashInfoPath)));
j.get_to(trashInfo);
@@ -60,7 +63,7 @@ void FileSelectScreen::update_file_list(std::vector& fL, const std::fi
for(int i = 0; i < globCount; i++) {
std::filesystem::path p = filesInPath[i];
std::string fExt = p.extension().string();
- if(fExt == "." + World::FILE_EXTENSION) {
+ if(fExt == World::DOT_FILE_EXTENSION) {
std::filesystem::path fullPath = savePath / filesInPath[i];
FileInfo fileInfoToAdd;
fileInfoToAdd.fileName = p.stem().string();
@@ -134,60 +137,52 @@ void FileSelectScreen::main_display() {
.layoutDirection = CLAY_TOP_TO_BOTTOM,
},
}) {
+ if(editMode) {
+ numberOfSelectedEntries = std::count_if(fileList.begin(), fileList.end(), [] (const FileInfo& f) { return f.selected; });
+ if(numberOfSelectedEntries == 0)
+ actionBarOpenAnim->animation_trigger_reverse();
+ else
+ actionBarOpenAnim->animation_trigger();
+ edit_title_bar();
+ }
+ else {
+ actionBarOpenAnim->animation_trigger_reverse();
+ title_bar();
+ }
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
- .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP },
- .layoutDirection = CLAY_TOP_TO_BOTTOM,
+ .layoutDirection = CLAY_LEFT_TO_RIGHT
},
}) {
- if(editMode) {
- numberOfSelectedEntries = std::count_if(fileList.begin(), fileList.end(), [] (const FileInfo& f) { return f.selected; });
- if(numberOfSelectedEntries == 0)
- actionBarOpenAnim->animation_trigger_reverse();
- else
- actionBarOpenAnim->animation_trigger();
- edit_title_bar();
- }
- else {
- actionBarOpenAnim->animation_trigger_reverse();
- title_bar();
- }
+ window_gap_side_bar(gui, "main display left fill", WindowFillSideBarConfig::Direction::LEFT);
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
- .layoutDirection = CLAY_LEFT_TO_RIGHT
+ .padding = CLAY_PADDING_ALL(gui.io.theme->padding1),
+ .childGap = gui.io.theme->childGap1,
+ .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP },
+ .layoutDirection = CLAY_TOP_TO_BOTTOM,
},
}) {
- window_gap_side_bar(gui, "main display left fill", WindowFillSideBarConfig::Direction::LEFT);
- CLAY_AUTO_ID({
- .layout = {
- .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
- .padding = CLAY_PADDING_ALL(gui.io.theme->padding1),
- .childGap = gui.io.theme->childGap1,
- .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP },
- .layoutDirection = CLAY_TOP_TO_BOTTOM,
- },
- }) {
- switch(selectedMenu) {
- case SelectedMenu::FILES:
- file_view();
- if(!editMode)
- create_file_button();
- break;
- case SelectedMenu::TRASH:
- file_view();
- break;
- case SelectedMenu::SETTINGS:
- break;
- }
+ switch(selectedMenu) {
+ case SelectedMenu::FILES:
+ file_view();
+ if(!editMode)
+ create_file_button();
+ break;
+ case SelectedMenu::TRASH:
+ file_view();
+ break;
+ case SelectedMenu::SETTINGS:
+ break;
}
- window_gap_side_bar(gui, "main display right fill", WindowFillSideBarConfig::Direction::RIGHT);
}
- window_gap_side_bar(gui, "main display bottom fill", WindowFillSideBarConfig::Direction::BOTTOM);
- menu_black_box();
+ window_gap_side_bar(gui, "main display right fill", WindowFillSideBarConfig::Direction::RIGHT);
}
+ window_gap_side_bar(gui, "main display bottom fill", WindowFillSideBarConfig::Direction::BOTTOM);
edit_action_bar();
+ menu_black_box();
}
}
}
@@ -211,7 +206,8 @@ void FileSelectScreen::create_file_button() {
svg_icon_button(gui, "add button", "data/icons/plus.svg", {
.onClick = [&] {
main.create_new_tab({
- .isClient = false
+ .isClient = false,
+ .filePathEmptyAutoSaveDir = savePath
});
main.screen = std::make_unique(main);
}
@@ -254,24 +250,18 @@ void FileSelectScreen::move_selected_files(const std::filesystem::path& fromPath
SDL_GetCurrentTime(¤tTime);
std::vector toFolderListNames;
-
- int globCount;
- char** filesInPath = SDL_GlobDirectory(toPath.c_str(), "*", 0, &globCount);
- if(filesInPath) {
- for(int i = 0; i < globCount; i++) {
- std::filesystem::path p(filesInPath[i]);
- toFolderListNames.emplace_back(p.filename().stem());
- }
- }
- else
+ try {
+ toFolderListNames = glob_path_as_string_list(toPath, "*", 0, [&](const auto& p){ return p.stem().string();});
+ } catch(...) {
SDL_CreateDirectory(toPath.string().c_str());
+ }
for(const FileInfo& f : fileList) {
if(f.selected) {
std::string newFileName = ensure_string_unique(toFolderListNames, f.fileName);
- std::filesystem::path filePath = fromPath / (f.fileName + "." + World::FILE_EXTENSION);
+ std::filesystem::path filePath = fromPath / (f.fileName + World::DOT_FILE_EXTENSION);
std::filesystem::path thumbnailPath = fromPath / (f.fileName + ".jpg");
- std::filesystem::path newFilePath = toPath / (newFileName + "." + World::FILE_EXTENSION);
+ std::filesystem::path newFilePath = toPath / (newFileName + World::DOT_FILE_EXTENSION);
std::filesystem::path newThumbnailPath = toPath / (newFileName + ".jpg");
SDL_RenamePath(filePath.string().c_str(), newFilePath.string().c_str());
SDL_RenamePath(thumbnailPath.string().c_str(), newThumbnailPath.string().c_str());
@@ -293,24 +283,18 @@ void FileSelectScreen::move_selected_files(const std::filesystem::path& fromPath
void FileSelectScreen::duplicate_selected_files(const std::filesystem::path& inPath) {
std::vector toFolderListNames;
-
- int globCount;
- char** filesInPath = SDL_GlobDirectory(inPath.c_str(), "*", 0, &globCount);
- if(filesInPath) {
- for(int i = 0; i < globCount; i++) {
- std::filesystem::path p(filesInPath[i]);
- toFolderListNames.emplace_back(p.filename().stem());
- }
- }
- else
+ try {
+ toFolderListNames = glob_path_as_string_list(inPath, "*", 0, [&](const auto& p){ return p.stem().string();});
+ } catch(...) {
SDL_CreateDirectory(inPath.string().c_str());
+ }
for(const FileInfo& f : fileList) {
if(f.selected) {
std::string newFileName = ensure_string_unique(toFolderListNames, f.fileName);
std::filesystem::path filePath = inPath / (f.fileName + World::DOT_FILE_EXTENSION);
std::filesystem::path thumbnailPath = inPath / (f.fileName + ".jpg");
- std::filesystem::path newFilePath = inPath / (newFileName + "." + World::FILE_EXTENSION);
+ std::filesystem::path newFilePath = inPath / (newFileName + World::DOT_FILE_EXTENSION);
std::filesystem::path newThumbnailPath = inPath / (newFileName + ".jpg");
SDL_CopyFile(filePath.string().c_str(), newFilePath.string().c_str());
SDL_CopyFile(thumbnailPath.string().c_str(), newThumbnailPath.string().c_str());
@@ -333,43 +317,67 @@ void FileSelectScreen::delete_selected_files_in_trash() {
void FileSelectScreen::edit_action_bar() {
auto& gui = main.g.gui;
if(actionBarOpenAnim->get_val()) {
- gui.element("edit action bar", [&](LayoutElement*, const Clay_ElementId& lId) {
- CLAY(lId, {
- .layout = {
- .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50 * actionBarOpenAnim->get_val())},
- .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
- .layoutDirection = CLAY_LEFT_TO_RIGHT,
+ gui.set_z_index(gui.get_z_index() + 3, [&] {
+ CLAY_AUTO_ID({
+ .layout = {
+ .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
+ .layoutDirection = CLAY_TOP_TO_BOTTOM
+ },
+ .floating = {
+ .zIndex = gui.get_z_index(),
+ .attachPoints = {
+ .element = CLAY_ATTACH_POINT_LEFT_TOP,
+ .parent = CLAY_ATTACH_POINT_LEFT_TOP,
},
- .backgroundColor = convert_vec4(gui.io.theme->backColor1),
- }) {
- if(actionBarOpenAnim->is_at_end()) {
- if(selectedMenu == SelectedMenu::FILES) {
- edit_action_bar_button("trash", "data/icons/trash.svg", "Trash", [&] {
- move_selected_files(savePath, trashPath, TrashMoveType::MOVE_TO_TRASH);
- update_file_list(fileList, savePath, false);
- editMode = false;
- });
- edit_action_bar_button("duplicate", "data/icons/RemixIcon/file-copy-line.svg", "Duplicate", [&] {
- duplicate_selected_files(savePath);
- update_file_list(fileList, savePath, false);
- editMode = false;
- });
- }
- else if(selectedMenu == SelectedMenu::TRASH) {
- edit_action_bar_button("restore", "data/icons/RemixIcon/refresh-line.svg", "Restore", [&] {
- move_selected_files(trashPath, savePath, TrashMoveType::MOVE_OUT_OF_TRASH);
- update_file_list(fileList, trashPath, true);
- editMode = false;
- });
- edit_action_bar_button("delete", "data/icons/trash.svg", "Delete", [&] {
- delete_selected_files_in_trash();
- update_file_list(fileList, trashPath, true);
- editMode = false;
- });
- }
- }
+ .attachTo = CLAY_ATTACH_TO_PARENT,
}
- });
+ }) {
+ CLAY_AUTO_ID({
+ .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
+ }) {}
+ window_fill_side_bar(gui, "edit action bar bottom fill", {
+ .dir = WindowFillSideBarConfig::Direction::BOTTOM,
+ .backgroundColor = gui.io.theme->backColor1
+ }, [&] {
+ gui.element("edit action bar", [&](LayoutElement*, const Clay_ElementId& lId) {
+ CLAY(lId, {
+ .layout = {
+ .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50 * actionBarOpenAnim->get_val())},
+ .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER },
+ .layoutDirection = CLAY_LEFT_TO_RIGHT,
+ }
+ }) {
+ if(actionBarOpenAnim->is_at_end()) {
+ if(selectedMenu == SelectedMenu::FILES) {
+ edit_action_bar_button("trash", "data/icons/trash.svg", "Trash", [&] {
+ move_selected_files(savePath, trashPath, TrashMoveType::MOVE_TO_TRASH);
+ update_file_list(fileList, savePath, false);
+ editMode = false;
+ });
+ edit_action_bar_button("duplicate", "data/icons/RemixIcon/file-copy-line.svg", "Duplicate", [&] {
+ duplicate_selected_files(savePath);
+ update_file_list(fileList, savePath, false);
+ editMode = false;
+ });
+ }
+ else if(selectedMenu == SelectedMenu::TRASH) {
+ edit_action_bar_button("restore", "data/icons/RemixIcon/refresh-line.svg", "Restore", [&] {
+ move_selected_files(trashPath, savePath, TrashMoveType::MOVE_OUT_OF_TRASH);
+ update_file_list(fileList, trashPath, true);
+ editMode = false;
+ });
+ edit_action_bar_button("delete", "data/icons/trash.svg", "Delete", [&] {
+ delete_selected_files_in_trash();
+ update_file_list(fileList, trashPath, true);
+ editMode = false;
+ });
+ }
+ }
+ }
+ });
+ });
+ }
+ });
}
}
@@ -560,7 +568,7 @@ void FileSelectScreen::file_view() {
std::filesystem::path folderPath = (selectedMenu == SelectedMenu::TRASH) ? trashPath : savePath;
auto fileButton = [&] (size_t i, bool isList, const Vector2f& iconSize) {
- std::filesystem::path filePath = folderPath / (fileList[i].fileName + "." + World::FILE_EXTENSION);
+ std::filesystem::path filePath = folderPath / (fileList[i].fileName + World::DOT_FILE_EXTENSION);
gui.element("file button", SelectableButton::Data{
.isSelected = editMode && fileList[i].selected,
.onClick = [&, filePath, i] {
@@ -653,7 +661,7 @@ void FileSelectScreen::file_view() {
.entryHeight = 150.0f,
.entryCount = fileList.size(),
.clipHorizontal = true,
- .xElementSize = CLAY_SIZING_FIT(0),
+ .xElementSize = CLAY_SIZING_GROW(0),
.elementContent = [&](size_t i) {
fileButton(i, true, Vector2f{100.0f, 100.0f});
}
diff --git a/src/Screens/PhoneDrawingProgramScreen.cpp b/src/Screens/PhoneDrawingProgramScreen.cpp
index 659e50b..ae699cd 100644
--- a/src/Screens/PhoneDrawingProgramScreen.cpp
+++ b/src/Screens/PhoneDrawingProgramScreen.cpp
@@ -5,6 +5,7 @@
#include "../GUIStuff/Elements/LayoutElement.hpp"
#include "../GUIStuff/ElementHelpers/ButtonHelpers.hpp"
#include "../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
+#include "../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "FileSelectScreen.hpp"
using namespace GUIStuff;
@@ -55,10 +56,12 @@ void PhoneDrawingProgramScreen::top_toolbar() {
svg_icon_button(gui, "back exit button", "data/icons/RemixIcon/arrow-left-s-line.svg", {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.onClick = [&] {
+ main.world->save_to_file(main.world->filePath);
main.set_tab_to_close(main.world.get());
main.screen = std::make_unique(main);
}
});
+ text_label(gui, main.world->name);
}
});
}
diff --git a/src/World.cpp b/src/World.cpp
index 0d567f3..3dcfb10 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -63,11 +63,11 @@ World::World(MainProgram& initMain, const CustomEvents::OpenInfiniPaintFileEvent
init_client(worldInfo.netSource);
else {
init_client_data_list();
+ set_name(name);
if(worldInfo.filePathSource.has_value())
load_from_file(worldInfo.filePathSource.value(), worldInfo.fileDataBuffer);
else
- load_empty_canvas();
- set_name(name);
+ load_empty_canvas(worldInfo.filePathEmptyAutoSaveDir);
#ifdef ENABLE_ORDERED_LIST_TEST
listDebugTest = netObjMan.make_obj>();
#endif
@@ -432,9 +432,10 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s
void World::autosave_to_directory(const std::filesystem::path& directoryToSaveAt) {
std::vector strList;
- for(auto& entry : std::filesystem::directory_iterator(directoryToSaveAt)) {
- if(entry.path().has_stem() && entry.path().has_extension() && entry.path().extension() == ("." + FILE_EXTENSION))
- strList.emplace_back(entry.path().stem().string());
+ try {
+ strList = glob_path_as_string_list(directoryToSaveAt, ("*" + World::DOT_FILE_EXTENSION).c_str(), 0, [&](const auto& p){ return p.stem().string();});
+ }
+ catch(...) {
}
std::string nameToSaveUnder = ensure_string_unique(strList, name);
save_to_file(directoryToSaveAt / std::filesystem::path(nameToSaveUnder + "." + FILE_EXTENSION));
@@ -482,11 +483,14 @@ void World::save_to_file(const std::filesystem::path& filePathToSaveAt) {
}
}
-void World::load_empty_canvas() {
+void World::load_empty_canvas(const std::optional& filePathEmptyAutoSaveDir) {
gridMan.server_init_no_file();
bMan.server_init_no_file();
drawProg.server_init_no_file();
canvasTheme.server_init_no_file();
+
+ if(filePathEmptyAutoSaveDir.has_value())
+ autosave_to_directory(filePathEmptyAutoSaveDir.value());
}
void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std::string_view buffer) {
diff --git a/src/World.hpp b/src/World.hpp
index 6301e6a..732d5a2 100644
--- a/src/World.hpp
+++ b/src/World.hpp
@@ -110,7 +110,7 @@ class World {
bool hasUnsavedLocalChanges = false;
- void load_empty_canvas();
+ void load_empty_canvas(const std::optional& filePathEmptyAutoSaveDir = std::nullopt);
Vector3f get_random_cursor_color();
void init_client_data_list();