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