TextField updates

This commit is contained in:
Jack Andersen 2015-12-20 11:59:23 -10:00
parent 95fd2f90a9
commit 49ff010a20
12 changed files with 192 additions and 200 deletions

View File

@ -21,7 +21,7 @@ class FileBrowser : public ModalWindow
{ {
FileBrowser& m_fb; FileBrowser& m_fb;
size_t m_idx; size_t m_idx;
Specter::ViewChild<Specter::Button> m_button; Specter::ViewChild<std::unique_ptr<Specter::Button>> m_button;
PathButton(FileBrowser& fb, ViewResources& res, size_t idx, const HECL::SystemString& str) PathButton(FileBrowser& fb, ViewResources& res, size_t idx, const HECL::SystemString& str)
: m_fb(fb), m_idx(idx) : m_fb(fb), m_idx(idx)
{ {
@ -34,7 +34,7 @@ class FileBrowser : public ModalWindow
friend struct PathButton; friend struct PathButton;
std::vector<PathButton> m_pathButtons; std::vector<PathButton> m_pathButtons;
Specter::ViewChild<Specter::TextField> m_fileField; Specter::ViewChild<std::unique_ptr<Specter::TextField>> m_fileField;
struct FileFieldBind : Specter::IStringBinding struct FileFieldBind : Specter::IStringBinding
{ {
FileBrowser& m_browser; FileBrowser& m_browser;
@ -45,8 +45,8 @@ class FileBrowser : public ModalWindow
} }
} m_fileFieldBind; } m_fileFieldBind;
Specter::ViewChild<Specter::ScrollView> m_fileScroll; Specter::ViewChild<std::unique_ptr<Specter::ScrollView>> m_fileScroll;
Specter::ViewChild<Specter::Table> m_fileListing; Specter::ViewChild<std::unique_ptr<Specter::Table>> m_fileListing;
public: public:
FileBrowser(ViewResources& res, View& parentView) FileBrowser(ViewResources& res, View& parentView)

View File

@ -28,6 +28,7 @@ class RootView : public View
IViewManager& m_viewMan; IViewManager& m_viewMan;
ViewResources* m_viewRes; ViewResources* m_viewRes;
View* m_activeTextView = nullptr; View* m_activeTextView = nullptr;
View* m_activeDragView = nullptr;
DeferredWindowEvents<RootView> m_events; DeferredWindowEvents<RootView> m_events;
@ -71,7 +72,12 @@ public:
if (m_activeTextView) if (m_activeTextView)
m_activeTextView->setActive(false); m_activeTextView->setActive(false);
m_activeTextView = textView; m_activeTextView = textView;
textView->setActive(true); if (textView)
textView->setActive(true);
}
void setActiveDragView(View* dragView)
{
m_activeDragView = dragView;
} }
void resetTooltip(ViewResources& res); void resetTooltip(ViewResources& res);

View File

@ -34,13 +34,7 @@ private:
updateSize(); updateSize();
} }
struct Child ViewChild<View*> m_views[2];
{
View* m_view = nullptr;
bool m_mouseIn = false;
bool m_mouseDown = false;
};
Child m_views[2];
ViewBlock m_splitBlock; ViewBlock m_splitBlock;
boo::IGraphicsBufferD* m_splitBlockBuf; boo::IGraphicsBufferD* m_splitBlockBuf;
TexShaderVert m_splitVerts[4]; TexShaderVert m_splitVerts[4];

View File

@ -24,6 +24,11 @@ class TextField : public Control
size_t m_selectionCount = 0; size_t m_selectionCount = 0;
size_t m_cursorPos = 0; size_t m_cursorPos = 0;
size_t m_cursorFrames = 0; size_t m_cursorFrames = 0;
size_t m_clickFrames = 15;
size_t m_clickFrames2 = 15;
size_t m_dragStart = 0;
size_t m_dragging = 0;
bool m_active = false; bool m_active = false;

View File

@ -66,6 +66,16 @@ public:
RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const Zeus::CColor& defaultColor); RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const Zeus::CColor& defaultColor);
}; };
struct RenderGlyphInfo
{
uint32_t m_char;
std::pair<int,int> m_dims;
int m_adv;
bool m_space = false;
RenderGlyphInfo(uint32_t ch, int width, int height, int adv)
: m_char(ch), m_dims(width, height), m_adv(adv), m_space(iswspace(ch)) {}
};
std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;} std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;}
const std::vector<RenderGlyph>& accessGlyphs() const {return m_glyphs;} const std::vector<RenderGlyph>& accessGlyphs() const {return m_glyphs;}
void updateGlyphs() {m_valid = false;} void updateGlyphs() {m_valid = false;}
@ -88,11 +98,11 @@ public:
std::pair<int,int> queryGlyphDimensions(size_t pos) const; std::pair<int,int> queryGlyphDimensions(size_t pos) const;
size_t reverseSelectGlyph(int x) const; size_t reverseSelectGlyph(int x) const;
int queryReverseAdvance(size_t idx) const; int queryReverseAdvance(size_t idx) const;
std::pair<size_t,size_t> queryWholeWordRange(size_t idx) const;
private: private:
std::vector<RenderGlyph> m_glyphs; std::vector<RenderGlyph> m_glyphs;
std::vector<std::pair<int,int>> m_glyphDims; std::vector<RenderGlyphInfo> m_glyphInfo;
std::vector<int> m_glyphAdvs;
}; };
} }

View File

@ -25,14 +25,7 @@ public:
}; };
private: private:
Position m_tbPos; Position m_tbPos;
struct Child std::vector<ViewChild<View*>> m_children;
{
View* m_view = nullptr;
bool m_mouseIn = false;
bool m_mouseDown = false;
Child(View* v) : m_view(v) {}
};
std::vector<Child> m_children;
ViewBlock m_tbBlock; ViewBlock m_tbBlock;
boo::IGraphicsBufferD* m_tbBlockBuf; boo::IGraphicsBufferD* m_tbBlockBuf;
@ -106,7 +99,11 @@ public:
int nominalHeight() const {return m_nomHeight;} int nominalHeight() const {return m_nomHeight;}
void clear() {m_children.clear();} void clear() {m_children.clear();}
void push_back(View* v) {m_children.push_back(v);} void push_back(View* v)
{
m_children.emplace_back();
m_children.back().m_view = v;
}
}; };
} }

View File

@ -209,12 +209,12 @@ public:
virtual void draw(boo::IGraphicsCommandQueue* gfxQ); virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
template <class ViewType> template <class ViewPtrType>
struct ViewChild struct ViewChild
{ {
std::unique_ptr<ViewType> m_view; ViewPtrType m_view;
bool m_mouseIn = false; bool m_mouseIn = false;
bool m_mouseDown = false; int m_mouseDown = 0;
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{ {
@ -222,10 +222,10 @@ struct ViewChild
return; return;
if (m_view->subRect().coordInRect(coord)) if (m_view->subRect().coordInRect(coord))
{ {
if (!m_mouseDown) if ((m_mouseDown & 1 << int(button)) == 0)
{ {
m_view->mouseDown(coord, button, mod); m_view->mouseDown(coord, button, mod);
m_mouseDown = true; m_mouseDown |= 1 << int(button);
} }
} }
} }
@ -234,10 +234,10 @@ struct ViewChild
{ {
if (!m_view) if (!m_view)
return; return;
if (m_mouseDown) if ((m_mouseDown & 1 << int(button)) != 0)
{ {
m_view->mouseUp(coord, button, mod); m_view->mouseUp(coord, button, mod);
m_mouseDown = false; m_mouseDown &= ~(1 << int(button));
} }
} }

View File

@ -38,6 +38,8 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{ {
if (m_activeTextView && !m_activeTextView->subRect().coordInRect(coord))
setActiveTextView(nullptr);
if (m_view) if (m_view)
m_view->mouseDown(coord, button, mods); m_view->mouseDown(coord, button, mods);
} }
@ -52,6 +54,8 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
{ {
if (m_view) if (m_view)
m_view->mouseMove(coord); m_view->mouseMove(coord);
if (m_activeDragView)
m_activeDragView->mouseMove(coord);
boo::SWindowRect ttrect = m_rootRect; boo::SWindowRect ttrect = m_rootRect;
ttrect.location[0] = coord.pixel[0]; ttrect.location[0] = coord.pixel[0];

View File

@ -57,7 +57,7 @@ View* SplitView::setContentView(int slot, View* view)
Log.report(LogVisor::FatalError, "out-of-range slot to RootView::SplitView::setContentView"); Log.report(LogVisor::FatalError, "out-of-range slot to RootView::SplitView::setContentView");
View* ret = m_views[slot].m_view; View* ret = m_views[slot].m_view;
m_views[slot].m_view = view; m_views[slot].m_view = view;
m_views[slot].m_mouseDown = false; m_views[slot].m_mouseDown = 0;
m_views[slot].m_mouseIn = false; m_views[slot].m_mouseIn = false;
updateSize(); updateSize();
return ret; return ret;
@ -99,34 +99,16 @@ void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butt
return; return;
} }
} }
if (m_views[0].m_view && !m_views[0].m_mouseDown && m_views[0].mouseDown(coord, button, mod);
m_views[0].m_view->subRect().coordInRect(coord)) m_views[1].mouseDown(coord, button, mod);
{
m_views[0].m_view->mouseDown(coord, button, mod);
m_views[0].m_mouseDown = true;
}
if (m_views[1].m_view && !m_views[1].m_mouseDown &&
m_views[1].m_view->subRect().coordInRect(coord))
{
m_views[1].m_view->mouseDown(coord, button, mod);
m_views[1].m_mouseDown = true;
}
} }
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)
{ {
if (button == boo::EMouseButton::Primary) if (button == boo::EMouseButton::Primary)
m_dragging = false; m_dragging = false;
if (m_views[0].m_view && m_views[0].m_mouseDown) m_views[0].mouseUp(coord, button, mod);
{ m_views[1].mouseUp(coord, button, mod);
m_views[0].m_view->mouseUp(coord, button, mod);
m_views[0].m_mouseDown = false;
}
if (m_views[1].m_view && m_views[1].m_mouseDown)
{
m_views[1].m_view->mouseUp(coord, button, mod);
m_views[1].m_mouseDown = false;
}
} }
void SplitView::mouseMove(const boo::SWindowCoord& coord) void SplitView::mouseMove(const boo::SWindowCoord& coord)
@ -152,64 +134,20 @@ void SplitView::mouseMove(const boo::SWindowCoord& coord)
rootView().window()->setCursor(boo::EMouseCursor::Pointer); rootView().window()->setCursor(boo::EMouseCursor::Pointer);
} }
if (m_views[0].m_view) m_views[0].mouseMove(coord);
{ m_views[1].mouseMove(coord);
if (m_views[0].m_view->subRect().coordInRect(coord))
{
if (!m_views[0].m_mouseIn)
{
m_views[0].m_view->mouseEnter(coord);
m_views[0].m_mouseIn = true;
}
m_views[0].m_view->mouseMove(coord);
}
else
{
if (m_views[0].m_mouseIn)
{
m_views[0].m_view->mouseLeave(coord);
m_views[0].m_mouseIn = false;
}
}
}
if (m_views[1].m_view)
{
if (m_views[1].m_view->subRect().coordInRect(coord))
{
if (!m_views[1].m_mouseIn)
{
m_views[1].m_view->mouseEnter(coord);
m_views[1].m_mouseIn = true;
}
m_views[1].m_view->mouseMove(coord);
}
else
{
if (m_views[1].m_mouseIn)
{
m_views[1].m_view->mouseLeave(coord);
m_views[1].m_mouseIn = false;
}
}
}
} }
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)
{ {
if (m_views[0].m_view && m_views[0].m_mouseIn) m_views[0].mouseLeave(coord);
{ m_views[1].mouseLeave(coord);
m_views[0].m_view->mouseLeave(coord);
m_views[0].m_mouseIn = false;
}
if (m_views[1].m_view && m_views[1].m_mouseIn)
{
m_views[1].m_view->mouseLeave(coord);
m_views[1].m_mouseIn = false;
}
} }
void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)

View File

@ -45,17 +45,17 @@ TextField::TextField(ViewResources& res, View& parentView, IStringBinding* strBi
m_bVertsBuf->load(m_verts, sizeof(m_verts)); m_bVertsBuf->load(m_verts, sizeof(m_verts));
m_text.reset(new TextView(res, *this, res.m_mainFont, TextView::Alignment::Left, 1024)); m_text.reset(new TextView(res, *this, res.m_mainFont, TextView::Alignment::Left, 1024));
setText("Test"); setText("テスト");
} }
void TextField::setText(const std::string& str) void TextField::setText(const std::string& str)
{ {
clearSelectionRange(); clearSelectionRange();
auto it = str.cbegin(); UTF8Iterator it(str.cbegin());
for (; it != str.cend() ; ++it) for (; it.iter() != str.cend() ; ++it)
if (*it == '\n') if (*it.iter() == '\n')
break; break;
m_textStr.assign(str.cbegin(), it); m_textStr.assign(str.cbegin(), it.iter());
m_text->typesetGlyphs(m_textStr, rootView().themeData().fieldText()); m_text->typesetGlyphs(m_textStr, rootView().themeData().fieldText());
} }
@ -95,18 +95,49 @@ void TextField::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butt
{ {
rootView().setActiveTextView(this); rootView().setActiveTextView(this);
if (!m_selectionCount) if (!m_selectionCount)
setSelectionRange(0, m_textStr.size()); setSelectionRange(0, m_text->accessGlyphs().size());
}
else if (m_clickFrames2 < 15)
{
setSelectionRange(0, m_text->accessGlyphs().size());
}
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);
setSelectionRange(range.first, range.second);
m_clickFrames2 = 0;
} }
else else
setCursorPos(m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0])); {
size_t startPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]);
setCursorPos(startPos);
m_dragging |= 1 << int(button);
m_dragStart = startPos;
rootView().setActiveDragView(this);
}
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 &= ~(1 << int(button));
if (m_dragging == 0)
rootView().setActiveDragView(nullptr);
} }
void TextField::mouseMove(const boo::SWindowCoord& coord) void TextField::mouseMove(const boo::SWindowCoord& coord)
{ {
if (m_dragging != 0)
{
size_t thisPos = m_text->reverseSelectGlyph(coord.pixel[0] - m_text->subRect().location[0]);
size_t minPos = std::min(m_dragStart, thisPos);
size_t maxPos = std::max(m_dragStart, thisPos);
if (minPos != maxPos)
setSelectionRange(minPos, maxPos-minPos);
else
setCursorPos(minPos);
}
} }
void TextField::mouseEnter(const boo::SWindowCoord& coord) void TextField::mouseEnter(const boo::SWindowCoord& coord)
@ -125,23 +156,26 @@ void TextField::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool
{ {
if (m_selectionCount) if (m_selectionCount)
{ {
std::string newStr(m_textStr.cbegin(), m_textStr.cbegin() + m_selectionStart); std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_selectionStart).iter());
utf8proc_uint8_t theChar[5] = {}; utf8proc_uint8_t theChar[5] = {};
utf8proc_ssize_t sz = utf8proc_encode_char(charCode, theChar); utf8proc_ssize_t sz = utf8proc_encode_char(charCode, theChar);
if (sz > 0) if (sz > 0)
newStr += (char*)theChar; newStr += (char*)theChar;
newStr.append(m_textStr.cbegin() + m_selectionStart + m_selectionCount, m_textStr.cend()); newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), m_textStr.cend());
size_t selStart = m_selectionStart;
setText(newStr); setText(newStr);
setCursorPos(selStart + 1);
} }
else else
{ {
std::string newStr(m_textStr.cbegin(), m_textStr.cbegin() + m_cursorPos); std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter());
utf8proc_uint8_t theChar[5] = {}; utf8proc_uint8_t theChar[5] = {};
utf8proc_ssize_t sz = utf8proc_encode_char(charCode, theChar); utf8proc_ssize_t sz = utf8proc_encode_char(charCode, theChar);
if (sz > 0) if (sz > 0)
newStr += (char*)theChar; newStr += (char*)theChar;
newStr.append(m_textStr.cbegin() + m_cursorPos, m_textStr.cend()); newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter(), m_textStr.cend());
setText(newStr); setText(newStr);
setCursorPos(m_cursorPos + 1);
} }
} }
@ -159,11 +193,49 @@ void TextField::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, boo
m_cursorPos = m_selectionStart + m_selectionCount - 1; m_cursorPos = m_selectionStart + m_selectionCount - 1;
setCursorPos(m_cursorPos+1); setCursorPos(m_cursorPos+1);
} }
else if (key == boo::ESpecialKey::Backspace)
{
if (m_selectionCount)
{
std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_selectionStart).iter());
newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), m_textStr.cend());
size_t selStart = m_selectionStart;
setText(newStr);
setCursorPos(selStart);
}
else if (m_cursorPos > 0)
{
std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + (m_cursorPos-1)).iter());
newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter(), m_textStr.cend());
setText(newStr);
setCursorPos(m_cursorPos-1);
}
}
else if (key == boo::ESpecialKey::Delete)
{
if (m_selectionCount)
{
std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_selectionStart).iter());
newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), m_textStr.cend());
size_t selStart = m_selectionStart;
setText(newStr);
setCursorPos(selStart);
}
else if (m_cursorPos < m_text->accessGlyphs().size())
{
std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter());
newStr.append((UTF8Iterator(m_textStr.cbegin()) + (m_cursorPos+1)).iter(), m_textStr.cend());
setText(newStr);
setCursorPos(m_cursorPos);
}
}
} }
void TextField::think() void TextField::think()
{ {
++m_cursorFrames; ++m_cursorFrames;
++m_clickFrames;
++m_clickFrames2;
} }
void TextField::setActive(bool active) void TextField::setActive(bool active)
@ -176,7 +248,7 @@ void TextField::setActive(bool active)
void TextField::setCursorPos(size_t pos) void TextField::setCursorPos(size_t pos)
{ {
clearSelectionRange(); clearSelectionRange();
m_cursorPos = std::min(pos, m_textStr.size()); m_cursorPos = std::min(pos, m_text->accessGlyphs().size());
m_cursorFrames = 0; m_cursorFrames = 0;
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
@ -191,8 +263,8 @@ void TextField::setCursorPos(size_t pos)
void TextField::setSelectionRange(size_t start, size_t count) void TextField::setSelectionRange(size_t start, size_t count)
{ {
m_selectionStart = std::min(start, m_textStr.size()-1); m_selectionStart = std::min(start, m_text->accessGlyphs().size()-1);
m_selectionCount = std::min(count, m_textStr.size()-m_selectionStart); m_selectionCount = std::min(count, m_text->accessGlyphs().size()-m_selectionStart);
ViewResources& res = rootView().viewRes(); ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor(); float pf = res.pixelFactor();

View File

@ -353,10 +353,8 @@ void TextView::typesetGlyphs(const std::string& str, const Zeus::CColor& default
uint32_t lCh = -1; uint32_t lCh = -1;
m_glyphs.clear(); m_glyphs.clear();
m_glyphs.reserve(str.size()); m_glyphs.reserve(str.size());
m_glyphDims.clear(); m_glyphInfo.clear();
m_glyphDims.reserve(str.size()); m_glyphInfo.reserve(str.size());
m_glyphAdvs.clear();
m_glyphAdvs.reserve(str.size());
int adv = 0; int adv = 0;
while (rem) while (rem)
@ -379,8 +377,7 @@ void TextView::typesetGlyphs(const std::string& str, const Zeus::CColor& default
if (lCh != -1) if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas); adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor); m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphDims.emplace_back(glyph->m_width, glyph->m_height); m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
m_glyphAdvs.push_back(adv);
lCh = glyph->m_glyphIdx; lCh = glyph->m_glyphIdx;
rem -= sz; rem -= sz;
@ -423,10 +420,8 @@ void TextView::typesetGlyphs(const std::wstring& str, const Zeus::CColor& defaul
uint32_t lCh = -1; uint32_t lCh = -1;
m_glyphs.clear(); m_glyphs.clear();
m_glyphs.reserve(str.size()); m_glyphs.reserve(str.size());
m_glyphDims.clear(); m_glyphInfo.clear();
m_glyphDims.reserve(str.size()); m_glyphInfo.reserve(str.size());
m_glyphAdvs.clear();
m_glyphAdvs.reserve(str.size());
int adv = 0; int adv = 0;
for (wchar_t ch : str) for (wchar_t ch : str)
@ -441,8 +436,7 @@ void TextView::typesetGlyphs(const std::wstring& str, const Zeus::CColor& defaul
if (lCh != -1) if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas); adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor); m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphDims.emplace_back(glyph->m_width, glyph->m_height); m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
m_glyphAdvs.push_back(adv);
lCh = glyph->m_glyphIdx; lCh = glyph->m_glyphIdx;
@ -514,12 +508,12 @@ void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
std::pair<int,int> TextView::queryGlyphDimensions(size_t pos) const std::pair<int,int> TextView::queryGlyphDimensions(size_t pos) const
{ {
if (pos >= m_glyphDims.size()) if (pos >= m_glyphInfo.size())
Log.report(LogVisor::FatalError, Log.report(LogVisor::FatalError,
"TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize, "TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize,
pos, m_glyphDims.size()); pos, m_glyphInfo.size());
return m_glyphDims[pos]; return m_glyphInfo[pos].m_dims;
} }
size_t TextView::reverseSelectGlyph(int x) const size_t TextView::reverseSelectGlyph(int x) const
@ -527,9 +521,9 @@ size_t TextView::reverseSelectGlyph(int x) const
size_t ret = 0; size_t ret = 0;
size_t idx = 1; size_t idx = 1;
int minDelta = abs(x); int minDelta = abs(x);
for (int adv : m_glyphAdvs) for (const RenderGlyphInfo& info : m_glyphInfo)
{ {
int thisDelta = abs(adv-x); int thisDelta = abs(info.m_adv-x);
if (thisDelta < minDelta) if (thisDelta < minDelta)
{ {
minDelta = thisDelta; minDelta = thisDelta;
@ -542,12 +536,35 @@ size_t TextView::reverseSelectGlyph(int x) const
int TextView::queryReverseAdvance(size_t idx) const int TextView::queryReverseAdvance(size_t idx) const
{ {
if (idx > m_glyphAdvs.size()) if (idx > m_glyphInfo.size())
Log.report(LogVisor::FatalError, Log.report(LogVisor::FatalError,
"TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize, "TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphAdvs.size()); idx, m_glyphInfo.size());
if (!idx) return 0; if (!idx) return 0;
return m_glyphAdvs[idx-1]; return m_glyphInfo[idx-1].m_adv;
}
std::pair<size_t,size_t> TextView::queryWholeWordRange(size_t idx) const
{
if (idx > m_glyphInfo.size())
Log.report(LogVisor::FatalError,
"TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphInfo.size());
if (m_glyphInfo.empty())
return {0,0};
if (idx == m_glyphInfo.size())
--idx;
size_t begin = idx;
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};
} }
} }

View File

@ -59,83 +59,32 @@ Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos)
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)
{ {
boo::SWindowRect childRect = subRect(); for (ViewChild<View*>& c : m_children)
int subLoc1 = childRect.location[1]; c.mouseDown(coord, button, mod);
for (Child& c : m_children)
{
childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight();
childRect.location[0] += m_padding;
childRect.location[1] = subLoc1 + (m_nomHeight - childRect.size[1]) / 2 - 1;
if (childRect.coordInRect(coord))
{
if (!c.m_mouseDown)
{
c.m_view->mouseDown(coord, button, mod);
c.m_mouseDown = true;
}
}
childRect.location[0] += childRect.size[0];
}
} }
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 (Child& c : m_children) for (ViewChild<View*>& c : m_children)
{ c.mouseUp(coord, button, mod);
if (c.m_mouseDown)
{
c.m_view->mouseUp(coord, button, mod);
c.m_mouseDown = false;
}
}
} }
void Toolbar::mouseMove(const boo::SWindowCoord& coord) void Toolbar::mouseMove(const boo::SWindowCoord& coord)
{ {
boo::SWindowRect childRect = subRect(); for (ViewChild<View*>& c : m_children)
int subLoc1 = childRect.location[1]; c.mouseMove(coord);
for (Child& c : m_children)
{
childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight();
childRect.location[0] += m_padding;
childRect.location[1] = subLoc1 + (m_nomHeight - childRect.size[1]) / 2 - 1;
if (childRect.coordInRect(coord))
{
if (!c.m_mouseIn)
{
c.m_view->mouseEnter(coord);
c.m_mouseIn = true;
}
c.m_view->mouseMove(coord);
}
else
{
if (c.m_mouseIn)
{
c.m_view->mouseLeave(coord);
c.m_mouseIn = false;
}
}
childRect.location[0] += childRect.size[0];
}
} }
void Toolbar::mouseEnter(const boo::SWindowCoord& coord) void Toolbar::mouseEnter(const boo::SWindowCoord& coord)
{ {
for (ViewChild<View*>& c : m_children)
c.mouseEnter(coord);
} }
void Toolbar::mouseLeave(const boo::SWindowCoord& coord) void Toolbar::mouseLeave(const boo::SWindowCoord& coord)
{ {
for (Child& c : m_children) for (ViewChild<View*>& c : m_children)
{ c.mouseLeave(coord);
if (c.m_mouseIn)
{
c.m_view->mouseLeave(coord);
c.m_mouseIn = false;
}
}
} }
void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
@ -147,7 +96,7 @@ void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
m_tbBlockBuf->load(&m_tbBlock, sizeof(ViewBlock)); m_tbBlockBuf->load(&m_tbBlock, sizeof(ViewBlock));
boo::SWindowRect childRect = sub; boo::SWindowRect childRect = sub;
for (Child& c : m_children) for (ViewChild<View*>& c : m_children)
{ {
childRect.size[0] = c.m_view->nominalWidth(); childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight(); childRect.size[1] = c.m_view->nominalHeight();
@ -165,7 +114,7 @@ void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ)
gfxQ->setDrawPrimitive(boo::Primitive::TriStrips); gfxQ->setDrawPrimitive(boo::Primitive::TriStrips);
gfxQ->draw(0, 10); gfxQ->draw(0, 10);
for (Child& c : m_children) for (ViewChild<View*>& c : m_children)
c.m_view->draw(gfxQ); c.m_view->draw(gfxQ);
} }