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
47GIFView::GIFView(TranslatorSettings* settings)
48	:
49	BGroupView("GIFView", B_VERTICAL),
50	fSettings(settings)
51{
52	SetViewUIColor(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("Version %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, 0)
159		.SetInsets(B_USE_DEFAULT_SPACING)
160		.Add(fTitle)
161		.Add(fVersion)
162		.Add(fCopyright)
163		.AddGlue()
164		.AddGrid(10.0f, 5.0f)
165			.Add(fPaletteMF->CreateLabelLayoutItem(), 0, 0)
166			.AddGroup(B_HORIZONTAL, 0.0f, 1, 0)
167				.Add(fPaletteMF->CreateMenuBarLayoutItem(), 0.0f)
168				.AddGlue()
169				.End()
170			.Add(fColorCountMF->CreateLabelLayoutItem(), 0, 1)
171			.AddGroup(B_HORIZONTAL, 0.0f, 1, 1)
172				.Add(fColorCountMF->CreateMenuBarLayoutItem(), 0.0f)
173				.AddGlue()
174				.End()
175			.End()
176		.AddStrut(B_USE_SMALL_SPACING)
177		.Add(fDitheringBox)
178		.Add(fInterlacedBox)
179		.Add(fTransparentBox)
180		.AddGlue()
181		.End();
182
183	fSettings->Acquire();
184
185	RestorePrefs();
186}
187
188
189GIFView::~GIFView()
190{
191	fSettings->Release();
192
193	delete fTitle;
194	delete fVersion;
195	delete fCopyright;
196	delete fPaletteMF;
197	delete fColorCountMF;
198	delete fDitheringBox;
199	delete fInterlacedBox;
200	delete fTransparentBox;
201}
202
203
204void
205GIFView::RestorePrefs()
206{
207	fColorCountMF->SetEnabled(false);
208	fUseDitheringCB->SetEnabled(true);
209
210	switch (fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE)) {
211		case WEB_SAFE_PALETTE:
212			fWebSafeMI->SetMarked(true);
213			break;
214
215		case BEOS_SYSTEM_PALETTE:
216			fBeOSSystemMI->SetMarked(true);
217			break;
218
219		case GREYSCALE_PALETTE:
220			fGreyScaleMI->SetMarked(true);
221			fUseDitheringCB->SetEnabled(false);
222			break;
223
224		case OPTIMAL_PALETTE:
225			fOptimalMI->SetMarked(true);
226			fColorCountMF->SetEnabled(true);
227			break;
228
229		default:
230		{
231			int32 value = WEB_SAFE_PALETTE;
232			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
233			fSettings->SaveSettings();
234			fWebSafeMI->SetMarked(true);
235		}
236	}
237
238	if (fColorCountMF->IsEnabled()
239		&& fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) > 0
240		&& fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) <= 8) {
241		// display the stored color count
242		fColorCountMI[fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) - 1]
243			->SetMarked(true);
244	} else {
245		// display 256 colors
246		fColorCount256MI->SetMarked(true);
247		int32 value = 8;
248		fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE, &value);
249		fSettings->SaveSettings();
250	}
251
252	fInterlacedCB->SetValue(fSettings->SetGetBool(GIF_SETTING_INTERLACED));
253
254	if (fGreyScaleMI->IsMarked())
255		fUseDitheringCB->SetValue(false);
256	else {
257		fUseDitheringCB->SetValue(
258			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING));
259	}
260	fUseTransparentCB->SetValue(
261		fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT));
262	fUseTransparentAutoRB->SetValue(
263		fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
264	fUseTransparentColorRB->SetValue(
265		!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
266	if (fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT)) {
267		fUseTransparentAutoRB->SetEnabled(true);
268		fUseTransparentColorRB->SetEnabled(true);
269		fRedTextControl->SetEnabled(
270			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
271		fGreenTextControl->SetEnabled(
272			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
273		fBlueTextControl->SetEnabled(
274			!fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO));
275	} else {
276		fUseTransparentAutoRB->SetEnabled(false);
277		fUseTransparentColorRB->SetEnabled(false);
278		fRedTextControl->SetEnabled(false);
279		fGreenTextControl->SetEnabled(false);
280		fBlueTextControl->SetEnabled(false);
281	}
282
283	char temp[4];
284	sprintf(temp, "%d",
285		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED));
286	fRedTextControl->SetText(temp);
287	sprintf(temp, "%d",
288		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN));
289	fGreenTextControl->SetText(temp);
290	sprintf(temp, "%d",
291		(int)fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE));
292	fBlueTextControl->SetText(temp);
293}
294
295
296void
297GIFView::AllAttached()
298{
299	BMessenger messenger(this);
300	fInterlacedCB->SetTarget(messenger);
301	fUseDitheringCB->SetTarget(messenger);
302	fUseTransparentCB->SetTarget(messenger);
303	fUseTransparentAutoRB->SetTarget(messenger);
304	fUseTransparentColorRB->SetTarget(messenger);
305	fRedTextControl->SetTarget(messenger);
306	fGreenTextControl->SetTarget(messenger);
307	fBlueTextControl->SetTarget(messenger);
308	fPaletteM->SetTargetForItems(messenger);
309	fColorCountM->SetTargetForItems(messenger);
310
311	BView::AllAttached();
312
313	if (Parent() == NULL && Window()->GetLayout() == NULL) {
314		Window()->SetLayout(new BGroupLayout(B_VERTICAL));
315		Window()->ResizeTo(PreferredSize().Width(), PreferredSize().Height());
316	}
317}
318
319
320void
321GIFView::MessageReceived(BMessage* message)
322{
323	switch (message->what) {
324		case GV_WEB_SAFE:
325		{
326			int32 value = WEB_SAFE_PALETTE;
327			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
328			fUseDitheringCB->SetEnabled(true);
329			fColorCountMF->SetEnabled(false);
330			fColorCount256MI->SetMarked(true);
331			break;
332		}
333
334		case GV_BEOS_SYSTEM:
335		{
336			int32 value = BEOS_SYSTEM_PALETTE;
337			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
338			fUseDitheringCB->SetEnabled(true);
339			fColorCountMF->SetEnabled(false);
340			fColorCount256MI->SetMarked(true);
341			break;
342		}
343
344		case GV_GREYSCALE:
345		{
346			int32 value = GREYSCALE_PALETTE;
347			bool usedithering = false;
348			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
349			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING, &usedithering);
350			fUseDitheringCB->SetEnabled(false);
351			fUseDitheringCB->SetValue(false);
352			fColorCountMF->SetEnabled(false);
353			fColorCount256MI->SetMarked(true);
354			break;
355		}
356
357		case GV_OPTIMAL:
358		{
359			int32 value = OPTIMAL_PALETTE;
360			fSettings->SetGetInt32(GIF_SETTING_PALETTE_MODE, &value);
361			fUseDitheringCB->SetEnabled(true);
362			fColorCountMF->SetEnabled(true);
363			fColorCountMI[fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE) - 1]
364				->SetMarked(true);
365			break;
366		}
367
368		case GV_SET_COLOR_COUNT:
369			if (fColorCountMF->IsEnabled()) {
370				int32 sizeInBits;
371				if (message->FindInt32(GIF_SETTING_PALETTE_SIZE, &sizeInBits)
372						>= B_OK && sizeInBits > 0 && sizeInBits <= 8) {
373					fSettings->SetGetInt32(GIF_SETTING_PALETTE_SIZE,
374						&sizeInBits);
375				}
376			}
377			break;
378
379		case GV_INTERLACED:
380		{
381			bool value = fInterlacedCB->Value();
382			fSettings->SetGetBool(GIF_SETTING_INTERLACED, &value);
383			break;
384		}
385
386		case GV_USE_DITHERING:
387		{
388			bool value = fUseDitheringCB->Value();
389			fSettings->SetGetBool(GIF_SETTING_USE_DITHERING, &value);
390			break;
391		}
392
393		case GV_USE_TRANSPARENT:
394		{
395			bool value = fUseTransparentCB->Value();
396			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT, &value);
397			if (value) {
398				fUseTransparentAutoRB->SetEnabled(true);
399				fUseTransparentColorRB->SetEnabled(true);
400				fRedTextControl->SetEnabled(fUseTransparentColorRB->Value());
401				fGreenTextControl->SetEnabled(fUseTransparentColorRB->Value());
402				fBlueTextControl->SetEnabled(fUseTransparentColorRB->Value());
403			} else {
404				fUseTransparentAutoRB->SetEnabled(false);
405				fUseTransparentColorRB->SetEnabled(false);
406				fRedTextControl->SetEnabled(false);
407				fGreenTextControl->SetEnabled(false);
408				fBlueTextControl->SetEnabled(false);
409			}
410			break;
411		}
412
413		case GV_USE_TRANSPARENT_AUTO:
414		{
415			bool value = true;
416			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO, &value);
417			fRedTextControl->SetEnabled(false);
418			fGreenTextControl->SetEnabled(false);
419			fBlueTextControl->SetEnabled(false);
420			break;
421		}
422
423		case GV_USE_TRANSPARENT_COLOR:
424		{
425			bool value = false;
426			fSettings->SetGetBool(GIF_SETTING_USE_TRANSPARENT_AUTO, &value);
427			fRedTextControl->SetEnabled(true);
428			fGreenTextControl->SetEnabled(true);
429			fBlueTextControl->SetEnabled(true);
430			break;
431		}
432
433		case GV_TRANSPARENT_RED:
434		{
435			int32 value = CheckInput(fRedTextControl);
436			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_RED, &value);
437			break;
438		}
439
440		case GV_TRANSPARENT_GREEN:
441		{
442			int32 value = CheckInput(fGreenTextControl);
443			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_GREEN, &value);
444			break;
445		}
446
447		case GV_TRANSPARENT_BLUE:
448		{
449			int32 value = CheckInput(fBlueTextControl);
450			fSettings->SetGetInt32(GIF_SETTING_TRANSPARENT_BLUE, &value);
451			break;
452		}
453
454		default:
455			BView::MessageReceived(message);
456	}
457
458	fSettings->SaveSettings();
459}
460
461
462int
463GIFView::CheckInput(BTextControl* control)
464{
465	int value = atoi(control->Text());
466	if (value < 0 || value > 255) {
467		value = (value < 0) ? 0 : 255;
468		char temp[4];
469		sprintf(temp, "%d", value);
470		control->SetText(temp);
471	}
472
473	return value;
474}
475