xref: /haiku/src/apps/processcontroller/MemoryBarMenu.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 "MemoryBarMenu.h"
22 #include "MemoryBarMenuItem.h"
23 #include "KernelMemoryBarMenuItem.h"
24 #include "ProcessController.h"
25 
26 #include <Bitmap.h>
27 #include <Roster.h>
28 #include <StringForSize.h>
29 #include <Window.h>
30 
31 #include <stdlib.h>
32 
33 
34 #define EXTRA 10
35 
36 float gMemoryTextWidth;
37 
38 
39 MemoryBarMenu::MemoryBarMenu(const char* name, info_pack* infos, system_info& systemInfo)
40 	: BMenu(name),
41 	fFirstShow(true)
42 {
43 	fTeamCount = systemInfo.used_teams + EXTRA;
44 	SetFlags(Flags() | B_PULSE_NEEDED);
45 
46 	fTeamList = (team_id*)malloc(sizeof (team_id) * fTeamCount);
47 
48 	unsigned int k;
49 	for (k = 0; k < systemInfo.used_teams; k++) {
50 		fTeamList[k] = infos[k].team_info.team;
51 	}
52 
53 	while (k < fTeamCount) {
54 		fTeamList[k++] = -1;
55 	}
56 
57 	char buffer[64];
58 	string_for_size(99999999.9, buffer, sizeof(buffer));
59 	gMemoryTextWidth = 2 * StringWidth(buffer) + 32;
60 
61 	fRecycleCount = EXTRA;
62 	fRecycleList = (MRecycleItem*)malloc(sizeof(MRecycleItem) * fRecycleCount);
63 	SetFont(be_plain_font);
64 	AddItem(new KernelMemoryBarMenuItem(systemInfo));
65 }
66 
67 
68 MemoryBarMenu::~MemoryBarMenu()
69 {
70 	free(fTeamList);
71 	free(fRecycleList);
72 }
73 
74 
75 void
76 MemoryBarMenu::Draw(BRect updateRect)
77 {
78 	if (fFirstShow) {
79 		Pulse();
80 		fFirstShow = false;
81 	}
82 
83 	BMenu::Draw(updateRect);
84 }
85 
86 
87 void
88 MemoryBarMenu::Pulse()
89 {
90 	system_info	sinfo;
91 	get_system_info(&sinfo);
92 	int64 committedMemory = (int64)sinfo.used_pages * B_PAGE_SIZE / 1024;
93 	int64 cachedMemory = (int64)sinfo.cached_pages * B_PAGE_SIZE / 1024;
94 	Window()->BeginViewTransaction();
95 
96 	// create the list of items to remove, for their team is gone. Update the old teams.
97 	int lastRecycle = 0;
98 	int firstRecycle = 0;
99 	int	k;
100 	MemoryBarMenuItem* item;
101 	int	total = 0;
102 	for (k = 1; (item = (MemoryBarMenuItem*)ItemAt(k)) != NULL; k++) {
103 		int m = item->UpdateSituation(committedMemory);
104 		if (m < 0) {
105 			if (lastRecycle == fRecycleCount) {
106 				fRecycleCount += EXTRA;
107 				fRecycleList = (MRecycleItem*)realloc(fRecycleList,
108 					sizeof(MRecycleItem) * fRecycleCount);
109 			}
110 			fRecycleList[lastRecycle].index = k;
111 			fRecycleList[lastRecycle++].item = item;
112 		} else {
113 			if (lastRecycle > 0) {
114 				RemoveItems(fRecycleList[0].index, lastRecycle, true);
115 				k -= lastRecycle;
116 				lastRecycle = 0;
117 			}
118 			total += m;
119 		}
120 	}
121 
122 	// Look new teams that have appeared. Create an item for them, or recycle from the list.
123 	int32 cookie = 0;
124 	info_pack infos;
125 	item = NULL;
126 	while (get_next_team_info(&cookie, &infos.team_info) == B_OK) {
127 		unsigned int j = 0;
128 		while (j < fTeamCount && infos.team_info.team != fTeamList[j]) {
129 			j++;
130 		}
131 
132 		if (j == fTeamCount) {
133 			// new team
134 			team_info info;
135 			j = 0;
136 			while (j < fTeamCount && fTeamList[j] != -1) {
137 				if (get_team_info(fTeamList[j], &info) != B_OK)
138 					fTeamList[j] = -1;
139 				else
140 					j++;
141 			}
142 
143 			if (j == fTeamCount) {
144 				fTeamCount += 10;
145 				fTeamList = (team_id*)realloc(fTeamList, sizeof(team_id) * fTeamCount);
146 			}
147 
148 			fTeamList[j] = infos.team_info.team;
149 			if (!get_team_name_and_icon(infos, true)) {
150 				// the team is already gone!
151 				delete infos.team_icon;
152 				fTeamList[j] = -1;
153 			} else {
154 				if (!item && firstRecycle < lastRecycle)
155 					item = fRecycleList[firstRecycle++].item;
156 
157 				if (item)
158 					item->Reset(infos.team_name, infos.team_info.team, infos.team_icon, true);
159 				else {
160 					AddItem(item = new MemoryBarMenuItem(infos.team_name,
161 						infos.team_info.team, infos.team_icon, true, NULL));
162 				}
163 
164 				int m = item->UpdateSituation(committedMemory);
165 				if (m >= 0) {
166 					total += m;
167 					item = NULL;
168 				} else
169 					fTeamList[j] = -1;
170 			}
171 		}
172 	}
173 
174 	if (item) {
175 		RemoveItem(item);
176 		delete item;
177 	}
178 
179 	// Delete the items that haven't been recycled.
180 	if (firstRecycle < lastRecycle) {
181 		RemoveItems(IndexOf(fRecycleList[firstRecycle].item),
182 			lastRecycle - firstRecycle, true);
183 	}
184 
185 	fLastTotalTime = system_time();
186 	KernelMemoryBarMenuItem	*kernelItem;
187 	if ((kernelItem = (KernelMemoryBarMenuItem*)ItemAt(0)) != NULL)
188 		kernelItem->UpdateSituation(committedMemory, cachedMemory);
189 
190 	Window()->EndViewTransaction();
191 	Window()->Flush();
192 }
193