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
SetRGBColor(rgb_color * col,uint8 r,uint8 g,uint8 b,uint8 a)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
BitmapView(BRect frame,const char * name,BMessage * mod,BBitmap * bitmap,const char * label,border_style borderstyle,int32 resize,int32 flags)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 {
45*fa19dd44Slooncraz SetViewUIColor(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
~BitmapView(void)10022c6ae69SDarkWyrm BitmapView::~BitmapView(void)
10122c6ae69SDarkWyrm {
10222c6ae69SDarkWyrm delete fPopUpMenu;
10322c6ae69SDarkWyrm }
10422c6ae69SDarkWyrm
10509a03cb8SDarkWyrm
10609a03cb8SDarkWyrm void
AttachedToWindow(void)10709a03cb8SDarkWyrm BitmapView::AttachedToWindow(void)
10822c6ae69SDarkWyrm {
10922c6ae69SDarkWyrm SetTarget((BHandler*)Window());
11022c6ae69SDarkWyrm fPopUpMenu->SetTargetForItems(this);
11122c6ae69SDarkWyrm }
11222c6ae69SDarkWyrm
11309a03cb8SDarkWyrm
11409a03cb8SDarkWyrm void
SetBitmap(BBitmap * bitmap)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
SetEnabled(bool value)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
SetStyle(border_style style)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
SetFixedSize(bool isfixed)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
MessageReceived(BMessage * msg)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: {
2534d99b24dSHumdinger 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
Draw(BRect rect)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
MouseDown(BPoint pt)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
FrameResized(float w,float h)38709a03cb8SDarkWyrm BitmapView::FrameResized(float w, float h)
38822c6ae69SDarkWyrm {
38922c6ae69SDarkWyrm CalculateBitmapRect();
39022c6ae69SDarkWyrm }
39122c6ae69SDarkWyrm
39209a03cb8SDarkWyrm
39309a03cb8SDarkWyrm void
CalculateBitmapRect(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
SetAcceptDrops(bool accept)40909a03cb8SDarkWyrm BitmapView::SetAcceptDrops(bool accept)
41022c6ae69SDarkWyrm {
41122c6ae69SDarkWyrm fAcceptDrops = accept;
41222c6ae69SDarkWyrm }
41322c6ae69SDarkWyrm
41409a03cb8SDarkWyrm
41509a03cb8SDarkWyrm void
SetAcceptPaste(bool accept)41609a03cb8SDarkWyrm BitmapView::SetAcceptPaste(bool accept)
41722c6ae69SDarkWyrm {
41822c6ae69SDarkWyrm fAcceptPaste = accept;
41922c6ae69SDarkWyrm }
42022c6ae69SDarkWyrm
42109a03cb8SDarkWyrm
42209a03cb8SDarkWyrm void
SetConstrainDrops(bool value)42309a03cb8SDarkWyrm BitmapView::SetConstrainDrops(bool value)
42422c6ae69SDarkWyrm {
42522c6ae69SDarkWyrm fConstrainDrops = value;
42622c6ae69SDarkWyrm }
42722c6ae69SDarkWyrm
42809a03cb8SDarkWyrm
42909a03cb8SDarkWyrm void
MaxBitmapSize(float * width,float * height) const43009a03cb8SDarkWyrm BitmapView::MaxBitmapSize(float *width, float *height) const
43122c6ae69SDarkWyrm {
43222c6ae69SDarkWyrm *width = fMaxWidth;
43322c6ae69SDarkWyrm *height = fMaxHeight;
43422c6ae69SDarkWyrm }
43522c6ae69SDarkWyrm
43609a03cb8SDarkWyrm
43709a03cb8SDarkWyrm void
SetMaxBitmapSize(const float & width,const float & height)43809a03cb8SDarkWyrm BitmapView::SetMaxBitmapSize(const float &width, const float &height)
43922c6ae69SDarkWyrm {
44022c6ae69SDarkWyrm fMaxWidth = width;
44122c6ae69SDarkWyrm fMaxHeight = height;
44222c6ae69SDarkWyrm
44322c6ae69SDarkWyrm ConstrainBitmap();
44422c6ae69SDarkWyrm }
44522c6ae69SDarkWyrm
44609a03cb8SDarkWyrm
44709a03cb8SDarkWyrm void
SetBitmapRemovable(bool isremovable)44809a03cb8SDarkWyrm BitmapView::SetBitmapRemovable(bool isremovable)
44922c6ae69SDarkWyrm {
45022c6ae69SDarkWyrm fRemovableBitmap = isremovable;
45122c6ae69SDarkWyrm }
45222c6ae69SDarkWyrm
45309a03cb8SDarkWyrm
45409a03cb8SDarkWyrm void
ConstrainBitmap(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
ClipboardHasBitmap(void)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 *
BitmapFromClipboard(void)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;
56474349b4fSAlexander von Gluck IV ssize_t 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;
59474349b4fSAlexander von Gluck IV ssize_t 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
ScaleRectToFit(const BRect & from,const BRect & to)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
RemoveBitmap(void)67109a03cb8SDarkWyrm BitmapView::RemoveBitmap(void)
67222c6ae69SDarkWyrm {
67322c6ae69SDarkWyrm SetBitmap(NULL);
67422c6ae69SDarkWyrm }
67522c6ae69SDarkWyrm
67609a03cb8SDarkWyrm
67709a03cb8SDarkWyrm void
PasteBitmap(void)67809a03cb8SDarkWyrm BitmapView::PasteBitmap(void)
67922c6ae69SDarkWyrm {
68022c6ae69SDarkWyrm BBitmap *bmp = BitmapFromClipboard();
68122c6ae69SDarkWyrm if (bmp)
68222c6ae69SDarkWyrm SetBitmap(bmp);
68322c6ae69SDarkWyrm
68422c6ae69SDarkWyrm if (fConstrainDrops)
68522c6ae69SDarkWyrm ConstrainBitmap();
68622c6ae69SDarkWyrm }
687