xref: /haiku/src/apps/stylededit/StatusView.cpp (revision e5d65858f2361fe0552495b61620c84dcee6bc00)
1 /*
2  * Copyright 2002-2012, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Vlad Slepukhin
7  *		Siarzhuk Zharski
8  */
9 
10 
11 #include "StatusView.h"
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <Catalog.h>
18 #include <CharacterSet.h>
19 #include <CharacterSetRoster.h>
20 #include <ControlLook.h>
21 #include <MenuItem.h>
22 #include <Message.h>
23 #include <PopUpMenu.h>
24 #include <ScrollView.h>
25 #include <StringView.h>
26 #include <Window.h>
27 
28 #include "Constants.h"
29 
30 
31 const float kHorzSpacing = 5.f;
32 #define UTF8_EXPAND_ARROW "\xe2\x96\xbe"
33 
34 using namespace BPrivate;
35 
36 
37 #undef B_TRANSLATION_CONTEXT
38 #define B_TRANSLATION_CONTEXT "StatusView"
39 
40 
41 StatusView::StatusView(BScrollView* scrollView)
42 			:
43 			BView(BRect(), "statusview",
44 				B_FOLLOW_BOTTOM | B_FOLLOW_LEFT, B_WILL_DRAW),
45 			fScrollView(scrollView),
46 			fPreferredSize(0., 0.),
47 			fReadOnly(false)
48 {
49 	memset(fCellWidth, 0, sizeof(fCellWidth));
50 }
51 
52 
53 StatusView::~StatusView()
54 {
55 }
56 
57 
58 void
59 StatusView::AttachedToWindow()
60 {
61 	SetFont(be_plain_font);
62 	SetFontSize(10.);
63 
64 	BMessage message(UPDATE_STATUS);
65 	message.AddInt32("line", 1);
66 	message.AddInt32("column", 1);
67 	message.AddString("encoding", "");
68 	SetStatus(&message);
69 
70 	BScrollBar* scrollBar = fScrollView->ScrollBar(B_HORIZONTAL);
71 	MoveTo(0., scrollBar->Frame().top);
72 
73 	rgb_color color = B_TRANSPARENT_COLOR;
74 	BView* parent = Parent();
75 	if (parent != NULL)
76 		color = parent->ViewColor();
77 
78 	if (color == B_TRANSPARENT_COLOR)
79 		color = ui_color(B_PANEL_BACKGROUND_COLOR);
80 
81 	SetViewColor(color);
82 
83 	ResizeToPreferred();
84 }
85 
86 
87 void
88 StatusView::GetPreferredSize(float* _width, float* _height)
89 {
90 	_ValidatePreferredSize();
91 
92 	if (_width)
93 		*_width = fPreferredSize.width;
94 
95 	if (_height)
96 		*_height = fPreferredSize.height;
97 }
98 
99 
100 void
101 StatusView::ResizeToPreferred()
102 {
103 	float width, height;
104 	GetPreferredSize(&width, &height);
105 
106 	if (Bounds().Width() > width)
107 		width = Bounds().Width();
108 
109 	BView::ResizeTo(width, height);
110 }
111 
112 
113 void
114 StatusView::Draw(BRect updateRect)
115 {
116 	if (fPreferredSize.width <= 0)
117 		return;
118 
119 	if (be_control_look != NULL) {
120 		BRect bounds(Bounds());
121 		be_control_look->DrawMenuBarBackground(this,
122 			bounds, updateRect,	ViewColor());
123 	}
124 
125 	BRect bounds(Bounds());
126 	rgb_color highColor = HighColor();
127 	SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
128 	StrokeLine(bounds.LeftTop(), bounds.RightTop());
129 
130 	float x = bounds.left;
131 	for (size_t i = 0; i < kStatusCellCount - 1; i++) {
132 		x += fCellWidth[i];
133 		StrokeLine(BPoint(x, bounds.top + 3), BPoint(x, bounds.bottom - 3));
134 	}
135 
136 	SetLowColor(ViewColor());
137 	SetHighColor(highColor);
138 
139 	font_height fontHeight;
140 	GetFontHeight(&fontHeight);
141 
142 	x = bounds.left;
143 	float y = (bounds.bottom + bounds.top
144 		+ ceilf(fontHeight.ascent) - ceilf(fontHeight.descent)) / 2;
145 
146 	for (size_t i = 0; i < kStatusCellCount; i++) {
147 		if (fCellText[i].Length() == 0)
148 			continue;
149 		DrawString(fCellText[i], BPoint(x + kHorzSpacing, y));
150 		x += fCellWidth[i];
151 	}
152 }
153 
154 
155 void
156 StatusView::MouseDown(BPoint where)
157 {
158 	if (!fReadOnly)
159 		return;
160 
161 	float left = fCellWidth[kPositionCell] + fCellWidth[kEncodingCell];
162 	if (where.x < left)
163 		return;
164 
165 	int32 clicks = 0;
166 	BMessage* message = Window()->CurrentMessage();
167 	if (message != NULL
168 		&& message->FindInt32("clicks", &clicks) == B_OK && clicks > 1)
169 			return;
170 
171 	BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
172 	menu->AddItem(new BMenuItem(B_TRANSLATE("Unlock file"),
173 					new BMessage(UNLOCK_FILE)));
174 	where.x = left;
175 	where.y = Bounds().bottom;
176 
177 	ConvertToScreen(&where);
178 	menu->SetTargetForItems(this);
179 	menu->Go(where, true, true,	true);
180 }
181 
182 
183 void
184 StatusView::SetStatus(BMessage* message)
185 {
186 	int32 line = 0, column = 0;
187 	if (B_OK == message->FindInt32("line", &line)
188 		&& B_OK == message->FindInt32("column", &column))
189 	{
190 		char info[256];
191 		snprintf(info, sizeof(info),
192 				B_TRANSLATE("line %d, column %d"), line, column);
193 		fCellText[kPositionCell].SetTo(info);
194 	}
195 
196 	if (B_OK == message->FindString("encoding", &fEncoding)) {
197 		// sometime corresponding Int-32 "encoding" attrib is read as string :(
198 		if (fEncoding.Length() == 0
199 			|| fEncoding.Compare("\xff\xff") == 0
200 			|| fEncoding.Compare("UTF-8") == 0)
201 		{
202 			// do not display default UTF-8 encoding
203 			fCellText[kEncodingCell].Truncate(0);
204 			fEncoding.Truncate(0);
205 		} else {
206 			const BCharacterSet* charset
207 				= BCharacterSetRoster::FindCharacterSetByName(fEncoding);
208 			fCellText[kEncodingCell]
209 				= charset != NULL ? charset->GetPrintName() : "";
210 		}
211 	}
212 
213 	bool modified = false;
214 	fReadOnly = false;
215 	if (B_OK == message->FindBool("modified", &modified) && modified) {
216 		fCellText[kFileStateCell] = B_TRANSLATE("Modified");
217 	} else if (B_OK == message->FindBool("readOnly", &fReadOnly) && fReadOnly) {
218 		fCellText[kFileStateCell] = B_TRANSLATE("Read-only");
219 		fCellText[kFileStateCell] << " " UTF8_EXPAND_ARROW;
220 	} else
221 		fCellText[kFileStateCell].Truncate(0);
222 
223 	_ValidatePreferredSize();
224 	Invalidate();
225 }
226 
227 
228 void
229 StatusView::_ValidatePreferredSize()
230 {
231 	float orgWidth = fPreferredSize.width;
232 	// width
233 	fPreferredSize.width = 0.f;
234 	for (size_t i = 0; i < kStatusCellCount; i++) {
235 		if (fCellText[i].Length() == 0) {
236 			fCellWidth[i] = 0;
237 			continue;
238 		}
239 		float width = ceilf(StringWidth(fCellText[i]));
240 		if (width > 0)
241 			width += kHorzSpacing * 2;
242 		if (width > fCellWidth[i] || i != kPositionCell)
243 			fCellWidth[i] = width;
244 		fPreferredSize.width += fCellWidth[i];
245 	}
246 
247 	// height
248 	font_height fontHeight;
249 	GetFontHeight(&fontHeight);
250 
251 	fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
252 		+ fontHeight.leading);
253 
254 	if (fPreferredSize.height < B_H_SCROLL_BAR_HEIGHT)
255 		fPreferredSize.height = B_H_SCROLL_BAR_HEIGHT;
256 
257 	float delta = fPreferredSize.width - orgWidth;
258 	ResizeBy(delta, 0);
259 	BScrollBar* scrollBar = fScrollView->ScrollBar(B_HORIZONTAL);
260 	scrollBar->ResizeBy(-delta, 0);
261 	scrollBar->MoveBy(delta, 0);
262 }
263 
264