xref: /haiku/src/apps/processcontroller/TeamBarMenu.cpp (revision a5061ecec55353a5f394759473f1fd6df04890da)
1 /*
2  * Copyright 2000, Georges-Edouard Berenger. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "TeamBarMenu.h"
8 #include "ThreadBarMenu.h"
9 #include "TeamBarMenuItem.h"
10 #include "NoiseBarMenuItem.h"
11 #include "ProcessController.h"
12 
13 #include <Bitmap.h>
14 #include <Roster.h>
15 #include <Window.h>
16 
17 #include <stdlib.h>
18 
19 
20 #define EXTRA 10
21 
22 
23 TeamBarMenu::TeamBarMenu(const char* title, info_pack* infos, int32 teamCount)
24 	: BMenu(title),
25 	fTeamCount(teamCount+EXTRA),
26 	fFirstShow(true)
27 {
28 	SetFlags(Flags() | B_PULSE_NEEDED);
29 	fTeamList = (team_id*)malloc(sizeof(team_id) * fTeamCount);
30 	int	k;
31 	for (k = 0; k < teamCount; k++) {
32 		fTeamList[k] = infos[k].team_info.team;
33 	}
34 	while (k < fTeamCount) {
35 		fTeamList[k++] = -1;
36 	}
37 	fRecycleCount = EXTRA;
38 	fRecycleList = (TRecycleItem*)malloc(sizeof(TRecycleItem) * fRecycleCount);
39 	SetFont(be_plain_font);
40 	gCurrentThreadBarMenu = NULL;
41 	fLastTotalTime = system_time();
42 	AddItem(new NoiseBarMenuItem());
43 }
44 
45 
46 TeamBarMenu::~TeamBarMenu()
47 {
48 	gCurrentThreadBarMenu = NULL;
49 	free(fTeamList);
50 	free(fRecycleList);
51 }
52 
53 
54 void
55 TeamBarMenu::Draw(BRect updateRect)
56 {
57 	BMenu::Draw (updateRect);
58 	if (fFirstShow) {
59 		Pulse();
60 		fFirstShow = false;
61 	}
62 }
63 
64 
65 void
66 TeamBarMenu::Pulse()
67 {
68 	Window()->BeginViewTransaction();
69 
70 	// create the list of items to remove, for their team is gone. Update the old teams.
71 	int lastRecycle = 0;
72 	int firstRecycle = 0;
73 	int	k;
74 	TeamBarMenuItem *item;
75 	double total = 0;
76 	for (k = 1; (item = (TeamBarMenuItem*)ItemAt(k)) != NULL; k++) {
77 		item->BarUpdate();
78 		if (item->fKernel < 0) {
79 			if (lastRecycle == fRecycleCount) {
80 				fRecycleCount += EXTRA;
81 				fRecycleList = (TRecycleItem*)realloc(fRecycleList,
82 					sizeof(TRecycleItem)*fRecycleCount);
83 			}
84 			fRecycleList[lastRecycle].index = k;
85 			fRecycleList[lastRecycle++].item = item;
86 		} else {
87 			if (lastRecycle > 0) {
88 				RemoveItems(fRecycleList[0].index, lastRecycle, true);
89 				k -= lastRecycle;
90 				lastRecycle = 0;
91 			}
92 			total += item->fUser + item->fKernel;
93 		}
94 	}
95 
96 	// Look new teams that have appeared. Create an item for them, or recycle from the list.
97 	int32 cookie = 0;
98 	info_pack infos;
99 	item = NULL;
100 	while (get_next_team_info(&cookie, &infos.team_info) == B_OK) {
101 		int	j = 0;
102 		while (j < fTeamCount && infos.team_info.team != fTeamList[j])
103 			j++;
104 		if (infos.team_info.team != fTeamList[j]) {
105 			// new team
106 			team_info info;
107 			j = 0;
108 			while (j < fTeamCount && fTeamList[j] != -1)
109 				if (get_team_info(fTeamList[j], &info) != B_OK)
110 					fTeamList[j] = -1;
111 				else
112 					j++;
113 			if (j == fTeamCount) {
114 				fTeamCount +=  10;
115 				fTeamList = (team_id*)realloc(fTeamList, sizeof(team_id) * fTeamCount);
116 			}
117 			fTeamList[j] = infos.team_info.team;
118 			if (!get_team_name_and_icon(infos, true)) {
119 				// the team is already gone!
120 				fTeamList[j] = -1;
121 			} else {
122 				if (!item && firstRecycle < lastRecycle) {
123 					item = fRecycleList[firstRecycle++].item;
124 				}
125 				if (item) {
126 					item->Reset(infos.team_name, infos.team_info.team, infos.team_icon, true);
127 				} else {
128 					BMessage* kill_team = new BMessage('KlTm');
129 					kill_team->AddInt32("team", infos.team_info.team);
130 					item = new TeamBarMenuItem(new ThreadBarMenu(infos.team_name,
131 						infos.team_info.team, infos.team_info.thread_count),
132 						kill_team, infos.team_info.team, infos.team_icon, true);
133 					item->SetTarget(gPCView);
134 					AddItem(item);
135 					item->BarUpdate();
136 				}
137 				if (item->fKernel >= 0) {
138 					total += item->fUser + item->fKernel;
139 					item = NULL;
140 				} else {
141 					fTeamList[j] = -1;
142 				}
143 			}
144 		}
145 	}
146 	if (item) {
147 		RemoveItem(item);
148 		delete item;
149 	}
150 
151 	// Delete the items that haven't been recycled.
152 	if (firstRecycle < lastRecycle)
153 		RemoveItems(IndexOf(fRecycleList[firstRecycle].item), lastRecycle - firstRecycle, true);
154 
155 	total /= gCPUcount;
156 	total = 1 - total;
157 
158 	fLastTotalTime = system_time();
159 	NoiseBarMenuItem* noiseItem;
160 	if ((noiseItem = (NoiseBarMenuItem*)ItemAt(0)) != NULL) {
161 		noiseItem->SetBusyWaiting(0);
162 		if (total >= 0)
163 			noiseItem->SetLost(total);
164 		else
165 			noiseItem->SetLost(0);
166 		noiseItem->DrawBar(false);
167 	}
168 
169 	if (gCurrentThreadBarMenu && gCurrentThreadBarMenu->LockLooperWithTimeout(25000) == B_OK) {
170 		gCurrentThreadBarMenu->Window()->BeginViewTransaction();
171 		gCurrentThreadBarMenu->Update();
172 		gCurrentThreadBarMenu->Window()->EndViewTransaction();
173 		gCurrentThreadBarMenu->Window()->Flush();
174 		gCurrentThreadBarMenu->UnlockLooper();
175 	}
176 
177 	Window()->EndViewTransaction();
178 	Window()->Flush();
179 }
180