1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
30trademarks of Be Incorporated in the United States and other countries. Other
31brand product names are registered trademarks or trademarks of their respective
32holders.
33All 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
60bool
61TWindowMenu::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
70TWindowMenu::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
82void
83TWindowMenu::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
223void
224TWindowMenu::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
241BPoint
242TWindowMenu::ScreenLocation()
243{
244	return BMenu::ScreenLocation();
245}
246
247
248void
249TWindowMenu::SetExpanded(bool status, int lastIndex)
250{
251	fExpanded = status;
252	fExpandedIndex = lastIndex;
253}
254