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 <Debug.h> 38 #include <Menu.h> 39 #include <NodeInfo.h> 40 41 #include "IconCache.h" 42 #include "IconMenuItem.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 return BInvoker::Invoke(&clone); 198 } 199 200 201 // #pragma mark - 202 203 204 SpecialModelMenuItem::SpecialModelMenuItem(const Model *model,BMenu *menu) 205 : ModelMenuItem(model,menu) 206 { 207 } 208 209 210 void 211 SpecialModelMenuItem::DrawContent() 212 { 213 Menu()->PushState(); 214 215 BFont font; 216 Menu()->GetFont(&font); 217 font.SetFace(B_ITALIC_FACE); 218 Menu()->SetFont(&font); 219 220 _inherited::DrawContent(); 221 Menu()->PopState(); 222 } 223 224 225 // #pragma mark - 226 227 228 IconMenuItem::IconMenuItem(const char *label, BMessage *message, BBitmap *icon) 229 : PositionPassingMenuItem(label, message), 230 fDeviceIcon(icon) 231 { 232 // IconMenuItem is used in synchronously invoked menus, make sure 233 // we invoke with a timeout 234 SetTimeout(kSynchMenuInvokeTimeout); 235 } 236 237 238 IconMenuItem::IconMenuItem(const char *label, BMessage *message, 239 const BNodeInfo *nodeInfo, icon_size which) 240 : PositionPassingMenuItem(label, message), 241 fDeviceIcon(NULL) 242 { 243 if (nodeInfo) { 244 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT); 245 if (nodeInfo->GetTrackerIcon(fDeviceIcon, B_MINI_ICON)) { 246 delete fDeviceIcon; 247 fDeviceIcon = NULL; 248 } 249 } 250 251 // IconMenuItem is used in synchronously invoked menus, make sure 252 // we invoke with a timeout 253 SetTimeout(kSynchMenuInvokeTimeout); 254 } 255 256 257 IconMenuItem::IconMenuItem(const char *label, BMessage *message, 258 const char *iconType, icon_size which) 259 : PositionPassingMenuItem(label, message), 260 fDeviceIcon(NULL) 261 { 262 BMimeType mime(iconType); 263 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT); 264 265 if (mime.GetIcon(fDeviceIcon, which) != B_OK) { 266 delete fDeviceIcon; 267 fDeviceIcon = NULL; 268 } 269 270 // IconMenuItem is used in synchronously invoked menus, make sure 271 // we invoke with a timeout 272 SetTimeout(kSynchMenuInvokeTimeout); 273 } 274 275 276 IconMenuItem::IconMenuItem(BMenu *submenu, BMessage *message, 277 const char *iconType, icon_size which) 278 : PositionPassingMenuItem(submenu, message), 279 fDeviceIcon(NULL) 280 { 281 BMimeType mime(iconType); 282 fDeviceIcon = new BBitmap(BRect(0, 0, which - 1, which - 1), B_COLOR_8_BIT); 283 284 if (mime.GetIcon(fDeviceIcon, which) != B_OK) { 285 delete fDeviceIcon; 286 fDeviceIcon = NULL; 287 } 288 289 // IconMenuItem is used in synchronously invoked menus, make sure 290 // we invoke with a timeout 291 SetTimeout(kSynchMenuInvokeTimeout); 292 } 293 294 295 IconMenuItem::~IconMenuItem() 296 { 297 delete fDeviceIcon; 298 } 299 300 301 void 302 IconMenuItem::GetContentSize(float *width, float *height) 303 { 304 _inherited::GetContentSize(width, height); 305 *width += 20; 306 *height += 3; 307 } 308 309 310 void 311 IconMenuItem::DrawContent() 312 { 313 BPoint drawPoint(ContentLocation()); 314 drawPoint.x += 20; 315 Menu()->MovePenTo(drawPoint); 316 _inherited::DrawContent(); 317 318 BPoint where(ContentLocation()); 319 where.y = Frame().top; 320 321 if (fDeviceIcon) { 322 if (IsEnabled()) 323 Menu()->SetDrawingMode(B_OP_OVER); 324 else 325 Menu()->SetDrawingMode(B_OP_BLEND); 326 327 Menu()->DrawBitmapAsync(fDeviceIcon, where); 328 } 329 } 330 331