Added more menus to phone version

This commit is contained in:
Yousef Khadadeh 2026-05-13 14:31:35 +03:00
parent 1b99c64c1b
commit 4774f1ee94
22 changed files with 633 additions and 306 deletions

View file

@ -75,7 +75,7 @@ void BookmarkManager::setup_list_gui() {
if(bookmarkListRoot) {
auto& gui = world.main.g.gui;
if(bookmarkListRoot->get_folder_list()->empty())
text_label_centered(gui, "No bookmarks yet...");
text_label_centered(gui, "No bookmarks exist.");
else {
gui.element<TreeListing>("bookmark list", TreeListing::Data {
.selectedIndices = &selectedBookmarkIndices,
@ -110,7 +110,7 @@ void BookmarkManager::setup_list_gui() {
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
},
}) {
text_label(gui, bookmark->get_name());
ellipse_wide_paragraph_label(gui, "bookmark name", bookmark->get_name());
}
if(!bookmark->is_folder()) {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
@ -375,7 +375,7 @@ void BookmarkManager::setup_list_gui() {
auto editingBookmarkLock = editingBookmark.lock();
if(editingBookmarkLock) {
text_label_centered(gui, editingBookmarkLock->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
text_label_centered(gui, editingBookmarkLock->is_folder() ? "Edit Folder" : "Edit Bookmark");
input_text_field(gui, "input edit name", "Name", &nameToEdit, {
.onEdit = [&] {
auto editingBookmarkLock = editingBookmark.lock();

View file

@ -758,7 +758,7 @@ CanvasComponentContainer::ObjInfo* DrawingProgram::add_file_to_canvas_by_data(co
}
float DrawingProgram::drag_point_radius() {
return 8.0f * world.main.g.final_gui_scale();
return (world.main.g.gui.io.isTouchDevice ? 10.0f : 8.0f) * world.main.g.final_gui_scale();
}
void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, const SkColor4f& c, const DrawData& drawData, float radiusMultiplier) {

View file

@ -122,7 +122,7 @@ void DrawingProgramLayerManagerGUI::setup_list_gui() {
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
},
}) {
text_label(gui, layer->get_name());
ellipse_wide_paragraph_label(gui, "layer name", layer->get_name());
}
if(!layer->is_folder()) {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
@ -411,7 +411,7 @@ void DrawingProgramLayerManagerGUI::setup_list_gui() {
auto editingLayerLock = editingLayer.lock();
if(editingLayerLock) {
text_label_centered(gui, editingLayerLock->is_folder() ? "Edit Layer Folder" : "Edit Layer");
text_label_centered(gui, editingLayerLock->is_folder() ? "Edit Folder" : "Edit Layer");
input_text_field(gui, "input edit name", "Name", &nameToEdit, {
.onEdit = [&] {
auto editingLayerLock = editingLayer.lock();

View file

@ -45,6 +45,7 @@ void GridModifyTool::set_grid(const NetObjWeakPtr<WorldGrid>& newGrid) {
oldGrid = g;
CoordSpaceHelper newCam;
newCam.inverseScale = g.size / WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
newCam.inverseScale = newCam.inverseScale.divide_double(drawP.world.main.g.final_gui_scale());
newCam.pos = g.offset - drawP.world.main.window.size.cast<WorldScalar>() * newCam.inverseScale * WorldScalar(0.5);
newCam.rotation = 0.0;
drawP.world.drawData.cam.smooth_move_to(drawP.world, newCam, drawP.world.main.window.size.cast<float>());
@ -219,7 +220,8 @@ void GridModifyTool::gui_phone_toolbox(PhoneDrawingProgramScreen& t) {
else
g.bounds = std::nullopt;
});
checkbox_boolean_field(gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates);
// Very hard to not have a rotated canvas on phone
//checkbox_boolean_field(gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates);
}
});
}

View file

@ -18,6 +18,8 @@
#include "TextLabelHelpers.hpp"
#include "../Elements/MutableTextLabel.hpp"
#include "../Elements/TextParagraph.hpp"
#include "../Elements/LayoutElement.hpp"
#include "Helpers/ConvertVec.hpp"
namespace GUIStuff { namespace ElementHelpers {
@ -65,4 +67,28 @@ void mutable_text_label(GUIManager& gui, const char* id, const std::string& val)
gui.element<MutableTextLabel>(id, val, textConfig);
}
void mutable_text_label_light(GUIManager& gui, const char* id, const std::string& val) {
Clay_TextElementConfig textConfig = CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor2), .fontSize = gui.io.fontSize });
gui.element<MutableTextLabel>(id, val, textConfig);
}
void ellipse_wide_paragraph_label(GUIManager& gui, const char* id, const std::string& val) {
gui.element<LayoutElement>(id, [&](LayoutElement* l, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)}}
}) {
if(l->get_bb().has_value()) {
RichText::TextData t;
t.paragraphs.emplace_back();
t.paragraphs.back().text = val;
gui.element<TextParagraph>("p", TextParagraph::Data{
.text = t,
.maxGrowX = l->get_bb().value().width(),
.ellipsis = true
});
}
}
});
}
}}

View file

@ -29,5 +29,8 @@ void text_label_light_centered(GUIManager& gui, std::string_view val);
void text_label_centered(GUIManager& gui, std::string_view val);
void mutable_text_label(GUIManager& gui, const char* id, const std::string& val);
void mutable_text_label_light(GUIManager& gui, const char* id, const std::string& val);
void ellipse_wide_paragraph_label(GUIManager& gui, const char* id, const std::string& val);
}}

View file

@ -31,9 +31,10 @@ void CheckBox::layout(const Clay_ElementId& id, const std::function<bool()>& isT
this->isTicked = isTicked;
this->onClick = onClick;
float size = gui.io.isTouchDevice ? 25 : 15;
CLAY(id, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(15), .height = CLAY_SIZING_FIXED(15)}
.sizing = {.width = CLAY_SIZING_FIXED(size), .height = CLAY_SIZING_FIXED(size)}
},
.custom = { .customData = this }
}) {}

View file

@ -43,9 +43,10 @@ template <typename T> class NumberSlider : public Element {
dd.maxData = maxData;
this->config = config;
float height = gui.io.isTouchDevice ? 25 : 10;
CLAY(id, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(100), .height = CLAY_SIZING_FIXED(10)}
.sizing = {.width = CLAY_SIZING_GROW(100), .height = CLAY_SIZING_FIXED(height)}
},
.custom = { .customData = this }
}) {

View file

@ -29,9 +29,10 @@ void RadioButton::layout(const Clay_ElementId& id, const std::function<bool()>&
this->onClick = onClick;
this->isTicked = isTicked;
float size = gui.io.isTouchDevice ? 25 : 20;
CLAY(id, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)}
.sizing = {.width = CLAY_SIZING_FIXED(size), .height = CLAY_SIZING_FIXED(size)}
},
.custom = { .customData = this }
}) {}

View file

@ -574,7 +574,7 @@ void GUIManager::layout_if_necessary() {
}
void GUIManager::layout() {
constexpr int LAYOUT_RUN_COUNT = 6;
constexpr int LAYOUT_RUN_COUNT = 8;
for(int i = 0; i < LAYOUT_RUN_COUNT; i++)
single_layout_run();
}

View file

@ -22,12 +22,13 @@
#include "ResourceDisplay/ImageResourceDisplay.hpp"
#include "DrawingProgram/DrawingProgramCache.hpp"
#include <SDL3/SDL_time.h>
#include <fstream>
GlobalConfig::GlobalConfig() {
load_default_palette();
displayName = Random::get().alphanumeric_str(10);
SDL_GetDateTimeLocalePreferences(&dateFormat, &timeFormat);
if(dateFormat == SDL_DATE_FORMAT_YYYYMMDD) // Can't display this in a friendly way, so changing it for now
dateFormat = SDL_DATE_FORMAT_DDMMYYYY;
}
nlohmann::json GlobalConfig::get_config_json(const InputManager& input) const {
@ -151,14 +152,12 @@ void GlobalConfig::set_config_json(InputManager& input, const nlohmann::json& j,
}
void GlobalConfig::save_palettes() {
using json = nlohmann::json;
json j;
nlohmann::json j;
auto palettesToSave = palettes;
palettesToSave.erase(palettesToSave.begin());
nlohmann::to_json(j, palettesToSave);
std::stringstream f;
f << j;
SDL_SaveFile((configPath / "palettes.json").string().c_str(), f.view().data(), f.view().size());
std::string saveJson = nlohmann::to_string(j);
SDL_SaveFile((configPath / "palettes.json").string().c_str(), saveJson.c_str(), saveJson.size());
}
void GlobalConfig::load_palettes() {
@ -166,9 +165,9 @@ void GlobalConfig::load_palettes() {
using json = nlohmann::json;
try {
json j(nlohmann::json::parse(read_file_to_string(configPath / "palettes.json")));
std::vector<Palette> palettes;
j.get_to(palettes);
palettes.insert(palettes.end(), palettes.begin(), palettes.end());
std::vector<Palette> p;
j.get_to(p);
palettes.insert(palettes.end(), p.begin(), p.end());
} catch(...) {}
}

View file

@ -20,6 +20,15 @@
#include "World.hpp"
#include "MainProgram.hpp"
#include "WorldUndoManager.hpp"
#include "GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "GUIStuff/ElementHelpers/LayoutHelpers.hpp"
#include "GUIStuff/ElementHelpers/ButtonHelpers.hpp"
#include "GUIStuff/ElementHelpers/TextBoxHelpers.hpp"
#include "GUIStuff/Elements/ManyElementScrollArea.hpp"
#include "GUIStuff/Elements/LayoutElement.hpp"
#include "GUIStuff/Elements/SelectableButton.hpp"
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
#include "WorldGrid.hpp"
#include <cereal/types/unordered_map.hpp>
GridManager::GridManager(World& w):
@ -254,3 +263,99 @@ void GridManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber
grids->emplace_back_direct(grids, wGrid);
}
}
void GridManager::setup_list_gui(const std::function<void()>& onStartModify) {
auto& gui = world.main.g.gui;
auto& main = world.main;
using namespace GUIStuff;
using namespace ElementHelpers;
auto add_grid = [&, onStartModify] {
if(!gridMenu.newName.empty()) {
main.world->gridMan.add_default_grid(gridMenu.newName);
main.world->drawProg.modify_grid(main.world->gridMan.grids->at(main.world->gridMan.grids->size() - 1)->obj);
if(onStartModify) onStartModify();
}
};
float ENTRY_HEIGHT = 25.0f;
if(main.world->gridMan.grids->empty())
text_label_centered(gui, "No grids exist.");
gui.element<ManyElementScrollArea>("grid menu entries", ManyElementScrollArea::Options{
.entryHeight = ENTRY_HEIGHT,
.entryCount = main.world->gridMan.grids->size(),
.clipHorizontal = true,
.elementContent = [&, onStartModify](size_t i) {
auto& grid = main.world->gridMan.grids->at(i)->obj;
bool selectedEntry = gridMenu.selectedGrid == i;
gui.element<LayoutElement>("elem", [&, onStartModify] (LayoutElement*, const Clay_ElementId& lId2) {
CLAY(lId2, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)},
.childGap = 2,
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT
},
.backgroundColor = selectedEntry ? convert_vec4<Clay_Color>(gui.io.theme->backColor1) : convert_vec4<Clay_Color>(gui.io.theme->backColor2)
}) {
text_label(gui, grid->get_display_name());
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.childGap = 1,
.childAlignment = {.x = CLAY_ALIGN_X_RIGHT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT
}
}) {
auto list_button = [&](const char* id, const char* svgPath, const std::function<void()>& onClick) {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
svg_icon_button(gui, id, svgPath, {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.size = ENTRY_HEIGHT,
.onClick = onClick
});
});
};
list_button("visibility eye", grid->visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", [&] {
grid->visible = !grid->visible;
NetworkingObjects::generic_serialized_class_send_update_to_all<WorldGrid>(grid);
});
list_button("edit pencil", "data/icons/pencil.svg", [&, onStartModify] {
main.world->drawProg.modify_grid(grid);
if(onStartModify) onStartModify();
});
list_button("delete trash", "data/icons/trash.svg", [&, i] {
main.world->gridMan.remove_grid(i);
});
}
}
}, LayoutElement::Callbacks {
.onClick = [&, i, onStartModify] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) {
if(l->mouseHovering && button.down && button.button == InputManager::MouseButton::LEFT) {
gridMenu.selectedGrid = i;
if(button.clicks == 2) {
main.world->drawProg.modify_grid(grid);
if(onStartModify) onStartModify();
}
gui.set_to_layout();
}
}
});
}
});
left_to_right_line_layout(gui, [&]() {
input_text(gui, "grid text input", &gridMenu.newName, {
.onEnter = [add_grid]() { add_grid(); }
});
svg_icon_button(gui, "grid add button", "data/icons/plusbold.svg", {
.size = SMALL_BUTTON_SIZE,
.onClick = [add_grid] { add_grid(); }
});
});
}
void GridManager::refresh_gui_data() {
gridMenu.newName.clear();
gridMenu.selectedGrid = std::numeric_limits<uint32_t>::max();
}

View file

@ -56,6 +56,13 @@ class GridManager {
void save_file(cereal::PortableBinaryOutputArchive& a) const;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
void finalize_grid_modify(const NetworkingObjects::NetObjTemporaryPtr<WorldGrid>& wGrid, const WorldGrid& oldGridData);
void refresh_gui_data();
void setup_list_gui(const std::function<void()>& onStartModify);
struct GridMenuGUIData {
std::string newName;
uint32_t selectedGrid = std::numeric_limits<uint32_t>::max();
} gridMenu;
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<WorldGrid>> grids;
World& world;

View file

@ -127,6 +127,7 @@ void MainProgram::save_config() {
std::stringstream f;
f << std::setw(4) << j;
SDL_SaveFile((conf.configPath / "config.json").string().c_str(), f.view().data(), f.view().size());
conf.save_palettes();
}
@ -290,6 +291,7 @@ void MainProgram::post_callback() {
void MainProgram::input_app_about_to_go_to_background_callback() {
screen->input_app_about_to_go_to_background_callback();
save_config();
post_callback();
}

View file

@ -31,12 +31,12 @@
#include "../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
#include "../GUIStuff/ElementHelpers/ColorPickerHelpers.hpp"
#include "../GUIStuff/ElementHelpers/CheckBoxHelpers.hpp"
#include "../GUIStuff/Elements/PositionAdjustingPopupMenu.hpp"
#include "../World.hpp"
#include "Helpers/StringHelpers.hpp"
#include "PhoneDrawingProgramScreen.hpp"
#include <SDL3/SDL_time.h>
#include <SDL3/SDL_timer.h>
#include <algorithm>
#define MAIN_MENU_SIZE 300
@ -44,16 +44,17 @@ using namespace GUIStuff;
using namespace ElementHelpers;
FileSelectScreen::FileSelectScreen(MainProgram& m): Screen(m) {
main.g.gui.io.isTouchDevice = true;
savePath = main.conf.configPath / "saves";
trashPath = main.conf.configPath / "trash";
trashInfoPath = main.conf.configPath / "trashInfo.json";
infoPath = main.conf.configPath / "fileSelectInfo.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);
nlohmann::json j(nlohmann::json::parse(read_file_to_string(infoPath)));
j.get_to(saveInfo);
}
catch(...) {}
@ -88,9 +89,9 @@ void FileSelectScreen::update_file_list(std::vector<FileInfo>& fL, const std::fi
fileInfoToAdd.fileName = p.stem().string();
if(trashUpdate) {
auto it = trashInfo.files.find(fileInfoToAdd.fileName);
if(it == trashInfo.files.end()) {
trashInfo.files[fileInfoToAdd.fileName].trashTime = currentTime;
auto it = saveInfo.trash.files.find(fileInfoToAdd.fileName);
if(it == saveInfo.trash.files.end()) {
saveInfo.trash.files[fileInfoToAdd.fileName].trashTime = currentTime;
fileInfoToAdd.lastModifyTime = currentTime;
}
else
@ -102,7 +103,7 @@ void FileSelectScreen::update_file_list(std::vector<FileInfo>& fL, const std::fi
// Remove file and thumbnail
SDL_RemovePath(fullPath.string().c_str());
SDL_RemovePath((savePath / fileInfoToAdd.fileName / ".jpg").string().c_str());
trashInfo.files.erase(it);
saveInfo.trash.files.erase(it);
continue;
}
else if(daysSinceMovedToTrash == 29)
@ -129,6 +130,33 @@ void FileSelectScreen::update_file_list(std::vector<FileInfo>& fL, const std::fi
}
else
SDL_CreateDirectory(savePath.string().c_str());
sort_file_list(fL);
}
void FileSelectScreen::sort_file_list(std::vector<FileInfo>& fL) {
switch(saveInfo.fileSort) {
case SaveInfo::FileSort::ALPHABETICAL_ASCENDING:
std::stable_sort(fL.begin(), fL.end(), [&](const FileInfo& a, const FileInfo& b) {
return std::lexicographical_compare(a.fileName.begin(), a.fileName.end(), b.fileName.begin(), b.fileName.end());
});
break;
case SaveInfo::FileSort::ALPHABETICAL_DESCENDING:
std::stable_sort(fL.begin(), fL.end(), [&](const FileInfo& a, const FileInfo& b) {
return std::lexicographical_compare(b.fileName.begin(), b.fileName.end(), a.fileName.begin(), a.fileName.end());
});
break;
case SaveInfo::FileSort::TIME_ASCENDING:
std::stable_sort(fL.begin(), fL.end(), [&](const FileInfo& a, const FileInfo& b) {
return b.lastModifyTime < a.lastModifyTime;
});
break;
case SaveInfo::FileSort::TIME_DESCENDING:
std::stable_sort(fL.begin(), fL.end(), [&](const FileInfo& a, const FileInfo& b) {
return a.lastModifyTime < b.lastModifyTime;
});
break;
}
}
void FileSelectScreen::main_display() {
@ -289,12 +317,12 @@ void FileSelectScreen::move_selected_files(const std::filesystem::path& fromPath
case TrashMoveType::NONE:
break;
case TrashMoveType::MOVE_TO_TRASH:
trashInfo.files[newFileName] = TrashInfo::TrashFile{
saveInfo.trash.files[newFileName] = TrashInfo::TrashFile{
.trashTime = currentTime
};
break;
case TrashMoveType::MOVE_OUT_OF_TRASH:
trashInfo.files.erase(f.fileName);
saveInfo.trash.files.erase(f.fileName);
break;
}
}
@ -330,7 +358,7 @@ void FileSelectScreen::delete_selected_files_in_trash() {
std::filesystem::path thumbnailPath = trashPath / (f.fileName + ".jpg");
SDL_RemovePath(filePath.string().c_str());
SDL_RemovePath(thumbnailPath.string().c_str());
trashInfo.files.erase(f.fileName);
saveInfo.trash.files.erase(f.fileName);
}
}
}
@ -338,71 +366,71 @@ void FileSelectScreen::delete_selected_files_in_trash() {
void FileSelectScreen::edit_action_bar() {
auto& gui = main.g.gui;
if(actionBarOpenAnim->get_val()) {
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,
},
.attachTo = CLAY_ATTACH_TO_PARENT,
}
}) {
gui.set_z_index(gui.get_z_index() + 3, [&] {
CLAY_AUTO_ID({
.layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
}) {}
gui.element<LayoutElement>("edit action bar bottom fill", [&](LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {}) {
window_fill_side_bar(gui, {
.dir = WindowFillSideBarConfig::Direction::BOTTOM,
.backgroundColor = gui.io.theme->backColor1
}, [&] {
gui.element<LayoutElement>("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;
});
}
}
}
});
});
.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,
},
.attachTo = CLAY_ATTACH_TO_PARENT,
}
});
}
});
}) {
CLAY_AUTO_ID({
.layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}},
}) {}
gui.element<LayoutElement>("edit action bar bottom fill", [&](LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {}) {
window_fill_side_bar(gui, {
.dir = WindowFillSideBarConfig::Direction::BOTTOM,
.backgroundColor = gui.io.theme->backColor1
}, [&] {
gui.element<LayoutElement>("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;
});
}
}
}
});
});
}
});
}
});
}
}
@ -484,10 +512,19 @@ void FileSelectScreen::title_bar() {
});
if(moreButton->get_bb().has_value() && moreOptionsMenu != MoreOptionsMenu::CLOSED) {
size_t elemCount = 0;
if(moreOptionsMenu == MoreOptionsMenu::MAIN)
elemCount = 2;
else if(moreOptionsMenu == MoreOptionsMenu::VIEW)
elemCount = 4;
switch(moreOptionsMenu) {
case MoreOptionsMenu::CLOSED:
break;
case MoreOptionsMenu::MAIN:
elemCount = 3;
break;
case MoreOptionsMenu::VIEW:
elemCount = 4;
break;
case MoreOptionsMenu::SORT:
elemCount = 4;
break;
}
gui.set_z_index(gui.get_z_index() + 10, [&] {
dropdown_many_element_popup_layout(gui, "more options popup", {
.button = moreButton,
@ -500,53 +537,98 @@ void FileSelectScreen::title_bar() {
.entrySize = {200.0f, 30.0f},
.entryCount = elemCount,
.entryLayout = [&] (size_t i) {
if(moreOptionsMenu == MoreOptionsMenu::MAIN) {
switch(i) {
case 0: {
text_transparent_option_button("Edit", "Edit", [&] {
moreOptionsMenu = MoreOptionsMenu::CLOSED;
start_edit_mode();
});
break;
}
case 1: {
text_transparent_option_button("View", "View", [&] {
moreOptionsMenu = MoreOptionsMenu::VIEW;
});
break;
switch(moreOptionsMenu) {
case MoreOptionsMenu::CLOSED:
break;
case MoreOptionsMenu::MAIN: {
switch(i) {
case 0: {
text_transparent_option_button("Edit", "Edit", [&] {
moreOptionsMenu = MoreOptionsMenu::CLOSED;
start_edit_mode();
});
break;
}
case 1: {
text_transparent_option_button("View", "View", [&] {
moreOptionsMenu = MoreOptionsMenu::VIEW;
});
break;
}
case 2: {
text_transparent_option_button("Sort", "Sort", [&] {
moreOptionsMenu = MoreOptionsMenu::SORT;
});
break;
}
}
break;
}
}
else if(moreOptionsMenu == MoreOptionsMenu::VIEW) {
switch(i) {
case 0: {
text_transparent_option_button("Large Grid", "Large Grid", [&] {
fileViewType = FileViewType::LARGE_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
case MoreOptionsMenu::VIEW: {
switch(i) {
case 0: {
text_transparent_option_button("Large Grid", "Large Grid", [&] {
saveInfo.fileViewType = SaveInfo::FileViewType::LARGE_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
case 1: {
text_transparent_option_button("Medium Grid", "Medium Grid", [&] {
saveInfo.fileViewType = SaveInfo::FileViewType::MEDIUM_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
case 2: {
text_transparent_option_button("Small Grid", "Small Grid", [&] {
saveInfo.fileViewType = SaveInfo::FileViewType::SMALL_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
case 3: {
text_transparent_option_button("List", "List", [&] {
saveInfo.fileViewType = SaveInfo::FileViewType::LIST;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
}
case 1: {
text_transparent_option_button("Medium Grid", "Medium Grid", [&] {
fileViewType = FileViewType::MEDIUM_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
case 2: {
text_transparent_option_button("Small Grid", "Small Grid", [&] {
fileViewType = FileViewType::SMALL_GRID;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
}
case 3: {
text_transparent_option_button("List", "List", [&] {
fileViewType = FileViewType::LIST;
moreOptionsMenu = MoreOptionsMenu::CLOSED;
});
break;
break;
}
case MoreOptionsMenu::SORT: {
switch(i) {
case 0: {
text_transparent_option_button("Alphabetical Ascending", "Alphabetical ↑", [&] {
saveInfo.fileSort = SaveInfo::FileSort::ALPHABETICAL_ASCENDING;
sort_file_list(fileList);
});
break;
}
case 1: {
text_transparent_option_button("Alphabetical Descending", "Alphabetical ↓", [&] {
saveInfo.fileSort = SaveInfo::FileSort::ALPHABETICAL_DESCENDING;
sort_file_list(fileList);
});
break;
}
case 2: {
text_transparent_option_button("Time Ascending", "Date modified ↑", [&] {
saveInfo.fileSort = SaveInfo::FileSort::TIME_ASCENDING;
sort_file_list(fileList);
});
break;
}
case 3: {
text_transparent_option_button("Time Descending", "Date modified ↓", [&] {
saveInfo.fileSort = SaveInfo::FileSort::TIME_DESCENDING;
sort_file_list(fileList);
});
break;
}
}
break;
}
}
}
@ -679,8 +761,8 @@ void FileSelectScreen::file_view() {
.layoutDirection = CLAY_TOP_TO_BOTTOM
}
}) {
text_label(gui, fileList[i].fileName);
text_label_light(gui, fileList[i].lastModifyDate);
mutable_text_label(gui, "file name label", fileList[i].fileName);
mutable_text_label_light(gui, "last modify date", fileList[i].lastModifyDate);
}
}
}
@ -720,14 +802,14 @@ void FileSelectScreen::file_view() {
}
}
});
text_label_light(gui, fileList[i].lastModifyDate);
mutable_text_label_light(gui, "last modify date", fileList[i].lastModifyDate);
}
}
}
});
};
if(fileViewType == FileViewType::LIST) {
if(saveInfo.fileViewType == SaveInfo::FileViewType::LIST) {
mainViewScrollArea = gui.element<ManyElementScrollArea>("File selector list", ManyElementScrollArea::Options{
.entryHeight = 150.0f,
.entryCount = fileList.size(),
@ -741,16 +823,16 @@ void FileSelectScreen::file_view() {
else {
Vector2f entrySize{0.0f, 0.0f};
Vector2f iconSize{0.0f, 0.0f};
switch(fileViewType) {
case FileViewType::LARGE_GRID:
switch(saveInfo.fileViewType) {
case SaveInfo::FileViewType::LARGE_GRID:
entrySize = {170.0f, 210.0f};
iconSize = {130.0f, 130.0f};
break;
case FileViewType::MEDIUM_GRID:
case SaveInfo::FileViewType::MEDIUM_GRID:
entrySize = {140.0f, 180.0f};
iconSize = {100.0f, 100.0f};
break;
case FileViewType::SMALL_GRID:
case SaveInfo::FileViewType::SMALL_GRID:
entrySize = {110.0f, 150.0f};
iconSize = {70.0f, 70.0f};
break;
@ -863,9 +945,9 @@ void FileSelectScreen::draw(SkCanvas* canvas) {
void FileSelectScreen::save_files() {
nlohmann::json j;
nlohmann::to_json(j, trashInfo);
nlohmann::to_json(j, saveInfo);
std::string saveJson = nlohmann::to_string(j);
SDL_SaveFile(trashInfoPath.string().c_str(), saveJson.c_str(), saveJson.size());
SDL_SaveFile(infoPath.string().c_str(), saveJson.c_str(), saveJson.size());
}
void FileSelectScreen::input_app_about_to_go_to_background_callback() {

View file

@ -39,12 +39,29 @@ class FileSelectScreen : public Screen {
std::unordered_map<std::string, TrashFile> files;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(TrashInfo, files)
};
~FileSelectScreen();
struct SaveInfo {
TrashInfo trash;
enum class FileSort {
ALPHABETICAL_ASCENDING,
ALPHABETICAL_DESCENDING,
TIME_ASCENDING,
TIME_DESCENDING
} fileSort = FileSort::ALPHABETICAL_ASCENDING;
enum class FileViewType {
LARGE_GRID,
MEDIUM_GRID,
SMALL_GRID,
LIST
} fileViewType = FileViewType::MEDIUM_GRID;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(SaveInfo, trash, fileSort, fileViewType)
} saveInfo;
~FileSelectScreen();
private:
std::filesystem::path savePath;
std::filesystem::path trashPath;
std::filesystem::path trashInfoPath;
std::filesystem::path infoPath;
void save_files();
@ -56,8 +73,8 @@ class FileSelectScreen : public Screen {
};
void update_file_list(std::vector<FileInfo>& fL, const std::filesystem::path& savePath, bool trashUpdate);
void sort_file_list(std::vector<FileInfo>& fL);
TrashInfo trashInfo;
std::vector<FileInfo> fileList;
GUIStuff::GUIFloatAnimation* mainMenuOpenAnim = nullptr;
@ -88,17 +105,11 @@ class FileSelectScreen : public Screen {
void duplicate_selected_files(const std::filesystem::path& inPath);
void delete_selected_files_in_trash();
enum class FileViewType {
LARGE_GRID,
MEDIUM_GRID,
SMALL_GRID,
LIST
} fileViewType = FileViewType::LARGE_GRID;
enum class MoreOptionsMenu {
CLOSED,
MAIN,
VIEW
VIEW,
SORT
} moreOptionsMenu = MoreOptionsMenu::CLOSED;
enum class SelectedMenu {
@ -111,3 +122,17 @@ class FileSelectScreen : public Screen {
size_t numberOfSelectedEntries;
bool editMode = false;
};
NLOHMANN_JSON_SERIALIZE_ENUM(FileSelectScreen::SaveInfo::FileSort, {
{FileSelectScreen::SaveInfo::FileSort::ALPHABETICAL_ASCENDING, "Alphabetical Ascending"},
{FileSelectScreen::SaveInfo::FileSort::ALPHABETICAL_DESCENDING, "Alphabetical Descending"},
{FileSelectScreen::SaveInfo::FileSort::TIME_ASCENDING, "Time Ascending"},
{FileSelectScreen::SaveInfo::FileSort::TIME_DESCENDING, "Time Descending"},
})
NLOHMANN_JSON_SERIALIZE_ENUM(FileSelectScreen::SaveInfo::FileViewType, {
{FileSelectScreen::SaveInfo::FileViewType::LARGE_GRID, "Large Grid"},
{FileSelectScreen::SaveInfo::FileViewType::MEDIUM_GRID, "Medium Grid"},
{FileSelectScreen::SaveInfo::FileViewType::SMALL_GRID, "Small Grid"},
{FileSelectScreen::SaveInfo::FileViewType::LIST, "List"},
})

View file

@ -42,6 +42,34 @@ void PhoneDrawingProgramScreen::update() {
DrawingProgramScreen::update();
}
void PhoneDrawingProgramScreen::center_message(const char* id, const std::string& m) {
auto& gui = main.g.gui;
auto& io = gui.io;
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.element<LayoutElement>(id, [&] (LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {
.zIndex = gui.get_z_index(),
.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER},
.attachTo = CLAY_ATTACH_TO_PARENT,
}
}) {
text_label(gui, m);
}
});
});
}
void PhoneDrawingProgramScreen::gui_layout_run() {
main_display();
}
@ -56,10 +84,105 @@ void PhoneDrawingProgramScreen::main_display() {
},
}) {
top_toolbar();
top_toolbar_settings_popup();
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
}) {}
bottom_toolbar();
if(!main.world->drawProg.layerMan.is_a_layer_being_edited())
center_message("Select layer to edit message", "Select a layer to edit");
}
}
void PhoneDrawingProgramScreen::top_toolbar_settings_popup() {
auto& gui = main.g.gui;
auto& io = gui.io;
switch(topToolbarSettingsPopup) {
case TopToolbarSettingsPopup::NONE:
break;
case TopToolbarSettingsPopup::HIDDEN_BUTTONS:
break;
case TopToolbarSettingsPopup::BOOKMARKS: {
gui.set_z_index(gui.get_z_index() + 20, [&] {
gui.element<LayoutElement>("bookmark menu", [&] (LayoutElement*, const Clay_ElementId& lId) {
Vector2f popupSize = {
std::clamp(gui.io.safeWindowRect.width() - 10.0f, 20.0f, 300.0f),
std::clamp(gui.io.safeWindowRect.height() - 40.0f, 50.0f, 600.0f)
};
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(popupSize.x()), .height = CLAY_SIZING_FIT(0, popupSize.y()) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Bookmarks");
main.world->bMan.setup_list_gui();
}
});
});
break;
}
case TopToolbarSettingsPopup::LAYERS: {
gui.set_z_index(gui.get_z_index() + 20, [&] {
gui.element<LayoutElement>("layer menu", [&] (LayoutElement*, const Clay_ElementId& lId) {
Vector2f popupSize = {
std::clamp(gui.io.safeWindowRect.width() - 10.0f, 20.0f, 300.0f),
std::clamp(gui.io.safeWindowRect.height() - 40.0f, 50.0f, 600.0f)
};
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(popupSize.x()), .height = CLAY_SIZING_FIT(0, popupSize.y()) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Layers");
main.world->drawProg.layerMan.listGUI.setup_list_gui();
}
});
});
break;
}
case TopToolbarSettingsPopup::GRIDS: {
gui.set_z_index(gui.get_z_index() + 20, [&] {
gui.element<LayoutElement>("grid menu", [&] (LayoutElement*, const Clay_ElementId& lId) {
Vector2f popupSize = {
std::clamp(gui.io.safeWindowRect.width() - 10.0f, 20.0f, 300.0f),
std::clamp(gui.io.safeWindowRect.height() - 40.0f, 50.0f, 600.0f)
};
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(popupSize.x()), .height = CLAY_SIZING_FIT(0, popupSize.y()) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Grids");
main.world->gridMan.setup_list_gui([&] {
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
settingsMenuPopup = SettingsMenuPopup::SETTINGS;
});
}
});
});
break;
}
}
}
@ -93,6 +216,7 @@ void PhoneDrawingProgramScreen::top_toolbar() {
}
});
top_toolbar_remaining_area();
top_toolbar_settings_popup();
}
});
}
@ -116,6 +240,30 @@ void PhoneDrawingProgramScreen::top_toolbar_remaining_area() {
main.world->redo_with_checks();
}
},
TopToolbarRemainingAreaButton{
.name = "Bookmarks",
.svgPath = "data/icons/bookmark.svg",
.isSelected = topToolbarSettingsPopup == TopToolbarSettingsPopup::BOOKMARKS,
.onClick = [&] {
topToolbarSettingsPopup = topToolbarSettingsPopup == TopToolbarSettingsPopup::BOOKMARKS ? TopToolbarSettingsPopup::NONE : TopToolbarSettingsPopup::BOOKMARKS;
}
},
TopToolbarRemainingAreaButton{
.name = "Layers",
.svgPath = "data/icons/layer.svg",
.isSelected = topToolbarSettingsPopup == TopToolbarSettingsPopup::LAYERS,
.onClick = [&] {
topToolbarSettingsPopup = topToolbarSettingsPopup == TopToolbarSettingsPopup::LAYERS ? TopToolbarSettingsPopup::NONE : TopToolbarSettingsPopup::LAYERS;
}
},
TopToolbarRemainingAreaButton{
.name = "Grids",
.svgPath = "data/icons/grid.svg",
.isSelected = topToolbarSettingsPopup == TopToolbarSettingsPopup::GRIDS,
.onClick = [&] {
topToolbarSettingsPopup = topToolbarSettingsPopup == TopToolbarSettingsPopup::GRIDS ? TopToolbarSettingsPopup::NONE : TopToolbarSettingsPopup::GRIDS;
}
},
};
gui.element<LayoutElement>("remaining area", [&](LayoutElement* l, const Clay_ElementId& lId) {
CLAY(lId, {
@ -152,6 +300,7 @@ void PhoneDrawingProgramScreen::top_toolbar_remaining_area() {
gui.new_id(i, [&] {
svg_icon_button(gui, "button", listOfTopToolbarButtons.front().svgPath, {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.isSelected = listOfTopToolbarButtons.front().isSelected,
.onClick = listOfTopToolbarButtons.front().onClick
});
listOfTopToolbarButtons.erase(listOfTopToolbarButtons.begin());
@ -161,10 +310,10 @@ void PhoneDrawingProgramScreen::top_toolbar_remaining_area() {
Element* e = svg_icon_button(gui, "Hidden buttons", "data/icons/RemixIcon/more-2-fill.svg", {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.onClick = [&] {
topToolbarButtonPopupOpen = !topToolbarButtonPopupOpen;
topToolbarSettingsPopup = topToolbarSettingsPopup == TopToolbarSettingsPopup::HIDDEN_BUTTONS ? TopToolbarSettingsPopup::NONE : TopToolbarSettingsPopup::HIDDEN_BUTTONS;
}
});
if(topToolbarButtonPopupOpen)
if(topToolbarSettingsPopup == TopToolbarSettingsPopup::HIDDEN_BUTTONS)
top_toolbar_hidden_button_popup(e, listOfTopToolbarButtons);
}
}
@ -202,10 +351,10 @@ void PhoneDrawingProgramScreen::top_toolbar_hidden_button_popup(GUIStuff::Elemen
}
});
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.set_z_index(gui.get_z_index() + 20, [&] {
dropdown_many_element_popup_layout(gui, "top toolbar hidden button popup", {
.button = b,
.clickAwayCallback = [&] { topToolbarButtonPopupOpen = false; },
.clickAwayCallback = [&] { topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE; },
.entrySize = {150.0f, 30.0f},
.entryCount = l.size(),
.entryLayout = [&] (size_t i) {
@ -213,8 +362,9 @@ void PhoneDrawingProgramScreen::top_toolbar_hidden_button_popup(GUIStuff::Elemen
gui.element<SelectableButton>("button", SelectableButton::Data{
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.onClick = [&, oC = listItem.onClick] {
if(topToolbarSettingsPopup == TopToolbarSettingsPopup::HIDDEN_BUTTONS)
topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
oC();
topToolbarButtonPopupOpen = false;
},
.innerContent = [&] (auto&) {
CLAY_AUTO_ID({

View file

@ -54,11 +54,11 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen {
void color_settings_popup(Vector4f* color, const ColorSelectorData& d, std::function<void()> backOnPaletteButton = nullptr, bool setAlphaToOne = false, bool setToTransparentCancelButton = false);
void reset_color_picker_popup_data();
private:
bool topToolbarButtonPopupOpen = false;
std::filesystem::path fileOldPath;
struct TopToolbarRemainingAreaButton {
std::string name;
std::string svgPath;
bool isSelected = false;
std::function<void()> onClick;
};
enum class SettingsMenuPopup {
@ -67,15 +67,25 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen {
COLOR_CHANGE
} settingsMenuPopup = SettingsMenuPopup::NONE;
enum class TopToolbarSettingsPopup {
NONE,
HIDDEN_BUTTONS,
BOOKMARKS,
LAYERS,
GRIDS
} topToolbarSettingsPopup = TopToolbarSettingsPopup::NONE;
Vector4f backgroundColorTemporary;
Vector4f* colorPickerPtr = nullptr;
ColorSelectorData colorPickerData;
void center_message(const char* id, const std::string& m);
void default_bottom_toolbar();
void bottom_toolbar_gui();
void bottom_extra_toolbar_gui();
void save_files();
void top_toolbar();
void top_toolbar_settings_popup();
void top_toolbar_remaining_area();
void top_toolbar_hidden_button_popup(GUIStuff::Element* b, std::vector<TopToolbarRemainingAreaButton> l);
void bottom_toolbar();

View file

@ -229,11 +229,11 @@ void Toolbar::layout_run() {
else if(optionsMenuOpen)
options_menu();
else if(main.world->clientStillConnecting)
still_connecting_center_message();
center_message("Connecting to server message", "Connecting to server...");
else if(playerMenuOpen)
player_list();
else if(!main.world->drawProg.layerMan.is_a_layer_being_edited())
no_layers_being_edited_message();
center_message("Select layer to edit message", "Select a layer to edit");
if(showPerformance)
performance_metrics();
@ -475,11 +475,11 @@ void Toolbar::top_toolbar() {
icon_button_top_toolbar("Menu Redo Button", "data/icons/redo.svg", false, [&] {
main.world->redo_with_checks();
});
Element* gridMenuButton = icon_button_top_toolbar("Grids Button", "data/icons/grid.svg", gridMenu.popupOpen, [&] {
if(gridMenu.popupOpen)
Element* gridMenuButton = icon_button_top_toolbar("Grids Button", "data/icons/grid.svg", gridMenuPopupOpen, [&] {
if(gridMenuPopupOpen)
stop_displaying_grid_menu();
else
gridMenu.popupOpen = true;
gridMenuPopupOpen = true;
});
Element* layerMenuButton = icon_button_top_toolbar("Layer Menu Button", "data/icons/layer.svg", layerMenuPopupOpen, [&] {
if(layerMenuPopupOpen)
@ -494,7 +494,7 @@ void Toolbar::top_toolbar() {
bookmarkMenuPopupOpen = true;
});
if(gridMenu.popupOpen)
if(gridMenuPopupOpen)
grid_menu(gridMenuButton);
if(bookmarkMenuPopupOpen)
bookmark_menu(bookmarkMenuButton);
@ -646,44 +646,32 @@ If you like this app, consider downloading the native version for your system)")
}
}
void Toolbar::still_connecting_center_message() {
void Toolbar::center_message(const char* id, const std::string& m) {
auto& gui = main.g.gui;
auto& io = gui.io;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label(gui, "Connecting to server...");
}
}
void Toolbar::no_layers_being_edited_message() {
auto& gui = main.g.gui;
auto& io = gui.io;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label(gui, "Select a layer to edit");
}
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.element<LayoutElement>(id, [&] (LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {
.zIndex = gui.get_z_index(),
.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER},
.attachTo = CLAY_ATTACH_TO_PARENT,
}
}) {
text_label(gui, m);
}
});
});
}
#ifndef __EMSCRIPTEN__
@ -783,80 +771,7 @@ void Toolbar::grid_menu(Element* gridMenuButton) {
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Grids");
float ENTRY_HEIGHT = 25.0f;
if(main.world->gridMan.grids->empty())
text_label_centered(gui, "No grids yet...");
gui.element<ManyElementScrollArea>("grid menu entries", ManyElementScrollArea::Options{
.entryHeight = ENTRY_HEIGHT,
.entryCount = main.world->gridMan.grids->size(),
.clipHorizontal = true,
.elementContent = [&](size_t i) {
auto& grid = main.world->gridMan.grids->at(i)->obj;
bool selectedEntry = gridMenu.selectedGrid == i;
gui.element<LayoutElement>("elem", [&] (LayoutElement*, const Clay_ElementId& lId2) {
CLAY(lId2, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)},
.childGap = 2,
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT
},
.backgroundColor = selectedEntry ? convert_vec4<Clay_Color>(io.theme->backColor1) : convert_vec4<Clay_Color>(io.theme->backColor2)
}) {
text_label(gui, grid->get_display_name());
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.childGap = 1,
.childAlignment = {.x = CLAY_ALIGN_X_RIGHT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT
}
}) {
auto list_button = [&](const char* id, const char* svgPath, const std::function<void()>& onClick) {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
svg_icon_button(gui, id, svgPath, {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.size = ENTRY_HEIGHT,
.onClick = onClick
});
});
};
list_button("visibility eye", grid->visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", [&] {
grid->visible = !grid->visible;
NetworkingObjects::generic_serialized_class_send_update_to_all<WorldGrid>(grid);
});
list_button("edit pencil", "data/icons/pencil.svg", [&] {
main.world->drawProg.modify_grid(grid);
stop_displaying_grid_menu();
});
list_button("delete trash", "data/icons/trash.svg", [&, i] {
main.world->gridMan.remove_grid(i);
});
}
}
}, LayoutElement::Callbacks {
.onClick = [&, i] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) {
if(l->mouseHovering && button.down && button.button == InputManager::MouseButton::LEFT) {
gridMenu.selectedGrid = i;
if(button.clicks == 2) {
main.world->drawProg.modify_grid(grid);
stop_displaying_grid_menu();
}
gui.set_to_layout();
}
}
});
}
});
left_to_right_line_layout(gui, [&]() {
input_text(gui, "grid text input", &gridMenu.newName, {
.onEnter = [&]() { add_grid(); }
});
svg_icon_button(gui, "grid add button", "data/icons/plusbold.svg", {
.size = SMALL_BUTTON_SIZE,
.onClick = [&] { add_grid(); }
});
});
main.world->gridMan.setup_list_gui([&]{stop_displaying_grid_menu();});
}
}, LayoutElement::Callbacks {
.onClick = [&, gridMenuButton] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) {
@ -868,18 +783,9 @@ void Toolbar::grid_menu(Element* gridMenuButton) {
}
}
void Toolbar::add_grid() {
if(!gridMenu.newName.empty()) {
main.world->gridMan.add_default_grid(gridMenu.newName);
main.world->drawProg.modify_grid(main.world->gridMan.grids->at(main.world->gridMan.grids->size() - 1)->obj);
stop_displaying_grid_menu();
}
}
void Toolbar::stop_displaying_grid_menu() {
gridMenu.newName.clear();
gridMenu.popupOpen = false;
gridMenu.selectedGrid = std::numeric_limits<uint32_t>::max();
gridMenuPopupOpen = false;
main.world->gridMan.refresh_gui_data();
main.g.gui.set_to_layout();
}

View file

@ -92,7 +92,6 @@ class Toolbar {
void global_log();
void top_toolbar();
void grid_menu(GUIStuff::Element* gridMenuButton);
void add_grid();
void stop_displaying_grid_menu();
void stop_displaying_bookmark_menu();
void stop_displaying_layer_menu();
@ -110,8 +109,7 @@ class Toolbar {
void load_default_theme();
void about_menu_inner_gui();
void web_version_welcome();
void still_connecting_center_message();
void no_layers_being_edited_message();
void center_message(const char* id, const std::string& m);
void close_popup_gui();
void add_world_to_close_popup_data(const std::shared_ptr<World>& w);
void general_settings_inner_gui();
@ -190,12 +188,7 @@ class Toolbar {
bool bookmarkMenuPopupOpen = false;
bool layerMenuPopupOpen = false;
struct GridMenu {
bool popupOpen = false;
std::string newName;
uint32_t selectedGrid = std::numeric_limits<uint32_t>::max();
} gridMenu;
bool gridMenuPopupOpen = false;
struct FilePicker {
bool isOpen = false;

View file

@ -536,8 +536,12 @@ void World::load_empty_canvas(const std::optional<std::filesystem::path>& filePa
drawProg.server_init_no_file();
canvasTheme.server_init_no_file();
if(filePathEmptyAutoSaveDir.has_value())
if(filePathEmptyAutoSaveDir.has_value()) {
bool oldSaveThumbnail = true;
saveThumbnail = false;
autosave_to_directory(filePathEmptyAutoSaveDir.value());
saveThumbnail = oldSaveThumbnail;
}
}
void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std::string_view buffer) {

View file

@ -622,8 +622,12 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
#endif
mS.m->update();
if(mS.m->setToQuit)
if(mS.m->setToQuit) {
#ifdef __ANDROID__
mS.m->input_app_about_to_go_to_background_callback();
#endif
return SDL_APP_SUCCESS;
}
if(mS.m->input.hideCursor) {
SDL_HideCursor();
@ -825,7 +829,13 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
}
#endif
return mS.m->setToQuit ? SDL_APP_SUCCESS : SDL_APP_CONTINUE;
if(mS.m->setToQuit) {
#ifdef __ANDROID__
mS.m->input_app_about_to_go_to_background_callback();
#endif
return SDL_APP_SUCCESS;
}
return SDL_APP_CONTINUE;
}
// NOTE: On Android, SDL_AppQuit is triggered by onDestroy. onDestroy may or may not be called, and even if it is, it may only be partially called. You should not rely on it.