From cae52eadaceea0a3be3cbaba24cfb6df250a3039 Mon Sep 17 00:00:00 2001
From: Janus <janus2@ymail.com>
Date: Tue, 7 Apr 2015 17:17:32 +0000
Subject: [PATCH] Showimage: Add zoom level to StatusBar.

* Improve StatusBar graphics (Same style as StyledEdit).
* Resize the StatusBar to best fit.
* Fixes #7394.
---
 src/apps/showimage/ShowImageStatusView.cpp | 200 ++++++++++++++++-----
 src/apps/showimage/ShowImageStatusView.h   |  31 +++-
 src/apps/showimage/ShowImageView.cpp       |   4 +
 src/apps/showimage/ShowImageWindow.cpp     |  56 ++----
 src/apps/showimage/ShowImageWindow.h       |   2 +-
 5 files changed, 199 insertions(+), 94 deletions(-)

diff --git a/src/apps/showimage/ShowImageStatusView.cpp b/src/apps/showimage/ShowImageStatusView.cpp
index 0092b4e013..a00eacf090 100644
--- a/src/apps/showimage/ShowImageStatusView.cpp
+++ b/src/apps/showimage/ShowImageStatusView.cpp
@@ -11,10 +11,12 @@
 
 #include "ShowImageStatusView.h"
 
+#include <ControlLook.h>
 #include <Entry.h>
 #include <MenuItem.h>
 #include <Path.h>
 #include <PopUpMenu.h>
+#include <ScrollView.h>
 
 #include <tracker_private.h>
 #include "DirMenu.h"
@@ -22,60 +24,106 @@
 #include "ShowImageView.h"
 #include "ShowImageWindow.h"
 
+const float kHorzSpacing = 5.f;
 
-ShowImageStatusView::ShowImageStatusView(BRect rect, const char* name,
-	uint32 resizingMode, uint32 flags)
+
+ShowImageStatusView::ShowImageStatusView(BScrollView* scrollView)
 	:
-	BView(rect, name, resizingMode, flags)
+	BView(BRect(), "statusview", B_FOLLOW_BOTTOM | B_FOLLOW_LEFT, B_WILL_DRAW),
+	fScrollView(scrollView),
+	fPreferredSize(0.0, 0.0)
 {
-	SetViewColor(B_TRANSPARENT_32_BIT);
-	SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
-	SetHighColor(0, 0, 0, 255);
+	memset(fCellWidth, 0, sizeof(fCellWidth));
+}
 
-	BFont font;
-	GetFont(&font);
-	font.SetSize(10.0);
-	SetFont(&font);
+
+void
+ShowImageStatusView::AttachedToWindow()
+{
+	SetFont(be_plain_font);
+	SetFontSize(10.0);
+
+	BScrollBar* scrollBar = fScrollView->ScrollBar(B_HORIZONTAL);
+	MoveTo(0.0, scrollBar->Frame().top);
+	rgb_color color = B_TRANSPARENT_COLOR;
+	BView* parent = Parent();
+	if (parent != NULL)
+		color = parent->ViewColor();
+
+	if (color == B_TRANSPARENT_COLOR)
+		color = ui_color(B_PANEL_BACKGROUND_COLOR);
+
+	SetViewColor(color);
+
+	ResizeToPreferred();
+}
+
+
+void
+ShowImageStatusView::GetPreferredSize(float* _width, float* _height)
+{
+	_ValidatePreferredSize();
+
+	if (_width)
+		*_width = fPreferredSize.width;
+
+	if (_height)
+		*_height = fPreferredSize.height;
+}
+
+
+void
+ShowImageStatusView::ResizeToPreferred()
+{
+	float width, height;
+	GetPreferredSize(&width, &height);
+
+	if (Bounds().Width() > width)
+		width = Bounds().Width();
+
+	BView::ResizeTo(width, height);
 }
 
 
 void
 ShowImageStatusView::Draw(BRect updateRect)
 {
-	rgb_color darkShadow = tint_color(LowColor(), B_DARKEN_2_TINT);
-	rgb_color shadow = tint_color(LowColor(), B_DARKEN_1_TINT);
-	rgb_color light = tint_color(LowColor(), B_LIGHTEN_MAX_TINT);
+	if (fPreferredSize.width <= 0)
+		return;
 
-	BRect b(Bounds());
+	if (be_control_look != NULL) {
+		BRect bounds(Bounds());
+		be_control_look->DrawMenuBarBackground(this,
+			bounds, updateRect,	ViewColor());
+	}
 
-	BeginLineArray(5);
-		AddLine(BPoint(b.left, b.top),
-				BPoint(b.right, b.top), darkShadow);
-		b.top += 1.0;
-		AddLine(BPoint(b.left, b.top),
-				BPoint(b.right, b.top), light);
-		AddLine(BPoint(b.right, b.top + 1.0),
-				BPoint(b.right, b.bottom), shadow);
-		AddLine(BPoint(b.right - 1.0, b.bottom),
-				BPoint(b.left + 1.0, b.bottom), shadow);
-		AddLine(BPoint(b.left, b.bottom),
-				BPoint(b.left, b.top + 1.0), light);
-	EndLineArray();
+	BRect bounds(Bounds());
+	rgb_color highColor = HighColor();
+	SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
+	StrokeLine(bounds.LeftTop(), bounds.RightTop());
 
-	b.InsetBy(1.0, 1.0);
+	float x = bounds.left;
+	for (size_t i = 0; i < kStatusCellCount - 1; i++) {
+		x += fCellWidth[i];
+		StrokeLine(BPoint(x, bounds.top + 3), BPoint(x, bounds.bottom - 3));
+	}
 
-	// Truncate and layout text
-	BString truncated(fText);
-	BFont font;
-	GetFont(&font);
-	font.TruncateString(&truncated, B_TRUNCATE_MIDDLE, b.Width() - 4.0);
-	font_height fh;
-	font.GetHeight(&fh);
+	SetLowColor(ViewColor());
+	SetHighColor(highColor);
 
-	FillRect(b, B_SOLID_LOW);
-	SetDrawingMode(B_OP_OVER);
-	DrawString(truncated.String(), BPoint(b.left + 2.0,
-		floorf(b.top + b.Height() / 2.0 + fh.ascent / 2.0)));
+	font_height fontHeight;
+	GetFontHeight(&fontHeight);
+
+	x = bounds.left;
+	float y = (bounds.bottom + bounds.top
+		+ ceilf(fontHeight.ascent) - ceilf(fontHeight.descent)) / 2;
+
+	for (size_t i = 0; i < kStatusCellCount; i++) {
+		if (fCellText[i].Length() == 0)
+			continue;
+		DrawString(fCellText[i], BPoint(x + kHorzSpacing, y));
+		x += fCellWidth[i];
+	}
 }
 
 
@@ -101,11 +149,81 @@ ShowImageStatusView::MouseDown(BPoint where)
 
 
 void
-ShowImageStatusView::Update(const entry_ref& ref, const BString& text)
+ShowImageStatusView::Update(const entry_ref& ref, const BString& text,
+	const BString& imageType, float zoom)
 {
-	fText = text;
 	fRef = ref;
 
+	_SetFrameText(text);
+	_SetZoomText(zoom);
+	_SetImageTypeText(imageType);
+
+	_ValidatePreferredSize();
 	Invalidate();
 }
 
+
+void
+ShowImageStatusView::SetZoom(float zoom)
+{
+	_SetZoomText(zoom);
+	_ValidatePreferredSize();
+	Invalidate();
+}
+
+
+void
+ShowImageStatusView::_SetFrameText(const BString& text)
+{
+	fCellText[0] = text;
+}
+
+
+void
+ShowImageStatusView::_SetZoomText(float zoom)
+{
+	fCellText[1].SetToFormat("%.0f%%", zoom * 100);
+}
+
+
+void
+ShowImageStatusView::_SetImageTypeText(const BString& imageType)
+{
+	fCellText[2] = imageType;
+}
+
+
+void
+ShowImageStatusView::_ValidatePreferredSize()
+{
+	float orgWidth = fPreferredSize.width;
+	// width
+	fPreferredSize.width = 0.f;
+	for (size_t i = 0; i < kStatusCellCount; i++) {
+		if (fCellText[i].Length() == 0) {
+			fCellWidth[i] = 0;
+			continue;
+		}
+		float width = ceilf(StringWidth(fCellText[i]));
+		if (width > 0)
+			width += kHorzSpacing * 2;
+		fCellWidth[i] = width;
+		fPreferredSize.width += fCellWidth[i];
+	}
+
+	// height
+	font_height fontHeight;
+	GetFontHeight(&fontHeight);
+
+	fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
+		+ fontHeight.leading);
+
+	if (fPreferredSize.height < B_H_SCROLL_BAR_HEIGHT)
+		fPreferredSize.height = B_H_SCROLL_BAR_HEIGHT;
+
+	float delta = fPreferredSize.width - orgWidth;
+	ResizeBy(delta, 0);
+	BScrollBar* scrollBar = fScrollView->ScrollBar(B_HORIZONTAL);
+	scrollBar->ResizeBy(-delta, 0);
+	scrollBar->MoveBy(delta, 0);
+}
diff --git a/src/apps/showimage/ShowImageStatusView.h b/src/apps/showimage/ShowImageStatusView.h
index 05807b4df8..ef70af320f 100644
--- a/src/apps/showimage/ShowImageStatusView.h
+++ b/src/apps/showimage/ShowImageStatusView.h
@@ -15,20 +15,37 @@
 #include <View.h>
 
 
+enum {
+	kFrameSizeCell,
+	kZoomCell,
+	kImageTypeCell,
+	kStatusCellCount
+};
+
+
 class ShowImageStatusView : public BView {
 public:
-								ShowImageStatusView(BRect rect,
-									const char* name, uint32 resizingMode,
-									uint32 flags);
+								ShowImageStatusView(BScrollView* scrollView);
 
+	virtual	void				AttachedToWindow();
+	virtual void				GetPreferredSize(float* _width, float* _height);
+	virtual	void				ResizeToPreferred();
 	virtual	void				Draw(BRect updateRect);
 	virtual	void				MouseDown(BPoint where);
 
 			void				Update(const entry_ref& ref,
-									const BString& text);
-
-private:
-			BString				fText;
+									const BString& text, const BString& imageType,
+									float zoom);
+			void				SetZoom(float zoom);
+ private:
+			void				_SetFrameText(const BString& text);
+			void				_SetZoomText(float zoom);
+			void				_SetImageTypeText(const BString& imageType);
+			void				_ValidatePreferredSize();
+			BScrollView*		fScrollView;
+			BSize				fPreferredSize;
+			BString				fCellText[kStatusCellCount];
+			float				fCellWidth[kStatusCellCount];
 			entry_ref			fRef;
 };
 
diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp
index fa55542a76..3279972f5a 100644
--- a/src/apps/showimage/ShowImageView.cpp
+++ b/src/apps/showimage/ShowImageView.cpp
@@ -1587,6 +1587,10 @@ ShowImageView::SetZoom(float zoom, BPoint where)
 		offset.y = (int)(where.y * fZoom / oldZoom + 0.5) - offset.y;
 		ScrollTo(offset);
 	}
+
+	BMessage message(MSG_UPDATE_STATUS_ZOOM);
+	message.AddFloat("zoom", fZoom);
+	_SendMessageToWindow(&message);
 }
 
 
diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp
index 90fce00342..0eefc9a177 100644
--- a/src/apps/showimage/ShowImageWindow.cpp
+++ b/src/apps/showimage/ShowImageWindow.cpp
@@ -230,35 +230,11 @@ ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref,
 			| B_FRAME_EVENTS);
 	// wrap a scroll view around the view
 	fScrollView = new BScrollView("image_scroller", fImageView,
-		B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER);
+		B_FOLLOW_ALL, 0, true, true, B_PLAIN_BORDER);
 	contentView->AddChild(fScrollView);
 
-	const int32 kstatusWidth = 190;
-	BRect rect;
-	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);
-	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);
-	contentView->AddChild(fStatusView);
-
-	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);
-	contentView->AddChild(fVerticalScrollBar);
+	fStatusView = new ShowImageStatusView(fScrollView);
+	fScrollView->AddChild(fStatusView);
 
 	// Update minimum window size
 	float toolBarMinWidth = fToolBar->MinSize().width;
@@ -973,6 +949,10 @@ ShowImageWindow::MessageReceived(BMessage* message)
 			fImageView->ZoomOut();
 			break;
 
+		case MSG_UPDATE_STATUS_ZOOM:
+			fStatusView->SetZoom(fImageView->Zoom());
+			break;
+
 		case kMsgOriginalSize:
 			if (message->FindInt32("behavior") == BButton::B_TOGGLE_BEHAVIOR) {
 				bool force = (message->FindInt32("be:value") == B_CONTROL_ON);
@@ -1040,8 +1020,6 @@ ShowImageWindow::MessageReceived(BMessage* message)
 				fToolBar->MoveBy(0, offset);
 				fScrollView->ResizeBy(0, -offset);
 				fScrollView->MoveBy(0, offset);
-				fVerticalScrollBar->ResizeBy(0, -offset);
-				fVerticalScrollBar->MoveBy(0, offset);
 				UpdateIfNeeded();
 				snooze(15000);
 			}
@@ -1061,12 +1039,7 @@ ShowImageWindow::MessageReceived(BMessage* message)
 				frame.top = fToolBar->Frame().bottom + 1;
 				fScrollView->MoveTo(fScrollView->Frame().left, 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);
+					frame.Height() + 1);
 			}
 			break;
 		}
@@ -1085,16 +1058,11 @@ ShowImageWindow::_UpdateStatusText(const BMessage* message)
 	if (fImageView->Bitmap() != NULL) {
 		BRect bounds = fImageView->Bitmap()->Bounds();
 		status << bounds.IntegerWidth() + 1
-			<< "x" << bounds.IntegerHeight() + 1 << ", " << fImageType;
+			<< "x" << bounds.IntegerHeight() + 1;
 	}
 
-	BString text;
-	if (message != NULL && message->FindString("status", &text) == B_OK
-		&& text.Length() > 0) {
-		status << ", " << text;
-	}
-
-	fStatusView->Update(fNavigator.CurrentRef(), status);
+	fStatusView->Update(fNavigator.CurrentRef(), status, fImageType,
+		fImageView->Zoom());
 }
 
 
@@ -1546,8 +1514,6 @@ ShowImageWindow::_SetToolBarVisible(bool visible, bool animate)
 	} else {
 		fScrollView->ResizeBy(0, -diff);
 		fScrollView->MoveBy(0, diff);
-		fVerticalScrollBar->ResizeBy(0, -diff);
-		fVerticalScrollBar->MoveBy(0, diff);
 		fToolBar->MoveBy(0, diff);
 		if (!visible)
 			fToolBar->Hide();
diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h
index 83c0113f0f..33a628a4f5 100644
--- a/src/apps/showimage/ShowImageWindow.h
+++ b/src/apps/showimage/ShowImageWindow.h
@@ -35,6 +35,7 @@ enum {
 	MSG_MODIFIED				= 'mMOD',
 	MSG_UPDATE_STATUS			= 'mUPS',
 	MSG_UPDATE_STATUS_TEXT		= 'mUPT',
+	MSG_UPDATE_STATUS_ZOOM		= 'mUPZ',
 	MSG_SELECTION				= 'mSEL',
 	MSG_FILE_NEXT				= 'mFLN',
 	MSG_FILE_PREV				= 'mFLP',
@@ -118,7 +119,6 @@ private:
 			BToolBar*			fToolBar;
 			bool				fToolBarVisible;
 			BScrollView*		fScrollView;
-			BScrollBar*			fVerticalScrollBar;
 			ShowImageView*		fImageView;
 			ShowImageStatusView* fStatusView;
 			ProgressWindow*		fProgressWindow;