* The ImageFileNavigator is now only for navigation, it doesn't load any images
anymore. * Moved the new ImageCache into its own source file. * The cache is now used within ShowImage. There is no read-ahead caching being done yet, though, but you can quickly return to previous images, and you can also skip images faster than before. * Improved separation between the ShowImageStatusView and the rest; ShowImageWindow no longer has a getter for the image view. * The status view is now using the private BDirMenu which implements enhancement ticket #6778. * Made a few more methods private/protected in ShowImageWindow. * Fixed bug #6797. * The bitmap is currently only owned by the ImageCache, but we need to have a separate referenceable object owning it. Added a TODO comment for this. * The ProgressWindow is currently not being used anymore, added a TODO comment for this as well. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39364 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright 2010, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ImageCache.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Bitmap.h>
|
||||
#include <BitmapStream.h>
|
||||
#include <Debug.h>
|
||||
#include <File.h>
|
||||
#include <Messenger.h>
|
||||
#include <TranslatorRoster.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "ShowImageConstants.h"
|
||||
|
||||
|
||||
struct QueueEntry {
|
||||
entry_ref ref;
|
||||
int32 page;
|
||||
status_t status;
|
||||
std::set<BMessenger> listeners;
|
||||
};
|
||||
|
||||
|
||||
/*static*/ ImageCache ImageCache::sCache;
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ImageCache::ImageCache()
|
||||
:
|
||||
fLocker("image cache"),
|
||||
fThreadCount(0),
|
||||
fBytes(0)
|
||||
{
|
||||
system_info info;
|
||||
get_system_info(&info);
|
||||
|
||||
fMaxThreadCount = (info.cpu_count + 1) / 2;
|
||||
fMaxBytes = info.max_pages * B_PAGE_SIZE / 8;
|
||||
fMaxEntries = 10;
|
||||
}
|
||||
|
||||
|
||||
ImageCache::~ImageCache()
|
||||
{
|
||||
// TODO: delete CacheEntries, and QueueEntries
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
|
||||
const BMessenger* target)
|
||||
{
|
||||
BAutolock locker(fLocker);
|
||||
|
||||
CacheMap::iterator find = fCacheMap.find(std::make_pair(ref, page));
|
||||
if (find != fCacheMap.end()) {
|
||||
CacheEntry* entry = find->second;
|
||||
|
||||
// Requeue cache entry to the end of the by-age list
|
||||
fCacheEntriesByAge.Remove(entry);
|
||||
fCacheEntriesByAge.Add(entry);
|
||||
|
||||
// Notify target, if any
|
||||
_NotifyTarget(entry, target);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
QueueMap::iterator findQueue = fQueueMap.find(std::make_pair(ref, page));
|
||||
QueueEntry* entry;
|
||||
|
||||
if (findQueue == fQueueMap.end()) {
|
||||
// Push new entry to the queue
|
||||
entry = new(std::nothrow) QueueEntry();
|
||||
if (entry == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
entry->ref = ref;
|
||||
entry->page = page;
|
||||
|
||||
if (fThreadCount < fMaxThreadCount) {
|
||||
// start a new worker thread to load the image
|
||||
thread_id thread = spawn_thread(&ImageCache::_QueueWorkerThread,
|
||||
"image loader", B_LOW_PRIORITY, this);
|
||||
if (thread >= B_OK) {
|
||||
atomic_add(&fThreadCount, 1);
|
||||
resume_thread(thread);
|
||||
} else if (fThreadCount == 0) {
|
||||
delete entry;
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
||||
fQueueMap.insert(std::make_pair(
|
||||
std::make_pair(entry->ref, entry->page), entry));
|
||||
fQueue.push_front(entry);
|
||||
} else
|
||||
entry = findQueue->second;
|
||||
|
||||
if (target != NULL) {
|
||||
// Attach target as listener
|
||||
entry->listeners.insert(*target);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
ImageCache::_QueueWorkerThread(void* _self)
|
||||
{
|
||||
ImageCache* self = (ImageCache*)_self;
|
||||
|
||||
// get next queue entry
|
||||
while (true) {
|
||||
self->fLocker.Lock();
|
||||
if (self->fQueue.empty()) {
|
||||
self->fLocker.Unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
QueueEntry* entry = *self->fQueue.begin();
|
||||
self->fQueue.pop_front();
|
||||
self->fLocker.Unlock();
|
||||
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
CacheEntry* cacheEntry = NULL;
|
||||
entry->status = self->_RetrieveImage(entry, &cacheEntry);
|
||||
|
||||
self->fLocker.Lock();
|
||||
self->fQueueMap.erase(std::make_pair(entry->ref, entry->page));
|
||||
self->fLocker.Unlock();
|
||||
|
||||
self->_NotifyListeners(cacheEntry, entry);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
atomic_add(&self->fThreadCount, -1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry)
|
||||
{
|
||||
CacheEntry* entry = new(std::nothrow) CacheEntry();
|
||||
if (entry == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ObjectDeleter<CacheEntry> deleter(entry);
|
||||
|
||||
BTranslatorRoster* roster = BTranslatorRoster::Default();
|
||||
if (roster == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
BFile file;
|
||||
status_t status = file.SetTo(&queueEntry->ref, B_READ_ONLY);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
translator_info info;
|
||||
memset(&info, 0, sizeof(translator_info));
|
||||
BMessage ioExtension;
|
||||
|
||||
if (queueEntry->page != 0
|
||||
&& 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();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Translate image data and create a new ShowImage window
|
||||
|
||||
BBitmapStream outstream;
|
||||
|
||||
status = roster->Identify(&file, &ioExtension, &info, 0, NULL,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
if (status == B_OK) {
|
||||
status = roster->Translate(&file, &info, &ioExtension, &outstream,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (fProgressWindow != NULL)
|
||||
fProgressWindow->Stop();
|
||||
#endif
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BBitmap* bitmap;
|
||||
if (outstream.DetachBitmap(&bitmap) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
entry->ref = queueEntry->ref;
|
||||
entry->page = queueEntry->page;
|
||||
entry->bitmap = bitmap;
|
||||
entry->type = info.name;
|
||||
entry->mimeType = info.MIME;
|
||||
|
||||
// get the number of documents (pages) if it has been supplied
|
||||
int32 documentCount = 0;
|
||||
if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK
|
||||
&& documentCount > 0)
|
||||
entry->pageCount = documentCount;
|
||||
else
|
||||
entry->pageCount = 1;
|
||||
|
||||
deleter.Detach();
|
||||
*_entry = entry;
|
||||
|
||||
BAutolock locker(fLocker);
|
||||
|
||||
fCacheMap.insert(std::make_pair(
|
||||
std::make_pair(entry->ref, entry->page), entry));
|
||||
fCacheEntriesByAge.Add(entry);
|
||||
|
||||
fBytes += bitmap->BitsLength();
|
||||
|
||||
while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) {
|
||||
if (fCacheMap.size() <= 2)
|
||||
break;
|
||||
|
||||
// Remove the oldest entry
|
||||
entry = fCacheEntriesByAge.RemoveHead();
|
||||
fBytes -= entry->bitmap->BitsLength();
|
||||
fCacheMap.erase(std::make_pair(entry->ref, entry->page));
|
||||
delete entry;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageCache::_NotifyListeners(CacheEntry* entry, QueueEntry* queueEntry)
|
||||
{
|
||||
ASSERT(fLocker.IsLocked());
|
||||
|
||||
if (queueEntry->listeners.empty())
|
||||
return;
|
||||
|
||||
BMessage notification(kMsgImageLoaded);
|
||||
_BuildNotification(entry, notification);
|
||||
|
||||
if (queueEntry->status != B_OK)
|
||||
notification.AddInt32("error", queueEntry->status);
|
||||
|
||||
std::set<BMessenger>::iterator iterator = queueEntry->listeners.begin();
|
||||
for (; iterator != queueEntry->listeners.end(); iterator++) {
|
||||
iterator->SendMessage(¬ification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageCache::_NotifyTarget(CacheEntry* entry, const BMessenger* target)
|
||||
{
|
||||
if (target == NULL)
|
||||
return;
|
||||
|
||||
BMessage notification(kMsgImageLoaded);
|
||||
_BuildNotification(entry, notification);
|
||||
|
||||
target->SendMessage(¬ification);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageCache::_BuildNotification(CacheEntry* entry, BMessage& message)
|
||||
{
|
||||
if (entry == NULL)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IMAGE_CACHE_H
|
||||
#define IMAGE_CACHE_H
|
||||
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <Entry.h>
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <kernel/util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
class BBitmap;
|
||||
class BMessage;
|
||||
class BMessenger;
|
||||
struct QueueEntry;
|
||||
|
||||
|
||||
enum {
|
||||
kMsgImageLoaded = 'ifnL'
|
||||
};
|
||||
|
||||
|
||||
struct CacheEntry : DoublyLinkedListLinkImpl<CacheEntry> {
|
||||
entry_ref ref;
|
||||
int32 page;
|
||||
int32 pageCount;
|
||||
BBitmap* bitmap;
|
||||
BString type;
|
||||
BString mimeType;
|
||||
};
|
||||
|
||||
|
||||
class ImageCache {
|
||||
public:
|
||||
static ImageCache& Default() { return sCache; }
|
||||
|
||||
status_t RetrieveImage(const entry_ref& ref, int32 page,
|
||||
const BMessenger* target);
|
||||
|
||||
private:
|
||||
ImageCache();
|
||||
virtual ~ImageCache();
|
||||
|
||||
static status_t _QueueWorkerThread(void* self);
|
||||
|
||||
status_t _RetrieveImage(QueueEntry* entry,
|
||||
CacheEntry** _entry);
|
||||
void _NotifyListeners(CacheEntry* entry,
|
||||
QueueEntry* queueEntry);
|
||||
void _NotifyTarget(CacheEntry* entry,
|
||||
const BMessenger* target);
|
||||
void _BuildNotification(CacheEntry* entry,
|
||||
BMessage& message);
|
||||
|
||||
private:
|
||||
typedef std::pair<entry_ref, int32> ImageSelector;
|
||||
typedef std::map<ImageSelector, CacheEntry*> CacheMap;
|
||||
typedef std::map<ImageSelector, QueueEntry*> QueueMap;
|
||||
typedef std::deque<QueueEntry*> QueueDeque;
|
||||
typedef DoublyLinkedList<CacheEntry> CacheList;
|
||||
|
||||
BLocker fLocker;
|
||||
CacheMap fCacheMap;
|
||||
CacheList fCacheEntriesByAge;
|
||||
QueueMap fQueueMap;
|
||||
QueueDeque fQueue;
|
||||
vint32 fThreadCount;
|
||||
int32 fMaxThreadCount;
|
||||
uint64 fBytes;
|
||||
uint64 fMaxBytes;
|
||||
size_t fMaxEntries;
|
||||
|
||||
static ImageCache sCache;
|
||||
};
|
||||
|
||||
|
||||
#endif // IMAGE_CACHE_H
|
||||
@@ -18,26 +18,20 @@
|
||||
|
||||
#include "ImageFileNavigator.h"
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <new>
|
||||
#include <set>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <BitmapStream.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <Locker.h>
|
||||
//#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
#include <Path.h>
|
||||
//#include <Path.h>
|
||||
#include <TranslatorRoster.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <tracker_private.h>
|
||||
#include <kernel/util/DoublyLinkedList.h>
|
||||
|
||||
#include "ProgressWindow.h"
|
||||
#include "ShowImageConstants.h"
|
||||
@@ -320,254 +314,10 @@ FolderNavigator::_CompareRefs(const entry_ref* refA, const entry_ref* refB)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
struct CacheEntry : DoublyLinkedListLinkImpl<CacheEntry> {
|
||||
entry_ref ref;
|
||||
int32 page;
|
||||
int32 pageCount;
|
||||
BBitmap* bitmap;
|
||||
BString type;
|
||||
BString mimeType;
|
||||
};
|
||||
|
||||
|
||||
struct QueueEntry {
|
||||
entry_ref ref;
|
||||
int32 page;
|
||||
std::set<BMessenger> listeners;
|
||||
};
|
||||
|
||||
|
||||
class ImageCache {
|
||||
public:
|
||||
ImageCache();
|
||||
virtual ~ImageCache();
|
||||
|
||||
void RetrieveImage(const entry_ref& ref,
|
||||
const BMessenger* target);
|
||||
|
||||
private:
|
||||
static status_t _QueueWorkerThread(void* self);
|
||||
|
||||
status_t _RetrieveImage(QueueEntry* entry,
|
||||
BMessage& message);
|
||||
void _NotifyListeners(QueueEntry* entry,
|
||||
BMessage& message);
|
||||
|
||||
private:
|
||||
typedef std::pair<entry_ref, int32> ImageSelector;
|
||||
typedef std::map<ImageSelector, CacheEntry*> CacheMap;
|
||||
typedef std::map<ImageSelector, QueueEntry*> QueueMap;
|
||||
typedef std::deque<QueueEntry*> QueueDeque;
|
||||
typedef DoublyLinkedList<CacheEntry> CacheList;
|
||||
|
||||
BLocker fCacheLocker;
|
||||
CacheMap fCacheMap;
|
||||
CacheList fCacheEntriesByAge;
|
||||
BLocker fQueueLocker;
|
||||
QueueMap fQueueMap;
|
||||
QueueDeque fQueue;
|
||||
vint32 fThreadCount;
|
||||
int32 fMaxThreadCount;
|
||||
uint64 fBytes;
|
||||
uint64 fMaxBytes;
|
||||
size_t fMaxEntries;
|
||||
};
|
||||
|
||||
|
||||
ImageCache::ImageCache()
|
||||
ImageFileNavigator::ImageFileNavigator(const entry_ref& ref,
|
||||
const BMessenger& trackerMessenger)
|
||||
:
|
||||
fCacheLocker("image cache"),
|
||||
fQueueLocker("image queue"),
|
||||
fThreadCount(0),
|
||||
fBytes(0)
|
||||
{
|
||||
system_info info;
|
||||
get_system_info(&info);
|
||||
|
||||
fMaxThreadCount = (info.cpu_count + 1) / 2;
|
||||
fMaxBytes = info.max_pages * B_PAGE_SIZE / 8;
|
||||
fMaxEntries = 10;
|
||||
}
|
||||
|
||||
|
||||
ImageCache::~ImageCache()
|
||||
{
|
||||
// TODO: delete CacheEntries, and QueueEntries
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageCache::RetrieveImage(const entry_ref& ref, const BMessenger* target)
|
||||
{
|
||||
// TODO!
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
ImageCache::_QueueWorkerThread(void* _self)
|
||||
{
|
||||
ImageCache* self = (ImageCache*)_self;
|
||||
|
||||
// get next queue entry
|
||||
while (true) {
|
||||
self->fQueueLocker.Lock();
|
||||
if (self->fQueue.empty()) {
|
||||
self->fQueueLocker.Unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
QueueEntry* entry = *self->fQueue.begin();
|
||||
self->fQueue.pop_front();
|
||||
self->fQueueLocker.Unlock();
|
||||
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
BMessage notification(kMsgImageLoaded);
|
||||
status_t status = self->_RetrieveImage(entry, notification);
|
||||
if (status != B_OK)
|
||||
notification.AddInt32("error", status);
|
||||
|
||||
self->fQueueLocker.Lock();
|
||||
self->fQueueMap.erase(std::make_pair(entry->ref, entry->page));
|
||||
self->fQueueLocker.Unlock();
|
||||
|
||||
self->_NotifyListeners(entry, notification);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
atomic_add(&self->fThreadCount, -1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ImageCache::_RetrieveImage(QueueEntry* queueEntry, BMessage& message)
|
||||
{
|
||||
CacheEntry* entry = new(std::nothrow) CacheEntry();
|
||||
if (entry == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ObjectDeleter<CacheEntry> deleter(entry);
|
||||
|
||||
BTranslatorRoster* roster = BTranslatorRoster::Default();
|
||||
if (roster == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
if (!entry_ref_is_file(queueEntry->ref))
|
||||
return B_IS_A_DIRECTORY;
|
||||
|
||||
BFile file;
|
||||
status_t status = file.SetTo(&queueEntry->ref, B_READ_ONLY);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
translator_info info;
|
||||
memset(&info, 0, sizeof(translator_info));
|
||||
BMessage ioExtension;
|
||||
|
||||
if (queueEntry->page != 0
|
||||
&& 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();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Translate image data and create a new ShowImage window
|
||||
|
||||
BBitmapStream outstream;
|
||||
|
||||
status = roster->Identify(&file, &ioExtension, &info, 0, NULL,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
if (status == B_OK) {
|
||||
status = roster->Translate(&file, &info, &ioExtension, &outstream,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (fProgressWindow != NULL)
|
||||
fProgressWindow->Stop();
|
||||
#endif
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BBitmap* bitmap;
|
||||
if (outstream.DetachBitmap(&bitmap) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
entry->ref = queueEntry->ref;
|
||||
entry->page = queueEntry->page;
|
||||
entry->bitmap = bitmap;
|
||||
entry->type = info.name;
|
||||
entry->mimeType = info.MIME;
|
||||
|
||||
// get the number of documents (pages) if it has been supplied
|
||||
int32 documentCount = 0;
|
||||
if (ioExtension.FindInt32("/documentCount", &documentCount) == B_OK
|
||||
&& documentCount > 0)
|
||||
entry->pageCount = documentCount;
|
||||
else
|
||||
entry->pageCount = 1;
|
||||
|
||||
message.AddString("type", info.name);
|
||||
message.AddString("mime", info.MIME);
|
||||
message.AddRef("ref", &entry->ref);
|
||||
message.AddInt32("page", entry->page);
|
||||
message.AddPointer("bitmap", (void*)bitmap);
|
||||
|
||||
deleter.Detach();
|
||||
|
||||
fCacheLocker.Lock();
|
||||
|
||||
fCacheMap.insert(std::make_pair(
|
||||
std::make_pair(entry->ref, entry->page), entry));
|
||||
fCacheEntriesByAge.Add(entry);
|
||||
|
||||
fBytes += bitmap->BitsLength();
|
||||
|
||||
while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) {
|
||||
if (fCacheMap.size() <= 2)
|
||||
break;
|
||||
|
||||
// Remove the oldest entry
|
||||
entry = fCacheEntriesByAge.RemoveHead();
|
||||
fBytes -= entry->bitmap->BitsLength();
|
||||
fCacheMap.erase(std::make_pair(entry->ref, entry->page));
|
||||
delete entry;
|
||||
}
|
||||
|
||||
fCacheLocker.Unlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageCache::_NotifyListeners(QueueEntry* entry, BMessage& message)
|
||||
{
|
||||
std::set<BMessenger>::iterator iterator = entry->listeners.begin();
|
||||
for (; iterator != entry->listeners.end(); iterator++) {
|
||||
iterator->SendMessage(&message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ImageFileNavigator::ImageFileNavigator(const BMessenger& target,
|
||||
const entry_ref& ref, const BMessenger& trackerMessenger)
|
||||
:
|
||||
fTarget(target),
|
||||
fProgressWindow(NULL),
|
||||
fCurrentRef(ref),
|
||||
fDocumentIndex(1),
|
||||
fDocumentCount(1)
|
||||
{
|
||||
@@ -585,95 +335,11 @@ ImageFileNavigator::~ImageFileNavigator()
|
||||
|
||||
|
||||
void
|
||||
ImageFileNavigator::SetProgressWindow(ProgressWindow* progressWindow)
|
||||
ImageFileNavigator::SetTo(const entry_ref& ref, int32 page, int32 pageCount)
|
||||
{
|
||||
fProgressWindow = progressWindow;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
translator_info info;
|
||||
memset(&info, 0, sizeof(translator_info));
|
||||
BMessage ioExtension;
|
||||
|
||||
if (page != 0 && ioExtension.AddInt32("/documentIndex", page) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
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
|
||||
|
||||
BBitmapStream outstream;
|
||||
|
||||
status_t status = roster->Identify(&file, &ioExtension, &info, 0, NULL,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
if (status == B_OK) {
|
||||
status = roster->Translate(&file, &info, &ioExtension, &outstream,
|
||||
B_TRANSLATOR_BITMAP);
|
||||
}
|
||||
|
||||
if (fProgressWindow != NULL)
|
||||
fProgressWindow->Stop();
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BBitmap* bitmap;
|
||||
if (outstream.DetachBitmap(&bitmap) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
fCurrentRef = ref;
|
||||
fDocumentIndex = page;
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageFileNavigator::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());
|
||||
fDocumentCount = pageCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -695,7 +361,7 @@ bool
|
||||
ImageFileNavigator::FirstPage()
|
||||
{
|
||||
if (fDocumentIndex != 1) {
|
||||
LoadImage(fCurrentRef, 1);
|
||||
fDocumentIndex = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -706,7 +372,7 @@ bool
|
||||
ImageFileNavigator::LastPage()
|
||||
{
|
||||
if (fDocumentIndex != fDocumentCount) {
|
||||
LoadImage(fCurrentRef, fDocumentCount);
|
||||
fDocumentIndex = fDocumentCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -717,7 +383,7 @@ bool
|
||||
ImageFileNavigator::NextPage()
|
||||
{
|
||||
if (fDocumentIndex < fDocumentCount) {
|
||||
LoadImage(fCurrentRef, ++fDocumentIndex);
|
||||
fDocumentIndex++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -728,7 +394,7 @@ bool
|
||||
ImageFileNavigator::PreviousPage()
|
||||
{
|
||||
if (fDocumentIndex > 1) {
|
||||
LoadImage(fCurrentRef, --fDocumentIndex);
|
||||
fDocumentIndex--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -740,31 +406,51 @@ ImageFileNavigator::GoToPage(int32 page)
|
||||
{
|
||||
if (page > 0 && page <= fDocumentCount && page != fDocumentIndex) {
|
||||
fDocumentIndex = page;
|
||||
LoadImage(fCurrentRef, fDocumentIndex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
ImageFileNavigator::FirstFile()
|
||||
{
|
||||
_LoadNextImage(true, true);
|
||||
entry_ref ref;
|
||||
if (fNavigator->FindNextImage(fCurrentRef, ref, false, true)) {
|
||||
SetTo(ref, 1, 1);
|
||||
fNavigator->UpdateSelection(fCurrentRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
ImageFileNavigator::NextFile()
|
||||
{
|
||||
_LoadNextImage(true, false);
|
||||
entry_ref ref;
|
||||
if (fNavigator->FindNextImage(fCurrentRef, ref, true, false)) {
|
||||
SetTo(ref, 1, 1);
|
||||
fNavigator->UpdateSelection(fCurrentRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
ImageFileNavigator::PreviousFile()
|
||||
{
|
||||
_LoadNextImage(false, false);
|
||||
entry_ref ref;
|
||||
if (fNavigator->FindNextImage(fCurrentRef, ref, false, false)) {
|
||||
SetTo(ref, 1, 1);
|
||||
fNavigator->UpdateSelection(fCurrentRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -785,7 +471,7 @@ ImageFileNavigator::HasPreviousFile()
|
||||
|
||||
|
||||
/*! Moves the current file into the trash.
|
||||
Returns true if a new file is being loaded, false if not.
|
||||
Returns true if a new file should be loaded, false if not.
|
||||
*/
|
||||
bool
|
||||
ImageFileNavigator::MoveFileToTrash()
|
||||
@@ -803,41 +489,12 @@ ImageFileNavigator::MoveFileToTrash()
|
||||
// could be invalid
|
||||
BMessenger tracker(kTrackerSignature);
|
||||
if (tracker.SendMessage(&trash) != B_OK)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
if (nextRef.device != -1 && LoadImage(nextRef) == B_OK) {
|
||||
fNavigator->UpdateSelection(nextRef);
|
||||
if (nextRef.device != -1) {
|
||||
SetTo(nextRef, 1, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
ImageFileNavigator::_LoadNextImage(bool next, bool rewind)
|
||||
{
|
||||
entry_ref currentRef = fCurrentRef;
|
||||
entry_ref ref;
|
||||
if (fNavigator->FindNextImage(currentRef, ref, next, rewind)) {
|
||||
// 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 (LoadImage(ref) != B_OK) {
|
||||
currentRef = ref;
|
||||
if (!fNavigator->FindNextImage(currentRef, ref, next, false))
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
fNavigator->UpdateSelection(fCurrentRef);
|
||||
return B_OK;
|
||||
}
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,27 +22,17 @@
|
||||
|
||||
|
||||
class Navigator;
|
||||
class ProgressWindow;
|
||||
|
||||
enum {
|
||||
kMsgImageLoaded = 'ifnL'
|
||||
};
|
||||
|
||||
|
||||
class ImageFileNavigator {
|
||||
public:
|
||||
ImageFileNavigator(const BMessenger& target,
|
||||
const entry_ref& ref,
|
||||
ImageFileNavigator(const entry_ref& ref,
|
||||
const BMessenger& trackerMessenger);
|
||||
virtual ~ImageFileNavigator();
|
||||
|
||||
void SetProgressWindow(
|
||||
ProgressWindow* progressWindow);
|
||||
|
||||
status_t LoadImage(const entry_ref& ref, int32 page = 1);
|
||||
const entry_ref& ImageRef() const { return fCurrentRef; }
|
||||
|
||||
void GetPath(BString* name);
|
||||
void SetTo(const entry_ref& ref, int32 page = 1,
|
||||
int32 pageCount = 1);
|
||||
const entry_ref& CurrentRef() const { return fCurrentRef; }
|
||||
|
||||
// The same image file may have multiple pages, TIFF images for
|
||||
// example. The page count is determined at image loading time.
|
||||
@@ -55,20 +45,15 @@ public:
|
||||
bool PreviousPage();
|
||||
bool GoToPage(int32 page);
|
||||
|
||||
void FirstFile();
|
||||
void NextFile();
|
||||
void PreviousFile();
|
||||
bool FirstFile();
|
||||
bool NextFile();
|
||||
bool PreviousFile();
|
||||
bool HasNextFile();
|
||||
bool HasPreviousFile();
|
||||
|
||||
bool MoveFileToTrash();
|
||||
|
||||
private:
|
||||
status_t _LoadNextImage(bool next, bool rewind);
|
||||
|
||||
private:
|
||||
BMessenger fTarget;
|
||||
ProgressWindow* fProgressWindow;
|
||||
Navigator* fNavigator;
|
||||
|
||||
entry_ref fCurrentRef;
|
||||
|
||||
@@ -3,10 +3,12 @@ SubDir HAIKU_TOP src apps showimage ;
|
||||
UsePrivateSystemHeaders ;
|
||||
UsePrivateHeaders tracker shared ;
|
||||
UsePublicHeaders [ FDirName be_apps Tracker ] ;
|
||||
SubDirHdrs $(HAIKU_TOP) src kits tracker ;
|
||||
|
||||
Application ShowImage :
|
||||
EntryMenuItem.cpp
|
||||
Filter.cpp
|
||||
ImageCache.cpp
|
||||
ImageFileNavigator.cpp
|
||||
PrintOptionsWindow.cpp
|
||||
ProgressWindow.cpp
|
||||
@@ -18,7 +20,7 @@ Application ShowImage :
|
||||
ShowImageView.cpp
|
||||
ShowImageWindow.cpp
|
||||
: libshared.a
|
||||
be tracker translation $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSTDC++)
|
||||
be tracker translation $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSTDC++)
|
||||
$(TARGET_LIBSUPC++)
|
||||
: ShowImage.rdef
|
||||
;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* Copyright 2003-2009 Haiku Inc. All rights reserved.
|
||||
* Copyright 2003-2010, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Fernando Francisco de Oliveira
|
||||
* Michael Wilber
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "ShowImageStatusView.h"
|
||||
|
||||
#include <Entry.h>
|
||||
@@ -14,6 +16,9 @@
|
||||
#include <Path.h>
|
||||
#include <PopUpMenu.h>
|
||||
|
||||
#include <tracker_private.h>
|
||||
#include "DirMenu.h"
|
||||
|
||||
#include "ShowImageView.h"
|
||||
#include "ShowImageWindow.h"
|
||||
|
||||
@@ -77,47 +82,30 @@ ShowImageStatusView::Draw(BRect updateRect)
|
||||
void
|
||||
ShowImageStatusView::MouseDown(BPoint where)
|
||||
{
|
||||
ShowImageWindow *window = dynamic_cast<ShowImageWindow *>(Window());
|
||||
if (!window || window->GetShowImageView() == NULL)
|
||||
return;
|
||||
BPrivate::BDirMenu* menu = new BDirMenu(NULL, B_REFS_RECEIVED);
|
||||
BEntry entry;
|
||||
if (entry.SetTo(&fRef) == B_OK)
|
||||
menu->Populate(&entry, Window(), false, false, true, false, true);
|
||||
else
|
||||
menu->Populate(NULL, Window(), false, false, true, false, true);
|
||||
|
||||
BPath path;
|
||||
path.SetTo(window->GetShowImageView()->Image());
|
||||
|
||||
BPopUpMenu popup("no title");
|
||||
popup.SetFont(be_plain_font);
|
||||
|
||||
while (path.GetParent(&path) == B_OK && path != "/") {
|
||||
popup.AddItem(new BMenuItem(path.Leaf(), NULL));
|
||||
}
|
||||
|
||||
BRect bounds(Bounds());
|
||||
ConvertToScreen(&bounds);
|
||||
where = bounds.LeftBottom();
|
||||
|
||||
BMenuItem *item;
|
||||
item = popup.Go(where, true, false, ConvertToScreen(Bounds()));
|
||||
|
||||
if (item) {
|
||||
path.SetTo(window->GetShowImageView()->Image());
|
||||
path.GetParent(&path);
|
||||
int index = popup.IndexOf(item);
|
||||
while (index--)
|
||||
path.GetParent(&path);
|
||||
BMessenger tracker("application/x-vnd.Be-TRAK");
|
||||
BMessage msg(B_REFS_RECEIVED);
|
||||
entry_ref ref;
|
||||
get_ref_for_path(path.Path(), &ref);
|
||||
msg.AddRef("refs", &ref);
|
||||
tracker.SendMessage(&msg);
|
||||
}
|
||||
menu->SetTargetForItems(BMessenger(kTrackerSignature));
|
||||
BPoint point = Bounds().LeftBottom();
|
||||
point.y += 3;
|
||||
ConvertToScreen(&point);
|
||||
BRect clickToOpenRect(Bounds());
|
||||
ConvertToScreen(&clickToOpenRect);
|
||||
menu->Go(point, true, true, clickToOpenRect);
|
||||
delete menu;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShowImageStatusView::SetText(BString &text)
|
||||
ShowImageStatusView::Update(const entry_ref& ref, const BString& text)
|
||||
{
|
||||
fText = text;
|
||||
fRef = ref;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2009 Haiku Inc. All rights reserved.
|
||||
* Copyright 2003-2010 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -10,21 +10,26 @@
|
||||
#define SHOW_IMAGE_STATUS_VIEW_H
|
||||
|
||||
|
||||
#include <Entry.h>
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
|
||||
class ShowImageStatusView : public BView {
|
||||
public:
|
||||
ShowImageStatusView(BRect rect, const char *name,
|
||||
uint32 resizingMode, uint32 flags);
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void MouseDown(BPoint where);
|
||||
void SetText(BString &text);
|
||||
|
||||
ShowImageStatusView(BRect rect,
|
||||
const char* name, uint32 resizingMode,
|
||||
uint32 flags);
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void MouseDown(BPoint where);
|
||||
|
||||
void Update(const entry_ref& ref,
|
||||
const BString& text);
|
||||
|
||||
private:
|
||||
BString fText;
|
||||
BString fText;
|
||||
entry_ref fRef;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ ShowImageView::_DeleteBitmap()
|
||||
delete fDisplayBitmap;
|
||||
fDisplayBitmap = NULL;
|
||||
|
||||
delete fBitmap;
|
||||
// TODO: the bitmap is currently only owned by the cache!!!
|
||||
fBitmap = NULL;
|
||||
}
|
||||
|
||||
@@ -751,6 +751,9 @@ ShowImageView::Draw(BRect updateRect)
|
||||
void
|
||||
ShowImageView::FrameResized(float /*width*/, float /*height*/)
|
||||
{
|
||||
if (fBitmap == NULL)
|
||||
return;
|
||||
|
||||
fFitToBoundsZoom = _FitToBoundsZoom();
|
||||
SetZoom(_ShouldStretch() ? fFitToBoundsZoom : fZoom);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <TranslationUtils.h>
|
||||
#include <TranslatorRoster.h>
|
||||
|
||||
#include "EntryMenuItem.h"
|
||||
#include "ImageCache.h"
|
||||
#include "ShowImageApp.h"
|
||||
#include "ShowImageConstants.h"
|
||||
#include "ShowImageStatusView.h"
|
||||
@@ -79,7 +79,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref,
|
||||
const BMessenger& trackerMessenger)
|
||||
:
|
||||
BWindow(BRect(5, 24, 250, 100), "", B_DOCUMENT_WINDOW, 0),
|
||||
fNavigator(this, ref, trackerMessenger),
|
||||
fNavigator(ref, trackerMessenger),
|
||||
fSavePanel(NULL),
|
||||
fBar(NULL),
|
||||
fBrowseMenu(NULL),
|
||||
@@ -96,7 +96,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref,
|
||||
|
||||
// create menu bar
|
||||
fBar = new BMenuBar(BRect(0, 0, Bounds().right, 1), "menu_bar");
|
||||
AddMenus(fBar);
|
||||
_AddMenus(fBar);
|
||||
AddChild(fBar);
|
||||
|
||||
BRect viewFrame = Bounds();
|
||||
@@ -142,7 +142,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref& ref,
|
||||
SetSizeLimits(250, 100000, 100, 100000);
|
||||
|
||||
// finish creating the window
|
||||
if (fNavigator.LoadImage(ref) != B_OK) {
|
||||
if (_LoadImage() != B_OK) {
|
||||
_LoadError(ref);
|
||||
Quit();
|
||||
return;
|
||||
@@ -173,14 +173,6 @@ ShowImageWindow::~ShowImageWindow()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShowImageWindow::UpdateTitle()
|
||||
{
|
||||
BPath path(fImageView->Image());
|
||||
SetTitle(path.Path());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShowImageWindow::BuildContextMenu(BMenu* menu)
|
||||
{
|
||||
@@ -261,7 +253,7 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu)
|
||||
|
||||
|
||||
void
|
||||
ShowImageWindow::AddMenus(BMenuBar* bar)
|
||||
ShowImageWindow::_AddMenus(BMenuBar* bar)
|
||||
{
|
||||
BMenu* menu = new BMenu(B_TRANSLATE("File"));
|
||||
|
||||
@@ -377,7 +369,7 @@ ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, float value)
|
||||
|
||||
|
||||
void
|
||||
ShowImageWindow::WindowRedimension(BBitmap* bitmap)
|
||||
ShowImageWindow::_WindowRedimension(BBitmap* bitmap)
|
||||
{
|
||||
BScreen screen;
|
||||
if (!screen.IsValid())
|
||||
@@ -492,12 +484,15 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
case kMsgImageLoaded:
|
||||
{
|
||||
bool first = fImageView->Bitmap() == NULL;
|
||||
entry_ref ref;
|
||||
message->FindRef("ref", &ref);
|
||||
if (!first && ref != fNavigator.CurrentRef()) {
|
||||
// ignore older images
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -507,9 +502,11 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
fImageType = message->FindString("type");
|
||||
fNavigator.SetTo(ref, message->FindInt32("page"),
|
||||
message->FindInt32("pageCount"));
|
||||
|
||||
if (first) {
|
||||
WindowRedimension(fImageView->Bitmap());
|
||||
_WindowRedimension(fImageView->Bitmap());
|
||||
fImageView->ResetZoom();
|
||||
fImageView->MakeFocus(true);
|
||||
// to receive key messages
|
||||
@@ -519,7 +516,7 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
if (!fImageView->StretchesToBounds()
|
||||
&& !fImageView->ShrinksToBounds()
|
||||
&& !fFullScreen)
|
||||
WindowRedimension(fImageView->Bitmap());
|
||||
_WindowRedimension(fImageView->Bitmap());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -596,7 +593,9 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
_UpdateStatusText(message);
|
||||
UpdateTitle();
|
||||
|
||||
BPath path(fImageView->Image());
|
||||
SetTitle(path.Path());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -648,23 +647,23 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
case MSG_PAGE_FIRST:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.FirstPage();
|
||||
if (_ClosePrompt() && fNavigator.FirstPage())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case MSG_PAGE_LAST:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.LastPage();
|
||||
if (_ClosePrompt() && fNavigator.LastPage())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case MSG_PAGE_NEXT:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.NextPage();
|
||||
if (_ClosePrompt() && fNavigator.NextPage())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case MSG_PAGE_PREV:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.PreviousPage();
|
||||
if (_ClosePrompt() && fNavigator.PreviousPage())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case MSG_GOTO_PAGE:
|
||||
@@ -679,13 +678,15 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
int32 currentPage = fNavigator.CurrentPage();
|
||||
int32 pages = fNavigator.PageCount();
|
||||
|
||||
// TODO: use radio mode instead!
|
||||
if (newPage > 0 && newPage <= pages) {
|
||||
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);
|
||||
if (fNavigator.GoToPage(newPage))
|
||||
_LoadImage();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -700,19 +701,23 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
case MSG_FILE_PREV:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.PreviousFile();
|
||||
if (_ClosePrompt() && fNavigator.PreviousFile())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case MSG_FILE_NEXT:
|
||||
if (_ClosePrompt())
|
||||
fNavigator.NextFile();
|
||||
if (_ClosePrompt() && fNavigator.NextFile())
|
||||
_LoadImage();
|
||||
break;
|
||||
|
||||
case kMsgDeleteCurrentFile:
|
||||
if (!fNavigator.MoveFileToTrash())
|
||||
{
|
||||
if (fNavigator.MoveFileToTrash())
|
||||
_LoadImage();
|
||||
else
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_ROTATE_90:
|
||||
fImageView->Rotate(90);
|
||||
@@ -838,7 +843,7 @@ ShowImageWindow::_UpdateStatusText(const BMessage* message)
|
||||
status << ", " << text;
|
||||
}
|
||||
|
||||
fStatusView->SetText(status);
|
||||
fStatusView->Update(fNavigator.CurrentRef(), status);
|
||||
}
|
||||
|
||||
|
||||
@@ -934,6 +939,7 @@ ShowImageWindow::_SaveToFile(BMessage* message)
|
||||
#undef B_TRANSLATE_CONTEXT
|
||||
#define B_TRANSLATE_CONTEXT "ClosePrompt"
|
||||
|
||||
|
||||
bool
|
||||
ShowImageWindow::_ClosePrompt()
|
||||
{
|
||||
@@ -969,6 +975,15 @@ ShowImageWindow::_ClosePrompt()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShowImageWindow::_LoadImage()
|
||||
{
|
||||
BMessenger us(this);
|
||||
return ImageCache::Default().RetrieveImage(fNavigator.CurrentRef(),
|
||||
fNavigator.CurrentPage(), &us);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShowImageWindow::_ToggleFullScreen()
|
||||
{
|
||||
|
||||
@@ -31,18 +31,16 @@ public:
|
||||
const BMessenger& trackerMessenger);
|
||||
virtual ~ShowImageWindow();
|
||||
|
||||
void BuildContextMenu(BMenu* menu);
|
||||
|
||||
protected:
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
ShowImageView* GetShowImageView() const { return fImageView; }
|
||||
|
||||
void UpdateTitle();
|
||||
void AddMenus(BMenuBar* bar);
|
||||
void BuildContextMenu(BMenu* menu);
|
||||
void WindowRedimension(BBitmap* bitmap);
|
||||
|
||||
private:
|
||||
void _AddMenus(BMenuBar* bar);
|
||||
void _WindowRedimension(BBitmap* bitmap);
|
||||
void _BuildViewMenu(BMenu* menu, bool popupMenu);
|
||||
BMenuItem* _AddItemMenu(BMenu* menu, const char* label,
|
||||
uint32 what, char shortcut, uint32 modifier,
|
||||
@@ -66,6 +64,7 @@ private:
|
||||
void _SaveToFile(BMessage* message);
|
||||
// Handle save file panel message
|
||||
bool _ClosePrompt();
|
||||
status_t _LoadImage();
|
||||
void _ToggleFullScreen();
|
||||
void _ApplySettings();
|
||||
void _SavePrintOptions();
|
||||
@@ -88,6 +87,7 @@ private:
|
||||
BRect fWindowFrame;
|
||||
BMessage* fPrintSettings;
|
||||
PrintOptions fPrintOptions;
|
||||
|
||||
BString fImageType;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user