Mon, 07 Jun 2021 20:56:13 +0300
#320 Textare is finished
--- a/Source/Gorgon/Widgets/Textarea.cpp Sun Jun 06 17:44:07 2021 +0300 +++ b/Source/Gorgon/Widgets/Textarea.cpp Mon Jun 07 20:56:13 2021 +0300 @@ -9,6 +9,7 @@ ScrollingWidget(temp), PropType(helper), AutoSelectAll(this), + WordWrap(this), Readonly(this) { overscroll = temp.GetSpacing() * 4; @@ -36,6 +37,8 @@ repeater.Register(Input::Keyboard::Keycodes::Right); repeater.Register(Input::Keyboard::Keycodes::Down); repeater.Register(Input::Keyboard::Keycodes::Up); + repeater.Register(Input::Keyboard::Keycodes::PageDown); + repeater.Register(Input::Keyboard::Keycodes::PageUp); repeater.Register(Input::Keyboard::Keycodes::Backspace); repeater.Register(Input::Keyboard::Keycodes::Delete); repeater.Register(Input::Keyboard::Keycodes::Enter); @@ -150,6 +153,26 @@ updateselection(); } + else if(key == Input::Keyboard::Keycodes::PageUp) { + glyphbyte selprev = selstart; + sellen = {0, 0}; + + moveselpageup(); + sellen = {selstart.glyph - selprev.glyph, selstart.byte - selprev.byte}; + selstart = selprev; + + updateselection(); + } + else if(key == Input::Keyboard::Keycodes::PageDown) { + glyphbyte selprev = selstart; + sellen = {0, 0}; + + moveselpagedown(); + sellen = {selstart.glyph - selprev.glyph, selstart.byte - selprev.byte}; + selstart = selprev; + + updateselection(); + } } else if(Input::Keyboard::CurrentModifier == Modifier::None) { @@ -216,6 +239,14 @@ moveseldown(); updateselection(); } + else if(key == Keycodes::PageUp) { + moveselpageup(); + updateselection(); + } + else if(key == Keycodes::PageDown) { + moveselpagedown(); + updateselection(); + } } } }); @@ -289,6 +320,16 @@ SelectAll(); return true; + + case Keycodes::Home: + selstart = {0, 0}; + updateselection(); + return true; + + case Keycodes::End: + selstart = selstart = {Length(), (int)text.size()}; + updateselection(); + return true; case Keycodes::C: { std::string s = GetSelectedText(); @@ -377,7 +418,7 @@ std::cout << selstart.glyph << " : " << sellen.glyph << std::endl; updatecursor(); - if(sellen.byte != 0) { + if(sellen.byte != 0 && IsFocused()) { auto s = selstart.byte; auto e = s + sellen.byte; @@ -391,7 +432,7 @@ nw += text.substr(e); stack.SetData(UI::ComponentTemplate::Text, nw); selectionin = true; - } + } else if(selectionin) { stack.SetData(UI::ComponentTemplate::Text, text); selectionin = false; @@ -418,6 +459,8 @@ dirty = false; } } + + updateselection(); } void Textarea::mousedown(UI::ComponentTemplate::Tag, Geometry::Point location, Input::Mouse::Button button) { @@ -532,7 +575,7 @@ void Textarea::moveselup() { auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag); selstart.glyph = printer->GetCharacterIndex( - text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y-1} + ScrollOffset(), wrap + text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y-1}, wrap ); selstart.byte = getbyteoffset(selstart.glyph); sellen = {0, 0}; @@ -542,7 +585,7 @@ void Textarea::moveseldown() { auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag); selstart.glyph = printer->GetCharacterIndex( - text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y+1+printer->GetHeight()} + ScrollOffset(), wrap + text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y+1+printer->GetHeight()}, wrap ); selstart.byte = getbyteoffset(selstart.glyph); sellen = {0, 0}; @@ -550,6 +593,27 @@ } + void Textarea::moveselpageup() { + auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag); + auto mysize = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).GetSize(); + selstart.glyph = printer->GetCharacterIndex( + text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y+1+printer->GetHeight()-mysize.Height}, wrap + ); + selstart.byte = getbyteoffset(selstart.glyph); + sellen = {0, 0}; + updateselection(); + } + + void Textarea::moveselpagedown() { + auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag); + auto mysize = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).GetSize(); + selstart.glyph = printer->GetCharacterIndex( + text, bounds.GetSize().Width, Geometry::Point{cursorlocation.X, cursorlocation.Y-printer->GetHeight()+mysize.Height}, wrap + ); + selstart.byte = getbyteoffset(selstart.glyph); + sellen = {0, 0}; + updateselection(); + } void Textarea::SetReadonly(const bool& value) { if(value == readonly) @@ -566,9 +630,6 @@ } bool Textarea::Done() { - if(autoselectall) - SelectAll(); - if(!dirty) return true; @@ -627,24 +688,23 @@ else pos += sellen.glyph; - auto pcurloc = cursorlocation; if(text == "") { cursorlocation = {0, 0}; } else { - cursorlocation = printer->GetPosition(text, stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width(), pos, wrap).TopLeft() - scrolloffset; + cursorlocation = printer->GetPosition(text, stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width(), pos, wrap).TopLeft(); } if(text == "") { stack.RemoveTagLocation(UI::ComponentTemplate::CaretTag); } else { - stack.SetTagLocation(UI::ComponentTemplate::CaretTag, {cursorlocation.X, cursorlocation.Y}); + stack.SetTagLocation(UI::ComponentTemplate::CaretTag, Geometry::Point{cursorlocation.X, cursorlocation.Y} - scrolloffset); } if(pos != curcursorpos) { curcursorpos = pos; - ensurevisible({cursorlocation + scrolloffset, 0, printer->GetHeight()}); + ensurevisible({cursorlocation, 0, printer->GetHeight()}); } } @@ -682,4 +742,24 @@ return byte; } + + void Textarea::SetWordWrap(const bool &value) { + if(wrap == value) + return; + + wrap = value; + if(wrap) { + stack.EnableTagWrap(UI::ComponentTemplate::ContentsTag); + } + else + stack.DisableTagWrap(UI::ComponentTemplate::ContentsTag); + + enablescroll(true, !wrap); + updateselection(); + updatebars(); + + if(wrap) + ScrollTo(0, ScrollOffset().Y); + } + } }
--- a/Source/Gorgon/Widgets/Textarea.h Sun Jun 06 17:44:07 2021 +0300 +++ b/Source/Gorgon/Widgets/Textarea.h Mon Jun 07 20:56:13 2021 +0300 @@ -219,6 +219,13 @@ return readonly; } + void SetWordWrap(const bool &value); + + + bool GetWordWrap() const { + return wrap; + } + /// Controls if the inputbox will be auto selected recieving focus /// or right after the user is done with editing. Default is false. @@ -226,6 +233,12 @@ &Textarea::GetAutoSelectAll, &Textarea::SetAutoSelectAll> AutoSelectAll; + /// Controls if the text in the text area will be wrapped. Disabling wordwrap will enable + /// horizontal scroll + BooleanProperty< Textarea, bool, + &Textarea::GetWordWrap, + &Textarea::SetWordWrap> WordWrap; + /// When set to true, the value contained in the inputbox cannot be edited /// by the user. Default is false. BooleanProperty< Textarea, bool, @@ -265,6 +278,10 @@ void moveselup(); void moveseldown(); + + void moveselpageup(); + + void moveselpagedown(); void eraseselected();
--- a/Testing/Source/Manual/UI_WidgetTest.cpp Sun Jun 06 17:44:07 2021 +0300 +++ b/Testing/Source/Manual/UI_WidgetTest.cpp Mon Jun 07 20:56:13 2021 +0300 @@ -6,6 +6,7 @@ #include <Gorgon/UI/Organizers/Flow.h> #include <Gorgon/Widgets/Window.h> #include <Gorgon/Widgets/Textarea.h> +#include <Gorgon/Widgets/Checkbox.h> std::string helptext = "Key list:\n" @@ -20,8 +21,13 @@ auto &org = app.wind.CreateOrganizer<UI::Organizers::Flow>(); Widgets::Textarea wgt1("Hello world\nI am a text area\n1\n2\n3\n4\n5"); + Widgets::Checkbox wrap("Wrap", true); + wrap.ChangedEvent.Register([&]{ + wgt1.WordWrap = (bool)wrap; + }); org + << wrap << org.Break << wgt1 ; wgt1.SetText(wgt1.GetText() + "A lot more text is written in here...");