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