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