From fc5ca95d01199ef05e072a79ce4bfe827736f097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 13 Jun 2005 20:09:46 +0000 Subject: [PATCH] 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 --- src/apps/showimage/ShowImageConstants.h | 1 + src/apps/showimage/ShowImageView.cpp | 212 ++++++++++++++---------- src/apps/showimage/ShowImageView.h | 4 + src/apps/showimage/ShowImageWindow.cpp | 35 ++-- src/apps/showimage/ShowImageWindow.h | 1 + 5 files changed, 153 insertions(+), 100 deletions(-) diff --git a/src/apps/showimage/ShowImageConstants.h b/src/apps/showimage/ShowImageConstants.h index 5b2f05446e..8bab51f262 100644 --- a/src/apps/showimage/ShowImageConstants.h +++ b/src/apps/showimage/ShowImageConstants.h @@ -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'; diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index c60b2d0eed..ebc0a72d7d 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -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(s * (rect.Height()+1.0))-1; + float s = width / bitmapWidth; + + if (s * bitmapHeight <= height) { + rect.right = width - 1; + rect.bottom = static_cast(s * bitmapHeight) - 1; // center vertically rect.OffsetBy(0, static_cast((height - rect.Height()) / 2)); } else { - s = height / (rect.Height()+1.0); - rect.right = static_cast(s * (rect.Width()+1.0))-1; - rect.bottom = height-1; + s = height / bitmapHeight; + rect.right = static_cast(s * bitmapWidth) - 1; + rect.bottom = height - 1; // center horizontally rect.OffsetBy(static_cast((width - rect.Width()) / 2), 0); } @@ -623,34 +629,40 @@ ShowImageView::AlignBitmap() zoom = fZoom; } // zoom image - rect.right = static_cast((rect.right+1.0)*zoom)-1; - rect.bottom = static_cast((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); +} + + diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 34b23cbbc1..caa410484d 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -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 diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 725555ae88..bc5a8bc51b 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -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(); +} + diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index b513e70afb..754b02b02e 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -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; }