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