fixed alignment and image layout, esc exits fullscreen mode, black background for fullscreen, zooming window toggles fullscreen, can still browse even if current image has been deleted, space toggles slideshow, swapped next/previous menu items (more logical)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13101 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2005-06-13 20:09:46 +00:00
parent fc95358474
commit fc5ca95d01
5 changed files with 153 additions and 100 deletions
+1
View File
@@ -64,6 +64,7 @@ const uint32 MSG_INVERT = 'mINV';
const uint32 MSG_SLIDE_SHOW = 'mSSW';
const uint32 MSG_SLIDE_SHOW_DELAY = 'mSSD';
const uint32 MSG_FULL_SCREEN = 'mFSC';
const uint32 MSG_EXIT_FULL_SCREEN = 'mEFS';
const uint32 MSG_SHOW_CAPTION = 'mSCP';
const uint32 MSG_PAGE_SETUP = 'mPSU';
const uint32 MSG_PREPARE_PRINT = 'mPPT';
+123 -89
View File
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <math.h>
#include <new>
#include <Debug.h>
#include <Message.h>
#include <ScrollBar.h>
@@ -68,7 +70,6 @@
#define SHOW_IMAGE_ORIENTATION_ATTRIBUTE "ShowImage:orientation"
#define BORDER_WIDTH 16
#define BORDER_HEIGHT 16
#define PEN_SIZE 1.0f
const rgb_color kBorderColor = { 0, 0, 0, 255 };
enum ShowImageView::image_orientation
@@ -193,8 +194,8 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
fShrinkToBounds = false;
fZoomToBounds = false;
fHasBorder = true;
fHAlignment = B_ALIGN_LEFT;
fVAlignment = B_ALIGN_TOP;
fHAlignment = B_ALIGN_CENTER;
fVAlignment = B_ALIGN_MIDDLE;
fSlideShow = false;
fSlideShowDelay = 3 * 10; // 3 seconds
fShowCaption = false;
@@ -512,6 +513,10 @@ ShowImageView::SetBorder(bool hasBorder)
{
if (fHasBorder != hasBorder) {
fHasBorder = hasBorder;
if (fHasBorder)
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
else
SetLowColor(0, 0, 0, 255);
FixupScrollBars();
Invalidate();
}
@@ -520,9 +525,7 @@ ShowImageView::SetBorder(bool hasBorder)
void
ShowImageView::SetAlignment(alignment horizontal, vertical_alignment vertical)
{
bool hasChanged;
hasChanged = fHAlignment != horizontal || fVAlignment != vertical;
if (hasChanged) {
if (fHAlignment != horizontal || fVAlignment != vertical) {
fHAlignment = horizontal;
fVAlignment = vertical;
FixupScrollBars();
@@ -539,36 +542,32 @@ ShowImageView::GetBitmap()
void
ShowImageView::GetName(BString *name)
{
*name = "";
BEntry entry(&fCurrentRef);
if (entry.InitCheck() == B_OK) {
char n[B_FILE_NAME_LENGTH];
if (entry.GetName(n) == B_OK) {
name->SetTo(n);
}
}
char n[B_FILE_NAME_LENGTH];
if (entry.InitCheck() >= B_OK && entry.GetName(n) >= B_OK) {
name->SetTo(n);
} else {
*name = "";
}
}
void
ShowImageView::GetPath(BString *name)
{
*name = "";
BEntry entry(&fCurrentRef);
if (entry.InitCheck() == B_OK) {
BPath path;
entry.GetPath(&path);
if (path.InitCheck() == B_OK) {
name->SetTo(path.Path());
}
}
BPath path;
if (entry.InitCheck() >= B_OK && entry.GetPath(&path) >= B_OK) {
name->SetTo(path.Path());
} else {
*name = "";
}
}
void
ShowImageView::FlushToLeftTop()
{
BRect rect = AlignBitmap();
BPoint p(rect.left, rect.top);
ScrollTo(p);
ScrollTo(rect.LeftTop());
}
void
@@ -591,26 +590,33 @@ BRect
ShowImageView::AlignBitmap()
{
BRect rect(fBitmap->Bounds());
float width, height;
width = Bounds().Width()-2*PEN_SIZE+1;
height = Bounds().Height()-2*PEN_SIZE+1;
if (width == 0 || height == 0) return rect;
fShrinkOrZoomToBounds = fShrinkToBounds &&
(rect.Width() >= Bounds().Width() || rect.Height() >= Bounds().Height()) ||
fZoomToBounds && rect.Width() < Bounds().Width() && rect.Height() < Bounds().Height();
// the width/height of the bitmap (in pixels)
float bitmapWidth = rect.Width() + 1.0;
float bitmapHeight = rect.Height() + 1.0;
// the available width/height for layouting the bitmap (in pixels)
float width = Bounds().Width() - 2 * PEN_SIZE + 1.0;
float height = Bounds().Height() - 2 * PEN_SIZE + 1.0;
if (width == 0 || height == 0)
return rect;
fShrinkOrZoomToBounds = (fShrinkToBounds &&
(bitmapWidth >= width || bitmapHeight >= height)) ||
(fZoomToBounds && (bitmapWidth < width && bitmapHeight < height));
if (fShrinkOrZoomToBounds) {
float s;
s = width / (rect.Width()+1.0);
if (s * (rect.Height()+1.0) <= height) {
rect.right = width-1;
rect.bottom = static_cast<int>(s * (rect.Height()+1.0))-1;
float s = width / bitmapWidth;
if (s * bitmapHeight <= height) {
rect.right = width - 1;
rect.bottom = static_cast<int>(s * bitmapHeight) - 1;
// center vertically
rect.OffsetBy(0, static_cast<int>((height - rect.Height()) / 2));
} else {
s = height / (rect.Height()+1.0);
rect.right = static_cast<int>(s * (rect.Width()+1.0))-1;
rect.bottom = height-1;
s = height / bitmapHeight;
rect.right = static_cast<int>(s * bitmapWidth) - 1;
rect.bottom = height - 1;
// center horizontally
rect.OffsetBy(static_cast<int>((width - rect.Width()) / 2), 0);
}
@@ -623,34 +629,40 @@ ShowImageView::AlignBitmap()
zoom = fZoom;
}
// zoom image
rect.right = static_cast<int>((rect.right+1.0)*zoom)-1;
rect.bottom = static_cast<int>((rect.bottom+1.0)*zoom)-1;
rect.right = floorf(bitmapWidth * zoom) - 1;
rect.bottom = floorf(bitmapHeight * zoom) - 1;
// align
switch (fHAlignment) {
case B_ALIGN_CENTER:
if (width > rect.Width()) {
rect.OffsetBy((width - rect.Width()) / 2.0, 0);
if (width > bitmapWidth) {
rect.OffsetBy((width - bitmapWidth) / 2.0, 0);
break;
}
// fall through
default:
case B_ALIGN_LEFT:
if (fHasBorder) {
rect.OffsetBy(BORDER_WIDTH, 0);
float border = min_c(BORDER_WIDTH, width - bitmapWidth);
if (border < 0)
border = 0;
rect.OffsetBy(border, 0);
}
break;
}
switch (fVAlignment) {
case B_ALIGN_MIDDLE:
if (height > rect.Height()) {
rect.OffsetBy(0, (height - rect.Height()) / 2.0);
if (height > bitmapHeight) {
rect.OffsetBy(0, (height - bitmapHeight) / 2.0);
break;
}
// fall through
default:
case B_ALIGN_TOP:
if (fHasBorder) {
rect.OffsetBy(0, BORDER_WIDTH);
float border = min_c(BORDER_WIDTH, height - bitmapHeight);
if (border < 0)
border = 0;
rect.OffsetBy(0, border);
}
break;
}
@@ -884,17 +896,7 @@ ShowImageView::ConstrainToImage(BPoint &point)
void
ShowImageView::ConstrainToImage(BRect &rect)
{
BRect bounds = fBitmap->Bounds();
BPoint leftTop, rightBottom;
leftTop = rect.LeftTop();
leftTop.ConstrainTo(bounds);
rightBottom = rect.RightBottom();
rightBottom.ConstrainTo(bounds);
rect.SetLeftTop(leftTop);
rect.SetRightBottom(rightBottom);
rect = rect & fBitmap->Bounds();
}
BBitmap*
@@ -902,8 +904,11 @@ ShowImageView::CopyFromRect(BRect srcRect)
{
BRect rect(0, 0, srcRect.Width(), srcRect.Height());
BView view(rect, NULL, B_FOLLOW_NONE, B_WILL_DRAW);
BBitmap *bitmap = new BBitmap(rect, fBitmap->ColorSpace(), true);
if (bitmap == NULL) return NULL;
BBitmap *bitmap = new(nothrow) BBitmap(rect, fBitmap->ColorSpace(), true);
if (bitmap == NULL || !bitmap->IsValid()) {
delete bitmap;
return NULL;
}
if (bitmap->Lock()) {
bitmap->AddChild(&view);
@@ -930,8 +935,11 @@ ShowImageView::CopySelection(uchar alpha, bool imageSize)
rect.bottom = floorf((rect.bottom + 1.0) * fScaleY - 1.0);
}
BView view(rect, NULL, B_FOLLOW_NONE, B_WILL_DRAW);
BBitmap *bitmap = new BBitmap(rect, hasAlpha ? B_RGBA32 : fBitmap->ColorSpace(), true);
if (bitmap == NULL) return NULL;
BBitmap *bitmap = new(nothrow) BBitmap(rect, hasAlpha ? B_RGBA32 : fBitmap->ColorSpace(), true);
if (bitmap == NULL || !bitmap->IsValid()) {
delete bitmap;
return NULL;
}
if (bitmap->Lock()) {
bitmap->AddChild(&view);
@@ -1201,9 +1209,11 @@ void
ShowImageView::MergeWithBitmap(BBitmap *merge, BRect selection)
{
BView view(fBitmap->Bounds(), NULL, B_FOLLOW_NONE, B_WILL_DRAW);
BBitmap *bitmap = new BBitmap(fBitmap->Bounds(), fBitmap->ColorSpace(), true);
if (bitmap == NULL)
BBitmap *bitmap = new(nothrow) BBitmap(fBitmap->Bounds(), fBitmap->ColorSpace(), true);
if (bitmap == NULL || !bitmap->IsValid()) {
delete bitmap;
return;
}
if (bitmap->Lock()) {
bitmap->AddChild(&view);
@@ -1445,7 +1455,6 @@ ShowImageView::KeyDown (const char * bytes, int32 numBytes)
case B_RIGHT_ARROW:
ScrollRestrictedBy(10, 0);
break;
case B_SPACE:
case B_ENTER:
NextFile();
break;
@@ -1456,13 +1465,21 @@ ShowImageView::KeyDown (const char * bytes, int32 numBytes)
break;
case B_END:
break;
case B_SPACE:
ToggleSlideShow();
break;
case B_ESCAPE:
if (fSlideShow) {
BMessenger msgr(Window());
msgr.SendMessage(MSG_SLIDE_SHOW);
}
// stop slide show
if (fSlideShow)
ToggleSlideShow();
ExitFullScreen();
ClearSelection();
break;
case B_DELETE:
// TODO: move image to Trash (script Tracker)
break;
}
}
}
@@ -1603,8 +1620,8 @@ ShowImageView::FixupScrollBar(orientation o, float bitmapLength, float viewLengt
psb = ScrollBar(o);
if (psb) {
if (fHasBorder && !fShrinkOrZoomToBounds) {
bitmapLength += BORDER_WIDTH*2;
if (fHasBorder && !fShrinkOrZoomToBounds && (fHAlignment == B_ALIGN_LEFT || fVAlignment == B_ALIGN_TOP)) {
bitmapLength += BORDER_WIDTH * 2;
}
range = bitmapLength - viewLength;
if (range < 0.0) {
@@ -1625,12 +1642,12 @@ ShowImageView::FixupScrollBars()
{
BRect rctview = Bounds(), rctbitmap(0, 0, 0, 0);
if (fBitmap) {
BRect rect(AlignBitmap());
rctbitmap.Set(0, 0, rect.Width(), rect.Height());
rctbitmap = AlignBitmap();
rctbitmap.OffsetTo(0, 0);
}
FixupScrollBar(B_HORIZONTAL, rctbitmap.Width(), rctview.Width());
FixupScrollBar(B_VERTICAL, rctbitmap.Height(), rctview.Height());
FixupScrollBar(B_HORIZONTAL, rctbitmap.Width() + 2 * PEN_SIZE, rctview.Width());
FixupScrollBar(B_VERTICAL, rctbitmap.Height() + 2 * PEN_SIZE, rctview.Height());
}
int32
@@ -1689,9 +1706,11 @@ ShowImageView::AddWhiteRect(BRect &rect)
{
// Paint white rectangle, using rect, into the background image
BView view(fBitmap->Bounds(), NULL, B_FOLLOW_NONE, B_WILL_DRAW);
BBitmap *bitmap = new BBitmap(fBitmap->Bounds(), fBitmap->ColorSpace(), true);
if (bitmap == NULL)
BBitmap *bitmap = new(nothrow) BBitmap(fBitmap->Bounds(), fBitmap->ColorSpace(), true);
if (bitmap == NULL || !bitmap->IsValid()) {
delete bitmap;
return;
}
if (bitmap->Lock()) {
bitmap->AddChild(&view);
@@ -1934,16 +1953,17 @@ ShowImageView::FindNextImageByDir(entry_ref *in_current, entry_ref *out_image, b
BList entries;
bool found = false;
int32 cur;
if (curImage.GetParent(&parent) != B_OK)
if (curImage.GetParent(&parent) != B_OK) {
return false;
}
// insert current ref, so we can find it easily after sorting
entries.AddItem(in_current);
while (parent.GetNextRef(&entry) == B_OK) {
if (entry != *in_current) {
entries.AddItem(new entry_ref(entry));
} else {
// insert current ref, so we can find it easily after sorting
entries.AddItem(in_current);
}
}
@@ -2019,9 +2039,9 @@ ShowImageView::FindNextImage(entry_ref *in_current, entry_ref *ref, bool next, b
BMessage reply;
if (fTrackerMessenger.SendMessage(&request, &reply) != B_OK)
return false;
return FindNextImageByDir(in_current, ref, next, rewind);;
if (reply.FindRef("result", &nextRef) != B_OK)
return false;
return FindNextImageByDir(in_current, ref, next, rewind);;
if (IsImage(&nextRef))
foundRef = true;
@@ -2037,11 +2057,9 @@ ShowImageView::FindNextImage(entry_ref *in_current, entry_ref *ref, bool next, b
bool
ShowImageView::ShowNextImage(bool next, bool rewind)
{
bool found;
entry_ref curRef, imgRef;
curRef = fCurrentRef;
found = FindNextImage(&curRef, &imgRef, next, 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
@@ -2305,3 +2323,19 @@ ShowImageView::SetIcon(bool clear)
SetIcon(clear, B_MINI_ICON);
SetIcon(clear, B_LARGE_ICON);
}
void
ShowImageView::ToggleSlideShow()
{
BMessenger msgr(Window());
msgr.SendMessage(MSG_SLIDE_SHOW);
}
void
ShowImageView::ExitFullScreen()
{
BMessenger m(Window());
m.SendMessage(MSG_EXIT_FULL_SCREEN);
}
+4
View File
@@ -41,6 +41,8 @@
// delay scaling operation, so that a sequence of zoom in/out operations works smoother
#define DELAYED_SCALING 1
// width of the black border stroked arround the bitmap
#define PEN_SIZE 1.0f
class ShowImageView : public BView {
public:
@@ -195,6 +197,8 @@ private:
void ShowPopUpMenu(BPoint screen);
void SettingsSetBool(const char* name, bool value);
void SetIcon(bool clear, icon_size which);
void ToggleSlideShow();
void ExitFullScreen();
BMessenger fTrackerMessenger; // of the window that this was launched from
entry_ref fCurrentRef; // of the image
+24 -11
View File
@@ -302,21 +302,21 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
pmenu = fBrowseMenu = new BMenu("Browse");
AddItemMenu(pmenu, "First Page", MSG_PAGE_FIRST, B_LEFT_ARROW, B_SHIFT_KEY, 'W', true);
AddItemMenu(pmenu, "Last Page", MSG_PAGE_LAST, B_RIGHT_ARROW, B_SHIFT_KEY, 'W', true);
AddItemMenu(pmenu, "Next Page", MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Previous Page", MSG_PAGE_PREV, B_LEFT_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Next Page", MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, 'W', true);
fGoToPageMenu = new BMenu("Go To Page");
fGoToPageMenu->SetRadioMode(true);
pmenu->AddItem(fGoToPageMenu);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Next File", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Previous File", MSG_FILE_PREV, B_UP_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Next File", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true);
pbar->AddItem(pmenu);
pmenu = new BMenu("Image");
AddItemMenu(pmenu, "Dither Image", MSG_DITHER_IMAGE, 0, 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Rotate +90°", MSG_ROTATE_90, ']', 0, 'W', true);
AddItemMenu(pmenu, "Rotate -90°", MSG_ROTATE_270, '[', 0, 'W', true);
AddItemMenu(pmenu, "Rotate +90°", MSG_ROTATE_90, ']', 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Mirror Vertical", MSG_MIRROR_VERTICAL, 0, 0, 'W', true);
AddItemMenu(pmenu, "Mirror Horizontal", MSG_MIRROR_HORIZONTAL, 0, 0, 'W', true);
@@ -365,9 +365,6 @@ ShowImageWindow::WindowRedimension(BBitmap *pbitmap)
{
BScreen screen;
BRect r(pbitmap->Bounds());
float width, height;
float maxWidth, maxHeight;
float minW, maxW, minH, maxH;
const float windowBorderWidth = 5;
const float windowBorderHeight = 5;
@@ -375,15 +372,16 @@ ShowImageWindow::WindowRedimension(BBitmap *pbitmap)
return; // invalid screen object
}
width = r.Width() + B_V_SCROLL_BAR_WIDTH;
height = r.Height() + 1 + fBar->Frame().Height() + B_H_SCROLL_BAR_HEIGHT;
float width = r.Width() + 2 * PEN_SIZE + B_V_SCROLL_BAR_WIDTH;
float height = r.Height() + 2 * PEN_SIZE + 1 + fBar->Frame().Height() + B_H_SCROLL_BAR_HEIGHT;
// dimensions so that window does not reach outside of screen
maxWidth = screen.Frame().Width() + 1 - windowBorderWidth - Frame().left;
maxHeight = screen.Frame().Height() + 1 - windowBorderHeight - Frame().top;
float maxWidth = screen.Frame().Width() + 1 - windowBorderWidth - Frame().left;
float maxHeight = screen.Frame().Height() + 1 - windowBorderHeight - Frame().top;
// We have to check size limits manually, otherwise
// menu bar will be too short for small images.
float minW, maxW, minH, maxH;
GetSizeLimits(&minW, &maxW, &minH, &maxH);
if (maxWidth > maxW) maxWidth = maxW;
if (maxHeight > maxH) maxHeight = maxH;
@@ -739,6 +737,10 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
case MSG_FULL_SCREEN:
ToggleFullScreen();
break;
case MSG_EXIT_FULL_SCREEN:
if (fFullScreen)
ToggleFullScreen();
break;
case MSG_SHOW_CAPTION:
fShowCaption = ToggleMenuItem(pmsg->what);
settings = my_app->Settings();
@@ -911,7 +913,11 @@ ShowImageWindow::ToggleFullScreen()
frame = fWindowFrame;
SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
fImageView->SetAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
// NOTE: I changed this to not use left/top alignment at all, because
// I have no idea why it would be useful. The layouting is much more
// predictable now. -Stephan
// fImageView->SetAlignment(B_ALIGN_LEFT, B_ALIGN_TOP);
fImageView->SetAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE);
}
fImageView->SetBorder(!fFullScreen);
fImageView->SetShowCaption(fFullScreen && fShowCaption);
@@ -1082,3 +1088,10 @@ ShowImageWindow::Quit()
BWindow::Quit();
}
void
ShowImageWindow::Zoom(BPoint origin, float width, float height)
{
// just go into fullscreen
ToggleFullScreen();
}
+1
View File
@@ -63,6 +63,7 @@ public:
virtual void MessageReceived(BMessage *pmsg);
virtual bool QuitRequested();
virtual void Quit();
virtual void Zoom(BPoint origin, float width, float height);
status_t InitCheck();
ShowImageView *GetShowImageView() const { return fImageView; }