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