diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e71fd9..aa07ab6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,8 @@ add_executable(Pilgrim src/main.cpp src/PilgrimApp.h src/MainWindow.cpp src/MainWindow.h + src/AboutDialog.cpp + src/AboutDialog.h ) target_link_libraries(${PROJECT_NAME} tvision) if(UNIX) diff --git a/src/AboutDialog.cpp b/src/AboutDialog.cpp new file mode 100644 index 0000000..03e6bed --- /dev/null +++ b/src/AboutDialog.cpp @@ -0,0 +1,180 @@ +// Componentes necessários para a declaração em AboutDialog.h +#define Uses_TDialog + +// Componentes necessários para a implementação em AboutDialog.cpp +#define Uses_TStaticText +#define Uses_TButton +#define Uses_TScrollBar +#define Uses_TEditor +#define Uses_TRect +#define Uses_TView +#define Uses_TWindowInit // TDialog herda dele, então é bom ter. +#define Uses_TEvent +#define Uses_TKeys +#define Uses_TScreen + +// 2. AGORA INCLUA SEU CABEÇALHO. +// Ele irá puxar com todas as definições acima ativadas. +#include "AboutDialog.h" + +// Outras inclusões C++ padrão +#include // Para strlen +#include // Para leitura de arquivo +#include // Para stringstream +#include // Para cerr + +// Função para fazer wrap do texto +std::string wrapText(const std::string& text, int maxWidth) { + std::string result; + std::istringstream iss(text); + std::string line; + + while (std::getline(iss, line)) { + if (line.length() <= maxWidth) { + result += line + "\n"; + } else { + // Fazer wrap da linha + std::string currentLine; + std::istringstream wordStream(line); + std::string word; + + while (wordStream >> word) { + if (currentLine.length() + word.length() + 1 <= maxWidth) { + if (!currentLine.empty()) currentLine += " "; + currentLine += word; + } else { + if (!currentLine.empty()) { + result += currentLine + "\n"; + currentLine = word; + } else { + // Palavra muito longa, quebrar + result += word.substr(0, maxWidth) + "\n"; + currentLine = word.substr(maxWidth); + } + } + } + if (!currentLine.empty()) { + result += currentLine + "\n"; + } + } + } + return result; +} + +TAboutDialog::TAboutDialog() : + TWindowInit(&TAboutDialog::initFrame), + TDialog(TRect(0, 0, 100, 30), "About Pilgrim") +{ + // Centralizar o diálogo programaticamente + int x = (TScreen::screenWidth - 100) / 2; + int y = (TScreen::screenHeight - 30) / 2; + moveTo(x, y); + + insert(new TStaticText(TRect(40, 1, 60, 2), "P I L G R I M")); + insert(new TStaticText(TRect(35, 2, 65, 3), "Digital Travel Journal")); + insert(new TStaticText(TRect(41, 3, 59, 4), "Version 1.0 - 2025")); + insert(new TStaticText(TRect(2, 4, 98, 5), + "══════════════════════════════════════════════════════════════════════════════════════════════")); + + const char* developerInfo = + "Developed by: Gustavo H. S. S. M.\n" + "GitHub: https://github.com/gmbrax\n" + "Git: https://git.gustavomiranda.xyz"; + + insert(new TStaticText(TRect(3, 6, 97, 10), developerInfo)); + insert(new TStaticText(TRect(3, 11, 20, 12), "License:")); + + // Criar apenas scrollbar vertical + TScrollBar* vScrollBar = new TScrollBar(TRect(96, 12, 97, 23)); + insert(vScrollBar); + + // Criar TEditor para mostrar a licença com scroll vertical apenas - área maior + TEditor* editor = new TEditor(TRect(3, 12, 96, 23), nullptr, vScrollBar, nullptr, 10000); + + // Tentar ler o arquivo LICENSE + std::string licenseContent; + std::ifstream licenseFile; + + // Tentar diferentes caminhos possíveis para o arquivo LICENSE + const char* possiblePaths[] = { + "LICENSE", + "../LICENSE", + "../../LICENSE", + "./LICENSE" + }; + + bool fileFound = false; + for (const char* path : possiblePaths) { + licenseFile.open(path); + if (licenseFile.is_open()) { + std::stringstream buffer; + buffer << licenseFile.rdbuf(); + licenseContent = buffer.str(); + licenseFile.close(); + fileFound = true; + break; + } + } + + if (!fileFound) { + // Fallback se não conseguir ler o arquivo + licenseContent = "Error loading LICENSE file.\n\n" + "Copyright (c) 2025 GHMiranda.\n\n" + "This software is distributed under the BSD license terms.\n\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n\n" + "1. Redistributions of source code must retain the above copyright\n" + " notice, this list of conditions and the following disclaimer.\n\n" + "2. Redistributions in binary form must reproduce the above copyright\n" + " notice, this list of conditions and the following disclaimer in\n" + " the documentation and/or other materials provided with the\n" + " distribution.\n\n" + "3. Neither the name of the copyright holder nor the names of its\n" + " contributors may be used to endorse or promote products derived\n" + " from this software without specific prior written permission.\n\n" + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" + "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" + "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n" + "FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n" + "COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n" + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n" + "BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n" + "LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n" + "CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n" + "LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n" + "ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" + "POSSIBILITY OF SUCH DAMAGE."; + } + + // Adicionar informações sobre bibliotecas utilizadas + licenseContent += "\n\n────────────────────────────────────────────────────────────────────────────\n\n"; + licenseContent += "USED LIBRARIES:\n\n"; + licenseContent += "• Turbo Vision (Magiblot fork)\n"; + licenseContent += " Modern port of Borland's Turbo Vision library\n"; + licenseContent += " GitHub: https://github.com/magiblot/tvision"; + + // Fazer wrap do texto para caber na largura do editor (93 caracteres) + std::string wrappedText = wrapText(licenseContent, 93); + + editor->insertText(wrappedText.c_str(), wrappedText.length(), true); + editor->setState(sfCursorVis, false); // Desabilitar cursor + editor->setState(sfActive, false); // Desabilitar edição + insert(editor); + + insert(new TButton(TRect(45, 27, 55, 29), "~O~K", cmOK, bfDefault)); +} + +void TAboutDialog::handleEvent(TEvent& event) { + TDialog::handleEvent(event); + + if (event.what == evKeyDown) { + switch (event.keyDown.keyCode) { + case kbAltX: + case kbEsc: + close(); + clearEvent(event); + break; + } + } +} diff --git a/src/AboutDialog.h b/src/AboutDialog.h new file mode 100644 index 0000000..e3e9b8a --- /dev/null +++ b/src/AboutDialog.h @@ -0,0 +1,28 @@ +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +// Passo 1: Defina TODOS os componentes da TVision necessários para esta janela aqui. +#define Uses_TDialog +#define Uses_TStaticText +#define Uses_TButton +#define Uses_TScrollBar +#define Uses_TEditor +#define Uses_TRect +#define Uses_TView +#define Uses_TWindowInit +#define Uses_TEvent +#define Uses_TKeys +#define Uses_TScreen + +// Passo 2: Agora, inclua os cabeçalhos necessários. +#include + +// Passo 3: Defina a sua classe. +class TAboutDialog : public TDialog +{ +public: + TAboutDialog(); + void handleEvent(TEvent& event) override; +}; + +#endif // ABOUTDIALOG_H diff --git a/src/PilgrimApp.cpp b/src/PilgrimApp.cpp index 1331f1c..c85d52d 100644 --- a/src/PilgrimApp.cpp +++ b/src/PilgrimApp.cpp @@ -1,4 +1,5 @@ #include "PilgrimApp.h" +#include "AboutDialog.h" #include #include #include @@ -119,12 +120,8 @@ void PilgrimApp::cascade() { } void PilgrimApp::about() { - messageBox("\003Pilgrim v1.0\n\n" - "\003Aplicação de demonstração\n" - "\003usando Turbo Vision\n\n" - "\003Desenvolvido com C++\n" - "\003e biblioteca TUI moderna", - mfInformation | mfOKButton); + TAboutDialog* dialog = new TAboutDialog(); + deskTop->insert(dialog); } void PilgrimApp::dosShell() {