implement file browser dialog
This commit is contained in:
@@ -258,14 +258,41 @@
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<!-- Browse Dialog Popup -->
|
||||
|
||||
<layout id="dialog-browse-item">
|
||||
<border dir="col" color=".4 .4 .4 .8" pad="4" height="120" width="100" margin="1 1 1 1" grow="1" align="center">
|
||||
<image-texture id="thumb-tex" width="100%" grow="1" height="1" aspect-ratio="1"/>
|
||||
<text id="title" text="File Name" margin="5 0 0 0" font-face="arial" font-size="11"/>
|
||||
</border>
|
||||
</layout>
|
||||
<layout id="dialog-browse">
|
||||
<border id="background" positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
|
||||
<border id="form" thickness="1" border-color=".2" pad="3" width="90%" height="90%" dir="col">
|
||||
<border id="title-bar" width="100%" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center">
|
||||
<text text="Browse PanoPainter Projects" font-face="arial" font-size="11"></text>
|
||||
</border>
|
||||
<border width="100%" height="100" color="0 0 0 .9" pad="10" dir="row" grow="1">
|
||||
<scroll id="files-list" dir="row" wrap="1" flood-events="1" grow="1" height="100%" margin="0 0 0 0" pad="0 20 0 0" color=".2 .2 .2 1">
|
||||
</scroll>
|
||||
</border>
|
||||
<node id="footer" height="40" dir="row" align="flex-end" justify="flex-end" pad="10">
|
||||
<node grow="1"><button id="btn-delete" text="Delete Project" width="100" height="30" margin="0 10 0 0" color="1 0 0 1"/></node>
|
||||
<button id="btn-ok" text="Open Project" width="100" height="30" margin="0 10 0 0"/>
|
||||
<button id="btn-cancel" text="Cancel" width="60" height="30" pad="10"/>
|
||||
</node>
|
||||
</border>
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<!-- Open Dialog Popup -->
|
||||
|
||||
<layout id="dialog-open-item">
|
||||
<border dir="row" color=".4 .4 .4 .8" pad="4" height="30" margin="1 0 1 0" align="center">
|
||||
<!--<image-texture id="thumb-tex" width="64" height="64"/>-->
|
||||
<text id="title" text="Title" font-face="arial" font-size="11"/>
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
<!-- Open Dialog Popup -->
|
||||
<layout id="dialog-open">
|
||||
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
|
||||
<border thickness="1" border-color=".2" pad="3">
|
||||
@@ -425,6 +452,10 @@
|
||||
<icon icon="page_add" width="20"/>
|
||||
<text text="Open" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-browse" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="page_add" width="20"/>
|
||||
<text text="Browse" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
</button-custom>
|
||||
<button-custom id="file-save" text="Menu" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
|
||||
<icon icon="disk" width="20"/>
|
||||
<text text="Save" margin="0 0 0 5" font-face="arial" font-size="11"/>
|
||||
@@ -605,7 +636,6 @@
|
||||
<text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
|
||||
</border>-->
|
||||
</node>
|
||||
<!--<ref id="settings"/>-->
|
||||
<!--<ref id="popup-menu"/>-->
|
||||
<!--<ref id="popup-dialog-open"/>-->
|
||||
</layout>
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
<ClCompile Include="engine\node_canvas.cpp" />
|
||||
<ClCompile Include="engine\node_checkbox.cpp" />
|
||||
<ClCompile Include="engine\node_color_quad.cpp" />
|
||||
<ClCompile Include="engine\node_dialog_browse.cpp" />
|
||||
<ClCompile Include="engine\node_dialog_layer_rename.cpp" />
|
||||
<ClCompile Include="engine\node_dialog_open.cpp" />
|
||||
<ClCompile Include="engine\node_icon.cpp" />
|
||||
@@ -301,6 +302,7 @@
|
||||
<ClInclude Include="engine\node_canvas.h" />
|
||||
<ClInclude Include="engine\node_checkbox.h" />
|
||||
<ClInclude Include="engine\node_color_quad.h" />
|
||||
<ClInclude Include="engine\node_dialog_browse.h" />
|
||||
<ClInclude Include="engine\node_dialog_layer_rename.h" />
|
||||
<ClInclude Include="engine\node_dialog_open.h" />
|
||||
<ClInclude Include="engine\node_icon.h" />
|
||||
|
||||
@@ -222,6 +222,9 @@
|
||||
<ClCompile Include="engine\node_progress_bar.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="engine\node_dialog_browse.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="engine\app.h">
|
||||
@@ -395,6 +398,9 @@
|
||||
<ClInclude Include="engine\node_progress_bar.h">
|
||||
<Filter>Header Files\ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="engine\node_dialog_browse.h">
|
||||
<Filter>Header Files\ui</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PanoPainter.rc">
|
||||
|
||||
@@ -231,8 +231,8 @@ void App::update(float dt)
|
||||
//glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
#ifndef __ANDROID__
|
||||
//layout.reload();
|
||||
#ifdef _WIN32
|
||||
layout.reload();
|
||||
#endif
|
||||
if (auto* main = layout[main_id])
|
||||
main->update(width, height, zoom);
|
||||
|
||||
@@ -123,6 +123,7 @@ public:
|
||||
void dialog_newdoc();
|
||||
void dialog_save();
|
||||
void dialog_open();
|
||||
void dialog_browse();
|
||||
void dialog_export();
|
||||
void dialog_layer_rename();
|
||||
void brush_update();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "app.h"
|
||||
#include "node_dialog_open.h"
|
||||
#include "node_dialog_browse.h"
|
||||
|
||||
void App::dialog_newdoc()
|
||||
{
|
||||
@@ -75,6 +76,37 @@ void App::dialog_open()
|
||||
}
|
||||
}
|
||||
|
||||
void App::dialog_browse()
|
||||
{
|
||||
if (canvas)
|
||||
{
|
||||
// load thumbnail test
|
||||
auto dialog = std::make_shared<NodeDialogBrowse>();
|
||||
dialog->m_manager = &layout;
|
||||
dialog->data_path = data_path;
|
||||
dialog->init();
|
||||
dialog->create();
|
||||
dialog->loaded();
|
||||
|
||||
layout[main_id]->add_child(dialog);
|
||||
layout[main_id]->update();
|
||||
|
||||
dialog->btn_ok->on_click = [this, dialog](Node*)
|
||||
{
|
||||
canvas->reset_camera();
|
||||
layers->clear();
|
||||
canvas->m_canvas->project_open(dialog->selected_path);
|
||||
doc_name = dialog->selected_name;
|
||||
if (auto docname = layout[main_id]->find<NodeText>("txt-docname"))
|
||||
docname->set_text(("Panodoc: " + doc_name).c_str());
|
||||
for (auto& i : canvas->m_canvas->m_order)
|
||||
layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str());
|
||||
dialog->destroy();
|
||||
ActionManager::clear();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void App::dialog_save()
|
||||
{
|
||||
if (canvas)
|
||||
|
||||
@@ -360,6 +360,11 @@ void App::init_menu_file()
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
popup->find<NodeButtonCustom>("file-browse")->on_click = [this](Node*) {
|
||||
dialog_browse();
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
popup->find<NodeButtonCustom>("file-save")->on_click = [this](Node*) {
|
||||
dialog_save();
|
||||
popup->mouse_release();
|
||||
|
||||
@@ -8,16 +8,17 @@
|
||||
|
||||
bool LayoutManager::load(const char* path)
|
||||
{
|
||||
if (m_loaded)
|
||||
return true; // already loaded
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
// struct stat tmp_info;
|
||||
// if (stat(path, &tmp_info) != 0)
|
||||
// return false;
|
||||
// if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
||||
// return false;
|
||||
// m_file_info = tmp_info;
|
||||
#if _WIN32
|
||||
struct stat tmp_info;
|
||||
if (stat(path, &tmp_info) != 0)
|
||||
return false;
|
||||
if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
||||
return false;
|
||||
m_file_info = tmp_info;
|
||||
#else
|
||||
if (m_loaded)
|
||||
return true; // already loaded
|
||||
#endif // __ANDROID__
|
||||
|
||||
m_path = path;
|
||||
|
||||
@@ -349,6 +349,7 @@ int main(int argc, char** argv)
|
||||
bool running = true;
|
||||
unsigned long t0 = GetTickCount();
|
||||
unsigned long t1;
|
||||
float one_sec = 0;
|
||||
while (running)
|
||||
{
|
||||
// If there any message in the queue process it
|
||||
@@ -362,6 +363,15 @@ int main(int argc, char** argv)
|
||||
{
|
||||
t1 = GetTickCount();
|
||||
float dt = (float)(t1 - t0) / 1000.0f;
|
||||
|
||||
// force redraw every one second
|
||||
one_sec += dt;
|
||||
if (one_sec > 1.f)
|
||||
{
|
||||
one_sec = 0;
|
||||
App::I.redraw = true;
|
||||
}
|
||||
|
||||
if (dt > 1.0f / 60.0f)
|
||||
{
|
||||
t0 = t1;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "node_stroke_preview.h"
|
||||
#include "node_canvas.h"
|
||||
#include "node_scroll.h"
|
||||
#include "node_dialog_browse.h"
|
||||
|
||||
void Node::watch(std::function<void(Node*)> observer)
|
||||
{
|
||||
@@ -739,6 +740,9 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
case kAttribute::FloodEvents:
|
||||
m_flood_events = attr->IntValue() > 0;
|
||||
break;
|
||||
case kAttribute::AspectRatio:
|
||||
YGNodeStyleSetAspectRatio(y_node, attr->FloatValue());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -791,6 +795,8 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
|
||||
CASE(kWidget::StrokePreview, NodeStrokePreview);
|
||||
CASE(kWidget::Canvas, NodeCanvas);
|
||||
CASE(kWidget::Scroll, NodeScroll);
|
||||
CASE(kWidget::DialogBrowse, NodeDialogBrowse);
|
||||
CASE(kWidget::DialogBrowseItem, NodeDialogBrowseItem);
|
||||
#undef CASE
|
||||
case kWidget::Ref:
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ enum class kAttribute : uint16_t
|
||||
Template = const_hash("template"),
|
||||
Value = const_hash("value"),
|
||||
Range = const_hash("range"),
|
||||
AspectRatio = const_hash("aspect-ratio"),
|
||||
};
|
||||
|
||||
enum class kWidget : uint16_t
|
||||
@@ -68,6 +69,8 @@ enum class kWidget : uint16_t
|
||||
StrokePreview = const_hash("stroke-preview"),
|
||||
Canvas = const_hash("canvas"),
|
||||
Scroll = const_hash("scroll"),
|
||||
DialogBrowse = const_hash("dialog-browse"),
|
||||
DialogBrowseItem = const_hash("dialog-browse-item"),
|
||||
};
|
||||
|
||||
class Node
|
||||
|
||||
166
engine/node_dialog_browse.cpp
Normal file
166
engine/node_dialog_browse.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "node_dialog_browse.h"
|
||||
#include "canvas.h"
|
||||
#include "node_image_texture.h"
|
||||
#include "asset.h"
|
||||
#include "node_message_box.h"
|
||||
#include "app.h"
|
||||
|
||||
Node* NodeDialogBrowse::clone_instantiate() const
|
||||
{
|
||||
return new NodeDialogBrowse();
|
||||
}
|
||||
|
||||
void NodeDialogBrowse::clone_finalize(Node* dest) const
|
||||
{
|
||||
NodeDialogBrowse* n = static_cast<NodeDialogBrowse*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
|
||||
void NodeDialogBrowse::init()
|
||||
{
|
||||
auto tpl = static_cast<const NodeBorder*>(init_template("dialog-browse"));
|
||||
m_color = tpl->m_color;
|
||||
m_border_color = tpl->m_border_color;;
|
||||
m_thinkness = tpl->m_thinkness;;
|
||||
init_controls();
|
||||
}
|
||||
|
||||
void NodeDialogBrowse::init_controls()
|
||||
{
|
||||
btn_ok = find<NodeButton>("btn-ok");
|
||||
btn_cancel = find<NodeButton>("btn-cancel");
|
||||
btn_cancel->on_click = [this](Node*) {
|
||||
destroy();
|
||||
};
|
||||
btn_delete = find<NodeButton>("btn-delete");
|
||||
btn_delete->on_click = [this](Node*) {
|
||||
if (!current)
|
||||
return;
|
||||
|
||||
auto msgbox = new NodeMessageBox();
|
||||
msgbox->m_manager = m_manager;
|
||||
msgbox->init();
|
||||
msgbox->m_title->set_text("Delete Project");
|
||||
msgbox->m_message->set_text(("Are you sure you want to delete " + current->m_file_name + "?").c_str());
|
||||
msgbox->btn_ok->on_click = [this,msgbox](Node*){
|
||||
auto path = current->m_path;
|
||||
int idx = container->get_child_index(current);
|
||||
container->remove_child(current);
|
||||
if (!container->m_children.empty())
|
||||
{
|
||||
int newidx = std::min<int>(idx, (int)container->m_children.size() - 1);
|
||||
auto next = (NodeDialogBrowseItem*)container->get_child_at(newidx);
|
||||
current = nullptr;
|
||||
next->on_selected(next);
|
||||
next->m_selected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = nullptr;
|
||||
auto image_tex = find<NodeImageTexture>("thumb-tex");
|
||||
image_tex->tex.destroy();
|
||||
}
|
||||
Asset::delete_file(path);
|
||||
msgbox->destroy();
|
||||
};
|
||||
root()->add_child(msgbox);
|
||||
root()->update();
|
||||
};
|
||||
container = find<Node>("files-list");
|
||||
auto names = Asset::list_files(data_path, false, ".*\\.pano");
|
||||
for (const auto& n : names)
|
||||
{
|
||||
auto node = new NodeDialogBrowseItem;
|
||||
node->m_manager = m_manager;
|
||||
node->init();
|
||||
node->m_text->set_text(n.c_str());
|
||||
node->m_path = data_path + "/" + n;
|
||||
node->m_file_name = n;
|
||||
node->on_selected = [&](NodeDialogBrowseItem* target) {
|
||||
if (target == current)
|
||||
return;
|
||||
selected_path = target->m_path;
|
||||
selected_file = target->m_file_name;
|
||||
selected_name = selected_file.substr(0, selected_file.length() - 5);
|
||||
if (current)
|
||||
current->m_selected = false;
|
||||
current = target;
|
||||
};
|
||||
|
||||
// load thumb
|
||||
ui::Image thumb = ui::Canvas::I->thumbnail_read(node->m_path);
|
||||
auto image_tex = node->find<NodeImageTexture>("thumb-tex");
|
||||
image_tex->tex.destroy();
|
||||
image_tex->tex.create(thumb);
|
||||
|
||||
container->add_child(node);
|
||||
}
|
||||
// if (auto* first = (NodeDialogBrowseItem*)container->get_child_at(0))
|
||||
// {
|
||||
// first->on_selected(first);
|
||||
// first->m_selected = true;
|
||||
// }
|
||||
}
|
||||
|
||||
void NodeDialogBrowse::loaded()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
Node* NodeDialogBrowseItem::clone_instantiate() const
|
||||
{
|
||||
return new NodeDialogBrowseItem;
|
||||
}
|
||||
void NodeDialogBrowseItem::clone_finalize(Node* dest) const
|
||||
{
|
||||
NodeDialogBrowseItem* n = static_cast<NodeDialogBrowseItem*>(dest);
|
||||
n->init_controls();
|
||||
}
|
||||
void NodeDialogBrowseItem::init()
|
||||
{
|
||||
auto tpl = static_cast<const NodeBorder*>(init_template("dialog-browse-item"));
|
||||
m_color = tpl->m_color;
|
||||
m_border_color = tpl->m_border_color;
|
||||
m_thinkness = tpl->m_thinkness;
|
||||
init_controls();
|
||||
}
|
||||
void NodeDialogBrowseItem::init_controls()
|
||||
{
|
||||
m_text = find<NodeText>("title");
|
||||
}
|
||||
void NodeDialogBrowseItem::loaded()
|
||||
{
|
||||
|
||||
}
|
||||
void NodeDialogBrowseItem::draw()
|
||||
{
|
||||
auto c = m_selected ? m_color_selected : m_color_normal;
|
||||
m_thinkness = m_selected ? 1.f : 0.f;
|
||||
m_color = m_mouse_inside ? m_color_hover : c;
|
||||
NodeBorder::draw();
|
||||
}
|
||||
kEventResult NodeDialogBrowseItem::handle_event(Event* e)
|
||||
{
|
||||
NodeBorder::handle_event(e);
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseEnter:
|
||||
break;
|
||||
case kEventType::MouseLeave:
|
||||
break;
|
||||
case kEventType::MouseDownL:
|
||||
m_selected = true;
|
||||
if (on_selected)
|
||||
on_selected(this);
|
||||
break;
|
||||
case kEventType::MouseUpL:
|
||||
break;
|
||||
default:
|
||||
return kEventResult::Available;
|
||||
break;
|
||||
}
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
46
engine/node_dialog_browse.h
Normal file
46
engine/node_dialog_browse.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include "node_border.h"
|
||||
#include "node_button.h"
|
||||
#include "node_image_texture.h"
|
||||
#include "node_text.h"
|
||||
#include "node_text_input.h"
|
||||
|
||||
class NodeDialogBrowseItem : public NodeBorder
|
||||
{
|
||||
public:
|
||||
NodeText* m_text;
|
||||
NodeImageTexture* m_thumb;
|
||||
glm::vec4 m_color_normal = glm::vec4(.4, .4, .4, 1);
|
||||
glm::vec4 m_color_selected = glm::vec4(.3, .3, .3, 1);
|
||||
glm::vec4 m_color_hover = glm::vec4(.5, .5, .5, 1);
|
||||
bool m_selected = false;
|
||||
std::string m_path;
|
||||
std::string m_file_name;
|
||||
std::function<void(NodeDialogBrowseItem* target)> on_selected;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_finalize(Node* dest) const override;
|
||||
virtual void init() override;
|
||||
void init_controls();
|
||||
virtual void loaded() override;
|
||||
virtual void draw() override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
};
|
||||
|
||||
class NodeDialogBrowse : public NodeBorder
|
||||
{
|
||||
public:
|
||||
NodeButton* btn_cancel;
|
||||
NodeButton* btn_ok;
|
||||
NodeButton* btn_delete;
|
||||
NodeDialogBrowseItem* current = nullptr;
|
||||
Node* container;
|
||||
std::string selected_path;
|
||||
std::string selected_file;
|
||||
std::string selected_name;
|
||||
std::string data_path;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_finalize(Node* dest) const override;
|
||||
virtual void init() override;
|
||||
void init_controls();
|
||||
virtual void loaded() override;
|
||||
};
|
||||
@@ -118,8 +118,14 @@ bool WacomTablet::init(HWND hWnd)
|
||||
if (LoadWintab())
|
||||
{
|
||||
/* check if WinTab available. */
|
||||
if (gpWTInfoA(0, 0, NULL))
|
||||
gpWTInfoA(0, 0, 0);
|
||||
if (UINT ret = gpWTInfoA(WTI_DEFSYSCTX, 0, &glogContext))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// this should just avoid errors in debug mode
|
||||
if (ret != sizeof(LOGCONTEXTA))
|
||||
return false;
|
||||
#endif // _DEBUG
|
||||
g_hCtx = TabletInit(hWnd);
|
||||
if (!g_hCtx)
|
||||
{
|
||||
@@ -147,6 +153,7 @@ bool WacomTablet::init(HWND hWnd)
|
||||
|
||||
void WacomTablet::terminate()
|
||||
{
|
||||
gpWTClose(g_hCtx);
|
||||
UnloadWintab();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user