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