xref: /haiku/src/apps/deskbar/WindowMenuItem.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
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