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