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