xref: /haiku/src/add-ons/translators/gif/GIFView.cpp (revision 55b40aa53a835472ec7952b138ae4256203d02e4)
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 
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 #include <InterfaceKit.h>
22 #include <String.h>
23 
24 #include "Prefs.h"
25 #include "SavePalette.h"
26 
27 #include "GIFView.h"
28 
29 extern int32 translatorVersion;
30 extern char translatorName[];
31 
32 // constructor
33 GIFView::GIFView(BRect rect, const char *name)
34 	: BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW)
35 {
36 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
37 
38 	font_height fh;
39 	be_bold_font->GetHeight(&fh);
40 	BRect r(10, 15, 10 + be_bold_font->StringWidth(translatorName),
41 		15 + fh.ascent + fh.descent);
42 
43 	BStringView *title = new BStringView(r, "Title", translatorName);
44 	title->SetFont(be_bold_font);
45 	AddChild(title);
46 
47 	char version_string[100];
48 	sprintf(version_string, "v%d.%d.%d %s", (int)(translatorVersion >> 8), (int)((translatorVersion >> 4) & 0xf),
49 		(int)(translatorVersion & 0xf), __DATE__);
50 	be_plain_font->GetHeight(&fh);
51 	r.bottom = r.top + fh.ascent + fh.descent;
52 	r.left = r.right + 2.0 * r.Height();
53 	r.right = r.left + be_plain_font->StringWidth(version_string);
54 
55 	BStringView *version = new BStringView(r, "Version", version_string);
56 	version->SetFont(be_plain_font);
57 	AddChild(version);
58 
59 	const char *copyrightString = "©2003 Daniel Switkin, software@switkin.com";
60 	r.top = r.bottom + 5;
61 	r.left = 10;
62 	r.bottom = r.top + fh.ascent + fh.descent;
63 	r.right = rect.right - 10;
64 
65 	BStringView *copyright = new BStringView(r, "Copyright", copyrightString);
66 	copyright->ResizeToPreferred();
67 	AddChild(copyright);
68 
69 	// menu fields (Palette & Colors)
70 	fWebSafeMI = new BMenuItem("Websafe", new BMessage(GV_WEB_SAFE), 0, 0);
71 	fBeOSSystemMI = new BMenuItem("BeOS System", new BMessage(GV_BEOS_SYSTEM), 0, 0);
72 	fGreyScaleMI = new BMenuItem("Greyscale", new BMessage(GV_GREYSCALE), 0, 0);
73 	fOptimalMI = new BMenuItem("Optimal", new BMessage(GV_OPTIMAL), 0, 0);
74 	fPaletteM = new BPopUpMenu("PalettePopUpMenu", true, true, B_ITEMS_IN_COLUMN);
75 	fPaletteM->AddItem(fWebSafeMI);
76 	fPaletteM->AddItem(fBeOSSystemMI);
77 	fPaletteM->AddItem(fGreyScaleMI);
78 	fPaletteM->AddItem(fOptimalMI);
79 
80 	fColorCountM = new BPopUpMenu("ColorCountPopUpMenu", true, true, B_ITEMS_IN_COLUMN);
81 	int32 count = 2;
82 	for (int32 i = 0; i < 8; i++) {
83 		BMessage* message = new BMessage(GV_SET_COLOR_COUNT);
84 		message->AddInt32("size in bits", i + 1);
85 		BString label;
86 		label << count;
87 		fColorCountMI[i] = new BMenuItem(label.String(), message, 0, 0);
88 		fColorCountM->AddItem(fColorCountMI[i]);
89 		count *= 2;
90 	}
91 	fColorCount256MI = fColorCountMI[7];
92 
93 	r.top = r.bottom + 14;
94 	r.bottom = r.top + 24;
95 	fPaletteMF = new BMenuField(r, "PaletteMenuField", "Palette",
96 		fPaletteM, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
97 	AddChild(fPaletteMF);
98 
99 	r.top = r.bottom + 5;
100 	r.bottom = r.top + 24;
101 	fColorCountMF = new BMenuField(r, "ColorCountMenuField", "Colors",
102 		fColorCountM, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE);
103 	AddChild(fColorCountMF);
104 
105 	// align menu fields
106 	float maxLabelWidth = ceilf(max_c(be_plain_font->StringWidth("Colors"),
107 									  be_plain_font->StringWidth("Palette")));
108 	fPaletteMF->SetDivider(maxLabelWidth + 7);
109 	fColorCountMF->SetDivider(maxLabelWidth + 7);
110 
111 	// check boxen
112 	r.top = fColorCountMF->Frame().bottom + 5;
113 	r.bottom = r.top + 10;
114 	fUseDitheringCB = new BCheckBox(r, "UseDithering", "Use dithering",
115 		new BMessage(GV_USE_DITHERING));
116 	AddChild(fUseDitheringCB);
117 
118 	r.top = fUseDitheringCB->Frame().bottom + 2;
119 	r.bottom = r.top + 10;
120 	fInterlacedCB = new BCheckBox(r, "Interlaced", "Write interlaced images",
121 		new BMessage(GV_INTERLACED));
122 	AddChild(fInterlacedCB);
123 
124 	r.top = fInterlacedCB->Frame().bottom + 2;
125 	r.bottom = r.top + 10;
126 	fUseTransparentCB = new BCheckBox(r, "UseTransparent", "Write transparent images",
127 		new BMessage(GV_USE_TRANSPARENT));
128 	AddChild(fUseTransparentCB);
129 
130 	// radio buttons
131 	r.top = fUseTransparentCB->Frame().bottom + 2;
132 	r.bottom = r.top + 10;
133 	r.right = r.left + be_plain_font->StringWidth("Automatic (from alpha channel)") + 20;
134 	fUseTransparentAutoRB = new BRadioButton(r, "UseTransparentAuto", "Automatic (from alpha channel)",
135 		new BMessage(GV_USE_TRANSPARENT_AUTO));
136 	AddChild(fUseTransparentAutoRB);
137 
138 	r.top = fUseTransparentAutoRB->Frame().bottom + 0;
139 	r.bottom = r.top + 10;
140 	r.left = 10;
141 	r.right = r.left + be_plain_font->StringWidth("Use RGB color") + 20;
142 	fUseTransparentColorRB = new BRadioButton(r, "UseTransparentColor", "Use RGB color",
143 		new BMessage(GV_USE_TRANSPARENT_COLOR));
144 	AddChild(fUseTransparentColorRB);
145 
146 	r.left = r.right + 1;
147 	r.right = r.left + 30;
148 	fTransparentRedTC = new BTextControl(r, "TransparentRed", "", "0",
149 		new BMessage(GV_TRANSPARENT_RED));
150 	AddChild(fTransparentRedTC);
151 	fTransparentRedTC->SetDivider(0);
152 
153 	r.left = r.right + 5;
154 	r.right = r.left + 30;
155 	fTransparentGreenTC = new BTextControl(r, "TransparentGreen", "", "0",
156 		new BMessage(GV_TRANSPARENT_GREEN));
157 	AddChild(fTransparentGreenTC);
158 	fTransparentGreenTC->SetDivider(0);
159 
160 	r.left = r.right + 5;
161 	r.right = r.left + 30;
162 	fTransparentBlueTC = new BTextControl(r, "TransparentBlue", "", "0",
163 		new BMessage(GV_TRANSPARENT_BLUE));
164 	AddChild(fTransparentBlueTC);
165 	fTransparentBlueTC->SetDivider(0);
166 
167 	BTextView *tr = fTransparentRedTC->TextView();
168 	BTextView *tg = fTransparentGreenTC->TextView();
169 	BTextView *tb = fTransparentBlueTC->TextView();
170 
171 	for (uint32 x = 0; x < 256; x++) {
172 		if (x < '0' || x > '9') {
173 			tr->DisallowChar(x);
174 			tg->DisallowChar(x);
175 			tb->DisallowChar(x);
176 		}
177 	}
178 
179 	RestorePrefs();
180 
181 	if (copyright->Frame().right + 10 > Bounds().Width())
182 		ResizeTo(copyright->Frame().right + 10, Bounds().Height());
183 }
184 
185 
186 GIFView::~GIFView()
187 {
188 	delete fPrefs;
189 }
190 
191 
192 void
193 GIFView::RestorePrefs()
194 {
195 	fPrefs = new Prefs();
196 
197 	fColorCountMF->SetEnabled(false);
198 	fUseDitheringCB->SetEnabled(true);
199 
200 	switch (fPrefs->palettemode) {
201 		case WEB_SAFE_PALETTE:
202 			fWebSafeMI->SetMarked(true);
203 			break;
204 		case BEOS_SYSTEM_PALETTE:
205 			fBeOSSystemMI->SetMarked(true);
206 			break;
207 		case GREYSCALE_PALETTE:
208 			fGreyScaleMI->SetMarked(true);
209 			fUseDitheringCB->SetEnabled(false);
210 			break;
211 		case OPTIMAL_PALETTE:
212 			fOptimalMI->SetMarked(true);
213 			fColorCountMF->SetEnabled(true);
214 			break;
215 		default:
216 			fPrefs->palettemode = WEB_SAFE_PALETTE;
217 			fWebSafeMI->SetMarked(true);
218 			break;
219 	}
220 
221 	if (fColorCountMF->IsEnabled() &&
222 		fPrefs->palette_size_in_bits > 0 &&
223 		fPrefs->palette_size_in_bits <= 8) {
224 		// display the stored color count
225 		fColorCountMI[fPrefs->palette_size_in_bits - 1]->SetMarked(true);
226 	} else {
227 		// display 256 colors
228 		fColorCount256MI->SetMarked(true);
229 		fPrefs->palette_size_in_bits = 8;
230 	}
231 
232 	fInterlacedCB->SetValue(fPrefs->interlaced);
233 
234 	if (fGreyScaleMI->IsMarked()) fUseDitheringCB->SetValue(false);
235 	else fUseDitheringCB->SetValue(fPrefs->usedithering);
236 	fUseTransparentCB->SetValue(fPrefs->usetransparent);
237 	fUseTransparentAutoRB->SetValue(fPrefs->usetransparentauto);
238 	fUseTransparentColorRB->SetValue(!fPrefs->usetransparentauto);
239 	if (fPrefs->usetransparent) {
240 		fUseTransparentAutoRB->SetEnabled(true);
241 		fUseTransparentColorRB->SetEnabled(true);
242 		fTransparentRedTC->SetEnabled(!fPrefs->usetransparentauto);
243 		fTransparentGreenTC->SetEnabled(!fPrefs->usetransparentauto);
244 		fTransparentBlueTC->SetEnabled(!fPrefs->usetransparentauto);
245 	} else {
246 		fUseTransparentAutoRB->SetEnabled(false);
247 		fUseTransparentColorRB->SetEnabled(false);
248 		fTransparentRedTC->SetEnabled(false);
249 		fTransparentGreenTC->SetEnabled(false);
250 		fTransparentBlueTC->SetEnabled(false);
251 	}
252 
253 	char temp[4];
254 	sprintf(temp, "%d", fPrefs->transparentred);
255 	fTransparentRedTC->SetText(temp);
256 	sprintf(temp, "%d", fPrefs->transparentgreen);
257 	fTransparentGreenTC->SetText(temp);
258 	sprintf(temp, "%d", fPrefs->transparentblue);
259 	fTransparentBlueTC->SetText(temp);
260 }
261 
262 // AllAttached
263 void
264 GIFView::AllAttached()
265 {
266 	BView::AllAttached();
267 	BMessenger msgr(this);
268 	fInterlacedCB->SetTarget(msgr);
269 	fUseDitheringCB->SetTarget(msgr);
270 	fUseTransparentCB->SetTarget(msgr);
271 	fUseTransparentAutoRB->SetTarget(msgr);
272 	fUseTransparentColorRB->SetTarget(msgr);
273 	fTransparentRedTC->SetTarget(msgr);
274 	fTransparentGreenTC->SetTarget(msgr);
275 	fTransparentBlueTC->SetTarget(msgr);
276 	fPaletteM->SetTargetForItems(msgr);
277 	fColorCountM->SetTargetForItems(msgr);
278 }
279 
280 // MessageReceived
281 void
282 GIFView::MessageReceived(BMessage *message)
283 {
284 	switch (message->what) {
285 		case GV_WEB_SAFE:
286 			fPrefs->palettemode = WEB_SAFE_PALETTE;
287 			fUseDitheringCB->SetEnabled(true);
288 			fColorCountMF->SetEnabled(false);
289 			fColorCount256MI->SetMarked(true);
290 			break;
291 		case GV_BEOS_SYSTEM:
292 			fPrefs->palettemode = BEOS_SYSTEM_PALETTE;
293 			fUseDitheringCB->SetEnabled(true);
294 			fColorCountMF->SetEnabled(false);
295 			fColorCount256MI->SetMarked(true);
296 			break;
297 		case GV_GREYSCALE:
298 			fPrefs->palettemode = GREYSCALE_PALETTE;
299 			fUseDitheringCB->SetEnabled(false);
300 			fUseDitheringCB->SetValue(false);
301 			fColorCountMF->SetEnabled(false);
302 			fColorCount256MI->SetMarked(true);
303 			fPrefs->usedithering = false;
304 			break;
305 		case GV_OPTIMAL:
306 			fPrefs->palettemode = OPTIMAL_PALETTE;
307 			fUseDitheringCB->SetEnabled(true);
308 			fColorCountMF->SetEnabled(true);
309 			fColorCountMI[fPrefs->palette_size_in_bits - 1]->SetMarked(true);
310 			break;
311 		case GV_SET_COLOR_COUNT:
312 			if (fColorCountMF->IsEnabled()) {
313 				int32 sizeInBits;
314 				if (message->FindInt32("size in bits", &sizeInBits) >= B_OK) {
315 					if (sizeInBits > 0 && sizeInBits <= 8)
316 						fPrefs->palette_size_in_bits = sizeInBits;
317 				}
318 			}
319 			break;
320 		case GV_INTERLACED:
321 			fPrefs->interlaced = fInterlacedCB->Value();
322 			break;
323 		case GV_USE_DITHERING:
324 			fPrefs->usedithering = fUseDitheringCB->Value();
325 			break;
326 		case GV_USE_TRANSPARENT:
327 			fPrefs->usetransparent = fUseTransparentCB->Value();
328 			if (fPrefs->usetransparent) {
329 				fUseTransparentAutoRB->SetEnabled(true);
330 				fUseTransparentColorRB->SetEnabled(true);
331 				fTransparentRedTC->SetEnabled(fUseTransparentColorRB->Value());
332 				fTransparentGreenTC->SetEnabled(fUseTransparentColorRB->Value());
333 				fTransparentBlueTC->SetEnabled(fUseTransparentColorRB->Value());
334 			} else {
335 				fUseTransparentAutoRB->SetEnabled(false);
336 				fUseTransparentColorRB->SetEnabled(false);
337 				fTransparentRedTC->SetEnabled(false);
338 				fTransparentGreenTC->SetEnabled(false);
339 				fTransparentBlueTC->SetEnabled(false);
340 			}
341 			break;
342 		case GV_USE_TRANSPARENT_AUTO:
343 			fPrefs->usetransparentauto = true;
344 			fTransparentRedTC->SetEnabled(false);
345 			fTransparentGreenTC->SetEnabled(false);
346 			fTransparentBlueTC->SetEnabled(false);
347 			break;
348 		case GV_USE_TRANSPARENT_COLOR:
349 			fPrefs->usetransparentauto = false;
350 			fTransparentRedTC->SetEnabled(true);
351 			fTransparentGreenTC->SetEnabled(true);
352 			fTransparentBlueTC->SetEnabled(true);
353 			break;
354 		case GV_TRANSPARENT_RED:
355 			fPrefs->transparentred = CheckInput(fTransparentRedTC);
356 			break;
357 		case GV_TRANSPARENT_GREEN:
358 			fPrefs->transparentgreen = CheckInput(fTransparentGreenTC);
359 			break;
360 		case GV_TRANSPARENT_BLUE:
361 			fPrefs->transparentblue = CheckInput(fTransparentBlueTC);
362 			break;
363 		default:
364 			BView::MessageReceived(message);
365 			break;
366 	}
367 	fPrefs->Save();
368 }
369 
370 int GIFView::CheckInput(BTextControl *control) {
371 	int value = atoi(control->Text());
372 	if (value < 0 || value > 255) {
373 		value = (value < 0) ? 0 : 255;
374 		char temp[4];
375 		sprintf(temp, "%d", value);
376 		control->SetText(temp);
377 	}
378 	return value;
379 }
380 
381