void PictureView::_BeginDrag(BPoint sourcePoint) { BBitmap* bitmap = _CopyPicture(128); if (bitmap == NULL) return; // fill the drag message BMessage drag(B_SIMPLE_DATA); drag.AddInt32("be:actions", B_COPY_TARGET); drag.AddInt32("be:actions", B_TRASH_TARGET); // name the clip after person name, if any BString name = B_TRANSLATE("%name% picture"); name.ReplaceFirst("%name%", Window() ? Window()->Title() : B_TRANSLATE("Unnamed person")); drag.AddString("be:clip_name", name.String()); BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster == NULL) { delete bitmap; return; } int32 infoCount; translator_info* info; BBitmapStream stream(bitmap); if (roster->GetTranslators(&stream, NULL, &info, &infoCount) == B_OK) { for (int32 i = 0; i < infoCount; i++) { const translation_format* formats; int32 count; roster->GetOutputFormats(info[i].translator, &formats, &count); for (int32 j = 0; j < count; j++) { if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) { // needed to send data in message drag.AddString("be:types", formats[j].MIME); // needed to pass data via file drag.AddString("be:filetypes", formats[j].MIME); drag.AddString("be:type_descriptions", formats[j].name); } } } } stream.DetachBitmap(&bitmap); // we also support "Passing Data via File" protocol drag.AddString("be:types", B_FILE_MIME_TYPE); sourcePoint -= fPictureRect.LeftTop(); SetMouseEventMask(B_POINTER_EVENTS); DragMessage(&drag, bitmap, B_OP_ALPHA, sourcePoint); bitmap = NULL; }
void PictureView::_HandleDrop(BMessage* msg) { entry_ref dirRef; BString name, type; bool saveToFile = msg->FindString("be:filetypes", &type) == B_OK && msg->FindRef("directory", &dirRef) == B_OK && msg->FindString("name", &name) == B_OK; bool sendInMessage = !saveToFile && msg->FindString("be:types", &type) == B_OK; if (!sendInMessage && !saveToFile) return; BBitmap* bitmap = fPicture; if (bitmap == NULL) return; BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster == NULL) return; BBitmapStream stream(bitmap); // find translation format we're asked for translator_info* outInfo; int32 outNumInfo; bool found = false; translation_format format; if (roster->GetTranslators(&stream, NULL, &outInfo, &outNumInfo) == B_OK) { for (int32 i = 0; i < outNumInfo; i++) { const translation_format* formats; int32 formatCount; roster->GetOutputFormats(outInfo[i].translator, &formats, &formatCount); for (int32 j = 0; j < formatCount; j++) { if (strcmp(formats[j].MIME, type.String()) == 0) { format = formats[j]; found = true; break; } } } } if (!found) { stream.DetachBitmap(&bitmap); return; } if (sendInMessage) { BMessage reply(B_MIME_DATA); BMallocIO memStream; if (roster->Translate(&stream, NULL, NULL, &memStream, format.type) == B_OK) { reply.AddData(format.MIME, B_MIME_TYPE, memStream.Buffer(), memStream.BufferLength()); msg->SendReply(&reply); } } else { BDirectory dir(&dirRef); BFile file(&dir, name.String(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); if (file.InitCheck() == B_OK && roster->Translate(&stream, NULL, NULL, &file, format.type) == B_OK) { BNodeInfo nodeInfo(&file); if (nodeInfo.InitCheck() == B_OK) nodeInfo.SetType(type.String()); } else { BString text = B_TRANSLATE("The file '%name%' could not " "be written."); text.ReplaceFirst("%name%", name); BAlert* alert = new BAlert(B_TRANSLATE("Error"), text.String(), B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } } // Detach, as we don't want our fPicture to be deleted stream.DetachBitmap(&bitmap); }