diff --git a/src/apps/showimage/ShowImageApp.cpp b/src/apps/showimage/ShowImageApp.cpp index 1c954485c3..903d2b95ad 100644 --- a/src/apps/showimage/ShowImageApp.cpp +++ b/src/apps/showimage/ShowImageApp.cpp @@ -46,8 +46,8 @@ int main(int, char **) ShowImageApp::ShowImageApp() : BApplication(APP_SIG) { - fbpulseStarted = false; - fpopenPanel = new BFilePanel(B_OPEN_PANEL); + fbPulseStarted = false; + fpOpenPanel = new BFilePanel(B_OPEN_PANEL); } void @@ -62,7 +62,7 @@ void ShowImageApp::ReadyToRun() { if (CountWindows() == WINDOWS_TO_IGNORE) - fpopenPanel->Show(); + fpOpenPanel->Show(); else // If image windows are already open // (paths supplied on the command line) @@ -73,10 +73,10 @@ ShowImageApp::ReadyToRun() void ShowImageApp::StartPulse() { - if (!fbpulseStarted) { + if (!fbPulseStarted) { // Tell the app to begin checking // for the number of open windows - fbpulseStarted = true; + fbPulseStarted = true; SetPulseRate(250000); // Set pulse to every 1/4 second } @@ -116,7 +116,7 @@ ShowImageApp::MessageReceived(BMessage *pmsg) { switch (pmsg->what) { case MSG_FILE_OPEN: - fpopenPanel->Show(); + fpOpenPanel->Show(); break; case MSG_WINDOW_QUIT: diff --git a/src/apps/showimage/ShowImageApp.h b/src/apps/showimage/ShowImageApp.h index 5f398d2aab..fca6ca6ed2 100644 --- a/src/apps/showimage/ShowImageApp.h +++ b/src/apps/showimage/ShowImageApp.h @@ -47,8 +47,8 @@ private: void StartPulse(); void Open(const entry_ref *pref); - BFilePanel *fpopenPanel; - bool fbpulseStarted; + BFilePanel *fpOpenPanel; + bool fbPulseStarted; }; #endif /* _ShowImageApp_h */ diff --git a/src/apps/showimage/ShowImageConstants.h b/src/apps/showimage/ShowImageConstants.h index adb28e03c1..22f72bbe4f 100644 --- a/src/apps/showimage/ShowImageConstants.h +++ b/src/apps/showimage/ShowImageConstants.h @@ -46,6 +46,9 @@ const uint32 MSG_PAGE_FIRST = 'mPGF'; const uint32 MSG_PAGE_LAST = 'mPGL'; const uint32 MSG_PAGE_NEXT = 'mPGN'; const uint32 MSG_PAGE_PREV = 'mPGP'; +const uint32 MSG_FILE_NEXT = 'mFLN'; +const uint32 MSG_FILE_PREV = 'mFLP'; +const uint32 MSG_FIT_TO_WINDOW_SIZE = 'mFWS'; extern const char *APP_SIG; diff --git a/src/apps/showimage/ShowImageStatusView.cpp b/src/apps/showimage/ShowImageStatusView.cpp index b6c3a4f76b..e030ddd24c 100644 --- a/src/apps/showimage/ShowImageStatusView.cpp +++ b/src/apps/showimage/ShowImageStatusView.cpp @@ -37,12 +37,12 @@ ShowImageStatusView::ShowImageStatusView(BRect rect, const char* name, void ShowImageStatusView::Draw(BRect updateRect) { - DrawString(fstrText.String(), BPoint(3, 11)); + DrawString(fText.String(), BPoint(3, 11)); } void -ShowImageStatusView::SetText(BString &strText) +ShowImageStatusView::SetText(BString &text) { - fstrText = strText; + fText = text; Invalidate(); } diff --git a/src/apps/showimage/ShowImageStatusView.h b/src/apps/showimage/ShowImageStatusView.h index 930ed0e9a7..78d08bcd6b 100644 --- a/src/apps/showimage/ShowImageStatusView.h +++ b/src/apps/showimage/ShowImageStatusView.h @@ -39,10 +39,10 @@ public: virtual void Draw(BRect updateRect); - void SetText(BString &strText); + void SetText(BString &text); private: - BString fstrText; + BString fText; }; #endif /* _ShowImageStatusView_h */ diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 97b731fe47..2a2c7a24ea 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "ShowImageConstants.h" #include "ShowImageView.h" @@ -55,36 +56,129 @@ #define PEN_SIZE 1.0f const rgb_color kborderColor = { 0, 0, 0, 255 }; +// use patterns to simulate marching ants for selection +void +ShowImageView::InitPatterns() +{ + uchar p; + uchar p1 = 0x33; + uchar p2 = 0xCC; + for (int i = 0; i <= 7; i ++) { + fPatternLeft.data[i] = p1; + fPatternRight.data[i] = p2; + if ((i / 2) % 2 == 0) { + p = 255; + } else { + p = 0; + } + fPatternUp.data[i] = p; + fPatternDown.data[i] = ~p; + } +} + +void +ShowImageView::RotatePatterns() +{ + int i; + uchar p; + bool set; + + // rotate up + p = fPatternUp.data[0]; + for (i = 0; i <= 6; i ++) { + fPatternUp.data[i] = fPatternUp.data[i+1]; + } + fPatternUp.data[7] = p; + + // rotate down + p = fPatternDown.data[7]; + for (i = 7; i >= 1; i --) { + fPatternDown.data[i] = fPatternDown.data[i-1]; + } + fPatternDown.data[0] = p; + + // rotate to left + p = fPatternLeft.data[0]; + set = (p & 0x80) != 0; + p <<= 1; + p &= 0xfe; + if (set) p |= 1; + memset(fPatternLeft.data, p, 8); + + // rotate to right + p = fPatternRight.data[0]; + set = (p & 1) != 0; + p >>= 1; + if (set) p |= 0x80; + memset(fPatternRight.data, p, 8); +} + +void +ShowImageView::Pulse() +{ + RotatePatterns(); + if (fbHasSelection) { + DrawSelectionBox(fSelectionRect); + } +} + ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, uint32 flags) : BView(rect, name, resizingMode, flags) { - fpbitmap = NULL; - fdocumentIndex = 1; - fdocumentCount = 1; - fbhasSelection = false; + InitPatterns(); - SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fpBitmap = NULL; + fDocumentIndex = 1; + fDocumentCount = 1; + fbHasSelection = false; + fResizeToViewBounds = false; + + SetViewColor(B_TRANSPARENT_COLOR); SetHighColor(kborderColor); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetPenSize(PEN_SIZE); } ShowImageView::~ShowImageView() { - delete fpbitmap; - fpbitmap = NULL; + delete fpBitmap; + fpBitmap = NULL; +} + +bool +ShowImageView::IsImage(const entry_ref *pref) +{ + BFile file(pref, B_READ_ONLY); + translator_info info; + memset(&info, 0, sizeof(translator_info)); + BMessage ioExtension; + + BTranslatorRoster *proster = BTranslatorRoster::Default(); + if (!proster) + return false; + + if (ioExtension.AddInt32("/documentIndex", fDocumentIndex) != B_OK) + return false; + + if (proster->Identify(&file, &ioExtension, &info, 0, NULL, + B_TRANSLATOR_BITMAP) != B_OK) + return false; + + return true; } void ShowImageView::SetImage(const entry_ref *pref) { - ClearViewBitmap(); - delete fpbitmap; - fpbitmap = NULL; + delete fpBitmap; + fpBitmap = NULL; + fbHasSelection = false; + fMakesSelection = false; entry_ref ref; if (!pref) - ref = fcurrentRef; + ref = fCurrentRef; else ref = *pref; @@ -95,10 +189,10 @@ ShowImageView::SetImage(const entry_ref *pref) translator_info info; memset(&info, 0, sizeof(translator_info)); BMessage ioExtension; - if (ref != fcurrentRef) + if (ref != fCurrentRef) // if new image, reset to first document - fdocumentIndex = 1; - if (ioExtension.AddInt32("/documentIndex", fdocumentIndex) != B_OK) + fDocumentIndex = 1; + if (ioExtension.AddInt32("/documentIndex", fDocumentIndex) != B_OK) return; if (proster->Identify(&file, &ioExtension, &info, 0, NULL, B_TRANSLATOR_BITMAP) != B_OK) @@ -109,39 +203,43 @@ ShowImageView::SetImage(const entry_ref *pref) if (proster->Translate(&file, &info, &ioExtension, &outstream, B_TRANSLATOR_BITMAP) != B_OK) return; - if (outstream.DetachBitmap(&fpbitmap) != B_OK) + if (outstream.DetachBitmap(&fpBitmap) != B_OK) return; - fcurrentRef = ref; + fCurrentRef = ref; // 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; + fDocumentCount = documentCount; else - fdocumentCount = 1; + fDocumentCount = 1; // send message to parent about new image BMessage msg(MSG_UPDATE_STATUS); msg.AddString("status", info.name); + msg.AddRef("ref", &fCurrentRef); BMessenger msgr(Window()); msgr.SendMessage(&msg); - - SetViewBitmap(fpbitmap, fpbitmap->Bounds(), - BRect(BORDER_WIDTH, BORDER_HEIGHT, - fpbitmap->Bounds().Width() + BORDER_WIDTH, - fpbitmap->Bounds().Height() + BORDER_HEIGHT), - B_FOLLOW_TOP | B_FOLLOW_LEFT, 0 - ); FixupScrollBars(); Invalidate(); } +void +ShowImageView::ResizeToViewBounds(bool resize) +{ + if (fResizeToViewBounds != resize) { + fResizeToViewBounds = resize; + FixupScrollBars(); + Invalidate(); + } +} + BBitmap * ShowImageView::GetBitmap() { - return fpbitmap; + return fpBitmap; } void @@ -150,43 +248,122 @@ ShowImageView::AttachedToWindow() FixupScrollBars(); } +BRect +ShowImageView::AlignBitmap() const +{ + BRect rect(fpBitmap->Bounds()); + if (fResizeToViewBounds) { + float width, height; + width = Bounds().Width()-2*PEN_SIZE; + height = Bounds().Height()-2*PEN_SIZE; + if (width > 0 && height > 0) { + float s; + s = width / rect.Width(); + + if (s * rect.Height() <= height) { + rect.right = width; + rect.bottom = s * rect.Height(); + // center horizontally + rect.OffsetBy(0, (height - rect.Height()) / 2); + } else { + rect.right = height / rect.Height() * rect.Width(); + rect.bottom = height; + // center vertically + rect.OffsetBy((width - rect.Width()) / 2, 0); + } + } + } else { + rect.OffsetBy(BORDER_WIDTH, BORDER_WIDTH); + } + rect.OffsetBy(PEN_SIZE, PEN_SIZE); + return rect; +} + +void +ShowImageView::Setup(BRect rect) +{ + fLeft = rect.left; + fTop = rect.top; + fScaleX = rect.Width() / fpBitmap->Bounds().Width(); + fScaleY = rect.Height() / fpBitmap->Bounds().Height(); +// XXX Is Width/Height off by one? +// fScaleX = (rect.Width()+1) / (fpBitmap->Bounds().Width()+1); +// fScaleY = (rect.Width()+1) / (fpBitmap->Bounds().Height()+1); +} + +BPoint +ShowImageView::ImageToView(BPoint p) const +{ + p.x = fScaleX * p.x + fLeft; + p.y = fScaleY * p.y + fTop; + return p; +} + +BPoint +ShowImageView::ViewToImage(BPoint p) const +{ + p.x = (p.x - fLeft) / fScaleX; + p.y = (p.y - fTop) / fScaleY; + return p; +} + +BRect +ShowImageView::ImageToView(BRect r) const +{ + BPoint leftTop(ImageToView(BPoint(r.left, r.top))); + BPoint rightBottom(ImageToView(BPoint(r.right, r.bottom))); + return BRect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y); +} + +void +ShowImageView::DrawBorder(BRect border) +{ + BRect bounds(Bounds()); + // top + FillRect(BRect(0, 0, bounds.right, border.top-1), B_SOLID_LOW); + // left + FillRect(BRect(0, border.top, border.left-1, border.bottom), B_SOLID_LOW); + // right + FillRect(BRect(border.right+1, border.top, bounds.right, border.bottom), B_SOLID_LOW); + // bottom + FillRect(BRect(0, border.bottom+1, bounds.right, bounds.bottom), B_SOLID_LOW); +} + void ShowImageView::Draw(BRect updateRect) { - if (fpbitmap) { + if (fpBitmap) { + BRect rect = AlignBitmap(); + Setup(rect); + + BRect border(rect); + border.InsetBy(-PEN_SIZE, -PEN_SIZE); + + DrawBorder(border); + // Draw black rectangle around image - StrokeRect( - BRect(BORDER_WIDTH - PEN_SIZE, - BORDER_HEIGHT - PEN_SIZE, - fpbitmap->Bounds().Width() + BORDER_WIDTH + PEN_SIZE, - fpbitmap->Bounds().Height() + BORDER_HEIGHT + PEN_SIZE)); - - if (fbhasSelection) - DrawSelectionBox(fselectionRect); + StrokeRect(border); + + // Draw image + DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect); + + if (fbHasSelection) + DrawSelectionBox(fSelectionRect); } } void ShowImageView::DrawSelectionBox(BRect &rect) { - // TODO: Make my own pattern to mimic the - // marching ants in Be's ShowImage? - - StrokeRect(rect, B_MIXED_COLORS); - Sync(); -} - -void -ShowImageView::ClearSelectionBox(BRect &rect) -{ - BRect bitmapRect = rect; - if (!bitmapRect.IsValid()) - printf("Invalid Rect\n"); - - bitmapRect.OffsetBy(-(BORDER_WIDTH), -(BORDER_HEIGHT)); - DrawBitmapAsync(fpbitmap, bitmapRect, rect); - // don't draw the bitmap immediately, more drawing - // almost always comes after this function is used + PushState(); + rgb_color white = {255, 255, 255}; + SetLowColor(white); + BRect r(ImageToView(rect)); + StrokeLine(BPoint(r.left, r.top), BPoint(r.right, r.top), fPatternLeft); + StrokeLine(BPoint(r.right, r.top+1), BPoint(r.right, r.bottom-1), fPatternUp); + StrokeLine(BPoint(r.left, r.bottom), BPoint(r.right, r.bottom), fPatternRight); + StrokeLine(BPoint(r.left, r.top+1), BPoint(r.left, r.bottom-1), fPatternDown); + PopState(); } void @@ -199,83 +376,64 @@ void ShowImageView::ConstrainToImage(BPoint &point) { point.ConstrainTo( - BRect( - BORDER_WIDTH, BORDER_HEIGHT, - fpbitmap->Bounds().Width() + BORDER_WIDTH, - fpbitmap->Bounds().Height() + BORDER_HEIGHT - ) + fpBitmap->Bounds() ); } void ShowImageView::MouseDown(BPoint point) { - // TODO: Need to handle the case where user clicks - // inside an existing selection and starts a drag operation + point = ViewToImage(point); - if (fbhasSelection) - ClearSelectionBox(fselectionRect); - - fbhasSelection = false; - - if (!fpbitmap) { - // Can't select anything if there is no image - Invalidate(); - return; - } - - BPoint firstPoint, secondPoint; - firstPoint = point; - ConstrainToImage(firstPoint); - secondPoint = firstPoint; - - BRect curSel, lastSel; - - BMessage *pmsg = Window()->CurrentMessage(); - uint32 buttons = static_cast(pmsg->FindInt32("buttons")); - bool bfirst = true; - // While any combination of mouse buttons is down, - // allow the user to size their selection. When all - // mouse buttons are up, the loop ends, and the selection - // has been made. - while (buttons) { - ConstrainToImage(secondPoint); - - // make a BRect that passes IsValid() - curSel.left = min(firstPoint.x, secondPoint.x); - curSel.top = min(firstPoint.y, secondPoint.y); - curSel.right = max(firstPoint.x, secondPoint.x); - curSel.bottom = max(firstPoint.y, secondPoint.y); - - if (!bfirst && curSel != lastSel) - ClearSelectionBox(lastSel); - if (curSel != lastSel) - DrawSelectionBox(curSel); - - snooze(25 * 1000); - lastSel = curSel; - GetMouse(&secondPoint, &buttons); - bfirst = false; - } - - if (curSel.IntegerWidth() < 2 && curSel.IntegerHeight() < 2) { - // The user must select at least 2 pixels - fbhasSelection = false; - Invalidate(); + if (fbHasSelection && fSelectionRect.Contains(point)) { + // TODO: start drag and drop } else { - fselectionRect = curSel; - fbhasSelection = true; + // begin new selection + fMakesSelection = true; + fbHasSelection = true; + SetMouseEventMask(B_POINTER_EVENTS); + ConstrainToImage(point); + fFirstPoint = point; + fSelectionRect.Set(point.x, point.y, point.x, point.y); + Invalidate(); + } +} + +void +ShowImageView::UpdateSelectionRect(BPoint point, bool final) { + BRect oldSelection = fSelectionRect; + point = ViewToImage(point); + ConstrainToImage(point); + fSelectionRect.left = min(fFirstPoint.x, point.x); + fSelectionRect.right = max(fFirstPoint.x, point.x); + fSelectionRect.top = min(fFirstPoint.y, point.y); + fSelectionRect.bottom = max(fFirstPoint.y, point.y); + if (final) { + // selection must contain a few pixels + if (fSelectionRect.Width() * fSelectionRect.Height() <= 1) { + fbHasSelection = false; + } + } + if (oldSelection != fSelectionRect || !fbHasSelection) { + Invalidate(); } } void ShowImageView::MouseMoved(BPoint point, uint32 state, const BMessage *pmsg) { + if (fMakesSelection) { + UpdateSelectionRect(point, false); + } } void ShowImageView::MouseUp(BPoint point) { + if (fMakesSelection) { + UpdateSelectionRect(point, true); + fMakesSelection = false; + } } void @@ -291,12 +449,21 @@ ShowImageView::MessageReceived(BMessage *pmsg) void ShowImageView::FixupScrollBars() { + BScrollBar *psb; + if (fResizeToViewBounds) { + psb = ScrollBar(B_HORIZONTAL); + if (psb) psb->SetRange(0, 0); + psb = ScrollBar(B_VERTICAL); + if (psb) psb->SetRange(0, 0); + return; + } + BRect rctview = Bounds(), rctbitmap(0, 0, 0, 0); - if (fpbitmap) - rctbitmap = fpbitmap->Bounds(); + if (fpBitmap) + rctbitmap = fpBitmap->Bounds(); float prop, range; - BScrollBar *psb = ScrollBar(B_HORIZONTAL); + psb = ScrollBar(B_HORIZONTAL); if (psb) { range = rctbitmap.Width() + (BORDER_WIDTH * 2) - rctview.Width(); if (range < 0) range = 0; @@ -322,20 +489,20 @@ ShowImageView::FixupScrollBars() int32 ShowImageView::CurrentPage() { - return fdocumentIndex; + return fDocumentIndex; } int32 ShowImageView::PageCount() { - return fdocumentCount; + return fDocumentCount; } void ShowImageView::FirstPage() { - if (fdocumentIndex != 1) { - fdocumentIndex = 1; + if (fDocumentIndex != 1) { + fDocumentIndex = 1; SetImage(NULL); } } @@ -343,8 +510,8 @@ ShowImageView::FirstPage() void ShowImageView::LastPage() { - if (fdocumentIndex != fdocumentCount) { - fdocumentIndex = fdocumentCount; + if (fDocumentIndex != fDocumentCount) { + fDocumentIndex = fDocumentCount; SetImage(NULL); } } @@ -352,8 +519,8 @@ ShowImageView::LastPage() void ShowImageView::NextPage() { - if (fdocumentIndex < fdocumentCount) { - fdocumentIndex++; + if (fDocumentIndex < fDocumentCount) { + fDocumentIndex++; SetImage(NULL); } } @@ -361,8 +528,88 @@ ShowImageView::NextPage() void ShowImageView::PrevPage() { - if (fdocumentIndex > 1) { - fdocumentIndex--; + if (fDocumentIndex > 1) { + fDocumentIndex--; SetImage(NULL); } } + +void +ShowImageView::FreeEntries(BList* entries) +{ + const int32 n = entries->CountItems(); + for (int32 i = 0; i < n; i ++) { + BEntry* entry = (BEntry*)entries->ItemAt(i); + delete entry; + } + entries->MakeEmpty(); +} + +// Notes: BDirectory::GetNextEntry() must not necessary +// return entries sorted by name, thou BFS does. +bool +ShowImageView::FindNextImage(BEntry* image, bool next) +{ + BEntry curImage(&fCurrentRef); + BEntry entry; + BDirectory parent; + BList entries; + + if (curImage.GetParent(&parent) != B_OK) + return false; + + while (parent.GetNextEntry(&entry) == B_OK) { + if (entry == curImage) { + // found current image + if (next) { + // find next image in directory + while (parent.GetNextEntry(&entry) == B_OK) { + entry_ref ref; + if (entry.GetRef(&ref) == B_OK && IsImage(&ref)) { + *image = entry; + return true; + } + } + } else { + // find privous image in directory + for (int32 i = entries.CountItems() - 1; i >= 0; i --) { + BEntry* entry = (BEntry*)entries.ItemAt(i); + entry_ref ref; + if (entry->GetRef(&ref) == B_OK && IsImage(&ref)) { + *image = *entry; + FreeEntries(&entries); + return true; + } + } + } + } + if (!next) { + // record entries if we search for previous file + entries.AddItem(new BEntry(entry)); + } + } + FreeEntries(&entries); + return false; +} + +void +ShowImageView::NextFile() +{ + BEntry image; + entry_ref ref; + + if (FindNextImage(&image, true) && image.GetRef(&ref) == B_OK) { + SetImage(&ref); + } +} + +void +ShowImageView::PrevFile() +{ + BEntry image; + entry_ref ref; + + if (FindNextImage(&image, false) && image.GetRef(&ref) == B_OK) { + SetImage(&ref); + } +} \ No newline at end of file diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 156bd78e9c..37242faeb4 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -40,7 +40,10 @@ public: uint32 flags); ~ShowImageView(); + void Pulse(); + void SetImage(const entry_ref *pref); + void ResizeToViewBounds(bool resize); BBitmap *GetBitmap(); virtual void AttachedToWindow(); @@ -60,18 +63,39 @@ public: void LastPage(); void NextPage(); void PrevPage(); + void NextFile(); + void PrevFile(); private: + void InitPatterns(); + void RotatePatterns(); + BRect AlignBitmap() const; + void Setup(BRect r); + BPoint ImageToView(BPoint p) const; + BPoint ViewToImage(BPoint p) const; + BRect ImageToView(BRect r) const; + bool IsImage(const entry_ref* pref); + void FreeEntries(BList* entries); + bool FindNextImage(BEntry* entry, bool next); void ConstrainToImage(BPoint &point); + void UpdateSelectionRect(BPoint point, bool final); + void DrawBorder(BRect border); void DrawSelectionBox(BRect &rect); - void ClearSelectionBox(BRect &rect); - entry_ref fcurrentRef; - int32 fdocumentIndex; - int32 fdocumentCount; - BBitmap *fpbitmap; - bool fbhasSelection; - BRect fselectionRect; + entry_ref fCurrentRef; + int32 fDocumentIndex; + int32 fDocumentCount; + BBitmap *fpBitmap; + bool fResizeToViewBounds; + float fLeft; // the origin of the image in the view + float fTop; + float fScaleX; + float fScaleY; + bool fMakesSelection; // is a selection being made + BPoint fFirstPoint; // first point in image space of selection + bool fbHasSelection; // is fSelectionRect valid + BRect fSelectionRect; // the selection in image space + pattern fPatternUp, fPatternDown, fPatternLeft, fPatternRight; }; #endif /* _ShowImageView_h */ diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 333b93e317..ad33fd6271 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -51,24 +51,28 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) : BWindow(BRect(50, 50, 350, 250), "", B_DOCUMENT_WINDOW, 0) { - fpsavePanel = NULL; - fpref = NULL; + fpSavePanel = NULL; + fpRef = NULL; + + // add shortcuts + AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(MSG_FILE_PREV)); + AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(MSG_FILE_NEXT)); // create menu bar - fpbar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar"); - LoadMenus(fpbar); - AddChild(fpbar); + fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar"); + LoadMenus(fpBar); + AddChild(fpBar); BRect viewFrame = Bounds(); - viewFrame.top = fpbar->Bounds().bottom + 1; + viewFrame.top = fpBar->Bounds().bottom + 1; viewFrame.right -= B_V_SCROLL_BAR_WIDTH; viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT; // create the image view - fpimageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL, - B_WILL_DRAW | B_FRAME_EVENTS); + fpImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED); // wrap a scroll view around the view - BScrollView *pscrollView = new BScrollView("image_scroller", fpimageView, + BScrollView *pscrollView = new BScrollView("image_scroller", fpImageView, B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER); AddChild(pscrollView); @@ -79,23 +83,23 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) rect.left = viewFrame.left + kstatusWidth; rect.right = viewFrame.right; BScrollBar *phscroll; - phscroll = new BScrollBar(rect, "hscroll", fpimageView, 0, 150, + phscroll = new BScrollBar(rect, "hscroll", fpImageView, 0, 150, B_HORIZONTAL); AddChild(phscroll); rect.left = 0; rect.right = kstatusWidth - 1; - fpstatusView = new ShowImageStatusView(rect, "status_view", B_FOLLOW_BOTTOM, + fpStatusView = new ShowImageStatusView(rect, "status_view", B_FOLLOW_BOTTOM, B_WILL_DRAW); - fpstatusView->SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR)); - AddChild(fpstatusView); + fpStatusView->SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR)); + AddChild(fpStatusView); rect = Bounds(); rect.top = viewFrame.top; rect.left = viewFrame.right + 1; rect.bottom = viewFrame.bottom; BScrollBar *pvscroll; - pvscroll = new BScrollBar(rect, "vscroll", fpimageView, 0, 150, B_VERTICAL); + pvscroll = new BScrollBar(rect, "vscroll", fpImageView, 0, 150, B_VERTICAL); AddChild(pvscroll); SetSizeLimits(250, 100000, 100, 100000); @@ -104,20 +108,22 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref) SetRef(pref); UpdateTitle(); - fpimageView->SetImage(pref); + fpImageView->SetImage(pref); + + SetPulseRate(100000); // every 1/10 second; ShowImageView needs it for marching ants Show(); } ShowImageWindow::~ShowImageWindow() { - delete fpref; + delete fpRef; } status_t ShowImageWindow::InitCheck() { - if (!fpref || !fpimageView) + if (!fpRef || !fpImageView) return B_ERROR; else return B_OK; @@ -126,16 +132,16 @@ ShowImageWindow::InitCheck() void ShowImageWindow::SetRef(const entry_ref *pref) { - if (!fpref) - fpref = new entry_ref(*pref); + if (!fpRef) + fpRef = new entry_ref(*pref); else - *fpref = *pref; + *fpRef = *pref; } void ShowImageWindow::UpdateTitle() { - BEntry entry(fpref); + BEntry entry(fpRef); if (entry.InitCheck() == B_OK) { BPath path; entry.GetPath(&path); @@ -173,7 +179,7 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar) AddItemMenu(pmenu, "Select All", MSG_SELECT_ALL, 'A', 0, 'W', false); pbar->AddItem(pmenu); - pmenu = fppageMenu = new BMenu("Page"); + 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); @@ -182,6 +188,7 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar) pmenu = new BMenu("Image"); AddItemMenu(pmenu, "Dither Image", MSG_DITHER_IMAGE, 0, 0, 'W', true); + AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true); pbar->AddItem(pmenu); } @@ -207,7 +214,7 @@ ShowImageWindow::WindowRedimension(BBitmap *pbitmap) // set the window's min & max size limits // based on document's data bounds float maxWidth = pbitmap->Bounds().Width() + B_V_SCROLL_BAR_WIDTH; - float maxHeight = pbitmap->Bounds().Height() + fpbar->Frame().Height() + + float maxHeight = pbitmap->Bounds().Height() + fpBar->Frame().Height() + B_H_SCROLL_BAR_HEIGHT + 1; float minWidth = min(maxWidth, 100.0f); float minHeight = min(maxHeight, 100.0f); @@ -237,13 +244,26 @@ ShowImageWindow::FrameResized(float width, float height) { } +bool +ShowImageWindow::ToggleMenuItem(uint32 what) +{ + BMenuItem *item; + bool marked = false; + item = fpBar->FindItem(what); + if (item != NULL) { + marked = !item->IsMarked(); + item->SetMarked(marked); + } + return marked; +} + void ShowImageWindow::MessageReceived(BMessage *pmsg) { switch (pmsg->what) { case MSG_OUTPUT_TYPE: // User clicked Save As then choose an output format - if (!fpsavePanel) + if (!fpSavePanel) // If user doesn't already have a save panel open SaveAs(pmsg); break; @@ -259,21 +279,27 @@ ShowImageWindow::MessageReceived(BMessage *pmsg) break; case B_CANCEL: - delete fpsavePanel; - fpsavePanel = NULL; + delete fpSavePanel; + fpSavePanel = NULL; break; case MSG_UPDATE_STATUS: { - bool benable = (fpimageView->PageCount() > 1) ? true : false; - if (fppageMenu->IsEnabled() != benable) + 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); + fpPageMenu->SetEnabled(benable); BString str; if (pmsg->FindString("status", &str) == B_OK) - fpstatusView->SetText(str); + fpStatusView->SetText(str); + + entry_ref ref; + if (pmsg->FindRef("ref", &ref) == B_OK) { + SetRef(&ref); + UpdateTitle(); + } break; } @@ -291,27 +317,41 @@ ShowImageWindow::MessageReceived(BMessage *pmsg) break; case MSG_PAGE_FIRST: - fpimageView->FirstPage(); + fpImageView->FirstPage(); break; case MSG_PAGE_LAST: - fpimageView->LastPage(); + fpImageView->LastPage(); break; case MSG_PAGE_NEXT: - fpimageView->NextPage(); + fpImageView->NextPage(); break; case MSG_PAGE_PREV: - fpimageView->PrevPage(); + fpImageView->PrevPage(); break; case MSG_DITHER_IMAGE: - BMenuItem *pmenuDither; - pmenuDither = fpbar->FindItem(pmsg->what); - pmenuDither->SetMarked(!pmenuDither->IsMarked()); - break; - + ToggleMenuItem(pmsg->what); + break; + + case MSG_FIT_TO_WINDOW_SIZE: + { + bool resize; + resize = ToggleMenuItem(pmsg->what); + fpImageView->ResizeToViewBounds(resize); + } + break; + + case MSG_FILE_PREV: + fpImageView->PrevFile(); + break; + + case MSG_FILE_NEXT: + fpImageView->NextFile(); + break; + default: BWindow::MessageReceived(pmsg); break; @@ -338,12 +378,12 @@ ShowImageWindow::SaveAs(BMessage *pmsg) ppanelMsg->AddInt32(TYPE_FLD, outType); // Create save panel and show it - fpsavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this), NULL, 0, + fpSavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this), NULL, 0, false, ppanelMsg); - if (!fpsavePanel) + if (!fpSavePanel) return; - fpsavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE); - fpsavePanel->Show(); + fpSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE); + fpSavePanel->Show(); } void @@ -375,7 +415,7 @@ ShowImageWindow::SaveToFile(BMessage *pmsg) return; // Translate the image and write it out to the output file - BBitmapStream stream(fpimageView->GetBitmap()); + BBitmapStream stream(fpImageView->GetBitmap()); BTranslatorRoster *proster = BTranslatorRoster::Default(); if (proster->Translate(outTranslator, &stream, NULL, &file, outType) != B_OK) { @@ -392,7 +432,7 @@ ShowImageWindow::SaveToFile(BMessage *pmsg) bool ShowImageWindow::CanQuit() { - if (fpsavePanel) + if (fpSavePanel) // Don't allow this window to be closed if a save panel is open return false; else diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index 351753b0e6..935d4f0e7e 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -52,7 +52,7 @@ public: virtual void Quit(); status_t InitCheck(); - ShowImageView *GetShowImageView() const { return fpimageView; } + ShowImageView *GetShowImageView() const { return fpImageView; } void SetRef(const entry_ref *pref); void UpdateTitle(); @@ -63,6 +63,8 @@ private: BMenuItem *AddItemMenu(BMenu *pmenu, char *caption, long unsigned int msg, char shortcut, uint32 modifier, char target, bool enabled); + + bool ToggleMenuItem(uint32 what); void SaveAs(BMessage *pmsg); // Handle Save As submenu choice @@ -71,12 +73,12 @@ private: bool CanQuit(); // returns true if the window can be closed safely, false if not - BFilePanel *fpsavePanel; - BMenuBar *fpbar; - BMenu *fppageMenu; - entry_ref *fpref; - ShowImageView *fpimageView; - ShowImageStatusView *fpstatusView; + BFilePanel *fpSavePanel; + BMenuBar *fpBar; + BMenu *fpPageMenu; + entry_ref *fpRef; + ShowImageView *fpImageView; + ShowImageStatusView *fpStatusView; }; #endif /* _ShowImageWindow_h */