add remote page loading
This commit is contained in:
@@ -370,6 +370,7 @@
|
||||
<ClCompile Include="src\node_image_texture.cpp" />
|
||||
<ClCompile Include="src\node_input_box.cpp" />
|
||||
<ClCompile Include="src\node_message_box.cpp" />
|
||||
<ClCompile Include="src\node_metadata.cpp" />
|
||||
<ClCompile Include="src\node_panel_brush.cpp" />
|
||||
<ClCompile Include="src\node_panel_color.cpp" />
|
||||
<ClCompile Include="src\node_panel_floating.cpp" />
|
||||
@@ -380,6 +381,7 @@
|
||||
<ClCompile Include="src\node_panel_animation.cpp" />
|
||||
<ClCompile Include="src\node_popup_menu.cpp" />
|
||||
<ClCompile Include="src\node_progress_bar.cpp" />
|
||||
<ClCompile Include="src\node_remote_page.cpp" />
|
||||
<ClCompile Include="src\node_scroll.cpp" />
|
||||
<ClCompile Include="src\node_settings.cpp" />
|
||||
<ClCompile Include="src\node_slider.cpp" />
|
||||
@@ -500,6 +502,7 @@
|
||||
<ClInclude Include="src\node_image_texture.h" />
|
||||
<ClInclude Include="src\node_input_box.h" />
|
||||
<ClInclude Include="src\node_message_box.h" />
|
||||
<ClInclude Include="src\node_metadata.h" />
|
||||
<ClInclude Include="src\node_panel_brush.h" />
|
||||
<ClInclude Include="src\node_panel_color.h" />
|
||||
<ClInclude Include="src\node_panel_floating.h" />
|
||||
@@ -510,6 +513,7 @@
|
||||
<ClInclude Include="src\node_panel_animation.h" />
|
||||
<ClInclude Include="src\node_popup_menu.h" />
|
||||
<ClInclude Include="src\node_progress_bar.h" />
|
||||
<ClInclude Include="src\node_remote_page.h" />
|
||||
<ClInclude Include="src\node_scroll.h" />
|
||||
<ClInclude Include="src\node_settings.h" />
|
||||
<ClInclude Include="src\node_slider.h" />
|
||||
|
||||
@@ -384,6 +384,12 @@
|
||||
<ClCompile Include="src\mp4enc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\node_remote_page.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\node_metadata.cpp">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libs\jpeg\jpgd.h">
|
||||
@@ -638,6 +644,12 @@
|
||||
<ClInclude Include="src\mp4enc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\node_remote_page.h">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\node_metadata.h">
|
||||
<Filter>Source Files\ui</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PanoPainter.rc">
|
||||
|
||||
28
data/dialogs/remote-page.xml
Normal file
28
data/dialogs/remote-page.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<root
|
||||
xmlns="http://panopainter.com/layout.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
>
|
||||
|
||||
<layout id="remote-page">
|
||||
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center" mouse-capture="1">
|
||||
<border thickness="1" border-color=".2" pad="3" max-width="650" dir="col" width="80%" height="80%">
|
||||
<border width="100%" height="30" color=".2 .2 .2 .9" dir="row" align="center" justify="center">
|
||||
<text id="title" text="PageTitle"></text>
|
||||
</border>
|
||||
<border width="100%" height="100%" color="0 0 0 .9" pad="10" dir="col">
|
||||
<!--window content-->
|
||||
<border color=".2" width="100%" height="1" grow="1">
|
||||
<scroll id="content" pad="10" margin="5" color=".3 .3 .3 .4" height="100%" dir="col" wrap="0" shrink="1">
|
||||
</scroll>
|
||||
</border>
|
||||
<!--footer buttons-->
|
||||
<node id="footer" height="60" dir="row" justify="flex-end">
|
||||
<!--<button id="btn-ok" text="Ok" width="100" height="30" margin="5 0 0 0"/>-->
|
||||
</node>
|
||||
</border>
|
||||
</border>
|
||||
</border>
|
||||
</layout>
|
||||
|
||||
</root>
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "settings.h"
|
||||
#include "serializer.h"
|
||||
#include "font.h"
|
||||
#include "node_remote_page.h"
|
||||
|
||||
void App::title_update()
|
||||
{
|
||||
@@ -1333,6 +1334,32 @@ void App::initLayout()
|
||||
}
|
||||
}
|
||||
|
||||
auto whatsnew = std::make_shared<NodeRemotePage>();
|
||||
whatsnew->m_manager = &layout;
|
||||
whatsnew->init();
|
||||
whatsnew->load_url("http://localhost:8080/app-content/whatsnew.xml", [this, whatsnew] (bool success) {
|
||||
if (success)
|
||||
{
|
||||
int last_id = Settings::value_or<Serializer::Integer>("whatsnew-id", 0);
|
||||
if (whatsnew->m_page_id <= g_version_build && whatsnew->m_page_id > last_id)
|
||||
{
|
||||
whatsnew->set_title(fmt::format("What's new in version {}", g_version_number));
|
||||
layout[main_id]->add_child(whatsnew);
|
||||
}
|
||||
whatsnew->add_button("Reload", 120, [this, whatsnew](Node*) {
|
||||
whatsnew->reload();
|
||||
});
|
||||
whatsnew->add_button("Read Later", 120, [this, whatsnew](Node*) {
|
||||
whatsnew->destroy();
|
||||
});
|
||||
whatsnew->add_button("Close", 100, [this, whatsnew](Node*) {
|
||||
Settings::set<Serializer::Integer>("whatsnew-id", whatsnew->m_page_id);
|
||||
Settings::save();
|
||||
whatsnew->destroy();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
brush_update(true, true);
|
||||
|
||||
// hacky thing to make the toolbar buttons not steal events when moving cursor fast
|
||||
|
||||
@@ -186,6 +186,7 @@ bool Asset::open_url(const std::string& url, std::function<bool(float)> progress
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &tmp_data);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler_asset);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
||||
#ifdef __ANDROID__
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
#endif
|
||||
@@ -221,7 +222,7 @@ std::future<bool>& Asset::open_url_async(const std::string& url,
|
||||
m_stop_async = false;
|
||||
remote_future = std::async([this, url, progress, complete] {
|
||||
bool ok = open_url(url, progress);
|
||||
if (ok && complete)
|
||||
if (complete)
|
||||
complete(ok);
|
||||
return ok;
|
||||
});
|
||||
|
||||
@@ -39,14 +39,28 @@ bool LayoutManager::load(const char* path)
|
||||
|
||||
m_path = path;
|
||||
|
||||
auto old = std::move(m_layouts);
|
||||
|
||||
Asset file;
|
||||
if (!(file.open(path) && file.read_all()))
|
||||
return false;
|
||||
tinyxml2::XMLDocument xml;
|
||||
auto ret = xml.Parse((char*)file.m_data, file.m_len);
|
||||
auto xml_string = std::string((char*)file.m_data, (size_t)file.m_len);
|
||||
file.close();
|
||||
|
||||
if (!parse(xml_string))
|
||||
return false;
|
||||
|
||||
if (on_loaded)
|
||||
on_loaded(m_loaded);
|
||||
m_loaded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LayoutManager::parse(const std::string& xml_string) noexcept
|
||||
{
|
||||
auto old = std::move(m_layouts);
|
||||
|
||||
tinyxml2::XMLDocument xml;
|
||||
auto ret = xml.Parse(xml_string.c_str(), xml_string.size());
|
||||
if (ret != tinyxml2::XMLError::XML_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
@@ -70,7 +84,7 @@ bool LayoutManager::load(const char* path)
|
||||
if (std::find(osv.begin(), osv.end(), PP_OS) == osv.end())
|
||||
{
|
||||
LOG("Layout %s not for this os(%s), skipping", id_str, PP_OS)
|
||||
current = current->NextSiblingElement("layout");
|
||||
current = current->NextSiblingElement("layout");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -105,11 +119,6 @@ bool LayoutManager::load(const char* path)
|
||||
}
|
||||
current = current->NextSiblingElement("layout");
|
||||
}
|
||||
|
||||
if (on_loaded)
|
||||
on_loaded(m_loaded);
|
||||
m_loaded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
12
src/layout.h
12
src/layout.h
@@ -1,15 +1,4 @@
|
||||
#pragma once
|
||||
#include "shape.h"
|
||||
#include "util.h"
|
||||
#include "shader.h"
|
||||
#include "font.h"
|
||||
#include "asset.h"
|
||||
#include "rtt.h"
|
||||
#include "bezier.h"
|
||||
#include "canvas.h"
|
||||
#include "event.h"
|
||||
#include <tinyxml2.h>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
class LayoutManager
|
||||
{
|
||||
@@ -23,6 +12,7 @@ public:
|
||||
void unload();
|
||||
void create();
|
||||
bool load(const char* path);
|
||||
bool parse(const std::string& xml_string) noexcept;
|
||||
bool reload();
|
||||
class Node* operator[](uint16_t id)
|
||||
{
|
||||
|
||||
@@ -1177,6 +1177,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
}
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
win32_show_cursor(true);
|
||||
App::I->ui_task_async([=] {
|
||||
int active = GET_WM_ACTIVATE_STATE(wp, lp);
|
||||
WacomTablet::I.set_focus(active);
|
||||
|
||||
25
src/node.cpp
25
src/node.cpp
@@ -37,6 +37,7 @@
|
||||
#include "node_panel_quick.h"
|
||||
#include "node_tool_bucket.h"
|
||||
#include "node_panel_animation.h"
|
||||
#include "node_metadata.h"
|
||||
|
||||
void Node::app_redraw()
|
||||
{
|
||||
@@ -389,6 +390,16 @@ std::shared_ptr<Node> Node::load_template(const std::string& filename, const std
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Node::parse_template(const std::string& xml_string, const std::string& name) const
|
||||
{
|
||||
LayoutManager m;
|
||||
std::shared_ptr<Node> ret;
|
||||
if (m.parse(xml_string))
|
||||
ret = m.get_ref(name.c_str())->m_children[0]->clone();
|
||||
m.unload();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Node::add_child(Node* n)
|
||||
{
|
||||
App::I->ui_task([&]
|
||||
@@ -749,6 +760,8 @@ Node::Node(Node&& o)
|
||||
m_pos_offset_childred = o.m_pos_offset_childred;
|
||||
m_clip_uncut = o.m_clip_uncut;
|
||||
|
||||
auto_width = o.auto_width;
|
||||
auto_height = o.auto_height;
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
@@ -764,12 +777,14 @@ void Node::SetWidth(float value)
|
||||
{
|
||||
YGNodeStyleSetWidth(y_node, value);
|
||||
m_size.x = value;
|
||||
auto_width = value == YGUndefined;
|
||||
app_redraw();
|
||||
}
|
||||
|
||||
void Node::SetWidthP(float value)
|
||||
{
|
||||
YGNodeStyleSetWidthPercent(y_node, value);
|
||||
auto_width = value == YGUndefined;
|
||||
app_redraw();
|
||||
}
|
||||
|
||||
@@ -777,12 +792,14 @@ void Node::SetHeight(float value)
|
||||
{
|
||||
YGNodeStyleSetHeight(y_node, value);
|
||||
m_size.y = value;
|
||||
auto_height = value == YGUndefined;
|
||||
app_redraw();
|
||||
}
|
||||
|
||||
void Node::SetHeightP(float value)
|
||||
{
|
||||
YGNodeStyleSetHeightPercent(y_node, value);
|
||||
auto_height = value == YGUndefined;
|
||||
app_redraw();
|
||||
}
|
||||
|
||||
@@ -1163,6 +1180,7 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
{
|
||||
YGNodeStyleSetWidth(y_node, YGUndefined);
|
||||
YGNodeStyleSetWidthPercent(y_node, YGUndefined);
|
||||
auto_width = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1170,6 +1188,7 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
YGNodeStyleSetWidthPercent(y_node, attr->FloatValue());
|
||||
else
|
||||
YGNodeStyleSetWidth(y_node, attr->FloatValue());
|
||||
auto_width = false;
|
||||
}
|
||||
break;
|
||||
case kAttribute::MinWidth:
|
||||
@@ -1183,6 +1202,7 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
{
|
||||
YGNodeStyleSetHeight(y_node, YGUndefined);
|
||||
YGNodeStyleSetHeightPercent(y_node, YGUndefined);
|
||||
auto_height = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1190,6 +1210,7 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
YGNodeStyleSetHeightPercent(y_node, attr->FloatValue());
|
||||
else
|
||||
YGNodeStyleSetHeight(y_node, attr->FloatValue());
|
||||
auto_height = false;
|
||||
}
|
||||
break;
|
||||
case kAttribute::MinHeight:
|
||||
@@ -1416,6 +1437,7 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
|
||||
CASE(kWidget::UserManual, NodeUserManual);
|
||||
CASE(kWidget::ToolBucket, NodeToolBucket);
|
||||
CASE(kWidget::Timeline, NodeAnimationTimeline);
|
||||
CASE(kWidget::Metadata, NodeMetadata);
|
||||
#undef CASE
|
||||
case kWidget::Ref:
|
||||
{
|
||||
@@ -1481,6 +1503,9 @@ void Node::clone_copy(Node* dest) const
|
||||
dest->m_pos_offset = m_pos_offset;
|
||||
dest->m_pos_offset_childred = m_pos_offset_childred;
|
||||
dest->m_clip_uncut = m_clip_uncut;
|
||||
|
||||
dest->auto_width = auto_width;
|
||||
dest->auto_height = auto_height;
|
||||
}
|
||||
|
||||
void Node::clone_children(Node* dest) const
|
||||
|
||||
14
src/node.h
14
src/node.h
@@ -97,6 +97,7 @@ enum class kWidget : uint16_t
|
||||
UserManual = const_hash("usermanual"),
|
||||
ToolBucket = const_hash("tool-bucket"),
|
||||
Timeline = const_hash("timeline"),
|
||||
Metadata = const_hash("metadata"),
|
||||
};
|
||||
|
||||
class Node : public std::enable_shared_from_this<Node>
|
||||
@@ -143,6 +144,9 @@ public:
|
||||
// it's actually rendering
|
||||
bool m_on_screen = false;
|
||||
|
||||
bool auto_width = true;
|
||||
bool auto_height = true;
|
||||
|
||||
Node(const Node&) = delete;
|
||||
Node& operator=(const Node&) = delete;
|
||||
Node&& operator=(Node&& o);
|
||||
@@ -279,6 +283,15 @@ public:
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
template<class T = Node> std::shared_ptr<T> add_child_xml(const std::string& xml_string, const std::string& name)
|
||||
{
|
||||
if (auto t = parse_template(xml_string, name))
|
||||
{
|
||||
add_child(t);
|
||||
return std::dynamic_pointer_cast<T>(t);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void on_tick(float dt) { };
|
||||
virtual kEventResult on_event(Event* e);
|
||||
@@ -296,6 +309,7 @@ public:
|
||||
const Node* init_template(const char* id);
|
||||
bool init_template_file(const std::string& path, const std::string& id);
|
||||
std::shared_ptr<Node> load_template(const std::string& filename, const std::string& name) const;
|
||||
std::shared_ptr<Node> parse_template(const std::string& xml_stirng, const std::string& name) const;
|
||||
void tick(float dt);
|
||||
void app_redraw();
|
||||
void add_child(Node* n);
|
||||
|
||||
25
src/node_metadata.cpp
Normal file
25
src/node_metadata.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "node_metadata.h"
|
||||
|
||||
NodeMetadata::NodeMetadata() noexcept
|
||||
{
|
||||
m_nodeID = const_hash("metadata");
|
||||
m_nodeID_s = "metadata";
|
||||
}
|
||||
|
||||
Node* NodeMetadata::clone_instantiate() const
|
||||
{
|
||||
return new NodeMetadata();
|
||||
}
|
||||
void NodeMetadata::clone_copy(Node* dest) const
|
||||
{
|
||||
Node::clone_copy(dest);
|
||||
NodeMetadata* n = static_cast<NodeMetadata*>(dest);
|
||||
n->m_props = m_props;
|
||||
}
|
||||
void NodeMetadata::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
{
|
||||
Node::parse_attributes(ka, attr);
|
||||
m_props[attr->Name()] = attr->Value();
|
||||
}
|
||||
12
src/node_metadata.h
Normal file
12
src/node_metadata.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "node.h"
|
||||
|
||||
class NodeMetadata : public Node
|
||||
{
|
||||
public:
|
||||
std::map<std::string, std::string> m_props;
|
||||
NodeMetadata() noexcept;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_copy(Node* dest) const override;
|
||||
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override;
|
||||
};
|
||||
98
src/node_remote_page.cpp
Normal file
98
src/node_remote_page.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "pch.h"
|
||||
#include "log.h"
|
||||
#include "node_remote_page.h"
|
||||
#include "node_button.h"
|
||||
#include "node_scroll.h"
|
||||
#include "asset.h"
|
||||
#include "node_text.h"
|
||||
#include "node_metadata.h"
|
||||
|
||||
Node* NodeRemotePage::clone_instantiate() const
|
||||
{
|
||||
return new NodeRemotePage();
|
||||
}
|
||||
|
||||
void NodeRemotePage::clone_copy(Node* dest) const
|
||||
{
|
||||
auto n = static_cast<NodeRemotePage*>(dest);
|
||||
n->m_page_id = m_page_id;
|
||||
n->m_loaded = m_loaded;
|
||||
}
|
||||
|
||||
void NodeRemotePage::init()
|
||||
{
|
||||
init_template_file("data/dialogs/remote-page.xml", "remote-page");
|
||||
init_controls();
|
||||
}
|
||||
|
||||
void NodeRemotePage::init_controls()
|
||||
{
|
||||
m_content = find<NodeScroll>("content");
|
||||
m_title = find<NodeText>("title");
|
||||
}
|
||||
|
||||
std::future<bool> NodeRemotePage::load_url(const std::string& url,
|
||||
std::function<void(bool success)> on_complete /*= nullptr*/) noexcept
|
||||
{
|
||||
m_loading = true;
|
||||
|
||||
auto align = m_content->add_child_ref<Node>();
|
||||
align->SetWidthP(100.f);
|
||||
align->SetHeightP(100.f);
|
||||
align->SetAlign(YGAlignCenter);
|
||||
align->SetJustify(YGJustifyCenter);
|
||||
auto text = align->add_child_ref<NodeText>();
|
||||
text->set_font(kFont::Arial_30);
|
||||
text->set_text("Connecting to the server...");
|
||||
|
||||
m_url = url;
|
||||
m_loaded = false;
|
||||
auto remote = std::make_shared<Asset>();
|
||||
auto prom = std::make_shared<std::promise<bool>>();
|
||||
remote->open_url_async(url, nullptr, [this, remote, align, text, prom, on_complete](bool success) {
|
||||
if (success)
|
||||
{
|
||||
m_content->add_child_xml(std::string((char*)remote->m_data, (size_t)remote->m_len), "about");
|
||||
if (auto meta = m_content->find<NodeMetadata>("metadata"))
|
||||
m_page_id = std::stol(meta->m_props["page-id"]);
|
||||
align->destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
text->set_text("Error loading the page");
|
||||
}
|
||||
m_loaded = success;
|
||||
m_loading = false;
|
||||
prom->set_value(success);
|
||||
if (on_complete)
|
||||
on_complete(success);
|
||||
});
|
||||
return prom->get_future();
|
||||
}
|
||||
|
||||
void NodeRemotePage::reload() noexcept
|
||||
{
|
||||
if (m_loading)
|
||||
return;
|
||||
m_content->remove_all_children();
|
||||
load_url(m_url);
|
||||
}
|
||||
|
||||
void NodeRemotePage::set_title(const std::string& title)
|
||||
{
|
||||
m_title->set_text(title);
|
||||
}
|
||||
|
||||
void NodeRemotePage::add_button(const std::string& label, int width,
|
||||
std::function<void(Node* target)> onclic /*= nullptr*/) noexcept
|
||||
{
|
||||
if (auto footer = find("footer"))
|
||||
{
|
||||
auto b = footer->add_child<NodeButton>();
|
||||
b->m_text->set_text(label);
|
||||
b->m_border->SetWidth(width);
|
||||
b->m_border->SetHeight(30);
|
||||
b->m_border->SetMargin(5, 0, 0, 0);
|
||||
b->on_click = onclic;
|
||||
}
|
||||
}
|
||||
23
src/node_remote_page.h
Normal file
23
src/node_remote_page.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "node_border.h"
|
||||
|
||||
class NodeRemotePage : public NodeBorder
|
||||
{
|
||||
class NodeScroll* m_content;
|
||||
class NodeText* m_title;
|
||||
bool m_loading;
|
||||
std::string m_url;
|
||||
public:
|
||||
bool m_loaded;
|
||||
int m_page_id;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_copy(Node* dest) const override;
|
||||
virtual void init() override;
|
||||
void init_controls();
|
||||
std::future<bool> load_url(const std::string& url,
|
||||
std::function<void(bool success)> on_complete = nullptr) noexcept;
|
||||
void reload() noexcept;
|
||||
void set_title(const std::string& title);
|
||||
void add_button(const std::string& label, int width,
|
||||
std::function<void(Node* target)> onclic = nullptr) noexcept;
|
||||
};
|
||||
@@ -20,6 +20,10 @@ void NodeText::clone_copy(Node* dest) const
|
||||
n->m_color = m_color;
|
||||
n->m_font_size = m_font_size;
|
||||
n->font_id = font_id;
|
||||
n->m_multiline = m_multiline;
|
||||
n->m_off = m_off;
|
||||
n->m_text_align_v = m_text_align_v;
|
||||
n->m_text_align_h = m_text_align_h;
|
||||
}
|
||||
|
||||
void NodeText::create()
|
||||
@@ -32,7 +36,7 @@ void NodeText::create()
|
||||
font_id = (kFont)const_hash(font);
|
||||
m_text_mesh.create();
|
||||
m_text_mesh.update(font_id, m_text);
|
||||
SetSize(m_text_mesh.bb);
|
||||
update_layout();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +45,7 @@ void NodeText::set_font(kFont fontID)
|
||||
font_id = fontID;
|
||||
m_text_mesh.create();
|
||||
m_text_mesh.update(font_id, m_text);
|
||||
SetSize(m_text_mesh.bb);
|
||||
}
|
||||
|
||||
void NodeText::restore_context()
|
||||
{
|
||||
Node::restore_context();
|
||||
create();
|
||||
update_layout();
|
||||
}
|
||||
|
||||
void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
|
||||
@@ -55,6 +53,25 @@ void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* att
|
||||
Node::parse_attributes(ka, attr);
|
||||
switch (ka)
|
||||
{
|
||||
case kAttribute::Multiline:
|
||||
m_multiline = attr->BoolValue();
|
||||
break;
|
||||
case kAttribute::TextAlign:
|
||||
if (strcmp(attr->Value(), "left") == 0)
|
||||
m_text_align_h = TextAlign::Begin;
|
||||
else if (strcmp(attr->Value(), "center") == 0)
|
||||
m_text_align_h = TextAlign::Center;
|
||||
else if (strcmp(attr->Value(), "right") == 0)
|
||||
m_text_align_h = TextAlign::End;
|
||||
break;
|
||||
case kAttribute::TextVerticalAlign:
|
||||
if (strcmp(attr->Value(), "top") == 0)
|
||||
m_text_align_v = TextAlign::Begin;
|
||||
else if (strcmp(attr->Value(), "center") == 0)
|
||||
m_text_align_v = TextAlign::Center;
|
||||
else if (strcmp(attr->Value(), "bottom") == 0)
|
||||
m_text_align_v = TextAlign::End;
|
||||
break;
|
||||
case kAttribute::TextWrapWidth:
|
||||
m_text_mesh.max_width = attr->IntValue();
|
||||
break;
|
||||
@@ -82,11 +99,11 @@ void NodeText::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* att
|
||||
}
|
||||
}
|
||||
|
||||
void NodeText::set_text(const char* s)
|
||||
void NodeText::set_text(const std::string& s)
|
||||
{
|
||||
m_text = s;
|
||||
m_text_mesh.update(font_id, s);
|
||||
SetSize(m_text_mesh.bb);
|
||||
update_layout();
|
||||
}
|
||||
|
||||
void NodeText::set_text_format(const char* fmt, ...)
|
||||
@@ -98,7 +115,39 @@ void NodeText::set_text_format(const char* fmt, ...)
|
||||
va_end(args);
|
||||
m_text = buffer;
|
||||
m_text_mesh.update(font_id, buffer);
|
||||
SetSize(m_text_mesh.bb);
|
||||
update_layout();
|
||||
}
|
||||
|
||||
void NodeText::update_layout()
|
||||
{
|
||||
if (auto_width)
|
||||
{
|
||||
YGNodeStyleSetWidth(y_node, m_text_mesh.bb.x);
|
||||
m_size.x = m_text_mesh.bb.x;
|
||||
}
|
||||
if (auto_height)
|
||||
{
|
||||
YGNodeStyleSetHeight(y_node, m_text_mesh.bb.y);
|
||||
m_size.y = m_text_mesh.bb.y;
|
||||
}
|
||||
|
||||
auto pad = GetPadding();
|
||||
float h = GetHeight() - (pad[1] + pad[3]);
|
||||
float w = GetWidth() - (pad[0] + pad[2]);
|
||||
|
||||
if (m_text_align_v == TextAlign::Begin)
|
||||
m_off.y = pad[0];
|
||||
else if (m_text_align_v == TextAlign::Center)
|
||||
m_off.y = (h - m_text_mesh.bb.y) * 0.5f + pad[0];
|
||||
else
|
||||
m_off.y = (h - m_text_mesh.bb.y) + pad[0];
|
||||
|
||||
if (m_text_align_h == TextAlign::Begin)
|
||||
m_off.x = pad[3];
|
||||
else if (m_text_align_v == TextAlign::Center)
|
||||
m_off.x = (w - m_text_mesh.bb.x) * 0.5f + pad[3];
|
||||
else
|
||||
m_off.x = (w - m_text_mesh.bb.x) + pad[3];
|
||||
}
|
||||
|
||||
void NodeText::draw()
|
||||
@@ -116,6 +165,8 @@ void NodeText::draw()
|
||||
|
||||
void NodeText::handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom)
|
||||
{
|
||||
auto pad = GetPadding();
|
||||
m_text_mesh.max_width = m_multiline ? new_size.x - (pad[1] + pad[3]) : 0;
|
||||
m_text_mesh.update(font_id, m_text);
|
||||
SetSize(m_text_mesh.bb);
|
||||
update_layout();
|
||||
}
|
||||
|
||||
@@ -5,20 +5,33 @@
|
||||
class NodeText : public Node
|
||||
{
|
||||
public:
|
||||
enum class TextAlign
|
||||
{
|
||||
Begin,
|
||||
Center,
|
||||
End,
|
||||
};
|
||||
TextMesh m_text_mesh;
|
||||
std::string m_text;
|
||||
std::string m_font = "arial";
|
||||
glm::vec4 m_color{ 1, 1, 1, 1 };
|
||||
int m_font_size = 11;
|
||||
kFont font_id;
|
||||
|
||||
bool m_multiline = false;
|
||||
glm::vec2 m_off;
|
||||
TextAlign m_text_align_v = TextAlign::Center;
|
||||
TextAlign m_text_align_h = TextAlign::Begin;
|
||||
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void clone_copy(Node* dest) const override;
|
||||
virtual void create() override;
|
||||
virtual void restore_context() override;
|
||||
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override;
|
||||
void set_text(const char* s);
|
||||
void set_text_format(const char* fmt, ...);
|
||||
void set_font(kFont fontID);
|
||||
virtual void draw() override;
|
||||
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom) override;
|
||||
|
||||
void set_text(const std::string& s);
|
||||
void set_text_format(const char* fmt, ...);
|
||||
void set_font(kFont fontID);
|
||||
void update_layout();
|
||||
};
|
||||
|
||||
@@ -33,9 +33,6 @@ void NodeTextInput::clone_copy(Node* dest) const
|
||||
{
|
||||
NodeBorder::clone_copy(dest);
|
||||
NodeTextInput* n = static_cast<NodeTextInput*>(dest);
|
||||
|
||||
n->m_multiline = m_multiline;
|
||||
|
||||
n->m_text_mesh.max_width = m_text_mesh.max_width;
|
||||
n->m_text_mesh.create();
|
||||
n->m_text_mesh.update(font_id, m_text);
|
||||
@@ -44,6 +41,7 @@ void NodeTextInput::clone_copy(Node* dest) const
|
||||
n->m_color = m_color;
|
||||
n->m_font_size = m_font_size;
|
||||
n->font_id = font_id;
|
||||
n->m_multiline = m_multiline;
|
||||
n->m_off = m_off;
|
||||
n->m_text_align_v = m_text_align_v;
|
||||
n->m_text_align_h = m_text_align_h;
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
glm::vec4 m_color{ 1, 1, 1, 1 };
|
||||
int m_font_size = 11;
|
||||
kFont font_id;
|
||||
|
||||
bool m_multiline = false;
|
||||
bool m_cursor_visible = false;
|
||||
glm::vec2 m_off;
|
||||
|
||||
Reference in New Issue
Block a user