2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-03 12:35:51 +00:00

New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:24:02 -10:00
parent 4fc3e42912
commit dcbc001cd2
54 changed files with 7939 additions and 9417 deletions

View File

@ -4,14 +4,11 @@
#include "specter/Control.hpp" #include "specter/Control.hpp"
#include "specter/Icon.hpp" #include "specter/Icon.hpp"
namespace specter namespace specter {
{
class Button : public Control class Button : public Control {
{
public: public:
enum class Style enum class Style {
{
Block, Block,
Text, Text,
}; };
@ -28,17 +25,13 @@ private:
SolidShaderVert m_verts[40]; SolidShaderVert m_verts[40];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void _loadVerts() void _loadVerts() { m_vertsBinding.load<decltype(m_verts)>(m_verts); }
{
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
RectangleConstraint m_constraint; RectangleConstraint m_constraint;
int m_nomWidth, m_nomHeight; int m_nomWidth, m_nomHeight;
int m_textWidth, m_textIconWidth; int m_textWidth, m_textIconWidth;
struct ButtonTarget : View struct ButtonTarget : View {
{
Button& m_button; Button& m_button;
bool m_pressed = false; bool m_pressed = false;
@ -57,8 +50,7 @@ private:
}; };
ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget; ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget;
struct MenuTarget : View struct MenuTarget : View {
{
Button& m_button; Button& m_button;
bool m_pressed = false; bool m_pressed = false;
@ -80,8 +72,7 @@ private:
ViewChild<std::unique_ptr<View>> m_modalMenu; ViewChild<std::unique_ptr<View>> m_modalMenu;
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
friend class Button; friend class Button;
@ -90,14 +81,12 @@ public:
}; };
~Button() { closeMenu({}); } ~Button() { closeMenu({}); }
Button(ViewResources& res, View& parentView, Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
IButtonBinding* controlBinding, std::string_view text, Icon* icon=nullptr,
Style style=Style::Block, const zeus::CColor& bgColor=zeus::CColor::skWhite,
RectangleConstraint constraint=RectangleConstraint());
Button(ViewResources& res, View& parentView,
IButtonBinding* controlBinding, std::string_view text, const zeus::CColor& textColor,
Icon* icon = nullptr, Style style = Style::Block, const zeus::CColor& bgColor = zeus::CColor::skWhite, Icon* icon = nullptr, Style style = Style::Block, const zeus::CColor& bgColor = zeus::CColor::skWhite,
RectangleConstraint constraint = RectangleConstraint()); RectangleConstraint constraint = RectangleConstraint());
Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
const zeus::CColor& textColor, Icon* icon = nullptr, Style style = Style::Block,
const zeus::CColor& bgColor = zeus::CColor::skWhite, RectangleConstraint constraint = RectangleConstraint());
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
@ -117,8 +106,7 @@ public:
void closeMenu(const boo::SWindowCoord& coord); void closeMenu(const boo::SWindowCoord& coord);
ViewChild<std::unique_ptr<View>>& getMenu() { return m_modalMenu; } ViewChild<std::unique_ptr<View>>& getMenu() { return m_modalMenu; }
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
m_viewVertBlock.m_color = color; m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf) if (m_viewVertBlockBuf)
@ -129,5 +117,4 @@ public:
} }
}; };
} } // namespace specter

View File

@ -2,32 +2,23 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
class Control; class Control;
class Button; class Button;
enum class ControlType enum class ControlType { Button, Float, Int, String, CVar };
{
Button,
Float,
Int,
String,
CVar
};
struct IControlBinding struct IControlBinding {
{
virtual ControlType type() const = 0; virtual ControlType type() const = 0;
virtual std::string_view name(const Control* control) const = 0; virtual std::string_view name(const Control* control) const = 0;
virtual std::string_view help(const Control* control) const { return {}; } virtual std::string_view help(const Control* control) const { return {}; }
}; };
struct IButtonBinding : IControlBinding struct IButtonBinding : IControlBinding {
{
ControlType type() const { return ControlType::Button; } ControlType type() const { return ControlType::Button; }
static IButtonBinding* castTo(IControlBinding* bind) static IButtonBinding* castTo(IControlBinding* bind) {
{ return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr; } return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr;
}
/** Pressed/Released while Hovering action, /** Pressed/Released while Hovering action,
* cancellable by holding the button and releasing outside */ * cancellable by holding the button and releasing outside */
@ -40,8 +31,7 @@ struct IButtonBinding : IControlBinding
virtual void up(const Button* button, const boo::SWindowCoord& coord) {} virtual void up(const Button* button, const boo::SWindowCoord& coord) {}
/** Optional style of menu to bind to button */ /** Optional style of menu to bind to button */
enum class MenuStyle enum class MenuStyle {
{
None, /**< No menu; normal button */ None, /**< No menu; normal button */
Primary, /**< Menu button replaces normal button */ Primary, /**< Menu button replaces normal button */
Auxiliary /**< Menu button placed alongside normal button */ Auxiliary /**< Menu button placed alongside normal button */
@ -54,67 +44,64 @@ struct IButtonBinding : IControlBinding
virtual std::unique_ptr<View> buildMenu(const specter::Button* button) { return std::unique_ptr<View>(); } virtual std::unique_ptr<View> buildMenu(const specter::Button* button) { return std::unique_ptr<View>(); }
}; };
struct IFloatBinding : IControlBinding struct IFloatBinding : IControlBinding {
{
ControlType type() const { return ControlType::Float; } ControlType type() const { return ControlType::Float; }
static IFloatBinding* castTo(IControlBinding* bind) static IFloatBinding* castTo(IControlBinding* bind) {
{ return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr; } return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr;
}
virtual float getDefault(const Control* control) const { return 0.0; } virtual float getDefault(const Control* control) const { return 0.0; }
virtual std::pair<float, float> getBounds(const Control* control) const { return std::make_pair(FLT_MIN, FLT_MAX); } virtual std::pair<float, float> getBounds(const Control* control) const { return std::make_pair(FLT_MIN, FLT_MAX); }
virtual void changed(const Control* control, float val) = 0; virtual void changed(const Control* control, float val) = 0;
}; };
struct IIntBinding : IControlBinding struct IIntBinding : IControlBinding {
{
ControlType type() const { return ControlType::Int; } ControlType type() const { return ControlType::Int; }
static IIntBinding* castTo(IControlBinding* bind) static IIntBinding* castTo(IControlBinding* bind) {
{ return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr; } return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr;
}
virtual int getDefault(const Control* control) const { return 0; } virtual int getDefault(const Control* control) const { return 0; }
virtual std::pair<int, int> getBounds(const Control* control) const { return std::make_pair(INT_MIN, INT_MAX); } virtual std::pair<int, int> getBounds(const Control* control) const { return std::make_pair(INT_MIN, INT_MAX); }
virtual void changed(const Control* control, int val) = 0; virtual void changed(const Control* control, int val) = 0;
}; };
struct IStringBinding : IControlBinding struct IStringBinding : IControlBinding {
{
ControlType type() const { return ControlType::String; } ControlType type() const { return ControlType::String; }
static IStringBinding* castTo(IControlBinding* bind) static IStringBinding* castTo(IControlBinding* bind) {
{ return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr; } return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr;
}
virtual std::string getDefault(const Control* control) const { return ""; } virtual std::string getDefault(const Control* control) const { return ""; }
virtual void changed(const Control* control, std::string_view val) = 0; virtual void changed(const Control* control, std::string_view val) = 0;
}; };
struct CVarControlBinding : IControlBinding struct CVarControlBinding : IControlBinding {
{
hecl::CVar* m_cvar; hecl::CVar* m_cvar;
CVarControlBinding(hecl::CVar* cvar) CVarControlBinding(hecl::CVar* cvar) : m_cvar(cvar) {}
: m_cvar(cvar) {}
ControlType type() const { return ControlType::CVar; } ControlType type() const { return ControlType::CVar; }
static CVarControlBinding* castTo(IControlBinding* bind) static CVarControlBinding* castTo(IControlBinding* bind) {
{ return bind->type() == ControlType::CVar ? static_cast<CVarControlBinding*>(bind) : nullptr; } return bind->type() == ControlType::CVar ? static_cast<CVarControlBinding*>(bind) : nullptr;
}
std::string_view name(const Control* control) const { return m_cvar->name(); } std::string_view name(const Control* control) const { return m_cvar->name(); }
std::string_view help(const Control* control) const { return m_cvar->rawHelp(); } std::string_view help(const Control* control) const { return m_cvar->rawHelp(); }
}; };
class Control : public View class Control : public View {
{
protected: protected:
IControlBinding* m_controlBinding = nullptr; IControlBinding* m_controlBinding = nullptr;
public: public:
Control(ViewResources& res, View& parentView, IControlBinding* controlBinding); Control(ViewResources& res, View& parentView, IControlBinding* controlBinding);
}; };
class ITextInputView : public Control, public boo::ITextInputCallback class ITextInputView : public Control, public boo::ITextInputCallback {
{
protected: protected:
static std::recursive_mutex m_textInputLk; static std::recursive_mutex m_textInputLk;
ITextInputView(ViewResources& res, View& parentView, ITextInputView(ViewResources& res, View& parentView, IControlBinding* controlBinding)
IControlBinding* controlBinding)
: Control(res, parentView, controlBinding) {} : Control(res, parentView, controlBinding) {}
public: public:
virtual void clipboardCopy() {} virtual void clipboardCopy() {}
virtual void clipboardCut() {} virtual void clipboardCut() {}
virtual void clipboardPaste() {} virtual void clipboardPaste() {}
}; };
} } // namespace specter

View File

@ -12,29 +12,19 @@
#include "PathButtons.hpp" #include "PathButtons.hpp"
#include <hecl/hecl.hpp> #include <hecl/hecl.hpp>
namespace specter namespace specter {
{
class FileBrowser : public ModalWindow, public IPathButtonsBinding class FileBrowser : public ModalWindow, public IPathButtonsBinding {
{
public: public:
enum class Type enum class Type { SaveFile, SaveDirectory, OpenFile, OpenDirectory, NewHECLProject, OpenHECLProject };
{
SaveFile,
SaveDirectory,
OpenFile,
OpenDirectory,
NewHECLProject,
OpenHECLProject
};
private: private:
Type m_type; Type m_type;
hecl::SystemString m_path; hecl::SystemString m_path;
std::vector<hecl::SystemString> m_comps; std::vector<hecl::SystemString> m_comps;
bool m_showingHidden = false; bool m_showingHidden = false;
class LeftSide : public View class LeftSide : public View {
{
friend class FileBrowser; friend class FileBrowser;
FileBrowser& m_fb; FileBrowser& m_fb;
LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {} LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
@ -42,8 +32,7 @@ private:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_left; } m_left;
class RightSide : public View class RightSide : public View {
{
friend class FileBrowser; friend class FileBrowser;
FileBrowser& m_fb; FileBrowser& m_fb;
RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {} RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
@ -54,15 +43,13 @@ private:
ViewChild<std::unique_ptr<SplitView>> m_split; ViewChild<std::unique_ptr<SplitView>> m_split;
void okActivated(bool viaButton); void okActivated(bool viaButton);
struct OKButton : IButtonBinding struct OKButton : IButtonBinding {
{
FileBrowser& m_fb; FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button; ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text; std::string m_text;
OKButton(FileBrowser& fb, ViewResources& res, std::string_view text) OKButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
: m_fb(fb), m_text(text) m_button.m_view.reset(
{ new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
m_button.m_view.reset(new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
RectangleConstraint(100 * res.pixelFactor(), -1, RectangleConstraint::Test::Minimum))); RectangleConstraint(100 * res.pixelFactor(), -1, RectangleConstraint::Test::Minimum)));
} }
std::string_view name(const Control* control) const { return m_text; } std::string_view name(const Control* control) const { return m_text; }
@ -70,15 +57,13 @@ private:
} m_ok; } m_ok;
void cancelActivated(); void cancelActivated();
struct CancelButton : IButtonBinding struct CancelButton : IButtonBinding {
{
FileBrowser& m_fb; FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button; ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text; std::string m_text;
CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text) CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
: m_fb(fb), m_text(text) m_button.m_view.reset(new Button(
{ res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
m_button.m_view.reset(new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
RectangleConstraint(m_fb.m_ok.m_button.m_view->nominalWidth(), -1, RectangleConstraint::Test::Minimum))); RectangleConstraint(m_fb.m_ok.m_button.m_view->nominalWidth(), -1, RectangleConstraint::Test::Minimum)));
} }
std::string_view name(const Control* control) const { return m_text; } std::string_view name(const Control* control) const { return m_text; }
@ -89,26 +74,21 @@ private:
ViewChild<std::unique_ptr<PathButtons>> m_pathButtons; ViewChild<std::unique_ptr<PathButtons>> m_pathButtons;
ViewChild<std::unique_ptr<TextField>> m_fileField; ViewChild<std::unique_ptr<TextField>> m_fileField;
struct FileFieldBind : IStringBinding struct FileFieldBind : IStringBinding {
{
FileBrowser& m_browser; FileBrowser& m_browser;
std::string m_name; std::string m_name;
FileFieldBind(FileBrowser& browser, const IViewManager& vm) FileFieldBind(FileBrowser& browser, const IViewManager& vm)
: m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {} : m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {}
std::string_view name(const Control* control) const { return m_name; } std::string_view name(const Control* control) const { return m_name; }
void changed(const Control* control, std::string_view val) void changed(const Control* control, std::string_view val) {}
{
}
} m_fileFieldBind; } m_fileFieldBind;
std::unique_ptr<MessageWindow> m_confirmWindow; std::unique_ptr<MessageWindow> m_confirmWindow;
struct FileListingDataBind : ITableDataBinding, ITableStateBinding struct FileListingDataBind : ITableDataBinding, ITableStateBinding {
{
FileBrowser& m_fb; FileBrowser& m_fb;
struct Entry struct Entry {
{
hecl::SystemString m_path; hecl::SystemString m_path;
std::string m_name; std::string m_name;
std::string m_type; std::string m_type;
@ -127,32 +107,30 @@ private:
size_t columnCount() const { return 3; } size_t columnCount() const { return 3; }
size_t rowCount() const { return m_entries.size(); } size_t rowCount() const { return m_entries.size(); }
std::string_view header(size_t cIdx) const std::string_view header(size_t cIdx) const {
{ switch (cIdx) {
switch (cIdx)
{
case 0: case 0:
return m_nameCol; return m_nameCol;
case 1: case 1:
return m_typeCol; return m_typeCol;
case 2: case 2:
return m_sizeCol; return m_sizeCol;
default: break; default:
break;
} }
return {}; return {};
} }
std::string_view cell(size_t cIdx, size_t rIdx) const std::string_view cell(size_t cIdx, size_t rIdx) const {
{ switch (cIdx) {
switch (cIdx)
{
case 0: case 0:
return m_entries.at(rIdx).m_name; return m_entries.at(rIdx).m_name;
case 1: case 1:
return m_entries.at(rIdx).m_type; return m_entries.at(rIdx).m_type;
case 2: case 2:
return m_entries.at(rIdx).m_size; return m_entries.at(rIdx).m_size;
default: break; default:
break;
} }
return {}; return {};
} }
@ -161,37 +139,26 @@ private:
bool columnSplitResizeAllowed() const { return true; } bool columnSplitResizeAllowed() const { return true; }
float getColumnSplit(size_t cIdx) const float getColumnSplit(size_t cIdx) const { return m_columnSplits[cIdx]; }
{
return m_columnSplits[cIdx];
}
void setColumnSplit(size_t cIdx, float split) void setColumnSplit(size_t cIdx, float split) { m_columnSplits[cIdx] = split; }
{
m_columnSplits[cIdx] = split;
}
void updateListing(const hecl::DirectoryEnumerator& dEnum) void updateListing(const hecl::DirectoryEnumerator& dEnum) {
{
m_entries.clear(); m_entries.clear();
m_entries.reserve(dEnum.size()); m_entries.reserve(dEnum.size());
for (const hecl::DirectoryEnumerator::Entry& d : dEnum) for (const hecl::DirectoryEnumerator::Entry& d : dEnum) {
{
m_entries.emplace_back(); m_entries.emplace_back();
Entry& ent = m_entries.back(); Entry& ent = m_entries.back();
ent.m_path = d.m_path; ent.m_path = d.m_path;
hecl::SystemUTF8Conv nameUtf8(d.m_name); hecl::SystemUTF8Conv nameUtf8(d.m_name);
ent.m_name = nameUtf8.str(); ent.m_name = nameUtf8.str();
if (d.m_isDir) if (d.m_isDir) {
{
if (hecl::SearchForProject(d.m_path)) if (hecl::SearchForProject(d.m_path))
ent.m_type = m_projStr; ent.m_type = m_projStr;
else else
ent.m_type = m_dirStr; ent.m_type = m_dirStr;
} } else {
else
{
ent.m_type = m_fileStr; ent.m_type = m_fileStr;
ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale), ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale),
hecl::HNFlags::B | hecl::HNFlags::Decimal); hecl::HNFlags::B | hecl::HNFlags::Decimal);
@ -205,14 +172,12 @@ private:
SortDirection m_sortDir = SortDirection::Ascending; SortDirection m_sortDir = SortDirection::Ascending;
bool m_needsUpdate = false; bool m_needsUpdate = false;
SortDirection getSort(size_t& cIdx) const SortDirection getSort(size_t& cIdx) const {
{
cIdx = m_sizeSort ? 2 : 0; cIdx = m_sizeSort ? 2 : 0;
return m_sortDir; return m_sortDir;
} }
void setSort(size_t cIdx, SortDirection dir) void setSort(size_t cIdx, SortDirection dir) {
{
if (cIdx == 1) if (cIdx == 1)
return; return;
m_sizeSort = cIdx == 2; m_sizeSort = cIdx == 2;
@ -220,8 +185,7 @@ private:
m_needsUpdate = true; m_needsUpdate = true;
} }
void setSelectedRow(size_t rIdx) void setSelectedRow(size_t rIdx) {
{
if (rIdx != -1) if (rIdx != -1)
m_fb.m_fileField.m_view->setText(m_entries.at(rIdx).m_name); m_fb.m_fileField.m_view->setText(m_entries.at(rIdx).m_name);
else else
@ -229,14 +193,9 @@ private:
m_fb.m_fileField.m_view->clearErrorState(); m_fb.m_fileField.m_view->clearErrorState();
} }
void rowActivated(size_t rIdx) void rowActivated(size_t rIdx) { m_fb.okActivated(false); }
{
m_fb.okActivated(false);
}
FileListingDataBind(FileBrowser& fb, const IViewManager& vm) FileListingDataBind(FileBrowser& fb, const IViewManager& vm) : m_fb(fb) {
: m_fb(fb)
{
m_nameCol = vm.translateOr("name", "Name"); m_nameCol = vm.translateOr("name", "Name");
m_typeCol = vm.translateOr("type", "Type"); m_typeCol = vm.translateOr("type", "Type");
m_sizeCol = vm.translateOr("size", "Size"); m_sizeCol = vm.translateOr("size", "Size");
@ -248,25 +207,20 @@ private:
} m_fileListingBind; } m_fileListingBind;
ViewChild<std::unique_ptr<Table>> m_fileListing; ViewChild<std::unique_ptr<Table>> m_fileListing;
struct BookmarkDataBind : ITableDataBinding, ITableStateBinding struct BookmarkDataBind : ITableDataBinding, ITableStateBinding {
{
FileBrowser& m_fb; FileBrowser& m_fb;
BookmarkDataBind(FileBrowser& fb) : m_fb(fb) {} BookmarkDataBind(FileBrowser& fb) : m_fb(fb) {}
struct Entry struct Entry {
{
hecl::SystemString m_path; hecl::SystemString m_path;
std::string m_name; std::string m_name;
Entry(std::pair<hecl::SystemString, std::string>&& path) Entry(std::pair<hecl::SystemString, std::string>&& path)
: m_path(std::move(path.first)), m_name(std::move(path.second)) {} : m_path(std::move(path.first)), m_name(std::move(path.second)) {}
Entry(hecl::SystemStringView path) Entry(hecl::SystemStringView path) : m_path(path) {
: m_path(path)
{
hecl::SystemUTF8Conv utf8(path); hecl::SystemUTF8Conv utf8(path);
if (utf8.str().size() == 1 && utf8.str()[0] == '/') if (utf8.str().size() == 1 && utf8.str()[0] == '/') {
{
m_name = "/"; m_name = "/";
return; return;
} }
@ -282,21 +236,14 @@ private:
size_t columnCount() const { return 1; } size_t columnCount() const { return 1; }
size_t rowCount() const { return m_entries.size(); } size_t rowCount() const { return m_entries.size(); }
std::string_view cell(size_t, size_t rIdx) const std::string_view cell(size_t, size_t rIdx) const { return m_entries.at(rIdx).m_name; }
{
return m_entries.at(rIdx).m_name;
}
void setSelectedRow(size_t rIdx) void setSelectedRow(size_t rIdx) {
{
if (rIdx != -1) if (rIdx != -1)
m_fb.navigateToPath(m_entries.at(rIdx).m_path); m_fb.navigateToPath(m_entries.at(rIdx).m_path);
} }
void rowActivated(size_t rIdx) void rowActivated(size_t rIdx) { m_fb.okActivated(true); }
{
m_fb.okActivated(true);
}
}; };
BookmarkDataBind m_systemBookmarkBind; BookmarkDataBind m_systemBookmarkBind;
@ -318,17 +265,14 @@ public:
std::function<void(bool, hecl::SystemStringView)> returnFunc) std::function<void(bool, hecl::SystemStringView)> returnFunc)
: FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {} : FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {}
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type, FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
hecl::SystemStringView initialPath, hecl::SystemStringView initialPath, std::function<void(bool, hecl::SystemStringView)> returnFunc);
std::function<void(bool, hecl::SystemStringView)> returnFunc);
static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path); static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path);
static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, const hecl::SystemString& sel);
const hecl::SystemString& sel);
void navigateToPath(hecl::SystemStringView path); void navigateToPath(hecl::SystemStringView path);
bool showingHidden() const { return m_showingHidden; } bool showingHidden() const { return m_showingHidden; }
void setShowingHidden(bool showingHidden) void setShowingHidden(bool showingHidden) {
{
m_showingHidden = showingHidden; m_showingHidden = showingHidden;
navigateToPath(m_path); navigateToPath(m_path);
} }
@ -350,5 +294,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -9,39 +9,35 @@
#include <athena/FileWriter.hpp> #include <athena/FileWriter.hpp>
#include <athena/DNA.hpp> #include <athena/DNA.hpp>
namespace specter namespace specter {
{ class FontTag {
class FontTag
{
friend class FontCache; friend class FontCache;
uint64_t m_hash = 0; uint64_t m_hash = 0;
FontTag(std::string_view name, bool subpixel, float points, unsigned dpi); FontTag(std::string_view name, bool subpixel, float points, unsigned dpi);
public: public:
FontTag() = default; FontTag() = default;
operator bool() const { return m_hash != 0; } operator bool() const { return m_hash != 0; }
uint64_t hash() const { return m_hash; } uint64_t hash() const { return m_hash; }
bool operator==(const FontTag& other) const { return m_hash == other.m_hash; } bool operator==(const FontTag& other) const { return m_hash == other.m_hash; }
}; };
} } // namespace specter
namespace std namespace std {
{ template <>
template <> struct hash<specter::FontTag> struct hash<specter::FontTag> {
{ size_t operator()(const specter::FontTag& handle) const noexcept { return size_t(handle.hash()); }
size_t operator() (const specter::FontTag& handle) const noexcept
{return size_t(handle.hash());}
}; };
} } // namespace std
namespace specter namespace specter {
{
class FreeTypeGZipMemFace class FreeTypeGZipMemFace {
{
FT_Library m_lib; FT_Library m_lib;
FT_StreamRec m_comp = {}; FT_StreamRec m_comp = {};
FT_StreamRec m_decomp = {}; FT_StreamRec m_decomp = {};
FT_Face m_face = nullptr; FT_Face m_face = nullptr;
public: public:
FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz); FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz);
FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete; FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete;
@ -49,13 +45,15 @@ public:
~FreeTypeGZipMemFace() { close(); } ~FreeTypeGZipMemFace() { close(); }
void open(); void open();
void close(); void close();
operator FT_Face() {open(); return m_face;} operator FT_Face() {
open();
return m_face;
}
}; };
using FCharFilter = std::pair<std::string, std::function<bool(uint32_t)>>; using FCharFilter = std::pair<std::string, std::function<bool(uint32_t)>>;
class FontAtlas class FontAtlas {
{
FT_Face m_face; FT_Face m_face;
std::vector<uint8_t> m_texmap; std::vector<uint8_t> m_texmap;
boo::ObjToken<boo::ITextureSA> m_tex; boo::ObjToken<boo::ITextureSA> m_tex;
@ -69,8 +67,7 @@ class FontAtlas
bool m_ready = false; bool m_ready = false;
public: public:
struct Glyph struct Glyph {
{
atUint32 m_unicodePoint; atUint32 m_unicodePoint;
atUint32 m_glyphIdx; atUint32 m_glyphIdx;
atUint32 m_layerIdx; atUint32 m_layerIdx;
@ -87,15 +84,13 @@ private:
std::vector<Glyph> m_glyphs; std::vector<Glyph> m_glyphs;
std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>> m_kernAdjs; std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>> m_kernAdjs;
struct TT_KernHead : athena::io::DNA<athena::Big> struct TT_KernHead : athena::io::DNA<athena::Big> {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> length; Value<atUint32> length;
Value<atUint16> coverage; Value<atUint16> coverage;
}; };
struct TT_KernSubHead : athena::io::DNA<athena::Big> struct TT_KernSubHead : athena::io::DNA<athena::Big> {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint16> nPairs; Value<atUint16> nPairs;
Value<atUint16> searchRange; Value<atUint16> searchRange;
@ -103,8 +98,7 @@ private:
Value<atUint16> rangeShift; Value<atUint16> rangeShift;
}; };
struct TT_KernPair : athena::io::DNA<athena::Big> struct TT_KernPair : athena::io::DNA<athena::Big> {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint16> left; Value<atUint16> left;
Value<atUint16> right; Value<atUint16> right;
@ -116,10 +110,8 @@ private:
std::unordered_map<atUint32, size_t> m_glyphLookup; std::unordered_map<atUint32, size_t> m_glyphLookup;
public: public:
FontAtlas(FT_Face face, uint32_t dpi, FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer);
bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer); FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileReader& reader);
FontAtlas(FT_Face face, uint32_t dpi,
bool subpixel, FCharFilter& filter, athena::io::FileReader& reader);
FontAtlas(const FontAtlas& other) = delete; FontAtlas(const FontAtlas& other) = delete;
FontAtlas& operator=(const FontAtlas& other) = delete; FontAtlas& operator=(const FontAtlas& other) = delete;
@ -131,15 +123,13 @@ public:
boo::ObjToken<boo::ITextureSA> texture(boo::IGraphicsDataFactory* gf) const; boo::ObjToken<boo::ITextureSA> texture(boo::IGraphicsDataFactory* gf) const;
bool subpixel() const { return m_subpixel; } bool subpixel() const { return m_subpixel; }
const Glyph* lookupGlyph(atUint32 charcode) const const Glyph* lookupGlyph(atUint32 charcode) const {
{
auto search = m_glyphLookup.find(charcode); auto search = m_glyphLookup.find(charcode);
if (search == m_glyphLookup.end()) if (search == m_glyphLookup.end())
return nullptr; return nullptr;
return &m_glyphs[search->second]; return &m_glyphs[search->second];
} }
atInt16 lookupKern(atUint32 leftIdx, atUint32 rightIdx) const atInt16 lookupKern(atUint32 leftIdx, atUint32 rightIdx) const {
{
auto pairSearch = m_kernAdjs.find(leftIdx); auto pairSearch = m_kernAdjs.find(leftIdx);
if (pairSearch == m_kernAdjs.cend()) if (pairSearch == m_kernAdjs.cend())
return 0; return 0;
@ -154,12 +144,10 @@ extern const FCharFilter AllCharFilter;
extern const FCharFilter LatinCharFilter; extern const FCharFilter LatinCharFilter;
extern const FCharFilter LatinAndJapaneseCharFilter; extern const FCharFilter LatinAndJapaneseCharFilter;
class FontCache class FontCache {
{
const hecl::Runtime::FileStoreManager& m_fileMgr; const hecl::Runtime::FileStoreManager& m_fileMgr;
hecl::SystemString m_cacheRoot; hecl::SystemString m_cacheRoot;
struct Library struct Library {
{
FT_Library m_lib; FT_Library m_lib;
Library(); Library();
~Library(); ~Library();
@ -170,33 +158,39 @@ class FontCache
FreeTypeGZipMemFace m_curvesFace; FreeTypeGZipMemFace m_curvesFace;
std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases; std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
public: public:
FontCache(const hecl::Runtime::FileStoreManager& fileMgr); FontCache(const hecl::Runtime::FileStoreManager& fileMgr);
FontCache(const FontCache& other) = delete; FontCache(const FontCache& other) = delete;
FontCache& operator=(const FontCache& other) = delete; FontCache& operator=(const FontCache& other) = delete;
FontTag prepCustomFont(std::string_view name, FT_Face face, FontTag prepCustomFont(std::string_view name, FT_Face face, FCharFilter filter = AllCharFilter, bool subpixel = false,
FCharFilter filter=AllCharFilter, bool subpixel=false,
float points = 10.0, uint32_t dpi = 72); float points = 10.0, uint32_t dpi = 72);
FontTag prepMainFont(FCharFilter filter=AllCharFilter, FontTag prepMainFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);} return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);
}
FontTag prepMonoFont(FCharFilter filter=AllCharFilter, FontTag prepMonoFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);} return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);
}
FontTag prepCurvesFont(FCharFilter filter=AllCharFilter, FontTag prepCurvesFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("spectercurves", m_curvesFace, filter, subpixel, points, dpi);} return prepCustomFont("spectercurves", m_curvesFace, filter, subpixel, points, dpi);
}
void closeBuiltinFonts() {m_regFace.close(); m_monoFace.close(); m_curvesFace.close();} void closeBuiltinFonts() {
m_regFace.close();
m_monoFace.close();
m_curvesFace.close();
}
const FontAtlas& lookupAtlas(FontTag tag) const; const FontAtlas& lookupAtlas(FontTag tag) const;
void destroyAtlases() { m_cachedAtlases.clear(); } void destroyAtlases() { m_cachedAtlases.clear(); }
}; };
} } // namespace specter

View File

@ -2,11 +2,9 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
struct IMenuNode struct IMenuNode {
{
virtual boo::ITexture* icon() const { return nullptr; } virtual boo::ITexture* icon() const { return nullptr; }
virtual const std::string* text() const { return nullptr; } virtual const std::string* text() const { return nullptr; }
virtual size_t subNodeCount() const { return 0; } virtual size_t subNodeCount() const { return 0; }
@ -14,5 +12,4 @@ struct IMenuNode
virtual void activated(const boo::SWindowCoord& coord) {} virtual void activated(const boo::SWindowCoord& coord) {}
}; };
} } // namespace specter

View File

@ -4,16 +4,13 @@
#include "SplitView.hpp" #include "SplitView.hpp"
#include <hecl/hecl.hpp> #include <hecl/hecl.hpp>
namespace specter namespace specter {
{
struct ISpaceController; struct ISpaceController;
struct IViewManager struct IViewManager {
{
public: public:
virtual const Translator* getTranslator() const { return nullptr; } virtual const Translator* getTranslator() const { return nullptr; }
virtual std::string_view translateOr(std::string_view key, std::string_view vor) const virtual std::string_view translateOr(std::string_view key, std::string_view vor) const {
{
const Translator* trans = getTranslator(); const Translator* trans = getTranslator();
if (trans) if (trans)
return trans->translateOr(key, vor); return trans->translateOr(key, vor);
@ -30,5 +27,4 @@ public:
virtual void pushRecentFile(hecl::SystemStringView path) {} virtual void pushRecentFile(hecl::SystemStringView path) {}
}; };
} } // namespace specter

View File

@ -2,17 +2,13 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
struct Icon struct Icon {
{
boo::ObjToken<boo::ITexture> m_tex; boo::ObjToken<boo::ITexture> m_tex;
zeus::CVector2f m_uvCoords[4]; zeus::CVector2f m_uvCoords[4];
Icon() = default; Icon() = default;
Icon(const boo::ObjToken<boo::ITexture>& tex, float rect[4]) Icon(const boo::ObjToken<boo::ITexture>& tex, float rect[4]) : m_tex(tex) {
: m_tex(tex)
{
m_uvCoords[0][0] = rect[0]; m_uvCoords[0][0] = rect[0];
m_uvCoords[0][1] = -rect[3]; m_uvCoords[0][1] = -rect[3];
@ -28,29 +24,26 @@ struct Icon
}; };
template <size_t COLS, size_t ROWS> template <size_t COLS, size_t ROWS>
class IconAtlas class IconAtlas {
{
boo::ObjToken<boo::ITextureS> m_tex; boo::ObjToken<boo::ITextureS> m_tex;
Icon m_icons[COLS][ROWS]; Icon m_icons[COLS][ROWS];
Icon MakeIcon(float x, float y) Icon MakeIcon(float x, float y) {
{ float rect[] = {x / float(COLS), y / float(ROWS), x / float(COLS) + 1.f / float(COLS),
float rect[] = {x / float(COLS), y / float(ROWS), y / float(ROWS) + 1.f / float(ROWS)};
x / float(COLS) + 1.f / float(COLS), y / float(ROWS) + 1.f / float(ROWS)};
return Icon(m_tex.get(), rect); return Icon(m_tex.get(), rect);
} }
public: public:
IconAtlas() = default; IconAtlas() = default;
operator bool() const { return m_tex; } operator bool() const { return m_tex; }
void initializeAtlas(const boo::ObjToken<boo::ITextureS>& tex) void initializeAtlas(const boo::ObjToken<boo::ITextureS>& tex) {
{
m_tex = tex; m_tex = tex;
for (int c = 0; c < COLS; ++c) for (int c = 0; c < COLS; ++c)
for (int r = 0; r < ROWS; ++r) for (int r = 0; r < ROWS; ++r)
m_icons[c][r] = MakeIcon(c, r); m_icons[c][r] = MakeIcon(c, r);
} }
void destroyAtlas() void destroyAtlas() {
{
for (int c = 0; c < COLS; ++c) for (int c = 0; c < COLS; ++c)
for (int r = 0; r < ROWS; ++r) for (int r = 0; r < ROWS; ++r)
m_icons[c][r].m_tex.reset(); m_icons[c][r].m_tex.reset();
@ -59,14 +52,13 @@ public:
Icon& getIcon(size_t c, size_t r) { return m_icons[c][r]; } Icon& getIcon(size_t c, size_t r) { return m_icons[c][r]; }
}; };
class IconView : public View class IconView : public View {
{
VertexBufferBindingTex m_vertexBinding; VertexBufferBindingTex m_vertexBinding;
public: public:
IconView(ViewResources& res, View& parentView, Icon& icon); IconView(ViewResources& res, View& parentView, Icon& icon);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -5,11 +5,9 @@
#include "ScrollView.hpp" #include "ScrollView.hpp"
#include "IMenuNode.hpp" #include "IMenuNode.hpp"
namespace specter namespace specter {
{
class Menu : public View class Menu : public View {
{
IMenuNode* m_rootNode; IMenuNode* m_rootNode;
IMenuNode* m_thisNode; IMenuNode* m_thisNode;
std::unique_ptr<Menu> m_subMenu; std::unique_ptr<Menu> m_subMenu;
@ -21,8 +19,7 @@ class Menu : public View
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void setVerts(int width, int height, float pf); void setVerts(int width, int height, float pf);
struct ContentView : View struct ContentView : View {
{
Menu& m_menu; Menu& m_menu;
ContentView(ViewResources& res, Menu& menu); ContentView(ViewResources& res, Menu& menu);
@ -32,8 +29,7 @@ class Menu : public View
size_t m_highlightedItem = -1; size_t m_highlightedItem = -1;
void setHighlightedItem(size_t idx); void setHighlightedItem(size_t idx);
void unsetHighlightedItem(size_t idx) void unsetHighlightedItem(size_t idx) {
{
if (m_highlightedItem == idx) if (m_highlightedItem == idx)
setHighlightedItem(-1); setHighlightedItem(-1);
} }
@ -43,8 +39,7 @@ class Menu : public View
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const { return m_menu.m_cWidth; } int nominalWidth() const { return m_menu.m_cWidth; }
@ -53,8 +48,7 @@ class Menu : public View
std::unique_ptr<ContentView> m_content; std::unique_ptr<ContentView> m_content;
ViewChild<std::unique_ptr<ScrollView>> m_scroll; ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct ItemView : View struct ItemView : View {
{
Menu& m_menu; Menu& m_menu;
std::unique_ptr<TextView> m_textView; std::unique_ptr<TextView> m_textView;
size_t m_idx; size_t m_idx;
@ -89,5 +83,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,18 +4,11 @@
#include "MultiLineTextView.hpp" #include "MultiLineTextView.hpp"
#include "Button.hpp" #include "Button.hpp"
namespace specter namespace specter {
{
class MessageWindow : public ModalWindow class MessageWindow : public ModalWindow {
{
public: public:
enum class Type enum class Type { InfoOk, ErrorOk, ConfirmOkCancel };
{
InfoOk,
ErrorOk,
ConfirmOkCancel
};
private: private:
Type m_type; Type m_type;
@ -23,38 +16,29 @@ private:
std::unique_ptr<MultiLineTextView> m_text; std::unique_ptr<MultiLineTextView> m_text;
struct OKBinding : IButtonBinding struct OKBinding : IButtonBinding {
{
MessageWindow& m_mw; MessageWindow& m_mw;
std::string m_name; std::string m_name;
OKBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {} OKBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {}
std::string_view name(const Control* control) const { return m_name; } std::string_view name(const Control* control) const { return m_name; }
void activated(const Button* button, const boo::SWindowCoord& coord) void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(true); }
{
m_mw.m_func(true);
}
} m_okBind; } m_okBind;
ViewChild<std::unique_ptr<Button>> m_ok; ViewChild<std::unique_ptr<Button>> m_ok;
struct CancelBinding : IButtonBinding struct CancelBinding : IButtonBinding {
{
MessageWindow& m_mw; MessageWindow& m_mw;
std::string m_name; std::string m_name;
CancelBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {} CancelBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {}
std::string_view name(const Control* control) const { return m_name; } std::string_view name(const Control* control) const { return m_name; }
void activated(const Button* button, const boo::SWindowCoord& coord) void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(false); }
{
m_mw.m_func(false);
}
} m_cancelBind; } m_cancelBind;
ViewChild<std::unique_ptr<Button>> m_cancel; ViewChild<std::unique_ptr<Button>> m_cancel;
public: public:
MessageWindow(ViewResources& res, View& parentView, MessageWindow(ViewResources& res, View& parentView, Type type, std::string_view message,
Type type, std::string_view message, std::function<void(bool ok)> func); std::function<void(bool ok)> func);
void updateContentOpacity(float opacity) void updateContentOpacity(float opacity) {
{
zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity); zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity);
ModalWindow::setMultiplyColor(color); ModalWindow::setMultiplyColor(color);
m_text->setMultiplyColor(color); m_text->setMultiplyColor(color);
@ -72,5 +56,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -3,19 +3,10 @@
#include <specter/View.hpp> #include <specter/View.hpp>
#include <specter/MultiLineTextView.hpp> #include <specter/MultiLineTextView.hpp>
namespace specter namespace specter {
{ class ModalWindow : public View {
class ModalWindow : public View
{
public: public:
enum class Phase enum class Phase { BuildIn, ResWait, Showing, BuildOut, Done };
{
BuildIn,
ResWait,
Showing,
BuildOut,
Done
};
private: private:
int m_frame = 0; int m_frame = 0;
@ -36,10 +27,8 @@ private:
ViewBlock m_viewBlock; ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_viewBlockBuf;
union union {
{ struct {
struct
{
SolidShaderVert lineVerts[22]; SolidShaderVert lineVerts[22];
SolidShaderVert fillVerts[16]; SolidShaderVert fillVerts[16];
} m_verts; } m_verts;
@ -54,10 +43,7 @@ private:
void setFillColors(float t); void setFillColors(float t);
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void _loadVerts() void _loadVerts() { m_vertsBinding.load<decltype(_m_verts)>(_m_verts); }
{
m_vertsBinding.load<decltype(_m_verts)>(_m_verts);
}
std::unique_ptr<TextView> m_cornersOutline[4]; std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4]; std::unique_ptr<TextView> m_cornersFilled[4];
@ -79,6 +65,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,11 +4,9 @@
#include "TextView.hpp" #include "TextView.hpp"
#include "FontCache.hpp" #include "FontCache.hpp"
namespace specter namespace specter {
{
class MultiLineTextView : public View class MultiLineTextView : public View {
{
ViewResources& m_viewSystem; ViewResources& m_viewSystem;
std::vector<std::unique_ptr<TextView>> m_lines; std::vector<std::unique_ptr<TextView>> m_lines;
const FontAtlas& m_fontAtlas; const FontAtlas& m_fontAtlas;
@ -21,23 +19,19 @@ class MultiLineTextView : public View
public: public:
MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font, MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
TextView::Alignment align=TextView::Alignment::Left, TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
size_t lineCapacity=256, float lineHeight=1.0); float lineHeight = 1.0);
MultiLineTextView(ViewResources& res, View& parentView, FontTag font, MultiLineTextView(ViewResources& res, View& parentView, FontTag font,
TextView::Alignment align=TextView::Alignment::Left, TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
size_t lineCapacity=256, float lineHeight=1.0); float lineHeight = 1.0);
void typesetGlyphs(std::string_view str, void typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite, unsigned wrap = 0);
const zeus::CColor& defaultColor=zeus::CColor::skWhite, void typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite,
unsigned wrap=0);
void typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite,
unsigned wrap = 0); unsigned wrap = 0);
void colorGlyphs(const zeus::CColor& newColor); void colorGlyphs(const zeus::CColor& newColor);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
for (std::unique_ptr<TextView>& l : m_lines) for (std::unique_ptr<TextView>& l : m_lines)
l->setMultiplyColor(color); l->setMultiplyColor(color);
} }
@ -49,5 +43,4 @@ public:
int nominalHeight() const { return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size(); } int nominalHeight() const { return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size(); }
}; };
} } // namespace specter

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -2,12 +2,10 @@
#include "specter/TextView.hpp" #include "specter/TextView.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class NumericField : public View class NumericField : public View {
{
std::string m_textStr; std::string m_textStr;
std::unique_ptr<TextView> m_text; std::unique_ptr<TextView> m_text;
SolidShaderVert m_verts[28]; SolidShaderVert m_verts[28];
@ -26,9 +24,9 @@ class NumericField : public View
void setHover(); void setHover();
void setPressed(); void setPressed();
void setDisabled(); void setDisabled();
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
friend class Button; friend class Button;
@ -48,5 +46,4 @@ public:
int nominalHeight() const { return m_nomHeight; } int nominalHeight() const { return m_nomHeight; }
}; };
} } // namespace specter

View File

@ -1,13 +1,9 @@
#pragma once #pragma once
namespace specter namespace specter {
{ class Outliner {
class Outliner class Node : public View {
{ struct INodeController {
class Node : public View
{
struct INodeController
{
virtual boo::ITexture* icon() const { return nullptr; } virtual boo::ITexture* icon() const { return nullptr; }
virtual const std::string* text() const { return nullptr; } virtual const std::string* text() const { return nullptr; }
virtual size_t subNodeCount() const { return 0; } virtual size_t subNodeCount() const { return 0; }
@ -21,8 +17,7 @@ class Outliner
bool m_collapsed; bool m_collapsed;
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme); void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme);
@ -38,5 +33,4 @@ class Outliner
void think(); void think();
}; };
}; };
} } // namespace specter

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -3,18 +3,14 @@
#include "Button.hpp" #include "Button.hpp"
#include "ScrollView.hpp" #include "ScrollView.hpp"
namespace specter namespace specter {
{
struct IPathButtonsBinding struct IPathButtonsBinding {
{
virtual void pathButtonActivated(size_t idx) = 0; virtual void pathButtonActivated(size_t idx) = 0;
}; };
class PathButtons : public ScrollView class PathButtons : public ScrollView {
{ struct ContentView : public View {
struct ContentView : public View
{
PathButtons& m_pb; PathButtons& m_pb;
boo::SWindowRect m_scissorRect; boo::SWindowRect m_scissorRect;
@ -23,37 +19,31 @@ class PathButtons : public ScrollView
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
int nominalWidth() const int nominalWidth() const {
{
int ret = 0; int ret = 0;
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
ret += b.m_button.m_view->nominalWidth() + 2; ret += b.m_button.m_view->nominalWidth() + 2;
return ret; return ret;
} }
int nominalHeight() const int nominalHeight() const {
{
return m_pb.m_pathButtons.size() ? m_pb.m_pathButtons[0].m_button.m_view->nominalHeight() : 0; return m_pb.m_pathButtons.size() ? m_pb.m_pathButtons[0].m_button.m_view->nominalHeight() : 0;
} }
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
ContentView(ViewResources& res, PathButtons& pb) ContentView(ViewResources& res, PathButtons& pb) : View(res, pb), m_pb(pb) {}
: View(res, pb), m_pb(pb) {}
}; };
ViewChild<std::unique_ptr<ContentView>> m_contentView; ViewChild<std::unique_ptr<ContentView>> m_contentView;
int m_pathButtonPending = -1; int m_pathButtonPending = -1;
IPathButtonsBinding& m_binding; IPathButtonsBinding& m_binding;
bool m_fillContainer; bool m_fillContainer;
struct PathButton final : IButtonBinding struct PathButton final : IButtonBinding {
{
PathButtons& m_pb; PathButtons& m_pb;
size_t m_idx; size_t m_idx;
ViewChild<std::unique_ptr<Button>> m_button; ViewChild<std::unique_ptr<Button>> m_button;
PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str) PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str) : m_pb(pb), m_idx(idx) {
: m_pb(pb), m_idx(idx)
{
m_button.m_view.reset(new Button(res, pb, this, hecl::SystemUTF8Conv(str).str())); m_button.m_view.reset(new Button(res, pb, this, hecl::SystemUTF8Conv(str).str()));
} }
std::string_view name(const Control* control) const { return m_button.m_view->getText(); } std::string_view name(const Control* control) const { return m_button.m_view->getText(); }
@ -72,5 +62,4 @@ public:
void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
}; };
} } // namespace specter

View File

@ -12,11 +12,9 @@
#include "optional.hpp" #include "optional.hpp"
#include "boo/boo.hpp" #include "boo/boo.hpp"
namespace specter namespace specter {
{
class RootView : public View class RootView : public View {
{
boo::IWindow* m_window = nullptr; boo::IWindow* m_window = nullptr;
boo::ObjToken<boo::ITextureR> m_renderTex; boo::ObjToken<boo::ITextureR> m_renderTex;
boo::SWindowRect m_rootRect = {}; boo::SWindowRect m_rootRect = {};
@ -37,14 +35,12 @@ class RootView : public View
boo::DeferredWindowEvents<RootView> m_events; boo::DeferredWindowEvents<RootView> m_events;
struct SplitMenuSystem : IMenuNode struct SplitMenuSystem : IMenuNode {
{
RootView& m_rv; RootView& m_rv;
std::string m_text; std::string m_text;
SplitView* m_splitView = nullptr; SplitView* m_splitView = nullptr;
enum class Phase enum class Phase {
{
Inactive, Inactive,
InteractiveSplit, InteractiveSplit,
InteractiveJoin, InteractiveJoin,
@ -71,8 +67,7 @@ class RootView : public View
SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx); SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx);
const std::string* text() const { return &m_text; } const std::string* text() const { return &m_text; }
size_t subNodeCount() const { return 2; } size_t subNodeCount() const { return 2; }
IMenuNode* subNode(size_t idx) IMenuNode* subNode(size_t idx) {
{
if (idx) if (idx)
return &m_joinActionNode; return &m_joinActionNode;
else else
@ -83,26 +78,22 @@ class RootView : public View
bool m_deferredSplit = false; bool m_deferredSplit = false;
bool m_deferredJoin = false; bool m_deferredJoin = false;
struct SplitActionNode : IMenuNode struct SplitActionNode : IMenuNode {
{
SplitMenuSystem& m_smn; SplitMenuSystem& m_smn;
std::string m_text; std::string m_text;
SplitActionNode(SplitMenuSystem& smn); SplitActionNode(SplitMenuSystem& smn);
const std::string* text() const { return &m_text; } const std::string* text() const { return &m_text; }
void activated(const boo::SWindowCoord& coord) void activated(const boo::SWindowCoord& coord) {
{
m_smn.m_deferredSplit = true; m_smn.m_deferredSplit = true;
m_smn.m_deferredCoord = coord; m_smn.m_deferredCoord = coord;
} }
} m_splitActionNode; } m_splitActionNode;
struct JoinActionNode : IMenuNode struct JoinActionNode : IMenuNode {
{
SplitMenuSystem& m_smn; SplitMenuSystem& m_smn;
std::string m_text; std::string m_text;
JoinActionNode(SplitMenuSystem& smn); JoinActionNode(SplitMenuSystem& smn);
const std::string* text() const { return &m_text; } const std::string* text() const { return &m_text; }
void activated(const boo::SWindowCoord& coord) void activated(const boo::SWindowCoord& coord) {
{
m_smn.m_deferredJoin = true; m_smn.m_deferredJoin = true;
m_smn.m_deferredCoord = coord; m_smn.m_deferredCoord = coord;
} }
@ -151,8 +142,7 @@ public:
std::vector<View*>& accessContentViews() { return m_views; } std::vector<View*>& accessContentViews() { return m_views; }
void adoptRightClickMenu(std::unique_ptr<View>&& menu, const boo::SWindowCoord& coord) void adoptRightClickMenu(std::unique_ptr<View>&& menu, const boo::SWindowCoord& coord) {
{
m_rightClickMenu.m_view = std::move(menu); m_rightClickMenu.m_view = std::move(menu);
m_rightClickMenuRootAndLoc = subRect(); m_rightClickMenuRootAndLoc = subRect();
m_rightClickMenuRootAndLoc.location[0] = coord.pixel[0]; m_rightClickMenuRootAndLoc.location[0] = coord.pixel[0];
@ -161,61 +151,47 @@ public:
} }
View* getRightClickMenu() { return m_rightClickMenu.m_view.get(); } View* getRightClickMenu() { return m_rightClickMenu.m_view.get(); }
void setActiveTextView(ITextInputView* textView) void setActiveTextView(ITextInputView* textView) {
{
if (m_activeTextView) if (m_activeTextView)
m_activeTextView->setActive(false); m_activeTextView->setActive(false);
m_activeTextView = textView; m_activeTextView = textView;
if (textView) if (textView)
textView->setActive(true); textView->setActive(true);
} }
void setActiveDragView(View* dragView) void setActiveDragView(View* dragView) { m_activeDragView = dragView; }
{ void unsetActiveDragView(View* dragView) {
m_activeDragView = dragView;
}
void unsetActiveDragView(View* dragView)
{
if (dragView == m_activeDragView) if (dragView == m_activeDragView)
m_activeDragView = nullptr; m_activeDragView = nullptr;
} }
void setActiveMenuButton(Button* button) void setActiveMenuButton(Button* button) { m_activeMenuButton = button; }
{ void unsetActiveMenuButton(Button* button) {
m_activeMenuButton = button;
}
void unsetActiveMenuButton(Button* button)
{
if (button == m_activeMenuButton) if (button == m_activeMenuButton)
m_activeMenuButton = nullptr; m_activeMenuButton = nullptr;
} }
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord) void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord) {
{
m_hoverSplitDragView = sv; m_hoverSplitDragView = sv;
m_activeSplitDragView = true; m_activeSplitDragView = true;
sv->startDragSplit(coord); sv->startDragSplit(coord);
} }
bool m_hSplitHover = false; bool m_hSplitHover = false;
void setHorizontalSplitHover(bool hover) void setHorizontalSplitHover(bool hover) {
{
m_hSplitHover = hover; m_hSplitHover = hover;
_updateCursor(); _updateCursor();
} }
bool m_vSplitHover = false; bool m_vSplitHover = false;
void setVerticalSplitHover(bool hover) void setVerticalSplitHover(bool hover) {
{
m_vSplitHover = hover; m_vSplitHover = hover;
_updateCursor(); _updateCursor();
} }
bool m_textFieldHover = false; bool m_textFieldHover = false;
void setTextFieldHover(bool hover) void setTextFieldHover(bool hover) {
{
m_textFieldHover = hover; m_textFieldHover = hover;
_updateCursor(); _updateCursor();
} }
bool m_spaceCornerHover = false; bool m_spaceCornerHover = false;
void setSpaceCornerHover(bool hover) void setSpaceCornerHover(bool hover) {
{
m_spaceCornerHover = hover; m_spaceCornerHover = hover;
_updateCursor(); _updateCursor();
} }
@ -223,16 +199,14 @@ public:
void resetTooltip(ViewResources& res); void resetTooltip(ViewResources& res);
void displayTooltip(std::string_view name, std::string_view help); void displayTooltip(std::string_view name, std::string_view help);
void beginInteractiveJoin(SplitView* sv, const boo::SWindowCoord& coord) void beginInteractiveJoin(SplitView* sv, const boo::SWindowCoord& coord) {
{
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin; m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
m_splitMenuSystem->m_splitView = sv; m_splitMenuSystem->m_splitView = sv;
m_splitMenuSystem->mouseMove(coord); m_splitMenuSystem->mouseMove(coord);
} }
private: private:
void _updateCursor() void _updateCursor() {
{
if (m_spaceCornerHover) if (m_spaceCornerHover)
m_window->setCursor(boo::EMouseCursor::Crosshairs); m_window->setCursor(boo::EMouseCursor::Crosshairs);
else if (m_vSplitHover) else if (m_vSplitHover)
@ -249,5 +223,4 @@ private:
std::unique_ptr<Tooltip> m_tooltip; std::unique_ptr<Tooltip> m_tooltip;
}; };
} } // namespace specter

View File

@ -3,20 +3,13 @@
#include "Button.hpp" #include "Button.hpp"
#include "IViewManager.hpp" #include "IViewManager.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class Button; class Button;
class ScrollView : public View class ScrollView : public View {
{
public: public:
enum class Style enum class Style { Plain, ThinIndicator, SideButtons };
{
Plain,
ThinIndicator,
SideButtons
};
private: private:
Style m_style; Style m_style;
@ -33,36 +26,25 @@ private:
SolidShaderVert m_verts[4]; SolidShaderVert m_verts[4];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
enum class SideButtonState enum class SideButtonState { None, ScrollLeft, ScrollRight } m_sideButtonState = SideButtonState::None;
{ struct SideButtonBinding : IButtonBinding {
None,
ScrollLeft,
ScrollRight
} m_sideButtonState = SideButtonState::None;
struct SideButtonBinding : IButtonBinding
{
ScrollView& m_sv; ScrollView& m_sv;
std::string m_leftName, m_rightName; std::string m_leftName, m_rightName;
SideButtonBinding(ScrollView& sv, IViewManager& vm) SideButtonBinding(ScrollView& sv, IViewManager& vm)
: m_sv(sv), : m_sv(sv)
m_leftName(vm.translateOr("scroll_left", "Scroll Left")), , m_leftName(vm.translateOr("scroll_left", "Scroll Left"))
m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {} , m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {}
std::string_view name(const Control* control) const std::string_view name(const Control* control) const {
{ return (control == reinterpret_cast<Control*>(m_sv.m_sideButtons[0].m_view.get())) ? m_leftName.c_str()
return (control == reinterpret_cast<Control*>(m_sv.m_sideButtons[0].m_view.get())) ? : m_rightName.c_str();
m_leftName.c_str() : m_rightName.c_str();
} }
void down(const Button* button, const boo::SWindowCoord& coord) void down(const Button* button, const boo::SWindowCoord& coord) {
{
if (button == m_sv.m_sideButtons[0].m_view.get()) if (button == m_sv.m_sideButtons[0].m_view.get())
m_sv.m_sideButtonState = SideButtonState::ScrollRight; m_sv.m_sideButtonState = SideButtonState::ScrollRight;
else else
m_sv.m_sideButtonState = SideButtonState::ScrollLeft; m_sv.m_sideButtonState = SideButtonState::ScrollLeft;
} }
void up(const Button* button, const boo::SWindowCoord& coord) void up(const Button* button, const boo::SWindowCoord& coord) { m_sv.m_sideButtonState = SideButtonState::None; }
{
m_sv.m_sideButtonState = SideButtonState::None;
}
} m_sideButtonBind; } m_sideButtonBind;
ViewChild<std::unique_ptr<Button>> m_sideButtons[2]; ViewChild<std::unique_ptr<Button>> m_sideButtons[2];
@ -71,8 +53,7 @@ private:
public: public:
ScrollView(ViewResources& res, View& parentView, Style style); ScrollView(ViewResources& res, View& parentView, Style style);
void setContentView(View* v) void setContentView(View* v) {
{
m_contentView.m_view = v; m_contentView.m_view = v;
updateSize(); updateSize();
} }
@ -96,5 +77,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,26 +4,22 @@
#include "Toolbar.hpp" #include "Toolbar.hpp"
#include "SplitView.hpp" #include "SplitView.hpp"
namespace specter namespace specter {
{
class Space; class Space;
struct ISplitSpaceController; struct ISplitSpaceController;
struct ISpaceController struct ISpaceController {
{
virtual bool spaceSplitAllowed() const { return false; } virtual bool spaceSplitAllowed() const { return false; }
virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) { return nullptr; } virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) { return nullptr; }
}; };
struct ISplitSpaceController struct ISplitSpaceController {
{
virtual SplitView* splitView() = 0; virtual SplitView* splitView() = 0;
virtual void updateSplit(float split) = 0; virtual void updateSplit(float split) = 0;
virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot) = 0; virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot) = 0;
}; };
class Space : public View class Space : public View {
{
friend class RootView; friend class RootView;
ISpaceController& m_controller; ISpaceController& m_controller;
Toolbar::Position m_tbPos; Toolbar::Position m_tbPos;
@ -33,8 +29,7 @@ class Space : public View
bool m_cornerDrag = false; bool m_cornerDrag = false;
int m_cornerDragPoint[2]; int m_cornerDragPoint[2];
struct CornerView : View struct CornerView : View {
{
Space& m_space; Space& m_space;
VertexBufferBindingSolid m_vertexBinding; VertexBufferBindingSolid m_vertexBinding;
bool m_flip; bool m_flip;
@ -51,8 +46,8 @@ class Space : public View
ViewChild<std::unique_ptr<CornerView>> m_cornerView; ViewChild<std::unique_ptr<CornerView>> m_cornerView;
public: public:
Space(ViewResources& res, View& parentView, ISpaceController& controller, Space(ViewResources& res, View& parentView, ISpaceController& controller, Toolbar::Position toolbarPos,
Toolbar::Position toolbarPos, unsigned tbUnits); unsigned tbUnits);
View* setContentView(View* view); View* setContentView(View* view);
Toolbar* toolbar() { return m_toolbar.m_view.get(); } Toolbar* toolbar() { return m_toolbar.m_view.get(); }
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
@ -65,8 +60,7 @@ public:
SplitView* findSplitViewOnSide(SplitView::Axis axis, int side); SplitView* findSplitViewOnSide(SplitView::Axis axis, int side);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
if (m_contentView.m_view) if (m_contentView.m_view)
m_contentView.m_view->setMultiplyColor(color); m_contentView.m_view->setMultiplyColor(color);
@ -78,5 +72,4 @@ public:
}; };
inline Space* View::castToSpace() { return isSpace() ? static_cast<Space*>(this) : nullptr; } inline Space* View::castToSpace() { return isSpace() ? static_cast<Space*>(this) : nullptr; }
} } // namespace specter

View File

@ -2,17 +2,15 @@
#include "specter/View.hpp" #include "specter/View.hpp"
namespace specter namespace specter {
{
struct ISplitSpaceController; struct ISplitSpaceController;
class SplitView : public View class SplitView : public View {
{
friend class RootView; friend class RootView;
friend class Space; friend class Space;
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
friend class SplitView; friend class SplitView;
boo::ObjToken<boo::ITextureS> m_shadingTex; boo::ObjToken<boo::ITextureS> m_shadingTex;
@ -21,19 +19,10 @@ public:
void destroy() { m_shadingTex.reset(); } void destroy() { m_shadingTex.reset(); }
}; };
enum class ArrowDir enum class ArrowDir { Up, Down, Left, Right };
{
Up, enum class Axis { Horizontal, Vertical };
Down,
Left,
Right
};
enum class Axis
{
Horizontal,
Vertical
};
private: private:
ISplitSpaceController* m_controller; ISplitSpaceController* m_controller;
Axis m_axis; Axis m_axis;
@ -48,8 +37,7 @@ private:
int m_clearanceA, m_clearanceB; int m_clearanceA, m_clearanceB;
void setHorizontalVerts(int width) void setHorizontalVerts(int width) {
{
m_splitVerts[0].m_pos.assign(0, 2, 0); m_splitVerts[0].m_pos.assign(0, 2, 0);
m_splitVerts[0].m_uv.assign(0, 0); m_splitVerts[0].m_uv.assign(0, 0);
m_splitVerts[1].m_pos.assign(0, -1, 0); m_splitVerts[1].m_pos.assign(0, -1, 0);
@ -60,8 +48,7 @@ private:
m_splitVerts[3].m_uv.assign(1, 0); m_splitVerts[3].m_uv.assign(1, 0);
} }
void setVerticalVerts(int height) void setVerticalVerts(int height) {
{
m_splitVerts[0].m_pos.assign(-1, height, 0); m_splitVerts[0].m_pos.assign(-1, height, 0);
m_splitVerts[0].m_uv.assign(0, 0); m_splitVerts[0].m_uv.assign(0, 0);
m_splitVerts[1].m_pos.assign(-1, 0, 0); m_splitVerts[1].m_pos.assign(-1, 0, 0);
@ -75,19 +62,19 @@ private:
VertexBufferBindingTex m_splitVertsBinding; VertexBufferBindingTex m_splitVertsBinding;
public: public:
SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
Axis axis, float split, int clearanceA=-1, int clearanceB=-1); int clearanceA = -1, int clearanceB = -1);
View* setContentView(int slot, View* view); View* setContentView(int slot, View* view);
void setSplit(float split); void setSplit(float split);
void setAxis(Axis axis); void setAxis(Axis axis);
Axis axis() const { return m_axis; } Axis axis() const { return m_axis; }
float split() const { return m_slide; } float split() const { return m_slide; }
bool testSplitHover(const boo::SWindowCoord& coord); bool testSplitHover(const boo::SWindowCoord& coord);
bool testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, bool testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, SplitView*& splitOut, int& slotOut,
SplitView*& splitOut, int& slotOut,
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot = -1); boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot = -1);
void getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut); void getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut);
bool testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut); bool testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut, float& splitOut,
Axis& axisOut);
void getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut); void getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut);
void startDragSplit(const boo::SWindowCoord& coord); void startDragSplit(const boo::SWindowCoord& coord);
void endDragSplit(); void endDragSplit();
@ -100,8 +87,7 @@ public:
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
m_splitBlock.m_color = color; m_splitBlock.m_color = color;
m_splitBlockBuf.access().finalAssign(m_splitBlock); m_splitBlockBuf.access().finalAssign(m_splitBlock);
@ -116,5 +102,4 @@ public:
}; };
inline SplitView* View::castToSplitView() { return isSplitView() ? static_cast<SplitView*>(this) : nullptr; } inline SplitView* View::castToSplitView() { return isSplitView() ? static_cast<SplitView*>(this) : nullptr; }
} } // namespace specter

View File

@ -5,38 +5,32 @@
#include "TextView.hpp" #include "TextView.hpp"
#include <array> #include <array>
namespace specter namespace specter {
{
#define SPECTER_TABLE_MAX_ROWS 128ul #define SPECTER_TABLE_MAX_ROWS 128ul
enum class SortDirection enum class SortDirection { None, Ascending, Descending };
{
None,
Ascending,
Descending
};
struct ITableDataBinding struct ITableDataBinding {
{
virtual size_t columnCount() const = 0; virtual size_t columnCount() const = 0;
virtual size_t rowCount() const = 0; virtual size_t rowCount() const = 0;
virtual std::string_view header(size_t cIdx) const { return {}; } virtual std::string_view header(size_t cIdx) const { return {}; }
virtual std::string_view cell(size_t cIdx, size_t rIdx) const { return {}; } virtual std::string_view cell(size_t cIdx, size_t rIdx) const { return {}; }
}; };
struct ITableStateBinding struct ITableStateBinding {
{
virtual float getColumnSplit(size_t cIdx) const { return -1.0; } virtual float getColumnSplit(size_t cIdx) const { return -1.0; }
virtual bool columnSplitResizeAllowed() const { return false; } virtual bool columnSplitResizeAllowed() const { return false; }
virtual void setColumnSplit(size_t cIdx, float split) {} virtual void setColumnSplit(size_t cIdx, float split) {}
virtual SortDirection getSort(size_t& cIdx) const {cIdx = 0; return SortDirection::None;} virtual SortDirection getSort(size_t& cIdx) const {
cIdx = 0;
return SortDirection::None;
}
virtual void setSort(size_t cIdx, SortDirection dir) {} virtual void setSort(size_t cIdx, SortDirection dir) {}
virtual void setSelectedRow(size_t rIdx) {} virtual void setSelectedRow(size_t rIdx) {}
virtual void rowActivated(size_t rIdx) {} virtual void rowActivated(size_t rIdx) {}
}; };
class Table : public View class Table : public View {
{
ITableDataBinding* m_data; ITableDataBinding* m_data;
ITableStateBinding* m_state; ITableStateBinding* m_state;
@ -47,8 +41,7 @@ class Table : public View
size_t m_deferredActivation = -1; size_t m_deferredActivation = -1;
size_t m_clickFrames = 15; size_t m_clickFrames = 15;
struct CellView : public View struct CellView : public View {
{
Table& m_t; Table& m_t;
std::unique_ptr<TextView> m_text; std::unique_ptr<TextView> m_text;
size_t m_c, m_r; size_t m_c, m_r;
@ -67,8 +60,7 @@ class Table : public View
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
std::vector<ViewChild<std::unique_ptr<CellView>>> m_headerViews; std::vector<ViewChild<std::unique_ptr<CellView>>> m_headerViews;
@ -90,8 +82,7 @@ class Table : public View
ViewChild<std::unique_ptr<ScrollView>> m_scroll; ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct RowsView : public View struct RowsView : public View {
{
Table& m_t; Table& m_t;
std::unique_ptr<SolidShaderVert[]> m_verts; std::unique_ptr<SolidShaderVert[]> m_verts;
@ -108,8 +99,7 @@ class Table : public View
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_rowsView; } m_rowsView;
@ -119,8 +109,8 @@ class Table : public View
void _updateData(); void _updateData();
public: public:
Table(ViewResources& res, View& parentView, ITableDataBinding* data, Table(ViewResources& res, View& parentView, ITableDataBinding* data, ITableStateBinding* state = nullptr,
ITableStateBinding* state=nullptr, size_t maxColumns=8); size_t maxColumns = 8);
void cycleSortColumn(size_t c); void cycleSortColumn(size_t c);
void selectRow(size_t r); void selectRow(size_t r);
@ -139,5 +129,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,11 +4,9 @@
#include "TextView.hpp" #include "TextView.hpp"
#include <boo/IWindow.hpp> #include <boo/IWindow.hpp>
namespace specter namespace specter {
{
class TextField : public ITextInputView class TextField : public ITextInputView {
{
bool m_hasTextSet = false; bool m_hasTextSet = false;
bool m_hasMarkSet = false; bool m_hasMarkSet = false;
std::string m_textStr; std::string m_textStr;
@ -54,12 +52,7 @@ class TextField : public ITextInputView
bool m_active = false; bool m_active = false;
bool m_error = false; bool m_error = false;
enum class BGState enum class BGState { Inactive, Hover, Disabled } m_bgState = BGState::Inactive;
{
Inactive,
Hover,
Disabled
} m_bgState = BGState::Inactive;
void setInactive(); void setInactive();
void setHover(); void setHover();
void setDisabled(); void setDisabled();
@ -85,17 +78,14 @@ public:
bool hasMarkedText() const; bool hasMarkedText() const;
std::pair<int, int> markedRange() const; std::pair<int, int> markedRange() const;
std::pair<int, int> selectedRange() const; std::pair<int, int> selectedRange() const;
void setMarkedText(std::string_view str, void setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int,int>& selectedRange,
const std::pair<int, int>& replacementRange); const std::pair<int, int>& replacementRange);
void unmarkText(); void unmarkText();
std::string substringForRange(const std::pair<int,int>& range, std::string substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
std::pair<int,int>& actualRange) const;
void insertText(std::string_view str, const std::pair<int, int>& range); void insertText(std::string_view str, const std::pair<int, int>& range);
int characterIndexAtPoint(const boo::SWindowCoord& point) const; int characterIndexAtPoint(const boo::SWindowCoord& point) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int,int>& range, boo::SWindowRect rectForCharacterRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
std::pair<int,int>& actualRange) const;
void think(); void think();
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
@ -112,8 +102,7 @@ public:
void setSelectionRange(size_t start, size_t count); void setSelectionRange(size_t start, size_t count);
void clearSelectionRange(); void clearSelectionRange();
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
m_viewVertBlock.m_color = color; m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf) if (m_viewVertBlockBuf)
@ -134,5 +123,4 @@ private:
void _setMarkedText(); void _setMarkedText();
}; };
} } // namespace specter

View File

@ -5,29 +5,20 @@
#include "FontCache.hpp" #include "FontCache.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class TextView : public View class TextView : public View {
{
public: public:
enum class Alignment enum class Alignment { Left, Center, Right };
{ struct RenderGlyph {
Left,
Center,
Right
};
struct RenderGlyph
{
zeus::CVector3f m_pos[4]; zeus::CVector3f m_pos[4];
zeus::CMatrix4f m_mv; zeus::CMatrix4f m_mv;
zeus::CVector3f m_uv[4]; zeus::CVector3f m_uv[4];
zeus::CColor m_color; zeus::CColor m_color;
// char _dummy[48]; // char _dummy[48];
RenderGlyph& operator=(const RenderGlyph& other) RenderGlyph& operator=(const RenderGlyph& other) {
{
m_pos[0] = other.m_pos[0]; m_pos[0] = other.m_pos[0];
m_pos[1] = other.m_pos[1]; m_pos[1] = other.m_pos[1];
m_pos[2] = other.m_pos[2]; m_pos[2] = other.m_pos[2];
@ -43,8 +34,7 @@ public:
RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor); RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor);
}; };
struct RenderGlyphInfo struct RenderGlyphInfo {
{
uint32_t m_char; uint32_t m_char;
std::pair<int, int> m_dims; std::pair<int, int> m_dims;
int m_adv; int m_adv;
@ -69,18 +59,14 @@ private:
void _commitResources(size_t capacity); void _commitResources(size_t capacity);
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
friend class TextView; friend class TextView;
friend class MultiLineTextView; friend class MultiLineTextView;
hecl::VertexBufferPool<RenderGlyph> m_glyphPool; hecl::VertexBufferPool<RenderGlyph> m_glyphPool;
void updateBuffers() void updateBuffers() { m_glyphPool.updateBuffers(); }
{
m_glyphPool.updateBuffers();
}
FontCache* m_fcache = nullptr; FontCache* m_fcache = nullptr;
boo::ObjToken<boo::IShaderPipeline> m_regular; boo::ObjToken<boo::IShaderPipeline> m_regular;
@ -88,24 +74,23 @@ public:
void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache); void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache);
void destroy() void destroy() {
{
m_glyphPool.doDestroy(); m_glyphPool.doDestroy();
m_regular.reset(); m_regular.reset();
m_subpixel.reset(); m_subpixel.reset();
} }
}; };
TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align=Alignment::Left, size_t capacity=256); TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align = Alignment::Left,
TextView(ViewResources& res, View& parentView, FontTag font, Alignment align=Alignment::Left, size_t capacity=256); size_t capacity = 256);
TextView(ViewResources& res, View& parentView, FontTag font, Alignment align = Alignment::Left,
size_t capacity = 256);
std::vector<RenderGlyph>& accessGlyphs() { return m_glyphs; } std::vector<RenderGlyph>& accessGlyphs() { return m_glyphs; }
const std::vector<RenderGlyph>& accessGlyphs() const { return m_glyphs; } const std::vector<RenderGlyph>& accessGlyphs() const { return m_glyphs; }
void typesetGlyphs(std::string_view str, void typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite);
const zeus::CColor& defaultColor=zeus::CColor::skWhite); void typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite);
void typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite);
void invalidateGlyphs(); void invalidateGlyphs();
void colorGlyphs(const zeus::CColor& newColor); void colorGlyphs(const zeus::CColor& newColor);
@ -128,5 +113,4 @@ private:
std::vector<RenderGlyphInfo> m_glyphInfo; std::vector<RenderGlyphInfo> m_glyphInfo;
}; };
} } // namespace specter

View File

@ -2,15 +2,12 @@
#include "specter/View.hpp" #include "specter/View.hpp"
namespace specter namespace specter {
{
#define SPECTER_TOOLBAR_GAUGE 28 #define SPECTER_TOOLBAR_GAUGE 28
class Toolbar : public View class Toolbar : public View {
{
public: public:
class Resources class Resources {
{
friend class ViewResources; friend class ViewResources;
friend class Toolbar; friend class Toolbar;
boo::ObjToken<boo::ITextureS> m_shadingTex; boo::ObjToken<boo::ITextureS> m_shadingTex;
@ -19,12 +16,8 @@ public:
void destroy() { m_shadingTex.reset(); } void destroy() { m_shadingTex.reset(); }
}; };
enum class Position enum class Position { None, Bottom, Top };
{
None,
Bottom,
Top
};
private: private:
unsigned m_units; unsigned m_units;
std::vector<std::vector<ViewChild<View*>>> m_children; std::vector<std::vector<ViewChild<View*>>> m_children;
@ -50,20 +43,15 @@ public:
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalHeight() const int nominalHeight() const { return m_nomGauge; }
{
return m_nomGauge;
}
void clear() void clear() {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
u.clear(); u.clear();
} }
void push_back(View* v, unsigned unit); void push_back(View* v, unsigned unit);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
@ -72,5 +60,4 @@ public:
} }
}; };
} } // namespace specter

View File

@ -3,11 +3,9 @@
#include "specter/View.hpp" #include "specter/View.hpp"
#include "specter/MultiLineTextView.hpp" #include "specter/MultiLineTextView.hpp"
namespace specter namespace specter {
{
class Tooltip : public View class Tooltip : public View {
{
ViewBlock m_ttBlock; ViewBlock m_ttBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_ttBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_ttBlockBuf;
SolidShaderVert m_ttVerts[16]; SolidShaderVert m_ttVerts[16];
@ -25,9 +23,9 @@ class Tooltip : public View
std::unique_ptr<TextView> m_cornersOutline[4]; std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4]; std::unique_ptr<TextView> m_cornersFilled[4];
public: public:
Tooltip(ViewResources& res, View& parentView, std::string_view title, Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view message);
std::string_view message);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
@ -35,5 +33,4 @@ public:
int nominalHeight() const { return m_nomHeight; } int nominalHeight() const { return m_nomHeight; }
}; };
} } // namespace specter

View File

@ -3,26 +3,24 @@
#include <string> #include <string>
#include <athena/DNAYaml.hpp> #include <athena/DNAYaml.hpp>
namespace specter namespace specter {
{
class Locale class Locale {
{
std::string_view m_name; std::string_view m_name;
std::string_view m_fullName; std::string_view m_fullName;
std::unique_ptr<athena::io::YAMLNode> m_rootNode; std::unique_ptr<athena::io::YAMLNode> m_rootNode;
const athena::io::YAMLNode* m_langNode; const athena::io::YAMLNode* m_langNode;
public: public:
Locale(std::string_view name, std::string_view fullName, Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength);
const unsigned char* yamlSource, size_t yamlLength);
std::string_view name() const { return m_name; } std::string_view name() const { return m_name; }
std::string_view fullName() const { return m_fullName; } std::string_view fullName() const { return m_fullName; }
const athena::io::YAMLNode* rootNode() const { return m_langNode; } const athena::io::YAMLNode* rootNode() const { return m_langNode; }
}; };
class Translator class Translator {
{
const Locale* m_targetLocale; const Locale* m_targetLocale;
public: public:
Translator(const Locale* targetLocale) { setLocale(targetLocale); } Translator(const Locale* targetLocale) { setLocale(targetLocale); }
void setLocale(const Locale* targetLocale); void setLocale(const Locale* targetLocale);
@ -30,5 +28,4 @@ public:
std::string_view translateOr(std::string_view key, std::string_view vor) const; std::string_view translateOr(std::string_view key, std::string_view vor) const;
}; };
} } // namespace specter

View File

@ -10,39 +10,31 @@
#include "hecl/UniformBufferPool.hpp" #include "hecl/UniformBufferPool.hpp"
#include "hecl/VertexBufferPool.hpp" #include "hecl/VertexBufferPool.hpp"
namespace specter namespace specter {
{
class IThemeData; class IThemeData;
class ViewResources; class ViewResources;
class RootView; class RootView;
extern zeus::CMatrix4f g_PlatformMatrix; extern zeus::CMatrix4f g_PlatformMatrix;
class RectangleConstraint class RectangleConstraint {
{
public: public:
enum class Test enum class Test { Fixed, Minimum, Maximum };
{
Fixed,
Minimum,
Maximum
};
private: private:
int m_x, m_y; int m_x, m_y;
Test m_xtest, m_ytest; Test m_xtest, m_ytest;
public: public:
RectangleConstraint(int x = -1, int y = -1, Test xtest = Test::Fixed, Test ytest = Test::Fixed) RectangleConstraint(int x = -1, int y = -1, Test xtest = Test::Fixed, Test ytest = Test::Fixed)
: m_x(x), m_y(y), m_xtest(xtest), m_ytest(ytest) {} : m_x(x), m_y(y), m_xtest(xtest), m_ytest(ytest) {}
std::pair<int,int> solve(int x, int y) const std::pair<int, int> solve(int x, int y) const {
{
std::pair<int, int> ret; std::pair<int, int> ret;
if (m_x < 0) if (m_x < 0)
ret.first = x; ret.first = x;
else else {
{ switch (m_xtest) {
switch (m_xtest)
{
case Test::Fixed: case Test::Fixed:
ret.first = m_x; ret.first = m_x;
break; break;
@ -57,10 +49,8 @@ public:
if (m_y < 0) if (m_y < 0)
ret.second = y; ret.second = y;
else else {
{ switch (m_ytest) {
switch (m_ytest)
{
case Test::Fixed: case Test::Fixed:
ret.second = m_y; ret.second = m_y;
break; break;
@ -79,59 +69,47 @@ public:
class Space; class Space;
class SplitView; class SplitView;
class View class View {
{
public: public:
struct SolidShaderVert struct SolidShaderVert {
{
zeus::CVector3f m_pos; zeus::CVector3f m_pos;
zeus::CColor m_color = zeus::CColor::skClear; zeus::CColor m_color = zeus::CColor::skClear;
}; };
struct TexShaderVert struct TexShaderVert {
{
zeus::CVector3f m_pos; zeus::CVector3f m_pos;
zeus::CVector2f m_uv; zeus::CVector2f m_uv;
}; };
struct ViewBlock struct ViewBlock {
{
zeus::CMatrix4f m_mv; zeus::CMatrix4f m_mv;
zeus::CColor m_color = zeus::CColor::skWhite; zeus::CColor m_color = zeus::CColor::skWhite;
void setViewRect(const boo::SWindowRect& root, const boo::SWindowRect& sub) void setViewRect(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
m_mv[0][0] = 2.0f / root.size[0]; m_mv[0][0] = 2.0f / root.size[0];
m_mv[1][1] = 2.0f / root.size[1]; m_mv[1][1] = 2.0f / root.size[1];
m_mv[3][0] = sub.location[0] * m_mv[0][0] - 1.0f; m_mv[3][0] = sub.location[0] * m_mv[0][0] - 1.0f;
m_mv[3][1] = sub.location[1] * m_mv[1][1] - 1.0f; m_mv[3][1] = sub.location[1] * m_mv[1][1] - 1.0f;
} }
void finalAssign(const ViewBlock& other) void finalAssign(const ViewBlock& other) {
{
m_mv = g_PlatformMatrix * other.m_mv; m_mv = g_PlatformMatrix * other.m_mv;
m_color = other.m_color; m_color = other.m_color;
} }
}; };
template <typename VertStruct> template <typename VertStruct>
struct VertexBufferBinding struct VertexBufferBinding {
{
typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf; typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf;
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding; boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
void load(const VertStruct* data, size_t count) void load(const VertStruct* data, size_t count) {
{ if (m_vertsBuf) {
if (m_vertsBuf)
{
VertStruct* out = m_vertsBuf.access(); VertStruct* out = m_vertsBuf.access();
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
out[i] = data[i]; out[i] = data[i];
} }
} }
template <typename VertArray> template <typename VertArray>
void load(const VertArray data) void load(const VertArray data) {
{ static_assert(std::is_same<std::remove_all_extents_t<VertArray>, VertStruct>::value, "mismatched type");
static_assert(std::is_same<std::remove_all_extents_t<VertArray>, if (m_vertsBuf) {
VertStruct>::value, "mismatched type");
if (m_vertsBuf)
{
constexpr size_t count = sizeof(VertArray) / sizeof(VertStruct); constexpr size_t count = sizeof(VertArray) / sizeof(VertStruct);
VertStruct* out = m_vertsBuf.access(); VertStruct* out = m_vertsBuf.access();
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
@ -141,16 +119,12 @@ public:
operator const boo::ObjToken<boo::IShaderDataBinding>&() { return m_shaderBinding; } operator const boo::ObjToken<boo::IShaderDataBinding>&() { return m_shaderBinding; }
}; };
struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert> struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert> {
{ void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
void init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf); const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf);
}; };
struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert> struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert> {
{ void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
void init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf, const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture); const boo::ObjToken<boo::ITexture>& texture);
}; };
@ -170,14 +144,12 @@ protected:
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
public: public:
struct Resources struct Resources {
{
hecl::UniformBufferPool<ViewBlock> m_bufPool; hecl::UniformBufferPool<ViewBlock> m_bufPool;
hecl::VertexBufferPool<SolidShaderVert> m_solidPool; hecl::VertexBufferPool<SolidShaderVert> m_solidPool;
hecl::VertexBufferPool<TexShaderVert> m_texPool; hecl::VertexBufferPool<TexShaderVert> m_texPool;
void updateBuffers() void updateBuffers() {
{
m_bufPool.updateBuffers(); m_bufPool.updateBuffers();
m_solidPool.updateBuffers(); m_solidPool.updateBuffers();
m_texPool.updateBuffers(); m_texPool.updateBuffers();
@ -188,8 +160,7 @@ public:
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme); void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() void destroy() {
{
m_bufPool.doDestroy(); m_bufPool.doDestroy();
m_solidPool.doDestroy(); m_solidPool.doDestroy();
m_texPool.doDestroy(); m_texPool.doDestroy();
@ -218,15 +189,13 @@ public:
int height() const { return m_subRect.size[1]; } int height() const { return m_subRect.size[1]; }
void updateSize(); void updateSize();
void setBackground(const zeus::CColor& color) void setBackground(const zeus::CColor& color) {
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_bgRect[i].m_color = color; m_bgRect[i].m_color = color;
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect); m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
virtual void setMultiplyColor(const zeus::CColor& color) virtual void setMultiplyColor(const zeus::CColor& color) {
{
m_viewVertBlock.m_color = color; m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf) if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock); m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
@ -256,8 +225,9 @@ public:
virtual void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {} virtual void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {}
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
virtual void resized(const ViewBlock& vb, const boo::SWindowRect& sub); virtual void resized(const ViewBlock& vb, const boo::SWindowRect& sub);
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor) {
const boo::SWindowRect& scissor) {resized(root, sub);} resized(root, sub);
}
virtual void think() {} virtual void think() {}
virtual void draw(boo::IGraphicsCommandQueue* gfxQ); virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
@ -268,20 +238,16 @@ public:
}; };
template <class ViewPtrType> template <class ViewPtrType>
struct ViewChild struct ViewChild {
{
ViewPtrType m_view = ViewPtrType(); ViewPtrType m_view = ViewPtrType();
bool m_mouseIn = false; bool m_mouseIn = false;
int m_mouseDown = 0; int m_mouseDown = 0;
bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (!m_view) if (!m_view)
return false; return false;
if (m_view->subRect().coordInRect(coord)) if (m_view->subRect().coordInRect(coord)) {
{ if ((m_mouseDown & 1 << int(button)) == 0) {
if ((m_mouseDown & 1 << int(button)) == 0)
{
m_view->mouseDown(coord, button, mod); m_view->mouseDown(coord, button, mod);
m_mouseDown |= 1 << int(button); m_mouseDown |= 1 << int(button);
} }
@ -290,59 +256,47 @@ struct ViewChild
return false; return false;
} }
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (!m_view) if (!m_view)
return; return;
if ((m_mouseDown & 1 << int(button)) != 0) if ((m_mouseDown & 1 << int(button)) != 0) {
{
m_view->mouseUp(coord, button, mod); m_view->mouseUp(coord, button, mod);
m_mouseDown &= ~(1 << int(button)); m_mouseDown &= ~(1 << int(button));
} }
} }
void mouseMove(const boo::SWindowCoord& coord) void mouseMove(const boo::SWindowCoord& coord) {
{
if (!m_view) if (!m_view)
return; return;
if (m_view->subRect().coordInRect(coord)) if (m_view->subRect().coordInRect(coord)) {
{ if (!m_mouseIn) {
if (!m_mouseIn)
{
m_view->mouseEnter(coord); m_view->mouseEnter(coord);
m_mouseIn = true; m_mouseIn = true;
} }
m_view->mouseMove(coord); m_view->mouseMove(coord);
} } else {
else if (m_mouseIn) {
{
if (m_mouseIn)
{
m_view->mouseLeave(coord); m_view->mouseLeave(coord);
m_mouseIn = false; m_mouseIn = false;
} }
} }
} }
void mouseEnter(const boo::SWindowCoord& coord) void mouseEnter(const boo::SWindowCoord& coord) {
{
if (!m_view) if (!m_view)
return; return;
} }
void mouseLeave(const boo::SWindowCoord& coord) void mouseLeave(const boo::SWindowCoord& coord) {
{
if (!m_view) if (!m_view)
return; return;
if (m_mouseIn) if (m_mouseIn) {
{
m_view->mouseLeave(coord); m_view->mouseLeave(coord);
m_mouseIn = false; m_mouseIn = false;
} }
} }
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
{
if (!m_view) if (!m_view)
return; return;
if (m_mouseIn) if (m_mouseIn)
@ -351,20 +305,15 @@ struct ViewChild
}; };
template <class ViewPtrType> template <class ViewPtrType>
struct ScissorViewChild : ViewChild<ViewPtrType> struct ScissorViewChild : ViewChild<ViewPtrType> {
{
using base = ViewChild<ViewPtrType>; using base = ViewChild<ViewPtrType>;
boo::SWindowRect m_scissorRect; boo::SWindowRect m_scissorRect;
bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (!base::m_view) if (!base::m_view)
return false; return false;
if (base::m_view->subRect().coordInRect(coord) && if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
m_scissorRect.coordInRect(coord)) if ((base::m_mouseDown & 1 << int(button)) == 0) {
{
if ((base::m_mouseDown & 1 << int(button)) == 0)
{
base::m_view->mouseDown(coord, button, mod); base::m_view->mouseDown(coord, button, mod);
base::m_mouseDown |= 1 << int(button); base::m_mouseDown |= 1 << int(button);
} }
@ -373,24 +322,17 @@ struct ScissorViewChild : ViewChild<ViewPtrType>
return false; return false;
} }
void mouseMove(const boo::SWindowCoord& coord) void mouseMove(const boo::SWindowCoord& coord) {
{
if (!base::m_view) if (!base::m_view)
return; return;
if (base::m_view->subRect().coordInRect(coord) && if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
m_scissorRect.coordInRect(coord)) if (!base::m_mouseIn) {
{
if (!base::m_mouseIn)
{
base::m_view->mouseEnter(coord); base::m_view->mouseEnter(coord);
base::m_mouseIn = true; base::m_mouseIn = true;
} }
base::m_view->mouseMove(coord); base::m_view->mouseMove(coord);
} } else {
else if (base::m_mouseIn) {
{
if (base::m_mouseIn)
{
base::m_view->mouseLeave(coord); base::m_view->mouseLeave(coord);
base::m_mouseIn = false; base::m_mouseIn = false;
} }
@ -398,5 +340,4 @@ struct ScissorViewChild : ViewChild<ViewPtrType>
} }
}; };
} } // namespace specter

View File

@ -7,10 +7,8 @@
#include <thread> #include <thread>
namespace specter namespace specter {
{ class IThemeData {
class IThemeData
{
public: public:
virtual const zeus::CColor& uiText() const = 0; virtual const zeus::CColor& uiText() const = 0;
virtual const zeus::CColor& uiAltText() const = 0; virtual const zeus::CColor& uiAltText() const = 0;
@ -56,8 +54,7 @@ public:
virtual const zeus::CColor& spaceTriangleShading2() const = 0; virtual const zeus::CColor& spaceTriangleShading2() const = 0;
}; };
class DefaultThemeData : public IThemeData class DefaultThemeData : public IThemeData {
{
zeus::CColor m_uiText = zeus::CColor::skWhite; zeus::CColor m_uiText = zeus::CColor::skWhite;
zeus::CColor m_uiAltText = zeus::CColor::skGrey; zeus::CColor m_uiAltText = zeus::CColor::skGrey;
zeus::CColor m_fieldText = zeus::CColor::skBlack; zeus::CColor m_fieldText = zeus::CColor::skBlack;
@ -146,10 +143,8 @@ public:
virtual const zeus::CColor& spaceTriangleShading2() const { return m_spaceTriangleShading2; } virtual const zeus::CColor& spaceTriangleShading2() const { return m_spaceTriangleShading2; }
}; };
class ViewResources class ViewResources {
{ void init(boo::IGraphicsDataFactory::Context& factory, const IThemeData& theme, FontCache* fcache) {
void init(boo::IGraphicsDataFactory::Context& factory, const IThemeData& theme, FontCache* fcache)
{
m_viewRes.init(factory, theme); m_viewRes.init(factory, theme);
m_textRes.init(factory, fcache); m_textRes.init(factory, fcache);
m_splitRes.init(factory, theme); m_splitRes.init(factory, theme);
@ -186,16 +181,13 @@ public:
ViewResources& operator=(const ViewResources& other) = delete; ViewResources& operator=(const ViewResources& other) = delete;
ViewResources& operator=(ViewResources&& other) = default; ViewResources& operator=(ViewResources&& other) = default;
void updateBuffers() void updateBuffers() {
{
m_viewRes.updateBuffers(); m_viewRes.updateBuffers();
m_textRes.updateBuffers(); m_textRes.updateBuffers();
} }
~ViewResources() ~ViewResources() {
{ if (m_fcacheThread.joinable()) {
if (m_fcacheThread.joinable())
{
m_fcacheInterrupt.store(true); m_fcacheInterrupt.store(true);
m_fcacheThread.join(); m_fcacheThread.join();
} }
@ -216,4 +208,3 @@ public:
const IThemeData& themeData() const { return *m_theme; } const IThemeData& themeData() const { return *m_theme; }
}; };
} // namespace specter } // namespace specter

View File

@ -1,13 +1,9 @@
#pragma once #pragma once
#if __specter__ #if __specter__
#define SPECTER_PROPERTY(n, d) \ #define SPECTER_PROPERTY(n, d) [[using specter: name(n), description(d)]]
[[using specter: name(n), description(d)]] #define SPECTER_ENUM(n, d, et) [[using specter: name(n), description(d), enum_type(et)]]
#define SPECTER_ENUM(n, d, et) \
[[using specter: name(n), description(d), enum_type(et)]]
#else #else
#define SPECTER_PROPERTY(n, d) #define SPECTER_PROPERTY(n, d)
#define SPECTER_ENUM(n, d, et) #define SPECTER_ENUM(n, d, et)
#endif #endif

View File

@ -16,4 +16,3 @@
#include "NodeSocket.hpp" #include "NodeSocket.hpp"
#include "FontCache.hpp" #include "FontCache.hpp"
#include "ViewResources.hpp" #include "ViewResources.hpp"

View File

@ -3,27 +3,25 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Button"); static logvisor::Module Log("specter::Button");
void Button::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void Button::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {}
{
}
Button::Button(ViewResources& res, View& parentView, Button::Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text, Icon* icon,
IButtonBinding* controlBinding, std::string_view text, Icon* icon,
Style style, const zeus::CColor& bgColor, RectangleConstraint constraint) Style style, const zeus::CColor& bgColor, RectangleConstraint constraint)
: Button(res, parentView, controlBinding, text, res.themeData().uiText(), icon, style, bgColor, constraint) {} : Button(res, parentView, controlBinding, text, res.themeData().uiText(), icon, style, bgColor, constraint) {}
Button::Button(ViewResources& res, View& parentView, Button::Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
IButtonBinding* controlBinding, std::string_view text, const zeus::CColor& textColor, const zeus::CColor& textColor, Icon* icon, Style style, const zeus::CColor& bgColor,
Icon* icon, Style style, const zeus::CColor& bgColor, RectangleConstraint constraint) RectangleConstraint constraint)
: Control(res, parentView, controlBinding), : Control(res, parentView, controlBinding)
m_style(style), m_textColor(textColor), m_bgColor(bgColor), m_textStr(text), m_constraint(constraint) , m_style(style)
{ , m_textColor(textColor)
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool , m_bgColor(bgColor)
{ , m_textStr(text)
, m_constraint(constraint) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 40, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 40, m_viewVertBlockBuf);
return true; return true;
@ -32,8 +30,7 @@ Button::Button(ViewResources& res, View& parentView,
m_buttonTarget.m_view.reset(new ButtonTarget(res, *this)); m_buttonTarget.m_view.reset(new ButtonTarget(res, *this));
m_menuTarget.m_view.reset(new MenuTarget(res, *this)); m_menuTarget.m_view.reset(new MenuTarget(res, *this));
if (style == Style::Block) if (style == Style::Block) {
{
zeus::CColor c1 = res.themeData().button1Inactive() * bgColor; zeus::CColor c1 = res.themeData().button1Inactive() * bgColor;
zeus::CColor c2 = res.themeData().button2Inactive() * bgColor; zeus::CColor c2 = res.themeData().button2Inactive() * bgColor;
m_verts[0].m_color = c1; m_verts[0].m_color = c1;
@ -49,9 +46,7 @@ Button::Button(ViewResources& res, View& parentView,
m_verts[34].m_color = c2; m_verts[34].m_color = c2;
for (int i = 35; i < 39; ++i) for (int i = 35; i < 39; ++i)
m_verts[i].m_color = c2; m_verts[i].m_color = c2;
} } else {
else
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_verts[i].m_color = zeus::CColor::skClear; m_verts[i].m_color = zeus::CColor::skClear;
for (int i = 31; i < 35; ++i) for (int i = 31; i < 35; ++i)
@ -71,13 +66,9 @@ Button::Button(ViewResources& res, View& parentView,
setText(m_textStr); setText(m_textStr);
} }
void Button::setText(std::string_view text) void Button::setText(std::string_view text) { setText(text, m_textColor); }
{
setText(text, m_textColor);
}
void Button::setText(std::string_view text, const zeus::CColor& textColor) void Button::setText(std::string_view text, const zeus::CColor& textColor) {
{
m_textStr = text; m_textStr = text;
m_textColor = textColor; m_textColor = textColor;
@ -85,8 +76,7 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int width, height; int width, height;
if (m_style == Style::Block) if (m_style == Style::Block) {
{
m_textWidth = m_text->nominalWidth(); m_textWidth = m_text->nominalWidth();
int nomWidth = m_textWidth + 12 * pf; int nomWidth = m_textWidth + 12 * pf;
if (m_icon) if (m_icon)
@ -136,8 +126,7 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
int arrowX = m_textIconWidth + 5 * pf; int arrowX = m_textIconWidth + 5 * pf;
int arrowY = 7 * pf; int arrowY = 7 * pf;
int menuBgX = m_textIconWidth; int menuBgX = m_textIconWidth;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary) if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
{
menuBgX = 0; menuBgX = 0;
arrowX -= 5 * pf; arrowX -= 5 * pf;
} }
@ -157,9 +146,7 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
m_verts[38].m_pos.assign(m_textIconWidth + 1, 1, 0); m_verts[38].m_pos.assign(m_textIconWidth + 1, 1, 0);
_loadVerts(); _loadVerts();
} } else {
else
{
width = m_text->nominalWidth(); width = m_text->nominalWidth();
height = 10 * pf; height = 10 * pf;
m_verts[0].m_pos.assign(1 * pf, -1 * pf, 0); m_verts[0].m_pos.assign(1 * pf, -1 * pf, 0);
@ -176,11 +163,9 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
m_textIconWidth = width; m_textIconWidth = width;
int arrowLineWidth = 7 * pf; int arrowLineWidth = 7 * pf;
if (m_menuStyle != IButtonBinding::MenuStyle::None) if (m_menuStyle != IButtonBinding::MenuStyle::None) {
{
width += 13 * pf; width += 13 * pf;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary) if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
{
arrowLineWidth = width; arrowLineWidth = width;
arrowX = 1 * pf; arrowX = 1 * pf;
} }
@ -198,8 +183,7 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
m_nomHeight = height; m_nomHeight = height;
} }
void Button::setIcon(Icon* icon) void Button::setIcon(Icon* icon) {
{
if (icon) if (icon)
m_icon.reset(new IconView(rootView().viewRes(), *this, *icon)); m_icon.reset(new IconView(rootView().viewRes(), *this, *icon));
else else
@ -208,8 +192,7 @@ void Button::setIcon(Icon* icon)
updateSize(); updateSize();
} }
void Button::colorGlyphs(const zeus::CColor& newColor) void Button::colorGlyphs(const zeus::CColor& newColor) {
{
m_textColor = newColor; m_textColor = newColor;
m_text->colorGlyphs(newColor); m_text->colorGlyphs(newColor);
for (int i = 28; i < 31; ++i) for (int i = 28; i < 31; ++i)
@ -217,10 +200,8 @@ void Button::colorGlyphs(const zeus::CColor& newColor)
_loadVerts(); _loadVerts();
} }
void Button::ButtonTarget::setInactive() void Button::ButtonTarget::setInactive() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1; m_button.m_verts[0].m_color = c1;
@ -229,9 +210,7 @@ void Button::ButtonTarget::setInactive()
m_button.m_verts[3].m_color = c2; m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2; m_button.m_verts[4].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = zeus::CColor::skClear; m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts(); m_button._loadVerts();
@ -239,10 +218,8 @@ void Button::ButtonTarget::setInactive()
} }
} }
void Button::MenuTarget::setInactive() void Button::MenuTarget::setInactive() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1; m_button.m_verts[31].m_color = c1;
@ -250,9 +227,7 @@ void Button::MenuTarget::setInactive()
m_button.m_verts[33].m_color = c1; m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2; m_button.m_verts[34].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 28; i < 31; ++i) for (int i = 28; i < 31; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor; m_button.m_verts[i].m_color = m_button.m_textColor;
for (int i = 31; i < 35; ++i) for (int i = 31; i < 35; ++i)
@ -261,10 +236,8 @@ void Button::MenuTarget::setInactive()
} }
} }
void Button::ButtonTarget::setHover() void Button::ButtonTarget::setHover() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1; m_button.m_verts[0].m_color = c1;
@ -273,9 +246,7 @@ void Button::ButtonTarget::setHover()
m_button.m_verts[3].m_color = c2; m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2; m_button.m_verts[4].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor; m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts(); m_button._loadVerts();
@ -283,10 +254,8 @@ void Button::ButtonTarget::setHover()
} }
} }
void Button::MenuTarget::setHover() void Button::MenuTarget::setHover() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1; m_button.m_verts[31].m_color = c1;
@ -294,9 +263,7 @@ void Button::MenuTarget::setHover()
m_button.m_verts[33].m_color = c1; m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2; m_button.m_verts[34].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 28; i < 31; ++i) for (int i = 28; i < 31; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor; m_button.m_verts[i].m_color = m_button.m_textColor;
for (int i = 31; i < 35; ++i) for (int i = 31; i < 35; ++i)
@ -305,10 +272,8 @@ void Button::MenuTarget::setHover()
} }
} }
void Button::ButtonTarget::setPressed() void Button::ButtonTarget::setPressed() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1; m_button.m_verts[0].m_color = c1;
@ -317,9 +282,7 @@ void Button::ButtonTarget::setPressed()
m_button.m_verts[3].m_color = c2; m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2; m_button.m_verts[4].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor; m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts(); m_button._loadVerts();
@ -327,10 +290,8 @@ void Button::ButtonTarget::setPressed()
} }
} }
void Button::MenuTarget::setPressed() void Button::MenuTarget::setPressed() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1; m_button.m_verts[31].m_color = c1;
@ -338,9 +299,7 @@ void Button::MenuTarget::setPressed()
m_button.m_verts[33].m_color = c1; m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2; m_button.m_verts[34].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 28; i < 31; ++i) for (int i = 28; i < 31; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor; m_button.m_verts[i].m_color = m_button.m_textColor;
for (int i = 31; i < 35; ++i) for (int i = 31; i < 35; ++i)
@ -349,10 +308,8 @@ void Button::MenuTarget::setPressed()
} }
} }
void Button::ButtonTarget::setDisabled() void Button::ButtonTarget::setDisabled() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1; m_button.m_verts[0].m_color = c1;
@ -361,9 +318,7 @@ void Button::ButtonTarget::setDisabled()
m_button.m_verts[3].m_color = c2; m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2; m_button.m_verts[4].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = zeus::CColor::skClear; m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts(); m_button._loadVerts();
@ -373,10 +328,8 @@ void Button::ButtonTarget::setDisabled()
} }
} }
void Button::MenuTarget::setDisabled() void Button::MenuTarget::setDisabled() {
{ if (m_button.m_style == Style::Block) {
if (m_button.m_style == Style::Block)
{
zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor; zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor; zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1; m_button.m_verts[31].m_color = c1;
@ -384,9 +337,7 @@ void Button::MenuTarget::setDisabled()
m_button.m_verts[33].m_color = c1; m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2; m_button.m_verts[34].m_color = c2;
m_button._loadVerts(); m_button._loadVerts();
} } else {
else
{
zeus::CColor dimText = m_button.m_textColor; zeus::CColor dimText = m_button.m_textColor;
dimText[3] *= 0.5; dimText[3] *= 0.5;
for (int i = 28; i < 31; ++i) for (int i = 28; i < 31; ++i)
@ -397,30 +348,25 @@ void Button::MenuTarget::setDisabled()
} }
} }
void Button::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (m_menuStyle != IButtonBinding::MenuStyle::Primary) if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.mouseDown(coord, button, mod); m_buttonTarget.mouseDown(coord, button, mod);
m_menuTarget.mouseDown(coord, button, mod); m_menuTarget.mouseDown(coord, button, mod);
} }
void Button::ButtonTarget::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::ButtonTarget::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_pressed = true; m_pressed = true;
setPressed(); setPressed();
if (m_button.m_controlBinding) if (m_button.m_controlBinding)
static_cast<IButtonBinding&>(*m_button.m_controlBinding).down(&m_button, coord); static_cast<IButtonBinding&>(*m_button.m_controlBinding).down(&m_button, coord);
} }
void Button::MenuTarget::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::MenuTarget::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_pressed = true; m_pressed = true;
setPressed(); setPressed();
if (m_hovered) if (m_hovered) {
{
Log.report(logvisor::Info, "button menu '%s' activated", m_button.m_textStr.c_str()); Log.report(logvisor::Info, "button menu '%s' activated", m_button.m_textStr.c_str());
if (m_button.m_controlBinding) if (m_button.m_controlBinding) {
{
m_button.m_modalMenu.m_view = static_cast<IButtonBinding&>(*m_button.m_controlBinding).buildMenu(&m_button); m_button.m_modalMenu.m_view = static_cast<IButtonBinding&>(*m_button.m_controlBinding).buildMenu(&m_button);
rootView().setActiveMenuButton(&m_button); rootView().setActiveMenuButton(&m_button);
m_button.updateSize(); m_button.updateSize();
@ -428,21 +374,17 @@ void Button::MenuTarget::mouseDown(const boo::SWindowCoord& coord, boo::EMouseBu
} }
} }
void Button::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (m_menuStyle != IButtonBinding::MenuStyle::Primary) if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.mouseUp(coord, button, mod); m_buttonTarget.mouseUp(coord, button, mod);
m_menuTarget.mouseUp(coord, button, mod); m_menuTarget.mouseUp(coord, button, mod);
} }
void Button::ButtonTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::ButtonTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (m_pressed) {
if (m_pressed)
{
if (m_button.m_controlBinding) if (m_button.m_controlBinding)
static_cast<IButtonBinding&>(*m_button.m_controlBinding).up(&m_button, coord); static_cast<IButtonBinding&>(*m_button.m_controlBinding).up(&m_button, coord);
if (m_hovered) if (m_hovered) {
{
Log.report(logvisor::Info, "button '%s' activated", m_button.m_textStr.c_str()); Log.report(logvisor::Info, "button '%s' activated", m_button.m_textStr.c_str());
if (m_button.m_controlBinding) if (m_button.m_controlBinding)
static_cast<IButtonBinding&>(*m_button.m_controlBinding).activated(&m_button, coord); static_cast<IButtonBinding&>(*m_button.m_controlBinding).activated(&m_button, coord);
@ -455,8 +397,7 @@ void Button::ButtonTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseBu
setInactive(); setInactive();
} }
void Button::MenuTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Button::MenuTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_pressed = false; m_pressed = false;
if (m_hovered) if (m_hovered)
setHover(); setHover();
@ -464,15 +405,13 @@ void Button::MenuTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButt
setInactive(); setInactive();
} }
void Button::mouseMove(const boo::SWindowCoord& coord) void Button::mouseMove(const boo::SWindowCoord& coord) {
{
if (m_menuStyle != IButtonBinding::MenuStyle::Primary) if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.mouseMove(coord); m_buttonTarget.mouseMove(coord);
m_menuTarget.mouseMove(coord); m_menuTarget.mouseMove(coord);
} }
void Button::ButtonTarget::mouseEnter(const boo::SWindowCoord& coord) void Button::ButtonTarget::mouseEnter(const boo::SWindowCoord& coord) {
{
m_hovered = true; m_hovered = true;
if (m_pressed) if (m_pressed)
setPressed(); setPressed();
@ -480,8 +419,7 @@ void Button::ButtonTarget::mouseEnter(const boo::SWindowCoord& coord)
setHover(); setHover();
} }
void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord) void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord) {
{
m_hovered = true; m_hovered = true;
if (m_pressed) if (m_pressed)
setPressed(); setPressed();
@ -489,61 +427,52 @@ void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord)
setHover(); setHover();
} }
void Button::mouseLeave(const boo::SWindowCoord& coord) void Button::mouseLeave(const boo::SWindowCoord& coord) {
{
if (m_menuStyle != IButtonBinding::MenuStyle::Primary) if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.mouseLeave(coord); m_buttonTarget.mouseLeave(coord);
m_menuTarget.mouseLeave(coord); m_menuTarget.mouseLeave(coord);
} }
void Button::ButtonTarget::mouseLeave(const boo::SWindowCoord& coord) void Button::ButtonTarget::mouseLeave(const boo::SWindowCoord& coord) {
{
m_hovered = false; m_hovered = false;
setInactive(); setInactive();
} }
void Button::MenuTarget::mouseLeave(const boo::SWindowCoord& coord) void Button::MenuTarget::mouseLeave(const boo::SWindowCoord& coord) {
{
m_hovered = false; m_hovered = false;
setInactive(); setInactive();
} }
void Button::closeMenu(const boo::SWindowCoord& coord) void Button::closeMenu(const boo::SWindowCoord& coord) {
{
rootView().unsetActiveMenuButton(this); rootView().unsetActiveMenuButton(this);
m_modalMenu.m_view.reset(); m_modalMenu.m_view.reset();
m_menuTarget.mouseMove(coord); m_menuTarget.mouseMove(coord);
} }
void Button::think() void Button::think() {
{
if (m_modalMenu.m_view) if (m_modalMenu.m_view)
m_modalMenu.m_view->think(); m_modalMenu.m_view->think();
} }
void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
boo::SWindowRect textRect = sub; boo::SWindowRect textRect = sub;
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
if (m_icon) if (m_icon) {
{
textRect.location[0] += 18 * pf; textRect.location[0] += 18 * pf;
boo::SWindowRect iconRect = sub; boo::SWindowRect iconRect = sub;
iconRect.size[0] = 16 * pf; iconRect.size[0] = 16 * pf;
iconRect.size[1] = 16 * pf; iconRect.size[1] = 16 * pf;
iconRect.location[1] += 2 * pf; iconRect.location[1] += 2 * pf;
if (m_style == Style::Block) if (m_style == Style::Block) {
{
iconRect.location[0] += 5 * pf; iconRect.location[0] += 5 * pf;
iconRect.location[1] += pf; iconRect.location[1] += pf;
} }
m_icon->resized(root, iconRect); m_icon->resized(root, iconRect);
} }
if (m_style == Style::Block) if (m_style == Style::Block) {
{
textRect.location[0] += 6 * pf; textRect.location[0] += 6 * pf;
textRect.location[1] += 7 * pf; textRect.location[1] += 7 * pf;
} }
@ -552,18 +481,12 @@ void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
textRect.size[1] = m_nomHeight; textRect.size[1] = m_nomHeight;
m_text->resized(root, textRect); m_text->resized(root, textRect);
if (m_style == Style::Block) if (m_style == Style::Block) {
{ if (m_menuStyle == IButtonBinding::MenuStyle::None) {
if (m_menuStyle == IButtonBinding::MenuStyle::None)
{
m_buttonTarget.m_view->resized(root, sub); m_buttonTarget.m_view->resized(root, sub);
} } else if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
else if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
{
m_menuTarget.m_view->resized(root, sub); m_menuTarget.m_view->resized(root, sub);
} } else {
else
{
boo::SWindowRect targetRect = sub; boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_textIconWidth; targetRect.size[0] = m_textIconWidth;
m_buttonTarget.m_view->resized(root, targetRect); m_buttonTarget.m_view->resized(root, targetRect);
@ -571,18 +494,13 @@ void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
targetRect.size[0] = 16 * pf; targetRect.size[0] = 16 * pf;
m_menuTarget.m_view->resized(root, targetRect); m_menuTarget.m_view->resized(root, targetRect);
} }
} } else {
else if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
{
if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
{
boo::SWindowRect targetRect = sub; boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_nomWidth; targetRect.size[0] = m_nomWidth;
targetRect.size[1] = m_nomHeight; targetRect.size[1] = m_nomHeight;
m_menuTarget.m_view->resized(root, targetRect); m_menuTarget.m_view->resized(root, targetRect);
} } else {
else
{
boo::SWindowRect targetRect = sub; boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_textIconWidth + 3 * pf; targetRect.size[0] = m_textIconWidth + 3 * pf;
targetRect.size[1] = m_nomHeight; targetRect.size[1] = m_nomHeight;
@ -593,8 +511,7 @@ void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
} }
} }
if (m_modalMenu.m_view) if (m_modalMenu.m_view) {
{
boo::SWindowRect menuRect = sub; boo::SWindowRect menuRect = sub;
if (m_style == Style::Text) if (m_style == Style::Text)
menuRect.location[1] -= 6 * pf; menuRect.location[1] -= 6 * pf;
@ -602,26 +519,20 @@ void Button::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
} }
} }
void Button::draw(boo::IGraphicsCommandQueue* gfxQ) void Button::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
if (m_style == Style::Block) if (m_style == Style::Block) {
{
gfxQ->draw(0, 28); gfxQ->draw(0, 28);
if (m_menuStyle != IButtonBinding::MenuStyle::None) if (m_menuStyle != IButtonBinding::MenuStyle::None) {
{
gfxQ->draw(31, 4); gfxQ->draw(31, 4);
gfxQ->draw(28, 3); gfxQ->draw(28, 3);
if (m_menuStyle == IButtonBinding::MenuStyle::Auxiliary) if (m_menuStyle == IButtonBinding::MenuStyle::Auxiliary)
gfxQ->draw(35, 4); gfxQ->draw(35, 4);
} }
} } else {
else
{
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
if (m_menuStyle != IButtonBinding::MenuStyle::None) if (m_menuStyle != IButtonBinding::MenuStyle::None) {
{
gfxQ->draw(28, 3); gfxQ->draw(28, 3);
gfxQ->draw(31, 4); gfxQ->draw(31, 4);
} }
@ -636,5 +547,4 @@ void Button::draw(boo::IGraphicsCommandQueue* gfxQ)
m_modalMenu.m_view->draw(gfxQ); m_modalMenu.m_view->draw(gfxQ);
} }
} } // namespace specter

View File

@ -1,12 +1,10 @@
#include "specter/Control.hpp" #include "specter/Control.hpp"
namespace specter namespace specter {
{
Control::Control(ViewResources& res, View& parentView, Control::Control(ViewResources& res, View& parentView, IControlBinding* controlBinding)
IControlBinding* controlBinding)
: View(res, parentView), m_controlBinding(controlBinding) {} : View(res, parentView), m_controlBinding(controlBinding) {}
std::recursive_mutex ITextInputView::m_textInputLk; std::recursive_mutex ITextInputView::m_textInputLk;
} } // namespace specter

View File

@ -2,32 +2,27 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/MessageWindow.hpp" #include "specter/MessageWindow.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::FileBrowser"); static logvisor::Module Log("specter::FileBrowser");
#define BROWSER_MARGIN 8 #define BROWSER_MARGIN 8
#define BROWSER_MIN_WIDTH 600 #define BROWSER_MIN_WIDTH 600
#define BROWSER_MIN_HEIGHT 300 #define BROWSER_MIN_HEIGHT 300
std::vector<hecl::SystemString> FileBrowser::PathComponents(hecl::SystemStringView path) std::vector<hecl::SystemString> FileBrowser::PathComponents(hecl::SystemStringView path) {
{
std::vector<hecl::SystemString> ret; std::vector<hecl::SystemString> ret;
hecl::SystemString sPath(path); hecl::SystemString sPath(path);
hecl::SanitizePath(sPath); hecl::SanitizePath(sPath);
if (sPath.empty()) if (sPath.empty())
return ret; return ret;
auto it = sPath.cbegin(); auto it = sPath.cbegin();
if (*it == _SYS_STR('/')) if (*it == _SYS_STR('/')) {
{
ret.push_back(_SYS_STR("/")); ret.push_back(_SYS_STR("/"));
++it; ++it;
} }
hecl::SystemString comp; hecl::SystemString comp;
for (; it != sPath.cend() ; ++it) for (; it != sPath.cend(); ++it) {
{ if (*it == _SYS_STR('/')) {
if (*it == _SYS_STR('/'))
{
if (comp.empty()) if (comp.empty())
continue; continue;
ret.push_back(std::move(comp)); ret.push_back(std::move(comp));
@ -41,25 +36,23 @@ std::vector<hecl::SystemString> FileBrowser::PathComponents(hecl::SystemStringVi
return ret; return ret;
} }
FileBrowser::FileBrowser(ViewResources& res, View& parentView, std::string_view title, FileBrowser::FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
Type type, hecl::SystemStringView initialPath, hecl::SystemStringView initialPath,
std::function<void(bool, hecl::SystemStringView)> returnFunc) std::function<void(bool, hecl::SystemStringView)> returnFunc)
: ModalWindow(res, parentView, RectangleConstraint(BROWSER_MIN_WIDTH * res.pixelFactor(), : ModalWindow(res, parentView,
BROWSER_MIN_HEIGHT * res.pixelFactor(), RectangleConstraint(BROWSER_MIN_WIDTH * res.pixelFactor(), BROWSER_MIN_HEIGHT * res.pixelFactor(),
RectangleConstraint::Test::Minimum, RectangleConstraint::Test::Minimum, RectangleConstraint::Test::Minimum))
RectangleConstraint::Test::Minimum)), , m_type(type)
m_type(type), , m_left(*this, res)
m_left(*this, res), , m_right(*this, res)
m_right(*this, res), , m_ok(*this, res, title)
m_ok(*this, res, title), , m_cancel(*this, res, rootView().viewManager().translateOr("cancel", "Cancel"))
m_cancel(*this, res, rootView().viewManager().translateOr("cancel", "Cancel")), , m_fileFieldBind(*this, rootView().viewManager())
m_fileFieldBind(*this, rootView().viewManager()), , m_fileListingBind(*this, rootView().viewManager())
m_fileListingBind(*this, rootView().viewManager()), , m_systemBookmarkBind(*this)
m_systemBookmarkBind(*this), , m_projectBookmarkBind(*this)
m_projectBookmarkBind(*this), , m_recentBookmarkBind(*this)
m_recentBookmarkBind(*this), , m_returnFunc(returnFunc) {
m_returnFunc(returnFunc)
{
setBackground({0, 0, 0, 0.5}); setBackground({0, 0, 0, 0.5});
IViewManager& vm = rootView().viewManager(); IViewManager& vm = rootView().viewManager();
@ -68,10 +61,12 @@ FileBrowser::FileBrowser(ViewResources& res, View& parentView, std::string_view
m_fileListing.m_view.reset(new Table(res, *this, &m_fileListingBind, &m_fileListingBind, 3)); m_fileListing.m_view.reset(new Table(res, *this, &m_fileListingBind, &m_fileListingBind, 3));
m_systemBookmarks.m_view.reset(new Table(res, *this, &m_systemBookmarkBind, &m_systemBookmarkBind, 1)); m_systemBookmarks.m_view.reset(new Table(res, *this, &m_systemBookmarkBind, &m_systemBookmarkBind, 1));
m_systemBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); m_systemBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont));
m_systemBookmarksLabel->typesetGlyphs(vm.translateOr("system_locations", "System Locations"), res.themeData().uiText()); m_systemBookmarksLabel->typesetGlyphs(vm.translateOr("system_locations", "System Locations"),
res.themeData().uiText());
m_projectBookmarks.m_view.reset(new Table(res, *this, &m_projectBookmarkBind, &m_projectBookmarkBind, 1)); m_projectBookmarks.m_view.reset(new Table(res, *this, &m_projectBookmarkBind, &m_projectBookmarkBind, 1));
m_projectBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); m_projectBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont));
m_projectBookmarksLabel->typesetGlyphs(vm.translateOr("recent_projects", "Recent Projects"), res.themeData().uiText()); m_projectBookmarksLabel->typesetGlyphs(vm.translateOr("recent_projects", "Recent Projects"),
res.themeData().uiText());
m_recentBookmarks.m_view.reset(new Table(res, *this, &m_recentBookmarkBind, &m_recentBookmarkBind, 1)); m_recentBookmarks.m_view.reset(new Table(res, *this, &m_recentBookmarkBind, &m_recentBookmarkBind, 1));
m_recentBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont)); m_recentBookmarksLabel.reset(new TextView(res, *this, res.m_mainFont));
m_recentBookmarksLabel->typesetGlyphs(vm.translateOr("recent_files", "Recent Files"), res.themeData().uiText()); m_recentBookmarksLabel->typesetGlyphs(vm.translateOr("recent_files", "Recent Files"), res.themeData().uiText());
@ -96,22 +91,18 @@ FileBrowser::FileBrowser(ViewResources& res, View& parentView, std::string_view
navigateToPath(initialPath); navigateToPath(initialPath);
m_split.m_view.reset(new SplitView(res, *this, nullptr, SplitView::Axis::Vertical, 0.2, m_split.m_view.reset(new SplitView(res, *this, nullptr, SplitView::Axis::Vertical, 0.2, 200 * res.pixelFactor(),
200 * res.pixelFactor(), 400 * res.pixelFactor())); 400 * res.pixelFactor()));
m_split.m_view->setContentView(0, &m_left); m_split.m_view->setContentView(0, &m_left);
m_split.m_view->setContentView(1, &m_right); m_split.m_view->setContentView(1, &m_right);
updateContentOpacity(0.0); updateContentOpacity(0.0);
} }
void FileBrowser::SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, void FileBrowser::SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, const hecl::SystemString& sel) {
const hecl::SystemString& sel)
{
size_t idx = 0; size_t idx = 0;
for (const BookmarkDataBind::Entry& e : binding.m_entries) for (const BookmarkDataBind::Entry& e : binding.m_entries) {
{ if (e.m_path == sel) {
if (e.m_path == sel)
{
table.selectRow(idx); table.selectRow(idx);
break; break;
} }
@ -121,16 +112,14 @@ void FileBrowser::SyncBookmarkSelections(Table& table, BookmarkDataBind& binding
table.selectRow(-1); table.selectRow(-1);
} }
void FileBrowser::navigateToPath(hecl::SystemStringView path) void FileBrowser::navigateToPath(hecl::SystemStringView path) {
{
hecl::Sstat theStat; hecl::Sstat theStat;
if (hecl::Stat(path.data(), &theStat)) if (hecl::Stat(path.data(), &theStat))
return; return;
m_path = hecl::SystemString(path); m_path = hecl::SystemString(path);
m_comps = PathComponents(m_path); m_comps = PathComponents(m_path);
if (S_ISREG(theStat.st_mode)) if (S_ISREG(theStat.st_mode)) {
{
hecl::SystemUTF8Conv utf8(m_comps.back()); hecl::SystemUTF8Conv utf8(m_comps.back());
m_fileField.m_view->setText(utf8.str()); m_fileField.m_view->setText(utf8.str());
m_fileField.m_view->clearErrorState(); m_fileField.m_view->clearErrorState();
@ -139,8 +128,7 @@ void FileBrowser::navigateToPath(hecl::SystemStringView path)
hecl::SystemString dir; hecl::SystemString dir;
bool needSlash = false; bool needSlash = false;
for (const hecl::SystemString& d : m_comps) for (const hecl::SystemString& d : m_comps) {
{
if (needSlash) if (needSlash)
dir += _SYS_STR('/'); dir += _SYS_STR('/');
if (d.compare(_SYS_STR("/"))) if (d.compare(_SYS_STR("/")))
@ -154,8 +142,7 @@ void FileBrowser::navigateToPath(hecl::SystemStringView path)
hecl::DirectoryEnumerator dEnum(dir, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, hecl::DirectoryEnumerator dEnum(dir, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted,
m_fileListingBind.m_sizeSort, m_fileListingBind.m_sizeSort,
m_fileListingBind.m_sortDir==SortDirection::Descending, m_fileListingBind.m_sortDir == SortDirection::Descending, !m_showingHidden);
!m_showingHidden);
m_fileListingBind.updateListing(dEnum); m_fileListingBind.updateListing(dEnum);
m_fileListing.m_view->selectRow(-1); m_fileListing.m_view->selectRow(-1);
m_fileListing.m_view->updateData(); m_fileListing.m_view->updateData();
@ -165,8 +152,7 @@ void FileBrowser::navigateToPath(hecl::SystemStringView path)
updateSize(); updateSize();
} }
void FileBrowser::updateContentOpacity(float opacity) void FileBrowser::updateContentOpacity(float opacity) {
{
zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity); zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity);
m_split.m_view->setMultiplyColor(color); m_split.m_view->setMultiplyColor(color);
m_pathButtons.m_view->setMultiplyColor(color); m_pathButtons.m_view->setMultiplyColor(color);
@ -182,14 +168,12 @@ void FileBrowser::updateContentOpacity(float opacity)
m_recentBookmarksLabel->setMultiplyColor(color); m_recentBookmarksLabel->setMultiplyColor(color);
} }
void FileBrowser::okActivated(bool viaButton) void FileBrowser::okActivated(bool viaButton) {
{
IViewManager& vm = rootView().viewManager(); IViewManager& vm = rootView().viewManager();
hecl::SystemString path; hecl::SystemString path;
bool needSlash = false; bool needSlash = false;
for (const hecl::SystemString& d : m_comps) for (const hecl::SystemString& d : m_comps) {
{
if (needSlash) if (needSlash)
path += _SYS_STR('/'); path += _SYS_STR('/');
if (d.compare(_SYS_STR("/"))) if (d.compare(_SYS_STR("/")))
@ -198,12 +182,10 @@ void FileBrowser::okActivated(bool viaButton)
} }
hecl::Sstat theStat; hecl::Sstat theStat;
if (hecl::Stat(path.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) if (hecl::Stat(path.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
{
hecl::SystemUTF8Conv utf8(path); hecl::SystemUTF8Conv utf8(path);
m_fileField.m_view->setErrorState( m_fileField.m_view->setErrorState(
hecl::Format(vm.translateOr("no_access_as_dir", "Unable to access '%s' as directory").data(), hecl::Format(vm.translateOr("no_access_as_dir", "Unable to access '%s' as directory").data(), utf8.c_str()));
utf8.c_str()));
return; return;
} }
@ -211,63 +193,47 @@ void FileBrowser::okActivated(bool viaButton)
path += hecl::SystemStringConv(m_fileField.m_view->getText()).sys_str(); path += hecl::SystemStringConv(m_fileField.m_view->getText()).sys_str();
int err = hecl::Stat(path.c_str(), &theStat); int err = hecl::Stat(path.c_str(), &theStat);
if (m_type == Type::SaveFile) if (m_type == Type::SaveFile) {
{ if (m_fileField.m_view->getText().empty()) {
if (m_fileField.m_view->getText().empty()) m_fileField.m_view->setErrorState(vm.translateOr("file_field_empty", "Unable to save empty file"));
{
m_fileField.m_view->setErrorState(
vm.translateOr("file_field_empty", "Unable to save empty file"));
return; return;
} }
if (!err && !S_ISDIR(theStat.st_mode)) if (!err && !S_ISDIR(theStat.st_mode)) {
{ m_confirmWindow.reset(
m_confirmWindow.reset(new MessageWindow(rootView().viewRes(), *this, new MessageWindow(rootView().viewRes(), *this, MessageWindow::Type::ConfirmOkCancel,
MessageWindow::Type::ConfirmOkCancel,
hecl::Format(vm.translateOr("overwrite_confirm", "Overwrite '%s'?").data(), path.c_str()), hecl::Format(vm.translateOr("overwrite_confirm", "Overwrite '%s'?").data(), path.c_str()),
[&,path](bool ok) [&, path](bool ok) {
{ if (ok) {
if (ok)
{
m_returnFunc(true, path); m_returnFunc(true, path);
m_confirmWindow->close(); m_confirmWindow->close();
close(); close();
} } else
else
m_confirmWindow->close(); m_confirmWindow->close();
})); }));
updateSize(); updateSize();
return; return;
} }
if (!err && S_ISDIR(theStat.st_mode)) if (!err && S_ISDIR(theStat.st_mode)) {
{
navigateToPath(path); navigateToPath(path);
return; return;
} }
m_returnFunc(true, path); m_returnFunc(true, path);
close(); close();
return; return;
} } else if (m_type == Type::SaveDirectory || m_type == Type::NewHECLProject) {
else if (m_type == Type::SaveDirectory || m_type == Type::NewHECLProject) if (m_fileField.m_view->getText().empty()) {
{
if (m_fileField.m_view->getText().empty())
{
m_fileField.m_view->setErrorState( m_fileField.m_view->setErrorState(
vm.translateOr("directory_field_empty", "Unable to make empty-named directory")); vm.translateOr("directory_field_empty", "Unable to make empty-named directory"));
return; return;
} }
if (!err && !S_ISDIR(theStat.st_mode)) if (!err && !S_ISDIR(theStat.st_mode)) {
{ m_fileField.m_view->setErrorState(vm.translateOr("no_overwrite_file", "Unable to make directory over file"));
m_fileField.m_view->setErrorState(
vm.translateOr("no_overwrite_file", "Unable to make directory over file"));
return; return;
} }
if (!err && S_ISDIR(theStat.st_mode)) if (!err && S_ISDIR(theStat.st_mode)) {
{ if (m_type == Type::NewHECLProject) {
if (m_type == Type::NewHECLProject)
{
hecl::ProjectRootPath projRoot = hecl::SearchForProject(path); hecl::ProjectRootPath projRoot = hecl::SearchForProject(path);
if (projRoot) if (projRoot) {
{
m_fileField.m_view->setErrorState( m_fileField.m_view->setErrorState(
vm.translateOr("no_overwrite_project", "Unable to make project within existing project")); vm.translateOr("no_overwrite_project", "Unable to make project within existing project"));
return; return;
@ -281,34 +247,24 @@ void FileBrowser::okActivated(bool viaButton)
return; return;
} }
if (m_type == Type::OpenFile) if (m_type == Type::OpenFile) {
{ if (!err && S_ISDIR(theStat.st_mode)) {
if (!err && S_ISDIR(theStat.st_mode))
{
navigateToPath(path); navigateToPath(path);
return; return;
} } else if (err || !S_ISREG(theStat.st_mode)) {
else if (err || !S_ISREG(theStat.st_mode))
{
hecl::SystemUTF8Conv utf8(path); hecl::SystemUTF8Conv utf8(path);
m_fileField.m_view->setErrorState( m_fileField.m_view->setErrorState(
hecl::Format(vm.translateOr("no_access_as_file", "Unable to access '%s' as file").data(), hecl::Format(vm.translateOr("no_access_as_file", "Unable to access '%s' as file").data(), utf8.c_str()));
utf8.c_str()));
return; return;
} }
m_returnFunc(true, path); m_returnFunc(true, path);
close(); close();
return; return;
} } else if (m_type == Type::OpenDirectory || m_type == Type::OpenHECLProject) {
else if (m_type == Type::OpenDirectory || m_type == Type::OpenHECLProject) if (!viaButton && !err && S_ISDIR(theStat.st_mode)) {
{ if (m_type == Type::OpenHECLProject) {
if (!viaButton && !err && S_ISDIR(theStat.st_mode))
{
if (m_type == Type::OpenHECLProject)
{
hecl::ProjectRootPath projRoot = hecl::SearchForProject(path); hecl::ProjectRootPath projRoot = hecl::SearchForProject(path);
if (projRoot) if (projRoot) {
{
m_returnFunc(true, projRoot.getAbsolutePath()); m_returnFunc(true, projRoot.getAbsolutePath());
close(); close();
return; return;
@ -317,12 +273,10 @@ void FileBrowser::okActivated(bool viaButton)
navigateToPath(path); navigateToPath(path);
return; return;
} }
if (err || !S_ISDIR(theStat.st_mode)) if (err || !S_ISDIR(theStat.st_mode)) {
{
hecl::SystemUTF8Conv utf8(path); hecl::SystemUTF8Conv utf8(path);
m_fileField.m_view->setErrorState( m_fileField.m_view->setErrorState(
hecl::Format(vm.translateOr("no_access_as_dir", "Unable to access '%s' as directory").data(), hecl::Format(vm.translateOr("no_access_as_dir", "Unable to access '%s' as directory").data(), utf8.c_str()));
utf8.c_str()));
return; return;
} }
m_returnFunc(true, path); m_returnFunc(true, path);
@ -331,12 +285,10 @@ void FileBrowser::okActivated(bool viaButton)
} }
} }
void FileBrowser::cancelActivated() void FileBrowser::cancelActivated() {
{
hecl::SystemString path; hecl::SystemString path;
bool needSlash = false; bool needSlash = false;
for (const hecl::SystemString& d : m_comps) for (const hecl::SystemString& d : m_comps) {
{
if (needSlash) if (needSlash)
path += _SYS_STR('/'); path += _SYS_STR('/');
if (d.compare(_SYS_STR("/"))) if (d.compare(_SYS_STR("/")))
@ -351,16 +303,14 @@ void FileBrowser::cancelActivated()
close(); close();
} }
void FileBrowser::pathButtonActivated(size_t idx) void FileBrowser::pathButtonActivated(size_t idx) {
{
if (idx >= m_comps.size()) if (idx >= m_comps.size())
return; return;
hecl::SystemString dir; hecl::SystemString dir;
bool needSlash = false; bool needSlash = false;
size_t i = 0; size_t i = 0;
for (const hecl::SystemString& d : m_comps) for (const hecl::SystemString& d : m_comps) {
{
if (needSlash) if (needSlash)
dir += _SYS_STR('/'); dir += _SYS_STR('/');
if (d.compare(_SYS_STR("/"))) if (d.compare(_SYS_STR("/")))
@ -372,8 +322,7 @@ void FileBrowser::pathButtonActivated(size_t idx)
navigateToPath(dir); navigateToPath(dir);
} }
void FileBrowser::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void FileBrowser::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (skipBuildInAnimation() || closed()) if (skipBuildInAnimation() || closed())
return; return;
@ -391,8 +340,7 @@ void FileBrowser::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton bu
m_cancel.m_button.mouseDown(coord, button, mod); m_cancel.m_button.mouseDown(coord, button, mod);
} }
void FileBrowser::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void FileBrowser::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (closed()) if (closed())
return; return;
@ -412,8 +360,7 @@ void FileBrowser::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton butt
m_confirmWindow->mouseUp(coord, button, mod); m_confirmWindow->mouseUp(coord, button, mod);
} }
void FileBrowser::mouseMove(const boo::SWindowCoord& coord) void FileBrowser::mouseMove(const boo::SWindowCoord& coord) {
{
if (closed()) if (closed())
return; return;
m_split.mouseMove(coord); m_split.mouseMove(coord);
@ -430,8 +377,7 @@ void FileBrowser::mouseMove(const boo::SWindowCoord& coord)
m_confirmWindow->mouseMove(coord); m_confirmWindow->mouseMove(coord);
} }
void FileBrowser::mouseLeave(const boo::SWindowCoord& coord) void FileBrowser::mouseLeave(const boo::SWindowCoord& coord) {
{
if (closed()) if (closed())
return; return;
m_split.mouseLeave(coord); m_split.mouseLeave(coord);
@ -445,30 +391,21 @@ void FileBrowser::mouseLeave(const boo::SWindowCoord& coord)
m_confirmWindow->mouseLeave(coord); m_confirmWindow->mouseLeave(coord);
} }
void FileBrowser::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void FileBrowser::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
{
m_pathButtons.scroll(coord, scroll); m_pathButtons.scroll(coord, scroll);
m_fileListing.scroll(coord, scroll); m_fileListing.scroll(coord, scroll);
} }
void FileBrowser::touchDown(const boo::STouchCoord& coord, uintptr_t tid) void FileBrowser::touchDown(const boo::STouchCoord& coord, uintptr_t tid) {}
{
}
void FileBrowser::touchUp(const boo::STouchCoord& coord, uintptr_t tid) void FileBrowser::touchUp(const boo::STouchCoord& coord, uintptr_t tid) {}
{
}
void FileBrowser::touchMove(const boo::STouchCoord& coord, uintptr_t tid) void FileBrowser::touchMove(const boo::STouchCoord& coord, uintptr_t tid) {}
{
}
void FileBrowser::charKeyDown(unsigned long charcode, boo::EModifierKey mod, bool isRepeat) void FileBrowser::charKeyDown(unsigned long charcode, boo::EModifierKey mod, bool isRepeat) {
{
if (skipBuildInAnimation() || closed()) if (skipBuildInAnimation() || closed())
return; return;
if ((mod & boo::EModifierKey::CtrlCommand) != boo::EModifierKey::None && !isRepeat) if ((mod & boo::EModifierKey::CtrlCommand) != boo::EModifierKey::None && !isRepeat) {
{
if (charcode == 'h' || charcode == 'H') if (charcode == 'h' || charcode == 'H')
setShowingHidden(!showingHidden()); setShowingHidden(!showingHidden());
else if (charcode == 'r' || charcode == 'R') else if (charcode == 'r' || charcode == 'R')
@ -476,16 +413,14 @@ void FileBrowser::charKeyDown(unsigned long charcode, boo::EModifierKey mod, boo
} }
} }
void FileBrowser::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mod, bool isRepeat) void FileBrowser::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mod, bool isRepeat) {
{
if (skipBuildInAnimation() || closed()) if (skipBuildInAnimation() || closed())
return; return;
if (key == boo::ESpecialKey::Enter && !isRepeat) if (key == boo::ESpecialKey::Enter && !isRepeat)
okActivated(true); okActivated(true);
} }
void FileBrowser::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void FileBrowser::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
ModalWindow::resized(root, root); ModalWindow::resized(root, root);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
@ -502,8 +437,7 @@ void FileBrowser::resized(const boo::SWindowRect& root, const boo::SWindowRect&
m_confirmWindow->resized(root, sub); m_confirmWindow->resized(root, sub);
} }
void FileBrowser::LeftSide::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void FileBrowser::LeftSide::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int div = (sub.size[1] - BROWSER_MARGIN * pf) / 3; int div = (sub.size[1] - BROWSER_MARGIN * pf) / 3;
@ -532,8 +466,7 @@ void FileBrowser::LeftSide::resized(const boo::SWindowRect& root, const boo::SWi
m_fb.m_recentBookmarksLabel->resized(root, labelRect); m_fb.m_recentBookmarksLabel->resized(root, labelRect);
} }
void FileBrowser::RightSide::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void FileBrowser::RightSide::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect pathRect = sub; boo::SWindowRect pathRect = sub;
@ -562,8 +495,7 @@ void FileBrowser::RightSide::resized(const boo::SWindowRect& root, const boo::SW
m_fb.m_cancel.m_button.m_view->resized(root, buttonRect); m_fb.m_cancel.m_button.m_view->resized(root, buttonRect);
} }
void FileBrowser::think() void FileBrowser::think() {
{
ModalWindow::think(); ModalWindow::think();
if (m_fileListingBind.m_needsUpdate) if (m_fileListingBind.m_needsUpdate)
navigateToPath(m_path); navigateToPath(m_path);
@ -578,8 +510,7 @@ void FileBrowser::think()
m_confirmWindow->think(); m_confirmWindow->think();
} }
void FileBrowser::draw(boo::IGraphicsCommandQueue* gfxQ) void FileBrowser::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
ModalWindow::draw(gfxQ); ModalWindow::draw(gfxQ);
m_split.m_view->draw(gfxQ); m_split.m_view->draw(gfxQ);
@ -587,8 +518,7 @@ void FileBrowser::draw(boo::IGraphicsCommandQueue* gfxQ)
m_confirmWindow->draw(gfxQ); m_confirmWindow->draw(gfxQ);
} }
void FileBrowser::LeftSide::draw(boo::IGraphicsCommandQueue* gfxQ) void FileBrowser::LeftSide::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
m_fb.m_systemBookmarks.m_view->draw(gfxQ); m_fb.m_systemBookmarks.m_view->draw(gfxQ);
m_fb.m_systemBookmarksLabel->draw(gfxQ); m_fb.m_systemBookmarksLabel->draw(gfxQ);
m_fb.m_projectBookmarks.m_view->draw(gfxQ); m_fb.m_projectBookmarks.m_view->draw(gfxQ);
@ -597,8 +527,7 @@ void FileBrowser::LeftSide::draw(boo::IGraphicsCommandQueue* gfxQ)
m_fb.m_recentBookmarksLabel->draw(gfxQ); m_fb.m_recentBookmarksLabel->draw(gfxQ);
} }
void FileBrowser::RightSide::draw(boo::IGraphicsCommandQueue* gfxQ) void FileBrowser::RightSide::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
m_fb.m_pathButtons.m_view->draw(gfxQ); m_fb.m_pathButtons.m_view->draw(gfxQ);
m_fb.m_fileListing.m_view->draw(gfxQ); m_fb.m_fileListing.m_view->draw(gfxQ);
m_fb.m_ok.m_button.m_view->draw(gfxQ); m_fb.m_ok.m_button.m_view->draw(gfxQ);
@ -606,4 +535,4 @@ void FileBrowser::RightSide::draw(boo::IGraphicsCommandQueue* gfxQ)
m_fb.m_fileField.m_view->draw(gfxQ); m_fb.m_fileField.m_view->draw(gfxQ);
} }
} } // namespace specter

View File

@ -26,27 +26,20 @@ extern "C" size_t SPECTERCURVES_SZ;
extern "C" const FT_Driver_ClassRec tt_driver_class; extern "C" const FT_Driver_ClassRec tt_driver_class;
namespace specter namespace specter {
{
static logvisor::Module Log("specter::FontCache"); static logvisor::Module Log("specter::FontCache");
const FCharFilter AllCharFilter = const FCharFilter AllCharFilter = std::make_pair("all-glyphs", [](uint32_t) -> bool { return true; });
std::make_pair("all-glyphs", [](uint32_t)->bool
{return true;});
const FCharFilter LatinCharFilter = const FCharFilter LatinCharFilter =
std::make_pair("latin-glyphs", [](uint32_t c)->bool std::make_pair("latin-glyphs", [](uint32_t c) -> bool { return c <= 0xff || ((c - 0x2200) <= (0x23FF - 0x2200)); });
{return c <= 0xff || ((c - 0x2200) <= (0x23FF - 0x2200));});
const FCharFilter LatinAndJapaneseCharFilter = const FCharFilter LatinAndJapaneseCharFilter = std::make_pair("latin-and-jp-glyphs", [](uint32_t c) -> bool {
std::make_pair("latin-and-jp-glyphs", [](uint32_t c)->bool return LatinCharFilter.second(c) || ((c - 0x2E00) <= (0x30FF - 0x2E00)) || ((c - 0x4E00) <= (0x9FFF - 0x4E00)) ||
{return LatinCharFilter.second(c) || ((c - 0xFF00) <= (0xFFEF - 0xFF00));
((c - 0x2E00) <= (0x30FF - 0x2E00)) || });
((c - 0x4E00) <= (0x9FFF - 0x4E00)) ||
((c - 0xFF00) <= (0xFFEF - 0xFF00));});
FontTag::FontTag(std::string_view name, bool subpixel, float points, uint32_t dpi) FontTag::FontTag(std::string_view name, bool subpixel, float points, uint32_t dpi) {
{
XXH64_state_t st; XXH64_state_t st;
XXH64_reset(&st, 0); XXH64_reset(&st, 0);
XXH64_update(&st, name.data(), name.size()); XXH64_update(&st, name.data(), name.size());
@ -56,37 +49,26 @@ FontTag::FontTag(std::string_view name, bool subpixel, float points, uint32_t dp
m_hash = XXH64_digest(&st); m_hash = XXH64_digest(&st);
} }
FreeTypeGZipMemFace::FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz) FreeTypeGZipMemFace::FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz) : m_lib(lib) {
: m_lib(lib)
{
m_comp.base = (unsigned char*)data; m_comp.base = (unsigned char*)data;
m_comp.size = sz; m_comp.size = sz;
m_comp.memory = lib->memory; m_comp.memory = lib->memory;
} }
void FreeTypeGZipMemFace::open() void FreeTypeGZipMemFace::open() {
{
if (m_face) if (m_face)
return; return;
if (FT_Stream_OpenGzip(&m_decomp, &m_comp)) if (FT_Stream_OpenGzip(&m_decomp, &m_comp))
Log.report(logvisor::Fatal, "unable to open FreeType gzip stream"); Log.report(logvisor::Fatal, "unable to open FreeType gzip stream");
FT_Open_Args args = FT_Open_Args args = {FT_OPEN_STREAM, nullptr, 0, nullptr, &m_decomp};
{
FT_OPEN_STREAM,
nullptr,
0,
nullptr,
&m_decomp
};
if (FT_Open_Face(m_lib, &args, 0, &m_face)) if (FT_Open_Face(m_lib, &args, 0, &m_face))
Log.report(logvisor::Fatal, "unable to open FreeType gzip face"); Log.report(logvisor::Fatal, "unable to open FreeType gzip face");
} }
void FreeTypeGZipMemFace::close() void FreeTypeGZipMemFace::close() {
{
if (!m_face) if (!m_face)
return; return;
FT_Done_Face(m_face); FT_Done_Face(m_face);
@ -95,8 +77,7 @@ void FreeTypeGZipMemFace::close()
#define TEXMAP_DIM 1024 #define TEXMAP_DIM 1024
static unsigned RoundUpPow2(unsigned v) static unsigned RoundUpPow2(unsigned v) {
{
v--; v--;
v |= v >> 1; v |= v >> 1;
v |= v >> 2; v |= v >> 2;
@ -108,31 +89,25 @@ static unsigned RoundUpPow2(unsigned v)
} }
using GreyPixel = uint8_t; using GreyPixel = uint8_t;
static void MemcpyRect(GreyPixel* img, const FT_Bitmap* bmp, unsigned slice, unsigned x, unsigned y) static void MemcpyRect(GreyPixel* img, const FT_Bitmap* bmp, unsigned slice, unsigned x, unsigned y) {
{
unsigned sy = TEXMAP_DIM * slice + y; unsigned sy = TEXMAP_DIM * slice + y;
for (unsigned i=0 ; i<bmp->rows ; ++i) for (unsigned i = 0; i < bmp->rows; ++i) {
{
const unsigned char* s = &bmp->buffer[bmp->pitch * i]; const unsigned char* s = &bmp->buffer[bmp->pitch * i];
GreyPixel* t = &img[TEXMAP_DIM * (sy + i) + x]; GreyPixel* t = &img[TEXMAP_DIM * (sy + i) + x];
memcpy(t, s, bmp->width); memcpy(t, s, bmp->width);
} }
} }
union RgbaPixel union RgbaPixel {
{
uint8_t rgba[4]; uint8_t rgba[4];
uint32_t pixel; uint32_t pixel;
}; };
static void MemcpyRect(RgbaPixel* img, const FT_Bitmap* bmp, unsigned slice, unsigned x, unsigned y) static void MemcpyRect(RgbaPixel* img, const FT_Bitmap* bmp, unsigned slice, unsigned x, unsigned y) {
{
unsigned sy = TEXMAP_DIM * slice + y; unsigned sy = TEXMAP_DIM * slice + y;
for (unsigned i=0 ; i<bmp->rows ; ++i) for (unsigned i = 0; i < bmp->rows; ++i) {
{
const unsigned char* s = &bmp->buffer[bmp->pitch * i]; const unsigned char* s = &bmp->buffer[bmp->pitch * i];
RgbaPixel* t = &img[TEXMAP_DIM * (sy + i) + x]; RgbaPixel* t = &img[TEXMAP_DIM * (sy + i) + x];
for (unsigned j=0 ; j<bmp->width/3 ; ++j) for (unsigned j = 0; j < bmp->width / 3; ++j) {
{
t[j].rgba[0] = s[j * 3]; t[j].rgba[0] = s[j * 3];
t[j].rgba[1] = s[j * 3 + 1]; t[j].rgba[1] = s[j * 3 + 1];
t[j].rgba[2] = s[j * 3 + 2]; t[j].rgba[2] = s[j * 3 + 2];
@ -141,29 +116,23 @@ static void MemcpyRect(RgbaPixel* img, const FT_Bitmap* bmp, unsigned slice, uns
} }
} }
static inline void GridFitGlyph(FT_GlyphSlot slot, FT_UInt& width, FT_UInt& height) {
static inline void GridFitGlyph(FT_GlyphSlot slot, FT_UInt& width, FT_UInt& height)
{
width = slot->metrics.width >> 6; width = slot->metrics.width >> 6;
height = slot->metrics.height >> 6; height = slot->metrics.height >> 6;
} }
void FontAtlas::buildKernTable(FT_Face face) void FontAtlas::buildKernTable(FT_Face face) {
{ if (face->driver->clazz == &tt_driver_class) {
if (face->driver->clazz == &tt_driver_class)
{
TT_Face ttface = reinterpret_cast<TT_Face>(face); TT_Face ttface = reinterpret_cast<TT_Face>(face);
if (!ttface->kern_table) if (!ttface->kern_table)
return; return;
athena::io::MemoryReader r(ttface->kern_table, ttface->kern_table_size); athena::io::MemoryReader r(ttface->kern_table, ttface->kern_table_size);
auto it = m_kernAdjs.end(); auto it = m_kernAdjs.end();
atUint32 nSubs = r.readUint32Big(); atUint32 nSubs = r.readUint32Big();
for (atUint32 i=0 ; i<nSubs ; ++i) for (atUint32 i = 0; i < nSubs; ++i) {
{
TT_KernHead kernHead; TT_KernHead kernHead;
kernHead.read(r); kernHead.read(r);
if (kernHead.coverage >> 8 != 0) if (kernHead.coverage >> 8 != 0) {
{
r.seek(kernHead.length - 6, athena::Current); r.seek(kernHead.length - 6, athena::Current);
continue; continue;
} }
@ -171,8 +140,7 @@ void FontAtlas::buildKernTable(FT_Face face)
TT_KernSubHead subHead; TT_KernSubHead subHead;
subHead.read(r); subHead.read(r);
for (atUint16 p=0 ; p<subHead.nPairs ; ++p) for (atUint16 p = 0; p < subHead.nPairs; ++p) {
{
TT_KernPair pair; TT_KernPair pair;
pair.read(r); pair.read(r);
if (it == m_kernAdjs.end() || it->first != pair.left) if (it == m_kernAdjs.end() || it->first != pair.left)
@ -187,8 +155,7 @@ void FontAtlas::buildKernTable(FT_Face face)
#define NO_ZLIB 0 #define NO_ZLIB 0
#define ZLIB_BUF_SZ 32768 #define ZLIB_BUF_SZ 32768
static void WriteCompressed(athena::io::FileWriter& writer, const atUint8* data, size_t sz) static void WriteCompressed(athena::io::FileWriter& writer, const atUint8* data, size_t sz) {
{
#if NO_ZLIB #if NO_ZLIB
writer.writeUBytes(data, sz); writer.writeUBytes(data, sz);
return; return;
@ -202,8 +169,7 @@ static void WriteCompressed(athena::io::FileWriter& writer, const atUint8* data,
writer.writeUint32Big(sz); writer.writeUint32Big(sz);
atUint64 adlerPos = writer.position(); atUint64 adlerPos = writer.position();
writer.writeUint32Big(0); /* Space for adler32 */ writer.writeUint32Big(0); /* Space for adler32 */
while (z.avail_in) while (z.avail_in) {
{
z.next_out = compBuf; z.next_out = compBuf;
z.avail_out = ZLIB_BUF_SZ; z.avail_out = ZLIB_BUF_SZ;
deflate(&z, Z_NO_FLUSH); deflate(&z, Z_NO_FLUSH);
@ -211,8 +177,7 @@ static void WriteCompressed(athena::io::FileWriter& writer, const atUint8* data,
} }
int finishCycle = Z_OK; int finishCycle = Z_OK;
while (finishCycle != Z_STREAM_END) while (finishCycle != Z_STREAM_END) {
{
z.next_out = compBuf; z.next_out = compBuf;
z.avail_out = ZLIB_BUF_SZ; z.avail_out = ZLIB_BUF_SZ;
finishCycle = deflate(&z, Z_FINISH); finishCycle = deflate(&z, Z_FINISH);
@ -225,8 +190,7 @@ static void WriteCompressed(athena::io::FileWriter& writer, const atUint8* data,
deflateEnd(&z); deflateEnd(&z);
} }
static bool ReadDecompressed(athena::io::FileReader& reader, atUint8* data, size_t sz) static bool ReadDecompressed(athena::io::FileReader& reader, atUint8* data, size_t sz) {
{
#if NO_ZLIB #if NO_ZLIB
reader.readUBytesToBuf(data, sz); reader.readUBytesToBuf(data, sz);
return true; return true;
@ -240,8 +204,7 @@ static bool ReadDecompressed(athena::io::FileReader& reader, atUint8* data, size
atUint32 adler32 = reader.readUint32Big(); atUint32 adler32 = reader.readUint32Big();
z.avail_out = std::min(sz, size_t(targetSz)); z.avail_out = std::min(sz, size_t(targetSz));
size_t readSz; size_t readSz;
while ((readSz = reader.readUBytesToBuf(compBuf, ZLIB_BUF_SZ))) while ((readSz = reader.readUBytesToBuf(compBuf, ZLIB_BUF_SZ))) {
{
z.next_in = compBuf; z.next_in = compBuf;
z.avail_in = readSz; z.avail_in = readSz;
if (inflate(&z, Z_NO_FLUSH) == Z_STREAM_END) if (inflate(&z, Z_NO_FLUSH) == Z_STREAM_END)
@ -252,14 +215,12 @@ static bool ReadDecompressed(athena::io::FileReader& reader, atUint8* data, size
return adler32 == z.adler; return adler32 == z.adler;
} }
FontAtlas::FontAtlas(FT_Face face, uint32_t dpi, FontAtlas::FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer)
bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer) : m_dpi(dpi)
: m_dpi(dpi), , m_ftXscale(face->size->metrics.x_scale)
m_ftXscale(face->size->metrics.x_scale), , m_ftXPpem(face->size->metrics.x_ppem)
m_ftXPpem(face->size->metrics.x_ppem), , m_lineHeight(face->size->metrics.height)
m_lineHeight(face->size->metrics.height), , m_subpixel(subpixel) {
m_subpixel(subpixel)
{
FT_Int32 baseFlags = FT_LOAD_NO_BITMAP; FT_Int32 baseFlags = FT_LOAD_NO_BITMAP;
if (subpixel) if (subpixel)
baseFlags |= FT_LOAD_TARGET_LCD; baseFlags |= FT_LOAD_TARGET_LCD;
@ -274,10 +235,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
unsigned curLineHeight = 0; unsigned curLineHeight = 0;
unsigned totalHeight = 1; unsigned totalHeight = 1;
m_fullTexmapLayers = 0; m_fullTexmapLayers = 0;
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -285,15 +244,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
FT_Load_Glyph(face, gindex, baseFlags); FT_Load_Glyph(face, gindex, baseFlags);
FT_UInt width, height; FT_UInt width, height;
GridFitGlyph(face->glyph, width, height); GridFitGlyph(face->glyph, width, height);
if (curLineWidth + width + 1 > TEXMAP_DIM) if (curLineWidth + width + 1 > TEXMAP_DIM) {
{
totalHeight += curLineHeight + 1; totalHeight += curLineHeight + 1;
curLineHeight = 0; curLineHeight = 0;
curLineWidth = 1; curLineWidth = 1;
} }
curLineHeight = std::max(curLineHeight, height); curLineHeight = std::max(curLineHeight, height);
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) {
{
totalHeight = 1; totalHeight = 1;
++m_fullTexmapLayers; ++m_fullTexmapLayers;
// printf("StagedB: %u\n", gindex); // printf("StagedB: %u\n", gindex);
@ -314,17 +271,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
writer.writeUint32Big(TEXMAP_DIM); writer.writeUint32Big(TEXMAP_DIM);
writer.writeUint32Big(m_finalHeight); writer.writeUint32Big(m_finalHeight);
if (subpixel) if (subpixel) {
{
/* Allocate texmap */ /* Allocate texmap */
if (m_fullTexmapLayers) if (m_fullTexmapLayers) {
{
// printf("ALLOC: %u\n", fullTexmapLayers + 1); // printf("ALLOC: %u\n", fullTexmapLayers + 1);
size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1); size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1);
m_texmap.resize(count * sizeof(RgbaPixel)); m_texmap.resize(count * sizeof(RgbaPixel));
} } else {
else
{
size_t count = TEXMAP_DIM * totalHeight; size_t count = TEXMAP_DIM * totalHeight;
m_texmap.resize(count * sizeof(RgbaPixel)); m_texmap.resize(count * sizeof(RgbaPixel));
} }
@ -335,10 +288,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
curLineHeight = 0; curLineHeight = 0;
totalHeight = 1; totalHeight = 1;
m_fullTexmapLayers = 0; m_fullTexmapLayers = 0;
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -349,15 +300,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_glyphs.emplace_back(); m_glyphs.emplace_back();
Glyph& g = m_glyphs.back(); Glyph& g = m_glyphs.back();
if (curLineWidth + width + 1 > TEXMAP_DIM) if (curLineWidth + width + 1 > TEXMAP_DIM) {
{
totalHeight += curLineHeight + 1; totalHeight += curLineHeight + 1;
curLineHeight = 0; curLineHeight = 0;
curLineWidth = 1; curLineWidth = 1;
} }
curLineHeight = std::max(curLineHeight, height); curLineHeight = std::max(curLineHeight, height);
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) {
{
totalHeight = 1; totalHeight = 1;
++m_fullTexmapLayers; ++m_fullTexmapLayers;
// printf("RealB: %u\n", gindex); // printf("RealB: %u\n", gindex);
@ -384,18 +333,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
} }
WriteCompressed(writer, m_texmap.data(), m_texmap.size()); WriteCompressed(writer, m_texmap.data(), m_texmap.size());
} } else {
else
{
/* Allocate texmap */ /* Allocate texmap */
if (m_fullTexmapLayers) if (m_fullTexmapLayers) {
{
// printf("ALLOC: %u\n", fullTexmapLayers + 1); // printf("ALLOC: %u\n", fullTexmapLayers + 1);
size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1); size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1);
m_texmap.resize(count * sizeof(GreyPixel)); m_texmap.resize(count * sizeof(GreyPixel));
} } else {
else
{
size_t count = TEXMAP_DIM * totalHeight; size_t count = TEXMAP_DIM * totalHeight;
m_texmap.resize(count * sizeof(GreyPixel)); m_texmap.resize(count * sizeof(GreyPixel));
} }
@ -406,10 +350,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
curLineHeight = 0; curLineHeight = 0;
totalHeight = 1; totalHeight = 1;
m_fullTexmapLayers = 0; m_fullTexmapLayers = 0;
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -420,15 +362,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_glyphs.emplace_back(); m_glyphs.emplace_back();
Glyph& g = m_glyphs.back(); Glyph& g = m_glyphs.back();
if (curLineWidth + width + 1 > TEXMAP_DIM) if (curLineWidth + width + 1 > TEXMAP_DIM) {
{
totalHeight += curLineHeight + 1; totalHeight += curLineHeight + 1;
curLineHeight = 0; curLineHeight = 0;
curLineWidth = 1; curLineWidth = 1;
} }
curLineHeight = std::max(curLineHeight, height); curLineHeight = std::max(curLineHeight, height);
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) {
{
totalHeight = 1; totalHeight = 1;
++m_fullTexmapLayers; ++m_fullTexmapLayers;
// printf("RealB: %u\n", gindex); // printf("RealB: %u\n", gindex);
@ -461,14 +401,12 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_ready = true; m_ready = true;
} }
FontAtlas::FontAtlas(FT_Face face, uint32_t dpi, FontAtlas::FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileReader& reader)
bool subpixel, FCharFilter& filter, athena::io::FileReader& reader) : m_dpi(dpi)
: m_dpi(dpi), , m_ftXscale(face->size->metrics.x_scale)
m_ftXscale(face->size->metrics.x_scale), , m_ftXPpem(face->size->metrics.x_ppem)
m_ftXPpem(face->size->metrics.x_ppem), , m_lineHeight(face->size->metrics.height)
m_lineHeight(face->size->metrics.height), , m_subpixel(subpixel) {
m_subpixel(subpixel)
{
FT_Int32 baseFlags = FT_LOAD_NO_BITMAP; FT_Int32 baseFlags = FT_LOAD_NO_BITMAP;
if (subpixel) if (subpixel)
baseFlags |= FT_LOAD_TARGET_LCD; baseFlags |= FT_LOAD_TARGET_LCD;
@ -479,10 +417,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
size_t glyphCount = 0; size_t glyphCount = 0;
FT_UInt gindex; FT_UInt gindex;
FT_ULong charcode = FT_Get_First_Char(face, &gindex); FT_ULong charcode = FT_Get_First_Char(face, &gindex);
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -496,17 +432,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
reader.readUint32Big(); reader.readUint32Big();
m_finalHeight = reader.readUint32Big(); m_finalHeight = reader.readUint32Big();
if (subpixel) if (subpixel) {
{
/* Allocate texmap */ /* Allocate texmap */
if (m_fullTexmapLayers) if (m_fullTexmapLayers) {
{
// printf("ALLOC: %u\n", fullTexmapLayers + 1); // printf("ALLOC: %u\n", fullTexmapLayers + 1);
size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1); size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1);
m_texmap.resize(count * sizeof(RgbaPixel)); m_texmap.resize(count * sizeof(RgbaPixel));
} } else {
else
{
size_t count = TEXMAP_DIM * m_finalHeight; size_t count = TEXMAP_DIM * m_finalHeight;
m_texmap.resize(count * sizeof(RgbaPixel)); m_texmap.resize(count * sizeof(RgbaPixel));
} }
@ -517,10 +449,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
unsigned curLineHeight = 0; unsigned curLineHeight = 0;
unsigned totalHeight = 1; unsigned totalHeight = 1;
m_fullTexmapLayers = 0; m_fullTexmapLayers = 0;
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -531,15 +461,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_glyphs.emplace_back(); m_glyphs.emplace_back();
Glyph& g = m_glyphs.back(); Glyph& g = m_glyphs.back();
if (curLineWidth + width + 1 > TEXMAP_DIM) if (curLineWidth + width + 1 > TEXMAP_DIM) {
{
totalHeight += curLineHeight + 1; totalHeight += curLineHeight + 1;
curLineHeight = 0; curLineHeight = 0;
curLineWidth = 1; curLineWidth = 1;
} }
curLineHeight = std::max(curLineHeight, height); curLineHeight = std::max(curLineHeight, height);
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) {
{
totalHeight = 1; totalHeight = 1;
++m_fullTexmapLayers; ++m_fullTexmapLayers;
// printf("RealB: %u\n", gindex); // printf("RealB: %u\n", gindex);
@ -566,18 +494,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
if (!ReadDecompressed(reader, m_texmap.data(), m_texmap.size())) if (!ReadDecompressed(reader, m_texmap.data(), m_texmap.size()))
return; return;
} } else {
else
{
/* Allocate texmap */ /* Allocate texmap */
if (m_fullTexmapLayers) if (m_fullTexmapLayers) {
{
// printf("ALLOC: %u\n", fullTexmapLayers + 1); // printf("ALLOC: %u\n", fullTexmapLayers + 1);
size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1); size_t count = TEXMAP_DIM * TEXMAP_DIM * (m_fullTexmapLayers + 1);
m_texmap.resize(count * sizeof(GreyPixel)); m_texmap.resize(count * sizeof(GreyPixel));
} } else {
else
{
size_t count = TEXMAP_DIM * m_finalHeight; size_t count = TEXMAP_DIM * m_finalHeight;
m_texmap.resize(count * sizeof(GreyPixel)); m_texmap.resize(count * sizeof(GreyPixel));
} }
@ -588,10 +511,8 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
unsigned curLineHeight = 0; unsigned curLineHeight = 0;
unsigned totalHeight = 1; unsigned totalHeight = 1;
m_fullTexmapLayers = 0; m_fullTexmapLayers = 0;
while (gindex != 0) while (gindex != 0) {
{ if (!filter.second(charcode)) {
if (!filter.second(charcode))
{
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
continue; continue;
} }
@ -602,15 +523,13 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_glyphs.emplace_back(); m_glyphs.emplace_back();
Glyph& g = m_glyphs.back(); Glyph& g = m_glyphs.back();
if (curLineWidth + width + 1 > TEXMAP_DIM) if (curLineWidth + width + 1 > TEXMAP_DIM) {
{
totalHeight += curLineHeight + 1; totalHeight += curLineHeight + 1;
curLineHeight = 0; curLineHeight = 0;
curLineWidth = 1; curLineWidth = 1;
} }
curLineHeight = std::max(curLineHeight, height); curLineHeight = std::max(curLineHeight, height);
if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) if (totalHeight + curLineHeight + 1 > TEXMAP_DIM) {
{
totalHeight = 1; totalHeight = 1;
++m_fullTexmapLayers; ++m_fullTexmapLayers;
// printf("RealB: %u\n", gindex); // printf("RealB: %u\n", gindex);
@ -643,56 +562,45 @@ FontAtlas::FontAtlas(FT_Face face, uint32_t dpi,
m_ready = true; m_ready = true;
} }
boo::ObjToken<boo::ITextureSA> FontAtlas::texture(boo::IGraphicsDataFactory* gf) const boo::ObjToken<boo::ITextureSA> FontAtlas::texture(boo::IGraphicsDataFactory* gf) const {
{
if (!m_ready) if (!m_ready)
return {}; return {};
if (m_tex) if (m_tex)
return m_tex; return m_tex;
gf->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) gf->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
{
if (m_subpixel) if (m_subpixel)
const_cast<boo::ObjToken<boo::ITextureSA>&>(m_tex) = const_cast<boo::ObjToken<boo::ITextureSA>&>(m_tex) =
ctx.newStaticArrayTexture(TEXMAP_DIM, m_finalHeight, m_fullTexmapLayers + 1, 1, ctx.newStaticArrayTexture(TEXMAP_DIM, m_finalHeight, m_fullTexmapLayers + 1, 1, boo::TextureFormat::RGBA8,
boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, boo::TextureClampMode::Repeat, m_texmap.data(), m_texmap.size());
m_texmap.data(), m_texmap.size());
else else
const_cast<boo::ObjToken<boo::ITextureSA>&>(m_tex) = const_cast<boo::ObjToken<boo::ITextureSA>&>(m_tex) =
ctx.newStaticArrayTexture(TEXMAP_DIM, m_finalHeight, m_fullTexmapLayers + 1, 1, ctx.newStaticArrayTexture(TEXMAP_DIM, m_finalHeight, m_fullTexmapLayers + 1, 1, boo::TextureFormat::I8,
boo::TextureFormat::I8, boo::TextureClampMode::Repeat, boo::TextureClampMode::Repeat, m_texmap.data(), m_texmap.size());
m_texmap.data(), m_texmap.size());
const_cast<std::vector<uint8_t>&>(m_texmap) = std::vector<uint8_t>(); const_cast<std::vector<uint8_t>&>(m_texmap) = std::vector<uint8_t>();
return true; return true;
} BooTrace); } BooTrace);
return m_tex; return m_tex;
} }
FontCache::Library::Library() FontCache::Library::Library() {
{
FT_Error err = FT_Init_FreeType(&m_lib); FT_Error err = FT_Init_FreeType(&m_lib);
if (err) if (err)
Log.report(logvisor::Fatal, "unable to FT_Init_FreeType"); Log.report(logvisor::Fatal, "unable to FT_Init_FreeType");
} }
FontCache::Library::~Library() FontCache::Library::~Library() { FT_Done_FreeType(m_lib); }
{
FT_Done_FreeType(m_lib);
}
FontCache::FontCache(const hecl::Runtime::FileStoreManager& fileMgr) FontCache::FontCache(const hecl::Runtime::FileStoreManager& fileMgr)
: m_fileMgr(fileMgr), : m_fileMgr(fileMgr)
m_cacheRoot(hecl::SystemString(m_fileMgr.getStoreRoot()) + _SYS_STR("/fontcache")), , m_cacheRoot(hecl::SystemString(m_fileMgr.getStoreRoot()) + _SYS_STR("/fontcache"))
m_regFace(m_fontLib, DROIDSANS_PERMISSIVE, DROIDSANS_PERMISSIVE_SZ), , m_regFace(m_fontLib, DROIDSANS_PERMISSIVE, DROIDSANS_PERMISSIVE_SZ)
m_monoFace(m_fontLib, BMONOFONT, BMONOFONT_SZ), , m_monoFace(m_fontLib, BMONOFONT, BMONOFONT_SZ)
m_curvesFace(m_fontLib, SPECTERCURVES, SPECTERCURVES_SZ) , m_curvesFace(m_fontLib, SPECTERCURVES, SPECTERCURVES_SZ) {
{
hecl::MakeDir(m_cacheRoot.c_str()); hecl::MakeDir(m_cacheRoot.c_str());
} }
FontTag FontCache::prepCustomFont(std::string_view name, FT_Face face, FontTag FontCache::prepCustomFont(std::string_view name, FT_Face face, FCharFilter filter, bool subpixel, float points,
FCharFilter filter, bool subpixel, uint32_t dpi) {
float points, uint32_t dpi)
{
/* Quick validation */ /* Quick validation */
if (!face) if (!face)
Log.report(logvisor::Fatal, "invalid freetype face"); Log.report(logvisor::Fatal, "invalid freetype face");
@ -712,17 +620,13 @@ FontTag FontCache::prepCustomFont(std::string_view name, FT_Face face,
/* Now check filesystem cache */ /* Now check filesystem cache */
hecl::SystemString cachePath = m_cacheRoot + _SYS_STR('/') + hecl::SysFormat(_SYS_STR("%" PRIx64), tag.hash()); hecl::SystemString cachePath = m_cacheRoot + _SYS_STR('/') + hecl::SysFormat(_SYS_STR("%" PRIx64), tag.hash());
hecl::Sstat st; hecl::Sstat st;
if (!hecl::Stat(cachePath.c_str(), &st) && S_ISREG(st.st_mode)) if (!hecl::Stat(cachePath.c_str(), &st) && S_ISREG(st.st_mode)) {
{
athena::io::FileReader r(cachePath); athena::io::FileReader r(cachePath);
if (!r.hasError()) if (!r.hasError()) {
{
atUint32 magic = r.readUint32Big(); atUint32 magic = r.readUint32Big();
if (r.position() == 4 && magic == 'FONT') if (r.position() == 4 && magic == 'FONT') {
{
std::unique_ptr<FontAtlas> fa = std::make_unique<FontAtlas>(face, dpi, subpixel, filter, r); std::unique_ptr<FontAtlas> fa = std::make_unique<FontAtlas>(face, dpi, subpixel, filter, r);
if (fa->isReady()) if (fa->isReady()) {
{
m_cachedAtlases.emplace(tag, std::move(fa)); m_cachedAtlases.emplace(tag, std::move(fa));
return tag; return tag;
} }
@ -739,12 +643,11 @@ FontTag FontCache::prepCustomFont(std::string_view name, FT_Face face,
return tag; return tag;
} }
const FontAtlas& FontCache::lookupAtlas(FontTag tag) const const FontAtlas& FontCache::lookupAtlas(FontTag tag) const {
{
auto search = m_cachedAtlases.find(tag); auto search = m_cachedAtlases.find(tag);
if (search == m_cachedAtlases.cend()) if (search == m_cachedAtlases.cend())
Log.report(logvisor::Fatal, "invalid font"); Log.report(logvisor::Fatal, "invalid font");
return *search->second.get(); return *search->second.get();
} }
} } // namespace specter

View File

@ -1,20 +1,15 @@
#include "specter/Icon.hpp" #include "specter/Icon.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
IconView::IconView(ViewResources& res, View& parentView, Icon& icon) IconView::IconView(ViewResources& res, View& parentView, Icon& icon) : View(res, parentView) {
: View(res, parentView) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertexBinding.init(ctx, res, 4, m_viewVertBlockBuf, icon.m_tex); m_vertexBinding.init(ctx, res, 4, m_viewVertBlockBuf, icon.m_tex);
return true; return true;
}); });
TexShaderVert verts[] = TexShaderVert verts[] = {
{
{{0, 1, 0}, icon.m_uvCoords[0]}, {{0, 1, 0}, icon.m_uvCoords[0]},
{{0, 0, 0}, icon.m_uvCoords[1]}, {{0, 0, 0}, icon.m_uvCoords[1]},
{{1, 1, 0}, icon.m_uvCoords[2]}, {{1, 1, 0}, icon.m_uvCoords[2]},
@ -24,18 +19,16 @@ IconView::IconView(ViewResources& res, View& parentView, Icon& icon)
setBackground(zeus::CColor::skBlue); setBackground(zeus::CColor::skBlue);
} }
void IconView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void IconView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
m_viewVertBlock.setViewRect(root, sub); m_viewVertBlock.setViewRect(root, sub);
m_viewVertBlock.m_mv[0][0] *= sub.size[0]; m_viewVertBlock.m_mv[0][0] *= sub.size[0];
m_viewVertBlock.m_mv[1][1] *= sub.size[1]; m_viewVertBlock.m_mv[1][1] *= sub.size[1];
View::resized(m_viewVertBlock, sub); View::resized(m_viewVertBlock, sub);
} }
void IconView::draw(boo::IGraphicsCommandQueue* gfxQ) void IconView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
gfxQ->setShaderDataBinding(m_vertexBinding); gfxQ->setShaderDataBinding(m_vertexBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
} }
} } // namespace specter

View File

@ -5,14 +5,10 @@
#define ROW_HEIGHT 18 #define ROW_HEIGHT 18
#define ITEM_MARGIN 1 #define ITEM_MARGIN 1
namespace specter namespace specter {
{
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode) Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode) : View(res, parentView) {
: View(res, parentView) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
return true; return true;
@ -24,8 +20,7 @@ Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode)
reset(rootNode); reset(rootNode);
} }
void Menu::reset(IMenuNode* rootNode) void Menu::reset(IMenuNode* rootNode) {
{
m_rootNode = rootNode; m_rootNode = rootNode;
m_thisNode = rootNode; m_thisNode = rootNode;
ViewResources& res = rootView().viewRes(); ViewResources& res = rootView().viewRes();
@ -47,19 +42,16 @@ void Menu::reset(IMenuNode* rootNode)
size_t subCount = rootNode->subNodeCount(); size_t subCount = rootNode->subNodeCount();
m_items.clear(); m_items.clear();
if (subCount) if (subCount) {
{
m_items.reserve(subCount); m_items.reserve(subCount);
for (size_t i=0 ; i<subCount ; ++i) for (size_t i = 0; i < subCount; ++i) {
{
IMenuNode* node = rootNode->subNode(i); IMenuNode* node = rootNode->subNode(i);
const std::string* nodeText = node->text(); const std::string* nodeText = node->text();
m_items.emplace_back(); m_items.emplace_back();
ViewChild<std::unique_ptr<ItemView>>& item = m_items.back(); ViewChild<std::unique_ptr<ItemView>>& item = m_items.back();
if (nodeText) if (nodeText) {
{
item.m_view.reset(new ItemView(res, *this, *nodeText, i, node)); item.m_view.reset(new ItemView(res, *this, *nodeText, i, node));
m_cWidth = std::max(m_cWidth, int(item.m_view->m_textView->nominalWidth() + 10 * pf)); m_cWidth = std::max(m_cWidth, int(item.m_view->m_textView->nominalWidth() + 10 * pf));
} }
@ -70,10 +62,8 @@ void Menu::reset(IMenuNode* rootNode)
} }
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode) Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode)
: View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode) : View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
return true; return true;
@ -84,11 +74,8 @@ Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode*
m_scroll.m_view->setContentView(m_content.get()); m_scroll.m_view->setContentView(m_content.get());
} }
Menu::ContentView::ContentView(ViewResources& res, Menu& menu) Menu::ContentView::ContentView(ViewResources& res, Menu& menu) : View(res, menu), m_menu(menu) {
: View(res, menu), m_menu(menu) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_hlVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf); m_hlVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true; return true;
@ -101,10 +88,8 @@ Menu::ContentView::ContentView(ViewResources& res, Menu& menu)
} }
Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node) Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node)
: View(res, menu), m_menu(menu), m_idx(idx), m_node(node) : View(res, menu), m_menu(menu), m_idx(idx), m_node(node) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
return true; return true;
}); });
@ -112,8 +97,7 @@ Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text,
m_textView->typesetGlyphs(text, res.themeData().uiText()); m_textView->typesetGlyphs(text, res.themeData().uiText());
} }
void Menu::setVerts(int width, int height, float pf) void Menu::setVerts(int width, int height, float pf) {
{
m_verts[0].m_pos.assign(0, height - m_cTop - pf, 0); m_verts[0].m_pos.assign(0, height - m_cTop - pf, 0);
m_verts[1].m_pos.assign(0, 0, 0); m_verts[1].m_pos.assign(0, 0, 0);
m_verts[2].m_pos.assign(width, height - m_cTop - pf, 0); m_verts[2].m_pos.assign(width, height - m_cTop - pf, 0);
@ -127,17 +111,14 @@ void Menu::setVerts(int width, int height, float pf)
m_vertsBinding.load<decltype(m_verts)>(m_verts); m_vertsBinding.load<decltype(m_verts)>(m_verts);
} }
void Menu::ContentView::setHighlightedItem(size_t idx) void Menu::ContentView::setHighlightedItem(size_t idx) {
{ if (idx == -1) {
if (idx == -1)
{
m_highlightedItem = -1; m_highlightedItem = -1;
return; return;
} }
ViewChild<std::unique_ptr<ItemView>>& vc = m_menu.m_items[idx]; ViewChild<std::unique_ptr<ItemView>>& vc = m_menu.m_items[idx];
if (!vc.m_view) if (!vc.m_view) {
{
m_highlightedItem = -1; m_highlightedItem = -1;
return; return;
} }
@ -155,98 +136,66 @@ void Menu::ContentView::setHighlightedItem(size_t idx)
m_hlVertsBinding.load<decltype(m_hlVerts)>(m_hlVerts); m_hlVertsBinding.load<decltype(m_hlVerts)>(m_hlVerts);
} }
void Menu::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_scroll.mouseDown(coord, button, mod); m_scroll.mouseDown(coord, button, mod);
} }
void Menu::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseDown(coord, button, mod); v.mouseDown(coord, button, mod);
} }
void Menu::ItemView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ItemView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {}
{
}
void Menu::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_scroll.mouseUp(coord, button, mod); m_scroll.mouseUp(coord, button, mod);
if (m_deferredActivation) if (m_deferredActivation) {
{
IMenuNode* node = m_deferredActivation; IMenuNode* node = m_deferredActivation;
m_deferredActivation = nullptr; m_deferredActivation = nullptr;
node->activated(coord); node->activated(coord);
} }
} }
void Menu::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseUp(coord, button, mod); v.mouseUp(coord, button, mod);
} }
void Menu::ItemView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ItemView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (m_menu.m_content->m_highlightedItem == m_idx) if (m_menu.m_content->m_highlightedItem == m_idx)
m_menu.m_deferredActivation = m_node; m_menu.m_deferredActivation = m_node;
} }
void Menu::mouseMove(const boo::SWindowCoord& coord) void Menu::mouseMove(const boo::SWindowCoord& coord) { m_scroll.mouseMove(coord); }
{
m_scroll.mouseMove(coord);
}
void Menu::ContentView::mouseMove(const boo::SWindowCoord& coord) void Menu::ContentView::mouseMove(const boo::SWindowCoord& coord) {
{
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseMove(coord); v.mouseMove(coord);
} }
void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord) void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord) { m_menu.m_content->setHighlightedItem(m_idx); }
{
m_menu.m_content->setHighlightedItem(m_idx);
}
void Menu::mouseLeave(const boo::SWindowCoord& coord) void Menu::mouseLeave(const boo::SWindowCoord& coord) { m_scroll.mouseLeave(coord); }
{
m_scroll.mouseLeave(coord);
}
void Menu::ContentView::mouseLeave(const boo::SWindowCoord& coord) void Menu::ContentView::mouseLeave(const boo::SWindowCoord& coord) {
{
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseLeave(coord); v.mouseLeave(coord);
} }
void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord) void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord) { m_menu.m_content->unsetHighlightedItem(m_idx); }
{
m_menu.m_content->unsetHighlightedItem(m_idx);
}
void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { m_scroll.scroll(coord, scroll); }
{
m_scroll.scroll(coord, scroll);
}
void Menu::think() void Menu::think() { m_scroll.m_view->think(); }
{
m_scroll.m_view->think();
}
void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect rect = sub; boo::SWindowRect rect = sub;
rect.size[0] = m_cWidth; rect.size[0] = m_cWidth;
if (rect.location[1] - m_cHeight < 0) if (rect.location[1] - m_cHeight < 0) {
{
rect.location[1] += ROW_HEIGHT * pf; rect.location[1] += ROW_HEIGHT * pf;
rect.size[1] = std::min(root.size[1] - rect.location[1], m_cHeight); rect.size[1] = std::min(root.size[1] - rect.location[1], m_cHeight);
} } else {
else
{
rect.location[1] -= m_cHeight; rect.location[1] -= m_cHeight;
rect.size[1] = m_cHeight; rect.size[1] = m_cHeight;
} }
@ -263,8 +212,7 @@ void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
} }
void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{
View::resized(root, sub); View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
m_scissorRect = scissor; m_scissorRect = scissor;
@ -273,16 +221,14 @@ void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindow
itemRect.size[1] = ROW_HEIGHT * pf; itemRect.size[1] = ROW_HEIGHT * pf;
itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN * pf; itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN * pf;
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf; int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf;
for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items) for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items) {
{
itemRect.location[1] -= itemAdv; itemRect.location[1] -= itemAdv;
if (c.m_view) if (c.m_view)
c.m_view->resized(root, itemRect); c.m_view->resized(root, itemRect);
} }
} }
void Menu::ItemView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Menu::ItemView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect textRect = sub; boo::SWindowRect textRect = sub;
@ -291,8 +237,7 @@ void Menu::ItemView::resized(const boo::SWindowRect& root, const boo::SWindowRec
m_textView->resized(root, textRect); m_textView->resized(root, textRect);
} }
void Menu::draw(boo::IGraphicsCommandQueue* gfxQ) void Menu::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
@ -302,12 +247,10 @@ void Menu::draw(boo::IGraphicsCommandQueue* gfxQ)
m_headText->draw(gfxQ); m_headText->draw(gfxQ);
} }
void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
gfxQ->setScissor(m_scissorRect); gfxQ->setScissor(m_scissorRect);
if (m_highlightedItem != -1) if (m_highlightedItem != -1) {
{
gfxQ->setShaderDataBinding(m_hlVertsBinding); gfxQ->setShaderDataBinding(m_hlVertsBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
} }
@ -317,10 +260,9 @@ void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->setScissor(rootView().subRect()); gfxQ->setScissor(rootView().subRect());
} }
void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ) void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
m_textView->draw(gfxQ); m_textView->draw(gfxQ);
} }
} } // namespace specter

View File

@ -3,90 +3,77 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/Menu.hpp" #include "specter/Menu.hpp"
namespace specter namespace specter {
{
MessageWindow::MessageWindow(ViewResources& res, View& parentView, MessageWindow::MessageWindow(ViewResources& res, View& parentView, Type type, std::string_view message,
Type type, std::string_view message,
std::function<void(bool)> func) std::function<void(bool)> func)
: ModalWindow(res, parentView, RectangleConstraint(), : ModalWindow(res, parentView, RectangleConstraint(),
type==Type::ErrorOk ? res.themeData().splashErrorBackground() : res.themeData().splashBackground()), type == Type::ErrorOk ? res.themeData().splashErrorBackground() : res.themeData().splashBackground())
m_type(type), m_func(func), , m_type(type)
m_okBind(*this, rootView().viewManager().translateOr("ok", "OK")), , m_func(func)
m_cancelBind(*this, rootView().viewManager().translateOr("cancel", "Cancel")) , m_okBind(*this, rootView().viewManager().translateOr("ok", "OK"))
{ , m_cancelBind(*this, rootView().viewManager().translateOr("cancel", "Cancel")) {
m_text.reset(new MultiLineTextView(res, *this, res.m_mainFont, TextView::Alignment::Center)); m_text.reset(new MultiLineTextView(res, *this, res.m_mainFont, TextView::Alignment::Center));
m_text->typesetGlyphs(message, res.themeData().uiText(), 380 * res.pixelFactor()); m_text->typesetGlyphs(message, res.themeData().uiText(), 380 * res.pixelFactor());
constraint() = RectangleConstraint(400 * res.pixelFactor(), 80 * res.pixelFactor() + m_text->nominalHeight()); constraint() = RectangleConstraint(400 * res.pixelFactor(), 80 * res.pixelFactor() + m_text->nominalHeight());
m_ok.m_view.reset(new Button(res, *this, &m_okBind, m_okBind.m_name, nullptr, m_ok.m_view.reset(new Button(res, *this, &m_okBind, m_okBind.m_name, nullptr, Button::Style::Block,
Button::Style::Block, zeus::CColor::skWhite, zeus::CColor::skWhite, RectangleConstraint(150 * res.pixelFactor())));
RectangleConstraint(150 * res.pixelFactor())));
if (type == Type::ConfirmOkCancel) if (type == Type::ConfirmOkCancel)
m_cancel.m_view.reset(new Button(res, *this, &m_cancelBind, m_cancelBind.m_name, nullptr, m_cancel.m_view.reset(new Button(res, *this, &m_cancelBind, m_cancelBind.m_name, nullptr, Button::Style::Block,
Button::Style::Block, zeus::CColor::skWhite, zeus::CColor::skWhite, RectangleConstraint(150 * res.pixelFactor())));
RectangleConstraint(150 * res.pixelFactor())));
updateContentOpacity(0.0); updateContentOpacity(0.0);
} }
void MessageWindow::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void MessageWindow::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{
if (closed() || skipBuildInAnimation()) if (closed() || skipBuildInAnimation())
return; return;
m_ok.mouseDown(coord, button, mods); m_ok.mouseDown(coord, button, mods);
m_cancel.mouseDown(coord, button, mods); m_cancel.mouseDown(coord, button, mods);
} }
void MessageWindow::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void MessageWindow::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{
if (closed()) if (closed())
return; return;
m_ok.mouseUp(coord, button, mods); m_ok.mouseUp(coord, button, mods);
m_cancel.mouseUp(coord, button, mods); m_cancel.mouseUp(coord, button, mods);
} }
void MessageWindow::mouseMove(const boo::SWindowCoord& coord) void MessageWindow::mouseMove(const boo::SWindowCoord& coord) {
{
if (closed()) if (closed())
return; return;
m_ok.mouseMove(coord); m_ok.mouseMove(coord);
m_cancel.mouseMove(coord); m_cancel.mouseMove(coord);
} }
void MessageWindow::mouseEnter(const boo::SWindowCoord& coord) void MessageWindow::mouseEnter(const boo::SWindowCoord& coord) {
{
if (closed()) if (closed())
return; return;
m_ok.mouseEnter(coord); m_ok.mouseEnter(coord);
m_cancel.mouseEnter(coord); m_cancel.mouseEnter(coord);
} }
void MessageWindow::mouseLeave(const boo::SWindowCoord& coord) void MessageWindow::mouseLeave(const boo::SWindowCoord& coord) {
{
if (closed()) if (closed())
return; return;
m_ok.mouseLeave(coord); m_ok.mouseLeave(coord);
m_cancel.mouseLeave(coord); m_cancel.mouseLeave(coord);
} }
void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
ModalWindow::resized(root, sub); ModalWindow::resized(root, sub);
boo::SWindowRect buttonRect = subRect(); boo::SWindowRect buttonRect = subRect();
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
buttonRect.location[1] += 20 * pf; buttonRect.location[1] += 20 * pf;
buttonRect.size[0] = m_ok.m_view->nominalWidth(); buttonRect.size[0] = m_ok.m_view->nominalWidth();
buttonRect.size[1] = m_ok.m_view->nominalHeight(); buttonRect.size[1] = m_ok.m_view->nominalHeight();
if (m_type == Type::ConfirmOkCancel) if (m_type == Type::ConfirmOkCancel) {
{
buttonRect.location[0] += 45 * pf; buttonRect.location[0] += 45 * pf;
m_ok.m_view->resized(root, buttonRect); m_ok.m_view->resized(root, buttonRect);
buttonRect.location[0] += 160 * pf; buttonRect.location[0] += 160 * pf;
m_cancel.m_view->resized(root, buttonRect); m_cancel.m_view->resized(root, buttonRect);
} } else {
else
{
buttonRect.location[0] += 125 * pf; buttonRect.location[0] += 125 * pf;
m_ok.m_view->resized(root, buttonRect); m_ok.m_view->resized(root, buttonRect);
} }
@ -97,8 +84,7 @@ void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect
m_text->resized(root, textRect); m_text->resized(root, textRect);
} }
void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ) void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
ModalWindow::draw(gfxQ); ModalWindow::draw(gfxQ);
m_text->draw(gfxQ); m_text->draw(gfxQ);
m_ok.m_view->draw(gfxQ); m_ok.m_view->draw(gfxQ);
@ -106,4 +92,4 @@ void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
m_cancel.m_view->draw(gfxQ); m_cancel.m_view->draw(gfxQ);
} }
} } // namespace specter

View File

@ -2,8 +2,7 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
#define WIRE_START 0 #define WIRE_START 0
#define WIRE_FRAMES 40 #define WIRE_FRAMES 40
@ -16,8 +15,7 @@ namespace specter
#define CONTENT_MARGIN 10 #define CONTENT_MARGIN 10
#define WINDOW_MIN_DIM 16 #define WINDOW_MIN_DIM 16
void ModalWindow::setLineVerts(int width, int height, float pf, float t) void ModalWindow::setLineVerts(int width, int height, float pf, float t) {
{
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
@ -65,8 +63,7 @@ void ModalWindow::setLineVerts(int width, int height, float pf, float t)
m_verts.lineVerts[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2); m_verts.lineVerts[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2);
} }
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) {
{
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
float t1 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t1 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f, 1.f);
@ -114,8 +111,7 @@ void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
m_verts.lineVerts[21].m_pos.assign(lineRight, lineBottom, 0); m_verts.lineVerts[21].m_pos.assign(lineRight, lineBottom, 0);
} }
void ModalWindow::setLineColors(float t) void ModalWindow::setLineColors(float t) {
{
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f); float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
@ -125,20 +121,15 @@ void ModalWindow::setLineColors(float t)
zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3); zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3);
m_cornersOutline[0]->colorGlyphs(c1); m_cornersOutline[0]->colorGlyphs(c1);
if (t < 0.5) if (t < 0.5) {
{
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
} } else if (t < 1.0) {
else if (t < 1.0)
{
m_cornersOutline[1]->colorGlyphs(c2); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[3]->colorGlyphs(c2);
} } else {
else
{
m_cornersOutline[1]->colorGlyphs(c2); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(c3); m_cornersOutline[2]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[3]->colorGlyphs(c2);
@ -171,8 +162,7 @@ void ModalWindow::setLineColors(float t)
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color; m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
} }
void ModalWindow::setLineColorsOut(float t) void ModalWindow::setLineColorsOut(float t) {
{
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f); float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
@ -182,20 +172,15 @@ void ModalWindow::setLineColorsOut(float t)
zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3); zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3);
m_cornersOutline[2]->colorGlyphs(c1); m_cornersOutline[2]->colorGlyphs(c1);
if (t < 0.5) if (t < 0.5) {
{
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
} } else if (t < 1.0) {
else if (t < 1.0)
{
m_cornersOutline[1]->colorGlyphs(c2); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[3]->colorGlyphs(c2);
} } else {
else
{
m_cornersOutline[1]->colorGlyphs(c2); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(c3); m_cornersOutline[0]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[3]->colorGlyphs(c2);
@ -228,8 +213,7 @@ void ModalWindow::setLineColorsOut(float t)
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color; m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
} }
void ModalWindow::setFillVerts(int width, int height, float pf) void ModalWindow::setFillVerts(int width, int height, float pf) {
{
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
float fillLeft = pf * LINE_WIDTH; float fillLeft = pf * LINE_WIDTH;
@ -264,8 +248,7 @@ void ModalWindow::setFillVerts(int width, int height, float pf)
m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0); m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0);
} }
void ModalWindow::setFillColors(float t) void ModalWindow::setFillColors(float t) {
{
t = zeus::clamp(0.f, t, 1.f); t = zeus::clamp(0.f, t, 1.f);
zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t); zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
@ -278,31 +261,28 @@ void ModalWindow::setFillColors(float t)
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint) ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint)
: ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {} : ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {}
ModalWindow::ModalWindow(ViewResources& res, View& parentView, ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint,
const RectangleConstraint& constraint,
const zeus::CColor& bgColor) const zeus::CColor& bgColor)
: View(res, parentView), : View(res, parentView)
m_constraint(constraint), , m_constraint(constraint)
m_windowBg(bgColor), , m_windowBg(bgColor)
m_windowBgClear(m_windowBg), , m_windowBgClear(m_windowBg)
m_line1(res.themeData().splash1()), , m_line1(res.themeData().splash1())
m_line2(res.themeData().splash2()), , m_line2(res.themeData().splash2())
m_line2Clear(m_line2) , m_line2Clear(m_line2) {
{
m_windowBgClear[3] = 0.0; m_windowBgClear[3] = 0.0;
m_line2Clear[3] = 0.0; m_line2Clear[3] = 0.0;
res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
{
buildResources(ctx, res); buildResources(ctx, res);
m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 38, m_viewBlockBuf); m_vertsBinding.init(ctx, res, 38, m_viewBlockBuf);
return true; return true;
} BooTrace); } BooTrace);
for (int i=0 ; i<4 ; ++i) for (int i = 0; i < 4; ++i) {
{ m_cornersOutline[i].reset(
m_cornersOutline[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1)); new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
m_cornersFilled[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1)); m_cornersFilled[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
} }
m_cornersOutline[0]->typesetGlyphs(L"\xF4F0"); m_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
@ -320,27 +300,23 @@ ModalWindow::ModalWindow(ViewResources& res, View& parentView,
_loadVerts(); _loadVerts();
} }
static float CubicEase(float t) static float CubicEase(float t) {
{
t *= 2.f; t *= 2.f;
if (t < 1) return 1.f/2.f*t*t*t; if (t < 1)
return 1.f / 2.f * t * t * t;
t -= 2.f; t -= 2.f;
return 1.f / 2.f * (t * t * t + 2.f); return 1.f / 2.f * (t * t * t + 2.f);
} }
void ModalWindow::think() void ModalWindow::think() {
{
specter::ViewResources& res = rootView().viewRes(); specter::ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor(); float pf = res.pixelFactor();
switch (m_phase) switch (m_phase) {
{ case Phase::BuildIn: {
case Phase::BuildIn:
{
bool loadVerts = false; bool loadVerts = false;
int doneCount = 0; int doneCount = 0;
if (m_frame > WIRE_START) if (m_frame > WIRE_START) {
{
float wt = (m_frame - WIRE_START) / float(WIRE_FRAMES); float wt = (m_frame - WIRE_START) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 2.f); wt = zeus::clamp(0.f, wt, 2.f);
m_lineTime = CubicEase(wt); m_lineTime = CubicEase(wt);
@ -350,8 +326,7 @@ void ModalWindow::think()
++doneCount; ++doneCount;
loadVerts = true; loadVerts = true;
} }
if (m_frame > SOLID_START) if (m_frame > SOLID_START) {
{
float ft = (m_frame - SOLID_START) / float(SOLID_FRAMES); float ft = (m_frame - SOLID_START) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 2.f); ft = zeus::clamp(0.f, ft, 2.f);
setFillColors(ft); setFillColors(ft);
@ -359,8 +334,7 @@ void ModalWindow::think()
++doneCount; ++doneCount;
loadVerts = true; loadVerts = true;
} }
if (res.fontCacheReady() && m_frame > CONTENT_START) if (res.fontCacheReady() && m_frame > CONTENT_START) {
{
if (!m_contentStartFrame) if (!m_contentStartFrame)
m_contentStartFrame = m_frame; m_contentStartFrame = m_frame;
float tt = (m_frame - m_contentStartFrame) / float(CONTENT_FRAMES); float tt = (m_frame - m_contentStartFrame) / float(CONTENT_FRAMES);
@ -376,17 +350,14 @@ void ModalWindow::think()
++m_frame; ++m_frame;
break; break;
} }
case Phase::ResWait: case Phase::ResWait: {
{ if (res.fontCacheReady()) {
if (res.fontCacheReady())
{
updateContentOpacity(1.0); updateContentOpacity(1.0);
m_phase = Phase::Showing; m_phase = Phase::Showing;
} }
break; break;
} }
case Phase::BuildOut: case Phase::BuildOut: {
{
{ {
float wt = (WIRE_FRAMES - m_frame) / float(WIRE_FRAMES); float wt = (WIRE_FRAMES - m_frame) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 1.f); wt = zeus::clamp(0.f, wt, 1.f);
@ -401,8 +372,7 @@ void ModalWindow::think()
ft = zeus::clamp(0.f, ft, 1.f); ft = zeus::clamp(0.f, ft, 1.f);
setFillColors(ft); setFillColors(ft);
} }
if (res.fontCacheReady()) if (res.fontCacheReady()) {
{
float tt = (CONTENT_FRAMES - m_frame) / float(CONTENT_FRAMES); float tt = (CONTENT_FRAMES - m_frame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f); tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt); updateContentOpacity(tt);
@ -411,12 +381,12 @@ void ModalWindow::think()
++m_frame; ++m_frame;
break; break;
} }
default: break; default:
break;
} }
} }
bool ModalWindow::skipBuildInAnimation() bool ModalWindow::skipBuildInAnimation() {
{
if (m_phase != Phase::BuildIn) if (m_phase != Phase::BuildIn)
return false; return false;
@ -432,19 +402,17 @@ bool ModalWindow::skipBuildInAnimation()
return true; return true;
} }
void ModalWindow::close(bool skipAnimation) void ModalWindow::close(bool skipAnimation) {
{
m_phase = skipAnimation ? Phase::Done : Phase::BuildOut; m_phase = skipAnimation ? Phase::Done : Phase::BuildOut;
m_frame = 0; m_frame = 0;
} }
void ModalWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void ModalWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect centerRect = sub; boo::SWindowRect centerRect = sub;
std::pair<int,int> constrained = m_constraint.solve(root.size[0] - CONTENT_MARGIN * pf * 2, std::pair<int, int> constrained =
root.size[1] - CONTENT_MARGIN * pf * 2); m_constraint.solve(root.size[0] - CONTENT_MARGIN * pf * 2, root.size[1] - CONTENT_MARGIN * pf * 2);
m_width = std::max(constrained.first, int(WINDOW_MIN_DIM * pf)); m_width = std::max(constrained.first, int(WINDOW_MIN_DIM * pf));
m_height = std::max(constrained.second, int(WINDOW_MIN_DIM * pf)); m_height = std::max(constrained.second, int(WINDOW_MIN_DIM * pf));
centerRect.size[0] = m_width; centerRect.size[0] = m_width;
@ -475,8 +443,7 @@ void ModalWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect&
m_cornersFilled[3]->resized(root, cornerRect); m_cornersFilled[3]->resized(root, cornerRect);
} }
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ) void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
if (m_phase == Phase::Done) if (m_phase == Phase::Done)
return; return;
@ -495,4 +462,4 @@ void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
m_cornersOutline[3]->draw(gfxQ); m_cornersOutline[3]->draw(gfxQ);
} }
} } // namespace specter

View File

@ -1,12 +1,10 @@
#include "specter/MultiLineTextView.hpp" #include "specter/MultiLineTextView.hpp"
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::MultiLineTextView"); static logvisor::Module Log("specter::MultiLineTextView");
std::string MultiLineTextView::LineWrap(std::string_view str, int wrap) std::string MultiLineTextView::LineWrap(std::string_view str, int wrap) {
{
size_t rem = str.size(); size_t rem = str.size();
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data()); const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
uint32_t lCh = -1; uint32_t lCh = -1;
@ -17,14 +15,12 @@ std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
size_t lastSpaceRem; size_t lastSpaceRem;
const utf8proc_uint8_t* lastSpaceIt = nullptr; const utf8proc_uint8_t* lastSpaceIt = nullptr;
size_t rollbackPos; size_t rollbackPos;
while (rem) while (rem) {
{
utf8proc_int32_t ch; utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch); utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (sz < 0) if (sz < 0)
Log.report(logvisor::Fatal, "invalid UTF-8 char"); Log.report(logvisor::Fatal, "invalid UTF-8 char");
if (ch == '\n') if (ch == '\n') {
{
ret += '\n'; ret += '\n';
lCh = -1; lCh = -1;
rem -= sz; rem -= sz;
@ -35,8 +31,7 @@ std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
} }
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch); const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph) if (!glyph) {
{
rem -= sz; rem -= sz;
it += sz; it += sz;
continue; continue;
@ -46,8 +41,7 @@ std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas); adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
adv += glyph->m_advance; adv += glyph->m_advance;
if (adv > wrap && lastSpaceIt) if (adv > wrap && lastSpaceIt) {
{
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos); ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
ret += '\n'; ret += '\n';
lCh = -1; lCh = -1;
@ -58,8 +52,7 @@ std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
continue; continue;
} }
if (sz == 1 && (it[0] == ' ' || it[0] == '-' || it[0] == '/' || it[0] == '\\')) if (sz == 1 && (it[0] == ' ' || it[0] == '-' || it[0] == '/' || it[0] == '\\')) {
{
lastSpaceIt = it + 1; lastSpaceIt = it + 1;
lastSpaceRem = rem - 1; lastSpaceRem = rem - 1;
rollbackPos = ret.size() + 1; rollbackPos = ret.size() + 1;
@ -74,8 +67,7 @@ std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
return ret; return ret;
} }
std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap) std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap) {
{
uint32_t lCh = -1; uint32_t lCh = -1;
int adv = 0; int adv = 0;
@ -83,11 +75,9 @@ std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap)
ret.reserve(str.size()); ret.reserve(str.size());
std::wstring_view::const_iterator lastSpaceIt = str.cend(); std::wstring_view::const_iterator lastSpaceIt = str.cend();
size_t rollbackPos; size_t rollbackPos;
for (std::wstring_view::const_iterator it = str.cbegin() ; it != str.cend() ; ++it) for (std::wstring_view::const_iterator it = str.cbegin(); it != str.cend(); ++it) {
{
wchar_t ch = *it; wchar_t ch = *it;
if (ch == L'\n') if (ch == L'\n') {
{
ret += L'\n'; ret += L'\n';
lCh = -1; lCh = -1;
lastSpaceIt = str.cend(); lastSpaceIt = str.cend();
@ -103,8 +93,7 @@ std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap)
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas); adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
adv += glyph->m_advance; adv += glyph->m_advance;
if (adv > wrap && lastSpaceIt != str.cend()) if (adv > wrap && lastSpaceIt != str.cend()) {
{
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos); ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
ret += L'\n'; ret += L'\n';
lCh = -1; lCh = -1;
@ -114,8 +103,7 @@ std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap)
continue; continue;
} }
if (ch == L' ' || ch == L'-') if (ch == L' ' || ch == L'-') {
{
lastSpaceIt = it + 1; lastSpaceIt = it + 1;
rollbackPos = ret.size() + 1; rollbackPos = ret.size() + 1;
} }
@ -126,45 +114,26 @@ std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap)
return ret; return ret;
} }
MultiLineTextView::MultiLineTextView(ViewResources& res, MultiLineTextView::MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
View& parentView, TextView::Alignment align, size_t lineCapacity, float lineHeight)
const FontAtlas& font, : View(res, parentView)
TextView::Alignment align, , m_viewSystem(res)
size_t lineCapacity, , m_fontAtlas(font)
float lineHeight) , m_align(align)
: View(res, parentView), , m_lineCapacity(lineCapacity)
m_viewSystem(res), , m_lineHeight(lineHeight) {
m_fontAtlas(font), commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
m_align(align),
m_lineCapacity(lineCapacity),
m_lineHeight(lineHeight)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
return true; return true;
}); });
} }
MultiLineTextView::MultiLineTextView(ViewResources& res, MultiLineTextView::MultiLineTextView(ViewResources& res, View& parentView, FontTag font, TextView::Alignment align,
View& parentView, size_t lineCapacity, float lineHeight)
FontTag font, : MultiLineTextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, lineCapacity, lineHeight) {}
TextView::Alignment align,
size_t lineCapacity,
float lineHeight)
: MultiLineTextView(res,
parentView,
res.m_textRes.m_fcache->lookupAtlas(font),
align,
lineCapacity,
lineHeight) {}
void MultiLineTextView::typesetGlyphs(std::string_view str, void MultiLineTextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor, unsigned wrap) {
const zeus::CColor& defaultColor, if (wrap) {
unsigned wrap)
{
if (wrap)
{
typesetGlyphs(LineWrap(str, wrap), defaultColor); typesetGlyphs(LineWrap(str, wrap), defaultColor);
return; return;
} }
@ -174,8 +143,7 @@ void MultiLineTextView::typesetGlyphs(std::string_view str,
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data()); const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
size_t lineCount = 0; size_t lineCount = 0;
while (rem) while (rem) {
{
utf8proc_int32_t ch; utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch); utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (sz < 0) if (sz < 0)
@ -192,14 +160,14 @@ void MultiLineTextView::typesetGlyphs(std::string_view str,
const utf8proc_uint8_t* beginIt = it; const utf8proc_uint8_t* beginIt = it;
size_t lineIt = 0; size_t lineIt = 0;
while (rem) while (rem) {
{
utf8proc_int32_t ch; utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch); utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (ch == '\n' || ch == '\0') if (ch == '\n' || ch == '\0') {
{ TextView& tv =
TextView& tv = (lineIt < m_lines.size()) ? *m_lines[lineIt] : (lineIt < m_lines.size())
*m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity)); ? *m_lines[lineIt]
: *m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::string((char*)beginIt, it - beginIt), defaultColor); tv.typesetGlyphs(std::string((char*)beginIt, it - beginIt), defaultColor);
m_width = std::max(m_width, tv.nominalWidth()); m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1; beginIt = it + 1;
@ -212,12 +180,8 @@ void MultiLineTextView::typesetGlyphs(std::string_view str,
updateSize(); updateSize();
} }
void MultiLineTextView::typesetGlyphs(std::wstring_view str, void MultiLineTextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor, unsigned wrap) {
const zeus::CColor& defaultColor, if (wrap) {
unsigned wrap)
{
if (wrap)
{
typesetGlyphs(LineWrap(str, wrap), defaultColor); typesetGlyphs(LineWrap(str, wrap), defaultColor);
return; return;
} }
@ -227,8 +191,7 @@ void MultiLineTextView::typesetGlyphs(std::wstring_view str,
auto it = str.cbegin(); auto it = str.cbegin();
size_t lineCount = 0; size_t lineCount = 0;
while (rem) while (rem) {
{
if (*it == L'\n' || *it == L'\0') if (*it == L'\n' || *it == L'\0')
++lineCount; ++lineCount;
--rem; --rem;
@ -241,12 +204,12 @@ void MultiLineTextView::typesetGlyphs(std::wstring_view str,
auto beginIt = it; auto beginIt = it;
size_t lineIt = 0; size_t lineIt = 0;
while (rem) while (rem) {
{ if (*it == L'\n' || *it == L'\0') {
if (*it == L'\n' || *it == L'\0') TextView& tv =
{ (lineIt < m_lines.size())
TextView& tv = (lineIt < m_lines.size()) ? *m_lines[lineIt] : ? *m_lines[lineIt]
*m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity)); : *m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::wstring(beginIt, it), defaultColor); tv.typesetGlyphs(std::wstring(beginIt, it), defaultColor);
m_width = std::max(m_width, tv.nominalWidth()); m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1; beginIt = it + 1;
@ -259,32 +222,28 @@ void MultiLineTextView::typesetGlyphs(std::wstring_view str,
updateSize(); updateSize();
} }
void MultiLineTextView::colorGlyphs(const zeus::CColor& newColor) void MultiLineTextView::colorGlyphs(const zeus::CColor& newColor) {
{
for (std::unique_ptr<TextView>& tv : m_lines) for (std::unique_ptr<TextView>& tv : m_lines)
tv->colorGlyphs(newColor); tv->colorGlyphs(newColor);
} }
void MultiLineTextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void MultiLineTextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
unsigned lHeight = unsigned(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6; unsigned lHeight = unsigned(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6;
unsigned decumHeight = lHeight * m_lines.size(); unsigned decumHeight = lHeight * m_lines.size();
boo::SWindowRect tsub = sub; boo::SWindowRect tsub = sub;
tsub.location[1] += decumHeight; tsub.location[1] += decumHeight;
tsub.size[1] = 10; tsub.size[1] = 10;
for (std::unique_ptr<TextView>& tv : m_lines) for (std::unique_ptr<TextView>& tv : m_lines) {
{
tsub.location[1] -= lHeight; tsub.location[1] -= lHeight;
tv->resized(root, tsub); tv->resized(root, tsub);
} }
} }
void MultiLineTextView::draw(boo::IGraphicsCommandQueue* gfxQ) void MultiLineTextView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
for (std::unique_ptr<TextView>& tv : m_lines) for (std::unique_ptr<TextView>& tv : m_lines)
tv->draw(gfxQ); tv->draw(gfxQ);
} }
} } // namespace specter

View File

@ -2,18 +2,15 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
PathButtons::PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer) PathButtons::PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer)
: ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer) : ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer) {
{
m_contentView.m_view.reset(new ContentView(res, *this)); m_contentView.m_view.reset(new ContentView(res, *this));
setContentView(m_contentView.m_view.get()); setContentView(m_contentView.m_view.get());
} }
void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps) void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps) {
{
m_pathButtons.clear(); m_pathButtons.clear();
m_pathButtons.reserve(comps.size()); m_pathButtons.reserve(comps.size());
size_t idx = 0; size_t idx = 0;
@ -22,51 +19,45 @@ void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps)
m_pathButtons.emplace_back(*this, res, idx++, c); m_pathButtons.emplace_back(*this, res, idx++, c);
} }
void PathButtons::setMultiplyColor(const zeus::CColor& color) void PathButtons::setMultiplyColor(const zeus::CColor& color) {
{
ScrollView::setMultiplyColor(color); ScrollView::setMultiplyColor(color);
for (PathButton& b : m_pathButtons) for (PathButton& b : m_pathButtons)
b.m_button.m_view->setMultiplyColor(color); b.m_button.m_view->setMultiplyColor(color);
} }
void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseDown(coord, button, mod); b.m_button.mouseDown(coord, button, mod);
} }
void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseUp(coord, button, mod); b.m_button.mouseUp(coord, button, mod);
if (m_pb.m_pathButtonPending >= 0) if (m_pb.m_pathButtonPending >= 0) {
{
m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending); m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending);
m_pb.m_pathButtonPending = -1; m_pb.m_pathButtonPending = -1;
} }
} }
void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord) void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord) {
{
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseMove(coord); b.m_button.mouseMove(coord);
} }
void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord) void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord) {
{
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseLeave(coord); b.m_button.mouseLeave(coord);
} }
void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{
View::resized(root, sub); View::resized(root, sub);
m_scissorRect = scissor; m_scissorRect = scissor;
m_scissorRect.size[1] += 2; m_scissorRect.size[1] += 2;
boo::SWindowRect pathRect = sub; boo::SWindowRect pathRect = sub;
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons) {
{
pathRect.size[0] = b.m_button.m_view->nominalWidth(); pathRect.size[0] = b.m_button.m_view->nominalWidth();
pathRect.size[1] = b.m_button.m_view->nominalHeight(); pathRect.size[1] = b.m_button.m_view->nominalHeight();
b.m_button.m_view->resized(root, pathRect); b.m_button.m_view->resized(root, pathRect);
@ -74,22 +65,19 @@ void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::
} }
} }
void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ if (m_fillContainer) {
if (m_fillContainer)
{
boo::SWindowRect fillRect = sub; boo::SWindowRect fillRect = sub;
fillRect.size[1] = 20 * rootView().viewRes().pixelFactor(); fillRect.size[1] = 20 * rootView().viewRes().pixelFactor();
View::resized(root, fillRect); View::resized(root, fillRect);
} }
} }
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
gfxQ->setScissor(m_scissorRect); gfxQ->setScissor(m_scissorRect);
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.m_view->draw(gfxQ); b.m_button.m_view->draw(gfxQ);
gfxQ->setScissor(rootView().subRect()); gfxQ->setScissor(rootView().subRect());
} }
} } // namespace specter

View File

@ -3,17 +3,14 @@
#include "specter/Space.hpp" #include "specter/Space.hpp"
#include "specter/Menu.hpp" #include "specter/Menu.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::RootView"); static logvisor::Module Log("specter::RootView");
RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* window) RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* window)
: View(res), m_window(window), m_viewMan(viewMan), m_viewRes(&res), m_events(*this) : View(res), m_window(window), m_viewMan(viewMan), m_viewRes(&res), m_events(*this) {
{
window->setCallback(&m_events); window->setCallback(&m_events);
boo::SWindowRect rect = window->getWindowFrame(); boo::SWindowRect rect = window->getWindowFrame();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
{
buildResources(ctx, res); buildResources(ctx, res);
m_splitMenuSystem.emplace(*this, ctx); m_splitMenuSystem.emplace(*this, ctx);
m_renderTex = ctx.newRenderTexture(rect.size[0], rect.size[1], boo::TextureClampMode::ClampToEdge, 3, 3); m_renderTex = ctx.newRenderTexture(rect.size[0], rect.size[1], boo::TextureClampMode::ClampToEdge, 3, 3);
@ -22,15 +19,13 @@ RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* wind
resized(rect, rect); resized(rect, rect);
} }
RootView::~RootView() RootView::~RootView() { m_window->setCallback(nullptr); }
{
m_window->setCallback(nullptr);
}
RootView::SplitMenuSystem::SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx) RootView::SplitMenuSystem::SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx)
: m_rv(rv), m_text(rv.m_viewMan.translateOr("boundary_action", "Boundary Action")), : m_rv(rv)
m_splitActionNode(*this), m_joinActionNode(*this) , m_text(rv.m_viewMan.translateOr("boundary_action", "Boundary Action"))
{ , m_splitActionNode(*this)
, m_joinActionNode(*this) {
ViewResources& res = *rv.m_viewRes; ViewResources& res = *rv.m_viewRes;
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 32, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 32, m_viewVertBlockBuf);
@ -86,48 +81,40 @@ RootView::SplitMenuSystem::SplitActionNode::SplitActionNode(SplitMenuSystem& smn
RootView::SplitMenuSystem::JoinActionNode::JoinActionNode(SplitMenuSystem& smn) RootView::SplitMenuSystem::JoinActionNode::JoinActionNode(SplitMenuSystem& smn)
: m_smn(smn), m_text(smn.m_rv.m_viewMan.translateOr("join", "Join")) {} : m_smn(smn), m_text(smn.m_rv.m_viewMan.translateOr("join", "Join")) {}
void RootView::SplitMenuSystem::setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir) void RootView::SplitMenuSystem::setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir) {
{
const boo::SWindowRect& root = m_rv.subRect(); const boo::SWindowRect& root = m_rv.subRect();
if (dir == SplitView::ArrowDir::Left || dir == SplitView::ArrowDir::Right) if (dir == SplitView::ArrowDir::Left || dir == SplitView::ArrowDir::Right) {
{
m_viewBlock.m_mv[0][1] = 2.0f * rect.size[1] / float(root.size[1]); m_viewBlock.m_mv[0][1] = 2.0f * rect.size[1] / float(root.size[1]);
m_viewBlock.m_mv[0][0] = 0.0f; m_viewBlock.m_mv[0][0] = 0.0f;
m_viewBlock.m_mv[1][0] = 2.0f * (dir == SplitView::ArrowDir::Left ? -rect.size[0] : rect.size[0]) / m_viewBlock.m_mv[1][0] =
float(root.size[0]); 2.0f * (dir == SplitView::ArrowDir::Left ? -rect.size[0] : rect.size[0]) / float(root.size[0]);
m_viewBlock.m_mv[1][1] = 0.0f; m_viewBlock.m_mv[1][1] = 0.0f;
m_viewBlock.m_mv[3][0] = 2.0f * (rect.location[0] + (dir == SplitView::ArrowDir::Left ? rect.size[0] : 0)) / m_viewBlock.m_mv[3][0] =
float(root.size[0]) - 1.0f; 2.0f * (rect.location[0] + (dir == SplitView::ArrowDir::Left ? rect.size[0] : 0)) / float(root.size[0]) - 1.0f;
m_viewBlock.m_mv[3][1] = 2.0f * rect.location[1] / float(root.size[1]) - 1.0f; m_viewBlock.m_mv[3][1] = 2.0f * rect.location[1] / float(root.size[1]) - 1.0f;
} } else {
else
{
m_viewBlock.m_mv[0][0] = 2.0f * rect.size[0] / float(root.size[0]); m_viewBlock.m_mv[0][0] = 2.0f * rect.size[0] / float(root.size[0]);
m_viewBlock.m_mv[0][1] = 0.0f; m_viewBlock.m_mv[0][1] = 0.0f;
m_viewBlock.m_mv[1][1] = 2.0f * (dir == SplitView::ArrowDir::Down ? -rect.size[1] : rect.size[1]) / m_viewBlock.m_mv[1][1] =
float(root.size[1]); 2.0f * (dir == SplitView::ArrowDir::Down ? -rect.size[1] : rect.size[1]) / float(root.size[1]);
m_viewBlock.m_mv[1][0] = 0.0f; m_viewBlock.m_mv[1][0] = 0.0f;
m_viewBlock.m_mv[3][0] = 2.0f * rect.location[0] / float(root.size[0]) - 1.0f; m_viewBlock.m_mv[3][0] = 2.0f * rect.location[0] / float(root.size[0]) - 1.0f;
m_viewBlock.m_mv[3][1] = 2.0f * (rect.location[1] + (dir == SplitView::ArrowDir::Down ? rect.size[1] : 0)) / m_viewBlock.m_mv[3][1] =
float(root.size[1]) - 1.0f; 2.0f * (rect.location[1] + (dir == SplitView::ArrowDir::Down ? rect.size[1] : 0)) / float(root.size[1]) - 1.0f;
} }
m_viewVertBlockBuf.access().finalAssign(m_viewBlock); m_viewVertBlockBuf.access().finalAssign(m_viewBlock);
} }
void RootView::SplitMenuSystem::setLineVerts(const boo::SWindowRect& rect, float split, SplitView::Axis axis) void RootView::SplitMenuSystem::setLineVerts(const boo::SWindowRect& rect, float split, SplitView::Axis axis) {
{
const boo::SWindowRect& root = m_rv.subRect(); const boo::SWindowRect& root = m_rv.subRect();
if (axis == SplitView::Axis::Horizontal) if (axis == SplitView::Axis::Horizontal) {
{
m_viewBlock.m_mv[0][0] = rect.size[0] / float(root.size[0]); m_viewBlock.m_mv[0][0] = rect.size[0] / float(root.size[0]);
m_viewBlock.m_mv[0][1] = 0.0f; m_viewBlock.m_mv[0][1] = 0.0f;
m_viewBlock.m_mv[1][1] = 2.0f / float(root.size[1]); m_viewBlock.m_mv[1][1] = 2.0f / float(root.size[1]);
m_viewBlock.m_mv[1][0] = 0.0f; m_viewBlock.m_mv[1][0] = 0.0f;
m_viewBlock.m_mv[3][0] = 2.0f * (rect.location[0] + rect.size[0] / 2.0f) / float(root.size[0]) - 1.0f; m_viewBlock.m_mv[3][0] = 2.0f * (rect.location[0] + rect.size[0] / 2.0f) / float(root.size[0]) - 1.0f;
m_viewBlock.m_mv[3][1] = (rect.location[1] + split * rect.size[1]) * m_viewBlock.m_mv[1][1] - 1.0f; m_viewBlock.m_mv[3][1] = (rect.location[1] + split * rect.size[1]) * m_viewBlock.m_mv[1][1] - 1.0f;
} } else {
else
{
m_viewBlock.m_mv[0][0] = 2.0f / float(root.size[0]); m_viewBlock.m_mv[0][0] = 2.0f / float(root.size[0]);
m_viewBlock.m_mv[0][1] = 0.0f; m_viewBlock.m_mv[0][1] = 0.0f;
m_viewBlock.m_mv[1][1] = rect.size[1] / float(root.size[1]); m_viewBlock.m_mv[1][1] = rect.size[1] / float(root.size[1]);
@ -138,13 +125,9 @@ void RootView::SplitMenuSystem::setLineVerts(const boo::SWindowRect& rect, float
m_viewVertBlockBuf.access().finalAssign(m_viewBlock); m_viewVertBlockBuf.access().finalAssign(m_viewBlock);
} }
void RootView::destroyed() void RootView::destroyed() { m_destroyed = true; }
{
m_destroyed = true;
}
void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&) void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&) {
{
m_rootRect = root; m_rootRect = root;
m_rootRect.location[0] = 0; m_rootRect.location[0] = 0;
m_rootRect.location[1] = 0; m_rootRect.location[1] = 0;
@ -153,8 +136,7 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
v->resized(m_rootRect, m_rootRect); v->resized(m_rootRect, m_rootRect);
if (m_tooltip) if (m_tooltip)
m_tooltip->resized(m_rootRect, m_rootRect); m_tooltip->resized(m_rootRect, m_rootRect);
if (m_rightClickMenu.m_view) if (m_rightClickMenu.m_view) {
{
float wr = root.size[0] / float(m_rightClickMenuRootAndLoc.size[0]); float wr = root.size[0] / float(m_rightClickMenuRootAndLoc.size[0]);
float hr = root.size[1] / float(m_rightClickMenuRootAndLoc.size[1]); float hr = root.size[1] / float(m_rightClickMenuRootAndLoc.size[1]);
m_rightClickMenuRootAndLoc.size[0] = root.size[0]; m_rightClickMenuRootAndLoc.size[0] = root.size[0];
@ -167,17 +149,13 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
m_resizeRTDirty = true; m_resizeRTDirty = true;
} }
void RootView::SplitMenuSystem::resized() void RootView::SplitMenuSystem::resized() {
{ if (m_phase == Phase::InteractiveJoin) {
if (m_phase == Phase::InteractiveJoin)
{
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::ArrowDir arrow; SplitView::ArrowDir arrow;
m_splitView->getJoinArrowHover(m_interactiveSlot, rect, arrow); m_splitView->getJoinArrowHover(m_interactiveSlot, rect, arrow);
setArrowVerts(rect, arrow); setArrowVerts(rect, arrow);
} } else if (m_phase == Phase::InteractiveSplit) {
else if (m_phase == Phase::InteractiveSplit)
{
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::Axis axis; SplitView::Axis axis;
m_splitView->getSplitLineHover(m_interactiveSlot, rect, axis); m_splitView->getSplitLineHover(m_interactiveSlot, rect, axis);
@ -185,38 +163,30 @@ void RootView::SplitMenuSystem::resized()
} }
} }
void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{ if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
m_splitMenuSystem->mouseDown(coord, button, mods); m_splitMenuSystem->mouseDown(coord, button, mods);
return; return;
} }
if (m_rightClickMenu.m_view) if (m_rightClickMenu.m_view) {
{
if (!m_rightClickMenu.mouseDown(coord, button, mods)) if (!m_rightClickMenu.mouseDown(coord, button, mods))
m_rightClickMenu.m_view.reset(); m_rightClickMenu.m_view.reset();
return; return;
} }
if (m_activeMenuButton) if (m_activeMenuButton) {
{
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu(); ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
if (!mv.mouseDown(coord, button, mods)) if (!mv.mouseDown(coord, button, mods))
m_activeMenuButton->closeMenu(coord); m_activeMenuButton->closeMenu(coord);
return; return;
} }
if (m_hoverSplitDragView) if (m_hoverSplitDragView) {
{ if (button == boo::EMouseButton::Primary) {
if (button == boo::EMouseButton::Primary)
{
m_activeSplitDragView = true; m_activeSplitDragView = true;
m_hoverSplitDragView->startDragSplit(coord); m_hoverSplitDragView->startDragSplit(coord);
} } else if (button == boo::EMouseButton::Secondary) {
else if (button == boo::EMouseButton::Secondary)
{
m_splitMenuSystem->m_splitView = m_hoverSplitDragView; m_splitMenuSystem->m_splitView = m_hoverSplitDragView;
adoptRightClickMenu(std::make_unique<specter::Menu>(*m_viewRes, *this, &*m_splitMenuSystem), coord); adoptRightClickMenu(std::make_unique<specter::Menu>(*m_viewRes, *this, &*m_splitMenuSystem), coord);
} }
@ -229,55 +199,45 @@ void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butto
v->mouseDown(coord, button, mods); v->mouseDown(coord, button, mods);
} }
void RootView::SplitMenuSystem::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::SplitMenuSystem::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mods) {
if (m_phase == Phase::InteractiveJoin) if (m_phase == Phase::InteractiveJoin) {
{
int origDummy; int origDummy;
SplitView* selSplit; SplitView* selSplit;
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::ArrowDir arrow; SplitView::ArrowDir arrow;
if (m_splitView->testJoinArrowHover(coord, origDummy, selSplit, m_interactiveSlot, rect, arrow)) if (m_splitView->testJoinArrowHover(coord, origDummy, selSplit, m_interactiveSlot, rect, arrow)) {
{
setArrowVerts(rect, arrow); setArrowVerts(rect, arrow);
m_interactiveDown = true; m_interactiveDown = true;
} }
} } else if (m_phase == Phase::InteractiveSplit) {
else if (m_phase == Phase::InteractiveSplit)
{
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::Axis axis; SplitView::Axis axis;
if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis)) if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis)) {
{
setLineVerts(rect, m_interactiveSplit, axis); setLineVerts(rect, m_interactiveSplit, axis);
m_interactiveDown = true; m_interactiveDown = true;
} }
} }
} }
void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{ if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
m_splitMenuSystem->mouseUp(coord, button, mods); m_splitMenuSystem->mouseUp(coord, button, mods);
return; return;
} }
if (m_rightClickMenu.m_view) if (m_rightClickMenu.m_view) {
{
m_rightClickMenu.mouseUp(coord, button, mods); m_rightClickMenu.mouseUp(coord, button, mods);
return; return;
} }
if (m_activeMenuButton) if (m_activeMenuButton) {
{
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu(); ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
mv.mouseUp(coord, button, mods); mv.mouseUp(coord, button, mods);
return; return;
} }
if (m_activeSplitDragView && button == boo::EMouseButton::Primary) if (m_activeSplitDragView && button == boo::EMouseButton::Primary) {
{
m_activeSplitDragView = false; m_activeSplitDragView = false;
m_hoverSplitDragView->endDragSplit(); m_hoverSplitDragView->endDragSplit();
m_spaceCornerHover = false; m_spaceCornerHover = false;
@ -290,39 +250,31 @@ void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
v->mouseUp(coord, button, mods); v->mouseUp(coord, button, mods);
} }
void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mods) {
if (m_phase == Phase::InteractiveJoin) if (m_phase == Phase::InteractiveJoin) {
{
int origSlot; int origSlot;
SplitView* selSplit; SplitView* selSplit;
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::ArrowDir arrow; SplitView::ArrowDir arrow;
if (m_splitView->testJoinArrowHover(coord, origSlot, selSplit, m_interactiveSlot, rect, arrow)) if (m_splitView->testJoinArrowHover(coord, origSlot, selSplit, m_interactiveSlot, rect, arrow)) {
{
setArrowVerts(rect, arrow); setArrowVerts(rect, arrow);
if (m_interactiveDown) if (m_interactiveDown) {
{
m_interactiveDown = false; m_interactiveDown = false;
m_phase = Phase::Inactive; m_phase = Phase::Inactive;
m_splitView->m_controller->joinViews(m_splitView, origSlot, selSplit, m_interactiveSlot); m_splitView->m_controller->joinViews(m_splitView, origSlot, selSplit, m_interactiveSlot);
} }
} }
} } else if (m_phase == Phase::InteractiveSplit) {
else if (m_phase == Phase::InteractiveSplit)
{
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::Axis axis; SplitView::Axis axis;
if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis)) if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis)) {
{
setLineVerts(rect, m_interactiveSplit, axis); setLineVerts(rect, m_interactiveSplit, axis);
if (m_interactiveDown) if (m_interactiveDown) {
{
m_interactiveDown = false; m_interactiveDown = false;
m_phase = Phase::Inactive; m_phase = Phase::Inactive;
Space* space = m_splitView->m_views[m_interactiveSlot].m_view->castToSpace(); Space* space = m_splitView->m_views[m_interactiveSlot].m_view->castToSpace();
if (space && space->m_controller.spaceSplitAllowed()) if (space && space->m_controller.spaceSplitAllowed()) {
{
ISplitSpaceController* ss = space->m_controller.spaceSplit(axis, 0); ISplitSpaceController* ss = space->m_controller.spaceSplit(axis, 0);
ss->splitView()->setSplit(m_interactiveSplit); ss->splitView()->setSplit(m_interactiveSplit);
} }
@ -331,15 +283,12 @@ void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMo
} }
} }
SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const {
{
if (sv->testSplitHover(coord)) if (sv->testSplitHover(coord))
return sv; return sv;
for (int i=0 ; i<2 ; ++i) for (int i = 0; i < 2; ++i) {
{
SplitView* child = sv->m_views[i].m_view->castToSplitView(); SplitView* child = sv->m_views[i].m_view->castToSplitView();
if (child) if (child) {
{
SplitView* res = recursiveTestSplitHover(child, coord); SplitView* res = recursiveTestSplitHover(child, coord);
if (res) if (res)
return res; return res;
@ -348,16 +297,13 @@ SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCo
return nullptr; return nullptr;
} }
void RootView::mouseMove(const boo::SWindowCoord& coord) void RootView::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
m_splitMenuSystem->mouseMove(coord); m_splitMenuSystem->mouseMove(coord);
return; return;
} }
if (m_rightClickMenu.m_view) if (m_rightClickMenu.m_view) {
{
m_hSplitHover = false; m_hSplitHover = false;
m_vSplitHover = false; m_vSplitHover = false;
_updateCursor(); _updateCursor();
@ -365,8 +311,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
return; return;
} }
if (m_activeMenuButton) if (m_activeMenuButton) {
{
m_hSplitHover = false; m_hSplitHover = false;
m_vSplitHover = false; m_vSplitHover = false;
_updateCursor(); _updateCursor();
@ -375,8 +320,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
return; return;
} }
if (m_activeSplitDragView) if (m_activeSplitDragView) {
{
m_hoverSplitDragView->moveDragSplit(coord); m_hoverSplitDragView->moveDragSplit(coord);
m_spaceCornerHover = false; m_spaceCornerHover = false;
if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal) if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal)
@ -387,20 +331,15 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
} }
m_hoverSplitDragView = nullptr; m_hoverSplitDragView = nullptr;
if (!m_spaceCornerHover) if (!m_spaceCornerHover) {
{ for (View* v : m_views) {
for (View* v : m_views)
{
SplitView* sv = v->castToSplitView(); SplitView* sv = v->castToSplitView();
if (sv) if (sv)
sv = recursiveTestSplitHover(sv, coord); sv = recursiveTestSplitHover(sv, coord);
if (sv) if (sv) {
{
m_hoverSplitDragView = sv; m_hoverSplitDragView = sv;
break; break;
} } else {
else
{
m_hSplitHover = false; m_hSplitHover = false;
m_vSplitHover = false; m_vSplitHover = false;
_updateCursor(); _updateCursor();
@ -410,14 +349,12 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
if (m_activeDragView) if (m_activeDragView)
m_activeDragView->mouseMove(coord); m_activeDragView->mouseMove(coord);
else else {
{
for (View* v : m_views) for (View* v : m_views)
v->mouseMove(coord); v->mouseMove(coord);
} }
if (m_hoverSplitDragView) if (m_hoverSplitDragView) {
{
if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal) if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal)
setHorizontalSplitHover(true); setHorizontalSplitHover(true);
else else
@ -427,8 +364,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
boo::SWindowRect ttrect = m_rootRect; boo::SWindowRect ttrect = m_rootRect;
ttrect.location[0] = coord.pixel[0]; ttrect.location[0] = coord.pixel[0];
ttrect.location[1] = coord.pixel[1]; ttrect.location[1] = coord.pixel[1];
if (m_tooltip) if (m_tooltip) {
{
if (coord.pixel[0] + m_tooltip->nominalWidth() > m_rootRect.size[0]) if (coord.pixel[0] + m_tooltip->nominalWidth() > m_rootRect.size[0])
ttrect.location[0] -= m_tooltip->nominalWidth(); ttrect.location[0] -= m_tooltip->nominalWidth();
if (coord.pixel[1] + m_tooltip->nominalHeight() > m_rootRect.size[1]) if (coord.pixel[1] + m_tooltip->nominalHeight() > m_rootRect.size[1])
@ -437,19 +373,15 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
} }
} }
void RootView::SplitMenuSystem::mouseMove(const boo::SWindowCoord& coord) void RootView::SplitMenuSystem::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_phase == Phase::InteractiveJoin) {
if (m_phase == Phase::InteractiveJoin)
{
int origDummy; int origDummy;
SplitView* selSplit; SplitView* selSplit;
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::ArrowDir arrow; SplitView::ArrowDir arrow;
if (m_splitView->testJoinArrowHover(coord, origDummy, selSplit, m_interactiveSlot, rect, arrow)) if (m_splitView->testJoinArrowHover(coord, origDummy, selSplit, m_interactiveSlot, rect, arrow))
setArrowVerts(rect, arrow); setArrowVerts(rect, arrow);
} } else if (m_phase == Phase::InteractiveSplit) {
else if (m_phase == Phase::InteractiveSplit)
{
boo::SWindowRect rect; boo::SWindowRect rect;
SplitView::Axis axis; SplitView::Axis axis;
if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis)) if (m_splitView->testSplitLineHover(coord, m_interactiveSlot, rect, m_interactiveSplit, axis))
@ -457,28 +389,23 @@ void RootView::SplitMenuSystem::mouseMove(const boo::SWindowCoord& coord)
} }
} }
void RootView::mouseEnter(const boo::SWindowCoord& coord) void RootView::mouseEnter(const boo::SWindowCoord& coord) {
{
for (View* v : m_views) for (View* v : m_views)
v->mouseEnter(coord); v->mouseEnter(coord);
} }
void RootView::mouseLeave(const boo::SWindowCoord& coord) void RootView::mouseLeave(const boo::SWindowCoord& coord) {
{ if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
m_splitMenuSystem->mouseLeave(coord); m_splitMenuSystem->mouseLeave(coord);
return; return;
} }
if (m_rightClickMenu.m_view) if (m_rightClickMenu.m_view) {
{
m_rightClickMenu.mouseLeave(coord); m_rightClickMenu.mouseLeave(coord);
return; return;
} }
if (m_activeMenuButton) if (m_activeMenuButton) {
{
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu(); ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
mv.mouseLeave(coord); mv.mouseLeave(coord);
return; return;
@ -488,15 +415,10 @@ void RootView::mouseLeave(const boo::SWindowCoord& coord)
v->mouseLeave(coord); v->mouseLeave(coord);
} }
void RootView::SplitMenuSystem::mouseLeave(const boo::SWindowCoord& coord) void RootView::SplitMenuSystem::mouseLeave(const boo::SWindowCoord& coord) {}
{
} void RootView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
if (m_activeMenuButton) {
void RootView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
{
if (m_activeMenuButton)
{
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu(); ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
mv.scroll(coord, scroll); mv.scroll(coord, scroll);
return; return;
@ -506,31 +428,25 @@ void RootView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& s
v->scroll(coord, scroll); v->scroll(coord, scroll);
} }
void RootView::touchDown(const boo::STouchCoord& coord, uintptr_t tid) void RootView::touchDown(const boo::STouchCoord& coord, uintptr_t tid) {
{
for (View* v : m_views) for (View* v : m_views)
v->touchDown(coord, tid); v->touchDown(coord, tid);
} }
void RootView::touchUp(const boo::STouchCoord& coord, uintptr_t tid) void RootView::touchUp(const boo::STouchCoord& coord, uintptr_t tid) {
{
for (View* v : m_views) for (View* v : m_views)
v->touchUp(coord, tid); v->touchUp(coord, tid);
} }
void RootView::touchMove(const boo::STouchCoord& coord, uintptr_t tid) void RootView::touchMove(const boo::STouchCoord& coord, uintptr_t tid) {
{
for (View* v : m_views) for (View* v : m_views)
v->touchMove(coord, tid); v->touchMove(coord, tid);
} }
void RootView::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) void RootView::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
{
for (View* v : m_views) for (View* v : m_views)
v->charKeyDown(charCode, mods, isRepeat); v->charKeyDown(charCode, mods, isRepeat);
if (m_activeTextView && if (m_activeTextView && (mods & (boo::EModifierKey::Ctrl | boo::EModifierKey::Command)) != boo::EModifierKey::None) {
(mods & (boo::EModifierKey::Ctrl|boo::EModifierKey::Command)) != boo::EModifierKey::None)
{
if (charCode == 'c' || charCode == 'C') if (charCode == 'c' || charCode == 'C')
m_activeTextView->clipboardCopy(); m_activeTextView->clipboardCopy();
else if (charCode == 'x' || charCode == 'X') else if (charCode == 'x' || charCode == 'X')
@ -540,21 +456,17 @@ void RootView::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool
} }
} }
void RootView::charKeyUp(unsigned long charCode, boo::EModifierKey mods) void RootView::charKeyUp(unsigned long charCode, boo::EModifierKey mods) {
{
for (View* v : m_views) for (View* v : m_views)
v->charKeyUp(charCode, mods); v->charKeyUp(charCode, mods);
} }
void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
{ if (key == boo::ESpecialKey::Enter && (mods & boo::EModifierKey::Alt) != boo::EModifierKey::None) {
if (key == boo::ESpecialKey::Enter && (mods & boo::EModifierKey::Alt) != boo::EModifierKey::None)
{
m_window->setFullscreen(!m_window->isFullscreen()); m_window->setFullscreen(!m_window->isFullscreen());
return; return;
} }
if (key == boo::ESpecialKey::Esc && m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) if (key == boo::ESpecialKey::Esc && m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
{
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::Inactive; m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::Inactive;
return; return;
} }
@ -564,51 +476,48 @@ void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool
m_activeTextView->specialKeyDown(key, mods, isRepeat); m_activeTextView->specialKeyDown(key, mods, isRepeat);
} }
void RootView::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) void RootView::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {
{
for (View* v : m_views) for (View* v : m_views)
v->specialKeyUp(key, mods); v->specialKeyUp(key, mods);
if (m_activeTextView) if (m_activeTextView)
m_activeTextView->specialKeyUp(key, mods); m_activeTextView->specialKeyUp(key, mods);
} }
void RootView::modKeyDown(boo::EModifierKey mod, bool isRepeat) void RootView::modKeyDown(boo::EModifierKey mod, bool isRepeat) {
{
for (View* v : m_views) for (View* v : m_views)
v->modKeyDown(mod, isRepeat); v->modKeyDown(mod, isRepeat);
if (m_activeTextView) if (m_activeTextView)
m_activeTextView->modKeyDown(mod, isRepeat); m_activeTextView->modKeyDown(mod, isRepeat);
} }
void RootView::modKeyUp(boo::EModifierKey mod) void RootView::modKeyUp(boo::EModifierKey mod) {
{
for (View* v : m_views) for (View* v : m_views)
v->modKeyUp(mod); v->modKeyUp(mod);
if (m_activeTextView) if (m_activeTextView)
m_activeTextView->modKeyUp(mod); m_activeTextView->modKeyUp(mod);
} }
void RootView::resetTooltip(ViewResources& res) void RootView::resetTooltip(ViewResources& res) {
{ m_tooltip.reset(
m_tooltip.reset(new Tooltip(res, *this, "Test", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi hendrerit nisl quis lobortis mattis. Mauris efficitur, est a vestibulum iaculis, leo orci pellentesque nunc, non rutrum ipsum lectus eget nisl. Aliquam accumsan vestibulum turpis. Duis id lacus ac lectus sollicitudin posuere vel sit amet metus. Aenean nec tortor id enim efficitur accumsan vitae eu ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce magna eros, lacinia a leo eget, volutpat rhoncus urna.")); new Tooltip(res, *this, "Test",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi hendrerit nisl quis lobortis mattis. "
"Mauris efficitur, est a vestibulum iaculis, leo orci pellentesque nunc, non rutrum ipsum lectus "
"eget nisl. Aliquam accumsan vestibulum turpis. Duis id lacus ac lectus sollicitudin posuere vel sit "
"amet metus. Aenean nec tortor id enim efficitur accumsan vitae eu ante. Lorem ipsum dolor sit amet, "
"consectetur adipiscing elit. Fusce magna eros, lacinia a leo eget, volutpat rhoncus urna."));
} }
void RootView::displayTooltip(std::string_view name, std::string_view help) void RootView::displayTooltip(std::string_view name, std::string_view help) {}
{
}
void RootView::internalThink() void RootView::internalThink() {
{ if (m_splitMenuSystem->m_deferredSplit) {
if (m_splitMenuSystem->m_deferredSplit)
{
m_splitMenuSystem->m_deferredSplit = false; m_splitMenuSystem->m_deferredSplit = false;
m_rightClickMenu.m_view.reset(); m_rightClickMenu.m_view.reset();
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveSplit; m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveSplit;
m_splitMenuSystem->mouseMove(m_splitMenuSystem->m_deferredCoord); m_splitMenuSystem->mouseMove(m_splitMenuSystem->m_deferredCoord);
} }
if (m_splitMenuSystem->m_deferredJoin) if (m_splitMenuSystem->m_deferredJoin) {
{
m_splitMenuSystem->m_deferredJoin = false; m_splitMenuSystem->m_deferredJoin = false;
m_rightClickMenu.m_view.reset(); m_rightClickMenu.m_view.reset();
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin; m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
@ -619,10 +528,8 @@ void RootView::internalThink()
m_rightClickMenu.m_view->think(); m_rightClickMenu.m_view->think();
} }
void RootView::draw(boo::IGraphicsCommandQueue* gfxQ) void RootView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ if (m_resizeRTDirty) {
if (m_resizeRTDirty)
{
gfxQ->resizeRenderTexture(m_renderTex, m_rootRect.size[0], m_rootRect.size[1]); gfxQ->resizeRenderTexture(m_renderTex, m_rootRect.size[0], m_rootRect.size[1]);
m_resizeRTDirty = false; m_resizeRTDirty = false;
gfxQ->schedulePostFrameHandler([&]() { m_events.m_resizeCv.notify_one(); }); gfxQ->schedulePostFrameHandler([&]() { m_events.m_resizeCv.notify_one(); });
@ -642,8 +549,7 @@ void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->resolveDisplay(m_renderTex); gfxQ->resolveDisplay(m_renderTex);
} }
void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ) void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
if (m_phase == Phase::Inactive) if (m_phase == Phase::Inactive)
return; return;
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
@ -653,4 +559,4 @@ void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->draw(28, 4); gfxQ->draw(28, 4);
} }
} } // namespace specter

View File

@ -3,31 +3,25 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/Button.hpp" #include "specter/Button.hpp"
namespace specter namespace specter {
{
#define MAX_SCROLL_SPEED 100 #define MAX_SCROLL_SPEED 100
ScrollView::ScrollView(ViewResources& res, View& parentView, Style style) ScrollView::ScrollView(ViewResources& res, View& parentView, Style style)
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) : View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true; return true;
}); });
if (style == Style::SideButtons) if (style == Style::SideButtons) {
{
m_sideButtons[0].m_view.reset(new Button(res, *this, &m_sideButtonBind, "<")); m_sideButtons[0].m_view.reset(new Button(res, *this, &m_sideButtonBind, "<"));
m_sideButtons[1].m_view.reset(new Button(res, *this, &m_sideButtonBind, ">")); m_sideButtons[1].m_view.reset(new Button(res, *this, &m_sideButtonBind, ">"));
} }
} }
bool ScrollView::_scroll(const boo::SScrollDelta& scroll) bool ScrollView::_scroll(const boo::SScrollDelta& scroll) {
{ if (m_contentView.m_view) {
if (m_contentView.m_view)
{
float ratioX = subRect().size[0] / float(m_contentView.m_view->nominalWidth()); float ratioX = subRect().size[0] / float(m_contentView.m_view->nominalWidth());
float ratioY = subRect().size[1] / float(m_contentView.m_view->nominalHeight()); float ratioY = subRect().size[1] / float(m_contentView.m_view->nominalHeight());
@ -38,15 +32,12 @@ bool ScrollView::_scroll(const boo::SScrollDelta& scroll)
bool ret = false; bool ret = false;
if (ratioX >= 1.f) if (ratioX >= 1.f) {
{
m_scroll[0] = 0; m_scroll[0] = 0;
m_targetScroll[0] = 0; m_targetScroll[0] = 0;
m_drawSideButtons = false; m_drawSideButtons = false;
ret = true; ret = true;
} } else {
else
{
m_drawSideButtons = true; m_drawSideButtons = true;
m_targetScroll[0] += scroll.delta[0] * mult; m_targetScroll[0] += scroll.delta[0] * mult;
m_targetScroll[0] = std::min(m_targetScroll[0], 0); m_targetScroll[0] = std::min(m_targetScroll[0], 0);
@ -54,31 +45,25 @@ bool ScrollView::_scroll(const boo::SScrollDelta& scroll)
m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth); m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth);
} }
if (ratioY >= 1.f) if (ratioY >= 1.f) {
{
m_scroll[1] = 0; m_scroll[1] = 0;
m_targetScroll[1] = 0; m_targetScroll[1] = 0;
ret = true; ret = true;
} } else {
else
{
m_targetScroll[1] -= scroll.delta[1] * mult; m_targetScroll[1] -= scroll.delta[1] * mult;
m_targetScroll[1] = std::max(m_targetScroll[1], 0); m_targetScroll[1] = std::max(m_targetScroll[1], 0);
int scrollHeight = m_contentView.m_view->nominalHeight() - subRect().size[1]; int scrollHeight = m_contentView.m_view->nominalHeight() - subRect().size[1];
m_targetScroll[1] = std::min(m_targetScroll[1], scrollHeight); m_targetScroll[1] = std::min(m_targetScroll[1], scrollHeight);
} }
if (scroll.isFine) if (scroll.isFine) {
{
m_scroll[0] = m_targetScroll[0]; m_scroll[0] = m_targetScroll[0];
m_scroll[1] = m_targetScroll[1]; m_scroll[1] = m_targetScroll[1];
ret = true; ret = true;
} }
return ret; return ret;
} } else {
else
{
m_scroll[0] = 0; m_scroll[0] = 0;
m_scroll[1] = 0; m_scroll[1] = 0;
m_targetScroll[0] = 0; m_targetScroll[0] = 0;
@ -89,79 +74,63 @@ bool ScrollView::_scroll(const boo::SScrollDelta& scroll)
return false; return false;
} }
int ScrollView::scrollAreaWidth() const int ScrollView::scrollAreaWidth() const {
{
int ret = subRect().size[0]; int ret = subRect().size[0];
if (m_style == Style::SideButtons && m_drawSideButtons) if (m_style == Style::SideButtons && m_drawSideButtons) {
{
ret -= m_sideButtons[0].m_view->nominalWidth(); ret -= m_sideButtons[0].m_view->nominalWidth();
ret -= m_sideButtons[1].m_view->nominalWidth(); ret -= m_sideButtons[1].m_view->nominalWidth();
} }
return std::max(0, ret); return std::max(0, ret);
} }
void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (m_style == Style::SideButtons && m_drawSideButtons) {
if (m_style == Style::SideButtons && m_drawSideButtons) if (m_sideButtons[0].mouseDown(coord, button, mod) || m_sideButtons[1].mouseDown(coord, button, mod))
{
if (m_sideButtons[0].mouseDown(coord, button, mod) ||
m_sideButtons[1].mouseDown(coord, button, mod))
return; return;
} }
m_contentView.mouseDown(coord, button, mod); m_contentView.mouseDown(coord, button, mod);
} }
void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (m_style == Style::SideButtons) {
if (m_style == Style::SideButtons)
{
m_sideButtons[0].mouseUp(coord, button, mod); m_sideButtons[0].mouseUp(coord, button, mod);
m_sideButtons[1].mouseUp(coord, button, mod); m_sideButtons[1].mouseUp(coord, button, mod);
} }
m_contentView.mouseUp(coord, button, mod); m_contentView.mouseUp(coord, button, mod);
} }
void ScrollView::mouseMove(const boo::SWindowCoord& coord) void ScrollView::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_style == Style::SideButtons && m_drawSideButtons) {
if (m_style == Style::SideButtons && m_drawSideButtons)
{
m_sideButtons[0].mouseMove(coord); m_sideButtons[0].mouseMove(coord);
m_sideButtons[1].mouseMove(coord); m_sideButtons[1].mouseMove(coord);
} }
m_contentView.mouseMove(coord); m_contentView.mouseMove(coord);
} }
void ScrollView::mouseEnter(const boo::SWindowCoord& coord) void ScrollView::mouseEnter(const boo::SWindowCoord& coord) {
{ if (m_style == Style::SideButtons && m_drawSideButtons) {
if (m_style == Style::SideButtons && m_drawSideButtons)
{
m_sideButtons[0].mouseEnter(coord); m_sideButtons[0].mouseEnter(coord);
m_sideButtons[1].mouseEnter(coord); m_sideButtons[1].mouseEnter(coord);
} }
m_contentView.mouseEnter(coord); m_contentView.mouseEnter(coord);
} }
void ScrollView::mouseLeave(const boo::SWindowCoord& coord) void ScrollView::mouseLeave(const boo::SWindowCoord& coord) {
{ if (m_style == Style::SideButtons) {
if (m_style == Style::SideButtons)
{
m_sideButtons[0].mouseLeave(coord); m_sideButtons[0].mouseLeave(coord);
m_sideButtons[1].mouseLeave(coord); m_sideButtons[1].mouseLeave(coord);
} }
m_contentView.mouseLeave(coord); m_contentView.mouseLeave(coord);
} }
void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
{ if (!scroll.isAccelerated) {
if (!scroll.isAccelerated)
{
boo::SScrollDelta newScroll = scroll; boo::SScrollDelta newScroll = scroll;
m_consecutiveScroll[m_consecutiveIdx][0] += scroll.delta[0]; m_consecutiveScroll[m_consecutiveIdx][0] += scroll.delta[0];
m_consecutiveScroll[m_consecutiveIdx][1] += scroll.delta[1]; m_consecutiveScroll[m_consecutiveIdx][1] += scroll.delta[1];
newScroll.delta[0] = 0; newScroll.delta[0] = 0;
newScroll.delta[1] = 0; newScroll.delta[1] = 0;
for (size_t i=0 ; i<16 ; ++i) for (size_t i = 0; i < 16; ++i) {
{
newScroll.delta[0] += m_consecutiveScroll[i][0]; newScroll.delta[0] += m_consecutiveScroll[i][0];
newScroll.delta[1] += m_consecutiveScroll[i][1]; newScroll.delta[1] += m_consecutiveScroll[i][1];
} }
@ -173,11 +142,9 @@ void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta&
updateSize(); updateSize();
} }
void ScrollView::setMultiplyColor(const zeus::CColor& color) void ScrollView::setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
if (m_style == Style::SideButtons) if (m_style == Style::SideButtons) {
{
m_sideButtons[0].m_view->setMultiplyColor(color); m_sideButtons[0].m_view->setMultiplyColor(color);
m_sideButtons[1].m_view->setMultiplyColor(color); m_sideButtons[1].m_view->setMultiplyColor(color);
} }
@ -185,14 +152,12 @@ void ScrollView::setMultiplyColor(const zeus::CColor& color)
m_contentView.m_view->setMultiplyColor(color); m_contentView.m_view->setMultiplyColor(color);
} }
void ScrollView::think() void ScrollView::think() {
{
m_consecutiveIdx = (m_consecutiveIdx + 1) % 16; m_consecutiveIdx = (m_consecutiveIdx + 1) % 16;
m_consecutiveScroll[m_consecutiveIdx][0] = 0.0; m_consecutiveScroll[m_consecutiveIdx][0] = 0.0;
m_consecutiveScroll[m_consecutiveIdx][1] = 0.0; m_consecutiveScroll[m_consecutiveIdx][1] = 0.0;
if (m_sideButtonState != SideButtonState::None) if (m_sideButtonState != SideButtonState::None) {
{
if (m_sideButtonState == SideButtonState::ScrollLeft) if (m_sideButtonState == SideButtonState::ScrollLeft)
m_targetScroll[0] -= 3; m_targetScroll[0] -= 3;
else if (m_sideButtonState == SideButtonState::ScrollRight) else if (m_sideButtonState == SideButtonState::ScrollRight)
@ -206,25 +171,19 @@ void ScrollView::think()
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int xSpeed = std::max(1, std::min(abs(m_targetScroll[0] - m_scroll[0]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED))); int xSpeed = std::max(1, std::min(abs(m_targetScroll[0] - m_scroll[0]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED)));
if (m_scroll[0] < m_targetScroll[0]) if (m_scroll[0] < m_targetScroll[0]) {
{
m_scroll[0] += xSpeed; m_scroll[0] += xSpeed;
update = true; update = true;
} } else if (m_scroll[0] > m_targetScroll[0]) {
else if (m_scroll[0] > m_targetScroll[0])
{
m_scroll[0] -= xSpeed; m_scroll[0] -= xSpeed;
update = true; update = true;
} }
int ySpeed = std::max(1, std::min(abs(m_targetScroll[1] - m_scroll[1]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED))); int ySpeed = std::max(1, std::min(abs(m_targetScroll[1] - m_scroll[1]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED)));
if (m_scroll[1] < m_targetScroll[1]) if (m_scroll[1] < m_targetScroll[1]) {
{
m_scroll[1] += ySpeed; m_scroll[1] += ySpeed;
update = true; update = true;
} } else if (m_scroll[1] > m_targetScroll[1]) {
else if (m_scroll[1] > m_targetScroll[1])
{
m_scroll[1] -= ySpeed; m_scroll[1] -= ySpeed;
update = true; update = true;
} }
@ -233,20 +192,17 @@ void ScrollView::think()
updateSize(); updateSize();
} }
void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
_scroll({}); _scroll({});
if (m_contentView.m_view) if (m_contentView.m_view) {
{
boo::SWindowRect cRect = sub; boo::SWindowRect cRect = sub;
cRect.location[0] += m_scroll[0]; cRect.location[0] += m_scroll[0];
cRect.location[1] += sub.size[1] - m_contentView.m_view->nominalHeight() + m_scroll[1]; cRect.location[1] += sub.size[1] - m_contentView.m_view->nominalHeight() + m_scroll[1];
cRect.size[0] = m_contentView.m_view->nominalWidth(); cRect.size[0] = m_contentView.m_view->nominalWidth();
cRect.size[1] = m_contentView.m_view->nominalHeight(); cRect.size[1] = m_contentView.m_view->nominalHeight();
m_contentView.m_scissorRect = sub; m_contentView.m_scissorRect = sub;
if (m_style == Style::SideButtons && m_drawSideButtons) if (m_style == Style::SideButtons && m_drawSideButtons) {
{
int width0 = m_sideButtons[0].m_view->nominalWidth() + 2; int width0 = m_sideButtons[0].m_view->nominalWidth() + 2;
int width1 = m_sideButtons[1].m_view->nominalWidth(); int width1 = m_sideButtons[1].m_view->nominalWidth();
cRect.location[0] += width0; cRect.location[0] += width0;
@ -257,13 +213,10 @@ void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& s
} }
m_contentView.m_view->resized(root, cRect, m_contentView.m_scissorRect); m_contentView.m_view->resized(root, cRect, m_contentView.m_scissorRect);
if (m_style == Style::ThinIndicator) {
if (m_style == Style::ThinIndicator)
{
float ratio = sub.size[1] / float(cRect.size[1]); float ratio = sub.size[1] / float(cRect.size[1]);
m_drawInd = ratio < 1.f; m_drawInd = ratio < 1.f;
if (m_drawInd) if (m_drawInd) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int barHeight = sub.size[1] * ratio; int barHeight = sub.size[1] * ratio;
int scrollHeight = sub.size[1] - barHeight; int scrollHeight = sub.size[1] - barHeight;
@ -279,9 +232,7 @@ void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& s
m_verts[i].m_color = color; m_verts[i].m_color = color;
m_vertsBinding.load<decltype(m_verts)>(m_verts); m_vertsBinding.load<decltype(m_verts)>(m_verts);
} }
} } else if (m_style == Style::SideButtons && m_drawSideButtons) {
else if (m_style == Style::SideButtons && m_drawSideButtons)
{
boo::SWindowRect bRect = sub; boo::SWindowRect bRect = sub;
bRect.size[0] = m_sideButtons[0].m_view->nominalWidth(); bRect.size[0] = m_sideButtons[0].m_view->nominalWidth();
bRect.size[1] = m_sideButtons[0].m_view->nominalHeight(); bRect.size[1] = m_sideButtons[0].m_view->nominalHeight();
@ -295,23 +246,18 @@ void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& s
} }
} }
void ScrollView::draw(boo::IGraphicsCommandQueue* gfxQ) void ScrollView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ if (m_contentView.m_view) {
if (m_contentView.m_view)
{
m_contentView.m_view->draw(gfxQ); m_contentView.m_view->draw(gfxQ);
if (m_style == Style::ThinIndicator && m_drawInd) if (m_style == Style::ThinIndicator && m_drawInd) {
{
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
} } else if (m_style == Style::SideButtons && m_drawSideButtons) {
else if (m_style == Style::SideButtons && m_drawSideButtons)
{
m_sideButtons[0].m_view->draw(gfxQ); m_sideButtons[0].m_view->draw(gfxQ);
m_sideButtons[1].m_view->draw(gfxQ); m_sideButtons[1].m_view->draw(gfxQ);
} }
} }
} }
} } // namespace specter

View File

@ -3,8 +3,7 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Space"); static logvisor::Module Log("specter::Space");
#define TRIANGLE_DIM 12 #define TRIANGLE_DIM 12
@ -18,12 +17,10 @@ static logvisor::Module Log("specter::Space");
static const zeus::CColor TriColor = {0.75, 0.75, 0.75, 1.0}; static const zeus::CColor TriColor = {0.75, 0.75, 0.75, 1.0};
Space::Space(ViewResources& res, View& parentView, ISpaceController& controller, Space::Space(ViewResources& res, View& parentView, ISpaceController& controller, Toolbar::Position tbPos,
Toolbar::Position tbPos, unsigned tbUnits) unsigned tbUnits)
: View(res, parentView), m_controller(controller), m_tbPos(tbPos) : View(res, parentView), m_controller(controller), m_tbPos(tbPos) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
return true; return true;
}); });
@ -35,10 +32,8 @@ Space::Space(ViewResources& res, View& parentView, ISpaceController& controller,
} }
Space::CornerView::CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor) Space::CornerView::CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor)
: View(res, space), m_space(space) : View(res, space), m_space(space) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf); m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf);
return true; return true;
@ -116,26 +111,22 @@ Space::CornerView::CornerView(ViewResources& res, Space& space, const zeus::CCol
m_vertexBinding.load<decltype(verts)>(verts); m_vertexBinding.load<decltype(verts)>(verts);
} }
View* Space::setContentView(View* view) View* Space::setContentView(View* view) {
{
View* ret = m_contentView.m_view; View* ret = m_contentView.m_view;
m_contentView.m_view = view; m_contentView.m_view = view;
updateSize(); updateSize();
return ret; return ret;
} }
void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
if (m_cornerView.mouseDown(coord, button, mod)) if (m_cornerView.mouseDown(coord, button, mod))
return; return;
m_contentView.mouseDown(coord, button, mod); m_contentView.mouseDown(coord, button, mod);
m_toolbar.mouseDown(coord, button, mod); m_toolbar.mouseDown(coord, button, mod);
} }
void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (button == boo::EMouseButton::Primary) {
if (button == boo::EMouseButton::Primary)
{
m_space.m_cornerDrag = true; m_space.m_cornerDrag = true;
m_space.m_cornerDragPoint[0] = coord.pixel[0]; m_space.m_cornerDragPoint[0] = coord.pixel[0];
m_space.m_cornerDragPoint[1] = coord.pixel[1]; m_space.m_cornerDragPoint[1] = coord.pixel[1];
@ -143,134 +134,94 @@ void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseBut
} }
} }
void Space::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_cornerView.mouseUp(coord, button, mod); m_cornerView.mouseUp(coord, button, mod);
m_contentView.mouseUp(coord, button, mod); m_contentView.mouseUp(coord, button, mod);
m_toolbar.mouseUp(coord, button, mod); m_toolbar.mouseUp(coord, button, mod);
} }
void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (button == boo::EMouseButton::Primary) {
if (button == boo::EMouseButton::Primary)
{
m_space.m_cornerDrag = false; m_space.m_cornerDrag = false;
rootView().unsetActiveDragView(&m_space); rootView().unsetActiveDragView(&m_space);
} }
} }
void Space::mouseMove(const boo::SWindowCoord& coord) void Space::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_cornerDrag) {
if (m_cornerDrag)
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf) if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf) {
{ if (m_cornerView.m_view->m_flip) {
if (m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1, coord); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1, coord);
} } else {
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 0); SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 0);
if (sv) if (sv) {
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord); rootView().beginInteractiveJoin(sv, coord);
} }
} }
} } else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf) {
else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf) if (m_cornerView.m_view->m_flip) {
{
if (m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord);
} } else {
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 0); SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 0);
if (sv) if (sv) {
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord); rootView().beginInteractiveJoin(sv, coord);
} }
} }
} } else if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf) {
else if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf) if (!m_cornerView.m_view->m_flip) {
{
if (!m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0, coord); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0, coord);
} } else {
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 1); SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 1);
if (sv) if (sv) {
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord); rootView().beginInteractiveJoin(sv, coord);
} }
} }
} } else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf) {
else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf) if (!m_cornerView.m_view->m_flip) {
{
if (!m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord);
} } else {
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 1); SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 1);
if (sv) if (sv) {
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None); rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord); rootView().beginInteractiveJoin(sv, coord);
} }
} }
} }
} } else {
else
{
m_cornerView.mouseMove(coord); m_cornerView.mouseMove(coord);
m_contentView.mouseMove(coord); m_contentView.mouseMove(coord);
m_toolbar.mouseMove(coord); m_toolbar.mouseMove(coord);
} }
} }
void Space::mouseEnter(const boo::SWindowCoord& coord) void Space::mouseEnter(const boo::SWindowCoord& coord) {
{
m_cornerView.mouseEnter(coord); m_cornerView.mouseEnter(coord);
m_contentView.mouseEnter(coord); m_contentView.mouseEnter(coord);
m_toolbar.mouseEnter(coord); m_toolbar.mouseEnter(coord);
} }
void Space::CornerView::mouseEnter(const boo::SWindowCoord& coord) void Space::CornerView::mouseEnter(const boo::SWindowCoord& coord) { rootView().setSpaceCornerHover(true); }
{
rootView().setSpaceCornerHover(true);
}
void Space::mouseLeave(const boo::SWindowCoord& coord) void Space::mouseLeave(const boo::SWindowCoord& coord) {
{
m_cornerView.mouseLeave(coord); m_cornerView.mouseLeave(coord);
m_contentView.mouseLeave(coord); m_contentView.mouseLeave(coord);
m_toolbar.mouseLeave(coord); m_toolbar.mouseLeave(coord);
} }
void Space::CornerView::mouseLeave(const boo::SWindowCoord& coord) void Space::CornerView::mouseLeave(const boo::SWindowCoord& coord) { rootView().setSpaceCornerHover(false); }
{
rootView().setSpaceCornerHover(false);
}
SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side) SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side) {
{
SplitView* ret = parentView().castToSplitView(); SplitView* ret = parentView().castToSplitView();
View* test = this; View* test = this;
while (ret) while (ret) {
{
if (ret->axis() != axis) if (ret->axis() != axis)
return nullptr; return nullptr;
if (ret->m_views[side ^ 1].m_view == test) if (ret->m_views[side ^ 1].m_view == test)
@ -282,39 +233,32 @@ SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side)
return nullptr; return nullptr;
} }
void Space::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Space::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
if (m_cornerView.m_view) if (m_cornerView.m_view) {
{
boo::SWindowRect cornerRect = sub; boo::SWindowRect cornerRect = sub;
int triDim = TRIANGLE_DIM * pf; int triDim = TRIANGLE_DIM * pf;
cornerRect.size[0] = cornerRect.size[1] = triDim; cornerRect.size[0] = cornerRect.size[1] = triDim;
if (cornerRect.location[0] < triDim && cornerRect.location[1] < triDim) if (cornerRect.location[0] < triDim && cornerRect.location[1] < triDim) {
{
cornerRect.location[0] += sub.size[0] - triDim; cornerRect.location[0] += sub.size[0] - triDim;
cornerRect.location[1] += sub.size[1] - triDim; cornerRect.location[1] += sub.size[1] - triDim;
m_cornerView.m_view->resized(root, cornerRect, true); m_cornerView.m_view->resized(root, cornerRect, true);
} } else
else
m_cornerView.m_view->resized(root, cornerRect, false); m_cornerView.m_view->resized(root, cornerRect, false);
} }
boo::SWindowRect tbRect = sub; boo::SWindowRect tbRect = sub;
if (m_toolbar.m_view) if (m_toolbar.m_view) {
{
tbRect.size[1] = m_toolbar.m_view->nominalHeight(); tbRect.size[1] = m_toolbar.m_view->nominalHeight();
if (m_tbPos == Toolbar::Position::Top) if (m_tbPos == Toolbar::Position::Top)
tbRect.location[1] += sub.size[1] - tbRect.size[1]; tbRect.location[1] += sub.size[1] - tbRect.size[1];
m_toolbar.m_view->resized(root, tbRect); m_toolbar.m_view->resized(root, tbRect);
} } else
else
tbRect.size[1] = 0; tbRect.size[1] = 0;
if (m_contentView.m_view) if (m_contentView.m_view) {
{
boo::SWindowRect contentRect = sub; boo::SWindowRect contentRect = sub;
if (m_tbPos == Toolbar::Position::Bottom) if (m_tbPos == Toolbar::Position::Bottom)
contentRect.location[1] += tbRect.size[1]; contentRect.location[1] += tbRect.size[1];
@ -324,23 +268,19 @@ void Space::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
} }
} }
void Space::CornerView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip) void Space::CornerView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip) {
{
m_flip = flip; m_flip = flip;
if (flip) if (flip) {
{
m_viewVertBlock.m_mv[0][0] = -2.0f / root.size[0]; m_viewVertBlock.m_mv[0][0] = -2.0f / root.size[0];
m_viewVertBlock.m_mv[1][1] = -2.0f / root.size[1]; m_viewVertBlock.m_mv[1][1] = -2.0f / root.size[1];
m_viewVertBlock.m_mv[3][0] = (sub.location[0] + sub.size[0]) * -m_viewVertBlock.m_mv[0][0] - 1.0f; m_viewVertBlock.m_mv[3][0] = (sub.location[0] + sub.size[0]) * -m_viewVertBlock.m_mv[0][0] - 1.0f;
m_viewVertBlock.m_mv[3][1] = (sub.location[1] + sub.size[1]) * -m_viewVertBlock.m_mv[1][1] - 1.0f; m_viewVertBlock.m_mv[3][1] = (sub.location[1] + sub.size[1]) * -m_viewVertBlock.m_mv[1][1] - 1.0f;
View::resized(m_viewVertBlock, sub); View::resized(m_viewVertBlock, sub);
} } else
else
View::resized(root, sub); View::resized(root, sub);
} }
void Space::draw(boo::IGraphicsCommandQueue* gfxQ) void Space::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
if (m_contentView.m_view) if (m_contentView.m_view)
m_contentView.m_view->draw(gfxQ); m_contentView.m_view->draw(gfxQ);
@ -350,11 +290,9 @@ void Space::draw(boo::IGraphicsCommandQueue* gfxQ)
m_cornerView.m_view->draw(gfxQ); m_cornerView.m_view->draw(gfxQ);
} }
void Space::CornerView::draw(boo::IGraphicsCommandQueue* gfxQ) void Space::CornerView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
gfxQ->setShaderDataBinding(m_vertexBinding); gfxQ->setShaderDataBinding(m_vertexBinding);
gfxQ->draw(0, 34); gfxQ->draw(0, 34);
} }
} } // namespace specter

View File

@ -4,29 +4,24 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/Space.hpp" #include "specter/Space.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::SplitView"); static logvisor::Module Log("specter::SplitView");
static const zeus::RGBA32 Tex[3] = static const zeus::RGBA32 Tex[3] = {{{0, 0, 0, 64}}, {{0, 0, 0, 255}}, {{255, 255, 255, 64}}};
{
{{0,0,0,64}},
{{0,0,0,255}},
{{255,255,255,64}}
};
void SplitView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void SplitView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{
m_shadingTex = ctx.newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 12); m_shadingTex = ctx.newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 12);
} }
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
Axis axis, float split, int clearanceA, int clearanceB) int clearanceA, int clearanceB)
: View(res, parentView), m_controller(controller), m_axis(axis), m_slide(split), : View(res, parentView)
m_clearanceA(clearanceA), m_clearanceB(clearanceB) , m_controller(controller)
{ , m_axis(axis)
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool , m_slide(split)
{ , m_clearanceA(clearanceA)
, m_clearanceB(clearanceB) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res); buildResources(ctx, res);
m_splitBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_splitBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_splitVertsBinding.init(ctx, res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex.get()); m_splitVertsBinding.init(ctx, res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex.get());
@ -34,8 +29,7 @@ SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController
}); });
} }
View* SplitView::setContentView(int slot, View* view) View* SplitView::setContentView(int slot, View* view) {
{
if (slot < 0 || slot > 1) if (slot < 0 || slot > 1)
Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView"); Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView");
View* ret = m_views[slot].m_view; View* ret = m_views[slot].m_view;
@ -46,23 +40,17 @@ View* SplitView::setContentView(int slot, View* view)
return ret; return ret;
} }
void SplitView::_setSplit(float slide) void SplitView::_setSplit(float slide) {
{
m_slide = std::min(std::max(slide, 0.0f), 1.0f); m_slide = std::min(std::max(slide, 0.0f), 1.0f);
const boo::SWindowRect& rect = subRect(); const boo::SWindowRect& rect = subRect();
if (rect.size[0] && rect.size[1] && if (rect.size[0] && rect.size[1] && (m_clearanceA >= 0 || m_clearanceB >= 0)) {
(m_clearanceA >= 0 || m_clearanceB >= 0)) if (m_axis == Axis::Horizontal) {
{
if (m_axis == Axis::Horizontal)
{
int slidePx = rect.size[1] * m_slide; int slidePx = rect.size[1] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA) if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[1]); m_slide = m_clearanceA / float(rect.size[1]);
if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB) if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB)
m_slide = 1.0 - m_clearanceB / float(rect.size[1]); m_slide = 1.0 - m_clearanceB / float(rect.size[1]);
} } else if (m_axis == Axis::Vertical) {
else if (m_axis == Axis::Vertical)
{
int slidePx = rect.size[0] * m_slide; int slidePx = rect.size[0] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA) if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[0]); m_slide = m_clearanceA / float(rect.size[0]);
@ -75,28 +63,22 @@ void SplitView::_setSplit(float slide)
m_controller->updateSplit(m_slide); m_controller->updateSplit(m_slide);
} }
void SplitView::setSplit(float slide) void SplitView::setSplit(float slide) {
{
_setSplit(slide); _setSplit(slide);
updateSize(); updateSize();
} }
void SplitView::setAxis(Axis axis) void SplitView::setAxis(Axis axis) {
{
m_axis = axis; m_axis = axis;
setSplit(m_slide); setSplit(m_slide);
} }
bool SplitView::testSplitHover(const boo::SWindowCoord& coord) bool SplitView::testSplitHover(const boo::SWindowCoord& coord) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4) if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
return true; return true;
} } else if (m_axis == Axis::Vertical) {
else if (m_axis == Axis::Vertical)
{
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4) if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
return true; return true;
@ -104,25 +86,20 @@ bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
return false; return false;
} }
bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, SplitView*& splitOut, int& slotOut,
SplitView*& splitOut, int& slotOut, boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot) {
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot)
{
if (!subRect().coordInRect(coord)) if (!subRect().coordInRect(coord))
return false; return false;
int origDummy; int origDummy;
ArrowDir dirDummy; ArrowDir dirDummy;
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal) {
{
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1) if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1) {
{
origSlotOut = 0; origSlotOut = 0;
dirOut = ArrowDir::Up; dirOut = ArrowDir::Up;
if (m_views[1].m_view) if (m_views[1].m_view) {
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0); return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
@ -133,13 +110,10 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
rectOut.location[1] += slidePx; rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx; rectOut.size[1] -= slidePx;
return true; return true;
} } else {
else
{
origSlotOut = 1; origSlotOut = 1;
dirOut = ArrowDir::Down; dirOut = ArrowDir::Down;
if (m_views[0].m_view) if (m_views[0].m_view) {
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1); return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
@ -150,16 +124,12 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
rectOut.size[1] = slidePx; rectOut.size[1] = slidePx;
return true; return true;
} }
} } else {
else
{
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1) if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1) {
{
origSlotOut = 0; origSlotOut = 0;
dirOut = ArrowDir::Right; dirOut = ArrowDir::Right;
if (m_views[1].m_view) if (m_views[1].m_view) {
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0); return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
@ -170,13 +140,10 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
rectOut.location[0] += slidePx; rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx; rectOut.size[0] -= slidePx;
return true; return true;
} } else {
else
{
origSlotOut = 1; origSlotOut = 1;
dirOut = ArrowDir::Left; dirOut = ArrowDir::Left;
if (m_views[0].m_view) if (m_views[0].m_view) {
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1); return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
@ -190,15 +157,11 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
} }
} }
void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if (slot == 1) if (slot == 1) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(0, rectOut, dirOut); return chSplit->getJoinArrowHover(0, rectOut, dirOut);
@ -207,11 +170,8 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.location[1] += slidePx; rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx; rectOut.size[1] -= slidePx;
dirOut = ArrowDir::Up; dirOut = ArrowDir::Up;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(1, rectOut, dirOut); return chSplit->getJoinArrowHover(1, rectOut, dirOut);
@ -220,14 +180,10 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.size[1] = slidePx; rectOut.size[1] = slidePx;
dirOut = ArrowDir::Down; dirOut = ArrowDir::Down;
} }
} } else {
else
{
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if (slot == 1) if (slot == 1) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(0, rectOut, dirOut); return chSplit->getJoinArrowHover(0, rectOut, dirOut);
@ -236,11 +192,8 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.location[0] += slidePx; rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx; rectOut.size[0] -= slidePx;
dirOut = ArrowDir::Right; dirOut = ArrowDir::Right;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(1, rectOut, dirOut); return chSplit->getJoinArrowHover(1, rectOut, dirOut);
@ -252,19 +205,15 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
} }
} }
bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut,
boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut) float& splitOut, Axis& axisOut) {
{
if (!subRect().coordInRect(coord)) if (!subRect().coordInRect(coord))
return false; return false;
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal) {
{
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
@ -276,11 +225,8 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]); splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
axisOut = Axis::Vertical; axisOut = Axis::Vertical;
return true; return true;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
@ -292,14 +238,10 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
axisOut = Axis::Vertical; axisOut = Axis::Vertical;
return true; return true;
} }
} } else {
else
{
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
@ -311,11 +253,8 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]); splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
axisOut = Axis::Horizontal; axisOut = Axis::Horizontal;
return true; return true;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
@ -330,15 +269,11 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
} }
} }
void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if (slot == 1) if (slot == 1) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(0, rectOut, axisOut); return chSplit->getSplitLineHover(0, rectOut, axisOut);
@ -347,11 +282,8 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
rectOut.location[1] += slidePx; rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx; rectOut.size[1] -= slidePx;
axisOut = Axis::Vertical; axisOut = Axis::Vertical;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal) if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(1, rectOut, axisOut); return chSplit->getSplitLineHover(1, rectOut, axisOut);
@ -360,14 +292,10 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
rectOut.size[1] = slidePx; rectOut.size[1] = slidePx;
axisOut = Axis::Vertical; axisOut = Axis::Vertical;
} }
} } else {
else
{
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if (slot == 1) if (slot == 1) {
{ if (m_views[1].m_view) {
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView(); SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(0, rectOut, axisOut); return chSplit->getSplitLineHover(0, rectOut, axisOut);
@ -376,11 +304,8 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
rectOut.location[0] += slidePx; rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx; rectOut.size[0] -= slidePx;
axisOut = Axis::Horizontal; axisOut = Axis::Horizontal;
} } else {
else if (m_views[0].m_view) {
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView(); SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical) if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(1, rectOut, axisOut); return chSplit->getSplitLineHover(1, rectOut, axisOut);
@ -392,8 +317,7 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
} }
} }
void SplitView::startDragSplit(const boo::SWindowCoord& coord) void SplitView::startDragSplit(const boo::SWindowCoord& coord) {
{
m_dragging = true; m_dragging = true;
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1])); setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
@ -401,55 +325,44 @@ void SplitView::startDragSplit(const boo::SWindowCoord& coord)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0])); setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
void SplitView::endDragSplit() void SplitView::endDragSplit() { m_dragging = false; }
{
m_dragging = false;
}
void SplitView::moveDragSplit(const boo::SWindowCoord& coord) void SplitView::moveDragSplit(const boo::SWindowCoord& coord) {
{
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1])); setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical) else if (m_axis == Axis::Vertical)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0])); setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_views[0].mouseDown(coord, button, mod); m_views[0].mouseDown(coord, button, mod);
m_views[1].mouseDown(coord, button, mod); m_views[1].mouseDown(coord, button, mod);
} }
void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_views[0].mouseUp(coord, button, mod); m_views[0].mouseUp(coord, button, mod);
m_views[1].mouseUp(coord, button, mod); m_views[1].mouseUp(coord, button, mod);
} }
void SplitView::mouseMove(const boo::SWindowCoord& coord) void SplitView::mouseMove(const boo::SWindowCoord& coord) {
{
m_views[0].mouseMove(coord); m_views[0].mouseMove(coord);
m_views[1].mouseMove(coord); m_views[1].mouseMove(coord);
} }
void SplitView::mouseEnter(const boo::SWindowCoord& coord) void SplitView::mouseEnter(const boo::SWindowCoord& coord) {
{
m_views[0].mouseEnter(coord); m_views[0].mouseEnter(coord);
m_views[1].mouseEnter(coord); m_views[1].mouseEnter(coord);
} }
void SplitView::mouseLeave(const boo::SWindowCoord& coord) void SplitView::mouseLeave(const boo::SWindowCoord& coord) {
{
m_views[0].mouseLeave(coord); m_views[0].mouseLeave(coord);
m_views[1].mouseLeave(coord); m_views[1].mouseLeave(coord);
} }
void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
_setSplit(m_slide); _setSplit(m_slide);
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal) {
{
boo::SWindowRect ssub = sub; boo::SWindowRect ssub = sub;
ssub.size[1] *= m_slide; ssub.size[1] *= m_slide;
if (m_views[0].m_view) if (m_views[0].m_view)
@ -461,9 +374,7 @@ void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& su
ssub.location[1] -= 1; ssub.location[1] -= 1;
m_splitBlock.setViewRect(root, ssub); m_splitBlock.setViewRect(root, ssub);
setHorizontalVerts(ssub.size[0]); setHorizontalVerts(ssub.size[0]);
} } else if (m_axis == Axis::Vertical) {
else if (m_axis == Axis::Vertical)
{
boo::SWindowRect ssub = sub; boo::SWindowRect ssub = sub;
ssub.size[0] *= m_slide; ssub.size[0] *= m_slide;
if (m_views[0].m_view) if (m_views[0].m_view)
@ -480,8 +391,7 @@ void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& su
m_splitVertsBinding.load<decltype(m_splitVerts)>(m_splitVerts); m_splitVertsBinding.load<decltype(m_splitVerts)>(m_splitVerts);
} }
void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ) void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
if (m_views[0].m_view) if (m_views[0].m_view)
m_views[0].m_view->draw(gfxQ); m_views[0].m_view->draw(gfxQ);
@ -491,5 +401,4 @@ void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
} }
} } // namespace specter

View File

@ -3,24 +3,25 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/ScrollView.hpp" #include "specter/ScrollView.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Table"); static logvisor::Module Log("specter::Table");
#define ROW_HEIGHT 18 #define ROW_HEIGHT 18
#define CELL_MARGIN 1 #define CELL_MARGIN 1
Table::Table(ViewResources& res, View& parentView, ITableDataBinding* data, Table::Table(ViewResources& res, View& parentView, ITableDataBinding* data, ITableStateBinding* state,
ITableStateBinding* state, size_t maxColumns) size_t maxColumns)
: View(res, parentView), m_data(data), m_state(state), m_maxColumns(maxColumns), : View(res, parentView)
m_hVerts(new SolidShaderVert[maxColumns * 6]), m_rowsView(*this, res) , m_data(data)
{ , m_state(state)
, m_maxColumns(maxColumns)
, m_hVerts(new SolidShaderVert[maxColumns * 6])
, m_rowsView(*this, res) {
if (!maxColumns) if (!maxColumns)
Log.report(logvisor::Fatal, "0-column tables not supported"); Log.report(logvisor::Fatal, "0-column tables not supported");
m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator)); m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator));
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, maxColumns * 6, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, maxColumns * 6, m_viewVertBlockBuf);
return true; return true;
@ -31,10 +32,8 @@ Table::Table(ViewResources& res, View& parentView, ITableDataBinding* data,
} }
Table::RowsView::RowsView(Table& t, ViewResources& res) Table::RowsView::RowsView(Table& t, ViewResources& res)
: View(res, t), m_t(t), m_verts(new SolidShaderVert[SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6]) : View(res, t), m_t(t), m_verts(new SolidShaderVert[SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6]) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6, m_viewVertBlockBuf);
return true; return true;
@ -44,8 +43,8 @@ Table::RowsView::RowsView(Table& t, ViewResources& res)
Table::CellView::CellView(Table& t, ViewResources& res) Table::CellView::CellView(Table& t, ViewResources& res)
: View(res, t), m_t(t), m_text(new TextView(res, *this, res.m_mainFont)), m_c(-1), m_r(-1) {} : View(res, t), m_t(t), m_text(new TextView(res, *this, res.m_mainFont)), m_c(-1), m_r(-1) {}
void Table::_setHeaderVerts(const boo::SWindowRect& sub) void Table::_setHeaderVerts(const boo::SWindowRect& sub) {
{; ;
if (m_headerViews.empty()) if (m_headerViews.empty())
return; return;
SolidShaderVert* v = m_hVerts.get(); SolidShaderVert* v = m_hVerts.get();
@ -70,33 +69,25 @@ void Table::_setHeaderVerts(const boo::SWindowRect& sub)
m_hCellRects = getCellRects(headRowRect); m_hCellRects = getCellRects(headRowRect);
auto cellRectsIt = m_hCellRects.begin(); auto cellRectsIt = m_hCellRects.begin();
for (c=0 ; c<std::min(m_maxColumns, m_columns) ; ++c) for (c = 0; c < std::min(m_maxColumns, m_columns); ++c) {
{
const ViewChild<std::unique_ptr<CellView>>& hv = *it; const ViewChild<std::unique_ptr<CellView>>& hv = *it;
const zeus::CColor* c1 = &theme.button1Inactive(); const zeus::CColor* c1 = &theme.button1Inactive();
const zeus::CColor* c2 = &theme.button2Inactive(); const zeus::CColor* c2 = &theme.button2Inactive();
if (hv.m_mouseDown && hv.m_mouseIn) if (hv.m_mouseDown && hv.m_mouseIn) {
{
c1 = &theme.button1Press(); c1 = &theme.button1Press();
c2 = &theme.button2Press(); c2 = &theme.button2Press();
} } else if (hv.m_mouseIn) {
else if (hv.m_mouseIn)
{
c1 = &theme.button1Hover(); c1 = &theme.button1Hover();
c2 = &theme.button2Hover(); c2 = &theme.button2Hover();
} }
zeus::CColor cm1 = *c1; zeus::CColor cm1 = *c1;
zeus::CColor cm2 = *c2; zeus::CColor cm2 = *c2;
if (sCol == c) if (sCol == c) {
{ if (sDir == SortDirection::Ascending) {
if (sDir == SortDirection::Ascending)
{
cm1 *= zeus::CColor::skGreen; cm1 *= zeus::CColor::skGreen;
cm2 *= zeus::CColor::skGreen; cm2 *= zeus::CColor::skGreen;
} } else if (sDir == SortDirection::Descending) {
else if (sDir == SortDirection::Descending)
{
cm1 *= zeus::CColor::skRed; cm1 *= zeus::CColor::skRed;
cm2 *= zeus::CColor::skRed; cm2 *= zeus::CColor::skRed;
} }
@ -125,8 +116,7 @@ void Table::_setHeaderVerts(const boo::SWindowRect& sub)
m_headerNeedsUpdate = false; m_headerNeedsUpdate = false;
} }
void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWindowRect& scissor) void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWindowRect& scissor) {
{
SolidShaderVert* v = m_verts.get(); SolidShaderVert* v = m_verts.get();
const IThemeData& theme = rootView().themeData(); const IThemeData& theme = rootView().themeData();
@ -139,8 +129,7 @@ void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWind
int rowHeight = ROW_HEIGHT * pf; int rowHeight = ROW_HEIGHT * pf;
int yOff = 0; int yOff = 0;
int idx = 0; int idx = 0;
while (sub.location[1] + yOff < scissor.location[1] + scissor.size[1] || (idx & 1) != 0) while (sub.location[1] + yOff < scissor.location[1] + scissor.size[1] || (idx & 1) != 0) {
{
yOff += spacing; yOff += spacing;
++idx; ++idx;
} }
@ -149,15 +138,13 @@ void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWind
std::vector<boo::SWindowRect> cellRects = m_t.getCellRects(sub); std::vector<boo::SWindowRect> cellRects = m_t.getCellRects(sub);
size_t r, c; size_t r, c;
for (r=0, c=0 ; r<SPECTER_TABLE_MAX_ROWS && for (r = 0, c = 0; r < SPECTER_TABLE_MAX_ROWS && (sub.location[1] + yOff + spacing) >= scissor.location[1]; ++r) {
(sub.location[1] + yOff + spacing) >= scissor.location[1] ; ++r) const zeus::CColor& color = (startIdx + r == m_t.m_selectedRow)
{ ? theme.tableCellBgSelected()
const zeus::CColor& color = (startIdx+r==m_t.m_selectedRow) ? theme.tableCellBgSelected() : : ((r & 1) ? theme.tableCellBg1() : theme.tableCellBg2());
((r&1) ? theme.tableCellBg1() : theme.tableCellBg2());
int xOff = 0; int xOff = 0;
auto cellRectsIt = cellRects.begin(); auto cellRectsIt = cellRects.begin();
for (c=0 ; c<std::min(m_t.m_maxColumns, m_t.m_columns) ; ++c) for (c = 0; c < std::min(m_t.m_maxColumns, m_t.m_columns); ++c) {
{
int div = cellRectsIt->size[0]; int div = cellRectsIt->size[0];
v[0].m_pos.assign(xOff + margin, yOff - margin, 0); v[0].m_pos.assign(xOff + margin, yOff - margin, 0);
v[0].m_color = color; v[0].m_color = color;
@ -181,13 +168,10 @@ void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWind
m_vertsBinding.load(m_verts.get(), 6 * r * c); m_vertsBinding.load(m_verts.get(), 6 * r * c);
} }
void Table::cycleSortColumn(size_t c) void Table::cycleSortColumn(size_t c) {
{
if (c >= m_columns) if (c >= m_columns)
Log.report(logvisor::Fatal, "cycleSortColumn out of bounds (%" PRISize ", %" PRISize ")", Log.report(logvisor::Fatal, "cycleSortColumn out of bounds (%" PRISize ", %" PRISize ")", c, m_columns);
c, m_columns); if (m_state) {
if (m_state)
{
size_t cIdx; size_t cIdx;
SortDirection dir = m_state->getSort(cIdx); SortDirection dir = m_state->getSort(cIdx);
if (dir == SortDirection::None || cIdx != c) if (dir == SortDirection::None || cIdx != c)
@ -199,17 +183,13 @@ void Table::cycleSortColumn(size_t c)
} }
} }
void Table::selectRow(size_t r) void Table::selectRow(size_t r) {
{
if (m_inSelectRow) if (m_inSelectRow)
return; return;
if (r >= m_rows && r != -1) if (r >= m_rows && r != -1)
Log.report(logvisor::Fatal, "selectRow out of bounds (%" PRISize ", %" PRISize ")", Log.report(logvisor::Fatal, "selectRow out of bounds (%" PRISize ", %" PRISize ")", r, m_rows);
r, m_rows); if (r == m_selectedRow) {
if (r == m_selectedRow) if (m_state) {
{
if (m_state)
{
m_inSelectRow = true; m_inSelectRow = true;
m_state->setSelectedRow(r); m_state->setSelectedRow(r);
m_inSelectRow = false; m_inSelectRow = false;
@ -217,24 +197,18 @@ void Table::selectRow(size_t r)
return; return;
} }
if (m_selectedRow != -1 && m_activePool != -1) if (m_selectedRow != -1 && m_activePool != -1) {
{
size_t poolIdx = m_selectedRow / SPECTER_TABLE_MAX_ROWS; size_t poolIdx = m_selectedRow / SPECTER_TABLE_MAX_ROWS;
int pool0 = (poolIdx & 1) != 0; int pool0 = (poolIdx & 1) != 0;
int pool1 = (poolIdx & 1) == 0; int pool1 = (poolIdx & 1) == 0;
if (m_activePool == poolIdx) if (m_activePool == poolIdx) {
{ for (auto& col : m_cellPools) {
for (auto& col : m_cellPools)
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool0].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS); ViewChild<std::unique_ptr<CellView>>& cv = col[pool0].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS);
if (cv.m_view) if (cv.m_view)
cv.m_view->deselect(); cv.m_view->deselect();
} }
} } else if (m_activePool + 1 == poolIdx) {
else if (m_activePool+1 == poolIdx) for (auto& col : m_cellPools) {
{
for (auto& col : m_cellPools)
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool1].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS); ViewChild<std::unique_ptr<CellView>>& cv = col[pool1].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS);
if (cv.m_view) if (cv.m_view)
cv.m_view->deselect(); cv.m_view->deselect();
@ -244,24 +218,18 @@ void Table::selectRow(size_t r)
m_selectedRow = r; m_selectedRow = r;
if (m_selectedRow != -1 && m_activePool != -1) if (m_selectedRow != -1 && m_activePool != -1) {
{
size_t poolIdx = m_selectedRow / SPECTER_TABLE_MAX_ROWS; size_t poolIdx = m_selectedRow / SPECTER_TABLE_MAX_ROWS;
int pool0 = (poolIdx & 1) != 0; int pool0 = (poolIdx & 1) != 0;
int pool1 = (poolIdx & 1) == 0; int pool1 = (poolIdx & 1) == 0;
if (m_activePool == poolIdx) if (m_activePool == poolIdx) {
{ for (auto& col : m_cellPools) {
for (auto& col : m_cellPools)
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool0].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS); ViewChild<std::unique_ptr<CellView>>& cv = col[pool0].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS);
if (cv.m_view) if (cv.m_view)
cv.m_view->select(); cv.m_view->select();
} }
} } else if (m_activePool + 1 == poolIdx) {
else if (m_activePool+1 == poolIdx) for (auto& col : m_cellPools) {
{
for (auto& col : m_cellPools)
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool1].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS); ViewChild<std::unique_ptr<CellView>>& cv = col[pool1].at(m_selectedRow % SPECTER_TABLE_MAX_ROWS);
if (cv.m_view) if (cv.m_view)
cv.m_view->select(); cv.m_view->select();
@ -271,24 +239,21 @@ void Table::selectRow(size_t r)
updateSize(); updateSize();
if (m_state) if (m_state) {
{
m_inSelectRow = true; m_inSelectRow = true;
m_state->setSelectedRow(r); m_state->setSelectedRow(r);
m_inSelectRow = false; m_inSelectRow = false;
} }
} }
void Table::setMultiplyColor(const zeus::CColor& color) void Table::setMultiplyColor(const zeus::CColor& color) {
{
View::setMultiplyColor(color); View::setMultiplyColor(color);
if (m_scroll.m_view) if (m_scroll.m_view)
m_scroll.m_view->setMultiplyColor(color); m_scroll.m_view->setMultiplyColor(color);
for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews)
if (hv.m_view) if (hv.m_view)
hv.m_view->m_text->setMultiplyColor(color); hv.m_view->m_text->setMultiplyColor(color);
for (auto& col : m_cellPools) for (auto& col : m_cellPools) {
{
for (ViewChild<std::unique_ptr<CellView>>& cv : col[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[0])
if (cv.m_view) if (cv.m_view)
cv.m_view->m_text->setMultiplyColor(color); cv.m_view->m_text->setMultiplyColor(color);
@ -298,35 +263,27 @@ void Table::setMultiplyColor(const zeus::CColor& color)
} }
} }
void Table::CellView::select() void Table::CellView::select() {
{
m_selected = true; m_selected = true;
m_text->colorGlyphs(rootView().themeData().fieldText()); m_text->colorGlyphs(rootView().themeData().fieldText());
} }
void Table::CellView::deselect() void Table::CellView::deselect() {
{
m_selected = false; m_selected = false;
m_text->colorGlyphs(rootView().themeData().uiText()); m_text->colorGlyphs(rootView().themeData().uiText());
} }
void Table::mouseDown(const boo::SWindowCoord& coord, void Table::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod) if (m_state && m_state->columnSplitResizeAllowed()) {
{
if (m_state && m_state->columnSplitResizeAllowed())
{
size_t cIdx = 0; size_t cIdx = 0;
for (const boo::SWindowRect& rect : m_hCellRects) for (const boo::SWindowRect& rect : m_hCellRects) {
{ if (cIdx == 0) {
if (cIdx == 0)
{
++cIdx; ++cIdx;
continue; continue;
} }
if (abs(coord.pixel[0] - rect.location[0]) < 4 && if (abs(coord.pixel[0] - rect.location[0]) < 4 &&
unsigned(coord.pixel[1] - subRect().location[1] - unsigned(coord.pixel[1] - subRect().location[1] - subRect().size[1] + rect.size[1]) <
subRect().size[1] + rect.size[1]) < unsigned(rect.size[1])) unsigned(rect.size[1])) {
{
m_hDraggingIdx = cIdx; m_hDraggingIdx = cIdx;
rootView().setActiveDragView(this); rootView().setActiveDragView(this);
return; return;
@ -339,21 +296,17 @@ void Table::mouseDown(const boo::SWindowCoord& coord,
if (m_headerNeedsUpdate) if (m_headerNeedsUpdate)
_setHeaderVerts(subRect()); _setHeaderVerts(subRect());
if (m_deferredActivation != -1 && m_state) if (m_deferredActivation != -1 && m_state) {
{
m_state->rowActivated(m_deferredActivation); m_state->rowActivated(m_deferredActivation);
m_deferredActivation = -1; m_deferredActivation = -1;
} }
} }
void Table::RowsView::mouseDown(const boo::SWindowCoord& coord, void Table::RowsView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod)
{
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
if (hv.mouseDown(coord, button, mod)) if (hv.mouseDown(coord, button, mod))
return; /* Trap header event */ return; /* Trap header event */
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
for (ViewChild<std::unique_ptr<CellView>>& cv : col[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[0])
cv.mouseDown(coord, button, mod); cv.mouseDown(coord, button, mod);
for (ViewChild<std::unique_ptr<CellView>>& cv : col[1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[1])
@ -361,47 +314,36 @@ void Table::RowsView::mouseDown(const boo::SWindowCoord& coord,
} }
} }
void Table::CellView::mouseDown(const boo::SWindowCoord& coord, void Table::CellView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod) if (m_r != -1) {
{
if (m_r != -1)
{
m_t.selectRow(m_r); m_t.selectRow(m_r);
if (m_t.m_clickFrames < 15) if (m_t.m_clickFrames < 15)
m_t.m_deferredActivation = m_r; m_t.m_deferredActivation = m_r;
else else
m_t.m_clickFrames = 0; m_t.m_clickFrames = 0;
} } else
else
m_t.m_headerNeedsUpdate = true; m_t.m_headerNeedsUpdate = true;
} }
void Table::mouseUp(const boo::SWindowCoord& coord, void Table::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod)
{
m_scroll.mouseUp(coord, button, mod); m_scroll.mouseUp(coord, button, mod);
if (m_headerNeedsUpdate) if (m_headerNeedsUpdate)
_setHeaderVerts(subRect()); _setHeaderVerts(subRect());
if (m_hDraggingIdx) if (m_hDraggingIdx) {
{
rootView().setActiveDragView(nullptr); rootView().setActiveDragView(nullptr);
m_hDraggingIdx = 0; m_hDraggingIdx = 0;
} }
} }
void Table::RowsView::mouseUp(const boo::SWindowCoord& coord, void Table::RowsView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod)
{
size_t idx = 0; size_t idx = 0;
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews) {
{
if (hv.m_mouseDown && hv.m_mouseIn) if (hv.m_mouseDown && hv.m_mouseIn)
m_t.cycleSortColumn(idx); m_t.cycleSortColumn(idx);
hv.mouseUp(coord, button, mod); hv.mouseUp(coord, button, mod);
++idx; ++idx;
} }
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
for (ViewChild<std::unique_ptr<CellView>>& cv : col[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[0])
cv.mouseUp(coord, button, mod); cv.mouseUp(coord, button, mod);
for (ViewChild<std::unique_ptr<CellView>>& cv : col[1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[1])
@ -409,19 +351,14 @@ void Table::RowsView::mouseUp(const boo::SWindowCoord& coord,
} }
} }
void Table::CellView::mouseUp(const boo::SWindowCoord& coord, void Table::CellView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_r == -1) if (m_r == -1)
m_t.m_headerNeedsUpdate = true; m_t.m_headerNeedsUpdate = true;
} }
void Table::mouseMove(const boo::SWindowCoord& coord) void Table::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_state && m_state->columnSplitResizeAllowed()) {
if (m_state && m_state->columnSplitResizeAllowed()) if (m_hDraggingIdx) {
{
if (m_hDraggingIdx)
{
float split = (coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]); float split = (coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]);
if (m_hDraggingIdx <= 1) if (m_hDraggingIdx <= 1)
@ -440,14 +377,12 @@ void Table::mouseMove(const boo::SWindowCoord& coord)
} }
size_t cIdx = 0; size_t cIdx = 0;
bool hovering = false; bool hovering = false;
for (const boo::SWindowRect& rect : m_hCellRects) for (const boo::SWindowRect& rect : m_hCellRects) {
{
if (cIdx++ == 0) if (cIdx++ == 0)
continue; continue;
if (abs(coord.pixel[0] - rect.location[0]) < 4 && if (abs(coord.pixel[0] - rect.location[0]) < 4 &&
unsigned(coord.pixel[1] - subRect().location[1] - unsigned(coord.pixel[1] - subRect().location[1] - subRect().size[1] + rect.size[1]) <
subRect().size[1] + rect.size[1]) < unsigned(rect.size[1])) unsigned(rect.size[1])) {
{
hovering = true; hovering = true;
break; break;
} }
@ -460,12 +395,10 @@ void Table::mouseMove(const boo::SWindowCoord& coord)
_setHeaderVerts(subRect()); _setHeaderVerts(subRect());
} }
void Table::RowsView::mouseMove(const boo::SWindowCoord& coord) void Table::RowsView::mouseMove(const boo::SWindowCoord& coord) {
{
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
hv.mouseMove(coord); hv.mouseMove(coord);
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
for (ViewChild<std::unique_ptr<CellView>>& cv : col[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[0])
cv.mouseMove(coord); cv.mouseMove(coord);
for (ViewChild<std::unique_ptr<CellView>>& cv : col[1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[1])
@ -473,32 +406,27 @@ void Table::RowsView::mouseMove(const boo::SWindowCoord& coord)
} }
} }
void Table::mouseEnter(const boo::SWindowCoord& coord) void Table::mouseEnter(const boo::SWindowCoord& coord) {
{
m_scroll.mouseEnter(coord); m_scroll.mouseEnter(coord);
if (m_headerNeedsUpdate) if (m_headerNeedsUpdate)
_setHeaderVerts(subRect()); _setHeaderVerts(subRect());
} }
void Table::CellView::mouseEnter(const boo::SWindowCoord& coord) void Table::CellView::mouseEnter(const boo::SWindowCoord& coord) {
{
if (m_r == -1) if (m_r == -1)
m_t.m_headerNeedsUpdate = true; m_t.m_headerNeedsUpdate = true;
} }
void Table::mouseLeave(const boo::SWindowCoord& coord) void Table::mouseLeave(const boo::SWindowCoord& coord) {
{
m_scroll.mouseLeave(coord); m_scroll.mouseLeave(coord);
if (m_headerNeedsUpdate) if (m_headerNeedsUpdate)
_setHeaderVerts(subRect()); _setHeaderVerts(subRect());
} }
void Table::RowsView::mouseLeave(const boo::SWindowCoord& coord) void Table::RowsView::mouseLeave(const boo::SWindowCoord& coord) {
{
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
hv.mouseLeave(coord); hv.mouseLeave(coord);
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
for (ViewChild<std::unique_ptr<CellView>>& cv : col[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[0])
cv.mouseLeave(coord); cv.mouseLeave(coord);
for (ViewChild<std::unique_ptr<CellView>>& cv : col[1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[1])
@ -506,107 +434,82 @@ void Table::RowsView::mouseLeave(const boo::SWindowCoord& coord)
} }
} }
void Table::CellView::mouseLeave(const boo::SWindowCoord& coord) void Table::CellView::mouseLeave(const boo::SWindowCoord& coord) {
{
if (m_r == -1) if (m_r == -1)
m_t.m_headerNeedsUpdate = true; m_t.m_headerNeedsUpdate = true;
} }
void Table::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void Table::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { m_scroll.scroll(coord, scroll); }
{
m_scroll.scroll(coord, scroll);
}
void Table::think() void Table::think() {
{
if (m_scroll.m_view) if (m_scroll.m_view)
m_scroll.m_view->think(); m_scroll.m_view->think();
++m_clickFrames; ++m_clickFrames;
} }
void Table::CellView::reset() void Table::CellView::reset() {
{
m_c = -1; m_c = -1;
m_r = -1; m_r = -1;
if (m_textHash) if (m_textHash) {
{
m_text->typesetGlyphs(""); m_text->typesetGlyphs("");
m_textHash = 0; m_textHash = 0;
} }
} }
bool Table::CellView::reset(size_t c) bool Table::CellView::reset(size_t c) {
{
m_c = c; m_c = c;
m_r = -1; m_r = -1;
auto headerText = m_t.m_data->header(c); auto headerText = m_t.m_data->header(c);
if (!headerText.empty()) if (!headerText.empty()) {
{
uint64_t hash = XXH64(headerText.data(), headerText.size(), 0); uint64_t hash = XXH64(headerText.data(), headerText.size(), 0);
if (hash != m_textHash) if (hash != m_textHash) {
{
m_text->typesetGlyphs(headerText, rootView().themeData().uiText()); m_text->typesetGlyphs(headerText, rootView().themeData().uiText());
m_textHash = hash; m_textHash = hash;
} }
return true; return true;
} } else if (m_textHash) {
else if (m_textHash)
{
m_text->typesetGlyphs(""); m_text->typesetGlyphs("");
m_textHash = 0; m_textHash = 0;
} }
return false; return false;
} }
bool Table::CellView::reset(size_t c, size_t r) bool Table::CellView::reset(size_t c, size_t r) {
{
m_c = c; m_c = c;
m_r = r; m_r = r;
auto cellText = m_t.m_data->cell(c, r); auto cellText = m_t.m_data->cell(c, r);
if (!cellText.empty()) if (!cellText.empty()) {
{
uint64_t hash = XXH64(cellText.data(), cellText.size(), 0); uint64_t hash = XXH64(cellText.data(), cellText.size(), 0);
if (hash != m_textHash) if (hash != m_textHash) {
{
m_text->typesetGlyphs(cellText, rootView().themeData().uiText()); m_text->typesetGlyphs(cellText, rootView().themeData().uiText());
m_textHash = hash; m_textHash = hash;
} }
return true; return true;
} } else if (m_textHash) {
else if (m_textHash)
{
m_text->typesetGlyphs(""); m_text->typesetGlyphs("");
m_textHash = 0; m_textHash = 0;
} }
return false; return false;
} }
std::vector<Table::ColumnPool>& Table::ensureCellPools(size_t rows, size_t cols, ViewResources& res) std::vector<Table::ColumnPool>& Table::ensureCellPools(size_t rows, size_t cols, ViewResources& res) {
{ if (m_cellPools.size() < cols) {
if (m_cellPools.size() < cols)
{
m_cellPools.reserve(cols); m_cellPools.reserve(cols);
for (size_t i = m_cellPools.size(); i < cols; ++i) for (size_t i = m_cellPools.size(); i < cols; ++i)
m_cellPools.emplace_back(); m_cellPools.emplace_back();
m_ensuredRows = 0; m_ensuredRows = 0;
} }
if (m_ensuredRows < rows) if (m_ensuredRows < rows) {
{ for (size_t i = 0; i < cols; ++i) {
for (size_t i=0 ; i<cols ; ++i)
{
ColumnPool& cp = m_cellPools[i]; ColumnPool& cp = m_cellPools[i];
if (rows > SPECTER_TABLE_MAX_ROWS) if (rows > SPECTER_TABLE_MAX_ROWS) {
{
for (int p = 0; p < 2; ++p) for (int p = 0; p < 2; ++p)
for (ViewChild<std::unique_ptr<CellView>>& cv : cp[p]) for (ViewChild<std::unique_ptr<CellView>>& cv : cp[p])
if (!cv.m_view) if (!cv.m_view)
cv.m_view.reset(new CellView(*this, res)); cv.m_view.reset(new CellView(*this, res));
} } else {
else
{
size_t r = 0; size_t r = 0;
for (ViewChild<std::unique_ptr<CellView>>& cv : cp[0]) for (ViewChild<std::unique_ptr<CellView>>& cv : cp[0]) {
{
if (!cv.m_view) if (!cv.m_view)
cv.m_view.reset(new CellView(*this, res)); cv.m_view.reset(new CellView(*this, res));
++r; ++r;
@ -620,8 +523,7 @@ std::vector<Table::ColumnPool>& Table::ensureCellPools(size_t rows, size_t cols,
return m_cellPools; return m_cellPools;
} }
void Table::_updateData() void Table::_updateData() {
{
m_header = false; m_header = false;
bool newViewChildren = false; bool newViewChildren = false;
if (m_columns != m_data->columnCount() || m_rows > m_data->rowCount() + SPECTER_TABLE_MAX_ROWS) if (m_columns != m_data->columnCount() || m_rows > m_data->rowCount() + SPECTER_TABLE_MAX_ROWS)
@ -633,8 +535,7 @@ void Table::_updateData()
return; return;
ViewResources& res = rootView().viewRes(); ViewResources& res = rootView().viewRes();
if (newViewChildren) if (newViewChildren) {
{
m_headerViews.clear(); m_headerViews.clear();
m_cellPools.clear(); m_cellPools.clear();
m_headerViews.reserve(m_columns); m_headerViews.reserve(m_columns);
@ -649,8 +550,7 @@ void Table::_updateData()
int pool0 = (poolIdx & 1) != 0; int pool0 = (poolIdx & 1) != 0;
int pool1 = (poolIdx & 1) == 0; int pool1 = (poolIdx & 1) == 0;
for (size_t c=0 ; c<m_columns ; ++c) for (size_t c = 0; c < m_columns; ++c) {
{
std::unique_ptr<CellView>& cv = m_headerViews[c].m_view; std::unique_ptr<CellView>& cv = m_headerViews[c].m_view;
if (!cv) if (!cv)
cv.reset(new CellView(*this, res)); cv.reset(new CellView(*this, res));
@ -659,24 +559,19 @@ void Table::_updateData()
ColumnPool& col = m_cellPools[c]; ColumnPool& col = m_cellPools[c];
if (poolIdx != m_activePool) if (poolIdx != m_activePool) {
{ for (size_t r = startRow, i = 0; i < SPECTER_TABLE_MAX_ROWS; ++r, ++i) {
for (size_t r=startRow, i=0 ; i<SPECTER_TABLE_MAX_ROWS ; ++r, ++i)
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool0][i]; ViewChild<std::unique_ptr<CellView>>& cv = col[pool0][i];
if (cv.m_view) if (cv.m_view) {
{
if (r < m_rows) if (r < m_rows)
cv.m_view->reset(c, r); cv.m_view->reset(c, r);
else else
cv.m_view->reset(); cv.m_view->reset();
} }
} }
for (size_t r=startRow+SPECTER_TABLE_MAX_ROWS, i=0 ; i<SPECTER_TABLE_MAX_ROWS ; ++r, ++i) for (size_t r = startRow + SPECTER_TABLE_MAX_ROWS, i = 0; i < SPECTER_TABLE_MAX_ROWS; ++r, ++i) {
{
ViewChild<std::unique_ptr<CellView>>& cv = col[pool1][i]; ViewChild<std::unique_ptr<CellView>>& cv = col[pool1][i];
if (cv.m_view) if (cv.m_view) {
{
if (r < m_rows) if (r < m_rows)
cv.m_view->reset(c, r); cv.m_view->reset(c, r);
else else
@ -689,14 +584,12 @@ void Table::_updateData()
m_activePool = poolIdx; m_activePool = poolIdx;
} }
void Table::updateData() void Table::updateData() {
{
m_activePool = -1; m_activePool = -1;
updateSize(); updateSize();
} }
std::vector<boo::SWindowRect> Table::getCellRects(const boo::SWindowRect& sub) const std::vector<boo::SWindowRect> Table::getCellRects(const boo::SWindowRect& sub) const {
{
if (!m_columns) if (!m_columns)
return {}; return {};
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
@ -705,12 +598,10 @@ std::vector<boo::SWindowRect> Table::getCellRects(const boo::SWindowRect& sub) c
bool valid = false; bool valid = false;
std::vector<float> splits; std::vector<float> splits;
splits.reserve(m_columns); splits.reserve(m_columns);
if (m_state) if (m_state) {
{
float lastSplit = 0.0; float lastSplit = 0.0;
size_t i; size_t i;
for (i=0 ; i<m_columns ; ++i) for (i = 0; i < m_columns; ++i) {
{
float split = m_state->getColumnSplit(i); float split = m_state->getColumnSplit(i);
if (split < lastSplit || split < 0.0 || split > 1.0) if (split < lastSplit || split < 0.0 || split > 1.0)
break; break;
@ -722,11 +613,9 @@ std::vector<boo::SWindowRect> Table::getCellRects(const boo::SWindowRect& sub) c
} }
/* Uniform split otherwise */ /* Uniform split otherwise */
if (!valid) if (!valid) {
{
float split = 0.0; float split = 0.0;
for (size_t i=0 ; i<m_columns ; ++i) for (size_t i = 0; i < m_columns; ++i) {
{
splits.push_back(split); splits.push_back(split);
split += 1.0 / float(m_columns); split += 1.0 / float(m_columns);
} }
@ -736,21 +625,17 @@ std::vector<boo::SWindowRect> Table::getCellRects(const boo::SWindowRect& sub) c
ret.reserve(m_columns); ret.reserve(m_columns);
int lastX = 0; int lastX = 0;
for (size_t i=0 ; i<m_columns ; ++i) for (size_t i = 0; i < m_columns; ++i) {
{
float nextSplit = (i == m_columns - 1) ? 1.0 : splits[i + 1]; float nextSplit = (i == m_columns - 1) ? 1.0 : splits[i + 1];
int x = nextSplit * sub.size[0]; int x = nextSplit * sub.size[0];
ret.push_back({sub.location[0] + lastX, sub.location[1], ret.push_back({sub.location[0] + lastX, sub.location[1], x - lastX, int(ROW_HEIGHT * pf)});
x - lastX, int(ROW_HEIGHT * pf)});
lastX = x; lastX = x;
} }
return ret; return ret;
} }
void Table::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
void Table::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
View::resized(root, sub); View::resized(root, sub);
if (m_scroll.m_view) if (m_scroll.m_view)
m_scroll.m_view->resized(root, sub); m_scroll.m_view->resized(root, sub);
@ -761,24 +646,21 @@ void Table::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
std::vector<boo::SWindowRect> cellRects = getCellRects(headRow); std::vector<boo::SWindowRect> cellRects = getCellRects(headRow);
_setHeaderVerts(sub); _setHeaderVerts(sub);
size_t cIdx = 0; size_t cIdx = 0;
for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews) for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews) {
{
if (hv.m_view) if (hv.m_view)
hv.m_view->resized(root, cellRects[cIdx], sub); hv.m_view->resized(root, cellRects[cIdx], sub);
++cIdx; ++cIdx;
} }
} }
int Table::RowsView::nominalHeight() const int Table::RowsView::nominalHeight() const {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int rows = m_t.m_rows + 1; int rows = m_t.m_rows + 1;
return rows * (ROW_HEIGHT + CELL_MARGIN * 2) * pf; return rows * (ROW_HEIGHT + CELL_MARGIN * 2) * pf;
} }
void Table::RowsView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void Table::RowsView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{
View::resized(root, sub); View::resized(root, sub);
_setRowVerts(sub, scissor); _setRowVerts(sub, scissor);
m_t._updateData(); m_t._updateData();
@ -798,17 +680,14 @@ void Table::RowsView::resized(const boo::SWindowRect& root, const boo::SWindowRe
int pool0 = (poolIdx & 1) != 0; int pool0 = (poolIdx & 1) != 0;
int pool1 = (poolIdx & 1) == 0; int pool1 = (poolIdx & 1) == 0;
int locationStart = spacing * poolIdx * SPECTER_TABLE_MAX_ROWS; int locationStart = spacing * poolIdx * SPECTER_TABLE_MAX_ROWS;
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
cellRectIt->location[1] -= locationStart; cellRectIt->location[1] -= locationStart;
for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool0]) {
{
cellRectIt->location[1] -= spacing; cellRectIt->location[1] -= spacing;
if (cv.m_view) if (cv.m_view)
cv.m_view->resized(root, *cellRectIt, cellScissor); cv.m_view->resized(root, *cellRectIt, cellScissor);
} }
for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool1]) {
{
cellRectIt->location[1] -= spacing; cellRectIt->location[1] -= spacing;
if (cv.m_view) if (cv.m_view)
cv.m_view->resized(root, *cellRectIt, cellScissor); cv.m_view->resized(root, *cellRectIt, cellScissor);
@ -821,8 +700,7 @@ void Table::RowsView::resized(const boo::SWindowRect& root, const boo::SWindowRe
} }
void Table::CellView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void Table::CellView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{
View::resized(root, sub); View::resized(root, sub);
boo::SWindowRect textRect = sub; boo::SWindowRect textRect = sub;
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
@ -832,14 +710,12 @@ void Table::CellView::resized(const boo::SWindowRect& root, const boo::SWindowRe
m_scissorRect = sub.intersect(scissor); m_scissorRect = sub.intersect(scissor);
} }
void Table::draw(boo::IGraphicsCommandQueue* gfxQ) void Table::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
if (m_scroll.m_view) if (m_scroll.m_view)
m_scroll.m_view->draw(gfxQ); m_scroll.m_view->draw(gfxQ);
} }
void Table::RowsView::draw(boo::IGraphicsCommandQueue* gfxQ) void Table::RowsView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->setScissor(m_scissorRect); gfxQ->setScissor(m_scissorRect);
@ -848,25 +724,21 @@ void Table::RowsView::draw(boo::IGraphicsCommandQueue* gfxQ)
int poolIdx = m_t.m_activePool; int poolIdx = m_t.m_activePool;
int pool0 = (poolIdx & 1) != 0; int pool0 = (poolIdx & 1) != 0;
int pool1 = (poolIdx & 1) == 0; int pool1 = (poolIdx & 1) == 0;
for (auto& col : m_t.m_cellPools) for (auto& col : m_t.m_cellPools) {
{
size_t idx = poolIdx * SPECTER_TABLE_MAX_ROWS; size_t idx = poolIdx * SPECTER_TABLE_MAX_ROWS;
for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool0]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool0]) {
{
if (cv.m_view && idx >= m_visibleStart && idx < m_visibleStart + m_visibleRows) if (cv.m_view && idx >= m_visibleStart && idx < m_visibleStart + m_visibleRows)
cv.m_view->draw(gfxQ); cv.m_view->draw(gfxQ);
++idx; ++idx;
} }
for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool1]) for (ViewChild<std::unique_ptr<CellView>>& cv : col[pool1]) {
{
if (cv.m_view && idx >= m_visibleStart && idx < m_visibleStart + m_visibleRows) if (cv.m_view && idx >= m_visibleStart && idx < m_visibleStart + m_visibleRows)
cv.m_view->draw(gfxQ); cv.m_view->draw(gfxQ);
++idx; ++idx;
} }
} }
if (m_t.m_header) if (m_t.m_header) {
{
gfxQ->setShaderDataBinding(m_t.m_vertsBinding); gfxQ->setShaderDataBinding(m_t.m_vertsBinding);
gfxQ->setScissor(rootView().subRect()); gfxQ->setScissor(rootView().subRect());
gfxQ->draw(1, m_t.m_columns * 6 - 2); gfxQ->draw(1, m_t.m_columns * 6 - 2);
@ -878,13 +750,11 @@ void Table::RowsView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->setScissor(rootView().subRect()); gfxQ->setScissor(rootView().subRect());
} }
void Table::CellView::draw(boo::IGraphicsCommandQueue* gfxQ) void Table::CellView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ if (m_scissorRect.size[0] && m_scissorRect.size[1]) {
if (m_scissorRect.size[0] && m_scissorRect.size[1])
{
gfxQ->setScissor(m_scissorRect); gfxQ->setScissor(m_scissorRect);
m_text->draw(gfxQ); m_text->draw(gfxQ);
} }
} }
} } // namespace specter

View File

@ -2,14 +2,11 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
TextField::TextField(ViewResources& res, View& parentView, IStringBinding* strBind) TextField::TextField(ViewResources& res, View& parentView, IStringBinding* strBind)
: ITextInputView(res, parentView, strBind) : ITextInputView(res, parentView, strBind) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res); buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 41, m_viewVertBlockBuf); m_vertsBinding.init(ctx, res, 41, m_viewVertBlockBuf);
return true; return true;
@ -25,14 +22,11 @@ TextField::TextField(ViewResources& res, View& parentView, IStringBinding* strBi
setText(strBind->getDefault(this)); setText(strBind->getDefault(this));
} }
void TextField::_setText() void TextField::_setText() {
{ if (m_hasTextSet) {
if (m_hasTextSet)
{
_clearSelectionRange(); _clearSelectionRange();
m_textStr = m_deferredTextStr; m_textStr = m_deferredTextStr;
m_text->typesetGlyphs(m_textStr, m_error ? rootView().themeData().uiText() : m_text->typesetGlyphs(m_textStr, m_error ? rootView().themeData().uiText() : rootView().themeData().fieldText());
rootView().themeData().fieldText());
if (m_controlBinding) if (m_controlBinding)
if (IStringBinding* strBind = IStringBinding::castTo(m_controlBinding)) if (IStringBinding* strBind = IStringBinding::castTo(m_controlBinding))
strBind->changed(this, m_textStr); strBind->changed(this, m_textStr);
@ -42,10 +36,8 @@ void TextField::_setText()
} }
} }
void TextField::_setMarkedText() void TextField::_setMarkedText() {
{ if (m_hasMarkSet) {
if (m_hasMarkSet)
{
m_markReplStart = m_deferredMarkReplStart; m_markReplStart = m_deferredMarkReplStart;
m_markReplCount = m_deferredMarkReplCount; m_markReplCount = m_deferredMarkReplCount;
m_markSelStart = m_deferredMarkSelStart; m_markSelStart = m_deferredMarkSelStart;
@ -53,19 +45,15 @@ void TextField::_setMarkedText()
size_t repPoint; size_t repPoint;
size_t repEnd; size_t repEnd;
if (m_selectionCount) if (m_selectionCount) {
{
repPoint = m_selectionStart; repPoint = m_selectionStart;
repEnd = m_selectionStart; repEnd = m_selectionStart;
} } else {
else
{
repPoint = m_cursorPos; repPoint = m_cursorPos;
repEnd = m_cursorPos; repEnd = m_cursorPos;
} }
if (m_markReplStart != SIZE_MAX) if (m_markReplStart != SIZE_MAX) {
{
repPoint += m_markReplStart; repPoint += m_markReplStart;
repEnd += m_markReplStart + m_markReplCount; repEnd += m_markReplStart + m_markReplCount;
} }
@ -77,8 +65,7 @@ void TextField::_setMarkedText()
std::string compStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + repPoint).iter()); std::string compStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + repPoint).iter());
compStr += m_deferredMarkStr; compStr += m_deferredMarkStr;
compStr += std::string((UTF8Iterator(textStr.cbegin()) + repEnd).iter(), textStr.cend()); compStr += std::string((UTF8Iterator(textStr.cbegin()) + repEnd).iter(), textStr.cend());
m_text->typesetGlyphs(compStr, m_error ? rootView().themeData().uiText() : m_text->typesetGlyphs(compStr, m_error ? rootView().themeData().uiText() : rootView().themeData().fieldText());
rootView().themeData().fieldText());
size_t pos = m_cursorPos; size_t pos = m_cursorPos;
if (m_deferredMarkStr.size()) if (m_deferredMarkStr.size())
@ -96,12 +83,10 @@ void TextField::_setMarkedText()
m_text->invalidateGlyphs(); m_text->invalidateGlyphs();
m_hasMarkSet = false; m_hasMarkSet = false;
} }
} }
void TextField::setText(std::string_view str) void TextField::setText(std::string_view str) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
UTF8Iterator it(str.cbegin()); UTF8Iterator it(str.cbegin());
for (; it.iter() != str.cend(); ++it) for (; it.iter() != str.cend(); ++it)
@ -111,11 +96,9 @@ void TextField::setText(std::string_view str)
m_hasTextSet = true; m_hasTextSet = true;
} }
void TextField::setInactive() void TextField::setInactive() {
{
const IThemeData& theme = rootView().themeData(); const IThemeData& theme = rootView().themeData();
if (m_error) if (m_error) {
{
m_verts[0].m_color = theme.textfield1Inactive() * zeus::CColor::skRed; m_verts[0].m_color = theme.textfield1Inactive() * zeus::CColor::skRed;
m_verts[1].m_color = theme.textfield2Inactive() * zeus::CColor::skRed; m_verts[1].m_color = theme.textfield2Inactive() * zeus::CColor::skRed;
m_verts[2].m_color = theme.textfield1Inactive() * zeus::CColor::skRed; m_verts[2].m_color = theme.textfield1Inactive() * zeus::CColor::skRed;
@ -123,9 +106,7 @@ void TextField::setInactive()
m_verts[4].m_color = theme.textfield2Inactive() * zeus::CColor::skRed; m_verts[4].m_color = theme.textfield2Inactive() * zeus::CColor::skRed;
for (int i = 5; i < 28; ++i) for (int i = 5; i < 28; ++i)
m_verts[i].m_color = theme.textfield2Inactive() * zeus::CColor::skRed; m_verts[i].m_color = theme.textfield2Inactive() * zeus::CColor::skRed;
} } else {
else
{
m_verts[0].m_color = theme.textfield1Inactive(); m_verts[0].m_color = theme.textfield1Inactive();
m_verts[1].m_color = theme.textfield2Inactive(); m_verts[1].m_color = theme.textfield2Inactive();
m_verts[2].m_color = theme.textfield1Inactive(); m_verts[2].m_color = theme.textfield1Inactive();
@ -138,11 +119,9 @@ void TextField::setInactive()
m_bgState = BGState::Inactive; m_bgState = BGState::Inactive;
} }
void TextField::setHover() void TextField::setHover() {
{
const IThemeData& theme = rootView().themeData(); const IThemeData& theme = rootView().themeData();
if (m_error) if (m_error) {
{
m_verts[0].m_color = theme.textfield1Hover() * zeus::CColor::skRed; m_verts[0].m_color = theme.textfield1Hover() * zeus::CColor::skRed;
m_verts[1].m_color = theme.textfield2Hover() * zeus::CColor::skRed; m_verts[1].m_color = theme.textfield2Hover() * zeus::CColor::skRed;
m_verts[2].m_color = theme.textfield1Hover() * zeus::CColor::skRed; m_verts[2].m_color = theme.textfield1Hover() * zeus::CColor::skRed;
@ -150,9 +129,7 @@ void TextField::setHover()
m_verts[4].m_color = theme.textfield2Hover() * zeus::CColor::skRed; m_verts[4].m_color = theme.textfield2Hover() * zeus::CColor::skRed;
for (int i = 5; i < 28; ++i) for (int i = 5; i < 28; ++i)
m_verts[i].m_color = theme.textfield2Inactive() * zeus::CColor::skRed; m_verts[i].m_color = theme.textfield2Inactive() * zeus::CColor::skRed;
} } else {
else
{
m_verts[0].m_color = theme.textfield1Hover(); m_verts[0].m_color = theme.textfield1Hover();
m_verts[1].m_color = theme.textfield2Hover(); m_verts[1].m_color = theme.textfield2Hover();
m_verts[2].m_color = theme.textfield1Hover(); m_verts[2].m_color = theme.textfield1Hover();
@ -165,11 +142,9 @@ void TextField::setHover()
m_bgState = BGState::Hover; m_bgState = BGState::Hover;
} }
void TextField::setDisabled() void TextField::setDisabled() {
{
const IThemeData& theme = rootView().themeData(); const IThemeData& theme = rootView().themeData();
if (m_error) if (m_error) {
{
m_verts[0].m_color = theme.textfield1Disabled() * zeus::CColor::skRed; m_verts[0].m_color = theme.textfield1Disabled() * zeus::CColor::skRed;
m_verts[1].m_color = theme.textfield2Disabled() * zeus::CColor::skRed; m_verts[1].m_color = theme.textfield2Disabled() * zeus::CColor::skRed;
m_verts[2].m_color = theme.textfield1Disabled() * zeus::CColor::skRed; m_verts[2].m_color = theme.textfield1Disabled() * zeus::CColor::skRed;
@ -177,9 +152,7 @@ void TextField::setDisabled()
m_verts[4].m_color = theme.textfield2Disabled() * zeus::CColor::skRed; m_verts[4].m_color = theme.textfield2Disabled() * zeus::CColor::skRed;
for (int i = 5; i < 28; ++i) for (int i = 5; i < 28; ++i)
m_verts[i].m_color = theme.textfield2Disabled() * zeus::CColor::skRed; m_verts[i].m_color = theme.textfield2Disabled() * zeus::CColor::skRed;
} } else {
else
{
m_verts[0].m_color = theme.textfield1Disabled(); m_verts[0].m_color = theme.textfield1Disabled();
m_verts[1].m_color = theme.textfield2Disabled(); m_verts[1].m_color = theme.textfield2Disabled();
m_verts[2].m_color = theme.textfield1Disabled(); m_verts[2].m_color = theme.textfield1Disabled();
@ -192,41 +165,34 @@ void TextField::setDisabled()
m_bgState = BGState::Disabled; m_bgState = BGState::Disabled;
} }
void TextField::refreshBg() void TextField::refreshBg() {
{ switch (m_bgState) {
switch (m_bgState)
{
case BGState::Inactive: case BGState::Inactive:
setInactive(); break; setInactive();
break;
case BGState::Hover: case BGState::Hover:
setHover(); break; setHover();
break;
case BGState::Disabled: case BGState::Disabled:
setDisabled(); break; setDisabled();
break;
} }
} }
void TextField::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void TextField::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (!m_active) if (!m_active) {
{
rootView().setActiveTextView(this); rootView().setActiveTextView(this);
} } else if (m_clickFrames2 < 15) {
else if (m_clickFrames2 < 15)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
setSelectionRange(0, len); setSelectionRange(0, len);
} } else if (m_clickFrames < 15) {
else if (m_clickFrames < 15)
{
size_t startPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]); size_t startPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]);
std::pair<size_t, size_t> range = m_text->queryWholeWordRange(startPos); std::pair<size_t, size_t> range = m_text->queryWholeWordRange(startPos);
setSelectionRange(range.first, range.second); setSelectionRange(range.first, range.second);
m_clickFrames2 = 0; m_clickFrames2 = 0;
} } else {
else
{
size_t startPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]); size_t startPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]);
setCursorPos(startPos); setCursorPos(startPos);
m_dragging |= size_t(1) << size_t(button); m_dragging |= size_t(1) << size_t(button);
@ -236,17 +202,14 @@ void TextField::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butt
m_clickFrames = 0; m_clickFrames = 0;
} }
void TextField::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void TextField::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
m_dragging &= ~(size_t(1) << size_t(button)); m_dragging &= ~(size_t(1) << size_t(button));
if (m_dragging == 0) if (m_dragging == 0)
rootView().setActiveDragView(nullptr); rootView().setActiveDragView(nullptr);
} }
void TextField::mouseMove(const boo::SWindowCoord& coord) void TextField::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_dragging != 0) {
if (m_dragging != 0)
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
size_t thisPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]); size_t thisPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]);
size_t minPos = std::min(m_dragStart, thisPos); size_t minPos = std::min(m_dragStart, thisPos);
@ -258,20 +221,17 @@ void TextField::mouseMove(const boo::SWindowCoord& coord)
} }
} }
void TextField::mouseEnter(const boo::SWindowCoord& coord) void TextField::mouseEnter(const boo::SWindowCoord& coord) {
{
setHover(); setHover();
rootView().setTextFieldHover(true); rootView().setTextFieldHover(true);
} }
void TextField::mouseLeave(const boo::SWindowCoord& coord) void TextField::mouseLeave(const boo::SWindowCoord& coord) {
{
setInactive(); setInactive();
rootView().setTextFieldHover(false); rootView().setTextFieldHover(false);
} }
void TextField::clipboardCopy() void TextField::clipboardCopy() {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (!m_selectionCount) if (!m_selectionCount)
@ -283,12 +243,11 @@ void TextField::clipboardCopy()
UTF8Iterator end(begin.iter()); UTF8Iterator end(begin.iter());
end += m_selectionCount; end += m_selectionCount;
rootView().window()->clipboardCopy(boo::EClipboardType::UTF8String, rootView().window()->clipboardCopy(boo::EClipboardType::UTF8String, (uint8_t*)&*begin.iter(),
(uint8_t*)&*begin.iter(), end.iter() - begin.iter()); end.iter() - begin.iter());
} }
void TextField::clipboardCut() void TextField::clipboardCut() {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (!m_selectionCount) if (!m_selectionCount)
@ -300,8 +259,8 @@ void TextField::clipboardCut()
UTF8Iterator end(begin.iter()); UTF8Iterator end(begin.iter());
end += m_selectionCount; end += m_selectionCount;
rootView().window()->clipboardCopy(boo::EClipboardType::UTF8String, rootView().window()->clipboardCopy(boo::EClipboardType::UTF8String, (uint8_t*)&*begin.iter(),
(uint8_t*)&*begin.iter(), end.iter() - begin.iter()); end.iter() - begin.iter());
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter());
newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend());
@ -310,17 +269,14 @@ void TextField::clipboardCut()
setCursorPos(selStart); setCursorPos(selStart);
} }
static std::string SanitizeUTF8TextLine(const char* string, size_t len) static std::string SanitizeUTF8TextLine(const char* string, size_t len) {
{
const char* it = string; const char* it = string;
utf8proc_int32_t ch; utf8proc_int32_t ch;
utf8proc_ssize_t sz; utf8proc_ssize_t sz;
std::string ret; std::string ret;
ret.reserve(len); ret.reserve(len);
for (sz = utf8proc_iterate((utf8proc_uint8_t*)it, -1, &ch); for (sz = utf8proc_iterate((utf8proc_uint8_t*)it, -1, &ch); it < string + len;
it < string+len; it += sz, sz = utf8proc_iterate((utf8proc_uint8_t*)it, -1, &ch)) {
it += sz, sz = utf8proc_iterate((utf8proc_uint8_t*)it, -1, &ch))
{
if (sz <= 0) if (sz <= 0)
break; break;
if (ch >= 0x20) if (ch >= 0x20)
@ -329,20 +285,16 @@ static std::string SanitizeUTF8TextLine(const char* string, size_t len)
return ret; return ret;
} }
void TextField::clipboardPaste() void TextField::clipboardPaste() {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
size_t retSz; size_t retSz;
std::unique_ptr<uint8_t[]> retData = std::unique_ptr<uint8_t[]> retData = rootView().window()->clipboardPaste(boo::EClipboardType::UTF8String, retSz);
rootView().window()->clipboardPaste(boo::EClipboardType::UTF8String, retSz);
std::string saniData = SanitizeUTF8TextLine((char*)retData.get(), retSz); std::string saniData = SanitizeUTF8TextLine((char*)retData.get(), retSz);
if (retData && saniData.size()) if (retData && saniData.size()) {
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
if (m_selectionCount) if (m_selectionCount) {
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter());
newStr.append(saniData); newStr.append(saniData);
std::string_view newStrView(newStr); std::string_view newStrView(newStr);
@ -350,9 +302,7 @@ void TextField::clipboardPaste()
newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend());
setText(newStr); setText(newStr);
setCursorPos(newSel); setCursorPos(newSel);
} } else {
else
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter());
newStr.append(saniData); newStr.append(saniData);
std::string_view newStrView(newStr); std::string_view newStrView(newStr);
@ -364,99 +314,73 @@ void TextField::clipboardPaste()
} }
} }
void TextField::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) void TextField::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (m_deferredMarkStr.size()) if (m_deferredMarkStr.size())
return; return;
if (key == boo::ESpecialKey::Left) if (key == boo::ESpecialKey::Left) {
{ if ((mods & boo::EModifierKey::Shift) != boo::EModifierKey::None) {
if ((mods & boo::EModifierKey::Shift) != boo::EModifierKey::None) if (m_cursorPos) {
{
if (m_cursorPos)
{
size_t origPos = m_cursorPos; size_t origPos = m_cursorPos;
if (m_selectionCount) if (m_selectionCount) {
{
if (m_cursorPos == m_selectionStart) if (m_cursorPos == m_selectionStart)
setSelectionRange(m_cursorPos - 1, m_selectionCount + 1); setSelectionRange(m_cursorPos - 1, m_selectionCount + 1);
else else
setSelectionRange(m_selectionStart, m_selectionCount - 1); setSelectionRange(m_selectionStart, m_selectionCount - 1);
} } else
else
setSelectionRange(m_cursorPos - 1, 1); setSelectionRange(m_cursorPos - 1, 1);
m_cursorPos = origPos - 1; m_cursorPos = origPos - 1;
} }
} } else {
else
{
if (m_selectionCount) if (m_selectionCount)
m_cursorPos = m_selectionStart; m_cursorPos = m_selectionStart;
setCursorPos(m_cursorPos == 0 ? 0 : (m_cursorPos - 1)); setCursorPos(m_cursorPos == 0 ? 0 : (m_cursorPos - 1));
} }
} } else if (key == boo::ESpecialKey::Right) {
else if (key == boo::ESpecialKey::Right) if ((mods & boo::EModifierKey::Shift) != boo::EModifierKey::None) {
{
if ((mods & boo::EModifierKey::Shift) != boo::EModifierKey::None)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
if (m_cursorPos < len) if (m_cursorPos < len) {
{
size_t origPos = m_cursorPos; size_t origPos = m_cursorPos;
if (m_selectionCount) if (m_selectionCount) {
{
if (m_cursorPos == m_selectionStart) if (m_cursorPos == m_selectionStart)
setSelectionRange(m_cursorPos + 1, m_selectionCount - 1); setSelectionRange(m_cursorPos + 1, m_selectionCount - 1);
else else
setSelectionRange(m_selectionStart, m_selectionCount + 1); setSelectionRange(m_selectionStart, m_selectionCount + 1);
} } else
else
setSelectionRange(m_cursorPos, 1); setSelectionRange(m_cursorPos, 1);
m_cursorPos = origPos + 1; m_cursorPos = origPos + 1;
} }
} } else {
else
{
if (m_selectionCount) if (m_selectionCount)
m_cursorPos = m_selectionStart + m_selectionCount - 1; m_cursorPos = m_selectionStart + m_selectionCount - 1;
setCursorPos(m_cursorPos + 1); setCursorPos(m_cursorPos + 1);
} }
} } else if (key == boo::ESpecialKey::Backspace) {
else if (key == boo::ESpecialKey::Backspace)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
if (m_selectionCount) if (m_selectionCount) {
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter());
newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend());
size_t selStart = m_selectionStart; size_t selStart = m_selectionStart;
setText(newStr); setText(newStr);
setCursorPos(selStart); setCursorPos(selStart);
} } else if (m_cursorPos > 0) {
else if (m_cursorPos > 0)
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + (m_cursorPos - 1)).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + (m_cursorPos - 1)).iter());
newStr.append((UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter(), textStr.cend());
setText(newStr); setText(newStr);
setCursorPos(m_cursorPos - 1); setCursorPos(m_cursorPos - 1);
} }
} } else if (key == boo::ESpecialKey::Delete) {
else if (key == boo::ESpecialKey::Delete)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
if (m_selectionCount) if (m_selectionCount) {
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_selectionStart).iter());
newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), textStr.cend());
size_t selStart = m_selectionStart; size_t selStart = m_selectionStart;
setText(newStr); setText(newStr);
setCursorPos(selStart); setCursorPos(selStart);
} } else if (m_cursorPos < len) {
else if (m_cursorPos < len)
{
std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter()); std::string newStr(textStr.cbegin(), (UTF8Iterator(textStr.cbegin()) + m_cursorPos).iter());
newStr.append((UTF8Iterator(textStr.cbegin()) + (m_cursorPos + 1)).iter(), textStr.cend()); newStr.append((UTF8Iterator(textStr.cbegin()) + (m_cursorPos + 1)).iter(), textStr.cend());
setText(newStr); setText(newStr);
@ -465,30 +389,25 @@ void TextField::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, boo
} }
} }
bool TextField::hasMarkedText() const bool TextField::hasMarkedText() const {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
return m_deferredMarkStr.size() != 0; return m_deferredMarkStr.size() != 0;
} }
std::pair<int,int> TextField::markedRange() const std::pair<int, int> TextField::markedRange() const {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (m_deferredMarkStr.empty()) if (m_deferredMarkStr.empty())
return {-1, 0}; return {-1, 0};
std::string_view deferredMarkStr(m_deferredMarkStr); std::string_view deferredMarkStr(m_deferredMarkStr);
return {m_cursorPos, UTF8Iterator(deferredMarkStr.cbegin()).countTo(deferredMarkStr.cend())}; return {m_cursorPos, UTF8Iterator(deferredMarkStr.cbegin()).countTo(deferredMarkStr.cend())};
} }
std::pair<int,int> TextField::selectedRange() const std::pair<int, int> TextField::selectedRange() const {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (!m_deferredSelectionCount) if (!m_deferredSelectionCount)
return {-1, 0}; return {-1, 0};
return {m_deferredSelectionStart, m_deferredSelectionCount}; return {m_deferredSelectionStart, m_deferredSelectionCount};
} }
void TextField::setMarkedText(std::string_view str, void TextField::setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int,int>& selectedRange, const std::pair<int, int>& replacementRange) {
const std::pair<int,int>& replacementRange)
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
m_deferredMarkStr = SanitizeUTF8TextLine(str.data(), str.size()); m_deferredMarkStr = SanitizeUTF8TextLine(str.data(), str.size());
m_deferredMarkSelStart = selectedRange.first; m_deferredMarkSelStart = selectedRange.first;
@ -497,8 +416,7 @@ void TextField::setMarkedText(std::string_view str,
m_deferredMarkReplCount = replacementRange.second; m_deferredMarkReplCount = replacementRange.second;
m_hasMarkSet = true; m_hasMarkSet = true;
} }
void TextField::unmarkText() void TextField::unmarkText() {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
m_deferredMarkStr.clear(); m_deferredMarkStr.clear();
m_deferredMarkReplStart = 0; m_deferredMarkReplStart = 0;
@ -508,9 +426,7 @@ void TextField::unmarkText()
m_hasMarkSet = true; m_hasMarkSet = true;
} }
std::string TextField::substringForRange(const std::pair<int,int>& range, std::string TextField::substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const {
std::pair<int,int>& actualRange) const
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
std::string_view deferredTextStr(m_deferredTextStr); std::string_view deferredTextStr(m_deferredTextStr);
UTF8Iterator begin(deferredTextStr.cbegin()); UTF8Iterator begin(deferredTextStr.cbegin());
@ -525,15 +441,13 @@ std::string TextField::substringForRange(const std::pair<int,int>& range,
actualRange.second = endIdx; actualRange.second = endIdx;
return std::string(begin.iter(), end.iter()); return std::string(begin.iter(), end.iter());
} }
void TextField::insertText(std::string_view str, const std::pair<int,int>& range) void TextField::insertText(std::string_view str, const std::pair<int, int>& range) {
{
std::string saniStr = SanitizeUTF8TextLine(str.data(), str.size()); std::string saniStr = SanitizeUTF8TextLine(str.data(), str.size());
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
std::string_view deferredTextStr(m_deferredTextStr); std::string_view deferredTextStr(m_deferredTextStr);
size_t curLen = UTF8Iterator(deferredTextStr.cbegin()).countTo(deferredTextStr.cend()); size_t curLen = UTF8Iterator(deferredTextStr.cbegin()).countTo(deferredTextStr.cend());
if (range.first < 0 || range.first >= curLen) if (range.first < 0 || range.first >= curLen) {
{
size_t beginPos = m_deferredCursorPos; size_t beginPos = m_deferredCursorPos;
if (m_selectionCount) if (m_selectionCount)
beginPos = m_selectionCount; beginPos = m_selectionCount;
@ -561,20 +475,17 @@ void TextField::insertText(std::string_view str, const std::pair<int,int>& range
setCursorPos(newSel); setCursorPos(newSel);
unmarkText(); unmarkText();
} }
int TextField::characterIndexAtPoint(const boo::SWindowCoord& point) const int TextField::characterIndexAtPoint(const boo::SWindowCoord& point) const {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
return m_text->reverseSelectGlyph(point.pixel[0]); return m_text->reverseSelectGlyph(point.pixel[0]);
} }
boo::SWindowRect TextField::rectForCharacterRange(const std::pair<int, int>& range, boo::SWindowRect TextField::rectForCharacterRange(const std::pair<int, int>& range,
std::pair<int,int>& actualRange) const std::pair<int, int>& actualRange) const {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
UTF8Iterator begin(textStr.cbegin()); UTF8Iterator begin(textStr.cbegin());
size_t curLen = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t curLen = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
if (range.first >= curLen) if (range.first >= curLen) {
{
const std::vector<TextView::RenderGlyph>& glyphs = m_text->accessGlyphs(); const std::vector<TextView::RenderGlyph>& glyphs = m_text->accessGlyphs();
const TextView::RenderGlyph& g = glyphs.back(); const TextView::RenderGlyph& g = glyphs.back();
return {subRect().location[0] + int(g.m_pos[3][0]), subRect().location[1] + int(g.m_pos[3][1]), 0, 0}; return {subRect().location[0] + int(g.m_pos[3][0]), subRect().location[1] + int(g.m_pos[3][1]), 0, 0};
@ -592,30 +503,23 @@ boo::SWindowRect TextField::rectForCharacterRange(const std::pair<int,int>& rang
int(g2.m_pos[3][0] - g1.m_pos[1][0]), int(g2.m_pos[0][1] - g1.m_pos[1][1])}; int(g2.m_pos[3][0] - g1.m_pos[1][0]), int(g2.m_pos[0][1] - g1.m_pos[1][1])};
} }
void TextField::think() void TextField::think() {
{
++m_cursorFrames; ++m_cursorFrames;
++m_clickFrames; ++m_clickFrames;
++m_clickFrames2; ++m_clickFrames2;
++m_errorFrames; ++m_errorFrames;
if (m_error && m_errorFrames <= 360) if (m_error && m_errorFrames <= 360) {
{
zeus::CColor errMult; zeus::CColor errMult;
zeus::CColor errBg; zeus::CColor errBg;
if (m_errorFrames < 300) if (m_errorFrames < 300) {
{
errMult = m_viewVertBlock.m_color; errMult = m_viewVertBlock.m_color;
errBg = rootView().themeData().tooltipBackground() * m_viewVertBlock.m_color; errBg = rootView().themeData().tooltipBackground() * m_viewVertBlock.m_color;
} } else if (m_errorFrames >= 360) {
else if (m_errorFrames >= 360)
{
errMult = zeus::CColor::skClear; errMult = zeus::CColor::skClear;
errBg = rootView().themeData().tooltipBackground(); errBg = rootView().themeData().tooltipBackground();
errBg[3] = 0.0; errBg[3] = 0.0;
} } else {
else
{
float t = (m_errorFrames - 300) / 60.0; float t = (m_errorFrames - 300) / 60.0;
errMult = zeus::CColor::lerp(m_viewVertBlock.m_color, zeus::CColor::skClear, t); errMult = zeus::CColor::lerp(m_viewVertBlock.m_color, zeus::CColor::skClear, t);
errBg = zeus::CColor::lerp(rootView().themeData().tooltipBackground() * m_viewVertBlock.m_color, errBg = zeus::CColor::lerp(rootView().themeData().tooltipBackground() * m_viewVertBlock.m_color,
@ -636,25 +540,20 @@ void TextField::think()
_setMarkedText(); _setMarkedText();
} }
void TextField::setActive(bool active) void TextField::setActive(bool active) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
m_active = active; m_active = active;
if (!active) if (!active) {
{
clearSelectionRange(); clearSelectionRange();
rootView().window()->claimKeyboardFocus(nullptr); rootView().window()->claimKeyboardFocus(nullptr);
} } else if (!m_selectionCount) {
else if (!m_selectionCount)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
setSelectionRange(0, len); setSelectionRange(0, len);
} }
} }
void TextField::_reallySetCursorPos(size_t pos) void TextField::_reallySetCursorPos(size_t pos) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int offset1 = 4 * pf + m_text->queryReverseAdvance(pos); int offset1 = 4 * pf + m_text->queryReverseAdvance(pos);
int offset2 = offset1 + 2 * pf; int offset2 = offset1 + 2 * pf;
@ -673,10 +572,8 @@ void TextField::_reallySetCursorPos(size_t pos)
rootView().window()->claimKeyboardFocus(focusRect); rootView().window()->claimKeyboardFocus(focusRect);
} }
void TextField::_setCursorPos() void TextField::_setCursorPos() {
{ if (m_hasCursorSet) {
if (m_hasCursorSet)
{
m_hasSelectionClear = true; m_hasSelectionClear = true;
_clearSelectionRange(); _clearSelectionRange();
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
@ -688,15 +585,13 @@ void TextField::_setCursorPos()
} }
} }
void TextField::setCursorPos(size_t pos) void TextField::setCursorPos(size_t pos) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
m_deferredCursorPos = pos; m_deferredCursorPos = pos;
m_hasCursorSet = true; m_hasCursorSet = true;
} }
void TextField::setErrorState(std::string_view message) void TextField::setErrorState(std::string_view message) {
{
m_error = true; m_error = true;
if (m_selectionCount) if (m_selectionCount)
_reallySetSelectionRange(m_selectionStart, m_selectionCount); _reallySetSelectionRange(m_selectionStart, m_selectionCount);
@ -711,8 +606,7 @@ void TextField::setErrorState(std::string_view message)
m_errorFrames = 0; m_errorFrames = 0;
} }
void TextField::clearErrorState() void TextField::clearErrorState() {
{
m_error = false; m_error = false;
if (m_selectionCount) if (m_selectionCount)
_reallySetSelectionRange(m_selectionStart, m_selectionCount); _reallySetSelectionRange(m_selectionStart, m_selectionCount);
@ -723,8 +617,7 @@ void TextField::clearErrorState()
m_errorFrames = 360; m_errorFrames = 360;
} }
void TextField::_reallySetSelectionRange(size_t start, size_t len) void TextField::_reallySetSelectionRange(size_t start, size_t len) {
{
ViewResources& res = rootView().viewRes(); ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor(); float pf = res.pixelFactor();
int offset1 = 5 * pf; int offset1 = 5 * pf;
@ -733,11 +626,9 @@ void TextField::_reallySetSelectionRange(size_t start, size_t len)
offset1 += glyphs[start].m_pos[0][0]; offset1 += glyphs[start].m_pos[0][0];
offset2 += glyphs[start + len - 1].m_pos[2][0]; offset2 += glyphs[start + len - 1].m_pos[2][0];
const zeus::CColor& selColor = rootView().themeData().selectedFieldText(); const zeus::CColor& selColor = rootView().themeData().selectedFieldText();
const zeus::CColor& deselColor = m_error ? rootView().themeData().uiText() : const zeus::CColor& deselColor = m_error ? rootView().themeData().uiText() : rootView().themeData().fieldText();
rootView().themeData().fieldText();
for (size_t i=0 ; i<glyphs.size() ; ++i) for (size_t i = 0; i < glyphs.size(); ++i) {
{
if (i >= start && i < start + len) if (i >= start && i < start + len)
glyphs[i].m_color = selColor; glyphs[i].m_color = selColor;
else else
@ -755,8 +646,7 @@ void TextField::_reallySetSelectionRange(size_t start, size_t len)
rootView().window()->claimKeyboardFocus(focusRect); rootView().window()->claimKeyboardFocus(focusRect);
} }
void TextField::_reallySetMarkRange(size_t start, size_t len) void TextField::_reallySetMarkRange(size_t start, size_t len) {
{
ViewResources& res = rootView().viewRes(); ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor(); float pf = res.pixelFactor();
int offset1 = 5 * pf; int offset1 = 5 * pf;
@ -780,10 +670,8 @@ void TextField::_reallySetMarkRange(size_t start, size_t len)
rootView().window()->claimKeyboardFocus(focusRect); rootView().window()->claimKeyboardFocus(focusRect);
} }
void TextField::_setSelectionRange() void TextField::_setSelectionRange() {
{ if (m_hasSelectionSet) {
if (m_hasSelectionSet)
{
std::string_view textStr(m_textStr); std::string_view textStr(m_textStr);
size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend()); size_t len = UTF8Iterator(textStr.cbegin()).countTo(textStr.cend());
m_selectionStart = std::min(m_deferredSelectionStart, len - 1); m_selectionStart = std::min(m_deferredSelectionStart, len - 1);
@ -795,12 +683,10 @@ void TextField::_setSelectionRange()
} }
} }
void TextField::setSelectionRange(size_t start, size_t count) void TextField::setSelectionRange(size_t start, size_t count) {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
if (!count) if (!count) {
{
setCursorPos(start); setCursorPos(start);
return; return;
} }
@ -811,15 +697,12 @@ void TextField::setSelectionRange(size_t start, size_t count)
m_hasSelectionClear = false; m_hasSelectionClear = false;
} }
void TextField::_clearSelectionRange() void TextField::_clearSelectionRange() {
{ if (m_hasSelectionClear) {
if (m_hasSelectionClear)
{
m_selectionStart = 0; m_selectionStart = 0;
m_selectionCount = 0; m_selectionCount = 0;
const zeus::CColor& deselColor = m_error ? rootView().themeData().uiText() : const zeus::CColor& deselColor = m_error ? rootView().themeData().uiText() : rootView().themeData().fieldText();
rootView().themeData().fieldText();
std::vector<TextView::RenderGlyph>& glyphs = m_text->accessGlyphs(); std::vector<TextView::RenderGlyph>& glyphs = m_text->accessGlyphs();
for (size_t i = 0; i < glyphs.size(); ++i) for (size_t i = 0; i < glyphs.size(); ++i)
@ -830,8 +713,7 @@ void TextField::_clearSelectionRange()
} }
} }
void TextField::clearSelectionRange() void TextField::clearSelectionRange() {
{
std::unique_lock<std::recursive_mutex> lk(m_textInputLk); std::unique_lock<std::recursive_mutex> lk(m_textInputLk);
m_deferredSelectionStart = 0; m_deferredSelectionStart = 0;
m_deferredSelectionCount = 0; m_deferredSelectionCount = 0;
@ -839,8 +721,7 @@ void TextField::clearSelectionRange()
m_hasSelectionSet = false; m_hasSelectionSet = false;
} }
void TextField::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void TextField::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int width = sub.size[0]; int width = sub.size[0];
int height = 20 * pf; int height = 20 * pf;
@ -881,8 +762,7 @@ void TextField::resized(const boo::SWindowRect& root, const boo::SWindowRect& su
m_verts[26].m_pos.assign(width + 1, 1, 0); m_verts[26].m_pos.assign(width + 1, 1, 0);
m_verts[27].m_pos.assign(width + 1, 0, 0); m_verts[27].m_pos.assign(width + 1, 0, 0);
if (m_error) if (m_error) {
{
boo::SWindowRect errRect = sub; boo::SWindowRect errRect = sub;
errRect.location[1] -= 16 * pf; errRect.location[1] -= 16 * pf;
errRect.location[0] += 5 * pf; errRect.location[0] += 5 * pf;
@ -916,24 +796,19 @@ void TextField::resized(const boo::SWindowRect& root, const boo::SWindowRect& su
m_text->resized(root, textRect); m_text->resized(root, textRect);
} }
void TextField::draw(boo::IGraphicsCommandQueue* gfxQ) void TextField::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 28); gfxQ->draw(0, 28);
if (m_active) if (m_active) {
{ if (!m_selectionCount && !m_markSelCount) {
if (!m_selectionCount && !m_markSelCount)
{
if (m_cursorFrames % 60 < 30) if (m_cursorFrames % 60 < 30)
gfxQ->draw(28, 4); gfxQ->draw(28, 4);
} } else
else
gfxQ->draw(28, 4); gfxQ->draw(28, 4);
} }
if (m_error) if (m_error) {
{
gfxQ->draw(32, 9); gfxQ->draw(32, 9);
m_errText->draw(gfxQ); m_errText->draw(gfxQ);
} }
@ -941,4 +816,4 @@ void TextField::draw(boo::IGraphicsCommandQueue* gfxQ)
m_text->draw(gfxQ); m_text->draw(gfxQ);
} }
} } // namespace specter

View File

@ -7,27 +7,22 @@
#include <freetype/internal/internal.h> #include <freetype/internal/internal.h>
#include <freetype/internal/ftobjs.h> #include <freetype/internal/ftobjs.h>
namespace specter namespace specter {
{
static logvisor::Module Log("specter::TextView"); static logvisor::Module Log("specter::TextView");
void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache) void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache) {
{
m_fcache = fcache; m_fcache = fcache;
m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{}); m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{});
m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{}); m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{});
} }
void TextView::_commitResources(size_t capacity) void TextView::_commitResources(size_t capacity) {
{
auto& res = rootView().viewRes(); auto& res = rootView().viewRes();
auto fontTex = m_fontAtlas.texture(res.m_factory); auto fontTex = m_fontAtlas.texture(res.m_factory);
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
{
buildResources(ctx, res); buildResources(ctx, res);
if (capacity) if (capacity) {
{
m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity); m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
boo::ObjToken<boo::IShaderPipeline> shader; boo::ObjToken<boo::IShaderPipeline> shader;
@ -43,25 +38,18 @@ void TextView::_commitResources(size_t capacity)
size_t uBufSizes[] = {sizeof(ViewBlock)}; size_t uBufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()}; boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()};
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, uBufs, nullptr, uBufOffs,
uBufs, nullptr, uBufOffs, uBufSizes, uBufSizes, 1, texs, nullptr, nullptr, 0, vBufInfo.second);
1, texs, nullptr, nullptr, 0, vBufInfo.second);
} }
return true; return true;
}); });
} }
TextView::TextView(ViewResources& res, TextView::TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align, size_t capacity)
View& parentView, const FontAtlas& font, : View(res, parentView), m_capacity(capacity), m_fontAtlas(font), m_align(align) {
Alignment align, size_t capacity)
: View(res, parentView),
m_capacity(capacity),
m_fontAtlas(font),
m_align(align)
{
if (size_t(hecl::VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity) if (size_t(hecl::VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity)
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]", Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]", capacity,
capacity, hecl::VertexBufferPool<RenderGlyph>::bucketCapacity()); hecl::VertexBufferPool<RenderGlyph>::bucketCapacity());
_commitResources(0); _commitResources(0);
} }
@ -69,8 +57,7 @@ TextView::TextView(ViewResources& res,
TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity) TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity)
: TextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {} : TextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {}
TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor) TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor) {
{
m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f); m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f);
m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f); m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f);
m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f); m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f);
@ -83,9 +70,9 @@ TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, cons
adv += glyph.m_advance; adv += glyph.m_advance;
} }
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) {
{ if (!val)
if (!val) return 0; return 0;
val = FT_MulFix(val, atlas.FT_Xscale()); val = FT_MulFix(val, atlas.FT_Xscale());
FT_Pos orig_x = val; FT_Pos orig_x = val;
@ -99,12 +86,10 @@ int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
return FT_PIX_ROUND(val) >> 6; return FT_PIX_ROUND(val) >> 6;
} }
void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor) void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor) {
{
UTF8Iterator it(str.begin()); UTF8Iterator it(str.begin());
size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0; size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0;
if (charLen > m_curSize) if (charLen > m_curSize) {
{
m_curSize = charLen; m_curSize = charLen;
_commitResources(charLen); _commitResources(charLen);
} }
@ -116,13 +101,10 @@ void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultCo
m_glyphInfo.reserve(charLen); m_glyphInfo.reserve(charLen);
int adv = 0; int adv = 0;
if (charLen) if (charLen) {
{ for (; it.iter() < str.end(); ++it) {
for (; it.iter() < str.end() ; ++it)
{
utf8proc_int32_t ch = *it; utf8proc_int32_t ch = *it;
if (ch == -1) if (ch == -1) {
{
Log.report(logvisor::Warning, "invalid UTF-8 char"); Log.report(logvisor::Warning, "invalid UTF-8 char");
break; break;
} }
@ -145,22 +127,17 @@ void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultCo
} }
} }
if (m_align == Alignment::Right) if (m_align == Alignment::Right) {
{
int adj = -adv; int adj = -adv;
for (RenderGlyph& g : m_glyphs) for (RenderGlyph& g : m_glyphs) {
{
g.m_pos[0][0] += adj; g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj; g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj; g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj; g.m_pos[3][0] += adj;
} }
} } else if (m_align == Alignment::Center) {
else if (m_align == Alignment::Center)
{
int adj = -adv / 2; int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs) for (RenderGlyph& g : m_glyphs) {
{
g.m_pos[0][0] += adj; g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj; g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj; g.m_pos[2][0] += adj;
@ -173,11 +150,9 @@ void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultCo
updateSize(); updateSize();
} }
void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor) void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor) {
{
size_t charLen = std::min(str.size(), m_capacity); size_t charLen = std::min(str.size(), m_capacity);
if (charLen > m_curSize) if (charLen > m_curSize) {
{
m_curSize = charLen; m_curSize = charLen;
_commitResources(charLen); _commitResources(charLen);
} }
@ -189,8 +164,7 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
m_glyphInfo.reserve(charLen); m_glyphInfo.reserve(charLen);
int adv = 0; int adv = 0;
for (wchar_t ch : str) for (wchar_t ch : str) {
{
if (ch == L'\n') if (ch == L'\n')
break; break;
@ -209,22 +183,17 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
break; break;
} }
if (m_align == Alignment::Right) if (m_align == Alignment::Right) {
{
int adj = -adv; int adj = -adv;
for (RenderGlyph& g : m_glyphs) for (RenderGlyph& g : m_glyphs) {
{
g.m_pos[0][0] += adj; g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj; g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj; g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj; g.m_pos[3][0] += adj;
} }
} } else if (m_align == Alignment::Center) {
else if (m_align == Alignment::Center)
{
int adj = -adv / 2; int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs) for (RenderGlyph& g : m_glyphs) {
{
g.m_pos[0][0] += adj; g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj; g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj; g.m_pos[2][0] += adj;
@ -237,21 +206,16 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
updateSize(); updateSize();
} }
void TextView::colorGlyphs(const zeus::CColor& newColor) void TextView::colorGlyphs(const zeus::CColor& newColor) {
{
for (RenderGlyph& glyph : m_glyphs) for (RenderGlyph& glyph : m_glyphs)
glyph.m_color = newColor; glyph.m_color = newColor;
invalidateGlyphs(); invalidateGlyphs();
} }
void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval, float fadeTime) void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval, float fadeTime) {}
{
}
void TextView::invalidateGlyphs() void TextView::invalidateGlyphs() {
{ if (m_glyphBuf) {
if (m_glyphBuf)
{
RenderGlyph* out = m_glyphBuf.access(); RenderGlyph* out = m_glyphBuf.access();
size_t i = 0; size_t i = 0;
for (RenderGlyph& glyph : m_glyphs) for (RenderGlyph& glyph : m_glyphs)
@ -259,45 +223,33 @@ void TextView::invalidateGlyphs()
} }
} }
void TextView::think() void TextView::think() {}
{
}
void TextView::resized(const boo::SWindowRect &root, const boo::SWindowRect& sub) void TextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { View::resized(root, sub); }
{
View::resized(root, sub);
}
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ) void TextView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
if (m_glyphs.size()) if (m_glyphs.size()) {
{
gfxQ->setShaderDataBinding(m_shaderBinding); gfxQ->setShaderDataBinding(m_shaderBinding);
gfxQ->drawInstances(0, 4, m_glyphs.size()); gfxQ->drawInstances(0, 4, m_glyphs.size());
} }
} }
std::pair<int,int> TextView::queryGlyphDimensions(size_t pos) const std::pair<int, int> TextView::queryGlyphDimensions(size_t pos) const {
{
if (pos >= m_glyphInfo.size()) if (pos >= m_glyphInfo.size())
Log.report(logvisor::Fatal, Log.report(logvisor::Fatal, "TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize, pos,
"TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize, m_glyphInfo.size());
pos, m_glyphInfo.size());
return m_glyphInfo[pos].m_dims; return m_glyphInfo[pos].m_dims;
} }
size_t TextView::reverseSelectGlyph(int x) const size_t TextView::reverseSelectGlyph(int x) const {
{
size_t ret = 0; size_t ret = 0;
size_t idx = 1; size_t idx = 1;
int minDelta = abs(x); int minDelta = abs(x);
for (const RenderGlyphInfo& info : m_glyphInfo) for (const RenderGlyphInfo& info : m_glyphInfo) {
{
int thisDelta = abs(info.m_adv - x); int thisDelta = abs(info.m_adv - x);
if (thisDelta < minDelta) if (thisDelta < minDelta) {
{
minDelta = thisDelta; minDelta = thisDelta;
ret = idx; ret = idx;
} }
@ -306,22 +258,19 @@ size_t TextView::reverseSelectGlyph(int x) const
return ret; return ret;
} }
int TextView::queryReverseAdvance(size_t idx) const int TextView::queryReverseAdvance(size_t idx) const {
{
if (idx > m_glyphInfo.size()) if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal, Log.report(logvisor::Fatal, "TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
"TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize, m_glyphInfo.size());
idx, m_glyphInfo.size()); if (!idx)
if (!idx) return 0; return 0;
return m_glyphInfo[idx - 1].m_adv; return m_glyphInfo[idx - 1].m_adv;
} }
std::pair<size_t,size_t> TextView::queryWholeWordRange(size_t idx) const std::pair<size_t, size_t> TextView::queryWholeWordRange(size_t idx) const {
{
if (idx > m_glyphInfo.size()) if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal, Log.report(logvisor::Fatal, "TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
"TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize, m_glyphInfo.size());
idx, m_glyphInfo.size());
if (m_glyphInfo.empty()) if (m_glyphInfo.empty())
return {0, 0}; return {0, 0};
@ -339,4 +288,4 @@ std::pair<size_t,size_t> TextView::queryWholeWordRange(size_t idx) const
return {begin, end - begin}; return {begin, end - begin};
} }
} } // namespace specter

View File

@ -5,33 +5,24 @@
#define TOOLBAR_PADDING 10 #define TOOLBAR_PADDING 10
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Space"); static logvisor::Module Log("specter::Space");
static const zeus::RGBA32 Tex[] = static const zeus::RGBA32 Tex[] = {{{255, 255, 255, 64}}, {{255, 255, 255, 64}}, {{0, 0, 0, 64}}, {{0, 0, 0, 64}}};
{
{{255,255,255,64}},
{{255,255,255,64}},
{{0,0,0,64}},
{{0,0,0,64}}
};
void Toolbar::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void Toolbar::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{
m_shadingTex = ctx.newStaticTexture(4, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 16); m_shadingTex = ctx.newStaticTexture(4, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 16);
} }
Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units) Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units)
: View(res, parentView), m_units(units), : View(res, parentView)
m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units), , m_units(units)
m_padding(res.pixelFactor() * TOOLBAR_PADDING) , m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units)
{ , m_padding(res.pixelFactor() * TOOLBAR_PADDING) {
m_children.reserve(units); m_children.reserve(units);
for (unsigned u = 0; u < units; ++u) for (unsigned u = 0; u < units; ++u)
m_children.emplace_back(); m_children.emplace_back();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
buildResources(ctx, res); buildResources(ctx, res);
m_tbBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_tbBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 10, m_tbBlockBuf, res.m_toolbarRes.m_shadingTex.get()); m_vertsBinding.init(ctx, res, 10, m_tbBlockBuf, res.m_toolbarRes.m_shadingTex.get());
@ -40,43 +31,37 @@ Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned
setBackground(res.themeData().toolbarBackground()); setBackground(res.themeData().toolbarBackground());
} }
void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
c.mouseDown(coord, button, mod); c.mouseDown(coord, button, mod);
} }
void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
c.mouseUp(coord, button, mod); c.mouseUp(coord, button, mod);
} }
void Toolbar::mouseMove(const boo::SWindowCoord& coord) void Toolbar::mouseMove(const boo::SWindowCoord& coord) {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
c.mouseMove(coord); c.mouseMove(coord);
} }
void Toolbar::mouseEnter(const boo::SWindowCoord& coord) void Toolbar::mouseEnter(const boo::SWindowCoord& coord) {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
c.mouseEnter(coord); c.mouseEnter(coord);
} }
void Toolbar::mouseLeave(const boo::SWindowCoord& coord) void Toolbar::mouseLeave(const boo::SWindowCoord& coord) {
{
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u)
c.mouseLeave(coord); c.mouseLeave(coord);
} }
void Toolbar::setHorizontalVerts(int width) void Toolbar::setHorizontalVerts(int width) {
{
m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0); m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0);
m_tbVerts[0].m_uv.assign(0, 0); m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 0); m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 0);
@ -100,8 +85,7 @@ void Toolbar::setHorizontalVerts(int width)
m_tbVerts[9].m_uv.assign(1, 0); m_tbVerts[9].m_uv.assign(1, 0);
} }
void Toolbar::setVerticalVerts(int height) void Toolbar::setVerticalVerts(int height) {
{
m_tbVerts[0].m_pos.assign(-1, height, 0); m_tbVerts[0].m_pos.assign(-1, height, 0);
m_tbVerts[0].m_uv.assign(0, 0); m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(-1, 0, 0); m_tbVerts[1].m_pos.assign(-1, 0, 0);
@ -125,8 +109,7 @@ void Toolbar::setVerticalVerts(int height)
m_tbVerts[9].m_uv.assign(1, 0); m_tbVerts[9].m_uv.assign(1, 0);
} }
void Toolbar::push_back(View* v, unsigned unit) void Toolbar::push_back(View* v, unsigned unit) {
{
if (unit >= m_units) if (unit >= m_units)
Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units); Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units);
std::vector<ViewChild<View*>>& u = m_children[unit]; std::vector<ViewChild<View*>>& u = m_children[unit];
@ -134,8 +117,7 @@ void Toolbar::push_back(View* v, unsigned unit)
u.back().m_view = v; u.back().m_view = v;
} }
void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
setHorizontalVerts(sub.size[0]); setHorizontalVerts(sub.size[0]);
m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts); m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts);
@ -144,15 +126,13 @@ void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE; float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE;
float yOff = 0.0; float yOff = 0.0;
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children) {
{
boo::SWindowRect childRect = sub; boo::SWindowRect childRect = sub;
boo::SWindowRect containRect = sub; boo::SWindowRect containRect = sub;
containRect.location[0] += m_padding; containRect.location[0] += m_padding;
containRect.size[0] -= m_padding * 2; containRect.size[0] -= m_padding * 2;
containRect.size[1] = gaugeUnit; containRect.size[1] = gaugeUnit;
for (ViewChild<View*>& c : u) for (ViewChild<View*>& c : u) {
{
c.m_view->containerResized(root, containRect); c.m_view->containerResized(root, containRect);
childRect.size[0] = c.m_view->nominalWidth(); childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight(); childRect.size[1] = c.m_view->nominalHeight();
@ -169,8 +149,7 @@ void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
} }
} }
void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ) void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
View::draw(gfxQ); View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 10); gfxQ->draw(0, 10);
@ -180,5 +159,4 @@ void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ)
c.m_view->draw(gfxQ); c.m_view->draw(gfxQ);
} }
} } // namespace specter

View File

@ -2,29 +2,24 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
#define TOOLTIP_MAX_WIDTH 316 #define TOOLTIP_MAX_WIDTH 316
#define TOOLTIP_MAX_TEXT_WIDTH 300 #define TOOLTIP_MAX_TEXT_WIDTH 300
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view message)
std::string_view message) : View(res, parentView), m_titleStr(title), m_messageStr(message) {
: View(res, parentView), m_titleStr(title), m_messageStr(message)
{
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
m_ttVerts[i].m_color = res.themeData().tooltipBackground(); m_ttVerts[i].m_color = res.themeData().tooltipBackground();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{
buildResources(ctx, res); buildResources(ctx, res);
m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf); m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf);
return true; return true;
}); });
for (int i=0 ; i<4 ; ++i) for (int i = 0; i < 4; ++i) {
{
m_cornersOutline[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1)); m_cornersOutline[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1));
m_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1)); m_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1));
} }
@ -40,8 +35,7 @@ Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title,
m_title.reset(new TextView(res, *this, res.m_heading14)); m_title.reset(new TextView(res, *this, res.m_heading14));
m_title->typesetGlyphs(m_titleStr); m_title->typesetGlyphs(m_titleStr);
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont)); m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
float pf = res.pixelFactor(); float pf = res.pixelFactor();
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
@ -50,8 +44,7 @@ Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title,
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3; m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3;
} }
void Tooltip::setVerts(int width, int height, float pf) void Tooltip::setVerts(int width, int height, float pf) {
{
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
width = std::max(width, margin.first * 2); width = std::max(width, margin.first * 2);
height = std::max(height, margin.second * 2); height = std::max(height, margin.second * 2);
@ -78,8 +71,7 @@ void Tooltip::setVerts(int width, int height, float pf)
m_vertsBinding.load<decltype(m_ttVerts)>(m_ttVerts); m_vertsBinding.load<decltype(m_ttVerts)>(m_ttVerts);
} }
void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
View::resized(root, sub); View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
setVerts(m_nomWidth, m_nomHeight, pf); setVerts(m_nomWidth, m_nomHeight, pf);
@ -111,8 +103,7 @@ void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
m_cornersFilled[3]->resized(root, cornerRect); m_cornersFilled[3]->resized(root, cornerRect);
} }
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) {
{
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 16); gfxQ->draw(0, 16);
@ -123,4 +114,4 @@ void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ)
m_message->draw(gfxQ); m_message->draw(gfxQ);
} }
} } // namespace specter

View File

@ -1,43 +1,33 @@
#include "specter/Translator.hpp" #include "specter/Translator.hpp"
#include "logvisor/logvisor.hpp" #include "logvisor/logvisor.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Translator"); static logvisor::Module Log("specter::Translator");
Locale::Locale(std::string_view name, std::string_view fullName, Locale::Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength)
const unsigned char* yamlSource, size_t yamlLength) : m_name(name), m_fullName(fullName) {
: m_name(name), m_fullName(fullName)
{
athena::io::YAMLDocReader reader; athena::io::YAMLDocReader reader;
yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength); yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength);
reader.parse(nullptr); reader.parse(nullptr);
m_rootNode = reader.releaseRootNode(); m_rootNode = reader.releaseRootNode();
if (m_rootNode) if (m_rootNode) {
{
m_langNode = m_rootNode->findMapChild(name.data()); m_langNode = m_rootNode->findMapChild(name.data());
if (!m_langNode) if (!m_langNode)
Log.report(logvisor::Fatal, "no root node '%s' found in locale", name.data()); Log.report(logvisor::Fatal, "no root node '%s' found in locale", name.data());
} } else
else
Log.report(logvisor::Warning, "locale empty"); Log.report(logvisor::Warning, "locale empty");
} }
void Translator::setLocale(const Locale* targetLocale) void Translator::setLocale(const Locale* targetLocale) {
{
if (!targetLocale) if (!targetLocale)
Log.report(logvisor::Fatal, "null locale"); Log.report(logvisor::Fatal, "null locale");
m_targetLocale = targetLocale; m_targetLocale = targetLocale;
} }
static std::string_view RecursiveLookup(const athena::io::YAMLNode* node, static std::string_view RecursiveLookup(const athena::io::YAMLNode* node, std::string_view::const_iterator start,
std::string_view::const_iterator start, std::string_view::const_iterator end) {
std::string_view::const_iterator end) for (std::string_view::const_iterator it = start; it != end; ++it) {
{ if (*it == '/') {
for (std::string_view::const_iterator it = start ; it != end ; ++it)
{
if (*it == '/')
{
const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, it)); const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, it));
if (!ch) if (!ch)
return nullptr; return nullptr;
@ -50,20 +40,18 @@ static std::string_view RecursiveLookup(const athena::io::YAMLNode* node,
return ch->m_scalarString; return ch->m_scalarString;
} }
std::string_view Translator::translate(std::string_view key) const std::string_view Translator::translate(std::string_view key) const {
{
if (!m_targetLocale->rootNode()) if (!m_targetLocale->rootNode())
return nullptr; return nullptr;
return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend()); return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend());
} }
std::string_view Translator::translateOr(std::string_view key, std::string_view vor) const std::string_view Translator::translateOr(std::string_view key, std::string_view vor) const {
{
std::string_view find = translate(key); std::string_view find = translate(key);
if (!find.empty()) if (!find.empty())
return find; return find;
return vor; return vor;
} }
} } // namespace specter

View File

@ -3,16 +3,13 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "hecl/Pipeline.hpp" #include "hecl/Pipeline.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::View"); static logvisor::Module Log("specter::View");
zeus::CMatrix4f g_PlatformMatrix; zeus::CMatrix4f g_PlatformMatrix;
void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{ switch (ctx.platform()) {
switch (ctx.platform())
{
case boo::IGraphicsDataFactory::Platform::Vulkan: case boo::IGraphicsDataFactory::Platform::Vulkan:
g_PlatformMatrix.m[1][1] = -1.f; g_PlatformMatrix.m[1][1] = -1.f;
break; break;
@ -23,27 +20,19 @@ void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const ITheme
m_texShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderTex{}); m_texShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderTex{});
} }
void View::buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res) void View::buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res) {
{
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf); m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
} }
View::View(ViewResources& res) View::View(ViewResources& res)
: m_rootView(*static_cast<RootView*>(this)), : m_rootView(*static_cast<RootView*>(this)), m_parentView(*static_cast<RootView*>(this)) {}
m_parentView(*static_cast<RootView*>(this)) {}
View::View(ViewResources& res, View& parentView) View::View(ViewResources& res, View& parentView) : m_rootView(parentView.rootView()), m_parentView(parentView) {}
: m_rootView(parentView.rootView()),
m_parentView(parentView) {}
void View::updateSize() void View::updateSize() { resized(m_rootView.rootRect(), m_subRect); }
{
resized(m_rootView.rootRect(), m_subRect);
}
void View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{
m_subRect = sub; m_subRect = sub;
m_viewVertBlock.setViewRect(root, sub); m_viewVertBlock.setViewRect(root, sub);
m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f); m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f);
@ -55,8 +44,7 @@ void View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect); m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub) void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub) {
{
m_subRect = sub; m_subRect = sub;
m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f); m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f);
m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f); m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f);
@ -67,24 +55,19 @@ void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub)
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect); m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
void View::draw(boo::IGraphicsCommandQueue* gfxQ) void View::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ if (m_bgVertsBinding.m_shaderBinding) {
if (m_bgVertsBinding.m_shaderBinding)
{
gfxQ->setShaderDataBinding(m_bgVertsBinding); gfxQ->setShaderDataBinding(m_bgVertsBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
} }
} }
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc) void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc) {
{
res.m_factory->commitTransaction(commitFunc BooTrace); res.m_factory->commitTransaction(commitFunc BooTrace);
} }
void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx, void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
ViewResources& res, size_t count, const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf) {
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf)
{
m_vertsBuf = res.m_viewRes.m_solidPool.allocateBlock(res.m_factory, count); m_vertsBuf = res.m_viewRes.m_solidPool.allocateBlock(res.m_factory, count);
auto vBufInfo = m_vertsBuf.getBufferInfo(); auto vBufInfo = m_vertsBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo(); auto uBufInfo = viewBlockBuf.getBufferInfo();
@ -93,17 +76,14 @@ void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ct
size_t bufOffs[] = {size_t(uBufInfo.second)}; size_t bufOffs[] = {size_t(uBufInfo.second)};
size_t bufSizes[] = {sizeof(ViewBlock)}; size_t bufSizes[] = {sizeof(ViewBlock)};
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_solidShader, m_shaderBinding =
vBufInfo.first.get(), nullptr, ctx.newShaderDataBinding(res.m_viewRes.m_solidShader, vBufInfo.first.get(), nullptr, nullptr, 1, bufs, nullptr,
nullptr, 1, bufs, nullptr, bufOffs, bufOffs, bufSizes, 0, nullptr, nullptr, nullptr, vBufInfo.second);
bufSizes, 0, nullptr, nullptr, nullptr, vBufInfo.second);
} }
void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx, void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf, const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture) const boo::ObjToken<boo::ITexture>& texture) {
{
m_vertsBuf = res.m_viewRes.m_texPool.allocateBlock(res.m_factory, count); m_vertsBuf = res.m_viewRes.m_texPool.allocateBlock(res.m_factory, count);
auto vBufInfo = m_vertsBuf.getBufferInfo(); auto vBufInfo = m_vertsBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo(); auto uBufInfo = viewBlockBuf.getBufferInfo();
@ -113,11 +93,8 @@ void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx,
size_t bufSizes[] = {sizeof(ViewBlock)}; size_t bufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> tex[] = {texture}; boo::ObjToken<boo::ITexture> tex[] = {texture};
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader, m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader, vBufInfo.first.get(), nullptr, nullptr, 1, bufs,
vBufInfo.first.get(), nullptr, nullptr, bufOffs, bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
nullptr, 1, bufs, nullptr, bufOffs,
bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
} }
} // namespace specter
}

View File

@ -1,11 +1,9 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::ViewResources"); static logvisor::Module Log("specter::ViewResources");
void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pf) void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pf) {
{
if (!factory || !fcache || !theme) if (!factory || !fcache || !theme)
Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null"); Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null");
m_pixelFactor = pf; m_pixelFactor = pf;
@ -22,8 +20,7 @@ void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache,
} BooTrace); } BooTrace);
} }
void ViewResources::destroyResData() void ViewResources::destroyResData() {
{
m_viewRes.destroy(); m_viewRes.destroy();
m_textRes.destroy(); m_textRes.destroy();
m_splitRes.destroy(); m_splitRes.destroy();
@ -31,8 +28,7 @@ void ViewResources::destroyResData()
m_buttonRes.destroy(); m_buttonRes.destroy();
} }
void ViewResources::prepFontCacheSync() void ViewResources::prepFontCacheSync() {
{
unsigned dpi = 72.f * m_pixelFactor; unsigned dpi = 72.f * m_pixelFactor;
if (m_fcacheInterrupt.load()) if (m_fcacheInterrupt.load())
return; return;
@ -58,14 +54,12 @@ void ViewResources::prepFontCacheSync()
m_fcacheReady.store(true); m_fcacheReady.store(true);
} }
void ViewResources::prepFontCacheAsync(boo::IWindow* window) void ViewResources::prepFontCacheAsync(boo::IWindow* window) {
{
m_fcacheReady.store(false); m_fcacheReady.store(false);
m_fcacheThread = std::thread([this]() { prepFontCacheSync(); }); m_fcacheThread = std::thread([this]() { prepFontCacheSync(); });
} }
void ViewResources::resetPixelFactor(float pf) void ViewResources::resetPixelFactor(float pf) {
{
m_pixelFactor = pf; m_pixelFactor = pf;
unsigned dpi = 72.f * m_pixelFactor; unsigned dpi = 72.f * m_pixelFactor;
m_curveFont = m_fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi); m_curveFont = m_fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi);

@ -1 +1 @@
Subproject commit e8dfecbb6e60dd79e01b62645ac8cf967cfd0a59 Subproject commit e172225845f7e683e40d809f60c6677b289adc64