#320 Bugs are fixed 4.x-dev

Sat, 22 May 2021 22:31:59 +0300

author
cemkalyoncu
date
Sat, 22 May 2021 22:31:59 +0300
branch
4.x-dev
changeset 1686
5fc838d40d0f
parent 1685
fbdaffb00e02
child 1687
dc9150a2185d

#320 Bugs are fixed
Enter, home, end, up, down
Shift+up/down is still not working

Source/Gorgon/Widgets/Textarea.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Textarea.h file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/Widgets/Textarea.cpp	Sat May 22 11:33:17 2021 +0300
+++ b/Source/Gorgon/Widgets/Textarea.cpp	Sat May 22 22:31:59 2021 +0300
@@ -34,8 +34,12 @@
         
         repeater.Register(Input::Keyboard::Keycodes::Left);
         repeater.Register(Input::Keyboard::Keycodes::Right);
+        repeater.Register(Input::Keyboard::Keycodes::Down);
+        repeater.Register(Input::Keyboard::Keycodes::Up);
         repeater.Register(Input::Keyboard::Keycodes::Backspace);
         repeater.Register(Input::Keyboard::Keycodes::Delete);
+        repeater.Register(Input::Keyboard::Keycodes::Enter);
+        repeater.Register(Input::Keyboard::Keycodes::Numpad_Enter);
 
         repeater.SetRepeatOnPress(true);
 
@@ -94,6 +98,11 @@
 
                 return;
             }
+            
+            if(key == Keycodes::Enter || key == Keycodes::Numpad_Enter) {
+                CharacterPressed('\n');    
+                return ;
+            }
 
             if(Input::Keyboard::CurrentModifier == Modifier::Shift) {
                 if(sellen.byte == allselected) {
@@ -151,6 +160,20 @@
                             moveselright();
                         }
                     }
+                    if(key == Keycodes::Up) {
+                        if(sellen.byte < 0) {
+                            selstart += sellen;
+
+                            moveselup();
+                        }
+                    }
+                    else if(key == Keycodes::Down) {
+                        if(sellen.byte > 0) {
+                            selstart += sellen;
+
+                            moveseldown();
+                        }
+                    }
 
                     sellen = {0, 0};
 
@@ -165,6 +188,14 @@
                         moveselright();
                         updateselection();
                     }
+                    else if(key == Keycodes::Up) {
+                        moveselup();
+                        updateselection();
+                    }
+                    else if(key == Keycodes::Down) {
+                        moveseldown();
+                        updateselection();
+                    }
                 }
             }
         });
@@ -185,32 +216,32 @@
                 return false;
             
             if(Input::Keyboard::CurrentModifier == Modifier::None) {
+                
                 switch(key) {
-                case Keycodes::Home:
-                    selstart = {0, 0};
+                case Keycodes::Home: {
+                    auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
+                    selstart.glyph = printer->GetCharacterIndex(
+                        text, bounds.GetSize().Width, {-1, cursorlocation.Y+1}, true
+                    );
+                    selstart.byte = getbyteoffset(selstart.glyph);
                     sellen = {0, 0};
                     updateselection();
 
                     return true;
+                }
 
-                case Keycodes::End:
-                    selstart = {Length(), (int)text.size()};
+                case Keycodes::End: {
+                    auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
+                    selstart.glyph = printer->GetCharacterIndex(
+                        text, bounds.GetSize().Width, 
+                        {std::numeric_limits<int>::max(), cursorlocation.Y+1}, true
+                    );
+                    selstart.byte = getbyteoffset(selstart.glyph);
                     sellen = {0, 0};
                     updateselection();
 
                     return true;
-
-                case Keycodes::Enter:
-                case Keycodes::Numpad_Enter:
-                    //TODO enter
-                    if(!readonly) {
-                        Done();
-                        
-                        ChangedEvent(text);
-                        dirty = false;
-                    }
-                    
-                    return true;
+                }
                 }
             }
             else if(Input::Keyboard::CurrentModifier == Modifier::Ctrl) {
@@ -357,39 +388,16 @@
         
         ismousedown = true;
         
-        //for font
-        int idx = stack.IndexOfTag(UI::ComponentTemplate::ContentsTag);
-
-        //no contents??!!
-        if(idx == -1)
-            return;
-
-        //contents is not a textholder
-        auto &temp = stack.GetTemplate(idx);
-        if(temp.GetType() != UI::ComponentType::Textholder)
-            return;
-
-        auto &textt = dynamic_cast<const UI::TextholderTemplate&>(temp);
-
-        //no renderer is set or renderer is not in valid state
-        if(!textt.IsReady())
-            return;
-
-        auto &renderer = textt.GetRenderer();
+        checkprinter();
         
-        auto bounds = stack.BoundsOf(idx);
+        auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
         
         location -= bounds.TopLeft();
         
-        selstart.glyph = renderer.GetCharacterIndex(text, bounds.Width(), location, true);
+        selstart.glyph = printer->GetCharacterIndex(text, bounds.Width(), location, true);
         selstart.byte  = 0;
-        int g = selstart.glyph;
-        pglyph = g;
-        
-        while(g) {
-            selstart.byte += String::UTF8Bytes(text[selstart.byte]);
-            g--;
-        }
+        pglyph = selstart.glyph;
+        selstart.byte = getbyteoffset(selstart.glyph);
         
         sellen = {0,0};
         
@@ -404,43 +412,20 @@
             return;
         }
         
-        //for font
-        int idx = stack.IndexOfTag(UI::ComponentTemplate::ContentsTag);
-
-        //no contents??!!
-        if(idx == -1)
-            return;
-
-        //contents is not a textholder
-        auto &temp = stack.GetTemplate(idx);
-        if(temp.GetType() != UI::ComponentType::Textholder)
-            return;
-
-        auto &textt = dynamic_cast<const UI::TextholderTemplate&>(temp);
-
-        //no renderer is set or renderer is not in valid state
-        if(!textt.IsReady())
-            return;
-
-        auto &renderer = textt.GetRenderer();
+        checkprinter();
         
-        auto bounds = stack.BoundsOf(idx);
+        auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
         
         location -= bounds.TopLeft();
         
-        int glyph = renderer.GetCharacterIndex(text, bounds.Width(), location, true);
+        int glyph = printer->GetCharacterIndex(text, bounds.Width(), location, true);
         
         if(glyph == pglyph)
             return;
         
         pglyph = glyph;
         
-        int byte  = 0;
-        int g = glyph;
-        while(g) {
-            byte += String::UTF8Bytes(text[byte]);
-            g--;
-        }
+        int byte  = getbyteoffset(glyph);
         
         sellen.glyph = glyph - selstart.glyph;
         sellen.byte  = byte  - selstart.byte;
@@ -500,6 +485,27 @@
         }
     }
 
+    void Textarea::moveselup() {
+        auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
+        selstart.glyph = printer->GetCharacterIndex(
+            text, bounds.GetSize().Width, {cursorlocation.X, cursorlocation.Y+1-printer->GetHeight()}, true
+        );
+        selstart.byte = getbyteoffset(selstart.glyph);
+        sellen = {0, 0};
+        updateselection();
+    }
+
+    void Textarea::moveseldown() {
+        auto bounds = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
+        selstart.glyph = printer->GetCharacterIndex(
+            text, bounds.GetSize().Width, {cursorlocation.X, cursorlocation.Y+1+printer->GetHeight()}, true
+        );
+        selstart.byte = getbyteoffset(selstart.glyph);
+        sellen = {0, 0};
+        updateselection();
+    }
+
+
 
     void Textarea::SetReadonly(const bool& value) {
         if(value == readonly)
@@ -554,25 +560,7 @@
     }
     
     void Textarea::updatecursor() {
-        //for font
-        int idx = stack.IndexOfTag(UI::ComponentTemplate::ContentsTag);
-
-        //no contents??!!
-        if(idx == -1)
-            return;
-
-        //contents is not a textholder
-        auto &temp = stack.GetTemplate(idx);
-        if(temp.GetType() != UI::ComponentType::Textholder)
-            return;
-
-        auto &textt = dynamic_cast<const UI::TextholderTemplate&>(temp);
-
-        //no renderer is set or renderer is not in valid state
-        if(!textt.IsReady())
-            return;
-        
-        auto &renderer = textt.GetRenderer();
+        checkprinter();
         
         if(selstart.byte < 0) {
             selstart  = {0, 0};
@@ -595,22 +583,53 @@
         else
             pos += sellen.glyph;
         
-        
-        Geometry::Point location;
-        
         if(text == "") {
-            location = {0, 0};
+            cursorlocation = {0, 0};
         }
         else {
-            location = renderer.GetPosition(text, stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width(), pos, true).TopLeft() - scrolloffset;
+            cursorlocation = printer->GetPosition(text, stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width(), pos, true).TopLeft() - scrolloffset;
         }
         
         if(text == "") {
             stack.RemoveTagLocation(UI::ComponentTemplate::CaretTag);
         }
         else {
-            stack.SetTagLocation(UI::ComponentTemplate::CaretTag, {location.X, location.Y});
+            stack.SetTagLocation(UI::ComponentTemplate::CaretTag, {cursorlocation.X, cursorlocation.Y});
         }
     }
+    
+    void Textarea::checkprinter() {
+        if(!printer) {
+            //for font
+            int idx = stack.IndexOfTag(UI::ComponentTemplate::ContentsTag);
+
+            //no contents??!!
+            if(idx == -1)
+                return;
+
+            //contents is not a textholder
+            auto &temp = stack.GetTemplate(idx);
+            if(temp.GetType() != UI::ComponentType::Textholder)
+                return;
+
+            auto &textt = dynamic_cast<const UI::TextholderTemplate&>(temp);
+
+            //no renderer is set or renderer is not in valid state
+            if(!textt.IsReady())
+                return;
+            
+            printer = &textt.GetRenderer();
+        }
+    }
+    
+    int Textarea::getbyteoffset(int g) {
+        int byte  = 0;
+        while(g) {
+            byte += String::UTF8Bytes(text[byte]);
+            g--;
+        }
+        
+        return byte;
+    }
 
 } }
--- a/Source/Gorgon/Widgets/Textarea.h	Sat May 22 11:33:17 2021 +0300
+++ b/Source/Gorgon/Widgets/Textarea.h	Sat May 22 22:31:59 2021 +0300
@@ -261,6 +261,10 @@
         void moveselleft();
 
         void moveselright();
+        
+        void moveselup();
+        
+        void moveseldown();
 
         void eraseselected();
         
@@ -279,6 +283,8 @@
         void updatecursor();
         
         virtual void moved() override { updatecursor(); }
+        
+        void checkprinter();
 
         Graphics::PointerStack::Token pointertoken;
         
@@ -296,9 +302,14 @@
         
         glyphbyte selstart = {0, 0};
         glyphbyte sellen   = {0, 0};
+        int getbyteoffset(int glyph);
         int glyphcount = 0;
         int pglyph = 0;
         
+        
+        Geometry::Point cursorlocation = {0, 0};
+        const Graphics::TextPrinter *printer = nullptr;
+        
         bool selectionin = false;
         
         struct UI::internal::prophelper<Textarea, std::string> helper = UI::internal::prophelper<Textarea, std::string>(this);

mercurial