From cd6b5cde06b9cc9ab9e5aacf03cda9dc853c34e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 1 Nov 2010 19:48:23 +0000 Subject: [PATCH] * Completed stippi's work on the ImageFileNavigator. * ShowImageWindow is now using such a navigator. * Removed navigation support from ShowImageView. * Prepared everything to support asynchronous image loading (which is not yet implemented, though). * Note, this commit brings some regressions I intend to fix in the next few days, namely deleting files won't work anymore, and dropping images onto ShowImage. There might be more I don't know about, though :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39259 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/showimage/ImageFileNavigator.cpp | 245 +++++----- src/apps/showimage/ImageFileNavigator.h | 69 ++- src/apps/showimage/Jamfile | 1 + src/apps/showimage/ShowImageView.cpp | 520 ++++------------------ src/apps/showimage/ShowImageView.h | 42 +- src/apps/showimage/ShowImageWindow.cpp | 346 +++++++------- src/apps/showimage/ShowImageWindow.h | 19 +- 7 files changed, 437 insertions(+), 805 deletions(-) diff --git a/src/apps/showimage/ImageFileNavigator.cpp b/src/apps/showimage/ImageFileNavigator.cpp index 12ea5cade9..933bdbfbe0 100644 --- a/src/apps/showimage/ImageFileNavigator.cpp +++ b/src/apps/showimage/ImageFileNavigator.cpp @@ -61,27 +61,11 @@ namespace BPrivate { const uint32 kMoveToTrash = 'Ttrs'; } -using std::nothrow; - - -#define SHOW_IMAGE_ORIENTATION_ATTRIBUTE "ShowImage:orientation" - -enum ImageFileNavigator::image_orientation -ImageFileNavigator::fTransformation[ImageProcessor::kNumberOfAffineTransformations][kNumberOfOrientations] = { - // rotate 90° - {k90, k180, k270, k0, k270V, k0V, k90V, k0H}, - // rotate -90° - {k270, k0, k90, k180, k90V, k0H, k270V, k0V}, - // mirror vertical - {k0H, k270V, k0V, k90V, k180, k270, k0, k90}, - // mirror horizontal - {k0V, k90V, k0H, k270V, k0, k90, k180, k270} -}; static bool -entry_ref_is_file(const entry_ref *ref) +entry_ref_is_file(const entry_ref& ref) { - BEntry entry(ref, true); + BEntry entry(&ref, true); if (entry.InitCheck() != B_OK) return false; @@ -89,11 +73,15 @@ entry_ref_is_file(const entry_ref *ref) } -ImageFileNavigator::ImageFileNavigator(BRect rect, const char *name, uint32 resizingMode, - uint32 flags) +// #pragma mark - + + +ImageFileNavigator::ImageFileNavigator(const BMessenger& target) : + fTarget(target), + fProgressWindow(NULL), fDocumentIndex(1), - fDocumentCount(1), + fDocumentCount(1) { } @@ -110,39 +98,38 @@ ImageFileNavigator::SetTrackerMessenger(const BMessenger& trackerMessenger) } -status_t -ImageFileNavigator::LoadImage(const entry_ref* ref, BBitmap** bitmap) +void +ImageFileNavigator::SetProgressWindow(ProgressWindow* progressWindow) { - if (bitmap == NULL) - return B_BAD_VALUE; + fProgressWindow = progressWindow; +} - // If no ref was specified, load the specified page of the current file. - if (ref == NULL) - ref = &fCurrentRef; - BTranslatorRoster *roster = BTranslatorRoster::Default(); +status_t +ImageFileNavigator::LoadImage(const entry_ref& ref, int32 page) +{ + BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster == NULL) return B_ERROR; if (!entry_ref_is_file(ref)) return B_ERROR; - BFile file(ref, B_READ_ONLY); + BFile file(&ref, B_READ_ONLY); translator_info info; memset(&info, 0, sizeof(translator_info)); BMessage ioExtension; - if (ref != &fCurrentRef) { - // if new image, reset to first document - fDocumentIndex = 1; - } - if (ioExtension.AddInt32("/documentIndex", fDocumentIndex) != B_OK) + if (page != 0 && ioExtension.AddInt32("/documentIndex", page) != B_OK) return B_ERROR; - BMessage progress(kMsgProgressStatusUpdate); - if (ioExtension.AddMessenger("/progressMonitor", fProgressWindow) == B_OK - && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) - fProgressWindow->Start(); + if (fProgressWindow != NULL) { + BMessage progress(kMsgProgressStatusUpdate); + if (ioExtension.AddMessenger("/progressMonitor", + fProgressWindow) == B_OK + && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) + fProgressWindow->Start(); + } // Translate image data and create a new ShowImage window @@ -155,25 +142,18 @@ ImageFileNavigator::LoadImage(const entry_ref* ref, BBitmap** bitmap) B_TRANSLATOR_BITMAP); } - fProgressWindow->Stop(); + if (fProgressWindow != NULL) + fProgressWindow->Stop(); if (status != B_OK) return status; - if (outstream.DetachBitmap(bitmap) != B_OK) + BBitmap* bitmap; + if (outstream.DetachBitmap(&bitmap) != B_OK) return B_ERROR; - fCurrentRef = *ref; - - // restore orientation - int32 orientation; - fImageOrientation = k0; - fInverted = false; - if (file.ReadAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE, B_INT32_TYPE, 0, - &orientation, sizeof(orientation)) == sizeof(orientation)) { - fInverted = (orientation & 256) != 0; - fImageOrientation = (orientation & 255) != 0; - } + fCurrentRef = ref; + fDocumentIndex = page; // get the number of documents (pages) if it has been supplied int32 documentCount = 0; @@ -183,11 +163,19 @@ ImageFileNavigator::LoadImage(const entry_ref* ref, BBitmap** bitmap) else fDocumentCount = 1; - fImageType = info.name; - fImageMime = info.MIME; + BMessage message(kMsgImageLoaded); + message.AddString("type", info.name); + message.AddString("mime", info.MIME); + message.AddRef("ref", &ref); + message.AddInt32("page", page); + message.AddPointer("bitmap", (void*)bitmap); + status = fTarget.SendMessage(&message); + if (status != B_OK) { + delete bitmap; + return status; + } be_roster->AddToRecentDocuments(&fCurrentRef, kApplicationSignature); - return B_OK; } @@ -230,79 +218,80 @@ ImageFileNavigator::PageCount() } -status_t -ImageFileNavigator::FirstPage(BBitmap** bitmap) +bool +ImageFileNavigator::FirstPage() { if (fDocumentIndex != 1) { - fDocumentIndex = 1; - return LoadImage(NULL, bitmap); + LoadImage(fCurrentRef, 1); + return true; } - return B_BAD_INDEX; + return false; } -status_t -ImageFileNavigator::LastPage(BBitmap** bitmap) +bool +ImageFileNavigator::LastPage() { if (fDocumentIndex != fDocumentCount) { - fDocumentIndex = fDocumentCount; - return LoadImage(NULL, bitmap); + LoadImage(fCurrentRef, fDocumentCount); + return true; } - return B_BAD_INDEX; + return false; } -status_t -ImageFileNavigator::NextPage(BBitmap** bitmap) +bool +ImageFileNavigator::NextPage() { if (fDocumentIndex < fDocumentCount) { - fDocumentIndex++; - return LoadImage(NULL, bitmap); + LoadImage(fCurrentRef, ++fDocumentIndex); + return true; } - return B_BAD_INDEX; + return false; } -status_t -ImageFileNavigator::PrevPage(BBitmap** bitmap) +bool +ImageFileNavigator::PreviousPage() { if (fDocumentIndex > 1) { - fDocumentIndex--; - return LoadImage(NULL, bitmap); + LoadImage(fCurrentRef, --fDocumentIndex); + return true; } - return B_BAD_INDEX; + return false; } -status_t -ImageFileNavigator::GoToPage(int32 page, BBitmap** bitmap) +bool +ImageFileNavigator::GoToPage(int32 page) { if (page > 0 && page <= fDocumentCount && page != fDocumentIndex) { fDocumentIndex = page; - return LoadImage(NULL, bitmap); + LoadImage(fCurrentRef, fDocumentIndex); + return true; } - return B_BAD_INDEX; + return false; } -status_t -ImageFileNavigator::FirstFile(BBitmap** bitmap) +void +ImageFileNavigator::FirstFile() { - return _LoadNextImage(true, true, bitmap); + _LoadNextImage(true, true); } -status_t -ImageFileNavigator::NextFile(BBitmap** bitmap) +void +ImageFileNavigator::NextFile() { - return _LoadNextImage(true, false, bitmap); + _LoadNextImage(true, false); } -status_t -ImageFileNavigator::PrevFile(BBitmap** bitmap) +void +ImageFileNavigator::PreviousFile() { - return _LoadNextImage(false, false, bitmap); + _LoadNextImage(false, false); } @@ -310,15 +299,36 @@ bool ImageFileNavigator::HasNextFile() { entry_ref ref; - return _FindNextImage(&fCurrentRef, &ref, true, false); + return _FindNextImage(fCurrentRef, ref, true, false); } bool -ImageFileNavigator::HasPrevFile() +ImageFileNavigator::HasPreviousFile() { entry_ref ref; - return _FindNextImage(&fCurrentRef, &ref, false, false); + return _FindNextImage(fCurrentRef, ref, false, false); +} + + +void +ImageFileNavigator::DeleteFile() +{ + // Move image to Trash + BMessage trash(BPrivate::kMoveToTrash); + trash.AddRef("refs", &fCurrentRef); + +// TODO! +#if 0 + // We create our own messenger because the member fTrackerMessenger + // could be invalid + BMessenger tracker(kTrackerSignature); + if (tracker.SendMessage(&trash) == B_OK && !NextFile()) { + // This is the last (or only file) in this directory, + // close the window + _SendMessageToWindow(B_QUIT_REQUESTED); + } +#endif } @@ -326,12 +336,12 @@ ImageFileNavigator::HasPrevFile() bool -ImageFileNavigator::_IsImage(const entry_ref *ref) +ImageFileNavigator::_IsImage(const entry_ref& ref) { - if (ref == NULL || !entry_ref_is_file(ref)) + if (!entry_ref_is_file(ref)) return false; - BFile file(ref, B_READ_ONLY); + BFile file(&ref, B_READ_ONLY); if (file.InitCheck() != B_OK) return false; @@ -354,19 +364,17 @@ ImageFileNavigator::_IsImage(const entry_ref *ref) bool -ImageFileNavigator::_FindNextImage(entry_ref* currentRef, entry_ref* ref, +ImageFileNavigator::_FindNextImage(const entry_ref& currentRef, entry_ref& ref, bool next, bool rewind) { // Based on GetTrackerWindowFile function from BeMail if (!fTrackerMessenger.IsValid()) return false; - // - // Ask the Tracker what the next/prev file in the window is. - // Continue asking for the next reference until a valid - // image is found. - // - entry_ref nextRef = *currentRef; + // Ask the Tracker what the next/prev file in the window is. + // Continue asking for the next reference until a valid + // image is found. + entry_ref nextRef = currentRef; bool foundRef = false; while (!foundRef) { BMessage request(B_GET_PROPERTY); @@ -392,35 +400,34 @@ ImageFileNavigator::_FindNextImage(entry_ref* currentRef, entry_ref* ref, if (reply.FindRef("result", &nextRef) != B_OK) return false; - if (_IsImage(&nextRef)) + if (_IsImage(nextRef)) foundRef = true; rewind = false; // stop asking for the first ref in the directory } - *ref = nextRef; + ref = nextRef; return foundRef; } -status_t -ImageFileNavigator::_LoadNextImage(bool next, bool rewind, BBitmap** bitmap) -{ - if (bitmap == NULL) - return B_BAD_VALUE; - entry_ref curRef = fCurrentRef; - entry_ref imgRef; - bool found = _FindNextImage(&curRef, &imgRef, next, rewind); +status_t +ImageFileNavigator::_LoadNextImage(bool next, bool rewind) +{ + entry_ref currentRef = fCurrentRef; + entry_ref ref; + bool found = _FindNextImage(currentRef, ref, next, rewind); if (found) { // Keep trying to load images until: // 1. The image loads successfully - // 2. The last file in the directory is found (for find next or find first) + // 2. The last file in the directory is found (for find next or find + // first) // 3. The first file in the directory is found (for find prev) // 4. The call to _FindNextImage fails for any other reason - while (LoadImage(&imgRef, bitmap) != B_OK) { - curRef = imgRef; - found = _FindNextImage(&curRef, &imgRef, next, false); + while (LoadImage(ref) != B_OK) { + currentRef = ref; + found = _FindNextImage(currentRef, ref, next, false); if (!found) return B_ENTRY_NOT_FOUND; } @@ -434,10 +441,10 @@ ImageFileNavigator::_LoadNextImage(bool next, bool rewind, BBitmap** bitmap) void ImageFileNavigator::_SetTrackerSelectionToCurrent() { - BMessage setsel(B_SET_PROPERTY); - setsel.AddSpecifier("Selection"); - setsel.AddRef("data", &fCurrentRef); - fTrackerMessenger.SendMessage(&setsel); + BMessage setSelection(B_SET_PROPERTY); + setSelection.AddSpecifier("Selection"); + setSelection.AddRef("data", &fCurrentRef); + fTrackerMessenger.SendMessage(&setSelection); } diff --git a/src/apps/showimage/ImageFileNavigator.h b/src/apps/showimage/ImageFileNavigator.h index 33df1a5ac5..e0331e2629 100644 --- a/src/apps/showimage/ImageFileNavigator.h +++ b/src/apps/showimage/ImageFileNavigator.h @@ -16,26 +16,30 @@ #define IMAGE_FILE_NAVIGATOR_H -#include #include -#include +#include #include -#include class ProgressWindow; +enum { + kMsgImageLoaded = 'ifnL' +}; + + class ImageFileNavigator { public: - ImageFileNavigator( - ProgressWindow* progressWindow); + ImageFileNavigator(const BMessenger& target); virtual ~ImageFileNavigator(); void SetTrackerMessenger( const BMessenger& trackerMessenger); + void SetProgressWindow( + ProgressWindow* progressWindow); - status_t LoadImage(const entry_ref* ref, BBitmap** bitmap); - const entry_ref* ImageRef() const { return &fCurrentRef; } + status_t LoadImage(const entry_ref& ref, int32 page = 1); + const entry_ref& ImageRef() const { return fCurrentRef; } void GetName(BString* name); void GetPath(BString* name); @@ -45,11 +49,11 @@ public: int32 CurrentPage(); int32 PageCount(); - status_t FirstPage(BBitmap** bitmap); - status_t LastPage(BBitmap** bitmap); - status_t NextPage(BBitmap** bitmap); - status_t PrevPage(BBitmap** bitmap); - status_t GoToPage(int32 page, BBitmap** bitmap); + bool FirstPage(); + bool LastPage(); + bool NextPage(); + bool PreviousPage(); + bool GoToPage(int32 page); // Navigation to the next/previous image file is based on // communication with Tracker, the folder containing the current @@ -57,37 +61,29 @@ public: // to find the next candidate file, then tries to load it as image. // As long as loading fails, the operation is repeated for the next // candidate file. - status_t FirstFile(BBitmap** bitmap); - status_t NextFile(BBitmap** bitmap); - status_t PrevFile(BBitmap** bitmap); + void FirstFile(); + void NextFile(); + void PreviousFile(); bool HasNextFile(); - bool HasPrevFile(); + bool HasPreviousFile(); + + void DeleteFile(); private: - enum image_orientation { - k0, // 0 - k90, // 1 - k180, // 2 - k270, // 3 - k0V, // 4 - k90V, // 5 - k0H, // 6 - k270V, // 7 - kNumberOfOrientations, - }; - - bool _IsImage(const entry_ref* pref); - bool _FindNextImage(entry_ref* inCurrent, - entry_ref* outImage, bool next, + bool _IsImage(const entry_ref& ref); + bool _FindNextImage(const entry_ref& current, + entry_ref& next, bool next, bool rewind); status_t _LoadNextImage(bool next, bool rewind); void _SetTrackerSelectionToCurrent(); private: + BMessenger fTarget; BMessenger fTrackerMessenger; // of the window that this was launched from - entry_ref fCurrentRef; + ProgressWindow* fProgressWindow; + entry_ref fCurrentRef; int32 fDocumentIndex; // of the image in the file int32 fDocumentCount; @@ -96,14 +92,7 @@ private: BString fImageType; // Type of image, for use in status bar and caption BString fImageMime; - - ProgressWindow* fProgressWindow; - - image_orientation fImageOrientation; - static image_orientation fTransformation[ - ImageProcessor - ::kNumberOfAffineTransformations] - [kNumberOfOrientations]; }; + #endif // IMAGE_FILE_NAVIGATOR_H diff --git a/src/apps/showimage/Jamfile b/src/apps/showimage/Jamfile index a017dbffa2..47034b0593 100644 --- a/src/apps/showimage/Jamfile +++ b/src/apps/showimage/Jamfile @@ -7,6 +7,7 @@ UsePublicHeaders [ FDirName be_apps Tracker ] ; Application ShowImage : EntryMenuItem.cpp Filter.cpp + ImageFileNavigator.cpp PrintOptionsWindow.cpp ProgressWindow.cpp ResizerWindow.cpp diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 2f3283bc62..bbe9059dad 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -55,11 +55,6 @@ #include "ShowImageWindow.h" -// TODO: Remove this and use Tracker's Command.h once it is moved into the private headers -namespace BPrivate { - const uint32 kMoveToTrash = 'Ttrs'; -} - using std::nothrow; @@ -94,17 +89,6 @@ const rgb_color kAlphaHigh = (rgb_color){ 0xe0, 0xe0, 0xe0, 0xff }; const uint32 kMsgPopUpMenuClosed = 'pmcl'; -static bool -entry_ref_is_file(const entry_ref *ref) -{ - BEntry entry(ref, true); - if (entry.InitCheck() != B_OK) - return false; - - return entry.IsFile(); -} - - inline void blend_colors(uint8* d, uint8 r, uint8 g, uint8 b, uint8 a) { @@ -184,8 +168,6 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, uint32 flags) : BView(rect, name, resizingMode, flags), - fDocumentIndex(1), - fDocumentCount(1), fBitmap(NULL), fDisplayBitmap(NULL), fSelectionBitmap(NULL), @@ -252,6 +234,7 @@ ShowImageView::Pulse() fSelectionBox.Animate(); fSelectionBox.Draw(this, Bounds()); } +#if 0 if (fSlideShow) { fSlideShowCountDown --; if (fSlideShowCountDown <= 0) { @@ -261,6 +244,7 @@ ShowImageView::Pulse() } } } +#endif // Hide cursor in full screen mode if (fFullScreen && !fHasSelection && !fShowingPopUpMenu && fIsActiveWin) { @@ -272,34 +256,6 @@ ShowImageView::Pulse() } -bool -ShowImageView::_IsImage(const entry_ref *ref) -{ - if (ref == NULL || !entry_ref_is_file(ref)) - return false; - - BFile file(ref, B_READ_ONLY); - if (file.InitCheck() != B_OK) - return false; - - BTranslatorRoster *roster = BTranslatorRoster::Default(); - if (!roster) - return false; - - BMessage ioExtension; - if (ioExtension.AddInt32("/documentIndex", fDocumentIndex) != B_OK) - return false; - - translator_info info; - memset(&info, 0, sizeof(translator_info)); - if (roster->Identify(&file, &ioExtension, &info, 0, NULL, - B_TRANSLATOR_BITMAP) != B_OK) - return false; - - return true; -} - - void ShowImageView::SetTrackerMessenger(const BMessenger& trackerMessenger) { @@ -310,8 +266,8 @@ ShowImageView::SetTrackerMessenger(const BMessenger& trackerMessenger) void ShowImageView::_SendMessageToWindow(BMessage *message) { - BMessenger msgr(Window()); - msgr.SendMessage(message); + BMessenger target(Window()); + target.SendMessage(message); } @@ -329,7 +285,6 @@ ShowImageView::_Notify() { BMessage msg(MSG_UPDATE_STATUS); - msg.AddString("status", fImageType.String()); msg.AddInt32("width", fBitmap->Bounds().IntegerWidth() + 1); msg.AddInt32("height", fBitmap->Bounds().IntegerHeight() + 1); @@ -345,17 +300,16 @@ void ShowImageView::_UpdateStatusText() { BMessage msg(MSG_UPDATE_STATUS_TEXT); - BString status_to_send = fImageType; if (fHasSelection) { char size[50]; - sprintf(size, " (%.0fx%.0f)", + sprintf(size, "(%.0fx%.0f)", fSelectionBox.Bounds().Width() + 1.0, fSelectionBox.Bounds().Height() + 1.0); - status_to_send << size; + + msg.AddString("status", size); } - msg.AddString("status", status_to_send.String()); _SendMessageToWindow(&msg); } @@ -383,132 +337,94 @@ ShowImageView::_DeleteSelectionBitmap() status_t -ShowImageView::SetImage(const entry_ref* ref) +ShowImageView::SetImage(const BMessage* message) { - // If no file was specified, load the specified page of - // the current file. - if (ref == NULL) - ref = &fCurrentRef; - - BTranslatorRoster *roster = BTranslatorRoster::Default(); - if (!roster) + BBitmap* bitmap; + entry_ref ref; + if (message->FindPointer("bitmap", (void**)&bitmap) != B_OK + || message->FindRef("ref", &ref) != B_OK || bitmap == NULL) return B_ERROR; - if (!entry_ref_is_file(ref)) - return B_ERROR; - - BFile file(ref, B_READ_ONLY); - translator_info info; - memset(&info, 0, sizeof(translator_info)); - BMessage ioExtension; - if (ref != &fCurrentRef) { - // if new image, reset to first document - fDocumentIndex = 1; - } - - if (ioExtension.AddInt32("/documentIndex", fDocumentIndex) != B_OK) - return B_ERROR; - - BMessage progress(kMsgProgressStatusUpdate); - if (ioExtension.AddMessenger("/progressMonitor", fProgressWindow) == B_OK - && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) - fProgressWindow->Start(); - - // Translate image data and create a new ShowImage window - - BBitmapStream outstream; - - status_t status = roster->Identify(&file, &ioExtension, &info, 0, NULL, - B_TRANSLATOR_BITMAP); + status_t status = SetImage(&ref, bitmap); if (status == B_OK) { - status = roster->Translate(&file, &info, &ioExtension, &outstream, - B_TRANSLATOR_BITMAP); + fFormatDescription = message->FindString("type"); + fMimeType = message->FindString("mime"); } - fProgressWindow->Stop(); + return status; +} - if (status != B_OK) - return status; - BBitmap *newBitmap = NULL; - if (outstream.DetachBitmap(&newBitmap) != B_OK) - return B_ERROR; - - // Now that I've successfully loaded the new bitmap, - // I can be sure it is safe to delete the old one, - // and clear everything +status_t +ShowImageView::SetImage(const entry_ref* ref, BBitmap* bitmap) +{ + // Delete the old one, and clear everything fUndo.Clear(); _SetHasSelection(false); fCreatingSelection = false; _DeleteBitmap(); - fBitmap = newBitmap; - fCurrentRef = *ref; - // prepare the display bitmap - if (fBitmap->ColorSpace() == B_RGBA32) - fDisplayBitmap = compose_checker_background(fBitmap); + fBitmap = bitmap; + if (ref == NULL) + fCurrentRef.device = -1; + else + fCurrentRef = *ref; - if (!fDisplayBitmap) - fDisplayBitmap = fBitmap; + if (fBitmap != NULL) { + // prepare the display bitmap + if (fBitmap->ColorSpace() == B_RGBA32) + fDisplayBitmap = compose_checker_background(fBitmap); - // restore orientation - int32 orientation; - fImageOrientation = k0; - if (file.ReadAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE, B_INT32_TYPE, 0, - &orientation, sizeof(orientation)) == sizeof(orientation)) { - orientation &= 255; - switch (orientation) { - case k0: - break; - case k90: - _DoImageOperation(ImageProcessor::kRotateClockwise, true); - break; - case k180: - _DoImageOperation(ImageProcessor::kRotateClockwise, true); - _DoImageOperation(ImageProcessor::kRotateClockwise, true); - break; - case k270: - _DoImageOperation(ImageProcessor::kRotateCounterClockwise, true); - break; - case k0V: - _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); - break; - case k90V: - _DoImageOperation(ImageProcessor::kRotateClockwise, true); - _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); - break; - case k0H: - _DoImageOperation(ImageProcessor::ImageProcessor::kFlipLeftToRight, true); - break; - case k270V: - _DoImageOperation(ImageProcessor::kRotateCounterClockwise, true); - _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); - break; + if (!fDisplayBitmap) + fDisplayBitmap = fBitmap; + + BNode node(ref); + + // restore orientation + int32 orientation; + fImageOrientation = k0; + if (node.ReadAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE, B_INT32_TYPE, 0, + &orientation, sizeof(orientation)) == sizeof(orientation)) { + orientation &= 255; + switch (orientation) { + case k0: + break; + case k90: + _DoImageOperation(ImageProcessor::kRotateClockwise, true); + break; + case k180: + _DoImageOperation(ImageProcessor::kRotateClockwise, true); + _DoImageOperation(ImageProcessor::kRotateClockwise, true); + break; + case k270: + _DoImageOperation(ImageProcessor::kRotateCounterClockwise, true); + break; + case k0V: + _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); + break; + case k90V: + _DoImageOperation(ImageProcessor::kRotateClockwise, true); + _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); + break; + case k0H: + _DoImageOperation(ImageProcessor::ImageProcessor::kFlipLeftToRight, true); + break; + case k270V: + _DoImageOperation(ImageProcessor::kRotateCounterClockwise, true); + _DoImageOperation(ImageProcessor::ImageProcessor::kFlipTopToBottom, true); + break; + } } } - // get the number of documents (pages) if it has been supplied - int32 documentCount = 0; - if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK - && documentCount > 0) - fDocumentCount = documentCount; - else - fDocumentCount = 1; - - fImageType = info.name; - fImageMime = info.MIME; - - GetPath(&fCaption); - if (fDocumentCount > 1) - fCaption << ", " << fDocumentIndex << "/" << fDocumentCount; - - fCaption << ", " << fImageType; + BPath path(ref); + fCaption = path.Path(); + fFormatDescription = "Bitmap"; + fMimeType = "image/x-be-bitmap"; fFitToBoundsZoom = _FitToBoundsZoom(); ResetZoom(); - - be_roster->AddToRecentDocuments(&fCurrentRef, kApplicationSignature); - + Invalidate(); _Notify(); return B_OK; } @@ -599,37 +515,13 @@ ShowImageView::SetFullScreen(bool fullScreen) } -BBitmap * -ShowImageView::GetBitmap() +BBitmap* +ShowImageView::Bitmap() { return fBitmap; } -void -ShowImageView::GetName(BString* outName) -{ - BEntry entry(&fCurrentRef); - char name[B_FILE_NAME_LENGTH]; - if (entry.InitCheck() < B_OK || entry.GetName(name) < B_OK) - outName->SetTo(""); - else - outName->SetTo(name); -} - - -void -ShowImageView::GetPath(BString *outPath) -{ - BEntry entry(&fCurrentRef); - BPath path; - if (entry.InitCheck() < B_OK || entry.GetPath(&path) < B_OK) - outPath->SetTo(""); - else - outPath->SetTo(path.Path()); -} - - void ShowImageView::SetScaleBilinear(bool enabled) { @@ -679,6 +571,9 @@ ShowImageView::_ShouldStretch() const float ShowImageView::_FitToBoundsZoom() const { + if (fBitmap == NULL) + return 1.0f; + // the width/height of the bitmap (in pixels) float bitmapWidth = fBitmap->Bounds().Width() + 1; float bitmapHeight = fBitmap->Bounds().Height() + 1; @@ -935,9 +830,9 @@ ShowImageView::_AddSupportedTypes(BMessage* msg, BBitmap* bitmap) // add the current image mime first, will make it the preferred format on // left mouse drag - msg->AddString("be:types", fImageMime); - msg->AddString("be:filetypes", fImageMime); - msg->AddString("be:type_descriptions", fImageType); + msg->AddString("be:types", fMimeType); + msg->AddString("be:filetypes", fMimeType); + msg->AddString("be:type_descriptions", fFormatDescription); bool foundOther = false; bool foundCurrent = false; @@ -951,7 +846,7 @@ ShowImageView::_AddSupportedTypes(BMessage* msg, BBitmap* bitmap) int32 count; roster->GetOutputFormats(info[i].translator, &formats, &count); for (int32 j = 0; j < count; j++) { - if (fImageMime == formats[j].MIME) { + if (fMimeType == formats[j].MIME) { foundCurrent = true; } else if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) { foundOther = true; @@ -1026,22 +921,23 @@ ShowImageView::_OutputFormatForType(BBitmap* bitmap, const char* type, { bool found = false; - BTranslatorRoster *roster = BTranslatorRoster::Default(); + BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster == NULL) return false; BBitmapStream stream(bitmap); - translator_info *outInfo; + translator_info* outInfo; int32 outNumInfo; if (roster->GetTranslators(&stream, NULL, &outInfo, &outNumInfo) == B_OK) { for (int32 i = 0; i < outNumInfo; i++) { - const translation_format *fmts; - int32 num_fmts; - roster->GetOutputFormats(outInfo[i].translator, &fmts, &num_fmts); - for (int32 j = 0; j < num_fmts; j++) { - if (strcmp(fmts[j].MIME, type) == 0) { - *format = fmts[j]; + 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) == 0) { + *format = formats[j]; found = true; break; } @@ -1441,18 +1337,8 @@ ShowImageView::KeyDown(const char* bytes, int32 numBytes) break; case B_DELETE: { - // Move image to Trash - BMessage trash(BPrivate::kMoveToTrash); - trash.AddRef("refs", &fCurrentRef); - // We create our own messenger because the member fTrackerMessenger - // could be invalid - BMessenger tracker(kTrackerSignature); - if (tracker.SendMessage(&trash) == B_OK) - if (!NextFile()) { - // This is the last (or only file) in this directory, - // close the window - _SendMessageToWindow(B_QUIT_REQUESTED); - } + // TODO! + //fNavigator.DeleteFile(); break; } case '+': @@ -1540,6 +1426,8 @@ void ShowImageView::MessageReceived(BMessage* message) { switch (message->what) { +// TODO! +#if 0 case B_SIMPLE_DATA: if (message->WasDropped()) { uint32 type; @@ -1553,7 +1441,7 @@ ShowImageView::MessageReceived(BMessage* message) } } break; - +#endif case B_COPY_TARGET: _HandleDrop(message); break; @@ -1610,20 +1498,6 @@ ShowImageView::FixupScrollBars() } -int32 -ShowImageView::CurrentPage() -{ - return fDocumentIndex; -} - - -int32 -ShowImageView::PageCount() -{ - return fDocumentCount; -} - - void ShowImageView::SetSelectionMode(bool selectionMode) { @@ -1737,201 +1611,6 @@ ShowImageView::CopySelectionToClipboard() } -void -ShowImageView::FirstPage() -{ - if (fDocumentIndex != 1) { - fDocumentIndex = 1; - SetImage(NULL); - } -} - - -void -ShowImageView::LastPage() -{ - if (fDocumentIndex != fDocumentCount) { - fDocumentIndex = fDocumentCount; - SetImage(NULL); - } -} - - -void -ShowImageView::NextPage() -{ - if (fDocumentIndex < fDocumentCount) { - fDocumentIndex++; - SetImage(NULL); - } -} - - -void -ShowImageView::PrevPage() -{ - if (fDocumentIndex > 1) { - fDocumentIndex--; - SetImage(NULL); - } -} - - -int -ShowImageView::_CompareEntries(const void* a, const void* b) -{ - entry_ref *r1, *r2; - r1 = *(entry_ref**)a; - r2 = *(entry_ref**)b; - return strcasecmp(r1->name, r2->name); -} - - -void -ShowImageView::GoToPage(int32 page) -{ - if (page > 0 && page <= fDocumentCount && page != fDocumentIndex) { - fDocumentIndex = page; - SetImage(NULL); - } -} - - -void -ShowImageView::_FreeEntries(BList* entries) -{ - const int32 n = entries->CountItems(); - for (int32 i = 0; i < n; i ++) { - entry_ref* ref = (entry_ref*)entries->ItemAt(i); - delete ref; - } - entries->MakeEmpty(); -} - - -void -ShowImageView::_SetTrackerSelectionToCurrent() -{ - BMessage setsel(B_SET_PROPERTY); - setsel.AddSpecifier("Selection"); - setsel.AddRef("data", &fCurrentRef); - fTrackerMessenger.SendMessage(&setsel); -} - - -bool -ShowImageView::_FindNextImage(entry_ref *in_current, entry_ref *ref, bool next, - bool rewind) -{ - // Based on GetTrackerWindowFile function from BeMail - if (!fTrackerMessenger.IsValid()) - return false; - - // - // Ask the Tracker what the next/prev file in the window is. - // Continue asking for the next reference until a valid - // image is found. - // - entry_ref nextRef = *in_current; - bool foundRef = false; - while (!foundRef) - { - BMessage request(B_GET_PROPERTY); - BMessage spc; - if (rewind) - spc.what = B_DIRECT_SPECIFIER; - else if (next) - spc.what = 'snxt'; - else - spc.what = 'sprv'; - spc.AddString("property", "Entry"); - if (rewind) - // if rewinding, ask for the ref to the - // first item in the directory - spc.AddInt32("data", 0); - else - spc.AddRef("data", &nextRef); - request.AddSpecifier(&spc); - - BMessage reply; - if (fTrackerMessenger.SendMessage(&request, &reply) != B_OK) - return false; - if (reply.FindRef("result", &nextRef) != B_OK) - return false; - - if (_IsImage(&nextRef)) - foundRef = true; - - rewind = false; - // stop asking for the first ref in the directory - } - - *ref = nextRef; - return foundRef; -} - -bool -ShowImageView::_ShowNextImage(bool next, bool rewind) -{ - entry_ref curRef = fCurrentRef; - entry_ref imgRef; - bool found = _FindNextImage(&curRef, &imgRef, next, rewind); - if (found) { - // Keep trying to load images until: - // 1. The image loads successfully - // 2. The last file in the directory is found (for find next or find first) - // 3. The first file in the directory is found (for find prev) - // 4. The call to _FindNextImage fails for any other reason - while (SetImage(&imgRef) != B_OK) { - curRef = imgRef; - found = _FindNextImage(&curRef, &imgRef, next, false); - if (!found) - return false; - } - _SetTrackerSelectionToCurrent(); - return true; - } - return false; -} - - -bool -ShowImageView::NextFile() -{ - return _ShowNextImage(true, false); -} - - -bool -ShowImageView::PrevFile() -{ - return _ShowNextImage(false, false); -} - - -bool -ShowImageView::HasNextFile() -{ - entry_ref ref; - return _FindNextImage(&fCurrentRef, &ref, true, false); -} - - -bool -ShowImageView::HasPrevFile() -{ - entry_ref ref; - return _FindNextImage(&fCurrentRef, &ref, false, false); -} - - -bool -ShowImageView::_FirstFile() -{ - return _ShowNextImage(true, true); -} - - void ShowImageView::SetZoom(float zoom, BPoint where) { @@ -2126,11 +1805,10 @@ ShowImageView::Rotate(int degree) void ShowImageView::Flip(bool vertical) { - if (vertical) { + if (vertical) _UserDoImageOperation(ImageProcessor::kFlipLeftToRight); - } else { + else _UserDoImageOperation(ImageProcessor::kFlipTopToBottom); - } } diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 785467b8dd..684fcb011d 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -54,8 +54,10 @@ public: void SetTrackerMessenger( const BMessenger& trackerMessenger); - status_t SetImage(const entry_ref* ref); + status_t SetImage(const BMessage* message); + status_t SetImage(const entry_ref* ref, BBitmap* bitmap); const entry_ref* Image() const { return &fCurrentRef; } + BBitmap* Bitmap(); BPoint ImageToView(BPoint p) const; BPoint ViewToImage(BPoint p) const; @@ -77,10 +79,6 @@ public: { return fStretchToBounds; } void SetFullScreen(bool fullScreen); - BBitmap* GetBitmap(); - void GetName(BString* name); - void GetPath(BString* name); - void FixupScrollBar(enum orientation orientation, float bitmapLength, float viewLength); void FixupScrollBars(); @@ -94,26 +92,13 @@ public: void CopySelectionToClipboard(); - int32 CurrentPage(); - int32 PageCount(); - - void FirstPage(); - void LastPage(); - void NextPage(); - void PrevPage(); - void GoToPage(int32 page); - - bool NextFile(); - bool PrevFile(); - bool HasNextFile(); - bool HasPrevFile(); - void SetSlideShowDelay(float seconds); float GetSlideShowDelay() const { return fSlideShowDelay / 10.0; } bool SlideShowStarted() const { return fSlideShow; } void StartSlideShow(); void StopSlideShow(); + void SetZoom(float zoom, BPoint where = BPoint(-1, -1)); void ZoomIn(BPoint where = BPoint(-1, -1)); @@ -170,15 +155,6 @@ private: bool _ShouldStretch() const; float _FitToBoundsZoom() const; BRect _AlignBitmap(); - bool _IsImage(const entry_ref* pref); - static int _CompareEntries(const void* a, const void* b); - void _FreeEntries(BList* entries); - void _SetTrackerSelectionToCurrent(); - bool _FindNextImage(entry_ref* inCurrent, - entry_ref* outImage, bool next, - bool rewind); - bool _ShowNextImage(bool next, bool rewind); - bool _FirstFile(); BBitmap* _CopySelection(uchar alpha = 255, bool imageSize = true); bool _AddSupportedTypes(BMessage* message, @@ -219,11 +195,6 @@ private: // of the window that this was launched from entry_ref fCurrentRef; - int32 fDocumentIndex; - // of the image in the file - int32 fDocumentCount; - // number of images in the file - BBitmap* fBitmap; BBitmap* fDisplayBitmap; BBitmap* fSelectionBitmap; @@ -259,9 +230,8 @@ private: bool fShowCaption; BString fCaption; - BString fImageType; - // Type of image, for use in status bar and caption - BString fImageMime; + BString fFormatDescription; + BString fMimeType; bool fShowingPopUpMenu; diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 508516b08a..9a1604c355 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -51,16 +51,19 @@ #include "ShowImageView.h" +// BMessage field names used in Save messages +const char* kTypeField = "be:type"; +const char* kTranslatorField = "be:translator"; + + // #pragma mark -- ShowImageWindow::RecentDocumentsMenu + class ShowImageWindow::RecentDocumentsMenu : public BMenu { public: - RecentDocumentsMenu(const char* title, - menu_layout layout = B_ITEMS_IN_COLUMN); - bool AddDynamicItem(add_state addState); - -private: - void UpdateRecentDocumentsMenu(); + RecentDocumentsMenu(const char* title, + menu_layout layout = B_ITEMS_IN_COLUMN); + bool AddDynamicItem(add_state addState); }; @@ -102,18 +105,33 @@ ShowImageWindow::RecentDocumentsMenu::AddDynamicItem(add_state addState) } +// #pragma mark + + +// This is temporary solution for building BString with printf like format. +// will be removed in the future. +static void +bs_printf(BString* string, const char* format, ...) +{ + va_list ap; + char* buf; + + va_start(ap, format); + vasprintf(&buf, format, ap); + string->SetTo(buf); + free(buf); + va_end(ap); +} + + // #pragma mark -- ShowImageWindow -// BMessage field names used in Save messages -const char* kTypeField = "be:type"; -const char* kTranslatorField = "be:translator"; - - ShowImageWindow::ShowImageWindow(const entry_ref* ref, const BMessenger& trackerMessenger) : BWindow(BRect(5, 24, 250, 100), "", B_DOCUMENT_WINDOW, 0), + fNavigator(this), fSavePanel(NULL), fBar(NULL), fOpenMenu(NULL), @@ -127,9 +145,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref* ref, fShowCaption(true), fPrintSettings(NULL), fResizerWindowMessenger(NULL), - fResizeItem(NULL), - fHeight(0), - fWidth(0) + fResizeItem(NULL) { _LoadSettings(); @@ -181,34 +197,16 @@ ShowImageWindow::ShowImageWindow(const entry_ref* ref, SetSizeLimits(250, 100000, 100, 100000); // finish creating the window - fImageView->SetImage(ref); - fImageView->SetTrackerMessenger(trackerMessenger); - -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "LoadAlerts" - - if (InitCheck() != B_OK) { - BAlert* alert; - alert = new BAlert( - B_TRANSLATE("ShowImage"), - B_TRANSLATE("Could not load image! Either the file or an image " - "translator for it does not exist."), - B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - alert->Go(); - - // quit if file could not be opened + fNavigator.SetTrackerMessenger(trackerMessenger); + if (fNavigator.LoadImage(*ref) != B_OK) { + _LoadError(*ref); Quit(); - return; } -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "Menus" - // add View menu here so it can access ShowImageView methods - BMenu* menu = new BMenu(B_TRANSLATE("View")); + BMenu* menu = new BMenu(B_TRANSLATE_WITH_CONTEXT("View", "Menus")); _BuildViewMenu(menu, false); fBar->AddItem(menu); - UpdateTitle(); SetPulseRate(100000); // every 1/10 second; ShowImageView needs it for marching ants @@ -216,14 +214,12 @@ ShowImageWindow::ShowImageWindow(const entry_ref* ref, _MarkMenuItem(menu, MSG_SELECTION_MODE, fImageView->IsSelectionModeEnabled()); - WindowRedimension(fImageView->GetBitmap()); - fImageView->ResetZoom(); - fImageView->MakeFocus(true); // to receive KeyDown messages - Show(); - // Tell application object to query the clipboard // and tell this window if it contains interesting data or not be_app_messenger.SendMessage(B_CLIPBOARD_CHANGED); + + // The window will be shown on screen automatically + Run(); } @@ -233,22 +229,11 @@ ShowImageWindow::~ShowImageWindow() } -status_t -ShowImageWindow::InitCheck() -{ - if (!fImageView || fImageView->GetBitmap() == NULL) - return B_ERROR; - - return B_OK; -} - - void ShowImageWindow::UpdateTitle() { - BString path; - fImageView->GetPath(&path); - SetTitle(path.String()); + BPath path(fImageView->Image()); + SetTitle(path.Path()); } @@ -559,6 +544,41 @@ void ShowImageWindow::MessageReceived(BMessage* message) { switch (message->what) { + case kMsgImageLoaded: + { + bool first = fImageView->Bitmap() == NULL; + + status_t status = fImageView->SetImage(message); + if (status != B_OK) { + entry_ref ref; + message->FindRef("ref", &ref); + + _LoadError(ref); + + // quit if file could not be opened + if (first) + Quit(); + break; + } + + fImageType = message->FindString("type"); + + if (first) { + WindowRedimension(fImageView->Bitmap()); + fImageView->ResetZoom(); + fImageView->MakeFocus(true); + // to receive key messages + + Show(); + } else { + if (!fImageView->StretchesToBounds() + && !fImageView->ShrinksToBounds() + && !fFullScreen) + WindowRedimension(fImageView->Bitmap()); + } + break; + } + case MSG_MODIFIED: // If image has been modified due to a Cut or Paste fModified = true; @@ -583,95 +603,61 @@ ShowImageWindow::MessageReceived(BMessage* message) case MSG_UPDATE_STATUS: { - int32 pages = fImageView->PageCount(); - int32 curPage = fImageView->CurrentPage(); + int32 pages = fNavigator.PageCount(); + int32 currentPage = fNavigator.CurrentPage(); - bool enable = (pages > 1) ? true : false; + bool enable = pages > 1 ? true : false; _EnableMenuItem(fBar, MSG_PAGE_FIRST, enable); _EnableMenuItem(fBar, MSG_PAGE_LAST, enable); _EnableMenuItem(fBar, MSG_PAGE_NEXT, enable); _EnableMenuItem(fBar, MSG_PAGE_PREV, enable); fGoToPageMenu->SetEnabled(enable); - _EnableMenuItem(fBar, MSG_FILE_NEXT, fImageView->HasNextFile()); - _EnableMenuItem(fBar, MSG_FILE_PREV, fImageView->HasPrevFile()); + _EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile()); + _EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile()); if (fGoToPageMenu->CountItems() != pages) { // Only rebuild the submenu if the number of // pages is different - while (fGoToPageMenu->CountItems() > 0) + while (fGoToPageMenu->CountItems() > 0) { // Remove all page numbers delete fGoToPageMenu->RemoveItem(0L); + } for (int32 i = 1; i <= pages; i++) { // Fill Go To page submenu with an entry for each page - BMessage* pgomsg = new BMessage(MSG_GOTO_PAGE); - pgomsg->AddInt32("page", i); + BMessage* goTo = new BMessage(MSG_GOTO_PAGE); + goTo->AddInt32("page", i); char shortcut = 0; - if (i < 10) { + if (i < 10) shortcut = '0' + i; - } else if (i == 10) { - shortcut = '0'; - } BString strCaption; strCaption << i; - BMenuItem* item = new BMenuItem(strCaption.String(), pgomsg, + BMenuItem* item = new BMenuItem(strCaption.String(), goTo, shortcut); - if (curPage == i) + if (currentPage == i) item->SetMarked(true); fGoToPageMenu->AddItem(item); } } else { // Make sure the correct page is marked - BMenuItem *pcurItem; - pcurItem = fGoToPageMenu->ItemAt(curPage - 1); - if (!pcurItem->IsMarked()) { - pcurItem->SetMarked(true); - } + BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1); + if (currentItem != NULL && !currentItem->IsMarked()) + currentItem->SetMarked(true); } - BString status; - bool messageProvidesSize = false; - if (message->FindInt32("width", &fWidth) >= B_OK - && message->FindInt32("height", &fHeight) >= B_OK) { - status << fWidth << "x" << fHeight; - messageProvidesSize = true; - } - - BString str; - if (message->FindString("status", &str) == B_OK && str.Length() > 0) { - if (status.Length() > 0) - status << ", "; - status << str; - } - - if (messageProvidesSize) { - _UpdateResizerWindow(fWidth, fHeight); - if (!fImageView->StretchesToBounds() - && !fImageView->ShrinksToBounds() - && !fFullScreen) - WindowRedimension(fImageView->GetBitmap()); - } - - fStatusView->SetText(status); - + _UpdateStatusText(message); UpdateTitle(); break; } case MSG_UPDATE_STATUS_TEXT: { - BString status; - status << fWidth << "x" << fHeight; - BString str; - if (message->FindString("status", &str) == B_OK && str.Length() > 0) { - status << ", " << str; - fStatusView->SetText(status); - } + _UpdateStatusText(message); break; } @@ -718,25 +704,26 @@ ShowImageWindow::MessageReceived(BMessage* message) case MSG_PAGE_FIRST: if (_ClosePrompt()) - fImageView->FirstPage(); + fNavigator.FirstPage(); break; case MSG_PAGE_LAST: if (_ClosePrompt()) - fImageView->LastPage(); + fNavigator.LastPage(); break; case MSG_PAGE_NEXT: if (_ClosePrompt()) - fImageView->NextPage(); + fNavigator.NextPage(); break; case MSG_PAGE_PREV: if (_ClosePrompt()) - fImageView->PrevPage(); + fNavigator.PreviousPage(); break; - case MSG_GOTO_PAGE: { + case MSG_GOTO_PAGE: + { if (!_ClosePrompt()) break; @@ -744,19 +731,20 @@ ShowImageWindow::MessageReceived(BMessage* message) if (message->FindInt32("page", &newPage) != B_OK) break; - int32 curPage = fImageView->CurrentPage(); - int32 pages = fImageView->PageCount(); + int32 currentPage = fNavigator.CurrentPage(); + int32 pages = fNavigator.PageCount(); if (newPage > 0 && newPage <= pages) { - BMenuItem* pcurItem = fGoToPageMenu->ItemAt(curPage - 1); - BMenuItem* pnewItem = fGoToPageMenu->ItemAt(newPage - 1); - if (pcurItem && pnewItem) { - pcurItem->SetMarked(false); - pnewItem->SetMarked(true); - fImageView->GoToPage(newPage); + BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1); + BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1); + if (currentItem != NULL && newItem != NULL) { + currentItem->SetMarked(false); + newItem->SetMarked(true); + fNavigator.GoToPage(newPage); } } - } break; + break; + } case MSG_SHRINK_TO_WINDOW: _ResizeToWindow(true, message->what); @@ -768,12 +756,12 @@ ShowImageWindow::MessageReceived(BMessage* message) case MSG_FILE_PREV: if (_ClosePrompt()) - fImageView->PrevFile(); + fNavigator.PreviousFile(); break; case MSG_FILE_NEXT: if (_ClosePrompt()) - fImageView->NextFile(); + fNavigator.NextFile(); break; case MSG_ROTATE_90: @@ -869,31 +857,20 @@ ShowImageWindow::MessageReceived(BMessage* message) fImageView->SetScaleBilinear(_ToggleMenuItem(message->what)); break; - case MSG_OPEN_RESIZER_WINDOW: { - if (fImageView->GetBitmap() != NULL) { - BRect rect = fImageView->GetBitmap()->Bounds(); - _OpenResizerWindow(rect.IntegerWidth()+1, rect.IntegerHeight()+1); - } - } break; - - case MSG_RESIZE: { - int w = message->FindInt32("w"); - int h = message->FindInt32("h"); - fImageView->ResizeImage(w, h); - } break; - case MSG_RESIZER_WINDOW_QUIT: delete fResizerWindowMessenger; fResizerWindowMessenger = NULL; break; - case MSG_DESKTOP_BACKGROUND: { + case MSG_DESKTOP_BACKGROUND: + { BMessage message(B_REFS_RECEIVED); message.AddRef("refs", fImageView->Image()); // This is used in the Backgrounds code for scaled placement message.AddInt32("placement", 'scpl'); be_roster->Launch("application/x-vnd.haiku-backgrounds", &message); - } break; + break; + } default: BWindow::MessageReceived(message); @@ -902,6 +879,40 @@ ShowImageWindow::MessageReceived(BMessage* message) } +void +ShowImageWindow::_UpdateStatusText(const BMessage* message) +{ + BString status; + if (fImageView->Bitmap() != NULL) { + BRect bounds = fImageView->Bitmap()->Bounds(); + status << bounds.IntegerWidth() + 1 + << "x" << bounds.IntegerHeight() + 1 << ", " << fImageType; + } + + BString text; + if (message != NULL && message->FindString("status", &text) == B_OK + && text.Length() > 0) { + status << ", " << text; + } + + fStatusView->SetText(status); +} + + +void +ShowImageWindow::_LoadError(const entry_ref& ref) +{ + // TODO: give a better error message! + BAlert* alert = new BAlert(B_TRANSLATE("ShowImage"), + B_TRANSLATE_WITH_CONTEXT("Could not load image! Either the " + "file or an image translator for it does not exist.", + "LoadAlerts"), + B_TRANSLATE_WITH_CONTEXT("OK", "Alerts"), NULL, NULL, + B_WIDTH_AS_USUAL, B_INFO_ALERT); + alert->Go(); +} + + void ShowImageWindow::_SaveAs(BMessage* message) { @@ -977,22 +988,6 @@ ShowImageWindow::_SaveToFile(BMessage* message) } -// This is temporary solution for building BString with printf like format. -// will be removed in the future. -static void -bs_printf(BString* string, const char* format, ...) -{ - va_list ap; - char* buf; - - va_start(ap, format); - vasprintf(&buf, format, ap); - string->SetTo(buf); - free(buf); - va_end(ap); -} - - #undef B_TRANSLATE_CONTEXT #define B_TRANSLATE_CONTEXT "ClosePrompt" @@ -1002,34 +997,32 @@ ShowImageWindow::_ClosePrompt() if (!fModified) return true; - int32 page, count; - count = fImageView->PageCount(); - page = fImageView->CurrentPage(); - BString prompt, name; - fImageView->GetName(&name); + int32 count = fNavigator.PageCount(); + int32 page = fNavigator.CurrentPage(); + BString prompt; if (count > 1) { bs_printf(&prompt, B_TRANSLATE("The document '%s' (page %d) has been changed. Do you " "want to close the document?"), - name.String(), page); + fImageView->Image()->name, page); } else { bs_printf(&prompt, B_TRANSLATE("The document '%s' has been changed. Do you want to " "close the document?"), - name.String()); + fImageView->Image()->name); } - BAlert* pAlert = new BAlert(B_TRANSLATE("Close document"), prompt.String(), + BAlert* alert = new BAlert(B_TRANSLATE("Close document"), prompt.String(), B_TRANSLATE("Cancel"), B_TRANSLATE("Close")); - if (pAlert->Go() == 0) { + if (alert->Go() == 0) { // Cancel return false; - } else { - // Close - fModified = false; - return true; } + + // Close + fModified = false; + return true; } @@ -1112,9 +1105,7 @@ ShowImageWindow::_SavePrintOptions() bool ShowImageWindow::_PageSetup() { - BString name; - fImageView->GetName(&name); - BPrintJob printJob(name.String()); + BPrintJob printJob(fImageView->Image()->name); if (fPrintSettings != NULL) printJob.SetSettings(new BMessage(*fPrintSettings)); @@ -1132,16 +1123,13 @@ void ShowImageWindow::_PrepareForPrint() { if (fPrintSettings == NULL) { - BString name; - fImageView->GetName(&name); - - BPrintJob printJob(""); + BPrintJob printJob(fImageView->Image()->name); if (printJob.ConfigJob() == B_OK) fPrintSettings = printJob.Settings(); } - fPrintOptions.SetBounds(fImageView->GetBitmap()->Bounds()); - fPrintOptions.SetWidth(fImageView->GetBitmap()->Bounds().Width() + 1); + fPrintOptions.SetBounds(fImageView->Bitmap()->Bounds()); + fPrintOptions.SetWidth(fImageView->Bitmap()->Bounds().Width() + 1); new PrintOptionsWindow(BPoint(Frame().left + 30, Frame().top + 50), &fPrintOptions, this); @@ -1157,10 +1145,7 @@ ShowImageWindow::_Print(BMessage* msg) _SavePrintOptions(); - BString name; - fImageView->GetName(&name); - - BPrintJob printJob(name.String()); + BPrintJob printJob(fImageView->Image()->name); if (fPrintSettings) printJob.SetSettings(new BMessage(*fPrintSettings)); @@ -1178,7 +1163,7 @@ ShowImageWindow::_Print(BMessage* msg) if (lastPage < firstPage) lastPage = firstPage; - BBitmap* bitmap = fImageView->GetBitmap(); + BBitmap* bitmap = fImageView->Bitmap(); float imageWidth = bitmap->Bounds().Width() + 1.0; float imageHeight = bitmap->Bounds().Height() + 1.0; @@ -1186,7 +1171,8 @@ ShowImageWindow::_Print(BMessage* msg) switch (fPrintOptions.Option()) { case PrintOptions::kFitToPage: { float w1 = printableRect.Width()+1; - float w2 = imageWidth * (printableRect.Height() + 1) / imageHeight; + float w2 = imageWidth * (printableRect.Height() + 1) + / imageHeight; if (w2 < w1) width = w2; else diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index 31d41fd58e..4690d64f0c 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -11,11 +11,11 @@ #define SHOW_IMAGE_WINDOW_H -#include "PrintOptionsWindow.h" - - #include +#include "ImageFileNavigator.h" +#include "PrintOptionsWindow.h" + class BFilePanel; class BMenu; @@ -35,7 +35,6 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); - status_t InitCheck(); ShowImageView* GetShowImageView() const { return fImageView; } void UpdateTitle(); @@ -62,6 +61,8 @@ private: void _MarkSlideShowDelay(float value); void _ResizeToWindow(bool shrink, uint32 what); + void _UpdateStatusText(const BMessage* message); + void _LoadError(const entry_ref& ref); void _SaveAs(BMessage* message); // Handle Save As submenu choice void _SaveToFile(BMessage* message); @@ -79,24 +80,24 @@ private: void _CloseResizerWindow(); private: + ImageFileNavigator fNavigator; BFilePanel* fSavePanel; BMenuBar* fBar; - BMenu* fOpenMenu -; BMenu* fBrowseMenu; + BMenu* fOpenMenu; + BMenu* fBrowseMenu; BMenu* fGoToPageMenu; BMenu* fSlideShowDelay; ShowImageView* fImageView; ShowImageStatusView* fStatusView; bool fModified; bool fFullScreen; - BRect fWindowFrame; bool fShowCaption; + BRect fWindowFrame; BMessage* fPrintSettings; PrintOptions fPrintOptions; BMessenger* fResizerWindowMessenger; BMenuItem* fResizeItem; - int32 fHeight; - int32 fWidth; + BString fImageType; };