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