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 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 29 MemoryBarMenuItem::~MemoryBarMenuItem() 30 { 31 } 32 33 34 void 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 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 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 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 202 MemoryBarMenuItem::UpdateSituation(int64 committedMemory) 203 { 204 fCommittedMemory = committedMemory; 205 BarUpdate(); 206 return fWriteMemory; 207 } 208 209 210 void 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 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