* Early work in progress of toying around with the idea to show some useful
panels when touching the screen border with the mouse while holding down the CTRL key. * Right now, a simple running applications list is shown on the top/bottom, and a list of the windows of the current app on the left/right edge which you can click to front. * Imagine you could configure this to show various panels like a shelf, a query window, workspaces, recent files, favourite files, folder contents, have a clipboard for files, ... * Just wanted to have it in SVN even if it's only barely useful right now - I would be glad to hear your opinions on this, and if it's worthwhile to continue working on this. -alpha git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41754 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -55,6 +55,7 @@ HaikuSubInclude showimage ;
|
|||||||
HaikuSubInclude soundrecorder ;
|
HaikuSubInclude soundrecorder ;
|
||||||
HaikuSubInclude stylededit ;
|
HaikuSubInclude stylededit ;
|
||||||
HaikuSubInclude sudoku ;
|
HaikuSubInclude sudoku ;
|
||||||
|
HaikuSubInclude switcher ;
|
||||||
HaikuSubInclude terminal ;
|
HaikuSubInclude terminal ;
|
||||||
HaikuSubInclude text_search ;
|
HaikuSubInclude text_search ;
|
||||||
HaikuSubInclude tracker ;
|
HaikuSubInclude tracker ;
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ApplicationsView.h"
|
||||||
|
|
||||||
|
#include "LaunchButton.h"
|
||||||
|
#include "Switcher.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgActivateApp = 'AcAp';
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationsView::ApplicationsView(uint32 location)
|
||||||
|
:
|
||||||
|
BGroupView((location & (kTopEdge | kBottomEdge)) != 0
|
||||||
|
? B_HORIZONTAL : B_VERTICAL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationsView::~ApplicationsView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ApplicationsView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
// TODO: make this dynamic!
|
||||||
|
|
||||||
|
BList teamList;
|
||||||
|
be_roster->GetAppList(&teamList);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < teamList.CountItems(); i++) {
|
||||||
|
app_info appInfo;
|
||||||
|
team_id team = (team_id)teamList.ItemAt(i);
|
||||||
|
if (be_roster->GetRunningAppInfo(team, &appInfo) == B_OK)
|
||||||
|
_AddTeam(appInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ApplicationsView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgActivateApp:
|
||||||
|
be_roster->ActivateApp(message->FindInt32("team"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BGroupView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ApplicationsView::_AddTeam(app_info& info)
|
||||||
|
{
|
||||||
|
if ((info.flags & B_BACKGROUND_APP) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BMessage* message = new BMessage(kMsgActivateApp);
|
||||||
|
message->AddInt32("team", info.team);
|
||||||
|
|
||||||
|
LaunchButton* button = new LaunchButton(info.signature, NULL, message,
|
||||||
|
this);
|
||||||
|
button->SetTo(&info.ref);
|
||||||
|
AddChild(button);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef APPLICATIONS_VIEW_H
|
||||||
|
#define APPLICATIONS_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <GroupView.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationsView : public BGroupView {
|
||||||
|
public:
|
||||||
|
ApplicationsView(uint32 location);
|
||||||
|
virtual ~ApplicationsView();
|
||||||
|
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _AddTeam(app_info& info);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // APPLICATIONS_VIEW_H
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "CaptureWindow.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
|
||||||
|
#include "Switcher.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const bigtime_t kUpdateDelay = 50000;
|
||||||
|
// 50 ms
|
||||||
|
|
||||||
|
|
||||||
|
class CaptureView : public BView {
|
||||||
|
public:
|
||||||
|
CaptureView();
|
||||||
|
virtual ~CaptureView();
|
||||||
|
|
||||||
|
void AddMoveOutNotification(BMessage* message);
|
||||||
|
|
||||||
|
virtual void MouseMoved(BPoint point, uint32 transit,
|
||||||
|
const BMessage* dragMessage);
|
||||||
|
virtual void KeyDown(const char* bytes, int32 numBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _UpdateLast(const BPoint& point);
|
||||||
|
void _Notify(uint32 location, team_id team);
|
||||||
|
void _SendMovedOutNotification();
|
||||||
|
|
||||||
|
static team_id _CurrentTeam();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fModifierMask;
|
||||||
|
BPoint fLastPoint;
|
||||||
|
team_id fLastTeam;
|
||||||
|
bigtime_t fLastEvent;
|
||||||
|
|
||||||
|
uint32 fMovedOutWhat;
|
||||||
|
BMessenger fMovedOutMessenger;
|
||||||
|
BRect fMovedOutFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CaptureView::CaptureView()
|
||||||
|
:
|
||||||
|
BView("main", 0),
|
||||||
|
fModifierMask(B_CONTROL_KEY),
|
||||||
|
fMovedOutWhat(0)
|
||||||
|
{
|
||||||
|
SetEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS, B_NO_POINTER_HISTORY);
|
||||||
|
_UpdateLast(BPoint(-1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CaptureView::~CaptureView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::AddMoveOutNotification(BMessage* message)
|
||||||
|
{
|
||||||
|
if (fMovedOutWhat != 0)
|
||||||
|
_SendMovedOutNotification();
|
||||||
|
|
||||||
|
if (message->FindMessenger("target", &fMovedOutMessenger) == B_OK
|
||||||
|
&& message->FindRect("frame", &fMovedOutFrame) == B_OK)
|
||||||
|
fMovedOutWhat = (uint32)message->FindInt32("what");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::MouseMoved(BPoint point, uint32 transit,
|
||||||
|
const BMessage* dragMessage)
|
||||||
|
{
|
||||||
|
ConvertToScreen(&point);
|
||||||
|
|
||||||
|
if (fMovedOutWhat != 0 && !fMovedOutFrame.Contains(point))
|
||||||
|
_SendMovedOutNotification();
|
||||||
|
|
||||||
|
uint32 modifiers = ::modifiers();
|
||||||
|
if ((modifiers & fModifierMask) == 0) {
|
||||||
|
_UpdateLast(point);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we will need to iterate over all existing screens to find the
|
||||||
|
// right one!
|
||||||
|
BScreen screen;
|
||||||
|
BRect screenFrame = screen.Frame();
|
||||||
|
|
||||||
|
uint32 location = kNowhere;
|
||||||
|
if (point.x <= screenFrame.left && fLastPoint.x > screenFrame.left)
|
||||||
|
location = kLeftEdge;
|
||||||
|
else if (point.x >= screenFrame.right && fLastPoint.x < screenFrame.right)
|
||||||
|
location = kRightEdge;
|
||||||
|
else if (point.y <= screenFrame.top && fLastPoint.y > screenFrame.top)
|
||||||
|
location = kTopEdge;
|
||||||
|
else if (point.y >= screenFrame.bottom && fLastPoint.y < screenFrame.bottom)
|
||||||
|
location = kBottomEdge;
|
||||||
|
|
||||||
|
if (location != kNowhere)
|
||||||
|
_Notify(location, fLastTeam);
|
||||||
|
|
||||||
|
_UpdateLast(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::KeyDown(const char* bytes, int32 numBytes)
|
||||||
|
{
|
||||||
|
if ((::modifiers() & (B_CONTROL_KEY | B_SHIFT_KEY | B_OPTION_KEY
|
||||||
|
| B_COMMAND_KEY)) != (B_COMMAND_KEY | B_CONTROL_KEY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32 location = kNowhere;
|
||||||
|
|
||||||
|
switch (bytes[0]) {
|
||||||
|
case '1':
|
||||||
|
location = kLeftEdge;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
location = kRightEdge;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
location = kTopEdge;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
location = kBottomEdge;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location != kNowhere)
|
||||||
|
_Notify(location, _CurrentTeam());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::_UpdateLast(const BPoint& point)
|
||||||
|
{
|
||||||
|
fLastPoint = point;
|
||||||
|
|
||||||
|
bigtime_t now = system_time();
|
||||||
|
|
||||||
|
// We update the currently active application only, if the mouse did
|
||||||
|
// not move over it for a certain time - this is necessary only for
|
||||||
|
// focus follow mouse.
|
||||||
|
if (now > fLastEvent + kUpdateDelay)
|
||||||
|
fLastTeam = _CurrentTeam();
|
||||||
|
|
||||||
|
fLastEvent = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::_Notify(uint32 location, team_id team)
|
||||||
|
{
|
||||||
|
if (location == kNowhere)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BMessage message(kMsgLocationTrigger);
|
||||||
|
message.AddInt32("location", location);
|
||||||
|
message.AddInt32("team", team);
|
||||||
|
|
||||||
|
be_app->PostMessage(&message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureView::_SendMovedOutNotification()
|
||||||
|
{
|
||||||
|
BMessage movedOut(fMovedOutWhat);
|
||||||
|
fMovedOutMessenger.SendMessage(&movedOut);
|
||||||
|
fMovedOutWhat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ team_id
|
||||||
|
CaptureView::_CurrentTeam()
|
||||||
|
{
|
||||||
|
app_info appInfo;
|
||||||
|
status_t status = be_roster->GetActiveAppInfo(&appInfo);
|
||||||
|
if (status == B_OK)
|
||||||
|
return appInfo.team;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
CaptureWindow::CaptureWindow()
|
||||||
|
:
|
||||||
|
BWindow(BRect(0, 0, 100, 100), "mouse capture", B_NO_BORDER_WINDOW_LOOK,
|
||||||
|
B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS, B_ALL_WORKSPACES)
|
||||||
|
{
|
||||||
|
fCaptureView = new CaptureView();
|
||||||
|
AddChild(fCaptureView);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CaptureWindow::~CaptureWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CaptureWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgHideWhenMouseMovedOut:
|
||||||
|
fCaptureView->AddMoveOutNotification(message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CAPTURE_WINDOW_H
|
||||||
|
#define CAPTURE_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
class CaptureView;
|
||||||
|
|
||||||
|
|
||||||
|
class CaptureWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
CaptureWindow();
|
||||||
|
virtual ~CaptureWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CaptureView* fCaptureView;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CAPTURE_WINDOW_H
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "GroupListView.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
class RendererLayoutItem : public BAbstractLayout {
|
||||||
|
public:
|
||||||
|
RendererLayoutItem(BView* owner, int32 index, void* item,
|
||||||
|
ListItemRenderer*& renderer)
|
||||||
|
:
|
||||||
|
fOwner(owner),
|
||||||
|
fIndex(index),
|
||||||
|
fItem(item),
|
||||||
|
fRenderer(renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItemRenderer* Renderer() const
|
||||||
|
{
|
||||||
|
fRenderer->SetTo(fOwner, fItem);
|
||||||
|
return fRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Index() const
|
||||||
|
{
|
||||||
|
return fIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Item() const
|
||||||
|
{
|
||||||
|
return fItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize BaseMinSize()
|
||||||
|
{
|
||||||
|
fRenderer->SetTo(fOwner, fItem);
|
||||||
|
return fRenderer->MinSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize BasePreferredSize()
|
||||||
|
{
|
||||||
|
fRenderer->SetTo(fOwner, fItem);
|
||||||
|
return fRenderer->PreferredSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void DerivedLayoutItems()
|
||||||
|
{
|
||||||
|
// shouldn't ever be called?
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BView* fOwner;
|
||||||
|
int32 fIndex;
|
||||||
|
void* fItem;
|
||||||
|
ListItemRenderer*& fRenderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GroupListView::GroupListView(const char* name, GroupListModel* model,
|
||||||
|
enum orientation orientation, float spacing)
|
||||||
|
:
|
||||||
|
BView(NULL, B_WILL_DRAW, new BGroupLayout(orientation, spacing)),
|
||||||
|
fModel(NULL),
|
||||||
|
fItemRenderer(NULL),
|
||||||
|
fGroupRenderer(NULL),
|
||||||
|
fSelectionMessage(NULL)
|
||||||
|
{
|
||||||
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
SetModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GroupListView::~GroupListView()
|
||||||
|
{
|
||||||
|
delete fModel;
|
||||||
|
delete fItemRenderer;
|
||||||
|
delete fGroupRenderer;
|
||||||
|
delete fSelectionMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::SetModel(GroupListModel* model)
|
||||||
|
{
|
||||||
|
// TODO: remove all previous
|
||||||
|
// TODO: add change mechanism
|
||||||
|
// TODO: use a "virtual" BGroupLayout (ie. one that create its layout items
|
||||||
|
// on the fly).
|
||||||
|
fModel = model;
|
||||||
|
|
||||||
|
std::map<addr_t, BGroupLayout*> groupMap;
|
||||||
|
|
||||||
|
int32 groupCount = model->CountGroups();
|
||||||
|
for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
|
||||||
|
BGroupLayout* groupItem = new BGroupLayout(B_VERTICAL, 0);
|
||||||
|
groupItem->SetVisible(false);
|
||||||
|
AddChild(groupItem);
|
||||||
|
|
||||||
|
void* group = model->GroupAt(groupIndex);
|
||||||
|
groupMap[(addr_t)group] = groupItem;
|
||||||
|
groupItem->AddItem(new RendererLayoutItem(this, groupIndex, group,
|
||||||
|
fGroupRenderer));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 itemCount = model->CountItems();
|
||||||
|
for (int itemIndex = 0; itemIndex < itemCount; itemIndex++) {
|
||||||
|
void* group = model->GroupForItemAt(itemIndex);
|
||||||
|
if (group == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BGroupLayout* groupItem = groupMap[(addr_t)group];
|
||||||
|
if (groupItem == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
groupItem->SetVisible(true);
|
||||||
|
|
||||||
|
RendererLayoutItem* rendererItem = new RendererLayoutItem(this,
|
||||||
|
itemIndex, model->ItemAt(itemIndex), fItemRenderer);
|
||||||
|
groupItem->AddItem(rendererItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::SetItemRenderer(ListItemRenderer* renderer)
|
||||||
|
{
|
||||||
|
fItemRenderer = renderer;
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::SetGroupRenderer(ListItemRenderer* renderer)
|
||||||
|
{
|
||||||
|
fGroupRenderer = renderer;
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::SetSelectionMessage(BMessage* message, BMessenger target)
|
||||||
|
{
|
||||||
|
fSelectionMessage = message;
|
||||||
|
fSelectionTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
default:
|
||||||
|
BView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::MouseDown(BPoint point)
|
||||||
|
{
|
||||||
|
if (fSelectionMessage == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BLayoutItem* item = _ItemAt(GetLayout(), point);
|
||||||
|
|
||||||
|
if (RendererLayoutItem* rendererItem
|
||||||
|
= dynamic_cast<RendererLayoutItem*>(item)) {
|
||||||
|
BMessage message(*fSelectionMessage);
|
||||||
|
|
||||||
|
int32 buttons = 0;
|
||||||
|
if (Window()->CurrentMessage() != NULL)
|
||||||
|
buttons = Window()->CurrentMessage()->FindInt32("buttons");
|
||||||
|
if (buttons != 0)
|
||||||
|
message.AddInt32("buttons", buttons);
|
||||||
|
message.AddInt32("index", rendererItem->Index());
|
||||||
|
message.AddPointer(rendererItem->Renderer() == fGroupRenderer
|
||||||
|
? "group" : "item", rendererItem->Item());
|
||||||
|
|
||||||
|
fSelectionTarget.SendMessage(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
_Draw(GetLayout(), updateRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupListView::_Draw(BLayoutItem* item, BRect updateRect)
|
||||||
|
{
|
||||||
|
if (RendererLayoutItem* rendererItem
|
||||||
|
= dynamic_cast<RendererLayoutItem*>(item)) {
|
||||||
|
ListItemRenderer* renderer = rendererItem->Renderer();
|
||||||
|
renderer->Draw(this, rendererItem->Frame(), rendererItem->Index(),
|
||||||
|
false);
|
||||||
|
} else if (BLayout* layout = dynamic_cast<BLayout*>(item)) {
|
||||||
|
for (int i = 0; i < layout->CountItems(); i++) {
|
||||||
|
item = layout->ItemAt(i);
|
||||||
|
if (!item->IsVisible() || !item->Frame().Intersects(updateRect))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_Draw(item, updateRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BLayoutItem*
|
||||||
|
GroupListView::_ItemAt(BLayoutItem* item, BPoint point)
|
||||||
|
{
|
||||||
|
if (RendererLayoutItem* rendererItem
|
||||||
|
= dynamic_cast<RendererLayoutItem*>(item))
|
||||||
|
return rendererItem;
|
||||||
|
|
||||||
|
if (BLayout* layout = dynamic_cast<BLayout*>(item)) {
|
||||||
|
for (int i = 0; i < layout->CountItems(); i++) {
|
||||||
|
item = layout->ItemAt(i);
|
||||||
|
if (!item->IsVisible() || !item->Frame().Contains(point))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return _ItemAt(item, point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef GROUP_LIST_VIEW_H
|
||||||
|
#define GROUP_LIST_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <GroupView.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
|
||||||
|
class GroupListModel {
|
||||||
|
public:
|
||||||
|
virtual int32 CountItems() = 0;
|
||||||
|
virtual void* ItemAt(int32 index) = 0;
|
||||||
|
|
||||||
|
virtual int32 CountGroups() = 0;
|
||||||
|
virtual void* GroupAt(int32 index) = 0;
|
||||||
|
virtual void* GroupForItemAt(int32 index) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename ItemType, typename GroupType>
|
||||||
|
class TypedGroupListModel : public GroupListModel {
|
||||||
|
public:
|
||||||
|
virtual ItemType* ItemAt(int32 index) = 0;
|
||||||
|
|
||||||
|
virtual GroupType* GroupAt(int32 index) = 0;
|
||||||
|
virtual GroupType* GroupForItemAt(int32 index) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ListItemRenderer {
|
||||||
|
public:
|
||||||
|
virtual void SetTo(BView* owner, void* item) = 0;
|
||||||
|
|
||||||
|
virtual BSize MinSize() = 0;
|
||||||
|
virtual BSize MaxSize() = 0;
|
||||||
|
virtual BSize PreferredSize() = 0;
|
||||||
|
|
||||||
|
virtual void Draw(BView* owner, BRect frame, int32 index,
|
||||||
|
bool selected) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GroupListView : public BView {
|
||||||
|
public:
|
||||||
|
GroupListView(const char* name,
|
||||||
|
GroupListModel* model = NULL,
|
||||||
|
enum orientation orientation = B_VERTICAL,
|
||||||
|
float spacing = 0);
|
||||||
|
virtual ~GroupListView();
|
||||||
|
|
||||||
|
GroupListModel* Model() const
|
||||||
|
{ return fModel; }
|
||||||
|
virtual void SetModel(GroupListModel* model);
|
||||||
|
|
||||||
|
ListItemRenderer* ItemRenderer() const
|
||||||
|
{ return fItemRenderer; }
|
||||||
|
virtual void SetItemRenderer(ListItemRenderer* renderer);
|
||||||
|
ListItemRenderer* GroupRenderer() const
|
||||||
|
{ return fGroupRenderer; }
|
||||||
|
virtual void SetGroupRenderer(ListItemRenderer* renderer);
|
||||||
|
|
||||||
|
BMessage* SelectionMessage() const
|
||||||
|
{ return fSelectionMessage; }
|
||||||
|
virtual void SetSelectionMessage(BMessage* message,
|
||||||
|
BMessenger target);
|
||||||
|
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual void MouseDown(BPoint point);
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Draw(BLayoutItem* item, BRect updateRect);
|
||||||
|
BLayoutItem* _ItemAt(BLayoutItem* item, BPoint point);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GroupListModel* fModel;
|
||||||
|
ListItemRenderer* fItemRenderer;
|
||||||
|
ListItemRenderer* fGroupRenderer;
|
||||||
|
|
||||||
|
BMessage* fSelectionMessage;
|
||||||
|
BMessenger fSelectionTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GROUP_LIST_VIEW_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
SubDir HAIKU_TOP src apps switcher ;
|
||||||
|
|
||||||
|
UsePrivateHeaders app interface shared ;
|
||||||
|
|
||||||
|
Application Switcher :
|
||||||
|
ApplicationsView.cpp
|
||||||
|
CaptureWindow.cpp
|
||||||
|
GroupListView.cpp
|
||||||
|
LaunchButton.cpp
|
||||||
|
PanelWindow.cpp
|
||||||
|
Switcher.cpp
|
||||||
|
WindowsView.cpp
|
||||||
|
|
||||||
|
: be translation $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) libshared.a
|
||||||
|
: Switcher.rdef
|
||||||
|
;
|
||||||
@@ -0,0 +1,397 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2009, Stephan Aßmus <[email protected]>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "LaunchButton.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <AppDefs.h>
|
||||||
|
#include <AppFileInfo.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Catalog.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Region.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFAULT_ICON_SIZE 64
|
||||||
|
|
||||||
|
#undef B_TRANSLATE_CONTEXT
|
||||||
|
#define B_TRANSLATE_CONTEXT "LaunchBox"
|
||||||
|
|
||||||
|
|
||||||
|
static const float kDragStartDist = 10.0;
|
||||||
|
static const float kDragBitmapAlphaScale = 0.6;
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t LaunchButton::sClickSpeed = 0;
|
||||||
|
bool LaunchButton::sIgnoreDoubleClick = true;
|
||||||
|
|
||||||
|
|
||||||
|
LaunchButton::LaunchButton(const char* name, const char* label,
|
||||||
|
BMessage* message, BHandler* target)
|
||||||
|
:
|
||||||
|
BIconButton(name, label, message, target),
|
||||||
|
fRef(NULL),
|
||||||
|
fAppSig(NULL),
|
||||||
|
fDescription(""),
|
||||||
|
fAnticipatingDrop(false),
|
||||||
|
fLastClickTime(0),
|
||||||
|
fIconSize(DEFAULT_ICON_SIZE)
|
||||||
|
{
|
||||||
|
if (sClickSpeed == 0 || get_click_speed(&sClickSpeed) != B_OK)
|
||||||
|
sClickSpeed = 500000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LaunchButton::~LaunchButton()
|
||||||
|
{
|
||||||
|
delete fRef;
|
||||||
|
free(fAppSig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BIconButton::AttachedToWindow();
|
||||||
|
_UpdateToolTip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
if (fAnticipatingDrop) {
|
||||||
|
rgb_color color = fRef ? ui_color(B_KEYBOARD_NAVIGATION_COLOR)
|
||||||
|
: (rgb_color){ 0, 130, 60, 255 };
|
||||||
|
SetHighColor(color);
|
||||||
|
// limit clipping region to exclude the blue rect we just drew
|
||||||
|
BRect r(Bounds());
|
||||||
|
StrokeRect(r);
|
||||||
|
r.InsetBy(1.0, 1.0);
|
||||||
|
BRegion region(r);
|
||||||
|
ConstrainClippingRegion(®ion);
|
||||||
|
}
|
||||||
|
if (IsValid()) {
|
||||||
|
BIconButton::Draw(updateRect);
|
||||||
|
} else {
|
||||||
|
rgb_color background = LowColor();
|
||||||
|
rgb_color lightShadow = tint_color(background,
|
||||||
|
(B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
|
||||||
|
rgb_color shadow = tint_color(background, B_DARKEN_1_TINT);
|
||||||
|
rgb_color light = tint_color(background, B_LIGHTEN_1_TINT);
|
||||||
|
BRect r(Bounds());
|
||||||
|
_DrawFrame(r, shadow, light, lightShadow, lightShadow);
|
||||||
|
r.InsetBy(2.0, 2.0);
|
||||||
|
SetHighColor(lightShadow);
|
||||||
|
FillRect(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case B_SIMPLE_DATA:
|
||||||
|
case B_REFS_RECEIVED: {
|
||||||
|
entry_ref ref;
|
||||||
|
if (message->FindRef("refs", &ref) == B_OK) {
|
||||||
|
if (fRef) {
|
||||||
|
if (ref != *fRef) {
|
||||||
|
BEntry entry(fRef, true);
|
||||||
|
if (entry.IsDirectory()) {
|
||||||
|
message->PrintToStream();
|
||||||
|
// copy stuff into the directory
|
||||||
|
} else {
|
||||||
|
message->what = B_REFS_RECEIVED;
|
||||||
|
team_id team;
|
||||||
|
if (fAppSig)
|
||||||
|
team = be_roster->TeamFor(fAppSig);
|
||||||
|
else
|
||||||
|
team = be_roster->TeamFor(fRef);
|
||||||
|
if (team < 0) {
|
||||||
|
if (fAppSig)
|
||||||
|
be_roster->Launch(fAppSig, message, &team);
|
||||||
|
else
|
||||||
|
be_roster->Launch(fRef, message, &team);
|
||||||
|
} else {
|
||||||
|
app_info appInfo;
|
||||||
|
if (team >= 0
|
||||||
|
&& be_roster->GetRunningAppInfo(team,
|
||||||
|
&appInfo) == B_OK) {
|
||||||
|
BMessenger messenger(appInfo.signature,
|
||||||
|
team);
|
||||||
|
if (messenger.IsValid())
|
||||||
|
messenger.SendMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetTo(&ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case B_PASTE:
|
||||||
|
case B_MODIFIERS_CHANGED:
|
||||||
|
default:
|
||||||
|
BIconButton::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
bigtime_t now = system_time();
|
||||||
|
bool callInherited = true;
|
||||||
|
if (sIgnoreDoubleClick && now - fLastClickTime < sClickSpeed)
|
||||||
|
callInherited = false;
|
||||||
|
fLastClickTime = now;
|
||||||
|
if (BMessage* message = Window()->CurrentMessage()) {
|
||||||
|
uint32 buttons;
|
||||||
|
message->FindInt32("buttons", (int32*)&buttons);
|
||||||
|
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0 && IsInside()) {
|
||||||
|
// context menu?
|
||||||
|
} else
|
||||||
|
fDragStart = where;
|
||||||
|
}
|
||||||
|
if (callInherited)
|
||||||
|
BIconButton::MouseDown(where);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::MouseUp(BPoint where)
|
||||||
|
{
|
||||||
|
if (fAnticipatingDrop) {
|
||||||
|
fAnticipatingDrop = false;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
BIconButton::MouseUp(where);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::MouseMoved(BPoint where, uint32 transit,
|
||||||
|
const BMessage* dragMessage)
|
||||||
|
{
|
||||||
|
if ((dragMessage && (transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW))
|
||||||
|
&& ((dragMessage->what == B_SIMPLE_DATA
|
||||||
|
|| dragMessage->what == B_REFS_RECEIVED) || fRef)) {
|
||||||
|
if (!fAnticipatingDrop) {
|
||||||
|
fAnticipatingDrop = true;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dragMessage || (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)) {
|
||||||
|
if (fAnticipatingDrop) {
|
||||||
|
fAnticipatingDrop = false;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BIconButton::MouseMoved(where, transit, dragMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
LaunchButton::MinSize()
|
||||||
|
{
|
||||||
|
return PreferredSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
LaunchButton::PreferredSize()
|
||||||
|
{
|
||||||
|
float minWidth = fIconSize;
|
||||||
|
float minHeight = fIconSize;
|
||||||
|
|
||||||
|
float hPadding = max_c(6.0, ceilf(minHeight / 3.0));
|
||||||
|
float vPadding = max_c(6.0, ceilf(minWidth / 3.0));
|
||||||
|
|
||||||
|
if (Label() != NULL && Label()[0] != '\0') {
|
||||||
|
font_height fh;
|
||||||
|
GetFontHeight(&fh);
|
||||||
|
minHeight += ceilf(fh.ascent + fh.descent) + vPadding;
|
||||||
|
minWidth += StringWidth(Label()) + vPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BSize(minWidth + hPadding, minHeight + vPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
LaunchButton::MaxSize()
|
||||||
|
{
|
||||||
|
return PreferredSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::SetTo(const entry_ref* ref)
|
||||||
|
{
|
||||||
|
free(fAppSig);
|
||||||
|
fAppSig = NULL;
|
||||||
|
|
||||||
|
delete fRef;
|
||||||
|
if (ref) {
|
||||||
|
fRef = new entry_ref(*ref);
|
||||||
|
// follow links
|
||||||
|
BEntry entry(fRef, true);
|
||||||
|
entry.GetRef(fRef);
|
||||||
|
|
||||||
|
_UpdateIcon(fRef);
|
||||||
|
// see if this is an application
|
||||||
|
BFile file(ref, B_READ_ONLY);
|
||||||
|
BAppFileInfo info;
|
||||||
|
if (info.SetTo(&file) == B_OK) {
|
||||||
|
char mimeSig[B_MIME_TYPE_LENGTH];
|
||||||
|
if (info.GetSignature(mimeSig) == B_OK) {
|
||||||
|
SetTo(mimeSig, false);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "no MIME signature for '%s'\n", fRef->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "no BAppFileInfo for '%s'\n", fRef->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fRef = NULL;
|
||||||
|
ClearIcon();
|
||||||
|
}
|
||||||
|
_UpdateToolTip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
entry_ref*
|
||||||
|
LaunchButton::Ref() const
|
||||||
|
{
|
||||||
|
return fRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::SetTo(const char* appSig, bool updateIcon)
|
||||||
|
{
|
||||||
|
if (appSig) {
|
||||||
|
free(fAppSig);
|
||||||
|
fAppSig = strdup(appSig);
|
||||||
|
if (updateIcon) {
|
||||||
|
entry_ref ref;
|
||||||
|
if (be_roster->FindApp(fAppSig, &ref) == B_OK)
|
||||||
|
SetTo(&ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_UpdateToolTip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::SetDescription(const char* text)
|
||||||
|
{
|
||||||
|
fDescription.SetTo(text);
|
||||||
|
_UpdateToolTip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::SetIconSize(uint32 size)
|
||||||
|
{
|
||||||
|
if (fIconSize == size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fIconSize = size;
|
||||||
|
_UpdateIcon(fRef);
|
||||||
|
|
||||||
|
InvalidateLayout();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::SetIgnoreDoubleClick(bool refuse)
|
||||||
|
{
|
||||||
|
sIgnoreDoubleClick = refuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::_UpdateToolTip()
|
||||||
|
{
|
||||||
|
// TODO: This works around a bug in the tool tip management.
|
||||||
|
// Remove when fixed (although no harm done...)
|
||||||
|
HideToolTip();
|
||||||
|
SetToolTip(static_cast<BToolTip*>(NULL));
|
||||||
|
|
||||||
|
if (fRef) {
|
||||||
|
BString helper(fRef->name);
|
||||||
|
if (fDescription.CountChars() > 0) {
|
||||||
|
if (fDescription != helper)
|
||||||
|
helper << "\n\n" << fDescription.String();
|
||||||
|
} else {
|
||||||
|
BFile file(fRef, B_READ_ONLY);
|
||||||
|
BAppFileInfo appFileInfo;
|
||||||
|
version_info info;
|
||||||
|
if (appFileInfo.SetTo(&file) == B_OK
|
||||||
|
&& appFileInfo.GetVersionInfo(&info,
|
||||||
|
B_APP_VERSION_KIND) == B_OK
|
||||||
|
&& strlen(info.short_info) > 0
|
||||||
|
&& helper.Compare(info.short_info) != 0) {
|
||||||
|
helper << "\n\n" << info.short_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetToolTip(helper.String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::_UpdateIcon(const entry_ref* ref)
|
||||||
|
{
|
||||||
|
BBitmap* icon = new BBitmap(BRect(0.0, 0.0, fIconSize - 1,
|
||||||
|
fIconSize - 1), B_RGBA32);
|
||||||
|
// NOTE: passing an invalid/unknown icon_size argument will cause
|
||||||
|
// the BNodeInfo to ignore it and just use the bitmap bounds.
|
||||||
|
if (BNodeInfo::GetTrackerIcon(ref, icon, (icon_size)fIconSize) == B_OK)
|
||||||
|
SetIcon(icon);
|
||||||
|
|
||||||
|
delete icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchButton::_DrawFrame(BRect r, rgb_color col1, rgb_color col2,
|
||||||
|
rgb_color col3, rgb_color col4)
|
||||||
|
{
|
||||||
|
BeginLineArray(8);
|
||||||
|
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col1);
|
||||||
|
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col1);
|
||||||
|
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col2);
|
||||||
|
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col2);
|
||||||
|
r.InsetBy(1.0, 1.0);
|
||||||
|
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col3);
|
||||||
|
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col3);
|
||||||
|
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col4);
|
||||||
|
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col4);
|
||||||
|
EndLineArray();
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006-2011, Stephan Aßmus <[email protected]>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef LAUNCH_BUTTON_H
|
||||||
|
#define LAUNCH_BUTTON_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <IconButton.h>
|
||||||
|
#include <List.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSG_ADD_SLOT = 'adsl',
|
||||||
|
MSG_CLEAR_SLOT = 'clsl',
|
||||||
|
MSG_REMOVE_SLOT = 'rmsl',
|
||||||
|
MSG_LAUNCH = 'lnch',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LaunchButton : public BIconButton {
|
||||||
|
public:
|
||||||
|
LaunchButton(const char* name,
|
||||||
|
const char* label = NULL,
|
||||||
|
BMessage* message = NULL,
|
||||||
|
BHandler* target = NULL);
|
||||||
|
virtual ~LaunchButton();
|
||||||
|
|
||||||
|
// BIconButton interface
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual void MouseDown(BPoint where);
|
||||||
|
virtual void MouseUp(BPoint where);
|
||||||
|
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||||
|
const BMessage* dragMessage);
|
||||||
|
|
||||||
|
virtual BSize MinSize();
|
||||||
|
virtual BSize PreferredSize();
|
||||||
|
virtual BSize MaxSize();
|
||||||
|
|
||||||
|
// LaunchButton
|
||||||
|
void SetTo(const entry_ref* ref);
|
||||||
|
entry_ref* Ref() const;
|
||||||
|
|
||||||
|
void SetTo(const char* appSig, bool updateIcon);
|
||||||
|
const char* AppSignature() const
|
||||||
|
{ return fAppSig; }
|
||||||
|
|
||||||
|
void SetDescription(const char* text);
|
||||||
|
const char* Description() const
|
||||||
|
{ return fDescription.String(); }
|
||||||
|
|
||||||
|
void SetIconSize(uint32 size);
|
||||||
|
uint32 IconSize() const
|
||||||
|
{ return fIconSize; }
|
||||||
|
|
||||||
|
static void SetIgnoreDoubleClick(bool refuse);
|
||||||
|
static bool IgnoreDoubleClick()
|
||||||
|
{ return sIgnoreDoubleClick; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _UpdateToolTip();
|
||||||
|
void _UpdateIcon(const entry_ref* ref);
|
||||||
|
|
||||||
|
void _DrawFrame(BRect frame,
|
||||||
|
rgb_color left, rgb_color top,
|
||||||
|
rgb_color right, rgb_color bottom);
|
||||||
|
|
||||||
|
private:
|
||||||
|
entry_ref* fRef;
|
||||||
|
char* fAppSig;
|
||||||
|
BString fDescription;
|
||||||
|
|
||||||
|
bool fAnticipatingDrop;
|
||||||
|
bigtime_t fLastClickTime;
|
||||||
|
BPoint fDragStart;
|
||||||
|
|
||||||
|
uint32 fIconSize;
|
||||||
|
|
||||||
|
static bigtime_t sClickSpeed;
|
||||||
|
static bool sIgnoreDoubleClick;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LAUNCH_BUTTON_H
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "PanelWindow.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <GroupLayout.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
|
||||||
|
#include "ApplicationsView.h"
|
||||||
|
#include "GroupListView.h"
|
||||||
|
#include "Switcher.h"
|
||||||
|
#include "WindowsView.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgShow = 'SHOW';
|
||||||
|
static const uint32 kMsgHide = 'HIDE';
|
||||||
|
|
||||||
|
static const int32 kMinShowState = 0;
|
||||||
|
static const int32 kMaxShowState = 4;
|
||||||
|
static const bigtime_t kMoveDelay = 15000;
|
||||||
|
// 25 ms
|
||||||
|
|
||||||
|
|
||||||
|
PanelWindow::PanelWindow(uint32 location, uint32 which, team_id team)
|
||||||
|
:
|
||||||
|
BWindow(BRect(-16000, -16000, -15900, -15900), "panel",
|
||||||
|
B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL,
|
||||||
|
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_AVOID_FOCUS,
|
||||||
|
B_ALL_WORKSPACES),
|
||||||
|
fLocation(location),
|
||||||
|
fShowState(kMinShowState)
|
||||||
|
{
|
||||||
|
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||||
|
|
||||||
|
BView* child = _ViewFor(location, which, team);
|
||||||
|
if (child != NULL)
|
||||||
|
AddChild(child);
|
||||||
|
|
||||||
|
Run();
|
||||||
|
PostMessage(kMsgShow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PanelWindow::~PanelWindow()
|
||||||
|
{
|
||||||
|
BMessage message(kMsgLocationFree);
|
||||||
|
message.AddInt32("location", fLocation);
|
||||||
|
be_app->PostMessage(&message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PanelWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgShow:
|
||||||
|
case kMsgHide:
|
||||||
|
_UpdateShowState(message->what);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BView*
|
||||||
|
PanelWindow::_ViewFor(uint32 location, uint32 which, team_id team) const
|
||||||
|
{
|
||||||
|
switch (which) {
|
||||||
|
case kShowApplications:
|
||||||
|
return new ApplicationsView(location);
|
||||||
|
case kShowApplicationWindows:
|
||||||
|
return new WindowsView(team, location);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PanelWindow::_UpdateShowState(uint32 how)
|
||||||
|
{
|
||||||
|
if ((how == kMsgShow && fShowState >= kMaxShowState)
|
||||||
|
|| (how == kMsgHide && fShowState <= kMinShowState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fShowState += how == kMsgShow ? 1 : -1;
|
||||||
|
|
||||||
|
// Compute start and end position depending on the location
|
||||||
|
// TODO: multi-screen support
|
||||||
|
BScreen screen;
|
||||||
|
BRect screenFrame = screen.Frame();
|
||||||
|
BPoint from;
|
||||||
|
BPoint to;
|
||||||
|
|
||||||
|
switch (fLocation) {
|
||||||
|
case kLeftEdge:
|
||||||
|
case kRightEdge:
|
||||||
|
from.y = screenFrame.top
|
||||||
|
+ (screenFrame.Height() - Bounds().Height()) / 2.f;
|
||||||
|
to.y = from.y;
|
||||||
|
break;
|
||||||
|
case kTopEdge:
|
||||||
|
case kBottomEdge:
|
||||||
|
from.x = screenFrame.left
|
||||||
|
+ (screenFrame.Width() - Bounds().Width()) / 2.f;
|
||||||
|
to.x = from.x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fLocation) {
|
||||||
|
case kLeftEdge:
|
||||||
|
from.x = screenFrame.left - Bounds().Width();
|
||||||
|
to.x = screenFrame.left;
|
||||||
|
break;
|
||||||
|
case kRightEdge:
|
||||||
|
from.x = screenFrame.right;
|
||||||
|
to.x = screenFrame.right - Bounds().Width();
|
||||||
|
break;
|
||||||
|
case kTopEdge:
|
||||||
|
from.y = screenFrame.top - Bounds().Height();
|
||||||
|
to.y = screenFrame.top;
|
||||||
|
break;
|
||||||
|
case kBottomEdge:
|
||||||
|
from.y = screenFrame.bottom;
|
||||||
|
to.y = screenFrame.bottom - Bounds().Height();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveTo(from.x + _Factor() * (to.x - from.x),
|
||||||
|
from.y + _Factor() * (to.y - from.y));
|
||||||
|
|
||||||
|
if (kMsgShow && IsHidden())
|
||||||
|
Show();
|
||||||
|
else if (fShowState == 0 && kMsgHide && !IsHidden())
|
||||||
|
Quit();
|
||||||
|
|
||||||
|
if ((how == kMsgShow && fShowState < kMaxShowState)
|
||||||
|
|| (how == kMsgHide && fShowState > kMinShowState)) {
|
||||||
|
BMessage move(how);
|
||||||
|
BMessageRunner::StartSending(this, &move, kMoveDelay, 1);
|
||||||
|
} else if (how == kMsgShow) {
|
||||||
|
// Hide the window once the mouse left its frame
|
||||||
|
BMessage hide(kMsgHideWhenMouseMovedOut);
|
||||||
|
hide.AddMessenger("target", this);
|
||||||
|
hide.AddInt32("what", kMsgHide);
|
||||||
|
|
||||||
|
// The window might not span over the whole screen, but one dimension
|
||||||
|
// should be ignored for the cursor movements
|
||||||
|
BRect frame = Frame();
|
||||||
|
switch (fLocation) {
|
||||||
|
case kLeftEdge:
|
||||||
|
case kRightEdge:
|
||||||
|
frame.top = screenFrame.top;
|
||||||
|
frame.bottom = screenFrame.bottom;
|
||||||
|
break;
|
||||||
|
case kTopEdge:
|
||||||
|
case kBottomEdge:
|
||||||
|
frame.left = screenFrame.left;
|
||||||
|
frame.right = screenFrame.right;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hide.AddRect("frame", frame);
|
||||||
|
be_app->PostMessage(&hide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
PanelWindow::_Factor()
|
||||||
|
{
|
||||||
|
float factor = 1.f * fShowState / kMaxShowState;
|
||||||
|
return 1 - (factor - 1) * (factor - 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PANEL_WINDOW_H
|
||||||
|
#define PANEL_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
class PanelWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
PanelWindow(uint32 location, uint32 which,
|
||||||
|
team_id team);
|
||||||
|
virtual ~PanelWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BView* _ViewFor(uint32 location, uint32 which,
|
||||||
|
team_id team) const;
|
||||||
|
void _UpdateShowState(uint32 how);
|
||||||
|
float _Factor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fLocation;
|
||||||
|
int32 fShowState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PANEL_WINDOW_H
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Switcher.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Catalog.h>
|
||||||
|
|
||||||
|
#include "CaptureWindow.h"
|
||||||
|
#include "PanelWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef B_TRANSLATE_CONTEXT
|
||||||
|
#define B_TRANSLATE_CONTEXT "Switcher"
|
||||||
|
|
||||||
|
|
||||||
|
const char* kSignature = "application/x-vnd.Haiku-Switcher";
|
||||||
|
|
||||||
|
|
||||||
|
Switcher::Switcher()
|
||||||
|
:
|
||||||
|
BApplication(kSignature),
|
||||||
|
fOccupiedLocations(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Switcher::~Switcher()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Switcher::ReadyToRun()
|
||||||
|
{
|
||||||
|
CaptureWindow* window = new CaptureWindow();
|
||||||
|
window->Run();
|
||||||
|
|
||||||
|
fCaptureMessenger = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Switcher::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgLocationTrigger:
|
||||||
|
{
|
||||||
|
uint32 location = (uint32)message->FindInt32("location");
|
||||||
|
if ((location & fOccupiedLocations) == 0) {
|
||||||
|
// TODO: make function configurable
|
||||||
|
uint32 which = kShowApplicationWindows;
|
||||||
|
if ((location & (kTopEdge | kBottomEdge)) != 0)
|
||||||
|
which = kShowApplications;
|
||||||
|
|
||||||
|
new PanelWindow(location, which,
|
||||||
|
(team_id)message->FindInt32("team"));
|
||||||
|
fOccupiedLocations |= location;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgLocationFree:
|
||||||
|
{
|
||||||
|
uint32 location;
|
||||||
|
if (message->FindInt32("location", (int32*)&location) == B_OK)
|
||||||
|
fOccupiedLocations &= ~location;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgHideWhenMouseMovedOut:
|
||||||
|
fCaptureMessenger.SendMessage(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BApplication::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int /*argc*/, char** /*argv*/)
|
||||||
|
{
|
||||||
|
Switcher app;
|
||||||
|
app.Run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef SWITCHER_H
|
||||||
|
#define SWITCHER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kNowhere = 0,
|
||||||
|
kTopEdge = 0x01,
|
||||||
|
kBottomEdge = 0x02,
|
||||||
|
kLeftEdge = 0x04,
|
||||||
|
kRightEdge = 0x08,
|
||||||
|
// TODO: not yet supported
|
||||||
|
kTopLeftCorner = 0x10,
|
||||||
|
kTopRightCorner = 0x20,
|
||||||
|
kBottomLeftCorner = 0x40,
|
||||||
|
kBottomRightCorner = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kShowApplications,
|
||||||
|
kShowApplicationWindows,
|
||||||
|
kShowWorkspaceWindows,
|
||||||
|
kShowAllWindows,
|
||||||
|
kShowWorkspaces,
|
||||||
|
kShowShelf,
|
||||||
|
kShowFavorites,
|
||||||
|
kShowRecentFiles,
|
||||||
|
kShowFilesClipboard,
|
||||||
|
kShowFolder,
|
||||||
|
kShowQuery
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgLocationTrigger = 'LoTr';
|
||||||
|
static const uint32 kMsgLocationFree = 'LoFr';
|
||||||
|
static const uint32 kMsgHideWhenMouseMovedOut = 'HwMo';
|
||||||
|
|
||||||
|
|
||||||
|
class Switcher : public BApplication {
|
||||||
|
public:
|
||||||
|
Switcher();
|
||||||
|
virtual ~Switcher();
|
||||||
|
|
||||||
|
virtual void ReadyToRun();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessenger fCaptureMessenger;
|
||||||
|
uint32 fOccupiedLocations;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const char* kSignature;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SWITCHER_H
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
resource app_signature "application/x-vnd.Haiku-Switcher";
|
||||||
|
|
||||||
|
//resource app_name_catalog_entry "x-vnd.Haiku-Switcher:System name:Switcher";
|
||||||
|
|
||||||
|
resource app_version {
|
||||||
|
major = 1,
|
||||||
|
middle = 0,
|
||||||
|
minor = 0,
|
||||||
|
|
||||||
|
variety = B_APPV_BETA,
|
||||||
|
internal = 0,
|
||||||
|
|
||||||
|
short_info = "Switcher",
|
||||||
|
long_info = "Switcher ©2011 Haiku, Inc."
|
||||||
|
};
|
||||||
|
|
||||||
|
resource app_flags B_SINGLE_LAUNCH | B_BACKGROUND_APP;
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "WindowsView.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <LayoutBuilder.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
|
||||||
|
#include <MessengerPrivate.h>
|
||||||
|
#include <WindowInfo.h>
|
||||||
|
#include <WindowPrivate.h>
|
||||||
|
|
||||||
|
#include "GroupListView.h"
|
||||||
|
#include "LaunchButton.h"
|
||||||
|
#include "Switcher.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgActivateWindow = 'AcWn';
|
||||||
|
|
||||||
|
|
||||||
|
class WindowModel : public TypedGroupListModel<client_window_info, void> {
|
||||||
|
public:
|
||||||
|
WindowModel(team_id team)
|
||||||
|
:
|
||||||
|
fWindows(true),
|
||||||
|
fWorkspaces(0),
|
||||||
|
fWorkspaceCount(0)
|
||||||
|
{
|
||||||
|
// TODO: more than one team via signature!
|
||||||
|
int32 count;
|
||||||
|
int32* tokens = get_token_list(team, &count);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
client_window_info* info = get_window_info(tokens[i]);
|
||||||
|
if (!_WindowShouldBeListed(info)) {
|
||||||
|
free(info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fWorkspaces |= info->workspaces;
|
||||||
|
fWindows.AddItem(info);
|
||||||
|
}
|
||||||
|
free(tokens);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < 32; i++) {
|
||||||
|
if ((fWorkspaces & (1UL << i)) != 0)
|
||||||
|
fWorkspaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fWindows.SortItems(&_CompareWindowInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~WindowModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BringToFront(int32 index)
|
||||||
|
{
|
||||||
|
client_window_info* info = fWindows.ItemAt(index);
|
||||||
|
if (info == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do_window_action(info->server_token, B_BRING_TO_FRONT, BRect(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close(int32 index)
|
||||||
|
{
|
||||||
|
client_window_info* info = fWindows.ItemAt(index);
|
||||||
|
if (info == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BMessenger window;
|
||||||
|
BMessenger::Private(window).SetTo(info->team, info->client_port,
|
||||||
|
info->client_token);
|
||||||
|
window.SendMessage(B_QUIT_REQUESTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 CountItems()
|
||||||
|
{
|
||||||
|
return fWindows.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual client_window_info* ItemAt(int32 index)
|
||||||
|
{
|
||||||
|
return fWindows.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 CountGroups()
|
||||||
|
{
|
||||||
|
return fWorkspaceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* GroupAt(int32 index)
|
||||||
|
{
|
||||||
|
return (void*)(_NthSetBit(index, fWorkspaces) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* GroupForItemAt(int32 index)
|
||||||
|
{
|
||||||
|
client_window_info* info = ItemAt(index);
|
||||||
|
return (void*)(_NthSetBit(0, info->workspaces) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _WindowShouldBeListed(client_window_info* info)
|
||||||
|
{
|
||||||
|
return info != NULL
|
||||||
|
&& (info->feel == B_NORMAL_WINDOW_FEEL
|
||||||
|
|| info->feel == kWindowScreenFeel)
|
||||||
|
&& (info->show_hide_level <= 0 || info->is_mini);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 _NthSetBit(int32 index, uint32 mask)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < 32; i++) {
|
||||||
|
if ((mask & (1UL << i)) != 0) {
|
||||||
|
if (index-- == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _CompareWindowInfo(const client_window_info* a,
|
||||||
|
const client_window_info* b)
|
||||||
|
{
|
||||||
|
return strcasecmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BObjectList<client_window_info> fWindows;
|
||||||
|
uint32 fWorkspaces;
|
||||||
|
int32 fWorkspaceCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StringItemRenderer : public ListItemRenderer {
|
||||||
|
public:
|
||||||
|
StringItemRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~StringItemRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetText(BView* owner, const BString& text)
|
||||||
|
{
|
||||||
|
fText = text;
|
||||||
|
owner->TruncateString(&fText, B_TRUNCATE_MIDDLE, 200);
|
||||||
|
SetWidth((int32)ceilf(owner->StringWidth(fText.String())));
|
||||||
|
|
||||||
|
font_height fontHeight;
|
||||||
|
owner->GetFontHeight(&fontHeight);
|
||||||
|
|
||||||
|
SetBaselineOffset(
|
||||||
|
2 + (int32)ceilf(fontHeight.ascent + fontHeight.leading / 2));
|
||||||
|
|
||||||
|
SetHeight((int32)ceilf(fontHeight.ascent)
|
||||||
|
+ (int32)ceilf(fontHeight.descent)
|
||||||
|
+ (int32)ceilf(fontHeight.leading) + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetWidth(int32 width)
|
||||||
|
{
|
||||||
|
fWidth = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetHeight(int32 height)
|
||||||
|
{
|
||||||
|
fHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetBaselineOffset(int32 offset)
|
||||||
|
{
|
||||||
|
fBaselineOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BString& Text() const
|
||||||
|
{
|
||||||
|
return fText;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize MinSize()
|
||||||
|
{
|
||||||
|
return BSize(fWidth, fHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize MaxSize()
|
||||||
|
{
|
||||||
|
return BSize(B_SIZE_UNLIMITED, fHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BSize PreferredSize()
|
||||||
|
{
|
||||||
|
return BSize(fWidth, fHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||||
|
{
|
||||||
|
owner->SetLowColor(owner->ViewColor());
|
||||||
|
owner->MovePenTo(frame.left, frame.top + fBaselineOffset);
|
||||||
|
owner->DrawString(fText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fText;
|
||||||
|
int32 fWidth;
|
||||||
|
int32 fHeight;
|
||||||
|
int32 fBaselineOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WorkspaceRenderer : public StringItemRenderer {
|
||||||
|
public:
|
||||||
|
virtual void SetTo(BView* owner, void* item)
|
||||||
|
{
|
||||||
|
fWorkspace = (uint32)item;
|
||||||
|
|
||||||
|
if ((uint32)current_workspace() == fWorkspace - 1)
|
||||||
|
SetText(owner, "Current workspace");
|
||||||
|
else {
|
||||||
|
BString text("Workspace ");
|
||||||
|
text << fWorkspace;
|
||||||
|
SetText(owner, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||||
|
{
|
||||||
|
owner->SetHighColor(tint_color(owner->ViewColor(), B_DARKEN_2_TINT));
|
||||||
|
StringItemRenderer::Draw(owner, frame, index, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fWorkspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WindowRenderer : public StringItemRenderer {
|
||||||
|
public:
|
||||||
|
virtual void SetTo(BView* owner, void* item)
|
||||||
|
{
|
||||||
|
fInfo = (client_window_info*)item;
|
||||||
|
SetText(owner, fInfo->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetWidth(int32 width)
|
||||||
|
{
|
||||||
|
StringItemRenderer::SetWidth(width + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Draw(BView* owner, BRect frame, int32 index, bool selected)
|
||||||
|
{
|
||||||
|
owner->SetHighColor(0, 0, 0);
|
||||||
|
frame.left += 20;
|
||||||
|
StringItemRenderer::Draw(owner, frame, index, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
client_window_info* fInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
WindowsView::WindowsView(team_id team, uint32 location)
|
||||||
|
:
|
||||||
|
BGridView("windows")
|
||||||
|
{
|
||||||
|
app_info info;
|
||||||
|
be_roster->GetRunningAppInfo(team, &info);
|
||||||
|
|
||||||
|
LaunchButton* launchButton = new LaunchButton(info.signature, NULL, NULL,
|
||||||
|
this);
|
||||||
|
launchButton->SetTo(&info.ref);
|
||||||
|
|
||||||
|
BStringView* nameView = new BStringView("name", info.ref.name);
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(font.Size() * 2);
|
||||||
|
font.SetFace(B_BOLD_FACE);
|
||||||
|
nameView->SetFont(&font);
|
||||||
|
|
||||||
|
fListView = new GroupListView("list", new WindowModel(team),
|
||||||
|
_Orientation(location));
|
||||||
|
fListView->SetItemRenderer(new WindowRenderer());
|
||||||
|
fListView->SetGroupRenderer(new WorkspaceRenderer());
|
||||||
|
|
||||||
|
GridLayout()->SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
|
||||||
|
B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
|
||||||
|
|
||||||
|
if (_Orientation(location) == B_HORIZONTAL) {
|
||||||
|
BLayoutBuilder::Grid<>(this)
|
||||||
|
.Add(launchButton, 0, 0)
|
||||||
|
.Add(nameView, 1, 0)
|
||||||
|
.Add(fListView, 2, 0);
|
||||||
|
} else {
|
||||||
|
BLayoutBuilder::Grid<>(this)
|
||||||
|
.Add(launchButton, 0, 0)
|
||||||
|
.Add(nameView, 1, 0)
|
||||||
|
.Add(fListView, 0, 1, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WindowsView::~WindowsView()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WindowsView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
fListView->SetSelectionMessage(new BMessage(kMsgActivateWindow), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WindowsView::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case kMsgActivateWindow:
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
if (message->FindInt32("index", &index) == B_OK
|
||||||
|
&& message->HasPointer("item")) {
|
||||||
|
WindowModel* model = (WindowModel*)fListView->Model();
|
||||||
|
|
||||||
|
if (message->FindInt32("buttons") == B_SECONDARY_MOUSE_BUTTON)
|
||||||
|
model->Close(index);
|
||||||
|
else
|
||||||
|
model->BringToFront(index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BGridView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
orientation
|
||||||
|
WindowsView::_Orientation(uint32 location)
|
||||||
|
{
|
||||||
|
return (location & (kTopEdge | kBottomEdge)) != 0
|
||||||
|
? B_HORIZONTAL : B_VERTICAL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef WINDOWS_VIEW_H
|
||||||
|
#define WINDOWS_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <GridView.h>
|
||||||
|
|
||||||
|
|
||||||
|
class GroupListView;
|
||||||
|
|
||||||
|
|
||||||
|
class WindowsView : public BGridView {
|
||||||
|
public:
|
||||||
|
WindowsView(team_id team, uint32 location);
|
||||||
|
virtual ~WindowsView();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
orientation _Orientation(uint32 location);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GroupListView* fListView;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // WINDOWS_VIEW_H
|
||||||
Reference in New Issue
Block a user