1*22c6ae69SDarkWyrm #include "BitmapView.h" 2*22c6ae69SDarkWyrm #include <Entry.h> 3*22c6ae69SDarkWyrm #include <TranslationUtils.h> 4*22c6ae69SDarkWyrm #include <TranslatorRoster.h> 5*22c6ae69SDarkWyrm #include <TranslatorFormats.h> 6*22c6ae69SDarkWyrm #include <Clipboard.h> 7*22c6ae69SDarkWyrm #include <BitmapStream.h> 8*22c6ae69SDarkWyrm #include <MenuItem.h> 9*22c6ae69SDarkWyrm #include <Font.h> 10*22c6ae69SDarkWyrm #include <Alert.h> 11*22c6ae69SDarkWyrm 12*22c6ae69SDarkWyrm // TODO: Add support for labels 13*22c6ae69SDarkWyrm 14*22c6ae69SDarkWyrm #define M_REMOVE_IMAGE 'mrmi' 15*22c6ae69SDarkWyrm #define M_PASTE_IMAGE 'mpsi' 16*22c6ae69SDarkWyrm 17*22c6ae69SDarkWyrm enum 18*22c6ae69SDarkWyrm { 19*22c6ae69SDarkWyrm CLIP_NONE=0, 20*22c6ae69SDarkWyrm CLIP_BEOS=1, 21*22c6ae69SDarkWyrm CLIP_SHOWIMAGE=2, 22*22c6ae69SDarkWyrm CLIP_PRODUCTIVE=3 23*22c6ae69SDarkWyrm }; 24*22c6ae69SDarkWyrm 25*22c6ae69SDarkWyrm inline void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255); 26*22c6ae69SDarkWyrm 27*22c6ae69SDarkWyrm void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a) 28*22c6ae69SDarkWyrm { 29*22c6ae69SDarkWyrm if(col) 30*22c6ae69SDarkWyrm { 31*22c6ae69SDarkWyrm col->red=r; 32*22c6ae69SDarkWyrm col->green=g; 33*22c6ae69SDarkWyrm col->blue=b; 34*22c6ae69SDarkWyrm col->alpha=a; 35*22c6ae69SDarkWyrm } 36*22c6ae69SDarkWyrm } 37*22c6ae69SDarkWyrm 38*22c6ae69SDarkWyrm BitmapView::BitmapView(BRect frame, const char *name, BMessage *mod, BBitmap *bitmap, 39*22c6ae69SDarkWyrm const char *label, border_style borderstyle,int32 resize,int32 flags) 40*22c6ae69SDarkWyrm : BView(frame, name, resize, flags) 41*22c6ae69SDarkWyrm { 42*22c6ae69SDarkWyrm SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 43*22c6ae69SDarkWyrm 44*22c6ae69SDarkWyrm if(bitmap && bitmap->IsValid()) 45*22c6ae69SDarkWyrm fBitmap=bitmap; 46*22c6ae69SDarkWyrm else 47*22c6ae69SDarkWyrm fBitmap=NULL; 48*22c6ae69SDarkWyrm 49*22c6ae69SDarkWyrm if(mod) 50*22c6ae69SDarkWyrm SetMessage(mod); 51*22c6ae69SDarkWyrm 52*22c6ae69SDarkWyrm fLabel=label; 53*22c6ae69SDarkWyrm fBorderStyle=borderstyle; 54*22c6ae69SDarkWyrm fFixedSize=false; 55*22c6ae69SDarkWyrm fEnabled=true; 56*22c6ae69SDarkWyrm fRemovableBitmap=false; 57*22c6ae69SDarkWyrm fAcceptDrops=true; 58*22c6ae69SDarkWyrm fAcceptPaste=true; 59*22c6ae69SDarkWyrm fConstrainDrops=true; 60*22c6ae69SDarkWyrm fMaxWidth=100; 61*22c6ae69SDarkWyrm fMaxHeight=100; 62*22c6ae69SDarkWyrm 63*22c6ae69SDarkWyrm fPopUpMenu=new BPopUpMenu("deletepopup",false,false); 64*22c6ae69SDarkWyrm fPopUpMenu->AddItem(new BMenuItem("Close This Menu",new BMessage(B_CANCEL))); 65*22c6ae69SDarkWyrm fPopUpMenu->AddSeparatorItem(); 66*22c6ae69SDarkWyrm 67*22c6ae69SDarkWyrm fPasteItem=new BMenuItem("Paste Photo from Clipboard",new BMessage(M_PASTE_IMAGE)); 68*22c6ae69SDarkWyrm fPopUpMenu->AddItem(fPasteItem); 69*22c6ae69SDarkWyrm 70*22c6ae69SDarkWyrm fPopUpMenu->AddSeparatorItem(); 71*22c6ae69SDarkWyrm 72*22c6ae69SDarkWyrm fRemoveItem=new BMenuItem("Remove Photo",new BMessage(M_REMOVE_IMAGE)); 73*22c6ae69SDarkWyrm fPopUpMenu->AddItem(fRemoveItem); 74*22c6ae69SDarkWyrm 75*22c6ae69SDarkWyrm CalculateBitmapRect(); 76*22c6ae69SDarkWyrm 77*22c6ae69SDarkWyrm // Calculate the offsets for each of the words -- the phrase will be center justified 78*22c6ae69SDarkWyrm fNoPhotoWidths[0]=StringWidth("Drop"); 79*22c6ae69SDarkWyrm fNoPhotoWidths[1]=StringWidth("a"); 80*22c6ae69SDarkWyrm fNoPhotoWidths[2]=StringWidth("Photo"); 81*22c6ae69SDarkWyrm fNoPhotoWidths[3]=StringWidth("Here"); 82*22c6ae69SDarkWyrm 83*22c6ae69SDarkWyrm font_height fh; 84*22c6ae69SDarkWyrm GetFontHeight(&fh); 85*22c6ae69SDarkWyrm float totalheight=fh.ascent+fh.descent+fh.leading; 86*22c6ae69SDarkWyrm float yoffset=(Bounds().Height()-10-(totalheight*4))/2; 87*22c6ae69SDarkWyrm fNoPhotoOffsets[0].Set( (Bounds().Width()-fNoPhotoWidths[0])/2,totalheight+yoffset); 88*22c6ae69SDarkWyrm fNoPhotoOffsets[1].Set( (Bounds().Width()-fNoPhotoWidths[1])/2,fNoPhotoOffsets[0].y+totalheight); 89*22c6ae69SDarkWyrm fNoPhotoOffsets[2].Set( (Bounds().Width()-fNoPhotoWidths[2])/2,fNoPhotoOffsets[1].y+totalheight); 90*22c6ae69SDarkWyrm fNoPhotoOffsets[3].Set( (Bounds().Width()-fNoPhotoWidths[3])/2,fNoPhotoOffsets[2].y+totalheight); 91*22c6ae69SDarkWyrm } 92*22c6ae69SDarkWyrm 93*22c6ae69SDarkWyrm BitmapView::~BitmapView(void) 94*22c6ae69SDarkWyrm { 95*22c6ae69SDarkWyrm delete fPopUpMenu; 96*22c6ae69SDarkWyrm } 97*22c6ae69SDarkWyrm 98*22c6ae69SDarkWyrm void BitmapView::AttachedToWindow(void) 99*22c6ae69SDarkWyrm { 100*22c6ae69SDarkWyrm SetTarget((BHandler*)Window()); 101*22c6ae69SDarkWyrm fPopUpMenu->SetTargetForItems(this); 102*22c6ae69SDarkWyrm } 103*22c6ae69SDarkWyrm 104*22c6ae69SDarkWyrm void BitmapView::SetBitmap(BBitmap *bitmap) 105*22c6ae69SDarkWyrm { 106*22c6ae69SDarkWyrm if(bitmap && bitmap->IsValid()) 107*22c6ae69SDarkWyrm { 108*22c6ae69SDarkWyrm if(fBitmap==bitmap) 109*22c6ae69SDarkWyrm return; 110*22c6ae69SDarkWyrm 111*22c6ae69SDarkWyrm fBitmap=bitmap; 112*22c6ae69SDarkWyrm } 113*22c6ae69SDarkWyrm else 114*22c6ae69SDarkWyrm { 115*22c6ae69SDarkWyrm if(fBitmap==NULL) 116*22c6ae69SDarkWyrm return; 117*22c6ae69SDarkWyrm 118*22c6ae69SDarkWyrm fBitmap=NULL; 119*22c6ae69SDarkWyrm } 120*22c6ae69SDarkWyrm 121*22c6ae69SDarkWyrm CalculateBitmapRect(); 122*22c6ae69SDarkWyrm if(!IsHidden()) 123*22c6ae69SDarkWyrm Invalidate(); 124*22c6ae69SDarkWyrm } 125*22c6ae69SDarkWyrm 126*22c6ae69SDarkWyrm void BitmapView::SetEnabled(bool value) 127*22c6ae69SDarkWyrm { 128*22c6ae69SDarkWyrm if(fEnabled!=value) 129*22c6ae69SDarkWyrm { 130*22c6ae69SDarkWyrm fEnabled=value; 131*22c6ae69SDarkWyrm Invalidate(); 132*22c6ae69SDarkWyrm } 133*22c6ae69SDarkWyrm } 134*22c6ae69SDarkWyrm 135*22c6ae69SDarkWyrm /* 136*22c6ae69SDarkWyrm void BitmapView::SetLabel(const char *label) 137*22c6ae69SDarkWyrm { 138*22c6ae69SDarkWyrm if(fLabel.Compare(label)!=0) 139*22c6ae69SDarkWyrm { 140*22c6ae69SDarkWyrm fLabel=label; 141*22c6ae69SDarkWyrm 142*22c6ae69SDarkWyrm CalculateBitmapRect(); 143*22c6ae69SDarkWyrm if(!IsHidden()) 144*22c6ae69SDarkWyrm Invalidate(); 145*22c6ae69SDarkWyrm } 146*22c6ae69SDarkWyrm } 147*22c6ae69SDarkWyrm */ 148*22c6ae69SDarkWyrm 149*22c6ae69SDarkWyrm void BitmapView::SetStyle(border_style style) 150*22c6ae69SDarkWyrm { 151*22c6ae69SDarkWyrm if(fBorderStyle!=style) 152*22c6ae69SDarkWyrm { 153*22c6ae69SDarkWyrm fBorderStyle=style; 154*22c6ae69SDarkWyrm 155*22c6ae69SDarkWyrm CalculateBitmapRect(); 156*22c6ae69SDarkWyrm if(!IsHidden()) 157*22c6ae69SDarkWyrm Invalidate(); 158*22c6ae69SDarkWyrm } 159*22c6ae69SDarkWyrm } 160*22c6ae69SDarkWyrm 161*22c6ae69SDarkWyrm void BitmapView::SetFixedSize(bool isfixed) 162*22c6ae69SDarkWyrm { 163*22c6ae69SDarkWyrm if(fFixedSize!=isfixed) 164*22c6ae69SDarkWyrm { 165*22c6ae69SDarkWyrm fFixedSize=isfixed; 166*22c6ae69SDarkWyrm 167*22c6ae69SDarkWyrm CalculateBitmapRect(); 168*22c6ae69SDarkWyrm if(!IsHidden()) 169*22c6ae69SDarkWyrm Invalidate(); 170*22c6ae69SDarkWyrm } 171*22c6ae69SDarkWyrm } 172*22c6ae69SDarkWyrm 173*22c6ae69SDarkWyrm void BitmapView::MessageReceived(BMessage *msg) 174*22c6ae69SDarkWyrm { 175*22c6ae69SDarkWyrm if(msg->WasDropped() && AcceptsDrops()) 176*22c6ae69SDarkWyrm { 177*22c6ae69SDarkWyrm // We'll handle two types of drops: those from Tracker and those from ShowImage 178*22c6ae69SDarkWyrm if(msg->what==B_SIMPLE_DATA) 179*22c6ae69SDarkWyrm { 180*22c6ae69SDarkWyrm int32 actions; 181*22c6ae69SDarkWyrm if(msg->FindInt32("be:actions",&actions)==B_OK) 182*22c6ae69SDarkWyrm { 183*22c6ae69SDarkWyrm // ShowImage drop. This is a negotiated drag&drop, so send a reply 184*22c6ae69SDarkWyrm BMessage reply(B_COPY_TARGET), response; 185*22c6ae69SDarkWyrm reply.AddString("be:types","image/jpeg"); 186*22c6ae69SDarkWyrm reply.AddString("be:types","image/png"); 187*22c6ae69SDarkWyrm 188*22c6ae69SDarkWyrm msg->SendReply(&reply,&response); 189*22c6ae69SDarkWyrm 190*22c6ae69SDarkWyrm // now, we've gotten the response 191*22c6ae69SDarkWyrm if(response.what==B_MIME_DATA) 192*22c6ae69SDarkWyrm { 193*22c6ae69SDarkWyrm // Obtain and translate the received data 194*22c6ae69SDarkWyrm uint8 *imagedata; 195*22c6ae69SDarkWyrm ssize_t datasize; 196*22c6ae69SDarkWyrm 197*22c6ae69SDarkWyrm // Try JPEG first 198*22c6ae69SDarkWyrm if(response.FindData("image/jpeg",B_MIME_DATA,(const void **)&imagedata,&datasize)!=B_OK) 199*22c6ae69SDarkWyrm { 200*22c6ae69SDarkWyrm // Try PNG next and piddle out if unsuccessful 201*22c6ae69SDarkWyrm if(response.FindData("image/png",B_PNG_FORMAT,(const void **)&imagedata,&datasize)!=B_OK) 202*22c6ae69SDarkWyrm return; 203*22c6ae69SDarkWyrm } 204*22c6ae69SDarkWyrm 205*22c6ae69SDarkWyrm // Set up to decode into memory 206*22c6ae69SDarkWyrm BMemoryIO memio(imagedata,datasize); 207*22c6ae69SDarkWyrm BTranslatorRoster *roster=BTranslatorRoster::Default(); 208*22c6ae69SDarkWyrm BBitmapStream bstream; 209*22c6ae69SDarkWyrm 210*22c6ae69SDarkWyrm if(roster->Translate(&memio,NULL,NULL,&bstream, B_TRANSLATOR_BITMAP)==B_OK) 211*22c6ae69SDarkWyrm { 212*22c6ae69SDarkWyrm BBitmap *bmp; 213*22c6ae69SDarkWyrm if(bstream.DetachBitmap(&bmp)!=B_OK) 214*22c6ae69SDarkWyrm return; 215*22c6ae69SDarkWyrm 216*22c6ae69SDarkWyrm SetBitmap(bmp); 217*22c6ae69SDarkWyrm 218*22c6ae69SDarkWyrm if(fConstrainDrops) 219*22c6ae69SDarkWyrm ConstrainBitmap(); 220*22c6ae69SDarkWyrm 221*22c6ae69SDarkWyrm Invoke(); 222*22c6ae69SDarkWyrm } 223*22c6ae69SDarkWyrm } 224*22c6ae69SDarkWyrm return; 225*22c6ae69SDarkWyrm } 226*22c6ae69SDarkWyrm 227*22c6ae69SDarkWyrm entry_ref ref; 228*22c6ae69SDarkWyrm if(msg->FindRef("refs",&ref)==B_OK) 229*22c6ae69SDarkWyrm { 230*22c6ae69SDarkWyrm // Tracker drop 231*22c6ae69SDarkWyrm BBitmap *bmp=BTranslationUtils::GetBitmap(&ref); 232*22c6ae69SDarkWyrm if(bmp) 233*22c6ae69SDarkWyrm { 234*22c6ae69SDarkWyrm SetBitmap(bmp); 235*22c6ae69SDarkWyrm 236*22c6ae69SDarkWyrm if(fConstrainDrops) 237*22c6ae69SDarkWyrm ConstrainBitmap(); 238*22c6ae69SDarkWyrm 239*22c6ae69SDarkWyrm Invoke(); 240*22c6ae69SDarkWyrm } 241*22c6ae69SDarkWyrm } 242*22c6ae69SDarkWyrm } 243*22c6ae69SDarkWyrm return; 244*22c6ae69SDarkWyrm } 245*22c6ae69SDarkWyrm 246*22c6ae69SDarkWyrm switch(msg->what) 247*22c6ae69SDarkWyrm { 248*22c6ae69SDarkWyrm case M_REMOVE_IMAGE: 249*22c6ae69SDarkWyrm { 250*22c6ae69SDarkWyrm BAlert *alert=new BAlert("Mr. Peeps!","This cannot be undone. Remove the image?","Remove", 251*22c6ae69SDarkWyrm "Cancel"); 252*22c6ae69SDarkWyrm int32 value=alert->Go(); 253*22c6ae69SDarkWyrm if(value==0) 254*22c6ae69SDarkWyrm { 255*22c6ae69SDarkWyrm SetBitmap(NULL); 256*22c6ae69SDarkWyrm 257*22c6ae69SDarkWyrm if(Target()) 258*22c6ae69SDarkWyrm { 259*22c6ae69SDarkWyrm BMessenger msgr(Target()); 260*22c6ae69SDarkWyrm 261*22c6ae69SDarkWyrm msgr.SendMessage(new BMessage(M_BITMAP_REMOVED)); 262*22c6ae69SDarkWyrm return; 263*22c6ae69SDarkWyrm } 264*22c6ae69SDarkWyrm } 265*22c6ae69SDarkWyrm } 266*22c6ae69SDarkWyrm case M_PASTE_IMAGE: 267*22c6ae69SDarkWyrm { 268*22c6ae69SDarkWyrm PasteBitmap(); 269*22c6ae69SDarkWyrm 270*22c6ae69SDarkWyrm Invoke(); 271*22c6ae69SDarkWyrm } 272*22c6ae69SDarkWyrm } 273*22c6ae69SDarkWyrm BView::MessageReceived(msg); 274*22c6ae69SDarkWyrm } 275*22c6ae69SDarkWyrm 276*22c6ae69SDarkWyrm void BitmapView::Draw(BRect rect) 277*22c6ae69SDarkWyrm { 278*22c6ae69SDarkWyrm if(fBitmap) 279*22c6ae69SDarkWyrm DrawBitmap(fBitmap,fBitmap->Bounds(),fBitmapRect); 280*22c6ae69SDarkWyrm else 281*22c6ae69SDarkWyrm { 282*22c6ae69SDarkWyrm SetHighColor(0,0,0,80); 283*22c6ae69SDarkWyrm SetDrawingMode(B_OP_ALPHA); 284*22c6ae69SDarkWyrm DrawString("Drop",fNoPhotoOffsets[0]); 285*22c6ae69SDarkWyrm DrawString("a",fNoPhotoOffsets[1]); 286*22c6ae69SDarkWyrm DrawString("Photo",fNoPhotoOffsets[2]); 287*22c6ae69SDarkWyrm DrawString("Here",fNoPhotoOffsets[3]); 288*22c6ae69SDarkWyrm SetDrawingMode(B_OP_COPY); 289*22c6ae69SDarkWyrm } 290*22c6ae69SDarkWyrm 291*22c6ae69SDarkWyrm if(fBorderStyle==B_FANCY_BORDER) 292*22c6ae69SDarkWyrm { 293*22c6ae69SDarkWyrm rgb_color base= {216,216,216,255}; 294*22c6ae69SDarkWyrm rgb_color work; 295*22c6ae69SDarkWyrm 296*22c6ae69SDarkWyrm SetHighColor(base); 297*22c6ae69SDarkWyrm StrokeRect(Bounds().InsetByCopy(2,2)); 298*22c6ae69SDarkWyrm 299*22c6ae69SDarkWyrm BeginLineArray(12); 300*22c6ae69SDarkWyrm 301*22c6ae69SDarkWyrm BRect r(Bounds()); 302*22c6ae69SDarkWyrm 303*22c6ae69SDarkWyrm work=tint_color(base,B_DARKEN_2_TINT); 304*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.RightTop(),work); 305*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.LeftBottom(),work); 306*22c6ae69SDarkWyrm r.left++; 307*22c6ae69SDarkWyrm 308*22c6ae69SDarkWyrm work=tint_color(base,B_DARKEN_4_TINT); 309*22c6ae69SDarkWyrm AddLine(r.RightTop(),r.RightBottom(),work); 310*22c6ae69SDarkWyrm AddLine(r.LeftBottom(),r.RightBottom(),work); 311*22c6ae69SDarkWyrm 312*22c6ae69SDarkWyrm r.right--; 313*22c6ae69SDarkWyrm r.top++; 314*22c6ae69SDarkWyrm r.bottom--; 315*22c6ae69SDarkWyrm 316*22c6ae69SDarkWyrm 317*22c6ae69SDarkWyrm work=tint_color(base,B_LIGHTEN_MAX_TINT); 318*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.RightTop(),work); 319*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.LeftBottom(),work); 320*22c6ae69SDarkWyrm r.left++; 321*22c6ae69SDarkWyrm 322*22c6ae69SDarkWyrm work=tint_color(base,B_DARKEN_3_TINT); 323*22c6ae69SDarkWyrm AddLine(r.RightTop(),r.RightBottom(),work); 324*22c6ae69SDarkWyrm AddLine(r.LeftBottom(),r.RightBottom(),work); 325*22c6ae69SDarkWyrm 326*22c6ae69SDarkWyrm // this rect handled by the above StrokeRect, so inset a total of 2 pixels 327*22c6ae69SDarkWyrm r.left++; 328*22c6ae69SDarkWyrm r.right-=2; 329*22c6ae69SDarkWyrm r.top+=2; 330*22c6ae69SDarkWyrm r.bottom-=2; 331*22c6ae69SDarkWyrm 332*22c6ae69SDarkWyrm 333*22c6ae69SDarkWyrm work=tint_color(base,B_DARKEN_3_TINT); 334*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.RightTop(),work); 335*22c6ae69SDarkWyrm AddLine(r.LeftTop(),r.LeftBottom(),work); 336*22c6ae69SDarkWyrm r.left++; 337*22c6ae69SDarkWyrm 338*22c6ae69SDarkWyrm work=tint_color(base,B_LIGHTEN_MAX_TINT); 339*22c6ae69SDarkWyrm AddLine(r.RightTop(),r.RightBottom(),work); 340*22c6ae69SDarkWyrm AddLine(r.LeftBottom(),r.RightBottom(),work); 341*22c6ae69SDarkWyrm 342*22c6ae69SDarkWyrm r.right--; 343*22c6ae69SDarkWyrm r.top++; 344*22c6ae69SDarkWyrm r.bottom--; 345*22c6ae69SDarkWyrm EndLineArray(); 346*22c6ae69SDarkWyrm 347*22c6ae69SDarkWyrm SetHighColor(tint_color(base,B_DARKEN_2_TINT)); 348*22c6ae69SDarkWyrm StrokeRect(r); 349*22c6ae69SDarkWyrm } 350*22c6ae69SDarkWyrm else 351*22c6ae69SDarkWyrm { 352*22c6ae69SDarkWyrm // Plain border 353*22c6ae69SDarkWyrm SetHighColor(0,0,0); 354*22c6ae69SDarkWyrm StrokeRect(fBitmapRect); 355*22c6ae69SDarkWyrm } 356*22c6ae69SDarkWyrm } 357*22c6ae69SDarkWyrm 358*22c6ae69SDarkWyrm void BitmapView::MouseDown(BPoint pt) 359*22c6ae69SDarkWyrm { 360*22c6ae69SDarkWyrm BPoint mousept; 361*22c6ae69SDarkWyrm uint32 buttons; 362*22c6ae69SDarkWyrm 363*22c6ae69SDarkWyrm GetMouse(&mousept,&buttons); 364*22c6ae69SDarkWyrm if(buttons & B_SECONDARY_MOUSE_BUTTON) 365*22c6ae69SDarkWyrm { 366*22c6ae69SDarkWyrm ConvertToScreen(&mousept); 367*22c6ae69SDarkWyrm 368*22c6ae69SDarkWyrm mousept.x= (mousept.x>5) ? mousept.x-5 : 0; 369*22c6ae69SDarkWyrm mousept.y= (mousept.y>5) ? mousept.y-5 : 0; 370*22c6ae69SDarkWyrm 371*22c6ae69SDarkWyrm if(AcceptsPaste() && ClipboardHasBitmap()) 372*22c6ae69SDarkWyrm fPasteItem->SetEnabled(true); 373*22c6ae69SDarkWyrm else 374*22c6ae69SDarkWyrm fPasteItem->SetEnabled(false); 375*22c6ae69SDarkWyrm 376*22c6ae69SDarkWyrm if(fRemovableBitmap && fBitmap) 377*22c6ae69SDarkWyrm fRemoveItem->SetEnabled(true); 378*22c6ae69SDarkWyrm else 379*22c6ae69SDarkWyrm fRemoveItem->SetEnabled(false); 380*22c6ae69SDarkWyrm 381*22c6ae69SDarkWyrm fPopUpMenu->Go(mousept,true,true,true); 382*22c6ae69SDarkWyrm } 383*22c6ae69SDarkWyrm } 384*22c6ae69SDarkWyrm 385*22c6ae69SDarkWyrm void BitmapView::FrameResized(float w, float h) 386*22c6ae69SDarkWyrm { 387*22c6ae69SDarkWyrm CalculateBitmapRect(); 388*22c6ae69SDarkWyrm } 389*22c6ae69SDarkWyrm 390*22c6ae69SDarkWyrm void BitmapView::CalculateBitmapRect(void) 391*22c6ae69SDarkWyrm { 392*22c6ae69SDarkWyrm if(!fBitmap || fFixedSize) 393*22c6ae69SDarkWyrm { 394*22c6ae69SDarkWyrm fBitmapRect=Bounds().InsetByCopy(1,1); 395*22c6ae69SDarkWyrm return; 396*22c6ae69SDarkWyrm } 397*22c6ae69SDarkWyrm 398*22c6ae69SDarkWyrm /* // Dynamic sizing algorithm 399*22c6ae69SDarkWyrm // 1) Check to see if either dimension is bigger than the view's display area 400*22c6ae69SDarkWyrm // 2) If smaller along both axes, make bitmap rect centered and return 401*22c6ae69SDarkWyrm // 3) Check to see if scaling is to be horizontal or vertical on basis of longer axis 402*22c6ae69SDarkWyrm // 4) Calculate scaling factor 403*22c6ae69SDarkWyrm // 5) Scale both axes down by scaling factor, accounting for border width 404*22c6ae69SDarkWyrm // 6) Center the rectangle in the direction of the smaller axis 405*22c6ae69SDarkWyrm 406*22c6ae69SDarkWyrm 407*22c6ae69SDarkWyrm uint8 borderwidth=(fBorderStyle==B_FANCY_BORDER)?5:1; 408*22c6ae69SDarkWyrm 409*22c6ae69SDarkWyrm BRect r(Bounds()); 410*22c6ae69SDarkWyrm r.InsetBy(borderwidth,borderwidth); 411*22c6ae69SDarkWyrm 412*22c6ae69SDarkWyrm if( (fBitmap->Bounds().Width()<=r.Width()) && 413*22c6ae69SDarkWyrm (fBitmap->Bounds().Height()<=r.Height()) ) 414*22c6ae69SDarkWyrm { 415*22c6ae69SDarkWyrm // Smaller than view, so just center and return 416*22c6ae69SDarkWyrm fBitmapRect=fBitmap->Bounds(); 417*22c6ae69SDarkWyrm fBitmapRect.OffsetBy( borderwidth+ 418*22c6ae69SDarkWyrm ((r.Width()-fBitmapRect.Width()-(borderwidth<<2))/2), 419*22c6ae69SDarkWyrm ((r.Height()-fBitmapRect.Height()-(borderwidth<<2))/2) ); 420*22c6ae69SDarkWyrm return; 421*22c6ae69SDarkWyrm } 422*22c6ae69SDarkWyrm 423*22c6ae69SDarkWyrm float multiplier=fBitmap->Bounds().Width()/fBitmap->Bounds().Height(); 424*22c6ae69SDarkWyrm float offset; 425*22c6ae69SDarkWyrm if(multiplier>1) 426*22c6ae69SDarkWyrm { 427*22c6ae69SDarkWyrm // Landscape orientation 428*22c6ae69SDarkWyrm 429*22c6ae69SDarkWyrm // Scale rectangle to bounds width and center height 430*22c6ae69SDarkWyrm r.bottom=r.top+(r.Width()/multiplier); 431*22c6ae69SDarkWyrm 432*22c6ae69SDarkWyrm offset= ((Bounds().Height()-(borderwidth<<1)) - r.Height())/2; 433*22c6ae69SDarkWyrm r.OffsetBy(0,offset); 434*22c6ae69SDarkWyrm } 435*22c6ae69SDarkWyrm else 436*22c6ae69SDarkWyrm { 437*22c6ae69SDarkWyrm // Portrait orientation 438*22c6ae69SDarkWyrm 439*22c6ae69SDarkWyrm // Scale rectangle to bounds height and center width 440*22c6ae69SDarkWyrm r.right=r.left+(r.Height()*multiplier); 441*22c6ae69SDarkWyrm 442*22c6ae69SDarkWyrm offset= ((Bounds().Width()-(borderwidth<<1)) - r.Width())/2; 443*22c6ae69SDarkWyrm r.OffsetBy(offset,0); 444*22c6ae69SDarkWyrm } 445*22c6ae69SDarkWyrm fBitmapRect=r; 446*22c6ae69SDarkWyrm */ 447*22c6ae69SDarkWyrm 448*22c6ae69SDarkWyrm uint8 borderwidth=(fBorderStyle==B_FANCY_BORDER)?5:1; 449*22c6ae69SDarkWyrm 450*22c6ae69SDarkWyrm BRect r(Bounds()); 451*22c6ae69SDarkWyrm fBitmapRect= ScaleRectToFit(fBitmap->Bounds(),r.InsetByCopy(borderwidth,borderwidth)); 452*22c6ae69SDarkWyrm } 453*22c6ae69SDarkWyrm 454*22c6ae69SDarkWyrm void BitmapView::SetAcceptDrops(bool accept) 455*22c6ae69SDarkWyrm { 456*22c6ae69SDarkWyrm fAcceptDrops=accept; 457*22c6ae69SDarkWyrm } 458*22c6ae69SDarkWyrm 459*22c6ae69SDarkWyrm void BitmapView::SetAcceptPaste(bool accept) 460*22c6ae69SDarkWyrm { 461*22c6ae69SDarkWyrm fAcceptPaste=accept; 462*22c6ae69SDarkWyrm } 463*22c6ae69SDarkWyrm 464*22c6ae69SDarkWyrm void BitmapView::SetConstrainDrops(bool value) 465*22c6ae69SDarkWyrm { 466*22c6ae69SDarkWyrm fConstrainDrops=value; 467*22c6ae69SDarkWyrm } 468*22c6ae69SDarkWyrm 469*22c6ae69SDarkWyrm void BitmapView::MaxBitmapSize(float *width, float *height) const 470*22c6ae69SDarkWyrm { 471*22c6ae69SDarkWyrm *width=fMaxWidth; 472*22c6ae69SDarkWyrm *height=fMaxHeight; 473*22c6ae69SDarkWyrm } 474*22c6ae69SDarkWyrm 475*22c6ae69SDarkWyrm void BitmapView::SetMaxBitmapSize(const float &width, const float &height) 476*22c6ae69SDarkWyrm { 477*22c6ae69SDarkWyrm fMaxWidth=width; 478*22c6ae69SDarkWyrm fMaxHeight=height; 479*22c6ae69SDarkWyrm 480*22c6ae69SDarkWyrm ConstrainBitmap(); 481*22c6ae69SDarkWyrm } 482*22c6ae69SDarkWyrm 483*22c6ae69SDarkWyrm void BitmapView::SetBitmapRemovable(bool isremovable) 484*22c6ae69SDarkWyrm { 485*22c6ae69SDarkWyrm fRemovableBitmap=isremovable; 486*22c6ae69SDarkWyrm } 487*22c6ae69SDarkWyrm 488*22c6ae69SDarkWyrm void BitmapView::ConstrainBitmap(void) 489*22c6ae69SDarkWyrm { 490*22c6ae69SDarkWyrm if(!fBitmap || fMaxWidth < 1 || fMaxHeight < 1) 491*22c6ae69SDarkWyrm return; 492*22c6ae69SDarkWyrm 493*22c6ae69SDarkWyrm BRect r=ScaleRectToFit(fBitmap->Bounds(),BRect(0,0,fMaxWidth-1,fMaxHeight-1)); 494*22c6ae69SDarkWyrm r.OffsetTo(0,0); 495*22c6ae69SDarkWyrm 496*22c6ae69SDarkWyrm BBitmap *scaled=new BBitmap(r,fBitmap->ColorSpace(),true); 497*22c6ae69SDarkWyrm BView *view=new BView(r,"drawview",0,0); 498*22c6ae69SDarkWyrm 499*22c6ae69SDarkWyrm scaled->Lock(); 500*22c6ae69SDarkWyrm scaled->AddChild(view); 501*22c6ae69SDarkWyrm view->DrawBitmap(fBitmap,fBitmap->Bounds(),scaled->Bounds()); 502*22c6ae69SDarkWyrm scaled->Unlock(); 503*22c6ae69SDarkWyrm 504*22c6ae69SDarkWyrm delete fBitmap; 505*22c6ae69SDarkWyrm fBitmap=new BBitmap(scaled,false); 506*22c6ae69SDarkWyrm } 507*22c6ae69SDarkWyrm 508*22c6ae69SDarkWyrm bool BitmapView::ClipboardHasBitmap(void) 509*22c6ae69SDarkWyrm { 510*22c6ae69SDarkWyrm BMessage *clip=NULL,flattened; 511*22c6ae69SDarkWyrm uint8 clipval=CLIP_NONE; 512*22c6ae69SDarkWyrm bool returnval; 513*22c6ae69SDarkWyrm 514*22c6ae69SDarkWyrm if(be_clipboard->Lock()) 515*22c6ae69SDarkWyrm { 516*22c6ae69SDarkWyrm clip=be_clipboard->Data(); 517*22c6ae69SDarkWyrm if(!clip->IsEmpty()) 518*22c6ae69SDarkWyrm { 519*22c6ae69SDarkWyrm returnval=(clip->FindMessage("image/bitmap",&flattened)==B_OK); 520*22c6ae69SDarkWyrm if(returnval) 521*22c6ae69SDarkWyrm clipval=CLIP_BEOS; 522*22c6ae69SDarkWyrm else 523*22c6ae69SDarkWyrm { 524*22c6ae69SDarkWyrm BString string; 525*22c6ae69SDarkWyrm returnval=(clip->FindString("class",&string)==B_OK && string=="BBitmap"); 526*22c6ae69SDarkWyrm 527*22c6ae69SDarkWyrm // Try method Gobe Productive uses if that, too, didn't work 528*22c6ae69SDarkWyrm if(returnval) 529*22c6ae69SDarkWyrm clipval=CLIP_SHOWIMAGE; 530*22c6ae69SDarkWyrm else 531*22c6ae69SDarkWyrm { 532*22c6ae69SDarkWyrm returnval=(clip->FindMessage("image/x-vnd.Be-bitmap",&flattened)==B_OK); 533*22c6ae69SDarkWyrm if(returnval) 534*22c6ae69SDarkWyrm clipval=CLIP_SHOWIMAGE; 535*22c6ae69SDarkWyrm else 536*22c6ae69SDarkWyrm clipval=CLIP_NONE; 537*22c6ae69SDarkWyrm } 538*22c6ae69SDarkWyrm } 539*22c6ae69SDarkWyrm } 540*22c6ae69SDarkWyrm be_clipboard->Unlock(); 541*22c6ae69SDarkWyrm } 542*22c6ae69SDarkWyrm return (clipval!=CLIP_NONE)?true:false; 543*22c6ae69SDarkWyrm } 544*22c6ae69SDarkWyrm 545*22c6ae69SDarkWyrm BBitmap *BitmapView::BitmapFromClipboard(void) 546*22c6ae69SDarkWyrm { 547*22c6ae69SDarkWyrm BMessage *clip=NULL,flattened; 548*22c6ae69SDarkWyrm BBitmap *bitmap; 549*22c6ae69SDarkWyrm 550*22c6ae69SDarkWyrm if(!be_clipboard->Lock()) 551*22c6ae69SDarkWyrm return NULL; 552*22c6ae69SDarkWyrm 553*22c6ae69SDarkWyrm clip=be_clipboard->Data(); 554*22c6ae69SDarkWyrm if(!clip) 555*22c6ae69SDarkWyrm return NULL; 556*22c6ae69SDarkWyrm 557*22c6ae69SDarkWyrm uint8 clipval=CLIP_NONE; 558*22c6ae69SDarkWyrm 559*22c6ae69SDarkWyrm // Try ArtPaint-style storage 560*22c6ae69SDarkWyrm status_t status=clip->FindMessage("image/bitmap",&flattened); 561*22c6ae69SDarkWyrm 562*22c6ae69SDarkWyrm // If that didn't work, try ShowImage-style 563*22c6ae69SDarkWyrm if(status!=B_OK) 564*22c6ae69SDarkWyrm { 565*22c6ae69SDarkWyrm BString string; 566*22c6ae69SDarkWyrm status=clip->FindString("class",&string); 567*22c6ae69SDarkWyrm 568*22c6ae69SDarkWyrm // Try method Gobe Productive uses if that, too, didn't work 569*22c6ae69SDarkWyrm if(status==B_OK && string=="BBitmap") 570*22c6ae69SDarkWyrm clipval=CLIP_SHOWIMAGE; 571*22c6ae69SDarkWyrm else 572*22c6ae69SDarkWyrm { 573*22c6ae69SDarkWyrm status=clip->FindMessage("image/x-vnd.Be-bitmap",&flattened); 574*22c6ae69SDarkWyrm if(status==B_OK) 575*22c6ae69SDarkWyrm clipval=CLIP_PRODUCTIVE; 576*22c6ae69SDarkWyrm else 577*22c6ae69SDarkWyrm clipval=CLIP_NONE; 578*22c6ae69SDarkWyrm } 579*22c6ae69SDarkWyrm } 580*22c6ae69SDarkWyrm else 581*22c6ae69SDarkWyrm clipval=CLIP_BEOS; 582*22c6ae69SDarkWyrm 583*22c6ae69SDarkWyrm be_clipboard->Unlock(); 584*22c6ae69SDarkWyrm 585*22c6ae69SDarkWyrm switch(clipval) 586*22c6ae69SDarkWyrm { 587*22c6ae69SDarkWyrm case CLIP_SHOWIMAGE: 588*22c6ae69SDarkWyrm { 589*22c6ae69SDarkWyrm // Showimage does it a slightly different way -- it dumps the BBitmap 590*22c6ae69SDarkWyrm // data directly to the clipboard message instead of packaging it in 591*22c6ae69SDarkWyrm // a bitmap like everyone else. 592*22c6ae69SDarkWyrm 593*22c6ae69SDarkWyrm if(!be_clipboard->Lock()) 594*22c6ae69SDarkWyrm return NULL; 595*22c6ae69SDarkWyrm 596*22c6ae69SDarkWyrm BMessage datamsg(*be_clipboard->Data()); 597*22c6ae69SDarkWyrm 598*22c6ae69SDarkWyrm be_clipboard->Unlock(); 599*22c6ae69SDarkWyrm 600*22c6ae69SDarkWyrm const void *buffer; 601*22c6ae69SDarkWyrm int32 bufferLength; 602*22c6ae69SDarkWyrm 603*22c6ae69SDarkWyrm BRect frame; 604*22c6ae69SDarkWyrm color_space cspace=B_NO_COLOR_SPACE; 605*22c6ae69SDarkWyrm 606*22c6ae69SDarkWyrm status=datamsg.FindRect("_frame",&frame); 607*22c6ae69SDarkWyrm if(status!=B_OK) 608*22c6ae69SDarkWyrm return NULL; 609*22c6ae69SDarkWyrm 610*22c6ae69SDarkWyrm status=datamsg.FindInt32("_cspace",(int32)cspace); 611*22c6ae69SDarkWyrm if(status!=B_OK) 612*22c6ae69SDarkWyrm return NULL; 613*22c6ae69SDarkWyrm cspace=B_RGBA32; 614*22c6ae69SDarkWyrm bitmap=new BBitmap(frame,cspace,true); 615*22c6ae69SDarkWyrm 616*22c6ae69SDarkWyrm status=datamsg.FindData("_data",B_RAW_TYPE,(const void **)&buffer, &bufferLength); 617*22c6ae69SDarkWyrm if(status!=B_OK) 618*22c6ae69SDarkWyrm { 619*22c6ae69SDarkWyrm delete bitmap; 620*22c6ae69SDarkWyrm return NULL; 621*22c6ae69SDarkWyrm } 622*22c6ae69SDarkWyrm 623*22c6ae69SDarkWyrm memcpy(bitmap->Bits(), buffer, bufferLength); 624*22c6ae69SDarkWyrm 625*22c6ae69SDarkWyrm return bitmap; 626*22c6ae69SDarkWyrm } 627*22c6ae69SDarkWyrm case CLIP_PRODUCTIVE: 628*22c6ae69SDarkWyrm // Productive doesn't name the packaged BBitmap data message the same, but 629*22c6ae69SDarkWyrm // uses exactly the same data format. 630*22c6ae69SDarkWyrm 631*22c6ae69SDarkWyrm case CLIP_BEOS: 632*22c6ae69SDarkWyrm { 633*22c6ae69SDarkWyrm const void *buffer; 634*22c6ae69SDarkWyrm int32 bufferLength; 635*22c6ae69SDarkWyrm 636*22c6ae69SDarkWyrm BRect frame; 637*22c6ae69SDarkWyrm color_space cspace=B_NO_COLOR_SPACE; 638*22c6ae69SDarkWyrm 639*22c6ae69SDarkWyrm status=flattened.FindRect("_frame",&frame); 640*22c6ae69SDarkWyrm if(status!=B_OK) 641*22c6ae69SDarkWyrm return NULL; 642*22c6ae69SDarkWyrm 643*22c6ae69SDarkWyrm status=flattened.FindInt32("_cspace",(int32)cspace); 644*22c6ae69SDarkWyrm if(status!=B_OK) 645*22c6ae69SDarkWyrm return NULL; 646*22c6ae69SDarkWyrm cspace=B_RGBA32; 647*22c6ae69SDarkWyrm bitmap=new BBitmap(frame,cspace,true); 648*22c6ae69SDarkWyrm 649*22c6ae69SDarkWyrm status=flattened.FindData("_data",B_RAW_TYPE,(const void **)&buffer, &bufferLength); 650*22c6ae69SDarkWyrm if(status!=B_OK) 651*22c6ae69SDarkWyrm { 652*22c6ae69SDarkWyrm delete bitmap; 653*22c6ae69SDarkWyrm return NULL; 654*22c6ae69SDarkWyrm } 655*22c6ae69SDarkWyrm 656*22c6ae69SDarkWyrm memcpy(bitmap->Bits(), buffer, bufferLength); 657*22c6ae69SDarkWyrm 658*22c6ae69SDarkWyrm return bitmap; 659*22c6ae69SDarkWyrm } 660*22c6ae69SDarkWyrm default: 661*22c6ae69SDarkWyrm return NULL; 662*22c6ae69SDarkWyrm } 663*22c6ae69SDarkWyrm 664*22c6ae69SDarkWyrm // shut the compiler up 665*22c6ae69SDarkWyrm return NULL; 666*22c6ae69SDarkWyrm } 667*22c6ae69SDarkWyrm 668*22c6ae69SDarkWyrm BRect ScaleRectToFit(const BRect &from, const BRect &to) 669*22c6ae69SDarkWyrm { 670*22c6ae69SDarkWyrm // Dynamic sizing algorithm 671*22c6ae69SDarkWyrm // 1) Check to see if either dimension is bigger than the view's display area 672*22c6ae69SDarkWyrm // 2) If smaller along both axes, make bitmap rect centered and return 673*22c6ae69SDarkWyrm // 3) Check to see if scaling is to be horizontal or vertical on basis of longer axis 674*22c6ae69SDarkWyrm // 4) Calculate scaling factor 675*22c6ae69SDarkWyrm // 5) Scale both axes down by scaling factor, accounting for border width 676*22c6ae69SDarkWyrm // 6) Center the rectangle in the direction of the smaller axis 677*22c6ae69SDarkWyrm 678*22c6ae69SDarkWyrm if(!to.IsValid()) 679*22c6ae69SDarkWyrm return from; 680*22c6ae69SDarkWyrm if(!from.IsValid()) 681*22c6ae69SDarkWyrm return to; 682*22c6ae69SDarkWyrm 683*22c6ae69SDarkWyrm BRect r(to); 684*22c6ae69SDarkWyrm 685*22c6ae69SDarkWyrm if( (from.Width()<=r.Width()) && 686*22c6ae69SDarkWyrm (from.Height()<=r.Height()) ) 687*22c6ae69SDarkWyrm { 688*22c6ae69SDarkWyrm // Smaller than view, so just center and return 689*22c6ae69SDarkWyrm r=from; 690*22c6ae69SDarkWyrm r.OffsetBy( (to.Width()-r.Width())/2, (to.Height()-r.Height())/2 ); 691*22c6ae69SDarkWyrm return r; 692*22c6ae69SDarkWyrm } 693*22c6ae69SDarkWyrm 694*22c6ae69SDarkWyrm float multiplier=from.Width()/from.Height(); 695*22c6ae69SDarkWyrm if(multiplier>1) 696*22c6ae69SDarkWyrm { 697*22c6ae69SDarkWyrm // Landscape orientation 698*22c6ae69SDarkWyrm 699*22c6ae69SDarkWyrm // Scale rectangle to bounds width and center height 700*22c6ae69SDarkWyrm r.bottom=r.top+(r.Width()/multiplier); 701*22c6ae69SDarkWyrm 702*22c6ae69SDarkWyrm r.OffsetBy(0,(to.Height() - r.Height())/2); 703*22c6ae69SDarkWyrm } 704*22c6ae69SDarkWyrm else 705*22c6ae69SDarkWyrm { 706*22c6ae69SDarkWyrm // Portrait orientation 707*22c6ae69SDarkWyrm 708*22c6ae69SDarkWyrm // Scale rectangle to bounds height and center width 709*22c6ae69SDarkWyrm r.right=r.left+(r.Height()*multiplier); 710*22c6ae69SDarkWyrm 711*22c6ae69SDarkWyrm r.OffsetBy((to.Width() - r.Width())/2,0); 712*22c6ae69SDarkWyrm } 713*22c6ae69SDarkWyrm return r; 714*22c6ae69SDarkWyrm } 715*22c6ae69SDarkWyrm 716*22c6ae69SDarkWyrm void BitmapView::RemoveBitmap(void) 717*22c6ae69SDarkWyrm { 718*22c6ae69SDarkWyrm SetBitmap(NULL); 719*22c6ae69SDarkWyrm } 720*22c6ae69SDarkWyrm 721*22c6ae69SDarkWyrm void BitmapView::PasteBitmap(void) 722*22c6ae69SDarkWyrm { 723*22c6ae69SDarkWyrm BBitmap *bmp=BitmapFromClipboard(); 724*22c6ae69SDarkWyrm if(bmp) 725*22c6ae69SDarkWyrm SetBitmap(bmp); 726*22c6ae69SDarkWyrm 727*22c6ae69SDarkWyrm if(fConstrainDrops) 728*22c6ae69SDarkWyrm ConstrainBitmap(); 729*22c6ae69SDarkWyrm } 730