1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered 30 trademarks of Be Incorporated in the United States and other countries. Other 31 brand product names are registered trademarks or trademarks of their respective 32 holders. 33 All rights reserved. 34 */ 35 36 37 #include "TeamMenu.h" 38 39 #include <algorithm> 40 #include <strings.h> 41 42 #include <Application.h> 43 #include <Collator.h> 44 #include <ControlLook.h> 45 #include <Debug.h> 46 #include <Mime.h> 47 #include <Roster.h> 48 49 #include "BarApp.h" 50 #include "BarMenuBar.h" 51 #include "BarView.h" 52 #include "DeskbarUtils.h" 53 #include "StatusView.h" 54 #include "TeamMenuItem.h" 55 56 57 // #pragma mark - TTeamMenuItem 58 59 60 TTeamMenu::TTeamMenu(TBarView* barView) 61 : 62 BMenu("Team Menu"), 63 fBarView(barView) 64 { 65 SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f); 66 SetFont(be_plain_font); 67 } 68 69 70 int 71 TTeamMenu::CompareByName(const void* first, const void* second) 72 { 73 BCollator collator; 74 BLocale::Default()->GetCollator(&collator); 75 76 return collator.Compare( 77 (*(static_cast<BarTeamInfo* const*>(first)))->name, 78 (*(static_cast<BarTeamInfo* const*>(second)))->name); 79 } 80 81 82 void 83 TTeamMenu::AttachedToWindow() 84 { 85 RemoveItems(0, CountItems(), true); 86 // remove all items 87 88 BMessenger self(this); 89 BList teamList; 90 TBarApp::Subscribe(self, &teamList); 91 92 bool dragging = fBarView != NULL && fBarView->Dragging(); 93 desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings(); 94 const int32 iconSize = static_cast<TBarApp*>(be_app)->TeamIconSize(); 95 const float iconPadding = be_control_look->ComposeSpacing(kIconPadding); 96 float iconOnlyWidth = iconSize + iconPadding; 97 if (settings->hideLabels) 98 iconOnlyWidth += iconPadding; // add an extra icon padding 99 const int32 large = be_control_look->ComposeIconSize(B_LARGE_ICON) 100 .IntegerWidth() + 1; 101 const int32 min = be_control_look->ComposeIconSize(kMinimumIconSize) 102 .IntegerWidth() + 1; 103 104 // calculate the minimum item width based on font and icon size 105 float minItemWidth = 0; 106 if (settings->hideLabels) { 107 minItemWidth = std::max(floorf(gMinimumWindowWidth / 2), 108 iconOnlyWidth); 109 } else { 110 float labelWidth = gMinimumWindowWidth - iconOnlyWidth 111 + (be_plain_font->Size() - 12) * 4; 112 if (iconSize <= large) // label wraps after 32x32 113 labelWidth += iconSize - min; 114 minItemWidth = iconOnlyWidth + labelWidth; 115 } 116 117 float maxItemWidth = minItemWidth; 118 119 int32 teamCount = teamList.CountItems(); 120 if (!settings->hideLabels) { 121 // go through list and find the widest label 122 for (int32 i = 0; i < teamCount; i++) { 123 BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i); 124 float labelWidth = StringWidth(barInfo->name); 125 // label wraps after 32x32 126 float itemWidth = iconSize > large 127 ? std::max(labelWidth, iconOnlyWidth) 128 : labelWidth + iconOnlyWidth + min 129 + (be_plain_font->Size() - 12) * 4; 130 maxItemWidth = std::max(maxItemWidth, itemWidth); 131 } 132 133 // but not too wide 134 maxItemWidth = std::min(maxItemWidth, gMaximumWindowWidth); 135 } 136 137 SetMaxContentWidth(maxItemWidth); 138 139 if (settings->sortRunningApps) 140 teamList.SortItems(TTeamMenu::CompareByName); 141 142 // go through list and add the items 143 for (int32 i = 0; i < teamCount; i++) { 144 // add items back 145 BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i); 146 TTeamMenuItem* item = new TTeamMenuItem(barInfo->teams, 147 barInfo->icon, barInfo->name, barInfo->sig, maxItemWidth); 148 149 if (settings->trackerAlwaysFirst 150 && strcasecmp(barInfo->sig, kTrackerSignature) == 0) { 151 AddItem(item, 0); 152 } else 153 AddItem(item); 154 155 if (dragging && item != NULL) { 156 bool canhandle = fBarView->AppCanHandleTypes(item->Signature()); 157 if (item->IsEnabled() != canhandle) 158 item->SetEnabled(canhandle); 159 160 BMenu* menu = item->Submenu(); 161 if (menu != NULL) { 162 menu->SetTrackingHook(fBarView->MenuTrackingHook, 163 fBarView->GetTrackingHookData()); 164 } 165 } 166 } 167 168 if (CountItems() == 0) { 169 BMenuItem* item = new BMenuItem("no application running", NULL); 170 item->SetEnabled(false); 171 AddItem(item); 172 } 173 174 if (dragging && fBarView->LockLooper()) { 175 SetTrackingHook(fBarView->MenuTrackingHook, 176 fBarView->GetTrackingHookData()); 177 fBarView->DragStart(); 178 fBarView->UnlockLooper(); 179 } 180 181 BMenu::AttachedToWindow(); 182 } 183 184 185 void 186 TTeamMenu::DetachedFromWindow() 187 { 188 if (fBarView != NULL) { 189 BLooper* looper = fBarView->Looper(); 190 if (looper != NULL && looper->Lock()) { 191 fBarView->DragStop(); 192 looper->Unlock(); 193 } 194 } 195 196 BMenu::DetachedFromWindow(); 197 198 BMessenger self(this); 199 TBarApp::Unsubscribe(self); 200 } 201 202 203 void 204 TTeamMenu::MessageReceived(BMessage* message) 205 { 206 TTeamMenuItem* item = NULL; 207 208 switch (message->what) { 209 case B_SOME_APP_QUIT: 210 case kRemoveTeam: 211 { 212 int32 itemIndex = -1; 213 message->FindInt32("itemIndex", &itemIndex); 214 team_id team = -1; 215 message->FindInt32("team", &team); 216 217 item = dynamic_cast<TTeamMenuItem*>(ItemAt(itemIndex)); 218 if (item != NULL && item->Teams()->HasItem((void*)(addr_t)team)) { 219 item->Teams()->RemoveItem(team); 220 RemoveItem(itemIndex); 221 delete item; 222 } 223 break; 224 } 225 226 default: 227 BMenu::MessageReceived(message); 228 break; 229 } 230 } 231 232 233 void 234 TTeamMenu::MouseDown(BPoint where) 235 { 236 if (fBarView == NULL || fBarView->Dragging()) 237 return BMenu::MouseDown(where); 238 239 BMenuItem* item = ItemAtPoint(where); 240 if (item == NULL) 241 return BMenu::MouseDown(where); 242 243 TTeamMenuItem* teamItem = dynamic_cast<TTeamMenuItem*>(item); 244 if (teamItem == NULL || !teamItem->HandleMouseDown(where)) 245 BMenu::MouseDown(where); 246 } 247 248 249 BMenuItem* 250 TTeamMenu::ItemAtPoint(BPoint point) 251 { 252 int32 itemCount = CountItems(); 253 for (int32 index = 0; index < itemCount; index++) { 254 BMenuItem* item = ItemAt(index); 255 if (item != NULL && item->Frame().Contains(point)) 256 return item; 257 } 258 259 // no item found 260 return NULL; 261 } 262