diff --git a/src/apps/showimage/ShowImageConstants.h b/src/apps/showimage/ShowImageConstants.h index f52fb25ae2..10a194c0cb 100644 --- a/src/apps/showimage/ShowImageConstants.h +++ b/src/apps/showimage/ShowImageConstants.h @@ -54,10 +54,11 @@ const uint32 MSG_ROTATE_ACLKWISE = 'mRAC'; const uint32 MSG_MIRROR_VERTICAL = 'mMIV'; const uint32 MSG_MIRROR_HORIZONTAL = 'mMIH'; const uint32 MSG_INVERT = 'mINV'; -const uint32 MSG_DIA_SHOW = 'mDIA'; -const uint32 MSG_DIA_SHOW_DELAY = 'mDSD'; +const uint32 MSG_SLIDE_SHOW = 'mSSW'; +const uint32 MSG_SLIDE_SHOW_DELAY = 'mSSD'; const uint32 MSG_FULL_SCREEN = 'mFSC'; const uint32 MSG_UPDATE_RECENT_DOCUMENTS = 'mURD'; +const uint32 MSG_SHOW_CAPTION = 'mSCP'; extern const char *APP_SIG; diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index b354ad3d72..f185a6139b 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "ShowImageConstants.h" #include "ShowImageView.h" @@ -132,10 +133,10 @@ ShowImageView::Pulse() RotatePatterns(); DrawSelectionBox(fSelectionRect); } - if (fDiaShow) { - fDiaShowCountDown --; - if (fDiaShowCountDown <= 0) { - fDiaShowCountDown = fDiaShowDelay; + if (fSlideShow) { + fSlideShowCountDown --; + if (fSlideShowCountDown <= 0) { + fSlideShowCountDown = fSlideShowDelay; if (!NextFile()) { FirstFile(); } @@ -155,9 +156,10 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, fAnimateSelection = true; fbHasSelection = false; fResizeToViewBounds = false; - fDiaShow = false; - SetDiaShowDelay(3); // 3 seconds + fSlideShow = false; + SetSlideShowDelay(3); // 3 seconds fBeginDrag = false; + fShowCaption = false; SetViewColor(B_TRANSPARENT_COLOR); SetHighColor(kborderColor); @@ -201,7 +203,6 @@ ShowImageView::Notify(const char* status) if (status != NULL) { msg.AddString("status", status); } - msg.AddRef("ref", &fCurrentRef); BMessenger msgr(Window()); msgr.SendMessage(&msg); @@ -262,12 +263,27 @@ ShowImageView::SetImage(const entry_ref *pref) fDocumentCount = documentCount; else fDocumentCount = 1; + + GetPath(&fCaption); + if (fDocumentCount > 1) { + fCaption << ", " << fDocumentIndex << "/" << fDocumentCount; + } + fCaption << ", " << info.name; AddToRecentDocuments(); Notify(info.name); } +void +ShowImageView::SetShowCaption(bool show) +{ + if (fShowCaption != show) { + fShowCaption = show; + Invalidate(); + } +} + void ShowImageView::ResizeToViewBounds(bool resize) { @@ -284,6 +300,20 @@ ShowImageView::GetBitmap() return fpBitmap; } +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()); + } + } +} + void ShowImageView::FlushToLeftTop() { @@ -379,6 +409,49 @@ ShowImageView::DrawBorder(BRect border) FillRect(BRect(0, border.bottom+1, bounds.right, bounds.bottom), B_SOLID_LOW); } +void +ShowImageView::DrawCaption() +{ + font_height fontHeight; + float width, height; + BRect bounds(Bounds()); + BFont font(be_plain_font); + BPoint pos; + BRect rect; + width = font.StringWidth(fCaption.String())+1; // 1 for text shadow + font.GetHeight(&fontHeight); + height = fontHeight.ascent + fontHeight.descent; + // center text vertically + pos.x = (bounds.left + bounds.right - width)/2; + // flush bottom + pos.y = bounds.bottom - fontHeight.descent - 5; + + // background rectangle + rect.Set(0, 0, (width-1)+2, (height-1)+2+1); // 2 for border and 1 for text shadow + rect.OffsetTo(pos); + rect.OffsetBy(-1, -1-fontHeight.ascent); // -1 for border + + PushState(); + // draw background + SetDrawingMode(B_OP_ALPHA); + SetHighColor(0, 0, 255, 128); + FillRect(rect); + // draw text + SetDrawingMode(B_OP_OVER); + SetFont(&font); + SetLowColor(B_TRANSPARENT_COLOR); + // text shadow + pos += BPoint(1, 1); + SetHighColor(0, 0, 0); + SetPenSize(1); + DrawString(fCaption.String(), pos); + // text + pos -= BPoint(1, 1); + SetHighColor(255, 255, 0); + DrawString(fCaption.String(), pos); + PopState(); +} + void ShowImageView::Draw(BRect updateRect) { @@ -397,8 +470,13 @@ ShowImageView::Draw(BRect updateRect) // Draw image DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect); - if (fbHasSelection) + if (fShowCaption) { + DrawCaption(); + } + + if (fbHasSelection) { DrawSelectionBox(fSelectionRect); + } } } @@ -780,7 +858,7 @@ ShowImageView::CopySelectionToClipboard() BMessage data; BBitmap* bitmap = CopySelection(); if (bitmap != NULL) { - #if 1 + #if 0 // According to BeBook and Becasso, Gobe Productive do the following. // Paste works in Productive, but not in Becasso and original ShowImage. BMessage msg(B_OK); // Becasso uses B_TRANSLATOR_BITMAP, BeBook says its unused @@ -932,21 +1010,21 @@ ShowImageView::FirstFile() } void -ShowImageView::SetDiaShowDelay(float seconds) +ShowImageView::SetSlideShowDelay(float seconds) { - fDiaShowDelay = (int)(seconds * 10.0); + fSlideShowDelay = (int)(seconds * 10.0); } void -ShowImageView::StartDiaShow() +ShowImageView::StartSlideShow() { - fDiaShow = true; fDiaShowCountDown = fDiaShowDelay; + fSlideShow = true; fSlideShowCountDown = fSlideShowDelay; } void -ShowImageView::StopDiaShow() +ShowImageView::StopSlideShow() { - fDiaShow = false; + fSlideShow = false; } int32 diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 26ea162cc9..8ae61f5e4b 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -44,8 +44,10 @@ public: void Pulse(); void SetImage(const entry_ref *pref); + void SetShowCaption(bool show); void ResizeToViewBounds(bool resize); BBitmap *GetBitmap(); + void GetPath(BString *name); void FlushToLeftTop(); virtual void AttachedToWindow(); @@ -72,9 +74,9 @@ public: void PrevPage(); bool NextFile(); bool PrevFile(); - void SetDiaShowDelay(float seconds); - void StartDiaShow(); - void StopDiaShow(); + void SetSlideShowDelay(float seconds); + void StartSlideShow(); + void StopSlideShow(); // Image manipulation void Rotate(int degree); // 90 and 270 only @@ -118,6 +120,7 @@ private: void HandleDrop(BMessage* msg); void UpdateSelectionRect(BPoint point, bool final); void DrawBorder(BRect border); + void DrawCaption(); void DrawSelectionBox(BRect &rect); entry_ref fCurrentRef; @@ -137,9 +140,12 @@ private: BRect fSelectionRect; // the selection in image space pattern fPatternUp, fPatternDown, fPatternLeft, fPatternRight; - bool fDiaShow; - int fDiaShowDelay; - int fDiaShowCountDown; + bool fSlideShow; + int fSlideShowDelay; + int fSlideShowCountDown; + + bool fShowCaption; + BString fCaption; }; #endif /* _ShowImageView_h */ diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index fe675cc054..aafb65d9b5 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -54,8 +54,8 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) : BWindow(BRect(50, 50, 350, 250), "", B_DOCUMENT_WINDOW, 0) { fpSavePanel = NULL; - fpRef = NULL; fFullScreen = false; + fShowCaption = true; // XXX what is best for default? // create menu bar fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar"); @@ -104,7 +104,6 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) SetSizeLimits(250, 100000, 100, 100000); // finish creating window - SetRef(pref); UpdateTitle(); fpImageView->SetImage(pref); @@ -116,6 +115,12 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) WindowRedimension(fpImageView->GetBitmap()); Show(); } else { + BAlert* alert; + alert = new BAlert("ShowImage", + "Could not load image! Either the file or an image translator for it does not exist.", + "OK", NULL, NULL, + B_WIDTH_AS_USUAL, B_INFO_ALERT); + alert->Go(); // exit if file could not be opened Quit(); } @@ -123,37 +128,23 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) ShowImageWindow::~ShowImageWindow() { - delete fpRef; } status_t ShowImageWindow::InitCheck() { - if (!fpRef || !fpImageView || fpImageView->GetBitmap() == NULL) + if (!fpImageView || fpImageView->GetBitmap() == NULL) return B_ERROR; else return B_OK; } -void -ShowImageWindow::SetRef(const entry_ref *pref) -{ - if (!fpRef) - fpRef = new entry_ref(*pref); - else - *fpRef = *pref; -} - void ShowImageWindow::UpdateTitle() { - BEntry entry(fpRef); - if (entry.InitCheck() == B_OK) { - BPath path; - entry.GetPath(&path); - if (path.InitCheck() == B_OK) - SetTitle(path.Path()); - } + BString path; + fpImageView->GetPath(&path); + SetTitle(path.String()); } void @@ -191,29 +182,6 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar) fpOpenMenu->Superitem()->SetTarget(be_app); fpOpenMenu->Superitem()->SetShortcut('O', 0); pmenu->AddSeparatorItem(); - AddItemMenu(pmenu, "Dia Show", MSG_DIA_SHOW, 0, 0, 'W', true); - BMenu* pDelay = new BMenu("Delay"); - pDelay->SetRadioMode(true); - // Note: ShowImage loades images in window thread so it becomes unresponsive if - // dia show delay is too short! (Especially if loading the image takes as long as - // or longer than the dia show delay). Should load in background thread! - // AddDelayItem(pDelay, "Half a Second", 0.5, false); - // AddDelayItem(pDelay, "One Second", 1, false); - // AddDelayItem(pDelay, "Two Second", 2, false); - AddDelayItem(pDelay, "Three Seconds", 3, true); - AddDelayItem(pDelay, "Four Second", 4, false); - AddDelayItem(pDelay, "Five Seconds", 5, false); - AddDelayItem(pDelay, "Six Seconds", 6, false); - AddDelayItem(pDelay, "Seven Seconds", 7, false); - AddDelayItem(pDelay, "Eight Seconds", 8, false); - AddDelayItem(pDelay, "Nine Seconds", 9, false); - AddDelayItem(pDelay, "Ten Seconds", 10, false); - AddDelayItem(pDelay, "Tweenty Seconds", 20, false); - pmenu->AddItem(pDelay); - pmenu->AddSeparatorItem(); - AddItemMenu(pmenu, "Next", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true); - AddItemMenu(pmenu, "Previous", MSG_FILE_PREV, B_UP_ARROW, 0, 'W', true); - pmenu->AddSeparatorItem(); BMenu *pmenuSaveAs = new BMenu("Save As...", B_ITEMS_IN_COLUMN); BTranslationUtils::AddTranslationItems(pmenuSaveAs, B_TRANSLATOR_BITMAP); // Fill Save As submenu with all types that can be converted @@ -237,11 +205,14 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar) AddItemMenu(pmenu, "Select All", MSG_SELECT_ALL, 'A', 0, 'W', true); pbar->AddItem(pmenu); - pmenu = fpPageMenu = new BMenu("Page"); - AddItemMenu(pmenu, "First", MSG_PAGE_FIRST, 'F', 0, 'W', true); - AddItemMenu(pmenu, "Last", MSG_PAGE_LAST, 'L', 0, 'W', true); - AddItemMenu(pmenu, "Next", MSG_PAGE_NEXT, 'N', 0, 'W', true); - AddItemMenu(pmenu, "Previous", MSG_PAGE_PREV, 'P', 0, 'W', true); + pmenu = fpBrowseMenu = new BMenu("Browse"); + AddItemMenu(pmenu, "First Page", MSG_PAGE_FIRST, 'F', 0, 'W', true); + AddItemMenu(pmenu, "Last Page", MSG_PAGE_LAST, 'L', 0, 'W', true); + AddItemMenu(pmenu, "Next Page", MSG_PAGE_NEXT, 'N', 0, 'W', true); + AddItemMenu(pmenu, "Previous Page", MSG_PAGE_PREV, 'P', 0, 'W', true); + 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); pbar->AddItem(pmenu); pmenu = new BMenu("Image"); @@ -257,9 +228,31 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar) pbar->AddItem(pmenu); pmenu = new BMenu("View"); + AddItemMenu(pmenu, "Slide Show", MSG_SLIDE_SHOW, 0, 0, 'W', true); + BMenu* pDelay = new BMenu("Slide Delay"); + pDelay->SetRadioMode(true); + // Note: ShowImage loades images in window thread so it becomes unresponsive if + // slide show delay is too short! (Especially if loading the image takes as long as + // or longer than the slide show delay). Should load in background thread! + // AddDelayItem(pDelay, "Half a Second", 0.5, false); + // AddDelayItem(pDelay, "One Second", 1, false); + // AddDelayItem(pDelay, "Two Second", 2, false); + AddDelayItem(pDelay, "Three Seconds", 3, true); + AddDelayItem(pDelay, "Four Second", 4, false); + AddDelayItem(pDelay, "Five Seconds", 5, false); + AddDelayItem(pDelay, "Six Seconds", 6, false); + AddDelayItem(pDelay, "Seven Seconds", 7, false); + AddDelayItem(pDelay, "Eight Seconds", 8, false); + AddDelayItem(pDelay, "Nine Seconds", 9, false); + AddDelayItem(pDelay, "Ten Seconds", 10, false); + AddDelayItem(pDelay, "Tweenty Seconds", 20, false); + pmenu->AddItem(pDelay); + pmenu->AddSeparatorItem(); AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true); AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true); + AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true); pbar->AddItem(pmenu); + MarkMenuItem(MSG_SHOW_CAPTION, fShowCaption); UpdateRecentDocumentsMenu(); } @@ -285,7 +278,7 @@ ShowImageWindow::AddDelayItem(BMenu *pmenu, char *caption, float value, bool mar { BMenuItem* pitem; BMessage* pmsg; - pmsg = new BMessage(MSG_DIA_SHOW_DELAY); + pmsg = new BMessage(MSG_SLIDE_SHOW_DELAY); pmsg->AddFloat("value", value); pitem = new BMenuItem(caption, pmsg, 0); @@ -341,6 +334,30 @@ ShowImageWindow::ToggleMenuItem(uint32 what) return marked; } +void +ShowImageWindow::EnableMenuItem(uint32 what, bool enable) +{ + BMenuItem* item; + item = fpBar->FindItem(what); + if (item && item->IsEnabled() != enable) { + // XXX: Does this apply to menu items too? + // Only call this function if the state is changing + // to avoid flickering + item->SetEnabled(enable); + } +} + +void +ShowImageWindow::MarkMenuItem(uint32 what, bool marked) +{ + BMenuItem* item; + item = fpBar->FindItem(what); + if (item && item->IsMarked() != marked) { + item->SetMarked(marked); + } +} + + void ShowImageWindow::MessageReceived(BMessage *pmsg) { @@ -370,20 +387,16 @@ ShowImageWindow::MessageReceived(BMessage *pmsg) case MSG_UPDATE_STATUS: { bool benable = (fpImageView->PageCount() > 1) ? true : false; - if (fpPageMenu->IsEnabled() != benable) - // Only call this function if the state is changing - // to avoid flickering - fpPageMenu->SetEnabled(benable); + EnableMenuItem(MSG_PAGE_FIRST, benable); + EnableMenuItem(MSG_PAGE_LAST, benable); + EnableMenuItem(MSG_PAGE_NEXT, benable); + EnableMenuItem(MSG_PAGE_PREV, benable); BString str; if (pmsg->FindString("status", &str) == B_OK) fpStatusView->SetText(str); - entry_ref ref; - if (pmsg->FindRef("ref", &ref) == B_OK) { - SetRef(&ref); - UpdateTitle(); - } + UpdateTitle(); break; } @@ -454,17 +467,17 @@ ShowImageWindow::MessageReceived(BMessage *pmsg) case MSG_INVERT: fpImageView->Invert(); break; - case MSG_DIA_SHOW: + case MSG_SLIDE_SHOW: if (ToggleMenuItem(pmsg->what)) { - fpImageView->StartDiaShow(); + fpImageView->StartSlideShow(); } else { - fpImageView->StopDiaShow(); + fpImageView->StopSlideShow(); } - case MSG_DIA_SHOW_DELAY: + case MSG_SLIDE_SHOW_DELAY: { float value; if (pmsg->FindFloat("value", &value) == B_OK) { - fpImageView->SetDiaShowDelay(value); + fpImageView->SetSlideShowDelay(value); } } break; @@ -472,6 +485,12 @@ ShowImageWindow::MessageReceived(BMessage *pmsg) case MSG_FULL_SCREEN: ToggleFullScreen(); break; + case MSG_SHOW_CAPTION: + fShowCaption = ToggleMenuItem(pmsg->what); + if (fFullScreen) { + fpImageView->SetShowCaption(fShowCaption); + } + break; case MSG_UPDATE_RECENT_DOCUMENTS: UpdateRecentDocumentsMenu(); @@ -584,6 +603,7 @@ ShowImageWindow::ToggleFullScreen() SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); } + fpImageView->SetShowCaption(fFullScreen && fShowCaption); MoveTo(frame.left, frame.top); ResizeTo(frame.Width(), frame.Height()); } diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index bef9f3d8b5..ac514a4d39 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -54,7 +54,6 @@ public: status_t InitCheck(); ShowImageView *GetShowImageView() const { return fpImageView; } - void SetRef(const entry_ref *pref); void UpdateTitle(); void LoadMenus(BMenuBar *pbar); void WindowRedimension(BBitmap *pbitmap); @@ -68,6 +67,8 @@ private: void UpdateRecentDocumentsMenu(); bool ToggleMenuItem(uint32 what); + void EnableMenuItem(uint32 what, bool enable); + void MarkMenuItem(uint32 what, bool marked); void SaveAs(BMessage *pmsg); // Handle Save As submenu choice @@ -80,12 +81,12 @@ private: BFilePanel *fpSavePanel; BMenuBar *fpBar; BMenu *fpOpenMenu; - BMenu *fpPageMenu; - entry_ref *fpRef; + BMenu *fpBrowseMenu; ShowImageView *fpImageView; ShowImageStatusView *fpStatusView; bool fFullScreen; BRect fWindowFrame; + bool fShowCaption; }; #endif /* _ShowImageWindow_h */