Skip to content

Commit

Permalink
Fixed Textfield navigation from last line is going to wrong line...
Browse files Browse the repository at this point in the history
Fixed Textfield navigation from last line is going to wrong line when last line is empty (jqPuwPEa39),
Rework Textfield caret based on detecting changes on start and end selection index (f1cao2EtWm)
  • Loading branch information
Neko-Box-Coder committed Aug 28, 2023
1 parent 477ac2c commit 43a4a8c
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 116 deletions.
3 changes: 2 additions & 1 deletion Include/ssGUI/DataClasses/CharacterRenderInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ namespace ssGUI
glm::vec2 BaselinePosition = glm::vec2();

//var: CharacterAtNewline
//True if this character is on a newline
//True if this character is on a newline.
//Note that the newline character itself won't be at newline, only the character after it will be
bool CharacterAtNewline = false;

//var: Rendered
Expand Down
4 changes: 2 additions & 2 deletions Include/ssGUI/DataClasses/SegmentedVector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,14 +679,14 @@ namespace ssGUI
//Returns the reference to first element
inline T& Front()
{
return InternalVectors[0].front();
return InternalVectors.at(0).front();
};

//function: Back
//Returns the reference to last element
inline T& Back()
{
return InternalVectors[InternalVectors.size()].back();
return InternalVectors.at(InternalVectors.size() - 1).back();
};
};
}
Expand Down
9 changes: 9 additions & 0 deletions Include/ssGUI/GUIObjectClasses/TextField.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ namespace ssGUI
uint64_t LastBlinkTime; //(Internal variable) Used to do the caret blinking animation
int32_t BlinkDuration; //(Internal variable) Used for the duration of the caret blinking
bool BlinkCaret; //(Internal variable) Flag for controlling the blinking of the caret
int LastStartSelectionIndex; //(Internal variable) Used for setting the caret to the correct position
int LastEndSelectionIndex; //(Internal variable) Used for setting the caret to the correct position
int CaretPosition; //(Internal variable) Used for setting position of carret
uint64_t LastArrowNavStartTime; //(Internal variable) Used to control the character navigation with arrow keys
int ArrowNavPauseDuration; //(Internal variable) Used to control the character navigation with arrow keys
Expand All @@ -26,6 +29,9 @@ namespace ssGUI
TextField::TextField() : LastBlinkTime(0),
BlinkDuration(500),
BlinkCaret(false),
LastStartSelectionIndex(-1),
LastEndSelectionIndex(-1),
CaretPosition(-1),
LastArrowNavStartTime(0),
ArrowNavPauseDuration(500),
LastArrowNavTime(0),
Expand Down Expand Up @@ -55,6 +61,9 @@ namespace ssGUI
uint64_t LastBlinkTime; //(Internal variable) Used to do the caret blinking animation
int32_t BlinkDuration; //(Internal variable) Used for the duration of the caret blinking
bool BlinkCaret; //(Internal variable) Flag for controlling the blinking of the caret
int LastStartSelectionIndex; //(Internal variable) Used for setting the caret to the correct position
int LastEndSelectionIndex; //(Internal variable) Used for setting the caret to the correct position
int CaretPosition; //(Internal variable) Used for setting position of carret

uint64_t LastArrowNavStartTime; //(Internal variable) Used to control the character navigation with arrow keys
int ArrowNavPauseDuration; //(Internal variable) Used to control the character navigation with arrow keys
Expand Down
154 changes: 89 additions & 65 deletions Src/ssGUI/GUIObjectClasses/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@ namespace ssGUI
StartSelectionIndex = other.GetStartSelectionIndex();
EndSelectionIndex = other.GetEndSelectionIndex();
DeselectWhenFocusLost = other.IsDeselectWhenFocusLost();
LastMouseDownInTextBound = other.LastMouseDownInTextBound;
SelectionColor = other.GetSelectionColor();
TextSelectedColor = other.GetTextSelectedColor();
LastDefaultFontsID = other.LastDefaultFontsID;
TextContentChanged = other.TextContentChanged;
MouseDoubleClickThresholdInMs = other.MouseDoubleClickThresholdInMs;
LastMouseDownTimestamp = other.LastMouseDownTimestamp;
LastClickSelectionTimestamp = other.LastClickSelectionTimestamp;
ClickSelectionStartIndex = other.ClickSelectionStartIndex;
ClickSelectionEndIndex = other.ClickSelectionEndIndex;

TextObjectCount++;
}
Expand Down Expand Up @@ -1027,63 +1034,71 @@ namespace ssGUI
}
}
}

int Text::GetEndOfPreviousWord(int curIndex)
namespace
{
//Check if there's any valid character before current character
int validCharBeforeIndex = -1;
for(int i = curIndex - 1; i >= 0; i--)
{
if(GetCharacterRenderInfo(i).Valid)
{
validCharBeforeIndex = i;
break;
}
}
if(validCharBeforeIndex < 0)
return curIndex;

enum class characterType
enum class CharacterType
{
LETTERS,
NUM,
SYMBOL,
SPACE_TAB_NEWLINE,
SPACE_TAB,
NEWLINE
};

auto getCharType = [&](wchar_t c)->characterType
CharacterType GetCharType(wchar_t c)
{
uint32_t charInt = (uint32_t)c;

//If letters
if((charInt >= 65 && charInt <= 90) || (charInt >= 97 && charInt <= 122))
return characterType::LETTERS;
return CharacterType::LETTERS;
//If numbers
if(charInt >= 48 && charInt <= 57)
return characterType::NUM;
return CharacterType::NUM;
//If Symbol
if((charInt >= 33 && charInt <= 47) || (charInt >= 58 && charInt <= 64) || (charInt >= 91 && charInt <= 96) || (charInt >= 123 && charInt <= 126))
return characterType::SYMBOL;
//If space, tab or newline
if(charInt == 9 || charInt == 10 || charInt == 12 || charInt == 13 || charInt == 32)
return characterType::SPACE_TAB_NEWLINE;

return characterType::LETTERS;
return CharacterType::SYMBOL;
//If space or tab
if(charInt == 9 || charInt == 12 || charInt == 13 || charInt == 32)
return CharacterType::SPACE_TAB;
//If newline
if(charInt == 10)
return CharacterType::NEWLINE;

return CharacterType::LETTERS;
};
}

int Text::GetEndOfPreviousWord(int curIndex)
{
//Check if there's any valid character before current character
int validCharBeforeIndex = -1;
for(int i = curIndex - 1; i >= 0; i--)
{
if(GetCharacterRenderInfo(i).Valid)
{
validCharBeforeIndex = i;
break;
}
}

if(validCharBeforeIndex < 0)
return curIndex;

characterType lastCharType = getCharType(GetInternalCharacterDetail(validCharBeforeIndex).Character);
CharacterType lastCharType = GetCharType(GetInternalCharacterDetail(validCharBeforeIndex).Character);
int lastValidIndex = validCharBeforeIndex;
for(int i = validCharBeforeIndex; i >= 0; i--)
{
if(!GetCharacterRenderInfo(i).Valid)
continue;

characterType curCharType = getCharType(GetInternalCharacterDetail(i).Character);
CharacterType curCharType = GetCharType(GetInternalCharacterDetail(i).Character);

//Return anything
if(lastCharType != curCharType && lastCharType != characterType::SPACE_TAB_NEWLINE)
if((lastCharType != curCharType && lastCharType != CharacterType::SPACE_TAB) || lastCharType == CharacterType::NEWLINE)
return lastValidIndex;

lastValidIndex = i;
lastCharType = curCharType;
}
Expand All @@ -1096,49 +1111,21 @@ namespace ssGUI
if(curIndex >= GetLastValidCharacterIndex())
return CharactersRenderInfos.size();

enum class characterType
{
LETTERS,
NUM,
SYMBOL,
SPACE_TAB_NEWLINE,
};

auto getCharType = [&](wchar_t c)->characterType
{
uint32_t charInt = (uint32_t)c;

//If letters
if((charInt >= 65 && charInt <= 90) || (charInt >= 97 && charInt <= 122))
return characterType::LETTERS;
//If numbers
if(charInt >= 48 && charInt <= 57)
return characterType::NUM;
//If Symbol
if((charInt >= 33 && charInt <= 47) || (charInt >= 58 && charInt <= 64) || (charInt >= 91 && charInt <= 96) || (charInt >= 123 && charInt <= 126))
return characterType::SYMBOL;
//If space, tab or newline
if(charInt == 9 || charInt == 10 || charInt == 12 || charInt == 13 || charInt == 32)
return characterType::SPACE_TAB_NEWLINE;

return characterType::LETTERS;
};

characterType lastCharType = getCharType(GetInternalCharacterDetail(curIndex).Character);
CharacterType lastCharType = GetCharType(GetInternalCharacterDetail(curIndex).Character);
int lastValidIndex = curIndex;
for(int i = curIndex; i <= CharactersRenderInfos.size(); i++)
for(int i = curIndex + 1; i <= CharactersRenderInfos.size(); i++)
{
if(i == CharactersRenderInfos.size())
return i;

if(!GetCharacterRenderInfo(i).Valid)
continue;

characterType curCharType = getCharType(GetInternalCharacterDetail(i).Character);
CharacterType curCharType = GetCharType(GetInternalCharacterDetail(i).Character);
lastValidIndex = i;

//Return anything
if(lastCharType != curCharType && lastCharType != characterType::SPACE_TAB_NEWLINE)
if((lastCharType != curCharType && lastCharType != CharacterType::SPACE_TAB) || lastCharType == CharacterType::NEWLINE)
return lastValidIndex;

lastCharType = curCharType;
Expand All @@ -1150,6 +1137,15 @@ namespace ssGUI
void Text::GetCurrentLineStartEndIndex(int curIndex, int& startIndex, int& endIndexInclusive)
{
curIndex = curIndex == CharactersRenderInfos.size() ? CharactersRenderInfos.size() - 1 : curIndex;

//ssLOG_LINE("CharactersRenderInfos.size(): " << CharactersRenderInfos.size());
//ssLOG_LINE("CurrentCharactersDetails.Size(): " << CurrentCharactersDetails.Size());

//ssLOG_LINE("GetCharacterRenderInfo(CharactersRenderInfos.size() - 1).CharacterAtNewline: " << GetCharacterRenderInfo(CharactersRenderInfos.size() - 1).CharacterAtNewline);
//ssLOG_LINE("GetCharacterRenderInfo(CharactersRenderInfos.size() - 1).Valid: " << GetCharacterRenderInfo(CharactersRenderInfos.size() - 1).Valid);

//ssLOG_LINE("CurrentCharactersDetails.At(CurrentCharactersDetails.Size() - 1).Character: " << (int)CurrentCharactersDetails.At(CurrentCharactersDetails.Size() - 1).Character);

for(int i = curIndex; i >= 0; i--)
{
if(!GetCharacterRenderInfo(i).Valid)
Expand Down Expand Up @@ -1180,7 +1176,20 @@ namespace ssGUI
{
bool passedCurLine = false;
bool endIndexSet = false;
curIndex = curIndex == CharactersRenderInfos.size() ? CharactersRenderInfos.size() - 1 : curIndex;

//Special case for querying beyond the last character when it is a newline character
if(curIndex == CharactersRenderInfos.size())
{
curIndex = CharactersRenderInfos.size() - 1;

if(!CurrentCharactersDetails.Empty() && CurrentCharactersDetails.At(CharactersRenderInfos.size() - 1).Character == L'\n')
{
endIndexInclusive = curIndex;
endIndexSet = true;
passedCurLine = true;
}
}

for(int i = curIndex; i >= 0; i--)
{
if(!GetCharacterRenderInfo(i).Valid)
Expand Down Expand Up @@ -1258,6 +1267,21 @@ namespace ssGUI
int prevLineEnd = 0;
GetPreviousLineStartEndIndex(curIndex, prevLineStart, prevLineEnd);

//ssLOG_LINE("curIndex: " << curIndex);
//ssLOG_LINE("curLineStart: " << curLineStart);
//ssLOG_LINE("curLineEnd: " << curLineEnd);
//ssLOG_LINE("prevLineStart: " << prevLineStart);
//ssLOG_LINE("prevLineEnd: " << prevLineEnd);
//ssLOG_LINE("CharactersRenderInfos.size(): " << CharactersRenderInfos.size());

//Special case if last character is a newline
if( curIndex >= CharactersRenderInfos.size() &&
!CurrentCharactersDetails.Empty() &&
CurrentCharactersDetails.Back().Character == L'\n')
{
curIndex = CharactersRenderInfos.size() - 1;
}

//Find out current position from this line (Depending on alignment)
//Right
if(GetTextHorizontalAlignment() == ssGUI::Enums::AlignmentHorizontal::RIGHT)
Expand All @@ -1270,7 +1294,7 @@ namespace ssGUI
curLinePosition = curIndex - curLineStart;

//If there's no previous line, just return start index
if(prevLineEnd >= curLineStart)
if(prevLineEnd >= curLineStart && prevLineStart >= curLineStart)
return curLineStart;

//Go to previous line if there's any
Expand Down
Loading

0 comments on commit 43a4a8c

Please sign in to comment.