xref: /haiku/src/apps/processcontroller/TeamBarMenuItem.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 
18 TeamBarMenuItem::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 
29 void
30 TeamBarMenuItem::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 
53 TeamBarMenuItem::~TeamBarMenuItem()
54 {
55 }
56 
57 
58 void
59 TeamBarMenuItem::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 
76 void
77 TeamBarMenuItem::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 
175 void
176 TeamBarMenuItem::GetContentSize(float* width, float* height)
177 {
178 	IconMenuItem::GetContentSize(width, height);
179 	if (width != NULL)
180 		*width += 40 + kBarWidth;
181 }
182 
183 
184 void
185 TeamBarMenuItem::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 
219 void
220 TeamBarMenuItem::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