xref: /haiku/src/apps/processcontroller/TeamBarMenu.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2 	ProcessController © 2000, Georges-Edouard Berenger, All Rights Reserved.
3 	Copyright (C) 2004 beunited.org
4 
5 	This library is free software; you can redistribute it and/or
6 	modify it under the terms of the GNU Lesser General Public
7 	License as published by the Free Software Foundation; either
8 	version 2.1 of the License, or (at your option) any later version.
9 
10 	This library is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 	Lesser General Public License for more details.
14 
15 	You should have received a copy of the GNU Lesser General Public
16 	License along with this library; if not, write to the Free Software
17 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 
21 #include "TeamBarMenu.h"
22 #include "ThreadBarMenu.h"
23 #include "TeamBarMenuItem.h"
24 #include "NoiseBarMenuItem.h"
25 #include "ProcessController.h"
26 
27 #include <Bitmap.h>
28 #include <Roster.h>
29 #include <Window.h>
30 
31 #include <stdlib.h>
32 
33 
34 #define EXTRA 10
35 
36 
37 TeamBarMenu::TeamBarMenu(const char* title, info_pack* infos, int32 teamCount)
38 	: BMenu(title),
39 	fTeamCount(teamCount+EXTRA),
40 	fFirstShow(true)
41 {
42 	SetFlags(Flags() | B_PULSE_NEEDED);
43 	fTeamList = (team_id*)malloc(sizeof(team_id) * fTeamCount);
44 	int	k;
45 	for (k = 0; k < teamCount; k++) {
46 		fTeamList[k] = infos[k].team_info.team;
47 	}
48 	while (k < fTeamCount) {
49 		fTeamList[k++] = -1;
50 	}
51 	fRecycleCount = EXTRA;
52 	fRecycleList = (TRecycleItem*)malloc(sizeof(TRecycleItem) * fRecycleCount);
53 	SetFont(be_plain_font);
54 	gCurrentThreadBarMenu = NULL;
55 	fLastTotalTime = system_time();
56 	AddItem(new NoiseBarMenuItem());
57 }
58 
59 
60 TeamBarMenu::~TeamBarMenu()
61 {
62 	gCurrentThreadBarMenu = NULL;
63 	free(fTeamList);
64 	free(fRecycleList);
65 }
66 
67 
68 void
69 TeamBarMenu::Draw(BRect updateRect)
70 {
71 	BMenu::Draw (updateRect);
72 	if (fFirstShow) {
73 		Pulse();
74 		fFirstShow = false;
75 	}
76 }
77 
78 
79 void
80 TeamBarMenu::Pulse()
81 {
82 	Window()->BeginViewTransaction();
83 
84 	// create the list of items to remove, for their team is gone. Update the old teams.
85 	int lastRecycle = 0;
86 	int firstRecycle = 0;
87 	int	k;
88 	TeamBarMenuItem *item;
89 	double total = 0;
90 	for (k = 1; (item = (TeamBarMenuItem*)ItemAt(k)) != NULL; k++) {
91 		item->BarUpdate();
92 		if (item->fKernel < 0) {
93 			if (lastRecycle == fRecycleCount) {
94 				fRecycleCount += EXTRA;
95 				fRecycleList = (TRecycleItem*)realloc(fRecycleList,
96 					sizeof(TRecycleItem)*fRecycleCount);
97 			}
98 			fRecycleList[lastRecycle].index = k;
99 			fRecycleList[lastRecycle++].item = item;
100 		} else {
101 			if (lastRecycle > 0) {
102 				RemoveItems(fRecycleList[0].index, lastRecycle, true);
103 				k -= lastRecycle;
104 				lastRecycle = 0;
105 			}
106 			total += item->fUser+item->fKernel;
107 		}
108 	}
109 
110 	// Look new teams that have appeared. Create an item for them, or recycle from the list.
111 	int32 cookie = 0;
112 	info_pack infos;
113 	item = NULL;
114 	while (get_next_team_info(&cookie, &infos.team_info) == B_OK) {
115 		int	j = 0;
116 		while (j < fTeamCount && infos.team_info.team != fTeamList[j])
117 			j++;
118 		if (infos.team_info.team != fTeamList[j]) {
119 			// new team
120 			team_info info;
121 			j = 0;
122 			while (j < fTeamCount && fTeamList[j] != -1)
123 				if (get_team_info(fTeamList[j], &info) != B_OK)
124 					fTeamList[j] = -1;
125 				else
126 					j++;
127 			if (j == fTeamCount) {
128 				fTeamCount +=  10;
129 				fTeamList = (team_id*)realloc(fTeamList, sizeof(team_id)*fTeamCount);
130 			}
131 			fTeamList[j] = infos.team_info.team;
132 			if (!get_team_name_and_icon(infos, true)) {
133 				// the team is already gone!
134 				delete infos.team_icon;
135 				fTeamList[j] = -1;
136 			} else {
137 				if (!item && firstRecycle < lastRecycle) {
138 					item = fRecycleList[firstRecycle++].item;
139 				}
140 				if (item) {
141 					item->Reset(infos.team_name, infos.team_info.team, infos.team_icon, true);
142 				} else {
143 					BMessage* kill_team = new BMessage('KlTm');
144 					kill_team->AddInt32("team", infos.team_info.team);
145 					item = new TeamBarMenuItem(new ThreadBarMenu(infos.team_name,
146 						infos.team_info.team, infos.team_info.thread_count),
147 						kill_team, infos.team_info.team, infos.team_icon, true);
148 					item->SetTarget(gPCView);
149 					AddItem(item);
150 					item->BarUpdate();
151 				}
152 				if (item->fKernel >= 0) {
153 					total += item->fUser + item->fKernel;
154 					item = NULL;
155 				} else {
156 					fTeamList[j] = -1;
157 				}
158 			}
159 		}
160 	}
161 	if (item) {
162 		RemoveItem(item);
163 		delete item;
164 	}
165 
166 	// Delete the items that haven't been recycled.
167 	if (firstRecycle < lastRecycle)
168 		RemoveItems(IndexOf(fRecycleList[firstRecycle].item), lastRecycle-firstRecycle, true);
169 
170 	total /= gCPUcount;
171 	total = 1-total;
172 
173 	fLastTotalTime = system_time();
174 	NoiseBarMenuItem* noiseItem;
175 	if ((noiseItem = (NoiseBarMenuItem*)ItemAt(0)) != NULL) {
176 		noiseItem->fBusyWaiting = 0;
177 		noiseItem->fLost = (total >= 0 ? total : 0);
178 		noiseItem->DrawBar(false);
179 	}
180 
181 	if (gCurrentThreadBarMenu && gCurrentThreadBarMenu->LockLooperWithTimeout(25000) == B_OK) {
182 		gCurrentThreadBarMenu->Window()->BeginViewTransaction();
183 		gCurrentThreadBarMenu->Update();
184 		gCurrentThreadBarMenu->Window()->EndViewTransaction();
185 		gCurrentThreadBarMenu->Window()->Flush();
186 		gCurrentThreadBarMenu->UnlockLooper();
187 	}
188 
189 	Window()->EndViewTransaction();
190 	Window()->Flush();
191 }
192