xref: /haiku/src/add-ons/translators/avif/ConfigView.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2021, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Emmanuel Gil Peyrot
7  */
8 
9 
10 #include "ConfigView.h"
11 
12 #include <stdio.h>
13 #include <string.h>
14 
15 #include <Catalog.h>
16 #include <CheckBox.h>
17 #include <LayoutBuilder.h>
18 #include <MenuField.h>
19 #include <MenuItem.h>
20 #include <Message.h>
21 #include <PopUpMenu.h>
22 #include <Slider.h>
23 #include <StringView.h>
24 
25 #include "avif/avif.h"
26 
27 #include "TranslatorSettings.h"
28 #include "AVIFTranslator.h"
29 
30 
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "ConfigView"
33 
34 
35 static const uint32 kMsgLossless = 'losl';
36 static const uint32 kMsgPixelFormat = 'pfmt';
37 static const uint32 kMsgQuality	= 'qlty';
38 static const uint32 kMsgSpeed = 'sped';
39 static const uint32 kMsgTilesHorizontal = 'tilh';
40 static const uint32 kMsgTilesVertical = 'tilv';
41 
42 
43 ConfigView::ConfigView(TranslatorSettings* settings)
44 	:
45 	BGroupView(B_TRANSLATE("AVIFTranslator Settings"), B_VERTICAL),
46 	fSettings(settings)
47 {
48 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
49 
50 	BStringView* title = new BStringView("title",
51 		B_TRANSLATE("AVIF image translator"));
52 	title->SetFont(be_bold_font);
53 
54 	char versionString[256];
55 	sprintf(versionString, "v%d.%d.%d, %s",
56 		static_cast<int>(B_TRANSLATION_MAJOR_VERSION(AVIF_TRANSLATOR_VERSION)),
57 		static_cast<int>(B_TRANSLATION_MINOR_VERSION(AVIF_TRANSLATOR_VERSION)),
58 		static_cast<int>(B_TRANSLATION_REVISION_VERSION(
59 			AVIF_TRANSLATOR_VERSION)),
60 		__DATE__);
61 
62 	BStringView* version = new BStringView("version", versionString);
63 
64 	BString copyrightsText;
65 	BStringView *copyrightView = new BStringView("Copyright",
66 		B_TRANSLATE(B_UTF8_COPYRIGHT "2021 Emmanuel Gil Peyrot"));
67 
68 	BString libavifInfo = B_TRANSLATE(
69 		"Based on libavif %version%");
70 	libavifInfo.ReplaceAll("%version%", avifVersion());
71 
72 	BStringView *copyright2View = new BStringView("Copyright2",
73 		libavifInfo.String());
74 	BStringView *copyright3View = new BStringView("Copyright3",
75 		B_TRANSLATE(B_UTF8_COPYRIGHT "2019 Joe Drago. All rights reserved."));
76 
77 	// output parameters
78 
79 	fLosslessCheckBox = new BCheckBox("lossless",
80 		B_TRANSLATE("Lossless"), new BMessage(kMsgLossless));
81 	bool lossless;
82 	fSettings->SetGetBool(AVIF_SETTING_LOSSLESS, &lossless);
83 	if (lossless)
84 		fLosslessCheckBox->SetValue(B_CONTROL_ON);
85 
86 	fPixelFormatMenu = new BPopUpMenu(B_TRANSLATE("Pixel format"));
87 
88 	static const avifPixelFormat pixelFormats[4] = {
89 		AVIF_PIXEL_FORMAT_YUV444,
90 		AVIF_PIXEL_FORMAT_YUV420,
91 		AVIF_PIXEL_FORMAT_YUV400,
92 		AVIF_PIXEL_FORMAT_YUV422,
93 	};
94 	for (size_t i = 0; i < 4; ++i) {
95 		BMessage* msg = new BMessage(kMsgPixelFormat);
96 		msg->AddInt32("value", pixelFormats[i]);
97 
98 		BMenuItem* item = new BMenuItem(
99 			avifPixelFormatToString(pixelFormats[i]), msg);
100 		if (fSettings->SetGetInt32(AVIF_SETTING_PIXEL_FORMAT) == pixelFormats[i])
101 			item->SetMarked(true);
102 		fPixelFormatMenu->AddItem(item);
103 	}
104 
105 	BMenuField* pixelFormatField = new BMenuField(B_TRANSLATE("Pixel format:"),
106 		fPixelFormatMenu);
107 
108 	rgb_color barColor = { 0, 0, 229, 255 };
109 
110 	fQualitySlider = new BSlider("quality", B_TRANSLATE("Output quality:"),
111 		new BMessage(kMsgQuality), AVIF_QUANTIZER_BEST_QUALITY,
112 		AVIF_QUANTIZER_WORST_QUALITY, B_HORIZONTAL, B_BLOCK_THUMB);
113 	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
114 	fQualitySlider->SetHashMarkCount(8);
115 	fQualitySlider->SetLimitLabels(B_TRANSLATE("Best"), B_TRANSLATE("Worst"));
116 	fQualitySlider->UseFillColor(true, &barColor);
117 	fQualitySlider->SetValue(fSettings->SetGetInt32(AVIF_SETTING_QUALITY));
118 	fQualitySlider->SetEnabled(!lossless);
119 
120 	fSpeedSlider = new BSlider("speed", B_TRANSLATE("Compression speed:"),
121 		new BMessage(kMsgSpeed), AVIF_SPEED_SLOWEST,
122 		AVIF_SPEED_FASTEST, B_HORIZONTAL, B_BLOCK_THUMB);
123 	fSpeedSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
124 	fSpeedSlider->SetHashMarkCount(11);
125 	fSpeedSlider->SetLimitLabels(B_TRANSLATE("Slow"),
126 		B_TRANSLATE("Faster but worse quality"));
127 	fSpeedSlider->UseFillColor(true, &barColor);
128 	fSpeedSlider->SetValue(fSettings->SetGetInt32(AVIF_SETTING_SPEED));
129 
130 	fHTilesSlider = new BSlider("htiles", B_TRANSLATE("Horizontal tiles:"),
131 		new BMessage(kMsgTilesHorizontal), 1, 6, B_HORIZONTAL,
132 		B_BLOCK_THUMB);
133 	fHTilesSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
134 	fHTilesSlider->SetHashMarkCount(6);
135 	fHTilesSlider->SetLimitLabels(B_TRANSLATE("1"),
136 		B_TRANSLATE("2⁶"));
137 	fHTilesSlider->UseFillColor(true, &barColor);
138 	fHTilesSlider->SetValue(
139 		fSettings->SetGetInt32(AVIF_SETTING_TILES_HORIZONTAL));
140 
141 	fVTilesSlider = new BSlider("vtiles", B_TRANSLATE("Vertical tiles:"),
142 		new BMessage(kMsgTilesVertical), 1, 6, B_HORIZONTAL,
143 		B_BLOCK_THUMB);
144 	fVTilesSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
145 	fVTilesSlider->SetHashMarkCount(6);
146 	fVTilesSlider->SetLimitLabels(B_TRANSLATE("1"),
147 		B_TRANSLATE("2⁶"));
148 	fVTilesSlider->UseFillColor(true, &barColor);
149 	fVTilesSlider->SetValue(
150 		fSettings->SetGetInt32(AVIF_SETTING_TILES_VERTICAL));
151 
152 	// Build the layout
153 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
154 		.SetInsets(B_USE_DEFAULT_SPACING)
155 		.Add(title)
156 		.Add(version)
157 		.Add(copyrightView)
158 		.AddGlue()
159 		.Add(fLosslessCheckBox)
160 		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
161 		        .Add(pixelFormatField->CreateLabelLayoutItem(), 0, 0)
162 			.AddGroup(B_HORIZONTAL, 0.0f, 1, 0)
163 				.Add(pixelFormatField->CreateMenuBarLayoutItem(), 0.0f)
164 				.AddGlue()
165 				.End()
166 			.End()
167 		.Add(fQualitySlider)
168 		.Add(fSpeedSlider)
169 		.Add(fHTilesSlider)
170 		.Add(fVTilesSlider)
171 		.AddGlue()
172 		.Add(copyright2View)
173 		.Add(copyright3View);
174 }
175 
176 
177 ConfigView::~ConfigView()
178 {
179 	fSettings->Release();
180 }
181 
182 
183 void
184 ConfigView::AttachedToWindow()
185 {
186 	BGroupView::AttachedToWindow();
187 
188 	fQualitySlider->SetTarget(this);
189 	fSpeedSlider->SetTarget(this);
190 	fHTilesSlider->SetTarget(this);
191 	fVTilesSlider->SetTarget(this);
192 
193 	if (Parent() == NULL && Window()->GetLayout() == NULL) {
194 		Window()->SetLayout(new BGroupLayout(B_VERTICAL));
195 		Window()->ResizeTo(PreferredSize().Width(),
196 			PreferredSize().Height());
197 	}
198 }
199 
200 
201 void
202 ConfigView::MessageReceived(BMessage* message)
203 {
204 	struct {
205 		const char*		name;
206 		uint32			what;
207 		TranSettingType	type;
208 	} maps[] = {
209 		{ AVIF_SETTING_LOSSLESS, kMsgLossless, TRAN_SETTING_BOOL },
210 		{ AVIF_SETTING_PIXEL_FORMAT, kMsgPixelFormat,
211 			TRAN_SETTING_INT32 },
212 		{ AVIF_SETTING_QUALITY, kMsgQuality, TRAN_SETTING_INT32 },
213 		{ AVIF_SETTING_SPEED, kMsgSpeed, TRAN_SETTING_INT32 },
214 		{ AVIF_SETTING_TILES_HORIZONTAL, kMsgTilesHorizontal,
215 			TRAN_SETTING_INT32 },
216 		{ AVIF_SETTING_TILES_VERTICAL, kMsgTilesVertical,
217 			TRAN_SETTING_INT32 },
218 		{ NULL }
219 	};
220 
221 	int i;
222 	for (i = 0; maps[i].name != NULL; i++) {
223 		if (maps[i].what == message->what)
224 			break;
225 	}
226 
227 	if (maps[i].name == NULL) {
228 		BGroupView::MessageReceived(message);
229 		return;
230 	}
231 
232 	int32 value;
233 	if (message->FindInt32("value", &value) == B_OK
234 		|| message->FindInt32("be:value", &value) == B_OK) {
235 		switch(maps[i].type) {
236 			case TRAN_SETTING_BOOL:
237 			{
238 				bool boolValue = value;
239 				fSettings->SetGetBool(maps[i].name, &boolValue);
240 				if (maps[i].what == kMsgLossless)
241 					fSpeedSlider->SetEnabled(!boolValue);
242 				break;
243 			}
244 			case TRAN_SETTING_INT32:
245 				fSettings->SetGetInt32(maps[i].name, &value);
246 				break;
247 		}
248 		fSettings->SaveSettings();
249 	}
250 }
251