xref: /haiku/src/add-ons/translators/gif/GIFView.cpp (revision 22440f4105cafc95cc1d49f9bc65bb395c527d86)
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 //	File: GIFView.cpp
4 //
5 //	Date: December 1999
6 //
7 //	Author: Daniel Switkin
8 //
9 //	Copyright 2003 (c) by Daniel Switkin. This file is made publically available
10 //	under the BSD license, with the stipulations that this complete header must
11 //	remain at the top of the file indefinitely, and credit must be given to the
12 //	original author in any about box using this software.
13 //
14 ////////////////////////////////////////////////////////////////////////////////
15 
16 // Additional authors:	Stephan Aßmus, <superstippi@gmx.de>
17 //						Philippe Saint-Pierre, <stpere@gmail.com>
18 //						Maxime Simon, <maxime.simon@gmail.com>
19 //						John Scipione, <jscipione@gmail.com>
20 
21 #include "GIFView.h"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #include <Box.h>
27 #include <Catalog.h>
28 #include <CheckBox.h>
29 #include <LayoutBuilder.h>
30 #include <MenuField.h>
31 #include <MenuItem.h>
32 #include <PopUpMenu.h>
33 #include <RadioButton.h>
34 #include <SpaceLayoutItem.h>
35 #include <StringView.h>
36 #include <String.h>
37 #include <TextControl.h>
38 
39 #include "GIFTranslator.h"
40 #include "SavePalette.h"
41 
42 
43 #undef B_TRANSLATION_CONTEXT
44 #define B_TRANSLATION_CONTEXT "GIFView"
45 
46 
47 GIFView::GIFView(TranslatorSettings* settings)
48 	:
49 	BGroupView("GIFView", B_VERTICAL),
50 	fSettings(settings)
51 {
52 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
53 
54 	fTitle = new BStringView("Title", B_TRANSLATE("GIF image translator"));
55 	fTitle->SetFont(be_bold_font);
56 
57 	char version_string[100];
58 	snprintf(version_string, sizeof(version_string),
59 		B_TRANSLATE("v%d.%d.%d %s"),
60 		int(B_TRANSLATION_MAJOR_VERSION(GIF_TRANSLATOR_VERSION)),
61 		int(B_TRANSLATION_MINOR_VERSION(GIF_TRANSLATOR_VERSION)),
62 		int(B_TRANSLATION_REVISION_VERSION(GIF_TRANSLATOR_VERSION)),
63 		__DATE__);
64 	fVersion = new BStringView("Version", version_string);
65 
66 	const char* copyrightString
67 		= "©2003 Daniel Switkin, software@switkin.com";
68 	fCopyright = new BStringView("Copyright", copyrightString);
69 
70 	// menu fields (Palette & Colors)
71 	fWebSafeMI = new BMenuItem(B_TRANSLATE("Websafe"),
72 		new BMessage(GV_WEB_SAFE), 0, 0);
73 	fBeOSSystemMI = new BMenuItem(B_TRANSLATE("BeOS system"),
74 		new BMessage(GV_BEOS_SYSTEM), 0, 0);
75 	fGreyScaleMI = new BMenuItem(B_TRANSLATE("Greyscale"),
76 		new BMessage(GV_GREYSCALE), 0, 0);
77 	fOptimalMI = new BMenuItem(B_TRANSLATE("Optimal"),
78 		new BMessage(GV_OPTIMAL), 0, 0);
79 	fPaletteM = new BPopUpMenu("PalettePopUpMenu", true, true,
80 		B_ITEMS_IN_COLUMN);
81 	fPaletteM->AddItem(fWebSafeMI);
82 	fPaletteM->AddItem(fBeOSSystemMI);
83 	fPaletteM->AddItem(fGreyScaleMI);
84 	fPaletteM->AddItem(fOptimalMI);
85 
86 	fColorCountM = new BPopUpMenu("ColorCountPopUpMenu", true, true,
87 		B_ITEMS_IN_COLUMN);
88 	int32 count = 2;
89 	for (int32 i = 0; i < 8; i++) {
90 		BMessage* message = new BMessage(GV_SET_COLOR_COUNT);
91 		message->AddInt32(GIF_SETTING_PALETTE_SIZE, i + 1);
92 		BString label;
93 		label << count;
94 		fColorCountMI[i] = new BMenuItem(label.String(), message, 0, 0);
95 		fColorCountM->AddItem(fColorCountMI[i]);
96 		count *= 2;
97 	}
98 	fColorCount256MI = fColorCountMI[7];
99 
100 	fPaletteMF = new BMenuField(B_TRANSLATE("Palette:"), fPaletteM);
101 	fPaletteMF->SetAlignment(B_ALIGN_RIGHT);
102 	fColorCountMF = new BMenuField(B_TRANSLATE("Colors:"), fColorCountM);
103 	fColorCountMF->SetAlignment(B_ALIGN_RIGHT);
104 
105 	// check boxes
106 	fUseDitheringCB = new BCheckBox(B_TRANSLATE("Use dithering"),
107 		new BMessage(GV_USE_DITHERING));
108 	fDitheringBox = new BBox("dithering", B_WILL_DRAW, B_NO_BORDER);
109 	fDitheringBox->SetLabel(fUseDitheringCB);
110 
111 	fInterlacedCB = new BCheckBox(B_TRANSLATE("Write interlaced images"),
112 		new BMessage(GV_INTERLACED));
113 	fInterlacedBox = new BBox("interlaced", B_WILL_DRAW, B_NO_BORDER);
114 	fInterlacedBox->SetLabel(fInterlacedCB);
115 
116 	fUseTransparentCB = new BCheckBox(B_TRANSLATE("Write transparent images"),
117 		new BMessage(GV_USE_TRANSPARENT));
118 
119 	// radio buttons
120 	fUseTransparentAutoRB = new BRadioButton(
121 		B_TRANSLATE("Automatic (from alpha channel)"),
122 		new BMessage(GV_USE_TRANSPARENT_AUTO));
123 
124 	fUseTransparentColorRB = new BRadioButton(B_TRANSLATE("Use RGB color"),
125 		new BMessage(GV_USE_TRANSPARENT_COLOR));
126 
127 	// text controls
128 	fRedTextControl = new BTextControl("", "0",
129 		new BMessage(GV_TRANSPARENT_RED));
130 	fGreenTextControl = new BTextControl("", "0",
131 		new BMessage(GV_TRANSPARENT_GREEN));
132 	fBlueTextControl = new BTextControl("", "0",
133 		new BMessage(GV_TRANSPARENT_BLUE));
134 
135 	fTransparentBox = new BBox(B_FANCY_BORDER,
136 		BLayoutBuilder::Grid<>(3.0f, 5.0f)
137 			.Add(fUseTransparentAutoRB, 0, 0, 4, 1)
138 			.Add(fUseTransparentColorRB, 0, 1)
139 			.Add(fRedTextControl, 1, 1)
140 			.Add(fGreenTextControl, 2, 1)
141 			.Add(fBlueTextControl, 3, 1)
142 			.SetInsets(10.0f, 6.0f, 10.0f, 10.0f)
143 			.View());
144 	fTransparentBox->SetLabel(fUseTransparentCB);
145 
146 	BTextView* redTextView = fRedTextControl->TextView();
147 	BTextView* greenTextView = fGreenTextControl->TextView();
148 	BTextView* bluetextView = fBlueTextControl->TextView();
149 
150 	for (uint32 x = 0; x < 256; x++) {
151 		if (x < '0' || x > '9') {
152 			redTextView->DisallowChar(x);
153 			greenTextView->DisallowChar(x);
154 			bluetextView->DisallowChar(x);
155 		}
156 	}
157 
158 	BLayoutBuilder::Group<>(this, B_VERTICAL, 10.0f)
159 		.SetInsets(10.0f)
160 		.AddGrid(10.0f, 5.0f)
161 			.Add(fTitle, 0, 0)
162 			.Add(fVersion, 1, 0)
163 			.Add(fCopyright, 0, 1, 2, 1)
164 			.End()
165 		.AddGlue()
166 
167 		.AddGrid(10.0f, 5.0f)
168 			.Add(fPaletteMF->CreateLabelLayoutItem(), 0, 0)
169 			.Add(fPaletteMF->CreateMenuBarLayoutItem(), 1, 0)
170 
171 			.Add(fColorCountMF->CreateLabelLayoutItem(), 0, 1)
172 			.Add(fColorCountMF->CreateMenuBarLayoutItem(), 1, 1)
173 
174 			.Add(BSpaceLayoutItem::CreateHorizontalStrut(10.0f), 1, 2)
175 		.End()
176 
177 		.Add(fDitheringBox)
178 		.Add(fInterlacedBox)
179 		.Add(fTransparentBox)
180 
181 		.AddGlue()
182 		.End();
183 
184 	BFont font;
185 	GetFont(&font);
186 
187 	fSettings->Acquire();
188 
189 	RestorePrefs();
190 }
191 
192 
193 GIFView::~GIFView()
194 {
195 	fSettings->Release();
196 
197 	delete fTitle;
198 	delete fVersion;
199 	delete fCopyright;
200 	delete fPaletteMF;
201 	delete fColorCountMF;
202 	delete fDitheringBox;
203 	delete fInterlacedBox;
204 	delete fTransparentBox;
205 }
206 
207 
208 void
209 GIFView::RestorePrefs()
210 {
211 	fColorCountMF->SetEnabled(false);
212 	fUseDitheringCB->SetEnabled(true);
213 
214 	switch (fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE)) {
215 		case WEB_SAFE_PALETTE:
216 			fWebSafeMI->SetMarked(true);
217 			break;
218 
219 		case BEOS_SYSTEM_PALETTE:
220 			fBeOSSystemMI->SetMarked(true);
221 			break;
222 
223 		case GREYSCALE_PALETTE:
224 			fGreyScaleMI->SetMarked(true);
225 			fUseDitheringCB->SetEnabled(false);
226 			break;
227 
228 		case OPTIMAL_PALETTE:
229 			fOptimalMI->SetMarked(true);
230 			fColorCountMF->SetEnabled(true);
231 			break;
232 
233 		default:
234 		{
235 			int32 value = WEB_SAFE_PALETTE;
236 			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
237 			fSettings->SaveSettings();
238 			fWebSafeMI->SetMarked(true);
239 		}
240 	}
241 
242 	if (fColorCountMF->IsEnabled()
243 		&& fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) > 0
244 		&& fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) <= 8) {
245 		// display the stored color count
246 		fColorCountMI[fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) - 1]
247 			->SetMarked(true);
248 	} else {
249 		// display 256 colors
250 		fColorCount256MI->SetMarked(true);
251 		int32 value = 8;
252 		fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE, &value);
253 		fSettings->SaveSettings();
254 	}
255 
256 	fInterlacedCB->SetValue(fSettings->SetGetBool(GIF_SETTING_INTERLACED));
257 
258 	if (fGreyScaleMI->IsMarked())
259 		fUseDitheringCB->SetValue(false);
260 	else {
261 		fUseDitheringCB->SetValue(
262 			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING));
263 	}
264 	fUseTransparentCB->SetValue(
265 		fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT));
266 	fUseTransparentAutoRB->SetValue(
267 		fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
268 	fUseTransparentColorRB->SetValue(
269 		!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
270 	if (fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT)) {
271 		fUseTransparentAutoRB->SetEnabled(true);
272 		fUseTransparentColorRB->SetEnabled(true);
273 		fRedTextControl->SetEnabled(
274 			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
275 		fGreenTextControl->SetEnabled(
276 			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
277 		fBlueTextControl->SetEnabled(
278 			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
279 	} else {
280 		fUseTransparentAutoRB->SetEnabled(false);
281 		fUseTransparentColorRB->SetEnabled(false);
282 		fRedTextControl->SetEnabled(false);
283 		fGreenTextControl->SetEnabled(false);
284 		fBlueTextControl->SetEnabled(false);
285 	}
286 
287 	char temp[4];
288 	sprintf(temp, "%d",
289 		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED));
290 	fRedTextControl->SetText(temp);
291 	sprintf(temp, "%d",
292 		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN));
293 	fGreenTextControl->SetText(temp);
294 	sprintf(temp, "%d",
295 		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE));
296 	fBlueTextControl->SetText(temp);
297 }
298 
299 
300 void
301 GIFView::AllAttached()
302 {
303 	BMessenger messenger(this);
304 	fInterlacedCB->SetTarget(messenger);
305 	fUseDitheringCB->SetTarget(messenger);
306 	fUseTransparentCB->SetTarget(messenger);
307 	fUseTransparentAutoRB->SetTarget(messenger);
308 	fUseTransparentColorRB->SetTarget(messenger);
309 	fRedTextControl->SetTarget(messenger);
310 	fGreenTextControl->SetTarget(messenger);
311 	fBlueTextControl->SetTarget(messenger);
312 	fPaletteM->SetTargetForItems(messenger);
313 	fColorCountM->SetTargetForItems(messenger);
314 
315 	BView::AllAttached();
316 
317 	if (Parent() == NULL && Window()->GetLayout() == NULL) {
318 		Window()->SetLayout(new BGroupLayout(B_VERTICAL));
319 		Window()->ResizeTo(PreferredSize().Width(), PreferredSize().Height());
320 	}
321 }
322 
323 
324 void
325 GIFView::MessageReceived(BMessage* message)
326 {
327 	switch (message->what) {
328 		case GV_WEB_SAFE:
329 		{
330 			int32 value = WEB_SAFE_PALETTE;
331 			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
332 			fUseDitheringCB->SetEnabled(true);
333 			fColorCountMF->SetEnabled(false);
334 			fColorCount256MI->SetMarked(true);
335 			break;
336 		}
337 
338 		case GV_BEOS_SYSTEM:
339 		{
340 			int32 value = BEOS_SYSTEM_PALETTE;
341 			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
342 			fUseDitheringCB->SetEnabled(true);
343 			fColorCountMF->SetEnabled(false);
344 			fColorCount256MI->SetMarked(true);
345 			break;
346 		}
347 
348 		case GV_GREYSCALE:
349 		{
350 			int32 value = GREYSCALE_PALETTE;
351 			bool usedithering = false;
352 			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
353 			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING, &usedithering);
354 			fUseDitheringCB->SetEnabled(false);
355 			fUseDitheringCB->SetValue(false);
356 			fColorCountMF->SetEnabled(false);
357 			fColorCount256MI->SetMarked(true);
358 			break;
359 		}
360 
361 		case GV_OPTIMAL:
362 		{
363 			int32 value = OPTIMAL_PALETTE;
364 			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
365 			fUseDitheringCB->SetEnabled(true);
366 			fColorCountMF->SetEnabled(true);
367 			fColorCountMI[fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) - 1]
368 				->SetMarked(true);
369 			break;
370 		}
371 
372 		case GV_SET_COLOR_COUNT:
373 			if (fColorCountMF->IsEnabled()) {
374 				int32 sizeInBits;
375 				if (message->FindInt32(GIF_SETTING_PALETTE_SIZE, &sizeInBits)
376 						>= B_OK && sizeInBits > 0 && sizeInBits <= 8) {
377 					fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE,
378 						&sizeInBits);
379 				}
380 			}
381 			break;
382 
383 		case GV_INTERLACED:
384 		{
385 			bool value = fInterlacedCB->Value();
386 			fSettings->SetGetBool(GIF_SETTING_INTERLACED, &value);
387 			break;
388 		}
389 
390 		case GV_USE_DITHERING:
391 		{
392 			bool value = fUseDitheringCB->Value();
393 			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING, &value);
394 			break;
395 		}
396 
397 		case GV_USE_TRANSPARENT:
398 		{
399 			bool value = fUseTransparentCB->Value();
400 			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT, &value);
401 			if (value) {
402 				fUseTransparentAutoRB->SetEnabled(true);
403 				fUseTransparentColorRB->SetEnabled(true);
404 				fRedTextControl->SetEnabled(fUseTransparentColorRB->Value());
405 				fGreenTextControl->SetEnabled(fUseTransparentColorRB->Value());
406 				fBlueTextControl->SetEnabled(fUseTransparentColorRB->Value());
407 			} else {
408 				fUseTransparentAutoRB->SetEnabled(false);
409 				fUseTransparentColorRB->SetEnabled(false);
410 				fRedTextControl->SetEnabled(false);
411 				fGreenTextControl->SetEnabled(false);
412 				fBlueTextControl->SetEnabled(false);
413 			}
414 			break;
415 		}
416 
417 		case GV_USE_TRANSPARENT_AUTO:
418 		{
419 			bool value = true;
420 			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO, &value);
421 			fRedTextControl->SetEnabled(false);
422 			fGreenTextControl->SetEnabled(false);
423 			fBlueTextControl->SetEnabled(false);
424 			break;
425 		}
426 
427 		case GV_USE_TRANSPARENT_COLOR:
428 		{
429 			bool value = false;
430 			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO, &value);
431 			fRedTextControl->SetEnabled(true);
432 			fGreenTextControl->SetEnabled(true);
433 			fBlueTextControl->SetEnabled(true);
434 			break;
435 		}
436 
437 		case GV_TRANSPARENT_RED:
438 		{
439 			int32 value = CheckInput(fRedTextControl);
440 			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED, &value);
441 			break;
442 		}
443 
444 		case GV_TRANSPARENT_GREEN:
445 		{
446 			int32 value = CheckInput(fGreenTextControl);
447 			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN, &value);
448 			break;
449 		}
450 
451 		case GV_TRANSPARENT_BLUE:
452 		{
453 			int32 value = CheckInput(fBlueTextControl);
454 			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE, &value);
455 			break;
456 		}
457 
458 		default:
459 			BView::MessageReceived(message);
460 	}
461 
462 	fSettings->SaveSettings();
463 }
464 
465 
466 int
467 GIFView::CheckInput(BTextControl* control)
468 {
469 	int value = atoi(control->Text());
470 	if (value < 0 || value > 255) {
471 		value = (value < 0) ? 0 : 255;
472 		char temp[4];
473 		sprintf(temp, "%d", value);
474 		control->SetText(temp);
475 	}
476 
477 	return value;
478 }
479