xref: /haiku/src/apps/deskbar/WindowMenu.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 
37 #include "WindowMenu.h"
38 
39 #include <Catalog.h>
40 #include <Locale.h>
41 #include <Window.h>
42 
43 #include "BarApp.h"
44 #include "BarView.h"
45 #include "ShowHideMenuItem.h"
46 #include "TeamMenu.h"
47 #include "TeamMenuItem.h"
48 #include "tracker_private.h"
49 #include "WindowMenuItem.h"
50 #include "WindowPrivate.h"
51 
52 
53 #undef B_TRANSLATION_CONTEXT
54 #define B_TRANSLATION_CONTEXT "WindowMenu"
55 
56 
57 //	#pragma mark - TWindowMenu
58 
59 
60 bool
61 TWindowMenu::WindowShouldBeListed(client_window_info* info)
62 {
63 	return ((info->feel == B_NORMAL_WINDOW_FEEL || info->feel == kWindowScreenFeel)
64 			// Window has the right feel
65 		&& info->show_hide_level <= 0);
66 			// Window is not hidden
67 }
68 
69 
70 TWindowMenu::TWindowMenu(const BList* team, const char* signature)
71 	:
72 	BMenu("Deskbar Team Menu"),
73 	fTeam(team),
74 	fApplicationSignature(signature),
75 	fExpanded(false),
76 	fExpandedIndex(0)
77 {
78 	SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
79 }
80 
81 
82 void
83 TWindowMenu::AttachedToWindow()
84 {
85 	SetFont(be_plain_font);
86 	RemoveItems(0, CountItems(), true);
87 	int32 miniCount = 0;
88 
89 	bool dragging = false;
90 	TBarView* barview =(static_cast<TBarApp*>(be_app))->BarView();
91 	if (barview != NULL && barview->LockLooper()) {
92 		// 'dragging' mode set in BarView::CacheDragData
93 		// invoke in MouseEnter in ExpandoMenuBar
94 		dragging = barview->Dragging();
95 		if (dragging) {
96 			// We don't want to show the menu when dragging, but it's not
97 			// possible to remove a submenu once it exists, so we simply hide it
98 			// Don't call BMenu::Hide(), it causes the menu to pop up every now
99 			// and then.
100 			Window()->Hide();
101 			// if in expando (horizontal or vertical)
102 			if (barview->ExpandoState()) {
103 				SetTrackingHook(barview->MenuTrackingHook,
104 					barview->GetTrackingHookData());
105 			}
106 			barview->DragStart();
107 		}
108 		barview->UnlockLooper();
109 	}
110 
111 	int32 parentMenuItems = 0;
112 
113 	int32 teamCount = fTeam->CountItems();
114 	for (int32 i = 0; i < teamCount; i++) {
115 		team_id theTeam = (addr_t)fTeam->ItemAt(i);
116 		int32 tokenCount = 0;
117 		int32* tokens = get_token_list(theTeam, &tokenCount);
118 
119 		for (int32 j = 0; j < tokenCount; j++) {
120 			client_window_info* wInfo = get_window_info(tokens[j]);
121 			if (wInfo == NULL)
122 				continue;
123 
124 			if (WindowShouldBeListed(wInfo)) {
125 				// Don't add new items if we're expanded. We've already done
126 				// this, they've just been moved.
127 				int32 numItems = CountItems();
128 
129 				// Find first item that sorts alphabetically after this window,
130 				// so we know where to put it
131 				for (int32 addIndex = 0; addIndex < numItems; addIndex++) {
132 					TWindowMenuItem* item
133 						= static_cast<TWindowMenuItem*>(ItemAt(addIndex));
134 					if (item != NULL
135 						&& strcasecmp(item->Label(), wInfo->name) > 0) {
136 						break;
137 					}
138 				}
139 
140 				if (!fExpanded) {
141 					TWindowMenuItem* item = new TWindowMenuItem(wInfo->name,
142 						wInfo->server_token, wInfo->is_mini,
143 						((1 << current_workspace()) & wInfo->workspaces) != 0,
144 						dragging);
145 
146 					// disable app's window dropping for now
147 					if (dragging)
148 						item->SetEnabled(false);
149 
150 					AddItem(item,
151 						TWindowMenuItem::InsertIndexFor(this, 0, item));
152 				} else {
153 					TTeamMenuItem* parentItem
154 						= static_cast<TTeamMenuItem*>(Superitem());
155 					if (parentItem->ExpandedWindowItem(wInfo->server_token)) {
156 						TWindowMenuItem* item = parentItem->ExpandedWindowItem(
157 							wInfo->server_token);
158 						if (item == NULL)
159 							continue;
160 
161 						item->SetTo(wInfo->name, wInfo->server_token,
162 							wInfo->is_mini,
163 							((1 << current_workspace()) & wInfo->workspaces)
164 								!= 0, dragging);
165 						parentMenuItems++;
166 					}
167 				}
168 
169 				if (wInfo->is_mini)
170 					miniCount++;
171 			}
172 			free(wInfo);
173 		}
174 		free(tokens);
175 	}
176 
177 	int32 itemCount = CountItems() + parentMenuItems;
178 	if (itemCount < 1) {
179 		TWindowMenuItem* noWindowsItem
180 			= new TWindowMenuItem(B_TRANSLATE("No windows"), -1, false, false);
181 
182 		noWindowsItem->SetEnabled(false);
183 		AddItem(noWindowsItem);
184 
185 		// Add a 'Quit application' item if no windows are open
186 		// unless the application is Tracker
187 		if (fApplicationSignature.ICompare(kTrackerSignature) != 0) {
188 			AddSeparatorItem();
189 			AddItem(new TShowHideMenuItem(B_TRANSLATE("Quit application"),
190 				fTeam, B_QUIT_REQUESTED));
191 		}
192 	} else {
193 		// Only add the window controls to the menu if we are not in drag mode
194 		if (!dragging) {
195 			TShowHideMenuItem* hide
196 				= new TShowHideMenuItem(B_TRANSLATE("Hide all"), fTeam,
197 					B_MINIMIZE_WINDOW);
198 			TShowHideMenuItem* show
199 				= new TShowHideMenuItem(B_TRANSLATE("Show all"), fTeam,
200 					B_BRING_TO_FRONT);
201 			TShowHideMenuItem* close
202 				= new TShowHideMenuItem(B_TRANSLATE("Close all"), fTeam,
203 					B_QUIT_REQUESTED);
204 
205 			if (miniCount == itemCount)
206 				hide->SetEnabled(false);
207 			else if (miniCount == 0)
208 				show->SetEnabled(false);
209 
210 			if (!parentMenuItems)
211 				AddSeparatorItem();
212 
213 			AddItem(hide);
214 			AddItem(show);
215 			AddItem(close);
216 		}
217 	}
218 
219 	BMenu::AttachedToWindow();
220 }
221 
222 
223 void
224 TWindowMenu::DetachedFromWindow()
225 {
226 	// in expando mode the teammenu will not call DragStop, thus, it needs to
227 	// be called from here
228 	TBarView* barview = (dynamic_cast<TBarApp*>(be_app))->BarView();
229 	if (barview && barview->ExpandoState() && barview->Dragging()
230 		&& barview->LockLooper()) {
231 		// We changed the show level in AttachedToWindow(). Undo it.
232 		Window()->Show();
233 		barview->DragStop();
234 		barview->UnlockLooper();
235 	}
236 
237 	BMenu::DetachedFromWindow();
238 }
239 
240 
241 BPoint
242 TWindowMenu::ScreenLocation()
243 {
244 	return BMenu::ScreenLocation();
245 }
246 
247 
248 void
249 TWindowMenu::SetExpanded(bool status, int lastIndex)
250 {
251 	fExpanded = status;
252 	fExpandedIndex = lastIndex;
253 }
254