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