* Removed the "shrink to window" option. Instead, there is now a "Fit to window"

menu item that just does that. Additionally, the image is always fit to the
  window size when first shown, or if the full screen mode switches.
  That also fixes #6765, and #6810.
* The ImageCache now also passes a referenced BitmapOwner object, and bitmaps
  are now actually freed when it's allowed to.
* Pressing the zoom button will cause ShowImage to enter full screen again. For
  some reason this has been removed as part of r19540.
* The progress window is now visible again, although not that often, as you will
  only see it for images that were not in the queue already. The window is now
  known to the ShowImageWindow instead of the ShowImageView.
* Moved most constants out of ShowImageConstants.h to where they belong.
* Dropping an image now opens it in another window.
* Removed EntryMenuItem as it's no longer used anywhere.
* Minor other cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-11-14 23:45:15 +00:00
parent cb49ed72a6
commit e206972309
14 changed files with 291 additions and 414 deletions

View File

@ -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 <Node.h>
#include <NodeInfo.h>
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;
}

View File

@ -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 <Bitmap.h>
#include <Entry.h>
#include <MenuItem.h>
#include <Mime.h>
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

View File

@ -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(&notification);
@ -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);
}

View File

@ -15,6 +15,7 @@
#include <String.h>
#include <kernel/util/DoublyLinkedList.h>
#include <Referenceable.h>
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<CacheEntry> {
int32 page;
int32 pageCount;
BBitmap* bitmap;
BitmapOwner* bitmapOwner;
BString type;
BString mimeType;
};

View File

@ -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

View File

@ -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 <stdio.h>
#include <string.h>
#include <Autolock.h>
#include <Catalog.h>
@ -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());

View File

@ -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:

View File

@ -9,6 +9,7 @@
* Ryan Leavengood
*/
#include "ShowImageApp.h"
#include <stdio.h>
@ -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);
}

View File

@ -18,6 +18,11 @@
#include <FilePanel.h>
enum {
MSG_FILE_OPEN = 'mFOP',
};
class ShowImageApp : public BApplication {
public:
ShowImageApp();

View File

@ -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'
};

View File

@ -12,6 +12,7 @@
* yellowTAB GmbH
* Bernd Korz
* Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/
@ -49,9 +50,8 @@
#include <tracker_private.h>
#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<ShowImageWindow*>(Window());
if (showImage)
showImage->BuildContextMenu(menu);
ShowImageWindow* window = dynamic_cast<ShowImageWindow*>(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();
}

View File

@ -15,10 +15,6 @@
#define SHOW_IMAGE_VIEW_H
#include "Filter.h"
#include "SelectionBox.h"
#include "ShowImageUndo.h"
#include <Bitmap.h>
#include <Entry.h>
#include <NodeInfo.h>
@ -26,11 +22,13 @@
#include <TranslatorRoster.h>
#include <View.h>
#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

View File

@ -10,6 +10,7 @@
* Michael Pfeiffer
* yellowTAB GmbH
* Bernd Korz
* Axel Dörfler, axeld@pinc-software.de
*/
@ -45,6 +46,7 @@
#include <TranslatorRoster.h>
#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();
}

View File

@ -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;