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/Icon.hpp"
namespace specter
{
namespace specter {
class Button : public Control
{
class Button : public Control {
public:
enum class Style
{
enum class Style {
Block,
Text,
};
@ -28,17 +25,13 @@ private:
SolidShaderVert m_verts[40];
VertexBufferBindingSolid m_vertsBinding;
void _loadVerts()
{
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
void _loadVerts() { m_vertsBinding.load<decltype(m_verts)>(m_verts); }
RectangleConstraint m_constraint;
int m_nomWidth, m_nomHeight;
int m_textWidth, m_textIconWidth;
struct ButtonTarget : View
{
struct ButtonTarget : View {
Button& m_button;
bool m_pressed = false;
@ -57,8 +50,7 @@ private:
};
ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget;
struct MenuTarget : View
{
struct MenuTarget : View {
Button& m_button;
bool m_pressed = false;
@ -80,8 +72,7 @@ private:
ViewChild<std::unique_ptr<View>> m_modalMenu;
public:
class Resources
{
class Resources {
friend class ViewResources;
friend class Button;
@ -89,15 +80,13 @@ public:
void destroy() {}
};
~Button() {closeMenu({});}
Button(ViewResources& res, View& parentView,
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,
RectangleConstraint constraint=RectangleConstraint());
~Button() { closeMenu({}); }
Button(ViewResources& res, View& parentView, 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, RectangleConstraint constraint = RectangleConstraint());
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
@ -108,17 +97,16 @@ public:
void setText(std::string_view text, const zeus::CColor& textColor);
void setText(std::string_view text);
void setIcon(Icon* icon=nullptr);
std::string_view getText() const {return m_textStr;}
void setIcon(Icon* icon = nullptr);
std::string_view getText() const { return m_textStr; }
void colorGlyphs(const zeus::CColor& newColor);
int nominalWidth() const {return m_nomWidth;}
int nominalHeight() const {return m_nomHeight;}
int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const { return m_nomHeight; }
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);
m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf)
@ -129,5 +117,4 @@ public:
}
};
}
} // namespace specter

View File

@ -2,32 +2,23 @@
#include "View.hpp"
namespace specter
{
namespace specter {
class Control;
class Button;
enum class ControlType
{
Button,
Float,
Int,
String,
CVar
};
enum class ControlType { Button, Float, Int, String, CVar };
struct IControlBinding
{
struct IControlBinding {
virtual ControlType type() 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 name(const Control* control) const = 0;
virtual std::string_view help(const Control* control) const { return {}; }
};
struct IButtonBinding : IControlBinding
{
struct IButtonBinding : IControlBinding {
ControlType type() const { return ControlType::Button; }
static IButtonBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr; }
static IButtonBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr;
}
/** Pressed/Released while Hovering action,
* cancellable by holding the button and releasing outside */
@ -40,81 +31,77 @@ struct IButtonBinding : IControlBinding
virtual void up(const Button* button, const boo::SWindowCoord& coord) {}
/** Optional style of menu to bind to button */
enum class MenuStyle
{
enum class MenuStyle {
None, /**< No menu; normal button */
Primary, /**< Menu button replaces normal button */
Auxiliary /**< Menu button placed alongside normal button */
};
/** Informs button which MenuStyle to present to user */
virtual MenuStyle menuStyle(const specter::Button* button) const {return MenuStyle::None;}
virtual MenuStyle menuStyle(const specter::Button* button) const { return MenuStyle::None; }
/** Called when user requests menu, Button assumes modal ownership */
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; }
static IFloatBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr; }
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 void changed(const Control* control, float val)=0;
static IFloatBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr;
}
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 void changed(const Control* control, float val) = 0;
};
struct IIntBinding : IControlBinding
{
struct IIntBinding : IControlBinding {
ControlType type() const { return ControlType::Int; }
static IIntBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr; }
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 void changed(const Control* control, int val)=0;
static IIntBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr;
}
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 void changed(const Control* control, int val) = 0;
};
struct IStringBinding : IControlBinding
{
struct IStringBinding : IControlBinding {
ControlType type() const { return ControlType::String; }
static IStringBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr; }
virtual std::string getDefault(const Control* control) const {return "";}
virtual void changed(const Control* control, std::string_view val)=0;
static IStringBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr;
}
virtual std::string getDefault(const Control* control) const { return ""; }
virtual void changed(const Control* control, std::string_view val) = 0;
};
struct CVarControlBinding : IControlBinding
{
struct CVarControlBinding : IControlBinding {
hecl::CVar* m_cvar;
CVarControlBinding(hecl::CVar* cvar)
: m_cvar(cvar) {}
CVarControlBinding(hecl::CVar* cvar) : m_cvar(cvar) {}
ControlType type() const { return ControlType::CVar; }
static CVarControlBinding* castTo(IControlBinding* bind)
{ 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 help(const Control* control) const {return m_cvar->rawHelp();}
static CVarControlBinding* castTo(IControlBinding* bind) {
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 help(const Control* control) const { return m_cvar->rawHelp(); }
};
class Control : public View
{
class Control : public View {
protected:
IControlBinding* m_controlBinding = nullptr;
public:
Control(ViewResources& res, View& parentView, IControlBinding* controlBinding);
};
class ITextInputView : public Control, public boo::ITextInputCallback
{
class ITextInputView : public Control, public boo::ITextInputCallback {
protected:
static std::recursive_mutex m_textInputLk;
ITextInputView(ViewResources& res, View& parentView,
IControlBinding* controlBinding)
ITextInputView(ViewResources& res, View& parentView, IControlBinding* controlBinding)
: Control(res, parentView, controlBinding) {}
public:
virtual void clipboardCopy() {}
virtual void clipboardCut() {}
virtual void clipboardPaste() {}
};
}
} // namespace specter

View File

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

View File

@ -9,53 +9,51 @@
#include <athena/FileWriter.hpp>
#include <athena/DNA.hpp>
namespace specter
{
class FontTag
{
namespace specter {
class FontTag {
friend class FontCache;
uint64_t m_hash = 0;
FontTag(std::string_view name, bool subpixel, float points, unsigned dpi);
public:
FontTag() = default;
operator bool() const {return m_hash != 0;}
uint64_t hash() const {return m_hash;}
bool operator==(const FontTag& other) const {return m_hash == other.m_hash;}
operator bool() const { return m_hash != 0; }
uint64_t hash() const { return m_hash; }
bool operator==(const FontTag& other) const { return m_hash == other.m_hash; }
};
}
} // namespace specter
namespace std
{
template <> struct hash<specter::FontTag>
{
size_t operator() (const specter::FontTag& handle) const noexcept
{return size_t(handle.hash());}
namespace std {
template <>
struct hash<specter::FontTag> {
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_StreamRec m_comp = {};
FT_StreamRec m_decomp = {};
FT_Face m_face = nullptr;
public:
FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz);
FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete;
FreeTypeGZipMemFace& operator=(const FreeTypeGZipMemFace& other) = delete;
~FreeTypeGZipMemFace() {close();}
~FreeTypeGZipMemFace() { close(); }
void open();
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)>>;
class FontAtlas
{
class FontAtlas {
FT_Face m_face;
std::vector<uint8_t> m_texmap;
boo::ObjToken<boo::ITextureSA> m_tex;
@ -69,8 +67,7 @@ class FontAtlas
bool m_ready = false;
public:
struct Glyph
{
struct Glyph {
atUint32 m_unicodePoint;
atUint32 m_glyphIdx;
atUint32 m_layerIdx;
@ -87,15 +84,13 @@ private:
std::vector<Glyph> m_glyphs;
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
Value<atUint32> length;
Value<atUint16> coverage;
};
struct TT_KernSubHead : athena::io::DNA<athena::Big>
{
struct TT_KernSubHead : athena::io::DNA<athena::Big> {
AT_DECL_DNA
Value<atUint16> nPairs;
Value<atUint16> searchRange;
@ -103,8 +98,7 @@ private:
Value<atUint16> rangeShift;
};
struct TT_KernPair : athena::io::DNA<athena::Big>
{
struct TT_KernPair : athena::io::DNA<athena::Big> {
AT_DECL_DNA
Value<atUint16> left;
Value<atUint16> right;
@ -116,30 +110,26 @@ private:
std::unordered_map<atUint32, size_t> m_glyphLookup;
public:
FontAtlas(FT_Face face, uint32_t dpi,
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::FileWriter& writer);
FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileReader& reader);
FontAtlas(const FontAtlas& other) = delete;
FontAtlas& operator=(const FontAtlas& other) = delete;
uint32_t dpi() const {return m_dpi;}
FT_Fixed FT_Xscale() const {return m_ftXscale;}
FT_UShort FT_XPPem() const {return m_ftXPpem;}
FT_Pos FT_LineHeight() const {return m_lineHeight;}
uint32_t dpi() const { return m_dpi; }
FT_Fixed FT_Xscale() const { return m_ftXscale; }
FT_UShort FT_XPPem() const { return m_ftXPpem; }
FT_Pos FT_LineHeight() const { return m_lineHeight; }
bool isReady() const { return m_ready; }
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);
if (search == m_glyphLookup.end())
return nullptr;
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);
if (pairSearch == m_kernAdjs.cend())
return 0;
@ -154,49 +144,53 @@ extern const FCharFilter AllCharFilter;
extern const FCharFilter LatinCharFilter;
extern const FCharFilter LatinAndJapaneseCharFilter;
class FontCache
{
class FontCache {
const hecl::Runtime::FileStoreManager& m_fileMgr;
hecl::SystemString m_cacheRoot;
struct Library
{
struct Library {
FT_Library m_lib;
Library();
~Library();
operator FT_Library() {return m_lib;}
operator FT_Library() { return m_lib; }
} m_fontLib;
FreeTypeGZipMemFace m_regFace;
FreeTypeGZipMemFace m_monoFace;
FreeTypeGZipMemFace m_curvesFace;
std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
public:
FontCache(const hecl::Runtime::FileStoreManager& fileMgr);
FontCache(const FontCache& other) = delete;
FontCache& operator=(const FontCache& other) = delete;
FontTag prepCustomFont(std::string_view name, FT_Face face,
FCharFilter filter=AllCharFilter, bool subpixel=false,
float points=10.0, uint32_t dpi=72);
FontTag prepCustomFont(std::string_view name, FT_Face face, FCharFilter filter = AllCharFilter, bool subpixel = false,
float points = 10.0, uint32_t dpi = 72);
FontTag prepMainFont(FCharFilter filter=AllCharFilter,
bool subpixel=false, float points=10.0, uint32_t dpi=72)
{return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);}
FontTag prepMainFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
uint32_t dpi = 72) {
return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);
}
FontTag prepMonoFont(FCharFilter filter=AllCharFilter,
bool subpixel=false, float points=10.0, uint32_t dpi=72)
{return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);}
FontTag prepMonoFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
uint32_t dpi = 72) {
return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);
}
FontTag prepCurvesFont(FCharFilter filter=AllCharFilter,
bool subpixel=false, float points=10.0, uint32_t dpi=72)
{return prepCustomFont("spectercurves", m_curvesFace, filter, subpixel, points, dpi);}
FontTag prepCurvesFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
uint32_t dpi = 72) {
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;
void destroyAtlases() {m_cachedAtlases.clear();}
void destroyAtlases() { m_cachedAtlases.clear(); }
};
}
} // namespace specter

View File

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

View File

@ -4,16 +4,13 @@
#include "SplitView.hpp"
#include <hecl/hecl.hpp>
namespace specter
{
namespace specter {
struct ISpaceController;
struct IViewManager
{
struct IViewManager {
public:
virtual const Translator* getTranslator() const {return nullptr;}
virtual std::string_view translateOr(std::string_view key, std::string_view vor) const
{
virtual const Translator* getTranslator() const { return nullptr; }
virtual std::string_view translateOr(std::string_view key, std::string_view vor) const {
const Translator* trans = getTranslator();
if (trans)
return trans->translateOr(key, vor);
@ -23,12 +20,11 @@ public:
virtual void deferSpaceSplit(ISpaceController* split, SplitView::Axis axis, int thisSlot,
const boo::SWindowCoord& coord) {}
virtual const std::vector<hecl::SystemString>* recentProjects() const {return nullptr;}
virtual const std::vector<hecl::SystemString>* recentProjects() const { return nullptr; }
virtual void pushRecentProject(hecl::SystemStringView path) {}
virtual const std::vector<hecl::SystemString>* recentFiles() const {return nullptr;}
virtual const std::vector<hecl::SystemString>* recentFiles() const { return nullptr; }
virtual void pushRecentFile(hecl::SystemStringView path) {}
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

@ -3,19 +3,10 @@
#include <specter/View.hpp>
#include <specter/MultiLineTextView.hpp>
namespace specter
{
class ModalWindow : public View
{
namespace specter {
class ModalWindow : public View {
public:
enum class Phase
{
BuildIn,
ResWait,
Showing,
BuildOut,
Done
};
enum class Phase { BuildIn, ResWait, Showing, BuildOut, Done };
private:
int m_frame = 0;
@ -36,10 +27,8 @@ private:
ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewBlockBuf;
union
{
struct
{
union {
struct {
SolidShaderVert lineVerts[22];
SolidShaderVert fillVerts[16];
} m_verts;
@ -54,31 +43,26 @@ private:
void setFillColors(float t);
VertexBufferBindingSolid m_vertsBinding;
void _loadVerts()
{
m_vertsBinding.load<decltype(_m_verts)>(_m_verts);
}
void _loadVerts() { m_vertsBinding.load<decltype(_m_verts)>(_m_verts); }
std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4];
protected:
virtual void updateContentOpacity(float opacity) {}
RectangleConstraint& constraint() {return m_constraint;}
RectangleConstraint& constraint() { return m_constraint; }
public:
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint, const zeus::CColor& bgColor);
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint);
void think();
bool skipBuildInAnimation();
void close(bool skipAnimation=false);
bool closed() const {return m_phase >= Phase::BuildOut;}
ModalWindow::Phase phase() const {return m_phase;}
void close(bool skipAnimation = false);
bool closed() const { return m_phase >= Phase::BuildOut; }
ModalWindow::Phase phase() const { return m_phase; }
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
}
} // namespace specter

View File

@ -4,11 +4,9 @@
#include "TextView.hpp"
#include "FontCache.hpp"
namespace specter
{
namespace specter {
class MultiLineTextView : public View
{
class MultiLineTextView : public View {
ViewResources& m_viewSystem;
std::vector<std::unique_ptr<TextView>> m_lines;
const FontAtlas& m_fontAtlas;
@ -21,23 +19,19 @@ class MultiLineTextView : public View
public:
MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
TextView::Alignment align=TextView::Alignment::Left,
size_t lineCapacity=256, float lineHeight=1.0);
TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
float lineHeight = 1.0);
MultiLineTextView(ViewResources& res, View& parentView, FontTag font,
TextView::Alignment align=TextView::Alignment::Left,
size_t lineCapacity=256, float lineHeight=1.0);
TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
float lineHeight = 1.0);
void typesetGlyphs(std::string_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);
void typesetGlyphs(std::string_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);
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)
l->setMultiplyColor(color);
}
@ -45,9 +39,8 @@ public:
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_width;}
int nominalHeight() const {return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size();}
int nominalWidth() const { return m_width; }
int nominalHeight() const { return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size(); }
};
}
} // namespace specter

View File

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

View File

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

View File

@ -2,12 +2,10 @@
#include "specter/TextView.hpp"
namespace specter
{
namespace specter {
class ViewResources;
class NumericField : public View
{
class NumericField : public View {
std::string m_textStr;
std::unique_ptr<TextView> m_text;
SolidShaderVert m_verts[28];
@ -26,9 +24,9 @@ class NumericField : public View
void setHover();
void setPressed();
void setDisabled();
public:
class Resources
{
class Resources {
friend class ViewResources;
friend class Button;
@ -44,9 +42,8 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ);
void setText(std::string_view text);
int nominalWidth() const {return m_nomWidth;}
int nominalHeight() const {return m_nomHeight;}
int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const { return m_nomHeight; }
};
}
} // namespace specter

View File

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

View File

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

View File

@ -3,18 +3,14 @@
#include "Button.hpp"
#include "ScrollView.hpp"
namespace specter
{
namespace specter {
struct IPathButtonsBinding
{
virtual void pathButtonActivated(size_t idx)=0;
struct IPathButtonsBinding {
virtual void pathButtonActivated(size_t idx) = 0;
};
class PathButtons : public ScrollView
{
struct ContentView : public View
{
class PathButtons : public ScrollView {
struct ContentView : public View {
PathButtons& m_pb;
boo::SWindowRect m_scissorRect;
@ -23,47 +19,41 @@ class PathButtons : public ScrollView
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
int nominalWidth() const
{
int nominalWidth() const {
int ret = 0;
for (PathButton& b : m_pb.m_pathButtons)
ret += b.m_button.m_view->nominalWidth() + 2;
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;
}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
ContentView(ViewResources& res, PathButtons& pb)
: View(res, pb), m_pb(pb) {}
ContentView(ViewResources& res, PathButtons& pb) : View(res, pb), m_pb(pb) {}
};
ViewChild<std::unique_ptr<ContentView>> m_contentView;
int m_pathButtonPending = -1;
IPathButtonsBinding& m_binding;
bool m_fillContainer;
struct PathButton final : IButtonBinding
{
struct PathButton final : IButtonBinding {
PathButtons& m_pb;
size_t m_idx;
ViewChild<std::unique_ptr<Button>> m_button;
PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str)
: m_pb(pb), m_idx(idx)
{
PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str) : m_pb(pb), m_idx(idx) {
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();}
void activated(const Button* button, const boo::SWindowCoord&) {m_pb.m_pathButtonPending = m_idx;}
std::string_view name(const Control* control) const { return m_button.m_view->getText(); }
void activated(const Button* button, const boo::SWindowCoord&) { m_pb.m_pathButtonPending = m_idx; }
};
friend struct PathButton;
std::vector<PathButton> m_pathButtons;
public:
PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer=false);
PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer = false);
void setButtons(const std::vector<hecl::SystemString>& comps);
void setMultiplyColor(const zeus::CColor& color);
@ -72,5 +62,4 @@ public:
void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
};
}
} // namespace specter

View File

@ -12,11 +12,9 @@
#include "optional.hpp"
#include "boo/boo.hpp"
namespace specter
{
namespace specter {
class RootView : public View
{
class RootView : public View {
boo::IWindow* m_window = nullptr;
boo::ObjToken<boo::ITextureR> m_renderTex;
boo::SWindowRect m_rootRect = {};
@ -37,14 +35,12 @@ class RootView : public View
boo::DeferredWindowEvents<RootView> m_events;
struct SplitMenuSystem : IMenuNode
{
struct SplitMenuSystem : IMenuNode {
RootView& m_rv;
std::string m_text;
SplitView* m_splitView = nullptr;
enum class Phase
{
enum class Phase {
Inactive,
InteractiveSplit,
InteractiveJoin,
@ -69,10 +65,9 @@ class RootView : public View
void draw(boo::IGraphicsCommandQueue* gfxQ);
SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx);
const std::string* text() const {return &m_text;}
size_t subNodeCount() const {return 2;}
IMenuNode* subNode(size_t idx)
{
const std::string* text() const { return &m_text; }
size_t subNodeCount() const { return 2; }
IMenuNode* subNode(size_t idx) {
if (idx)
return &m_joinActionNode;
else
@ -83,26 +78,22 @@ class RootView : public View
bool m_deferredSplit = false;
bool m_deferredJoin = false;
struct SplitActionNode : IMenuNode
{
struct SplitActionNode : IMenuNode {
SplitMenuSystem& m_smn;
std::string m_text;
SplitActionNode(SplitMenuSystem& smn);
const std::string* text() const {return &m_text;}
void activated(const boo::SWindowCoord& coord)
{
const std::string* text() const { return &m_text; }
void activated(const boo::SWindowCoord& coord) {
m_smn.m_deferredSplit = true;
m_smn.m_deferredCoord = coord;
}
} m_splitActionNode;
struct JoinActionNode : IMenuNode
{
struct JoinActionNode : IMenuNode {
SplitMenuSystem& m_smn;
std::string m_text;
JoinActionNode(SplitMenuSystem& smn);
const std::string* text() const {return &m_text;}
void activated(const boo::SWindowCoord& coord)
{
const std::string* text() const { return &m_text; }
void activated(const boo::SWindowCoord& coord) {
m_smn.m_deferredJoin = true;
m_smn.m_deferredCoord = coord;
}
@ -115,7 +106,7 @@ public:
~RootView();
void destroyed();
bool isDestroyed() const {return m_destroyed;}
bool isDestroyed() const { return m_destroyed; }
void resized(const boo::SWindowRect& rect, bool) { resized(rect, rect); }
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
@ -136,86 +127,71 @@ public:
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods);
void modKeyDown(boo::EModifierKey mod, bool isRepeat);
void modKeyUp(boo::EModifierKey mod);
boo::ITextInputCallback* getTextInputCallback() {return m_activeTextView;}
boo::ITextInputCallback* getTextInputCallback() { return m_activeTextView; }
void internalThink();
void dispatchEvents() {m_events.dispatchEvents();}
void dispatchEvents() { m_events.dispatchEvents(); }
void draw(boo::IGraphicsCommandQueue* gfxQ);
const boo::SWindowRect& rootRect() const {return m_rootRect;}
const boo::SWindowRect& rootRect() const { return m_rootRect; }
boo::IWindow* window() const {return m_window;}
IViewManager& viewManager() const {return m_viewMan;}
ViewResources& viewRes() const {return *m_viewRes;}
const IThemeData& themeData() const {return *m_viewRes->m_theme;}
const boo::ObjToken<boo::ITextureR>& renderTex() const {return m_renderTex;}
boo::IWindow* window() const { return m_window; }
IViewManager& viewManager() const { return m_viewMan; }
ViewResources& viewRes() const { return *m_viewRes; }
const IThemeData& themeData() const { return *m_viewRes->m_theme; }
const boo::ObjToken<boo::ITextureR>& renderTex() const { return m_renderTex; }
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_rightClickMenuRootAndLoc = subRect();
m_rightClickMenuRootAndLoc.location[0] = coord.pixel[0];
m_rightClickMenuRootAndLoc.location[1] = coord.pixel[1];
updateSize();
}
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)
m_activeTextView->setActive(false);
m_activeTextView = textView;
if (textView)
textView->setActive(true);
}
void setActiveDragView(View* dragView)
{
m_activeDragView = dragView;
}
void unsetActiveDragView(View* dragView)
{
void setActiveDragView(View* dragView) { m_activeDragView = dragView; }
void unsetActiveDragView(View* dragView) {
if (dragView == m_activeDragView)
m_activeDragView = nullptr;
}
void setActiveMenuButton(Button* button)
{
m_activeMenuButton = button;
}
void unsetActiveMenuButton(Button* button)
{
void setActiveMenuButton(Button* button) { m_activeMenuButton = button; }
void unsetActiveMenuButton(Button* button) {
if (button == m_activeMenuButton)
m_activeMenuButton = nullptr;
}
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord)
{
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord) {
m_hoverSplitDragView = sv;
m_activeSplitDragView = true;
sv->startDragSplit(coord);
}
bool m_hSplitHover = false;
void setHorizontalSplitHover(bool hover)
{
void setHorizontalSplitHover(bool hover) {
m_hSplitHover = hover;
_updateCursor();
}
bool m_vSplitHover = false;
void setVerticalSplitHover(bool hover)
{
void setVerticalSplitHover(bool hover) {
m_vSplitHover = hover;
_updateCursor();
}
bool m_textFieldHover = false;
void setTextFieldHover(bool hover)
{
void setTextFieldHover(bool hover) {
m_textFieldHover = hover;
_updateCursor();
}
bool m_spaceCornerHover = false;
void setSpaceCornerHover(bool hover)
{
void setSpaceCornerHover(bool hover) {
m_spaceCornerHover = hover;
_updateCursor();
}
@ -223,16 +199,14 @@ public:
void resetTooltip(ViewResources& res);
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_splitView = sv;
m_splitMenuSystem->mouseMove(coord);
}
private:
void _updateCursor()
{
void _updateCursor() {
if (m_spaceCornerHover)
m_window->setCursor(boo::EMouseCursor::Crosshairs);
else if (m_vSplitHover)
@ -249,5 +223,4 @@ private:
std::unique_ptr<Tooltip> m_tooltip;
};
}
} // namespace specter

View File

@ -3,20 +3,13 @@
#include "Button.hpp"
#include "IViewManager.hpp"
namespace specter
{
namespace specter {
class ViewResources;
class Button;
class ScrollView : public View
{
class ScrollView : public View {
public:
enum class Style
{
Plain,
ThinIndicator,
SideButtons
};
enum class Style { Plain, ThinIndicator, SideButtons };
private:
Style m_style;
@ -33,36 +26,25 @@ private:
SolidShaderVert m_verts[4];
VertexBufferBindingSolid m_vertsBinding;
enum class SideButtonState
{
None,
ScrollLeft,
ScrollRight
} m_sideButtonState = SideButtonState::None;
struct SideButtonBinding : IButtonBinding
{
enum class SideButtonState { None, ScrollLeft, ScrollRight } m_sideButtonState = SideButtonState::None;
struct SideButtonBinding : IButtonBinding {
ScrollView& m_sv;
std::string m_leftName, m_rightName;
SideButtonBinding(ScrollView& sv, IViewManager& vm)
: m_sv(sv),
m_leftName(vm.translateOr("scroll_left", "Scroll Left")),
m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {}
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() : m_rightName.c_str();
: m_sv(sv)
, m_leftName(vm.translateOr("scroll_left", "Scroll Left"))
, m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {}
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()
: 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())
m_sv.m_sideButtonState = SideButtonState::ScrollRight;
else
m_sv.m_sideButtonState = SideButtonState::ScrollLeft;
}
void up(const Button* button, const boo::SWindowCoord& coord)
{
m_sv.m_sideButtonState = SideButtonState::None;
}
void up(const Button* button, const boo::SWindowCoord& coord) { m_sv.m_sideButtonState = SideButtonState::None; }
} m_sideButtonBind;
ViewChild<std::unique_ptr<Button>> m_sideButtons[2];
@ -71,8 +53,7 @@ private:
public:
ScrollView(ViewResources& res, View& parentView, Style style);
void setContentView(View* v)
{
void setContentView(View* v) {
m_contentView.m_view = v;
updateSize();
}
@ -83,11 +64,11 @@ public:
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll);
int getScrollX() const {return m_scroll[0];}
int getScrollY() const {return m_scroll[1];}
int getScrollX() const { return m_scroll[0]; }
int getScrollY() const { return m_scroll[1]; }
int nominalWidth() const {return subRect().size[0];}
int nominalHeight() const {return subRect().size[1];}
int nominalWidth() const { return subRect().size[0]; }
int nominalHeight() const { return subRect().size[1]; }
void setMultiplyColor(const zeus::CColor& color);
@ -96,5 +77,4 @@ public:
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

@ -4,11 +4,9 @@
#include "TextView.hpp"
#include <boo/IWindow.hpp>
namespace specter
{
namespace specter {
class TextField : public ITextInputView
{
class TextField : public ITextInputView {
bool m_hasTextSet = false;
bool m_hasMarkSet = false;
std::string m_textStr;
@ -54,12 +52,7 @@ class TextField : public ITextInputView
bool m_active = false;
bool m_error = false;
enum class BGState
{
Inactive,
Hover,
Disabled
} m_bgState = BGState::Inactive;
enum class BGState { Inactive, Hover, Disabled } m_bgState = BGState::Inactive;
void setInactive();
void setHover();
void setDisabled();
@ -68,7 +61,7 @@ class TextField : public ITextInputView
public:
TextField(ViewResources& res, View& parentView, IStringBinding* strBind);
std::string_view getText() const {return m_textStr;}
std::string_view getText() const { return m_textStr; }
void setText(std::string_view str);
void clipboardCopy();
@ -83,26 +76,23 @@ public:
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
bool hasMarkedText() const;
std::pair<int,int> markedRange() const;
std::pair<int,int> selectedRange() const;
void setMarkedText(std::string_view str,
const std::pair<int,int>& selectedRange,
const std::pair<int,int>& replacementRange);
std::pair<int, int> markedRange() const;
std::pair<int, int> selectedRange() const;
void setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int, int>& replacementRange);
void unmarkText();
std::string substringForRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const;
void insertText(std::string_view str, const std::pair<int,int>& range);
std::string substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
void insertText(std::string_view str, const std::pair<int, int>& range);
int characterIndexAtPoint(const boo::SWindowCoord& point) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
void think();
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_nomWidth;}
int nominalHeight() const {return m_nomHeight;}
int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const { return m_nomHeight; }
void setActive(bool active);
void setCursorPos(size_t pos);
@ -112,8 +102,7 @@ public:
void setSelectionRange(size_t start, size_t count);
void clearSelectionRange();
void setMultiplyColor(const zeus::CColor& color)
{
void setMultiplyColor(const zeus::CColor& color) {
View::setMultiplyColor(color);
m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf)
@ -134,5 +123,4 @@ private:
void _setMarkedText();
};
}
} // namespace specter

View File

@ -5,29 +5,20 @@
#include "FontCache.hpp"
namespace specter
{
namespace specter {
class ViewResources;
class TextView : public View
{
class TextView : public View {
public:
enum class Alignment
{
Left,
Center,
Right
};
struct RenderGlyph
{
enum class Alignment { Left, Center, Right };
struct RenderGlyph {
zeus::CVector3f m_pos[4];
zeus::CMatrix4f m_mv;
zeus::CVector3f m_uv[4];
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[1] = other.m_pos[1];
m_pos[2] = other.m_pos[2];
@ -43,10 +34,9 @@ public:
RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor);
};
struct RenderGlyphInfo
{
struct RenderGlyphInfo {
uint32_t m_char;
std::pair<int,int> m_dims;
std::pair<int, int> m_dims;
int m_adv;
bool m_space = false;
@ -69,18 +59,14 @@ private:
void _commitResources(size_t capacity);
public:
class Resources
{
class Resources {
friend class ViewResources;
friend class TextView;
friend class MultiLineTextView;
hecl::VertexBufferPool<RenderGlyph> m_glyphPool;
void updateBuffers()
{
m_glyphPool.updateBuffers();
}
void updateBuffers() { m_glyphPool.updateBuffers(); }
FontCache* m_fcache = nullptr;
boo::ObjToken<boo::IShaderPipeline> m_regular;
@ -88,45 +74,43 @@ public:
void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache);
void destroy()
{
void destroy() {
m_glyphPool.doDestroy();
m_regular.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, FontTag font, Alignment align=Alignment::Left, size_t capacity=256);
TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align = Alignment::Left,
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;}
const std::vector<RenderGlyph>& accessGlyphs() const {return m_glyphs;}
std::vector<RenderGlyph>& accessGlyphs() { return m_glyphs; }
const std::vector<RenderGlyph>& accessGlyphs() const { return m_glyphs; }
void typesetGlyphs(std::string_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite);
void typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite);
void typesetGlyphs(std::string_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 colorGlyphs(const zeus::CColor& newColor);
void colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval=0.2, float fadeTime=0.5);
void colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval = 0.2, float fadeTime = 0.5);
void think();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_width;}
int nominalHeight() const {return m_fontAtlas.FT_LineHeight() >> 6;}
int nominalWidth() const { return m_width; }
int nominalHeight() const { return m_fontAtlas.FT_LineHeight() >> 6; }
std::pair<int,int> queryGlyphDimensions(size_t pos) const;
std::pair<int, int> queryGlyphDimensions(size_t pos) const;
size_t reverseSelectGlyph(int x) const;
int queryReverseAdvance(size_t idx) const;
std::pair<size_t,size_t> queryWholeWordRange(size_t idx) const;
std::pair<size_t, size_t> queryWholeWordRange(size_t idx) const;
private:
std::vector<RenderGlyph> m_glyphs;
std::vector<RenderGlyphInfo> m_glyphInfo;
};
}
} // namespace specter

View File

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

View File

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

View File

@ -3,32 +3,29 @@
#include <string>
#include <athena/DNAYaml.hpp>
namespace specter
{
namespace specter {
class Locale
{
class Locale {
std::string_view m_name;
std::string_view m_fullName;
std::unique_ptr<athena::io::YAMLNode> m_rootNode;
const athena::io::YAMLNode* m_langNode;
public:
Locale(std::string_view name, std::string_view fullName,
const unsigned char* yamlSource, size_t yamlLength);
std::string_view name() const {return m_name;}
std::string_view fullName() const {return m_fullName;}
const athena::io::YAMLNode* rootNode() const {return m_langNode;}
Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength);
std::string_view name() const { return m_name; }
std::string_view fullName() const { return m_fullName; }
const athena::io::YAMLNode* rootNode() const { return m_langNode; }
};
class Translator
{
class Translator {
const Locale* m_targetLocale;
public:
Translator(const Locale* targetLocale) {setLocale(targetLocale);}
Translator(const Locale* targetLocale) { setLocale(targetLocale); }
void setLocale(const Locale* targetLocale);
std::string_view translate(std::string_view key) 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/VertexBufferPool.hpp"
namespace specter
{
namespace specter {
class IThemeData;
class ViewResources;
class RootView;
extern zeus::CMatrix4f g_PlatformMatrix;
class RectangleConstraint
{
class RectangleConstraint {
public:
enum class Test
{
Fixed,
Minimum,
Maximum
};
enum class Test { Fixed, Minimum, Maximum };
private:
int m_x, m_y;
Test m_xtest, m_ytest;
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) {}
std::pair<int,int> solve(int x, int y) const
{
std::pair<int,int> ret;
std::pair<int, int> solve(int x, int y) const {
std::pair<int, int> ret;
if (m_x < 0)
ret.first = x;
else
{
switch (m_xtest)
{
else {
switch (m_xtest) {
case Test::Fixed:
ret.first = m_x;
break;
@ -57,10 +49,8 @@ public:
if (m_y < 0)
ret.second = y;
else
{
switch (m_ytest)
{
else {
switch (m_ytest) {
case Test::Fixed:
ret.second = m_y;
break;
@ -79,78 +69,62 @@ public:
class Space;
class SplitView;
class View
{
class View {
public:
struct SolidShaderVert
{
struct SolidShaderVert {
zeus::CVector3f m_pos;
zeus::CColor m_color = zeus::CColor::skClear;
};
struct TexShaderVert
{
struct TexShaderVert {
zeus::CVector3f m_pos;
zeus::CVector2f m_uv;
};
struct ViewBlock
{
struct ViewBlock {
zeus::CMatrix4f m_mv;
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[1][1] = 2.0f / root.size[1];
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;
}
void finalAssign(const ViewBlock& other)
{
void finalAssign(const ViewBlock& other) {
m_mv = g_PlatformMatrix * other.m_mv;
m_color = other.m_color;
}
};
template <typename VertStruct>
struct VertexBufferBinding
{
struct VertexBufferBinding {
typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf;
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
void load(const VertStruct* data, size_t count)
{
if (m_vertsBuf)
{
void load(const VertStruct* data, size_t count) {
if (m_vertsBuf) {
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];
}
}
template <typename VertArray>
void load(const VertArray data)
{
static_assert(std::is_same<std::remove_all_extents_t<VertArray>,
VertStruct>::value, "mismatched type");
if (m_vertsBuf)
{
void load(const VertArray data) {
static_assert(std::is_same<std::remove_all_extents_t<VertArray>, VertStruct>::value, "mismatched type");
if (m_vertsBuf) {
constexpr size_t count = sizeof(VertArray) / sizeof(VertStruct);
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];
}
}
operator const boo::ObjToken<boo::IShaderDataBinding>&() { return m_shaderBinding; }
};
struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert>
{
void init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert> {
void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf);
};
struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert>
{
void init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert> {
void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture);
};
@ -170,14 +144,12 @@ protected:
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
public:
struct Resources
{
struct Resources {
hecl::UniformBufferPool<ViewBlock> m_bufPool;
hecl::VertexBufferPool<SolidShaderVert> m_solidPool;
hecl::VertexBufferPool<TexShaderVert> m_texPool;
void updateBuffers()
{
void updateBuffers() {
m_bufPool.updateBuffers();
m_solidPool.updateBuffers();
m_texPool.updateBuffers();
@ -188,8 +160,7 @@ public:
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy()
{
void destroy() {
m_bufPool.doDestroy();
m_solidPool.doDestroy();
m_texPool.doDestroy();
@ -210,30 +181,28 @@ public:
View(const View& other) = delete;
View& operator=(const View& other) = delete;
View& parentView() {return m_parentView;}
RootView& rootView() {return m_rootView;}
const RootView& rootView() const {return m_rootView;}
const boo::SWindowRect& subRect() const {return m_subRect;}
int width() const {return m_subRect.size[0];}
int height() const {return m_subRect.size[1];}
View& parentView() { return m_parentView; }
RootView& rootView() { return m_rootView; }
const RootView& rootView() const { return m_rootView; }
const boo::SWindowRect& subRect() const { return m_subRect; }
int width() const { return m_subRect.size[0]; }
int height() const { return m_subRect.size[1]; }
void updateSize();
void setBackground(const zeus::CColor& color)
{
for (int i=0 ; i<4 ; ++i)
void setBackground(const zeus::CColor& color) {
for (int i = 0; i < 4; ++i)
m_bgRect[i].m_color = color;
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;
if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
}
virtual int nominalWidth() const {return 0;}
virtual int nominalHeight() const {return 0;}
virtual int nominalWidth() const { return 0; }
virtual int nominalHeight() const { return 0; }
virtual void setActive(bool) {}
@ -256,8 +225,9 @@ public:
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 ViewBlock& vb, const boo::SWindowRect& sub);
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) {resized(root, sub);}
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor) {
resized(root, sub);
}
virtual void think() {}
virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
@ -268,20 +238,16 @@ public:
};
template <class ViewPtrType>
struct ViewChild
{
struct ViewChild {
ViewPtrType m_view = ViewPtrType();
bool m_mouseIn = false;
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)
return false;
if (m_view->subRect().coordInRect(coord))
{
if ((m_mouseDown & 1 << int(button)) == 0)
{
if (m_view->subRect().coordInRect(coord)) {
if ((m_mouseDown & 1 << int(button)) == 0) {
m_view->mouseDown(coord, button, mod);
m_mouseDown |= 1 << int(button);
}
@ -290,59 +256,47 @@ struct ViewChild
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)
return;
if ((m_mouseDown & 1 << int(button)) != 0)
{
if ((m_mouseDown & 1 << int(button)) != 0) {
m_view->mouseUp(coord, button, mod);
m_mouseDown &= ~(1 << int(button));
}
}
void mouseMove(const boo::SWindowCoord& coord)
{
void mouseMove(const boo::SWindowCoord& coord) {
if (!m_view)
return;
if (m_view->subRect().coordInRect(coord))
{
if (!m_mouseIn)
{
if (m_view->subRect().coordInRect(coord)) {
if (!m_mouseIn) {
m_view->mouseEnter(coord);
m_mouseIn = true;
}
m_view->mouseMove(coord);
}
else
{
if (m_mouseIn)
{
} else {
if (m_mouseIn) {
m_view->mouseLeave(coord);
m_mouseIn = false;
}
}
}
void mouseEnter(const boo::SWindowCoord& coord)
{
void mouseEnter(const boo::SWindowCoord& coord) {
if (!m_view)
return;
}
void mouseLeave(const boo::SWindowCoord& coord)
{
void mouseLeave(const boo::SWindowCoord& coord) {
if (!m_view)
return;
if (m_mouseIn)
{
if (m_mouseIn) {
m_view->mouseLeave(coord);
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)
return;
if (m_mouseIn)
@ -351,20 +305,15 @@ struct ViewChild
};
template <class ViewPtrType>
struct ScissorViewChild : ViewChild<ViewPtrType>
{
struct ScissorViewChild : ViewChild<ViewPtrType> {
using base = ViewChild<ViewPtrType>;
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)
return false;
if (base::m_view->subRect().coordInRect(coord) &&
m_scissorRect.coordInRect(coord))
{
if ((base::m_mouseDown & 1 << int(button)) == 0)
{
if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
if ((base::m_mouseDown & 1 << int(button)) == 0) {
base::m_view->mouseDown(coord, button, mod);
base::m_mouseDown |= 1 << int(button);
}
@ -373,24 +322,17 @@ struct ScissorViewChild : ViewChild<ViewPtrType>
return false;
}
void mouseMove(const boo::SWindowCoord& coord)
{
void mouseMove(const boo::SWindowCoord& coord) {
if (!base::m_view)
return;
if (base::m_view->subRect().coordInRect(coord) &&
m_scissorRect.coordInRect(coord))
{
if (!base::m_mouseIn)
{
if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
if (!base::m_mouseIn) {
base::m_view->mouseEnter(coord);
base::m_mouseIn = true;
}
base::m_view->mouseMove(coord);
}
else
{
if (base::m_mouseIn)
{
} else {
if (base::m_mouseIn) {
base::m_view->mouseLeave(coord);
base::m_mouseIn = false;
}
@ -398,5 +340,4 @@ struct ScissorViewChild : ViewChild<ViewPtrType>
}
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

@ -3,27 +3,25 @@
#include "specter/ViewResources.hpp"
#include "specter/RootView.hpp"
namespace specter
{
namespace specter {
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,
IButtonBinding* controlBinding, std::string_view text, Icon* icon,
Button::Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text, Icon* icon,
Style style, const zeus::CColor& bgColor, RectangleConstraint constraint)
: Button(res, parentView, controlBinding, text, res.themeData().uiText(), icon, style, bgColor, constraint) {}
Button::Button(ViewResources& res, View& parentView,
IButtonBinding* controlBinding, std::string_view text, const zeus::CColor& textColor,
Icon* icon, Style style, const zeus::CColor& bgColor, RectangleConstraint constraint)
: Control(res, parentView, controlBinding),
m_style(style), m_textColor(textColor), m_bgColor(bgColor), m_textStr(text), m_constraint(constraint)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
Button::Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
const zeus::CColor& textColor, Icon* icon, Style style, const zeus::CColor& bgColor,
RectangleConstraint constraint)
: Control(res, parentView, controlBinding)
, m_style(style)
, m_textColor(textColor)
, m_bgColor(bgColor)
, m_textStr(text)
, m_constraint(constraint) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 40, m_viewVertBlockBuf);
return true;
@ -32,8 +30,7 @@ Button::Button(ViewResources& res, View& parentView,
m_buttonTarget.m_view.reset(new ButtonTarget(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 c2 = res.themeData().button2Inactive() * bgColor;
m_verts[0].m_color = c1;
@ -41,23 +38,21 @@ Button::Button(ViewResources& res, View& parentView,
m_verts[2].m_color = c1;
m_verts[3].m_color = c2;
m_verts[4].m_color = c2;
for (int i=5 ; i<28 ; ++i)
for (int i = 5; i < 28; ++i)
m_verts[i].m_color = c2;
m_verts[31].m_color = c1;
m_verts[32].m_color = c2;
m_verts[33].m_color = c1;
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;
}
else
{
for (int i=0 ; i<4 ; ++i)
} else {
for (int i = 0; i < 4; ++i)
m_verts[i].m_color = zeus::CColor::skClear;
for (int i=31 ; i<35 ; ++i)
for (int i = 31; i < 35; ++i)
m_verts[i].m_color = zeus::CColor::skClear;
}
for (int i=28 ; i<31 ; ++i)
for (int i = 28; i < 31; ++i)
m_verts[i].m_color = m_textColor;
_loadVerts();
@ -71,13 +66,9 @@ Button::Button(ViewResources& res, View& parentView,
setText(m_textStr);
}
void Button::setText(std::string_view text)
{
setText(text, m_textColor);
}
void Button::setText(std::string_view text) { 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_textColor = textColor;
@ -85,111 +76,105 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
float pf = rootView().viewRes().pixelFactor();
int width, height;
if (m_style == Style::Block)
{
if (m_style == Style::Block) {
m_textWidth = m_text->nominalWidth();
int nomWidth = m_textWidth + 12*pf;
int nomWidth = m_textWidth + 12 * pf;
if (m_icon)
nomWidth += 18*pf;
std::pair<int,int> constraint = m_constraint.solve(nomWidth, 20 * pf);
nomWidth += 18 * pf;
std::pair<int, int> constraint = m_constraint.solve(nomWidth, 20 * pf);
width = constraint.first;
height = constraint.second;
m_verts[0].m_pos.assign(1, height+1, 0);
m_verts[0].m_pos.assign(1, height + 1, 0);
m_verts[1].m_pos.assign(1, 1, 0);
m_verts[2].m_pos.assign(width+1, height+1, 0);
m_verts[3].m_pos.assign(width+1, 1, 0);
m_verts[4].m_pos.assign(width+1, 1, 0);
m_verts[2].m_pos.assign(width + 1, height + 1, 0);
m_verts[3].m_pos.assign(width + 1, 1, 0);
m_verts[4].m_pos.assign(width + 1, 1, 0);
m_textIconWidth = width;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
width += 12*pf;
width += 12 * pf;
else if (m_menuStyle == IButtonBinding::MenuStyle::Auxiliary)
width += 16*pf;
width += 16 * pf;
m_verts[5].m_pos.assign(1, height+1, 0);
m_verts[6].m_pos.assign(1, height+1, 0);
m_verts[7].m_pos.assign(0, height+1, 0);
m_verts[5].m_pos.assign(1, height + 1, 0);
m_verts[6].m_pos.assign(1, height + 1, 0);
m_verts[7].m_pos.assign(0, height + 1, 0);
m_verts[8].m_pos.assign(1, 1, 0);
m_verts[9].m_pos.assign(0, 1, 0);
m_verts[10].m_pos.assign(0, 1, 0);
m_verts[11].m_pos.assign(width+2, height+1, 0);
m_verts[12].m_pos.assign(width+2, height+1, 0);
m_verts[13].m_pos.assign(width+1, height+1, 0);
m_verts[14].m_pos.assign(width+2, 1, 0);
m_verts[15].m_pos.assign(width+1, 1, 0);
m_verts[16].m_pos.assign(width+1, 1, 0);
m_verts[11].m_pos.assign(width + 2, height + 1, 0);
m_verts[12].m_pos.assign(width + 2, height + 1, 0);
m_verts[13].m_pos.assign(width + 1, height + 1, 0);
m_verts[14].m_pos.assign(width + 2, 1, 0);
m_verts[15].m_pos.assign(width + 1, 1, 0);
m_verts[16].m_pos.assign(width + 1, 1, 0);
m_verts[17].m_pos.assign(1, height+2, 0);
m_verts[18].m_pos.assign(1, height+2, 0);
m_verts[19].m_pos.assign(1, height+1, 0);
m_verts[20].m_pos.assign(width+1, height+2, 0);
m_verts[21].m_pos.assign(width+1, height+1, 0);
m_verts[22].m_pos.assign(width+1, height+1, 0);
m_verts[17].m_pos.assign(1, height + 2, 0);
m_verts[18].m_pos.assign(1, height + 2, 0);
m_verts[19].m_pos.assign(1, height + 1, 0);
m_verts[20].m_pos.assign(width + 1, height + 2, 0);
m_verts[21].m_pos.assign(width + 1, height + 1, 0);
m_verts[22].m_pos.assign(width + 1, height + 1, 0);
m_verts[23].m_pos.assign(1, 1, 0);
m_verts[24].m_pos.assign(1, 1, 0);
m_verts[25].m_pos.assign(1, 0, 0);
m_verts[26].m_pos.assign(width+1, 1, 0);
m_verts[27].m_pos.assign(width+1, 0, 0);
m_verts[26].m_pos.assign(width + 1, 1, 0);
m_verts[27].m_pos.assign(width + 1, 0, 0);
int arrowX = m_textIconWidth + 5*pf;
int arrowY = 7*pf;
int arrowX = m_textIconWidth + 5 * pf;
int arrowY = 7 * pf;
int menuBgX = m_textIconWidth;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
{
if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
menuBgX = 0;
arrowX -= 5*pf;
arrowX -= 5 * pf;
}
m_verts[28].m_pos.assign(arrowX + 4*pf, arrowY + 1*pf, 0);
m_verts[29].m_pos.assign(arrowX, arrowY + 5*pf, 0);
m_verts[30].m_pos.assign(arrowX + 8*pf, arrowY + 5*pf, 0);
m_verts[28].m_pos.assign(arrowX + 4 * pf, arrowY + 1 * pf, 0);
m_verts[29].m_pos.assign(arrowX, arrowY + 5 * pf, 0);
m_verts[30].m_pos.assign(arrowX + 8 * pf, arrowY + 5 * pf, 0);
m_verts[31].m_pos.assign(menuBgX+1, height+1, 0);
m_verts[32].m_pos.assign(menuBgX+1, 1, 0);
m_verts[33].m_pos.assign(width+1, height+1, 0);
m_verts[34].m_pos.assign(width+1, 1, 0);
m_verts[31].m_pos.assign(menuBgX + 1, height + 1, 0);
m_verts[32].m_pos.assign(menuBgX + 1, 1, 0);
m_verts[33].m_pos.assign(width + 1, height + 1, 0);
m_verts[34].m_pos.assign(width + 1, 1, 0);
m_verts[35].m_pos.assign(m_textIconWidth, height+1, 0);
m_verts[35].m_pos.assign(m_textIconWidth, height + 1, 0);
m_verts[36].m_pos.assign(m_textIconWidth, 1, 0);
m_verts[37].m_pos.assign(m_textIconWidth+1, height+1, 0);
m_verts[38].m_pos.assign(m_textIconWidth+1, 1, 0);
m_verts[37].m_pos.assign(m_textIconWidth + 1, height + 1, 0);
m_verts[38].m_pos.assign(m_textIconWidth + 1, 1, 0);
_loadVerts();
}
else
{
} else {
width = m_text->nominalWidth();
height = 10 * pf;
m_verts[0].m_pos.assign(1*pf, -1*pf, 0);
m_verts[1].m_pos.assign(1*pf, -2*pf, 0);
m_verts[2].m_pos.assign(width, -1*pf, 0);
m_verts[3].m_pos.assign(width, -2*pf, 0);
m_verts[0].m_pos.assign(1 * pf, -1 * pf, 0);
m_verts[1].m_pos.assign(1 * pf, -2 * pf, 0);
m_verts[2].m_pos.assign(width, -1 * pf, 0);
m_verts[3].m_pos.assign(width, -2 * pf, 0);
int arrowX = width + 5*pf;
m_verts[28].m_pos.assign(arrowX + 4*pf, 1*pf, 0);
m_verts[29].m_pos.assign(arrowX, 5*pf, 0);
m_verts[30].m_pos.assign(arrowX + 8*pf, 5*pf, 0);
int arrowX = width + 5 * pf;
m_verts[28].m_pos.assign(arrowX + 4 * pf, 1 * pf, 0);
m_verts[29].m_pos.assign(arrowX, 5 * pf, 0);
m_verts[30].m_pos.assign(arrowX + 8 * pf, 5 * pf, 0);
m_textWidth = width;
m_textIconWidth = width;
int arrowLineWidth = 7*pf;
if (m_menuStyle != IButtonBinding::MenuStyle::None)
{
width += 13*pf;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
{
int arrowLineWidth = 7 * pf;
if (m_menuStyle != IButtonBinding::MenuStyle::None) {
width += 13 * pf;
if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
arrowLineWidth = width;
arrowX = 1*pf;
arrowX = 1 * pf;
}
}
m_verts[31].m_pos.assign(arrowX, -1*pf, 0);
m_verts[32].m_pos.assign(arrowX, -2*pf, 0);
m_verts[33].m_pos.assign(arrowX + arrowLineWidth, -1*pf, 0);
m_verts[34].m_pos.assign(arrowX + arrowLineWidth, -2*pf, 0);
m_verts[31].m_pos.assign(arrowX, -1 * pf, 0);
m_verts[32].m_pos.assign(arrowX, -2 * pf, 0);
m_verts[33].m_pos.assign(arrowX + arrowLineWidth, -1 * pf, 0);
m_verts[34].m_pos.assign(arrowX + arrowLineWidth, -2 * pf, 0);
_loadVerts();
}
@ -198,8 +183,7 @@ void Button::setText(std::string_view text, const zeus::CColor& textColor)
m_nomHeight = height;
}
void Button::setIcon(Icon* icon)
{
void Button::setIcon(Icon* icon) {
if (icon)
m_icon.reset(new IconView(rootView().viewRes(), *this, *icon));
else
@ -208,19 +192,16 @@ void Button::setIcon(Icon* icon)
updateSize();
}
void Button::colorGlyphs(const zeus::CColor& newColor)
{
void Button::colorGlyphs(const zeus::CColor& newColor) {
m_textColor = newColor;
m_text->colorGlyphs(newColor);
for (int i=28 ; i<31 ; ++i)
for (int i = 28; i < 31; ++i)
m_verts[i].m_color = newColor;
_loadVerts();
}
void Button::ButtonTarget::setInactive()
{
if (m_button.m_style == Style::Block)
{
void Button::ButtonTarget::setInactive() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1;
@ -229,20 +210,16 @@ void Button::ButtonTarget::setInactive()
m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=0 ; i<4 ; ++i)
} else {
for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts();
m_button.m_text->colorGlyphs(m_button.m_textColor);
}
}
void Button::MenuTarget::setInactive()
{
if (m_button.m_style == Style::Block)
{
void Button::MenuTarget::setInactive() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Inactive() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Inactive() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1;
@ -250,21 +227,17 @@ void Button::MenuTarget::setInactive()
m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=28 ; i<31 ; ++i)
} else {
for (int i = 28; i < 31; ++i)
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)
m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts();
}
}
void Button::ButtonTarget::setHover()
{
if (m_button.m_style == Style::Block)
{
void Button::ButtonTarget::setHover() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1;
@ -273,20 +246,16 @@ void Button::ButtonTarget::setHover()
m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=0 ; i<4 ; ++i)
} else {
for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts();
m_button.m_text->colorGlyphs(m_button.m_textColor);
}
}
void Button::MenuTarget::setHover()
{
if (m_button.m_style == Style::Block)
{
void Button::MenuTarget::setHover() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Hover() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Hover() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1;
@ -294,21 +263,17 @@ void Button::MenuTarget::setHover()
m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=28 ; i<31 ; ++i)
} else {
for (int i = 28; i < 31; ++i)
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)
m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts();
}
}
void Button::ButtonTarget::setPressed()
{
if (m_button.m_style == Style::Block)
{
void Button::ButtonTarget::setPressed() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1;
@ -317,20 +282,16 @@ void Button::ButtonTarget::setPressed()
m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=0 ; i<4 ; ++i)
} else {
for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts();
m_button.m_text->colorGlyphs(m_button.m_textColor);
}
}
void Button::MenuTarget::setPressed()
{
if (m_button.m_style == Style::Block)
{
void Button::MenuTarget::setPressed() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Press() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Press() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1;
@ -338,21 +299,17 @@ void Button::MenuTarget::setPressed()
m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=28 ; i<31 ; ++i)
} else {
for (int i = 28; i < 31; ++i)
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)
m_button.m_verts[i].m_color = m_button.m_textColor;
m_button._loadVerts();
}
}
void Button::ButtonTarget::setDisabled()
{
if (m_button.m_style == Style::Block)
{
void Button::ButtonTarget::setDisabled() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor;
m_button.m_verts[0].m_color = c1;
@ -361,10 +318,8 @@ void Button::ButtonTarget::setDisabled()
m_button.m_verts[3].m_color = c2;
m_button.m_verts[4].m_color = c2;
m_button._loadVerts();
}
else
{
for (int i=0 ; i<4 ; ++i)
} else {
for (int i = 0; i < 4; ++i)
m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts();
zeus::CColor dimText = m_button.m_textColor;
@ -373,10 +328,8 @@ void Button::ButtonTarget::setDisabled()
}
}
void Button::MenuTarget::setDisabled()
{
if (m_button.m_style == Style::Block)
{
void Button::MenuTarget::setDisabled() {
if (m_button.m_style == Style::Block) {
zeus::CColor c1 = rootView().themeData().button1Disabled() * m_button.m_bgColor;
zeus::CColor c2 = rootView().themeData().button2Disabled() * m_button.m_bgColor;
m_button.m_verts[31].m_color = c1;
@ -384,43 +337,36 @@ void Button::MenuTarget::setDisabled()
m_button.m_verts[33].m_color = c1;
m_button.m_verts[34].m_color = c2;
m_button._loadVerts();
}
else
{
} else {
zeus::CColor dimText = m_button.m_textColor;
dimText[3] *= 0.5;
for (int i=28 ; i<31 ; ++i)
for (int i = 28; i < 31; ++i)
m_button.m_verts[i].m_color = dimText;
for (int i=31 ; i<35 ; ++i)
for (int i = 31; i < 35; ++i)
m_button.m_verts[i].m_color = zeus::CColor::skClear;
m_button._loadVerts();
}
}
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)
m_buttonTarget.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;
setPressed();
if (m_button.m_controlBinding)
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;
setPressed();
if (m_hovered)
{
if (m_hovered) {
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);
rootView().setActiveMenuButton(&m_button);
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)
m_buttonTarget.mouseUp(coord, button, mod);
m_menuTarget.mouseUp(coord, button, mod);
}
void Button::ButtonTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_pressed)
{
void Button::ButtonTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_pressed) {
if (m_button.m_controlBinding)
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());
if (m_button.m_controlBinding)
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();
}
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;
if (m_hovered)
setHover();
@ -464,15 +405,13 @@ void Button::MenuTarget::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButt
setInactive();
}
void Button::mouseMove(const boo::SWindowCoord& coord)
{
void Button::mouseMove(const boo::SWindowCoord& coord) {
if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.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;
if (m_pressed)
setPressed();
@ -480,8 +419,7 @@ void Button::ButtonTarget::mouseEnter(const boo::SWindowCoord& coord)
setHover();
}
void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord)
{
void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord) {
m_hovered = true;
if (m_pressed)
setPressed();
@ -489,139 +427,112 @@ void Button::MenuTarget::mouseEnter(const boo::SWindowCoord& coord)
setHover();
}
void Button::mouseLeave(const boo::SWindowCoord& coord)
{
void Button::mouseLeave(const boo::SWindowCoord& coord) {
if (m_menuStyle != IButtonBinding::MenuStyle::Primary)
m_buttonTarget.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;
setInactive();
}
void Button::MenuTarget::mouseLeave(const boo::SWindowCoord& coord)
{
void Button::MenuTarget::mouseLeave(const boo::SWindowCoord& coord) {
m_hovered = false;
setInactive();
}
void Button::closeMenu(const boo::SWindowCoord& coord)
{
void Button::closeMenu(const boo::SWindowCoord& coord) {
rootView().unsetActiveMenuButton(this);
m_modalMenu.m_view.reset();
m_menuTarget.mouseMove(coord);
}
void Button::think()
{
void Button::think() {
if (m_modalMenu.m_view)
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);
boo::SWindowRect textRect = sub;
float pf = rootView().viewRes().pixelFactor();
if (m_icon)
{
textRect.location[0] += 18*pf;
if (m_icon) {
textRect.location[0] += 18 * pf;
boo::SWindowRect iconRect = sub;
iconRect.size[0] = 16*pf;
iconRect.size[1] = 16*pf;
iconRect.location[1] += 2*pf;
if (m_style == Style::Block)
{
iconRect.location[0] += 5*pf;
iconRect.size[0] = 16 * pf;
iconRect.size[1] = 16 * pf;
iconRect.location[1] += 2 * pf;
if (m_style == Style::Block) {
iconRect.location[0] += 5 * pf;
iconRect.location[1] += pf;
}
m_icon->resized(root, iconRect);
}
if (m_style == Style::Block)
{
textRect.location[0] += 6*pf;
textRect.location[1] += 7*pf;
if (m_style == Style::Block) {
textRect.location[0] += 6 * pf;
textRect.location[1] += 7 * pf;
}
textRect.location[0] += m_textWidth / 2;
textRect.size[0] = m_textWidth;
textRect.size[1] = m_nomHeight;
m_text->resized(root, textRect);
if (m_style == Style::Block)
{
if (m_menuStyle == IButtonBinding::MenuStyle::None)
{
if (m_style == Style::Block) {
if (m_menuStyle == IButtonBinding::MenuStyle::None) {
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);
}
else
{
} else {
boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_textIconWidth;
m_buttonTarget.m_view->resized(root, targetRect);
targetRect.location[0] += targetRect.size[0];
targetRect.size[0] = 16*pf;
targetRect.size[0] = 16 * pf;
m_menuTarget.m_view->resized(root, targetRect);
}
}
else
{
if (m_menuStyle == IButtonBinding::MenuStyle::Primary)
{
} else {
if (m_menuStyle == IButtonBinding::MenuStyle::Primary) {
boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_nomWidth;
targetRect.size[1] = m_nomHeight;
m_menuTarget.m_view->resized(root, targetRect);
}
else
{
} else {
boo::SWindowRect targetRect = sub;
targetRect.size[0] = m_textIconWidth + 3*pf;
targetRect.size[0] = m_textIconWidth + 3 * pf;
targetRect.size[1] = m_nomHeight;
m_buttonTarget.m_view->resized(root, targetRect);
targetRect.location[0] += targetRect.size[0];
targetRect.size[0] = 15*pf;
targetRect.size[0] = 15 * pf;
m_menuTarget.m_view->resized(root, targetRect);
}
}
if (m_modalMenu.m_view)
{
if (m_modalMenu.m_view) {
boo::SWindowRect menuRect = sub;
if (m_style == Style::Text)
menuRect.location[1] -= 6*pf;
menuRect.location[1] -= 6 * pf;
m_modalMenu.m_view->resized(root, menuRect);
}
}
void Button::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void Button::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding);
if (m_style == Style::Block)
{
if (m_style == Style::Block) {
gfxQ->draw(0, 28);
if (m_menuStyle != IButtonBinding::MenuStyle::None)
{
if (m_menuStyle != IButtonBinding::MenuStyle::None) {
gfxQ->draw(31, 4);
gfxQ->draw(28, 3);
if (m_menuStyle == IButtonBinding::MenuStyle::Auxiliary)
gfxQ->draw(35, 4);
}
}
else
{
} else {
gfxQ->draw(0, 4);
if (m_menuStyle != IButtonBinding::MenuStyle::None)
{
if (m_menuStyle != IButtonBinding::MenuStyle::None) {
gfxQ->draw(28, 3);
gfxQ->draw(31, 4);
}
@ -636,5 +547,4 @@ void Button::draw(boo::IGraphicsCommandQueue* gfxQ)
m_modalMenu.m_view->draw(gfxQ);
}
}
} // namespace specter

View File

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

View File

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

View File

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

View File

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

View File

@ -5,14 +5,10 @@
#define ROW_HEIGHT 18
#define ITEM_MARGIN 1
namespace specter
{
namespace specter {
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode)
: View(res, parentView)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode) : View(res, parentView) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
return true;
@ -24,44 +20,40 @@ Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode)
reset(rootNode);
}
void Menu::reset(IMenuNode* rootNode)
{
void Menu::reset(IMenuNode* rootNode) {
m_rootNode = rootNode;
m_thisNode = rootNode;
ViewResources& res = rootView().viewRes();
for (int i=0 ; i<8 ; ++i)
for (int i = 0; i < 8; ++i)
m_verts[i].m_color = res.themeData().tooltipBackground();
m_vertsBinding.load<decltype(m_verts)>(m_verts);
m_subMenu.reset();
const std::string* headText = rootNode->text();
m_headText->typesetGlyphs(headText?*headText:"", rootView().themeData().uiAltText());
m_headText->typesetGlyphs(headText ? *headText : "", rootView().themeData().uiAltText());
float pf = rootView().viewRes().pixelFactor();
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN*2) * pf;
m_cWidth = m_headText->nominalWidth() + 10*pf;
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf;
m_cWidth = m_headText->nominalWidth() + 10 * pf;
m_cHeight = headText ? itemAdv : 0;
m_cTop = m_cHeight;
size_t subCount = rootNode->subNodeCount();
m_items.clear();
if (subCount)
{
if (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);
const std::string* nodeText = node->text();
m_items.emplace_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));
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));
}
m_cHeight += itemAdv;
@ -70,10 +62,8 @@ void Menu::reset(IMenuNode* rootNode)
}
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode)
: View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
: View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
return true;
@ -84,11 +74,8 @@ Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode*
m_scroll.m_view->setContentView(m_content.get());
}
Menu::ContentView::ContentView(ViewResources& res, Menu& menu)
: View(res, menu), m_menu(menu)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
Menu::ContentView::ContentView(ViewResources& res, Menu& menu) : View(res, menu), m_menu(menu) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_hlVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
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)
: View(res, menu), m_menu(menu), m_idx(idx), m_node(node)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
: View(res, menu), m_menu(menu), m_idx(idx), m_node(node) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
return true;
});
@ -112,32 +97,28 @@ Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text,
m_textView->typesetGlyphs(text, res.themeData().uiText());
}
void Menu::setVerts(int width, int height, float pf)
{
m_verts[0].m_pos.assign(0, height-m_cTop-pf, 0);
void Menu::setVerts(int width, int height, float pf) {
m_verts[0].m_pos.assign(0, height - m_cTop - pf, 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);
m_verts[3].m_pos.assign(width, 0, 0);
m_verts[4].m_pos.assign(0, height, 0);
m_verts[5].m_pos.assign(0, height-m_cTop+pf, 0);
m_verts[5].m_pos.assign(0, height - m_cTop + pf, 0);
m_verts[6].m_pos.assign(width, height, 0);
m_verts[7].m_pos.assign(width, height-m_cTop+pf, 0);
m_verts[7].m_pos.assign(width, height - m_cTop + pf, 0);
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
void Menu::ContentView::setHighlightedItem(size_t idx)
{
if (idx == -1)
{
void Menu::ContentView::setHighlightedItem(size_t idx) {
if (idx == -1) {
m_highlightedItem = -1;
return;
}
ViewChild<std::unique_ptr<ItemView>>& vc = m_menu.m_items[idx];
if (!vc.m_view)
{
if (!vc.m_view) {
m_highlightedItem = -1;
return;
}
@ -147,106 +128,74 @@ void Menu::ContentView::setHighlightedItem(size_t idx)
const boo::SWindowRect& itemRect = vc.m_view->subRect();
int y = itemRect.location[1] - bgRect.location[1];
m_hlVerts[0].m_pos.assign(0, y+itemRect.size[1], 0);
m_hlVerts[0].m_pos.assign(0, y + itemRect.size[1], 0);
m_hlVerts[1].m_pos.assign(0, y, 0);
m_hlVerts[2].m_pos.assign(itemRect.size[0], y+itemRect.size[1], 0);
m_hlVerts[2].m_pos.assign(itemRect.size[0], y + itemRect.size[1], 0);
m_hlVerts[3].m_pos.assign(itemRect.size[0], y, 0);
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);
}
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)
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);
if (m_deferredActivation)
{
if (m_deferredActivation) {
IMenuNode* node = m_deferredActivation;
m_deferredActivation = nullptr;
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)
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)
m_menu.m_deferredActivation = m_node;
}
void Menu::mouseMove(const boo::SWindowCoord& coord)
{
m_scroll.mouseMove(coord);
}
void Menu::mouseMove(const boo::SWindowCoord& 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)
v.mouseMove(coord);
}
void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord)
{
m_menu.m_content->setHighlightedItem(m_idx);
}
void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord) { m_menu.m_content->setHighlightedItem(m_idx); }
void Menu::mouseLeave(const boo::SWindowCoord& coord)
{
m_scroll.mouseLeave(coord);
}
void Menu::mouseLeave(const boo::SWindowCoord& 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)
v.mouseLeave(coord);
}
void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord)
{
m_menu.m_content->unsetHighlightedItem(m_idx);
}
void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord) { m_menu.m_content->unsetHighlightedItem(m_idx); }
void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
{
m_scroll.scroll(coord, scroll);
}
void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { m_scroll.scroll(coord, scroll); }
void Menu::think()
{
m_scroll.m_view->think();
}
void Menu::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();
boo::SWindowRect rect = sub;
rect.size[0] = m_cWidth;
if (rect.location[1] - m_cHeight < 0)
{
rect.location[1] += ROW_HEIGHT*pf;
if (rect.location[1] - m_cHeight < 0) {
rect.location[1] += ROW_HEIGHT * pf;
rect.size[1] = std::min(root.size[1] - rect.location[1], m_cHeight);
}
else
{
} else {
rect.location[1] -= m_cHeight;
rect.size[1] = m_cHeight;
}
@ -255,44 +204,40 @@ void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
m_scroll.m_view->resized(root, rect);
setVerts(rect.size[0], rect.size[1], pf);
rect.location[0] += 5*pf;
rect.location[1] += rect.size[1] - (ROW_HEIGHT + ITEM_MARGIN - 5)*pf;
rect.location[0] += 5 * pf;
rect.location[1] += rect.size[1] - (ROW_HEIGHT + ITEM_MARGIN - 5) * pf;
rect.size[0] = m_headText->nominalWidth();
rect.size[1] = m_headText->nominalHeight();
m_headText->resized(root, rect);
}
void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor)
{
const boo::SWindowRect& scissor) {
View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor();
m_scissorRect = scissor;
boo::SWindowRect itemRect = sub;
itemRect.size[0] = m_menu.m_cWidth;
itemRect.size[1] = ROW_HEIGHT*pf;
itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN*pf;
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN*2) * pf;
for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items)
{
itemRect.size[1] = ROW_HEIGHT * pf;
itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN * pf;
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf;
for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items) {
itemRect.location[1] -= itemAdv;
if (c.m_view)
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);
float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect textRect = sub;
textRect.location[0] += 5*pf;
textRect.location[1] += 5*pf;
textRect.location[0] += 5 * pf;
textRect.location[1] += 5 * pf;
m_textView->resized(root, textRect);
}
void Menu::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void Menu::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 4);
@ -302,12 +247,10 @@ void Menu::draw(boo::IGraphicsCommandQueue* gfxQ)
m_headText->draw(gfxQ);
}
void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
gfxQ->setScissor(m_scissorRect);
if (m_highlightedItem != -1)
{
if (m_highlightedItem != -1) {
gfxQ->setShaderDataBinding(m_hlVertsBinding);
gfxQ->draw(0, 4);
}
@ -317,10 +260,9 @@ void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->setScissor(rootView().subRect());
}
void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
m_textView->draw(gfxQ);
}
}
} // namespace specter

View File

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

View File

@ -2,8 +2,7 @@
#include "specter/ViewResources.hpp"
#include "specter/RootView.hpp"
namespace specter
{
namespace specter {
#define WIRE_START 0
#define WIRE_FRAMES 40
@ -16,15 +15,14 @@ namespace specter
#define CONTENT_MARGIN 10
#define WINDOW_MIN_DIM 16
void ModalWindow::setLineVerts(int width, int height, float pf, float t)
{
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
void ModalWindow::setLineVerts(int width, int height, float pf, float t) {
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
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 lineLeft = 0;
float lineRight = pf*LINE_WIDTH;
float lineTop = height-margin.second;
float lineRight = pf * LINE_WIDTH;
float lineTop = height - margin.second;
float lineBottom = margin.second;
m_verts.lineVerts[0].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[1].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineLeft, lineBottom, 0}, t1);
@ -33,9 +31,9 @@ void ModalWindow::setLineVerts(int width, int height, float pf, float t)
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineRight = width - margin.first;
lineTop = height;
lineBottom = height-pf*LINE_WIDTH;
lineBottom = height - pf * LINE_WIDTH;
m_verts.lineVerts[5].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos;
m_verts.lineVerts[7].m_pos.assign(lineLeft, lineBottom, 0);
@ -43,9 +41,9 @@ void ModalWindow::setLineVerts(int width, int height, float pf, float t)
m_verts.lineVerts[9].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t1);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = width-pf*LINE_WIDTH;
lineLeft = width - pf * LINE_WIDTH;
lineRight = width;
lineTop = height-margin.second;
lineTop = height - margin.second;
lineBottom = margin.second;
m_verts.lineVerts[11].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos;
@ -55,8 +53,8 @@ void ModalWindow::setLineVerts(int width, int height, float pf, float t)
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = pf*LINE_WIDTH;
lineRight = width - margin.first;
lineTop = pf * LINE_WIDTH;
lineBottom = 0;
m_verts.lineVerts[17].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos;
@ -65,15 +63,14 @@ 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);
}
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
{
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) {
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
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 lineLeft = 0;
float lineRight = pf*LINE_WIDTH;
float lineTop = height-margin.second;
float lineRight = pf * LINE_WIDTH;
float lineTop = height - margin.second;
float lineBottom = margin.second;
m_verts.lineVerts[0].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t1);
m_verts.lineVerts[1].m_pos.assign(lineLeft, lineBottom, 0);
@ -82,9 +79,9 @@ void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineRight = width - margin.first;
lineTop = height;
lineBottom = height-pf*LINE_WIDTH;
lineBottom = height - pf * LINE_WIDTH;
m_verts.lineVerts[5].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t1);
m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos;
m_verts.lineVerts[7].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineLeft, lineBottom, 0}, t1);
@ -92,9 +89,9 @@ void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
m_verts.lineVerts[9].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = width-pf*LINE_WIDTH;
lineLeft = width - pf * LINE_WIDTH;
lineRight = width;
lineTop = height-margin.second;
lineTop = height - margin.second;
lineBottom = margin.second;
m_verts.lineVerts[11].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t2);
m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos;
@ -104,8 +101,8 @@ void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = pf*LINE_WIDTH;
lineRight = width - margin.first;
lineTop = pf * LINE_WIDTH;
lineBottom = 0;
m_verts.lineVerts[17].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t2);
m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos;
@ -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);
}
void ModalWindow::setLineColors(float t)
{
void ModalWindow::setLineColors(float t) {
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 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);
m_cornersOutline[0]->colorGlyphs(c1);
if (t < 0.5)
{
if (t < 0.5) {
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[2]->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[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2);
}
else
{
} else {
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(c3);
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;
}
void ModalWindow::setLineColorsOut(float t)
{
void ModalWindow::setLineColorsOut(float t) {
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 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);
m_cornersOutline[2]->colorGlyphs(c1);
if (t < 0.5)
{
if (t < 0.5) {
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[0]->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[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2);
}
else
{
} else {
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2);
@ -228,13 +213,12 @@ void ModalWindow::setLineColorsOut(float t)
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
}
void ModalWindow::setFillVerts(int width, int height, float pf)
{
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
void ModalWindow::setFillVerts(int width, int height, float pf) {
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
float fillLeft = pf*LINE_WIDTH;
float fillRight = width-pf*LINE_WIDTH;
float fillTop = height-margin.second;
float fillLeft = pf * LINE_WIDTH;
float fillRight = width - pf * LINE_WIDTH;
float fillTop = height - margin.second;
float fillBottom = margin.second;
m_verts.fillVerts[0].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[1].m_pos.assign(fillLeft, fillBottom, 0);
@ -243,9 +227,9 @@ void ModalWindow::setFillVerts(int width, int height, float pf)
m_verts.fillVerts[4].m_pos = m_verts.fillVerts[3].m_pos;
fillLeft = margin.first;
fillRight = width-margin.first;
fillTop = height-pf*LINE_WIDTH;
fillBottom = height-margin.second;
fillRight = width - margin.first;
fillTop = height - pf * LINE_WIDTH;
fillBottom = height - margin.second;
m_verts.fillVerts[5].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[6].m_pos = m_verts.fillVerts[5].m_pos;
m_verts.fillVerts[7].m_pos.assign(fillLeft, fillBottom, 0);
@ -254,9 +238,9 @@ void ModalWindow::setFillVerts(int width, int height, float pf)
m_verts.fillVerts[10].m_pos = m_verts.fillVerts[9].m_pos;
fillLeft = margin.first;
fillRight = width-margin.first;
fillRight = width - margin.first;
fillTop = margin.second;
fillBottom = pf*LINE_WIDTH;
fillBottom = pf * LINE_WIDTH;
m_verts.fillVerts[11].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[12].m_pos = m_verts.fillVerts[11].m_pos;
m_verts.fillVerts[13].m_pos.assign(fillLeft, fillBottom, 0);
@ -264,45 +248,41 @@ void ModalWindow::setFillVerts(int width, int height, float pf)
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);
zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
for (int i=0 ; i<16 ; ++i)
for (int i = 0; i < 16; ++i)
m_verts.fillVerts[i].m_color = color;
for (int i=0 ; i<4 ; ++i)
for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->colorGlyphs(color);
}
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint)
: ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {}
ModalWindow::ModalWindow(ViewResources& res, View& parentView,
const RectangleConstraint& constraint,
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint,
const zeus::CColor& bgColor)
: View(res, parentView),
m_constraint(constraint),
m_windowBg(bgColor),
m_windowBgClear(m_windowBg),
m_line1(res.themeData().splash1()),
m_line2(res.themeData().splash2()),
m_line2Clear(m_line2)
{
: View(res, parentView)
, m_constraint(constraint)
, m_windowBg(bgColor)
, m_windowBgClear(m_windowBg)
, m_line1(res.themeData().splash1())
, m_line2(res.themeData().splash2())
, m_line2Clear(m_line2) {
m_windowBgClear[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);
m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 38, m_viewBlockBuf);
return true;
} BooTrace);
for (int i=0 ; i<4 ; ++i)
{
m_cornersOutline[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
for (int i = 0; i < 4; ++i) {
m_cornersOutline[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");
@ -320,28 +300,24 @@ ModalWindow::ModalWindow(ViewResources& res, View& parentView,
_loadVerts();
}
static float CubicEase(float t)
{
static float CubicEase(float t) {
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;
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();
float pf = res.pixelFactor();
switch (m_phase)
{
case Phase::BuildIn:
{
switch (m_phase) {
case Phase::BuildIn: {
bool loadVerts = false;
int doneCount = 0;
if (m_frame > WIRE_START)
{
float wt = (m_frame-WIRE_START) / float(WIRE_FRAMES);
if (m_frame > WIRE_START) {
float wt = (m_frame - WIRE_START) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 2.f);
m_lineTime = CubicEase(wt);
setLineVerts(m_width, m_height, pf, m_lineTime);
@ -350,20 +326,18 @@ void ModalWindow::think()
++doneCount;
loadVerts = true;
}
if (m_frame > SOLID_START)
{
float ft = (m_frame-SOLID_START) / float(SOLID_FRAMES);
if (m_frame > SOLID_START) {
float ft = (m_frame - SOLID_START) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 2.f);
setFillColors(ft);
if (ft == 2.f)
++doneCount;
loadVerts = true;
}
if (res.fontCacheReady() && m_frame > CONTENT_START)
{
if (res.fontCacheReady() && m_frame > CONTENT_START) {
if (!m_contentStartFrame)
m_contentStartFrame = m_frame;
float tt = (m_frame-m_contentStartFrame) / float(CONTENT_FRAMES);
float tt = (m_frame - m_contentStartFrame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
if (tt == 1.f)
@ -376,17 +350,14 @@ void ModalWindow::think()
++m_frame;
break;
}
case Phase::ResWait:
{
if (res.fontCacheReady())
{
case Phase::ResWait: {
if (res.fontCacheReady()) {
updateContentOpacity(1.0);
m_phase = Phase::Showing;
}
break;
}
case Phase::BuildOut:
{
case Phase::BuildOut: {
{
float wt = (WIRE_FRAMES - m_frame) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 1.f);
@ -401,8 +372,7 @@ void ModalWindow::think()
ft = zeus::clamp(0.f, ft, 1.f);
setFillColors(ft);
}
if (res.fontCacheReady())
{
if (res.fontCacheReady()) {
float tt = (CONTENT_FRAMES - m_frame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
@ -411,12 +381,12 @@ void ModalWindow::think()
++m_frame;
break;
}
default: break;
default:
break;
}
}
bool ModalWindow::skipBuildInAnimation()
{
bool ModalWindow::skipBuildInAnimation() {
if (m_phase != Phase::BuildIn)
return false;
@ -432,19 +402,17 @@ bool ModalWindow::skipBuildInAnimation()
return true;
}
void ModalWindow::close(bool skipAnimation)
{
void ModalWindow::close(bool skipAnimation) {
m_phase = skipAnimation ? Phase::Done : Phase::BuildOut;
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();
boo::SWindowRect centerRect = sub;
std::pair<int,int> constrained = m_constraint.solve(root.size[0] - CONTENT_MARGIN * pf * 2,
root.size[1] - CONTENT_MARGIN * pf * 2);
std::pair<int, int> constrained =
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_height = std::max(constrained.second, int(WINDOW_MIN_DIM * pf));
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);
}
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_phase == Phase::Done)
return;
@ -495,4 +462,4 @@ void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
m_cornersOutline[3]->draw(gfxQ);
}
}
} // namespace specter

View File

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

View File

@ -2,18 +2,15 @@
#include "specter/RootView.hpp"
#include "specter/ViewResources.hpp"
namespace specter
{
namespace specter {
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));
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.reserve(comps.size());
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);
}
void PathButtons::setMultiplyColor(const zeus::CColor& color)
{
void PathButtons::setMultiplyColor(const zeus::CColor& color) {
ScrollView::setMultiplyColor(color);
for (PathButton& b : m_pathButtons)
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)
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)
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_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)
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)
b.m_button.mouseLeave(coord);
}
void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor)
{
const boo::SWindowRect& scissor) {
View::resized(root, sub);
m_scissorRect = scissor;
m_scissorRect.size[1] += 2;
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[1] = b.m_button.m_view->nominalHeight();
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)
{
if (m_fillContainer)
{
void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
if (m_fillContainer) {
boo::SWindowRect fillRect = sub;
fillRect.size[1] = 20 * rootView().viewRes().pixelFactor();
View::resized(root, fillRect);
}
}
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
gfxQ->setScissor(m_scissorRect);
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.m_view->draw(gfxQ);
gfxQ->setScissor(rootView().subRect());
}
}
} // namespace specter

View File

@ -3,17 +3,14 @@
#include "specter/Space.hpp"
#include "specter/Menu.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::RootView");
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);
boo::SWindowRect rect = window->getWindowFrame();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
buildResources(ctx, res);
m_splitMenuSystem.emplace(*this, ctx);
m_renderTex = ctx.newRenderTexture(rect.size[0], rect.size[1], boo::TextureClampMode::ClampToEdge, 3, 3);
@ -22,21 +19,19 @@ RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* wind
resized(rect, rect);
}
RootView::~RootView()
{
m_window->setCallback(nullptr);
}
RootView::~RootView() { m_window->setCallback(nullptr); }
RootView::SplitMenuSystem::SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx)
: m_rv(rv), m_text(rv.m_viewMan.translateOr("boundary_action", "Boundary Action")),
m_splitActionNode(*this), m_joinActionNode(*this)
{
: m_rv(rv)
, m_text(rv.m_viewMan.translateOr("boundary_action", "Boundary Action"))
, m_splitActionNode(*this)
, m_joinActionNode(*this) {
ViewResources& res = *rv.m_viewRes;
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 32, m_viewVertBlockBuf);
zeus::CColor col = {0.0,0.0,0.0,0.5};
for (int i=0 ; i<32 ; ++i)
zeus::CColor col = {0.0, 0.0, 0.0, 0.5};
for (int i = 0; i < 32; ++i)
m_verts[i].m_color = col;
m_verts[0].m_pos.assign(0.0, 0.25, 0);
@ -86,48 +81,40 @@ RootView::SplitMenuSystem::SplitActionNode::SplitActionNode(SplitMenuSystem& smn
RootView::SplitMenuSystem::JoinActionNode::JoinActionNode(SplitMenuSystem& smn)
: 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();
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][0] = 0.0f;
m_viewBlock.m_mv[1][0] = 2.0f * (dir == SplitView::ArrowDir::Left ? -rect.size[0] : rect.size[0]) /
float(root.size[0]);
m_viewBlock.m_mv[1][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[3][0] = 2.0f * (rect.location[0] + (dir == SplitView::ArrowDir::Left ? rect.size[0] : 0)) /
float(root.size[0]) - 1.0f;
m_viewBlock.m_mv[3][0] =
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;
}
else
{
} else {
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[1][1] = 2.0f * (dir == SplitView::ArrowDir::Down ? -rect.size[1] : rect.size[1]) /
float(root.size[1]);
m_viewBlock.m_mv[1][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[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)) /
float(root.size[1]) - 1.0f;
m_viewBlock.m_mv[3][1] =
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);
}
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();
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][1] = 0.0f;
m_viewBlock.m_mv[1][1] = 2.0f / float(root.size[1]);
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][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][1] = 0.0f;
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);
}
void RootView::destroyed()
{
m_destroyed = true;
}
void RootView::destroyed() { 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.location[0] = 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);
if (m_tooltip)
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 hr = root.size[1] / float(m_rightClickMenuRootAndLoc.size[1]);
m_rightClickMenuRootAndLoc.size[0] = root.size[0];
@ -167,17 +149,13 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
m_resizeRTDirty = true;
}
void RootView::SplitMenuSystem::resized()
{
if (m_phase == Phase::InteractiveJoin)
{
void RootView::SplitMenuSystem::resized() {
if (m_phase == Phase::InteractiveJoin) {
boo::SWindowRect rect;
SplitView::ArrowDir arrow;
m_splitView->getJoinArrowHover(m_interactiveSlot, rect, arrow);
setArrowVerts(rect, arrow);
}
else if (m_phase == Phase::InteractiveSplit)
{
} else if (m_phase == Phase::InteractiveSplit) {
boo::SWindowRect rect;
SplitView::Axis 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)
{
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
m_splitMenuSystem->mouseDown(coord, button, mods);
return;
}
if (m_rightClickMenu.m_view)
{
if (m_rightClickMenu.m_view) {
if (!m_rightClickMenu.mouseDown(coord, button, mods))
m_rightClickMenu.m_view.reset();
return;
}
if (m_activeMenuButton)
{
if (m_activeMenuButton) {
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
if (!mv.mouseDown(coord, button, mods))
m_activeMenuButton->closeMenu(coord);
return;
}
if (m_hoverSplitDragView)
{
if (button == boo::EMouseButton::Primary)
{
if (m_hoverSplitDragView) {
if (button == boo::EMouseButton::Primary) {
m_activeSplitDragView = true;
m_hoverSplitDragView->startDragSplit(coord);
}
else if (button == boo::EMouseButton::Secondary)
{
} else if (button == boo::EMouseButton::Secondary) {
m_splitMenuSystem->m_splitView = m_hoverSplitDragView;
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);
}
void RootView::SplitMenuSystem::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{
if (m_phase == Phase::InteractiveJoin)
{
void RootView::SplitMenuSystem::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button,
boo::EModifierKey mods) {
if (m_phase == Phase::InteractiveJoin) {
int origDummy;
SplitView* selSplit;
boo::SWindowRect rect;
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);
m_interactiveDown = true;
}
}
else if (m_phase == Phase::InteractiveSplit)
{
} else if (m_phase == Phase::InteractiveSplit) {
boo::SWindowRect rect;
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);
m_interactiveDown = true;
}
}
}
void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
m_splitMenuSystem->mouseUp(coord, button, mods);
return;
}
if (m_rightClickMenu.m_view)
{
if (m_rightClickMenu.m_view) {
m_rightClickMenu.mouseUp(coord, button, mods);
return;
}
if (m_activeMenuButton)
{
if (m_activeMenuButton) {
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
mv.mouseUp(coord, button, mods);
return;
}
if (m_activeSplitDragView && button == boo::EMouseButton::Primary)
{
if (m_activeSplitDragView && button == boo::EMouseButton::Primary) {
m_activeSplitDragView = false;
m_hoverSplitDragView->endDragSplit();
m_spaceCornerHover = false;
@ -290,39 +250,31 @@ void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
v->mouseUp(coord, button, mods);
}
void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{
if (m_phase == Phase::InteractiveJoin)
{
void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
boo::EModifierKey mods) {
if (m_phase == Phase::InteractiveJoin) {
int origSlot;
SplitView* selSplit;
boo::SWindowRect rect;
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);
if (m_interactiveDown)
{
if (m_interactiveDown) {
m_interactiveDown = false;
m_phase = Phase::Inactive;
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;
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);
if (m_interactiveDown)
{
if (m_interactiveDown) {
m_interactiveDown = false;
m_phase = Phase::Inactive;
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);
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))
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();
if (child)
{
if (child) {
SplitView* res = recursiveTestSplitHover(child, coord);
if (res)
return res;
@ -348,16 +297,13 @@ SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCo
return nullptr;
}
void RootView::mouseMove(const boo::SWindowCoord& coord)
{
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
void RootView::mouseMove(const boo::SWindowCoord& coord) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
m_splitMenuSystem->mouseMove(coord);
return;
}
if (m_rightClickMenu.m_view)
{
if (m_rightClickMenu.m_view) {
m_hSplitHover = false;
m_vSplitHover = false;
_updateCursor();
@ -365,8 +311,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
return;
}
if (m_activeMenuButton)
{
if (m_activeMenuButton) {
m_hSplitHover = false;
m_vSplitHover = false;
_updateCursor();
@ -375,8 +320,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
return;
}
if (m_activeSplitDragView)
{
if (m_activeSplitDragView) {
m_hoverSplitDragView->moveDragSplit(coord);
m_spaceCornerHover = false;
if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal)
@ -387,20 +331,15 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
}
m_hoverSplitDragView = nullptr;
if (!m_spaceCornerHover)
{
for (View* v : m_views)
{
if (!m_spaceCornerHover) {
for (View* v : m_views) {
SplitView* sv = v->castToSplitView();
if (sv)
sv = recursiveTestSplitHover(sv, coord);
if (sv)
{
if (sv) {
m_hoverSplitDragView = sv;
break;
}
else
{
} else {
m_hSplitHover = false;
m_vSplitHover = false;
_updateCursor();
@ -410,14 +349,12 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
if (m_activeDragView)
m_activeDragView->mouseMove(coord);
else
{
else {
for (View* v : m_views)
v->mouseMove(coord);
}
if (m_hoverSplitDragView)
{
if (m_hoverSplitDragView) {
if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal)
setHorizontalSplitHover(true);
else
@ -427,8 +364,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
boo::SWindowRect ttrect = m_rootRect;
ttrect.location[0] = coord.pixel[0];
ttrect.location[1] = coord.pixel[1];
if (m_tooltip)
{
if (m_tooltip) {
if (coord.pixel[0] + m_tooltip->nominalWidth() > m_rootRect.size[0])
ttrect.location[0] -= m_tooltip->nominalWidth();
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)
{
if (m_phase == Phase::InteractiveJoin)
{
void RootView::SplitMenuSystem::mouseMove(const boo::SWindowCoord& coord) {
if (m_phase == Phase::InteractiveJoin) {
int origDummy;
SplitView* selSplit;
boo::SWindowRect rect;
SplitView::ArrowDir arrow;
if (m_splitView->testJoinArrowHover(coord, origDummy, selSplit, m_interactiveSlot, rect, arrow))
setArrowVerts(rect, arrow);
}
else if (m_phase == Phase::InteractiveSplit)
{
} else if (m_phase == Phase::InteractiveSplit) {
boo::SWindowRect rect;
SplitView::Axis 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)
v->mouseEnter(coord);
}
void RootView::mouseLeave(const boo::SWindowCoord& coord)
{
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive)
{
void RootView::mouseLeave(const boo::SWindowCoord& coord) {
if (m_splitMenuSystem->m_phase != SplitMenuSystem::Phase::Inactive) {
m_splitMenuSystem->mouseLeave(coord);
return;
}
if (m_rightClickMenu.m_view)
{
if (m_rightClickMenu.m_view) {
m_rightClickMenu.mouseLeave(coord);
return;
}
if (m_activeMenuButton)
{
if (m_activeMenuButton) {
ViewChild<std::unique_ptr<View>>& mv = m_activeMenuButton->getMenu();
mv.mouseLeave(coord);
return;
@ -488,15 +415,10 @@ void RootView::mouseLeave(const boo::SWindowCoord& 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();
mv.scroll(coord, scroll);
return;
@ -506,31 +428,25 @@ void RootView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& s
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)
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)
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)
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)
v->charKeyDown(charCode, mods, isRepeat);
if (m_activeTextView &&
(mods & (boo::EModifierKey::Ctrl|boo::EModifierKey::Command)) != boo::EModifierKey::None)
{
if (m_activeTextView && (mods & (boo::EModifierKey::Ctrl | boo::EModifierKey::Command)) != boo::EModifierKey::None) {
if (charCode == 'c' || charCode == 'C')
m_activeTextView->clipboardCopy();
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)
v->charKeyUp(charCode, mods);
}
void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat)
{
if (key == boo::ESpecialKey::Enter && (mods & boo::EModifierKey::Alt) != boo::EModifierKey::None)
{
void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
if (key == boo::ESpecialKey::Enter && (mods & boo::EModifierKey::Alt) != boo::EModifierKey::None) {
m_window->setFullscreen(!m_window->isFullscreen());
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;
return;
}
@ -564,51 +476,48 @@ void RootView::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool
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)
v->specialKeyUp(key, mods);
if (m_activeTextView)
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)
v->modKeyDown(mod, isRepeat);
if (m_activeTextView)
m_activeTextView->modKeyDown(mod, isRepeat);
}
void RootView::modKeyUp(boo::EModifierKey mod)
{
void RootView::modKeyUp(boo::EModifierKey mod) {
for (View* v : m_views)
v->modKeyUp(mod);
if (m_activeTextView)
m_activeTextView->modKeyUp(mod);
}
void RootView::resetTooltip(ViewResources& res)
{
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."));
void RootView::resetTooltip(ViewResources& res) {
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."));
}
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()
{
if (m_splitMenuSystem->m_deferredSplit)
{
void RootView::internalThink() {
if (m_splitMenuSystem->m_deferredSplit) {
m_splitMenuSystem->m_deferredSplit = false;
m_rightClickMenu.m_view.reset();
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveSplit;
m_splitMenuSystem->mouseMove(m_splitMenuSystem->m_deferredCoord);
}
if (m_splitMenuSystem->m_deferredJoin)
{
if (m_splitMenuSystem->m_deferredJoin) {
m_splitMenuSystem->m_deferredJoin = false;
m_rightClickMenu.m_view.reset();
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
@ -619,13 +528,11 @@ void RootView::internalThink()
m_rightClickMenu.m_view->think();
}
void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
if (m_resizeRTDirty)
{
void RootView::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_resizeRTDirty) {
gfxQ->resizeRenderTexture(m_renderTex, m_rootRect.size[0], m_rootRect.size[1]);
m_resizeRTDirty = false;
gfxQ->schedulePostFrameHandler([&](){m_events.m_resizeCv.notify_one();});
gfxQ->schedulePostFrameHandler([&]() { m_events.m_resizeCv.notify_one(); });
}
m_viewRes->updateBuffers();
gfxQ->setRenderTarget(m_renderTex);
@ -642,8 +549,7 @@ void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->resolveDisplay(m_renderTex);
}
void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_phase == Phase::Inactive)
return;
gfxQ->setShaderDataBinding(m_vertsBinding);
@ -653,4 +559,4 @@ void RootView::SplitMenuSystem::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->draw(28, 4);
}
}
} // namespace specter

View File

@ -3,31 +3,25 @@
#include "specter/RootView.hpp"
#include "specter/Button.hpp"
namespace specter
{
namespace specter {
#define MAX_SCROLL_SPEED 100
ScrollView::ScrollView(ViewResources& res, View& parentView, Style style)
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager())
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true;
});
if (style == Style::SideButtons)
{
if (style == Style::SideButtons) {
m_sideButtons[0].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)
{
if (m_contentView.m_view)
{
bool ScrollView::_scroll(const boo::SScrollDelta& scroll) {
if (m_contentView.m_view) {
float ratioX = subRect().size[0] / float(m_contentView.m_view->nominalWidth());
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;
if (ratioX >= 1.f)
{
if (ratioX >= 1.f) {
m_scroll[0] = 0;
m_targetScroll[0] = 0;
m_drawSideButtons = false;
ret = true;
}
else
{
} else {
m_drawSideButtons = true;
m_targetScroll[0] += scroll.delta[0] * mult;
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);
}
if (ratioY >= 1.f)
{
if (ratioY >= 1.f) {
m_scroll[1] = 0;
m_targetScroll[1] = 0;
ret = true;
}
else
{
} else {
m_targetScroll[1] -= scroll.delta[1] * mult;
m_targetScroll[1] = std::max(m_targetScroll[1], 0);
int scrollHeight = m_contentView.m_view->nominalHeight() - subRect().size[1];
m_targetScroll[1] = std::min(m_targetScroll[1], scrollHeight);
}
if (scroll.isFine)
{
if (scroll.isFine) {
m_scroll[0] = m_targetScroll[0];
m_scroll[1] = m_targetScroll[1];
ret = true;
}
return ret;
}
else
{
} else {
m_scroll[0] = 0;
m_scroll[1] = 0;
m_targetScroll[0] = 0;
@ -89,79 +74,63 @@ bool ScrollView::_scroll(const boo::SScrollDelta& scroll)
return false;
}
int ScrollView::scrollAreaWidth() const
{
int ScrollView::scrollAreaWidth() const {
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[1].m_view->nominalWidth();
}
return std::max(0, ret);
}
void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
if (m_sideButtons[0].mouseDown(coord, button, mod) ||
m_sideButtons[1].mouseDown(coord, button, mod))
void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_style == Style::SideButtons && m_drawSideButtons) {
if (m_sideButtons[0].mouseDown(coord, button, mod) || m_sideButtons[1].mouseDown(coord, button, mod))
return;
}
m_contentView.mouseDown(coord, button, mod);
}
void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_style == Style::SideButtons)
{
void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_style == Style::SideButtons) {
m_sideButtons[0].mouseUp(coord, button, mod);
m_sideButtons[1].mouseUp(coord, button, mod);
}
m_contentView.mouseUp(coord, button, mod);
}
void ScrollView::mouseMove(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
void ScrollView::mouseMove(const boo::SWindowCoord& coord) {
if (m_style == Style::SideButtons && m_drawSideButtons) {
m_sideButtons[0].mouseMove(coord);
m_sideButtons[1].mouseMove(coord);
}
m_contentView.mouseMove(coord);
}
void ScrollView::mouseEnter(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
void ScrollView::mouseEnter(const boo::SWindowCoord& coord) {
if (m_style == Style::SideButtons && m_drawSideButtons) {
m_sideButtons[0].mouseEnter(coord);
m_sideButtons[1].mouseEnter(coord);
}
m_contentView.mouseEnter(coord);
}
void ScrollView::mouseLeave(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons)
{
void ScrollView::mouseLeave(const boo::SWindowCoord& coord) {
if (m_style == Style::SideButtons) {
m_sideButtons[0].mouseLeave(coord);
m_sideButtons[1].mouseLeave(coord);
}
m_contentView.mouseLeave(coord);
}
void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
{
if (!scroll.isAccelerated)
{
void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
if (!scroll.isAccelerated) {
boo::SScrollDelta newScroll = scroll;
m_consecutiveScroll[m_consecutiveIdx][0] += scroll.delta[0];
m_consecutiveScroll[m_consecutiveIdx][1] += scroll.delta[1];
newScroll.delta[0] = 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[1] += m_consecutiveScroll[i][1];
}
@ -173,11 +142,9 @@ void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta&
updateSize();
}
void ScrollView::setMultiplyColor(const zeus::CColor& color)
{
void ScrollView::setMultiplyColor(const zeus::CColor& color) {
View::setMultiplyColor(color);
if (m_style == Style::SideButtons)
{
if (m_style == Style::SideButtons) {
m_sideButtons[0].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);
}
void ScrollView::think()
{
m_consecutiveIdx = (m_consecutiveIdx+1) % 16;
void ScrollView::think() {
m_consecutiveIdx = (m_consecutiveIdx + 1) % 16;
m_consecutiveScroll[m_consecutiveIdx][0] = 0.0;
m_consecutiveScroll[m_consecutiveIdx][1] = 0.0;
if (m_sideButtonState != SideButtonState::None)
{
if (m_sideButtonState != SideButtonState::None) {
if (m_sideButtonState == SideButtonState::ScrollLeft)
m_targetScroll[0] -= 3;
else if (m_sideButtonState == SideButtonState::ScrollRight)
@ -205,26 +170,20 @@ void ScrollView::think()
bool update = false;
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)));
if (m_scroll[0] < m_targetScroll[0])
{
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]) {
m_scroll[0] += xSpeed;
update = true;
}
else if (m_scroll[0] > m_targetScroll[0])
{
} else if (m_scroll[0] > m_targetScroll[0]) {
m_scroll[0] -= xSpeed;
update = true;
}
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])
{
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]) {
m_scroll[1] += ySpeed;
update = true;
}
else if (m_scroll[1] > m_targetScroll[1])
{
} else if (m_scroll[1] > m_targetScroll[1]) {
m_scroll[1] -= ySpeed;
update = true;
}
@ -233,20 +192,17 @@ void ScrollView::think()
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);
_scroll({});
if (m_contentView.m_view)
{
if (m_contentView.m_view) {
boo::SWindowRect cRect = sub;
cRect.location[0] += m_scroll[0];
cRect.location[1] += sub.size[1] - m_contentView.m_view->nominalHeight() + m_scroll[1];
cRect.size[0] = m_contentView.m_view->nominalWidth();
cRect.size[1] = m_contentView.m_view->nominalHeight();
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 width1 = m_sideButtons[1].m_view->nominalWidth();
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);
if (m_style == Style::ThinIndicator)
{
if (m_style == Style::ThinIndicator) {
float ratio = sub.size[1] / float(cRect.size[1]);
m_drawInd = ratio < 1.f;
if (m_drawInd)
{
if (m_drawInd) {
float pf = rootView().viewRes().pixelFactor();
int barHeight = sub.size[1] * ratio;
int scrollHeight = sub.size[1] - barHeight;
@ -271,17 +224,15 @@ void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& s
int x = sub.size[0];
int y = sub.size[1] - scrollHeight * prog;
m_verts[0].m_pos.assign(x, y, 0);
m_verts[1].m_pos.assign(x, y-barHeight, 0);
m_verts[2].m_pos.assign(x+2*pf, y, 0);
m_verts[3].m_pos.assign(x+2*pf, y-barHeight, 0);
m_verts[1].m_pos.assign(x, y - barHeight, 0);
m_verts[2].m_pos.assign(x + 2 * pf, y, 0);
m_verts[3].m_pos.assign(x + 2 * pf, y - barHeight, 0);
const zeus::CColor& color = rootView().themeData().scrollIndicator();
for (int i=0 ; i<4 ; ++i)
for (int i = 0; i < 4; ++i)
m_verts[i].m_color = color;
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;
bRect.size[0] = m_sideButtons[0].m_view->nominalWidth();
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)
{
if (m_contentView.m_view)
{
void ScrollView::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_contentView.m_view) {
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->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[1].m_view->draw(gfxQ);
}
}
}
}
} // namespace specter

View File

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

View File

@ -4,29 +4,24 @@
#include "specter/ViewResources.hpp"
#include "specter/Space.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::SplitView");
static const zeus::RGBA32 Tex[3] =
{
{{0,0,0,64}},
{{0,0,0,255}},
{{255,255,255,64}}
};
static const zeus::RGBA32 Tex[3] = {{{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);
}
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller,
Axis axis, float split, int clearanceA, int clearanceB)
: View(res, parentView), m_controller(controller), m_axis(axis), m_slide(split),
m_clearanceA(clearanceA), m_clearanceB(clearanceB)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
int clearanceA, int clearanceB)
: View(res, parentView)
, m_controller(controller)
, m_axis(axis)
, m_slide(split)
, m_clearanceA(clearanceA)
, m_clearanceB(clearanceB) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
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());
@ -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)
Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView");
View* ret = m_views[slot].m_view;
@ -46,23 +40,17 @@ View* SplitView::setContentView(int slot, View* view)
return ret;
}
void SplitView::_setSplit(float slide)
{
void SplitView::_setSplit(float slide) {
m_slide = std::min(std::max(slide, 0.0f), 1.0f);
const boo::SWindowRect& rect = subRect();
if (rect.size[0] && rect.size[1] &&
(m_clearanceA >= 0 || m_clearanceB >= 0))
{
if (m_axis == Axis::Horizontal)
{
if (rect.size[0] && rect.size[1] && (m_clearanceA >= 0 || m_clearanceB >= 0)) {
if (m_axis == Axis::Horizontal) {
int slidePx = rect.size[1] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[1]);
if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB)
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;
if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[0]);
@ -75,28 +63,22 @@ void SplitView::_setSplit(float slide)
m_controller->updateSplit(m_slide);
}
void SplitView::setSplit(float slide)
{
void SplitView::setSplit(float slide) {
_setSplit(slide);
updateSize();
}
void SplitView::setAxis(Axis axis)
{
void SplitView::setAxis(Axis axis) {
m_axis = axis;
setSplit(m_slide);
}
bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
{
if (m_axis == Axis::Horizontal)
{
bool SplitView::testSplitHover(const boo::SWindowCoord& coord) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
return true;
}
else if (m_axis == Axis::Vertical)
{
} else if (m_axis == Axis::Vertical) {
int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
return true;
@ -104,25 +86,20 @@ bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
return false;
}
bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut,
SplitView*& splitOut, int& slotOut,
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot)
{
bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, SplitView*& splitOut, int& slotOut,
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot) {
if (!subRect().coordInRect(coord))
return false;
int origDummy;
ArrowDir dirDummy;
if (m_axis == Axis::Horizontal)
{
if (m_axis == Axis::Horizontal) {
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;
dirOut = ArrowDir::Up;
if (m_views[1].m_view)
{
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
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.size[1] -= slidePx;
return true;
}
else
{
} else {
origSlotOut = 1;
dirOut = ArrowDir::Down;
if (m_views[0].m_view)
{
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
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;
return true;
}
}
else
{
} else {
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;
dirOut = ArrowDir::Right;
if (m_views[1].m_view)
{
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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.size[0] -= slidePx;
return true;
}
else
{
} else {
origSlotOut = 1;
dirOut = ArrowDir::Left;
if (m_views[0].m_view)
{
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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)
{
if (m_axis == Axis::Horizontal)
{
void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
@ -207,11 +170,8 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
dirOut = ArrowDir::Up;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
@ -220,14 +180,10 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.size[1] = slidePx;
dirOut = ArrowDir::Down;
}
}
else
{
} else {
int slidePx = subRect().size[0] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
@ -236,11 +192,8 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
dirOut = ArrowDir::Right;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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,
boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut)
{
bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut,
float& splitOut, Axis& axisOut) {
if (!subRect().coordInRect(coord))
return false;
if (m_axis == Axis::Horizontal)
{
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0)
{
if (m_views[1].m_view)
{
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
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]);
axisOut = Axis::Vertical;
return true;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
@ -292,14 +238,10 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
axisOut = Axis::Vertical;
return true;
}
}
else
{
} else {
int slidePx = subRect().size[0] * m_slide;
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0)
{
if (m_views[1].m_view)
{
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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]);
axisOut = Axis::Horizontal;
return true;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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)
{
if (m_axis == Axis::Horizontal)
{
void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
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.size[1] -= slidePx;
axisOut = Axis::Vertical;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
@ -360,14 +292,10 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
rectOut.size[1] = slidePx;
axisOut = Axis::Vertical;
}
}
else
{
} else {
int slidePx = subRect().size[0] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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.size[0] -= slidePx;
axisOut = Axis::Horizontal;
}
else
{
if (m_views[0].m_view)
{
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
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;
if (m_axis == Axis::Horizontal)
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]));
}
void SplitView::endDragSplit()
{
m_dragging = false;
}
void SplitView::endDragSplit() { m_dragging = false; }
void SplitView::moveDragSplit(const boo::SWindowCoord& coord)
{
void SplitView::moveDragSplit(const boo::SWindowCoord& coord) {
if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical)
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[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[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[1].mouseMove(coord);
}
void SplitView::mouseEnter(const boo::SWindowCoord& coord)
{
void SplitView::mouseEnter(const boo::SWindowCoord& coord) {
m_views[0].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[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);
_setSplit(m_slide);
if (m_axis == Axis::Horizontal)
{
if (m_axis == Axis::Horizontal) {
boo::SWindowRect ssub = sub;
ssub.size[1] *= m_slide;
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;
m_splitBlock.setViewRect(root, ssub);
setHorizontalVerts(ssub.size[0]);
}
else if (m_axis == Axis::Vertical)
{
} else if (m_axis == Axis::Vertical) {
boo::SWindowRect ssub = sub;
ssub.size[0] *= m_slide;
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);
}
void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
if (m_views[0].m_view)
m_views[0].m_view->draw(gfxQ);
@ -491,5 +401,4 @@ void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->draw(0, 4);
}
}
} // namespace specter

View File

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

View File

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

View File

@ -7,27 +7,22 @@
#include <freetype/internal/internal.h>
#include <freetype/internal/ftobjs.h>
namespace specter
{
namespace specter {
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_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{});
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 fontTex = m_fontAtlas.texture(res.m_factory);
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx)
{
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
buildResources(ctx, res);
if (capacity)
{
if (capacity) {
m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
boo::ObjToken<boo::IShaderPipeline> shader;
@ -43,25 +38,18 @@ void TextView::_commitResources(size_t capacity)
size_t uBufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()};
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1,
uBufs, nullptr, uBufOffs, uBufSizes,
1, texs, nullptr, nullptr, 0, vBufInfo.second);
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, uBufs, nullptr, uBufOffs,
uBufSizes, 1, texs, nullptr, nullptr, 0, vBufInfo.second);
}
return true;
});
}
TextView::TextView(ViewResources& res,
View& parentView, const FontAtlas& font,
Alignment align, size_t capacity)
: View(res, parentView),
m_capacity(capacity),
m_fontAtlas(font),
m_align(align)
{
TextView::TextView(ViewResources& res, View& parentView, const FontAtlas& font, 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)
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
capacity, hecl::VertexBufferPool<RenderGlyph>::bucketCapacity());
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]", capacity,
hecl::VertexBufferPool<RenderGlyph>::bucketCapacity());
_commitResources(0);
}
@ -69,8 +57,7 @@ TextView::TextView(ViewResources& res,
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::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[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);
@ -83,9 +70,9 @@ TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, cons
adv += glyph.m_advance;
}
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
{
if (!val) return 0;
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) {
if (!val)
return 0;
val = FT_MulFix(val, atlas.FT_Xscale());
FT_Pos orig_x = val;
@ -99,12 +86,10 @@ int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
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());
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;
_commitResources(charLen);
}
@ -116,13 +101,10 @@ void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultCo
m_glyphInfo.reserve(charLen);
int adv = 0;
if (charLen)
{
for (; it.iter() < str.end() ; ++it)
{
if (charLen) {
for (; it.iter() < str.end(); ++it) {
utf8proc_int32_t ch = *it;
if (ch == -1)
{
if (ch == -1) {
Log.report(logvisor::Warning, "invalid UTF-8 char");
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;
for (RenderGlyph& g : m_glyphs)
{
for (RenderGlyph& g : m_glyphs) {
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
}
else if (m_align == Alignment::Center)
{
} else if (m_align == Alignment::Center) {
int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs)
{
for (RenderGlyph& g : m_glyphs) {
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
@ -173,11 +150,9 @@ void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultCo
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);
if (charLen > m_curSize)
{
if (charLen > m_curSize) {
m_curSize = charLen;
_commitResources(charLen);
}
@ -189,8 +164,7 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
m_glyphInfo.reserve(charLen);
int adv = 0;
for (wchar_t ch : str)
{
for (wchar_t ch : str) {
if (ch == L'\n')
break;
@ -209,22 +183,17 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
break;
}
if (m_align == Alignment::Right)
{
if (m_align == Alignment::Right) {
int adj = -adv;
for (RenderGlyph& g : m_glyphs)
{
for (RenderGlyph& g : m_glyphs) {
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
}
else if (m_align == Alignment::Center)
{
} else if (m_align == Alignment::Center) {
int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs)
{
for (RenderGlyph& g : m_glyphs) {
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
@ -237,21 +206,16 @@ void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultC
updateSize();
}
void TextView::colorGlyphs(const zeus::CColor& newColor)
{
void TextView::colorGlyphs(const zeus::CColor& newColor) {
for (RenderGlyph& glyph : m_glyphs)
glyph.m_color = newColor;
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()
{
if (m_glyphBuf)
{
void TextView::invalidateGlyphs() {
if (m_glyphBuf) {
RenderGlyph* out = m_glyphBuf.access();
size_t i = 0;
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)
{
View::resized(root, sub);
}
void TextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { View::resized(root, sub); }
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
if (m_glyphs.size())
{
if (m_glyphs.size()) {
gfxQ->setShaderDataBinding(m_shaderBinding);
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())
Log.report(logvisor::Fatal,
"TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize,
pos, m_glyphInfo.size());
Log.report(logvisor::Fatal, "TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize, pos,
m_glyphInfo.size());
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 idx = 1;
int minDelta = abs(x);
for (const RenderGlyphInfo& info : m_glyphInfo)
{
int thisDelta = abs(info.m_adv-x);
if (thisDelta < minDelta)
{
for (const RenderGlyphInfo& info : m_glyphInfo) {
int thisDelta = abs(info.m_adv - x);
if (thisDelta < minDelta) {
minDelta = thisDelta;
ret = idx;
}
@ -306,37 +258,34 @@ size_t TextView::reverseSelectGlyph(int x) const
return ret;
}
int TextView::queryReverseAdvance(size_t idx) const
{
int TextView::queryReverseAdvance(size_t idx) const {
if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal,
"TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphInfo.size());
if (!idx) return 0;
return m_glyphInfo[idx-1].m_adv;
Log.report(logvisor::Fatal, "TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
m_glyphInfo.size());
if (!idx)
return 0;
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())
Log.report(logvisor::Fatal,
"TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphInfo.size());
Log.report(logvisor::Fatal, "TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
m_glyphInfo.size());
if (m_glyphInfo.empty())
return {0,0};
return {0, 0};
if (idx == m_glyphInfo.size())
--idx;
size_t begin = idx;
while (begin > 0 && !m_glyphInfo[begin-1].m_space)
while (begin > 0 && !m_glyphInfo[begin - 1].m_space)
--begin;
size_t end = idx;
while (end < m_glyphInfo.size() && !m_glyphInfo[end].m_space)
++end;
return {begin, end-begin};
return {begin, end - begin};
}
}
} // namespace specter

View File

@ -5,33 +5,24 @@
#define TOOLBAR_PADDING 10
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::Space");
static const zeus::RGBA32 Tex[] =
{
{{255,255,255,64}},
{{255,255,255,64}},
{{0,0,0,64}},
{{0,0,0,64}}
};
static const zeus::RGBA32 Tex[] = {{{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);
}
Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units)
: View(res, parentView), m_units(units),
m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units),
m_padding(res.pixelFactor() * TOOLBAR_PADDING)
{
: View(res, parentView)
, m_units(units)
, m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units)
, m_padding(res.pixelFactor() * TOOLBAR_PADDING) {
m_children.reserve(units);
for (unsigned u=0 ; u<units ; ++u)
for (unsigned u = 0; u < units; ++u)
m_children.emplace_back();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
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());
@ -40,43 +31,37 @@ Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned
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 (ViewChild<View*>& c : u)
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 (ViewChild<View*>& c : u)
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 (ViewChild<View*>& c : u)
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 (ViewChild<View*>& c : u)
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 (ViewChild<View*>& c : u)
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_uv.assign(0, 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);
}
void Toolbar::setVerticalVerts(int height)
{
void Toolbar::setVerticalVerts(int height) {
m_tbVerts[0].m_pos.assign(-1, height, 0);
m_tbVerts[0].m_uv.assign(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);
}
void Toolbar::push_back(View* v, unsigned unit)
{
void Toolbar::push_back(View* v, unsigned unit) {
if (unit >= m_units)
Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units);
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;
}
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);
setHorizontalVerts(sub.size[0]);
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 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 containRect = sub;
containRect.location[0] += m_padding;
containRect.size[0] -= m_padding * 2;
containRect.size[1] = gaugeUnit;
for (ViewChild<View*>& c : u)
{
for (ViewChild<View*>& c : u) {
c.m_view->containerResized(root, containRect);
childRect.size[0] = c.m_view->nominalWidth();
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);
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 10);
@ -180,5 +159,4 @@ void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ)
c.m_view->draw(gfxQ);
}
}
} // namespace specter

View File

@ -2,29 +2,24 @@
#include "specter/ViewResources.hpp"
#include "specter/RootView.hpp"
namespace specter
{
namespace specter {
#define TOOLTIP_MAX_WIDTH 316
#define TOOLTIP_MAX_TEXT_WIDTH 300
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title,
std::string_view message)
: View(res, parentView), m_titleStr(title), m_messageStr(message)
{
for (int i=0 ; i<16 ; ++i)
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view message)
: View(res, parentView), m_titleStr(title), m_messageStr(message) {
for (int i = 0; i < 16; ++i)
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);
m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf);
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_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1));
}
@ -40,53 +35,50 @@ Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title,
m_title.reset(new TextView(res, *this, res.m_heading14));
m_title->typesetGlyphs(m_titleStr);
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite,
int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, int(TOOLTIP_MAX_TEXT_WIDTH * 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);
m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf),
int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + margin.first * 2));
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3;
}
void Tooltip::setVerts(int width, int height, float pf)
{
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
width = std::max(width, margin.first*2);
height = std::max(height, margin.second*2);
void Tooltip::setVerts(int width, int height, float pf) {
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
width = std::max(width, margin.first * 2);
height = std::max(height, margin.second * 2);
m_ttVerts[0].m_pos.assign(0, height-margin.second, 0);
m_ttVerts[0].m_pos.assign(0, height - margin.second, 0);
m_ttVerts[1].m_pos.assign(0, margin.second, 0);
m_ttVerts[2].m_pos.assign(width, height-margin.second, 0);
m_ttVerts[2].m_pos.assign(width, height - margin.second, 0);
m_ttVerts[3].m_pos.assign(width, margin.second, 0);
m_ttVerts[4].m_pos.assign(width, margin.second, 0);
m_ttVerts[5].m_pos.assign(margin.first, height, 0);
m_ttVerts[6].m_pos.assign(margin.first, height, 0);
m_ttVerts[7].m_pos.assign(margin.first, height-margin.second, 0);
m_ttVerts[8].m_pos.assign(width-margin.first, height, 0);
m_ttVerts[9].m_pos.assign(width-margin.first, height-margin.second, 0);
m_ttVerts[10].m_pos.assign(width-margin.first, height-margin.second, 0);
m_ttVerts[7].m_pos.assign(margin.first, height - margin.second, 0);
m_ttVerts[8].m_pos.assign(width - margin.first, height, 0);
m_ttVerts[9].m_pos.assign(width - margin.first, height - margin.second, 0);
m_ttVerts[10].m_pos.assign(width - margin.first, height - margin.second, 0);
m_ttVerts[11].m_pos.assign(margin.first, margin.second, 0);
m_ttVerts[12].m_pos.assign(margin.first, margin.second, 0);
m_ttVerts[13].m_pos.assign(margin.first, 0, 0);
m_ttVerts[14].m_pos.assign(width-margin.first, margin.second, 0);
m_ttVerts[15].m_pos.assign(width-margin.first, 0, 0);
m_ttVerts[14].m_pos.assign(width - margin.first, margin.second, 0);
m_ttVerts[15].m_pos.assign(width - margin.first, 0, 0);
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);
float pf = rootView().viewRes().pixelFactor();
setVerts(m_nomWidth, m_nomHeight, pf);
m_ttBlock.setViewRect(root, sub);
m_ttBlockBuf.access().finalAssign(m_ttBlock);
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
boo::SWindowRect textRect = sub;
textRect.location[0] += margin.first;
@ -111,16 +103,15 @@ void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
m_cornersFilled[3]->resized(root, cornerRect);
}
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ)
{
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) {
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 16);
for (int i=0 ; i<4 ; ++i)
for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->draw(gfxQ);
m_title->draw(gfxQ);
m_message->draw(gfxQ);
}
}
} // namespace specter

View File

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

View File

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

View File

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

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