diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 27f01dc2ed..e73e2dc5b1 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -234,9 +234,15 @@ ShowImageView::Pulse() } if (fHideCursor && !fHasSelection && !fShowingPopUpMenu && fIsActiveWin) { - if (fHideCursorCountDown <= 0) - be_app->ObscureCursor(); - else + if (fHideCursorCountDown <= 0) { + BPoint mousePos; + uint32 buttons; + GetMouse(&mousePos, &buttons, false); + if (Bounds().Contains(mousePos)) { + be_app->ObscureCursor(); + _ShowToolBarIfEnabled(false); + } + } else fHideCursorCountDown--; } } @@ -1147,6 +1153,7 @@ void ShowImageView::MouseMoved(BPoint point, uint32 state, const BMessage* message) { fHideCursorCountDown = HIDE_CURSOR_DELAY_TIME; + _ShowToolBarIfEnabled(true); if (fCreatingSelection) _UpdateSelectionRect(point, false); else if (fScrollingBitmap) @@ -1824,6 +1831,15 @@ ShowImageView::_ExitFullScreen() } +void +ShowImageView::_ShowToolBarIfEnabled(bool show) +{ + BMessage message(kShowToolBarIfEnabled); + message.AddBool("show", show); + Window()->PostMessage(&message); +} + + void ShowImageView::WindowActivated(bool active) { diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index ab3a9b1e07..d028e5c3be 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -178,6 +178,7 @@ private: void _ToggleSlideShow(); void _StopSlideShow(); void _ExitFullScreen(); + void _ShowToolBarIfEnabled(bool show); private: ShowImageUndo fUndo; diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 39da5f093a..aabf2c0225 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -97,7 +97,9 @@ enum { kMsgOriginalSize = 'mOSZ', kMsgStretchToWindow = 'mStW', kMsgNextSlide = 'mNxS', - kMsgToggleToolBar = 'mTTB' + kMsgToggleToolBar = 'mTTB', + kMsgSlideToolBar = 'mSTB', + kMsgFinishSlidingToolBar = 'mFST' }; @@ -127,7 +129,7 @@ bs_printf(BString* string, const char* format, ...) ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref, const BMessenger& trackerMessenger) : - BWindow(frame, "", B_DOCUMENT_WINDOW, 0), + BWindow(frame, "", B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS), fNavigator(ref, trackerMessenger), fSavePanel(NULL), fBar(NULL), @@ -148,15 +150,25 @@ ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref, { _ApplySettings(); + SetLayout(new BGroupLayout(B_VERTICAL, 0)); + // create menu bar - fBar = new BMenuBar(BRect(0, 0, Bounds().right, 1), "menu_bar"); + fBar = new BMenuBar("menu_bar"); _AddMenus(fBar); + float menuBarMinWidth = fBar->MinSize().width; AddChild(fBar); - BRect viewFrame = Bounds(); - viewFrame.top = fBar->Bounds().Height() + 1; - viewFrame.bottom = viewFrame.top + 30; + // Add a content view so the tool bar can be moved outside of the + // visible portion without colliding with the menu bar. + BView* contentView = new BView(BRect(), "content", B_FOLLOW_NONE, 0); + contentView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + contentView->SetExplicitMinSize(BSize(250, 100)); + AddChild(contentView); + + // Create the tool bar + BRect viewFrame = contentView->Bounds(); + viewFrame.right -= B_V_SCROLL_BAR_WIDTH; fToolBarView = new ToolBarView(viewFrame); // Add the tool icons. @@ -184,21 +196,21 @@ ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref, B_TRANSLATE("Zoom in")); fToolBarView->AddAction(MSG_ZOOM_OUT, this, tool_bar_icon(kIconZoomOut), B_TRANSLATE("Zoom out")); -// fToolBarView->AddSeparator(); -// fToolBarView->AddAction(MSG_FULL_SCREEN, this, -// tool_bar_icon(kIconViewFullScreen), B_TRANSLATE("Full screen")); + fToolBarView->AddGlue(); + fToolBarView->AddAction(MSG_FULL_SCREEN, this, + tool_bar_icon(kIconViewWindowed), B_TRANSLATE("Leave full screen")); + fToolBarView->SetActionVisible(MSG_FULL_SCREEN, false); fToolBarView->ResizeTo(viewFrame.Width(), fToolBarView->MinSize().height); - AddChild(fToolBarView); + contentView->AddChild(fToolBarView); if (fShowToolBar) viewFrame.top = fToolBarView->Frame().bottom + 1; else fToolBarView->Hide(); - viewFrame.bottom = Bounds().bottom; - viewFrame.right -= B_V_SCROLL_BAR_WIDTH; + viewFrame.bottom = contentView->Bounds().bottom; viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT; // create the image view @@ -208,40 +220,38 @@ ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref, // wrap a scroll view around the view fScrollView = new BScrollView("image_scroller", fImageView, B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER); - AddChild(fScrollView); + contentView->AddChild(fScrollView); const int32 kstatusWidth = 190; BRect rect; - rect = Bounds(); + rect = contentView->Bounds(); rect.top = viewFrame.bottom + 1; rect.left = viewFrame.left + kstatusWidth; rect.right = viewFrame.right + 1; rect.bottom += 1; BScrollBar* horizontalScrollBar = new BScrollBar(rect, "hscroll", fImageView, 0, 150, B_HORIZONTAL); - AddChild(horizontalScrollBar); + contentView->AddChild(horizontalScrollBar); rect.left = 0; rect.right = kstatusWidth - 1; rect.bottom -= 1; fStatusView = new ShowImageStatusView(rect, "status_view", B_FOLLOW_BOTTOM, B_WILL_DRAW); - AddChild(fStatusView); + contentView->AddChild(fStatusView); - rect = Bounds(); + rect = contentView->Bounds(); rect.top = viewFrame.top - 1; rect.left = viewFrame.right + 1; rect.bottom = viewFrame.bottom + 1; rect.right += 1; fVerticalScrollBar = new BScrollBar(rect, "vscroll", fImageView, 0, 150, B_VERTICAL); - AddChild(fVerticalScrollBar); + contentView->AddChild(fVerticalScrollBar); // Update minimum window size - float menuBarMinWidth; - fBar->GetPreferredSize(&menuBarMinWidth, NULL); - float toolBarMinWidth; - fToolBarView->GetPreferredSize(&toolBarMinWidth, NULL); + float toolBarMinWidth = fToolBarView->MinSize().width; + printf("menu min size: %.1f, tool bar: %.1f\n", menuBarMinWidth, toolBarMinWidth); SetSizeLimits(std::max(menuBarMinWidth, toolBarMinWidth), 100000, 100, 100000); @@ -345,8 +355,8 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu) _MarkMenuItem(menu, kMsgStretchToWindow, fImageView->StretchesToBounds()); if (!popupMenu) { - _AddItemMenu(menu, B_TRANSLATE("Show tool bar"), kMsgToggleToolBar, 0, - 0, this); + _AddItemMenu(menu, B_TRANSLATE("Show tool bar"), kMsgToggleToolBar, + 'T', 0, this); _MarkMenuItem(menu, kMsgToggleToolBar, !fToolBarView->IsHidden(fToolBarView)); } @@ -882,15 +892,8 @@ ShowImageWindow::MessageReceived(BMessage* message) case MSG_SLIDE_SHOW: { - // TODO: Maybe two distinct messages? Also once the tool bar - // automatically shows in full screen mode, the icon should - // be a pause. There should be a separate icon to leave full - // screen mode as well. - bool fullScreen; - if (message->FindBool("full screen", &fullScreen) == B_OK - && fullScreen) { - _ToggleFullScreen(); - } + bool fullScreen = false; + message->FindBool("full screen", &fullScreen); BMenuItem* item = fBar->FindItem(message->what); if (item == NULL) @@ -899,9 +902,13 @@ ShowImageWindow::MessageReceived(BMessage* message) if (item->IsMarked()) { item->SetMarked(false); _StopSlideShow(); + fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, false); } else if (_ClosePrompt()) { item->SetMarked(true); + if (!fFullScreen && fullScreen) + _ToggleFullScreen(); _StartSlideShow(); + fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, true); } break; } @@ -913,6 +920,7 @@ ShowImageWindow::MessageReceived(BMessage* message) item->SetMarked(false); _StopSlideShow(); + fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, false); break; } @@ -1004,7 +1012,7 @@ ShowImageWindow::MessageReceived(BMessage* message) case kMsgToggleToolBar: { fShowToolBar = _ToggleMenuItem(message->what); - _SetToolBarVisible(fShowToolBar); + _SetToolBarVisible(fShowToolBar, true); ShowImageSettings* settings = my_app->Settings(); @@ -1014,6 +1022,54 @@ ShowImageWindow::MessageReceived(BMessage* message) } break; } + case kShowToolBarIfEnabled: + { + bool show; + if (message->FindBool("show", &show) != B_OK) + break; + _SetToolBarVisible(fShowToolBar && show, true); + break; + } + case kMsgSlideToolBar: + { + float offset; + if (message->FindFloat("offset", &offset) == B_OK) { + fToolBarView->MoveBy(0, offset); + fScrollView->ResizeBy(0, -offset); + fScrollView->MoveBy(0, offset); + fVerticalScrollBar->ResizeBy(0, -offset); + fVerticalScrollBar->MoveBy(0, offset); + UpdateIfNeeded(); + snooze(15000); + } + break; + } + case kMsgFinishSlidingToolBar: + { + float offset; + bool show; + if (message->FindFloat("offset", &offset) == B_OK + && message->FindBool("show", &show) == B_OK) { + // Compensate rounding errors with the final placement + if (show) { + fToolBarView->MoveTo(fToolBarView->Frame().left, 0); + } else { + fToolBarView->MoveTo(fToolBarView->Frame().left, offset); + fToolBarView->Hide(); + } + BRect frame = fToolBarView->Parent()->Bounds(); + frame.top = fToolBarView->Frame().bottom + 1; + fScrollView->MoveTo(0, frame.top); + fScrollView->ResizeTo(fScrollView->Bounds().Width(), + frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1); + fVerticalScrollBar->MoveTo( + frame.right - B_V_SCROLL_BAR_WIDTH + 1, frame.top); + fVerticalScrollBar->ResizeTo( + fVerticalScrollBar->Bounds().Width(), + frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1); + } + break; + } default: BWindow::MessageReceived(message); @@ -1231,7 +1287,7 @@ ShowImageWindow::_ToggleFullScreen() SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); } - fToolBarView->SetActionPressed(MSG_FULL_SCREEN, fFullScreen); + fToolBarView->SetActionVisible(MSG_FULL_SCREEN, fFullScreen); _SetToolBarVisible(!fFullScreen && fShowToolBar); MoveTo(frame.left, frame.top); @@ -1453,24 +1509,40 @@ ShowImageWindow::_UpdateRatingMenu() void -ShowImageWindow::_SetToolBarVisible(bool visible) +ShowImageWindow::_SetToolBarVisible(bool visible, bool animate) { if (visible == !fToolBarView->IsHidden()) return; - float diff = fToolBarView->Bounds().Height() + 1; - if (!visible) { + float diff = fToolBarView->Bounds().Height() + 2; + if (!visible) diff = -diff; - fToolBarView->Hide(); - } - - fScrollView->ResizeBy(0, -diff); - fScrollView->MoveBy(0, diff); - fVerticalScrollBar->ResizeBy(0, -diff); - fVerticalScrollBar->MoveBy(0, diff); - - if (visible) + else fToolBarView->Show(); + + if (animate) { + // Slide the controls into view. We do this with messages in order + // not to block the window thread. + const float kAnimationOffsets[] = { 0.05, 0.2, 0.5, 0.2, 0.05 }; + const int32 steps = sizeof(kAnimationOffsets) / sizeof(float); + float originalY = fToolBarView->Frame().top; + for (int32 i = 0; i < steps; i++) { + BMessage message(kMsgSlideToolBar); + message.AddFloat("offset", floorf(diff * kAnimationOffsets[i])); + PostMessage(&message, this); + } + BMessage finalMessage(kMsgFinishSlidingToolBar); + finalMessage.AddFloat("offset", originalY + diff); + finalMessage.AddBool("show", visible); + PostMessage(&finalMessage, this); + } else { + fScrollView->ResizeBy(0, -diff); + fScrollView->MoveBy(0, diff); + fVerticalScrollBar->ResizeBy(0, -diff); + fVerticalScrollBar->MoveBy(0, diff); + if (!visible) + fToolBarView->Hide(); + } } diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index 847b6acfc8..f5cf499b41 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -42,6 +42,7 @@ enum { MSG_SLIDE_SHOW = 'mSSW', kMsgStopSlideShow = 'msss', MSG_FULL_SCREEN = 'mFSC', + kShowToolBarIfEnabled = 'mSTE', MSG_EXIT_FULL_SCREEN = 'mEFS', MSG_WINDOW_HAS_QUIT = 'wndq' }; @@ -102,7 +103,8 @@ private: void _UpdateRatingMenu(); - void _SetToolBarVisible(bool visible); + void _SetToolBarVisible(bool visible, + bool animate = false); private: ImageFileNavigator fNavigator;