1/*
2 * Copyright 2001-2009, Haiku.
3 * Copyright 2002, Thomas Kurschel.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		Rafael Romo
8 *		Thomas Kurschel
9 *		Axel D��rfler, axeld@pinc-software.de
10 */
11
12
13#include "MonitorView.h"
14
15#include <stdio.h>
16
17#include <Catalog.h>
18#include <Locale.h>
19#include <Roster.h>
20#include <Screen.h>
21
22#include "Constants.h"
23
24#undef B_TRANSLATION_CONTEXT
25#define B_TRANSLATION_CONTEXT "Monitor View"
26
27
28MonitorView::MonitorView(BRect rect, const char *name, int32 width, int32 height)
29	: BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
30	fMaxWidth(1920),
31	fMaxHeight(1200),
32	fWidth(width),
33	fHeight(height),
34	fDPI(0)
35{
36	BScreen screen(B_MAIN_SCREEN_ID);
37	fDesktopColor = screen.DesktopColor(current_workspace());
38}
39
40
41MonitorView::~MonitorView()
42{
43}
44
45
46void
47MonitorView::AttachedToWindow()
48{
49	SetViewColor(B_TRANSPARENT_COLOR);
50	fBackgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR);
51
52	_UpdateDPI();
53}
54
55
56void
57MonitorView::MouseDown(BPoint point)
58{
59	be_roster->Launch(kBackgroundsSignature);
60}
61
62
63void
64MonitorView::Draw(BRect updateRect)
65{
66	rgb_color darkColor = {160, 160, 160, 255};
67	rgb_color blackColor = {0, 0, 0, 255};
68	rgb_color redColor = {228, 0, 0, 255};
69	rgb_color whiteColor = {255, 255, 255, 255};
70	BRect outerRect = _MonitorBounds();
71
72	SetHighColor(fBackgroundColor);
73	FillRect(updateRect);
74
75	SetDrawingMode(B_OP_OVER);
76
77	// frame & background
78
79	SetHighColor(darkColor);
80	FillRoundRect(outerRect, 3.0, 3.0);
81
82	SetHighColor(blackColor);
83	StrokeRoundRect(outerRect, 3.0, 3.0);
84
85	SetHighColor(fDesktopColor);
86
87	BRect innerRect(outerRect.InsetByCopy(4, 4));
88	FillRoundRect(innerRect, 2.0, 2.0);
89
90	SetHighColor(blackColor);
91	StrokeRoundRect(innerRect, 2.0, 2.0);
92
93	SetDrawingMode(B_OP_COPY);
94
95	// power light
96
97	SetHighColor(redColor);
98	BPoint powerPos(outerRect.left + 5, outerRect.bottom - 2);
99	StrokeLine(powerPos, BPoint(powerPos.x + 2, powerPos.y));
100
101	// DPI
102
103	if (fDPI == 0)
104		return;
105
106	font_height fontHeight;
107	GetFontHeight(&fontHeight);
108	float height = ceilf(fontHeight.ascent + fontHeight.descent);
109
110	char text[64];
111	snprintf(text, sizeof(text), B_TRANSLATE("%ld dpi"), fDPI);
112
113	float width = StringWidth(text);
114	if (width > innerRect.Width() || height > innerRect.Height())
115		return;
116
117	SetLowColor(fDesktopColor);
118	SetHighColor(whiteColor);
119
120	DrawString(text, BPoint(innerRect.left + (innerRect.Width() - width) / 2,
121		innerRect.top + fontHeight.ascent + (innerRect.Height() - height) / 2));
122}
123
124
125void
126MonitorView::SetResolution(int32 width, int32 height)
127{
128	if (fWidth == width && fHeight == height)
129		return;
130
131	fWidth = width;
132	fHeight = height;
133
134	_UpdateDPI();
135	Invalidate();
136}
137
138
139void
140MonitorView::SetMaxResolution(int32 width, int32 height)
141{
142	if (fMaxWidth == width && fMaxHeight == height)
143		return;
144
145	fMaxWidth = width;
146	fMaxHeight = height;
147
148	Invalidate();
149}
150
151
152void
153MonitorView::MessageReceived(BMessage* message)
154{
155	switch (message->what) {
156		case B_COLORS_UPDATED:
157		{
158			message->FindColor(ui_color_name(B_PANEL_BACKGROUND_COLOR),
159				&fBackgroundColor);
160			break;
161		}
162		case UPDATE_DESKTOP_MSG:
163		{
164			int32 width, height;
165			if (message->FindInt32("width", &width) == B_OK
166				&& message->FindInt32("height", &height) == B_OK)
167				SetResolution(width, height);
168			break;
169		}
170
171		case UPDATE_DESKTOP_COLOR_MSG:
172		{
173			BScreen screen(Window());
174			rgb_color color = screen.DesktopColor(current_workspace());
175			if (color != fDesktopColor) {
176				fDesktopColor = color;
177				Invalidate();
178			}
179			break;
180		}
181
182		default:
183			BView::MessageReceived(message);
184			break;
185	}
186}
187
188
189BRect
190MonitorView::_MonitorBounds()
191{
192	float maxWidth = Bounds().Width();
193	float maxHeight = Bounds().Height();
194	if (maxWidth / maxHeight > (float)fMaxWidth / fMaxHeight)
195		maxWidth = maxHeight / fMaxHeight * fMaxWidth;
196	else
197		maxHeight = maxWidth / fMaxWidth * fMaxHeight;
198
199	float factorX = (float)fWidth / fMaxWidth;
200	float factorY = (float)fHeight / fMaxHeight;
201
202	if (factorX > factorY && factorX > 1) {
203		factorY /= factorX;
204		factorX = 1;
205	} else if (factorY > factorX && factorY > 1) {
206		factorX /= factorY;
207		factorY = 1;
208	}
209
210	float width = maxWidth * factorX;
211	float height = maxHeight * factorY;
212
213	BSize size = Bounds().Size();
214	return BRect((size.width - width) / 2, (size.height - height) / 2,
215		(size.width + width) / 2, (size.height + height) / 2);
216}
217
218
219void
220MonitorView::_UpdateDPI()
221{
222	fDPI = 0;
223
224	BScreen screen(Window());
225	monitor_info info;
226	if (screen.GetMonitorInfo(&info) != B_OK)
227		return;
228
229	double x = info.width / 2.54;
230	double y = info.height / 2.54;
231
232	fDPI = (int32)round((fWidth / x + fHeight / y) / 2);
233}
234