1/* 2 * Copyright 2022, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "ThemeWindow.h" 8 9#include <stdio.h> 10 11#include <Button.h> 12#include <Catalog.h> 13#include <Directory.h> 14#include <File.h> 15#include <FilePanel.h> 16#include <FindDirectory.h> 17#include <LayoutBuilder.h> 18#include <Locale.h> 19#include <Messenger.h> 20#include <Path.h> 21#include <SeparatorView.h> 22 23#include "PrefHandler.h" 24#include "TermConst.h" 25#include "ThemeView.h" 26 27 28#undef B_TRANSLATION_CONTEXT 29#define B_TRANSLATION_CONTEXT "Terminal ThemeWindow" 30 31// local messages 32const uint32 MSG_DEFAULTS_PRESSED = 'defl'; 33const uint32 MSG_SAVEAS_PRESSED = 'canl'; 34const uint32 MSG_REVERT_PRESSED = 'revt'; 35 36 37ThemeWindow::ThemeWindow(const BMessenger& messenger) 38 : 39 BWindow(BRect(0, 0, 0, 0), B_TRANSLATE("Colors"), B_TITLED_WINDOW, 40 B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), 41 fPreviousPref(new PrefHandler(PrefHandler::Default())), 42 fSavePanel(NULL), 43 fDirty(false), 44 fTerminalMessenger(messenger) 45{ 46 fDefaultsButton = new BButton("defaults", B_TRANSLATE("Defaults"), 47 new BMessage(MSG_DEFAULTS_PRESSED), B_WILL_DRAW); 48 49 fRevertButton = new BButton("revert", B_TRANSLATE("Revert"), 50 new BMessage(MSG_REVERT_PRESSED), B_WILL_DRAW); 51 52 fSaveAsFileButton = new BButton("savebutton", 53 B_TRANSLATE("Save to file" B_UTF8_ELLIPSIS), 54 new BMessage(MSG_SAVEAS_PRESSED), B_WILL_DRAW); 55 56 fThemeView = new ThemeView("Theme", fTerminalMessenger); 57 58 BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 59 .SetInsets(B_USE_WINDOW_SPACING) 60 .Add(fThemeView) 61 .AddGroup(B_HORIZONTAL) 62 .Add(fDefaultsButton) 63 .Add(fRevertButton) 64 .AddGlue() 65 .Add(fSaveAsFileButton) 66 .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0); 67 68 fRevertButton->SetEnabled(fDirty); 69 70 AddShortcut('Q', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 71 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 72 73 CenterOnScreen(); 74 Show(); 75} 76 77 78void 79ThemeWindow::Quit() 80{ 81 fTerminalMessenger.SendMessage(MSG_THEME_CLOSED); 82 delete fPreviousPref; 83 delete fSavePanel; 84 BWindow::Quit(); 85} 86 87 88bool 89ThemeWindow::QuitRequested() 90{ 91 if (fDirty) 92 _Save(); 93 94 return true; 95} 96 97 98void 99ThemeWindow::_SaveAs() 100{ 101 if (!fSavePanel) { 102 BMessenger messenger(this); 103 fSavePanel = new BFilePanel(B_SAVE_PANEL, &messenger); 104 } 105 106 BPath path; 107 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 108 path.Append("Terminal/Themes"); 109 create_directory(path.Path(), 0755); 110 fSavePanel->SetPanelDirectory(path.Path()); 111 } 112 113 fSavePanel->Show(); 114} 115 116 117void 118ThemeWindow::_SaveRequested(BMessage *msg) 119{ 120 entry_ref dirref; 121 const char* filename; 122 123 msg->FindRef("directory", &dirref); 124 msg->FindString("name", &filename); 125 126 BDirectory dir(&dirref); 127 BPath path(&dir, filename); 128 129 PrefHandler *prefHandler = PrefHandler::Default(); 130 131 BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 132 char buffer[512]; 133 134 for (const char** table = ThemeView::kColorTable; *table != NULL; ++table) { 135 int len = snprintf(buffer, sizeof(buffer), "\"%s\" , \"%s\"\n", 136 *table, prefHandler->getString(*table)); 137 file.Write(buffer, len); 138 } 139 140 // Name the theme after the filename 141 int len = snprintf(buffer, sizeof(buffer), "\"%s\" , \"%s\"\n", 142 PREF_THEME_NAME, filename); 143 file.Write(buffer, len); 144 145 fThemeView->UpdateMenu(); 146} 147 148 149void 150ThemeWindow::_Save() 151{ 152 delete fPreviousPref; 153 fPreviousPref = new PrefHandler(PrefHandler::Default()); 154 155 PrefHandler::Default()->SaveDefaultAsText(); 156 fDirty = false; 157} 158 159 160void 161ThemeWindow::_Revert() 162{ 163 if (fDirty) { 164 PrefHandler::SetDefault(new PrefHandler(fPreviousPref)); 165 166 fThemeView->Revert(); 167 168 fDirty = false; 169 fRevertButton->SetEnabled(fDirty); 170 } 171} 172 173 174void 175ThemeWindow::MessageReceived(BMessage *message) 176{ 177 switch (message->what) { 178 179 case MSG_SAVEAS_PRESSED: 180 _SaveAs(); 181 break; 182 183 case MSG_REVERT_PRESSED: 184 _Revert(); 185 break; 186 187 case MSG_DEFAULTS_PRESSED: 188 PrefHandler::SetDefault(new PrefHandler(false)); 189 fThemeView->SetDefaults(); 190 // fallthrough 191 192 case MSG_THEME_MODIFIED: 193 fDirty = true; 194 fRevertButton->SetEnabled(fDirty); 195 break; 196 197 case B_SAVE_REQUESTED: 198 _SaveRequested(message); 199 break; 200 201 default: 202 BWindow::MessageReceived(message); 203 break; 204 } 205} 206