#include "TeamMenu.h"
#include <algorithm>
#include <strings.h>
#include <Application.h>
#include <Collator.h>
#include <ControlLook.h>
#include <Debug.h>
#include <Mime.h>
#include <Roster.h>
#include "BarApp.h"
#include "BarMenuBar.h"
#include "BarView.h"
#include "DeskbarUtils.h"
#include "StatusView.h"
#include "TeamMenuItem.h"
TTeamMenu::TTeamMenu(TBarView* barView)
:
BMenu("Team Menu"),
fBarView(barView)
{
SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
}
int
TTeamMenu::CompareByName(const void* first, const void* second)
{
BCollator collator;
BLocale::Default()->GetCollator(&collator);
return collator.Compare(
(*(static_cast<BarTeamInfo* const*>(first)))->name,
(*(static_cast<BarTeamInfo* const*>(second)))->name);
}
void
TTeamMenu::AttachedToWindow()
{
RemoveItems(0, CountItems(), true);
BMessenger self(this);
BList teamList;
TBarApp::Subscribe(self, &teamList);
bool dragging = fBarView != NULL && fBarView->Dragging();
desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
const int32 iconSize = static_cast<TBarApp*>(be_app)->TeamIconSize();
const float iconPadding = be_control_look->ComposeSpacing(kIconPadding);
float iconOnlyWidth = iconSize + iconPadding;
if (settings->hideLabels)
iconOnlyWidth += iconPadding;
const int32 large = be_control_look->ComposeIconSize(B_LARGE_ICON)
.IntegerWidth() + 1;
const int32 min = be_control_look->ComposeIconSize(kMinimumIconSize)
.IntegerWidth() + 1;
float minItemWidth = 0;
if (settings->hideLabels) {
minItemWidth = std::max(floorf(gMinimumWindowWidth / 2),
iconOnlyWidth);
} else {
float labelWidth = gMinimumWindowWidth - iconOnlyWidth
+ (be_plain_font->Size() - 12) * 4;
if (iconSize <= large)
labelWidth += iconSize - min;
minItemWidth = iconOnlyWidth + labelWidth;
}
float maxItemWidth = minItemWidth;
int32 teamCount = teamList.CountItems();
if (!settings->hideLabels) {
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i);
float labelWidth = StringWidth(barInfo->name);
float itemWidth = iconSize > large
? std::max(labelWidth, iconOnlyWidth)
: labelWidth + iconOnlyWidth + min
+ (be_plain_font->Size() - 12) * 4;
maxItemWidth = std::max(maxItemWidth, itemWidth);
}
maxItemWidth = std::min(maxItemWidth, gMaximumWindowWidth);
}
SetMaxContentWidth(maxItemWidth);
if (settings->sortRunningApps)
teamList.SortItems(TTeamMenu::CompareByName);
for (int32 i = 0; i < teamCount; i++) {
BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i);
TTeamMenuItem* item = new TTeamMenuItem(barInfo->teams,
barInfo->icon, barInfo->name, barInfo->sig, maxItemWidth);
if (settings->trackerAlwaysFirst
&& strcasecmp(barInfo->sig, kTrackerSignature) == 0) {
AddItem(item, 0);
} else
AddItem(item);
if (dragging && item != NULL) {
bool canhandle = fBarView->AppCanHandleTypes(item->Signature());
if (item->IsEnabled() != canhandle)
item->SetEnabled(canhandle);
BMenu* menu = item->Submenu();
if (menu != NULL) {
menu->SetTrackingHook(fBarView->MenuTrackingHook,
fBarView->GetTrackingHookData());
}
}
}
if (CountItems() == 0) {
BMenuItem* item = new BMenuItem("no application running", NULL);
item->SetEnabled(false);
AddItem(item);
}
if (dragging && fBarView->LockLooper()) {
SetTrackingHook(fBarView->MenuTrackingHook,
fBarView->GetTrackingHookData());
fBarView->DragStart();
fBarView->UnlockLooper();
}
BMenu::AttachedToWindow();
}
void
TTeamMenu::DetachedFromWindow()
{
if (fBarView != NULL) {
BLooper* looper = fBarView->Looper();
if (looper != NULL && looper->Lock()) {
fBarView->DragStop();
looper->Unlock();
}
}
BMenu::DetachedFromWindow();
BMessenger self(this);
TBarApp::Unsubscribe(self);
}
void
TTeamMenu::MessageReceived(BMessage* message)
{
TTeamMenuItem* item = NULL;
switch (message->what) {
case B_SOME_APP_QUIT:
case kRemoveTeam:
{
int32 itemIndex = -1;
message->FindInt32("itemIndex", &itemIndex);
team_id team = -1;
message->FindInt32("team", &team);
item = dynamic_cast<TTeamMenuItem*>(ItemAt(itemIndex));
if (item != NULL && item->Teams()->HasItem((void*)(addr_t)team)) {
item->Teams()->RemoveItem(team);
RemoveItem(itemIndex);
delete item;
}
break;
}
default:
BMenu::MessageReceived(message);
break;
}
}
void
TTeamMenu::MouseDown(BPoint where)
{
if (fBarView == NULL || fBarView->Dragging())
return BMenu::MouseDown(where);
BMenuItem* item = ItemAtPoint(where);
if (item == NULL)
return BMenu::MouseDown(where);
TTeamMenuItem* teamItem = dynamic_cast<TTeamMenuItem*>(item);
if (teamItem == NULL || !teamItem->HandleMouseDown(where))
BMenu::MouseDown(where);
}
BMenuItem*
TTeamMenu::ItemAtPoint(BPoint point)
{
int32 itemCount = CountItems();
for (int32 index = 0; index < itemCount; index++) {
BMenuItem* item = ItemAt(index);
if (item != NULL && item->Frame().Contains(point))
return item;
}
return NULL;
}