1/*
2 * Copyright 2010-2017, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Philippe Houdoin
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 "webp/encode.h"
26
27#include "TranslatorSettings.h"
28#include "WebPTranslator.h"
29
30
31#undef B_TRANSLATION_CONTEXT
32#define B_TRANSLATION_CONTEXT "ConfigView"
33
34
35static const uint32 kMsgQuality	= 'qlty';
36static const uint32 kMsgPreset	= 'prst';
37static const uint32 kMsgMethod	= 'metd';
38static const uint32 kMsgPreprocessing = 'pprc';
39
40static const struct preset_name {
41	const char*	name;
42	WebPPreset	id;
43} kPresetNames[] = {
44	{ B_TRANSLATE("Default"), 	WEBP_PRESET_DEFAULT },
45	{ B_TRANSLATE("Picture"), 	WEBP_PRESET_PICTURE },
46	{ B_TRANSLATE("Photo"), 	WEBP_PRESET_PHOTO },
47	{ B_TRANSLATE("Drawing"), 	WEBP_PRESET_DRAWING },
48	{ B_TRANSLATE("Icon"), 		WEBP_PRESET_ICON },
49	{ B_TRANSLATE("Text"), 		WEBP_PRESET_TEXT },
50	{ NULL },
51};
52
53
54ConfigView::ConfigView(TranslatorSettings* settings)
55	:
56	BGroupView(B_TRANSLATE("WebPTranslator Settings"), B_VERTICAL),
57	fSettings(settings)
58{
59	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
60
61	BStringView* title = new BStringView("title",
62		B_TRANSLATE("WebP image translator"));
63	title->SetFont(be_bold_font);
64
65	char versionString[256];
66	sprintf(versionString, "v%d.%d.%d, %s",
67		static_cast<int>(B_TRANSLATION_MAJOR_VERSION(WEBP_TRANSLATOR_VERSION)),
68		static_cast<int>(B_TRANSLATION_MINOR_VERSION(WEBP_TRANSLATOR_VERSION)),
69		static_cast<int>(B_TRANSLATION_REVISION_VERSION(
70			WEBP_TRANSLATOR_VERSION)),
71		__DATE__);
72
73	BStringView* version = new BStringView("version", versionString);
74
75	BString copyrightsText;
76	BStringView *copyrightView = new BStringView("Copyright",
77		B_TRANSLATE(B_UTF8_COPYRIGHT "2010-2017 Haiku Inc."));
78
79	BString libwebpInfo = B_TRANSLATE(
80		"Based on libwebp %version%");
81	int v = WebPGetEncoderVersion();
82	char libwebpVersion[32];
83	snprintf(libwebpVersion, sizeof(libwebpVersion),
84		"%d.%d.%d", v >> 16, (v>>8)&255, v&255);
85	libwebpInfo.ReplaceAll("%version%", libwebpVersion);
86
87	BStringView *copyright2View = new BStringView("Copyright2",
88		libwebpInfo.String());
89	BStringView *copyright3View = new BStringView("Copyright3",
90		B_TRANSLATE(B_UTF8_COPYRIGHT "2010-2017 Google Inc."));
91
92	// output parameters
93
94	fPresetsMenu = new BPopUpMenu(B_TRANSLATE("Preset"));
95	const struct preset_name* preset = kPresetNames;
96	while (preset->name != NULL) {
97		BMessage* msg = new BMessage(kMsgPreset);
98		msg->AddInt32("value", preset->id);
99
100		BMenuItem* item = new BMenuItem(preset->name, msg);
101		if (fSettings->SetGetInt32(WEBP_SETTING_PRESET) == preset->id)
102			item->SetMarked(true);
103		fPresetsMenu->AddItem(item);
104
105		preset++;
106	}
107	BMenuField* presetsField = new BMenuField(B_TRANSLATE("Output preset:"),
108		fPresetsMenu);
109
110	fQualitySlider = new BSlider("quality", B_TRANSLATE("Output quality:"),
111		new BMessage(kMsgQuality), 0, 100, B_HORIZONTAL, B_BLOCK_THUMB);
112	fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
113	fQualitySlider->SetHashMarkCount(10);
114	fQualitySlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));
115	fQualitySlider->SetValue(fSettings->SetGetInt32(WEBP_SETTING_QUALITY));
116
117	fMethodSlider = new BSlider("method", B_TRANSLATE("Compression method:"),
118		new BMessage(kMsgMethod), 0, 6, B_HORIZONTAL, B_BLOCK_THUMB);
119	fMethodSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
120	fMethodSlider->SetHashMarkCount(7);
121	fMethodSlider->SetLimitLabels(B_TRANSLATE("Fast"),
122		B_TRANSLATE("Slower but better"));
123	fMethodSlider->SetValue(fSettings->SetGetInt32(WEBP_SETTING_METHOD));
124
125	fPreprocessingCheckBox = new BCheckBox("preprocessing",
126		B_TRANSLATE("Preprocessing filter"), new BMessage(kMsgPreprocessing));
127	if (fSettings->SetGetBool(WEBP_SETTING_PREPROCESSING))
128		fPreprocessingCheckBox->SetValue(B_CONTROL_ON);
129
130	// Build the layout
131	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
132		.SetInsets(B_USE_DEFAULT_SPACING)
133		.Add(title)
134		.Add(version)
135		.Add(copyrightView)
136		.AddGlue()
137		.AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
138			.Add(presetsField->CreateLabelLayoutItem(), 0, 0)
139			.AddGroup(B_HORIZONTAL, 0.0f, 1, 0)
140				.Add(presetsField->CreateMenuBarLayoutItem(), 0.0f)
141				.AddGlue()
142				.End()
143			.End()
144		.Add(fQualitySlider)
145		.Add(fMethodSlider)
146		.Add(fPreprocessingCheckBox)
147		.AddGlue()
148		.Add(copyright2View)
149		.Add(copyright3View);
150}
151
152
153ConfigView::~ConfigView()
154{
155	fSettings->Release();
156}
157
158
159void
160ConfigView::AttachedToWindow()
161{
162	BGroupView::AttachedToWindow();
163
164	fPresetsMenu->SetTargetForItems(this);
165
166	fQualitySlider->SetTarget(this);
167	fMethodSlider->SetTarget(this);
168	fPreprocessingCheckBox->SetTarget(this);
169
170	if (Parent() == NULL && Window()->GetLayout() == NULL) {
171		Window()->SetLayout(new BGroupLayout(B_VERTICAL));
172		Window()->ResizeTo(PreferredSize().Width(), PreferredSize().Height());
173	}
174}
175
176
177void
178ConfigView::MessageReceived(BMessage* message)
179{
180	struct {
181		const char*		name;
182		uint32			what;
183		TranSettingType	type;
184	} maps[] = {
185		{ WEBP_SETTING_PRESET, kMsgPreset, TRAN_SETTING_INT32 },
186		{ WEBP_SETTING_QUALITY, kMsgQuality, TRAN_SETTING_INT32 },
187		{ WEBP_SETTING_METHOD, kMsgMethod, TRAN_SETTING_INT32 },
188		{ WEBP_SETTING_PREPROCESSING, kMsgPreprocessing, TRAN_SETTING_BOOL },
189		{ NULL }
190	};
191
192	int i;
193	for (i = 0; maps[i].name != NULL; i++) {
194		if (maps[i].what == message->what)
195			break;
196	}
197
198	if (maps[i].name == NULL) {
199		BGroupView::MessageReceived(message);
200		return;
201	}
202
203	int32 value;
204	if (message->FindInt32("value", &value) == B_OK
205		|| message->FindInt32("be:value", &value) == B_OK) {
206		switch(maps[i].type) {
207			case TRAN_SETTING_BOOL:
208			{
209				bool boolValue = value;
210				fSettings->SetGetBool(maps[i].name, &boolValue);
211				break;
212			}
213			case TRAN_SETTING_INT32:
214				fSettings->SetGetInt32(maps[i].name, &value);
215				break;
216		}
217		fSettings->SaveSettings();
218	}
219}
220