1/*
2 * Copyright 2000, Georges-Edouard Berenger. All rights reserved.
3 * Copyright 2022, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6#include "TeamBarMenuItem.h"
7
8#include "Colors.h"
9#include "ProcessController.h"
10#include "ThreadBarMenu.h"
11#include "ThreadBarMenuItem.h"
12#include "Utilities.h"
13
14#include <Bitmap.h>
15#include <ControlLook.h>
16
17
18TeamBarMenuItem::TeamBarMenuItem(BMenu* menu, BMessage* kill_team, team_id team,
19	BBitmap* icon, bool deleteIcon)
20	:
21	IconMenuItem(icon, menu, true, deleteIcon),
22	fTeamID(team)
23{
24	SetMessage(kill_team);
25	Init();
26}
27
28
29void
30TeamBarMenuItem::Init()
31{
32	if (get_team_usage_info(fTeamID, B_TEAM_USAGE_SELF, &fTeamUsageInfo) != B_OK)
33		fTeamUsageInfo.kernel_time = fTeamUsageInfo.user_time = 0;
34
35	if (fTeamID == B_SYSTEM_TEAM) {
36		thread_info thinfos;
37		bigtime_t idle = 0;
38		for (unsigned int t = 1; t <= gCPUcount; t++) {
39			if (get_thread_info(t, &thinfos) == B_OK)
40				idle += thinfos.kernel_time + thinfos.user_time;
41		}
42		fTeamUsageInfo.kernel_time += fTeamUsageInfo.user_time;
43		fTeamUsageInfo.user_time = idle;
44	}
45
46	fLastTime = system_time();
47	fKernel = -1;
48	fGrenze1 = -1;
49	fGrenze2 = -1;
50}
51
52
53TeamBarMenuItem::~TeamBarMenuItem()
54{
55}
56
57
58void
59TeamBarMenuItem::DrawContent()
60{
61	BPoint loc;
62
63	DrawIcon();
64	if (fKernel < 0)
65		BarUpdate();
66	else
67		DrawBar(true);
68
69	loc = ContentLocation();
70	loc.x += ceilf(be_control_look->DefaultLabelSpacing() * 3.3f);
71	Menu()->MovePenTo(loc);
72	BMenuItem::DrawContent();
73}
74
75
76void
77TeamBarMenuItem::DrawBar(bool force)
78{
79	const bool selected = IsSelected();
80	BRect frame = Frame();
81	BMenu* menu = Menu();
82	rgb_color highColor = menu->HighColor();
83
84	BFont font;
85	menu->GetFont(&font);
86	frame = bar_rect(frame, &font);
87
88	if (fKernel < 0)
89		return;
90
91	if (fGrenze1 < 0)
92		force = true;
93
94	if (force) {
95		if (selected)
96			menu->SetHighColor(gFrameColorSelected);
97		else
98			menu->SetHighColor(gFrameColor);
99
100		menu->StrokeRect(frame);
101	}
102
103	frame.InsetBy(1, 1);
104	BRect r = frame;
105	float grenze1 = frame.left + (frame.right - frame.left)
106		* fKernel / gCPUcount;
107	float grenze2 = frame.left + (frame.right - frame.left)
108		* (fKernel + fUser) / gCPUcount;
109
110	if (grenze1 > frame.right)
111		grenze1 = frame.right;
112
113	if (grenze2 > frame.right)
114		grenze2 = frame.right;
115
116	r.right = grenze1;
117	if (!force)
118		r.left = fGrenze1;
119
120	if (r.left < r.right) {
121		if (selected)
122			menu->SetHighColor(gKernelColorSelected);
123		else
124			menu->SetHighColor(gKernelColor);
125
126		menu->FillRect(r);
127	}
128
129	r.left = grenze1;
130	r.right = grenze2;
131
132	if (!force) {
133		if (fGrenze2 > r.left && r.left >= fGrenze1)
134			r.left = fGrenze2;
135
136		if (fGrenze1 < r.right && r.right <= fGrenze2)
137			r.right = fGrenze1;
138	}
139
140	if (r.left < r.right) {
141		if (selected) {
142			menu->SetHighColor(fTeamID == B_SYSTEM_TEAM
143				? gIdleColorSelected
144				: gUserColorSelected);
145		} else {
146			menu->SetHighColor(fTeamID == B_SYSTEM_TEAM
147				? gIdleColor
148				: gUserColor);
149		}
150
151		menu->FillRect(r);
152	}
153
154	r.left = grenze2;
155	r.right = frame.right;
156
157	if (!force)
158		r.right = fGrenze2;
159
160	if (r.left < r.right) {
161		if (selected)
162			menu->SetHighColor(gWhiteSelected);
163		else
164			menu->SetHighColor(kWhite);
165
166		menu->FillRect(r);
167	}
168
169	menu->SetHighColor(highColor);
170	fGrenze1 = grenze1;
171	fGrenze2 = grenze2;
172}
173
174
175void
176TeamBarMenuItem::GetContentSize(float* width, float* height)
177{
178	IconMenuItem::GetContentSize(width, height);
179	if (width != NULL)
180		*width += 40 + kBarWidth;
181}
182
183
184void
185TeamBarMenuItem::BarUpdate()
186{
187	team_usage_info usage;
188	if (get_team_usage_info(fTeamID, B_TEAM_USAGE_SELF, &usage) == B_OK) {
189		bigtime_t now = system_time();
190		bigtime_t idle = 0;
191		if (fTeamID == B_SYSTEM_TEAM) {
192			thread_info thinfos;
193			for (unsigned int t = 1; t <= gCPUcount; t++) {
194				if (get_thread_info(t, &thinfos) == B_OK)
195					idle += thinfos.kernel_time + thinfos.user_time;
196			}
197			usage.kernel_time += usage.user_time;
198			usage.user_time = idle;
199			idle -= fTeamUsageInfo.user_time;
200		}
201
202		fKernel = double(usage.kernel_time - fTeamUsageInfo.kernel_time - idle)
203			/ double(now - fLastTime);
204
205		fUser = double(usage.user_time - fTeamUsageInfo.user_time)
206			/ double(now - fLastTime);
207
208		if (fKernel < 0)
209			fKernel = 0;
210
211		fLastTime = now;
212		fTeamUsageInfo = usage;
213		DrawBar(false);
214	} else
215		fKernel = -1;
216}
217
218
219void
220TeamBarMenuItem::Reset(char* name, team_id team, BBitmap* icon, bool deleteIcon)
221{
222	IconMenuItem::Reset(icon, deleteIcon);
223
224	SetLabel(name);
225	fTeamID = team;
226	Init();
227
228	Message()->ReplaceInt32("team", team);
229	((ThreadBarMenu*)Submenu())->Reset(team);
230	BarUpdate();
231}
232