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 if (fSeparatorItem != NULL) 160 fDeskbarMenuItem->SetContentSize(width - kSepItemWidth, height); 161 else { 162 int32 count = CountItems(); 163 if (fDeskbarMenuItem != NULL) 164 fDeskbarMenuItem->SetContentSize(floorf(width / count), height); 165 if (fAppListMenuItem != NULL) 166 fAppListMenuItem->SetContentSize(floorf(width / count), height); 167 } 168 169 InvalidateLayout(); 170 } 171 172 173 bool 174 TBarMenuBar::AddTeamMenu() 175 { 176 if (CountItems() > 1) 177 return false; 178 179 BRect frame(Frame()); 180 181 delete fAppListMenuItem; 182 fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f, FetchTeamIcon(), 183 new TTeamMenu(fBarView), fBarView); 184 185 bool added = AddItem(fAppListMenuItem, fBarView->Left() ? 0 : 1); 186 187 if (added) 188 SmartResize(frame.Width() - 1.0f, frame.Height()); 189 else 190 SmartResize(frame.Width(), frame.Height()); 191 192 return added; 193 } 194 195 196 bool 197 TBarMenuBar::RemoveTeamMenu() 198 { 199 if (CountItems() < 2) 200 return false; 201 202 bool removed = false; 203 204 if (fAppListMenuItem != NULL && RemoveItem(fAppListMenuItem)) { 205 delete fAppListMenuItem; 206 fAppListMenuItem = NULL; 207 SmartResize(-1, -1); 208 removed = true; 209 } 210 211 return removed; 212 } 213 214 215 bool 216 TBarMenuBar::AddSeparatorItem() 217 { 218 if (CountItems() > 1) 219 return false; 220 221 BRect frame(Frame()); 222 223 delete fSeparatorItem; 224 fSeparatorItem = new TSeparatorItem(); 225 226 bool added = AddItem(fSeparatorItem); 227 228 if (added) 229 SmartResize(frame.Width() - 1.0f, frame.Height()); 230 else 231 SmartResize(frame.Width(), frame.Height()); 232 233 return added; 234 } 235 236 237 bool 238 TBarMenuBar::RemoveSeperatorItem() 239 { 240 if (CountItems() < 2) 241 return false; 242 243 bool removed = false; 244 245 if (fSeparatorItem != NULL && RemoveItem(fSeparatorItem)) { 246 delete fSeparatorItem; 247 fSeparatorItem = NULL; 248 SmartResize(-1, -1); 249 removed = true; 250 } 251 252 return removed; 253 } 254 255 256 void 257 TBarMenuBar::Draw(BRect updateRect) 258 { 259 // skip the fancy BMenuBar drawing code 260 BMenu::Draw(updateRect); 261 } 262 263 264 void 265 TBarMenuBar::DrawBackground(BRect updateRect) 266 { 267 BMenu::DrawBackground(updateRect); 268 } 269 270 271 void 272 TBarMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message) 273 { 274 // the following code parallels that in ExpandoMenuBar for DnD tracking 275 276 if (!message) { 277 // force a cleanup 278 fBarView->DragStop(true); 279 BMenuBar::MouseMoved(where, code, message); 280 return; 281 } 282 283 switch (code) { 284 case B_ENTERED_VIEW: 285 { 286 BPoint loc; 287 uint32 buttons; 288 GetMouse(&loc, &buttons); 289 if (message != NULL && buttons != 0) { 290 // attempt to start DnD tracking 291 fBarView->CacheDragData(const_cast<BMessage*>(message)); 292 MouseDown(loc); 293 } 294 break; 295 } 296 } 297 298 BMenuBar::MouseMoved(where, code, message); 299 } 300 301 302 static void 303 init_tracking_hook(BMenuItem* item, bool (*hookFunction)(BMenu*, void*), 304 void* state) 305 { 306 if (!item) 307 return; 308 309 BMenu* windowMenu = item->Submenu(); 310 if (windowMenu) { 311 // have a menu, set the tracking hook 312 windowMenu->SetTrackingHook(hookFunction, state); 313 } 314 } 315 316 317 void 318 TBarMenuBar::InitTrackingHook(bool (*hookFunction)(BMenu*, void*), 319 void* state, bool both) 320 { 321 BPoint loc; 322 uint32 buttons; 323 GetMouse(&loc, &buttons); 324 // set the hook functions for the two menus 325 // will always have the deskbar menu 326 // may have the app menu as well (mini mode) 327 if (fDeskbarMenuItem->Frame().Contains(loc) || both) 328 init_tracking_hook(fDeskbarMenuItem, hookFunction, state); 329 330 if (fAppListMenuItem && (fAppListMenuItem->Frame().Contains(loc) || both)) 331 init_tracking_hook(fAppListMenuItem, hookFunction, state); 332 } 333 334 335 const BBitmap* 336 TBarMenuBar::FetchTeamIcon() 337 { 338 const BBitmap* teamIcon = NULL; 339 340 if (fTeamIconData == NULL || fTeamIconSize == 0) { 341 // we haven't fetched vector icon data yet, fetch it 342 fTeamIconData = (const uint8*)AppResSet()->FindResource( 343 B_VECTOR_ICON_TYPE, R_TeamIconVector, &fTeamIconSize); 344 } 345 346 if (fTeamIconData != NULL && fTeamIconSize > 0) { 347 // seems valid, scale bitmap according to font size 348 float iconHeight = std::max(kTeamIconBitmapHeight, 349 ceilf(kTeamIconBitmapHeight * be_plain_font->Size() / 12.f)); 350 // but limit by be_bold_font_size 351 iconHeight = std::min(iconHeight, 352 ceilf(kTeamIconBitmapHeight * be_bold_font->Size() / 12.f)); 353 BRect iconRect = BRect(0, 0, iconHeight, iconHeight); 354 iconRect.InsetBy(-1, -1); 355 // grow icon by 1px so that it renders nicely at 12pt font size 356 BBitmap* icon = new(std::nothrow) BBitmap(iconRect, B_RGBA32); 357 if (icon != NULL && BIconUtils::GetVectorIcon(fTeamIconData, 358 fTeamIconSize, icon) == B_OK) { 359 // rasterize vector icon into a bitmap at the scaled size 360 teamIcon = icon; 361 } 362 } 363 364 return teamIcon; 365 } 366