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 32 const uint32 MSG_DEFAULTS_PRESSED = 'defl'; 33 const uint32 MSG_SAVEAS_PRESSED = 'canl'; 34 const uint32 MSG_REVERT_PRESSED = 'revt'; 35 36 37 ThemeWindow::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 78 void 79 ThemeWindow::Quit() 80 { 81 fTerminalMessenger.SendMessage(MSG_THEME_CLOSED); 82 delete fPreviousPref; 83 delete fSavePanel; 84 BWindow::Quit(); 85 } 86 87 88 bool 89 ThemeWindow::QuitRequested() 90 { 91 if (fDirty) 92 _Save(); 93 94 return true; 95 } 96 97 98 void 99 ThemeWindow::_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 117 void 118 ThemeWindow::_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 149 void 150 ThemeWindow::_Save() 151 { 152 delete fPreviousPref; 153 fPreviousPref = new PrefHandler(PrefHandler::Default()); 154 155 PrefHandler::Default()->SaveDefaultAsText(); 156 fDirty = false; 157 } 158 159 160 void 161 ThemeWindow::_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 174 void 175 ThemeWindow::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