diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-24 12:24:17 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-24 12:24:17 (GMT) |
| commit | 9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d (patch) | |
| tree | ac7d040253b459ce102e476cb19ab59e3cfa90d7 /src/gui/preview | |
| parent | 6bf98ccdca39936a3c51367862eed7c49f8786ec (diff) | |
| parent | bdc69f31c0be94191015838886bdcc2bc67f1acb (diff) | |
| download | powder-9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d.zip powder-9b5b85f9b01cbda7ef9a7ec2a15b2a35630a5b9d.tar.gz | |
Merge branch 'reorganisation' of github.com:FacialTurd/The-Powder-Toy
Diffstat (limited to 'src/gui/preview')
| -rw-r--r-- | src/gui/preview/Comment.h | 28 | ||||
| -rw-r--r-- | src/gui/preview/PreviewController.cpp | 192 | ||||
| -rw-r--r-- | src/gui/preview/PreviewController.h | 45 | ||||
| -rw-r--r-- | src/gui/preview/PreviewModel.cpp | 360 | ||||
| -rw-r--r-- | src/gui/preview/PreviewModel.h | 85 | ||||
| -rw-r--r-- | src/gui/preview/PreviewModelException.h | 19 | ||||
| -rw-r--r-- | src/gui/preview/PreviewView.cpp | 614 | ||||
| -rw-r--r-- | src/gui/preview/PreviewView.h | 74 |
8 files changed, 1417 insertions, 0 deletions
diff --git a/src/gui/preview/Comment.h b/src/gui/preview/Comment.h new file mode 100644 index 0000000..1d84042 --- /dev/null +++ b/src/gui/preview/Comment.h @@ -0,0 +1,28 @@ +#ifndef COMMENT_H_ +#define COMMENT_H_ + +#include <string> + +class SaveComment +{ +public: + int authorID; + std::string authorName; + std::string authorNameFormatted; + std::string comment; + SaveComment(int userID, std::string username, std::string usernameFormatted, std::string commentText): + authorID(userID), authorName(username), authorNameFormatted(usernameFormatted), comment(commentText) + { + } + SaveComment(const SaveComment & comment): + authorID(comment.authorID), authorName(comment.authorName), authorNameFormatted(comment.authorNameFormatted), comment(comment.comment) + { + } + SaveComment(const SaveComment * comment): + authorID(comment->authorID), authorName(comment->authorName), authorNameFormatted(comment->authorNameFormatted), comment(comment->comment) + { + } +}; + + +#endif /* COMMENT_H_ */ diff --git a/src/gui/preview/PreviewController.cpp b/src/gui/preview/PreviewController.cpp new file mode 100644 index 0000000..30622c2 --- /dev/null +++ b/src/gui/preview/PreviewController.cpp @@ -0,0 +1,192 @@ +#include <sstream> +#include "client/Client.h" +#include "PreviewController.h" +#include "PreviewView.h" +#include "PreviewModel.h" +#include "PreviewModelException.h" +#include "gui/dialogues/ErrorMessage.h" +#include "gui/login/LoginController.h" +#include "Controller.h" + +PreviewController::PreviewController(int saveID, int saveDate, ControllerCallback * callback): + HasExited(false), + saveId(saveID), + saveDate(saveDate), + loginWindow(NULL) +{ + previewModel = new PreviewModel(); + previewView = new PreviewView(); + previewModel->AddObserver(previewView); + previewView->AttachController(this); + + previewModel->UpdateSave(saveID, saveDate); + + if(Client::Ref().GetAuthUser().ID) + { + previewModel->SetCommentBoxEnabled(true); + } + + Client::Ref().AddListener(this); + + this->callback = callback; +} + +PreviewController::PreviewController(int saveID, ControllerCallback * callback): + HasExited(false), + saveId(saveID), + saveDate(0), + loginWindow(NULL) +{ + previewModel = new PreviewModel(); + previewView = new PreviewView(); + previewModel->AddObserver(previewView); + previewView->AttachController(this); + + previewModel->UpdateSave(saveID, 0); + + if(Client::Ref().GetAuthUser().ID) + { + previewModel->SetCommentBoxEnabled(true); + } + + Client::Ref().AddListener(this); + + this->callback = callback; +} + +void PreviewController::Update() +{ + if(loginWindow && loginWindow->HasExited == true) + { + delete loginWindow; + loginWindow = NULL; + } + + try + { + previewModel->Update(); + } + catch (PreviewModelException & e) + { + Exit(); + new ErrorMessage("Error", e.what()); + } + if(previewModel->GetDoOpen() && previewModel->GetSave() && previewModel->GetSave()->GetGameSave()) + { + Exit(); + } +} + +bool PreviewController::SubmitComment(std::string comment) +{ + if(comment.length() < 4) + { + new ErrorMessage("Error", "Comment is too short"); + return false; + } + else + { + RequestStatus status = Client::Ref().AddComment(saveId, comment); + if(status != RequestOkay) + { + new ErrorMessage("Error Submitting comment", Client::Ref().GetLastError()); + return false; + } + else + { + previewModel->UpdateComments(1); + } + } + return true; +} + +void PreviewController::ShowLogin() +{ + loginWindow = new LoginController(); + ui::Engine::Ref().ShowWindow(loginWindow->GetView()); +} + +void PreviewController::NotifyAuthUserChanged(Client * sender) +{ + previewModel->SetCommentBoxEnabled(sender->GetAuthUser().ID); +} + +SaveInfo * PreviewController::GetSave() +{ + return previewModel->GetSave(); +} + +bool PreviewController::GetDoOpen() +{ + return previewModel->GetDoOpen(); +} + +void PreviewController::DoOpen() +{ + previewModel->SetDoOpen(true); +} + +void PreviewController::Report(std::string message) +{ + if(Client::Ref().ReportSave(saveId, message) == RequestOkay) + { + Exit(); + new ErrorMessage("Information", "Report submitted"); //TODO: InfoMessage + } + else + new ErrorMessage("Error", "Unable file report"); +} + +void PreviewController::FavouriteSave() +{ + if(previewModel->GetSave() && Client::Ref().GetAuthUser().ID) + { + if(previewModel->GetSave()->Favourite) + previewModel->SetFavourite(false); + else + previewModel->SetFavourite(true); + } +} + +void PreviewController::OpenInBrowser() +{ + std::stringstream uriStream; + uriStream << "http://" << SERVER << "/Browse/View.html?ID=" << saveId; + OpenURI(uriStream.str()); +} + +void PreviewController::NextCommentPage() +{ + if(previewModel->GetCommentsPageNum() < previewModel->GetCommentsPageCount() && previewModel->GetCommentsLoaded()) + previewModel->UpdateComments(previewModel->GetCommentsPageNum()+1); +} + +void PreviewController::PrevCommentPage() +{ + if(previewModel->GetCommentsPageNum()>1 && previewModel->GetCommentsLoaded()) + previewModel->UpdateComments(previewModel->GetCommentsPageNum()-1); +} + +void PreviewController::Exit() +{ + if(ui::Engine::Ref().GetWindow() == previewView) + { + ui::Engine::Ref().CloseWindow(); + } + HasExited = true; + if(callback) + callback->ControllerExit(); +} + +PreviewController::~PreviewController() { + if(ui::Engine::Ref().GetWindow() == previewView) + { + ui::Engine::Ref().CloseWindow(); + } + Client::Ref().RemoveListener(this); + delete previewModel; + delete previewView; + if(callback) + delete callback; +} + diff --git a/src/gui/preview/PreviewController.h b/src/gui/preview/PreviewController.h new file mode 100644 index 0000000..e1e429d --- /dev/null +++ b/src/gui/preview/PreviewController.h @@ -0,0 +1,45 @@ +#ifndef PREVIEWCONTROLLER_H_ +#define PREVIEWCONTROLLER_H_ + +#include "gui/preview/PreviewModel.h" +#include "gui/preview/PreviewView.h" +#include "Controller.h" +#include "client/SaveInfo.h" +#include "client/ClientListener.h" + +class LoginController; +class PreviewModel; +class PreviewView; +class PreviewController: public ClientListener { + int saveId; + int saveDate; + PreviewModel * previewModel; + PreviewView * previewView; + LoginController * loginWindow; + ControllerCallback * callback; +public: + virtual void NotifyAuthUserChanged(Client * sender); + inline int SaveID() { return saveId; }; + + bool HasExited; + PreviewController(int saveID, ControllerCallback * callback); + PreviewController(int saveID, int saveDate, ControllerCallback * callback); + void Exit(); + void DoOpen(); + void OpenInBrowser(); + void Report(std::string message); + void ShowLogin(); + bool GetDoOpen(); + SaveInfo * GetSave(); + PreviewView * GetView() { return previewView; } + void Update(); + void FavouriteSave(); + bool SubmitComment(std::string comment); + + void NextCommentPage(); + void PrevCommentPage(); + + virtual ~PreviewController(); +}; + +#endif /* PREVIEWCONTROLLER_H_ */ diff --git a/src/gui/preview/PreviewModel.cpp b/src/gui/preview/PreviewModel.cpp new file mode 100644 index 0000000..8d608cf --- /dev/null +++ b/src/gui/preview/PreviewModel.cpp @@ -0,0 +1,360 @@ +#include <cmath> +#include "PreviewModel.h" +#include "client/Client.h" +#include "client/GameSave.h"; +#include "PreviewModelException.h" + +PreviewModel::PreviewModel(): + save(NULL), + saveComments(NULL), + doOpen(false), + updateSaveDataWorking(false), + updateSaveDataFinished(false), + updateSaveInfoWorking(false), + updateSaveInfoFinished(false), + updateSaveCommentsWorking(false), + updateSaveCommentsFinished(false), + commentsTotal(0), + commentsPageNumber(1), + commentBoxEnabled(false) +{ + +} + +void * PreviewModel::updateSaveInfoTHelper(void * obj) +{ + return ((PreviewModel*)obj)->updateSaveInfoT(); +} + +void * PreviewModel::updateSaveDataTHelper(void * obj) +{ + return ((PreviewModel*)obj)->updateSaveDataT(); +} + +void * PreviewModel::updateSaveCommentsTHelper(void * obj) +{ + return ((PreviewModel*)obj)->updateSaveCommentsT(); +} + +void PreviewModel::updateSaveInfoTDelete(void * arg) +{ + delete arg; +} +void PreviewModel::updateSaveDataTDelete(void * arg) +{ + free(arg); +} +void PreviewModel::updateSaveCommentsTDelete(void * arg) +{ + for(int i = 0; i < ((std::vector<SaveComment*> *)arg)->size(); i++) + delete ((std::vector<SaveComment*> *)arg)->at(i); + ((std::vector<SaveComment*> *)arg)->clear(); + delete arg; +} + +void * PreviewModel::updateSaveInfoT() +{ + SaveInfo * tempSave; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + tempSave = Client::Ref().GetSave(tSaveID, tSaveDate); + pthread_cleanup_push(&updateSaveInfoTDelete,tempSave); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_testcancel(); + updateSaveInfoFinished = true; + pthread_cleanup_pop(0); + return tempSave; +} + +void * PreviewModel::updateSaveDataT() +{ + int tempDataSize; + unsigned char * tempData; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + tempData = Client::Ref().GetSaveData(tSaveID, tSaveDate, tempDataSize); + pthread_cleanup_push(&updateSaveDataTDelete,tempData); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_testcancel(); + saveDataBuffer.clear(); + if (tempData) + saveDataBuffer.insert(saveDataBuffer.begin(), tempData, tempData+tempDataSize); + updateSaveDataFinished = true; + pthread_cleanup_pop(1); + return NULL; +} + +void * PreviewModel::updateSaveCommentsT() +{ + std::vector<SaveComment*> * tempComments; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); + tempComments = Client::Ref().GetComments(tSaveID, (commentsPageNumber-1)*20, 20); + pthread_cleanup_push(&updateSaveCommentsTDelete,tempComments); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_testcancel(); + updateSaveCommentsFinished = true; + pthread_cleanup_pop(0); + return tempComments; +} + +void PreviewModel::SetFavourite(bool favourite) +{ + if(save) + { + Client::Ref().FavouriteSave(save->id, favourite); + save->Favourite = favourite; + notifySaveChanged(); + } +} + +bool PreviewModel::GetCommentBoxEnabled() +{ + return commentBoxEnabled; +} + +void PreviewModel::SetCommentBoxEnabled(bool enabledState) +{ + if(enabledState != commentBoxEnabled) + { + commentBoxEnabled = enabledState; + notifyCommentBoxEnabledChanged(); + } +} + +void PreviewModel::UpdateSave(int saveID, int saveDate) +{ + this->tSaveID = saveID; + this->tSaveDate = saveDate; + + if(save) + { + delete save; + save = NULL; + } + saveDataBuffer.clear(); + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + saveComments->clear(); + delete saveComments; + saveComments = NULL; + } + notifySaveChanged(); + notifySaveCommentsChanged(); + + if(!updateSaveDataWorking) + { + updateSaveDataWorking = true; + updateSaveDataFinished = false; + pthread_create(&updateSaveDataThread, 0, &PreviewModel::updateSaveDataTHelper, this); + } + + if(!updateSaveInfoWorking) + { + updateSaveInfoWorking = true; + updateSaveInfoFinished = false; + pthread_create(&updateSaveInfoThread, 0, &PreviewModel::updateSaveInfoTHelper, this); + } + + if(!updateSaveCommentsWorking) + { + commentsLoaded = false; + updateSaveCommentsWorking = true; + updateSaveCommentsFinished = false; + pthread_create(&updateSaveCommentsThread, 0, &PreviewModel::updateSaveCommentsTHelper, this); + } +} + +void PreviewModel::SetDoOpen(bool doOpen) +{ + this->doOpen = doOpen; +} + +bool PreviewModel::GetDoOpen() +{ + return doOpen; +} + +SaveInfo * PreviewModel::GetSave() +{ + return save; +} + +int PreviewModel::GetCommentsPageNum() +{ + return commentsPageNumber; +} + +int PreviewModel::GetCommentsPageCount() +{ + return max(1, (int)(ceil(commentsTotal/20.0f))); +} + +bool PreviewModel::GetCommentsLoaded() +{ + return commentsLoaded; +} + +void PreviewModel::UpdateComments(int pageNumber) +{ + commentsLoaded = false; + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + saveComments->clear(); + delete saveComments; + saveComments = NULL; + } + + //resultCount = 0; + commentsPageNumber = pageNumber; + notifySaveCommentsChanged(); + notifyCommentsPageChanged(); + + //Threading + if(!updateSaveCommentsWorking) + { + updateSaveCommentsFinished = false; + updateSaveCommentsWorking = true; + pthread_create(&updateSaveCommentsThread, 0, &PreviewModel::updateSaveCommentsTHelper, this); + } +} + +std::vector<SaveComment*> * PreviewModel::GetComments() +{ + return saveComments; +} + +void PreviewModel::notifySaveChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifySaveChanged(this); + } +} + +void PreviewModel::notifyCommentBoxEnabledChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyCommentBoxEnabledChanged(this); + } +} + +void PreviewModel::notifyCommentsPageChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyCommentsPageChanged(this); + } +} + +void PreviewModel::notifySaveCommentsChanged() +{ + for(int i = 0; i < observers.size(); i++) + { + observers[i]->NotifyCommentsChanged(this); + } +} + +void PreviewModel::AddObserver(PreviewView * observer) { + observers.push_back(observer); + observer->NotifySaveChanged(this); + observer->NotifyCommentsChanged(this); + observer->NotifyCommentsPageChanged(this); + observer->NotifyCommentBoxEnabledChanged(this); +} + +void PreviewModel::Update() +{ + if(updateSaveDataWorking) + { + if(updateSaveDataFinished) + { + updateSaveDataWorking = false; + pthread_join(updateSaveDataThread, NULL); + + if(updateSaveInfoFinished && save) + { + commentsTotal = save->Comments; + try + { + save->SetGameSave(new GameSave(&saveDataBuffer[0], saveDataBuffer.size())); + } + catch(ParseException &e) + { + throw PreviewModelException("Save file corrupt or from newer version"); + } + notifySaveChanged(); + notifyCommentsPageChanged(); + } + } + } + + if(updateSaveInfoWorking) + { + if(updateSaveInfoFinished) + { + if(save) + { + delete save; + save = NULL; + } + updateSaveInfoWorking = false; + pthread_join(updateSaveInfoThread, (void**)(&save)); + if(updateSaveDataFinished && save) + { + commentsTotal = save->Comments; + try + { + save->SetGameSave(new GameSave(&saveDataBuffer[0], saveDataBuffer.size())); + } + catch(ParseException &e) + { + throw PreviewModelException("Save file corrupt or from newer version"); + } + notifyCommentsPageChanged(); + } + notifySaveChanged(); + + if(!save) + throw PreviewModelException("Unable to load save"); + } + } + + if(updateSaveCommentsWorking) + { + if(updateSaveCommentsFinished) + { + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + saveComments->clear(); + delete saveComments; + saveComments = NULL; + } + commentsLoaded = true; + updateSaveCommentsWorking = false; + pthread_join(updateSaveCommentsThread, (void**)(&saveComments)); + notifySaveCommentsChanged(); + } + } +} + +PreviewModel::~PreviewModel() { + pthread_cancel(updateSaveDataThread); + pthread_cancel(updateSaveInfoThread); + pthread_cancel(updateSaveCommentsThread); + if(save) + delete save; + if(saveComments) + { + for(int i = 0; i < saveComments->size(); i++) + delete saveComments->at(i); + saveComments->clear(); + delete saveComments; + } + saveDataBuffer.clear(); +} + diff --git a/src/gui/preview/PreviewModel.h b/src/gui/preview/PreviewModel.h new file mode 100644 index 0000000..846614c --- /dev/null +++ b/src/gui/preview/PreviewModel.h @@ -0,0 +1,85 @@ +#ifndef PREVIEWMODEL_H_ +#define PREVIEWMODEL_H_ + +#include <vector> +#include <iostream> +#include <pthread.h> +#undef GetUserName //God dammit microsoft! +#include "PreviewView.h" +#include "client/SaveInfo.h" +#include "gui/preview/Comment.h" +#include "gui/search/Thumbnail.h" + +using namespace std; + +struct SaveData +{ + unsigned char * data; + int length; +}; + +class PreviewView; +class PreviewModel { + bool doOpen; + bool commentBoxEnabled; + vector<PreviewView*> observers; + SaveInfo * save; + vector<char> saveDataBuffer; + std::vector<SaveComment*> * saveComments; + void notifySaveChanged(); + void notifySaveCommentsChanged(); + void notifyCommentsPageChanged(); + void notifyCommentBoxEnabledChanged(); + + //Background retrieval + int tSaveID; + int tSaveDate; + + // + bool commentsLoaded; + int commentsTotal; + int commentsPageNumber; + + bool updateSaveDataWorking; + volatile bool updateSaveDataFinished; + pthread_t updateSaveDataThread; + static void * updateSaveDataTHelper(void * obj); + static void updateSaveDataTDelete(void * arg); + void * updateSaveDataT(); + + bool updateSaveInfoWorking; + volatile bool updateSaveInfoFinished; + pthread_t updateSaveInfoThread; + static void * updateSaveInfoTHelper(void * obj); + static void updateSaveInfoTDelete(void * arg); + void * updateSaveInfoT(); + + bool updateSaveCommentsWorking; + volatile bool updateSaveCommentsFinished; + pthread_t updateSaveCommentsThread; + static void * updateSaveCommentsTHelper(void * obj); + static void updateSaveCommentsTDelete(void * arg); + void * updateSaveCommentsT(); +public: + PreviewModel(); + SaveInfo * GetSave(); + std::vector<SaveComment*> * GetComments(); + + bool GetCommentBoxEnabled(); + void SetCommentBoxEnabled(bool enabledState); + + bool GetCommentsLoaded(); + int GetCommentsPageNum(); + int GetCommentsPageCount(); + void UpdateComments(int pageNumber); + + void AddObserver(PreviewView * observer); + void UpdateSave(int saveID, int saveDate); + void SetFavourite(bool favourite); + bool GetDoOpen(); + void SetDoOpen(bool doOpen); + void Update(); + virtual ~PreviewModel(); +}; + +#endif /* PREVIEWMODEL_H_ */ diff --git a/src/gui/preview/PreviewModelException.h b/src/gui/preview/PreviewModelException.h new file mode 100644 index 0000000..85dce1d --- /dev/null +++ b/src/gui/preview/PreviewModelException.h @@ -0,0 +1,19 @@ +#ifndef PREVIEWMODELEXCEPTION_H_ +#define PREVIEWMODELEXCEPTION_H_ + +#include <string> +#include <exception> +using namespace std; + +struct PreviewModelException: public exception { + string message; +public: + PreviewModelException(string message_): message(message_) {} + const char * what() const throw() + { + return message.c_str(); + } + ~PreviewModelException() throw() {}; +}; + +#endif /* PREVIEWMODELEXCEPTION_H_ */ diff --git a/src/gui/preview/PreviewView.cpp b/src/gui/preview/PreviewView.cpp new file mode 100644 index 0000000..4211732 --- /dev/null +++ b/src/gui/preview/PreviewView.cpp @@ -0,0 +1,614 @@ +#include <sstream> +#include <vector> +#include <cmath> +#include "PreviewView.h" +#include "gui/dialogues/TextPrompt.h" +#include "simulation/SaveRenderer.h" +#include "gui/interface/Point.h" +#include "gui/interface/Window.h" +#include "gui/interface/Textbox.h" +#include "gui/Style.h" +#include "Format.h" +#include "gui/search/Thumbnail.h" +#include "client/Client.h" +#include "gui/interface/ScrollPanel.h" +#include "gui/interface/AvatarButton.h" +#include "gui/interface/Keys.h" + +class PreviewView::LoginAction: public ui::ButtonAction +{ + PreviewView * v; +public: + LoginAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + v->c->ShowLogin(); + } +}; + +class PreviewView::SubmitCommentAction: public ui::ButtonAction +{ + PreviewView * v; +public: + SubmitCommentAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + v->submitComment(); + } +}; + +class PreviewView::AutoCommentSizeAction: public ui::TextboxAction +{ + PreviewView * v; +public: + AutoCommentSizeAction(PreviewView * v): v(v) {} + virtual void TextChangedCallback(ui::Textbox * sender) { + v->commentBoxAutoHeight(); + } +}; + +PreviewView::PreviewView(): + ui::Window(ui::Point(-1, -1), ui::Point((XRES/2)+210, (YRES/2)+150)), + savePreview(NULL), + doOpen(false), + addCommentBox(NULL), + submitCommentButton(NULL), + commentBoxHeight(20), + showAvatars(true) +{ + class FavAction: public ui::ButtonAction + { + PreviewView * v; + public: + FavAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + v->c->FavouriteSave(); + } + }; + + showAvatars = Client::Ref().GetPrefBool("ShowAvatars", true); + + favButton = new ui::Button(ui::Point(50, Size.Y-19), ui::Point(51, 19), "Fav"); + favButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; favButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + favButton->SetIcon(IconFavourite); + favButton->SetActionCallback(new FavAction(this)); + favButton->Enabled = Client::Ref().GetAuthUser().ID?true:false; + AddComponent(favButton); + + class ReportPromptCallback: public TextDialogueCallback { + public: + PreviewView * v; + ReportPromptCallback(PreviewView * v_) { v = v_; } + virtual void TextCallback(TextPrompt::DialogueResult result, std::string resultText) { + if (result == TextPrompt::ResultOkay) + v->c->Report(resultText); + } + virtual ~ReportPromptCallback() { } + }; + + class ReportAction: public ui::ButtonAction + { + PreviewView * v; + public: + ReportAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + new TextPrompt("Report Save", "Things to consider when reporting:\n\bw1)\bg When reporting stolen saves, please include the ID of the original save.\n\bw2)\bg Do not waste staff time with fake or bogus reports, doing so may result in a ban.", "", "[reason]", true, new ReportPromptCallback(v)); + } + }; + reportButton = new ui::Button(ui::Point(100, Size.Y-19), ui::Point(51, 19), "Report"); + reportButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; reportButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + reportButton->SetIcon(IconReport); + reportButton->SetActionCallback(new ReportAction(this)); + reportButton->Enabled = Client::Ref().GetAuthUser().ID?true:false; + AddComponent(reportButton); + + class OpenAction: public ui::ButtonAction + { + PreviewView * v; + public: + OpenAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + v->c->DoOpen(); + } + }; + openButton = new ui::Button(ui::Point(0, Size.Y-19), ui::Point(51, 19), "Open"); + openButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; openButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + openButton->SetIcon(IconOpen); + openButton->SetActionCallback(new OpenAction(this)); + AddComponent(openButton); + + class BrowserOpenAction: public ui::ButtonAction + { + PreviewView * v; + public: + BrowserOpenAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + v->c->OpenInBrowser(); + } + }; + + browserOpenButton = new ui::Button(ui::Point((XRES/2)-107, Size.Y-19), ui::Point(108, 19), "Open in browser"); + browserOpenButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; browserOpenButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + browserOpenButton->SetIcon(IconOpen); + browserOpenButton->SetActionCallback(new BrowserOpenAction(this)); + AddComponent(browserOpenButton); + + if(showAvatars) + saveNameLabel = new ui::Label(ui::Point(39, (YRES/2)+4), ui::Point(100, 16), ""); + else + saveNameLabel = new ui::Label(ui::Point(5, (YRES/2)+4), ui::Point(100, 16), ""); + saveNameLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + saveNameLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(saveNameLabel); + + if(showAvatars) + saveDescriptionLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15+21), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+4+15+17)-25), ""); + else + saveDescriptionLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15+19), ui::Point((XRES/2)-10, Size.Y-((YRES/2)+4+15+17)-23), ""); + saveDescriptionLabel->SetMultiline(true); + saveDescriptionLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + saveDescriptionLabel->Appearance.VerticalAlign = ui::Appearance::AlignTop; + saveDescriptionLabel->SetTextColour(ui::Colour(180, 180, 180)); + AddComponent(saveDescriptionLabel); + + if(showAvatars) + authorDateLabel = new ui::Label(ui::Point(39, (YRES/2)+4+15), ui::Point(180, 16), ""); + else + authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15), ui::Point(200, 16), ""); + authorDateLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + authorDateLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(authorDateLabel); + + if(showAvatars) + { + avatarButton = new ui::AvatarButton(ui::Point(4, (YRES/2)+4), ui::Point(34, 34), ""); + AddComponent(avatarButton); + } + + viewsLabel = new ui::Label(ui::Point((XRES/2)-80, (YRES/2)+4+15), ui::Point(80, 16), ""); + viewsLabel->Appearance.HorizontalAlign = ui::Appearance::AlignRight; + viewsLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + AddComponent(viewsLabel); + + + pageInfo = new ui::Label(ui::Point((XRES/2) + 5, Size.Y+1), ui::Point(Size.X-((XRES/2) + 10), 15), "Page 1 of 1"); + pageInfo->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; authorDateLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + + saveIDTextbox = new ui::Textbox(ui::Point((XRES/2)-55, Size.Y-40), ui::Point(50, 16), "0000000"); + saveIDTextbox->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + saveIDTextbox->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + saveIDTextbox->ReadOnly = true; + AddComponent(saveIDTextbox); + + class CopyIDAction: public ui::ButtonAction + { + PreviewView * v; + public: + CopyIDAction(PreviewView * v_){ v = v_; } + virtual void ActionCallback(ui::Button * sender) + { + ClipboardPush((char*)v->saveIDTextbox->GetText().c_str()); + } + }; + + ui::Button * tempButton = new ui::Button(ui::Point((XRES/2)-130, Size.Y-40), ui::Point(70, 16), "Copy Save ID"); + tempButton->Appearance.HorizontalAlign = ui::Appearance::AlignCentre; + tempButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + tempButton->SetActionCallback(new CopyIDAction(this)); + AddComponent(tempButton); + + commentsPanel = new ui::ScrollPanel(ui::Point((XRES/2)+1, 1), ui::Point((Size.X-(XRES/2))-2, Size.Y-commentBoxHeight)); + AddComponent(commentsPanel); + + AddComponent(pageInfo); +} + +void PreviewView::AttachController(PreviewController * controller) +{ + c = controller; + saveIDTextbox->SetText(format::NumberToString<int>(c->SaveID())); +} + +void PreviewView::commentBoxAutoHeight() +{ + if(!addCommentBox) + return; + int textWidth = Graphics::textwidth(addCommentBox->GetText().c_str()); + if(textWidth+15 > Size.X-(XRES/2)-48) + { + addCommentBox->Appearance.VerticalAlign = ui::Appearance::AlignTop; + + int oldSize = addCommentBox->Size.Y; + addCommentBox->AutoHeight(); + int newSize = addCommentBox->Size.Y+5; + addCommentBox->Size.Y = oldSize; + + commentBoxHeight = newSize+22; + commentBoxPositionX = (XRES/2)+4; + commentBoxPositionY = Size.Y-(newSize+21); + commentBoxSizeX = Size.X-(XRES/2)-8; + commentBoxSizeY = newSize; + } + else + { + commentBoxHeight = 20; + addCommentBox->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + + commentBoxPositionX = (XRES/2)+4; + commentBoxPositionY = Size.Y-19; + commentBoxSizeX = Size.X-(XRES/2)-48; + commentBoxSizeY = 17; + } + commentsPanel->Size.Y = Size.Y-commentBoxHeight; +} + +void PreviewView::DoDraw() +{ + Window::DoDraw(); + Graphics * g = ui::Engine::Ref().g; + for(int i = 0; i < commentTextComponents.size(); i++) + { + int linePos = commentTextComponents[i]->Position.Y+commentsPanel->ViewportPosition.Y+commentTextComponents[i]->Size.Y+4; + if(linePos > 0 && linePos < Size.Y-commentBoxHeight) + g->draw_line( + Position.X+1+XRES/2, + Position.Y+linePos, + Position.X+Size.X-2, + Position.Y+linePos, + 255, 255, 255, 100); + } + if(c->GetDoOpen()) + { + g->fillrect(Position.X+(Size.X/2)-101, Position.Y+(Size.Y/2)-26, 202, 52, 0, 0, 0, 210); + g->drawrect(Position.X+(Size.X/2)-100, Position.Y+(Size.Y/2)-25, 200, 50, 255, 255, 255, 180); + g->drawtext(Position.X+(Size.X/2)-(Graphics::textwidth("Loading save...")/2), Position.Y+(Size.Y/2)-5, "Loading save...", style::Colour::InformationTitle.Red, style::Colour::InformationTitle.Green, style::Colour::InformationTitle.Blue, 255); + } + g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 255, 255, 255, 255); + +} + +void PreviewView::OnDraw() +{ + Graphics * g = ui::Engine::Ref().g; + + //Window Background+Outline + g->clearrect(Position.X-2, Position.Y-2, Size.X+4, Size.Y+4); + + //Save preview (top-left) + if(savePreview && savePreview->Buffer) + { + g->draw_image(savePreview, (Position.X+1)+(((XRES/2)-savePreview->Width)/2), (Position.Y+1)+(((YRES/2)-savePreview->Height)/2), 255); + } + g->drawrect(Position.X, Position.Y, (XRES/2)+1, (YRES/2)+1, 255, 255, 255, 100); + g->draw_line(Position.X+XRES/2, Position.Y+1, Position.X+XRES/2, Position.Y+Size.Y-2, 200, 200, 200, 255); + + if(votesUp || votesDown) + { + float ryf; + int nyu, nyd; + int lv = (votesUp>votesDown)?votesUp:votesDown; + lv = (lv>10)?lv:10; + + if (50>lv) + { + ryf = 50.0f/((float)lv); + nyu = votesUp*ryf; + nyd = votesDown*ryf; + } + else + { + ryf = ((float)lv)/50.0f; + nyu = votesUp/ryf; + nyd = votesDown/ryf; + } + nyu = nyu>50?50:nyu; + nyd = nyd>50?50:nyd; + + g->fillrect(Position.X+(XRES/2)-55, Position.Y+(YRES/2)+3, 53, 7, 0, 107, 10, 255); + g->fillrect(Position.X+(XRES/2)-55, Position.Y+(YRES/2)+9, 53, 7, 107, 10, 0, 255); + g->drawrect(Position.X+(XRES/2)-55, Position.Y+(YRES/2)+3, 53, 7, 128, 128, 128, 255); + g->drawrect(Position.X+(XRES/2)-55, Position.Y+(YRES/2)+9, 53, 7, 128, 128, 128, 255); + + g->fillrect(Position.X+(XRES/2)-4-nyu, Position.Y+(YRES/2)+5, nyu, 3, 57, 187, 57, 255); + g->fillrect(Position.X+(XRES/2)-4-nyd, Position.Y+(YRES/2)+11, nyd, 3, 187, 57, 57, 255); + } +} + +void PreviewView::OnTick(float dt) +{ + if(addCommentBox) + { + ui::Point positionDiff = ui::Point(commentBoxPositionX, commentBoxPositionY)-addCommentBox->Position; + ui::Point sizeDiff = ui::Point(commentBoxSizeX, commentBoxSizeY)-addCommentBox->Size; + + if(positionDiff.X!=0) + { + int xdiff = positionDiff.X/5; + if(xdiff == 0) + xdiff = 1*isign(positionDiff.X); + addCommentBox->Position.X += xdiff; + } + if(positionDiff.Y!=0) + { + int ydiff = positionDiff.Y/5; + if(ydiff == 0) + ydiff = 1*isign(positionDiff.Y); + addCommentBox->Position.Y += ydiff; + } + + if(sizeDiff.X!=0) + { + int xdiff = sizeDiff.X/5; + if(xdiff == 0) + xdiff = 1*isign(sizeDiff.X); + addCommentBox->Size.X += xdiff; + addCommentBox->Invalidate(); + } + if(sizeDiff.Y!=0) + { + int ydiff = sizeDiff.Y/5; + if(ydiff == 0) + ydiff = 1*isign(sizeDiff.Y); + addCommentBox->Size.Y += ydiff; + addCommentBox->Invalidate(); + } + } + + c->Update(); +} + +void PreviewView::OnTryExit(ExitMethod method) +{ + c->Exit(); +} + +void PreviewView::OnMouseWheel(int x, int y, int d) +{ + if(commentsPanel->GetScrollLimit() == 1 && d < 0) + c->NextCommentPage(); + if(commentsPanel->GetScrollLimit() == -1 && d > 0) + c->PrevCommentPage(); + +} + +void PreviewView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt) +{ + if ((key == KEY_ENTER || key == KEY_RETURN) && (!addCommentBox || !addCommentBox->IsFocused())) + openButton->DoAction(); +} + +void PreviewView::NotifySaveChanged(PreviewModel * sender) +{ + SaveInfo * save = sender->GetSave(); + if(savePreview) + delete savePreview; + savePreview = NULL; + if(save) + { + votesUp = save->votesUp; + votesDown = save->votesDown; + saveNameLabel->SetText(save->name); + if(showAvatars) { + avatarButton->SetUsername(save->userName); + authorDateLabel->SetText("\bw" + save->userName + " \bgDate:\bw " + format::UnixtimeToDateMini(save->date)); + } + else + { + authorDateLabel->SetText("\bgAuthor:\bw " + save->userName + " \bgDate:\bw " + format::UnixtimeToDateMini(save->date)); + } + viewsLabel->SetText("\bgViews:\bw " + format::NumberToString<int>(save->Views)); + saveDescriptionLabel->SetText(save->Description); + if(save->Favourite) + { + favButton->Enabled = true; + favButton->SetText("Unfav"); + } + else if(Client::Ref().GetAuthUser().ID) + { + favButton->Enabled = true; + favButton->SetText("Fav"); + } + else + { + favButton->SetText("Fav"); + favButton->Enabled = false; + } + + if(save->GetGameSave()) + { + savePreview = SaveRenderer::Ref().Render(save->GetGameSave(), false, true); + + if(savePreview && savePreview->Buffer && !(savePreview->Width == XRES/2 && savePreview->Width == YRES/2)) + { + int newSizeX, newSizeY; + pixel * oldData = savePreview->Buffer; + float factorX = ((float)XRES/2)/((float)savePreview->Width); + float factorY = ((float)YRES/2)/((float)savePreview->Height); + float scaleFactor = factorY < factorX ? factorY : factorX; + savePreview->Buffer = Graphics::resample_img(oldData, savePreview->Width, savePreview->Height, savePreview->Width*scaleFactor, savePreview->Height*scaleFactor); + delete[] oldData; + savePreview->Width *= scaleFactor; + savePreview->Height *= scaleFactor; + } + } + } + else + { + votesUp = 0; + votesDown = 0; + saveNameLabel->SetText(""); + authorDateLabel->SetText(""); + saveDescriptionLabel->SetText(""); + favButton->Enabled = false; + } +} + +void PreviewView::submitComment() +{ + if(addCommentBox) + { + std::string comment = std::string(addCommentBox->GetText()); + submitCommentButton->Enabled = false; + addCommentBox->SetText(""); + addCommentBox->SetPlaceholder("Submitting comment"); //This doesn't appear to ever show since no separate thread is created + FocusComponent(NULL); + + if (!c->SubmitComment(comment)) + addCommentBox->SetText(comment); + + addCommentBox->SetPlaceholder("Add comment"); + submitCommentButton->Enabled = true; + + commentBoxAutoHeight(); + } +} + +void PreviewView::NotifyCommentBoxEnabledChanged(PreviewModel * sender) +{ + if(addCommentBox) + { + RemoveComponent(addCommentBox); + delete addCommentBox; + addCommentBox = NULL; + } + if(submitCommentButton) + { + RemoveComponent(submitCommentButton); + delete submitCommentButton; + submitCommentButton = NULL; + } + if(sender->GetCommentBoxEnabled()) + { + commentBoxPositionX = (XRES/2)+4; + commentBoxPositionY = Size.Y-19; + commentBoxSizeX = Size.X-(XRES/2)-48; + commentBoxSizeY = 17; + + addCommentBox = new ui::Textbox(ui::Point((XRES/2)+4, Size.Y-19), ui::Point(Size.X-(XRES/2)-48, 17), "", "Add Comment"); + addCommentBox->SetActionCallback(new AutoCommentSizeAction(this)); + addCommentBox->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + addCommentBox->SetMultiline(true); + AddComponent(addCommentBox); + submitCommentButton = new ui::Button(ui::Point(Size.X-40, Size.Y-19), ui::Point(40, 19), "Submit"); + submitCommentButton->SetActionCallback(new SubmitCommentAction(this)); + //submitCommentButton->Enabled = false; + AddComponent(submitCommentButton); + } + else + { + submitCommentButton = new ui::Button(ui::Point(XRES/2, Size.Y-19), ui::Point(Size.X-(XRES/2), 19), "Login to comment"); + submitCommentButton->SetActionCallback(new LoginAction(this)); + AddComponent(submitCommentButton); + } +} + +void PreviewView::NotifyCommentsPageChanged(PreviewModel * sender) +{ + std::stringstream pageInfoStream; + pageInfoStream << "Page " << sender->GetCommentsPageNum() << " of " << sender->GetCommentsPageCount(); + pageInfo->SetText(pageInfoStream.str()); +} + +void PreviewView::NotifyCommentsChanged(PreviewModel * sender) +{ + std::vector<SaveComment*> * comments = sender->GetComments(); + + for(int i = 0; i < commentComponents.size(); i++) + { + commentsPanel->RemoveChild(commentComponents[i]); + delete commentComponents[i]; + } + commentComponents.clear(); + commentTextComponents.clear(); + commentsPanel->InnerSize = ui::Point(0, 0); + + if(comments) + { + for(int i = 0; i < commentComponents.size(); i++) + { + commentsPanel->RemoveChild(commentComponents[i]); + delete commentComponents[i]; + } + commentComponents.clear(); + commentTextComponents.clear(); + + int currentY = 0;//-yOffset; + ui::Label * tempUsername; + ui::Label * tempComment; + ui::AvatarButton * tempAvatar; + for(int i = 0; i < comments->size(); i++) + { + int usernameY = currentY+5, commentY; + if(showAvatars) + { + tempAvatar = new ui::AvatarButton(ui::Point(2, currentY+7), ui::Point(26, 26), comments->at(i)->authorName); + commentComponents.push_back(tempAvatar); + commentsPanel->AddChild(tempAvatar); + } + + if(showAvatars) + tempUsername = new ui::Label(ui::Point(31, currentY+3), ui::Point(Size.X-((XRES/2) + 13), 16), comments->at(i)->authorNameFormatted); + else + tempUsername = new ui::Label(ui::Point(5, currentY+3), ui::Point(Size.X-((XRES/2) + 13), 16), comments->at(i)->authorNameFormatted); + tempUsername->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tempUsername->Appearance.VerticalAlign = ui::Appearance::AlignBottom; + currentY += 16; + + commentComponents.push_back(tempUsername); + commentsPanel->AddChild(tempUsername); + + commentY = currentY+5; + if(showAvatars) + tempComment = new ui::Label(ui::Point(31, currentY+5), ui::Point(Size.X-((XRES/2) + 13 + 26), -1), comments->at(i)->comment); + else + tempComment = new ui::Label(ui::Point(5, currentY+5), ui::Point(Size.X-((XRES/2) + 13), -1), comments->at(i)->comment); + tempComment->SetMultiline(true); + tempComment->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + tempComment->Appearance.VerticalAlign = ui::Appearance::AlignTop; + tempComment->SetTextColour(ui::Colour(180, 180, 180)); + currentY += tempComment->Size.Y+4; + + commentComponents.push_back(tempComment); + commentsPanel->AddChild(tempComment); + commentTextComponents.push_back(tempComment); + } + + commentsPanel->InnerSize = ui::Point(commentsPanel->Size.X, currentY+4); + } +} + +/*void PreviewView::NotifyPreviewChanged(PreviewModel * sender) +{ + savePreview = sender->GetGameSave(); + if(savePreview && savePreview->Data && !(savePreview->Width == XRES/2 && savePreview->Height == YRES/2)) + { + int newSizeX, newSizeY; + float factorX = ((float)XRES/2)/((float)savePreview->Width); + float factorY = ((float)YRES/2)/((float)savePreview->Height); + float scaleFactor = factorY < factorX ? factorY : factorX; + savePreview->Data = Graphics::resample_img(savePreview->Data, savePreview->Width, savePreview->Height, savePreview->Width*scaleFactor, savePreview->Height*scaleFactor); + savePreview->Width *= scaleFactor; + savePreview->Height *= scaleFactor; + } +}*/ + +PreviewView::~PreviewView() +{ + if(addCommentBox) + { + RemoveComponent(addCommentBox); + delete addCommentBox; + } + if(submitCommentButton) + { + RemoveComponent(submitCommentButton); + delete submitCommentButton; + } + if(savePreview) + delete savePreview; +} + diff --git a/src/gui/preview/PreviewView.h b/src/gui/preview/PreviewView.h new file mode 100644 index 0000000..2fef5ac --- /dev/null +++ b/src/gui/preview/PreviewView.h @@ -0,0 +1,74 @@ +#ifndef PREVIEWVIEW_H_ +#define PREVIEWVIEW_H_ + +#include <vector> +#include "Comment.h" +#include "gui/interface/Window.h" +#include "gui/preview/PreviewController.h" +#include "gui/preview/PreviewModel.h" +#include "gui/interface/Button.h" +#include "gui/interface/Label.h" +#include "gui/interface/Textbox.h" + +namespace ui +{ + class ScrollPanel; + class AvatarButton; +} + +class VideoBuffer; +class PreviewModel; +class PreviewController; +class PreviewView: public ui::Window { + class SubmitCommentAction; + class LoginAction; + class AutoCommentSizeAction; + PreviewController * c; + VideoBuffer * savePreview; + ui::Button * openButton; + ui::Button * browserOpenButton; + ui::Button * favButton; + ui::Button * reportButton; + ui::Button * submitCommentButton; + ui::Textbox * addCommentBox; + ui::Label * saveNameLabel; + ui::Label * authorDateLabel; + ui::AvatarButton * avatarButton; + ui::Label * pageInfo; + ui::Label * saveDescriptionLabel; + ui::Label * viewsLabel; + ui::Textbox * saveIDTextbox; + ui::ScrollPanel * commentsPanel; + std::vector<ui::Component*> commentComponents; + std::vector<ui::Component*> commentTextComponents; + int votesUp; + int votesDown; + bool doOpen; + bool showAvatars; + + int commentBoxHeight; + float commentBoxPositionX; + float commentBoxPositionY; + float commentBoxSizeX; + float commentBoxSizeY; + + void displayComments(); + void commentBoxAutoHeight(); + void submitComment(); +public: + void AttachController(PreviewController * controller); + PreviewView(); + void NotifySaveChanged(PreviewModel * sender); + void NotifyCommentsChanged(PreviewModel * sender); + void NotifyCommentsPageChanged(PreviewModel * sender); + void NotifyCommentBoxEnabledChanged(PreviewModel * sender); + virtual void OnDraw(); + virtual void DoDraw(); + virtual void OnTick(float dt); + virtual void OnTryExit(ExitMethod method); + virtual void OnMouseWheel(int x, int y, int d); + virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt); + virtual ~PreviewView(); +}; + +#endif /* PREVIEWVIEW_H_ */ |
