* Completed stippi's work on the ImageFileNavigator.

* ShowImageWindow is now using such a navigator.
* Removed navigation support from ShowImageView.
* Prepared everything to support asynchronous image loading (which is not yet
  implemented, though).
* Note, this commit brings some regressions I intend to fix in the next few
  days, namely deleting files won't work anymore, and dropping images onto
  ShowImage. There might be more I don't know about, though :-)


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