xref: /haiku/src/apps/processcontroller/MemoryBarMenuItem.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
1 /*
2  * Copyright 2000, Georges-Edouard Berenger. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "MemoryBarMenuItem.h"
8 
9 #include "Colors.h"
10 #include "MemoryBarMenu.h"
11 #include "ProcessController.h"
12 
13 #include <Bitmap.h>
14 #include <StringForSize.h>
15 
16 #include <stdio.h>
17 
18 
19 MemoryBarMenuItem::MemoryBarMenuItem(const char *label, team_id team,
20 		BBitmap* icon, bool deleteIcon, BMessage* message)
21 	: BMenuItem(label, message),
22 	fTeamID(team),
23 	fIcon(icon),
24 	fDeleteIcon(deleteIcon)
25 {
26 	Init();
27 }
28 
29 
30 MemoryBarMenuItem::~MemoryBarMenuItem()
31 {
32 	if (fDeleteIcon)
33 		delete fIcon;
34 }
35 
36 
37 void
38 MemoryBarMenuItem::Init()
39 {
40 	fWriteMemory = -1;
41 	fAllMemory = -1;
42 	fGrenze1 = -1;
43 	fGrenze2 = -1;
44 	fLastCommitted = -1;
45 	fLastWrite = -1;
46 	fLastAll = -1;
47 }
48 
49 
50 void
51 MemoryBarMenuItem::DrawContent()
52 {
53 	DrawIcon();
54 	if (fWriteMemory < 0)
55 		BarUpdate();
56 	else
57 		DrawBar(true);
58 
59 	BPoint loc = ContentLocation();
60 	loc.x += 20;
61 	Menu()->MovePenTo(loc);
62 	BMenuItem::DrawContent();
63 }
64 
65 
66 void
67 MemoryBarMenuItem::DrawIcon()
68 {
69 	// TODO: exact code duplication with TeamBarMenuItem::DrawIcon()
70 	if (!fIcon)
71 		return;
72 
73 	BPoint loc = ContentLocation();
74 	BRect frame = Frame();
75 
76 	loc.y = frame.top + (frame.bottom - frame.top - 15) / 2;
77 
78 	BMenu* menu = Menu();
79 
80 	if (fIcon->ColorSpace() == B_RGBA32) {
81 		menu->SetDrawingMode(B_OP_ALPHA);
82 		menu->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
83 	} else
84 		menu->SetDrawingMode(B_OP_OVER);
85 
86 	menu->DrawBitmap(fIcon, loc);
87 
88 	menu->SetDrawingMode(B_OP_COPY);
89 }
90 
91 
92 void
93 MemoryBarMenuItem::DrawBar(bool force)
94 {
95 	// only draw anything if something has changed
96 	if (!force && fWriteMemory == fLastWrite && fAllMemory == fLastAll
97 		&& fCommittedMemory == fLastCommitted)
98 		return;
99 
100 	bool selected = IsSelected();
101 	BRect frame = Frame();
102 	BMenu* menu = Menu();
103 	rgb_color highColor = menu->HighColor();
104 
105 	BFont font;
106 	menu->GetFont(&font);
107 	BRect rect = bar_rect(frame, &font);
108 
109 	// draw the bar itself
110 	if (fWriteMemory < 0)
111 		return;
112 
113 	if (fGrenze1 < 0)
114 		force = true;
115 
116 	if (force) {
117 		if (selected)
118 			menu->SetHighColor(gFrameColorSelected);
119 		else
120 			menu->SetHighColor(gFrameColor);
121 		menu->StrokeRect(rect);
122 	}
123 
124 	rect.InsetBy(1, 1);
125 	BRect r = rect;
126 	double grenze1 = rect.left + (rect.right - rect.left) * float(fWriteMemory)
127 		/ fCommittedMemory;
128 	double grenze2 = rect.left + (rect.right - rect.left) * float(fAllMemory)
129 		/ fCommittedMemory;
130 	if (grenze1 > rect.right)
131 		grenze1 = rect.right;
132 	if (grenze2 > rect.right)
133 		grenze2 = rect.right;
134 	r.right = grenze1;
135 	if (!force)
136 		r.left = fGrenze1;
137 	if (r.left < r.right) {
138 		if (selected)
139 			menu->SetHighColor(gKernelColorSelected);
140 		else
141 			menu->SetHighColor(gKernelColor);
142 		menu->FillRect(r);
143 	}
144 
145 	r.left = grenze1;
146 	r.right = grenze2;
147 
148 	if (!force) {
149 		if (fGrenze2 > r.left && r.left >= fGrenze1)
150 			r.left = fGrenze2;
151 		if (fGrenze1 < r.right && r.right  <= fGrenze2)
152 			r.right = fGrenze1;
153 	}
154 
155 	if (r.left < r.right) {
156 		if (selected)
157 			menu->SetHighColor(gUserColorSelected);
158 		else
159 			menu->SetHighColor(gUserColor);
160 		menu->FillRect(r);
161 	}
162 
163 	r.left = grenze2;
164 	r.right = rect.right;
165 
166 	if (!force)
167 		r.right = fGrenze2;
168 
169 	if (r.left < r.right) {
170 		if (selected)
171 			menu->SetHighColor(gWhiteSelected);
172 		else
173 			menu->SetHighColor(kWhite);
174 		menu->FillRect(r);
175 	}
176 
177 	menu->SetHighColor(highColor);
178 	fGrenze1 = grenze1;
179 	fGrenze2 = grenze2;
180 
181 	fLastCommitted = fCommittedMemory;
182 
183 	// Draw the values if necessary; if only fCommitedMemory changes, only
184 	// the bar might have to be updated
185 
186 	if (!force && fWriteMemory == fLastWrite && fAllMemory == fLastAll)
187 		return;
188 
189 	if (selected)
190 		menu->SetLowColor(gMenuBackColorSelected);
191 	else
192 		menu->SetLowColor(gMenuBackColor);
193 
194 	BRect textRect(rect.left - kMargin - gMemoryTextWidth, frame.top,
195 		rect.left - kMargin, frame.bottom);
196 	menu->FillRect(textRect, B_SOLID_LOW);
197 
198 	fLastWrite = fWriteMemory;
199 	fLastAll = fAllMemory;
200 
201 	if (selected)
202 		menu->SetHighColor(ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR));
203 	else
204 		menu->SetHighColor(ui_color(B_MENU_ITEM_TEXT_COLOR));
205 
206 	char infos[128];
207 	string_for_size(fWriteMemory * 1024.0, infos, sizeof(infos));
208 
209 	BPoint loc(rect.left - kMargin - gMemoryTextWidth / 2 - menu->StringWidth(infos),
210 		rect.bottom + 1);
211 	menu->DrawString(infos, loc);
212 
213 	string_for_size(fAllMemory * 1024.0, infos, sizeof(infos));
214 	loc.x = rect.left - kMargin - menu->StringWidth(infos);
215 	menu->DrawString(infos, loc);
216 	menu->SetHighColor(highColor);
217 }
218 
219 
220 void
221 MemoryBarMenuItem::GetContentSize(float* _width, float* _height)
222 {
223 	BMenuItem::GetContentSize(_width, _height);
224 	if (*_height < 16)
225 		*_height = 16;
226 	*_width += 30 + kBarWidth + kMargin + gMemoryTextWidth;
227 }
228 
229 
230 int
231 MemoryBarMenuItem::UpdateSituation(int64 committedMemory)
232 {
233 	fCommittedMemory = committedMemory;
234 	BarUpdate();
235 	return fWriteMemory;
236 }
237 
238 
239 void
240 MemoryBarMenuItem::BarUpdate()
241 {
242 	area_info areaInfo;
243 	ssize_t cookie = 0;
244 	int64 lram_size = 0;
245 	int64 lwram_size = 0;
246 	bool exists = false;
247 
248 	while (get_next_area_info(fTeamID, &cookie, &areaInfo) == B_OK) {
249 		exists = true;
250 		lram_size += areaInfo.ram_size;
251 
252 		// TODO: this won't work this way anymore under Haiku!
253 //		int zone = (int (areaInfo.address) & 0xf0000000) >> 24;
254 		if ((areaInfo.protection & B_WRITE_AREA) != 0)
255 			lwram_size += areaInfo.ram_size;
256 //			&& (zone & 0xf0) != 0xA0			// Exclude media buffers
257 //			&& (fTeamID != gAppServerTeamID || zone != 0x90))	// Exclude app_server side of bitmaps
258 	}
259 	if (!exists) {
260 		team_info info;
261 		exists = get_team_info(fTeamID, &info) == B_OK;
262 	}
263 	if (exists) {
264 		fWriteMemory = lwram_size / 1024;
265 		fAllMemory = lram_size / 1024;
266 		DrawBar(false);
267 	} else
268 		fWriteMemory = -1;
269 }
270 
271 
272 void
273 MemoryBarMenuItem::Reset(char* name, team_id team, BBitmap* icon,
274 	bool deleteIcon)
275 {
276 	SetLabel(name);
277 	fTeamID = team;
278 	if (fDeleteIcon)
279 		delete fIcon;
280 
281 	fDeleteIcon = deleteIcon;
282 	fIcon = icon;
283 	Init();
284 }
285