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 trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 // menu items with small icons. 36 37 #include "IconCache.h" 38 #include "IconMenuItem.h" 39 40 #include <Debug.h> 41 #include <Menu.h> 42 #include <NodeInfo.h> 43 44 45 ModelMenuItem::ModelMenuItem(const Model *model, const char *title, 46 BMessage *message, char shortcut, uint32 modifiers, 47 bool drawText, bool extraPad) 48 : BMenuItem(title, message, shortcut, modifiers), 49 fModel(*model), 50 fHeightDelta(0), 51 fDrawText(drawText), 52 fExtraPad(extraPad) 53 { 54 ThrowOnInitCheckError(&fModel); 55 // The 'fExtraPad' field is used to when this menu item is added to 56 // a menubar instead of a menu. Menus and MenuBars space out items 57 // differently (more space around items in a menu). This class wants 58 // to be able to space item the same, no matter where they are. The 59 // fExtraPad field allows for that. 60 61 if (model->IsRoot()) 62 SetLabel(model->Name()); 63 64 // ModelMenuItem is used in synchronously invoked menus, make sure 65 // we invoke with a timeout 66 SetTimeout(kSynchMenuInvokeTimeout); 67 } 68 69 70 ModelMenuItem::ModelMenuItem(const Model *model, BMenu *menu, bool drawText, 71 bool extraPad) 72 : BMenuItem(menu), 73 fModel(*model), 74 fHeightDelta(0), 75 fDrawText(drawText), 76 fExtraPad(extraPad) 77 { 78 ThrowOnInitCheckError(&fModel); 79 // ModelMenuItem is used in synchronously invoked menus, make sure 80 // we invoke with a timeout 81 SetTimeout(kSynchMenuInvokeTimeout); 82 } 83 84 85 ModelMenuItem::~ModelMenuItem() 86 { 87 } 88 89 90 status_t 91 ModelMenuItem::SetEntry(const BEntry *entry) 92 { 93 return fModel.SetTo(entry); 94 } 95 96 97 void 98 ModelMenuItem::DrawContent() 99 { 100 if (fDrawText) { 101 BPoint drawPoint(ContentLocation()); 102 drawPoint.x += 20 + (fExtraPad ? 6 : 0); 103 if (fHeightDelta > 0) 104 drawPoint.y += ceil(fHeightDelta / 2); 105 Menu()->MovePenTo(drawPoint); 106 _inherited::DrawContent(); 107 } 108 DrawIcon(); 109 } 110 111 112 void 113 ModelMenuItem::Highlight(bool hilited) 114 { 115 _inherited::Highlight(hilited); 116 DrawIcon(); 117 } 118 119 120 static void 121 DimmedIconBlitter(BView *view, BPoint where, BBitmap *bitmap, void *) 122 { 123 view->SetDrawingMode(B_OP_BLEND); 124 view->DrawBitmap(bitmap, where); 125 view->SetDrawingMode(B_OP_OVER); 126 } 127 128 129 void 130 ModelMenuItem::DrawIcon() 131 { 132 Menu()->PushState(); 133 134 BPoint where(ContentLocation()); 135 // center icon with text. 136 137 float deltaHeight = fHeightDelta < 0 ? -fHeightDelta : 0; 138 where.y += ceil( deltaHeight/2 ); 139 140 if (fExtraPad) 141 where.x += 6; 142 143 Menu()->SetDrawingMode(B_OP_OVER); 144 Menu()->SetLowColor(B_TRANSPARENT_32_BIT); 145 146 // draw small icon, synchronously 147 if (IsEnabled()) 148 IconCache::sIconCache->Draw(fModel.ResolveIfLink(), Menu(), where, 149 kNormalIcon, B_MINI_ICON); 150 else { 151 // dimmed, for now use a special blitter; icon cache should 152 // know how to blit one eventually 153 IconCache::sIconCache->SyncDraw(fModel.ResolveIfLink(), Menu(), where, 154 kNormalIcon, B_MINI_ICON, DimmedIconBlitter); 155 } 156 157 Menu()->PopState(); 158 } 159 160 161 void 162 ModelMenuItem::GetContentSize(float *width, float *height) 163 { 164 _inherited::GetContentSize(width, height); 165 fHeightDelta = 16 - *height; 166 if (*height < 16) 167 *height = 16; 168 *width = *width + 20 + (fExtraPad ? 18 : 0); 169 } 170 171 172 status_t 173 ModelMenuItem::Invoke(BMessage *message) 174 { 175 if (!Menu()) 176 return B_ERROR; 177 178 if (!IsEnabled()) 179 return B_ERROR; 180 181 if (!message) 182 message = Message(); 183 184 if (!message) 185 return B_BAD_VALUE; 186 187 BMessage clone(*message); 188 clone.AddInt32("index", Menu()->IndexOf(this)); 189 clone.AddInt64("when", system_time()); 190 clone.AddPointer("source", this); 191 192 if ((modifiers() & B_OPTION_KEY) == 0) { 193 // if option not held, remove refs to close to prevent closing 194 // parent window 195 clone.RemoveData("nodeRefsToClose"); 196 } 197 198 return BInvoker::Invoke(&clone); 199 } 200 201 202 // #pragma mark - 203 204 205 SpecialModelMenuItem::SpecialModelMenuItem(const Model *model,BMenu *menu) 206 : ModelMenuItem(model,menu) 207 { 208 } 209 210 211 void 212 SpecialModelMenuItem::DrawContent() 213 { 214 Menu()->PushState(); 215 216 BFont font; 217 Menu()->GetFont(&font); 218 font.SetFace(B_ITALIC_FACE); 219 Menu()->SetFont(&font); 220 221 _inherited::DrawContent(); 222 Menu()->PopState(); 223 } 224 225 226 // #pragma mark - 227 228 229 IconMenuItem::IconMenuItem(const char *label, BMessage *message, BBitmap *icon) 230 : PositionPassingMenuItem(label, message), 231 fDeviceIcon(icon) 232 { 233 // IconMenuItem is used in synchronously invoked menus, make sure 234 // we invoke with a timeout 235 SetTimeout(kSynchMenuInvokeTimeout); 236 } 237 238 239 IconMenuItem::IconMenuItem(const char *label, BMessage *message, 240 const BNodeInfo *nodeInfo, icon_size which) 241 : PositionPassingMenuItem(label, message), 242 fDeviceIcon(NULL) 243 { 244 if (nodeInfo) { 245 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_CMAP8); 246 if (nodeInfo->GetTrackerIcon(fDeviceIcon, B_MINI_ICON)) { 247 delete fDeviceIcon; 248 fDeviceIcon = NULL; 249 } 250 } 251 252 // IconMenuItem is used in synchronously invoked menus, make sure 253 // we invoke with a timeout 254 SetTimeout(kSynchMenuInvokeTimeout); 255 } 256 257 258 IconMenuItem::IconMenuItem(const char *label, BMessage *message, 259 const char *iconType, icon_size which) 260 : PositionPassingMenuItem(label, message), 261 fDeviceIcon(NULL) 262 { 263 BMimeType mime(iconType); 264 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_CMAP8); 265 266 if (mime.GetIcon(fDeviceIcon, which) != B_OK) { 267 delete fDeviceIcon; 268 fDeviceIcon = NULL; 269 } 270 271 // IconMenuItem is used in synchronously invoked menus, make sure 272 // we invoke with a timeout 273 SetTimeout(kSynchMenuInvokeTimeout); 274 } 275 276 277 IconMenuItem::IconMenuItem(BMenu *submenu, BMessage *message, 278 const char *iconType, icon_size which) 279 : PositionPassingMenuItem(submenu, message), 280 fDeviceIcon(NULL) 281 { 282 BMimeType mime(iconType); 283 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_CMAP8); 284 285 if (mime.GetIcon(fDeviceIcon, which) != B_OK) { 286 delete fDeviceIcon; 287 fDeviceIcon = NULL; 288 } 289 290 // IconMenuItem is used in synchronously invoked menus, make sure 291 // we invoke with a timeout 292 SetTimeout(kSynchMenuInvokeTimeout); 293 } 294 295 296 IconMenuItem::~IconMenuItem() 297 { 298 delete fDeviceIcon; 299 } 300 301 302 void 303 IconMenuItem::GetContentSize(float *width, float *height) 304 { 305 _inherited::GetContentSize(width, height); 306 *width += 20; 307 *height += 3; 308 } 309 310 311 void 312 IconMenuItem::DrawContent() 313 { 314 BPoint drawPoint(ContentLocation()); 315 drawPoint.x += 20; 316 Menu()->MovePenTo(drawPoint); 317 _inherited::DrawContent(); 318 319 BPoint where(ContentLocation()); 320 where.y = Frame().top; 321 322 if (fDeviceIcon) { 323 if (IsEnabled()) 324 Menu()->SetDrawingMode(B_OP_OVER); 325 else 326 Menu()->SetDrawingMode(B_OP_BLEND); 327 328 Menu()->DrawBitmapAsync(fDeviceIcon, where); 329 } 330 } 331 332