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 #include "WindowMenuItem.h" 37 38 #include <stdio.h> 39 40 #include <Bitmap.h> 41 #include <Debug.h> 42 43 #include "BarApp.h" 44 #include "BarMenuBar.h" 45 #include "ExpandoMenuBar.h" 46 #include "icons.h" 47 #include "ResourceSet.h" 48 #include "TeamMenu.h" 49 #include "WindowMenu.h" 50 51 52 const float kHPad = 10.0f; 53 const float kVPad = 2.0f; 54 const float kLabelOffset = 8.0f; 55 const BRect kIconRect(1.0f, 1.0f, 13.0f, 14.0f); 56 57 58 TWindowMenuItem::TWindowMenuItem(const char* title, int32 id, bool mini, 59 bool currentWorkspace, bool dragging) 60 : 61 BMenuItem(title, NULL), 62 fID(id), 63 fMini(mini), 64 fCurrentWorkSpace(currentWorkspace), 65 fDragging(dragging), 66 fExpanded(false), 67 fRequireUpdate(false), 68 fModified(false), 69 fFullTitle("") 70 { 71 Initialize(title); 72 } 73 74 75 void 76 TWindowMenuItem::Initialize(const char* title) 77 { 78 if (fMini) { 79 fBitmap = fCurrentWorkSpace 80 ? AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowHiddenIcon) 81 : AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowHiddenSwitchIcon); 82 } else { 83 fBitmap = fCurrentWorkSpace 84 ? AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowShownIcon) 85 : AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_WindowShownSwitchIcon); 86 } 87 88 BFont font(be_plain_font); 89 fTitleWidth = ceilf(font.StringWidth(title)); 90 fFullTitle = title; 91 font_height fontHeight; 92 font.GetHeight(&fontHeight); 93 fTitleAscent = ceilf(fontHeight.ascent); 94 fTitleDescent = ceilf(fontHeight.descent + fontHeight.leading); 95 } 96 97 98 void 99 TWindowMenuItem::SetTo(const char* title, int32 id, bool mini, 100 bool currentWorkspace, bool dragging) 101 { 102 fModified = fCurrentWorkSpace != currentWorkspace || fMini != mini; 103 104 fID = id; 105 fMini = mini; 106 fCurrentWorkSpace = currentWorkspace; 107 fDragging = dragging; 108 fRequireUpdate = false; 109 110 Initialize(title); 111 } 112 113 114 bool 115 TWindowMenuItem::ChangedState() 116 { 117 return fModified; 118 } 119 120 121 void 122 TWindowMenuItem::SetLabel(const char* string) 123 { 124 fFullTitle = string; 125 BString truncatedTitle = fFullTitle; 126 127 if (fExpanded && Menu()) { 128 BPoint contLoc = ContentLocation() + BPoint(kHPad, kVPad); 129 contLoc.x += kIconRect.Width() + kLabelOffset; 130 131 be_plain_font->TruncateString(&truncatedTitle, B_TRUNCATE_MIDDLE, 132 Frame().Width() - contLoc.x - 3.0f); 133 } 134 135 if (strcmp(Label(), truncatedTitle.String()) != 0) 136 BMenuItem::SetLabel(truncatedTitle.String()); 137 } 138 139 140 const char* 141 TWindowMenuItem::FullTitle() const 142 { 143 return fFullTitle.String(); 144 } 145 146 147 /*static*/ int32 148 TWindowMenuItem::InsertIndexFor(BMenu* menu, int32 startIndex, 149 TWindowMenuItem* newItem) 150 { 151 for (int32 index = startIndex;; index++) { 152 TWindowMenuItem* item 153 = dynamic_cast<TWindowMenuItem*>(menu->ItemAt(index)); 154 if (item == NULL 155 || strcasecmp(item->FullTitle(), newItem->FullTitle()) > 0) 156 return index; 157 } 158 } 159 160 161 int32 162 TWindowMenuItem::ID() 163 { 164 return fID; 165 } 166 167 168 void 169 TWindowMenuItem::GetContentSize(float* width, float* height) 170 { 171 if (width != NULL) { 172 if (!fExpanded) { 173 *width = kHPad + fTitleWidth + kHPad; 174 if (fID >= 0) 175 *width += fBitmap->Bounds().Width() + kLabelOffset; 176 } else 177 *width = Frame().Width()/* - kHPad*/; 178 } 179 180 // Note: when the item is in "expanded mode", ie embedded into 181 // the Deskbar itself, then a truncated label is used in SetLabel() 182 // The code here is ignorant of this fact, but it doesn't seem to 183 // hurt anything. 184 185 if (height != NULL) { 186 *height = (fID >= 0) ? fBitmap->Bounds().Height() : 0.0f; 187 float labelHeight = fTitleAscent + fTitleDescent; 188 *height = (labelHeight > *height) ? labelHeight : *height; 189 *height += kVPad * 2; 190 } 191 } 192 193 194 void 195 TWindowMenuItem::Draw() 196 { 197 if (!fExpanded) { 198 BMenuItem::Draw(); 199 return; 200 } 201 202 rgb_color menuColor = tint_color(Menu()->ViewColor(), 1.07); 203 BRect frame(Frame()); 204 BMenu* menu = Menu(); 205 206 menu->PushState(); 207 208 // if not selected or being tracked on, fill with gray 209 TBarView* barview = (static_cast<TBarApp*>(be_app))->BarView(); 210 if ((!IsSelected() && !menu->IsRedrawAfterSticky()) 211 || barview->Dragging() || !IsEnabled()) { 212 213 rgb_color shadow = tint_color(menuColor, 1.09); 214 menu->SetHighColor(shadow); 215 frame.right = frame.left + kHPad / 2; 216 menu->FillRect(frame); 217 218 menu->SetHighColor(menuColor); 219 frame.left = frame.right + 1; 220 frame.right = Frame().right; 221 menu->FillRect(frame); 222 } 223 224 if (IsEnabled() && IsSelected() && !menu->IsRedrawAfterSticky()) { 225 // fill 226 menu->SetHighColor(tint_color(menuColor, 227 B_HIGHLIGHT_BACKGROUND_TINT)); 228 menu->FillRect(frame); 229 } else 230 menu->SetLowColor(menuColor); 231 232 DrawContent(); 233 menu->PopState(); 234 } 235 236 237 void 238 TWindowMenuItem::DrawContent() 239 { 240 BMenu* menu = Menu(); 241 menu->PushState(); 242 243 BRect frame(Frame()); 244 BPoint contLoc = ContentLocation() + BPoint(kHPad, kVPad); 245 //if (fExpanded) 246 // contLoc.x += kHPad; 247 248 if (fID >= 0) { 249 menu->SetDrawingMode(B_OP_OVER); 250 251 float width = fBitmap->Bounds().Width(); 252 253 if (width > 16) 254 contLoc.x -= 8; 255 256 menu->MovePenTo(contLoc); 257 menu->DrawBitmapAsync(fBitmap); 258 259 if (width > 16) 260 contLoc.x += 8; 261 262 contLoc.x += kIconRect.Width() + kLabelOffset; 263 } 264 265 menu->SetDrawingMode(B_OP_COPY); 266 267 contLoc.y = frame.top 268 + ((frame.Height() - fTitleAscent - fTitleDescent) / 2) + 1.0f; 269 270 menu->MovePenTo(contLoc); 271 // Set the pen color so that the label is always visible. 272 menu->SetHighColor(0, 0, 0); 273 274 BMenuItem::DrawContent(); 275 276 menu->PopState(); 277 } 278 279 280 status_t 281 TWindowMenuItem::Invoke(BMessage* /*message*/) 282 { 283 if (!fDragging) { 284 if (fID >= 0) { 285 int32 action = (modifiers() & B_CONTROL_KEY) != 0 286 ? B_MINIMIZE_WINDOW : B_BRING_TO_FRONT; 287 288 bool doZoom = false; 289 BRect zoomRect(0.0f, 0.0f, 0.0f, 0.0f); 290 BMenuItem* item; 291 if (!fExpanded) 292 item = Menu()->Superitem(); 293 else 294 item = this; 295 296 if (item->Menu()->Window() != NULL) { 297 zoomRect = item->Menu()->ConvertToScreen(item->Frame()); 298 doZoom = (fMini && action == B_BRING_TO_FRONT) 299 || (!fMini && action == B_MINIMIZE_WINDOW); 300 } 301 302 do_window_action(fID, action, zoomRect, doZoom); 303 } 304 } 305 return B_OK; 306 } 307 308 309 void 310 TWindowMenuItem::ExpandedItem(bool status) 311 { 312 if (fExpanded != status) { 313 fExpanded = status; 314 SetLabel(fFullTitle.String()); 315 } 316 } 317 318 319 void 320 TWindowMenuItem::SetRequireUpdate() 321 { 322 fRequireUpdate = true; 323 } 324 325 326 bool 327 TWindowMenuItem::RequiresUpdate() 328 { 329 return fRequireUpdate; 330 } 331 332