btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / deskbar / DeskbarMenu.cpp
blobac4a28808588df7db70a25ba1364be68059422b4
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
37 #include "DeskbarMenu.h"
39 #include <Debug.h>
40 #include <Bitmap.h>
41 #include <Catalog.h>
42 #include <Dragger.h>
43 #include <Locale.h>
44 #include <Menu.h>
45 #include <MenuItem.h>
46 #include <Roster.h>
48 #include "BarApp.h"
49 #include "BarView.h"
50 #include "DeskbarUtils.h"
51 #include "IconMenuItem.h"
52 #include "MountMenu.h"
53 #include "RecentItems.h"
54 #include "StatusView.h"
56 #include "tracker_private.h"
58 #undef B_TRANSLATION_CONTEXT
59 #define B_TRANSLATION_CONTEXT "DeskbarMenu"
61 #define ROSTER_SIG "application/x-vnd.Be-ROST"
63 #ifdef MOUNT_MENU_IN_DESKBAR
64 class DeskbarMountMenu : public BPrivate::MountMenu {
65 public:
66 DeskbarMountMenu(const char* name);
67 virtual bool AddDynamicItem(add_state s);
69 #endif // MOUNT_MENU_IN_DESKBAR
71 //#define SHOW_RECENT_FIND_ITEMS
73 namespace BPrivate {
74 BMenu* TrackerBuildRecentFindItemsMenu(const char*);
77 using namespace BPrivate;
80 // #pragma mark - TDeskbarMenu
83 TDeskbarMenu::TDeskbarMenu(TBarView* barView)
85 BNavMenu("DeskbarMenu", B_REFS_RECEIVED, DefaultTarget()),
86 fAddState(kStart),
87 fBarView(barView)
92 void
93 TDeskbarMenu::AttachedToWindow()
95 if (fBarView != NULL && fBarView->LockLooper()) {
96 if (fBarView->Dragging()) {
97 SetTypesList(fBarView->CachedTypesList());
98 SetTarget(BMessenger(fBarView));
99 SetTrackingHookDeep(this, fBarView->MenuTrackingHook,
100 fBarView->GetTrackingHookData());
101 fBarView->DragStart();
102 } else {
103 SetTypesList(NULL);
104 SetTarget(DefaultTarget());
105 SetTrackingHookDeep(this, NULL, NULL);
108 fBarView->UnlockLooper();
111 BNavMenu::AttachedToWindow();
115 void
116 TDeskbarMenu::DetachedFromWindow()
118 if (fBarView != NULL) {
119 BLooper* looper = fBarView->Looper();
120 if (looper != NULL && looper->Lock()) {
121 fBarView->DragStop();
122 looper->Unlock();
126 // don't call BNavMenu::DetachedFromWindow
127 // it sets the TypesList to NULL
128 BMenu::DetachedFromWindow();
132 bool
133 TDeskbarMenu::StartBuildingItemList()
135 RemoveItems(0, CountItems(), true);
136 fAddState = kStart;
137 return BNavMenu::StartBuildingItemList();
141 void
142 TDeskbarMenu::DoneBuildingItemList()
144 if (fItemList->CountItems() <= 0) {
145 BMenuItem* item
146 = new BMenuItem(B_TRANSLATE("<Deskbar folder is empty>"), 0);
147 item->SetEnabled(false);
148 AddItem(item);
149 } else
150 BNavMenu::DoneBuildingItemList();
154 bool
155 TDeskbarMenu::AddNextItem()
157 if (fAddState == kStart)
158 return AddStandardDeskbarMenuItems();
160 TrackingHookData* data = fBarView->GetTrackingHookData();
161 if (fAddState == kAddingRecents) {
162 static const char* recentTitle[] = {
163 B_TRANSLATE_MARK("Recent documents"),
164 B_TRANSLATE_MARK("Recent folders"),
165 B_TRANSLATE_MARK("Recent applications")};
166 const int recentType[] = {kRecentDocuments, kRecentFolders,
167 kRecentApplications};
168 const int recentTypes = 3;
169 TRecentsMenu* recentItem[recentTypes];
171 bool enabled = false;
173 for (int i = 0; i < recentTypes; i++) {
174 recentItem[i]
175 = new TRecentsMenu(B_TRANSLATE_NOCOLLECT(recentTitle[i]),
176 fBarView, recentType[i]);
178 if (recentItem[i])
179 enabled |= recentItem[i]->RecentsEnabled();
181 if (enabled) {
182 AddSeparatorItem();
184 for (int i = 0; i < recentTypes; i++) {
185 if (!recentItem[i])
186 continue;
188 if (recentItem[i]->RecentsEnabled()) {
189 recentItem[i]->SetTypesList(TypesList());
190 recentItem[i]->SetTarget(Target());
191 AddItem(recentItem[i]);
194 if (data && fBarView && fBarView->Dragging()) {
195 recentItem[i]->InitTrackingHook(data->fTrackingHook,
196 &data->fTarget, data->fDragMessage);
199 } else {
200 for (int i = 0; i < recentTypes; i++)
201 delete recentItem[i];
204 AddSeparatorItem();
205 fAddState = kAddingDeskbarMenu;
206 return true;
209 if (fAddState == kAddingDeskbarMenu) {
210 // keep reentering and adding items
211 // until this returns false
212 bool done = BNavMenu::AddNextItem();
213 BMenuItem* item = ItemAt(CountItems() - 1);
214 if (item) {
215 BNavMenu* menu = dynamic_cast<BNavMenu*>(item->Menu());
216 if (menu) {
217 if (data && fBarView->Dragging()) {
218 menu->InitTrackingHook(data->fTrackingHook,
219 &data->fTarget, data->fDragMessage);
220 } else
221 menu->InitTrackingHook(0, NULL, NULL);
225 if (!done)
226 fAddState = kDone;
227 return done;
230 return false;
234 bool
235 TDeskbarMenu::AddStandardDeskbarMenuItems()
237 bool dragging = false;
238 if (fBarView)
239 dragging = fBarView->Dragging();
241 BMenuItem* item;
243 // One of them is used if HAIKU_DISTRO_COMPATIBILITY_OFFICIAL, and the other if
244 // not. However, we want both of them to end up in the catalog, so we have to
245 // make them visible to collectcatkeys in either case.
246 B_TRANSLATE_MARK_VOID("About Haiku")
247 B_TRANSLATE_MARK_VOID("About this system")
249 item = new BMenuItem(
250 #ifdef HAIKU_DISTRO_COMPATIBILITY_OFFICIAL
251 B_TRANSLATE_NOCOLLECT("About Haiku")
252 #else
253 B_TRANSLATE_NOCOLLECT("About this system")
254 #endif
255 , new BMessage(kShowSplash));
256 item->SetEnabled(!dragging);
257 AddItem(item);
259 static const char* kFindMenuItemStr
260 = B_TRANSLATE_MARK("Find" B_UTF8_ELLIPSIS);
262 #ifdef SHOW_RECENT_FIND_ITEMS
263 item = new BMenuItem(
264 TrackerBuildRecentFindItemsMenu(kFindMenuItemStr),
265 new BMessage(kFindButton));
266 #else
267 item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kFindMenuItemStr),
268 new BMessage(kFindButton));
269 #endif
270 item->SetEnabled(!dragging);
271 AddItem(item);
273 item = new BMenuItem(B_TRANSLATE("Show replicants"),
274 new BMessage(kToggleDraggers));
275 item->SetEnabled(!dragging);
276 item->SetMarked(BDragger::AreDraggersDrawn());
277 AddItem(item);
279 static const char* kMountMenuStr = B_TRANSLATE_MARK("Mount");
281 #ifdef MOUNT_MENU_IN_DESKBAR
282 DeskbarMountMenu* mountMenu = new DeskbarMountMenu(
283 B_TRANSLATE_NOCOLLECT(kMountMenuStr));
284 mountMenu->SetEnabled(!dragging);
285 AddItem(mountMenu);
286 #endif
288 item = new BMenuItem(B_TRANSLATE("Deskbar preferences" B_UTF8_ELLIPSIS),
289 new BMessage(kConfigShow));
290 item->SetTarget(be_app);
291 AddItem(item);
293 AddSeparatorItem();
295 BMenu* shutdownMenu = new BMenu(B_TRANSLATE("Shutdown" B_UTF8_ELLIPSIS));
297 item = new BMenuItem(B_TRANSLATE("Restart system"),
298 new BMessage(kRebootSystem));
299 item->SetEnabled(!dragging);
300 shutdownMenu->AddItem(item);
302 B_TRANSLATE_MARK_VOID("Suspend");
304 #ifdef APM_SUPPORT
305 if (_kapm_control_(APM_CHECK_ENABLED) == B_OK) {
306 item = new BMenuItem(B_TRANSLATE_NOCOLLECT("Suspend"),
307 new BMessage(kSuspendSystem));
308 item->SetEnabled(!dragging);
309 shutdownMenu->AddItem(item);
311 #endif
313 item = new BMenuItem(B_TRANSLATE("Power off"),
314 new BMessage(kShutdownSystem));
315 item->SetEnabled(!dragging);
316 shutdownMenu->AddItem(item);
317 shutdownMenu->SetFont(be_plain_font);
319 shutdownMenu->SetTargetForItems(be_app);
320 BMessage* message = new BMessage(kShutdownSystem);
321 message->AddBool("confirm", true);
322 AddItem(new BMenuItem(shutdownMenu, message));
324 fAddState = kAddingRecents;
326 return true;
330 void
331 TDeskbarMenu::ClearMenuBuildingState()
333 fAddState = kDone;
334 fMenuBuilt = false;
335 // force the menu to get rebuilt each time
336 BNavMenu::ClearMenuBuildingState();
340 void
341 TDeskbarMenu::ResetTargets()
343 // This method does not recurse into submenus
344 // and does not affect menu items in submenus.
345 // (e.g. "Restart System" and "Power Off")
347 BNavMenu::ResetTargets();
349 // if we are dragging, set the target to whatever was set
350 // else set it to the default (Tracker)
351 if (!fBarView->Dragging())
352 SetTarget(DefaultTarget());
354 // now set the target for the menuitems to the currently
355 // set target, which may or may not be tracker
356 SetTargetForItems(Target());
358 for (int32 i = 0; ; i++) {
359 BMenuItem* item = ItemAt(i);
360 if (item == NULL)
361 break;
363 if (item->Message()) {
364 switch (item->Message()->what) {
365 case kFindButton:
366 item->SetTarget(BMessenger(kTrackerSignature));
367 break;
369 case kShowSplash:
370 case kToggleDraggers:
371 case kConfigShow:
372 case kConfigQuit:
373 case kAlwaysTop:
374 case kExpandNewTeams:
375 case kHideLabels:
376 case kResizeTeamIcons:
377 case kSortRunningApps:
378 case kTrackerFirst:
379 case kRebootSystem:
380 case kSuspendSystem:
381 case kShutdownSystem:
382 case kRealignReplicants:
383 case kShowHideTime:
384 case kShowSeconds:
385 case kShowDayOfWeek:
386 case kShowTimeZone:
387 case kGetClockSettings:
388 item->SetTarget(be_app);
389 break;
396 BPoint
397 TDeskbarMenu::ScreenLocation()
399 bool vertical = fBarView->Vertical();
400 int32 expando = (fBarView->State() == kExpandoState);
401 BPoint point;
403 BRect rect = Supermenu()->Bounds();
404 Supermenu()->ConvertToScreen(&rect);
406 if (expando && vertical && fBarView->Left()) {
407 PRINT(("Left\n"));
408 point = rect.RightTop() + BPoint(0, 3);
409 } else if (expando && vertical && !fBarView->Left()) {
410 PRINT(("Right\n"));
411 point = rect.LeftTop() - BPoint(Bounds().Width(), 0) + BPoint(0, 3);
412 } else
413 point = BMenu::ScreenLocation();
415 return point;
419 /*static*/
420 BMessenger
421 TDeskbarMenu::DefaultTarget()
423 // if Tracker is not available we target the BarApp
424 BMessenger target(kTrackerSignature);
425 if (target.IsValid())
426 return target;
428 return BMessenger(be_app);
432 // #pragma mark -
435 TRecentsMenu::TRecentsMenu(const char* name, TBarView* bar, int32 which,
436 const char* signature, entry_ref* appRef)
437 : BNavMenu(name, B_REFS_RECEIVED, TDeskbarMenu::DefaultTarget()),
438 fWhich(which),
439 fAppRef(NULL),
440 fSignature(NULL),
441 fRecentsCount(0),
442 fRecentsEnabled(false),
443 fItemIndex(0),
444 fBarView(bar)
446 TBarApp* app = dynamic_cast<TBarApp*>(be_app);
447 if (app == NULL)
448 return;
450 switch (which) {
451 case kRecentDocuments:
452 fRecentsCount = app->Settings()->recentDocsCount;
453 fRecentsEnabled = app->Settings()->recentDocsEnabled;
454 break;
455 case kRecentApplications:
456 fRecentsCount = app->Settings()->recentAppsCount;
457 fRecentsEnabled = app->Settings()->recentAppsEnabled;
458 break;
459 case kRecentAppDocuments:
460 fRecentsCount = app->Settings()->recentDocsCount;
461 fRecentsEnabled = app->Settings()->recentDocsEnabled;
462 if (signature != NULL)
463 fSignature = strdup(signature);
464 if (appRef != NULL)
465 fAppRef = new entry_ref(*appRef);
466 break;
467 case kRecentFolders:
468 fRecentsCount = app->Settings()->recentFoldersCount;
469 fRecentsEnabled = app->Settings()->recentFoldersEnabled;
470 break;
475 TRecentsMenu::~TRecentsMenu()
477 delete fAppRef;
478 free(fSignature);
482 void
483 TRecentsMenu::DetachedFromWindow()
485 // BNavMenu::DetachedFromWindow sets the TypesList to NULL
486 BMenu::DetachedFromWindow();
490 bool
491 TRecentsMenu::StartBuildingItemList()
493 RemoveItems(0, CountItems(), true);
495 // !! note: don't call inherited from here
496 // the navref is not set for this menu
497 // but it still needs to be a draggable navmenu
498 // simply return true so that AddNextItem is called
500 // return BNavMenu::StartBuildingItemList();
501 return true;
505 bool
506 TRecentsMenu::AddNextItem()
508 if (fRecentsCount > 0 && fRecentsEnabled && AddRecents(fRecentsCount))
509 return true;
511 fItemIndex = 0;
512 return false;
516 bool
517 TRecentsMenu::AddRecents(int32 count)
519 if (fItemIndex == 0) {
520 fRecentList.MakeEmpty();
521 BRoster roster;
523 switch (fWhich) {
524 case kRecentDocuments:
525 roster.GetRecentDocuments(&fRecentList, count);
526 break;
527 case kRecentApplications:
528 roster.GetRecentApps(&fRecentList, count);
529 break;
530 case kRecentAppDocuments:
531 roster.GetRecentDocuments(&fRecentList, count, NULL,
532 fSignature);
533 break;
534 case kRecentFolders:
535 roster.GetRecentFolders(&fRecentList, count);
536 break;
537 default:
538 return false;
542 for (;;) {
543 entry_ref ref;
544 if (fRecentList.FindRef("refs", fItemIndex++, &ref) != B_OK)
545 break;
547 if (ref.name && strlen(ref.name) > 0) {
548 Model model(&ref, true);
550 if (fWhich != kRecentApplications) {
551 BMessage* message = new BMessage(B_REFS_RECEIVED);
552 if (fWhich == kRecentAppDocuments) {
553 // add application as handler
554 message->AddRef("handler", fAppRef);
557 ModelMenuItem* item = BNavMenu::NewModelItem(&model,
558 message, Target(), false, NULL, TypesList());
560 if (item)
561 AddItem(item);
562 } else {
563 // The application items expand to a list of recent documents
564 // for that application - so they must be handled extra
565 BFile file(&ref, B_READ_ONLY);
566 char signature[B_MIME_TYPE_LENGTH];
568 BAppFileInfo appInfo(&file);
569 if (appInfo.InitCheck() != B_OK
570 || appInfo.GetSignature(signature) != B_OK)
571 continue;
573 ModelMenuItem* item = NULL;
574 BMessage doc;
575 be_roster->GetRecentDocuments(&doc, 1, NULL, signature);
576 // ToDo: check if the documents do exist at all to
577 // avoid the creation of the submenu.
579 if (doc.CountNames(B_REF_TYPE) > 0) {
580 // create recents menu that will contain the recent docs of
581 // this app
582 TRecentsMenu* docs = new TRecentsMenu(model.Name(),
583 fBarView, kRecentAppDocuments, signature, &ref);
584 docs->SetTypesList(TypesList());
585 docs->SetTarget(Target());
587 item = new ModelMenuItem(&model, docs);
588 } else
589 item = new ModelMenuItem(&model, model.Name(), NULL);
591 if (item) {
592 // add refs-message so that the recent app can be launched
593 BMessage* msg = new BMessage(B_REFS_RECEIVED);
594 msg->AddRef("refs", &ref);
595 item->SetMessage(msg);
596 item->SetTarget(Target());
598 AddItem(item);
602 // return true so that we know to reenter this list
603 return true;
607 // return false if we are done with this list
608 return false;
612 void
613 TRecentsMenu::DoneBuildingItemList()
615 // !! note: don't call inherited here
616 // the object list is not built
617 // and this list does not need to be sorted
618 // BNavMenu::DoneBuildingItemList();
620 if (CountItems() > 0)
621 SetTargetForItems(Target());
625 void
626 TRecentsMenu::ClearMenuBuildingState()
628 fMenuBuilt = false;
629 BNavMenu::ClearMenuBuildingState();
633 void
634 TRecentsMenu::ResetTargets()
636 BNavMenu::ResetTargets();
638 // if we are dragging, set the target to whatever was set
639 // else set it to the default (Tracker)
640 if (!fBarView->Dragging())
641 SetTarget(TDeskbarMenu::DefaultTarget());
643 // now set the target for the menuitems to the currently
644 // set target, which may or may not be tracker
645 SetTargetForItems(Target());
649 // #pragma mark - DeskbarMountMenu
652 #ifdef MOUNT_MENU_IN_DESKBAR
653 DeskbarMountMenu::DeskbarMountMenu(const char* name)
654 : BPrivate::MountMenu(name)
656 SetFont(be_plain_font);
660 bool
661 DeskbarMountMenu::AddDynamicItem(add_state s)
663 BPrivate::MountMenu::AddDynamicItem(s);
665 SetTargetForItems(BMessenger(kTrackerSignature));
667 return false;
669 #endif // MOUNT_MENU_IN_DESKBAR