diff --git a/src/apps/showimage/EntryMenuItem.cpp b/src/apps/showimage/EntryMenuItem.cpp deleted file mode 100644 index 80ccc63144..0000000000 --- a/src/apps/showimage/EntryMenuItem.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2003-2009 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Pfeiffer, laplace@haiku-os.org - */ - -#include "EntryMenuItem.h" - -#include -#include - - -EntryMenuItem::EntryMenuItem(entry_ref* ref, const char* label, - BMessage* message, char shortcut, uint32 modifiers) - : - BMenuItem(label, message, shortcut, modifiers), - fEntry(*ref), - fSmallIcon(NULL) -{ -} - - -EntryMenuItem::~EntryMenuItem() -{ - delete fSmallIcon; -} - - -void -EntryMenuItem::GetContentSize(float* width, float* height) -{ - BMenuItem::GetContentSize(width, height); - *width += kTextIndent; - if (*height < kIconSize) { - *height = kIconSize; - } -} - - -void -EntryMenuItem::DrawContent() -{ - BView* view = Menu(); - BPoint pos(view->PenLocation()); - - if (fSmallIcon == NULL) { - fSmallIcon = LoadIcon(); // Load on demand - } - - view->MovePenBy(kTextIndent, 0); - BMenuItem::DrawContent(); - - if (fSmallIcon) { - view->SetDrawingMode(B_OP_OVER); - view->DrawBitmap(fSmallIcon, pos); - } -} - - -BBitmap* -EntryMenuItem::GetIcon(BMimeType* mimeType) -{ - BBitmap* icon; - icon = new BBitmap(BRect(0, 0, kIconSize - 1, kIconSize - 1), B_CMAP8); - if (mimeType->GetIcon(icon, B_MINI_ICON) != B_OK) { - delete icon; - icon = NULL; - } - return icon; -} - - -BBitmap* -EntryMenuItem::LoadIcon() -{ - BBitmap* icon = NULL; - BNode node(&fEntry); - BNodeInfo info(&node); - char type[B_MIME_TYPE_LENGTH+1]; - - // Note: BNodeInfo::GetTrackerIcon does not work as expected! - - // Try to get the icon stored in file attribute - icon = new BBitmap(BRect(0, 0, kIconSize-1, kIconSize-1), B_CMAP8); - if (info.GetIcon(icon, B_MINI_ICON) == B_OK) { - return icon; - } - delete icon; - icon = NULL; - - // Get the icon from type - if (info.GetType(type) == B_OK) { - BMimeType mimeType(type); - BMimeType superType; - if (mimeType.InitCheck() == B_OK) { - icon = GetIcon(&mimeType); - // Or super type - if (icon == NULL && mimeType.GetSupertype(&superType) == B_OK) { - icon = GetIcon(&superType); - } - } - } - - return icon; -} - diff --git a/src/apps/showimage/EntryMenuItem.h b/src/apps/showimage/EntryMenuItem.h deleted file mode 100644 index f128ba189c..0000000000 --- a/src/apps/showimage/EntryMenuItem.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2003-2009 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Pfeiffer, laplace@haiku-os.org - */ -#ifndef ENTRY_MENU_ITEM_H -#define ENTRY_MENU_ITEM_H - - -#include -#include -#include -#include - - -class EntryMenuItem : public BMenuItem { -public: - EntryMenuItem(entry_ref* entry, const char* label, - BMessage* message, char shortcut = 0, uint32 modifiers = 0); - ~EntryMenuItem(); - - void GetContentSize(float* width, float* height); - void DrawContent(); - -private: - BBitmap* GetIcon(BMimeType* mimeType); - BBitmap* LoadIcon(); - - entry_ref fEntry; - BBitmap* fSmallIcon; - - enum { - kIconSize = 16, - kTextIndent = kIconSize + 4, - }; -}; - - -#endif // ENTRY_MENU_ITEM_H - diff --git a/src/apps/showimage/ImageCache.cpp b/src/apps/showimage/ImageCache.cpp index 1161d8c253..fac1410cf0 100644 --- a/src/apps/showimage/ImageCache.cpp +++ b/src/apps/showimage/ImageCache.cpp @@ -35,6 +35,22 @@ struct QueueEntry { // #pragma mark - +BitmapOwner::BitmapOwner(BBitmap* bitmap) + : + fBitmap(bitmap) +{ +} + + +BitmapOwner::~BitmapOwner() +{ + delete fBitmap; +} + + +// #pragma mark - + + ImageCache::ImageCache() : fLocker("image cache"), @@ -177,16 +193,14 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry) && ioExtension.AddInt32("/documentIndex", queueEntry->page) != B_OK) return B_NO_MEMORY; -// TODO: rethink this! -#if 0 - if (fProgressWindow != NULL) { - BMessage progress(kMsgProgressStatusUpdate); - if (ioExtension.AddMessenger("/progressMonitor", - fProgressWindow) == B_OK - && ioExtension.AddMessage("/progressMessage", &progress) == B_OK) - fProgressWindow->Start(); + // TODO: this doesn't work for images that already are in the queue... + if (!queueEntry->listeners.empty()) { + BMessage progress(kMsgImageCacheProgressUpdate); + progress.AddRef("ref", &queueEntry->ref); + ioExtension.AddMessenger("/progressMonitor", + *queueEntry->listeners.begin()); + ioExtension.AddMessage("/progressMessage", &progress); } -#endif // Translate image data and create a new ShowImage window @@ -198,12 +212,6 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry) status = roster->Translate(&file, &info, &ioExtension, &outstream, B_TRANSLATOR_BITMAP); } - -#if 0 - if (fProgressWindow != NULL) - fProgressWindow->Stop(); -#endif - if (status != B_OK) return status; @@ -211,6 +219,12 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry) if (outstream.DetachBitmap(&bitmap) != B_OK) return B_ERROR; + entry->bitmapOwner = new(std::nothrow) BitmapOwner(bitmap); + if (entry->bitmapOwner == NULL) { + delete bitmap; + return B_NO_MEMORY; + } + entry->ref = queueEntry->ref; entry->page = queueEntry->page; entry->bitmap = bitmap; @@ -244,6 +258,8 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry) entry = fCacheEntriesByAge.RemoveHead(); fBytes -= entry->bitmap->BitsLength(); fCacheMap.erase(std::make_pair(entry->ref, entry->page)); + + entry->bitmapOwner->ReleaseReference(); delete entry; } @@ -259,7 +275,7 @@ ImageCache::_NotifyListeners(CacheEntry* entry, QueueEntry* queueEntry) if (queueEntry->listeners.empty()) return; - BMessage notification(kMsgImageLoaded); + BMessage notification(kMsgImageCacheImageLoaded); _BuildNotification(entry, notification); if (queueEntry->status != B_OK) @@ -278,7 +294,7 @@ ImageCache::_NotifyTarget(CacheEntry* entry, const BMessenger* target) if (target == NULL) return; - BMessage notification(kMsgImageLoaded); + BMessage notification(kMsgImageCacheImageLoaded); _BuildNotification(entry, notification); target->SendMessage(¬ification); @@ -291,10 +307,14 @@ ImageCache::_BuildNotification(CacheEntry* entry, BMessage& message) if (entry == NULL) return; + entry->bitmapOwner->AcquireReference(); + // this is the reference owned by the target + message.AddString("type", entry->type); message.AddString("mime", entry->mimeType); message.AddRef("ref", &entry->ref); message.AddInt32("page", entry->page); message.AddInt32("pageCount", entry->pageCount); message.AddPointer("bitmap", (void*)entry->bitmap); + message.AddPointer("bitmapOwner", (void*)entry->bitmapOwner); } diff --git a/src/apps/showimage/ImageCache.h b/src/apps/showimage/ImageCache.h index 92a8ac936b..58b1e39e91 100644 --- a/src/apps/showimage/ImageCache.h +++ b/src/apps/showimage/ImageCache.h @@ -15,6 +15,7 @@ #include #include +#include class BBitmap; @@ -24,7 +25,18 @@ struct QueueEntry; enum { - kMsgImageLoaded = 'ifnL' + kMsgImageCacheImageLoaded = 'icIL', + kMsgImageCacheProgressUpdate = 'icPU' +}; + + +class BitmapOwner : public Referenceable { +public: + BitmapOwner(BBitmap* bitmap); + virtual ~BitmapOwner(); + +private: + BBitmap* fBitmap; }; @@ -33,6 +45,7 @@ struct CacheEntry : DoublyLinkedListLinkImpl { int32 page; int32 pageCount; BBitmap* bitmap; + BitmapOwner* bitmapOwner; BString type; BString mimeType; }; diff --git a/src/apps/showimage/Jamfile b/src/apps/showimage/Jamfile index 311dbc1163..541f405f85 100644 --- a/src/apps/showimage/Jamfile +++ b/src/apps/showimage/Jamfile @@ -6,7 +6,6 @@ UsePublicHeaders [ FDirName be_apps Tracker ] ; SubDirHdrs $(HAIKU_TOP) src kits tracker ; Application ShowImage : - EntryMenuItem.cpp Filter.cpp ImageCache.cpp ImageFileNavigator.cpp @@ -19,11 +18,10 @@ Application ShowImage : ShowImageUndo.cpp ShowImageView.cpp ShowImageWindow.cpp - : libshared.a - be tracker translation $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSTDC++) - $(TARGET_LIBSUPC++) + : libshared.a be tracker translation $(HAIKU_LOCALE_LIBS) + $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) : ShowImage.rdef - ; +; DoCatalogs ShowImage : x-vnd.Haiku-ShowImage diff --git a/src/apps/showimage/ProgressWindow.cpp b/src/apps/showimage/ProgressWindow.cpp index 9fb577c889..569f3adc26 100644 --- a/src/apps/showimage/ProgressWindow.cpp +++ b/src/apps/showimage/ProgressWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -7,6 +7,7 @@ #include "ProgressWindow.h" #include +#include #include #include @@ -24,10 +25,13 @@ static const uint32 kMsgShow = 'show'; #define B_TRANSLATE_CONTEXT "ProgressWindow" -ProgressWindow::ProgressWindow(BWindow* referenceWindow, bool center) +ProgressWindow::ProgressWindow() : BWindow(BRect(0, 0, 250, 100), B_TRANSLATE("Progress monitor"), - B_MODAL_WINDOW_LOOK, B_FLOATING_APP_WINDOW_FEEL, + B_MODAL_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,// B_FLOATING_APP_WINDOW_FEEL, + // TODO: a bug in the app_server prevents an initial floating-app feel + // to work correctly; the window will then not be visible for the first + // image, even though it's later set to normal feel in that case. B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS), fRunner(NULL) { @@ -45,14 +49,7 @@ ProgressWindow::ProgressWindow(BWindow* referenceWindow, bool center) fStatusBar->SetResizingMode(B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT); view->AddChild(fStatusBar); - BScreen screen(referenceWindow); - if (!center) { - ResizeTo(Bounds().Width(), height + 9); - // TODO: frame width! - MoveTo(screen.Frame().left + 5, - screen.Frame().bottom - Bounds().Height() - 5); - } else - CenterIn(screen.Frame()); + ResizeTo(Bounds().Width(), height + 9); Run(); } @@ -65,10 +62,27 @@ ProgressWindow::~ProgressWindow() void -ProgressWindow::Start() +ProgressWindow::Start(BWindow* referenceWindow, bool center) { BAutolock _(this); + BScreen screen(referenceWindow); + if (!center) { + BMessage settings; + GetDecoratorSettings(&settings); + + int32 borderWidth; + if (settings.FindInt32("border", &borderWidth) != B_OK) + borderWidth = 5; + + MoveTo(screen.Frame().left + borderWidth, + screen.Frame().bottom - Bounds().Height() - borderWidth); + } else + CenterIn(screen.Frame()); + + SetFeel(referenceWindow->IsHidden() + ? B_NORMAL_WINDOW_FEEL : B_FLOATING_APP_WINDOW_FEEL); + fRetrievedUpdate = false; fRetrievedShow = false; delete fRunner; @@ -104,7 +118,7 @@ ProgressWindow::MessageReceived(BMessage *message) fRetrievedShow = true; break; - case kMsgProgressStatusUpdate: + case kMsgProgressUpdate: float percent; if (message->FindFloat("percent", &percent) == B_OK) fStatusBar->Update(percent - fStatusBar->CurrentValue()); diff --git a/src/apps/showimage/ProgressWindow.h b/src/apps/showimage/ProgressWindow.h index 12c8fd9af6..8fce65c167 100644 --- a/src/apps/showimage/ProgressWindow.h +++ b/src/apps/showimage/ProgressWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef PROGRESS_WINDOW_H @@ -13,15 +13,21 @@ class BMessageRunner; class BStatusBar; +// public message constants +enum { + kMsgProgressUpdate = 'pwPU' +}; + + class ProgressWindow : public BWindow { public: - ProgressWindow(BWindow* referenceWindow, - bool center = false); + ProgressWindow(); virtual ~ProgressWindow(); virtual void MessageReceived(BMessage* message); - void Start(); + void Start(BWindow* referenceWindow, + bool center = false); void Stop(); private: diff --git a/src/apps/showimage/ShowImageApp.cpp b/src/apps/showimage/ShowImageApp.cpp index b1c18348fa..6c4c7f9acd 100644 --- a/src/apps/showimage/ShowImageApp.cpp +++ b/src/apps/showimage/ShowImageApp.cpp @@ -9,6 +9,7 @@ * Ryan Leavengood */ + #include "ShowImageApp.h" #include @@ -26,12 +27,13 @@ #include "ShowImageWindow.h" -#define WINDOWS_TO_IGNORE 1 - #undef B_TRANSLATE_CONTEXT #define B_TRANSLATE_CONTEXT "AboutWindow" + const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage"; +const int32 kWindowsToIgnore = 1; + // ignore the always open file panel ShowImageApp::ShowImageApp() @@ -87,7 +89,7 @@ ShowImageApp::ArgvReceived(int32 argc, char **argv) void ShowImageApp::ReadyToRun() { - if (CountWindows() == WINDOWS_TO_IGNORE) + if (CountWindows() == kWindowsToIgnore) fOpenPanel->Show(); else { // If image windows are already open @@ -109,9 +111,6 @@ ShowImageApp::MessageReceived(BMessage* message) fOpenPanel->Show(); break; - case MSG_WINDOW_QUIT: - break; - case B_CANCEL: // File open panel was closed, // start checking count of open windows @@ -137,6 +136,7 @@ ShowImageApp::AboutRequested() "Michael Wilber", "Michael Pfeiffer", "Ryan Leavengood", + "Axel Dörfler", NULL }; BAboutWindow about(B_TRANSLATE("ShowImage"), 2003, authors); @@ -149,7 +149,7 @@ ShowImageApp::Pulse() { // Bug: The BFilePanel is automatically closed if the volume that // is displayed is unmounted. - if (!IsLaunching() && CountWindows() <= WINDOWS_TO_IGNORE) { + if (!IsLaunching() && CountWindows() <= kWindowsToIgnore) { // If the application is not launching and // all windows are closed except for the file open panel, // quit the application @@ -212,8 +212,8 @@ ShowImageApp::_BroadcastToWindows(BMessage* message) const int32 count = CountWindows(); for (int32 i = 0; i < count; i ++) { // BMessenger checks for us if BWindow is still a valid object - BMessenger msgr(WindowAt(i)); - msgr.SendMessage(message); + BMessenger messenger(WindowAt(i)); + messenger.SendMessage(message); } } @@ -238,7 +238,7 @@ ShowImageApp::_CheckClipboard() be_clipboard->Unlock(); } - BMessage msg(MSG_CLIPBOARD_CHANGED); + BMessage msg(B_CLIPBOARD_CHANGED); msg.AddBool("data_available", dataAvailable); _BroadcastToWindows(&msg); } diff --git a/src/apps/showimage/ShowImageApp.h b/src/apps/showimage/ShowImageApp.h index 27c610b0fb..3139e87c40 100644 --- a/src/apps/showimage/ShowImageApp.h +++ b/src/apps/showimage/ShowImageApp.h @@ -18,6 +18,11 @@ #include +enum { + MSG_FILE_OPEN = 'mFOP', +}; + + class ShowImageApp : public BApplication { public: ShowImageApp(); diff --git a/src/apps/showimage/ShowImageConstants.h b/src/apps/showimage/ShowImageConstants.h index 1c02ba59cf..342ad30b42 100644 --- a/src/apps/showimage/ShowImageConstants.h +++ b/src/apps/showimage/ShowImageConstants.h @@ -16,49 +16,8 @@ enum { - MSG_CAPTURE_MOUSE = 'mCPM', - MSG_CHANGE_FOCUS = 'mCFS', - MSG_FILE_OPEN = 'mFOP', - MSG_WINDOW_QUIT = 'mWQT', - MSG_OUTPUT_TYPE = 'BTMN', - MSG_SAVE_PANEL = 'mFSP', - MSG_CLEAR_SELECT = 'mCSL', - MSG_SELECT_ALL = 'mSAL', - MSG_CLIPBOARD_CHANGED = 'mCLP', - MSG_MODIFIED = 'mMOD', - MSG_UPDATE_STATUS = 'mUPS', - MSG_UPDATE_STATUS_TEXT = 'mUPT', MSG_UNDO_STATE = 'mUNS', - MSG_SELECTION_MODE = 'mSLM', - MSG_SELECTION = 'mSEL', - MSG_PAGE_FIRST = 'mPGF', - MSG_PAGE_LAST = 'mPGL', - MSG_PAGE_NEXT = 'mPGN', - MSG_PAGE_PREV = 'mPGP', - MSG_GOTO_PAGE = 'mGTP', - MSG_FILE_NEXT = 'mFLN', - MSG_FILE_PREV = 'mFLP', - kMsgDeleteCurrentFile = 'mDcF', - MSG_SHRINK_TO_WINDOW = 'mSTW', - MSG_STRETCH_TO_WINDOW = 'mZTW', - MSG_ROTATE_90 = 'mR90', - MSG_ROTATE_270 = 'mR27', - MSG_FLIP_LEFT_TO_RIGHT = 'mFLR', - MSG_FLIP_TOP_TO_BOTTOM = 'mFTB', - MSG_SLIDE_SHOW = 'mSSW', - MSG_SLIDE_SHOW_DELAY = 'mSSD', - MSG_FULL_SCREEN = 'mFSC', - MSG_EXIT_FULL_SCREEN = 'mEFS', - MSG_SHOW_CAPTION = 'mSCP', - MSG_PAGE_SETUP = 'mPSU', - MSG_PREPARE_PRINT = 'mPPT', - MSG_PRINT = 'mPRT', - MSG_ZOOM_IN = 'mZIN', - MSG_ZOOM_OUT = 'mZOU', - MSG_ORIGINAL_SIZE = 'mOSZ', - MSG_SCALE_BILINEAR = 'mSBL', - MSG_DESKTOP_BACKGROUND = 'mDBG', - kMsgProgressStatusUpdate = 'SIup' + MSG_PRINT = 'mPRT' }; diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 79528e962a..67738b6a66 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -12,6 +12,7 @@ * yellowTAB GmbH * Bernd Korz * Stephan Aßmus + * Axel Dörfler, axeld@pinc-software.de */ @@ -49,9 +50,8 @@ #include -#include "ProgressWindow.h" +#include "ImageCache.h" #include "ShowImageApp.h" -#include "ShowImageConstants.h" #include "ShowImageWindow.h" @@ -68,11 +68,16 @@ class PopUpMenu : public BPopUpMenu { }; +// the delay time for hiding the cursor in 1/10 seconds (the pulse rate) +#define HIDE_CURSOR_DELAY_TIME 20 #define SHOW_IMAGE_ORIENTATION_ATTRIBUTE "ShowImage:orientation" + + const rgb_color kBorderColor = { 0, 0, 0, 255 }; enum ShowImageView::image_orientation -ShowImageView::fTransformation[ImageProcessor::kNumberOfAffineTransformations][kNumberOfOrientations] = { +ShowImageView::fTransformation[ImageProcessor::kNumberOfAffineTransformations] + [kNumberOfOrientations] = { // rotate 90° {k90, k180, k270, k0, k270V, k0V, k90V, k0H}, // rotate -90° @@ -168,6 +173,7 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, uint32 flags) : BView(rect, name, resizingMode, flags), + fBitmapOwner(NULL), fBitmap(NULL), fDisplayBitmap(NULL), fSelectionBitmap(NULL), @@ -178,10 +184,8 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, fBitmapLocationInView(0.0, 0.0), - fShrinkToBounds(true), fStretchToBounds(false), - fFitToBoundsZoom(1.0), - fFullScreen(false), + fHideCursor(false), fScrollingBitmap(false), fCreatingSelection(false), fFirstPoint(0.0, 0.0), @@ -194,14 +198,13 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, fShowCaption(false), fShowingPopUpMenu(false), fHideCursorCountDown(HIDE_CURSOR_DELAY_TIME), - fIsActiveWin(true), - fProgressWindow(NULL) + fIsActiveWin(true) { ShowImageSettings* settings; settings = my_app->Settings(); if (settings->Lock()) { - fShrinkToBounds = settings->GetBool("ShrinksToBounds", fShrinkToBounds); - fStretchToBounds = settings->GetBool("ZoomToBounds", fStretchToBounds); + fStretchToBounds = settings->GetBool("StretchToBounds", + fStretchToBounds); fSlideShowDelay = settings->GetInt32("SlideShowDelay", fSlideShowDelay); fScaleBilinear = settings->GetBool("ScaleBilinear", fScaleBilinear); settings->Unlock(); @@ -246,8 +249,7 @@ ShowImageView::Pulse() } #endif - // Hide cursor in full screen mode - if (fFullScreen && !fHasSelection && !fShowingPopUpMenu && fIsActiveWin) { + if (fHideCursor && !fHasSelection && !fShowingPopUpMenu && fIsActiveWin) { if (fHideCursorCountDown <= 0) be_app->ObscureCursor(); else @@ -316,7 +318,12 @@ ShowImageView::_DeleteBitmap() delete fDisplayBitmap; fDisplayBitmap = NULL; - // TODO: the bitmap is currently only owned by the cache!!! + if (fBitmapOwner != NULL) + fBitmapOwner->ReleaseReference(); + else + delete fBitmap; + + fBitmapOwner = NULL; fBitmap = NULL; } @@ -342,6 +349,8 @@ ShowImageView::SetImage(const BMessage* message) if (status == B_OK) { fFormatDescription = message->FindString("type"); fMimeType = message->FindString("mime"); + + message->FindPointer("bitmapOwner", (void**)&fBitmapOwner); } return status; @@ -417,9 +426,7 @@ ShowImageView::SetImage(const entry_ref* ref, BBitmap* bitmap) be_roster->AddToRecentDocuments(ref, kApplicationSignature); - fFitToBoundsZoom = _FitToBoundsZoom(); - ResetZoom(); - Invalidate(); + FitToBounds(); _Notify(); return B_OK; } @@ -479,34 +486,23 @@ ShowImageView::SetShowCaption(bool show) } -void -ShowImageView::SetShrinkToBounds(bool enable) -{ - if (fShrinkToBounds != enable) { - _SettingsSetBool("ShrinksToBounds", enable); - fShrinkToBounds = enable; - if (enable) - SetZoom(fFitToBoundsZoom); - } -} - - void ShowImageView::SetStretchToBounds(bool enable) { if (fStretchToBounds != enable) { - _SettingsSetBool("ZoomToBounds", enable); + _SettingsSetBool("StretchToBounds", enable); fStretchToBounds = enable; if (enable) - SetZoom(fFitToBoundsZoom); + FitToBounds(); } } void -ShowImageView::SetFullScreen(bool fullScreen) +ShowImageView::SetHideIdlingCursor(bool hide) { - fFullScreen = fullScreen; + fHideCursor = hide; + FitToBounds(); } @@ -531,35 +527,16 @@ ShowImageView::SetScaleBilinear(bool enabled) void ShowImageView::AttachedToWindow() { - ResetZoom(); + FitToBounds(); fUndo.SetWindow(Window()); FixupScrollBars(); - - fProgressWindow = new ProgressWindow(Window()); } void -ShowImageView::DetachedFromWindow() +ShowImageView::FrameResized(float width, float height) { - fProgressWindow->Lock(); - fProgressWindow->Quit(); -} - - -bool -ShowImageView::_ShouldShrink() const -{ - return fShrinkToBounds && fBitmap->Bounds().Width() > Bounds().Width() - && fBitmap->Bounds().Height() > Bounds().Height(); -} - - -bool -ShowImageView::_ShouldStretch() const -{ - return fStretchToBounds && fBitmap->Bounds().Width() < Bounds().Width() - && fBitmap->Bounds().Height() < Bounds().Height(); + FixupScrollBars(); } @@ -748,17 +725,6 @@ ShowImageView::Draw(BRect updateRect) } -void -ShowImageView::FrameResized(float /*width*/, float /*height*/) -{ - if (fBitmap == NULL) - return; - - fFitToBoundsZoom = _FitToBoundsZoom(); - SetZoom(_ShouldStretch() ? fFitToBoundsZoom : fZoom); -} - - BBitmap* ShowImageView::_CopySelection(uchar alpha, bool imageSize) { @@ -1336,6 +1302,12 @@ ShowImageView::KeyDown(const char* bytes, int32 numBytes) case B_DELETE: _SendMessageToWindow(kMsgDeleteCurrentFile); break; + case '0': + FitToBounds(); + break; + case '1': + SetZoom(1.0f); + break; case '+': case '=': ZoomIn(); @@ -1394,9 +1366,9 @@ ShowImageView::_ShowPopUpMenu(BPoint screen) if (!fShowingPopUpMenu) { PopUpMenu* menu = new PopUpMenu("PopUpMenu", this); - ShowImageWindow* showImage = dynamic_cast(Window()); - if (showImage) - showImage->BuildContextMenu(menu); + ShowImageWindow* window = dynamic_cast(Window()); + if (window != NULL) + window->BuildContextMenu(menu); screen += BPoint(2, 2); menu->Go(screen, true, true, true); @@ -1421,22 +1393,6 @@ void ShowImageView::MessageReceived(BMessage* message) { switch (message->what) { -// TODO! -#if 0 - case B_SIMPLE_DATA: - if (message->WasDropped()) { - uint32 type; - int32 count; - status_t ret = message->GetInfo("refs", &type, &count); - if (ret == B_OK && type == B_REF_TYPE) { - // If file was dropped, open it as the selection - entry_ref ref; - if (message->FindRef("refs", 0, &ref) == B_OK) - SetImage(&ref); - } - } - break; -#endif case B_COPY_TARGET: _HandleDrop(message); break; @@ -1456,7 +1412,8 @@ ShowImageView::MessageReceived(BMessage* message) void -ShowImageView::FixupScrollBar(orientation o, float bitmapLength, float viewLength) +ShowImageView::FixupScrollBar(orientation o, float bitmapLength, + float viewLength) { float prop, range; BScrollBar *psb; @@ -1609,10 +1566,11 @@ ShowImageView::CopySelectionToClipboard() void ShowImageView::SetZoom(float zoom, BPoint where) { + float fitToBoundsZoom = _FitToBoundsZoom(); if (zoom > 32) zoom = 32; - if (zoom < fFitToBoundsZoom / 2) - zoom = fFitToBoundsZoom / 2; + if (zoom < fitToBoundsZoom / 2) + zoom = fitToBoundsZoom / 2; if (zoom == fZoom) { // window size might have changed @@ -1652,8 +1610,9 @@ ShowImageView::ZoomIn(BPoint where) // snap zoom to "fit to bounds", and "original size" float zoom = fZoom * 1.2; float zoomSnap = fZoom * 1.25; - if (fZoom < fFitToBoundsZoom && zoomSnap > fFitToBoundsZoom) - zoom = fFitToBoundsZoom; + float fitToBoundsZoom = _FitToBoundsZoom(); + if (fZoom < fitToBoundsZoom - 0.001 && zoomSnap > fitToBoundsZoom) + zoom = fitToBoundsZoom; if (fZoom < 1.0 && zoomSnap > 1.0) zoom = 1.0; @@ -1667,8 +1626,9 @@ ShowImageView::ZoomOut(BPoint where) // snap zoom to "fit to bounds", and "original size" float zoom = fZoom / 1.2; float zoomSnap = fZoom / 1.25; - if (fZoom > fFitToBoundsZoom && zoomSnap < fFitToBoundsZoom) - zoom = fFitToBoundsZoom; + float fitToBoundsZoom = _FitToBoundsZoom(); + if (fZoom > fitToBoundsZoom + 0.001 && zoomSnap < fitToBoundsZoom) + zoom = fitToBoundsZoom; if (fZoom > 1.0 && zoomSnap < 1.0) zoom = 1.0; @@ -1676,21 +1636,21 @@ ShowImageView::ZoomOut(BPoint where) } -/*! Resets the zoom to what it should be when opening an image, depending - on the current settings. +/*! Fits to image to the view bounds. */ void -ShowImageView::ResetZoom() +ShowImageView::FitToBounds() { if (fBitmap == NULL) return; - fFitToBoundsZoom = _FitToBoundsZoom(); - - if (_ShouldShrink() || _ShouldStretch()) - SetZoom(fFitToBoundsZoom); + float fitToBoundsZoom = _FitToBoundsZoom(); + if (!fStretchToBounds && fitToBoundsZoom > 1.0f) + SetZoom(1.0f); else - SetZoom(1.0); + SetZoom(fitToBoundsZoom); + + FixupScrollBars(); } diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 3ad38b2939..eff4e24394 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -15,10 +15,6 @@ #define SHOW_IMAGE_VIEW_H -#include "Filter.h" -#include "SelectionBox.h" -#include "ShowImageUndo.h" - #include #include #include @@ -26,11 +22,13 @@ #include #include +#include "Filter.h" +#include "SelectionBox.h" +#include "ShowImageUndo.h" -// the delay time for hiding the cursor in 1/10 seconds (the pulse rate) -#define HIDE_CURSOR_DELAY_TIME 20 -class ProgressWindow; +class BitmapOwner; + class ShowImageView : public BView { public: @@ -39,9 +37,8 @@ public: virtual ~ShowImageView(); virtual void AttachedToWindow(); - virtual void DetachedFromWindow(); + virtual void FrameResized(float width, float height); virtual void Draw(BRect updateRect); - virtual void FrameResized(float width, float height); virtual void MouseDown(BPoint point); virtual void MouseMoved(BPoint point, uint32 state, const BMessage* dragMessage); @@ -68,16 +65,14 @@ public: void SaveToFile(BDirectory* dir, const char* name, BBitmap* bitmap, const translation_format* format); + void SetScaleBilinear(bool b); - bool GetScaleBilinear() { return fScaleBilinear; } + bool ScaleBilinear() { return fScaleBilinear; } void SetShowCaption(bool show); - void SetShrinkToBounds(bool enable); - bool ShrinksToBounds() const - { return fShrinkToBounds; } void SetStretchToBounds(bool enable); bool StretchesToBounds() const { return fStretchToBounds; } - void SetFullScreen(bool fullScreen); + void SetHideIdlingCursor(bool hide); void FixupScrollBar(enum orientation orientation, float bitmapLength, float viewLength); @@ -99,11 +94,13 @@ public: void StartSlideShow(); void StopSlideShow(); + void FitToBounds(); void SetZoom(float zoom, BPoint where = BPoint(-1, -1)); + float Zoom() const + { return fZoom; } void ZoomIn(BPoint where = BPoint(-1, -1)); void ZoomOut(BPoint where = BPoint(-1, -1)); - void ResetZoom(); // Image manipulation void Rotate(int degree); // 90 and 270 only @@ -151,7 +148,6 @@ private: void _UserDoImageOperation( enum ImageProcessor::operation op, bool quiet = false); - bool _ShouldShrink() const; bool _ShouldStretch() const; float _FitToBoundsZoom() const; BRect _AlignBitmap(); @@ -193,6 +189,7 @@ private: ShowImageUndo fUndo; entry_ref fCurrentRef; + BitmapOwner* fBitmapOwner; BBitmap* fBitmap; BBitmap* fDisplayBitmap; BBitmap* fSelectionBitmap; @@ -203,10 +200,8 @@ private: BPoint fBitmapLocationInView; - bool fShrinkToBounds; bool fStretchToBounds; - float fFitToBoundsZoom; - bool fFullScreen; + bool fHideCursor; bool fScrollingBitmap; bool fCreatingSelection; BPoint fFirstPoint; @@ -238,8 +233,6 @@ private: bool fIsActiveWin; // Is the parent window the active window? - ProgressWindow* fProgressWindow; - image_orientation fImageOrientation; static image_orientation fTransformation[ ImageProcessor diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 3617691b35..034f9fd913 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -10,6 +10,7 @@ * Michael Pfeiffer * yellowTAB GmbH * Bernd Korz + * Axel Dörfler, axeld@pinc-software.de */ @@ -45,6 +46,7 @@ #include #include "ImageCache.h" +#include "ProgressWindow.h" #include "ShowImageApp.h" #include "ShowImageConstants.h" #include "ShowImageStatusView.h" @@ -56,6 +58,40 @@ const char* kTypeField = "be:type"; const char* kTranslatorField = "be:translator"; +// message constants +enum { + MSG_CAPTURE_MOUSE = 'mCPM', + MSG_CHANGE_FOCUS = 'mCFS', + MSG_WINDOW_QUIT = 'mWQT', + MSG_OUTPUT_TYPE = 'BTMN', + MSG_SAVE_PANEL = 'mFSP', + MSG_CLEAR_SELECT = 'mCSL', + MSG_SELECT_ALL = 'mSAL', + MSG_SELECTION_MODE = 'mSLM', + MSG_PAGE_FIRST = 'mPGF', + MSG_PAGE_LAST = 'mPGL', + MSG_PAGE_NEXT = 'mPGN', + MSG_PAGE_PREV = 'mPGP', + MSG_GOTO_PAGE = 'mGTP', + MSG_ZOOM_IN = 'mZIN', + MSG_ZOOM_OUT = 'mZOU', + MSG_SCALE_BILINEAR = 'mSBL', + MSG_DESKTOP_BACKGROUND = 'mDBG', + MSG_ROTATE_90 = 'mR90', + MSG_ROTATE_270 = 'mR27', + MSG_FLIP_LEFT_TO_RIGHT = 'mFLR', + MSG_FLIP_TOP_TO_BOTTOM = 'mFTB', + MSG_SLIDE_SHOW_DELAY = 'mSSD', + MSG_FULL_SCREEN = 'mFSC', + MSG_SHOW_CAPTION = 'mSCP', + MSG_PAGE_SETUP = 'mPSU', + MSG_PREPARE_PRINT = 'mPPT', + kMsgFitToWindow = 'mFtW', + kMsgOriginalSize = 'mOSZ', + kMsgStretchToWindow = 'mStW' +}; + + // This is temporary solution for building BString with printf like format. // will be removed in the future. static void @@ -87,6 +123,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref, fSlideShowDelay(NULL), fImageView(NULL), fStatusView(NULL), + fProgressWindow(new ProgressWindow()), fModified(false), fFullScreen(false), fShowCaption(true), @@ -106,7 +143,8 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref, // create the image view fImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL, - B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED); + B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED + | B_FRAME_EVENTS); // wrap a scroll view around the view BScrollView* scrollView = new BScrollView("image_scroller", fImageView, B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER); @@ -170,6 +208,8 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref, ShowImageWindow::~ShowImageWindow() { + fProgressWindow->Lock(); + fProgressWindow->Quit(); } @@ -212,7 +252,9 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu) menu->AddSeparatorItem(); _AddItemMenu(menu, B_TRANSLATE("Original size"), - MSG_ORIGINAL_SIZE, '1', 0, this); + kMsgOriginalSize, '1', 0, this); + _AddItemMenu(menu, B_TRANSLATE("Fit to window"), + kMsgFitToWindow, '0', 0, this); _AddItemMenu(menu, B_TRANSLATE("Zoom in"), MSG_ZOOM_IN, '+', 0, this); _AddItemMenu(menu, B_TRANSLATE("Zoom out"), MSG_ZOOM_OUT, '-', 0, this); @@ -221,13 +263,8 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu) if (!popupMenu || fFullScreen) { _AddItemMenu(menu, B_TRANSLATE("High-quality zooming"), MSG_SCALE_BILINEAR, 0, 0, this); - - menu->AddSeparatorItem(); - - _AddItemMenu(menu, B_TRANSLATE("Shrink to window"), - MSG_SHRINK_TO_WINDOW, 0, 0, this); _AddItemMenu(menu, B_TRANSLATE("Stretch to window"), - MSG_STRETCH_TO_WINDOW, 0, 0, this); + kMsgStretchToWindow, 0, 0, this); menu->AddSeparatorItem(); } @@ -240,9 +277,8 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu) MSG_SHOW_CAPTION, 0, 0, this); _MarkMenuItem(menu, MSG_SHOW_CAPTION, fShowCaption); - _MarkMenuItem(menu, MSG_SCALE_BILINEAR, fImageView->GetScaleBilinear()); - _MarkMenuItem(menu, MSG_SHRINK_TO_WINDOW, fImageView->ShrinksToBounds()); - _MarkMenuItem(menu, MSG_STRETCH_TO_WINDOW, fImageView->StretchesToBounds()); + _MarkMenuItem(menu, MSG_SCALE_BILINEAR, fImageView->ScaleBilinear()); + _MarkMenuItem(menu, kMsgStretchToWindow, fImageView->StretchesToBounds()); if (popupMenu) { menu->AddSeparatorItem(); @@ -369,10 +405,11 @@ ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, float value) void -ShowImageWindow::_WindowRedimension(BBitmap* bitmap) +ShowImageWindow::_ResizeWindowToImage() { + BBitmap* bitmap = fImageView->Bitmap(); BScreen screen; - if (!screen.IsValid()) + if (bitmap == NULL || !screen.IsValid()) return; // TODO: use View::GetPreferredSize() instead? @@ -410,13 +447,6 @@ ShowImageWindow::_WindowRedimension(BBitmap* bitmap) } -void -ShowImageWindow::FrameResized(float width, float height) -{ - BWindow::FrameResized(width, height); -} - - bool ShowImageWindow::_ToggleMenuItem(uint32 what) { @@ -467,22 +497,30 @@ ShowImageWindow::_MarkSlideShowDelay(float value) void -ShowImageWindow::_ResizeToWindow(bool shrink, uint32 what) +ShowImageWindow::Zoom(BPoint origin, float width, float height) { - bool enabled = _ToggleMenuItem(what); - if (shrink) - fImageView->SetShrinkToBounds(enabled); - else - fImageView->SetStretchToBounds(enabled); + _ToggleFullScreen(); } void ShowImageWindow::MessageReceived(BMessage* message) { + if (message->WasDropped()) { + uint32 type; + int32 count; + status_t status = message->GetInfo("refs", &type, &count); + if (status == B_OK && type == B_REF_TYPE) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + } + } + switch (message->what) { - case kMsgImageLoaded: + case kMsgImageCacheImageLoaded: { + fProgressWindow->Stop(); + bool first = fImageView->Bitmap() == NULL; entry_ref ref; message->FindRef("ref", &ref); @@ -505,18 +543,25 @@ ShowImageWindow::MessageReceived(BMessage* message) fNavigator.SetTo(ref, message->FindInt32("page"), message->FindInt32("pageCount")); + if (first || (!fImageView->StretchesToBounds() && !fFullScreen)) { + _ResizeWindowToImage(); + fImageView->FitToBounds(); + } 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 kMsgImageCacheProgressUpdate: + { + entry_ref ref; + if (message->FindRef("ref", &ref) == B_OK + && ref == fNavigator.CurrentRef()) { + message->what = kMsgProgressUpdate; + fProgressWindow->PostMessage(message); } break; } @@ -692,12 +737,13 @@ ShowImageWindow::MessageReceived(BMessage* message) break; } - case MSG_SHRINK_TO_WINDOW: - _ResizeToWindow(true, message->what); + case kMsgFitToWindow: + fImageView->FitToBounds(); break; - case MSG_STRETCH_TO_WINDOW: - _ResizeToWindow(false, message->what); + case kMsgStretchToWindow: + fImageView->SetStretchToBounds( + _ToggleMenuItem(kMsgStretchToWindow)); break; case MSG_FILE_PREV: @@ -802,7 +848,7 @@ ShowImageWindow::MessageReceived(BMessage* message) fImageView->ZoomOut(); break; - case MSG_ORIGINAL_SIZE: + case kMsgOriginalSize: fImageView->SetZoom(1.0); break; @@ -984,6 +1030,8 @@ ShowImageWindow::_LoadImage(bool forward) if (status != B_OK) return status; + fProgressWindow->Start(this); + // Preload previous/next images - two in the navigation direction, one // in the opposite direction. @@ -1034,10 +1082,12 @@ ShowImageWindow::_ToggleFullScreen() SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); } - fImageView->SetFullScreen(fFullScreen); - fImageView->SetShowCaption(fFullScreen && fShowCaption); MoveTo(frame.left, frame.top); ResizeTo(frame.Width(), frame.Height()); + + fImageView->SetHideIdlingCursor(fFullScreen); + fImageView->SetShowCaption(fFullScreen && fShowCaption); + fImageView->FitToBounds(); } @@ -1199,11 +1249,5 @@ ShowImageWindow::QuitRequested() return false; } - bool quit = _ClosePrompt(); - if (quit) { - // tell the app to forget about this window - be_app->PostMessage(MSG_WINDOW_QUIT); - } - - return quit; + return _ClosePrompt(); } diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index 6181da50ba..6c6987f870 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -21,10 +21,25 @@ class BFilePanel; class BMenu; class BMenuBar; class BMenuItem; +class ProgressWindow; class ShowImageView; class ShowImageStatusView; +// public message constants +enum { + MSG_MODIFIED = 'mMOD', + MSG_UPDATE_STATUS = 'mUPS', + MSG_UPDATE_STATUS_TEXT = 'mUPT', + MSG_SELECTION = 'mSEL', + MSG_FILE_NEXT = 'mFLN', + MSG_FILE_PREV = 'mFLP', + kMsgDeleteCurrentFile = 'mDcF', + MSG_SLIDE_SHOW = 'mSSW', + MSG_EXIT_FULL_SCREEN = 'mEFS' +}; + + class ShowImageWindow : public BWindow { public: ShowImageWindow(const entry_ref& ref, @@ -34,13 +49,13 @@ public: void BuildContextMenu(BMenu* menu); protected: - virtual void FrameResized(float width, float height); + virtual void Zoom(BPoint origin, float width, float height); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); private: void _AddMenus(BMenuBar* bar); - void _WindowRedimension(BBitmap* bitmap); + void _ResizeWindowToImage(); void _BuildViewMenu(BMenu* menu, bool popupMenu); BMenuItem* _AddItemMenu(BMenu* menu, const char* label, uint32 what, char shortcut, uint32 modifier, @@ -55,7 +70,6 @@ private: void _MarkMenuItem(BMenu* menu, uint32 what, bool marked); void _MarkSlideShowDelay(float value); - void _ResizeToWindow(bool shrink, uint32 what); void _UpdateStatusText(const BMessage* message); void _LoadError(const entry_ref& ref); @@ -82,6 +96,7 @@ private: BMenu* fSlideShowDelay; ShowImageView* fImageView; ShowImageStatusView* fStatusView; + ProgressWindow* fProgressWindow; bool fModified; bool fFullScreen; bool fShowCaption;