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 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 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 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 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 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 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