* added LaunchBox, an application launcher with drag&drop support

* it has been rewritten from using liblayout to use the new Haiku
  layout framework
* TODO: it should come with default settings
* TODO: the minimum window size is not yet set by the layout framework (?)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21373 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2007-06-09 12:01:39 +00:00
parent 35169c9564
commit 25648ff020
21 changed files with 2969 additions and 0 deletions
+1
View File
@@ -13,6 +13,7 @@ SubInclude HAIKU_TOP src apps fontdemo ;
SubInclude HAIKU_TOP src apps glteapot ;
SubInclude HAIKU_TOP src apps icon-o-matic ;
SubInclude HAIKU_TOP src apps installer ;
SubInclude HAIKU_TOP src apps launchbox ;
SubInclude HAIKU_TOP src apps magnify ;
SubInclude HAIKU_TOP src apps mail ;
SubInclude HAIKU_TOP src apps mandelbrot ;
+110
View File
@@ -0,0 +1,110 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include <stdio.h>
#include <Alert.h>
#include <Entry.h>
#include <Message.h>
#include <String.h>
#include "support.h"
#include "MainWindow.h"
#include "App.h"
// constructor
App::App()
: BApplication("application/x.vnd-YellowBites.LaunchBox")
{
}
// destructor
App::~App()
{
}
// QuitRequested
bool
App::QuitRequested()
{
BMessage settings('sett');
for (int32 i = 0; BWindow* window = WindowAt(i); i++) {
if (MainWindow* padWindow = dynamic_cast<MainWindow*>(window)) {
BMessage* windowSettings = padWindow->Settings();
if (windowSettings && padWindow->Lock()) {
padWindow->SaveSettings(windowSettings);
padWindow->Unlock();
settings.AddMessage("window", windowSettings);
}
}
}
save_settings(&settings, "main_settings", "LaunchBox");
return true;
}
// ReadyToRun
void
App::ReadyToRun()
{
bool windowAdded = false;
BRect frame(50.0, 50.0, 65.0, 100.0);
BMessage settings('sett');
status_t status = load_settings(&settings, "main_settings", "LaunchBox");
if (status >= B_OK) {
BMessage windowMessage;
for (int32 i = 0; settings.FindMessage("window", i, &windowMessage) >= B_OK; i++) {
BString name("Pad ");
name << i + 1;
BMessage* windowSettings = new BMessage(windowMessage);
MainWindow* window = new MainWindow(name.String(), frame, windowSettings);
window->Show();
windowAdded = true;
frame.OffsetBy(10.0, 10.0);
windowMessage.MakeEmpty();
}
}
if (!windowAdded) {
MainWindow* window = new MainWindow("Pad 1", frame);
window->Show();
}
}
// MessageReceived
void
App::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_ADD_WINDOW: {
BMessage* settings = new BMessage('sett');
message->FindMessage("window", settings);
BString name("Pad ");
name << CountWindows() + 1;
MainWindow* window = new MainWindow(name.String(),
BRect(50.0, 50.0, 65.0, 100.0), settings);
window->Show();
break;
}
default:
BApplication::MessageReceived(message);
break;
}
}
// AboutRequested
void
App::AboutRequested()
{
(new BAlert("about", "LaunchBox by stippi\n\n"
"for bonefish\n\n\n"
"v1.1.0",
"Neat", NULL, NULL))->Go(NULL);
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef APP_H
#define APP_H
#include <Application.h>
#include <List.h>
class MainWindow;
class App : public BApplication {
public:
App();
virtual ~App();
virtual bool QuitRequested();
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
virtual void AboutRequested();
private:
};
#endif // APP_H
+760
View File
@@ -0,0 +1,760 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic
// it should be placed into a common folder for generic useful stuff
#include "IconButton.h"
#include <new>
#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <Control.h>
#include <Entry.h>
#include <Looper.h>
#include <Message.h>
#include <Mime.h>
#include <Path.h>
#include <Region.h>
#include <Roster.h>
#include <TranslationUtils.h>
#include <Window.h>
using std::nothrow;
// constructor
IconButton::IconButton(const char* name, uint32 id, const char* label,
BMessage* message, BHandler* target)
: BView(BRect(0.0, 0.0, 10.0, 10.0), name, B_FOLLOW_NONE, B_WILL_DRAW),
BInvoker(message, target),
fButtonState(STATE_ENABLED),
fID(id),
fNormalBitmap(NULL),
fDisabledBitmap(NULL),
fClickedBitmap(NULL),
fDisabledClickedBitmap(NULL),
fLabel(label),
fTargetCache(target)
{
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetViewColor(B_TRANSPARENT_32_BIT);
}
// destructor
IconButton::~IconButton()
{
_DeleteBitmaps();
}
// MessageReceived
void
IconButton::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BView::MessageReceived(message);
break;
}
}
// AttachedToWindow
void
IconButton::AttachedToWindow()
{
SetTarget(fTargetCache);
if (!Target()) {
SetTarget(Window());
}
}
// Draw
void
IconButton::Draw(BRect area)
{
rgb_color background = LowColor();
if (BView* parent = Parent())
background = parent->ViewColor();
rgb_color lightShadow, shadow, darkShadow, light;
BRect r(Bounds());
BBitmap* bitmap = fNormalBitmap;
// adjust colors and bitmap according to flags
if (IsEnabled()) {
lightShadow = tint_color(background, B_DARKEN_1_TINT);
shadow = tint_color(background, B_DARKEN_2_TINT);
darkShadow = tint_color(background, B_DARKEN_4_TINT);
light = tint_color(background, B_LIGHTEN_MAX_TINT);
SetHighColor(0, 0, 0, 255);
} else {
lightShadow = tint_color(background, 1.11);
shadow = tint_color(background, B_DARKEN_1_TINT);
darkShadow = tint_color(background, B_DARKEN_2_TINT);
light = tint_color(background, B_LIGHTEN_2_TINT);
bitmap = fDisabledBitmap;
SetHighColor(tint_color(background, B_DISABLED_LABEL_TINT));
}
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) {
if (IsEnabled()) {
// background = tint_color(background, B_DARKEN_2_TINT);
// background = tint_color(background, B_LIGHTEN_1_TINT);
background = tint_color(background, B_DARKEN_1_TINT);
bitmap = fClickedBitmap;
} else {
// background = tint_color(background, B_DARKEN_1_TINT);
// background = tint_color(background, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0);
background = tint_color(background, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
bitmap = fDisabledClickedBitmap;
}
// background
SetLowColor(background);
r.InsetBy(2.0, 2.0);
StrokeLine(r.LeftBottom(), r.LeftTop(), B_SOLID_LOW);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_LOW);
r.InsetBy(-2.0, -2.0);
}
// draw frame only if tracking
if (DrawBorder()) {
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
DrawPressedBorder(r, background, shadow, darkShadow, lightShadow, light);
else
DrawNormalBorder(r, background, shadow, darkShadow, lightShadow, light);
r.InsetBy(2.0, 2.0);
} else
_DrawFrame(r, background, background, background, background);
float width = Bounds().Width();
float height = Bounds().Height();
// bitmap
BRegion originalClippingRegion;
if (bitmap && bitmap->IsValid()) {
float x = floorf((width - bitmap->Bounds().Width()) / 2.0 + 0.5);
float y = floorf((height - bitmap->Bounds().Height()) / 2.0 + 0.5);
BPoint point(x, y);
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
point += BPoint(1.0, 1.0);
if (bitmap->ColorSpace() == B_RGBA32 || bitmap->ColorSpace() == B_RGBA32_BIG) {
FillRect(r, B_SOLID_LOW);
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
}
DrawBitmap(bitmap, point);
// constrain clipping region
BRegion region= originalClippingRegion;
GetClippingRegion(&region);
region.Exclude(bitmap->Bounds().OffsetByCopy(point));
ConstrainClippingRegion(&region);
}
// background
SetDrawingMode(B_OP_COPY);
FillRect(r, B_SOLID_LOW);
ConstrainClippingRegion(&originalClippingRegion);
// label
if (fLabel.CountChars() > 0) {
SetDrawingMode(B_OP_COPY);
font_height fh;
GetFontHeight(&fh);
float y = Bounds().bottom - 4.0;
y -= fh.descent;
float x = (width - StringWidth(fLabel.String())) / 2.0;
DrawString(fLabel.String(), BPoint(x, y));
}
}
// MouseDown
void
IconButton::MouseDown(BPoint where)
{
if (IsValid()) {
if (_HasFlags(STATE_ENABLED)/* && !_HasFlags(STATE_FORCE_PRESSED)*/) {
if (Bounds().Contains(where)) {
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
_AddFlags(STATE_PRESSED | STATE_TRACKING);
} else {
_ClearFlags(STATE_PRESSED | STATE_TRACKING);
}
}
}
}
// MouseUp
void
IconButton::MouseUp(BPoint where)
{
if (IsValid()) {
// if (!_HasFlags(STATE_FORCE_PRESSED)) {
if (_HasFlags(STATE_ENABLED) && _HasFlags(STATE_PRESSED) && Bounds().Contains(where))
Invoke();
else if (Bounds().Contains(where))
_AddFlags(STATE_INSIDE);
_ClearFlags(STATE_PRESSED | STATE_TRACKING);
// }
}
}
// MouseMoved
void
IconButton::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
{
if (IsValid()) {
uint32 buttons = 0;
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
// catch a mouse up event that we might have missed
if (!buttons && _HasFlags(STATE_PRESSED)) {
MouseUp(where);
return;
}
if (buttons && !_HasFlags(STATE_TRACKING))
return;
if ((transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW)
&& _HasFlags(STATE_ENABLED))
_AddFlags(STATE_INSIDE);
else
_ClearFlags(STATE_INSIDE);
if (_HasFlags(STATE_TRACKING)) {
if (Bounds().Contains(where))
_AddFlags(STATE_PRESSED);
else
_ClearFlags(STATE_PRESSED);
}
}
}
#define MIN_SPACE 15.0
// GetPreferredSize
void
IconButton::GetPreferredSize(float* width, float* height)
{
float minWidth = 0.0;
float minHeight = 0.0;
if (IsValid()) {
minWidth += fNormalBitmap->Bounds().IntegerWidth() + 1.0;
minHeight += fNormalBitmap->Bounds().IntegerHeight() + 1.0;
} else {
minWidth += MIN_SPACE;
minHeight += MIN_SPACE;
}
if (minWidth < MIN_SPACE)
minWidth = MIN_SPACE;
if (minHeight < MIN_SPACE)
minHeight = MIN_SPACE;
if (fLabel.CountChars() > 0) {
font_height fh;
GetFontHeight(&fh);
minHeight += ceilf(fh.ascent + fh.descent) + 4.0;
minWidth += StringWidth(fLabel.String()) + 4.0;
}
if (width)
*width = minWidth + 4.0;
if (height)
*height = minHeight + 4.0;
}
// Invoke
status_t
IconButton::Invoke(BMessage* message)
{
if (!message)
message = Message();
if (message) {
BMessage clone(*message);
clone.AddInt64("be:when", system_time());
clone.AddPointer("be:source", (BView*)this);
clone.AddInt32("be:value", Value());
clone.AddInt32("id", ID());
return BInvoker::Invoke(&clone);
}
return BInvoker::Invoke(message);
}
// SetPressed
void
IconButton::SetPressed(bool pressed)
{
if (pressed)
_AddFlags(STATE_FORCE_PRESSED);
else
_ClearFlags(STATE_FORCE_PRESSED);
}
// IsPressed
bool
IconButton::IsPressed() const
{
return _HasFlags(STATE_FORCE_PRESSED);
}
// SetIcon
status_t
IconButton::SetIcon(const char* pathToBitmap)
{
status_t status = B_BAD_VALUE;
if (pathToBitmap) {
BBitmap* fileBitmap = NULL;
// try to load bitmap from either relative or absolute path
BEntry entry(pathToBitmap, true);
if (!entry.Exists()) {
app_info info;
status = be_app->GetAppInfo(&info);
if (status == B_OK) {
BEntry app_entry(&info.ref, true);
BPath path;
app_entry.GetPath(&path);
status = path.InitCheck();
if (status == B_OK) {
status = path.GetParent(&path);
if (status == B_OK) {
status = path.Append(pathToBitmap, true);
if (status == B_OK)
fileBitmap = BTranslationUtils::GetBitmap(path.Path());
else
printf("IconButton::SetIcon() - path.Append() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - path.GetParent() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - path.InitCheck() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - be_app->GetAppInfo() failed: %s\n", strerror(status));
} else
fileBitmap = BTranslationUtils::GetBitmap(pathToBitmap);
if (fileBitmap) {
status = _MakeBitmaps(fileBitmap);
delete fileBitmap;
} else
status = B_ERROR;
}
return status;
}
// SetIcon
status_t
IconButton::SetIcon(const BBitmap* bitmap)
{
if (bitmap && bitmap->ColorSpace() == B_CMAP8) {
status_t status = bitmap->InitCheck();
if (status >= B_OK) {
if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap)) {
status = _MakeBitmaps(rgb32Bitmap);
delete rgb32Bitmap;
} else
status = B_NO_MEMORY;
}
return status;
} else
return _MakeBitmaps(bitmap);
}
// SetIcon
status_t
IconButton::SetIcon(const BMimeType* fileType, bool small)
{
status_t status = fileType ? fileType->InitCheck() : B_BAD_VALUE;
if (status >= B_OK) {
BBitmap* mimeBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_CMAP8);
if (mimeBitmap && mimeBitmap->IsValid()) {
status = fileType->GetIcon(mimeBitmap, small ? B_MINI_ICON : B_LARGE_ICON);
if (status >= B_OK) {
if (BBitmap* bitmap = _ConvertToRGB32(mimeBitmap)) {
status = _MakeBitmaps(bitmap);
delete bitmap;
} else
printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n");
} else
printf("IconButton::SetIcon() - fileType->GetIcon() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - B_CMAP8 bitmap is not valid\n");
delete mimeBitmap;
} else
printf("IconButton::SetIcon() - fileType is not valid: %s\n", strerror(status));
return status;
}
// SetIcon
status_t
IconButton::SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height, color_space format, bool convertToBW)
{
status_t status = B_BAD_VALUE;
if (bitsFromQuickRes && width > 0 && height > 0) {
BBitmap* quickResBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, width - 1.0, height - 1.0), format);
status = quickResBitmap ? quickResBitmap->InitCheck() : B_ERROR;
if (status >= B_OK) {
// It doesn't look right to copy BitsLength() bytes, but bitmaps
// exported from QuickRes still contain their padding, so it is alright.
memcpy(quickResBitmap->Bits(), bitsFromQuickRes, quickResBitmap->BitsLength());
if (format != B_RGB32 && format != B_RGBA32 && format != B_RGB32_BIG && format != B_RGBA32_BIG) {
// colorspace needs conversion
BBitmap* bitmap = new(nothrow) BBitmap(quickResBitmap->Bounds(), B_RGB32, true);
if (bitmap && bitmap->IsValid()) {
BView* helper = new BView(bitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW);
if (bitmap->Lock()) {
bitmap->AddChild(helper);
helper->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
helper->FillRect(helper->Bounds());
helper->SetDrawingMode(B_OP_OVER);
helper->DrawBitmap(quickResBitmap, BPoint(0.0, 0.0));
helper->Sync();
bitmap->Unlock();
}
status = _MakeBitmaps(bitmap);
} else
printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n");
delete bitmap;
} else {
// native colorspace (32 bits)
if (convertToBW) {
// convert to gray scale icon
uint8* bits = (uint8*)quickResBitmap->Bits();
uint32 bpr = quickResBitmap->BytesPerRow();
for (uint32 y = 0; y < height; y++) {
uint8* handle = bits;
uint8 gray;
for (uint32 x = 0; x < width; x++) {
gray = uint8((116 * handle[0] + 600 * handle[1] + 308 * handle[2]) / 1024);
handle[0] = gray;
handle[1] = gray;
handle[2] = gray;
handle += 4;
}
bits += bpr;
}
}
status = _MakeBitmaps(quickResBitmap);
}
} else
printf("IconButton::SetIcon() - error allocating bitmap: %s\n", strerror(status));
delete quickResBitmap;
}
return status;
}
// ClearIcon
void
IconButton::ClearIcon()
{
_DeleteBitmaps();
_Update();
}
// Bitmap
BBitmap*
IconButton::Bitmap() const
{
BBitmap* bitmap = NULL;
if (fNormalBitmap && fNormalBitmap->IsValid()) {
bitmap = new(nothrow) BBitmap(fNormalBitmap);
if (bitmap->IsValid()) {
// TODO: remove this functionality when we use real transparent bitmaps
uint8* bits = (uint8*)bitmap->Bits();
uint32 bpr = bitmap->BytesPerRow();
uint32 width = bitmap->Bounds().IntegerWidth() + 1;
uint32 height = bitmap->Bounds().IntegerHeight() + 1;
color_space format = bitmap->ColorSpace();
if (format == B_CMAP8) {
// replace gray with magic transparent index
} else if (format == B_RGB32) {
for (uint32 y = 0; y < height; y++) {
uint8* bitsHandle = bits;
for (uint32 x = 0; x < width; x++) {
if (bitsHandle[0] == 216
&& bitsHandle[1] == 216
&& bitsHandle[2] == 216) {
bitsHandle[3] = 0; // make this pixel completely transparent
}
bitsHandle += 4;
}
bits += bpr;
}
}
} else {
delete bitmap;
bitmap = NULL;
}
}
return bitmap;
}
// DrawBorder
bool
IconButton::DrawBorder() const
{
return (IsEnabled() && (_HasFlags(STATE_INSIDE) || _HasFlags(STATE_TRACKING))
|| _HasFlags(STATE_FORCE_PRESSED));
}
// DrawNormalBorder
void
IconButton::DrawNormalBorder(BRect r, rgb_color background,
rgb_color shadow, rgb_color darkShadow,
rgb_color lightShadow, rgb_color light)
{
_DrawFrame(r, shadow, darkShadow, light, lightShadow);
}
// DrawPressedBorder
void
IconButton::DrawPressedBorder(BRect r, rgb_color background,
rgb_color shadow, rgb_color darkShadow,
rgb_color lightShadow, rgb_color light)
{
_DrawFrame(r, shadow, light, darkShadow, background);
}
// IsValid
bool
IconButton::IsValid() const
{
return (fNormalBitmap && fDisabledBitmap && fClickedBitmap && fDisabledClickedBitmap
&& fNormalBitmap->IsValid()
&& fDisabledBitmap->IsValid()
&& fClickedBitmap->IsValid()
&& fDisabledClickedBitmap->IsValid());
}
// Value
int32
IconButton::Value() const
{
return _HasFlags(STATE_PRESSED) ? B_CONTROL_ON : B_CONTROL_OFF;
}
// SetValue
void
IconButton::SetValue(int32 value)
{
if (value)
_AddFlags(STATE_PRESSED);
else
_ClearFlags(STATE_PRESSED);
}
// IsEnabled
bool
IconButton::IsEnabled() const
{
return _HasFlags(STATE_ENABLED) ? B_CONTROL_ON : B_CONTROL_OFF;
}
// SetEnabled
void
IconButton::SetEnabled(bool enabled)
{
if (enabled)
_AddFlags(STATE_ENABLED);
else
_ClearFlags(STATE_ENABLED | STATE_TRACKING | STATE_INSIDE);
}
// _ConvertToRGB32
BBitmap*
IconButton::_ConvertToRGB32(const BBitmap* bitmap) const
{
BBitmap* convertedBitmap = new(nothrow) BBitmap(bitmap->Bounds(), B_BITMAP_ACCEPTS_VIEWS, B_RGBA32);
if (convertedBitmap && convertedBitmap->IsValid()) {
memset(convertedBitmap->Bits(), 0, convertedBitmap->BitsLength());
BView* helper = new BView(bitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW);
if (convertedBitmap->Lock()) {
convertedBitmap->AddChild(helper);
helper->SetDrawingMode(B_OP_OVER);
helper->DrawBitmap(bitmap, BPoint(0.0, 0.0));
helper->Sync();
convertedBitmap->Unlock();
}
} else {
delete convertedBitmap;
convertedBitmap = NULL;
}
return convertedBitmap;
}
// _MakeBitmaps
status_t
IconButton::_MakeBitmaps(const BBitmap* bitmap)
{
status_t status = bitmap ? bitmap->InitCheck() : B_BAD_VALUE;
if (status >= B_OK) {
// make our own versions of the bitmap
BRect b(bitmap->Bounds());
_DeleteBitmaps();
color_space format = bitmap->ColorSpace();
fNormalBitmap = new(nothrow) BBitmap(b, format);
fDisabledBitmap = new(nothrow) BBitmap(b, format);
fClickedBitmap = new(nothrow) BBitmap(b, format);
fDisabledClickedBitmap = new(nothrow) BBitmap(b, format);
if (IsValid()) {
// copy bitmaps from file bitmap
uint8* nBits = (uint8*)fNormalBitmap->Bits();
uint8* dBits = (uint8*)fDisabledBitmap->Bits();
uint8* cBits = (uint8*)fClickedBitmap->Bits();
uint8* dcBits = (uint8*)fDisabledClickedBitmap->Bits();
uint8* fBits = (uint8*)bitmap->Bits();
int32 nbpr = fNormalBitmap->BytesPerRow();
int32 fbpr = bitmap->BytesPerRow();
int32 pixels = b.IntegerWidth() + 1;
int32 lines = b.IntegerHeight() + 1;
// nontransparent version:
if (format == B_RGB32 || format == B_RGB32_BIG) {
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = 255;
// clicked bits are darker (lame method...)
cBits[nOffset + 0] = (uint8)((float)nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = (uint8)((float)nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = (uint8)((float)nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = 255;
// disabled bits have less contrast (lame method...)
uint8 grey = 216;
float dist = (nBits[nOffset + 0] - grey) * 0.4;
dBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dBits[nOffset + 2] = (uint8)(grey + dist);
dBits[nOffset + 3] = 255;
// disabled bits have less contrast (lame method...)
grey = 188;
dist = (nBits[nOffset + 0] - grey) * 0.4;
dcBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dcBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dcBits[nOffset + 2] = (uint8)(grey + dist);
dcBits[nOffset + 3] = 255;
}
nBits += nbpr;
dBits += nbpr;
cBits += nbpr;
dcBits += nbpr;
fBits += fbpr;
}
// transparent version:
} else if (format == B_RGBA32 || format == B_RGBA32_BIG) {
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = fBits[fOffset + 3];
// clicked bits are darker (lame method...)
cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = fBits[fOffset + 3];
// disabled bits have less opacity
dBits[nOffset + 0] = fBits[fOffset + 0];
dBits[nOffset + 1] = fBits[fOffset + 1];
dBits[nOffset + 2] = fBits[fOffset + 2];
dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5);
// disabled bits have less contrast (lame method...)
dcBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8);
dcBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
dcBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5);
}
nBits += nbpr;
dBits += nbpr;
cBits += nbpr;
dcBits += nbpr;
fBits += fbpr;
}
// unsupported format
} else {
printf("IconButton::_MakeBitmaps() - bitmap has unsupported colorspace\n");
status = B_MISMATCHED_VALUES;
_DeleteBitmaps();
}
} else {
printf("IconButton::_MakeBitmaps() - error allocating local bitmaps\n");
status = B_NO_MEMORY;
_DeleteBitmaps();
}
} else
printf("IconButton::_MakeBitmaps() - bitmap is not valid\n");
return status;
}
// _DeleteBitmaps
void
IconButton::_DeleteBitmaps()
{
delete fNormalBitmap;
fNormalBitmap = NULL;
delete fDisabledBitmap;
fDisabledBitmap = NULL;
delete fClickedBitmap;
fClickedBitmap = NULL;
delete fDisabledClickedBitmap;
fDisabledClickedBitmap = NULL;
}
// _Update
void
IconButton::_Update()
{
if (LockLooper()) {
Invalidate();
UnlockLooper();
}
}
// _AddFlags
void
IconButton::_AddFlags(uint32 flags)
{
if (!(fButtonState & flags)) {
fButtonState |= flags;
_Update();
}
}
// _ClearFlags
void
IconButton::_ClearFlags(uint32 flags)
{
if (fButtonState & flags) {
fButtonState &= ~flags;
_Update();
}
}
// _HasFlags
bool
IconButton::_HasFlags(uint32 flags) const
{
return (fButtonState & flags);
}
// _DrawFrame
void
IconButton::_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();
}
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
/** gui class that loads an image from disk and shows it
as clickable button */
// TODO: inherit from BControl?
// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic
// it should be placed into a common folder for generic useful stuff
#ifndef ICON_BUTTON_H
#define ICON_BUTTON_H
#include <Invoker.h>
#include <String.h>
#include <View.h>
class BBitmap;
class BMimeType;
class IconButton : public BView, public BInvoker {
public:
IconButton(const char* name,
uint32 id,
const char* label = NULL,
BMessage* message = NULL,
BHandler* target = NULL);
virtual ~IconButton();
// BView interface
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* message);
virtual void GetPreferredSize(float* width,
float* height);
// BInvoker interface
virtual status_t Invoke(BMessage* message = NULL);
// IconButton
bool IsValid() const;
virtual int32 Value() const;
virtual void SetValue(int32 value);
bool IsEnabled() const;
void SetEnabled(bool enable);
void SetPressed(bool pressed);
bool IsPressed() const;
uint32 ID() const
{ return fID; }
status_t SetIcon(const char* pathToBitmap);
status_t SetIcon(const BBitmap* bitmap);
status_t SetIcon(const BMimeType* fileType,
bool small = true);
status_t SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height,
color_space format,
bool convertToBW = false);
void ClearIcon();
BBitmap* Bitmap() const;
// caller has to delete the returned bitmap
virtual bool DrawBorder() const;
virtual void DrawNormalBorder(BRect r,
rgb_color background,
rgb_color shadow,
rgb_color darkShadow,
rgb_color lightShadow,
rgb_color light);
virtual void DrawPressedBorder(BRect r,
rgb_color background,
rgb_color shadow,
rgb_color darkShadow,
rgb_color lightShadow,
rgb_color light);
protected:
enum {
STATE_NONE = 0x0000,
STATE_TRACKING = 0x0001,
STATE_PRESSED = 0x0002,
STATE_ENABLED = 0x0004,
STATE_INSIDE = 0x0008,
STATE_FORCE_PRESSED = 0x0010,
};
void _AddFlags(uint32 flags);
void _ClearFlags(uint32 flags);
bool _HasFlags(uint32 flags) const;
void _DrawFrame(BRect frame,
rgb_color col1,
rgb_color col2,
rgb_color col3,
rgb_color col4);
// private:
BBitmap* _ConvertToRGB32(const BBitmap* bitmap) const;
status_t _MakeBitmaps(const BBitmap* bitmap);
void _DeleteBitmaps();
void _SendMessage() const;
void _Update();
uint32 fButtonState;
int32 fID;
BBitmap* fNormalBitmap;
BBitmap* fDisabledBitmap;
BBitmap* fClickedBitmap;
BBitmap* fDisabledClickedBitmap;
BString fLabel;
BHandler* fTargetCache;
};
#endif // ICON_BUTTON_H
+22
View File
@@ -0,0 +1,22 @@
SubDir HAIKU_TOP src apps launchbox ;
AddSubDirSupportedPlatforms libbe_test ;
Application LaunchBox :
App.cpp
IconButton.cpp
LaunchButton.cpp
main.cpp
MainWindow.cpp
NamePanel.cpp
PadView.cpp
Panel.cpp
support.cpp
: be translation
: LaunchBox.rdef
;
if $(TARGET_PLATFORM) = libbe_test {
HaikuInstall install-test-apps : $(HAIKU_APP_TEST_DIR) : LaunchBox
: tests!apps ;
}
+55
View File
@@ -0,0 +1,55 @@
resource app_signature "application/x-vnd.Haiku-LaunchBox";
resource app_flags B_SINGLE_LAUNCH;
resource app_version {
major = 1,
middle = 1,
minor = 0,
variety = B_APPV_ALPHA,
internal = 1,
short_info = "LaunchBox",
long_info = "LaunchBox ©2006 Haiku"
};
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
resource vector_icon {
$"6E6369660D0500020112023DEB47BD4D713B47993BE4594843FB4BC62F000032"
$"FF005A03FF990003FFE40003FDFF7502000602000000B6FA0BB6FA0B00000046"
$"86C94A0BE800FF0000FFFF6666020006023727A3AEA7053080AD38FA08496B7B"
$"4AC41300F70606FF9804040200060234A005341E7FB7602E3817404893414A70"
$"1400FF6666FFC200000200060239496E39C491BC42BD3BF1B749D83049AAFF00"
$"B20404FF8B03030200160236FA0B36FA0B36FA0BB6FA0B48D2FD4A56710096FF"
$"580200060338EC7E3992F0BA0B4939582E4ABDF947F9C300FF000066FF0000FF"
$"610202020006033C13B4BC6C533F097A3E9A69478C893F11A700FFACACA7FFF1"
$"F1FFB4B4B4020112033B000000000000000039000046C0004BB00000FF1FA7FF"
$"0BFFFF000C060A8ABF0ABC08CAA134603C40584C554C55595260455F485E4444"
$"4A4F42444A3C50334EBA4BC7E5060DE6FF8802364E5C405240464046C0FBC13D"
$"C4F9BEC1C2C2C005CAD6BB675C205C235920BF27B8EFC280B311BDE2BB25363C"
$"BCDDBD1A363C2A20462E2C4834500A0425442C44353E2B3E0A032F44353E2C44"
$"0A043E513E47385038570A03384D38503E470207BFD6B95343B760BDA6BD2633"
$"43BB79BFE1334339493949BE05C26DC494BE11C0C1C041C688BCF456315435C8"
$"67B8DCC70EB6DBC7F5B7C3C624B5F34B26C50BB57F47280A063343B89FC30BB8"
$"A1C30DBADBC546BADDC54739490A042E4F3A4339422D4E0604BF4233C44DB5A0"
$"BEEFBCB13840BD95BE8FBDC5BEBD4334BF3ABCFDC4F0B64359220605EE023A4B"
$"3852384E3857BEC15F43524357434E414B0A042054206034603454100A010100"
$"000A0C010B000A000101000A00010A123ECDF73EDA22BEDA223ECDF7494B02C5"
$"A04A01178400040A02010A023ECDF73EDA22BEDA223ECDF7494B02C5A04A0A03"
$"010A023E292D3E320CBE328D3E28AE48F3C2447A6A0A04010A023CACE53CB6B4"
$"BCB8813CAB20486D1B48A8BB0A050102000A080103000A060104000A08010500"
$"0A0A0106000A090107000A0001081001178400040A070108000A0B010900"
};
#else // HAIKU_TARGET_PLATFORM_HAIKU
//resource large_icon {
//};
//
//resource mini_icon {
//};
#endif // HAIKU_TARGET_PLATFORM_HAIKU
+348
View File
@@ -0,0 +1,348 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "LaunchButton.h"
#include <malloc.h> // string.h is not enough on Haiku?!?
#include <stdio.h>
#include <string.h>
#include <AppDefs.h>
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <File.h>
#include <Node.h>
#include <NodeInfo.h>
#include <Region.h>
#include <Roster.h>
#include <Window.h>
//#include "BubbleHelper.h"
#include "PadView.h"
static const float kDragStartDist = 10.0;
static const float kDragBitmapAlphaScale = 0.6;
//static const char* kEmptyHelpString = "You can drag an icon here.";
bigtime_t
LaunchButton::fClickSpeed = 0;
// constructor
LaunchButton::LaunchButton(const char* name, uint32 id, const char* label,
BMessage* message, BHandler* target)
: IconButton(name, id, label, message, target),
fRef(NULL),
fAppSig(NULL),
fDescription(""),
fAnticipatingDrop(false),
fLastClickTime(0)
{
if (fClickSpeed == 0 || get_click_speed(&fClickSpeed) < B_OK)
fClickSpeed = 500000;
BSize size(32.0 + 8.0, 32.0 + 8.0);
SetExplicitMinSize(size);
SetExplicitMaxSize(size);
}
// destructor
LaunchButton::~LaunchButton()
{
delete fRef;
if (fAppSig)
free(fAppSig);
}
// AttachedToWindow
void
LaunchButton::AttachedToWindow()
{
IconButton::AttachedToWindow();
_UpdateToolTip();
}
// DetachedFromWindow
void
LaunchButton::DetachedFromWindow()
{
// BubbleHelper::Default()->SetHelp(this, NULL);
}
// Draw
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(&region);
}
if (IsValid()) {
IconButton::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);
}
}
// MessageReceived
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 < B_OK) {
if (fAppSig)
be_roster->Launch(fAppSig, message, &team);
else
be_roster->Launch(fRef, message, &team);
} else {
app_info appInfo;
if (team >= B_OK && 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:
IconButton::MessageReceived(message);
break;
}
}
// MouseDown
void
LaunchButton::MouseDown(BPoint where)
{
bigtime_t now = system_time();
bool callInherited = true;
if (now - fLastClickTime < fClickSpeed)
callInherited = false;
fLastClickTime = now;
if (BMessage* message = Window()->CurrentMessage()) {
uint32 buttons;
message->FindInt32("buttons", (int32*)&buttons);
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
if (PadView* parent = dynamic_cast<PadView*>(Parent())) {
parent->DisplayMenu(ConvertToParent(where), this);
_ClearFlags(STATE_INSIDE);
callInherited = false;
}
} else {
fDragStart = where;
}
}
if (callInherited)
IconButton::MouseDown(where);
}
// MouseUp
void
LaunchButton::MouseUp(BPoint where)
{
if (fAnticipatingDrop) {
fAnticipatingDrop = false;
Invalidate();
}
IconButton::MouseUp(where);
}
// MouseMoved
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();
}
}
// see if we should create a drag message
if (_HasFlags(STATE_TRACKING) && fRef) {
BPoint diff = where - fDragStart;
float dist = sqrtf(diff.x * diff.x + diff.y * diff.y);
if (dist >= kDragStartDist) {
// stop tracking
_ClearFlags(STATE_PRESSED | STATE_TRACKING | STATE_INSIDE);
// create drag bitmap and message
if (BBitmap* bitmap = Bitmap()) {
if (bitmap->ColorSpace() == B_RGB32) {
// make semitransparent
uint8* bits = (uint8*)bitmap->Bits();
uint32 width = bitmap->Bounds().IntegerWidth() + 1;
uint32 height = bitmap->Bounds().IntegerHeight() + 1;
uint32 bpr = bitmap->BytesPerRow();
for (uint32 y = 0; y < height; y++) {
uint8* bitsHandle = bits;
for (uint32 x = 0; x < width; x++) {
bitsHandle[3] = uint8(bitsHandle[3] * kDragBitmapAlphaScale);
bitsHandle += 4;
}
bits += bpr;
}
}
BMessage message(B_SIMPLE_DATA);
message.AddPointer("button", this);
message.AddRef("refs", fRef);
DragMessage(&message, bitmap, B_OP_ALPHA, fDragStart);
}
}
}
IconButton::MouseMoved(where, transit, dragMessage);
}
// SetTo
void
LaunchButton::SetTo(const entry_ref* ref)
{
if (fAppSig) {
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 {
printf("no MIME sig\n");
}
} else {
printf("no app\n");
}
} else {
fRef = NULL;
ClearIcon();
}
_UpdateToolTip();
}
// Ref
entry_ref*
LaunchButton::Ref() const
{
return fRef;
}
// SetTo
void
LaunchButton::SetTo(const char* appSig, bool updateIcon)
{
if (appSig) {
if (fAppSig)
free(fAppSig);
fAppSig = strdup(appSig);
if (updateIcon) {
entry_ref ref;
if (be_roster->FindApp(fAppSig, &ref) >= B_OK)
SetTo(&ref);
}
}
_UpdateToolTip();
}
// SetDesciption
void
LaunchButton::SetDescription(const char* text)
{
fDescription.SetTo(text);
_UpdateToolTip();
}
// _UpdateToolTip
void
LaunchButton::_UpdateToolTip()
{
if (fRef) {
BString helper(fRef->name);
if (fDescription.CountChars() > 0) {
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 << "\n\n" << info.short_info;
}
}
// BubbleHelper::Default()->SetHelp(this, helper.String());
} else {
// BubbleHelper::Default()->SetHelp(this, kEmptyHelpString);
}
}
// _UpdateIcon
void
LaunchButton::_UpdateIcon(const entry_ref* ref)
{
BBitmap* icon = new BBitmap(BRect(0.0, 0.0, 31.0, 31.0), B_RGBA32);
if (BNodeInfo::GetTrackerIcon(ref, icon, B_LARGE_ICON) >= B_OK)
SetIcon(icon);
delete icon;
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef LAUNCH_BUTTON_H
#define LAUNCH_BUTTON_H
#include <List.h>
#include <String.h>
#include "IconButton.h"
enum {
MSG_ADD_SLOT = 'adsl',
MSG_CLEAR_SLOT = 'clsl',
MSG_REMOVE_SLOT = 'rmsl',
MSG_LAUNCH = 'lnch',
};
class LaunchButton : public IconButton {
public:
LaunchButton(const char* name,
uint32 id,
const char* label = NULL,
BMessage* message = NULL,
BHandler* target = NULL);
virtual ~LaunchButton();
// IconButton interface
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
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);
// 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(); }
private:
void _UpdateToolTip();
void _UpdateIcon(const entry_ref* ref);
entry_ref* fRef;
char* fAppSig;
BString fDescription;
bool fAnticipatingDrop;
bigtime_t fLastClickTime;
BPoint fDragStart;
static bigtime_t fClickSpeed;
};
#endif // LAUNCH_BUTTON_H
+475
View File
@@ -0,0 +1,475 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "MainWindow.h"
#include <stdio.h>
#include <Alert.h>
#include <Application.h>
#include <GroupLayout.h>
#include <Menu.h>
#include <MenuItem.h>
#include <Messenger.h>
#include <Path.h>
#include <Roster.h>
#include <Screen.h>
#include "support.h"
#include "LaunchButton.h"
#include "NamePanel.h"
#include "PadView.h"
// constructor
MainWindow::MainWindow(const char* name, BRect frame)
: BWindow(frame, name,
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE
| B_WILL_ACCEPT_FIRST_CLICK | B_NO_WORKSPACE_ACTIVATION),
fSettings(new BMessage('sett')),
fPadView(new PadView("pad view")),
fLastID(0),
fNamePanelFrame(-1000.0, -1000.0, -900.0, -900.0),
fAutoRaise(false),
fShowOnAllWorkspaces(true)
{
bool buttonsAdded = false;
if (load_settings(fSettings, "main_settings", "LaunchBox") >= B_OK)
buttonsAdded = LoadSettings(fSettings);
if (!buttonsAdded) {
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
}
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(fPadView);
}
// constructor
MainWindow::MainWindow(const char* name, BRect frame, BMessage* settings)
: BWindow(frame, name,
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE
| B_WILL_ACCEPT_FIRST_CLICK | B_NO_WORKSPACE_ACTIVATION),
fSettings(settings),
fPadView(new PadView("pad view")),
fLastID(0),
fNamePanelFrame(-1000.0, -1000.0, -900.0, -900.0),
fAutoRaise(false),
fShowOnAllWorkspaces(true)
{
if (!LoadSettings(settings)) {
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)));
}
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(fPadView);
}
// destructor
MainWindow::~MainWindow()
{
delete fSettings;
}
// QuitRequested
bool
MainWindow::QuitRequested()
{
int32 padWindowCount = 0;
for (int32 i = 0; BWindow* window = be_app->WindowAt(i); i++) {
if (dynamic_cast<MainWindow*>(window))
padWindowCount++;
}
if (padWindowCount == 1) {
be_app->PostMessage(B_QUIT_REQUESTED);
return false;
} else {
BAlert* alert = new BAlert("last chance", "Really close this pad?\n"
"(The pad will not be remembered.)",
"Close", "Cancel", NULL);
if (alert->Go() == 1)
return false;
}
return true;
}
// MessageReceived
void
MainWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_LAUNCH: {
BView* pointer;
if (message->FindPointer("be:source", (void**)&pointer) >= B_OK) {
if (LaunchButton* button = dynamic_cast<LaunchButton*>(pointer)) {
if (button->AppSignature()) {
be_roster->Launch(button->AppSignature());
} else {
BEntry entry(button->Ref(), true);
if (entry.IsDirectory()) {
// open in Tracker
BMessenger messenger("application/x-vnd.Be-TRAK");
if (messenger.IsValid()) {
BMessage trackerMessage(B_REFS_RECEIVED);
trackerMessage.AddRef("refs", button->Ref());
messenger.SendMessage(&trackerMessage);
}
} else {
status_t ret = be_roster->Launch(button->Ref());
if (ret < B_OK)
fprintf(stderr, "launching %s failed: %s\n",
button->Ref()->name, strerror(ret));
}
}
}
}
break;
}
case MSG_ADD_SLOT: {
LaunchButton* button;
if (message->FindPointer("be:source", (void**)&button) >= B_OK) {
fPadView->AddButton(new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH)), button);
}
break;
}
case MSG_CLEAR_SLOT: {
LaunchButton* button;
if (message->FindPointer("be:source", (void**)&button) >= B_OK)
button->SetTo((entry_ref*)NULL);
break;
}
case MSG_REMOVE_SLOT: {
LaunchButton* button;
if (message->FindPointer("be:source", (void**)&button) >= B_OK) {
if (fPadView->RemoveButton(button))
delete button;
}
break;
}
case MSG_SET_DESCRIPTION: {
LaunchButton* button;
if (message->FindPointer("be:source", (void**)&button) >= B_OK) {
const char* name;
if (message->FindString("name", &name) >= B_OK) {
// message comes from a previous name panel
button->SetDescription(name);
message->FindRect("frame", &fNamePanelFrame);
} else {
// message comes from pad view
entry_ref* ref = button->Ref();
if (ref) {
BString helper("Description for '");
helper << ref->name << "'";
// BRect* frame = fNamePanelFrame.IsValid() ? &fNamePanelFrame : NULL;
new NamePanel(helper.String(),
button->Description(),
this, this,
new BMessage(*message),
fNamePanelFrame);
}
}
}
break;
}
case MSG_ADD_WINDOW: {
BMessage settings('sett');
SaveSettings(&settings);
message->AddMessage("window", &settings);
be_app->PostMessage(message);
break;
}
case MSG_SHOW_BORDER:
SetLook(B_TITLED_WINDOW_LOOK);
break;
case MSG_HIDE_BORDER:
SetLook(B_BORDERED_WINDOW_LOOK);
break;
case MSG_TOGGLE_AUTORAISE:
ToggleAutoRaise();
break;
case MSG_SHOW_ON_ALL_WORKSPACES:
fShowOnAllWorkspaces = !fShowOnAllWorkspaces;
break;
case B_SIMPLE_DATA:
case B_REFS_RECEIVED:
case B_PASTE:
case B_MODIFIERS_CHANGED:
break;
case B_ABOUT_REQUESTED:
be_app->PostMessage(message);
break;
default:
BWindow::MessageReceived(message);
break;
}
}
// Show
void
MainWindow::Show()
{
BWindow::Show();
_GetLocation();
}
// ScreenChanged
void
MainWindow::ScreenChanged(BRect frame, color_space format)
{
_AdjustLocation(Frame());
}
// WorkspaceActivated
void
MainWindow::WorkspaceActivated(int32 workspace, bool active)
{
if (fShowOnAllWorkspaces) {
if (!active) {
SetWorkspaces(1 << current_workspace());
_AdjustLocation(Frame());
} else
_GetLocation();
}
}
// FrameMoved
void
MainWindow::FrameMoved(BPoint origin)
{
if (IsActive())
_GetLocation();
}
// FrameResized
void
MainWindow::FrameResized(float width, float height)
{
if (IsActive())
_GetLocation();
BWindow::FrameResized(width, height);
}
// ToggleAutoRaise
void
MainWindow::ToggleAutoRaise()
{
fAutoRaise = !fAutoRaise;
if (fAutoRaise)
fPadView->SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
else
fPadView->SetEventMask(0);
}
// LoadSettings
bool
MainWindow::LoadSettings(const BMessage* message)
{
// restore window positioning
BPoint point;
bool useAdjust = false;
if (message->FindPoint("window position", &point) == B_OK) {
fScreenPosition = point;
useAdjust = true;
}
float borderDist;
if (message->FindFloat("border distance", &borderDist) == B_OK) {
fBorderDist = borderDist;
}
// restore window frame
BRect frame;
if (message->FindRect("window frame", &frame) == B_OK) {
if (useAdjust) {
_AdjustLocation(frame);
} else {
make_sure_frame_is_on_screen(frame, this);
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
}
}
// restore name panel frame
if (message->FindRect("name panel frame", &frame) == B_OK) {
if (frame.IsValid()) {
make_sure_frame_is_on_screen(frame, this);
fNamePanelFrame = frame;
}
}
// restore window look
window_look look;
if (message->FindInt32("window look", (int32*)&look) == B_OK)
SetLook(look);
// restore buttons
const char* path;
bool buttonAdded = false;
for (int32 i = 0; message->FindString("path", i, &path) >= B_OK; i++) {
LaunchButton* button = new LaunchButton("launch button", fLastID++, NULL,
new BMessage(MSG_LAUNCH));
fPadView->AddButton(button);
BString signature;
if (message->FindString("signature", i, &signature) >= B_OK
&& signature.CountChars() > 0) {
button->SetTo(signature.String(), true);
} else {
entry_ref ref;
if (get_ref_for_path(path, &ref) >= B_OK)
button->SetTo(&ref);
}
const char* text;
if (message->FindString("description", i, &text) >= B_OK)
button->SetDescription(text);
buttonAdded = true;
}
// restore auto raise setting
bool autoRaise;
if (message->FindBool("auto raise", &autoRaise) == B_OK && autoRaise)
ToggleAutoRaise();
// store workspace setting
bool showOnAllWorkspaces;
if (message->FindBool("all workspaces", &showOnAllWorkspaces) == B_OK)
fShowOnAllWorkspaces = showOnAllWorkspaces;
if (!fShowOnAllWorkspaces) {
uint32 workspaces;
if (message->FindInt32("workspaces", (int32*)&workspaces) == B_OK)
SetWorkspaces(workspaces);
}
return buttonAdded;
}
// SaveSettings
void
MainWindow::SaveSettings(BMessage* message)
{
// make sure the positioning info is correct
_GetLocation();
// store window position
if (message->ReplacePoint("window position", fScreenPosition) != B_OK)
message->AddPoint("window position", fScreenPosition);
if (message->ReplaceFloat("border distance", fBorderDist) != B_OK)
message->AddFloat("border distance", fBorderDist);
// store window frame
if (message->ReplaceRect("window frame", Frame()) != B_OK)
message->AddRect("window frame", Frame());
// store name panel frame
if (message->ReplaceRect("name panel frame", fNamePanelFrame) != B_OK)
message->AddRect("name panel frame", fNamePanelFrame);
if (message->ReplaceInt32("window look", Look()) != B_OK)
message->AddInt32("window look", Look());
// store buttons
message->RemoveName("path");
message->RemoveName("description");
message->RemoveName("signature");
for (int32 i = 0; LaunchButton* button = fPadView->ButtonAt(i); i++) {
BPath path(button->Ref());
if (path.InitCheck() >= B_OK)
message->AddString("path", path.Path());
else
message->AddString("path", "");
message->AddString("description", button->Description());
if (button->AppSignature())
message->AddString("signature", button->AppSignature());
else
message->AddString("signature", "");
}
// store auto raise setting
if (message->ReplaceBool("auto raise", fAutoRaise) != B_OK)
message->AddBool("auto raise", fAutoRaise);
// store workspace setting
if (message->ReplaceBool("all workspaces", fShowOnAllWorkspaces) != B_OK)
message->AddBool("all workspaces", fShowOnAllWorkspaces);
if (message->ReplaceInt32("workspaces", Workspaces()) != B_OK)
message->AddInt32("workspaces", Workspaces());
}
// _GetLocation
void
MainWindow::_GetLocation()
{
BRect frame = Frame();
BPoint origin = frame.LeftTop();
BPoint center(origin.x + frame.Width() / 2.0, origin.y + frame.Height() / 2.0);
BScreen screen(this);
BRect screenFrame = screen.Frame();
fScreenPosition.x = center.x / screenFrame.Width();
fScreenPosition.y = center.y / screenFrame.Height();
if (fabs(0.5 - fScreenPosition.x) > fabs(0.5 - fScreenPosition.y)) {
// nearest to left or right border
if (fScreenPosition.x < 0.5)
fBorderDist = frame.left - screenFrame.left;
else
fBorderDist = screenFrame.right - frame.right;
} else {
// nearest to top or bottom border
if (fScreenPosition.y < 0.5)
fBorderDist = frame.top - screenFrame.top;
else
fBorderDist = screenFrame.bottom - frame.bottom;
}
}
// _AdjustLocation
void
MainWindow::_AdjustLocation(BRect frame)
{
BScreen screen(this);
BRect screenFrame = screen.Frame();
BPoint center(fScreenPosition.x * screenFrame.Width(),
fScreenPosition.y * screenFrame.Height());
BPoint frameCenter(frame.left + frame.Width() / 2.0,
frame.top + frame.Height() / 2.0);
frame.OffsetBy(center - frameCenter);
// ignore border dist when distance too large
if (fBorderDist < 10.0) {
// see which border we mean depending on screen position
BPoint offset(0.0, 0.0);
if (fabs(0.5 - fScreenPosition.x) > fabs(0.5 - fScreenPosition.y)) {
// left or right border
if (fScreenPosition.x < 0.5)
offset.x = (screenFrame.left + fBorderDist) - frame.left;
else
offset.x = (screenFrame.right - fBorderDist) - frame.right;
} else {
// top or bottom border
if (fScreenPosition.y < 0.5)
offset.y = (screenFrame.top + fBorderDist) - frame.top;
else
offset.y = (screenFrame.bottom - fBorderDist) - frame.bottom;
}
frame.OffsetBy(offset);
}
make_sure_frame_is_on_screen(frame, this);
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <Window.h>
class PadView;
enum {
MSG_SHOW_BORDER = 'shbr',
MSG_HIDE_BORDER = 'hdbr',
MSG_TOGGLE_AUTORAISE = 'tgar',
MSG_SHOW_ON_ALL_WORKSPACES = 'awrk',
MSG_SET_DESCRIPTION = 'dscr',
MSG_ADD_WINDOW = 'addw',
};
class MainWindow : public BWindow {
public:
MainWindow(const char* name,
BRect frame);
MainWindow(const char* name,
BRect frame, BMessage* settings);
virtual ~MainWindow();
// BWindow interface
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
virtual void Show();
virtual void ScreenChanged(BRect frame, color_space format);
virtual void WorkspaceActivated(int32 workspace, bool active);
virtual void FrameMoved(BPoint origin);
virtual void FrameResized(float width,
float height);
// MainWindow
void ToggleAutoRaise();
bool AutoRaise() const
{ return fAutoRaise; }
bool ShowOnAllWorkspaces() const
{ return fShowOnAllWorkspaces; }
BPoint ScreenPosition() const
{ return fScreenPosition; }
bool LoadSettings(const BMessage* message);
void SaveSettings(BMessage* message);
BMessage* Settings() const
{ return fSettings; }
private:
void _GetLocation();
void _AdjustLocation(BRect frame);
BMessage* fSettings;
PadView* fPadView;
int32 fLastID;
float fBorderDist;
BPoint fScreenPosition; // not really the position, 0...1 = left...right
BRect fNamePanelFrame;
bool fAutoRaise;
bool fShowOnAllWorkspaces;
};
#endif // MAIN_WINDOW_H
+149
View File
@@ -0,0 +1,149 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include <stdio.h>
#include <Button.h>
#include <GroupLayoutBuilder.h>
#include <SpaceLayoutItem.h>
#include <Screen.h>
#include <TextControl.h>
#include "NamePanel.h"
enum {
MSG_PANEL_OK,
MSG_PANEL_CANCEL,
};
// constructor
NamePanel::NamePanel(const char* label,
const char* text,
BWindow *window,
BHandler* target,
BMessage* message,
BRect frame)
: Panel(frame, "Name Panel",
B_MODAL_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE),
fWindow(window),
fTarget(target),
fMessage(message)
{
BButton* defaultButton = new BButton("Ok", new BMessage(MSG_PANEL_OK));
BButton* cancelButton = new BButton("Cancel", new BMessage(MSG_PANEL_CANCEL));
fNameTC = new BTextControl(label, text, NULL);
BView* topView = BGroupLayoutBuilder(B_VERTICAL, 10)
.AddGlue()
// controls
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 5)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(5))
// text control
.Add(fNameTC->CreateLabelLayoutItem())
.Add(fNameTC->CreateTextViewLayoutItem())
.Add(BSpaceLayoutItem::CreateHorizontalStrut(5))
)
.AddGlue()
// buttons
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 5)
.Add(BSpaceLayoutItem::CreateGlue())
.Add(cancelButton)
.Add(defaultButton)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(5))
)
.AddGlue()
;
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(topView);
SetDefaultButton(defaultButton);
fNameTC->MakeFocus(true);
if (fWindow && fWindow->Lock()) {
fSavedTargetWindowFeel = fWindow->Feel();
if (fSavedTargetWindowFeel != B_NORMAL_WINDOW_FEEL)
fWindow->SetFeel(B_NORMAL_WINDOW_FEEL);
fWindow->Unlock();
}
AddToSubset(fWindow);
Hide();
Show();
if (Lock()) {
frame = _CalculateFrame(Frame());
MoveTo(frame.LeftTop());
// ResizeTo(frame.Width(), frame.Height());
Show();
Unlock();
}
}
// destructor
NamePanel::~NamePanel()
{
if (fWindow && fWindow->Lock()) {
fWindow->SetFeel(fSavedTargetWindowFeel);
fWindow->Unlock();
}
delete fMessage;
}
// MessageReceived
void NamePanel::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_PANEL_CANCEL:
Quit();
break;
case MSG_PANEL_OK: {
if (!fTarget)
fTarget = fWindow;
BLooper* looper = fTarget ? fTarget->Looper() : NULL;
if (fMessage && looper) {
BMessage cloneMessage(*fMessage);
cloneMessage.AddString("name", fNameTC->Text());
cloneMessage.AddRect("frame", Frame());
looper->PostMessage(&cloneMessage, fTarget);
}
Quit();
break;
}
default:
Panel::MessageReceived(message);
}
}
// _CalculateFrame
BRect
NamePanel::_CalculateFrame(BRect frame)
{
BScreen screen(this);
BRect screenFrame = screen.Frame();
if (!frame.IsValid())
frame.Set(-1000.0, -1000.0, -900.0, -900.0);
if (!screenFrame.Contains(frame)) {
float width = frame.Width();
float height = frame.Height();
BPoint center;
center.x = screenFrame.left + screenFrame.Width() / 2.0;
center.y = screenFrame.top + screenFrame.Height() / 4.0;
frame.left = center.x - width / 2.0;
frame.right = frame.left + width;
frame.top = center.y - height / 2.0;
frame.bottom = frame.top + height;
}
return frame;
}
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef NAME_PANEL_H
#define NAME_PANEL_H
#include "Panel.h"
class BTextControl;
class NamePanel : public Panel {
public:
NamePanel(const char* label,
const char* text,
BWindow* window,
BHandler* target,
BMessage* message,
BRect frame = BRect(-1000.0, -1000.0, -900.0, -900.0));
virtual ~NamePanel();
virtual void MessageReceived(BMessage *message);
private:
BRect _CalculateFrame(BRect frame);
BTextControl* fNameTC;
BWindow* fWindow;
BHandler* fTarget;
BMessage* fMessage;
window_feel fSavedTargetWindowFeel;
};
#endif // NAME_PANEL_H
+350
View File
@@ -0,0 +1,350 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "PadView.h"
#include <stdio.h>
#include <Application.h>
#include <GroupLayout.h>
#include <MenuItem.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <Region.h>
#include <Screen.h>
#include <SpaceLayoutItem.h>
#include "LaunchButton.h"
#include "MainWindow.h"
bigtime_t kActivationDelay = 40000;
// constructor
PadView::PadView(const char* name)
: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE,
new BGroupLayout(B_VERTICAL, 4)),
fDragging(false),
fClickTime(0)
{
SetViewColor(B_TRANSPARENT_32_BIT);
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
get_click_speed(&kActivationDelay);
GetLayout()->AddItem(BSpaceLayoutItem::CreateVerticalStrut(5));
}
// destructor
PadView::~PadView()
{
}
// Draw
void
PadView::Draw(BRect updateRect)
{
rgb_color background = LowColor();
rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
BRect r(Bounds());
BeginLineArray(4);
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), light);
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), light);
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), shadow);
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), shadow);
EndLineArray();
r.InsetBy(1.0, 1.0);
StrokeRect(r, B_SOLID_LOW);
r.InsetBy(1.0, 1.0);
// dots along top
BPoint dot = r.LeftTop();
BPoint stop = r.RightTop();
int32 num = 1;
while (dot.x <= stop.x) {
rgb_color col1;
rgb_color col2;
switch (num) {
case 1:
col1 = shadow;
col2 = background;
break;
case 2:
col1 = background;
col2 = light;
break;
case 3:
col1 = background;
col2 = background;
num = 0;
break;
}
SetHighColor(col1);
StrokeLine(dot, dot, B_SOLID_HIGH);
SetHighColor(col2);
dot.y++;
StrokeLine(dot, dot, B_SOLID_HIGH);
dot.y++;
StrokeLine(dot, dot, B_SOLID_LOW);
dot.y++;
SetHighColor(col1);
StrokeLine(dot, dot, B_SOLID_HIGH);
dot.y++;
SetHighColor(col2);
StrokeLine(dot, dot, B_SOLID_HIGH);
dot.y -= 4.0;
// next pixel
num++;
dot.x++;
}
r.top += 5.0;
FillRect(r, B_SOLID_LOW);
}
// MessageReceived
void
PadView::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BView::MessageReceived(message);
break;
}
}
// MouseDown
void
PadView::MouseDown(BPoint where)
{
if (BWindow* window = Window()) {
BRegion region;
GetClippingRegion(&region);
if (region.Contains(where)) {
bool handle = true;
for (int32 i = 0; BView* child = ChildAt(i); i++) {
if (child->Frame().Contains(where)) {
handle = false;
break;
}
}
if (handle) {
if (BMessage* message = window->CurrentMessage()) {
uint32 buttons;
message->FindInt32("buttons", (int32*)&buttons);
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
BRect r = Bounds();
r.InsetBy(2.0, 2.0);
r.top += 6.0;
if (r.Contains(where)) {
DisplayMenu(where);
} else {
// sends the window to the back
window->Activate(false);
}
} else {
if (system_time() - fClickTime < kActivationDelay) {
window->Minimize(true);
fClickTime = 0;
} else {
window->Activate();
fDragOffset = ConvertToScreen(where) - window->Frame().LeftTop();
fDragging = true;
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
fClickTime = system_time();
}
}
}
}
}
}
}
// MouseUp
void
PadView::MouseUp(BPoint where)
{
if (BWindow* window = Window()) {
uint32 buttons;
window->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
if (buttons & B_PRIMARY_MOUSE_BUTTON
&& system_time() - fClickTime < kActivationDelay
&& window->IsActive())
window->Activate();
}
fDragging = false;
}
// MouseMoved
void
PadView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
if (MainWindow* window = dynamic_cast<MainWindow*>(Window())) {
if (fDragging) {
window->MoveTo(ConvertToScreen(where) - fDragOffset);
} else if (window->AutoRaise()) {
where = ConvertToScreen(where);
BScreen screen(window);
BRect frame = screen.Frame();
BRect windowFrame = window->Frame();
if (where.x == frame.left || where.x == frame.right
|| where.y == frame.top || where.y == frame.bottom) {
BPoint position = window->ScreenPosition();
bool raise = false;
if (fabs(0.5 - position.x) > fabs(0.5 - position.y)) {
// left or right border
if (where.y >= windowFrame.top && where.y <= windowFrame.bottom) {
if (position.x < 0.5 && where.x == frame.left)
raise = true;
else if (position.x > 0.5 && where.x == frame.right)
raise = true;
}
} else {
// top or bottom border
if (where.x >= windowFrame.left && where.x <= windowFrame.right) {
if (position.y < 0.5 && where.y == frame.top)
raise = true;
else if (position.y > 0.5 && where.y == frame.top)
raise = true;
}
}
if (raise)
window->Activate();
}
}
}
}
// AddButton
void
PadView::AddButton(LaunchButton* button, LaunchButton* beforeButton)
{
BLayout* layout = GetLayout();
if (beforeButton)
layout->AddView(layout->IndexOfView(beforeButton), button);
else
layout->AddView(button);
}
// RemoveButton
bool
PadView::RemoveButton(LaunchButton* button)
{
return GetLayout()->RemoveView(button);
}
// ButtonAt
LaunchButton*
PadView::ButtonAt(int32 index) const
{
return dynamic_cast<LaunchButton*>(ChildAt(index));
}
// DisplayMenu
void
PadView::DisplayMenu(BPoint where, LaunchButton* button) const
{
if (MainWindow* window = dynamic_cast<MainWindow*>(Window())) {
LaunchButton* nearestButton = button;
if (!nearestButton) {
// find the nearest button
for (int32 i = 0; (nearestButton = ButtonAt(i)); i++) {
if (nearestButton->Frame().top > where.y)
break;
}
}
BPopUpMenu* menu = new BPopUpMenu("launch popup", false, false);
// add button
BMessage* message = new BMessage(MSG_ADD_SLOT);
message->AddPointer("be:source", (void*)nearestButton);
BMenuItem* item = new BMenuItem("Add Button Here", message);
item->SetTarget(window);
menu->AddItem(item);
// button options
if (button) {
// remove button
message = new BMessage(MSG_CLEAR_SLOT);
message->AddPointer("be:source", (void*)button);
item = new BMenuItem("Clear Button", message);
item->SetTarget(window);
menu->AddItem(item);
// remove button
message = new BMessage(MSG_REMOVE_SLOT);
message->AddPointer("be:source", (void*)button);
item = new BMenuItem("Remove Button", message);
item->SetTarget(window);
menu->AddItem(item);
if (button->Ref()) {
message = new BMessage(MSG_SET_DESCRIPTION);
message->AddPointer("be:source", (void*)button);
item = new BMenuItem("Set Description"B_UTF8_ELLIPSIS, message);
item->SetTarget(window);
menu->AddItem(item);
}
}
menu->AddSeparatorItem();
// window settings
BMenu* settingsM = new BMenu("Settings");
settingsM->SetFont(be_plain_font);
uint32 what = window->Look() == B_BORDERED_WINDOW_LOOK ? MSG_SHOW_BORDER : MSG_HIDE_BORDER;
item = new BMenuItem("Show Window Border", new BMessage(what));
item->SetTarget(window);
item->SetMarked(what == MSG_HIDE_BORDER);
settingsM->AddItem(item);
item = new BMenuItem("Auto Raise", new BMessage(MSG_TOGGLE_AUTORAISE));
item->SetTarget(window);
item->SetMarked(window->AutoRaise());
settingsM->AddItem(item);
item = new BMenuItem("Show On All Workspaces", new BMessage(MSG_SHOW_ON_ALL_WORKSPACES));
item->SetTarget(window);
item->SetMarked(window->ShowOnAllWorkspaces());
settingsM->AddItem(item);
menu->AddItem(settingsM);
menu->AddSeparatorItem();
// pad commands
BMenu* padM = new BMenu("Pad");
padM->SetFont(be_plain_font);
// new pad
item = new BMenuItem("New", new BMessage(MSG_ADD_WINDOW));
item->SetTarget(be_app);
padM->AddItem(item);
// new pad
item = new BMenuItem("Clone", new BMessage(MSG_ADD_WINDOW));
item->SetTarget(window);
padM->AddItem(item);
padM->AddSeparatorItem();
// close
item = new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED));
item->SetTarget(window);
padM->AddItem(item);
menu->AddItem(padM);
// app commands
BMenu* appM = new BMenu("LaunchBox");
appM->SetFont(be_plain_font);
// about
item = new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED));
item->SetTarget(be_app);
appM->AddItem(item);
// quit
item = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED));
item->SetTarget(be_app);
appM->AddItem(item);
menu->AddItem(appM);
// finish popup
menu->SetAsyncAutoDestruct(true);
menu->SetFont(be_plain_font);
where = ConvertToScreen(where);
BRect mouseRect(where, where);
mouseRect.InsetBy(-4.0, -4.0);
menu->Go(where, true, false, mouseRect, true);
}
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef PAD_VIEW_H
#define PAD_VIEW_H
#include <View.h>
class LaunchButton;
class PadView : public BView {
public:
PadView(const char* name);
virtual ~PadView();
// BView interface
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);
// PadView
void AddButton(LaunchButton* button,
LaunchButton* beforeButton = NULL);
bool RemoveButton(LaunchButton* button);
LaunchButton* ButtonAt(int32 index) const;
void DisplayMenu(BPoint where,
LaunchButton* button = NULL) const;
private:
BPoint fDragOffset;
bool fDragging;
bigtime_t fClickTime;
};
#endif // PAD_VIEW_H
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "Panel.h"
#include <stdio.h>
#include <InterfaceDefs.h>
#include <Message.h>
#include <MessageFilter.h>
class EscapeFilter : public BMessageFilter {
public:
EscapeFilter(Panel* target)
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fPanel(target)
{
}
virtual ~EscapeFilter()
{
}
virtual filter_result Filter(BMessage* message, BHandler** target)
{
filter_result result = B_DISPATCH_MESSAGE;
switch (message->what) {
case B_KEY_DOWN:
case B_UNMAPPED_KEY_DOWN: {
uint32 key;
if (message->FindInt32("raw_char", (int32*)&key) >= B_OK) {
if (key == B_ESCAPE) {
result = B_SKIP_MESSAGE;
fPanel->Cancel();
}
}
break;
}
default:
break;
}
return result;
}
private:
Panel* fPanel;
};
// constructor
Panel::Panel(BRect frame, const char* title,
window_type type, uint32 flags,
uint32 workspace)
: BWindow(frame, title, type, flags, workspace)
{
_InstallFilter();
}
// constructor
Panel::Panel(BRect frame, const char* title,
window_look look, window_feel feel,
uint32 flags, uint32 workspace)
: BWindow(frame, title, look, feel, flags, workspace)
{
_InstallFilter();
}
// destructor
Panel::~Panel()
{
}
// MessageReceived
void
Panel::Cancel()
{
PostMessage(B_QUIT_REQUESTED);
}
// _InstallFilter
void
Panel::_InstallFilter()
{
AddCommonFilter(new EscapeFilter(this));
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef PANEL_H
#define PANEL_H
#include <Window.h>
class Panel : public BWindow {
public:
Panel(BRect frame,
const char* title,
window_type type,
uint32 flags,
uint32 workspace = B_CURRENT_WORKSPACE);
Panel(BRect frame,
const char* title,
window_look look,
window_feel feel,
uint32 flags,
uint32 workspace = B_CURRENT_WORKSPACE);
virtual ~Panel();
// Panel
virtual void Cancel();
private:
void _InstallFilter();
};
#endif // PANEL_H
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include <stdio.h>
#include "App.h"
int
main(int argc, char** argv)
{
new App();
be_app->Run();
delete be_app;
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
#!/bin/sh
../../../generated/tests/libbe_test/x86/apps/run_haiku_registrar || exit
if test -f ../../../generated/tests/libbe_test/x86/apps/haiku_app_server; then
../../../generated/tests/libbe_test/x86/apps//haiku_app_server &
else
echo "You need to \"TARGET_PLATFORM=libbe_test jam install-test-apps\" first."
fi
sleep 1s
if test -f ../../../generated/tests/libbe_test/x86/apps/LaunchBox; then
../../../generated/tests/libbe_test/x86/apps/LaunchBox
else
echo "You need to \"TARGET_PLATFORM=libbe_test jam install-test-apps\" first."
fi
+115
View File
@@ -0,0 +1,115 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "support.h"
#include <stdio.h>
#include <string.h>
#include <Directory.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Screen.h>
#include <View.h>
// load_settings
status_t
load_settings(BMessage* message, const char* fileName, const char* folder)
{
status_t ret = B_BAD_VALUE;
if (message) {
BPath path;
if ((ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path)) == B_OK) {
// passing folder is optional
if (folder)
ret = path.Append( folder );
if (ret == B_OK && (ret = path.Append(fileName)) == B_OK ) {
BFile file(path.Path(), B_READ_ONLY);
if ((ret = file.InitCheck()) == B_OK) {
ret = message->Unflatten(&file);
file.Unset();
}
}
}
}
return ret;
}
// save_settings
status_t
save_settings(BMessage* message, const char* fileName, const char* folder)
{
status_t ret = B_BAD_VALUE;
if (message) {
BPath path;
if ((ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path)) == B_OK) {
// passing folder is optional
if (folder && (ret = path.Append(folder)) == B_OK)
ret = create_directory(path.Path(), 0777);
if (ret == B_OK && (ret = path.Append(fileName)) == B_OK) {
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
if ((ret = file.InitCheck()) == B_OK) {
ret = message->Flatten(&file);
file.Unset();
}
}
}
}
return ret;
}
// stroke_frame
void
stroke_frame(BView* v, BRect r, rgb_color left, rgb_color top,
rgb_color right, rgb_color bottom)
{
if (v && r.IsValid()) {
v->BeginLineArray(4);
v->AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), left);
v->AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), top);
v->AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), right);
v->AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), bottom);
v->EndLineArray();
}
}
// make_sure_frame_is_on_screen
bool
make_sure_frame_is_on_screen(BRect& frame, BWindow* window = NULL)
{
BScreen* screen = window ? new BScreen(window) : new BScreen(B_MAIN_SCREEN_ID);
bool success = false;
if (frame.IsValid() && screen->IsValid()) {
BRect screenFrame = screen->Frame();
if (!screenFrame.Contains(frame)) {
// make sure frame fits in the screen
if (frame.Width() > screenFrame.Width())
frame.right -= frame.Width() - screenFrame.Width() + 10.0;
if (frame.Height() > screenFrame.Height())
frame.bottom -= frame.Height() - screenFrame.Height() + 30.0;
// frame is now at the most the size of the screen
if (frame.right > screenFrame.right)
frame.OffsetBy(-(frame.right - screenFrame.right), 0.0);
if (frame.bottom > screenFrame.bottom)
frame.OffsetBy(0.0, -(frame.bottom - screenFrame.bottom));
if (frame.left < screenFrame.left)
frame.OffsetBy((screenFrame.left - frame.left), 0.0);
if (frame.top < screenFrame.top)
frame.OffsetBy(0.0, (screenFrame.top - frame.top));
}
success = true;
}
delete screen;
return success;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#ifndef SUPPORT_H
#define SUPPORT_H
#include <GraphicsDefs.h>
#include <Rect.h>
class BMessage;
class BView;
class BWindow;
status_t load_settings(BMessage* message, const char* fileName,
const char* folder = NULL);
status_t save_settings(BMessage* message, const char* fileName,
const char* folder = NULL);
// looper of view must be locked!
void stroke_frame(BView* view, BRect frame,
rgb_color left, rgb_color top,
rgb_color right, rgb_color bottom);
bool make_sure_frame_is_on_screen(BRect& frame, BWindow* window = NULL);
#endif // SUPPORT_H