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