diff --git a/HBC/META.XML b/HBC/META.XML index 0a09f86d..5d5eb1c1 100644 --- a/HBC/META.XML +++ b/HBC/META.XML @@ -2,8 +2,8 @@ USB Loader GX USB Loader GX Team - 2.0 r1063 - 201102041525 + 2.0 r1064 + 201102051039 Loads games from USB-devices USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times. diff --git a/gui.pnproj b/gui.pnproj index 80f6da60..3ff70a53 100644 --- a/gui.pnproj +++ b/gui.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/ZipFile.cpp b/source/ZipFile.cpp index 0f9dcb1b..e1a7be12 100644 --- a/source/ZipFile.cpp +++ b/source/ZipFile.cpp @@ -55,6 +55,57 @@ bool ZipFile::LoadList() return true; } +bool ZipFile::FindFile(const char *file) +{ + if (!File) return false; + + char filename[MAXPATHLEN]; + + int ret = unzGoToFirstFile(File); + if (ret != UNZ_OK) return false; + + do + { + if(unzGetCurrentFileInfo(File, &cur_file_info, filename, sizeof(filename), NULL, 0, NULL, 0) != UNZ_OK) + continue; + + const char *realfilename = strrchr(filename, '/'); + if(!realfilename || strlen(realfilename) == 0) + realfilename = filename; + + if(strcasecmp(realfilename, file) == 0) + return true; + } + while(unzGoToNextFile(File) == UNZ_OK); + + return false; +} + +bool ZipFile::FindFilePart(const char *partfilename, std::string &realname) +{ + if (!File) return false; + + char filename[MAXPATHLEN]; + + int ret = unzGoToFirstFile(File); + if (ret != UNZ_OK) return false; + + do + { + if(unzGetCurrentFileInfo(File, &cur_file_info, filename, sizeof(filename), NULL, 0, NULL, 0) != UNZ_OK) + continue; + + if(strcasestr(filename, partfilename) != 0) + { + realname = filename; + return true; + } + } + while(unzGoToNextFile(File) == UNZ_OK); + + return false; +} + bool ZipFile::ExtractAll(const char *dest) { if (!File) return false; diff --git a/source/ZipFile.h b/source/ZipFile.h index b9d756e4..5e61c079 100644 --- a/source/ZipFile.h +++ b/source/ZipFile.h @@ -29,6 +29,7 @@ #define _ZIPFILE_H_ #include +#include typedef struct { @@ -48,6 +49,10 @@ class ZipFile //!Extract all files from a zip file to a directory //!\param dest Destination path to where to extract bool ExtractAll(const char *dest); + //!Find a file inside the zip and return if it is existent or not + bool FindFile(const char *filename); + //!Only needed a part of a filename to find the real one + bool FindFilePart(const char *partfilename, std::string &realname); protected: bool LoadList(); unzFile File; diff --git a/source/menu.cpp b/source/menu.cpp index 9aafeed9..14b66473 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -22,6 +22,7 @@ #include "settings/Settings.h" #include "settings/CGameSettings.h" #include "themes/CTheme.h" +#include "themes/ThemeMenu.h" #include "themes/ThemeDownloader.h" #include "usbloader/disc.h" #include "usbloader/GameList.h" @@ -217,6 +218,9 @@ int MainMenu(int menu) case MENU_SETTINGS: currentMenu = MenuSettings(); break; + case MENU_THEMEMENU: + currentMenu = ThemeMenu::Run(); + break; case MENU_THEMEDOWNLOADER: currentMenu = ThemeDownloader::Run(); break; diff --git a/source/menu.h b/source/menu.h index e9cee0b0..f535941f 100644 --- a/source/menu.h +++ b/source/menu.h @@ -29,7 +29,8 @@ enum MENU_GAME_SETTINGS, MENU_HOMEBREWBROWSE, BOOTHOMEBREW, - MENU_THEMEDOWNLOADER + MENU_THEMEDOWNLOADER, + MENU_THEMEMENU, }; void ResumeGui(); diff --git a/source/settings/SettingsPrompts.cpp b/source/settings/SettingsPrompts.cpp index 73471943..e7f8845e 100644 --- a/source/settings/SettingsPrompts.cpp +++ b/source/settings/SettingsPrompts.cpp @@ -332,213 +332,3 @@ int MenuLanguageSelect() return returnhere; } - - -/**************************************************************************** - * MenuThemeSelect - ***************************************************************************/ -int MenuThemeSelect() -{ - int cnt = 0; - int ret = 0, choice = 0; - int returnVal = 0; - - GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png")); - GuiImageData settingsbg(Resources::GetFile("settings_background.png"), Resources::GetFileSize("settings_background.png")); - - GuiTrigger trigA; - trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A ); - GuiTrigger trigB; - trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B ); - - GuiText titleTxt(Settings.theme_path, 24, ( GXColor ) {0, 0, 0, 255} ); - titleTxt.SetAlignment( ALIGN_CENTRE, ALIGN_MIDDLE ); - titleTxt.SetPosition( 0, 0 ); - GuiButton pathBtn( 300, 50 ); - pathBtn.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); - pathBtn.SetPosition( 0, 28 ); - pathBtn.SetLabel( &titleTxt ); - pathBtn.SetSoundOver( btnSoundOver ); - pathBtn.SetSoundClick( btnSoundClick2 ); - pathBtn.SetTrigger( &trigA ); - pathBtn.SetEffectGrow(); - - GuiImage backgroundImg( &settingsbg ); - backgroundImg.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); - backgroundImg.SetPosition( 0, 0 ); - - GuiText backBtnTxt( tr( "Back" ) , 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); - backBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 ); - GuiImage backBtnImg( &btnOutline ); - if ( Settings.wsprompt == ON ) - { - backBtnTxt.SetWidescreen( Settings.widescreen ); - backBtnImg.SetWidescreen( Settings.widescreen ); - } - GuiButton backBtn( btnOutline.GetWidth(), btnOutline.GetHeight() ); - backBtn.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); - backBtn.SetPosition( -190, 400 ); - backBtn.SetLabel( &backBtnTxt ); - backBtn.SetImage( &backBtnImg ); - backBtn.SetSoundOver( btnSoundOver ); - backBtn.SetSoundClick( btnSoundClick2 ); - backBtn.SetTrigger( &trigA ); - backBtn.SetTrigger( &trigB ); - backBtn.SetEffectGrow(); - - GuiText defaultBtnTxt( tr( "Default" ) , 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); - defaultBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 ); - GuiImage defaultBtnImg( &btnOutline ); - if ( Settings.wsprompt == ON ) - { - defaultBtnTxt.SetWidescreen( Settings.widescreen ); - defaultBtnImg.SetWidescreen( Settings.widescreen ); - } - GuiButton defaultBtn( btnOutline.GetWidth(), btnOutline.GetHeight() ); - defaultBtn.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); - defaultBtn.SetPosition( 0, 400 ); - defaultBtn.SetLabel( &defaultBtnTxt ); - defaultBtn.SetImage( &defaultBtnImg ); - defaultBtn.SetSoundOver( btnSoundOver ); - defaultBtn.SetSoundClick( btnSoundClick2 ); - defaultBtn.SetTrigger( &trigA ); - defaultBtn.SetEffectGrow(); - - DirList * Dir = new DirList(Settings.theme_path, ".them"); - OptionList options2; - - for ( cnt = 0; cnt < Dir->GetFilecount(); cnt++ ) - { - char filename[64]; - strlcpy( filename, Dir->GetFilename( cnt ), sizeof( filename ) ); - char *dot = strchr( filename, '.' ); - if ( dot ) *dot = '\0'; - options2.SetName( cnt, "%s", filename ); - options2.SetValue( cnt, NULL ); - - } - - GuiCustomOptionBrowser optionBrowser4( 396, 280, &options2, "bg_options_settings.png"); - optionBrowser4.SetPosition( 0, 90 ); - optionBrowser4.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); - - HaltGui(); - GuiWindow w( screenwidth, screenheight ); - w.Append( &backgroundImg ); - w.Append( &pathBtn ); - w.Append( &backBtn ); - w.Append( &defaultBtn ); - w.Append( &optionBrowser4 ); - mainWindow->Append( &w ); - - w.SetEffect( EFFECT_FADE, 20 ); - ResumeGui(); - - while ( w.GetEffect() > 0 ) usleep(100); - - while (returnVal == 0) - { - usleep(100); - - if (shutdown) - Sys_Shutdown(); - else if (reset) - Sys_Reboot(); - - else if ( backBtn.GetState() == STATE_CLICKED ) - break; - - else if ( defaultBtn.GetState() == STATE_CLICKED ) - { - choice = WindowPrompt(0, tr( "Do you want to load the default theme?" ), tr( "OK" ), tr( "Cancel" ) ); - if ( choice == 1 ) - { - HaltGui(); - Theme::SetDefault(); - Theme::Reload(); - ResumeGui(); - Settings.Save(); - returnVal = 1; - } - defaultBtn.ResetState(); - } - - else if ( pathBtn.GetState() == STATE_CLICKED ) - { - w.Remove( &optionBrowser4 ); - w.Remove( &backBtn ); - w.Remove( &pathBtn ); - w.Remove( &defaultBtn ); - int result = BrowseDevice(Settings.theme_path, sizeof(Settings.theme_path), FB_DEFAULT, noFILES); - w.Append( &optionBrowser4 ); - w.Append( &pathBtn ); - w.Append( &backBtn ); - w.Append( &defaultBtn ); - if (result == 1) - { - if (Settings.theme_path[strlen(Settings.theme_path)-1] != '/') - strcat(Settings.theme_path, "/"); - - HaltGui(); - delete Dir; - Dir = new DirList(Settings.theme_path, ".them"); - options2.ClearList(); - for ( cnt = 0; cnt < Dir->GetFilecount(); cnt++ ) - { - char filename[64]; - strlcpy( filename, Dir->GetFilename( cnt ), sizeof( filename ) ); - char *dot = strchr( filename, '.' ); - if ( dot ) *dot = '\0'; - options2.SetName( cnt, "%s", filename ); - options2.SetValue( cnt, NULL ); - } - titleTxt.SetText(Settings.theme_path); - ResumeGui(); - WindowPrompt( tr( "Theme path is changed." ), 0, tr( "OK" ) ); - } - pathBtn.ResetState(); - } - - ret = optionBrowser4.GetClickedOption(); - - if (ret >= 0 && ret < Dir->GetFilecount()) - { - choice = WindowPrompt( tr( "Do you want to load this theme?" ), Dir->GetFilename(ret), tr( "Yes" ), tr( "Cancel" ) ); - if ( choice == 1 ) - { - snprintf(Settings.theme, sizeof( Settings.theme ), "%s", Dir->GetFilepath(ret)); - if ( !CheckFile( Settings.theme ) ) - { - WindowPrompt( tr( "File not found." ), tr( "Loading default theme." ), tr( "OK" ) ); - HaltGui(); - Theme::SetDefault(); - Theme::Reload(); - ResumeGui(); - } - else - { - HaltGui(); - Theme::Load(Settings.theme); - Theme::Reload(); - ResumeGui(); - } - Settings.Save(); - returnVal = 1; - break; - } - optionBrowser4.SetFocus( 1 ); - } - } - - w.SetEffect( EFFECT_FADE, -20 ); - while ( w.GetEffect() > 0 ) usleep(100); - - HaltGui(); - mainWindow->Remove( &w ); - ResumeGui(); - - delete Dir; - - return returnVal; -} - diff --git a/source/settings/SettingsPrompts.h b/source/settings/SettingsPrompts.h index d1c13e49..d16a12ac 100644 --- a/source/settings/SettingsPrompts.h +++ b/source/settings/SettingsPrompts.h @@ -10,6 +10,5 @@ bool MenuBackgroundMusic(); int MenuLanguageSelect(); -int MenuThemeSelect(); #endif diff --git a/source/settings/menus/CustomPathsSM.cpp b/source/settings/menus/CustomPathsSM.cpp index adb55682..97841f84 100644 --- a/source/settings/menus/CustomPathsSM.cpp +++ b/source/settings/menus/CustomPathsSM.cpp @@ -144,17 +144,7 @@ int CustomPathsSM::GetMenuInternal() else if (ret == ++Idx) { titleTxt->SetText(tr( "Theme Path" )); - HaltGui(); - GuiWindow * parent = (GuiWindow *) parentElement; - if(parent) parent->SetState(STATE_DISABLED); - this->SetState(STATE_DEFAULT); - this->Remove(optionBrowser); - ResumeGui(); - int res = MenuThemeSelect(); - if(parent) parent->SetState(STATE_DEFAULT); - this->Append(optionBrowser); - if (res == 1) - return MENU_SETTINGS; + ChangePath(Settings.theme_path, sizeof(Settings.theme_path)); } //! Settings: WiiTDB Path diff --git a/source/settings/menus/GlobalSettings.cpp b/source/settings/menus/GlobalSettings.cpp index 5a0262eb..e0428b22 100644 --- a/source/settings/menus/GlobalSettings.cpp +++ b/source/settings/menus/GlobalSettings.cpp @@ -56,10 +56,11 @@ void GlobalSettings::SetupMainButtons() SetMainButton(pos++, tr( "Parental Control" ), MainButtonImgData, MainButtonImgOverData); SetMainButton(pos++, tr( "Sound" ), MainButtonImgData, MainButtonImgOverData); SetMainButton(pos++, tr( "Custom Paths" ), MainButtonImgData, MainButtonImgOverData); + SetMainButton(pos++, tr( "Theme Menu" ), MainButtonImgData, MainButtonImgOverData); + SetMainButton(pos++, tr( "Theme Downloader" ), MainButtonImgData, MainButtonImgOverData); SetMainButton(pos++, tr( "Update" ), MainButtonImgData, MainButtonImgOverData); SetMainButton(pos++, tr( "Default Settings" ), MainButtonImgData, MainButtonImgOverData); SetMainButton(pos++, tr( "Credits" ), creditsImgData, creditsImgOverData); - SetMainButton(pos++, tr( "Theme Downloader" ), MainButtonImgData, MainButtonImgOverData); } void GlobalSettings::CreateSettingsMenu(int menuNr) @@ -139,6 +140,28 @@ void GlobalSettings::CreateSettingsMenu(int menuNr) CurrentMenu = new CustomPathsSM(); Append(CurrentMenu); } + //! Theme Menu + else if(menuNr == Idx++) + { + if(!Settings.godmode && (Settings.ParentalBlocks & BLOCK_THEME_MENU)) + { + WindowPrompt(tr( "Permission denied." ), tr( "Console must be unlocked for this option." ), tr( "OK" )); + return; + } + + returnMenu = MENU_THEMEMENU; + } + //! Theme Downloader + else if(menuNr == Idx++) + { + if(!Settings.godmode && (Settings.ParentalBlocks & BLOCK_THEME_DOWNLOADER)) + { + WindowPrompt(tr( "Permission denied." ), tr( "Console must be unlocked for this option." ), tr( "OK" )); + return; + } + + returnMenu = MENU_THEMEDOWNLOADER; + } //! Update else if(menuNr == Idx++) { @@ -186,17 +209,6 @@ void GlobalSettings::CreateSettingsMenu(int menuNr) Append(backBtn); ShowMenu(); } - //! Theme Downloader - else if(menuNr == Idx++) - { - if(!Settings.godmode && (Settings.ParentalBlocks & BLOCK_THEME_DOWNLOADER)) - { - WindowPrompt(tr( "Permission denied." ), tr( "Console must be unlocked for this option." ), tr( "OK" )); - return; - } - - returnMenu = MENU_THEMEDOWNLOADER; - } } void GlobalSettings::DeleteSettingsMenu() diff --git a/source/themes/ThemeDownloader.cpp b/source/themes/ThemeDownloader.cpp index bdbc9c2f..a4cce52b 100644 --- a/source/themes/ThemeDownloader.cpp +++ b/source/themes/ThemeDownloader.cpp @@ -1,10 +1,25 @@ /**************************************************************************** - * Theme_Downloader - * USB Loader GX 2009 + * Copyright (C) 2011 + * by Dimok * - * Theme downloader for USB Loader GX + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. * - * Theme_Downloader.cpp + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. ***************************************************************************/ #include #include @@ -245,9 +260,6 @@ void ThemeDownloader::SetupMainButtons() void ThemeDownloader::AddMainButtons() { - if(!ThemeList) - SetupMainButtons(); - HaltGui(); for(u32 i = 0; i < MainButton.size(); ++i) Remove(MainButton[i]); @@ -278,7 +290,7 @@ void ThemeDownloader::MainButtonClicked(int button) GuiImageData *thumbimageData = ThemePreviews[button % 4]; const char *downloadlink = ThemeList->GetDownloadLink(button); - gprintf("\nTheme_Prompt(%s ,%s, , %s)", title, author, downloadlink); + gprintf("\nTheme_Prompt(%s ,%s, %s)", title, author, downloadlink); bool leave = false; int result = 0; @@ -305,7 +317,7 @@ void ThemeDownloader::MainButtonClicked(int button) titleTxt2.SetPosition(230, 50); titleTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, WRAP); - GuiText authorTxt(tr( "Author:" ), 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + GuiText authorTxt(tr( "Author(s):" ), 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); authorTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); authorTxt.SetPosition(230, 100); @@ -424,63 +436,50 @@ int ThemeDownloader::DownloadTheme(const char *url, const char *title) return -2; } - ZipFile zipfile(filepath); + ZipFile *zipfile = new ZipFile(filepath); - int result = zipfile.ExtractAll(Settings.theme_path); + int result = zipfile->ExtractAll(Settings.theme_path); if(result < 0) { WindowPrompt(tr( "Failed to extract." ), tr( "Unsupported format, try to extract manually TempTheme.zip." ), tr( "OK" )); return -3; } - remove(filepath); + std::string themeDir; + std::string Filename; + zipfile->FindFilePart(".them", Filename); + zipfile->FindFilePart("/", themeDir); - DirList newDir(Settings.theme_path); + if(!zipfile->FindFile("theme_preview.png") && themeDir.size() != 0) + { + size_t pos = themeDir.find("/"); + if(pos != std::string::npos) + { + themeDir.erase(pos); + char filepath[255]; + char newfilepath[255]; + snprintf(filepath, sizeof(filepath), "%s/tmp/%s.jpg", Settings.theme_path, title); + snprintf(newfilepath, sizeof(newfilepath), "%s/%s/theme_preview.png", Settings.theme_path, themeDir.c_str()); + CopyFile(filepath, newfilepath); + } + + } + + delete zipfile; + remove(filepath); int choice = WindowPrompt(tr( "Successfully extracted theme." ), tr( "Do you want to apply it now?" ), tr( "Yes" ), tr( "No" )); if (choice == 0) return -1; - char Filename[255]; - memset(Filename, 0, sizeof(Filename)); - - for(int i = 0; i < newDir.GetFilecount(); ++i) - { - const char * FilenameNew = newDir.GetFilename(i); - if(!FilenameNew) - continue; - - const char * FileExt = strrchr(FilenameNew, '.'); - if(!FileExt || strcasecmp(FileExt, ".them") != 0) - continue; - - bool Found = false; - - for(int j = 0; j < oldDir.GetFilecount(); ++j) - { - const char * FilenameOld = oldDir.GetFilename(j); - if(!FilenameOld) - continue; - - if(strcasecmp(FilenameNew, FilenameOld) == 0) - Found = true; - } - - if(!Found) - { - snprintf(Filename, sizeof(Filename), FilenameNew); - break; - } - } - - if(Filename[0] == 0) + if(Filename.size() == 0) { WindowPrompt(tr( "ERROR: Can't set up theme." ), tr( "The .them file was not found in the zip." ), tr( "OK" )); return -1; } char real_themepath[1024]; - snprintf(real_themepath, sizeof(real_themepath), "%s/%s", Settings.theme_path, Filename); + snprintf(real_themepath, sizeof(real_themepath), "%s/%s", Settings.theme_path, Filename.c_str()); if (Theme::Load(real_themepath)) { diff --git a/source/themes/ThemeDownloader.h b/source/themes/ThemeDownloader.h index 03de636c..da8923a5 100644 --- a/source/themes/ThemeDownloader.h +++ b/source/themes/ThemeDownloader.h @@ -1,3 +1,26 @@ +/**************************************************************************** + * Copyright (C) 2011 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ #ifndef _THEME_DOWNLOADER_H_ #define _THEME_DOWNLOADER_H_ diff --git a/source/themes/ThemeMenu.cpp b/source/themes/ThemeMenu.cpp new file mode 100644 index 00000000..262c20f6 --- /dev/null +++ b/source/themes/ThemeMenu.cpp @@ -0,0 +1,441 @@ +/**************************************************************************** + * Copyright (C) 2011 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include + +#include "ThemeMenu.h" +#include "language/gettext.h" +#include "prompts/PromptWindows.h" +#include "prompts/ProgressWindow.h" +#include "FileOperations/DirList.h" +#include "network/networkops.h" +#include "themes/CTheme.h" +#include "FileOperations/fileops.h" +#include "sys.h" +#include "menu/menus.h" +#include "utils/ShowError.h" +#include "utils/tools.h" +#include "gecko.h" + + +ThemeMenu::ThemeMenu() + : FlyingButtonsMenu(tr("Theme Menu")) +{ + delete MainButtonImgData; + delete MainButtonImgOverData; + + MainButtonImgData = Resources::GetImageData("theme_box.png"); + MainButtonImgOverData = NULL; + + ParentMenu = MENU_SETTINGS; + + for(int i = 0; i < 4; ++i) + ThemePreviews[i] = NULL; + + defaultBtnTxt = new GuiText(tr( "Default" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + defaultBtnTxt->SetMaxWidth(btnOutline->GetWidth() - 30); + defaultBtnImg = new GuiImage(btnOutline); + if (Settings.wsprompt) + { + defaultBtnTxt->SetWidescreen(Settings.widescreen); + defaultBtnImg->SetWidescreen(Settings.widescreen); + } + defaultBtn = new GuiButton(btnOutline->GetWidth(), btnOutline->GetHeight()); + defaultBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + defaultBtn->SetPosition(-20, 400); + defaultBtn->SetLabel(defaultBtnTxt); + defaultBtn->SetImage(defaultBtnImg); + defaultBtn->SetSoundOver(btnSoundOver); + defaultBtn->SetSoundClick(btnSoundClick2); + defaultBtn->SetTrigger(trigA); + defaultBtn->SetEffectGrow(); + Append(defaultBtn); + + backBtn->SetPosition(-205, 400); +} + +ThemeMenu::~ThemeMenu() +{ + HaltGui(); + for(u32 i = 0; i < MainButton.size(); ++i) + Remove(MainButton[i]); + Remove(defaultBtn); + + delete defaultBtn; + delete defaultBtnTxt; + delete defaultBtnImg; + for(int i = 0; i < 4; ++i) + delete ThemePreviews[i]; +} + +int ThemeMenu::Run() +{ + ThemeMenu * Menu = new ThemeMenu(); + mainWindow->Append(Menu); + + Menu->ShowMenu(); + + int returnMenu = MENU_NONE; + + while((returnMenu = Menu->MainLoop()) == MENU_NONE); + + delete Menu; + + return returnMenu; +} + +int ThemeMenu::MainLoop() +{ + if(defaultBtn->GetState() == STATE_CLICKED) + { + int choice = WindowPrompt(0, tr("Do you want to load the default theme?"), tr("Yes"), tr("Cancel")); + if(choice) + { + HaltGui(); + Theme::SetDefault(); + Theme::Reload(); + ResumeGui(); + return MENU_THEMEMENU; + } + + defaultBtn->ResetState(); + } + + return FlyingButtonsMenu::MainLoop(); +} + +void ThemeMenu::SetMainButton(int position, const char * ButtonText, GuiImageData * imageData, GuiImageData * themeImg) +{ + if(position >= (int) MainButton.size()) + { + MainButtonImg.resize(position+1); + MainButtonImgOver.resize(position+1); + MainButtonTxt.resize(position+1); + MainButton.resize(position+1); + } + + MainButtonImg[position] = new GuiImage(imageData); + MainButtonImgOver[position] = new GuiImage(themeImg); + MainButtonImgOver[position]->SetScale(0.4); + MainButtonImgOver[position]->SetPosition(50, -45); + + MainButtonTxt[position] = new GuiText(ButtonText, 18, ( GXColor ) {0, 0, 0, 255}); + MainButtonTxt[position]->SetAlignment(ALIGN_CENTER, ALIGN_TOP); + MainButtonTxt[position]->SetPosition(0, 10); + MainButtonTxt[position]->SetMaxWidth(imageData->GetWidth() - 10, DOTTED); + + MainButton[position] = new GuiButton(imageData->GetWidth(), imageData->GetHeight()); + MainButton[position]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + MainButton[position]->SetSoundOver(btnSoundOver); + MainButton[position]->SetSoundClick(btnSoundClick); + MainButton[position]->SetImage(MainButtonImg[position]); + MainButton[position]->SetImageOver(MainButtonImg[position]); + MainButton[position]->SetIcon(MainButtonImgOver[position]); + MainButton[position]->SetLabel(MainButtonTxt[position]); + MainButton[position]->SetTrigger(trigA); + MainButton[position]->SetEffectGrow(); + + switch(position % 4) + { + case 0: + MainButton[position]->SetPosition(90, 75); + break; + case 1: + MainButton[position]->SetPosition(340, 75); + break; + case 2: + MainButton[position]->SetPosition(90, 230); + break; + case 3: + MainButton[position]->SetPosition(340, 230); + break; + default: + break; + } +} + +GuiImageData * ThemeMenu::GetImageData(int theme) +{ + char filepath[300]; + snprintf(filepath, sizeof(filepath), "%stheme_preview.png", ThemeList[theme].ImageFolder.c_str()); + + return (new GuiImageData(filepath)); +} + +void ThemeMenu::SetupMainButtons() +{ + ThemeList.clear(); + + DirList ThemeDir(Settings.theme_path, ".them", DirList::Files); + if (ThemeDir.GetFilecount() == 0) + { + WindowPrompt(tr( "No themes found." ), 0, "OK"); + returnMenu = MENU_SETTINGS; + } + + for(int i = 0; i < ThemeDir.GetFilecount(); ++i) + { + u8 *buffer = NULL; + u64 filesize; + gprintf("%i %s\n", i, ThemeDir.GetFilepath(i)); + LoadFileToMem(ThemeDir.GetFilepath(i), &buffer, &filesize); + + if(!buffer) continue; + + buffer[filesize-1] = '\0'; + + int size = ThemeList.size(); + ThemeList.resize(size+1); + + ThemeList[size].Filepath = ThemeDir.GetFilepath(i); + GetNodeText(buffer, "Theme-Title:", ThemeList[size].Title); + GetNodeText(buffer, "Theme-Team:", ThemeList[size].Team); + GetNodeText(buffer, "Theme-Version:", ThemeList[size].Version); + GetNodeText(buffer, "Image-Folder:", ThemeList[size].ImageFolder); + + if(ThemeList[size].Title.size() == 0 && ThemeDir.GetFilename(i)) + { + ThemeList[size].Title = ThemeDir.GetFilename(i); + size_t pos = ThemeList[size].Title.rfind('.'); + if(pos != std::string::npos) + ThemeList[size].Title.erase(pos); + } + + if(ThemeList[size].ImageFolder.size() == 0) + { + ThemeList[size].ImageFolder = ThemeDir.GetFilepath(i); + size_t pos = ThemeList[size].ImageFolder.rfind('.'); + if(pos != std::string::npos) + ThemeList[size].ImageFolder.erase(pos); + ThemeList[size].ImageFolder += '/'; + } + else + { + std::string tempString = ThemeList[size].ImageFolder; + ThemeList[size].ImageFolder = Settings.theme_path; + ThemeList[size].ImageFolder += tempString; + ThemeList[size].ImageFolder += '/'; + } + + SetMainButton(size, ThemeList[size].Title.c_str(), MainButtonImgData, NULL); + + free(buffer); + } +} + +bool ThemeMenu::GetNodeText(const u8 *buffer, const char *node, std::string &outtext) +{ + const char * nodeText = strcasestr((const char *) buffer, node); + if(!nodeText) + return false; + + nodeText += strlen(node); + + while(*nodeText == ' ') nodeText++; + + while(*nodeText != '\0' && *nodeText != '\\' && *nodeText != '\n' && *nodeText != '"') + { + outtext.push_back(*nodeText); + nodeText++; + } + + return true; +} + +void ThemeMenu::AddMainButtons() +{ + HaltGui(); + for(u32 i = 0; i < MainButton.size(); ++i) + Remove(MainButton[i]); + + int FirstItem = currentPage*4; + int n = 0; + + for(int i = FirstItem; i < (int) MainButton.size() && i < FirstItem+4; ++i) + { + delete ThemePreviews[n]; + ThemePreviews[n] = GetImageData(i); + MainButtonImgOver[i]->SetImage(ThemePreviews[n]); + n++; + } + + FlyingButtonsMenu::AddMainButtons(); +} + +void ThemeMenu::MainButtonClicked(int button) +{ + //! TODO: Clean me + const char * title = ThemeList[button].Title.c_str(); + const char * author = ThemeList[button].Team.c_str(); + const char * version = ThemeList[button].Version.c_str(); + GuiImageData *thumbimageData = ThemePreviews[button % 4]; + + gprintf("\nTheme_Prompt(%s ,%s)", title, author); + bool leave = false; + + GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png")); + GuiImageData dialogBox(Resources::GetFile("theme_dialogue_box.png"), Resources::GetFileSize("theme_dialogue_box.png")); + + GuiImage dialogBoxImg(&dialogBox); + + GuiWindow promptWindow(dialogBox.GetWidth(), dialogBox.GetHeight()); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + int PositionY = 30; + + GuiText titleTxt(tr( "Theme Title:" ), 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(230, PositionY); + PositionY += 20; + + GuiText titleTxt2(title, 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + titleTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt2.SetPosition(230, PositionY); + titleTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, WRAP); + + if(titleTxt2.GetTextWidth() >= dialogBox.GetWidth() - 220) + PositionY += 50; + else + PositionY += 30; + + GuiText authorTxt(tr( "Author(s):" ), 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + authorTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + authorTxt.SetPosition(230, PositionY); + PositionY += 20; + + GuiText authorTxt2(author, 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + authorTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + authorTxt2.SetPosition(230, PositionY); + authorTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, DOTTED); + + if(authorTxt2.GetTextWidth() >= dialogBox.GetWidth() - 220) + PositionY += 50; + else + PositionY += 30; + + GuiText versionTxt(tr( "Version:" ), 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + versionTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + versionTxt.SetPosition(230, PositionY); + + GuiText versionTxt2(version, 18, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + versionTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + versionTxt2.SetPosition(235+versionTxt.GetTextWidth(), PositionY); + versionTxt2.SetMaxWidth(dialogBox.GetWidth() - 220, DOTTED); + + GuiText applyBtnTxt(tr( "Apply" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + applyBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30); + GuiImage applyBtnImg(&btnOutline); + if (Settings.wsprompt) + { + applyBtnTxt.SetWidescreen(Settings.widescreen); + applyBtnImg.SetWidescreen(Settings.widescreen); + } + GuiButton applyBtn(&applyBtnImg, &applyBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 170, &trigA, btnSoundOver, btnSoundClick2, 1); + applyBtn.SetLabel(&applyBtnTxt); + applyBtn.SetScale(0.9); + + GuiText backBtnTxt(tr( "Back" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows text color")); + backBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30); + GuiImage backBtnImg(&btnOutline); + if (Settings.wsprompt) + { + backBtnTxt.SetWidescreen(Settings.widescreen); + backBtnImg.SetWidescreen(Settings.widescreen); + } + GuiButton backBtn(&backBtnImg, &backBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 220, &trigA, btnSoundOver, btnSoundClick2, 1); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetTrigger(&trigB); + backBtn.SetScale(0.9); + + GuiImage ThemeImage(thumbimageData); + ThemeImage.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + ThemeImage.SetPosition(20, 10); + ThemeImage.SetScale(0.8); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&ThemeImage); + promptWindow.Append(&titleTxt); + promptWindow.Append(&titleTxt2); + promptWindow.Append(&authorTxt); + promptWindow.Append(&authorTxt2); + promptWindow.Append(&versionTxt); + promptWindow.Append(&versionTxt2); + promptWindow.Append(&applyBtn); + promptWindow.Append(&backBtn); + + HaltGui(); + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while (!leave) + { + usleep(100); + + if (shutdown) + Sys_Shutdown(); + else if (reset) + Sys_Reboot(); + + if (applyBtn.GetState() == STATE_CLICKED) + { + int choice = WindowPrompt(tr( "Do you want to apply this theme?" ), title, tr( "Yes" ), tr( "Cancel" )); + if (choice) + { + if (Theme::Load(ThemeList[button].Filepath.c_str())) + { + snprintf(Settings.theme, sizeof(Settings.theme), ThemeList[button].Filepath.c_str()); + Theme::Reload(); + returnMenu = MENU_THEMEMENU; + leave = true; + } + } + mainWindow->SetState(STATE_DISABLED); + promptWindow.SetState(STATE_DEFAULT); + mainWindow->ChangeFocus(&promptWindow); + applyBtn.ResetState(); + } + + else if (backBtn.GetState() == STATE_CLICKED) + { + leave = true; + backBtn.ResetState(); + } + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while (promptWindow.GetEffect() > 0) usleep(100); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} diff --git a/source/themes/ThemeMenu.h b/source/themes/ThemeMenu.h new file mode 100644 index 00000000..12089d7e --- /dev/null +++ b/source/themes/ThemeMenu.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * Copyright (C) 2011 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _THEME_MENU_H_ +#define _THEME_MENU_H_ + +#include +#include +#include "settings/menus/FlyingButtonsMenu.hpp" +#include "FileOperations/DirList.h" +#include "themes/Theme_List.h" + +class ThemeMenu : public FlyingButtonsMenu +{ + public: + ThemeMenu(); + ~ThemeMenu(); + static int Run(); + int MainLoop(); + protected: + void CreateSettingsMenu(int index) { MainButtonClicked(index); }; + void MainButtonClicked(int button); + void AddMainButtons(); + void SetupMainButtons(); + void SetMainButton(int position, const char * ButtonText, GuiImageData * imageData, GuiImageData * imageOver); + GuiImageData * GetImageData(int theme); + bool GetNodeText(const u8 *buffer, const char *node, std::string &outtext); + + struct ThemeInfoStruct + { + std::string Filepath; + std::string Title; + std::string Team; + std::string Version; + std::string ImageFolder; + }; + std::vector ThemeList; + GuiText * defaultBtnTxt; + GuiImage * defaultBtnImg; + GuiButton * defaultBtn; + GuiImageData * ThemePreviews[4]; +}; + +#endif