Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered
trademarks of Be Incorporated in the United States and other countries. Other
brand product names are registered trademarks or trademarks of their respective
holders.
All rights reserved.
*/
#include "BarView.h"
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <ControlLook.h>
#include <Debug.h>
#include <Directory.h>
#include <LocaleRoster.h>
#include <NodeInfo.h>
#include <Roster.h>
#include <Screen.h>
#include <String.h>
#include <StringList.h>
#include "icons.h"
#include "BarApp.h"
#include "BarMenuBar.h"
#include "BarWindow.h"
#include "DeskbarMenu.h"
#include "DeskbarUtils.h"
#include "ExpandoMenuBar.h"
#include "FSUtils.h"
#include "InlineScrollView.h"
#include "ResourceSet.h"
#include "StatusView.h"
#include "TeamMenuItem.h"
const int32 kDefaultRecentDocCount = 10;
const int32 kDefaultRecentAppCount = 10;
const int32 kMenuTrackMargin = 20;
const float kMinTeamItemHeight = 20.0f;
const float kScrollerDimension = 12.0f;
const uint32 kUpdateOrientation = 'UpOr';
class BarViewMessageFilter : public BMessageFilter
{
public:
BarViewMessageFilter(TBarView* barView);
virtual ~BarViewMessageFilter();
virtual filter_result Filter(BMessage* message, BHandler** target);
private:
TBarView* fBarView;
};
BarViewMessageFilter::BarViewMessageFilter(TBarView* barView)
:
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fBarView(barView)
{
}
BarViewMessageFilter::~BarViewMessageFilter()
{
}
filter_result
BarViewMessageFilter::Filter(BMessage* message, BHandler** target)
{
if (message->what == B_MOUSE_DOWN || message->what == B_MOUSE_MOVED) {
BPoint where = message->FindPoint("be:view_where");
uint32 transit = message->FindInt32("be:transit");
BMessage* dragMessage = NULL;
if (message->HasMessage("be:drag_message")) {
dragMessage = new BMessage();
message->FindMessage("be:drag_message", dragMessage);
}
switch (message->what) {
case B_MOUSE_DOWN:
fBarView->MouseDown(where);
break;
case B_MOUSE_MOVED:
fBarView->MouseMoved(where, transit, dragMessage);
break;
}
delete dragMessage;
}
return B_DISPATCH_MESSAGE;
}
TBarView::TBarView(BRect frame, bool vertical, bool left, bool top,
int32 state, float)
:
BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
fBarApp(static_cast<TBarApp*>(be_app)),
fBarWindow(NULL),
fInlineScrollView(NULL),
fBarMenuBar(NULL),
fExpandoMenuBar(NULL),
fTrayLocation(1),
fIsRaised(false),
fMouseDownOutside(false),
fVertical(vertical),
fTop(top),
fLeft(left),
fState(state),
fRefsRcvdOnly(true),
fDragMessage(NULL),
fCachedTypesList(NULL),
fMaxRecentDocs(kDefaultRecentDocCount),
fMaxRecentApps(kDefaultRecentAppCount),
fLastDragItem(NULL),
fMouseFilter(NULL),
fTabHeight(kMenuBarHeight)
{
BWindow* tmpWindow = new(std::nothrow) BWindow(BRect(), NULL,
B_TITLED_WINDOW, 0);
if (tmpWindow != NULL) {
BMessage settings;
if (tmpWindow->GetDecoratorSettings(&settings) == B_OK) {
BRect tabRect;
if (settings.FindRect("tab frame", &tabRect) == B_OK)
fTabHeight = tabRect.Height();
}
delete tmpWindow;
}
BRect menuFrame(frame);
if (fVertical)
menuFrame.bottom = menuFrame.top + fTabHeight - 1;
else
menuFrame.bottom = menuFrame.top + TeamMenuItemHeight();
fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this);
AddChild(fBarMenuBar);
fReplicantTray = new TReplicantTray(this);
fResizeControl = new TResizeControl(this);
fDragRegion = new TDragRegion(this, fReplicantTray);
fDragRegion->AddChild(fResizeControl);
fDragRegion->AddChild(fReplicantTray);
if (fTrayLocation != 0)
AddChild(fDragRegion);
fExpandoMenuBar = new TExpandoMenuBar(
fVertical ? B_ITEMS_IN_COLUMN : B_ITEMS_IN_ROW, this);
fInlineScrollView = new TInlineScrollView(fExpandoMenuBar,
fVertical ? B_VERTICAL : B_HORIZONTAL);
AddChild(fInlineScrollView);
if (state == kMiniState)
fInlineScrollView->Hide();
if (fBarApp->Settings()->autoHide && !IsHidden())
Hide();
}
TBarView::~TBarView()
{
delete fDragMessage;
delete fCachedTypesList;
delete fBarMenuBar;
}
void
TBarView::AttachedToWindow()
{
BView::AttachedToWindow();
fBarWindow = dynamic_cast<TBarWindow*>(Window());
SetViewUIColor(B_MENU_BACKGROUND_COLOR);
SetFont(be_plain_font);
fMouseFilter = new BarViewMessageFilter(this);
Window()->AddCommonFilter(fMouseFilter);
fTrackingHookData.fTrackingHook = MenuTrackingHook;
fTrackingHookData.fTarget = BMessenger(this);
fTrackingHookData.fDragMessage = new BMessage(B_REFS_RECEIVED);
if (!fVertical)
UpdatePlacement();
}
void
TBarView::DetachedFromWindow()
{
Window()->RemoveCommonFilter(fMouseFilter);
delete fMouseFilter;
fMouseFilter = NULL;
delete fTrackingHookData.fDragMessage;
fTrackingHookData.fDragMessage = NULL;
}
void
TBarView::Draw(BRect)
{
BRect bounds(Bounds());
rgb_color hilite = tint_color(ViewColor(), B_DARKEN_1_TINT);
SetHighColor(hilite);
if (AcrossTop())
StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
else if (AcrossBottom())
StrokeLine(bounds.LeftTop(), bounds.RightTop());
if (fVertical && fState == kExpandoState) {
SetHighColor(hilite);
BRect frame(fExpandoMenuBar->Frame());
StrokeLine(BPoint(frame.left, frame.top - 1),
BPoint(frame.right, frame.top -1));
}
}
void
TBarView::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_LOCALE_CHANGED:
case kRealignReplicants:
case kShowHideTime:
case kShowSeconds:
case kShowDayOfWeek:
case kShowTimeZone:
case kGetClockSettings:
fReplicantTray->MessageReceived(message);
break;
case B_REFS_RECEIVED:
HandleDeskbarMenu(message);
break;
case B_ARCHIVED_OBJECT:
{
int32 id;
if (AddItem(message, B_DESKBAR_TRAY, &id) == B_OK)
Looper()->DetachCurrentMessage();
break;
}
case kUpdateOrientation:
{
_ChangeState(message);
break;
}
default:
BView::MessageReceived(message);
}
}
void
TBarView::MouseDown(BPoint where)
{
if (fBarWindow == NULL || fBarWindow->IsShowingMenu()
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseDown(where);
}
BMessage* currentMessage = Window()->CurrentMessage();
if (currentMessage == NULL)
return BView::MouseDown(where);
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
bool autoHide = settings->autoHide;
BPoint whereScreen = currentMessage->GetPoint("screen_where",
ConvertToScreen(where));
fMouseDownOutside = !Window()->Frame().Contains(whereScreen);
if (fMouseDownOutside) {
if (!alwaysOnTop && autoRaise && fIsRaised)
RaiseDeskbar(false);
if (autoHide && !IsHidden())
HideDeskbar(true);
} else {
if (!autoRaise && !alwaysOnTop)
Window()->Activate(true);
if ((modifiers() & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
| B_SHIFT_KEY)) == (B_CONTROL_KEY | B_COMMAND_KEY)) {
fDragRegion->MouseDown(fDragRegion->DragRegion().LeftTop());
return BView::MouseDown(where);
}
}
BView::MouseDown(where);
}
void
TBarView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
if (fDragRegion->IsDragging())
return fDragRegion->MouseMoved(where, transit, dragMessage);
else if (fResizeControl->IsResizing())
return BView::MouseMoved(where, transit, dragMessage);
desk_settings* settings = fBarApp->Settings();
bool alwaysOnTop = settings->alwaysOnTop;
bool autoRaise = settings->autoRaise;
bool autoHide = settings->autoHide;
if (!autoRaise && !autoHide) {
SetEventMask(0);
return BView::MouseMoved(where, transit, dragMessage);
} else if (EventMask() != B_POINTER_EVENTS) {
SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
}
if (fBarWindow == NULL || fBarWindow->IsShowingMenu()
|| fReplicantTray->fTime->IsShowingCalendar()) {
return BView::MouseMoved(where, transit, dragMessage);
}
BMessage* currentMessage = Window()->CurrentMessage();
if (currentMessage == NULL)
return BView::MouseMoved(where, transit, dragMessage);
BPoint whereScreen = currentMessage->GetPoint("screen_where",
ConvertToScreen(where));
BRect screenFrame = (BScreen(Window())).Frame();
bool onScreenEdge = whereScreen.x == screenFrame.left
|| whereScreen.x == screenFrame.right
|| whereScreen.y == screenFrame.top
|| whereScreen.y == screenFrame.bottom;
if (!Window()->Frame().Contains(whereScreen)) {
if (!alwaysOnTop && autoRaise && fIsRaised && !fMouseDownOutside)
RaiseDeskbar(false);
BRect preventHideArea = Window()->Frame().InsetByCopy(
-kMaxPreventHidingDist, -kMaxPreventHidingDist);
if (!preventHideArea.Contains(whereScreen)
&& autoHide && !IsHidden()) {
HideDeskbar(true);
}
} else if (onScreenEdge) {
if (!alwaysOnTop && autoRaise && !fIsRaised && !fMouseDownOutside)
RaiseDeskbar(true);
if (autoHide && IsHidden())
HideDeskbar(false);
}
BView::MouseMoved(where, transit, dragMessage);
}
void
TBarView::MouseUp(BPoint where)
{
fMouseDownOutside = false;
BView::MouseUp(where);
}
void
TBarView::PlaceDeskbarMenu()
{
float width = 0;
float height = 0;
BRect menuFrame(Bounds());
if (fVertical) {
width = static_cast<TBarApp*>(be_app)->Settings()->width;
height = fTabHeight;
} else {
if (fState == kMiniState) {
width = gMinimumWindowWidth;
height = std::max(fTabHeight,
kGutter + fReplicantTray->MaxReplicantHeight() + kGutter);
} else {
width = gMinimumWindowWidth / 2
+ be_control_look->ComposeSpacing(kIconPadding);
height = std::max(TeamMenuItemHeight(),
kGutter + fReplicantTray->MaxReplicantHeight() + kGutter);
}
}
menuFrame.bottom = menuFrame.top + height;
if (fBarMenuBar == NULL) {
fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this);
AddChild(fBarMenuBar);
} else
fBarMenuBar->SmartResize(-1, -1);
if (fState == kMiniState) {
fBarMenuBar->RemoveSeperatorItem();
fBarMenuBar->AddTeamMenu();
} else if (fVertical) {
fBarMenuBar->RemoveSeperatorItem();
fBarMenuBar->RemoveTeamMenu();
} else {
fBarMenuBar->RemoveTeamMenu();
fBarMenuBar->AddSeparatorItem();
}
fBarMenuBar->SmartResize(width, height);
fBarMenuBar->MoveTo(B_ORIGIN);
}
void
TBarView::PlaceTray(bool vertSwap, bool leftSwap)
{
BPoint statusLoc;
if (fTrayLocation == 0) {
if (!fReplicantTray->IsHidden())
fReplicantTray->Hide();
return;
} else if (fReplicantTray->IsHidden())
fReplicantTray->Show();
fReplicantTray->RealignReplicants();
fDragRegion->ResizeToPreferred();
if (fVertical) {
if (fResizeControl->IsHidden())
fResizeControl->Show();
if (fLeft) {
fReplicantTray->MoveTo(gDragWidth + kGutter, kGutter);
fReplicantTray->ResizeBy(-(gDragWidth + kGutter), 0);
} else {
fReplicantTray->MoveTo(0, kGutter);
}
statusLoc.x = 0;
statusLoc.y = fBarMenuBar->Frame().bottom + 1;
} else {
if (fState == kMiniState) {
statusLoc.x = fLeft ? fBarMenuBar->Frame().right + 1 : 0;
statusLoc.y = 0;
fReplicantTray->MoveTo(fLeft ? gDragWidth : 0, kGutter);
fReplicantTray->ResizeBy(0, -4);
} else {
fReplicantTray->MoveTo(2, 0);
fReplicantTray->ResizeBy(-2, 0);
BRect screenFrame = (BScreen(Window())).Frame();
statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width();
statusLoc.y = 0;
}
}
fDragRegion->MoveTo(statusLoc);
fResizeControl->ResizeTo(gDragWidth, fDragRegion->Bounds().Height() - 2);
if (fVertical) {
fResizeControl->MoveTo(
fLeft ? fBarApp->Settings()->width - gDragWidth : 0, 1);
if (fResizeControl->IsHidden())
fResizeControl->Show();
} else {
if (!fResizeControl->IsHidden())
fResizeControl->Hide();
}
fDragRegion->Invalidate();
}
void
TBarView::PlaceApplicationBar()
{
BRect screenFrame = (BScreen(Window())).Frame();
if (fState == kMiniState) {
if (!fInlineScrollView->IsHidden())
fInlineScrollView->Hide();
SizeWindow(screenFrame);
PositionWindow(screenFrame);
Window()->UpdateIfNeeded();
if (!fVertical) {
fBarMenuBar->MoveTo(fLeft ? 0 : fDragRegion->Bounds().right + 1,
0);
}
Invalidate();
return;
}
if (fInlineScrollView->IsHidden())
fInlineScrollView->Show();
BRect expandoFrame(0, 0, 0, 0);
if (fVertical) {
expandoFrame.left = fDragRegion->Frame().left;
expandoFrame.top = fTrayLocation != 0 ? fDragRegion->Frame().bottom + 1
: fBarMenuBar->Frame().bottom + 1;
expandoFrame.right = fBarApp->Settings()->width;
expandoFrame.bottom = fState == kFullState ? screenFrame.bottom
: Frame().bottom;
} else {
expandoFrame.top = 0;
expandoFrame.bottom = TeamMenuItemHeight();
expandoFrame.left = screenFrame.left + fBarMenuBar->Frame().Width();
expandoFrame.right = screenFrame.right - fDragRegion->Frame().Width() - 1;
}
fInlineScrollView->DetachScrollers();
fInlineScrollView->MoveTo(expandoFrame.LeftTop());
fInlineScrollView->ResizeTo(expandoFrame.Width(), fVertical
? screenFrame.bottom - expandoFrame.top : expandoFrame.bottom);
fExpandoMenuBar->ResizeTo(expandoFrame.Width(), expandoFrame.Height());
fExpandoMenuBar->MoveTo(0, 0);
fExpandoMenuBar->BuildItems();
fExpandoMenuBar->SizeWindow(0);
}
void
TBarView::GetPreferredWindowSize(BRect screenFrame, float* width,
float* height)
{
float windowHeight = 0;
float windowWidth = 0;
bool setToHiddenSize = fBarApp->Settings()->autoHide && IsHidden()
&& !fDragRegion->IsDragging();
if (setToHiddenSize) {
windowHeight = kHiddenDimension;
if (fState == kExpandoState && !fVertical) {
windowWidth = screenFrame.Width();
} else
windowWidth = kHiddenDimension;
} else if (fVertical) {
if (fState == kFullState) {
windowHeight = std::max(screenFrame.bottom, windowHeight);
} else {
if (fTrayLocation != 0)
windowHeight = fDragRegion->Frame().bottom;
else
windowHeight = fBarMenuBar->Frame().bottom;
if (fState == kExpandoState && fExpandoMenuBar != NULL) {
windowHeight += fExpandoMenuBar->Bounds().Height();
}
}
windowWidth = fBarApp->Settings()->width;
} else {
if (fState == kMiniState) {
windowHeight = fBarMenuBar->Frame().Height();
windowWidth = fDragRegion->Frame().Width()
+ fBarMenuBar->Frame().Width() + 1;
} else {
windowHeight = std::max(TeamMenuItemHeight(),
kGutter + fReplicantTray->MaxReplicantHeight() + kGutter);
windowWidth = screenFrame.Width();
}
}
*width = windowWidth;
*height = windowHeight;
}
void
TBarView::SizeWindow(BRect screenFrame)
{
float windowWidth;
float windowHeight;
GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
Window()->ResizeTo(windowWidth, windowHeight);
ResizeTo(windowWidth, windowHeight);
}
void
TBarView::PositionWindow(BRect screenFrame)
{
float windowWidth;
float windowHeight;
GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
BPoint moveLoc(0, 0);
if (!fLeft && (fVertical || fState == kMiniState))
moveLoc.x = screenFrame.right - windowWidth;
if (!fTop)
moveLoc.y = screenFrame.bottom - windowHeight;
Window()->MoveTo(moveLoc);
}
void
TBarView::CheckForScrolling()
{
if (fInlineScrollView == NULL && fExpandoMenuBar == NULL)
return;
if (fExpandoMenuBar->CheckForSizeOverrun())
fInlineScrollView->AttachScrollers();
else
fInlineScrollView->DetachScrollers();
}
void
TBarView::SaveSettings()
{
desk_settings* settings = fBarApp->Settings();
settings->vertical = fVertical;
settings->left = fLeft;
settings->top = fTop;
settings->state = fState;
fReplicantTray->SaveTimeSettings();
}
void
TBarView::UpdatePlacement()
{
ChangeState(fState, fVertical, fLeft, fTop);
}
void
TBarView::ChangeState(int32 state, bool vertical, bool left, bool top,
bool async)
{
BMessage message(kUpdateOrientation);
message.AddInt32("state", state);
message.AddBool("vertical", vertical);
message.AddBool("left", left);
message.AddBool("top", top);
if (async)
BMessenger(this).SendMessage(&message);
else
_ChangeState(&message);
}
void
TBarView::_ChangeState(BMessage* message)
{
int32 state = message->FindInt32("state");
bool vertical = message->FindBool("vertical");
bool left = message->FindBool("left");
bool top = message->FindBool("top");
bool vertSwap = (fVertical != vertical);
bool leftSwap = (fLeft != left);
bool stateChanged = (fState != state);
fState = state;
fVertical = vertical;
fLeft = left;
fTop = top;
if (stateChanged || vertSwap) {
be_app->PostMessage(kStateChanged);
TBarWindow* barWindow = dynamic_cast<TBarWindow*>(Window());
if (barWindow != NULL)
barWindow->SetSizeLimits();
if (vertSwap && fExpandoMenuBar != NULL) {
if (fVertical) {
fInlineScrollView->SetOrientation(B_VERTICAL);
fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN);
fExpandoMenuBar->StartMonitoringWindows();
} else {
fInlineScrollView->SetOrientation(B_HORIZONTAL);
fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW);
fExpandoMenuBar->StopMonitoringWindows();
}
}
}
PlaceDeskbarMenu();
PlaceTray(vertSwap, leftSwap);
PlaceApplicationBar();
}
void
TBarView::RaiseDeskbar(bool raise)
{
fIsRaised = raise;
if (raise) {
Window()->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
Window()->SetFeel(B_NORMAL_WINDOW_FEEL);
} else
Window()->SendBehind(Window());
}
void
TBarView::HideDeskbar(bool hide)
{
BRect screenFrame = (BScreen(Window())).Frame();
if (hide) {
Hide();
if (fBarWindow != NULL)
fBarWindow->SetSizeLimits();
PositionWindow(screenFrame);
SizeWindow(screenFrame);
} else {
Show();
if (fBarWindow != NULL)
fBarWindow->SetSizeLimits();
SizeWindow(screenFrame);
PositionWindow(screenFrame);
}
}
void
TBarView::CacheDragData(const BMessage* incoming)
{
if (!incoming)
return;
if (Dragging() && SpringLoadedFolderCompareMessages(incoming, fDragMessage))
return;
SpringLoadedFolderCacheDragData(incoming, &fDragMessage, &fCachedTypesList);
}
static void
init_tracking_hook(BMenuItem* item,
bool (*hookFunction)(BMenu*, void*), void* state)
{
if (!item)
return;
BMenu* windowMenu = item->Submenu();
if (windowMenu) {
windowMenu->SetTrackingHook(hookFunction, state);
}
}
status_t
TBarView::DragStart()
{
if (!Dragging())
return B_OK;
BPoint loc;
uint32 buttons;
GetMouse(&loc, &buttons);
if (fExpandoMenuBar != NULL && fExpandoMenuBar->Frame().Contains(loc)) {
ConvertToScreen(&loc);
BPoint expandoLocation = fExpandoMenuBar->ConvertFromScreen(loc);
TTeamMenuItem* item = fExpandoMenuBar->TeamItemAtPoint(expandoLocation);
if (fLastDragItem)
init_tracking_hook(fLastDragItem, NULL, NULL);
if (item != NULL) {
if (item == fLastDragItem)
return B_OK;
fLastDragItem = item;
}
}
return B_OK;
}
bool
TBarView::MenuTrackingHook(BMenu* menu, void* castToThis)
{
TrackingHookData* data = static_cast<TrackingHookData*>(castToThis);
if (!data)
return false;
TBarView* barView = dynamic_cast<TBarView*>(data->fTarget.Target(NULL));
if (!barView || !menu->LockLooper())
return false;
uint32 buttons;
BPoint location;
menu->GetMouse(&location, &buttons);
bool endMenu = true;
BRect frame(menu->Bounds());
frame.InsetBy(-kMenuTrackMargin, -kMenuTrackMargin);
if (frame.Contains(location)) {
endMenu = false;
} else {
menu->ConvertToScreen(&location);
if (barView->LockLooper()) {
TExpandoMenuBar* expandoMenuBar = barView->ExpandoMenuBar();
TBarWindow* barWindow
= dynamic_cast<TBarWindow*>(barView->Window());
TDeskbarMenu* deskbarMenu = barWindow->DeskbarMenu();
if (deskbarMenu && deskbarMenu->LockLooper()) {
deskbarMenu->ConvertFromScreen(&location);
if (deskbarMenu->Frame().Contains(location))
endMenu = false;
deskbarMenu->UnlockLooper();
}
if (endMenu && expandoMenuBar) {
expandoMenuBar->ConvertFromScreen(&location);
BMenuItem* item = expandoMenuBar->TeamItemAtPoint(location);
if (item)
endMenu = false;
}
barView->UnlockLooper();
}
}
menu->UnlockLooper();
return endMenu;
}
TrackingHookData*
TBarView::GetTrackingHookData()
{
return &fTrackingHookData;
}
void
TBarView::DragStop(bool full)
{
if (!Dragging())
return;
if (fExpandoMenuBar != NULL) {
if (fLastDragItem != NULL) {
init_tracking_hook(fLastDragItem, NULL, NULL);
fLastDragItem = NULL;
}
}
if (full) {
delete fDragMessage;
fDragMessage = NULL;
delete fCachedTypesList;
fCachedTypesList = NULL;
}
}
bool
TBarView::AppCanHandleTypes(const char* signature)
{
if (modifiers() & B_CONTROL_KEY) {
return true;
}
if (!signature || strlen(signature) == 0
|| !fCachedTypesList || fCachedTypesList->CountStrings() == 0)
return false;
if (strcasecmp(signature, kTrackerSignature) == 0) {
return true;
}
entry_ref hintref;
BMimeType appmime(signature);
if (appmime.GetAppHint(&hintref) != B_OK)
return false;
BFile file(&hintref, O_RDONLY);
BAppFileInfo fileinfo(&file);
int32 count = fCachedTypesList->CountStrings();
for (int32 i = 0 ; i < count ; i++) {
if (fileinfo.IsSupportedType(fCachedTypesList->StringAt(i).String()))
return true;
}
return false;
}
void
TBarView::SetDragOverride(bool on)
{
fRefsRcvdOnly = on;
}
bool
TBarView::DragOverride()
{
return fRefsRcvdOnly;
}
status_t
TBarView::SendDragMessage(const char* signature, entry_ref* ref)
{
status_t err = B_ERROR;
if (fDragMessage != NULL) {
if (fRefsRcvdOnly) {
fDragMessage->what = B_REFS_RECEIVED;
}
BRoster roster;
if (signature != NULL && *signature != '\0'
&& roster.IsRunning(signature)) {
BMessenger messenger(signature);
err = messenger.SendMessage(fDragMessage);
} else if (ref != NULL) {
FSLaunchItem((const entry_ref*)ref, (const BMessage*)fDragMessage,
true, true);
} else if (signature != NULL && *signature != '\0')
roster.Launch(signature, fDragMessage);
}
return err;
}
bool
TBarView::InvokeItem(const char* signature)
{
if (Dragging() && AppCanHandleTypes(signature)) {
SendDragMessage(signature);
DragStop(true);
return true;
}
return false;
}
void
TBarView::HandleDeskbarMenu(BMessage* messagewithdestination)
{
if (!Dragging())
return;
if (fVertical && fState != kExpandoState) {
if (fBarMenuBar->CountItems() >= 2) {
uint32 buttons;
BPoint location;
GetMouse(&location, &buttons);
if (fBarMenuBar->ItemAt(1)->Frame().Contains(location))
return;
}
}
if (messagewithdestination) {
entry_ref ref;
if (messagewithdestination->FindRef("refs", &ref) == B_OK) {
BEntry entry(&ref, true);
if (entry.IsDirectory()) {
AddRefsToDeskbarMenu(DragMessage(), &ref);
} else
SendDragMessage(NULL, &ref);
}
} else {
AddRefsToDeskbarMenu(DragMessage(), NULL);
}
DragStop(true);
}
status_t
TBarView::ItemInfo(int32 id, const char** name, DeskbarShelf* shelf)
{
*shelf = B_DESKBAR_TRAY;
return fReplicantTray->ItemInfo(id, name);
}
status_t
TBarView::ItemInfo(const char* name, int32* id, DeskbarShelf* shelf)
{
*shelf = B_DESKBAR_TRAY;
return fReplicantTray->ItemInfo(name, id);
}
bool
TBarView::ItemExists(int32 id, DeskbarShelf)
{
return fReplicantTray->IconExists(id);
}
bool
TBarView::ItemExists(const char* name, DeskbarShelf)
{
return fReplicantTray->IconExists(name);
}
int32
TBarView::CountItems(DeskbarShelf)
{
return fReplicantTray->ReplicantCount();
}
BSize
TBarView::MaxItemSize(DeskbarShelf shelf)
{
return BSize(fReplicantTray->MaxReplicantWidth(),
fReplicantTray->MaxReplicantHeight());
}
status_t
TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id)
{
return fReplicantTray->AddIcon(item, id);
}
status_t
TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id)
{
return fReplicantTray->LoadAddOn(entry, id);
}
void
TBarView::RemoveItem(int32 id)
{
fReplicantTray->RemoveIcon(id);
}
void
TBarView::RemoveItem(const char* name, DeskbarShelf)
{
fReplicantTray->RemoveIcon(name);
}
BRect
TBarView::OffsetIconFrame(BRect rect) const
{
BRect frame(Frame());
frame.left += fDragRegion->Frame().left + fReplicantTray->Frame().left
+ rect.left;
frame.top += fDragRegion->Frame().top + fReplicantTray->Frame().top
+ rect.top;
frame.right = frame.left + rect.Width();
frame.bottom = frame.top + rect.Height();
return frame;
}
BRect
TBarView::IconFrame(int32 id) const
{
return OffsetIconFrame(fReplicantTray->IconFrame(id));
}
BRect
TBarView::IconFrame(const char* name) const
{
return OffsetIconFrame(fReplicantTray->IconFrame(name));
}
float
TBarView::TeamMenuItemHeight() const
{
const int32 iconSize = fBarApp->TeamIconSize();
const float iconPadding = be_control_look->ComposeSpacing(kIconPadding);
float iconOnlyHeight = iconSize + iconPadding / 2;
const int32 large = be_control_look->ComposeIconSize(B_LARGE_ICON)
.IntegerWidth() + 1;
font_height fontHeight;
if (fExpandoMenuBar != NULL)
fExpandoMenuBar->GetFontHeight(&fontHeight);
else
GetFontHeight(&fontHeight);
float labelHeight = fontHeight.ascent + fontHeight.descent;
labelHeight = labelHeight < kMinTeamItemHeight ? kMinTeamItemHeight
: ceilf(labelHeight * 1.1f);
if (fBarApp->Settings()->hideLabels && iconSize > B_MINI_ICON) {
return iconOnlyHeight;
} else if (!fVertical || (fVertical && iconSize <= large)) {
return std::max(iconOnlyHeight, labelHeight);
} else if (fVertical && iconSize > large) {
return ceilf(iconOnlyHeight + labelHeight);
} else {
return labelHeight;
}
}