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