xref: /haiku/src/apps/terminal/ThemeWindow.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
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