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 "BarMenuBar.h" 38 39 #include <algorithm> 40 41 #include <Bitmap.h> 42 #include <ControlLook.h> 43 #include <Debug.h> 44 #include <IconUtils.h> 45 #include <NodeInfo.h> 46 47 #include "icons.h" 48 49 #include "BarMenuTitle.h" 50 #include "BarView.h" 51 #include "BarWindow.h" 52 #include "DeskbarMenu.h" 53 #include "DeskbarUtils.h" 54 #include "ResourceSet.h" 55 #include "StatusView.h" 56 #include "TeamMenu.h" 57 58 59 const float kSepItemWidth = 5.0f; 60 61 const float kTeamIconBitmapHeight = 19.f; 62 63 64 // #pragma mark - TSeparatorItem 65 66 67 TSeparatorItem::TSeparatorItem() 68 : 69 BSeparatorItem() 70 { 71 } 72 73 74 void 75 TSeparatorItem::Draw() 76 { 77 BMenu* menu = Menu(); 78 if (menu == NULL) 79 return; 80 81 BRect frame(Frame()); 82 frame.right = frame.left + kSepItemWidth; 83 rgb_color base = ui_color(B_MENU_BACKGROUND_COLOR); 84 85 menu->PushState(); 86 87 menu->SetHighColor(tint_color(base, 1.22)); 88 frame.top--; 89 // need to expand the frame for some reason 90 91 // stroke a darker line on the left edge 92 menu->StrokeLine(frame.LeftTop(), frame.LeftBottom()); 93 frame.left++; 94 95 // fill in background 96 be_control_look->DrawButtonBackground(menu, frame, frame, base); 97 98 menu->PopState(); 99 } 100 101 102 // #pragma mark - TBarMenuBar 103 104 105 TBarMenuBar::TBarMenuBar(BRect frame, const char* name, TBarView* barView) 106 : 107 BMenuBar(frame, name, B_FOLLOW_NONE, B_ITEMS_IN_ROW, false), 108 fBarView(barView), 109 fAppListMenuItem(NULL), 110 fSeparatorItem(NULL), 111 fTeamIconData(NULL), 112 fTeamIconSize(0) 113 { 114 SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f); 115 116 TDeskbarMenu* beMenu = new TDeskbarMenu(barView); 117 TBarWindow::SetDeskbarMenu(beMenu); 118 119 BBitmap* icon = NULL; 120 size_t dataSize; 121 const void* data = AppResSet()->FindResource(B_VECTOR_ICON_TYPE, 122 R_LeafLogoBitmap, &dataSize); 123 if (data != NULL) { 124 // Scale bitmap according to font size 125 float width = std::max(63.f, ceilf(63 * be_plain_font->Size() / 12.f)); 126 // but limit by be_bold_font size 127 width = std::min(width, ceilf(63.f * be_bold_font->Size() / 12.f)); 128 float height = std::max(22.f, ceilf(22 * be_plain_font->Size() / 12.f)); 129 height = std::min(height, ceilf(22.f * be_bold_font->Size() / 12.f)); 130 icon = new BBitmap(BRect(0, 0, width - 1, height - 1), B_RGBA32); 131 if (icon->InitCheck() != B_OK 132 || BIconUtils::GetVectorIcon((const uint8*)data, dataSize, icon) 133 != B_OK) { 134 delete icon; 135 icon = NULL; 136 } 137 } 138 139 fDeskbarMenuItem = new TBarMenuTitle(0.0f, 0.0f, icon, beMenu, fBarView); 140 AddItem(fDeskbarMenuItem); 141 } 142 143 144 TBarMenuBar::~TBarMenuBar() 145 { 146 } 147 148 149 void 150 TBarMenuBar::SmartResize(float width, float height) 151 { 152 if (width == -1.0f && height == -1.0f) { 153 BRect frame = Frame(); 154 width = frame.Width(); 155 height = frame.Height(); 156 } else 157 ResizeTo(width, height); 158 159 width -= 1; 160 161 if (fSeparatorItem != NULL) 162 fDeskbarMenuItem->SetContentSize(width - kSepItemWidth, height); 163 else { 164 int32 count = CountItems(); 165 if (fDeskbarMenuItem) 166 fDeskbarMenuItem->SetContentSize(width / count, height); 167 if (fAppListMenuItem) 168 fAppListMenuItem->SetContentSize(width / count, height); 169 } 170 171 InvalidateLayout(); 172 } 173 174 175 bool 176 TBarMenuBar::AddTeamMenu() 177 { 178 if (CountItems() > 1) 179 return false; 180 181 BRect frame(Frame()); 182 183 delete fAppListMenuItem; 184 fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f, FetchTeamIcon(), 185 new TTeamMenu(fBarView), fBarView); 186 187 bool added = AddItem(fAppListMenuItem, fBarView->Left() ? 0 : 1); 188 189 if (added) 190 SmartResize(frame.Width() - 1.0f, frame.Height()); 191 else 192 SmartResize(frame.Width(), frame.Height()); 193 194 return added; 195 } 196 197 198 bool 199 TBarMenuBar::RemoveTeamMenu() 200 { 201 if (CountItems() < 2) 202 return false; 203 204 bool removed = false; 205 206 if (fAppListMenuItem != NULL && RemoveItem(fAppListMenuItem)) { 207 delete fAppListMenuItem; 208 fAppListMenuItem = NULL; 209 SmartResize(-1, -1); 210 removed = true; 211 } 212 213 return removed; 214 } 215 216 217 bool 218 TBarMenuBar::AddSeparatorItem() 219 { 220 if (CountItems() > 1) 221 return false; 222 223 BRect frame(Frame()); 224 225 delete fSeparatorItem; 226 fSeparatorItem = new TSeparatorItem(); 227 228 bool added = AddItem(fSeparatorItem); 229 230 if (added) 231 SmartResize(frame.Width() - 1.0f, frame.Height()); 232 else 233 SmartResize(frame.Width(), frame.Height()); 234 235 return added; 236 } 237 238 239 bool 240 TBarMenuBar::RemoveSeperatorItem() 241 { 242 if (CountItems() < 2) 243 return false; 244 245 bool removed = false; 246 247 if (fSeparatorItem != NULL && RemoveItem(fSeparatorItem)) { 248 delete fSeparatorItem; 249 fSeparatorItem = NULL; 250 SmartResize(-1, -1); 251 removed = true; 252 } 253 254 return removed; 255 } 256 257 258 void 259 TBarMenuBar::Draw(BRect updateRect) 260 { 261 // skip the fancy BMenuBar drawing code 262 BMenu::Draw(updateRect); 263 } 264 265 266 void 267 TBarMenuBar::DrawBackground(BRect updateRect) 268 { 269 BMenu::DrawBackground(updateRect); 270 } 271 272 273 void 274 TBarMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message) 275 { 276 // the following code parallels that in ExpandoMenuBar for DnD tracking 277 278 if (!message) { 279 // force a cleanup 280 fBarView->DragStop(true); 281 BMenuBar::MouseMoved(where, code, message); 282 return; 283 } 284 285 switch (code) { 286 case B_ENTERED_VIEW: 287 { 288 BPoint loc; 289 uint32 buttons; 290 GetMouse(&loc, &buttons); 291 if (message != NULL && buttons != 0) { 292 // attempt to start DnD tracking 293 fBarView->CacheDragData(const_cast<BMessage*>(message)); 294 MouseDown(loc); 295 } 296 break; 297 } 298 } 299 300 BMenuBar::MouseMoved(where, code, message); 301 } 302 303 304 static void 305 init_tracking_hook(BMenuItem* item, bool (*hookFunction)(BMenu*, void*), 306 void* state) 307 { 308 if (!item) 309 return; 310 311 BMenu* windowMenu = item->Submenu(); 312 if (windowMenu) { 313 // have a menu, set the tracking hook 314 windowMenu->SetTrackingHook(hookFunction, state); 315 } 316 } 317 318 319 void 320 TBarMenuBar::InitTrackingHook(bool (*hookFunction)(BMenu*, void*), 321 void* state, bool both) 322 { 323 BPoint loc; 324 uint32 buttons; 325 GetMouse(&loc, &buttons); 326 // set the hook functions for the two menus 327 // will always have the deskbar menu 328 // may have the app menu as well (mini mode) 329 if (fDeskbarMenuItem->Frame().Contains(loc) || both) 330 init_tracking_hook(fDeskbarMenuItem, hookFunction, state); 331 332 if (fAppListMenuItem && (fAppListMenuItem->Frame().Contains(loc) || both)) 333 init_tracking_hook(fAppListMenuItem, hookFunction, state); 334 } 335 336 337 const BBitmap* 338 TBarMenuBar::FetchTeamIcon() 339 { 340 const BBitmap* teamIcon = NULL; 341 342 if (fTeamIconData == NULL || fTeamIconSize == 0) { 343 // we haven't fetched vector icon data yet, fetch it 344 fTeamIconData = (const uint8*)AppResSet()->FindResource( 345 B_VECTOR_ICON_TYPE, R_TeamIconVector, &fTeamIconSize); 346 } 347 348 if (fTeamIconData != NULL && fTeamIconSize > 0) { 349 // seems valid, scale bitmap according to font size 350 float iconHeight = std::max(kTeamIconBitmapHeight, 351 ceilf(kTeamIconBitmapHeight * be_plain_font->Size() / 12.f)); 352 // but limit by be_bold_font_size 353 iconHeight = std::min(iconHeight, 354 ceilf(kTeamIconBitmapHeight * be_bold_font->Size() / 12.f)); 355 BRect iconRect = BRect(0, 0, iconHeight, iconHeight); 356 iconRect.InsetBy(-1, -1); 357 // grow icon by 1px so that it renders nicely at 12pt font size 358 BBitmap* icon = new(std::nothrow) BBitmap(iconRect, B_RGBA32); 359 if (icon != NULL && BIconUtils::GetVectorIcon(fTeamIconData, 360 fTeamIconSize, icon) == B_OK) { 361 // rasterize vector icon into a bitmap at the scaled size 362 teamIcon = icon; 363 } 364 } 365 366 return teamIcon; 367 } 368