#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 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(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