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
ThemeWindow(const BMessenger & messenger)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
Quit()79 ThemeWindow::Quit()
80 {
81 fTerminalMessenger.SendMessage(MSG_THEME_CLOSED);
82 delete fPreviousPref;
83 delete fSavePanel;
84 BWindow::Quit();
85 }
86
87
88 bool
QuitRequested()89 ThemeWindow::QuitRequested()
90 {
91 if (fDirty)
92 _Save();
93
94 return true;
95 }
96
97
98 void
_SaveAs()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
_SaveRequested(BMessage * msg)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
_Save()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
_Revert()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
MessageReceived(BMessage * message)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