Tags, fixes #55

This commit is contained in:
Simon Robertshaw 2012-08-04 20:55:59 +01:00
parent 82d2bcc7c2
commit 5a2da01a5b
11 changed files with 252 additions and 28 deletions

View File

@ -1262,6 +1262,55 @@ std::vector<SaveComment*> * Client::GetComments(int saveID, int start, int count
return commentArray;
}
std::vector<std::pair<std::string, int> > * Client::GetTags(int start, int count, string query, int & resultCount)
{
lastError = "";
resultCount = 0;
std::vector<std::pair<std::string, int> > * tagArray = new std::vector<std::pair<std::string, int> >();
std::stringstream urlStream;
char * data;
int dataStatus, dataLength;
urlStream << "http://" << SERVER << "/Browse/Tags.json?Start=" << start << "&Count=" << count;
if(query.length())
{
urlStream << "&Search_Query=";
if(query.length())
urlStream << URLEscape(query);
}
data = http_simple_get((char *)urlStream.str().c_str(), &dataStatus, &dataLength);
if(dataStatus == 200 && data)
{
try
{
std::istringstream dataStream(data);
json::Object objDocument;
json::Reader::Read(objDocument, dataStream);
json::Number tempCount = objDocument["TagTotal"];
resultCount = tempCount.Value();
json::Array tagsArray = objDocument["Tags"];
for(int j = 0; j < tagsArray.Size(); j++)
{
json::Number tagCount = tagsArray[j]["Count"];
json::String tag = tagsArray[j]["Tag"];
tagArray->push_back(std::pair<std::string, int>(tag.Value(), tagCount.Value()));
}
}
catch (json::Exception &e)
{
lastError = "Could not read response";
}
}
else
{
lastError = http_ret_text(dataStatus);
}
if(data)
free(data);
return tagArray;
}
std::vector<SaveInfo*> * Client::SearchSaves(int start, int count, string query, string sort, std::string category, int & resultCount)
{
lastError = "";

View File

@ -111,6 +111,7 @@ public:
LoginStatus Login(string username, string password, User & user);
void ClearThumbnailRequests();
std::vector<SaveInfo*> * SearchSaves(int start, int count, string query, string sort, string category, int & resultCount);
std::vector<std::pair<std::string, int> > * GetTags(int start, int count, string query, int & resultCount);
std::vector<SaveComment*> * GetComments(int saveID, int start, int count);
Thumbnail * GetPreview(int saveID, int saveDate);
Thumbnail * GetThumbnail(int saveID, int saveDate);

View File

@ -14,18 +14,21 @@ namespace ui
HorizontalAlign(AlignCentre),
VerticalAlign(AlignMiddle),
BackgroundHover(30, 30, 30),
BackgroundHover(20, 20, 20),
BackgroundInactive(0, 0, 0),
BackgroundActive(255, 255, 255),
BackgroundDisabled(100, 100, 100),
BackgroundDisabled(10, 10, 10),
TextHover(255, 255, 255),
TextInactive(255, 255, 255),
TextActive(0, 0, 0),
TextDisabled(100, 100, 100),
BorderHover(255, 255, 255),
BorderInactive(200, 200, 200),
BorderActive(255, 255, 255),
BorderActive(235, 235, 235),
BorderDisabled(100, 100, 100),
Margin(1, 4),
icon(NoIcon),

View File

@ -40,10 +40,12 @@ namespace ui
ui::Colour TextHover;
ui::Colour TextInactive;
ui::Colour TextActive;
ui::Colour TextDisabled;
ui::Colour BorderHover;
ui::Colour BorderInactive;
ui::Colour BorderActive;
ui::Colour BorderDisabled;
ui::Border Margin;

View File

@ -86,32 +86,45 @@ void Button::Draw(const Point& screenPos)
Graphics * g = ui::Engine::Ref().g;
Point Position = screenPos;
ui::Colour bgColour(0, 0, 0);
ui::Colour textColour = Appearance.TextInactive;
ui::Colour borderColour = Appearance.BorderInactive;
ui::Colour backgroundColour = Appearance.BackgroundInactive;
if(Enabled)
{
if(isButtonDown || (isTogglable && toggle))
{
bgColour = Appearance.BackgroundActive;
g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundActive.Red, Appearance.BackgroundActive.Green, Appearance.BackgroundActive.Blue, 255);
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BorderActive.Red, Appearance.BorderActive.Green, Appearance.BorderActive.Blue, 255);
g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, Appearance.TextActive.Red, Appearance.TextActive.Green, Appearance.TextActive.Blue, 255);
textColour = Appearance.TextActive;
borderColour = Appearance.BorderActive;
backgroundColour = Appearance.BackgroundActive;
}
else if (isMouseInside)
{
textColour = Appearance.TextHover;
borderColour = Appearance.BorderHover;
backgroundColour = Appearance.BackgroundHover;
}
else
{
bgColour = Appearance.BackgroundInactive;
g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundInactive.Red, Appearance.BackgroundInactive.Green, Appearance.BackgroundInactive.Blue, 255);
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BorderInactive.Red, Appearance.BorderInactive.Green, Appearance.BorderInactive.Blue, 255);
g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, Appearance.TextInactive.Red, Appearance.TextInactive.Green, Appearance.TextInactive.Blue, 255);
textColour = Appearance.TextInactive;
borderColour = Appearance.BorderInactive;
backgroundColour = Appearance.BackgroundInactive;
}
}
else
{
bgColour = Appearance.BackgroundInactive;
g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, Appearance.BackgroundInactive.Red, Appearance.BackgroundInactive.Green, Appearance.BackgroundInactive.Blue, 180);
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, Appearance.BackgroundDisabled.Red, Appearance.BackgroundDisabled.Green, Appearance.BackgroundDisabled.Blue, Appearance.BackgroundDisabled.Alpha);
g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, 180, 180, 180, 255);
textColour = Appearance.TextDisabled;
borderColour = Appearance.BorderDisabled;
backgroundColour = Appearance.BackgroundDisabled;
}
bool iconInvert = (bgColour.Blue + (3*bgColour.Green) + (2*bgColour.Red))>544?true:false;
bgColour = Appearance.BackgroundInactive;
g->fillrect(Position.X+1, Position.Y+1, Size.X-2, Size.Y-2, backgroundColour.Red, backgroundColour.Green, backgroundColour.Blue, backgroundColour.Alpha);
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, borderColour.Red, borderColour.Green, borderColour.Blue, borderColour.Alpha);
g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, buttonDisplayText, textColour.Red, textColour.Green, textColour.Blue, textColour.Alpha);
bool iconInvert = (backgroundColour.Blue + (3*backgroundColour.Green) + (2*backgroundColour.Red))>544?true:false;
if(Appearance.icon)
{

View File

@ -96,11 +96,19 @@ SearchController::~SearchController()
delete searchView;
}
void SearchController::DoSearch(std::string query)
void SearchController::DoSearch(std::string query, bool now)
{
nextQuery = query;
nextQueryTime = clock()+(0.6 * CLOCKS_PER_SEC);
nextQueryDone = false;
if(!now)
{
nextQueryTime = clock()+(0.6 * CLOCKS_PER_SEC);
nextQueryDone = false;
}
else
{
nextQueryDone = true;
searchModel->UpdateSaveList(1, nextQuery);
}
//searchModel->UpdateSaveList(1, query);
}

View File

@ -30,7 +30,7 @@ public:
~SearchController();
SearchView * GetView() { return searchView; }
void Exit();
void DoSearch(std::string query);
void DoSearch(std::string query, bool now = false);
void NextPage();
void PrevPage();
void ChangeSort();

View File

@ -12,10 +12,16 @@ SearchModel::SearchModel():
updateSaveListFinished(false),
saveListLoaded(false),
currentPage(1),
resultCount(0)
resultCount(0),
showTags(true)
{
}
void SearchModel::SetShowTags(bool show)
{
showTags = show;
}
void * SearchModel::updateSaveListTHelper(void * obj)
{
return ((SearchModel *)obj)->updateSaveListT();
@ -23,14 +29,27 @@ void * SearchModel::updateSaveListTHelper(void * obj)
void * SearchModel::updateSaveListT()
{
void ** information = new void*[2];
std::string category = "";
if(showFavourite)
category = "Favourites";
if(showOwn && Client::Ref().GetAuthUser().ID)
category = "by:"+Client::Ref().GetAuthUser().Username;
vector<SaveInfo*> * tempSaveList = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, resultCount);
information[0] = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, resultCount);
if(showTags)
{
int tagResultCount;
information[1] = Client::Ref().GetTags(0, 24, "", tagResultCount);
}
else
{
information[1] = NULL;
}
updateSaveListFinished = true;
return tempSaveList;
return information;
}
void SearchModel::UpdateSaveList(int pageNumber, std::string query)
@ -46,6 +65,11 @@ void SearchModel::UpdateSaveList(int pageNumber, std::string query)
selected.clear();
notifySelectedChanged();
if(pageNumber == 1 && !showOwn && !showFavourite && currentSort == "best" && query == "")
SetShowTags(true);
else
SetShowTags(false);
//Threading
if(!updateSaveListWorking)
{
@ -78,6 +102,11 @@ vector<SaveInfo*> SearchModel::GetSaveList()
return saveList;
}
vector<pair<string, int> > SearchModel::GetTagList()
{
return tagList;
}
void SearchModel::Update()
{
if(updateSaveListWorking)
@ -87,10 +116,25 @@ void SearchModel::Update()
updateSaveListWorking = false;
lastError = "";
saveListLoaded = true;
vector<SaveInfo*> * tempSaveList;
pthread_join(updateSaveListThread, (void**)(&tempSaveList));
saveList = *tempSaveList;
delete tempSaveList;
void ** tempInformation;
//vector<SaveInfo*> * tempSaveList;
pthread_join(updateSaveListThread, (void**)(&tempInformation));
saveList = *(vector<SaveInfo*>*)tempInformation[0];
delete (vector<SaveInfo*>*)tempInformation[0];
if(tempInformation[1])
{
tagList = *(vector<pair<string, int> >*)tempInformation[1];
delete (vector<pair<string, int> >*)tempInformation[1];
}
else
{
tagList = vector<pair<string, int> >();
}
delete[] tempInformation;
if(!saveList.size())
{
lastError = Client::Ref().GetLastError();

View File

@ -21,10 +21,12 @@ private:
vector<int> selected;
vector<SearchView*> observers;
vector<SaveInfo*> saveList;
vector<pair<string, int> > tagList;
int currentPage;
int resultCount;
bool showOwn;
bool showFavourite;
bool showTags;
void notifySaveListChanged();
void notifySelectedChanged();
void notifyPageChanged();
@ -43,9 +45,11 @@ public:
SearchModel();
virtual ~SearchModel();
void SetShowTags(bool show);
void AddObserver(SearchView * observer);
void UpdateSaveList(int pageNumber, std::string query);
vector<SaveInfo*> GetSaveList();
vector<pair<string, int> > GetTagList();
string GetLastError() { return lastError; }
int GetPageCount() { return max(1, (int)(ceil(resultCount/16))); }
int GetPageNum() { return currentPage; }

View File

@ -16,6 +16,7 @@ SearchView::SearchView():
nextButton = new ui::Button(ui::Point(XRES+BARSIZE-52, YRES+MENUSIZE-18), ui::Point(50, 16), "Next \x95");
previousButton = new ui::Button(ui::Point(1, YRES+MENUSIZE-18), ui::Point(50, 16), "\x96 Prev");
infoLabel = new ui::Label(ui::Point(51, YRES+MENUSIZE-18), ui::Point(XRES+BARSIZE-102, 16), "Loading...");
tagsLabel = new ui::Label(ui::Point(51, YRES+MENUSIZE-18), ui::Point(XRES+BARSIZE-102, 16), "Popular Tags:");
class SearchAction : public ui::TextboxAction
{
@ -219,6 +220,12 @@ SearchView::~SearchView()
delete infoLabel;
}
void SearchView::Search(std::string query)
{
searchField->SetText(query);
c->DoSearch(query, true);
}
void SearchView::NotifySortChanged(SearchModel * sender)
{
sortButton->SetText("Show "+sender->GetSort());
@ -293,14 +300,29 @@ void SearchView::NotifySaveListChanged(SearchModel * sender)
int buttonWidth, buttonHeight, saveX = 0, saveY = 0, savesX = 5, savesY = 4, buttonPadding = 1;
int buttonAreaWidth, buttonAreaHeight, buttonXOffset, buttonYOffset;
int tagWidth, tagHeight, tagX = 0, tagY = 0, tagsX = 6, tagsY = 4, tagPadding = 1;
int tagAreaWidth, tagAreaHeight, tagXOffset, tagYOffset;
vector<SaveInfo*> saves = sender->GetSaveList();
vector<pair<string, int> > tags = sender->GetTagList();
//string messageOfTheDay = sender->GetMessageOfTheDay();
RemoveComponent(tagsLabel);
tagsLabel->SetParentWindow(NULL);
Client::Ref().ClearThumbnailRequests();
for(i = 0; i < saveButtons.size(); i++)
{
RemoveComponent(saveButtons[i]);
delete saveButtons[i];
}
for(i = 0; i < tagButtons.size(); i++)
{
RemoveComponent(tagButtons[i]);
delete tagButtons[i];
}
saveButtons.clear();
tagButtons.clear();
if(!sender->GetSavesLoaded())
{
nextButton->Enabled = false;
@ -341,12 +363,34 @@ void SearchView::NotifySaveListChanged(SearchModel * sender)
delete errorLabel;
errorLabel = NULL;
}
buttonXOffset = buttonPadding;
buttonYOffset = 28;
buttonXOffset = buttonPadding;
buttonAreaWidth = Size.X;
buttonAreaHeight = Size.Y - buttonYOffset - 18;
if(tags.size())
{
buttonYOffset += (buttonAreaHeight/savesY) - buttonPadding*2;
buttonAreaHeight = Size.Y - buttonYOffset - 18;
savesY--;
tagXOffset = tagPadding;
tagYOffset = 60;
tagAreaWidth = Size.X;
tagAreaHeight = ((buttonAreaHeight/savesY) - buttonPadding*2)-(tagYOffset-28)-5;
tagWidth = (tagAreaWidth/tagsX) - tagPadding*2;
tagHeight = (tagAreaHeight/tagsY) - tagPadding*2;
AddComponent(tagsLabel);
tagsLabel->Position.Y = tagYOffset-16;
}
buttonWidth = (buttonAreaWidth/savesX) - buttonPadding*2;
buttonHeight = (buttonAreaHeight/savesY) - buttonPadding*2;
class SaveOpenAction: public ui::SaveButtonAction
{
SearchView * v;
@ -361,6 +405,59 @@ void SearchView::NotifySaveListChanged(SearchModel * sender)
v->c->Selected(sender->GetSave()->GetID(), sender->GetSelected());
}
};
class TagAction: public ui::ButtonAction
{
SearchView * v;
std::string tag;
public:
TagAction(SearchView * v, std::string tag) : v(v), tag(tag) {}
virtual void ActionCallback(ui::Button * sender)
{
v->Search(tag);
}
};
for(i = 0; i < tags.size(); i++)
{
int maxTagVotes = tags[0].second;
pair<string, int> tag = tags[i];
if(tagX == tagsX)
{
if(tagY == tagsY-1)
break;
tagX = 0;
tagY++;
}
int tagAlpha = 192;
if (maxTagVotes)
tagAlpha = 127+(128*tag.second)/maxTagVotes;
ui::Button * tagButton;
tagButton = new ui::Button(
ui::Point(
tagXOffset + tagPadding + tagX*(tagWidth+tagPadding*2),
tagYOffset + tagPadding + tagY*(tagHeight+tagPadding*2)
),
ui::Point(tagWidth, tagHeight),
tag.first
);
tagButton->SetActionCallback(new TagAction(this, tag.first));
tagButton->Appearance.BorderInactive = ui::Colour(0, 0, 0);
tagButton->Appearance.BorderHover = ui::Colour(0, 0, 0);
tagButton->Appearance.BorderActive = ui::Colour(0, 0, 0);
tagButton->Appearance.BackgroundHover = ui::Colour(0, 0, 0);
tagButton->Appearance.TextInactive = ui::Colour(tagAlpha, tagAlpha, tagAlpha);
tagButton->Appearance.TextHover = ui::Colour((tagAlpha*5)/6, (tagAlpha*5)/6, tagAlpha);
AddComponent(tagButton);
tagButtons.push_back(tagButton);
tagX++;
}
for(i = 0; i < saves.size(); i++)
{
if(saveX == savesX)

View File

@ -19,12 +19,14 @@ class SearchView: public ui::Window
private:
SearchController * c;
vector<ui::SaveButton*> saveButtons;
vector<ui::Button*> tagButtons;
ui::Button * favButton;
ui::Button * nextButton;
ui::Button * previousButton;
ui::Label * errorLabel;
ui::Textbox * searchField;
ui::Label * infoLabel;
ui::Label * tagsLabel;
ui::Button * sortButton;
ui::Button * ownButton;
ui::Spinner * loadingSpinner;
@ -44,6 +46,7 @@ public:
SearchView();
virtual ~SearchView();
void AttachController(SearchController * _c) { c = _c; }
virtual void Search(std::string);
virtual void OnTick(float dt);
virtual void OnMouseWheel(int x, int y, int d);
virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt);