The-Powder-Toy/src/interface/SaveButton.cpp
Simon Robertshaw 785fbcefdf Fix divide-by-zero error
...  when displaying save buttons that have zero votes.
2012-11-15 13:01:25 +00:00

416 lines
11 KiB
C++

#include <iostream>
#include <typeinfo>
#include "SaveButton.h"
#include "client/SaveInfo.h"
#include "graphics/Graphics.h"
#include "Engine.h"
#include "client/ThumbnailBroker.h"
#include "simulation/SaveRenderer.h"
#include "Format.h"
#include "ContextMenu.h"
#include "Keys.h"
namespace ui {
SaveButton::SaveButton(Point position, Point size, SaveInfo * save):
Component(position, size),
file(NULL),
save(save),
thumbnail(NULL),
isMouseInside(false),
isButtonDown(false),
actionCallback(NULL),
selectable(false),
selected(false),
waitingForThumb(false),
isMouseInsideAuthor(false),
isMouseInsideHistory(false),
showVotes(false)
{
menu = new ContextMenu(this);
menu->AddItem(ContextMenuItem("Open", 0, true));
menu->AddItem(ContextMenuItem("Select", 1, true));
menu->AddItem(ContextMenuItem("View History", 2, true));
menu->AddItem(ContextMenuItem("More by this user", 3, true));
if(save)
{
name = save->name;
if(Graphics::textwidth((char *)name.c_str()) > Size.X)
{
int position = Graphics::textwidthx((char *)name.c_str(), Size.X - 22);
name = name.erase(position, name.length()-position);
name += "...";
}
std::string votes, icon;
int j;
votes = format::NumberToString<int>(save->GetVotesUp()-save->GetVotesDown());
icon += 0xBB;
for (int j = 1; j < votes.length(); j++)
icon += 0xBC;
icon += 0xB9;
icon += 0xBA;
votesBackground = icon;
for (std::string::iterator iter = icon.begin(), end = icon.end(); iter != end; ++iter)
*iter -= 14;
votesBackground2 = icon;
for (std::string::iterator iter = votes.begin(), end = votes.end(); iter != end; ++iter)
if(*iter != '-')
*iter += 127;
votesString = votes;
int voteMax = std::max(save->GetVotesUp(),save->GetVotesDown());
if (voteMax)
{
if (voteMax < 34)
{
float ry = 33.0f/voteMax;
if (voteMax<8)
ry = ry/(8-voteMax);
voteBarHeightUp = (int)(save->GetVotesUp()*ry)-1;
voteBarHeightDown = (int)(save->GetVotesDown()*ry)-1;
}
else
{
float ry = voteMax/33.0f;
voteBarHeightUp = (int)(save->GetVotesUp()/ry)-1;
voteBarHeightDown = (int)(save->GetVotesDown()/ry)-1;
}
}
else
{
voteBarHeightUp = 0;
voteBarHeightDown = 0;
}
}
}
SaveButton::SaveButton(Point position, Point size, SaveFile * file):
Component(position, size),
save(NULL),
file(file),
thumbnail(NULL),
isMouseInside(false),
isButtonDown(false),
actionCallback(NULL),
selectable(false),
selected(false),
wantsDraw(false),
waitingForThumb(false),
isMouseInsideAuthor(false),
isMouseInsideHistory(false),
showVotes(false)
{
if(file)
{
name = file->GetDisplayName();
if(Graphics::textwidth((char *)name.c_str()) > Size.X)
{
int position = Graphics::textwidthx((char *)name.c_str(), Size.X - 22);
name = name.erase(position, name.length()-position);
name += "...";
}
}
}
SaveButton::~SaveButton()
{
ThumbnailBroker::Ref().DetachThumbnailListener(this);
if(thumbnail)
delete thumbnail;
if(actionCallback)
delete actionCallback;
if(save)
delete save;
if(file)
delete file;
}
void SaveButton::OnThumbnailReady(Thumbnail * thumb)
{
if(thumb)
{
if(thumbnail)
delete thumbnail;
thumbnail = thumb;
waitingForThumb = false;
}
}
void SaveButton::Tick(float dt)
{
if(!thumbnail && !waitingForThumb)
{
if(save)
{
if(save->GetGameSave())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RenderThumbnail(save->GetGameSave(), Size.X-3, Size.Y-25, this);
}
else if(save->GetID())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RetrieveThumbnail(save->GetID(), save->GetVersion(), Size.X-3, Size.Y-25, this);
}
}
else if(file && file->GetGameSave())
{
waitingForThumb = true;
ThumbnailBroker::Ref().RenderThumbnail(file->GetGameSave(), Size.X-3, Size.Y-25, this);
}
}
}
void SaveButton::Draw(const Point& screenPos)
{
Graphics * g = ui::Engine::Ref().g;
float scaleFactor;
ui::Point thumbBoxSize(0, 0);
wantsDraw = true;
if(selected && selectable)
{
g->fillrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 100, 170, 255, 100);
}
if(thumbnail)
{
thumbBoxSize = ui::Point(thumbnail->Size.X, thumbnail->Size.Y);
if(save && save->id)
g->draw_image(thumbnail->Data, screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbnail->Size.X, thumbnail->Size.Y, 255);
else
g->draw_image(thumbnail->Data, screenPos.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbnail->Size.X, thumbnail->Size.Y, 255);
}
else
{
scaleFactor = (Size.Y-25)/((float)YRES);
thumbBoxSize = ui::Point(((float)XRES)*scaleFactor, ((float)YRES)*scaleFactor);
}
if(save)
{
if(save->id)
{
if(isMouseInside)
{
g->drawrect(screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 210, 230, 255, 255);
g->drawrect(screenPos.X-4+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, 7, thumbBoxSize.Y, 210, 230, 255, 255);
}
else
{
g->drawrect(screenPos.X-3+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 180, 180, 180, 255);
g->drawrect(screenPos.X-4+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, 7, thumbBoxSize.Y, 180, 180, 180, 255);
}
g->fillrect(screenPos.X-3+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+1+(Size.Y-20-thumbBoxSize.Y)/2, 5, (thumbBoxSize.Y+1)/2-1, 0, 107, 10, 255);
g->fillrect(screenPos.X-3+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-20)/2, 5, thumbBoxSize.Y/2-1, 107, 10, 0, 255);
g->fillrect(screenPos.X-2+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-20)/2-voteBarHeightUp, 3, voteBarHeightUp, 57, 187, 57, 255); //green
g->fillrect(screenPos.X-2+thumbBoxSize.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-20)/2, 3, voteBarHeightDown, 187, 57, 57, 255); //red
}
else
{
if(isMouseInside)
g->drawrect(screenPos.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 210, 230, 255, 255);
else
g->drawrect(screenPos.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 180, 180, 180, 255);
}
if(isMouseInside && !isMouseInsideAuthor)
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)name.c_str()))/2, screenPos.Y+Size.Y - 21, name, 255, 255, 255, 255);
else
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)name.c_str()))/2, screenPos.Y+Size.Y - 21, name, 180, 180, 180, 255);
if(isMouseInsideAuthor)
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save->userName.c_str()))/2, screenPos.Y+Size.Y - 10, save->userName, 200, 230, 255, 255);
else
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save->userName.c_str()))/2, screenPos.Y+Size.Y - 10, save->userName, 100, 130, 160, 255);
if (showVotes)// && !isMouseInside)
{
int x = screenPos.X-7+(Size.X-thumbBoxSize.X)/2+thumbBoxSize.X-Graphics::textwidth(votesBackground.c_str());
int y = screenPos.Y-23+(Size.Y-thumbBoxSize.Y)/2+thumbBoxSize.Y;
g->drawtext(x, y, votesBackground, 16, 72, 16, 255);
g->drawtext(x, y, votesBackground2, 192, 192, 192, 255);
g->drawtext(x+3, y, votesString, 255, 255, 255, 255);
}
if (isMouseInsideHistory && showVotes)
{
int x = screenPos.X;
int y = screenPos.Y-15+(Size.Y-thumbBoxSize.Y)/2+thumbBoxSize.Y;
g->fillrect(x+1, y+1, 7, 8, 255, 255, 255, 255);
if (isMouseInsideHistory) {
g->drawtext(x, y, "\xA6", 200, 100, 80, 255);
} else {
g->drawtext(x, y, "\xA6", 160, 70, 50, 255);
}
}
if (!save->GetPublished())
{
g->drawtext(screenPos.X, screenPos.Y-2, "\xCD", 255, 255, 255, 255);
g->drawtext(screenPos.X, screenPos.Y-2, "\xCE", 212, 151, 81, 255);
}
}
if(file)
{
if(isMouseInside)
g->drawrect(screenPos.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 210, 230, 255, 255);
else
g->drawrect(screenPos.X+(Size.X-thumbBoxSize.X)/2, screenPos.Y+(Size.Y-21-thumbBoxSize.Y)/2, thumbBoxSize.X, thumbBoxSize.Y, 180, 180, 180, 255);
if(isMouseInside)
{
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)name.c_str()))/2, screenPos.Y+Size.Y - 21, name, 255, 255, 255, 255);
}
else
{
g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)name.c_str()))/2, screenPos.Y+Size.Y - 21, name, 180, 180, 180, 255);
}
}
if(isMouseInside && selectable)
{
g->clearrect(screenPos.X+(Size.X-20), screenPos.Y+6, 14, 14);
g->drawrect(screenPos.X+(Size.X-20), screenPos.Y+6, 14, 14, 255, 255, 255, 255);
if(selected)
g->fillrect(screenPos.X+(Size.X-18), screenPos.Y+8, 10, 10, 255, 255, 255, 255);
}
}
void SaveButton::OnMouseUnclick(int x, int y, unsigned int button)
{
if(button != 1)
{
return; //left click only!
}
if(x>=Size.X-20 && y>=6 && y<=20 && x<=Size.X-6 && selectable)
{
selected = !selected;
DoSelection();
return;
}
if(isButtonDown)
{
isButtonDown = false;
if(isMouseInsideAuthor)
DoAuthorAction();
else if(isMouseInsideHistory)
DoHistoryAction();
else
DoAction();
}
}
void SaveButton::OnContextMenuAction(int item)
{
switch(item)
{
case 0:
DoAction();
break;
case 1:
selected = !selected;
DoSelection();
break;
case 2:
DoHistoryAction();
break;
case 3:
DoAuthorAction();
break;
}
}
void SaveButton::OnMouseClick(int x, int y, unsigned int button)
{
if(button == BUTTON_RIGHT)
{
if(menu)
menu->Show(GetScreenPos() + ui::Point(x, y));
}
else
{
isButtonDown = true;
if(button !=1 && selectable)
{
selected = !selected;
DoSelection();
}
}
}
void SaveButton::OnMouseMovedInside(int x, int y, int dx, int dy)
{
if(y > Size.Y-11)
isMouseInsideAuthor = true;
else
isMouseInsideAuthor = false;
if(showVotes && y > Size.Y-29 && y < Size.Y - 18 && x > 0 && x < 9)
isMouseInsideHistory = true;
else
isMouseInsideHistory = false;
}
void SaveButton::OnMouseEnter(int x, int y)
{
isMouseInside = true;
}
void SaveButton::OnMouseLeave(int x, int y)
{
isMouseInside = false;
isMouseInsideAuthor = false;
isMouseInsideHistory = false;
}
void SaveButton::DoHistoryAction()
{
if(actionCallback)
actionCallback->HistoryActionCallback(this);
}
void SaveButton::DoAuthorAction()
{
if(actionCallback)
actionCallback->AuthorActionCallback(this);
}
void SaveButton::DoAction()
{
if(actionCallback)
actionCallback->ActionCallback(this);
}
void SaveButton::DoSelection()
{
if(menu)
{
if(selected)
menu->SetItem(1, "Deselect");
else
menu->SetItem(1, "Select");
}
if(selectable && actionCallback)
actionCallback->SelectedCallback(this);
}
void SaveButton::SetActionCallback(SaveButtonAction * action)
{
actionCallback = action;
}
} /* namespace ui */