122c6ae69SDarkWyrm #include "BitmapView.h" 209a03cb8SDarkWyrm #include <Alert.h> 309a03cb8SDarkWyrm #include <BitmapStream.h> 409a03cb8SDarkWyrm #include <Clipboard.h> 509a03cb8SDarkWyrm #include <Font.h> 609a03cb8SDarkWyrm #include <MenuItem.h> 722c6ae69SDarkWyrm #include <Entry.h> 822c6ae69SDarkWyrm #include <TranslationUtils.h> 922c6ae69SDarkWyrm #include <TranslatorRoster.h> 1022c6ae69SDarkWyrm #include <TranslatorFormats.h> 1122c6ae69SDarkWyrm 1222c6ae69SDarkWyrm // TODO: Add support for labels 1322c6ae69SDarkWyrm 1422c6ae69SDarkWyrm #define M_REMOVE_IMAGE 'mrmi' 1522c6ae69SDarkWyrm #define M_PASTE_IMAGE 'mpsi' 1622c6ae69SDarkWyrm 1722c6ae69SDarkWyrm enum 1822c6ae69SDarkWyrm { 1922c6ae69SDarkWyrm CLIP_NONE = 0, 2022c6ae69SDarkWyrm CLIP_BEOS = 1, 2122c6ae69SDarkWyrm CLIP_SHOWIMAGE = 2, 2222c6ae69SDarkWyrm CLIP_PRODUCTIVE = 3 2322c6ae69SDarkWyrm }; 2422c6ae69SDarkWyrm 2509a03cb8SDarkWyrm 2622c6ae69SDarkWyrm inline void SetRGBColor(rgb_color *col, uint8 r, uint8 g, uint8 b, uint8 a = 255); 2722c6ae69SDarkWyrm 2809a03cb8SDarkWyrm 2909a03cb8SDarkWyrm void 3009a03cb8SDarkWyrm SetRGBColor(rgb_color *col, uint8 r, uint8 g, uint8 b, uint8 a) 3122c6ae69SDarkWyrm { 3209a03cb8SDarkWyrm if (col) { 3322c6ae69SDarkWyrm col->red = r; 3422c6ae69SDarkWyrm col->green = g; 3522c6ae69SDarkWyrm col->blue = b; 3622c6ae69SDarkWyrm col->alpha = a; 3722c6ae69SDarkWyrm } 3822c6ae69SDarkWyrm } 3922c6ae69SDarkWyrm 4009a03cb8SDarkWyrm 4122c6ae69SDarkWyrm BitmapView::BitmapView(BRect frame, const char *name, BMessage *mod, BBitmap *bitmap, 4222c6ae69SDarkWyrm const char *label, border_style borderstyle, int32 resize, int32 flags) 4322c6ae69SDarkWyrm : BView(frame, name, resize, flags) 4422c6ae69SDarkWyrm { 4522c6ae69SDarkWyrm SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 4622c6ae69SDarkWyrm 4722c6ae69SDarkWyrm if (bitmap && bitmap->IsValid()) 4822c6ae69SDarkWyrm fBitmap = bitmap; 4922c6ae69SDarkWyrm else 5022c6ae69SDarkWyrm fBitmap = NULL; 5122c6ae69SDarkWyrm 5222c6ae69SDarkWyrm if (mod) 5322c6ae69SDarkWyrm SetMessage(mod); 5422c6ae69SDarkWyrm 5522c6ae69SDarkWyrm fLabel = label; 5622c6ae69SDarkWyrm fBorderStyle = borderstyle; 5722c6ae69SDarkWyrm fFixedSize = false; 5822c6ae69SDarkWyrm fEnabled = true; 5922c6ae69SDarkWyrm fRemovableBitmap = false; 6022c6ae69SDarkWyrm fAcceptDrops = true; 6122c6ae69SDarkWyrm fAcceptPaste = true; 6222c6ae69SDarkWyrm fConstrainDrops = true; 6322c6ae69SDarkWyrm fMaxWidth = 100; 6422c6ae69SDarkWyrm fMaxHeight = 100; 6522c6ae69SDarkWyrm 6622c6ae69SDarkWyrm fPopUpMenu = new BPopUpMenu("deletepopup", false, false); 6722c6ae69SDarkWyrm fPopUpMenu->AddItem(new BMenuItem("Close This Menu", new BMessage(B_CANCEL))); 6822c6ae69SDarkWyrm fPopUpMenu->AddSeparatorItem(); 6922c6ae69SDarkWyrm 7022c6ae69SDarkWyrm fPasteItem = new BMenuItem("Paste Photo from Clipboard", new BMessage(M_PASTE_IMAGE)); 7122c6ae69SDarkWyrm fPopUpMenu->AddItem(fPasteItem); 7222c6ae69SDarkWyrm 7322c6ae69SDarkWyrm fPopUpMenu->AddSeparatorItem(); 7422c6ae69SDarkWyrm 7522c6ae69SDarkWyrm fRemoveItem = new BMenuItem("Remove Photo", new BMessage(M_REMOVE_IMAGE)); 7622c6ae69SDarkWyrm fPopUpMenu->AddItem(fRemoveItem); 7722c6ae69SDarkWyrm 7822c6ae69SDarkWyrm CalculateBitmapRect(); 7922c6ae69SDarkWyrm 8022c6ae69SDarkWyrm // Calculate the offsets for each of the words -- the phrase will be center justified 8122c6ae69SDarkWyrm fNoPhotoWidths[0] = StringWidth("Drop"); 8222c6ae69SDarkWyrm fNoPhotoWidths[1] = StringWidth("a"); 8322c6ae69SDarkWyrm fNoPhotoWidths[2] = StringWidth("Photo"); 8422c6ae69SDarkWyrm fNoPhotoWidths[3] = StringWidth("Here"); 8522c6ae69SDarkWyrm 8622c6ae69SDarkWyrm font_height fh; 8722c6ae69SDarkWyrm GetFontHeight(&fh); 8822c6ae69SDarkWyrm float totalheight = fh.ascent + fh.descent + fh.leading; 8922c6ae69SDarkWyrm float yoffset = (Bounds().Height() - 10 - (totalheight * 4)) / 2; 9022c6ae69SDarkWyrm fNoPhotoOffsets[0].Set((Bounds().Width() - fNoPhotoWidths[0]) / 2, totalheight + yoffset); 9109a03cb8SDarkWyrm fNoPhotoOffsets[1].Set((Bounds().Width() - fNoPhotoWidths[1]) / 2, 9209a03cb8SDarkWyrm fNoPhotoOffsets[0].y + totalheight); 9309a03cb8SDarkWyrm fNoPhotoOffsets[2].Set((Bounds().Width() - fNoPhotoWidths[2]) / 2, 9409a03cb8SDarkWyrm fNoPhotoOffsets[1].y + totalheight); 9509a03cb8SDarkWyrm fNoPhotoOffsets[3].Set((Bounds().Width() - fNoPhotoWidths[3]) / 2, 9609a03cb8SDarkWyrm fNoPhotoOffsets[2].y + totalheight); 9722c6ae69SDarkWyrm } 9822c6ae69SDarkWyrm 9909a03cb8SDarkWyrm 10022c6ae69SDarkWyrm BitmapView::~BitmapView(void) 10122c6ae69SDarkWyrm { 10222c6ae69SDarkWyrm delete fPopUpMenu; 10322c6ae69SDarkWyrm } 10422c6ae69SDarkWyrm 10509a03cb8SDarkWyrm 10609a03cb8SDarkWyrm void 10709a03cb8SDarkWyrm BitmapView::AttachedToWindow(void) 10822c6ae69SDarkWyrm { 10922c6ae69SDarkWyrm SetTarget((BHandler*)Window()); 11022c6ae69SDarkWyrm fPopUpMenu->SetTargetForItems(this); 11122c6ae69SDarkWyrm } 11222c6ae69SDarkWyrm 11309a03cb8SDarkWyrm 11409a03cb8SDarkWyrm void 11509a03cb8SDarkWyrm BitmapView::SetBitmap(BBitmap *bitmap) 11622c6ae69SDarkWyrm { 11709a03cb8SDarkWyrm if (bitmap && bitmap->IsValid()) { 11822c6ae69SDarkWyrm if (fBitmap == bitmap) 11922c6ae69SDarkWyrm return; 12022c6ae69SDarkWyrm fBitmap = bitmap; 12109a03cb8SDarkWyrm } else { 12209a03cb8SDarkWyrm if (!fBitmap) 12322c6ae69SDarkWyrm return; 12422c6ae69SDarkWyrm fBitmap = NULL; 12522c6ae69SDarkWyrm } 12622c6ae69SDarkWyrm 12722c6ae69SDarkWyrm CalculateBitmapRect(); 12822c6ae69SDarkWyrm if (!IsHidden()) 12922c6ae69SDarkWyrm Invalidate(); 13022c6ae69SDarkWyrm } 13122c6ae69SDarkWyrm 13209a03cb8SDarkWyrm 13309a03cb8SDarkWyrm void 13409a03cb8SDarkWyrm BitmapView::SetEnabled(bool value) 13522c6ae69SDarkWyrm { 13609a03cb8SDarkWyrm if (fEnabled != value) { 13722c6ae69SDarkWyrm fEnabled = value; 13822c6ae69SDarkWyrm Invalidate(); 13922c6ae69SDarkWyrm } 14022c6ae69SDarkWyrm } 14122c6ae69SDarkWyrm 14209a03cb8SDarkWyrm 14322c6ae69SDarkWyrm /* 14409a03cb8SDarkWyrm void 14509a03cb8SDarkWyrm BitmapView::SetLabel(const char *label) 14622c6ae69SDarkWyrm { 14709a03cb8SDarkWyrm if (fLabel.Compare(label) != 0) { 14822c6ae69SDarkWyrm fLabel = label; 14922c6ae69SDarkWyrm 15022c6ae69SDarkWyrm CalculateBitmapRect(); 15122c6ae69SDarkWyrm if (!IsHidden()) 15222c6ae69SDarkWyrm Invalidate(); 15322c6ae69SDarkWyrm } 15422c6ae69SDarkWyrm } 15522c6ae69SDarkWyrm */ 15622c6ae69SDarkWyrm 15709a03cb8SDarkWyrm 15809a03cb8SDarkWyrm void 15909a03cb8SDarkWyrm BitmapView::SetStyle(border_style style) 16022c6ae69SDarkWyrm { 16109a03cb8SDarkWyrm if (fBorderStyle != style) { 16222c6ae69SDarkWyrm fBorderStyle = style; 16322c6ae69SDarkWyrm 16422c6ae69SDarkWyrm CalculateBitmapRect(); 16522c6ae69SDarkWyrm if (!IsHidden()) 16622c6ae69SDarkWyrm Invalidate(); 16722c6ae69SDarkWyrm } 16822c6ae69SDarkWyrm } 16922c6ae69SDarkWyrm 17009a03cb8SDarkWyrm 17109a03cb8SDarkWyrm void 17209a03cb8SDarkWyrm BitmapView::SetFixedSize(bool isfixed) 17322c6ae69SDarkWyrm { 17409a03cb8SDarkWyrm if (fFixedSize != isfixed) { 17522c6ae69SDarkWyrm fFixedSize = isfixed; 17622c6ae69SDarkWyrm 17722c6ae69SDarkWyrm CalculateBitmapRect(); 17822c6ae69SDarkWyrm if (!IsHidden()) 17922c6ae69SDarkWyrm Invalidate(); 18022c6ae69SDarkWyrm } 18122c6ae69SDarkWyrm } 18222c6ae69SDarkWyrm 18309a03cb8SDarkWyrm 18409a03cb8SDarkWyrm void 18509a03cb8SDarkWyrm BitmapView::MessageReceived(BMessage *msg) 18622c6ae69SDarkWyrm { 18709a03cb8SDarkWyrm if (msg->WasDropped() && AcceptsDrops()) { 18822c6ae69SDarkWyrm // We'll handle two types of drops: those from Tracker and those from ShowImage 18909a03cb8SDarkWyrm if (msg->what == B_SIMPLE_DATA) { 19022c6ae69SDarkWyrm int32 actions; 19109a03cb8SDarkWyrm if (msg->FindInt32("be:actions", &actions) == B_OK) { 19222c6ae69SDarkWyrm // ShowImage drop. This is a negotiated drag&drop, so send a reply 19322c6ae69SDarkWyrm BMessage reply(B_COPY_TARGET), response; 19422c6ae69SDarkWyrm reply.AddString("be:types", "image/jpeg"); 19522c6ae69SDarkWyrm reply.AddString("be:types", "image/png"); 19622c6ae69SDarkWyrm 19722c6ae69SDarkWyrm msg->SendReply(&reply, &response); 19822c6ae69SDarkWyrm 19922c6ae69SDarkWyrm // now, we've gotten the response 20009a03cb8SDarkWyrm if (response.what == B_MIME_DATA) { 20122c6ae69SDarkWyrm // Obtain and translate the received data 20222c6ae69SDarkWyrm uint8 *imagedata; 20322c6ae69SDarkWyrm ssize_t datasize; 20422c6ae69SDarkWyrm 20522c6ae69SDarkWyrm // Try JPEG first 20609a03cb8SDarkWyrm if (response.FindData("image/jpeg", B_MIME_DATA, 20709a03cb8SDarkWyrm (const void **)&imagedata, &datasize) != B_OK) { 20822c6ae69SDarkWyrm // Try PNG next and piddle out if unsuccessful 20909a03cb8SDarkWyrm if (response.FindData("image/png", B_PNG_FORMAT, 21009a03cb8SDarkWyrm (const void **)&imagedata, &datasize) != B_OK) 21122c6ae69SDarkWyrm return; 21222c6ae69SDarkWyrm } 21322c6ae69SDarkWyrm 21422c6ae69SDarkWyrm // Set up to decode into memory 21522c6ae69SDarkWyrm BMemoryIO memio(imagedata, datasize); 21622c6ae69SDarkWyrm BTranslatorRoster *roster = BTranslatorRoster::Default(); 21722c6ae69SDarkWyrm BBitmapStream bstream; 21822c6ae69SDarkWyrm 21922c6ae69SDarkWyrm if (roster->Translate(&memio, NULL, NULL, &bstream, B_TRANSLATOR_BITMAP) == B_OK) 22022c6ae69SDarkWyrm { 22122c6ae69SDarkWyrm BBitmap *bmp; 22222c6ae69SDarkWyrm if (bstream.DetachBitmap(&bmp) != B_OK) 22322c6ae69SDarkWyrm return; 22422c6ae69SDarkWyrm SetBitmap(bmp); 22522c6ae69SDarkWyrm 22622c6ae69SDarkWyrm if (fConstrainDrops) 22722c6ae69SDarkWyrm ConstrainBitmap(); 22822c6ae69SDarkWyrm Invoke(); 22922c6ae69SDarkWyrm } 23022c6ae69SDarkWyrm } 23122c6ae69SDarkWyrm return; 23222c6ae69SDarkWyrm } 23322c6ae69SDarkWyrm 23422c6ae69SDarkWyrm entry_ref ref; 23509a03cb8SDarkWyrm if (msg->FindRef("refs", &ref) == B_OK) { 23622c6ae69SDarkWyrm // Tracker drop 23722c6ae69SDarkWyrm BBitmap *bmp = BTranslationUtils::GetBitmap(&ref); 23809a03cb8SDarkWyrm if (bmp) { 23922c6ae69SDarkWyrm SetBitmap(bmp); 24022c6ae69SDarkWyrm 24122c6ae69SDarkWyrm if (fConstrainDrops) 24222c6ae69SDarkWyrm ConstrainBitmap(); 24322c6ae69SDarkWyrm Invoke(); 24422c6ae69SDarkWyrm } 24522c6ae69SDarkWyrm } 24622c6ae69SDarkWyrm } 24722c6ae69SDarkWyrm return; 24822c6ae69SDarkWyrm } 24922c6ae69SDarkWyrm 25022c6ae69SDarkWyrm switch (msg->what) 25122c6ae69SDarkWyrm { 25209a03cb8SDarkWyrm case M_REMOVE_IMAGE: { 253*4d99b24dSHumdinger BAlert *alert = new BAlert("ResEdit", "This cannot be undone. " 254aed35104SHumdinger "Remove the image?", "Remove", "Cancel"); 255aed35104SHumdinger alert->SetShortcut(1, B_ESCAPE); 25622c6ae69SDarkWyrm int32 value = alert->Go(); 25709a03cb8SDarkWyrm if (value == 0) { 25822c6ae69SDarkWyrm SetBitmap(NULL); 25922c6ae69SDarkWyrm 26009a03cb8SDarkWyrm if (Target()) { 26122c6ae69SDarkWyrm BMessenger msgr(Target()); 26222c6ae69SDarkWyrm 26322c6ae69SDarkWyrm msgr.SendMessage(new BMessage(M_BITMAP_REMOVED)); 26422c6ae69SDarkWyrm return; 26522c6ae69SDarkWyrm } 26622c6ae69SDarkWyrm } 26722c6ae69SDarkWyrm } 26822c6ae69SDarkWyrm case M_PASTE_IMAGE: 26922c6ae69SDarkWyrm { 27022c6ae69SDarkWyrm PasteBitmap(); 27122c6ae69SDarkWyrm Invoke(); 27222c6ae69SDarkWyrm } 27322c6ae69SDarkWyrm } 27422c6ae69SDarkWyrm BView::MessageReceived(msg); 27522c6ae69SDarkWyrm } 27622c6ae69SDarkWyrm 27709a03cb8SDarkWyrm 27809a03cb8SDarkWyrm void 27909a03cb8SDarkWyrm BitmapView::Draw(BRect rect) 28022c6ae69SDarkWyrm { 28122c6ae69SDarkWyrm if (fBitmap) 28222c6ae69SDarkWyrm DrawBitmap(fBitmap, fBitmap->Bounds(), fBitmapRect); 28309a03cb8SDarkWyrm else { 28422c6ae69SDarkWyrm SetHighColor(0, 0, 0, 80); 28522c6ae69SDarkWyrm SetDrawingMode(B_OP_ALPHA); 28622c6ae69SDarkWyrm DrawString("Drop", fNoPhotoOffsets[0]); 28722c6ae69SDarkWyrm DrawString("a", fNoPhotoOffsets[1]); 28822c6ae69SDarkWyrm DrawString("Photo", fNoPhotoOffsets[2]); 28922c6ae69SDarkWyrm DrawString("Here", fNoPhotoOffsets[3]); 29022c6ae69SDarkWyrm SetDrawingMode(B_OP_COPY); 29122c6ae69SDarkWyrm } 29222c6ae69SDarkWyrm 29309a03cb8SDarkWyrm if (fBorderStyle == B_FANCY_BORDER) { 29422c6ae69SDarkWyrm rgb_color base= { 216, 216, 216, 255 }; 29522c6ae69SDarkWyrm rgb_color work; 29622c6ae69SDarkWyrm 29722c6ae69SDarkWyrm SetHighColor(base); 29822c6ae69SDarkWyrm StrokeRect(Bounds().InsetByCopy(2, 2)); 29922c6ae69SDarkWyrm 30022c6ae69SDarkWyrm BeginLineArray(12); 30122c6ae69SDarkWyrm 30222c6ae69SDarkWyrm BRect r(Bounds()); 30322c6ae69SDarkWyrm 30422c6ae69SDarkWyrm work = tint_color(base, B_DARKEN_2_TINT); 30522c6ae69SDarkWyrm AddLine(r.LeftTop(), r.RightTop(), work); 30622c6ae69SDarkWyrm AddLine(r.LeftTop(), r.LeftBottom(), work); 30722c6ae69SDarkWyrm r.left++; 30822c6ae69SDarkWyrm 30922c6ae69SDarkWyrm work = tint_color(base, B_DARKEN_4_TINT); 31022c6ae69SDarkWyrm AddLine(r.RightTop(), r.RightBottom(), work); 31122c6ae69SDarkWyrm AddLine(r.LeftBottom(), r.RightBottom(), work); 31222c6ae69SDarkWyrm 31322c6ae69SDarkWyrm r.right--; 31422c6ae69SDarkWyrm r.top++; 31522c6ae69SDarkWyrm r.bottom--; 31622c6ae69SDarkWyrm 31722c6ae69SDarkWyrm 31822c6ae69SDarkWyrm work = tint_color(base, B_LIGHTEN_MAX_TINT); 31922c6ae69SDarkWyrm AddLine(r.LeftTop(), r.RightTop(), work); 32022c6ae69SDarkWyrm AddLine(r.LeftTop(), r.LeftBottom(), work); 32122c6ae69SDarkWyrm r.left++; 32222c6ae69SDarkWyrm 32322c6ae69SDarkWyrm work = tint_color(base, B_DARKEN_3_TINT); 32422c6ae69SDarkWyrm AddLine(r.RightTop(), r.RightBottom(), work); 32522c6ae69SDarkWyrm AddLine(r.LeftBottom(), r.RightBottom(), work); 32622c6ae69SDarkWyrm 32722c6ae69SDarkWyrm // this rect handled by the above StrokeRect, so inset a total of 2 pixels 32822c6ae69SDarkWyrm r.left++; 32922c6ae69SDarkWyrm r.right -= 2; 33022c6ae69SDarkWyrm r.top += 2; 33122c6ae69SDarkWyrm r.bottom -= 2; 33222c6ae69SDarkWyrm 33322c6ae69SDarkWyrm 33422c6ae69SDarkWyrm work = tint_color(base, B_DARKEN_3_TINT); 33522c6ae69SDarkWyrm AddLine(r.LeftTop(), r.RightTop(), work); 33622c6ae69SDarkWyrm AddLine(r.LeftTop(), r.LeftBottom(), work); 33722c6ae69SDarkWyrm r.left++; 33822c6ae69SDarkWyrm 33922c6ae69SDarkWyrm work = tint_color(base, B_LIGHTEN_MAX_TINT); 34022c6ae69SDarkWyrm AddLine(r.RightTop(), r.RightBottom(), work); 34122c6ae69SDarkWyrm AddLine(r.LeftBottom(), r.RightBottom(), work); 34222c6ae69SDarkWyrm 34322c6ae69SDarkWyrm r.right--; 34422c6ae69SDarkWyrm r.top++; 34522c6ae69SDarkWyrm r.bottom--; 34622c6ae69SDarkWyrm EndLineArray(); 34722c6ae69SDarkWyrm 34822c6ae69SDarkWyrm SetHighColor(tint_color(base, B_DARKEN_2_TINT)); 34922c6ae69SDarkWyrm StrokeRect(r); 35009a03cb8SDarkWyrm } else { 35122c6ae69SDarkWyrm // Plain border 35222c6ae69SDarkWyrm SetHighColor(0, 0, 0); 35322c6ae69SDarkWyrm StrokeRect(fBitmapRect); 35422c6ae69SDarkWyrm } 35522c6ae69SDarkWyrm } 35622c6ae69SDarkWyrm 35709a03cb8SDarkWyrm 35809a03cb8SDarkWyrm void 35909a03cb8SDarkWyrm BitmapView::MouseDown(BPoint pt) 36022c6ae69SDarkWyrm { 36122c6ae69SDarkWyrm BPoint mousept; 36222c6ae69SDarkWyrm uint32 buttons; 36322c6ae69SDarkWyrm 36422c6ae69SDarkWyrm GetMouse(&mousept, &buttons); 36509a03cb8SDarkWyrm if (buttons & B_SECONDARY_MOUSE_BUTTON) { 36622c6ae69SDarkWyrm ConvertToScreen(&mousept); 36722c6ae69SDarkWyrm 36822c6ae69SDarkWyrm mousept.x= (mousept.x>5) ? mousept.x-5 : 0; 36922c6ae69SDarkWyrm mousept.y= (mousept.y>5) ? mousept.y-5 : 0; 37022c6ae69SDarkWyrm 37122c6ae69SDarkWyrm if (AcceptsPaste() && ClipboardHasBitmap()) 37222c6ae69SDarkWyrm fPasteItem->SetEnabled(true); 37322c6ae69SDarkWyrm else 37422c6ae69SDarkWyrm fPasteItem->SetEnabled(false); 37522c6ae69SDarkWyrm 37622c6ae69SDarkWyrm if (fRemovableBitmap && fBitmap) 37722c6ae69SDarkWyrm fRemoveItem->SetEnabled(true); 37822c6ae69SDarkWyrm else 37922c6ae69SDarkWyrm fRemoveItem->SetEnabled(false); 38022c6ae69SDarkWyrm 38122c6ae69SDarkWyrm fPopUpMenu->Go(mousept, true, true, true); 38222c6ae69SDarkWyrm } 38322c6ae69SDarkWyrm } 38422c6ae69SDarkWyrm 38509a03cb8SDarkWyrm 38609a03cb8SDarkWyrm void 38709a03cb8SDarkWyrm BitmapView::FrameResized(float w, float h) 38822c6ae69SDarkWyrm { 38922c6ae69SDarkWyrm CalculateBitmapRect(); 39022c6ae69SDarkWyrm } 39122c6ae69SDarkWyrm 39209a03cb8SDarkWyrm 39309a03cb8SDarkWyrm void 39409a03cb8SDarkWyrm BitmapView::CalculateBitmapRect(void) 39522c6ae69SDarkWyrm { 39609a03cb8SDarkWyrm if (!fBitmap || fFixedSize) { 39722c6ae69SDarkWyrm fBitmapRect = Bounds().InsetByCopy(1, 1); 39822c6ae69SDarkWyrm return; 39922c6ae69SDarkWyrm } 40022c6ae69SDarkWyrm 40122c6ae69SDarkWyrm uint8 borderwidth = (fBorderStyle == B_FANCY_BORDER) ? 5 : 1; 40222c6ae69SDarkWyrm 40322c6ae69SDarkWyrm BRect r(Bounds()); 40422c6ae69SDarkWyrm fBitmapRect= ScaleRectToFit(fBitmap->Bounds(), r.InsetByCopy(borderwidth, borderwidth)); 40522c6ae69SDarkWyrm } 40622c6ae69SDarkWyrm 40709a03cb8SDarkWyrm 40809a03cb8SDarkWyrm void 40909a03cb8SDarkWyrm BitmapView::SetAcceptDrops(bool accept) 41022c6ae69SDarkWyrm { 41122c6ae69SDarkWyrm fAcceptDrops = accept; 41222c6ae69SDarkWyrm } 41322c6ae69SDarkWyrm 41409a03cb8SDarkWyrm 41509a03cb8SDarkWyrm void 41609a03cb8SDarkWyrm BitmapView::SetAcceptPaste(bool accept) 41722c6ae69SDarkWyrm { 41822c6ae69SDarkWyrm fAcceptPaste = accept; 41922c6ae69SDarkWyrm } 42022c6ae69SDarkWyrm 42109a03cb8SDarkWyrm 42209a03cb8SDarkWyrm void 42309a03cb8SDarkWyrm BitmapView::SetConstrainDrops(bool value) 42422c6ae69SDarkWyrm { 42522c6ae69SDarkWyrm fConstrainDrops = value; 42622c6ae69SDarkWyrm } 42722c6ae69SDarkWyrm 42809a03cb8SDarkWyrm 42909a03cb8SDarkWyrm void 43009a03cb8SDarkWyrm BitmapView::MaxBitmapSize(float *width, float *height) const 43122c6ae69SDarkWyrm { 43222c6ae69SDarkWyrm *width = fMaxWidth; 43322c6ae69SDarkWyrm *height = fMaxHeight; 43422c6ae69SDarkWyrm } 43522c6ae69SDarkWyrm 43609a03cb8SDarkWyrm 43709a03cb8SDarkWyrm void 43809a03cb8SDarkWyrm BitmapView::SetMaxBitmapSize(const float &width, const float &height) 43922c6ae69SDarkWyrm { 44022c6ae69SDarkWyrm fMaxWidth = width; 44122c6ae69SDarkWyrm fMaxHeight = height; 44222c6ae69SDarkWyrm 44322c6ae69SDarkWyrm ConstrainBitmap(); 44422c6ae69SDarkWyrm } 44522c6ae69SDarkWyrm 44609a03cb8SDarkWyrm 44709a03cb8SDarkWyrm void 44809a03cb8SDarkWyrm BitmapView::SetBitmapRemovable(bool isremovable) 44922c6ae69SDarkWyrm { 45022c6ae69SDarkWyrm fRemovableBitmap = isremovable; 45122c6ae69SDarkWyrm } 45222c6ae69SDarkWyrm 45309a03cb8SDarkWyrm 45409a03cb8SDarkWyrm void 45509a03cb8SDarkWyrm BitmapView::ConstrainBitmap(void) 45622c6ae69SDarkWyrm { 45722c6ae69SDarkWyrm if (!fBitmap || fMaxWidth < 1 || fMaxHeight < 1) 45822c6ae69SDarkWyrm return; 45922c6ae69SDarkWyrm 46022c6ae69SDarkWyrm BRect r = ScaleRectToFit(fBitmap->Bounds(), BRect(0, 0, fMaxWidth - 1, fMaxHeight - 1)); 46122c6ae69SDarkWyrm r.OffsetTo(0, 0); 46222c6ae69SDarkWyrm 46322c6ae69SDarkWyrm BBitmap *scaled = new BBitmap(r, fBitmap->ColorSpace(), true); 46422c6ae69SDarkWyrm BView *view = new BView(r, "drawview", 0, 0); 46522c6ae69SDarkWyrm 46622c6ae69SDarkWyrm scaled->Lock(); 46722c6ae69SDarkWyrm scaled->AddChild(view); 46822c6ae69SDarkWyrm view->DrawBitmap(fBitmap, fBitmap->Bounds(), scaled->Bounds()); 46922c6ae69SDarkWyrm scaled->Unlock(); 47022c6ae69SDarkWyrm 47122c6ae69SDarkWyrm delete fBitmap; 47222c6ae69SDarkWyrm fBitmap = new BBitmap(scaled, false); 47322c6ae69SDarkWyrm } 47422c6ae69SDarkWyrm 47509a03cb8SDarkWyrm 47609a03cb8SDarkWyrm bool 47709a03cb8SDarkWyrm BitmapView::ClipboardHasBitmap(void) 47822c6ae69SDarkWyrm { 47922c6ae69SDarkWyrm BMessage *clip = NULL, flattened; 48022c6ae69SDarkWyrm uint8 clipval = CLIP_NONE; 48122c6ae69SDarkWyrm bool returnval; 48222c6ae69SDarkWyrm 48309a03cb8SDarkWyrm if (be_clipboard->Lock()) { 48422c6ae69SDarkWyrm clip = be_clipboard->Data(); 48509a03cb8SDarkWyrm if (!clip->IsEmpty()) { 48622c6ae69SDarkWyrm returnval = (clip->FindMessage("image/bitmap", &flattened) == B_OK); 48722c6ae69SDarkWyrm if (returnval) 48822c6ae69SDarkWyrm clipval = CLIP_BEOS; 48909a03cb8SDarkWyrm else { 49022c6ae69SDarkWyrm BString string; 49122c6ae69SDarkWyrm returnval = (clip->FindString("class", &string) == B_OK && string == "BBitmap"); 49222c6ae69SDarkWyrm 49322c6ae69SDarkWyrm // Try method Gobe Productive uses if that, too, didn't work 49422c6ae69SDarkWyrm if (returnval) 49522c6ae69SDarkWyrm clipval = CLIP_SHOWIMAGE; 49609a03cb8SDarkWyrm else { 49722c6ae69SDarkWyrm returnval = (clip->FindMessage("image/x-vnd.Be-bitmap", &flattened) == B_OK); 49822c6ae69SDarkWyrm if (returnval) 49922c6ae69SDarkWyrm clipval = CLIP_SHOWIMAGE; 50022c6ae69SDarkWyrm else 50122c6ae69SDarkWyrm clipval = CLIP_NONE; 50222c6ae69SDarkWyrm } 50322c6ae69SDarkWyrm } 50422c6ae69SDarkWyrm } 50522c6ae69SDarkWyrm be_clipboard->Unlock(); 50622c6ae69SDarkWyrm } 50722c6ae69SDarkWyrm return (clipval != CLIP_NONE)?true:false; 50822c6ae69SDarkWyrm } 50922c6ae69SDarkWyrm 51009a03cb8SDarkWyrm 51109a03cb8SDarkWyrm BBitmap * 51209a03cb8SDarkWyrm BitmapView::BitmapFromClipboard(void) 51322c6ae69SDarkWyrm { 51422c6ae69SDarkWyrm BMessage *clip = NULL, flattened; 51522c6ae69SDarkWyrm BBitmap *bitmap; 51622c6ae69SDarkWyrm 51722c6ae69SDarkWyrm if (!be_clipboard->Lock()) 51822c6ae69SDarkWyrm return NULL; 51922c6ae69SDarkWyrm 52022c6ae69SDarkWyrm clip = be_clipboard->Data(); 52122c6ae69SDarkWyrm if (!clip) 52222c6ae69SDarkWyrm return NULL; 52322c6ae69SDarkWyrm 52422c6ae69SDarkWyrm uint8 clipval = CLIP_NONE; 52522c6ae69SDarkWyrm 52622c6ae69SDarkWyrm // Try ArtPaint-style storage 52722c6ae69SDarkWyrm status_t status = clip->FindMessage("image/bitmap", &flattened); 52822c6ae69SDarkWyrm 52922c6ae69SDarkWyrm // If that didn't work, try ShowImage-style 53009a03cb8SDarkWyrm if (status != B_OK) { 53122c6ae69SDarkWyrm BString string; 53222c6ae69SDarkWyrm status = clip->FindString("class", &string); 53322c6ae69SDarkWyrm 53422c6ae69SDarkWyrm // Try method Gobe Productive uses if that, too, didn't work 53522c6ae69SDarkWyrm if (status == B_OK && string == "BBitmap") 53622c6ae69SDarkWyrm clipval = CLIP_SHOWIMAGE; 53709a03cb8SDarkWyrm else { 53822c6ae69SDarkWyrm status = clip->FindMessage("image/x-vnd.Be-bitmap", &flattened); 53922c6ae69SDarkWyrm if (status == B_OK) 54022c6ae69SDarkWyrm clipval = CLIP_PRODUCTIVE; 54122c6ae69SDarkWyrm else 54222c6ae69SDarkWyrm clipval = CLIP_NONE; 54322c6ae69SDarkWyrm } 54422c6ae69SDarkWyrm } 54522c6ae69SDarkWyrm else 54622c6ae69SDarkWyrm clipval = CLIP_BEOS; 54722c6ae69SDarkWyrm 54822c6ae69SDarkWyrm be_clipboard->Unlock(); 54922c6ae69SDarkWyrm 55009a03cb8SDarkWyrm switch (clipval) { 55109a03cb8SDarkWyrm case CLIP_SHOWIMAGE: { 55222c6ae69SDarkWyrm // Showimage does it a slightly different way -- it dumps the BBitmap 55322c6ae69SDarkWyrm // data directly to the clipboard message instead of packaging it in 55422c6ae69SDarkWyrm // a bitmap like everyone else. 55522c6ae69SDarkWyrm 55622c6ae69SDarkWyrm if (!be_clipboard->Lock()) 55722c6ae69SDarkWyrm return NULL; 55822c6ae69SDarkWyrm 55922c6ae69SDarkWyrm BMessage datamsg(*be_clipboard->Data()); 56022c6ae69SDarkWyrm 56122c6ae69SDarkWyrm be_clipboard->Unlock(); 56222c6ae69SDarkWyrm 56322c6ae69SDarkWyrm const void *buffer; 56422c6ae69SDarkWyrm int32 bufferLength; 56522c6ae69SDarkWyrm 56622c6ae69SDarkWyrm BRect frame; 56722c6ae69SDarkWyrm color_space cspace = B_NO_COLOR_SPACE; 56822c6ae69SDarkWyrm 56922c6ae69SDarkWyrm status = datamsg.FindRect("_frame", &frame); 57022c6ae69SDarkWyrm if (status != B_OK) 57122c6ae69SDarkWyrm return NULL; 57222c6ae69SDarkWyrm 57322c6ae69SDarkWyrm status = datamsg.FindInt32("_cspace", (int32)cspace); 57422c6ae69SDarkWyrm if (status != B_OK) 57522c6ae69SDarkWyrm return NULL; 57622c6ae69SDarkWyrm cspace = B_RGBA32; 57722c6ae69SDarkWyrm bitmap = new BBitmap(frame, cspace, true); 57822c6ae69SDarkWyrm 57922c6ae69SDarkWyrm status = datamsg.FindData("_data", B_RAW_TYPE, (const void **)&buffer, &bufferLength); 58009a03cb8SDarkWyrm if (status != B_OK) { 58122c6ae69SDarkWyrm delete bitmap; 58222c6ae69SDarkWyrm return NULL; 58322c6ae69SDarkWyrm } 58422c6ae69SDarkWyrm 58522c6ae69SDarkWyrm memcpy(bitmap->Bits(), buffer, bufferLength); 58622c6ae69SDarkWyrm return bitmap; 58722c6ae69SDarkWyrm } 58822c6ae69SDarkWyrm case CLIP_PRODUCTIVE: 58922c6ae69SDarkWyrm // Productive doesn't name the packaged BBitmap data message the same, but 59022c6ae69SDarkWyrm // uses exactly the same data format. 59122c6ae69SDarkWyrm 59209a03cb8SDarkWyrm case CLIP_BEOS: { 59322c6ae69SDarkWyrm const void *buffer; 59422c6ae69SDarkWyrm int32 bufferLength; 59522c6ae69SDarkWyrm 59622c6ae69SDarkWyrm BRect frame; 59722c6ae69SDarkWyrm color_space cspace = B_NO_COLOR_SPACE; 59822c6ae69SDarkWyrm 59922c6ae69SDarkWyrm status = flattened.FindRect("_frame", &frame); 60022c6ae69SDarkWyrm if (status != B_OK) 60122c6ae69SDarkWyrm return NULL; 60222c6ae69SDarkWyrm 60322c6ae69SDarkWyrm status = flattened.FindInt32("_cspace", (int32)cspace); 60422c6ae69SDarkWyrm if (status != B_OK) 60522c6ae69SDarkWyrm return NULL; 60622c6ae69SDarkWyrm cspace = B_RGBA32; 60722c6ae69SDarkWyrm bitmap = new BBitmap(frame, cspace, true); 60822c6ae69SDarkWyrm 60922c6ae69SDarkWyrm status = flattened.FindData("_data", B_RAW_TYPE, (const void **)&buffer, &bufferLength); 61009a03cb8SDarkWyrm if (status != B_OK) { 61122c6ae69SDarkWyrm delete bitmap; 61222c6ae69SDarkWyrm return NULL; 61322c6ae69SDarkWyrm } 61422c6ae69SDarkWyrm 61522c6ae69SDarkWyrm memcpy(bitmap->Bits(), buffer, bufferLength); 61622c6ae69SDarkWyrm return bitmap; 61722c6ae69SDarkWyrm } 61822c6ae69SDarkWyrm default: 61922c6ae69SDarkWyrm return NULL; 62022c6ae69SDarkWyrm } 62122c6ae69SDarkWyrm 62222c6ae69SDarkWyrm // shut the compiler up 62322c6ae69SDarkWyrm return NULL; 62422c6ae69SDarkWyrm } 62522c6ae69SDarkWyrm 62609a03cb8SDarkWyrm 62709a03cb8SDarkWyrm BRect 62809a03cb8SDarkWyrm ScaleRectToFit(const BRect &from, const BRect &to) 62922c6ae69SDarkWyrm { 63022c6ae69SDarkWyrm // Dynamic sizing algorithm 63122c6ae69SDarkWyrm // 1) Check to see if either dimension is bigger than the view's display area 63222c6ae69SDarkWyrm // 2) If smaller along both axes, make bitmap rect centered and return 63322c6ae69SDarkWyrm // 3) Check to see if scaling is to be horizontal or vertical on basis of longer axis 63422c6ae69SDarkWyrm // 4) Calculate scaling factor 63522c6ae69SDarkWyrm // 5) Scale both axes down by scaling factor, accounting for border width 63622c6ae69SDarkWyrm // 6) Center the rectangle in the direction of the smaller axis 63722c6ae69SDarkWyrm 63822c6ae69SDarkWyrm if (!to.IsValid()) 63922c6ae69SDarkWyrm return from; 64022c6ae69SDarkWyrm if (!from.IsValid()) 64122c6ae69SDarkWyrm return to; 64222c6ae69SDarkWyrm 64322c6ae69SDarkWyrm BRect r(to); 64422c6ae69SDarkWyrm 64509a03cb8SDarkWyrm if ((from.Width() <= r.Width()) && (from.Height() <= r.Height())) { 64622c6ae69SDarkWyrm // Smaller than view, so just center and return 64722c6ae69SDarkWyrm r = from; 64822c6ae69SDarkWyrm r.OffsetBy((to.Width() - r.Width()) / 2, (to.Height() - r.Height()) / 2); 64922c6ae69SDarkWyrm return r; 65022c6ae69SDarkWyrm } 65122c6ae69SDarkWyrm 65222c6ae69SDarkWyrm float multiplier = from.Width()/from.Height(); 65309a03cb8SDarkWyrm if (multiplier > 1) { 65422c6ae69SDarkWyrm // Landscape orientation 65522c6ae69SDarkWyrm 65622c6ae69SDarkWyrm // Scale rectangle to bounds width and center height 65722c6ae69SDarkWyrm r.bottom = r.top + (r.Width() / multiplier); 65822c6ae69SDarkWyrm r.OffsetBy(0, (to.Height() - r.Height()) / 2); 65909a03cb8SDarkWyrm } else { 66022c6ae69SDarkWyrm // Portrait orientation 66122c6ae69SDarkWyrm 66222c6ae69SDarkWyrm // Scale rectangle to bounds height and center width 66322c6ae69SDarkWyrm r.right = r.left + (r.Height() * multiplier); 66422c6ae69SDarkWyrm r.OffsetBy((to.Width() - r.Width()) / 2, 0); 66522c6ae69SDarkWyrm } 66622c6ae69SDarkWyrm return r; 66722c6ae69SDarkWyrm } 66822c6ae69SDarkWyrm 66909a03cb8SDarkWyrm 67009a03cb8SDarkWyrm void 67109a03cb8SDarkWyrm BitmapView::RemoveBitmap(void) 67222c6ae69SDarkWyrm { 67322c6ae69SDarkWyrm SetBitmap(NULL); 67422c6ae69SDarkWyrm } 67522c6ae69SDarkWyrm 67609a03cb8SDarkWyrm 67709a03cb8SDarkWyrm void 67809a03cb8SDarkWyrm BitmapView::PasteBitmap(void) 67922c6ae69SDarkWyrm { 68022c6ae69SDarkWyrm BBitmap *bmp = BitmapFromClipboard(); 68122c6ae69SDarkWyrm if (bmp) 68222c6ae69SDarkWyrm SetBitmap(bmp); 68322c6ae69SDarkWyrm 68422c6ae69SDarkWyrm if (fConstrainDrops) 68522c6ae69SDarkWyrm ConstrainBitmap(); 68622c6ae69SDarkWyrm } 687