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