xref: /haiku/src/apps/deskbar/WindowMenuItem.cpp (revision a4ef4a49150f118d47324242917a596a3f8f8bd5)
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 	}
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 	menu->SetDrawingMode(B_OP_COPY);
222 
223 	if (fID >= 0) {
224 		menu->SetDrawingMode(B_OP_OVER);
225 
226 		float width = fBitmap->Bounds().Width();
227 
228 		if (width > 16)
229 			contLoc.x -= 8;
230 
231 		menu->MovePenTo(contLoc);
232 		menu->DrawBitmapAsync(fBitmap);
233 
234 		if (width > 16)
235 			contLoc.x += 8;
236 
237 		contLoc.x += kIconRect.Width() + kLabelOffset;
238 
239 		menu->SetDrawingMode(B_OP_COPY);
240 	}
241 	contLoc.y = frame.top
242 		+ ((frame.Height() - fTitleAscent - fTitleDescent) / 2) + 1.0f;
243 	menu->PopState();
244 
245 	menu->MovePenTo(contLoc);
246 	// Set the pen color so that the label is always visible.
247 	menu->SetHighColor(0, 0, 0);
248 
249 	BMenuItem::DrawContent();
250 }
251 
252 
253 status_t
254 TWindowMenuItem::Invoke(BMessage* /*message*/)
255 {
256 	if (!fDragging) {
257 		if (fID >= 0) {
258 			int32 action = (modifiers() & B_CONTROL_KEY) != 0
259 				? B_MINIMIZE_WINDOW : B_BRING_TO_FRONT;
260 
261 			bool doZoom = false;
262 			BRect zoomRect(0.0f, 0.0f, 0.0f, 0.0f);
263 			BMenuItem *item;
264 			if (!fExpanded)
265 				item = Menu()->Superitem();
266 			else
267 				item = this;
268 
269 			if (item->Menu()->Window() != NULL) {
270 				zoomRect = item->Menu()->ConvertToScreen(item->Frame());
271 				doZoom = fMini && action == B_BRING_TO_FRONT
272 					|| !fMini && action == B_MINIMIZE_WINDOW;
273 			}
274 
275 			do_window_action(fID, action, zoomRect, doZoom);
276 		}
277 	}
278 	return B_OK;
279 }
280 
281 
282 void
283 TWindowMenuItem::ExpandedItem(bool status)
284 {
285 	if (fExpanded != status) {
286 		fExpanded = status;
287 		SetLabel(fFullTitle.String());
288 	}
289 }
290 
291 
292 void
293 TWindowMenuItem::SetRequireUpdate()
294 {
295 	fRequireUpdate = true;
296 }
297 
298 
299 bool
300 TWindowMenuItem::RequiresUpdate()
301 {
302 	return fRequireUpdate;
303 }
304 
305