Слияние кода завершено, страница обновится автоматически
#include "listview.hpp"
void TreeItem::UpdatePosition(long long n){
//上多
extend_start+=n;
}
ImageItem::ImageItem(SDL_Texture* t):_t(t){
SDL_QueryTexture(t,0,0,&w,&h);
}
void ImageItem::Draw(Renderer* render,ListState state,SDL_Rect& rect){
render->DrawTexture(0,&rect,_t);
}
ImageItem::~ImageItem(){
SDL_DestroyTexture(_t);
}
const char* TextItem::text(){return _text;}
TextItem::TextItem(Window* window,const char* text,Font* font,SDL_Color normal_color,
SDL_Color on_color,SDL_Color select_color){
_text=text;
this->font=font;
this->on_color=on_color;
this->select_color=select_color;
this->normal_color=normal_color;
auto r=window->renderer;
_normal=r->RenderText(font,text,normal_color);
_select=r->RenderText(font,text,select_color);
_on=r->RenderText(font,text,on_color);
SDL_QueryTexture(_normal,NULL,NULL,&w,&h);
}
void TextItem::Draw(Renderer* render,ListState state,SDL_Rect& r){
SDL_Rect src{0,0,min(w,r.w),min(h,r.h)};
switch(state){
case ListState::Normal:
render->DrawTexture(&src,&r,_normal);
return;
case ListState::Select:
render->DrawTexture(&src,&r,_select);
return;
case ListState::On:
render->DrawTexture(&src,&r,_on);
return;
}
}
//将更新三个不同状态的文本缓存
void TextItem::SetText(Window* window,const char* text,Font* font,SDL_Color normal_color,
SDL_Color on_color,SDL_Color select_color){
_text=text;
this->on_color=on_color;
this->font=font;
this->normal_color=normal_color;
this->select_color=select_color;
auto r=window->renderer;
_normal=r->RenderText(font,text,normal_color);
_select=r->RenderText(font,text,select_color);
_on=r->RenderText(font,text,on_color);
SDL_QueryTexture(_normal,NULL,NULL,&w,&h);
}
TextItem::~TextItem(){
SDL_DestroyTexture(_normal);
SDL_DestroyTexture(_select);
SDL_DestroyTexture(_on);
}
void ListView::Clear(bool freed){
if(freed){
for(auto item=items.begin(),end=items.end();item!=end;item++){
delete *item;
}
}
items.clear();
select=-1;
on=-1;
cur_item=0;
}
void ListView::ListenScroll(void* list){
if(((ListView*)list)->pressed){
auto size=((ListView*)list)->items.size();
if(size){
int x,y;
auto &r=((ListView*)list)->_area;
SDL_GetMouseState(&x,&y);
if(y<r.y){
((ListView*)list)->cur_item=0;
((ListView*)list)->scroll.y=r.y;
return;
}
((ListView*)list)->cur_item=min(size-1.,(y-r.y)/((ListView*)list)->_factor);
((ListView*)list)->scroll.y=r.y+((ListView*)list)->_factor*((ListView*)list)->cur_item;
}
return;
}
((ListView*)list)->_belong->RemoveTask(((ListView*)list)->_task);
((ListView*)list)->_task=NULL;
}
void ListView::ListenMouse(void* list){
auto &r=((ListView*)list)->_area;
int x,y;
SDL_GetMouseState(&x,&y);
if(x<r.x||x>r.x+r.w||y<r.y||y>r.y+r.h){
((ListView*)list)->on=-1;
((ListView*)list)->_in=false;
((ListView*)list)->_belong->RemoveTask(((ListView*)list)->_task);
((ListView*)list)->scroll_color=((ListView*)list)->normal_scroll_color;
((ListView*)list)->_task=NULL;
SDL_SetCursor(arrow_cursor);
return;
}
auto &g=((ListView*)list)->scroll;
if(x<g.x){
//项
((ListView*)list)->scroll_color=((ListView*)list)->normal_scroll_color;
((ListView*)list)->on=((ListView*)list)->cur_item+
(y-r.y-((ListView*)list)->space)/(((ListView*)list)->item_height+((ListView*)list)->space);
if(((ListView*)list)->on>=((ListView*)list)->items.size()){
((ListView*)list)->on=-1;
SDL_SetCursor(arrow_cursor);
return;
}
((ListView*)list)->items.operator[](((ListView*)list)->on)->_on((ListView*)list,x,y);
SDL_SetCursor(button_cursor);
return;
}
((ListView*)list)->on=-1;
if(g.x<=x&&x<=g.x+r.w&&g.y<=y&&y<=g.y+g.h){
((ListView*)list)->scroll_color=((ListView*)list)->on_scroll_color;
return;
}
((ListView*)list)->scroll_color=((ListView*)list)->normal_scroll_color;
}
size_t ListView::selected(){return select;}
ListView::ListView(Window* window,SDL_Rect& rect,int space,int item_h,
SDL_Color background,SDL_Color select_color,SDL_Color on_color,
SDL_Color normal_scroll_color,SDL_Color on_scroll_color):BaseListView(window){
_in=false;
scroll.w=10,scroll.x=rect.x+rect.w-10,scroll.y=rect.y,scroll.h=rect.h;
cur_item=0;
this->select_color=select_color;
this->on_color=on_color;
this->background=background;
this->space=space;
this->normal_scroll_color=normal_scroll_color;
this->on_scroll_color=on_scroll_color;
this->scroll_color=normal_scroll_color;
item_height=item_h;
_area=rect;
select=-1;
on=-1;
max_item=(rect.h)/(item_h+space);
_t=window->renderer->CreateTexture(rect.w,item_h);
SDL_SetTextureBlendMode(_t,SDL_BLENDMODE_BLEND);
_task=NULL;
}
ListView::ListView(Window* window):BaseListView(window){
_task=NULL;
_in=false;
background=Color::Gray;
item_height=14;
space=3;
select_color=Color::Blue;
on_color=Color::SkyBlueGray;
normal_scroll_color={0,0,0,120};
on_scroll_color={0,0,0,220};
cur_item=0;
_t=window->renderer->CreateTexture(0,0);
select=-1;
on=-1;
max_item=0;
}
void ListView::ItemChanged(){
_factor=(double)_area.h/(double)items.size();
scroll.h=ceil(_factor);
}
void ListView::SetSize(int w,int h){
SDL_DestroyTexture(_t);
_t=_belong->renderer->CreateTexture(w-5,h);
_area.w=w,_area.h=h;
}
void ListView::SetPosition(int x,int y){
scroll.x+=x-_area.x,scroll.y+=y-_area.y;
_area.x=x,_area.y=y;
}
void ListView::OffsetPosition(int x,int y){
scroll.x+=x,scroll.y+=y;
_area.x+=x,_area.y+=y;
}
ListItem* ListView::AddItem(ListItem* item){
item->OnAdd(&items);
_factor=(double)_area.h/(double)items.size();
scroll.h=ceil(_factor);
return item;
}
void ListView::AddItem(vector<ListItem*>* src){
auto& i=items;
i.reserve(items.size()+src->size());
for(auto item=src->begin(),end=src->end();item!=end;item++){
(*item)->OnAdd(&i);
}
_factor=(double)_area.h/(double)items.size();
scroll.h=ceil(_factor);
}
ListItem* ListView::RemoveItem(size_t index){
if(index<items.size()){
cur_item=0;
on=-1;
select=-1;
auto i=items.operator[](index);
for(auto item=items.erase(items.begin()+index),end=items.end();item!=end;item++)(*item)->UpdatePosition(-1);
if(items.empty()){
scroll.h=_area.h;
return i;
}
_factor=(double)_area.h/(double)items.size();
scroll.h=ceil(_factor);
return i;
}
throw out_of_range(to_string(index));
}
void ListView::_mouse_wheel(SDL_MouseWheelEvent& event){
long long s=(long long)items.size();
if(!s){
return;
}
auto y=event.y;
if(y<0){
//下
if(cur_item-y<s){
cur_item-=y;
scroll.y-=ceil(y*_factor);
return;
}
cur_item=s-1;
scroll.y=_area.y+_area.h-ceil(_factor);
return;
}
if(y>0){
//上
if(cur_item-y<=0){
cur_item=0;
scroll.y=_area.y;
return;
}
cur_item-=y;
scroll.y-=ceil(y*_factor);
}
}
void ListView::_press(int x,int y,int clicks,unsigned char key){
if(!_enabled){
return;
}
if(x-_area.x>_area.w-10){
auto w=_belong;
if(_task){
w->RemoveTask(_task);
}
_task=w->AddTask(ListenScroll,this,1,false,true);
return;
}
}
void ListView::_release(int x,int y,int clicks,unsigned char key){
if(!_enabled){
return;
}
auto t=y-_area.y;
if(t<space||t>_area.h-space){
return;
}
if(x-_area.x>_area.w-10){
//滚动条
return;
}
if(on==-1){
return;
}
select=on;
if(clicks==1){
items.operator[](select)->_click(this,x,y,key);
return;
}
items.operator[](select)->_double_click(this,x,y,key);
}
void ListView::_mouse_move(int x,int y){
if(!_task&&_enabled){
_in=true;
_task=_belong->AddTask(ListenMouse,this,1,false,true);
}
}
void ListView::_draw(){
auto r=_belong->renderer;
r->SetColor(background);
r->FillRect(_area);
auto h=item_height;
SDL_Rect rect{_area.x,_area.y+space,_area.w,item_height},_r{0,0,_area.w,item_height};
auto t=_t;
for(auto item=items.begin()+cur_item,end=items.end(),stop=item+max_item,
selected=items.begin()+select,on_item=items.begin()+on;item!=end;item++){
r->SetTarget(t);
ListState state;
if(item==selected){
state=ListState::Select;
r->SetColor(select_color);
}
else if(item==on_item){
state=ListState::On;
r->SetColor(on_color);
}
else{
state=ListState::Normal;
r->SetColor(background);
}
r->Clear();
(*item)->Draw(r,state,_r);
r->SetTarget(NULL);
if(item==stop){
rect.h=_area.h-rect.y;
SDL_Rect src{0,0,rect.w,rect.h};
r->DrawTexture(&src,&rect,t);
break;
}
else{
r->DrawTexture(0,&rect,t);
}
rect.y+=space+h;
}
if(!_in){
return;
}
//绘制滚动条
r->SetColor(scroll_color);
r->FillRect(scroll);
}
void ListView::_key_down(SDL_Keysym& sym){}
ListView::~ListView(){
if(_task){
_belong->RemoveTask(_task);
}
}
void TreeItem::CollectCount(size_t& count){
for(auto item=children->begin(),end=children->end();item!=end;item++){
auto t=(TreeItem*)*item;
if(t->extend){
t->CollectCount(count);
count+=t->children->size();
}
}
extend=false;
}
void TreeItem::ExtendOrFold(){
if(extend){
//折叠
auto begin=list->begin()+extend_start+1;
auto size=children->size();
CollectCount(size);
auto s=-size;
for(auto item=list->erase(begin,begin+size),end=list->end();item!=end;item++)(*item)->UpdatePosition(s);
return;
}
//extend
auto begin=list->begin();
size_t adder=extend_start+1;
auto size=children->size();
for(auto item=begin+adder;item!=list->end();item++)(*item)->UpdatePosition(size);
list->insert(begin+adder,children->begin(),children->end());//因为存在多个不同列表项 需要做变更缓存
for(auto item=children->begin(),end=children->end();item!=end;item++){
((TreeItem*)*item)->extend_start=adder++;
((TreeItem*)*item)->extend=false;
}
extend=true;
}
//使用时必须统一为TreeItem
TreeItem::TreeItem(Window* window,const char* text,int extend_offset,Font* font,SDL_Color normal_color,
SDL_Color on_color,SDL_Color select_color):
TextItem(window,text,font,normal_color,on_color,select_color){
children=new vector<TreeItem*>();
offset=0;
_offset=extend_offset;
depth=0;
parent=NULL;
extend=false;
}
//此方法中进行插入操作
void TreeItem::OnAdd(vector<ListItem*>* l){
extend=false;
list=l;
extend_start=l->size();
l->push_back(this);
}
TreeItem* TreeItem::Add(TreeItem* item){
item->list=list,item->extend=false;
if(extend){
item->extend_start=extend_start+1;
list->insert(list->begin()+extend_start,this);
}
children->push_back(item);
item->offset=offset+item->_offset;
item->depth=depth+1;
item->parent=this;
return item;
}
TreeItem::~TreeItem(){
if(!extend){
for(auto item=children->begin(),end=children->end();item!=end;item++){
delete *item;
}
}
delete children;
}
void TreeItem::_click(BaseListView* list,int x,int y,unsigned char key){
ExtendOrFold();
list->ItemChanged();
OnClick(x,y,key);
}
void TreeItem::_double_click(BaseListView* list,int x,int y,unsigned char key){
ExtendOrFold();
list->ItemChanged();
OnDoubleClick(x,y,key);
}
void TreeItem::Draw(Renderer* render,ListState state,SDL_Rect& rect){
if(!children->empty()){
SDL_Point p1{offset+3,3};
if(extend){
SDL_Point p2{5+offset,3+(h>>1)};
render->SetColor(normal_color);
render->DrawLine(p1,p2);
p1.x=10+offset;
render->DrawLine(p2,p1);
}
else{
SDL_Point p2{5+offset,h>>1};
render->SetColor(normal_color);
render->DrawLine(p1,p2);
p1.y=h-3;
render->DrawLine(p2,p1);
}
}
SDL_Rect r{10+offset+rect.x,0,w,h};
switch(state){
case ListState::Normal:
render->DrawTexture(NULL,&r,_normal);
return;
case ListState::Select:
render->DrawTexture(NULL,&r,_select);
return;
case ListState::On:
render->DrawTexture(NULL,&r,_on);
return;
}
}
void TreeTextItem::OnClick(int x,int y,unsigned char key){}
void TreeTextItem::OnDoubleClick(int x,int y,unsigned char key){}
TreeTextItem::TreeTextItem(Window* window,const char* text,int extend_offset,
Font* font,SDL_Color normal_color,SDL_Color on_color,SDL_Color select_color)
:TreeItem(window,text,extend_offset,font,normal_color,on_color,select_color){}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )