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
GIFView(TranslatorSettings * settings)47 GIFView::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
~GIFView()189 GIFView::~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
204 void
RestorePrefs()205 GIFView::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
296 void
AllAttached()297 GIFView::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
320 void
MessageReceived(BMessage * message)321 GIFView::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
462 int
CheckInput(BTextControl * control)463 GIFView::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