Files
tesses-framework/src/SDL2/Views/EditTextView.cpp

384 lines
14 KiB
C++

#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
namespace Tesses::Framework::SDL2::Views
{
EditTextView::EditTextView() : EditTextView(std::string())
{
}
EditTextView::EditTextView(std::string hint) : View()
{
this->hint = hint;
this->cursorPos=0;
this->cursorEnd=std::string::npos;
}
void EditTextView::TypeText(std::string text)
{
size_t cursorBegin = this->cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size())
{
this->text.erase(cursorBegin,cursorEnd-cursorBegin);
this->text.insert(cursorBegin,text);
}
else if(cursorBegin <= this->text.size()) {
this->text.insert(cursorBegin,text);
}
this->cursorPos = cursorBegin+text.size();
this->cursorEnd = std::string::npos;
}
void EditTextView::SetText(std::string text)
{
View::SetText(text);
this->cursorPos=0;
this->cursorEnd = std::string::npos;
}
void EditTextView::SetHint(std::string hint)
{
this->hint = hint;
}
std::string EditTextView::GetHint()
{
return this->hint;
}
std::pair<int,int> EditTextView::PreferedMinSize()
{
int x=-2;
int y=-2;
auto win = this->GetWindow();
if(win != nullptr)
{
x=-1;
y=win->monospaced_font->MaxHeight()+16;
}
return std::pair<int,int>(x,y);
}
bool EditTextView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
{
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
{
if(event.type == SDL_TEXTINPUT)
{
if(this->GetViewFlag(VIEWFLAG_TOUCHED))
{
this->SetViewFlag(VIEWFLAG_TOUCHED,false);
if(!this->text.empty())
{
this->cursorPos=0;
this->cursorEnd=this->text.size();
}
}
TypeText(event.text.text);
}
else if(event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDL_KeyCode::SDLK_c:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
size_t cursorBegin = cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size() && this->text.size() > 0)
{
std::string res = this->text.substr(cursorBegin,cursorEnd-cursorBegin);
//SDL_GetClipboardText()
SDL_SetClipboardText(res.c_str());
}
}
}
break;
case SDL_KeyCode::SDLK_v:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
if(SDL_HasClipboardText())
{
char* text = SDL_GetClipboardText();
if(text != NULL)
{
TypeText(text);
}
SDL_free(text);
}
}
}
break;
case SDL_KeyCode::SDLK_x:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
size_t cursorBegin = cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size() && this->text.size() > 0)
{
std::string res = this->text.substr(cursorBegin,cursorEnd-cursorBegin);
//SDL_GetClipboardText()
SDL_SetClipboardText(res.c_str());
TypeText("");
}
}
}
break;
case SDL_KeyCode::SDLK_a:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
this->cursorPos=0;
this->cursorEnd=this->text.size();
}
}
break;
case SDL_KeyCode::SDLK_BACKSPACE:
{
if(this->cursorEnd == std::string::npos)
{
if(this->cursorPos > 0)
{
this->cursorPos--;
this->text.erase(this->cursorPos,1);
}
}
else {
TypeText("");
}
}
break;
case SDL_KeyCode::SDLK_DELETE:
{
if(this->cursorEnd == std::string::npos)
{
if(this->cursorPos + 1 <= this->text.size())
{
this->text.erase(this->cursorPos,1);
}
}
else {
TypeText("");
}
}
break;
case SDL_KeyCode::SDLK_LEFT:
{
if((event.key.keysym.mod & KMOD_SHIFT) != 0)
{
if(this->cursorEnd > this->text.size())
this->cursorEnd = this->cursorPos;
this->cursorEnd--;
if(this->cursorEnd > this->text.size()) this->cursorEnd=0;
if(this->cursorEnd == this->cursorPos) this->cursorEnd = std::string::npos;
}
else
{
if(cursorPos > cursorEnd)
{
cursorPos ^= cursorEnd;
cursorEnd ^= cursorPos;
cursorPos ^= cursorEnd;
}
this->cursorPos--;
this->cursorEnd=std::string::npos;
if(this->cursorPos > this->text.size()) this->cursorPos=0;
}
}
break;
case SDL_KeyCode::SDLK_RIGHT:
if((event.key.keysym.mod & KMOD_SHIFT) != 0)
{
if(this->cursorEnd == std::string::npos)
this->cursorEnd = this->cursorPos;
this->cursorEnd++;
if(this->cursorEnd > this->text.size()) this->cursorEnd=this->text.size();
if(this->cursorEnd == this->cursorPos) this->cursorEnd = std::string::npos;
}
else
{
if(cursorPos > cursorEnd)
{
cursorPos ^= cursorEnd;
cursorEnd ^= cursorPos;
cursorPos ^= cursorEnd;
}
if(cursorEnd != std::string::npos)
{
this->cursorPos=cursorEnd+1;
}else {
this->cursorPos++;
}
this->cursorEnd=std::string::npos;
if(this->cursorPos > this->text.size()) this->cursorPos=this->text.size();
}
break;
}
}
}
if(event.type == SDL_MOUSEBUTTONDOWN)
{
if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h)
{
this->GetWindow()->MakeActive(this);
this->SetViewFlag(VIEWFLAG_TOUCHED,false);
SDL_StartTextInput();
}
}
if(event.type == SDL_FINGERDOWN)
{
auto pos = this->GetCordFromEvent(event);
if(pos.first >= myVisibleBounds.x && pos.first < myVisibleBounds.x+myVisibleBounds.w && pos.second >= myVisibleBounds.y && pos.second < myVisibleBounds.y+myVisibleBounds.h)
{
this->GetWindow()->MakeActive(this);
this->SetViewFlag(VIEWFLAG_TOUCHED,true);
SDL_StartTextInput();
}
}
return View::OnEvent(event,myBounds,myVisibleBounds);
}
void EditTextView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
{
size_t cursorBegin = this->cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
auto win = this->GetWindow();
//SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
//SDL_RenderFillRect(renderer,&r);
int textW=win->monospaced_font->MaxWidth()+2;
int textH=win->monospaced_font->MaxHeight();
int noChars = (r.w-16) / textW;
int x=0;
int y=(r.h/2)-((textH+16)/2);
x+=r.x+8;
y+=r.y+8;
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
SDL_Color& color = win->palette.GetBorderColor(isHovering,isActive,isMouseDown);
size_t tracking = this->cursorPos;
if(cursorEnd != std::string::npos)
tracking = this->cursorEnd;
size_t off = noChars == 0 ? (size_t)0 : ((tracking / (size_t)noChars) * (size_t)noChars);
std::string& datext = this->text.empty() ? this->hint : this->text;
//printf("%i %i %i\n",(int) tracking,(int)off,(int)noChars);
for(size_t i = 0; i < (size_t)noChars; i++)
{
if(cursorEnd == std::string::npos && (i+off) == cursorBegin)
{
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
int x1=((int)i*textW)+x;
int y1 = y;
int y2 = y+textH;
SDL_RenderDrawLine(renderer,x1,y1,x1,y2);
}
if(i + off < datext.size())
{
if(cursorEnd != std::string::npos && (i+off) >= cursorBegin && (i+off) < cursorEnd)
{
SDL_Rect r0={.x=((int)i*textW)+x,.y=y,.w=textW,.h=textH+8};
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
SDL_RenderFillRect(renderer,&r0);
auto ch=win->monospaced_font->GetCharOfColor(datext[i+off],color);
SDL_Rect src={.x=0,.y=0,.w=0,.h=0};
SDL_QueryTexture(ch,NULL,NULL,&src.w,&src.h);
SDL_Rect dest = {.x=((int)i*textW)+x+1,.y=y,.w=src.w,.h=src.h};
SDL_RenderCopy(renderer,ch,&src,&dest);
}
else {
auto ch=win->monospaced_font->GetCharOfColor(datext[i+off],this->text.empty() ? color : win->palette.accent);
SDL_Rect src={.x=0,.y=0,.w=0,.h=0};
SDL_QueryTexture(ch,NULL,NULL,&src.w,&src.h);
SDL_Rect dest = {.x=((int)i*textW)+x+1,.y=y,.w=src.w,.h=src.h};
SDL_RenderCopy(renderer,ch,&src,&dest);
}
}
}
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
SDL_Rect r2={.x=r.x,.y=y-4,.w=r.w,.h=textH+16};
for(size_t i=0;i < 4; i++)
{
SDL_RenderDrawRect(renderer,&r2);
r2.x++;
r2.y++;
r2.w-=2;
r2.h-=2;
}
}
}
#endif