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	if (Parent())
51		fBackgroundColor = Parent()->ViewColor();
52	else
53		fBackgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR);
54
55	_UpdateDPI();
56}
57
58
59void
60MonitorView::MouseDown(BPoint point)
61{
62	be_roster->Launch(kBackgroundsSignature);
63}
64
65
66void
67MonitorView::Draw(BRect updateRect)
68{
69	rgb_color darkColor = {160, 160, 160, 255};
70	rgb_color blackColor = {0, 0, 0, 255};
71	rgb_color redColor = {228, 0, 0, 255};
72	rgb_color whiteColor = {255, 255, 255, 255};
73	BRect outerRect = _MonitorBounds();
74
75	SetHighColor(fBackgroundColor);
76	FillRect(updateRect);
77
78	SetDrawingMode(B_OP_OVER);
79
80	// frame & background
81
82	SetHighColor(darkColor);
83	FillRoundRect(outerRect, 3.0, 3.0);
84
85	SetHighColor(blackColor);
86	StrokeRoundRect(outerRect, 3.0, 3.0);
87
88	SetHighColor(fDesktopColor);
89
90	BRect innerRect(outerRect.InsetByCopy(4, 4));
91	FillRoundRect(innerRect, 2.0, 2.0);
92
93	SetHighColor(blackColor);
94	StrokeRoundRect(innerRect, 2.0, 2.0);
95
96	SetDrawingMode(B_OP_COPY);
97
98	// power light
99
100	SetHighColor(redColor);
101	BPoint powerPos(outerRect.left + 5, outerRect.bottom - 2);
102	StrokeLine(powerPos, BPoint(powerPos.x + 2, powerPos.y));
103
104	// DPI
105
106	if (fDPI == 0)
107		return;
108
109	font_height fontHeight;
110	GetFontHeight(&fontHeight);
111	float height = ceilf(fontHeight.ascent + fontHeight.descent);
112
113	char text[64];
114	snprintf(text, sizeof(text), B_TRANSLATE("%ld dpi"), fDPI);
115
116	float width = StringWidth(text);
117	if (width > innerRect.Width() || height > innerRect.Height())
118		return;
119
120	SetLowColor(fDesktopColor);
121	SetHighColor(whiteColor);
122
123	DrawString(text, BPoint(innerRect.left + (innerRect.Width() - width) / 2,
124		innerRect.top + fontHeight.ascent + (innerRect.Height() - height) / 2));
125}
126
127
128void
129MonitorView::SetResolution(int32 width, int32 height)
130{
131	if (fWidth == width && fHeight == height)
132		return;
133
134	fWidth = width;
135	fHeight = height;
136
137	_UpdateDPI();
138	Invalidate();
139}
140
141
142void
143MonitorView::SetMaxResolution(int32 width, int32 height)
144{
145	if (fMaxWidth == width && fMaxHeight == height)
146		return;
147
148	fMaxWidth = width;
149	fMaxHeight = height;
150
151	Invalidate();
152}
153
154
155void
156MonitorView::MessageReceived(BMessage* message)
157{
158	switch (message->what) {
159		case UPDATE_DESKTOP_MSG:
160		{
161			int32 width, height;
162			if (message->FindInt32("width", &width) == B_OK
163				&& message->FindInt32("height", &height) == B_OK)
164				SetResolution(width, height);
165			break;
166		}
167
168		case UPDATE_DESKTOP_COLOR_MSG:
169		{
170			BScreen screen(Window());
171			rgb_color color = screen.DesktopColor(current_workspace());
172			if (color != fDesktopColor) {
173				fDesktopColor = color;
174				Invalidate();
175			}
176			break;
177		}
178
179		default:
180			BView::MessageReceived(message);
181			break;
182	}
183}
184
185
186BRect
187MonitorView::_MonitorBounds()
188{
189	float maxWidth = Bounds().Width();
190	float maxHeight = Bounds().Height();
191	if (maxWidth / maxHeight > (float)fMaxWidth / fMaxHeight)
192		maxWidth = maxHeight / fMaxHeight * fMaxWidth;
193	else
194		maxHeight = maxWidth / fMaxWidth * fMaxHeight;
195
196	float factorX = (float)fWidth / fMaxWidth;
197	float factorY = (float)fHeight / fMaxHeight;
198
199	if (factorX > factorY && factorX > 1) {
200		factorY /= factorX;
201		factorX = 1;
202	} else if (factorY > factorX && factorY > 1) {
203		factorX /= factorY;
204		factorY = 1;
205	}
206
207	float width = maxWidth * factorX;
208	float height = maxHeight * factorY;
209
210	BSize size = Bounds().Size();
211	return BRect((size.width - width) / 2, (size.height - height) / 2,
212		(size.width + width) / 2, (size.height + height) / 2);
213}
214
215
216void
217MonitorView::_UpdateDPI()
218{
219	fDPI = 0;
220
221	BScreen screen(Window());
222	monitor_info info;
223	if (screen.GetMonitorInfo(&info) != B_OK)
224		return;
225
226	double x = info.width / 2.54;
227	double y = info.height / 2.54;
228
229	fDPI = (int32)round((fWidth / x + fHeight / y) / 2);
230}
231