Initial Checkin. Coded by Oliver Ruiz Dorantes (urnen@users.sf.net)
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@589 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
267cf83fb3
commit
48d741f719
53
src/prefs/sounds/Colors.h
Normal file
53
src/prefs/sounds/Colors.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//Useful until be gets around to making these sorts of things
|
||||||
|
//globals akin to be_plain_font, etc.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _SGB_COLORS_H_
|
||||||
|
#define _SGB_COLORS_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CONSTANT DEFINITIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
//Be standard UI colors
|
||||||
|
const rgb_color BeBackgroundGrey = {216,216,216, 255};
|
||||||
|
const rgb_color BeInactiveControlGrey = {240,240,240, 255};
|
||||||
|
const rgb_color BeFocusBlue = {0, 0, 229, 255};
|
||||||
|
const rgb_color BeHighlight = {255,255,255, 255};
|
||||||
|
const rgb_color BeShadow = {152,152,152, 255};
|
||||||
|
const rgb_color BeDarkShadow = {108,108,108, 255};
|
||||||
|
const rgb_color BeLightShadow = {194,194,194, 255};
|
||||||
|
const rgb_color BeButtonGrey = {232,232,232, 255};
|
||||||
|
const rgb_color BeInactiveGrey = {127,127,127, 255};
|
||||||
|
const rgb_color BeListSelectGrey = {178,178,178, 255};
|
||||||
|
const rgb_color BeTitleBarYellow = {255,203,0, 255};
|
||||||
|
|
||||||
|
//Other colors
|
||||||
|
const rgb_color Black = {0, 0, 0, 255};
|
||||||
|
const rgb_color White = {255,255,255, 255};
|
||||||
|
const rgb_color Red = {255,0, 0, 255};
|
||||||
|
const rgb_color Green = {0, 167,0, 255};
|
||||||
|
const rgb_color LightGreen = {90, 240,90, 255};
|
||||||
|
const rgb_color Blue = {49, 61, 225, 255};
|
||||||
|
const rgb_color LightBlue = {64, 162,255, 255};
|
||||||
|
const rgb_color Purple = {144,64, 221, 255};
|
||||||
|
const rgb_color LightPurple = {166,74, 255, 255};
|
||||||
|
const rgb_color Lavender = {193,122,255, 255};
|
||||||
|
const rgb_color Yellow = {255,203,0, 255};
|
||||||
|
const rgb_color Orange = {255,163,0, 255};
|
||||||
|
const rgb_color Flesh = {255,231,186, 255};
|
||||||
|
const rgb_color Tan = {208,182,121, 255};
|
||||||
|
const rgb_color Brown = {154,110,45, 255};
|
||||||
|
const rgb_color Grey = {200,200,200, 255};
|
||||||
|
const rgb_color LightMetallicBlue = {143,166,240, 255};
|
||||||
|
const rgb_color MedMetallicBlue = {75, 96, 154, 255};
|
||||||
|
const rgb_color DarkMetallicBlue = {78, 89, 126, 255};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
43
src/prefs/sounds/HApp.cpp
Normal file
43
src/prefs/sounds/HApp.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "HApp.h"
|
||||||
|
#include "HWindow.h"
|
||||||
|
#include "HAboutWindow.h"
|
||||||
|
#include "RectUtils.h"
|
||||||
|
|
||||||
|
#define APP_SIG "application/x-vnd.openSounds"
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HApp::HApp() :BApplication(APP_SIG)
|
||||||
|
{
|
||||||
|
BRect rect;
|
||||||
|
RectUtils utils;
|
||||||
|
if(utils.LoadRectFromApp("window_rect",&rect) == false)
|
||||||
|
{
|
||||||
|
rect.Set(50,50,450,400);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWindow *win = new HWindow(rect,"OpenSounds");
|
||||||
|
win->Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor
|
||||||
|
***********************************************************/
|
||||||
|
HApp::~HApp()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* AboutRequested
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HApp::AboutRequested()
|
||||||
|
{
|
||||||
|
(new HAboutWindow("openSounds",
|
||||||
|
__DATE__,
|
||||||
|
"Created by Atsushi Takamatsu @ Sapporo,Japan.\nOpenBeOS Development by Oliver Ruiz Dorantes @ Tarragona,Spain",
|
||||||
|
"http://anas.worldonline.es/urnenfel/beos/openbeos",
|
||||||
|
"E-Mail: urnenfelder@worldonline.es"))->Show();
|
||||||
|
}
|
13
src/prefs/sounds/HApp.h
Normal file
13
src/prefs/sounds/HApp.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __HAPP_H__
|
||||||
|
#define __HAPP_H__
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
|
||||||
|
class HApp :public BApplication{
|
||||||
|
public:
|
||||||
|
HApp();
|
||||||
|
virtual ~HApp();
|
||||||
|
protected:
|
||||||
|
virtual void AboutRequested();
|
||||||
|
};
|
||||||
|
#endif
|
82
src/prefs/sounds/HEventItem.cpp
Normal file
82
src/prefs/sounds/HEventItem.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include "HEventItem.h"
|
||||||
|
#include "ResourceUtils.h"
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <View.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <MediaFiles.h>
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Beep.h>
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HEventItem::HEventItem(const char* name,const char* path)
|
||||||
|
:CLVEasyItem(0,false,false,20)
|
||||||
|
,fName(name)
|
||||||
|
{
|
||||||
|
//BBitmap* bitmap = new BBitmap(BRect(0,0,15,15),B_COLOR_8_BIT);
|
||||||
|
BBitmap *bitmap = ResourceUtils().GetBitmapResource('BBMP',"Sound Bitmap");
|
||||||
|
SetColumnContent(0,bitmap,false);
|
||||||
|
SetColumnContent(1,fName.String(),false,false);
|
||||||
|
SetColumnContent(2,"",false,false);
|
||||||
|
delete bitmap;
|
||||||
|
SetPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor
|
||||||
|
***********************************************************/
|
||||||
|
HEventItem::~HEventItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set path
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventItem::SetPath(const char* in_path)
|
||||||
|
{
|
||||||
|
fPath = in_path;
|
||||||
|
BPath path(in_path);
|
||||||
|
BPath parent;
|
||||||
|
BMediaFiles mfiles;
|
||||||
|
entry_ref ref;
|
||||||
|
|
||||||
|
if(path.InitCheck() == B_OK)
|
||||||
|
{
|
||||||
|
SetColumnContent(2,path.Leaf(),false,false);
|
||||||
|
::get_ref_for_path(path.Path(),&ref);
|
||||||
|
if(mfiles.SetRefFor(BMediaFiles::B_SOUNDS,Name(),ref) != B_OK)
|
||||||
|
(new BAlert("","Error","OK"))->Go();
|
||||||
|
path.GetParent(&parent);
|
||||||
|
SetColumnContent(3,parent.Path(),false,false);// falta
|
||||||
|
}else{
|
||||||
|
SetColumnContent(2,"<none>",false,false);
|
||||||
|
//if(mfiles.RemoveRefFor(BMediaFiles::B_SOUNDS,Name(),ref) != B_OK)
|
||||||
|
// (new BAlert("","Entry not found","OK"))->Go();
|
||||||
|
mfiles.RemoveItem(BMediaFiles::B_SOUNDS,Name());
|
||||||
|
::add_system_beep_event(Name());
|
||||||
|
SetColumnContent(3,"<none>",false,false);// falta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Remove
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventItem::Remove()
|
||||||
|
{
|
||||||
|
BMediaFiles mfiles;
|
||||||
|
|
||||||
|
mfiles.RemoveItem(BMediaFiles::B_SOUNDS,Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
*
|
||||||
|
***********************************************************/
|
||||||
|
const char*
|
||||||
|
HEventItem::Path() const
|
||||||
|
{
|
||||||
|
return fPath.String();
|
||||||
|
}
|
26
src/prefs/sounds/HEventItem.h
Normal file
26
src/prefs/sounds/HEventItem.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __HEVENTITEM_H__
|
||||||
|
#define __HEVENTITEM_H__
|
||||||
|
|
||||||
|
#include "CLVEasyItem.h"
|
||||||
|
#include <String.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
|
||||||
|
|
||||||
|
class HEventItem :public CLVEasyItem {
|
||||||
|
public:
|
||||||
|
HEventItem(const char* event_name
|
||||||
|
,const char* path);
|
||||||
|
virtual ~HEventItem();
|
||||||
|
|
||||||
|
const char* Name()const {return fName.String();}
|
||||||
|
const char* Path()const;
|
||||||
|
void Remove();
|
||||||
|
void SetPath(const char* path);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fName;
|
||||||
|
BString fPath;
|
||||||
|
float fText_offset;
|
||||||
|
};
|
||||||
|
#endif
|
242
src/prefs/sounds/HEventList.cpp
Normal file
242
src/prefs/sounds/HEventList.cpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
#include "HEventList.h"
|
||||||
|
#include "HEventItem.h"
|
||||||
|
|
||||||
|
#include "HWindow.h"
|
||||||
|
#include "IconMenuItem.h"
|
||||||
|
|
||||||
|
#include <ClassInfo.h>
|
||||||
|
#include <MediaFiles.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <MenuField.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Mime.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HEventList::HEventList(BRect rect
|
||||||
|
,CLVContainerView** ContainerView
|
||||||
|
,const char* name)
|
||||||
|
:ColumnListView(rect
|
||||||
|
,ContainerView
|
||||||
|
,name
|
||||||
|
,B_FOLLOW_ALL
|
||||||
|
,B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE
|
||||||
|
,B_SINGLE_SELECTION_LIST
|
||||||
|
,false
|
||||||
|
,false
|
||||||
|
,true)
|
||||||
|
{
|
||||||
|
AddColumn(new CLVColumn(NULL,20,CLV_LOCK_AT_BEGINNING|CLV_NOT_MOVABLE|
|
||||||
|
CLV_NOT_RESIZABLE|CLV_PUSH_PASS|CLV_MERGE_WITH_RIGHT));
|
||||||
|
AddColumn(new CLVColumn("Event",100,CLV_SORT_KEYABLE));
|
||||||
|
AddColumn( new CLVColumn("Sound",130,CLV_SORT_KEYABLE));
|
||||||
|
AddColumn( new CLVColumn("Path",200,CLV_SORT_KEYABLE));
|
||||||
|
SetSortKey(1);
|
||||||
|
SetSortFunction(CLVEasyItem::CompareItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor
|
||||||
|
***********************************************************/
|
||||||
|
HEventList::~HEventList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set type
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::SetType(const char* type)
|
||||||
|
{
|
||||||
|
RemoveAll();
|
||||||
|
BMediaFiles mfiles;
|
||||||
|
mfiles.RewindRefs(type);
|
||||||
|
|
||||||
|
BString name;
|
||||||
|
entry_ref ref;
|
||||||
|
while(mfiles.GetNextRef(&name,&ref) == B_OK)
|
||||||
|
{
|
||||||
|
AddItem(new HEventItem(name.String(),BPath(&ref).Path()));
|
||||||
|
}
|
||||||
|
SortItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Remove all items
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::RemoveAll()
|
||||||
|
{
|
||||||
|
int32 count = CountItems();
|
||||||
|
while(count> 0)
|
||||||
|
delete fPointerList.RemoveItem(--count);
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Add event item
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::AddEvent(HEventItem *item)
|
||||||
|
{
|
||||||
|
fPointerList.AddItem(item);
|
||||||
|
AddItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Remove event item
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::RemoveEvent(HEventItem *item)
|
||||||
|
{
|
||||||
|
item->Remove();
|
||||||
|
fPointerList.RemoveItem(item);
|
||||||
|
RemoveItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Selection Changed
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::SelectionChanged()
|
||||||
|
{
|
||||||
|
int32 sel = CurrentSelection();
|
||||||
|
if(sel >= 0)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(ItemAt(sel),HEventItem);
|
||||||
|
if(!item)
|
||||||
|
return;
|
||||||
|
BMessage msg(M_EVENT_CHANGED);
|
||||||
|
msg.AddString("name",item->Name());
|
||||||
|
|
||||||
|
msg.AddString("path",item->Path());
|
||||||
|
Window()->PostMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* MouseDown
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HEventList::MouseDown(BPoint pos)
|
||||||
|
{
|
||||||
|
BPoint point = pos;
|
||||||
|
int32 buttons;
|
||||||
|
|
||||||
|
Window()->CurrentMessage()->FindInt32("buttons", &buttons);
|
||||||
|
this->MakeFocus(true);
|
||||||
|
|
||||||
|
// 右クリックのハンドリング
|
||||||
|
if(buttons == B_SECONDARY_MOUSE_BUTTON)
|
||||||
|
{
|
||||||
|
int32 sel = IndexOf(pos);
|
||||||
|
if(sel >= 0)
|
||||||
|
Select(sel);
|
||||||
|
else
|
||||||
|
DeselectAll();
|
||||||
|
sel = CurrentSelection();
|
||||||
|
bool enabled = (sel >= 0)?true:false;
|
||||||
|
|
||||||
|
BPopUpMenu *theMenu = new BPopUpMenu("RIGHT_CLICK",false,false);
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(10);
|
||||||
|
theMenu->SetFont(&font);
|
||||||
|
/* HWindow *parent = cast_as(Window(),HWindow);
|
||||||
|
|
||||||
|
BMenuField *menufield = cast_as(parent->FindView("filemenu"),BMenuField);
|
||||||
|
BMenu *old_menu = menufield->Menu();
|
||||||
|
|
||||||
|
int32 menus = old_menu->CountItems();
|
||||||
|
|
||||||
|
for(register int32 i = 0;i < menus-3;i++)
|
||||||
|
{
|
||||||
|
BMenuItem *old_item = old_menu->ItemAt(i);
|
||||||
|
if(!old_item)
|
||||||
|
continue;
|
||||||
|
BMessage *old_msg = old_item->Message();
|
||||||
|
BMessage *msg = new BMessage(*old_msg );
|
||||||
|
BMenuItem *new_item = new BMenuItem(old_item->Label(),msg);
|
||||||
|
new_item->SetEnabled(enabled);
|
||||||
|
theMenu->AddItem(new_item);
|
||||||
|
}
|
||||||
|
theMenu->AddSeparatorItem();
|
||||||
|
theMenu->AddItem(new BMenuItem("<none>",new BMessage(M_NONE_MESSAGE)));
|
||||||
|
theMenu->AddItem(new BMenuItem("Other…",new BMessage(M_OTHER_MESSAGE)));
|
||||||
|
theMenu->FindItem(M_NONE_MESSAGE)->SetEnabled(enabled);
|
||||||
|
theMenu->FindItem(M_OTHER_MESSAGE)->SetEnabled(enabled);
|
||||||
|
*/
|
||||||
|
BMenu *submenu = new BMenu("Open With…");
|
||||||
|
submenu->SetFont(&font);
|
||||||
|
BMimeType mime("audio");
|
||||||
|
|
||||||
|
if(enabled)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(this->ItemAt(sel),HEventItem);
|
||||||
|
const char* path = item->Path();
|
||||||
|
BFile file(path,B_READ_ONLY);
|
||||||
|
BNodeInfo ninfo(&file);
|
||||||
|
char type[B_MIME_TYPE_LENGTH+1];
|
||||||
|
ninfo.GetType(type);
|
||||||
|
mime.SetTo(type);
|
||||||
|
}
|
||||||
|
BMessage message;
|
||||||
|
mime.GetSupportingApps(&message);
|
||||||
|
/* int32 sub;
|
||||||
|
int32 supers;
|
||||||
|
message.FindInt32("be:subs", &sub);
|
||||||
|
message.FindInt32("be:supers", &supers);
|
||||||
|
*/
|
||||||
|
for (int32 index =0; ; index++)
|
||||||
|
{
|
||||||
|
const char *signature;
|
||||||
|
int32 length;
|
||||||
|
|
||||||
|
if (message.FindData("applications", 'CSTR', index, (const void **)&signature,
|
||||||
|
&length) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
entry_ref ref;
|
||||||
|
if(be_roster->FindApp(signature,&ref) != B_OK)
|
||||||
|
continue;
|
||||||
|
BMessage *msg = new BMessage(M_OPEN_WITH);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
msg->AddString("sig",signature);
|
||||||
|
|
||||||
|
BBitmap *icon = new BBitmap(BRect(0,0,15,15),B_COLOR_8_BIT);
|
||||||
|
BNodeInfo::GetTrackerIcon(&ref,icon,B_MINI_ICON);
|
||||||
|
|
||||||
|
submenu->AddItem(new IconMenuItem(BPath(&ref).Leaf(),msg,0,0,icon));
|
||||||
|
// push each of the supporting apps signature uniquely
|
||||||
|
//queryIterator->PushUniqueSignature(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
theMenu->AddItem(submenu);
|
||||||
|
theMenu->AddSeparatorItem();
|
||||||
|
theMenu->AddItem(new BMenuItem("Remove Event",new BMessage(M_REMOVE_EVENT)));
|
||||||
|
//theMenu->FindItem(M_OPEN_WITH)->SetEnabled(enabled);
|
||||||
|
theMenu->FindItem(M_REMOVE_EVENT)->SetEnabled(enabled);
|
||||||
|
submenu->SetEnabled(enabled);
|
||||||
|
BRect r;
|
||||||
|
ConvertToScreen(&pos);
|
||||||
|
r.top = pos.y - 5;
|
||||||
|
r.bottom = pos.y + 5;
|
||||||
|
r.left = pos.x - 5;
|
||||||
|
r.right = pos.x + 5;
|
||||||
|
|
||||||
|
BMenuItem *theItem = theMenu->Go(pos, false,true,r);
|
||||||
|
if(theItem)
|
||||||
|
{
|
||||||
|
BMessage* aMessage = theItem->Message();
|
||||||
|
if(aMessage)
|
||||||
|
this->Window()->PostMessage(aMessage);
|
||||||
|
}
|
||||||
|
delete theMenu;
|
||||||
|
}else
|
||||||
|
ColumnListView::MouseDown(point);
|
||||||
|
}
|
30
src/prefs/sounds/HEventList.h
Normal file
30
src/prefs/sounds/HEventList.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __HEVENTLIST_H__
|
||||||
|
#define __HEVENTLIST_H__
|
||||||
|
|
||||||
|
#include "ColumnListView.h"
|
||||||
|
|
||||||
|
class HEventItem;
|
||||||
|
|
||||||
|
enum{
|
||||||
|
M_EVENT_CHANGED = 'SCAG'
|
||||||
|
};
|
||||||
|
|
||||||
|
class HEventList :public ColumnListView {
|
||||||
|
public:
|
||||||
|
HEventList(BRect rect
|
||||||
|
,CLVContainerView** ContainerView
|
||||||
|
,const char* name="EventList");
|
||||||
|
virtual ~HEventList();
|
||||||
|
void RemoveAll();
|
||||||
|
void AddEvent(HEventItem *item);
|
||||||
|
void RemoveEvent(HEventItem *item);
|
||||||
|
|
||||||
|
void SetType(const char* type);
|
||||||
|
protected:
|
||||||
|
virtual void MouseDown(BPoint point);
|
||||||
|
virtual void SelectionChanged();
|
||||||
|
private:
|
||||||
|
BList fPointerList;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
22
src/prefs/sounds/HTypeList.h
Normal file
22
src/prefs/sounds/HTypeList.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef __HTYPELIST_H__
|
||||||
|
#define __HTYPELIST_H__
|
||||||
|
|
||||||
|
#include <ListView.h>
|
||||||
|
|
||||||
|
enum{
|
||||||
|
M_TYPE_CHANGED = 'TCHD'
|
||||||
|
};
|
||||||
|
|
||||||
|
class HTypeList :public BListView{
|
||||||
|
public:
|
||||||
|
HTypeList(BRect rect,const char* name = "TypeList");
|
||||||
|
virtual ~HTypeList();
|
||||||
|
protected:
|
||||||
|
void AddType(const char* name);
|
||||||
|
void Init();
|
||||||
|
void RemoveAll();
|
||||||
|
virtual void SelectionChanged();
|
||||||
|
private:
|
||||||
|
BList fPointerList;
|
||||||
|
};
|
||||||
|
#endif
|
578
src/prefs/sounds/HWindow.cpp
Normal file
578
src/prefs/sounds/HWindow.cpp
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
#include "HWindow.h"
|
||||||
|
#include "HEventList.h"
|
||||||
|
#include "HEventItem.h"
|
||||||
|
#include "HTypeList.h"
|
||||||
|
#include "BetterScrollView.h"
|
||||||
|
#include "RectUtils.h"
|
||||||
|
#include "TextEntryAlert.h"
|
||||||
|
|
||||||
|
#include <ClassInfo.h>
|
||||||
|
#include <MediaFiles.h>
|
||||||
|
#include <MenuBar.h>
|
||||||
|
#include <Box.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <MenuField.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <Beep.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Sound.h>
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HWindow::HWindow(BRect rect ,const char* name)
|
||||||
|
:_inherited(rect,name,B_TITLED_WINDOW,0)
|
||||||
|
,fFilePanel(NULL)
|
||||||
|
,fPlayer(NULL)
|
||||||
|
{
|
||||||
|
InitMenu();
|
||||||
|
InitGUI();
|
||||||
|
float min_width,min_height,max_width,max_height;
|
||||||
|
GetSizeLimits(&min_width,&max_width,&min_height,&max_height);
|
||||||
|
min_width = 320;
|
||||||
|
min_height = 150;
|
||||||
|
SetSizeLimits(min_width,max_width,min_height,max_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor
|
||||||
|
***********************************************************/
|
||||||
|
HWindow::~HWindow()
|
||||||
|
{
|
||||||
|
delete fFilePanel;
|
||||||
|
delete fPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Initialize GUIs.
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::InitGUI()
|
||||||
|
{
|
||||||
|
BRect rect = Bounds();
|
||||||
|
rect.top = KeyMenuBar()->Bounds().Height()+1;
|
||||||
|
|
||||||
|
/*fTypeList = new HTypeList(rect);
|
||||||
|
BScrollView *scrollView = new BScrollView(""
|
||||||
|
,fTypeList
|
||||||
|
,B_FOLLOW_LEFT|B_FOLLOW_TOP_BOTTOM
|
||||||
|
,0
|
||||||
|
,false
|
||||||
|
,true);
|
||||||
|
AddChild(scrollView);
|
||||||
|
*/
|
||||||
|
//rect.left = rect.right + B_V_SCROLL_BAR_WIDTH+3;
|
||||||
|
rect.right -= B_V_SCROLL_BAR_WIDTH;
|
||||||
|
rect.bottom = Bounds().bottom - B_H_SCROLL_BAR_HEIGHT - 80;
|
||||||
|
BetterScrollView *betterScrollView;
|
||||||
|
fEventList = new HEventList(rect,(CLVContainerView**)&betterScrollView);
|
||||||
|
fEventList->SetType(BMediaFiles::B_SOUNDS);
|
||||||
|
AddChild(betterScrollView);
|
||||||
|
|
||||||
|
app_info info;
|
||||||
|
be_app->GetAppInfo(&info);
|
||||||
|
BEntry entry(&info.ref);
|
||||||
|
float width;
|
||||||
|
BFile appfile(&entry,B_WRITE_ONLY);
|
||||||
|
attr_info ainfo;
|
||||||
|
|
||||||
|
if(appfile.GetAttrInfo("event_width",&ainfo) == B_OK)
|
||||||
|
{
|
||||||
|
appfile.ReadAttr("event_width",B_FLOAT_TYPE,0,&width,sizeof(float));
|
||||||
|
CLVColumn *col = fEventList->ColumnAt(1);
|
||||||
|
if(col)
|
||||||
|
col->SetWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(appfile.GetAttrInfo("sound_width",&ainfo) == B_OK)
|
||||||
|
{
|
||||||
|
appfile.ReadAttr("sound_width",B_FLOAT_TYPE,0,&width,sizeof(float));
|
||||||
|
CLVColumn *col = fEventList->ColumnAt(2);
|
||||||
|
if(col)
|
||||||
|
col->SetWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.top = rect.bottom +1;
|
||||||
|
rect.bottom = Bounds().bottom;
|
||||||
|
rect.right = Bounds().right;
|
||||||
|
BView *view = new BView(rect,"",B_FOLLOW_LEFT_RIGHT|B_FOLLOW_BOTTOM,B_WILL_DRAW|B_PULSE_NEEDED);
|
||||||
|
view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
AddChild(view);
|
||||||
|
rect = view->Bounds();
|
||||||
|
rect.top += 10;
|
||||||
|
rect.bottom -= 10;
|
||||||
|
rect.left += 10;
|
||||||
|
rect.right -= 10;
|
||||||
|
BBox *box = new BBox(rect,"",B_FOLLOW_ALL);
|
||||||
|
view->AddChild(box);
|
||||||
|
rect = box->Bounds();
|
||||||
|
rect.top += 10;
|
||||||
|
rect.left += 10;
|
||||||
|
rect.right -= 10;
|
||||||
|
rect.bottom = rect.top + 20;
|
||||||
|
BMenu *menu = new BMenu("file");
|
||||||
|
menu->SetRadioMode(true);
|
||||||
|
menu->SetLabelFromMarked(true);
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("<none>",new BMessage(M_NONE_MESSAGE)));
|
||||||
|
menu->AddItem(new BMenuItem("Other…",new BMessage(M_OTHER_MESSAGE)));
|
||||||
|
BMenuField *menuField = new BMenuField(rect
|
||||||
|
,"filemenu"
|
||||||
|
,"Sound File:"
|
||||||
|
,menu
|
||||||
|
,B_FOLLOW_TOP|B_FOLLOW_LEFT);
|
||||||
|
menuField->SetDivider(menuField->StringWidth("Media Files:")+3);
|
||||||
|
box->AddChild(menuField);
|
||||||
|
rect.OffsetBy(0,25);
|
||||||
|
rect.left = rect.right - 80;
|
||||||
|
BButton *button = new BButton(rect
|
||||||
|
,"play"
|
||||||
|
,"Play"
|
||||||
|
,new BMessage(M_PLAY_MESSAGE)
|
||||||
|
,B_FOLLOW_RIGHT|B_FOLLOW_TOP);
|
||||||
|
box->AddChild(button);
|
||||||
|
|
||||||
|
rect.OffsetBy(-90,0);
|
||||||
|
button = new BButton(rect
|
||||||
|
,"stop"
|
||||||
|
,"Stop"
|
||||||
|
,new BMessage(M_STOP_MESSAGE)
|
||||||
|
,B_FOLLOW_RIGHT|B_FOLLOW_TOP);
|
||||||
|
box->AddChild(button);
|
||||||
|
|
||||||
|
rect.OffsetBy(-110,0);
|
||||||
|
button = new BButton(rect
|
||||||
|
,"setsystem"
|
||||||
|
,"As System event"
|
||||||
|
,NULL
|
||||||
|
,B_FOLLOW_RIGHT|B_FOLLOW_TOP);
|
||||||
|
button->ResizeToPreferred();
|
||||||
|
box->AddChild(button);
|
||||||
|
|
||||||
|
// setup file menu
|
||||||
|
SetupMenuField();
|
||||||
|
menu->FindItem("<none>")->SetMarked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Initalize Menus
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::InitMenu()
|
||||||
|
{
|
||||||
|
BMenuBar *menuBar = new BMenuBar(Bounds(),"MENUBAR");
|
||||||
|
BMenu *menu;
|
||||||
|
BMenuItem *item;
|
||||||
|
|
||||||
|
menu = new BMenu("File");
|
||||||
|
item = new BMenuItem("Add New Event…",new BMessage(M_ADD_EVENT),'A');
|
||||||
|
item->SetTarget(this);
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
item = new BMenuItem("Remove Event",new BMessage(M_REMOVE_EVENT),'R');
|
||||||
|
item->SetTarget(this);
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
item = new BMenuItem("About openSounds…",new BMessage(B_ABOUT_REQUESTED),0,0);
|
||||||
|
item->SetTarget(be_app);
|
||||||
|
menu->AddItem(item);
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
item = new BMenuItem("Quit",new BMessage(B_QUIT_REQUESTED),'Q',0);
|
||||||
|
menu->AddItem(item);
|
||||||
|
menuBar->AddItem(menu);
|
||||||
|
this->AddChild(menuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* MessageReceived
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
|
switch(message->what)
|
||||||
|
{
|
||||||
|
case M_OPEN_WITH:
|
||||||
|
{
|
||||||
|
entry_ref app_ref;
|
||||||
|
if(message->FindRef("refs",&app_ref) == B_OK)
|
||||||
|
{
|
||||||
|
BMessage msg(B_REFS_RECEIVED);
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(sel < 0)
|
||||||
|
break;
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
const char* path = item->Path();
|
||||||
|
entry_ref ref;
|
||||||
|
::get_ref_for_path(path,&ref);
|
||||||
|
msg.AddRef("refs",&ref);
|
||||||
|
be_roster->Launch(&app_ref,&msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_REMOVE_EVENT:
|
||||||
|
{
|
||||||
|
RemoveEvent();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_ADD_EVENT:
|
||||||
|
{
|
||||||
|
char new_Event[20];
|
||||||
|
(new BAlert("Add an event","Note that to use this event, applications should call him by the function:\n status_t system_beep(const char *eventName);\n declared on be/support/Beep.h","OK",NULL,NULL,
|
||||||
|
B_WIDTH_AS_USUAL,B_WARNING_ALERT))->Go();
|
||||||
|
if (((new TextEntryAlert("Add an event ...","Type name: ", "new event name",
|
||||||
|
"Create","Cancel",true,120,1,B_WIDTH_AS_USUAL,false,
|
||||||
|
NULL,B_FLOATING_WINDOW_LOOK)
|
||||||
|
)->Go(new_Event,20))==0){
|
||||||
|
add_system_beep_event(new_Event);
|
||||||
|
|
||||||
|
BMediaFiles mfiles;
|
||||||
|
mfiles.RewindRefs("Sound");
|
||||||
|
entry_ref ref;
|
||||||
|
mfiles.GetRefFor("Sound",new_Event,&ref);
|
||||||
|
fEventList->AddEvent(new HEventItem(new_Event,BPath(&ref).Path()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_OTHER_MESSAGE:
|
||||||
|
{
|
||||||
|
if(!fFilePanel)
|
||||||
|
fFilePanel = new BFilePanel();
|
||||||
|
fFilePanel->SetTarget(this);
|
||||||
|
fFilePanel->Show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case B_REFS_RECEIVED:
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(message->FindRef("refs",&ref) == B_OK && sel >= 0)
|
||||||
|
{
|
||||||
|
BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField);
|
||||||
|
BMenu *menu = menufield->Menu();
|
||||||
|
// check audio file
|
||||||
|
BNode node(&ref);
|
||||||
|
BNodeInfo ninfo(&node);
|
||||||
|
char type[B_MIME_TYPE_LENGTH+1];
|
||||||
|
ninfo.GetType(type);
|
||||||
|
BMimeType mtype(type);
|
||||||
|
BMimeType superType;
|
||||||
|
mtype.GetSupertype(&superType);
|
||||||
|
if(strcmp(superType.Type(),"audio") != 0)
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
(new BAlert("","This is not a audio file.","OK",NULL,NULL,
|
||||||
|
B_WIDTH_AS_USUAL,B_STOP_ALERT))->Go();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// add file item
|
||||||
|
BMessage *msg = new BMessage(M_ITEM_MESSAGE);
|
||||||
|
BPath path(&ref);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
if(!(menu->FindItem(path.Leaf())))
|
||||||
|
menu->AddItem(new BMenuItem(path.Leaf(),msg),0);
|
||||||
|
// refresh item
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
item->SetPath(path.Path());
|
||||||
|
fEventList->InvalidateItem(sel);
|
||||||
|
// check file menu
|
||||||
|
BMenuItem *menuitem = menu->FindItem(path.Leaf());
|
||||||
|
if(menuitem)
|
||||||
|
menuitem->SetMarked(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_PLAY_MESSAGE:
|
||||||
|
{
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(sel >= 0)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
//system_beep(item->Name());
|
||||||
|
const char* path = item->Path();
|
||||||
|
if(path)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
::get_ref_for_path(path,&ref);
|
||||||
|
/*BSound *sound = new BSound(&ref);
|
||||||
|
if(sound->InitCheck() == B_OK)
|
||||||
|
{
|
||||||
|
fSoundPlayer.Start();
|
||||||
|
fId = fSoundPlayer.StartPlaying(sound);
|
||||||
|
sound->ReleaseRef();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//fSoundHandle = ::play_sound(&ref,false,false,true);
|
||||||
|
delete fPlayer;
|
||||||
|
fPlayer = new BFileGameSound(&ref,false);
|
||||||
|
fPlayer->StartPlaying();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_STOP_MESSAGE:
|
||||||
|
{
|
||||||
|
//::stop_sound(fSoundHandle);
|
||||||
|
if(!fPlayer)
|
||||||
|
break;
|
||||||
|
if(fPlayer->IsPlaying())
|
||||||
|
{
|
||||||
|
fPlayer->StopPlaying();
|
||||||
|
delete fPlayer;
|
||||||
|
fPlayer = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_EVENT_CHANGED:
|
||||||
|
{
|
||||||
|
const char* path;
|
||||||
|
BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField);
|
||||||
|
BMenu *menu = menufield->Menu();
|
||||||
|
|
||||||
|
if(message->FindString("path",&path) == B_OK)
|
||||||
|
{
|
||||||
|
BPath path(path);
|
||||||
|
if(path.InitCheck() != B_OK)
|
||||||
|
{
|
||||||
|
BMenuItem *item = menu->FindItem("<none>");
|
||||||
|
if(item)
|
||||||
|
item->SetMarked(true);
|
||||||
|
}else{
|
||||||
|
BMenuItem *item = menu->FindItem(path.Leaf());
|
||||||
|
if(item)
|
||||||
|
item->SetMarked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_ITEM_MESSAGE:
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
if(message->FindRef("refs",&ref) == B_OK)
|
||||||
|
{
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(sel >= 0)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
item->SetPath(BPath(&ref).Path());
|
||||||
|
fEventList->InvalidateItem(sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case M_NONE_MESSAGE:
|
||||||
|
{
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(sel >= 0)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
item->SetPath(NULL);
|
||||||
|
fEventList->InvalidateItem(sel);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
_inherited::MessageReceived(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Init menu
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::SetupMenuField()
|
||||||
|
{
|
||||||
|
BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField);
|
||||||
|
BMenu *menu = menufield->Menu();
|
||||||
|
int32 count = fEventList->CountItems();
|
||||||
|
for(register int32 i = 0;i < count;i++)
|
||||||
|
{
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(i),HEventItem);
|
||||||
|
if(!item)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BPath path(item->Path());
|
||||||
|
if(path.InitCheck() != B_OK)
|
||||||
|
continue;
|
||||||
|
if( menu->FindItem(path.Leaf()) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BMessage *msg = new BMessage(M_ITEM_MESSAGE);
|
||||||
|
entry_ref ref;
|
||||||
|
::get_ref_for_path(path.Path(),&ref);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
menu->AddItem(new BMenuItem(path.Leaf(),msg),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BPath path("/boot/beos/etc/sounds");
|
||||||
|
status_t err = B_OK;
|
||||||
|
BDirectory dir( path.Path() );
|
||||||
|
BEntry entry;
|
||||||
|
BPath item_path;
|
||||||
|
while( err == B_OK ){
|
||||||
|
err = dir.GetNextEntry( (BEntry*)&entry, TRUE );
|
||||||
|
if( entry.InitCheck() != B_NO_ERROR ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry.GetPath(&item_path);
|
||||||
|
|
||||||
|
if( menu->FindItem(item_path.Leaf()) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BMessage *msg = new BMessage(M_ITEM_MESSAGE);
|
||||||
|
entry_ref ref;
|
||||||
|
::get_ref_for_path(item_path.Path(),&ref);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.SetTo("/boot/home/config/sounds");
|
||||||
|
dir.SetTo(path.Path());
|
||||||
|
err = B_OK;
|
||||||
|
while( err == B_OK ){
|
||||||
|
err = dir.GetNextEntry( (BEntry*)&entry, TRUE );
|
||||||
|
if( entry.InitCheck() != B_NO_ERROR ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry.GetPath(&item_path);
|
||||||
|
|
||||||
|
if( menu->FindItem(item_path.Leaf()) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BMessage *msg = new BMessage(M_ITEM_MESSAGE);
|
||||||
|
entry_ref ref;
|
||||||
|
|
||||||
|
::get_ref_for_path(item_path.Path(),&ref);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.SetTo("/boot/home/media");
|
||||||
|
dir.SetTo(path.Path());
|
||||||
|
err = B_OK;
|
||||||
|
while( err == B_OK ){
|
||||||
|
err = dir.GetNextEntry( (BEntry*)&entry, TRUE );
|
||||||
|
if( entry.InitCheck() != B_NO_ERROR ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry.GetPath(&item_path);
|
||||||
|
|
||||||
|
if( menu->FindItem(item_path.Leaf()) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BMessage *msg = new BMessage(M_ITEM_MESSAGE);
|
||||||
|
entry_ref ref;
|
||||||
|
|
||||||
|
::get_ref_for_path(item_path.Path(),&ref);
|
||||||
|
msg->AddRef("refs",&ref);
|
||||||
|
menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Remove Event
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::RemoveEvent()
|
||||||
|
{
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
if(sel < 0)
|
||||||
|
return;
|
||||||
|
// check system beep event
|
||||||
|
HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem);
|
||||||
|
if(::strcmp(item->Name(),"Beep") == 0
|
||||||
|
||::strcmp(item->Name(),"Startup")==0
|
||||||
|
||::strcmp(item->Name(),"New E-mail") == 0)
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
(new BAlert("","This is a system beep event.","OK"))->Go();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
int32 index = (new BAlert("","Would you like to remove this event?","OK","Cancel"))->Go();
|
||||||
|
if(index == 0)
|
||||||
|
{
|
||||||
|
if(item)
|
||||||
|
fEventList->RemoveEvent(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Pulse
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::Pulse()
|
||||||
|
{
|
||||||
|
int32 sel = fEventList->CurrentSelection();
|
||||||
|
BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField);
|
||||||
|
BButton *button = cast_as(FindView("play"),BButton);
|
||||||
|
BButton *stop = cast_as(FindView("stop"),BButton);
|
||||||
|
|
||||||
|
if(!menufield)
|
||||||
|
return;
|
||||||
|
if(sel >=0)
|
||||||
|
{
|
||||||
|
menufield->SetEnabled(true);
|
||||||
|
button->SetEnabled(true);
|
||||||
|
}else{
|
||||||
|
menufield->SetEnabled(false);
|
||||||
|
button->SetEnabled(false);
|
||||||
|
}
|
||||||
|
if(fPlayer)
|
||||||
|
{
|
||||||
|
if(fPlayer->IsPlaying())
|
||||||
|
stop->SetEnabled(true);
|
||||||
|
else
|
||||||
|
stop->SetEnabled(false);
|
||||||
|
}else
|
||||||
|
stop->SetEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* DispatchMessage
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HWindow::DispatchMessage(BMessage *message,BHandler *handler)
|
||||||
|
{
|
||||||
|
if(message->what == B_PULSE)
|
||||||
|
Pulse();
|
||||||
|
BWindow::DispatchMessage(message,handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* QuitRequested
|
||||||
|
***********************************************************/
|
||||||
|
bool
|
||||||
|
HWindow::QuitRequested()
|
||||||
|
{
|
||||||
|
RectUtils utils;
|
||||||
|
CLVColumn *col = fEventList->ColumnAt(1);
|
||||||
|
float width = col->Width();
|
||||||
|
|
||||||
|
app_info info;
|
||||||
|
be_app->GetAppInfo(&info);
|
||||||
|
BEntry entry(&info.ref);
|
||||||
|
|
||||||
|
BFile appfile(&entry,B_WRITE_ONLY);
|
||||||
|
appfile.WriteAttr("event_width",B_FLOAT_TYPE,0,&width,sizeof(float));
|
||||||
|
|
||||||
|
col = fEventList->ColumnAt(2);
|
||||||
|
width = col->Width();
|
||||||
|
appfile.WriteAttr("sound_width",B_FLOAT_TYPE,0,&width,sizeof(float));
|
||||||
|
|
||||||
|
fEventList->RemoveAll();
|
||||||
|
|
||||||
|
utils.SaveRectToApp("window_rect",this->Frame());
|
||||||
|
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||||
|
return true;
|
||||||
|
}
|
44
src/prefs/sounds/HWindow.h
Normal file
44
src/prefs/sounds/HWindow.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef __HWINDOW_H__
|
||||||
|
#define __HWINDOW_H__
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
#include <FilePanel.h>
|
||||||
|
#include <FileGameSound.h>
|
||||||
|
|
||||||
|
class HEventList;
|
||||||
|
class HTypeList;
|
||||||
|
|
||||||
|
enum{
|
||||||
|
M_PLAY_MESSAGE = 'MPLM',
|
||||||
|
M_STOP_MESSAGE = 'MSTO',
|
||||||
|
M_REMOVE_MESSAGE = 'MREM',
|
||||||
|
M_ITEM_MESSAGE = 'MITE',
|
||||||
|
M_OTHER_MESSAGE = 'MOTH',
|
||||||
|
M_NONE_MESSAGE = 'MNON',
|
||||||
|
M_ADD_EVENT = 'MADE',
|
||||||
|
M_REMOVE_EVENT = 'MREE',
|
||||||
|
M_OPEN_WITH = 'MOPW'
|
||||||
|
};
|
||||||
|
|
||||||
|
class HWindow :public BWindow {
|
||||||
|
public:
|
||||||
|
HWindow(BRect rect ,const char* name);
|
||||||
|
protected:
|
||||||
|
virtual ~HWindow();
|
||||||
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
virtual void DispatchMessage(BMessage *message
|
||||||
|
,BHandler *handler);
|
||||||
|
void InitGUI();
|
||||||
|
void InitMenu();
|
||||||
|
void SetupMenuField();
|
||||||
|
void Pulse();
|
||||||
|
void RemoveEvent();
|
||||||
|
private:
|
||||||
|
//HTypeList* fTypeList;
|
||||||
|
HEventList* fEventList;
|
||||||
|
typedef BWindow _inherited;
|
||||||
|
BFilePanel* fFilePanel;
|
||||||
|
BFileGameSound *fPlayer;
|
||||||
|
};
|
||||||
|
#endif
|
BIN
src/prefs/sounds/Icon.rsrc
Normal file
BIN
src/prefs/sounds/Icon.rsrc
Normal file
Binary file not shown.
BIN
src/prefs/sounds/Resource.rsrc
Normal file
BIN
src/prefs/sounds/Resource.rsrc
Normal file
Binary file not shown.
213
src/prefs/sounds/Santa/BetterScrollView.cpp
Normal file
213
src/prefs/sounds/Santa/BetterScrollView.cpp
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
//Conventions:
|
||||||
|
// Global constants (declared with const) and #defines - all uppercase letters with words separated
|
||||||
|
// by underscores.
|
||||||
|
// (E.G., #define MY_DEFINE 5).
|
||||||
|
// (E.G., const int MY_CONSTANT = 5;).
|
||||||
|
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
|
||||||
|
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
|
||||||
|
// associating them with a particular enumerated set.
|
||||||
|
// (E.G., typedef int MyTypedef;).
|
||||||
|
// (E.G., enum MyEnumConst {MEC_ONE, MEC_TWO};)
|
||||||
|
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int g_my_global;).
|
||||||
|
// Argument and local variables - begin with a lowercase letter followed by
|
||||||
|
// lowercase words separated by underscores.
|
||||||
|
// (E.G., int my_local;).
|
||||||
|
// Member variables - begin with "m_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int m_my_member;).
|
||||||
|
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
|
||||||
|
// separated by uppercase letters.
|
||||||
|
// (E.G., void MyFunction(void);).
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "BetterScrollView.h"
|
||||||
|
#include "Colors.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** BetterScrollView CLASS
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <stdio.h>
|
||||||
|
BetterScrollView::BetterScrollView(const char *name, BView *target, uint32 resizeMask, uint32 flags,
|
||||||
|
bool horizontal, bool vertical, bool scroll_view_corner, border_style border)
|
||||||
|
: BScrollView(name, target, resizeMask, flags, horizontal, vertical, border)
|
||||||
|
{
|
||||||
|
m_target = target;
|
||||||
|
m_data_rect.Set(-1,-1,-1,-1);
|
||||||
|
m_h_scrollbar = ScrollBar(B_HORIZONTAL);
|
||||||
|
m_v_scrollbar = ScrollBar(B_VERTICAL);
|
||||||
|
if(scroll_view_corner && horizontal && vertical)
|
||||||
|
{
|
||||||
|
m_scroll_view_corner = new ScrollViewCorner(m_v_scrollbar->Frame().left,
|
||||||
|
m_h_scrollbar->Frame().top);
|
||||||
|
AddChild(m_scroll_view_corner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_scroll_view_corner = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BetterScrollView::~BetterScrollView()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void BetterScrollView::SetDataRect(BRect data_rect, bool scrolling_allowed)
|
||||||
|
{
|
||||||
|
m_data_rect = data_rect;
|
||||||
|
UpdateScrollBars(scrolling_allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BetterScrollView::FrameResized(float new_width, float new_height)
|
||||||
|
{
|
||||||
|
BScrollView::FrameResized(new_width,new_height);
|
||||||
|
UpdateScrollBars(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BetterScrollView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BScrollView::AttachedToWindow();
|
||||||
|
UpdateScrollBars(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BetterScrollView::UpdateScrollBars(bool scrolling_allowed)
|
||||||
|
{
|
||||||
|
//Figure out the bounds and scroll if necessary
|
||||||
|
BRect view_bounds = m_target->Bounds();
|
||||||
|
|
||||||
|
float page_width, page_height, view_width, view_height;
|
||||||
|
view_width = view_bounds.right-view_bounds.left;
|
||||||
|
view_height = view_bounds.bottom-view_bounds.top;
|
||||||
|
|
||||||
|
float min,max;
|
||||||
|
if(scrolling_allowed)
|
||||||
|
{
|
||||||
|
//Figure out the width of the page rectangle
|
||||||
|
page_width = m_data_rect.right-m_data_rect.left;
|
||||||
|
page_height = m_data_rect.bottom-m_data_rect.top;
|
||||||
|
if(view_width > page_width)
|
||||||
|
page_width = view_width;
|
||||||
|
if(view_height > page_height)
|
||||||
|
page_height = view_height;
|
||||||
|
|
||||||
|
//Adjust positions
|
||||||
|
float delta_x = 0.0;
|
||||||
|
if(m_h_scrollbar)
|
||||||
|
{
|
||||||
|
if(view_bounds.left < m_data_rect.left)
|
||||||
|
delta_x = m_data_rect.left - view_bounds.left;
|
||||||
|
else if(view_bounds.right > m_data_rect.left+page_width)
|
||||||
|
delta_x = m_data_rect.left+page_width - view_bounds.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
float delta_y = 0.0;
|
||||||
|
if(m_v_scrollbar)
|
||||||
|
{
|
||||||
|
if(view_bounds.top < m_data_rect.top)
|
||||||
|
delta_y = m_data_rect.top - view_bounds.top;
|
||||||
|
else if(view_bounds.bottom > m_data_rect.top+page_height)
|
||||||
|
delta_y = m_data_rect.top+page_height - view_bounds.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(delta_x != 0.0 || delta_y != 0.0)
|
||||||
|
{
|
||||||
|
m_target->ScrollTo(BPoint(view_bounds.left+delta_x,view_bounds.top+delta_y));
|
||||||
|
view_bounds = Bounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min = m_data_rect.left;
|
||||||
|
if(view_bounds.left < min)
|
||||||
|
min = view_bounds.left;
|
||||||
|
max = m_data_rect.right;
|
||||||
|
if(view_bounds.right > max)
|
||||||
|
max = view_bounds.right;
|
||||||
|
page_width = max-min;
|
||||||
|
min = m_data_rect.top;
|
||||||
|
if(view_bounds.top < min)
|
||||||
|
min = view_bounds.top;
|
||||||
|
max = m_data_rect.bottom;
|
||||||
|
if(view_bounds.bottom > max)
|
||||||
|
max = view_bounds.bottom;
|
||||||
|
page_height = max-min;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Figure out the ratio of the bounds rectangle width or height to the page rectangle width or height
|
||||||
|
float width_prop = view_width/page_width;
|
||||||
|
float height_prop = view_height/page_height;
|
||||||
|
|
||||||
|
//Set the scroll bar ranges and proportions. If the whole document is visible, inactivate the
|
||||||
|
//slider
|
||||||
|
bool active_scroller = false;
|
||||||
|
if(m_h_scrollbar)
|
||||||
|
{
|
||||||
|
if(width_prop >= 1.0)
|
||||||
|
m_h_scrollbar->SetRange(0.0,0.0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min = m_data_rect.left;
|
||||||
|
max = m_data_rect.left + page_width - view_width;
|
||||||
|
if(view_bounds.left < min)
|
||||||
|
min = view_bounds.left;
|
||||||
|
if(view_bounds.left > max)
|
||||||
|
max = view_bounds.left;
|
||||||
|
m_h_scrollbar->SetRange(min,max);
|
||||||
|
m_h_scrollbar->SetSteps(ceil(view_width/20), view_width);
|
||||||
|
active_scroller = true;
|
||||||
|
}
|
||||||
|
m_h_scrollbar->SetProportion(width_prop);
|
||||||
|
}
|
||||||
|
if(m_v_scrollbar)
|
||||||
|
{
|
||||||
|
if(height_prop >= 1.0)
|
||||||
|
m_v_scrollbar->SetRange(0.0,0.0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
min = m_data_rect.top;
|
||||||
|
max = m_data_rect.top + page_height - view_height;
|
||||||
|
if(view_bounds.top < min)
|
||||||
|
min = view_bounds.top;
|
||||||
|
if(view_bounds.top > max)
|
||||||
|
max = view_bounds.top;
|
||||||
|
m_v_scrollbar->SetRange(min,max);
|
||||||
|
m_v_scrollbar->SetSteps(ceil(view_height/20), view_height);
|
||||||
|
active_scroller = true;
|
||||||
|
}
|
||||||
|
m_v_scrollbar->SetProportion(height_prop);
|
||||||
|
}
|
||||||
|
if(m_scroll_view_corner)
|
||||||
|
{
|
||||||
|
rgb_color cur_color = m_scroll_view_corner->ViewColor();
|
||||||
|
rgb_color new_color;
|
||||||
|
if(active_scroller)
|
||||||
|
new_color = BeBackgroundGrey;
|
||||||
|
else
|
||||||
|
new_color = BeInactiveControlGrey;
|
||||||
|
if(new_color.red != cur_color.red || new_color.green != cur_color.green ||
|
||||||
|
new_color.blue != cur_color.blue || new_color.alpha != cur_color.alpha)
|
||||||
|
{
|
||||||
|
m_scroll_view_corner->SetViewColor(new_color);
|
||||||
|
m_scroll_view_corner->Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
78
src/prefs/sounds/Santa/BetterScrollView.h
Normal file
78
src/prefs/sounds/Santa/BetterScrollView.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
//Conventions:
|
||||||
|
// Global constants (declared with const) and #defines - all uppercase letters with words separated
|
||||||
|
// by underscores.
|
||||||
|
// (E.G., #define MY_DEFINE 5).
|
||||||
|
// (E.G., const int MY_CONSTANT = 5;).
|
||||||
|
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
|
||||||
|
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
|
||||||
|
// associating them with a particular enumerated set.
|
||||||
|
// (E.G., typedef int MyTypedef;).
|
||||||
|
// (E.G., enum MyEnumConst {MEC_ONE, MEC_TWO};)
|
||||||
|
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int g_my_global;).
|
||||||
|
// Argument and local variables - begin with a lowercase letter followed by
|
||||||
|
// lowercase words separated by underscores.
|
||||||
|
// (E.G., int my_local;).
|
||||||
|
// Member variables - begin with "m_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int m_my_member;).
|
||||||
|
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
|
||||||
|
// separated by uppercase letters.
|
||||||
|
// (E.G., void MyFunction(void);).
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _SGB_BETTER_SCROLL_VIEW_H_
|
||||||
|
#define _SGB_BETTER_SCROLL_VIEW_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <ScrollView.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "ScrollViewCorner.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLASS DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class BetterScrollView : public BScrollView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BetterScrollView(const char *name, BView *target, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||||
|
uint32 flags = B_FRAME_EVENTS | B_WILL_DRAW, bool horizontal = true, bool vertical = true,
|
||||||
|
bool scroll_view_corner = true, border_style border = B_FANCY_BORDER);
|
||||||
|
virtual ~BetterScrollView();
|
||||||
|
virtual void SetDataRect(BRect data_rect, bool scrolling_allowed = true);
|
||||||
|
inline BRect DataRect() {return m_data_rect;}
|
||||||
|
virtual void FrameResized(float new_width, float new_height);
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateScrollBars(bool scrolling_allowed);
|
||||||
|
|
||||||
|
BRect m_data_rect;
|
||||||
|
BScrollBar* m_h_scrollbar;
|
||||||
|
BScrollBar* m_v_scrollbar;
|
||||||
|
ScrollViewCorner* m_scroll_view_corner;
|
||||||
|
BView* m_target;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
426
src/prefs/sounds/Santa/CLVColumn.cpp
Normal file
426
src/prefs/sounds/Santa/CLVColumn.cpp
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
//Column list header source file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <string.h>
|
||||||
|
#include <Window.h>
|
||||||
|
#include <Region.h>
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "CLVColumn.h"
|
||||||
|
#include "ColumnListView.h"
|
||||||
|
#include "CLVColumnLabelView.h"
|
||||||
|
#include "NewStrings.h"
|
||||||
|
#include "Descending.h"
|
||||||
|
#include "Ascending.h"
|
||||||
|
#include "PrefilledBitmap.h"
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLVColumn CLASS DEFINITION
|
||||||
|
//******************************************************************************************************
|
||||||
|
CLVColumn::CLVColumn(const char* label,float width,uint32 flags,float min_width)
|
||||||
|
{
|
||||||
|
if(flags & CLV_EXPANDER)
|
||||||
|
{
|
||||||
|
label = NULL;
|
||||||
|
width = 15.0;
|
||||||
|
min_width = 15.0;
|
||||||
|
flags &= CLV_NOT_MOVABLE | CLV_LOCK_AT_BEGINNING | CLV_HIDDEN | CLV_LOCK_WITH_RIGHT;
|
||||||
|
flags |= CLV_EXPANDER | CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT;
|
||||||
|
}
|
||||||
|
if(min_width < 4.0)
|
||||||
|
min_width = 4.0;
|
||||||
|
if(width < min_width)
|
||||||
|
width = min_width;
|
||||||
|
if(label)
|
||||||
|
{
|
||||||
|
fLabel = new char[strlen(label)+1];
|
||||||
|
strcpy((char*)fLabel,label);
|
||||||
|
if(CLV_HEADER_TRUNCATE)
|
||||||
|
{
|
||||||
|
int32 truncated_text_length = strlen(label)+3;
|
||||||
|
fTruncatedText = new char[truncated_text_length];
|
||||||
|
fTruncatedText[0] = 0;
|
||||||
|
fCachedRect.Set(-1,-1,-1,-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fTruncatedText = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fLabel = NULL;
|
||||||
|
fTruncatedText = NULL;
|
||||||
|
}
|
||||||
|
fWidth = width;
|
||||||
|
fMinWidth = min_width;
|
||||||
|
fFlags = flags;
|
||||||
|
fPushedByExpander = false;
|
||||||
|
fParent = NULL;
|
||||||
|
fSortMode = NoSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLVColumn::~CLVColumn()
|
||||||
|
{
|
||||||
|
if(fParent)
|
||||||
|
fParent->RemoveColumn(this);
|
||||||
|
if(fLabel)
|
||||||
|
delete[] fLabel;
|
||||||
|
if(fTruncatedText)
|
||||||
|
delete[] fTruncatedText;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float CLVColumn::Width() const
|
||||||
|
{
|
||||||
|
return fWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumn::SetWidth(float width)
|
||||||
|
{
|
||||||
|
if(width < fMinWidth)
|
||||||
|
width = fMinWidth;
|
||||||
|
if(width != fWidth)
|
||||||
|
{
|
||||||
|
float OldWidth = fWidth;
|
||||||
|
fWidth = width;
|
||||||
|
if(IsShown() && fParent)
|
||||||
|
{
|
||||||
|
//Figure out the area after this column to scroll
|
||||||
|
BRect ColumnViewBounds = fParent->fColumnLabelView->Bounds();
|
||||||
|
BRect MainViewBounds = fParent->Bounds();
|
||||||
|
BRect SourceArea = ColumnViewBounds;
|
||||||
|
float Delta = width-OldWidth;
|
||||||
|
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
|
||||||
|
SourceArea.left = fColumnEnd+1.0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Delta >= 0)
|
||||||
|
SourceArea.left = fColumnBegin;
|
||||||
|
else
|
||||||
|
SourceArea.left = (fColumnBegin-Delta)+1;
|
||||||
|
}
|
||||||
|
BRect DestArea = SourceArea;
|
||||||
|
DestArea.left += Delta;
|
||||||
|
DestArea.right += Delta;
|
||||||
|
float LimitShift;
|
||||||
|
if(DestArea.right > ColumnViewBounds.right)
|
||||||
|
{
|
||||||
|
LimitShift = DestArea.right-ColumnViewBounds.right;
|
||||||
|
DestArea.right -= LimitShift;
|
||||||
|
SourceArea.right -= LimitShift;
|
||||||
|
}
|
||||||
|
if(DestArea.left < ColumnViewBounds.left)
|
||||||
|
{
|
||||||
|
LimitShift = ColumnViewBounds.left - DestArea.left;
|
||||||
|
DestArea.left += LimitShift;
|
||||||
|
SourceArea.left += LimitShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scroll the area that is being shifted
|
||||||
|
BWindow* ParentWindow = fParent->Window();
|
||||||
|
if(ParentWindow)
|
||||||
|
ParentWindow->UpdateIfNeeded();
|
||||||
|
fParent->fColumnLabelView->CopyBits(SourceArea,DestArea);
|
||||||
|
SourceArea.top = MainViewBounds.top;
|
||||||
|
SourceArea.bottom = MainViewBounds.bottom;
|
||||||
|
DestArea.top = MainViewBounds.top;
|
||||||
|
DestArea.bottom = MainViewBounds.bottom;
|
||||||
|
fParent->CopyBits(SourceArea,DestArea);
|
||||||
|
|
||||||
|
//Invalidate the region that got revealed
|
||||||
|
DestArea = ColumnViewBounds;
|
||||||
|
if(width > OldWidth)
|
||||||
|
{
|
||||||
|
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
|
||||||
|
{
|
||||||
|
DestArea.left = fColumnEnd+1.0;
|
||||||
|
DestArea.right = fColumnEnd+Delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DestArea.left = fColumnBegin;
|
||||||
|
DestArea.right = fColumnBegin+Delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DestArea.left = ColumnViewBounds.right+Delta+1.0;
|
||||||
|
DestArea.right = ColumnViewBounds.right;
|
||||||
|
}
|
||||||
|
fParent->fColumnLabelView->Invalidate(DestArea);
|
||||||
|
DestArea.top = MainViewBounds.top;
|
||||||
|
DestArea.bottom = MainViewBounds.bottom;
|
||||||
|
fParent->Invalidate(DestArea);
|
||||||
|
|
||||||
|
if(fFlags & CLV_HEADER_TRUNCATE)
|
||||||
|
{
|
||||||
|
//Do truncation of label
|
||||||
|
BRect invalid_region = TruncateText(width);
|
||||||
|
if(fCachedRect != BRect(-1,-1,-1,-1))
|
||||||
|
fCachedRect.right += Delta;
|
||||||
|
if(invalid_region != BRect(-1,-1,-1,-1))
|
||||||
|
{
|
||||||
|
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
|
||||||
|
GetHeaderView()->Invalidate(invalid_region);
|
||||||
|
else
|
||||||
|
GetHeaderView()->Invalidate(fCachedRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Invalidate the old or new resize handle as necessary
|
||||||
|
/*DestArea = ColumnViewBounds;
|
||||||
|
if(width > OldWidth)
|
||||||
|
DestArea.left = fColumnEnd;
|
||||||
|
else
|
||||||
|
DestArea.left = fColumnEnd + Delta;
|
||||||
|
DestArea.right = DestArea.left;
|
||||||
|
fParent->fColumnLabelView->Invalidate(DestArea);
|
||||||
|
*/
|
||||||
|
fParent->fColumnLabelView->Invalidate();
|
||||||
|
//Update the column sizes, positions and group positions
|
||||||
|
fParent->UpdateColumnSizesDataRectSizeScrollBars(false);
|
||||||
|
fParent->fColumnLabelView->UpdateDragGroups();
|
||||||
|
}
|
||||||
|
if(fParent)
|
||||||
|
fParent->ColumnWidthChanged(fParent->fColumnList.IndexOf(this),fWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect CLVColumn::TruncateText(float column_width)
|
||||||
|
//Returns whether the truncated text has changed
|
||||||
|
{
|
||||||
|
column_width -= 1+8+5+1;
|
||||||
|
//Because when I draw the text I start drawing 8 pixels to the right from the text area's left edge,
|
||||||
|
//which is in turn 1 pixel smaller than the column at each edge, and I want 5 trailing pixels.
|
||||||
|
BRect invalid(-1,-1,-1,-1);
|
||||||
|
if(fParent == NULL)
|
||||||
|
return invalid;
|
||||||
|
const char* text = GetLabel();
|
||||||
|
char new_text[256];
|
||||||
|
BFont font;
|
||||||
|
fParent->GetFont(&font);
|
||||||
|
GetTruncatedString(text,new_text,column_width,256,&font);
|
||||||
|
if(strcmp(fTruncatedText,new_text)!=0)
|
||||||
|
{
|
||||||
|
//The truncated text has changed
|
||||||
|
invalid = fCachedRect;
|
||||||
|
if(invalid != BRect(-1,-1,-1,-1))
|
||||||
|
{
|
||||||
|
//Figure out which region just got changed
|
||||||
|
int32 cmppos;
|
||||||
|
int32 cmplen = strlen(new_text);
|
||||||
|
char remember = 0;
|
||||||
|
for(cmppos = 0; cmppos <= cmplen; cmppos++)
|
||||||
|
if(new_text[cmppos] != fTruncatedText[cmppos])
|
||||||
|
{
|
||||||
|
remember = new_text[cmppos];
|
||||||
|
new_text[cmppos] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
invalid.left += 8 + be_plain_font->StringWidth(new_text);
|
||||||
|
new_text[cmppos] = remember;
|
||||||
|
}
|
||||||
|
//Remember the new truncated text
|
||||||
|
strcpy(fTruncatedText,new_text);
|
||||||
|
}
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GetTruncatedString(const char* full_string, char* truncated, float width, int32 truncate_buf_size,
|
||||||
|
const BFont* font)
|
||||||
|
{
|
||||||
|
Strtcpy(truncated,full_string,truncate_buf_size);
|
||||||
|
int32 choppos = strlen(truncated)-1;
|
||||||
|
while(choppos >= -2 && font->StringWidth(truncated) > width)
|
||||||
|
{
|
||||||
|
while(choppos > 0 && truncated[choppos-1] == ' ')
|
||||||
|
choppos--;
|
||||||
|
if(choppos > 0 || (choppos == 0 && truncated[0] == ' '))
|
||||||
|
truncated[choppos] = '.';
|
||||||
|
if(choppos > -1)
|
||||||
|
truncated[choppos+1] = '.';
|
||||||
|
if(choppos > -2)
|
||||||
|
truncated[choppos+2] = '.';
|
||||||
|
truncated[choppos+3] = 0;
|
||||||
|
choppos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32 CLVColumn::Flags() const
|
||||||
|
{
|
||||||
|
return fFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CLVColumn::IsShown() const
|
||||||
|
{
|
||||||
|
if(fFlags & CLV_HIDDEN)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumn::SetShown(bool Shown)
|
||||||
|
{
|
||||||
|
bool shown = IsShown();
|
||||||
|
if(shown != Shown)
|
||||||
|
{
|
||||||
|
if(Shown)
|
||||||
|
fFlags &= 0xFFFFFFFF^CLV_HIDDEN;
|
||||||
|
else
|
||||||
|
fFlags |= CLV_HIDDEN;
|
||||||
|
if(fParent)
|
||||||
|
{
|
||||||
|
float UpdateLeft = fColumnBegin;
|
||||||
|
fParent->UpdateColumnSizesDataRectSizeScrollBars();
|
||||||
|
fParent->fColumnLabelView->UpdateDragGroups();
|
||||||
|
if(Shown)
|
||||||
|
UpdateLeft = fColumnBegin;
|
||||||
|
BRect Area = fParent->fColumnLabelView->Bounds();
|
||||||
|
Area.left = UpdateLeft;
|
||||||
|
fParent->fColumnLabelView->Invalidate(Area);
|
||||||
|
Area = fParent->Bounds();
|
||||||
|
Area.left = UpdateLeft;
|
||||||
|
fParent->Invalidate(Area);
|
||||||
|
if(fFlags & CLV_EXPANDER)
|
||||||
|
{
|
||||||
|
if(!Shown)
|
||||||
|
fParent->fExpanderColumn = -1;
|
||||||
|
else
|
||||||
|
fParent->fExpanderColumn = fParent->IndexOfColumn(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLVSortMode CLVColumn::SortMode() const
|
||||||
|
{
|
||||||
|
return fSortMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLVColumn::SetSortMode(CLVSortMode mode)
|
||||||
|
{
|
||||||
|
if(fParent)
|
||||||
|
fParent->SetSortMode(fParent->IndexOfColumn(this),mode);
|
||||||
|
else
|
||||||
|
fSortMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* CLVColumn::GetLabel() const
|
||||||
|
{
|
||||||
|
return fLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ColumnListView* CLVColumn::GetParent() const
|
||||||
|
{
|
||||||
|
return fParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BView* CLVColumn::GetHeaderView() const
|
||||||
|
{
|
||||||
|
if(fParent)
|
||||||
|
return fParent->fColumnLabelView;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumn::DrawColumnHeader(BView* view, BRect header_rect, bool sort_key, bool focus,
|
||||||
|
float font_ascent)
|
||||||
|
{
|
||||||
|
char* label;
|
||||||
|
if(fFlags & CLV_HEADER_TRUNCATE)
|
||||||
|
{
|
||||||
|
if(fCachedRect == BRect(-1,-1,-1,-1))
|
||||||
|
{
|
||||||
|
//Have never drawn it before
|
||||||
|
TruncateText(header_rect.right-header_rect.left);
|
||||||
|
}
|
||||||
|
label = fTruncatedText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
label = fLabel;
|
||||||
|
|
||||||
|
if(label)
|
||||||
|
{
|
||||||
|
if(focus)
|
||||||
|
view->SetHighColor(BeFocusBlue);
|
||||||
|
else
|
||||||
|
view->SetHighColor(Black);
|
||||||
|
|
||||||
|
//Draw the label
|
||||||
|
view->SetDrawingMode(B_OP_OVER);
|
||||||
|
BPoint text_point;
|
||||||
|
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
|
||||||
|
text_point.Set(header_rect.left+8.0,header_rect.top+1.0+font_ascent);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BFont label_font;
|
||||||
|
view->GetFont(&label_font);
|
||||||
|
float string_width = label_font.StringWidth(label);
|
||||||
|
text_point.Set(header_rect.right-8.0-string_width,header_rect.top+1.0+font_ascent);
|
||||||
|
}
|
||||||
|
view->DrawString(label,text_point);
|
||||||
|
view->SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
//Underline if this is a selected sort column
|
||||||
|
if(sort_key)
|
||||||
|
{
|
||||||
|
PrefilledBitmap *bitmap = NULL;
|
||||||
|
switch(fSortMode)
|
||||||
|
{
|
||||||
|
case Ascending:
|
||||||
|
bitmap = new PrefilledBitmap(BRect(0,0,8,15),B_CMAP8,kAscendingIconBits);
|
||||||
|
break;
|
||||||
|
case Descending:
|
||||||
|
bitmap = new PrefilledBitmap(BRect(0,0,8,15),B_CMAP8,kDescendingIconBits);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
float Width = view->StringWidth(label);
|
||||||
|
view->StrokeLine(BPoint(text_point.x-1,text_point.y+2.0),
|
||||||
|
BPoint(text_point.x-1+Width,text_point.y+2.0));
|
||||||
|
|
||||||
|
if(bitmap && header_rect.Width() > 10+20)
|
||||||
|
{
|
||||||
|
|
||||||
|
view->SetDrawingMode(B_OP_OVER);
|
||||||
|
BRect iconBounds = header_rect;
|
||||||
|
iconBounds.left= iconBounds.right - 8;
|
||||||
|
BRegion region;
|
||||||
|
region.Include(iconBounds);
|
||||||
|
view->ConstrainClippingRegion(®ion);
|
||||||
|
view->DrawBitmap(bitmap,iconBounds);
|
||||||
|
}
|
||||||
|
delete bitmap;
|
||||||
|
}
|
||||||
|
fCachedRect = header_rect;
|
||||||
|
}
|
||||||
|
}
|
161
src/prefs/sounds/Santa/CLVColumn.h
Normal file
161
src/prefs/sounds/Santa/CLVColumn.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
//Column list header header file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CLV_COLUMN_H_
|
||||||
|
#define _CLV_COLUMN_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <Rect.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class ColumnListView;
|
||||||
|
class CLVColumn;
|
||||||
|
class CLVListItem;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CONSTANTS
|
||||||
|
//******************************************************************************************************
|
||||||
|
//Flags
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CLV_SORT_KEYABLE = 0x00000001, //Can be used as the sorting key
|
||||||
|
CLV_NOT_MOVABLE = 0x00000002, //Column can't be moved by user
|
||||||
|
CLV_NOT_RESIZABLE = 0x00000004, //Column can't be resized by user
|
||||||
|
CLV_LOCK_AT_BEGINNING = 0x00000008, //Movable columns may not be placed or moved by the user
|
||||||
|
//into a position before this one
|
||||||
|
CLV_LOCK_AT_END = 0x00000010, //Movable columns may not be placed or moved by the user
|
||||||
|
//into a position after this one
|
||||||
|
CLV_HIDDEN = 0x00000020, //This column is hidden initially
|
||||||
|
CLV_MERGE_WITH_RIGHT = 0x00000040, //Merge this column label with the one that follows it.
|
||||||
|
CLV_LOCK_WITH_RIGHT = 0x00000080, //Lock this column to the one that follows it such that
|
||||||
|
//if the column to the right is moved by the user, this
|
||||||
|
//one will move with it and vice versa
|
||||||
|
CLV_EXPANDER = 0x00000100, //Column contains an expander. You may only use one
|
||||||
|
//expander in a ColumnListView, and an expander may not be
|
||||||
|
//added to a non-hierarchal ColumnListView. It may not
|
||||||
|
//have a label. Its width is automatically set to 20.0.
|
||||||
|
//The only flags that affect it are CLV_NOT_MOVABLE,
|
||||||
|
//CLV_LOCK_AT_BEGINNING, CLV_NOT_SHOWN and
|
||||||
|
//CLV_LOCK_WITH_RIGHT. The others are set for you:
|
||||||
|
//CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT
|
||||||
|
CLV_PUSH_PASS = 0x00000200, //Causes this column, if pushed by an expander to the
|
||||||
|
//left, to pass that push on and also push the next
|
||||||
|
//column to the right.
|
||||||
|
CLV_HEADER_TRUNCATE = 0x00000400, //Causes this column label to be tructated with an ellipsis
|
||||||
|
//if the column header is narrower than the text it contains.
|
||||||
|
CLV_TELL_ITEMS_WIDTH = 0x00000800, //Causes items in this column to be informed when the column
|
||||||
|
//width is changed. This is necessary for CLVEasyItems.
|
||||||
|
CLV_RIGHT_JUSTIFIED = 0x00001000 //Causes the column, when resized, to shift its content,
|
||||||
|
//not just the content of subsequent columns. This does not
|
||||||
|
//affect the rendering of content in items in the column,
|
||||||
|
//just the area that gets scrolled.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CLVSortMode
|
||||||
|
{
|
||||||
|
Ascending,
|
||||||
|
Descending,
|
||||||
|
NoSort
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** FUNCTIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
void GetTruncatedString(const char* full_string, char* truncated, float width, int32 truncate_buf_size,
|
||||||
|
const BFont* font);
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** ColumnListView CLASS DECLARATION
|
||||||
|
//******************************************************************************************************
|
||||||
|
class CLVColumn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Constructor and destructor
|
||||||
|
CLVColumn( const char* label,
|
||||||
|
float width = 20.0,
|
||||||
|
uint32 flags = 0,
|
||||||
|
float min_width = 20.0);
|
||||||
|
virtual ~CLVColumn();
|
||||||
|
|
||||||
|
//Archival stuff
|
||||||
|
/* Not implemented yet
|
||||||
|
CLVColumn(BMessage* archive);
|
||||||
|
static CLVColumn* Instantiate(BMessage* data);
|
||||||
|
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Functions
|
||||||
|
float Width() const;
|
||||||
|
virtual void SetWidth(float width); //Can be overridden to detect changes to the column width
|
||||||
|
//however since you are probably overriding
|
||||||
|
//ColumnListView and dealing with an array of columns
|
||||||
|
//anyway, it is probably more useful to override
|
||||||
|
//ColumnListView::ColumnWidthChanged to detect changes to
|
||||||
|
//column widths
|
||||||
|
uint32 Flags() const;
|
||||||
|
bool IsShown() const;
|
||||||
|
virtual void SetShown(bool shown);
|
||||||
|
CLVSortMode SortMode() const;
|
||||||
|
virtual void SetSortMode(CLVSortMode mode);
|
||||||
|
const char* GetLabel() const;
|
||||||
|
ColumnListView* GetParent() const ;
|
||||||
|
BView* GetHeaderView() const;
|
||||||
|
virtual void DrawColumnHeader(BView* view, BRect header_rect, bool sort_key, bool focus,
|
||||||
|
float font_ascent);
|
||||||
|
//Can be overridden to implement your own column header drawing, for example if you want to do
|
||||||
|
//string truncation.
|
||||||
|
//- The background will already be filled with and LowColor set to BeBackgroundGrey
|
||||||
|
//- The highlight and shadow edges will already be drawn
|
||||||
|
//- The header_rect does not include the one-pixel border for the highlight and shadow edges.
|
||||||
|
//- The view font will already be set to the font specified when the ColumnListView was
|
||||||
|
// constructed, and should not be changed
|
||||||
|
//- If text is being rendered, it should be rendered at
|
||||||
|
// BPoint text_point(header_rect.left+8.0,header_rect.top+1.0+font_ascent)
|
||||||
|
//- If sort_key is true, the text should be underlined, with the underline being drawn from
|
||||||
|
// BPoint(text_point.x-1,text_point.y+2.0) to BPoint(text_point.x-1+label_width,text_point.y+2.0)
|
||||||
|
//- If focus is true, the text and underline should be in BeFocusBlue, otherwise in Black.
|
||||||
|
private:
|
||||||
|
friend class ColumnListView;
|
||||||
|
friend class CLVColumnLabelView;
|
||||||
|
friend class CLVListItem;
|
||||||
|
|
||||||
|
BRect TruncateText(float column_width);
|
||||||
|
|
||||||
|
char *fLabel;
|
||||||
|
char* fTruncatedText;
|
||||||
|
BRect fCachedRect;
|
||||||
|
float fWidth;
|
||||||
|
float fMinWidth;
|
||||||
|
float fColumnBegin;
|
||||||
|
float fColumnEnd;
|
||||||
|
uint32 fFlags;
|
||||||
|
bool fPushedByExpander;
|
||||||
|
CLVSortMode fSortMode;
|
||||||
|
ColumnListView* fParent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
788
src/prefs/sounds/Santa/CLVColumnLabelView.cpp
Normal file
788
src/prefs/sounds/Santa/CLVColumnLabelView.cpp
Normal file
@ -0,0 +1,788 @@
|
|||||||
|
//ColumnLabelView class source file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <Region.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "CLVColumnLabelView.h"
|
||||||
|
#include "ColumnListView.h"
|
||||||
|
#include "CLVColumn.h"
|
||||||
|
#include "Cursors.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** FUNCTION DEFINITIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
CLVColumnLabelView::CLVColumnLabelView(BRect Bounds,ColumnListView* parent,const BFont* Font)
|
||||||
|
: BView(Bounds,NULL,B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP,B_WILL_DRAW|B_FRAME_EVENTS),
|
||||||
|
fDragGroups(10)
|
||||||
|
{
|
||||||
|
SetFont(Font);
|
||||||
|
SetViewColor(BeBackgroundGrey);
|
||||||
|
SetLowColor(BeBackgroundGrey);
|
||||||
|
SetHighColor(Black);
|
||||||
|
fParent = parent;
|
||||||
|
fDisplayList = &fParent->fColumnDisplayList;
|
||||||
|
fColumnClicked = NULL;
|
||||||
|
fColumnDragging = false;
|
||||||
|
fColumnResizing = false;
|
||||||
|
fModifiedCursor = false;
|
||||||
|
font_height FontAttributes;
|
||||||
|
Font->GetHeight(&FontAttributes);
|
||||||
|
fFontAscent = ceil(FontAttributes.ascent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLVColumnLabelView::~CLVColumnLabelView()
|
||||||
|
{
|
||||||
|
int32 NumberOfGroups = fDragGroups.CountItems();
|
||||||
|
for(int32 Counter = 0; Counter < NumberOfGroups; Counter++)
|
||||||
|
fDragGroups.RemoveItem(int32(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::Draw(BRect update_rect)
|
||||||
|
{
|
||||||
|
BRect ViewBounds = Bounds();
|
||||||
|
|
||||||
|
//Draw each column label in turn
|
||||||
|
float ColumnBegin = 0.0;
|
||||||
|
float ColumnEnd = -1.0;
|
||||||
|
bool MergeWithLeft = false;
|
||||||
|
int32 NumberOfColumns = fDisplayList->CountItems();
|
||||||
|
BPoint Start,Stop;
|
||||||
|
for(int32 ColumnDraw = 0; ColumnDraw < NumberOfColumns; ColumnDraw++)
|
||||||
|
{
|
||||||
|
CLVColumn* ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnDraw);
|
||||||
|
if(ThisColumn->IsShown())
|
||||||
|
{
|
||||||
|
//Figure out where this column is
|
||||||
|
ColumnBegin = ThisColumn->fColumnBegin;
|
||||||
|
ColumnEnd = ThisColumn->fColumnEnd;
|
||||||
|
//Start by figuring out if this column will merge with a shown column to the right
|
||||||
|
bool MergeWithRight = false;
|
||||||
|
if(ThisColumn->fFlags & CLV_MERGE_WITH_RIGHT)
|
||||||
|
{
|
||||||
|
for(int32 ColumnCounter = ColumnDraw+1; ColumnCounter < NumberOfColumns;
|
||||||
|
ColumnCounter++)
|
||||||
|
{
|
||||||
|
CLVColumn* NextColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnCounter);
|
||||||
|
if(NextColumn->IsShown())
|
||||||
|
{
|
||||||
|
//The next column is shown
|
||||||
|
MergeWithRight = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(!(NextColumn->fFlags & CLV_MERGE_WITH_RIGHT))
|
||||||
|
//The next column is not shown and doesn't pass on the merge
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(update_rect.Intersects(BRect(ColumnBegin,ViewBounds.top,ColumnEnd,
|
||||||
|
ViewBounds.bottom)))
|
||||||
|
{
|
||||||
|
//Need to draw this column
|
||||||
|
BeginLineArray(4);
|
||||||
|
//Top line
|
||||||
|
Start.Set(ColumnBegin,ViewBounds.top);
|
||||||
|
Stop.Set(ColumnEnd-1.0,ViewBounds.top);
|
||||||
|
if(MergeWithRight && !(ThisColumn == fColumnClicked && fColumnResizing))
|
||||||
|
Stop.x = ColumnEnd;
|
||||||
|
AddLine(Start,Stop,BeHighlight);
|
||||||
|
//Left line
|
||||||
|
if(!MergeWithLeft)
|
||||||
|
AddLine(BPoint(ColumnBegin,ViewBounds.top+1.0),
|
||||||
|
BPoint(ColumnBegin,ViewBounds.bottom),BeHighlight);
|
||||||
|
//Bottom line
|
||||||
|
Start.Set(ColumnBegin+1.0,ViewBounds.bottom);
|
||||||
|
if(MergeWithLeft)
|
||||||
|
Start.x = ColumnBegin;
|
||||||
|
Stop.Set(ColumnEnd-1.0,ViewBounds.bottom);
|
||||||
|
if(MergeWithRight && !(ThisColumn == fColumnClicked && fColumnResizing))
|
||||||
|
Stop.x = ColumnEnd;
|
||||||
|
AddLine(Start,Stop,BeShadow);
|
||||||
|
//Right line
|
||||||
|
if(ThisColumn == fColumnClicked && fColumnResizing)
|
||||||
|
AddLine(BPoint(ColumnEnd,ViewBounds.top),BPoint(ColumnEnd,ViewBounds.bottom),
|
||||||
|
BeFocusBlue);
|
||||||
|
else if(!MergeWithRight)
|
||||||
|
AddLine(BPoint(ColumnEnd,ViewBounds.top),BPoint(ColumnEnd,ViewBounds.bottom),
|
||||||
|
BeShadow);
|
||||||
|
EndLineArray();
|
||||||
|
|
||||||
|
//Add the label
|
||||||
|
//Limit the clipping region to the interior of the box
|
||||||
|
BRect TextRect(ColumnBegin+1.0,ViewBounds.top+1.0,ColumnEnd-1.0,
|
||||||
|
ViewBounds.bottom-1.0);
|
||||||
|
BRegion TextRegion;
|
||||||
|
TextRegion.Include(TextRect);
|
||||||
|
ConstrainClippingRegion(&TextRegion);
|
||||||
|
|
||||||
|
bool focus;
|
||||||
|
bool sort_key;
|
||||||
|
if(ThisColumn == fColumnClicked && !fColumnResizing)
|
||||||
|
focus = true;
|
||||||
|
else
|
||||||
|
focus = false;
|
||||||
|
if(fParent->fSortKeyList.HasItem(ThisColumn) && ThisColumn->fSortMode != NoSort)
|
||||||
|
sort_key = true;
|
||||||
|
else
|
||||||
|
sort_key = false;
|
||||||
|
|
||||||
|
ThisColumn->DrawColumnHeader(this,TextRect,sort_key,focus,fFontAscent);
|
||||||
|
|
||||||
|
//Restore the clipping region
|
||||||
|
ConstrainClippingRegion(NULL);
|
||||||
|
}
|
||||||
|
//Set MergeWithLeft flag for the next column to the appropriate state
|
||||||
|
MergeWithLeft = MergeWithRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add highlight and shadow to the region after the columns if necessary
|
||||||
|
if(ColumnEnd < ViewBounds.right)
|
||||||
|
{
|
||||||
|
ColumnBegin = ColumnEnd+1.0;
|
||||||
|
if(update_rect.Intersects(BRect(ColumnEnd+1.0,ViewBounds.top,ViewBounds.right,
|
||||||
|
ViewBounds.bottom)))
|
||||||
|
{
|
||||||
|
BeginLineArray(3);
|
||||||
|
//Top line
|
||||||
|
AddLine(BPoint(ColumnBegin,ViewBounds.top),BPoint(ViewBounds.right,ViewBounds.top),
|
||||||
|
BeHighlight);
|
||||||
|
//Left line
|
||||||
|
AddLine(BPoint(ColumnBegin,ViewBounds.top+1.0),BPoint(ColumnBegin,ViewBounds.bottom),
|
||||||
|
BeHighlight);
|
||||||
|
//Bottom line
|
||||||
|
Start.Set(ColumnBegin+1.0,ViewBounds.bottom);
|
||||||
|
if(MergeWithLeft)
|
||||||
|
Start.x = ColumnBegin;
|
||||||
|
Stop.Set(ViewBounds.right,ViewBounds.bottom);
|
||||||
|
AddLine(Start,Stop,BeShadow);
|
||||||
|
EndLineArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draw the dragging box if necessary
|
||||||
|
if(fColumnClicked && fColumnDragging)
|
||||||
|
{
|
||||||
|
float DragOutlineLeft = fPreviousMousePos.x-fDragBoxMouseHoldOffset;
|
||||||
|
float GroupBegin = ((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
|
||||||
|
if(DragOutlineLeft < GroupBegin && fSnapGroupBefore == -1)
|
||||||
|
DragOutlineLeft = GroupBegin;
|
||||||
|
if(DragOutlineLeft > GroupBegin && fSnapGroupAfter == -1)
|
||||||
|
DragOutlineLeft = GroupBegin;
|
||||||
|
float DragOutlineRight = DragOutlineLeft + fDragBoxWidth;
|
||||||
|
BeginLineArray(4);
|
||||||
|
AddLine(BPoint(DragOutlineLeft,ViewBounds.top),BPoint(DragOutlineRight,
|
||||||
|
ViewBounds.top),BeFocusBlue);
|
||||||
|
AddLine(BPoint(DragOutlineLeft,ViewBounds.bottom),BPoint(DragOutlineRight,
|
||||||
|
ViewBounds.bottom),BeFocusBlue);
|
||||||
|
AddLine(BPoint(DragOutlineLeft,ViewBounds.top+1.0),BPoint(DragOutlineLeft,
|
||||||
|
ViewBounds.bottom-1.0),BeFocusBlue);
|
||||||
|
AddLine(BPoint(DragOutlineRight,ViewBounds.top+1.0),BPoint(DragOutlineRight,
|
||||||
|
ViewBounds.bottom-1.0),BeFocusBlue);
|
||||||
|
EndLineArray();
|
||||||
|
fPrevDragOutlineLeft = DragOutlineLeft;
|
||||||
|
fPrevDragOutlineRight = DragOutlineRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::MouseDown(BPoint Point)
|
||||||
|
{
|
||||||
|
//Only pay attention to primary mouse button
|
||||||
|
bool WatchMouse = false;
|
||||||
|
BPoint MousePos;
|
||||||
|
uint32 Buttons;
|
||||||
|
GetMouse(&MousePos,&Buttons);
|
||||||
|
if(Buttons == B_PRIMARY_MOUSE_BUTTON)
|
||||||
|
{
|
||||||
|
BRect ViewBounds = Bounds();
|
||||||
|
|
||||||
|
//Make sure no other column was already clicked. If so, just discard the old one and redraw the
|
||||||
|
//view
|
||||||
|
if(fColumnClicked != NULL)
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
fColumnClicked = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find the column that the user clicked, if any
|
||||||
|
bool GrabbedResizeTab = false;
|
||||||
|
int32 NumberOfColumns = fDisplayList->CountItems();
|
||||||
|
int32 ColumnFind;
|
||||||
|
CLVColumn* ThisColumn = NULL;
|
||||||
|
for(ColumnFind = 0; ColumnFind < NumberOfColumns; ColumnFind++)
|
||||||
|
{
|
||||||
|
ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
|
||||||
|
if(ThisColumn->IsShown())
|
||||||
|
{
|
||||||
|
float ColumnBegin = ThisColumn->fColumnBegin;
|
||||||
|
float ColumnEnd = ThisColumn->fColumnEnd;
|
||||||
|
if(Point.x >= ColumnBegin && Point.x <= ColumnEnd)
|
||||||
|
{
|
||||||
|
//User clicked in this column
|
||||||
|
if(Point.x <= ColumnBegin+2.0)
|
||||||
|
{
|
||||||
|
//User clicked the resize tab preceding this column
|
||||||
|
for(ColumnFind--; ColumnFind >= 0; ColumnFind--)
|
||||||
|
{
|
||||||
|
ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
|
||||||
|
if(ThisColumn->IsShown())
|
||||||
|
{
|
||||||
|
GrabbedResizeTab = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Point.x >= ColumnEnd-2.0)
|
||||||
|
{
|
||||||
|
//User clicked the resize tab for (after) this column
|
||||||
|
GrabbedResizeTab = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//The user clicked in this column
|
||||||
|
fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
|
||||||
|
fColumnResizing = false;
|
||||||
|
fPreviousMousePos = Point;
|
||||||
|
fMouseClickedPos = Point;
|
||||||
|
fColumnDragging = false;
|
||||||
|
SetSnapMinMax();
|
||||||
|
fDragBoxMouseHoldOffset = Point.x-
|
||||||
|
((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
|
||||||
|
Invalidate(BRect(ColumnBegin+1.0,ViewBounds.top+1.0,ColumnEnd-1.0,
|
||||||
|
ViewBounds.bottom-1.0));
|
||||||
|
|
||||||
|
//Start watching the mouse
|
||||||
|
WatchMouse = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(GrabbedResizeTab)
|
||||||
|
{
|
||||||
|
//The user grabbed a resize tab. See if resizing of this column is allowed
|
||||||
|
if(!(ThisColumn->fFlags & CLV_NOT_RESIZABLE))
|
||||||
|
{
|
||||||
|
fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
|
||||||
|
fColumnResizing = true;
|
||||||
|
fPreviousMousePos = Point;
|
||||||
|
fMouseClickedPos = Point;
|
||||||
|
fColumnDragging = false;
|
||||||
|
fResizeMouseHoldOffset = Point.x-fColumnClicked->fColumnEnd;
|
||||||
|
Invalidate(BRect(fColumnClicked->fColumnEnd,ViewBounds.top,ThisColumn->fColumnEnd,
|
||||||
|
ViewBounds.bottom));
|
||||||
|
|
||||||
|
//Start watching the mouse
|
||||||
|
WatchMouse = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(WatchMouse)
|
||||||
|
SetMouseEventMask(B_POINTER_EVENTS,B_NO_POINTER_HISTORY);
|
||||||
|
fPreviousMousePos = MousePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::MouseMoved(BPoint where, uint32 code, const BMessage *message)
|
||||||
|
{
|
||||||
|
bool should_show_modified_cursor = false;
|
||||||
|
if(fColumnClicked == NULL)
|
||||||
|
{
|
||||||
|
if(code != B_EXITED_VIEW)
|
||||||
|
{
|
||||||
|
//Check for whether to switch the mouse to indicate that you can resize
|
||||||
|
int32 NumberOfColumns = fDisplayList->CountItems();
|
||||||
|
for(int32 ColumnFind = 0; ColumnFind < NumberOfColumns; ColumnFind++)
|
||||||
|
{
|
||||||
|
CLVColumn* ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
|
||||||
|
if(ThisColumn->IsShown())
|
||||||
|
{
|
||||||
|
float ColumnEnd = ThisColumn->fColumnEnd;
|
||||||
|
if(where.x >= ColumnEnd-2.0 && where.x <= ColumnEnd+2.0)
|
||||||
|
{
|
||||||
|
//User clicked the resize tab for (after) this column
|
||||||
|
if(!(ThisColumn->fFlags & CLV_NOT_RESIZABLE))
|
||||||
|
should_show_modified_cursor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(where.x < ColumnEnd+2.0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!fColumnResizing)
|
||||||
|
{
|
||||||
|
//User is clicking or dragging
|
||||||
|
BRect ViewBounds = Bounds();
|
||||||
|
if((where.x<fMouseClickedPos.x-2.0 || where.x>fMouseClickedPos.x+2.0) &&
|
||||||
|
!fColumnDragging)
|
||||||
|
{
|
||||||
|
//User is initiating a drag
|
||||||
|
if(fTheDragGroup->Flags & CLV_NOT_MOVABLE)
|
||||||
|
{
|
||||||
|
//Not allowed to drag this column - terminate the click
|
||||||
|
Invalidate(BRect(fColumnClicked->fColumnBegin,ViewBounds.top,
|
||||||
|
fColumnClicked->fColumnEnd,ViewBounds.bottom));
|
||||||
|
fColumnClicked = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Actually initiate a drag
|
||||||
|
fColumnDragging = true;
|
||||||
|
fPrevDragOutlineLeft = -1.0;
|
||||||
|
fPrevDragOutlineRight = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now deal with dragging
|
||||||
|
if(fColumnDragging)
|
||||||
|
{
|
||||||
|
//User is dragging
|
||||||
|
if(where.x<fPreviousMousePos.x || where.x>fPreviousMousePos.x)
|
||||||
|
{
|
||||||
|
//Mouse moved since I last checked
|
||||||
|
ViewBounds = Bounds();
|
||||||
|
|
||||||
|
bool ColumnSnapped;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//Live dragging of columns
|
||||||
|
ColumnSnapped = false;
|
||||||
|
float ColumnsUpdateLeft = 0.0;
|
||||||
|
float ColumnsUpdateRight = 0.0;
|
||||||
|
float MainViewUpdateLeft = 0.0;
|
||||||
|
float MainViewUpdateRight = 0.0;
|
||||||
|
CLVColumn* LastSwapColumn = NULL;
|
||||||
|
if(fSnapMin != -1.0 && where.x < fSnapMin)
|
||||||
|
{
|
||||||
|
//Shift the group left
|
||||||
|
ColumnsUpdateLeft = fTheShownGroupBefore->GroupBegin;
|
||||||
|
ColumnsUpdateRight = fTheDragGroup->GroupEnd;
|
||||||
|
MainViewUpdateLeft = ColumnsUpdateLeft;
|
||||||
|
MainViewUpdateRight = ColumnsUpdateRight;
|
||||||
|
LastSwapColumn = fTheShownGroupBefore->LastColumnShown;
|
||||||
|
if(fTheDragGroup->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
|
||||||
|
ColumnsUpdateRight += 1.0;
|
||||||
|
else if(fTheShownGroupBefore->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
|
||||||
|
ColumnsUpdateRight += 1.0;
|
||||||
|
ShiftDragGroup(fSnapGroupBefore);
|
||||||
|
ColumnSnapped = true;
|
||||||
|
}
|
||||||
|
if(fSnapMax != -1.0 && where.x > fSnapMax)
|
||||||
|
{
|
||||||
|
//Shift the group right
|
||||||
|
ColumnsUpdateLeft = fTheDragGroup->GroupBegin;
|
||||||
|
ColumnsUpdateRight = fTheShownGroupAfter->GroupEnd;
|
||||||
|
MainViewUpdateLeft = ColumnsUpdateLeft;
|
||||||
|
MainViewUpdateRight = ColumnsUpdateRight;
|
||||||
|
LastSwapColumn = fTheDragGroup->LastColumnShown;
|
||||||
|
if(fTheDragGroup->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
|
||||||
|
ColumnsUpdateRight += 1.0;
|
||||||
|
else if(fTheShownGroupAfter->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
|
||||||
|
ColumnsUpdateRight += 1.0;
|
||||||
|
ShiftDragGroup(fSnapGroupAfter+1);
|
||||||
|
ColumnSnapped = true;
|
||||||
|
}
|
||||||
|
if(ColumnSnapped)
|
||||||
|
{
|
||||||
|
//Redraw the snapped column labels
|
||||||
|
Invalidate(BRect(ColumnsUpdateLeft,ViewBounds.top,ColumnsUpdateRight,
|
||||||
|
ViewBounds.bottom));
|
||||||
|
BRect MainViewBounds = fParent->Bounds();
|
||||||
|
//Modify MainViewUpdateRight if more columns are pushed by expanders
|
||||||
|
if(LastSwapColumn->fFlags & CLV_EXPANDER ||
|
||||||
|
(LastSwapColumn->fPushedByExpander && (LastSwapColumn->fFlags &
|
||||||
|
CLV_PUSH_PASS)))
|
||||||
|
{
|
||||||
|
int32 NumberOfColumns = fDisplayList->CountItems();
|
||||||
|
for(int32 ColumnCounter = fDisplayList->IndexOf(LastSwapColumn)+1;
|
||||||
|
ColumnCounter < NumberOfColumns; ColumnCounter++)
|
||||||
|
{
|
||||||
|
CLVColumn* ThisColumn =
|
||||||
|
(CLVColumn*)fDisplayList->ItemAt(ColumnCounter);
|
||||||
|
if(ThisColumn->IsShown())
|
||||||
|
{
|
||||||
|
if(ThisColumn->fPushedByExpander)
|
||||||
|
MainViewUpdateRight = ThisColumn->fColumnEnd;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fParent->Invalidate(BRect(MainViewUpdateLeft,MainViewBounds.top,
|
||||||
|
MainViewUpdateRight,MainViewBounds.bottom));
|
||||||
|
}
|
||||||
|
}while(ColumnSnapped);
|
||||||
|
//Erase and redraw the drag rectangle but not the interior to avoid label flicker
|
||||||
|
float Min = fPrevDragOutlineLeft;
|
||||||
|
float Max = fPrevDragOutlineRight;
|
||||||
|
float Min2 = where.x-fDragBoxMouseHoldOffset;
|
||||||
|
float GroupBegin = ((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
|
||||||
|
if(Min2 < GroupBegin && fSnapGroupBefore == -1)
|
||||||
|
Min2 = GroupBegin;
|
||||||
|
if(Min2 > GroupBegin && fSnapGroupAfter == -1)
|
||||||
|
Min2 = GroupBegin;
|
||||||
|
float Max2 = Min2 + fDragBoxWidth;
|
||||||
|
float Temp;
|
||||||
|
if(Min2 < Min || Min == -1.0)
|
||||||
|
{Temp = Min2;Min2 = Min;Min = Temp;}
|
||||||
|
if(Max2 > Max || Max == -1.0)
|
||||||
|
{Temp = Max2;Max2 = Max;Max = Temp;}
|
||||||
|
Invalidate(BRect(Min,ViewBounds.top+1.0,Min,ViewBounds.bottom-1.0));
|
||||||
|
if(Min2 != -1.0)
|
||||||
|
Invalidate(BRect(Min2,ViewBounds.top+1.0,Min2,ViewBounds.bottom-1.0));
|
||||||
|
Invalidate(BRect(Max,ViewBounds.top+1.0,Max,ViewBounds.bottom-1.0));
|
||||||
|
if(Max2 != -1.0)
|
||||||
|
Invalidate(BRect(Max2,ViewBounds.top+1.0,Max2,ViewBounds.bottom-1.0));
|
||||||
|
Invalidate(BRect(Min,ViewBounds.top,Max,ViewBounds.top));
|
||||||
|
Invalidate(BRect(Min,ViewBounds.bottom,Max,ViewBounds.bottom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//User is resizing the column
|
||||||
|
if(where.x<fPreviousMousePos.x || where.x>fPreviousMousePos.x)
|
||||||
|
{
|
||||||
|
float NewWidth = where.x - fResizeMouseHoldOffset - fColumnClicked->fColumnBegin;
|
||||||
|
if(NewWidth < fColumnClicked->fMinWidth)
|
||||||
|
NewWidth = fColumnClicked->fMinWidth;
|
||||||
|
if(NewWidth != fColumnClicked->fWidth)
|
||||||
|
fColumnClicked->SetWidth(NewWidth);
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
should_show_modified_cursor = true;
|
||||||
|
}
|
||||||
|
fPreviousMousePos = where;
|
||||||
|
if(fModifiedCursor && !should_show_modified_cursor)
|
||||||
|
{
|
||||||
|
be_app->SetCursor(B_HAND_CURSOR);
|
||||||
|
be_app->ShowCursor();
|
||||||
|
}
|
||||||
|
if(should_show_modified_cursor && !fModifiedCursor)
|
||||||
|
{
|
||||||
|
be_app->SetCursor(c_v_resize_cursor);
|
||||||
|
be_app->ShowCursor();
|
||||||
|
}
|
||||||
|
fModifiedCursor = should_show_modified_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::MouseUp(BPoint where)
|
||||||
|
{
|
||||||
|
if(fColumnClicked == NULL)
|
||||||
|
return;
|
||||||
|
BRect ViewBounds = Bounds();
|
||||||
|
if(!fColumnDragging && !fColumnResizing)
|
||||||
|
{
|
||||||
|
//Column was clicked
|
||||||
|
uint32 ColumnFlags = fColumnClicked->Flags();
|
||||||
|
if(ColumnFlags&CLV_SORT_KEYABLE)
|
||||||
|
{
|
||||||
|
//The column is a "sortable" column
|
||||||
|
uint32 Modifiers;
|
||||||
|
Window()->CurrentMessage()->FindInt32("modifiers",(int32*)&Modifiers);
|
||||||
|
if(!(Modifiers&B_SHIFT_KEY))
|
||||||
|
{
|
||||||
|
//The user wants to select it as the main sorting column
|
||||||
|
if(fParent->fSortKeyList.ItemAt(0) == fColumnClicked)
|
||||||
|
//The column was already selected; switch sort modes
|
||||||
|
fParent->ReverseSortMode(fParent->fColumnList.IndexOf(fColumnClicked));
|
||||||
|
else
|
||||||
|
//The user selected this column for sorting
|
||||||
|
fParent->SetSortKey(fParent->fColumnList.IndexOf(fColumnClicked));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//The user wants to add it as a secondary sorting column
|
||||||
|
if(fParent->fSortKeyList.HasItem(fColumnClicked))
|
||||||
|
//The column was already selected; switch sort modes
|
||||||
|
fParent->ReverseSortMode(fParent->fColumnList.IndexOf(fColumnClicked));
|
||||||
|
else
|
||||||
|
//The user selected this column for sorting
|
||||||
|
fParent->AddSortKey(fParent->fColumnList.IndexOf(fColumnClicked));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(fColumnDragging)
|
||||||
|
{
|
||||||
|
//Column was dragging; erase the drag box but not the interior to avoid label flicker
|
||||||
|
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.top+1.0,
|
||||||
|
fPrevDragOutlineLeft,ViewBounds.bottom-1.0));
|
||||||
|
Invalidate(BRect(fPrevDragOutlineRight,ViewBounds.top+1.0,
|
||||||
|
fPrevDragOutlineRight,ViewBounds.bottom-1.0));
|
||||||
|
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.top,
|
||||||
|
fPrevDragOutlineRight,ViewBounds.top));
|
||||||
|
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.bottom,
|
||||||
|
fPrevDragOutlineRight,ViewBounds.bottom));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//Column was resizing; erase the drag tab
|
||||||
|
Invalidate(BRect(fColumnClicked->fColumnEnd,ViewBounds.top,fColumnClicked->fColumnEnd,
|
||||||
|
ViewBounds.bottom));
|
||||||
|
//Unhighlight the label and forget the column
|
||||||
|
Invalidate(BRect(fColumnClicked->fColumnBegin+1.0,ViewBounds.top+1.0,
|
||||||
|
fColumnClicked->fColumnEnd-1.0,ViewBounds.bottom-1.0));
|
||||||
|
fColumnClicked = NULL;
|
||||||
|
fColumnDragging = false;
|
||||||
|
fColumnResizing = false;
|
||||||
|
if(fModifiedCursor)
|
||||||
|
{
|
||||||
|
be_app->SetCursor(B_HAND_CURSOR);
|
||||||
|
be_app->ShowCursor();
|
||||||
|
fModifiedCursor = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::ShiftDragGroup(int32 NewPos)
|
||||||
|
//Shift the drag group into a new position
|
||||||
|
{
|
||||||
|
int32 NumberOfGroups = fDragGroups.CountItems();
|
||||||
|
int32 GroupCounter;
|
||||||
|
CLVDragGroup* ThisGroup;
|
||||||
|
int32 NumberOfColumnsInGroup;
|
||||||
|
int32 ColumnCounter;
|
||||||
|
BList NewDisplayList;
|
||||||
|
|
||||||
|
//Copy the groups up to the new position
|
||||||
|
for(GroupCounter = 0; GroupCounter < NewPos; GroupCounter++)
|
||||||
|
{
|
||||||
|
if(GroupCounter != fDragGroup)
|
||||||
|
{
|
||||||
|
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
|
||||||
|
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex -
|
||||||
|
ThisGroup->GroupStartDispListIndex + 1;
|
||||||
|
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
|
||||||
|
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
|
||||||
|
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Copy the group into the new position
|
||||||
|
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(fDragGroup);
|
||||||
|
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex - ThisGroup->GroupStartDispListIndex + 1;
|
||||||
|
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
|
||||||
|
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
|
||||||
|
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
|
||||||
|
//Copy the rest of the groups, but skip the dragging group
|
||||||
|
for(GroupCounter = NewPos; GroupCounter < NumberOfGroups; GroupCounter++)
|
||||||
|
{
|
||||||
|
if(GroupCounter != fDragGroup)
|
||||||
|
{
|
||||||
|
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
|
||||||
|
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex -
|
||||||
|
ThisGroup->GroupStartDispListIndex + 1;
|
||||||
|
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
|
||||||
|
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
|
||||||
|
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the new order
|
||||||
|
*fDisplayList = NewDisplayList;
|
||||||
|
|
||||||
|
//Update columns and drag groups
|
||||||
|
fParent->UpdateColumnSizesDataRectSizeScrollBars();
|
||||||
|
UpdateDragGroups();
|
||||||
|
SetSnapMinMax();
|
||||||
|
|
||||||
|
//Inform the program that the display order changed
|
||||||
|
int32* NewOrder = new int32[fParent->CountColumns()];
|
||||||
|
fParent->GetDisplayOrder(NewOrder);
|
||||||
|
fParent->DisplayOrderChanged(NewOrder);
|
||||||
|
delete[] NewOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::UpdateDragGroups()
|
||||||
|
{
|
||||||
|
//Make a copy of the DragGroups list. Use it to store the CLVDragGroup's for recycling
|
||||||
|
BList TempList(fDragGroups);
|
||||||
|
fDragGroups.MakeEmpty();
|
||||||
|
int32 NumberOfColumns = fDisplayList->CountItems();
|
||||||
|
bool ContinueGroup = false;
|
||||||
|
CLVDragGroup* CurrentGroup = NULL;
|
||||||
|
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
|
||||||
|
{
|
||||||
|
CLVColumn* CurrentColumn = (CLVColumn*)fDisplayList->ItemAt(Counter);
|
||||||
|
if(!ContinueGroup)
|
||||||
|
{
|
||||||
|
//Recycle or obtain a new CLVDragGroup
|
||||||
|
CurrentGroup = (CLVDragGroup*)TempList.RemoveItem(int32(0));
|
||||||
|
if(CurrentGroup == NULL)
|
||||||
|
CurrentGroup = new CLVDragGroup;
|
||||||
|
//Add the CLVDragGroup to the DragGroups list
|
||||||
|
fDragGroups.AddItem(CurrentGroup);
|
||||||
|
//Set up the new DragGroup
|
||||||
|
CurrentGroup->GroupStartDispListIndex = Counter;
|
||||||
|
CurrentGroup->GroupStopDispListIndex = Counter;
|
||||||
|
CurrentGroup->Flags = 0;
|
||||||
|
if(CurrentColumn->IsShown())
|
||||||
|
{
|
||||||
|
CurrentGroup->GroupBegin = CurrentColumn->fColumnBegin;
|
||||||
|
CurrentGroup->GroupEnd = CurrentColumn->fColumnEnd;
|
||||||
|
CurrentGroup->LastColumnShown = CurrentColumn;
|
||||||
|
CurrentGroup->Shown = true;
|
||||||
|
if(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING)
|
||||||
|
CurrentGroup->AllLockBeginning = true;
|
||||||
|
else
|
||||||
|
CurrentGroup->AllLockBeginning = false;
|
||||||
|
if(CurrentColumn->fFlags & CLV_LOCK_AT_END)
|
||||||
|
CurrentGroup->AllLockEnd = true;
|
||||||
|
else
|
||||||
|
CurrentGroup->AllLockEnd = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentGroup->GroupBegin = -1.0;
|
||||||
|
CurrentGroup->GroupEnd = -1.0;
|
||||||
|
CurrentGroup->LastColumnShown = NULL;
|
||||||
|
CurrentGroup->Shown = false;
|
||||||
|
if(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING)
|
||||||
|
CurrentGroup->AllLockBeginning = true;
|
||||||
|
else
|
||||||
|
CurrentGroup->AllLockBeginning = false;
|
||||||
|
if(CurrentColumn->fFlags & CLV_LOCK_AT_END)
|
||||||
|
CurrentGroup->AllLockEnd = true;
|
||||||
|
else
|
||||||
|
CurrentGroup->AllLockEnd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Add this column to the current DragGroup
|
||||||
|
CurrentGroup->GroupStopDispListIndex = Counter;
|
||||||
|
if(CurrentColumn->IsShown())
|
||||||
|
{
|
||||||
|
if(CurrentGroup->GroupBegin == -1.0)
|
||||||
|
CurrentGroup->GroupBegin = CurrentColumn->fColumnBegin;
|
||||||
|
CurrentGroup->GroupEnd = CurrentColumn->fColumnEnd;
|
||||||
|
CurrentGroup->LastColumnShown = CurrentColumn;
|
||||||
|
CurrentGroup->Shown = true;
|
||||||
|
}
|
||||||
|
if(!(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING))
|
||||||
|
CurrentGroup->AllLockBeginning = false;
|
||||||
|
if(!(CurrentColumn->fFlags & CLV_LOCK_AT_END))
|
||||||
|
CurrentGroup->AllLockEnd = false;
|
||||||
|
}
|
||||||
|
CurrentGroup->Flags |= CurrentColumn->fFlags & (CLV_NOT_MOVABLE|CLV_LOCK_AT_BEGINNING|
|
||||||
|
CLV_LOCK_AT_END);
|
||||||
|
//See if I should add more columns to this group
|
||||||
|
if(CurrentColumn->fFlags & CLV_LOCK_WITH_RIGHT)
|
||||||
|
ContinueGroup = true;
|
||||||
|
else
|
||||||
|
ContinueGroup = false;
|
||||||
|
}
|
||||||
|
//If any unused groups remain in TempList, delete them
|
||||||
|
while((CurrentGroup = (CLVDragGroup*)TempList.RemoveItem(int32(0))) != NULL)
|
||||||
|
delete CurrentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVColumnLabelView::SetSnapMinMax()
|
||||||
|
{
|
||||||
|
//Find the column group that the user is dragging and the shown group before it
|
||||||
|
int32 NumberOfGroups = fDragGroups.CountItems();
|
||||||
|
int32 ColumnCount;
|
||||||
|
fDragGroup = -1;
|
||||||
|
fTheShownGroupBefore = NULL;
|
||||||
|
fSnapGroupBefore = -1;
|
||||||
|
CLVDragGroup* ThisGroup;
|
||||||
|
int32 GroupCounter;
|
||||||
|
for(GroupCounter = 0; GroupCounter < NumberOfGroups; GroupCounter++)
|
||||||
|
{
|
||||||
|
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
|
||||||
|
for(ColumnCount = ThisGroup->GroupStartDispListIndex; ColumnCount <=
|
||||||
|
ThisGroup->GroupStopDispListIndex; ColumnCount++)
|
||||||
|
if(fDisplayList->ItemAt(ColumnCount) == fColumnClicked)
|
||||||
|
{
|
||||||
|
fDragGroup = GroupCounter;
|
||||||
|
fTheDragGroup = ThisGroup;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(fDragGroup != -1)
|
||||||
|
break;
|
||||||
|
else if(ThisGroup->Shown)
|
||||||
|
{
|
||||||
|
fTheShownGroupBefore = ThisGroup;
|
||||||
|
fSnapGroupBefore = GroupCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find the position of shown group after the one that the user is dragging
|
||||||
|
fTheShownGroupAfter = NULL;
|
||||||
|
fSnapGroupAfter = -1;
|
||||||
|
for(GroupCounter = fDragGroup+1; GroupCounter < NumberOfGroups; GroupCounter++)
|
||||||
|
{
|
||||||
|
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
|
||||||
|
if(ThisGroup->Shown)
|
||||||
|
{
|
||||||
|
fTheShownGroupAfter = ThisGroup;
|
||||||
|
fSnapGroupAfter = GroupCounter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//See if it can actually snap in the given direction
|
||||||
|
if(fSnapGroupBefore != -1)
|
||||||
|
{
|
||||||
|
if(fTheShownGroupBefore->Flags & CLV_LOCK_AT_BEGINNING)
|
||||||
|
if(!fTheDragGroup->AllLockBeginning)
|
||||||
|
fSnapGroupBefore = -1;
|
||||||
|
if(fTheDragGroup->Flags & CLV_LOCK_AT_END)
|
||||||
|
if(!fTheShownGroupBefore->AllLockEnd)
|
||||||
|
fSnapGroupBefore = -1;
|
||||||
|
}
|
||||||
|
if(fSnapGroupAfter != -1)
|
||||||
|
{
|
||||||
|
if(fTheShownGroupAfter->Flags & CLV_LOCK_AT_END)
|
||||||
|
if(!fTheDragGroup->AllLockEnd)
|
||||||
|
fSnapGroupAfter = -1;
|
||||||
|
if(fTheDragGroup->Flags & CLV_LOCK_AT_BEGINNING)
|
||||||
|
if(!fTheShownGroupAfter->AllLockBeginning)
|
||||||
|
fSnapGroupAfter = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find the minumum and maximum positions for the group to snap
|
||||||
|
fSnapMin = -1.0;
|
||||||
|
fSnapMax = -1.0;
|
||||||
|
fDragBoxWidth = fTheDragGroup->GroupEnd-fTheDragGroup->GroupBegin;
|
||||||
|
if(fSnapGroupBefore != -1)
|
||||||
|
{
|
||||||
|
fSnapMin = fTheShownGroupBefore->GroupBegin + fDragBoxWidth;
|
||||||
|
if(fSnapMin > fTheShownGroupBefore->GroupEnd)
|
||||||
|
fSnapMin = fTheShownGroupBefore->GroupEnd;
|
||||||
|
}
|
||||||
|
if(fSnapGroupAfter != -1)
|
||||||
|
{
|
||||||
|
fSnapMax = fTheShownGroupAfter->GroupEnd - fDragBoxWidth;
|
||||||
|
if(fSnapMax < fTheShownGroupAfter->GroupBegin)
|
||||||
|
fSnapMax = fTheShownGroupAfter->GroupBegin;
|
||||||
|
}
|
||||||
|
}
|
99
src/prefs/sounds/Santa/CLVColumnLabelView.h
Normal file
99
src/prefs/sounds/Santa/CLVColumnLabelView.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//CLVColumnLabelView class header file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CLV_COLUMN_LABEL_VIEW_H_
|
||||||
|
#define _CLV_COLUMN_LABEL_VIEW_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <View.h>
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class ColumnListView;
|
||||||
|
class CLVColumn;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLASS AND STRUCTURE DECLARATIONS, ASSOCIATED CONSTANTS AND STATIC FUNCTIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
struct CLVDragGroup
|
||||||
|
{
|
||||||
|
int32 GroupStartDispListIndex; //Indices in the column display list where this group starts
|
||||||
|
int32 GroupStopDispListIndex; //and finishes
|
||||||
|
float GroupBegin,GroupEnd; //-1.0 if whole group is hidden
|
||||||
|
CLVColumn* LastColumnShown;
|
||||||
|
bool AllLockBeginning;
|
||||||
|
bool AllLockEnd;
|
||||||
|
bool Shown; //False if none of the columns in this group are shown
|
||||||
|
uint32 Flags; //Uses CLV_NOT_MOVABLE, CLV_LOCK_AT_BEGINNING, CLV_LOCK_AT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CLVColumnLabelView : public BView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Constructor and destructor
|
||||||
|
CLVColumnLabelView(BRect Bounds,ColumnListView* Parent,const BFont* Font);
|
||||||
|
~CLVColumnLabelView();
|
||||||
|
|
||||||
|
//BView overrides
|
||||||
|
virtual void Draw(BRect UpdateRect);
|
||||||
|
virtual void MouseDown(BPoint Point);
|
||||||
|
virtual void MouseMoved(BPoint where, uint32 code, const BMessage *message);
|
||||||
|
virtual void MouseUp(BPoint where);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ColumnListView;
|
||||||
|
friend class CLVColumn;
|
||||||
|
|
||||||
|
float fFontAscent;
|
||||||
|
BList* fDisplayList;
|
||||||
|
|
||||||
|
//Column select and drag stuff
|
||||||
|
CLVColumn* fColumnClicked;
|
||||||
|
BPoint fPreviousMousePos;
|
||||||
|
BPoint fMouseClickedPos;
|
||||||
|
bool fColumnDragging;
|
||||||
|
bool fColumnResizing;
|
||||||
|
bool fModifiedCursor;
|
||||||
|
BList fDragGroups; //Groups of CLVColumns that must drag together
|
||||||
|
int32 fDragGroup; //Index into DragGroups of the group being dragged by user
|
||||||
|
CLVDragGroup* fTheDragGroup;
|
||||||
|
CLVDragGroup* fTheShownGroupBefore;
|
||||||
|
CLVDragGroup* fTheShownGroupAfter;
|
||||||
|
int32 fSnapGroupBefore, //Index into DragGroups of TheShownGroupBefore and
|
||||||
|
fSnapGroupAfter; //TheShownGroupAfter, if the group the user is dragging is
|
||||||
|
//allowed to snap there, otherwise -1
|
||||||
|
float fDragBoxMouseHoldOffset,fResizeMouseHoldOffset;
|
||||||
|
float fDragBoxWidth; //Can include multiple columns; depends on CLV_LOCK_WITH_RIGHT
|
||||||
|
float fPrevDragOutlineLeft,fPrevDragOutlineRight;
|
||||||
|
float fSnapMin,fSnapMax; //-1.0 indicates the column can't snap in the given direction
|
||||||
|
ColumnListView* fParent;
|
||||||
|
|
||||||
|
//Private functions
|
||||||
|
void ShiftDragGroup(int32 NewPos);
|
||||||
|
void UpdateDragGroups();
|
||||||
|
void SetSnapMinMax();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
576
src/prefs/sounds/Santa/CLVEasyItem.cpp
Normal file
576
src/prefs/sounds/Santa/CLVEasyItem.cpp
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
//CLVListItem source file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <string.h>
|
||||||
|
#include <Region.h>
|
||||||
|
#include <ClassInfo.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "CLVEasyItem.h"
|
||||||
|
#include "Colors.h"
|
||||||
|
#include "CLVColumn.h"
|
||||||
|
#include "ColumnListView.h"
|
||||||
|
#include "NewStrings.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLVEasyItem CLASS DEFINITION
|
||||||
|
//******************************************************************************************************
|
||||||
|
CLVEasyItem::CLVEasyItem(uint32 level, bool superitem, bool expanded, float minheight)
|
||||||
|
: CLVListItem(level,superitem,expanded,minheight)
|
||||||
|
{
|
||||||
|
text_offset = 0.0;
|
||||||
|
SetTextColor(0,0,0);
|
||||||
|
fBackgroundColor=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLVEasyItem::~CLVEasyItem()
|
||||||
|
{
|
||||||
|
int num_columns = m_column_types.CountItems();
|
||||||
|
for(int column = 0; column < num_columns; column++)
|
||||||
|
{
|
||||||
|
int32 type = (int32)m_column_types.ItemAt(column);
|
||||||
|
bool bitmap_is_copy = false;
|
||||||
|
if(type & CLVColFlagBitmapIsCopy)
|
||||||
|
bitmap_is_copy = true;
|
||||||
|
type &= CLVColTypesMask;
|
||||||
|
if(type == CLVColStaticText || type == CLVColTruncateText)
|
||||||
|
delete[] ((char*)m_column_content.ItemAt(column));
|
||||||
|
if(type == CLVColTruncateText)
|
||||||
|
delete[] ((char*)m_aux_content.ItemAt(column));
|
||||||
|
if(type == CLVColBitmap && bitmap_is_copy)
|
||||||
|
delete ((BBitmap*)m_column_content.ItemAt(column));
|
||||||
|
delete (BRect*)m_cached_rects.ItemAt(column);
|
||||||
|
}
|
||||||
|
SetBackgroundColor(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::PrepListsForSet(int column_index)
|
||||||
|
{
|
||||||
|
int cur_num_columns = m_column_types.CountItems();
|
||||||
|
bool delete_old = (cur_num_columns >= column_index-1);
|
||||||
|
while(cur_num_columns <= column_index)
|
||||||
|
{
|
||||||
|
m_column_types.AddItem((void*)CLVColNone);
|
||||||
|
m_column_content.AddItem(NULL);
|
||||||
|
m_aux_content.AddItem(NULL);
|
||||||
|
m_cached_rects.AddItem(new BRect(-1,-1,-1,-1));
|
||||||
|
cur_num_columns++;
|
||||||
|
}
|
||||||
|
if(delete_old)
|
||||||
|
{
|
||||||
|
//Column content exists already so delete the old entries
|
||||||
|
int32 old_type = (int32)m_column_types.ItemAt(column_index);
|
||||||
|
bool bitmap_is_copy = false;
|
||||||
|
if(old_type & CLVColFlagBitmapIsCopy)
|
||||||
|
bitmap_is_copy = true;
|
||||||
|
old_type &= CLVColTypesMask;
|
||||||
|
|
||||||
|
void* old_content = m_column_content.ItemAt(column_index);
|
||||||
|
char* old_truncated = (char*)m_aux_content.ItemAt(column_index);
|
||||||
|
if(old_type == CLVColStaticText || old_type == CLVColTruncateText)
|
||||||
|
delete[] ((char*)old_content);
|
||||||
|
if(old_type == CLVColTruncateText)
|
||||||
|
delete[] old_truncated;
|
||||||
|
if(old_type == CLVColBitmap && bitmap_is_copy)
|
||||||
|
delete ((BBitmap*)old_content);
|
||||||
|
((BRect**)m_cached_rects.Items())[column_index]->Set(-1,-1,-1,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::SetColumnContent(int column_index, const char *text, bool truncate, bool right_justify)
|
||||||
|
{
|
||||||
|
PrepListsForSet(column_index);
|
||||||
|
|
||||||
|
//Create the new entry
|
||||||
|
((BRect**)m_cached_rects.Items())[column_index]->Set(-1,-1,-1,-1);
|
||||||
|
if(text == NULL || text[0] == 0)
|
||||||
|
{
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColNone;
|
||||||
|
((char**)m_column_content.Items())[column_index] = NULL;
|
||||||
|
((char**)m_aux_content.Items())[column_index] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char* copy = Strdup_new(text);
|
||||||
|
((char**)m_column_content.Items())[column_index] = copy;
|
||||||
|
|
||||||
|
if(!truncate)
|
||||||
|
{
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColStaticText;
|
||||||
|
((char**)m_aux_content.Items())[column_index] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColTruncateText|CLVColFlagNeedsTruncation;
|
||||||
|
copy = new char[strlen(text)+3];
|
||||||
|
strcpy(copy,text);
|
||||||
|
((char**)m_aux_content.Items())[column_index] = copy;
|
||||||
|
}
|
||||||
|
if(right_justify)
|
||||||
|
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::SetColumnContent(int column_index, const BBitmap *bitmap, float horizontal_offset, bool copy,
|
||||||
|
bool right_justify)
|
||||||
|
{
|
||||||
|
PrepListsForSet(column_index);
|
||||||
|
|
||||||
|
//Create the new entry
|
||||||
|
if(bitmap == NULL)
|
||||||
|
{
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColNone;
|
||||||
|
((char**)m_column_content.Items())[column_index] = NULL;
|
||||||
|
((char**)m_aux_content.Items())[column_index] = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(copy)
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColBitmap|CLVColFlagBitmapIsCopy;
|
||||||
|
else
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColBitmap;
|
||||||
|
if(right_justify)
|
||||||
|
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
|
||||||
|
BBitmap* the_bitmap;
|
||||||
|
if(copy)
|
||||||
|
{
|
||||||
|
the_bitmap = new BBitmap(bitmap->Bounds(),bitmap->ColorSpace());
|
||||||
|
int32 copy_ints = bitmap->BitsLength()/4;
|
||||||
|
int32* source = (int32*)bitmap->Bits();
|
||||||
|
int32* dest = (int32*)the_bitmap->Bits();
|
||||||
|
for(int32 i = 0; i < copy_ints; i++)
|
||||||
|
dest[i] = source[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
the_bitmap = (BBitmap*)bitmap;
|
||||||
|
((BBitmap**)m_column_content.Items())[column_index] = the_bitmap;
|
||||||
|
((int32*)m_aux_content.Items())[column_index] = (int32)horizontal_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::SetColumnUserTextContent(int column_index, bool truncate, bool right_justify)
|
||||||
|
{
|
||||||
|
PrepListsForSet(column_index);
|
||||||
|
if(truncate)
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColTruncateUserText;
|
||||||
|
else
|
||||||
|
((int32*)m_column_types.Items())[column_index] = CLVColUserText;
|
||||||
|
if(right_justify)
|
||||||
|
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* CLVEasyItem::GetColumnContentText(int column_index)
|
||||||
|
{
|
||||||
|
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
|
||||||
|
if(type == CLVColStaticText || type == CLVColTruncateText)
|
||||||
|
return (char*)m_column_content.ItemAt(column_index);
|
||||||
|
if(type == CLVColTruncateUserText || type == CLVColUserText)
|
||||||
|
return GetUserText(column_index,-1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BBitmap* CLVEasyItem::GetColumnContentBitmap(int column_index)
|
||||||
|
{
|
||||||
|
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
|
||||||
|
if(type != CLVColBitmap)
|
||||||
|
return NULL;
|
||||||
|
return (BBitmap*)m_column_content.ItemAt(column_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::DrawItemColumn(BView *owner, BRect item_column_rect, int32 column_index, bool complete)
|
||||||
|
{
|
||||||
|
rgb_color color;
|
||||||
|
|
||||||
|
bool selected = IsSelected();
|
||||||
|
if(selected)
|
||||||
|
color = ((ColumnListView*)owner)->ItemSelectColor();
|
||||||
|
else{
|
||||||
|
if(fBackgroundColor)
|
||||||
|
{
|
||||||
|
color.red = fBackgroundColor->red;
|
||||||
|
color.blue = fBackgroundColor->blue;
|
||||||
|
color.green = fBackgroundColor->green;
|
||||||
|
complete = true;
|
||||||
|
}else
|
||||||
|
color = owner->ViewColor();
|
||||||
|
}
|
||||||
|
owner->SetLowColor(color);
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
bool highlightTextOnly = ((ColumnListView*)owner)->HighlightTextOnly();
|
||||||
|
|
||||||
|
|
||||||
|
if(selected || complete)
|
||||||
|
{
|
||||||
|
owner->SetHighColor(color);
|
||||||
|
if(!highlightTextOnly && selected)
|
||||||
|
owner->FillRect(item_column_rect);
|
||||||
|
else if(!highlightTextOnly &&complete)
|
||||||
|
owner->FillRect(item_column_rect);
|
||||||
|
else if(highlightTextOnly&&complete)
|
||||||
|
owner->Invalidate(item_column_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(column_index == -1)
|
||||||
|
return;
|
||||||
|
int32 type = (int32)m_column_types.ItemAt(column_index);
|
||||||
|
if(type == 0)
|
||||||
|
return;
|
||||||
|
bool needs_truncation = false;
|
||||||
|
if(type & CLVColFlagNeedsTruncation)
|
||||||
|
needs_truncation = true;
|
||||||
|
bool right_justify = false;
|
||||||
|
if(type & CLVColFlagRightJustify)
|
||||||
|
right_justify = true;
|
||||||
|
type &= CLVColTypesMask;
|
||||||
|
|
||||||
|
BRegion Region;
|
||||||
|
Region.Include(item_column_rect);
|
||||||
|
owner->ConstrainClippingRegion(&Region);
|
||||||
|
|
||||||
|
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
|
||||||
|
if(cached_rect != NULL)
|
||||||
|
*cached_rect = item_column_rect;
|
||||||
|
|
||||||
|
if(type == CLVColStaticText || type == CLVColTruncateText || type == CLVColTruncateUserText ||
|
||||||
|
type == CLVColUserText)
|
||||||
|
{
|
||||||
|
const char* text = NULL;
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
|
||||||
|
|
||||||
|
if(type == CLVColTruncateText)
|
||||||
|
{
|
||||||
|
if(needs_truncation)
|
||||||
|
{
|
||||||
|
BFont owner_font;
|
||||||
|
owner->GetFont(&owner_font);
|
||||||
|
TruncateText(column_index,item_column_rect.right-item_column_rect.left,&owner_font);
|
||||||
|
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
text = (const char*)m_aux_content.ItemAt(column_index);
|
||||||
|
}
|
||||||
|
else if(type == CLVColStaticText)
|
||||||
|
text = (const char*)m_column_content.ItemAt(column_index);
|
||||||
|
else if(type == CLVColTruncateUserText)
|
||||||
|
text = GetUserText(column_index,item_column_rect.right-item_column_rect.left);
|
||||||
|
else if(type == CLVColUserText)
|
||||||
|
text = GetUserText(column_index,-1);
|
||||||
|
|
||||||
|
if(text != NULL)
|
||||||
|
{
|
||||||
|
BPoint draw_point;
|
||||||
|
if(!right_justify)
|
||||||
|
draw_point.Set(item_column_rect.left+2.0,item_column_rect.top+text_offset);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BFont font;
|
||||||
|
owner->GetFont(&font);
|
||||||
|
float string_width = font.StringWidth(text);
|
||||||
|
draw_point.Set(item_column_rect.right-2.0-string_width,item_column_rect.top+text_offset);
|
||||||
|
}
|
||||||
|
if(selected && highlightTextOnly)
|
||||||
|
{
|
||||||
|
float stringWidth = owner->StringWidth(text);
|
||||||
|
if(stringWidth>0)
|
||||||
|
{
|
||||||
|
font_height FontAttributes;
|
||||||
|
BFont owner_font;
|
||||||
|
owner->GetFont(&owner_font);
|
||||||
|
owner_font.GetHeight(&FontAttributes);
|
||||||
|
float FontHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
|
||||||
|
|
||||||
|
BRect textRect(item_column_rect);
|
||||||
|
textRect.right = textRect.left + stringWidth + 3;
|
||||||
|
float pad = (textRect.Height() - FontHeight)/2.0;
|
||||||
|
textRect.top += pad;
|
||||||
|
textRect.bottom = textRect.top + FontHeight;
|
||||||
|
owner->SetHighColor(color);
|
||||||
|
owner->FillRoundRect(textRect,1,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
owner->SetHighColor(fTextColor);
|
||||||
|
owner->DrawString(text,draw_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == CLVColBitmap)
|
||||||
|
{
|
||||||
|
const BBitmap* bitmap = (BBitmap*)m_column_content.ItemAt(column_index);
|
||||||
|
BRect bounds = bitmap->Bounds();
|
||||||
|
float horizontal_offset = (float)((int32)m_aux_content.ItemAt(column_index));
|
||||||
|
if(!right_justify)
|
||||||
|
{
|
||||||
|
item_column_rect.left += horizontal_offset;
|
||||||
|
item_column_rect.right = item_column_rect.left + (bounds.right-bounds.left);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_column_rect.left = item_column_rect.right-horizontal_offset-(bounds.right-bounds.left);
|
||||||
|
item_column_rect.right -= horizontal_offset;
|
||||||
|
}
|
||||||
|
item_column_rect.top += ceil(((item_column_rect.bottom-item_column_rect.top)-(bounds.bottom-bounds.top))/2.0);
|
||||||
|
item_column_rect.bottom = item_column_rect.top + (bounds.bottom-bounds.top);
|
||||||
|
|
||||||
|
if(selected && highlightTextOnly)
|
||||||
|
{
|
||||||
|
BRect selectRect(item_column_rect);
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
owner->SetHighColor(color);
|
||||||
|
selectRect.bottom += 2;
|
||||||
|
selectRect.right += 3;
|
||||||
|
selectRect.top -= 2;
|
||||||
|
selectRect.left -= 1;
|
||||||
|
owner->FillRoundRect(selectRect,2,2);
|
||||||
|
}
|
||||||
|
owner->SetDrawingMode(B_OP_OVER);
|
||||||
|
owner->DrawBitmap(bitmap,item_column_rect);
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
}
|
||||||
|
owner->ConstrainClippingRegion(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::Update(BView *owner, const BFont *font)
|
||||||
|
{
|
||||||
|
CLVListItem::Update(owner,font);
|
||||||
|
font_height FontAttributes;
|
||||||
|
BFont owner_font;
|
||||||
|
owner->GetFont(&owner_font);
|
||||||
|
owner_font.GetHeight(&FontAttributes);
|
||||||
|
float FontHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
|
||||||
|
text_offset = ceil(FontAttributes.ascent) + (Height()-FontHeight)/2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CLVEasyItem::CompareItems(const CLVListItem *a_Item1, const CLVListItem *a_Item2, int32 KeyColumn)
|
||||||
|
{
|
||||||
|
const CLVEasyItem* Item1 = cast_as(a_Item1,const CLVEasyItem);
|
||||||
|
const CLVEasyItem* Item2 = cast_as(a_Item2,const CLVEasyItem);
|
||||||
|
if(Item1 == NULL || Item2 == NULL || Item1->m_column_types.CountItems() <= KeyColumn ||
|
||||||
|
Item2->m_column_types.CountItems() <= KeyColumn)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int32 type1 = ((int32)Item1->m_column_types.ItemAt(KeyColumn)) & CLVColTypesMask;
|
||||||
|
int32 type2 = ((int32)Item2->m_column_types.ItemAt(KeyColumn)) & CLVColTypesMask;
|
||||||
|
|
||||||
|
if(!((type1 == CLVColStaticText || type1 == CLVColTruncateText || type1 == CLVColTruncateUserText ||
|
||||||
|
type1 == CLVColUserText) && (type2 == CLVColStaticText || type2 == CLVColTruncateText ||
|
||||||
|
type2 == CLVColTruncateUserText || type2 == CLVColUserText)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char* text1 = NULL;
|
||||||
|
const char* text2 = NULL;
|
||||||
|
|
||||||
|
if(type1 == CLVColStaticText || type1 == CLVColTruncateText)
|
||||||
|
text1 = (const char*)Item1->m_column_content.ItemAt(KeyColumn);
|
||||||
|
else if(type1 == CLVColTruncateUserText || type1 == CLVColUserText)
|
||||||
|
text1 = Item1->GetUserText(KeyColumn,-1);
|
||||||
|
|
||||||
|
if(type2 == CLVColStaticText || type2 == CLVColTruncateText)
|
||||||
|
text2 = (const char*)Item2->m_column_content.ItemAt(KeyColumn);
|
||||||
|
else if(type2 == CLVColTruncateUserText || type2 == CLVColUserText)
|
||||||
|
text2 = Item2->GetUserText(KeyColumn,-1);
|
||||||
|
|
||||||
|
return strcasecmp(text1,text2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect CLVEasyItem::TruncateText(int32 column_index, float column_width, BFont* font)
|
||||||
|
{
|
||||||
|
column_width -= 4;
|
||||||
|
//Because when I draw the text I start drawing 2 pixels to the right from the column's left edge, and want
|
||||||
|
//to stop 2 pixels before the right edge
|
||||||
|
BRect invalid(-1,-1,-1,-1);
|
||||||
|
char* full_text = (char*)m_column_content.ItemAt(column_index);
|
||||||
|
char new_text[256];
|
||||||
|
char* truncated_text = (char*)m_aux_content.ItemAt(column_index);
|
||||||
|
BString STR = full_text;
|
||||||
|
font->TruncateString(&STR,B_TRUNCATE_END,column_width);
|
||||||
|
::strncpy(new_text,STR.String(),256);
|
||||||
|
//GetTruncatedString(full_text,new_text,column_width,256,font);
|
||||||
|
if(strcmp(truncated_text,new_text)!=0)
|
||||||
|
{
|
||||||
|
//The truncated text has changed
|
||||||
|
BRect* temp = (BRect*)m_cached_rects.ItemAt(column_index);
|
||||||
|
if(temp != NULL && *temp != BRect(-1,-1,-1,-1))
|
||||||
|
{
|
||||||
|
invalid = *temp;
|
||||||
|
|
||||||
|
//Figure out which region just got changed
|
||||||
|
int32 cmppos;
|
||||||
|
int32 cmplen = strlen(new_text);
|
||||||
|
char remember = 0;
|
||||||
|
for(cmppos = 0; cmppos <= cmplen; cmppos++)
|
||||||
|
if(new_text[cmppos] != truncated_text[cmppos])
|
||||||
|
{
|
||||||
|
remember = new_text[cmppos];
|
||||||
|
new_text[cmppos] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
invalid.left += 2 + font->StringWidth(new_text);
|
||||||
|
new_text[cmppos] = remember;
|
||||||
|
}
|
||||||
|
//Remember the new truncated text
|
||||||
|
strcpy(truncated_text,new_text);
|
||||||
|
}
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::ColumnWidthChanged(int32 column_index, float column_width, ColumnListView *the_view)
|
||||||
|
{
|
||||||
|
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
|
||||||
|
if(cached_rect == NULL || *cached_rect == BRect(-1,-1,-1,-1))
|
||||||
|
return;
|
||||||
|
float width_delta = column_width-(cached_rect->right-cached_rect->left);
|
||||||
|
cached_rect->right += width_delta;
|
||||||
|
|
||||||
|
int num_columns = m_cached_rects.CountItems();
|
||||||
|
for(int column = 0; column < num_columns; column++)
|
||||||
|
if(column != column_index)
|
||||||
|
{
|
||||||
|
BRect* other_rect = (BRect*)m_cached_rects.ItemAt(column);
|
||||||
|
if(other_rect->left > cached_rect->left)
|
||||||
|
other_rect->OffsetBy(width_delta,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 type = (int32)m_column_types.ItemAt(column_index);
|
||||||
|
bool right_justify = (type&CLVColFlagRightJustify);
|
||||||
|
type &= CLVColTypesMask;
|
||||||
|
BRect invalid;
|
||||||
|
BFont view_font;
|
||||||
|
if(type == CLVColTruncateText)
|
||||||
|
{
|
||||||
|
BRect bounds = the_view->Bounds();
|
||||||
|
if(cached_rect->top <= bounds.bottom && cached_rect->bottom >= bounds.top)
|
||||||
|
{
|
||||||
|
//If it's onscreen, truncate and invalidate the changed area
|
||||||
|
the_view->GetFont(&view_font);
|
||||||
|
invalid = TruncateText(column_index, column_width,&view_font);
|
||||||
|
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
|
||||||
|
if(invalid != BRect(-1.0,-1.0,-1.0,-1.0))
|
||||||
|
{
|
||||||
|
if(!right_justify)
|
||||||
|
the_view->Invalidate(invalid);
|
||||||
|
else
|
||||||
|
the_view->Invalidate(*cached_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//If it's not onscreen flag it for truncation the next time it's drawn
|
||||||
|
((int32*)m_column_types.Items())[column_index] |= CLVColFlagNeedsTruncation;
|
||||||
|
}
|
||||||
|
if(type == CLVColTruncateUserText)
|
||||||
|
{
|
||||||
|
char old_text[256];
|
||||||
|
Strtcpy(old_text,GetUserText(column_index,column_width-width_delta),256);
|
||||||
|
char new_text[256];
|
||||||
|
Strtcpy(new_text,GetUserText(column_index,column_width),256);
|
||||||
|
if(strcmp(old_text,new_text) != 0)
|
||||||
|
{
|
||||||
|
BRect* temp = (BRect*)m_cached_rects.ItemAt(column_index);
|
||||||
|
if(temp != NULL && *temp != BRect(-1,-1,-1,-1))
|
||||||
|
{
|
||||||
|
invalid = *temp;
|
||||||
|
if(!right_justify)
|
||||||
|
{
|
||||||
|
//The truncation changed, so find the point of divergence.
|
||||||
|
int change_pos = 0;
|
||||||
|
while(old_text[change_pos] == new_text[change_pos])
|
||||||
|
change_pos++;
|
||||||
|
new_text[change_pos] = 0;
|
||||||
|
the_view->GetFont(&view_font);
|
||||||
|
invalid.left += 2 + view_font.StringWidth(new_text);
|
||||||
|
the_view->Invalidate(invalid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
the_view->Invalidate(*cached_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::FrameChanged(int32 column_index, BRect new_frame, ColumnListView *the_view)
|
||||||
|
{
|
||||||
|
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
|
||||||
|
if(cached_rect == NULL)
|
||||||
|
return;
|
||||||
|
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
|
||||||
|
if(type == CLVColTruncateText)
|
||||||
|
if(*cached_rect != new_frame)
|
||||||
|
{
|
||||||
|
*cached_rect = new_frame;
|
||||||
|
|
||||||
|
//If it's onscreen, truncate and invalidate the changed area
|
||||||
|
if(new_frame.Intersects(the_view->Bounds()))
|
||||||
|
{
|
||||||
|
BFont view_font;
|
||||||
|
the_view->GetFont(&view_font);
|
||||||
|
BRect invalid = TruncateText(column_index, new_frame.right-new_frame.left,&view_font);
|
||||||
|
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
|
||||||
|
if(invalid != BRect(-1.0,-1.0,-1.0,-1.0))
|
||||||
|
the_view->Invalidate(invalid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//If it's not onscreen flag it for truncation the next time it's drawn
|
||||||
|
((int32*)m_column_types.Items())[column_index] |= CLVColFlagNeedsTruncation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* CLVEasyItem::GetUserText(int32 column_index, float column_width) const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVEasyItem::SetTextColor(uchar red,uchar green,uchar blue)
|
||||||
|
{
|
||||||
|
fTextColor.red = red;
|
||||||
|
fTextColor.green = green;
|
||||||
|
fTextColor.blue = blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLVEasyItem::SetBackgroundColor(rgb_color *color)
|
||||||
|
{
|
||||||
|
delete fBackgroundColor;
|
||||||
|
if(color)
|
||||||
|
{
|
||||||
|
fBackgroundColor = new rgb_color;
|
||||||
|
fBackgroundColor->red = color->red;
|
||||||
|
fBackgroundColor->blue = color->blue;
|
||||||
|
fBackgroundColor->green = color->green;
|
||||||
|
}else
|
||||||
|
fBackgroundColor = NULL;
|
||||||
|
}
|
98
src/prefs/sounds/Santa/CLVEasyItem.h
Normal file
98
src/prefs/sounds/Santa/CLVEasyItem.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//CLVEasyItem header file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CLV_EASY_ITEM_H_
|
||||||
|
#define _CLV_EASY_ITEM_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <List.h>
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "CLVListItem.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TYPE DEFINITIONS AND CONSTANTS
|
||||||
|
//******************************************************************************************************
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CLVColNone = 0x00000000,
|
||||||
|
CLVColStaticText = 0x00000001,
|
||||||
|
CLVColTruncateText = 0x00000002,
|
||||||
|
CLVColBitmap = 0x00000003,
|
||||||
|
CLVColUserText = 0x00000004,
|
||||||
|
CLVColTruncateUserText = 0x00000005,
|
||||||
|
|
||||||
|
CLVColTypesMask = 0x00000007,
|
||||||
|
|
||||||
|
CLVColFlagBitmapIsCopy = 0x00000008,
|
||||||
|
CLVColFlagNeedsTruncation = 0x00000010,
|
||||||
|
CLVColFlagRightJustify = 0x00000020
|
||||||
|
};
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLVEasyItem CLASS DECLARATION
|
||||||
|
//******************************************************************************************************
|
||||||
|
class CLVEasyItem : public CLVListItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Constructor and destructor
|
||||||
|
CLVEasyItem(uint32 level = 0, bool superitem = false, bool expanded = false, float minheight = 0.0);
|
||||||
|
virtual ~CLVEasyItem();
|
||||||
|
|
||||||
|
virtual void SetColumnContent(int column_index, const BBitmap *bitmap, float horizontal_offset = 2.0,
|
||||||
|
bool copy = true, bool right_justify = false);
|
||||||
|
virtual void SetColumnContent(int column_index, const char *text, bool truncate = true,
|
||||||
|
bool right_justify = false);
|
||||||
|
virtual void SetColumnUserTextContent(int column_index, bool truncate = true, bool right_justify = false);
|
||||||
|
const char* GetColumnContentText(int column_index);
|
||||||
|
const BBitmap* GetColumnContentBitmap(int column_index);
|
||||||
|
virtual void DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index, bool complete);
|
||||||
|
virtual void Update(BView *owner, const BFont *font);
|
||||||
|
static int CompareItems(const CLVListItem* a_Item1, const CLVListItem* a_Item2, int32 KeyColumn);
|
||||||
|
BRect TruncateText(int32 column_index, float column_width, BFont* font);
|
||||||
|
//Returns the area that needs to be redrawn, or BRect(-1,-1,-1,-1) if nothing
|
||||||
|
virtual void ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view);
|
||||||
|
virtual void FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view);
|
||||||
|
inline float GetTextOffset() {return text_offset;}
|
||||||
|
virtual const char* GetUserText(int32 column_index, float column_width) const;
|
||||||
|
void SetTextColor(uchar red,uchar green,uchar blue);
|
||||||
|
void SetBackgroundColor(rgb_color *color);
|
||||||
|
|
||||||
|
BList m_column_types; //List of int32's converted from CLVColumnTypes
|
||||||
|
BList m_column_content; //List of char* (full content) or BBitmap*
|
||||||
|
private:
|
||||||
|
void PrepListsForSet(int column_index);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BList m_aux_content; //List of char* (truncated content) or int32 for bitmap horizontal offset
|
||||||
|
BList m_cached_rects; //List of BRect for truncated text
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float text_offset;
|
||||||
|
rgb_color fTextColor;
|
||||||
|
rgb_color *fBackgroundColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
231
src/prefs/sounds/Santa/CLVListItem.cpp
Normal file
231
src/prefs/sounds/Santa/CLVListItem.cpp
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//CLVListItem source file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <Region.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "CLVListItem.h"
|
||||||
|
#include "ColumnListView.h"
|
||||||
|
#include "CLVColumn.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLVItem CLASS DEFINITION
|
||||||
|
//******************************************************************************************************
|
||||||
|
CLVListItem::CLVListItem(uint32 level, bool superitem, bool expanded, float minheight)
|
||||||
|
: BListItem(level, expanded),
|
||||||
|
fExpanderButtonRect(-1.0,-1.0,-1.0,-1.0),
|
||||||
|
fExpanderColumnRect(-1.0,-1.0,-1.0,-1.0)
|
||||||
|
{
|
||||||
|
fSuperItem = superitem;
|
||||||
|
fOutlineLevel = level;
|
||||||
|
fMinHeight = minheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLVListItem::~CLVListItem()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
BRect CLVListItem::ItemColumnFrame(int32 column_index, ColumnListView* owner)
|
||||||
|
{
|
||||||
|
BList* ColumnList = &owner->fColumnList;
|
||||||
|
CLVColumn* ThisColumn = (CLVColumn*)ColumnList->ItemAt(column_index);
|
||||||
|
if(!ThisColumn->IsShown())
|
||||||
|
return BRect(-1,-1,-1,-1);
|
||||||
|
|
||||||
|
int32 DisplayIndex = owner->IndexOf(this);
|
||||||
|
BRect itemRect;
|
||||||
|
if(DisplayIndex >= 0)
|
||||||
|
itemRect = owner->ItemFrame(DisplayIndex);
|
||||||
|
else
|
||||||
|
return BRect(-1,-1,-1,-1);
|
||||||
|
|
||||||
|
//Figure out what the limit is for expanders pushing other columns
|
||||||
|
float PushMax = 100000;
|
||||||
|
if(ThisColumn->fPushedByExpander || (ThisColumn->fFlags & CLV_EXPANDER))
|
||||||
|
{
|
||||||
|
BList* DisplayList = &owner->fColumnDisplayList;
|
||||||
|
int32 NumberOfColumns = DisplayList->CountItems();
|
||||||
|
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
|
||||||
|
{
|
||||||
|
CLVColumn* SomeColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
|
||||||
|
if((SomeColumn->fFlags & CLV_EXPANDER) || SomeColumn->fPushedByExpander)
|
||||||
|
PushMax = SomeColumn->fColumnEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect ThisColumnRect = itemRect;
|
||||||
|
ThisColumnRect.left = ThisColumn->fColumnBegin;
|
||||||
|
ThisColumnRect.right = ThisColumn->fColumnEnd;
|
||||||
|
|
||||||
|
if(ThisColumn->fFlags & CLV_EXPANDER)
|
||||||
|
{
|
||||||
|
ThisColumnRect.right += OutlineLevel() * 20.0;
|
||||||
|
if(ThisColumnRect.right > PushMax)
|
||||||
|
ThisColumnRect.right = PushMax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ThisColumn->fPushedByExpander)
|
||||||
|
{
|
||||||
|
float Shift = OutlineLevel() * 20.0;
|
||||||
|
ThisColumnRect.left += Shift;
|
||||||
|
ThisColumnRect.right += Shift;
|
||||||
|
if(Shift > 0.0 && ThisColumnRect.right > PushMax)
|
||||||
|
ThisColumnRect.right = PushMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ThisColumnRect.right >= ThisColumnRect.left)
|
||||||
|
return ThisColumnRect;
|
||||||
|
else
|
||||||
|
return BRect(-1,-1,-1,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVListItem::DrawItem(BView* owner, BRect itemRect, bool complete)
|
||||||
|
{
|
||||||
|
BList* DisplayList = &((ColumnListView*)owner)->fColumnDisplayList;
|
||||||
|
int32 NumberOfColumns = DisplayList->CountItems();
|
||||||
|
float PushMax = itemRect.right;
|
||||||
|
CLVColumn* ThisColumn;
|
||||||
|
BRect ThisColumnRect = itemRect;
|
||||||
|
float ExpanderDelta = OutlineLevel() * 20.0;
|
||||||
|
//Figure out what the limit is for expanders pushing other columns
|
||||||
|
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
|
||||||
|
{
|
||||||
|
ThisColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
|
||||||
|
if((ThisColumn->fFlags & CLV_EXPANDER) || ThisColumn->fPushedByExpander)
|
||||||
|
PushMax = ThisColumn->fColumnEnd;
|
||||||
|
}
|
||||||
|
BRegion ClippingRegion;
|
||||||
|
if(!complete)
|
||||||
|
owner->GetClippingRegion(&ClippingRegion);
|
||||||
|
else
|
||||||
|
ClippingRegion.Set(itemRect);
|
||||||
|
float LastColumnEnd = -1.0;
|
||||||
|
|
||||||
|
//Draw the columns
|
||||||
|
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
|
||||||
|
{
|
||||||
|
ThisColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
|
||||||
|
if(!ThisColumn->IsShown())
|
||||||
|
continue;
|
||||||
|
ThisColumnRect.left = ThisColumn->fColumnBegin;
|
||||||
|
ThisColumnRect.right = LastColumnEnd = ThisColumn->fColumnEnd;
|
||||||
|
float Shift = 0.0;
|
||||||
|
if((ThisColumn->fFlags & CLV_EXPANDER) || ThisColumn->fPushedByExpander)
|
||||||
|
Shift = ExpanderDelta;
|
||||||
|
if(ThisColumn->fFlags & CLV_EXPANDER)
|
||||||
|
{
|
||||||
|
ThisColumnRect.right += Shift;
|
||||||
|
if(ThisColumnRect.right > PushMax)
|
||||||
|
ThisColumnRect.right = PushMax;
|
||||||
|
fExpanderColumnRect = ThisColumnRect;
|
||||||
|
if(ClippingRegion.Intersects(ThisColumnRect))
|
||||||
|
{
|
||||||
|
//Give the programmer a chance to do his kind of highlighting if the item is selected
|
||||||
|
DrawItemColumn(owner, ThisColumnRect,
|
||||||
|
((ColumnListView*)owner)->fColumnList.IndexOf(ThisColumn),complete);
|
||||||
|
if(fSuperItem)
|
||||||
|
{
|
||||||
|
//Draw the expander, clip manually
|
||||||
|
float TopOffset = ceil((ThisColumnRect.bottom-ThisColumnRect.top-10.0)/2.0);
|
||||||
|
float LeftOffset = ThisColumn->fColumnEnd + Shift - 3.0 - 10.0;
|
||||||
|
float RightClip = LeftOffset + 10.0 - ThisColumnRect.right;
|
||||||
|
if(RightClip < 0.0)
|
||||||
|
RightClip = 0.0;
|
||||||
|
BBitmap* Arrow;
|
||||||
|
if(IsExpanded())
|
||||||
|
Arrow = &((ColumnListView*)owner)->fDownArrow;
|
||||||
|
else
|
||||||
|
Arrow = &((ColumnListView*)owner)->fRightArrow;
|
||||||
|
if(LeftOffset <= ThisColumnRect.right)
|
||||||
|
{
|
||||||
|
fExpanderButtonRect.Set(LeftOffset,ThisColumnRect.top+TopOffset,
|
||||||
|
LeftOffset+10.0-RightClip,ThisColumnRect.top+TopOffset+10.0);
|
||||||
|
owner->SetDrawingMode(B_OP_OVER);
|
||||||
|
owner->DrawBitmap(Arrow, BRect(0.0,0.0,10.0-RightClip,10.0),fExpanderButtonRect);
|
||||||
|
owner->SetDrawingMode(B_OP_COPY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fExpanderButtonRect.Set(-1.0,-1.0,-1.0,-1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThisColumnRect.left += Shift;
|
||||||
|
ThisColumnRect.right += Shift;
|
||||||
|
if(Shift > 0.0 && ThisColumnRect.right > PushMax)
|
||||||
|
ThisColumnRect.right = PushMax;
|
||||||
|
if(ThisColumnRect.right >= ThisColumnRect.left && ClippingRegion.Intersects(ThisColumnRect))
|
||||||
|
DrawItemColumn(owner, ThisColumnRect,
|
||||||
|
((ColumnListView*)owner)->fColumnList.IndexOf(ThisColumn),complete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Fill the area after all the columns (so the select highlight goes all the way across)
|
||||||
|
ThisColumnRect.left = LastColumnEnd + 1.0;
|
||||||
|
ThisColumnRect.right = owner->Bounds().right;
|
||||||
|
if(ThisColumnRect.left <= ThisColumnRect.right && ClippingRegion.Intersects(ThisColumnRect))
|
||||||
|
DrawItemColumn(owner, ThisColumnRect,-1,complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float CLVListItem::ExpanderShift(int32 column_index, ColumnListView* owner)
|
||||||
|
{
|
||||||
|
CLVColumn* ThisColumn = owner->ColumnAt(column_index);
|
||||||
|
if(!(ThisColumn->fPushedByExpander || ThisColumn->fFlags & CLV_EXPANDER))
|
||||||
|
return 0.0;
|
||||||
|
else
|
||||||
|
return OutlineLevel() * 20.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVListItem::Update(BView* owner, const BFont* font)
|
||||||
|
{
|
||||||
|
BListItem::Update(owner,font);
|
||||||
|
float ItemHeight = Height();
|
||||||
|
if(ItemHeight < fMinHeight)
|
||||||
|
ItemHeight = fMinHeight;
|
||||||
|
SetHeight(ItemHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVListItem::ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view)
|
||||||
|
{
|
||||||
|
//Get rid of a warning
|
||||||
|
column_index = 0;
|
||||||
|
column_width = 0;
|
||||||
|
the_view = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CLVListItem::FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view)
|
||||||
|
{
|
||||||
|
//Get rid of a warning
|
||||||
|
column_index = 0;
|
||||||
|
new_frame.left = 0;
|
||||||
|
the_view = NULL;
|
||||||
|
|
||||||
|
}
|
82
src/prefs/sounds/Santa/CLVListItem.h
Normal file
82
src/prefs/sounds/Santa/CLVListItem.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//CLVListItem header file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CLV_LIST_ITEM_H_
|
||||||
|
#define _CLV_LIST_ITEM_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <ListItem.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class ColumnListView;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLVListItem CLASS DECLARATION
|
||||||
|
//******************************************************************************************************
|
||||||
|
class CLVListItem : public BListItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Constructor and destructor
|
||||||
|
CLVListItem(uint32 level = 0, bool superitem = false, bool expanded = false, float minheight = 0.0);
|
||||||
|
virtual ~CLVListItem();
|
||||||
|
|
||||||
|
//Archival stuff
|
||||||
|
/* Not implemented yet
|
||||||
|
CLVItem(BMessage* archive);
|
||||||
|
static CLVItem* Instantiate(BMessage* data);
|
||||||
|
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual void DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index,
|
||||||
|
bool complete) = 0; //column_index (0-N) is based on the order in which the columns were added
|
||||||
|
//to the ColumnListView, not the display order. An index of -1 indicates
|
||||||
|
//that the program needs to draw a blank area beyond the last column. The
|
||||||
|
//main purpose is to allow the highlighting bar to continue all the way to
|
||||||
|
//the end of the ColumnListView, even after the end of the last column.
|
||||||
|
virtual void DrawItem(BView* owner, BRect itemRect, bool complete);
|
||||||
|
//In general, you don't need or want to override DrawItem().
|
||||||
|
BRect ItemColumnFrame(int32 column_index, ColumnListView* owner);
|
||||||
|
float ExpanderShift(int32 column_index, ColumnListView* owner);
|
||||||
|
virtual void Update(BView* owner, const BFont* font);
|
||||||
|
inline bool IsSuperItem() const {return fSuperItem;}
|
||||||
|
inline void SetSuperItem(bool superitem) {fSuperItem = superitem;}
|
||||||
|
inline uint32 OutlineLevel() const {return fOutlineLevel;}
|
||||||
|
inline void SetOutlineLevel(uint32 level) {fOutlineLevel = level;}
|
||||||
|
inline bool ExpanderRectContains(BPoint where) {return fExpanderButtonRect.Contains(where);}
|
||||||
|
virtual void ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view);
|
||||||
|
virtual void FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ColumnListView;
|
||||||
|
|
||||||
|
bool fSuperItem;
|
||||||
|
uint32 fOutlineLevel;
|
||||||
|
float fMinHeight;
|
||||||
|
BRect fExpanderButtonRect;
|
||||||
|
BRect fExpanderColumnRect;
|
||||||
|
BList* fSortingContextBList;
|
||||||
|
ColumnListView* fSortingContextCLV;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1691
src/prefs/sounds/Santa/ColumnListView.cpp
Normal file
1691
src/prefs/sounds/Santa/ColumnListView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
238
src/prefs/sounds/Santa/ColumnListView.h
Normal file
238
src/prefs/sounds/Santa/ColumnListView.h
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
//Column list view header file
|
||||||
|
|
||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CLV_COLUMN_LIST_VIEW_H_
|
||||||
|
#define _CLV_COLUMN_LIST_VIEW_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <ListView.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "Colors.h"
|
||||||
|
#include "CLVColumn.h"
|
||||||
|
class CLVListItem;
|
||||||
|
class CLVColumnLabelView;
|
||||||
|
class CLVFillerView;
|
||||||
|
class CLVContainerView;
|
||||||
|
#include "PrefilledBitmap.h"
|
||||||
|
#include "BetterScrollView.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CONSTANTS AND TYPE DEFINITIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
typedef int (*CLVCompareFuncPtr)(const CLVListItem* item1, const CLVListItem* item2, int32 sort_key);
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** ColumnListView CLASS DECLARATION
|
||||||
|
//******************************************************************************************************
|
||||||
|
class ColumnListView : public BListView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Constructor and destructor
|
||||||
|
ColumnListView( BRect Frame,
|
||||||
|
CLVContainerView** ContainerView, //Used to get back a pointer to the container
|
||||||
|
//view that will hold the ColumnListView, the
|
||||||
|
//the CLVColumnLabelView, and the scrollbars.
|
||||||
|
//If no scroll bars or border are asked for,
|
||||||
|
//this will act like a plain BView container.
|
||||||
|
const char* Name = NULL,
|
||||||
|
uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||||
|
uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
|
||||||
|
list_view_type Type = B_SINGLE_SELECTION_LIST,
|
||||||
|
bool hierarchical = false,
|
||||||
|
bool horizontal = true, //Which scroll bars should I add, if any
|
||||||
|
bool vertical = true,
|
||||||
|
bool scroll_view_corner = true,
|
||||||
|
border_style border = B_NO_BORDER, //What type of border to add, if any
|
||||||
|
const BFont* LabelFont = be_plain_font);
|
||||||
|
virtual ~ColumnListView();
|
||||||
|
|
||||||
|
//Archival stuff
|
||||||
|
/*** Not implemented yet
|
||||||
|
ColumnListView(BMessage* archive);
|
||||||
|
static ColumnListView* Instantiate(BMessage* data);
|
||||||
|
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||||
|
***/
|
||||||
|
|
||||||
|
//Column setup functions
|
||||||
|
virtual bool AddColumn(CLVColumn* Column); //Note that a column may only be added to
|
||||||
|
//one ColumnListView at a time, and may not
|
||||||
|
//be added more than once to the same
|
||||||
|
//ColumnListView without removing it
|
||||||
|
//inbetween
|
||||||
|
virtual bool AddColumnList(BList* NewColumns);
|
||||||
|
virtual bool RemoveColumn(CLVColumn* Column);
|
||||||
|
virtual bool RemoveColumns(CLVColumn* Column, int32 Count); //Finds Column in ColumnList
|
||||||
|
//and removes Count columns and
|
||||||
|
//their data from the view
|
||||||
|
//and its items
|
||||||
|
int32 CountColumns() const;
|
||||||
|
int32 IndexOfColumn(CLVColumn* column) const;
|
||||||
|
CLVColumn* ColumnAt(int32 column_index) const;
|
||||||
|
virtual bool SetDisplayOrder(const int32* Order);
|
||||||
|
//Sets the display order: each int32 in the Order list specifies the column index of the
|
||||||
|
//next column to display. Note that this DOES NOT get called if the user drags a
|
||||||
|
//column, so overriding it will not inform you of user changes. If you need that info,
|
||||||
|
//override DisplayOrderChanged instead. Also note that SetDisplayOrder does call
|
||||||
|
//DisplayOrderChanged(false).
|
||||||
|
void GetDisplayOrder(int32* order) const;
|
||||||
|
//Fills a caller-provided array with the display order of the columns in the same format
|
||||||
|
//as used in calling SetDisplayOrder. The order pointer should point to an array
|
||||||
|
//int32 order[n] where n is the number of columns in the ColumnListView.
|
||||||
|
virtual void ColumnWidthChanged(int32 ColumnIndex, float NewWidth);
|
||||||
|
virtual void DisplayOrderChanged(const int32* order);
|
||||||
|
//Override this if you want to find out when the display order changed.
|
||||||
|
virtual void SetSortKey(int32 ColumnIndex, bool doSort = true);
|
||||||
|
//Set it to -1 to remove the sort key.
|
||||||
|
virtual void AddSortKey(int32 ColumnIndex, bool doSort = true);
|
||||||
|
void ReverseSortMode(int32 ColumnIndex, bool doSort = true);
|
||||||
|
virtual void SetSortMode(int32 ColumnIndex,CLVSortMode Mode, bool doSort = true);
|
||||||
|
//Override this to filter the modes
|
||||||
|
int32 GetSorting(int32* SortKeys, CLVSortMode* SortModes) const;
|
||||||
|
//Returns the number of used sort keys, and fills the provided arrays with the sort keys
|
||||||
|
//by column index and sort modes, in priority order. The pointers should point to an array
|
||||||
|
//int32 SortKeys[n], and an array CLVSortMode SortModes[n] where n is the number of sortable
|
||||||
|
//columns in the ColumnListView. Note: sorting will only occur if the key column is shown.
|
||||||
|
void SetSorting(int32 NumberOfKeys, int32* SortKeys, CLVSortMode* SortModes, bool doSort = true);
|
||||||
|
//Sets the sorting parameters using the same format returned by Sorting
|
||||||
|
virtual void SortingChanged(); //Override this to detect changes to the sorting keys or modes.
|
||||||
|
|
||||||
|
inline void SetItemSelectColor(bool window_active, rgb_color color)
|
||||||
|
{
|
||||||
|
if(window_active) fSelectedItemColorWindowActive = color;
|
||||||
|
else fSelectedItemColorWindowInactive = color;
|
||||||
|
}
|
||||||
|
inline rgb_color ItemSelectColor(bool window_active) const
|
||||||
|
{
|
||||||
|
if(window_active) return fSelectedItemColorWindowActive;
|
||||||
|
return fSelectedItemColorWindowInactive;
|
||||||
|
}
|
||||||
|
inline rgb_color ItemSelectColor() const
|
||||||
|
{
|
||||||
|
if(fWindowActive) return fSelectedItemColorWindowActive;
|
||||||
|
return fSelectedItemColorWindowInactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BView overrides
|
||||||
|
virtual void FrameResized(float Width, float Height);
|
||||||
|
virtual void ScrollTo(BPoint point);
|
||||||
|
virtual void MouseDown(BPoint point);
|
||||||
|
virtual void MouseUp(BPoint where);
|
||||||
|
virtual void MouseMoved(BPoint where, uint32 code, const BMessage* message);
|
||||||
|
virtual void WindowActivated(bool active);
|
||||||
|
|
||||||
|
//List functions
|
||||||
|
virtual bool AddUnder(BListItem* item, BListItem* superitem);
|
||||||
|
virtual bool AddItem(BListItem* item, int32 fullListIndex);
|
||||||
|
virtual bool AddItem(BListItem* item);
|
||||||
|
virtual bool AddList(BList* newItems); //This must be a BList of
|
||||||
|
//BListItem*'s, NOT CLVListItem*'s
|
||||||
|
virtual bool AddList(BList* newItems, int32 fullListIndex); //This must be a BList of
|
||||||
|
//BListItem*'s, NOT CLVListItem*'s
|
||||||
|
virtual bool EfficientAddListHierarchical(BList* newItems, int32 fullListIndex, bool expanded);
|
||||||
|
//visible indicates whether or not the items are under an item which is expanded. If
|
||||||
|
//expanded is false, NONE of these items will be showing. If expanded is true, ALL of
|
||||||
|
//them will be, so make sure that all of them are in an expanded state. Not checking is
|
||||||
|
//done for you. The list is of BListItem*'s, NOT CLVListItem*'s.
|
||||||
|
virtual bool RemoveItem(BListItem* item);
|
||||||
|
virtual BListItem* RemoveItem(int32 fullListIndex); //Actually returns CLVListItem
|
||||||
|
virtual bool RemoveItems(int32 fullListIndex, int32 count);
|
||||||
|
virtual void MakeEmpty();
|
||||||
|
CLVListItem* FullListItemAt(int32 fullListIndex) const;
|
||||||
|
int32 FullListIndexOf(const CLVListItem* item) const;
|
||||||
|
int32 FullListIndexOf(BPoint point) const;
|
||||||
|
CLVListItem* FullListFirstItem() const;
|
||||||
|
CLVListItem* FullListLastItem() const;
|
||||||
|
bool FullListHasItem(const CLVListItem* item) const;
|
||||||
|
int32 FullListCountItems() const;
|
||||||
|
bool FullListIsEmpty() const;
|
||||||
|
int32 FullListCurrentSelection(int32 index = 0) const;
|
||||||
|
void FullListDoForEach(bool (*func)(CLVListItem*));
|
||||||
|
void FullListDoForEach(bool (*func)(CLVListItem*, void*), void* arg2);
|
||||||
|
CLVListItem* Superitem(const CLVListItem* item) const;
|
||||||
|
int32 FullListNumberOfSubitems(const CLVListItem* item) const;
|
||||||
|
virtual void Expand(CLVListItem* item);
|
||||||
|
virtual void Collapse(CLVListItem* item);
|
||||||
|
bool IsExpanded(int32 fullListIndex) const;
|
||||||
|
void SetSortFunction(CLVCompareFuncPtr compare);
|
||||||
|
void SortItems();
|
||||||
|
virtual CLVContainerView* CreateContainer(bool horizontal, bool vertical, bool scroll_view_corner,
|
||||||
|
border_style border, uint32 ResizingMode, uint32 flags);
|
||||||
|
bool HighlightTextOnly() {return fHighlightTextOnly;}
|
||||||
|
void SetHighlightTextOnly(bool enable) {fHighlightTextOnly = enable;}
|
||||||
|
private:
|
||||||
|
friend class CLVMainView;
|
||||||
|
friend class CLVColumn;
|
||||||
|
friend class CLVColumnLabelView;
|
||||||
|
friend class CLVListItem;
|
||||||
|
|
||||||
|
void UpdateColumnSizesDataRectSizeScrollBars(bool scrolling_allowed = true);
|
||||||
|
void ColumnsChanged();
|
||||||
|
void EmbedInContainer(bool horizontal, bool vertical, bool scroll_view_corner, border_style border,
|
||||||
|
uint32 ResizingMode, uint32 flags);
|
||||||
|
void SortListArray(CLVListItem** SortArray, int32 NumberOfItems);
|
||||||
|
void MakeEmptyPrivate();
|
||||||
|
bool AddHierarchicalListPrivate(BList* newItems, int32 fullListIndex);
|
||||||
|
bool AddItemPrivate(CLVListItem* item, int32 fullListIndex);
|
||||||
|
void SortFullListSegment(int32 OriginalListStartIndex, int32 InsertionPoint, BList* NewList);
|
||||||
|
BList* SortItemsInThisLevel(int32 OriginalListStartIndex);
|
||||||
|
static int PlainBListSortFunc(BListItem** item1, BListItem** item2);
|
||||||
|
static int HierarchicalBListSortFunc(BListItem** item1, BListItem** item2);
|
||||||
|
|
||||||
|
CLVColumnLabelView* fColumnLabelView;
|
||||||
|
CLVContainerView* fScrollView;
|
||||||
|
bool fHierarchical;
|
||||||
|
BList fColumnList;
|
||||||
|
BList fColumnDisplayList;
|
||||||
|
BList fSortKeyList; //List contains CLVColumn pointers
|
||||||
|
BList fFullItemList; //List contains CLVListItem pointers
|
||||||
|
PrefilledBitmap fRightArrow;
|
||||||
|
PrefilledBitmap fDownArrow;
|
||||||
|
int32 fExpanderColumn;
|
||||||
|
CLVCompareFuncPtr fCompare;
|
||||||
|
bool fWatchingForDrag;
|
||||||
|
BPoint fLastMouseDown;
|
||||||
|
int32 fNoKeyMouseDownItemIndex;
|
||||||
|
rgb_color fSelectedItemColorWindowActive;
|
||||||
|
rgb_color fSelectedItemColorWindowInactive;
|
||||||
|
bool fWindowActive;
|
||||||
|
bool fHighlightTextOnly;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CLVContainerView : public BetterScrollView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CLVContainerView(ColumnListView* target, uint32 resizingMode, uint32 flags, bool horizontal, bool vertical,
|
||||||
|
bool scroll_view_corner, border_style border);
|
||||||
|
~CLVContainerView();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ColumnListView;
|
||||||
|
bool IsBeingDestroyed;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
166
src/prefs/sounds/Santa/Cursors.cpp
Normal file
166
src/prefs/sounds/Santa/Cursors.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
//******************************************************************************************************
|
||||||
|
//**** PROJECT HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "Cursors.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CONSTANT DEFINITIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
uint8 c_v_resize_cursor_data[68] =
|
||||||
|
{
|
||||||
|
16,1,7,7,
|
||||||
|
0,0, //0000000000000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
17,16, //0001000100010000
|
||||||
|
49,24, //0011000100011000
|
||||||
|
113,28, //0111000100011100
|
||||||
|
49,24, //0011000100011000
|
||||||
|
17,16, //0001000100010000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
27,176, //0001101110110000
|
||||||
|
59,184, //0011101110111000
|
||||||
|
123,188,//0111101110111100
|
||||||
|
251,190,//1111101110111110
|
||||||
|
123,188,//0111101110111100
|
||||||
|
59,184, //0011101110111000
|
||||||
|
27,176, //0001101110110000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
0,0 //0000000000000000
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 c_h_resize_cursor_data[68] =
|
||||||
|
{
|
||||||
|
16,1,7,7,
|
||||||
|
0,0, //0000000000000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
7,192, //0000011111000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
127,252,//0111111111111100
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
7,192, //0000011111000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
|
||||||
|
1,0, //0000000100000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
7,192, //0000011111000000
|
||||||
|
15,224, //0000111111100000
|
||||||
|
15,224, //0000111111100000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
255,254,//1111111111111110
|
||||||
|
255,254,//1111111111111110
|
||||||
|
255,254,//1111111111111110
|
||||||
|
0,0, //0000000000000000
|
||||||
|
15,224, //0000111111100000
|
||||||
|
15,224, //0000111111100000
|
||||||
|
7,192, //0000011111000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
0,0 //0000000000000000
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 c_crosshairs_cursor_data[68] =
|
||||||
|
{
|
||||||
|
16,1,7,7,
|
||||||
|
0,0, //0000000000000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
125,124,//0111110101111100
|
||||||
|
0,0, //0000000000000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
1,0, //0000000100000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
0,0, //0000000000000000
|
||||||
|
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
255,254,//1111111111111110
|
||||||
|
255,254,//1111111111111110
|
||||||
|
255,254,//1111111111111110
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
3,128, //0000001110000000
|
||||||
|
0,0 //0000000000000000
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 c_magnify_cursor_data[68] =
|
||||||
|
{
|
||||||
|
16,1,6,6,
|
||||||
|
0,0, //0000000000000000
|
||||||
|
7,0, //0000011100000000
|
||||||
|
24,192, //0001100011000000
|
||||||
|
32,32, //0010000000100000
|
||||||
|
32,32, //0010000000100000
|
||||||
|
64,16, //0100000000010000
|
||||||
|
64,16, //0100000000010000
|
||||||
|
64,16, //0100000000010000
|
||||||
|
32,32, //0010000000100000
|
||||||
|
32,32, //0010000000100000
|
||||||
|
24,240, //0001100011110000
|
||||||
|
7,56, //0000011100111000
|
||||||
|
0,28, //0000000000011100
|
||||||
|
0,14, //0000000000001110
|
||||||
|
0,4, //0000000000000100
|
||||||
|
0,0, //0000000000000000
|
||||||
|
|
||||||
|
7,0, //0000011100000000
|
||||||
|
31,192, //0001111111000000
|
||||||
|
63,224, //0011111111100000
|
||||||
|
120,240,//0111100011110000
|
||||||
|
112,112,//0111000001110000
|
||||||
|
224,56, //1110000000111000
|
||||||
|
224,56, //1110000000111000
|
||||||
|
224,56, //1110000000111000
|
||||||
|
112,112,//0111000001110000
|
||||||
|
120,240,//0111100011110000
|
||||||
|
63,248, //0011111111111000
|
||||||
|
31,252, //0001111111111100
|
||||||
|
7,62, //0000011100111110
|
||||||
|
0,31, //0000000000011111
|
||||||
|
0,14, //0000000000001110
|
||||||
|
0,4, //0000000000000100
|
||||||
|
};
|
||||||
|
|
||||||
|
const void* c_v_resize_cursor = c_v_resize_cursor_data;
|
||||||
|
const void* c_h_resize_cursor = c_h_resize_cursor_data;
|
||||||
|
const void* c_crosshairs_cursor = c_crosshairs_cursor_data;
|
||||||
|
const void* c_magnify_cursor = c_magnify_cursor_data;
|
||||||
|
|
20
src/prefs/sounds/Santa/Cursors.h
Normal file
20
src/prefs/sounds/Santa/Cursors.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _SGB_CURSORS_H_
|
||||||
|
#define _SGB_CURSORS_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CONSTANT DEFINITIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
extern const void* c_v_resize_cursor;
|
||||||
|
extern const void* c_h_resize_cursor;
|
||||||
|
extern const void* c_crosshairs_cursor;
|
||||||
|
extern const void* c_magnify_cursor;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_SGB_CURSORS_H_
|
19
src/prefs/sounds/Santa/Descending.h
Normal file
19
src/prefs/sounds/Santa/Descending.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const unsigned char kDescendingIconBits [] = {
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
|
||||||
|
};
|
||||||
|
|
244
src/prefs/sounds/Santa/NewStrings.cpp
Normal file
244
src/prefs/sounds/Santa/NewStrings.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <Font.h>
|
||||||
|
#include <Looper.h>
|
||||||
|
#include <Rect.h>
|
||||||
|
|
||||||
|
#include "NewStrings.h"
|
||||||
|
|
||||||
|
float GetStringsMaxWidth(const char** strings, int32 num_strings, const BFont* font,
|
||||||
|
float* string_widths)
|
||||||
|
//Fills the stringsWidths array with the width of each individual string in the array using
|
||||||
|
//BFont::GetStringWidths(), then finds the longest string width in the array and returns that width.
|
||||||
|
//If a string_widths array is provided, it fills it in with the length of each string.
|
||||||
|
{
|
||||||
|
int32 strlens_fixed[20];
|
||||||
|
int32* strlens;
|
||||||
|
bool release_string_lengths = false;
|
||||||
|
if(num_strings <= 20)
|
||||||
|
strlens = strlens_fixed;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strlens = new int32[num_strings];
|
||||||
|
release_string_lengths = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float strwidths_fixed[20];
|
||||||
|
bool release_string_widths = false;
|
||||||
|
if(string_widths == NULL)
|
||||||
|
{
|
||||||
|
if(num_strings <= 20)
|
||||||
|
string_widths = strwidths_fixed;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string_widths = new float[num_strings];
|
||||||
|
release_string_widths = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 i;
|
||||||
|
for(i = 0; i < num_strings; i++)
|
||||||
|
strlens[i] = strlen(strings[i]);
|
||||||
|
font->GetStringWidths(strings,strlens,num_strings,string_widths);
|
||||||
|
float max = string_widths[0];
|
||||||
|
for(i = 1; i < num_strings; i++)
|
||||||
|
if(string_widths[i] > max)
|
||||||
|
max = string_widths[i];
|
||||||
|
|
||||||
|
if(release_string_widths)
|
||||||
|
delete[] string_widths;
|
||||||
|
if(release_string_lengths)
|
||||||
|
delete[] strlens;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect StringBoundingBox(const char* string, const BFont* font, bool full_height, bool round_up)
|
||||||
|
{
|
||||||
|
const char* string_array[1] = {string};
|
||||||
|
struct escapement_delta delta_array[1] = {{0,0}};
|
||||||
|
BRect rect_array[1];
|
||||||
|
font->GetBoundingBoxesForStrings(string_array,1,B_SCREEN_METRIC,delta_array,rect_array);
|
||||||
|
if(full_height)
|
||||||
|
{
|
||||||
|
struct font_height font_height_struct;
|
||||||
|
font->GetHeight(&font_height_struct);
|
||||||
|
rect_array[0].top = 0-font_height_struct.ascent;
|
||||||
|
rect_array[0].bottom = font_height_struct.descent;
|
||||||
|
}
|
||||||
|
if(round_up)
|
||||||
|
{
|
||||||
|
rect_array[0].left = floor(rect_array[0].left);
|
||||||
|
rect_array[0].top = floor(rect_array[0].top);
|
||||||
|
rect_array[0].right = ceil(rect_array[0].right);
|
||||||
|
rect_array[0].bottom = ceil(rect_array[0].bottom);
|
||||||
|
}
|
||||||
|
return rect_array[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect GetMaxStringBoundingBoxes(const char** strings, int32 num_strings, const BFont* font,
|
||||||
|
BRect* rects, bool full_height, bool round_up)
|
||||||
|
{
|
||||||
|
BRect rects_fixed[20];
|
||||||
|
bool release_rects = false;
|
||||||
|
if(rects == NULL)
|
||||||
|
{
|
||||||
|
if(num_strings <= 20)
|
||||||
|
rects = rects_fixed;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rects = new BRect[num_strings];
|
||||||
|
release_rects = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct escapement_delta delta_array_fixed[20];
|
||||||
|
bool release_deltas = false;
|
||||||
|
struct escapement_delta* delta_array = delta_array_fixed;
|
||||||
|
if(num_strings > 20)
|
||||||
|
{
|
||||||
|
delta_array = new escapement_delta[num_strings];
|
||||||
|
release_deltas = true;
|
||||||
|
}
|
||||||
|
int32 i;
|
||||||
|
for(i=0; i<num_strings; i++)
|
||||||
|
{
|
||||||
|
delta_array[i].nonspace = 0;
|
||||||
|
delta_array[i].space = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
font->GetBoundingBoxesForStrings(strings,num_strings,B_SCREEN_METRIC,delta_array,rects);
|
||||||
|
struct font_height font_height_struct;
|
||||||
|
if(full_height)
|
||||||
|
{
|
||||||
|
font->GetHeight(&font_height_struct);
|
||||||
|
if(round_up)
|
||||||
|
{
|
||||||
|
font_height_struct.ascent = ceil(font_height_struct.ascent);
|
||||||
|
font_height_struct.descent = ceil(font_height_struct.descent);
|
||||||
|
}
|
||||||
|
for(i=0; i<num_strings; i++)
|
||||||
|
{
|
||||||
|
rects[i].top = 0-font_height_struct.ascent;
|
||||||
|
rects[i].bottom = font_height_struct.descent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(round_up)
|
||||||
|
for(i=0; i<num_strings; i++)
|
||||||
|
{
|
||||||
|
rects[i].left = floor(rects[i].left);
|
||||||
|
rects[i].right = ceil(rects[i].right);
|
||||||
|
if(!full_height)
|
||||||
|
{
|
||||||
|
rects[i].top = floor(rects[i].top);
|
||||||
|
rects[i].bottom = ceil(rects[i].bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect max = rects[0];
|
||||||
|
for(i=0; i<num_strings; i++)
|
||||||
|
{
|
||||||
|
if(max.left > rects[i].left)
|
||||||
|
max.left = rects[i].left;
|
||||||
|
if((!full_height) && max.top > rects[i].top)
|
||||||
|
max.top = rects[i].top;
|
||||||
|
if(max.right < rects[i].right)
|
||||||
|
max.right = rects[i].right;
|
||||||
|
if((!full_height) && max.bottom < rects[i].bottom)
|
||||||
|
max.bottom = rects[i].bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(release_rects)
|
||||||
|
delete[] rects;
|
||||||
|
if(release_deltas)
|
||||||
|
delete[] delta_array;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* Strdup_new(const char* source)
|
||||||
|
{
|
||||||
|
char* dest = new char[strlen(source)+1];
|
||||||
|
strcpy(dest,source);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* Strcat_new(const char* string_1, const char* string_2)
|
||||||
|
{
|
||||||
|
int len_1 = strlen(string_1);
|
||||||
|
char* dest = new char[len_1+strlen(string_2)+1];
|
||||||
|
strcpy(dest,string_1);
|
||||||
|
strcpy(&dest[len_1],string_2);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* Strcat_new(const char* string_1, const char* string_2, const char* string_3)
|
||||||
|
{
|
||||||
|
int len_1 = strlen(string_1);
|
||||||
|
int len_2 = strlen(string_2);
|
||||||
|
char* dest = new char[len_1+len_2+strlen(string_3)+1];
|
||||||
|
strcpy(dest,string_1);
|
||||||
|
strcpy(&dest[len_1],string_2);
|
||||||
|
strcpy(&dest[len_1+len_2],string_3);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* Strcat_new(const char* string_1, const char* string_2, const char* string_3, const char* string_4)
|
||||||
|
{
|
||||||
|
int len_1 = strlen(string_1);
|
||||||
|
int len_2 = strlen(string_2);
|
||||||
|
int len_3 = strlen(string_3);
|
||||||
|
char* dest = new char[len_1+len_2+len_3+strlen(string_4)+1];
|
||||||
|
strcpy(dest,string_1);
|
||||||
|
strcpy(&dest[len_1],string_2);
|
||||||
|
strcpy(&dest[len_1+len_2],string_3);
|
||||||
|
strcpy(&dest[len_1+len_2+len_3],string_4);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *Strtcpy(char *dst, const char *src, int len)
|
||||||
|
{
|
||||||
|
strncpy(dst,src,len-1);
|
||||||
|
dst[len-1] = 0;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StrToUpper(char* string)
|
||||||
|
{
|
||||||
|
while(*string != 0)
|
||||||
|
{
|
||||||
|
if(*string >= 'a' && *string <= 'z')
|
||||||
|
*string = *string - 'a' + 'A';
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StrToLower(char* string)
|
||||||
|
{
|
||||||
|
while(*string != 0)
|
||||||
|
{
|
||||||
|
if(*string >= 'A' && *string <= 'Z')
|
||||||
|
*string = *string - 'A' + 'a';
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
}
|
48
src/prefs/sounds/Santa/NewStrings.h
Normal file
48
src/prefs/sounds/Santa/NewStrings.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
#ifndef _SGB_NEW_STRINGS_H_
|
||||||
|
#define _SGB_NEW_STRINGS_H_
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
//Fills the StringsWidths array with the width of each individual string in the array using
|
||||||
|
//BFont::GetStringWidths(), then finds the longest string width in the array and returns that width.
|
||||||
|
//If a string_widths array is provided, it fills it in with the length of each string.
|
||||||
|
float GetStringsMaxWidth(const char** strings, int32 num_strings, const BFont* font,
|
||||||
|
float* string_widths = NULL);
|
||||||
|
|
||||||
|
//Gets the bounding box for one or more strings. If full_height is true, it increases the top and bottom to
|
||||||
|
//the font's ascent and descent. If round_up is true, it rounds each edge up to the next pixel to get the
|
||||||
|
//box that will actually be occupied onscreen.
|
||||||
|
BRect StringBoundingBox(const char* string, const BFont* font, bool full_height = false,
|
||||||
|
bool round_up = true);
|
||||||
|
BRect GetMaxStringBoundingBoxes(const char** strings, int32 num_strings, const BFont* font,
|
||||||
|
BRect* rects = NULL, bool full_height = false, bool round_up = true);
|
||||||
|
|
||||||
|
//Each of these functions either duplicates or concatenates the strings into a new char array allocated
|
||||||
|
//with new. The resulting char array must be delete[]'d when finished with it.
|
||||||
|
char *Strdup_new(const char *source);
|
||||||
|
char *Strcat_new(const char *string_1, const char *string_2);
|
||||||
|
char *Strcat_new(const char *string_1, const char *string_2, const char *string_3);
|
||||||
|
char *Strcat_new(const char *string_1, const char *string_2, const char *string_3, const char *string_4);
|
||||||
|
|
||||||
|
//Added because due to some error, the Be libraries on x86 don't export strtcopy. Len includes the null
|
||||||
|
//terminator.
|
||||||
|
char *Strtcpy(char *dst, const char *src, int len);
|
||||||
|
|
||||||
|
//Just some handy functions....
|
||||||
|
void StrToUpper(char* string);
|
||||||
|
void StrToLower(char* string);
|
||||||
|
|
||||||
|
#endif
|
32
src/prefs/sounds/Santa/PrefilledBitmap.cpp
Normal file
32
src/prefs/sounds/Santa/PrefilledBitmap.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
#include "PrefilledBitmap.h"
|
||||||
|
|
||||||
|
PrefilledBitmap::PrefilledBitmap(BRect bounds, color_space space, const void *data, int32 length,
|
||||||
|
bool acceptsViews, bool needsContiguousMemory)
|
||||||
|
: BBitmap(bounds, space, acceptsViews, needsContiguousMemory)
|
||||||
|
{
|
||||||
|
if(length == 0)
|
||||||
|
{
|
||||||
|
if(space == B_CMAP8)
|
||||||
|
length = ((int32(bounds.right-bounds.left+1)+3)&0xFFFFFFFC)*int32(bounds.bottom-bounds.top+1);
|
||||||
|
else if(space == B_RGB32)
|
||||||
|
length = int32(bounds.right-bounds.left+1)*int32(bounds.bottom-bounds.top+1)*3;
|
||||||
|
}
|
||||||
|
SetBits(data, length, 0, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PrefilledBitmap::~PrefilledBitmap()
|
||||||
|
{ }
|
42
src/prefs/sounds/Santa/PrefilledBitmap.h
Normal file
42
src/prefs/sounds/Santa/PrefilledBitmap.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
//*** DESCRIPTION ***
|
||||||
|
//Useful until be implements BBitmap::BBitmap(BRect bounds, color_space space, const void *data,
|
||||||
|
// bool acceptsViews, bool needsContiguousMemory)
|
||||||
|
//or something like it...
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _SGB_PREFILLED_BITMAP_H_
|
||||||
|
#define _SGB_PREFILLED_BITMAP_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <Bitmap.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLASS DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class PrefilledBitmap : public BBitmap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrefilledBitmap(BRect bounds, color_space space, const void *data, int32 length = 0,
|
||||||
|
bool acceptsViews = false, bool needsContiguousMemory = false);
|
||||||
|
//length can be automatically calculated for B_CMAP8 and B_RGB32
|
||||||
|
~PrefilledBitmap();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
41
src/prefs/sounds/Santa/ScrollViewCorner.cpp
Normal file
41
src/prefs/sounds/Santa/ScrollViewCorner.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
#include <ScrollBar.h>
|
||||||
|
#include "Colors.h"
|
||||||
|
#include "ScrollViewCorner.h"
|
||||||
|
|
||||||
|
|
||||||
|
ScrollViewCorner::ScrollViewCorner(float Left,float Top)
|
||||||
|
: BView(BRect(Left,Top,Left+B_V_SCROLL_BAR_WIDTH,Top+B_H_SCROLL_BAR_HEIGHT),NULL,B_FOLLOW_RIGHT |
|
||||||
|
B_FOLLOW_BOTTOM,B_WILL_DRAW)
|
||||||
|
{
|
||||||
|
SetHighColor(BeShadow);
|
||||||
|
SetViewColor(BeInactiveGrey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ScrollViewCorner::~ScrollViewCorner()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void ScrollViewCorner::Draw(BRect Update)
|
||||||
|
{
|
||||||
|
if(Update.bottom >= B_H_SCROLL_BAR_HEIGHT)
|
||||||
|
StrokeLine(BPoint(0.0,B_H_SCROLL_BAR_HEIGHT),BPoint(B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT));
|
||||||
|
if(Update.right >= B_V_SCROLL_BAR_WIDTH)
|
||||||
|
StrokeLine(BPoint(B_V_SCROLL_BAR_WIDTH,0.0),
|
||||||
|
BPoint(B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT-1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
46
src/prefs/sounds/Santa/ScrollViewCorner.h
Normal file
46
src/prefs/sounds/Santa/ScrollViewCorner.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
//*** DESCRIPTION ***
|
||||||
|
//If you have a BScrollView with horizontal and vertical sliders that isn't
|
||||||
|
//seated to the lower-right corner of a B_DOCUMENT_WINDOW, there's a "hole"
|
||||||
|
//between the sliders that needs to be filled. You can use this to fill it.
|
||||||
|
//In general, it looks best to set the ScrollViewCorner color to
|
||||||
|
//BeInactiveControlGrey if the vertical BScrollBar is inactive, and the color
|
||||||
|
//to BeBackgroundGrey if the vertical BScrollBar is active. Have a look at
|
||||||
|
//Demo3 of ColumnListView to see what I mean if this is unclear.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _SGB_SCROLL_VIEW_CORNER_H_
|
||||||
|
#define _SGB_SCROLL_VIEW_CORNER_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** SYSTEM HEADER FILES
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** CLASS DECLARATIONS
|
||||||
|
//******************************************************************************************************
|
||||||
|
class ScrollViewCorner : public BView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScrollViewCorner(float Left,float Top);
|
||||||
|
~ScrollViewCorner();
|
||||||
|
virtual void Draw(BRect Update);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
525
src/prefs/sounds/Santa/TextEntryAlert.cpp
Normal file
525
src/prefs/sounds/Santa/TextEntryAlert.cpp
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
//Name: TextEntryAlert.cpp
|
||||||
|
//Author: Brian Tietz
|
||||||
|
//Conventions:
|
||||||
|
// Global constants (declared with const) and #defines - begin with "c_" followed by lowercase
|
||||||
|
// words separated by underscores.
|
||||||
|
// (E.G., #define c_my_constant 5).
|
||||||
|
// (E.G., const int c_my_constant = 5;).
|
||||||
|
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int g_my_global;).
|
||||||
|
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
|
||||||
|
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
|
||||||
|
// associating them with a particular enumerated set.
|
||||||
|
// (E.G., typedef int MyTypedef;).
|
||||||
|
// (E.G., enum MyEnumConst {c_mec_one, c_mec_two};)
|
||||||
|
// Private member variables - begin with "m_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int m_my_member;).
|
||||||
|
// Public or friend-accessible member variables - all lowercase words separated by underscores.
|
||||||
|
// (E.G., int public_member;).
|
||||||
|
// Argument and local variables - begin with a lowercase letter followed by
|
||||||
|
// lowercase words separated by underscores. If the name is already taken by a public member
|
||||||
|
// variable, prefix with a_ or l_
|
||||||
|
// (E.G., int my_local; int a_my_arg, int l_my_local).
|
||||||
|
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
|
||||||
|
// separated by uppercase letters.
|
||||||
|
// (E.G., void MyFunction(void);).
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** System header files
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <string.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** Project header files
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include "TextEntryAlert.h"
|
||||||
|
#include "Colors.h"
|
||||||
|
#include "NewStrings.h"
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** Constants
|
||||||
|
//******************************************************************************************************
|
||||||
|
const float c_text_border_width = 2;
|
||||||
|
const float c_text_margin = 1;
|
||||||
|
const float c_item_spacing = 9;
|
||||||
|
const float c_non_inline_label_spacing = 5;
|
||||||
|
const float c_inline_label_spacing = 7;
|
||||||
|
const float c_usual_button_width = 74;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** BMessage what constants for internal use
|
||||||
|
//******************************************************************************************************
|
||||||
|
const uint32 c_button_pressed = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlert
|
||||||
|
//******************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
TextEntryAlert::TextEntryAlert(const char* title, const char* info_text, const char* initial_entry_text,
|
||||||
|
const char* button_0_label, const char* button_1_label, bool inline_label, float min_text_box_width,
|
||||||
|
int min_text_box_rows, button_width width_style, bool multi_line, const BRect* frame,
|
||||||
|
window_look look, window_feel feel, uint32 flags)
|
||||||
|
: BWindow((frame?*frame:BRect(50,50,60,60)),title,look,feel,flags)
|
||||||
|
{
|
||||||
|
//Get unadjusted sizes of the two text boxes
|
||||||
|
BRect info_text_box;
|
||||||
|
BRect entry_text_rect;
|
||||||
|
const char* strings[2] = {info_text?info_text:"",initial_entry_text?initial_entry_text:""};
|
||||||
|
escapement_delta zero_escapements[2] = {{0,0},{0,0}};
|
||||||
|
BRect result_rects[2];
|
||||||
|
be_plain_font->GetBoundingBoxesForStrings(strings,2,B_SCREEN_METRIC,zero_escapements,result_rects);
|
||||||
|
struct font_height plain_font_height;
|
||||||
|
be_plain_font->GetHeight(&plain_font_height);
|
||||||
|
info_text_box = result_rects[0];
|
||||||
|
info_text_box.bottom = info_text_box.top + ceil(plain_font_height.ascent) +
|
||||||
|
ceil(plain_font_height.descent);
|
||||||
|
entry_text_rect = result_rects[1];
|
||||||
|
entry_text_rect.bottom = entry_text_rect.top +
|
||||||
|
(ceil(plain_font_height.ascent)+ceil(plain_font_height.descent))*min_text_box_rows +
|
||||||
|
ceil(plain_font_height.leading)*(min_text_box_rows-1);
|
||||||
|
entry_text_rect.InsetBy(0-(c_text_margin+c_text_border_width),
|
||||||
|
0-(c_text_margin+c_text_border_width));
|
||||||
|
if(entry_text_rect.Width() < min_text_box_width)
|
||||||
|
entry_text_rect.right = entry_text_rect.left+min_text_box_width;
|
||||||
|
entry_text_rect.bottom -= 1; //To make it look like BTextControl
|
||||||
|
|
||||||
|
//Position and create label
|
||||||
|
m_label_view = NULL;
|
||||||
|
if(info_text)
|
||||||
|
{
|
||||||
|
info_text_box.OffsetTo(c_item_spacing,c_item_spacing);
|
||||||
|
if(inline_label)
|
||||||
|
info_text_box.OffsetBy(0,c_text_border_width+c_text_margin);
|
||||||
|
else
|
||||||
|
info_text_box.OffsetBy(c_non_inline_label_spacing,-2);
|
||||||
|
info_text_box.bottom += 2; //Compensate for offset used by BTextView
|
||||||
|
info_text_box.right += 1;
|
||||||
|
m_label_view = new BTextView(info_text_box,NULL,info_text_box.OffsetToCopy(0,0),
|
||||||
|
B_FOLLOW_LEFT|B_FOLLOW_TOP,B_WILL_DRAW);
|
||||||
|
m_label_view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
m_label_view->SetText(info_text);
|
||||||
|
m_label_view->MakeEditable(false);
|
||||||
|
m_label_view->MakeSelectable(false);
|
||||||
|
m_label_view->SetWordWrap(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info_text_box.Set(0,0,0,0);
|
||||||
|
inline_label = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create buttons
|
||||||
|
m_buttons[0] = NULL;
|
||||||
|
m_buttons[1] = NULL;
|
||||||
|
BMessage* message;
|
||||||
|
float button_0_width, button_1_width, buttons_height;
|
||||||
|
float max_buttons_width = 0;
|
||||||
|
if(button_0_label != NULL)
|
||||||
|
{
|
||||||
|
message = new BMessage(c_button_pressed);
|
||||||
|
message->AddInt32("which",0);
|
||||||
|
m_buttons[0] = new BButton(BRect(0,0,0,0),button_0_label,button_0_label,message,B_FOLLOW_LEFT|
|
||||||
|
B_FOLLOW_BOTTOM);
|
||||||
|
m_buttons[0]->GetPreferredSize(&button_0_width,&buttons_height);
|
||||||
|
max_buttons_width = button_0_width;
|
||||||
|
}
|
||||||
|
if(button_1_label != NULL)
|
||||||
|
{
|
||||||
|
message = new BMessage(c_button_pressed);
|
||||||
|
message->AddInt32("which",1);
|
||||||
|
m_buttons[1] = new BButton(BRect(0,0,0,0),button_1_label,button_1_label,message,B_FOLLOW_RIGHT|
|
||||||
|
B_FOLLOW_BOTTOM);
|
||||||
|
m_buttons[1]->GetPreferredSize(&button_1_width,&buttons_height);
|
||||||
|
if(max_buttons_width < button_1_width)
|
||||||
|
max_buttons_width = button_1_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Position and create text entry box
|
||||||
|
if(inline_label)
|
||||||
|
entry_text_rect.OffsetTo(info_text_box.right+c_inline_label_spacing,c_item_spacing);
|
||||||
|
else
|
||||||
|
entry_text_rect.OffsetTo(c_item_spacing,info_text_box.bottom+c_non_inline_label_spacing-4);
|
||||||
|
//-5 is to compensate for extra pixels that BeOS adds to the font height
|
||||||
|
if(frame != NULL)
|
||||||
|
{
|
||||||
|
if(entry_text_rect.left + min_text_box_width < frame->Width()-c_item_spacing)
|
||||||
|
entry_text_rect.right = frame->Width()+c_item_spacing;
|
||||||
|
else
|
||||||
|
entry_text_rect.right = entry_text_rect.left + min_text_box_width;
|
||||||
|
if(min_text_box_rows > 1)
|
||||||
|
{
|
||||||
|
float bottom = frame->Height()-c_item_spacing;
|
||||||
|
if(button_0_label != NULL || button_1_label != NULL)
|
||||||
|
bottom -= (buttons_height+c_item_spacing);
|
||||||
|
if(bottom > entry_text_rect.bottom)
|
||||||
|
entry_text_rect.bottom = bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_text_entry_view = new TextEntryAlertTextEntryView(entry_text_rect.InsetByCopy(c_text_border_width,
|
||||||
|
c_text_border_width),multi_line);
|
||||||
|
if(initial_entry_text)
|
||||||
|
m_text_entry_view->SetText(initial_entry_text);
|
||||||
|
|
||||||
|
//Position the buttons
|
||||||
|
if(m_buttons[0] != NULL && m_buttons[1] != NULL)
|
||||||
|
{
|
||||||
|
float button_left;
|
||||||
|
if(inline_label)
|
||||||
|
button_left = info_text_box.left;
|
||||||
|
else
|
||||||
|
button_left = entry_text_rect.left;
|
||||||
|
m_buttons[0]->MoveTo(button_left,entry_text_rect.bottom+c_item_spacing);
|
||||||
|
if(width_style == B_WIDTH_AS_USUAL)
|
||||||
|
m_buttons[0]->ResizeTo(c_usual_button_width,buttons_height);
|
||||||
|
else if(width_style == B_WIDTH_FROM_LABEL)
|
||||||
|
m_buttons[0]->ResizeTo(button_0_width,buttons_height);
|
||||||
|
else //if(width_style == B_WIDTH_FROM_WIDEST)
|
||||||
|
m_buttons[0]->ResizeTo(max_buttons_width,buttons_height);
|
||||||
|
}
|
||||||
|
BButton* right_button = NULL;
|
||||||
|
if(m_buttons[1] != NULL)
|
||||||
|
right_button = m_buttons[1];
|
||||||
|
else if(m_buttons[0] != NULL)
|
||||||
|
right_button = m_buttons[0];
|
||||||
|
if(right_button != NULL)
|
||||||
|
{
|
||||||
|
if(width_style == B_WIDTH_AS_USUAL)
|
||||||
|
right_button->ResizeTo(c_usual_button_width,buttons_height);
|
||||||
|
else if(width_style == B_WIDTH_FROM_LABEL)
|
||||||
|
right_button->ResizeTo(right_button==m_buttons[1]?button_1_width:button_0_width,
|
||||||
|
buttons_height);
|
||||||
|
else //(width_style == B_WIDTH_FROM_WIDEST)
|
||||||
|
right_button->ResizeTo(max_buttons_width,buttons_height);
|
||||||
|
right_button->MoveTo(entry_text_rect.right-right_button->Frame().Width()+1,
|
||||||
|
entry_text_rect.bottom+c_item_spacing);
|
||||||
|
if(!multi_line)
|
||||||
|
right_button->MakeDefault(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Resize the window
|
||||||
|
float height;
|
||||||
|
if(m_buttons[0])
|
||||||
|
height = m_buttons[0]->Frame().bottom+c_item_spacing-1;
|
||||||
|
else if(m_buttons[1])
|
||||||
|
height = m_buttons[1]->Frame().bottom+c_item_spacing-1;
|
||||||
|
else
|
||||||
|
height = entry_text_rect.bottom+c_item_spacing-1;
|
||||||
|
ResizeTo(entry_text_rect.right+c_item_spacing,height);
|
||||||
|
|
||||||
|
BRect bounds = Bounds();
|
||||||
|
if(frame == NULL)
|
||||||
|
{
|
||||||
|
BRect screen_frame = BScreen().Frame();
|
||||||
|
MoveTo(ceil((screen_frame.Width()-bounds.Width())/2),
|
||||||
|
ceil((screen_frame.Height()-bounds.Height()-19)/2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create the background view and add the children
|
||||||
|
BView* filler = new TextEntryAlertBackgroundView(bounds,entry_text_rect);
|
||||||
|
if(m_label_view)
|
||||||
|
filler->AddChild(m_label_view);
|
||||||
|
filler->AddChild(m_text_entry_view);
|
||||||
|
if(m_buttons[0])
|
||||||
|
filler->AddChild(m_buttons[0]);
|
||||||
|
if(m_buttons[1])
|
||||||
|
filler->AddChild(m_buttons[1]);
|
||||||
|
AddChild(filler);
|
||||||
|
|
||||||
|
//Complete the setup
|
||||||
|
m_invoker = NULL;
|
||||||
|
m_done_mutex = B_ERROR;
|
||||||
|
m_text_entry_buffer = NULL;
|
||||||
|
m_button_pressed = NULL;
|
||||||
|
float min_width = c_item_spacing;
|
||||||
|
if(m_buttons[0])
|
||||||
|
min_width += (m_buttons[0]->Frame().Width() + c_item_spacing);
|
||||||
|
if(m_buttons[1])
|
||||||
|
min_width += (m_buttons[0]->Frame().Width() + c_item_spacing);
|
||||||
|
if(min_width < 120)
|
||||||
|
min_width = 120;
|
||||||
|
float min_height = entry_text_rect.top;
|
||||||
|
min_height += (ceil(plain_font_height.ascent)+ceil(plain_font_height.descent));
|
||||||
|
min_height += ((c_text_margin+c_text_border_width)*2 + c_item_spacing);
|
||||||
|
if(m_buttons[0] || m_buttons[1])
|
||||||
|
min_height += (buttons_height + c_item_spacing);
|
||||||
|
min_width -= 2; //Need this for some reason
|
||||||
|
min_height -= 2;
|
||||||
|
SetSizeLimits(min_width,100000,min_height,100000);
|
||||||
|
AddCommonFilter(new BMessageFilter(B_KEY_DOWN,KeyDownFilterStatic));
|
||||||
|
m_shortcut[0] = 0;
|
||||||
|
m_shortcut[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TextEntryAlert::~TextEntryAlert()
|
||||||
|
{
|
||||||
|
if(m_invoker)
|
||||||
|
delete m_invoker;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 TextEntryAlert::Go(char* text_entry_buffer, int32 buffer_size)
|
||||||
|
{
|
||||||
|
int32 button_pressed = -1;
|
||||||
|
m_text_entry_buffer = text_entry_buffer;
|
||||||
|
m_button_pressed = &button_pressed;
|
||||||
|
m_buffer_size = buffer_size;
|
||||||
|
sem_id done_mutex = create_sem(0,"text_entry_alert_done");
|
||||||
|
m_done_mutex = done_mutex;
|
||||||
|
if(done_mutex < B_NO_ERROR)
|
||||||
|
{
|
||||||
|
Quit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
m_text_entry_view->MakeFocus(true);
|
||||||
|
m_text_entry_view->SetMaxBytes(buffer_size);
|
||||||
|
Show();
|
||||||
|
acquire_sem(done_mutex);
|
||||||
|
delete_sem(done_mutex);
|
||||||
|
return button_pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t TextEntryAlert::Go(BInvoker *invoker)
|
||||||
|
{
|
||||||
|
m_invoker = invoker;
|
||||||
|
m_text_entry_view->MakeFocus(true);
|
||||||
|
Show();
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlert::SetShortcut(int32 index, char shortcut)
|
||||||
|
{
|
||||||
|
m_shortcut[index] = shortcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char TextEntryAlert::Shortcut(int32 index) const
|
||||||
|
{
|
||||||
|
return m_shortcut[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filter_result TextEntryAlert::KeyDownFilterStatic(BMessage* message, BHandler** target,
|
||||||
|
BMessageFilter* filter)
|
||||||
|
{
|
||||||
|
return ((TextEntryAlert*)filter->Looper())->KeyDownFilter(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filter_result TextEntryAlert::KeyDownFilter(BMessage *message)
|
||||||
|
{
|
||||||
|
if(message->what == B_KEY_DOWN)
|
||||||
|
{
|
||||||
|
char byte;
|
||||||
|
if(message->FindInt8("byte",(int8*)&byte) == B_NO_ERROR && !message->HasInt8("byte",1))
|
||||||
|
{
|
||||||
|
char space = B_SPACE;
|
||||||
|
if(m_shortcut[0] && byte == m_shortcut[0])
|
||||||
|
{
|
||||||
|
m_buttons[0]->KeyDown(&space,1);
|
||||||
|
return B_SKIP_MESSAGE;
|
||||||
|
}
|
||||||
|
else if(m_shortcut[1] && byte == m_shortcut[1])
|
||||||
|
{
|
||||||
|
m_buttons[1]->KeyDown(&space,1);
|
||||||
|
return B_SKIP_MESSAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_DISPATCH_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BTextView* TextEntryAlert::LabelView(void) const
|
||||||
|
{
|
||||||
|
return m_label_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BTextView* TextEntryAlert::TextEntryView(void) const
|
||||||
|
{
|
||||||
|
return m_text_entry_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlert::SetTabAllowed(bool allow)
|
||||||
|
{
|
||||||
|
m_text_entry_view->SetTabAllowed(allow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TextEntryAlert::TabAllowed()
|
||||||
|
{
|
||||||
|
return m_text_entry_view->TabAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlert::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
if(message->what == c_button_pressed)
|
||||||
|
{
|
||||||
|
int32 which;
|
||||||
|
if(message->FindInt32("which",&which) == B_NO_ERROR)
|
||||||
|
{
|
||||||
|
const char* text = m_text_entry_view->Text();
|
||||||
|
if(text == NULL)
|
||||||
|
text = "";
|
||||||
|
if(m_done_mutex < B_NO_ERROR)
|
||||||
|
{
|
||||||
|
//Asynchronous version: add the necessary fields
|
||||||
|
BMessage* message = m_invoker->Message();
|
||||||
|
if(message && (message->AddInt32("which",which) == B_NO_ERROR ||
|
||||||
|
message->ReplaceInt32("which",which) == B_NO_ERROR) &&
|
||||||
|
(message->AddString("entry_text",text) == B_NO_ERROR ||
|
||||||
|
message->ReplaceString("entry_text",text) == B_NO_ERROR))
|
||||||
|
m_invoker->Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Synchronous version: set the result button and text buffer, then release the thread
|
||||||
|
//that created me
|
||||||
|
*m_button_pressed = which;
|
||||||
|
if(m_text_entry_buffer)
|
||||||
|
Strtcpy(m_text_entry_buffer,text,m_buffer_size);
|
||||||
|
release_sem(m_done_mutex);
|
||||||
|
m_done_mutex = B_ERROR;
|
||||||
|
}
|
||||||
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextEntryAlert::Quit()
|
||||||
|
{
|
||||||
|
//Release the mutex if I'm synchronous and I haven't released it yet
|
||||||
|
if(m_done_mutex >= B_NO_ERROR)
|
||||||
|
release_sem(m_done_mutex);
|
||||||
|
BWindow::Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlertBackgroundView
|
||||||
|
//******************************************************************************************************
|
||||||
|
TextEntryAlertBackgroundView::TextEntryAlertBackgroundView(BRect frame, BRect entry_text_rect)
|
||||||
|
: BView(frame,NULL,B_FOLLOW_ALL_SIDES,B_WILL_DRAW|B_FRAME_EVENTS)
|
||||||
|
{
|
||||||
|
m_entry_text_rect = entry_text_rect;
|
||||||
|
m_cached_bounds = Bounds();
|
||||||
|
rgb_color background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||||
|
m_dark_1_color = tint_color(background_color,B_DARKEN_1_TINT);
|
||||||
|
m_dark_2_color = tint_color(background_color,B_DARKEN_4_TINT);
|
||||||
|
SetViewColor(background_color);
|
||||||
|
SetDrawingMode(B_OP_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlertBackgroundView::Draw(BRect update_rect)
|
||||||
|
{
|
||||||
|
if(update_rect.Intersects(m_entry_text_rect))
|
||||||
|
{
|
||||||
|
SetHighColor(m_dark_1_color);
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.left,m_entry_text_rect.top),
|
||||||
|
BPoint(m_entry_text_rect.right,m_entry_text_rect.top));
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.left,m_entry_text_rect.top+1),
|
||||||
|
BPoint(m_entry_text_rect.left,m_entry_text_rect.bottom));
|
||||||
|
SetHighColor(White);
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.right,m_entry_text_rect.top+1),
|
||||||
|
BPoint(m_entry_text_rect.right,m_entry_text_rect.bottom-1));
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.bottom),
|
||||||
|
BPoint(m_entry_text_rect.right,m_entry_text_rect.bottom));
|
||||||
|
SetHighColor(m_dark_2_color);
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.top+1),
|
||||||
|
BPoint(m_entry_text_rect.right-1,m_entry_text_rect.top+1));
|
||||||
|
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.top+2),
|
||||||
|
BPoint(m_entry_text_rect.left+1,m_entry_text_rect.bottom-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlertBackgroundView::FrameResized(float width, float heigh)
|
||||||
|
{
|
||||||
|
BRect new_bounds = Bounds();
|
||||||
|
float width_delta = new_bounds.right - m_cached_bounds.right;
|
||||||
|
float height_delta = new_bounds.bottom - m_cached_bounds.bottom;
|
||||||
|
BRect new_entry_text_rect = m_entry_text_rect;
|
||||||
|
new_entry_text_rect.right += width_delta;
|
||||||
|
new_entry_text_rect.bottom += height_delta;
|
||||||
|
|
||||||
|
float right_min = m_entry_text_rect.right;
|
||||||
|
if(right_min > new_entry_text_rect.right)
|
||||||
|
right_min = new_entry_text_rect.right;
|
||||||
|
float right_max = m_entry_text_rect.right;
|
||||||
|
if(right_max < new_entry_text_rect.right)
|
||||||
|
right_max = new_entry_text_rect.right;
|
||||||
|
float bottom_min = m_entry_text_rect.bottom;
|
||||||
|
if(bottom_min > new_entry_text_rect.bottom)
|
||||||
|
bottom_min = new_entry_text_rect.bottom;
|
||||||
|
float bottom_max = m_entry_text_rect.bottom;
|
||||||
|
if(bottom_max < new_entry_text_rect.bottom)
|
||||||
|
bottom_max = new_entry_text_rect.bottom;
|
||||||
|
|
||||||
|
if(new_entry_text_rect.right != m_entry_text_rect.right)
|
||||||
|
Invalidate(BRect(right_min-1,new_entry_text_rect.top,right_max,bottom_max));
|
||||||
|
if(new_entry_text_rect.bottom != m_entry_text_rect.bottom)
|
||||||
|
Invalidate(BRect(new_entry_text_rect.left,bottom_min-1,right_max,bottom_max));
|
||||||
|
|
||||||
|
m_entry_text_rect = new_entry_text_rect;
|
||||||
|
m_cached_bounds = new_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlertTextEntryView
|
||||||
|
//******************************************************************************************************
|
||||||
|
TextEntryAlertTextEntryView::TextEntryAlertTextEntryView(BRect frame, bool multi_line)
|
||||||
|
: BTextView(frame,NULL,frame.OffsetToCopy(0,0).InsetByCopy(c_text_margin,c_text_margin),
|
||||||
|
multi_line?B_FOLLOW_ALL_SIDES:B_FOLLOW_LEFT_RIGHT,B_WILL_DRAW|B_NAVIGABLE)
|
||||||
|
{
|
||||||
|
m_tab_allowed = false;
|
||||||
|
m_multi_line = multi_line;
|
||||||
|
SetViewColor(White);
|
||||||
|
SetWordWrap(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlertTextEntryView::SetTabAllowed(bool allow)
|
||||||
|
{
|
||||||
|
m_tab_allowed = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlertTextEntryView::KeyDown(const char* bytes, int32 num_bytes)
|
||||||
|
{
|
||||||
|
if(num_bytes == 1 && (bytes[0] == B_TAB && (!m_tab_allowed)) || (bytes[0] == B_ENTER && (!m_multi_line)))
|
||||||
|
{
|
||||||
|
BView::KeyDown(bytes,num_bytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BTextView::KeyDown(bytes,num_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TextEntryAlertTextEntryView::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BTextView::AttachedToWindow();
|
||||||
|
const char* text = Text();
|
||||||
|
if(text)
|
||||||
|
{
|
||||||
|
int32 length = strlen(text);
|
||||||
|
Select(length,length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
165
src/prefs/sounds/Santa/TextEntryAlert.h
Normal file
165
src/prefs/sounds/Santa/TextEntryAlert.h
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
//Name: TextEntryAlert.h
|
||||||
|
//Author: Brian Tietz
|
||||||
|
//Conventions:
|
||||||
|
// Global constants (declared with const) and #defines - begin with "c_" followed by lowercase
|
||||||
|
// words separated by underscores.
|
||||||
|
// (E.G., #define c_my_constant 5).
|
||||||
|
// (E.G., const int c_my_constant = 5;).
|
||||||
|
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int g_my_global;).
|
||||||
|
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
|
||||||
|
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
|
||||||
|
// associating them with a particular enumerated set.
|
||||||
|
// (E.G., typedef int MyTypedef;).
|
||||||
|
// (E.G., enum MyEnumConst {c_mec_one, c_mec_two};)
|
||||||
|
// Private member variables - begin with "m_" followed by lowercase words separated by underscores.
|
||||||
|
// (E.G., int m_my_member;).
|
||||||
|
// Public or friend-accessible member variables - all lowercase words separated by underscores.
|
||||||
|
// (E.G., int public_member;).
|
||||||
|
// Argument and local variables - begin with a lowercase letter followed by
|
||||||
|
// lowercase words separated by underscores. If the name is already taken by a public member
|
||||||
|
// variable, prefix with a_ or l_
|
||||||
|
// (E.G., int my_local; int a_my_arg, int l_my_local).
|
||||||
|
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
|
||||||
|
// separated by uppercase letters.
|
||||||
|
// (E.G., void MyFunction(void);).
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _TEXT_ENTRY_ALERT_H_
|
||||||
|
#define _TEXT_ENTRY_ALERT_H_
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** System header files
|
||||||
|
//******************************************************************************************************
|
||||||
|
#include <Window.h>
|
||||||
|
#include <TextView.h>
|
||||||
|
#include <MessageFilter.h>
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** Forward name declarations
|
||||||
|
//******************************************************************************************************
|
||||||
|
class TextEntryAlertTextEntryView;
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlert
|
||||||
|
//******************************************************************************************************
|
||||||
|
class TextEntryAlert : public BWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextEntryAlert(const char* title, const char* info_text, const char* initial_entry_text,
|
||||||
|
const char* button_0_label, const char* button_1_label = NULL,
|
||||||
|
bool inline_label = true, float min_text_box_width = 120, int min_text_box_rows = 1,
|
||||||
|
button_width width_style = B_WIDTH_AS_USUAL, bool multi_line = false,
|
||||||
|
const BRect* frame = NULL, window_look look = B_MODAL_WINDOW_LOOK,
|
||||||
|
window_feel feel = B_MODAL_APP_WINDOW_FEEL,
|
||||||
|
uint32 flags = B_NOT_RESIZABLE|B_ASYNCHRONOUS_CONTROLS);
|
||||||
|
//The title is not displayed unless you use a window_look other than the default. info_text
|
||||||
|
//is the label applied to the text entry box. If inline_label is true, then the label is
|
||||||
|
//placed to the left of the text entry box, otherwise it is placed above it. If a frame is
|
||||||
|
//not specified, the TextEntryAlert will be auto-sized and auto-positioned to accommodate
|
||||||
|
//the text. The minimum text entry box size can be specified using min_text_box_width and
|
||||||
|
//text_box_rows. Multi-line specifies whether the user can hit return and enter multiple
|
||||||
|
//lines of text, regardless of the height of the text box.
|
||||||
|
~TextEntryAlert();
|
||||||
|
|
||||||
|
int32 Go(char* text_entry_buffer, int32 buffer_size);
|
||||||
|
//Synchronous version: The function doesn't return until the user has clicked a button and
|
||||||
|
//the panel has been removed from the screen. The value it returns is the index of
|
||||||
|
//the clicked button (0 or 1, left-to-right). The user-entered (or unchanged) text is
|
||||||
|
//stored in text_entry_buffer. The TextEntryAlert is deleted before it returns, and should
|
||||||
|
//be considered invalid after Go is called. If the TextEntryAlert is sent a
|
||||||
|
//B_QUIT_REQUESTED message while the panel is still on-screen, it returns -1.
|
||||||
|
status_t Go(BInvoker* invoker);
|
||||||
|
//Asynchronous version: The function returns immediately (with B_OK) and the button index is
|
||||||
|
//delivered as the int32 "which" field of the BMessage that's sent to the BInvoker's target,
|
||||||
|
//and the text message is delivered as the string "entry_text" field of the BMessage. The
|
||||||
|
//TextEntryBox will take posession of the BInvoker and delete it when finished. The
|
||||||
|
//TextEntryAlert is deleted when the user hits any of the buttons, and should be considered
|
||||||
|
//invalid after Go is called. If the TextEntryAlert is sent a B_QUIT_REQUESTED message
|
||||||
|
//while the panel is still on-screen, it suppresses sending of the message.
|
||||||
|
|
||||||
|
void SetShortcut(int32 index, char shortcut);
|
||||||
|
char Shortcut(int32 index) const;
|
||||||
|
//These functions set and return the shortcut character that's mapped to the button at
|
||||||
|
//index. A given button can have only one shortcut except for the rightmost button, which,
|
||||||
|
//in addition to the shortcut that you give it here, is always mapped to B_ENTER. If you
|
||||||
|
//create a "Cancel" button, you should give it a shortcut of B_ESCAPE. If multi_line was
|
||||||
|
//specified as true in the TextEntryAlert constructor, no shortcuts are allowed, including
|
||||||
|
//the built-in B_ENTER shortcut on the rightmost button.
|
||||||
|
|
||||||
|
void SetTabAllowed(bool allow);
|
||||||
|
//By default, tab is not allowed, being used for navigation instead. Set this to true to
|
||||||
|
//allow the user to actually enter a tab character in the text entry box.
|
||||||
|
bool TabAllowed();
|
||||||
|
|
||||||
|
BTextView* LabelView(void) const;
|
||||||
|
BTextView* TextEntryView(void) const;
|
||||||
|
//Returns a pointer to the BTextView object that contains the textual information or the
|
||||||
|
//user-editable text that's displayed in the panel, respectively. You can fiddle with these
|
||||||
|
//objects but you mustn't delete them.
|
||||||
|
|
||||||
|
//BWindow overrides
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual void Quit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BTextView* m_label_view;
|
||||||
|
TextEntryAlertTextEntryView* m_text_entry_view;
|
||||||
|
static filter_result KeyDownFilterStatic(BMessage* message, BHandler** target,
|
||||||
|
BMessageFilter* filter);
|
||||||
|
filter_result KeyDownFilter(BMessage* message);
|
||||||
|
BButton* m_buttons[2];
|
||||||
|
char m_shortcut[2];
|
||||||
|
|
||||||
|
//For the synchronous version (pointers point to data areas owned by thread that called Go)
|
||||||
|
sem_id m_done_mutex; //Mutex to release when the user hits a button or the window closes
|
||||||
|
char* m_text_entry_buffer; //Buffer to store the user-entered text when the user hits a button
|
||||||
|
int32* m_button_pressed; //Place to store the button index that the user hit
|
||||||
|
int32 m_buffer_size;
|
||||||
|
|
||||||
|
//For the asynchronous version
|
||||||
|
BInvoker *m_invoker; //I own this object and will delete it when done.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlertBackgroundView
|
||||||
|
//******************************************************************************************************
|
||||||
|
class TextEntryAlertBackgroundView : public BView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextEntryAlertBackgroundView(BRect frame, BRect entry_text_rect);
|
||||||
|
virtual void Draw(BRect update_rect);
|
||||||
|
virtual void FrameResized(float width, float heigh);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BRect m_entry_text_rect;
|
||||||
|
BRect m_cached_bounds;
|
||||||
|
rgb_color m_dark_1_color;
|
||||||
|
rgb_color m_dark_2_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************************************
|
||||||
|
//**** TextEntryAlertTextEntryView
|
||||||
|
//******************************************************************************************************
|
||||||
|
class TextEntryAlertTextEntryView : public BTextView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextEntryAlertTextEntryView(BRect frame, bool multi_line);
|
||||||
|
|
||||||
|
void SetTabAllowed(bool allow);
|
||||||
|
inline bool TabAllowed() {return m_tab_allowed;}
|
||||||
|
virtual void KeyDown(const char* bytes, int32 num_bytes);
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_tab_allowed;
|
||||||
|
bool m_multi_line;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_TEXT_ENTRY_ALERT_H_
|
20
src/prefs/sounds/Utils/BitmapView.h
Normal file
20
src/prefs/sounds/Utils/BitmapView.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __HBITMAPVIEW_H__
|
||||||
|
#define __HBITMAPVIEW_H__
|
||||||
|
|
||||||
|
#include <View.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
|
||||||
|
class BitmapView :public BView {
|
||||||
|
public:
|
||||||
|
BitmapView(BRect rect,
|
||||||
|
const char* name,
|
||||||
|
uint32 resizing_mode,
|
||||||
|
BBitmap *bitmap,
|
||||||
|
rgb_color bgcolor = ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
virtual ~BitmapView();
|
||||||
|
virtual void Draw(BRect rect);
|
||||||
|
void SetBitmap(BBitmap *bitmap);
|
||||||
|
protected:
|
||||||
|
BBitmap *fBitmap;
|
||||||
|
};
|
||||||
|
#endif
|
118
src/prefs/sounds/Utils/CTextView.cpp
Normal file
118
src/prefs/sounds/Utils/CTextView.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
|
||||||
|
#include "CTextView.h"
|
||||||
|
|
||||||
|
CTextView::CTextView(BRect a_frame,const char* a_name,int32 a_resize_mode,int32 a_flags)
|
||||||
|
: BTextView(a_frame, a_name, BRect(4.0,4.0,a_frame.right-a_frame.left-4.0,a_frame.bottom-a_frame.top-4.0),
|
||||||
|
a_resize_mode,a_flags)
|
||||||
|
{
|
||||||
|
ResetTextRect();
|
||||||
|
m_modified = false;
|
||||||
|
m_modified_disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CTextView::~CTextView()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::DetachedFromWindow()
|
||||||
|
{
|
||||||
|
//This is sort of what the destructor should do, but... Derived class's destructors get called before
|
||||||
|
//CTextView's destructor so StoreChange won't get to the derived class's version of it.
|
||||||
|
if(m_modified)
|
||||||
|
{
|
||||||
|
StoreChange();
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::FrameResized(float a_width, float a_height)
|
||||||
|
{
|
||||||
|
ResetTextRect();
|
||||||
|
BTextView::FrameResized(a_width,a_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::MakeFocus(bool a_focused)
|
||||||
|
{
|
||||||
|
BTextView::MakeFocus(a_focused);
|
||||||
|
if(!a_focused && m_modified)
|
||||||
|
{
|
||||||
|
StoreChange();
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::InsertText(const char *a_text, int32 a_length, int32 a_offset,
|
||||||
|
const text_run_array *a_runs)
|
||||||
|
{
|
||||||
|
BTextView::InsertText(a_text, a_length, a_offset, a_runs);
|
||||||
|
if(!m_modified_disabled)
|
||||||
|
Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::Modified()
|
||||||
|
{
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::SetText(const char *text, int32 length, const text_run_array *runs)
|
||||||
|
{
|
||||||
|
m_modified_disabled = true;
|
||||||
|
BTextView::SetText(text,length,runs);
|
||||||
|
m_modified_disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::SetText(const char *text, const text_run_array *runs)
|
||||||
|
{
|
||||||
|
m_modified_disabled = true;
|
||||||
|
BTextView::SetText(text,runs);
|
||||||
|
m_modified_disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::SetText(BFile *file, int32 offset, int32 length, const text_run_array *runs)
|
||||||
|
{
|
||||||
|
m_modified_disabled = true;
|
||||||
|
BTextView::SetText(file,offset,length,runs);
|
||||||
|
m_modified_disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::StoreChange()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void CTextView::ResetTextRect()
|
||||||
|
{
|
||||||
|
BRect textRect = Bounds();
|
||||||
|
textRect.left = 4.0;
|
||||||
|
textRect.top = 4.0;
|
||||||
|
textRect.right -= 4.0;
|
||||||
|
textRect.bottom -= 4.0;
|
||||||
|
SetTextRect(textRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CTextView::HasBeenModified()
|
||||||
|
{
|
||||||
|
return m_modified;
|
||||||
|
}
|
58
src/prefs/sounds/Utils/CTextView.h
Normal file
58
src/prefs/sounds/Utils/CTextView.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//*** LICENSE ***
|
||||||
|
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
|
||||||
|
//being made publicly available and free to use in freeware and shareware products with a price under $25
|
||||||
|
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
|
||||||
|
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
|
||||||
|
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
|
||||||
|
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
|
||||||
|
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
|
||||||
|
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
|
||||||
|
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
|
||||||
|
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
|
||||||
|
//ColumnListView source, including modified versions, but keep this documentation and license with it.
|
||||||
|
|
||||||
|
//*** DESCRIPTION ***
|
||||||
|
//CTextView class
|
||||||
|
|
||||||
|
//Extends BTextView functionality somewhat. Automates setting up the TextRect and updating it during resizing
|
||||||
|
//so that re-wrapping is live. Also provides a StoreChanges hook function that is called when the CTextView
|
||||||
|
//loses focus or is removed from the window or destroyed. This is useful if the view is of an object that can
|
||||||
|
//exist without the view, so that this more persistent object can be kept up-to-date when the text is modified,
|
||||||
|
//without having to update the other object every time a character is entered.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _CTEXT_VIEW_H_
|
||||||
|
#define _CTEXT_VIEW_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <TextView.h>
|
||||||
|
|
||||||
|
|
||||||
|
class CTextView : public BTextView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTextView(BRect a_frame,const char* a_name,int32 a_resize_mode,int32 a_flags);
|
||||||
|
virtual ~CTextView();
|
||||||
|
|
||||||
|
//BTextView overrides
|
||||||
|
virtual void DetachedFromWindow();
|
||||||
|
virtual void FrameResized(float a_width, float a_height);
|
||||||
|
virtual void MakeFocus(bool a_focused);
|
||||||
|
void SetText(const char *text, int32 length, const text_run_array *runs = NULL);
|
||||||
|
void SetText(const char *text, const text_run_array *runs = NULL);
|
||||||
|
void SetText(BFile *file, int32 offset, int32 length, const text_run_array *runs = NULL);
|
||||||
|
virtual void StoreChange();
|
||||||
|
virtual void Modified();
|
||||||
|
bool HasBeenModified();
|
||||||
|
void ResetTextRect();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void InsertText(const char *a_text, int32 a_length, int32 a_offset, const text_run_array *a_runs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_modified;
|
||||||
|
bool m_modified_disabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
363
src/prefs/sounds/Utils/HAboutWindow.cpp
Normal file
363
src/prefs/sounds/Utils/HAboutWindow.cpp
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
#include "HAboutWindow.h"
|
||||||
|
#include <Screen.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Resources.h>
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <ClassInfo.h>
|
||||||
|
|
||||||
|
#include "BitmapView.h"
|
||||||
|
#include "CTextView.h"
|
||||||
|
#include "URLView.h"
|
||||||
|
|
||||||
|
#define ICON_OFFSET 60
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HAboutWindow::HAboutWindow(const char* app_name,
|
||||||
|
const char* built_date,
|
||||||
|
const char* comment,
|
||||||
|
const char* url,
|
||||||
|
const char* email)
|
||||||
|
:BWindow(BRect(-1,-1,-1,-1),
|
||||||
|
"",
|
||||||
|
B_FLOATING_WINDOW_LOOK,
|
||||||
|
B_MODAL_APP_WINDOW_FEEL,
|
||||||
|
B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
|
||||||
|
{
|
||||||
|
BString window_title = "About ";
|
||||||
|
window_title << app_name;
|
||||||
|
SetTitle(window_title.String());
|
||||||
|
this->AddShortcut('W',0,new BMessage(B_QUIT_REQUESTED));
|
||||||
|
CalcFontHeights();
|
||||||
|
/********** Get max width **********/
|
||||||
|
BString build = "Built date: ";
|
||||||
|
build << built_date;
|
||||||
|
|
||||||
|
float max_width = ICON_OFFSET;
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(10);
|
||||||
|
|
||||||
|
max_width = font.StringWidth(build.String());
|
||||||
|
BFont boldfont(be_bold_font);
|
||||||
|
boldfont.SetSize(14);
|
||||||
|
if(max_width < boldfont.StringWidth(app_name) )
|
||||||
|
max_width = boldfont.StringWidth(app_name);
|
||||||
|
|
||||||
|
/**************************************/
|
||||||
|
InitGUI();
|
||||||
|
LoadIcon();
|
||||||
|
SetComment(comment);
|
||||||
|
int32 lines = fComment->CountLines();
|
||||||
|
float result = 0;
|
||||||
|
for(register int32 i = 0; i < lines ; i++)
|
||||||
|
{
|
||||||
|
float tmp = fComment->LineWidth(i);
|
||||||
|
if(tmp > result )
|
||||||
|
result = tmp;
|
||||||
|
}
|
||||||
|
if(max_width < result)
|
||||||
|
max_width = result;
|
||||||
|
if(max_width < font.StringWidth(url))
|
||||||
|
max_width = font.StringWidth(url);
|
||||||
|
float width = max_width + ICON_OFFSET + 20;
|
||||||
|
|
||||||
|
int32 isUrlMail = 0;
|
||||||
|
if(url)
|
||||||
|
isUrlMail++;
|
||||||
|
if(email)
|
||||||
|
isUrlMail++;
|
||||||
|
|
||||||
|
float height = fPlainHeight* (2+lines + isUrlMail) + fBoldHeight + 35;
|
||||||
|
|
||||||
|
ResizeTo(width,height);
|
||||||
|
BRect screen_limits = BScreen().Frame();
|
||||||
|
MoveTo(screen_limits.left+floor((screen_limits.Width()-width)/2),
|
||||||
|
screen_limits.top+floor((screen_limits.Height()-height)/2));
|
||||||
|
|
||||||
|
/************** url view ************/
|
||||||
|
float start_pos = fComment->Frame().bottom;
|
||||||
|
|
||||||
|
BRect url_rect(ICON_OFFSET,start_pos,width,start_pos+fPlainHeight);
|
||||||
|
|
||||||
|
HAboutView *bgview = cast_as(FindView("aboutview"),HAboutView);
|
||||||
|
|
||||||
|
if(url)
|
||||||
|
{
|
||||||
|
BString url_string = url;
|
||||||
|
|
||||||
|
int32 index = url_string.FindFirst("http:");
|
||||||
|
if(index != B_ERROR)
|
||||||
|
{
|
||||||
|
url_string = &url[index];
|
||||||
|
}
|
||||||
|
//(new BAlert("",url_string.String(),"OK"))->Go();
|
||||||
|
URLView *urlView = new URLView(url_rect,"url",url,url_string.String());
|
||||||
|
urlView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
urlView->SetFont(&font);
|
||||||
|
bgview->AddChild(urlView);
|
||||||
|
|
||||||
|
url_rect.OffsetBy(0,fPlainHeight+3);
|
||||||
|
}
|
||||||
|
/************** mail view ****************/
|
||||||
|
if(email)
|
||||||
|
{
|
||||||
|
BString mail = email;
|
||||||
|
|
||||||
|
int32 index = mail.FindLast(" ");
|
||||||
|
if(index != B_ERROR)
|
||||||
|
{
|
||||||
|
mail = &email[index+1];
|
||||||
|
}else{
|
||||||
|
index = mail.FindFirst(":");
|
||||||
|
if(index != B_ERROR)
|
||||||
|
{
|
||||||
|
mail = &email[index+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BString mail_uri = "mailto:";
|
||||||
|
mail_uri << mail;
|
||||||
|
|
||||||
|
URLView *mailView = new URLView(url_rect,"email",email,mail_uri.String());
|
||||||
|
mailView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
mailView->SetFont(&font);
|
||||||
|
bgview->AddChild(mailView);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAppName(app_name);
|
||||||
|
SetBuiltDate(built_date);
|
||||||
|
|
||||||
|
LoadVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* InitGUI
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::InitGUI()
|
||||||
|
{
|
||||||
|
BRect bitmapRect(0,0,31,31);
|
||||||
|
bitmapRect.OffsetBy(20,5);
|
||||||
|
|
||||||
|
fAboutView = new HAboutView(Bounds());
|
||||||
|
BRect rect(ICON_OFFSET,15,ICON_OFFSET,15+fBoldHeight);
|
||||||
|
fAppName = new BStringView(rect,"name","",B_FOLLOW_NONE);
|
||||||
|
fAboutView->AddChild(fAppName);
|
||||||
|
rect.OffsetBy(0,fBoldHeight);
|
||||||
|
rect.bottom = rect.top + fPlainHeight;
|
||||||
|
fVersion = new BStringView(rect,"ver","",B_FOLLOW_NONE);
|
||||||
|
fAboutView->AddChild(fVersion);
|
||||||
|
rect.OffsetBy(0,fPlainHeight);
|
||||||
|
fBuiltDate = new BStringView(rect,"build","",B_FOLLOW_NONE);
|
||||||
|
fAboutView->AddChild(fBuiltDate);
|
||||||
|
rect.OffsetBy(0,fPlainHeight);
|
||||||
|
fComment = new CTextView(rect,"comment",B_FOLLOW_NONE,B_WILL_DRAW);
|
||||||
|
fAboutView->AddChild(fComment);
|
||||||
|
AddChild(fAboutView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Load icon from application resource
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::LoadIcon()
|
||||||
|
{
|
||||||
|
//Extract title bitmap
|
||||||
|
BBitmap *icon = new BBitmap(BRect(0,0,31,31),B_COLOR_8_BIT);
|
||||||
|
app_info info;
|
||||||
|
BPath path;
|
||||||
|
be_app->GetAppInfo(&info);
|
||||||
|
BNodeInfo::GetTrackerIcon(&info.ref,icon,B_LARGE_ICON);
|
||||||
|
fAboutView->SetBitmap(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Load versino from application resource.
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::LoadVersion()
|
||||||
|
{
|
||||||
|
//Extract version resource
|
||||||
|
BString version = "";
|
||||||
|
BResources* app_version_resource = BApplication::AppResources();
|
||||||
|
if(app_version_resource)
|
||||||
|
{
|
||||||
|
size_t resource_size;
|
||||||
|
const char* app_version_data = (const char*)app_version_resource->LoadResource('APPV',
|
||||||
|
"BEOS:APP_VERSION",&resource_size);
|
||||||
|
if(app_version_data && resource_size > 20)
|
||||||
|
{
|
||||||
|
const char* status[] = {"Development","Alpha","Beta","Gamma",
|
||||||
|
"Golden master","Final"};
|
||||||
|
app_version_info *info = (app_version_info*)app_version_data;
|
||||||
|
uint32 v1 = info->v1;
|
||||||
|
uint32 v2 = info->v2;
|
||||||
|
uint32 v3 = info->v3;
|
||||||
|
version << v1 << "." << v2 << "." << v3;
|
||||||
|
if(info->status != 5)
|
||||||
|
version << " " <<status[info->status];
|
||||||
|
if(info->rel != 0)
|
||||||
|
version << " Release " << info->rel;
|
||||||
|
SetVersion(version.String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set applicaiton name
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::SetAppName(const char* name)
|
||||||
|
{
|
||||||
|
BFont font(be_bold_font);
|
||||||
|
font.SetSize(14);
|
||||||
|
|
||||||
|
BRect rect(0,0,font.StringWidth(name),fBoldHeight);
|
||||||
|
BRect old_rect = fAppName->Bounds();
|
||||||
|
fAppName->SetFont(&font);
|
||||||
|
fAppName->ResizeBy(rect.Width()-old_rect.Width(),rect.Height()-old_rect.Height());
|
||||||
|
fAppName->SetText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set application built date.
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::SetBuiltDate(const char* date)
|
||||||
|
{
|
||||||
|
BString title="Built date: ";
|
||||||
|
title << date;
|
||||||
|
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(10);
|
||||||
|
|
||||||
|
BRect rect(0,0,font.StringWidth(title.String()),fPlainHeight);
|
||||||
|
BRect old_rect = fBuiltDate->Bounds();
|
||||||
|
fBuiltDate->SetFont(&font);
|
||||||
|
fBuiltDate->ResizeBy(rect.Width()-old_rect.Width(),rect.Height()-old_rect.Height());
|
||||||
|
fBuiltDate->SetText(title.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set comments
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::SetComment(const char* text)
|
||||||
|
{
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(10);
|
||||||
|
|
||||||
|
fComment->SetFont(&font);
|
||||||
|
fComment->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
fComment->MakeEditable(false);
|
||||||
|
fComment->MakeFocus(false);
|
||||||
|
fComment->MakeSelectable(false);
|
||||||
|
fComment->SetWordWrap(false);
|
||||||
|
fComment->SetText(text);
|
||||||
|
int32 lines = fComment->CountLines();
|
||||||
|
BRect rect(0,0,font.StringWidth(text)+4,fPlainHeight*lines+4);
|
||||||
|
BRect old_rect = fComment->Bounds();
|
||||||
|
fComment->ResizeBy(rect.Width()-old_rect.Width(),rect.Height()-old_rect.Height());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set version info
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::SetVersion(const char* version)
|
||||||
|
{
|
||||||
|
BString title="Version ";
|
||||||
|
title << version;
|
||||||
|
|
||||||
|
BFont font(be_plain_font);
|
||||||
|
font.SetSize(10);
|
||||||
|
|
||||||
|
BRect rect(0,0,font.StringWidth(title.String()),fPlainHeight);
|
||||||
|
BRect old_rect = fVersion->Bounds();
|
||||||
|
fVersion->SetFont(&font);
|
||||||
|
fVersion->ResizeBy(rect.Width()-old_rect.Width(),rect.Height()-old_rect.Height());
|
||||||
|
fVersion->SetText(title.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Calc font height
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutWindow::CalcFontHeights()
|
||||||
|
{
|
||||||
|
BFont plainfont(be_plain_font);
|
||||||
|
plainfont.SetSize(10);
|
||||||
|
|
||||||
|
font_height FontAttributes;
|
||||||
|
plainfont.GetHeight(&FontAttributes);
|
||||||
|
fPlainHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
|
||||||
|
|
||||||
|
BFont boldfont(be_bold_font);
|
||||||
|
boldfont.SetSize(14);
|
||||||
|
|
||||||
|
boldfont.GetHeight(&FontAttributes);
|
||||||
|
fBoldHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* HAboutView
|
||||||
|
****************************************************************************/
|
||||||
|
const float kBorderWidth = 32.0f;
|
||||||
|
const rgb_color kDarkBorderColor = {184, 184, 184, 255};
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor
|
||||||
|
***********************************************************/
|
||||||
|
HAboutView::HAboutView(BRect rect,BBitmap *icon)
|
||||||
|
:BView(rect,"aboutview",B_FOLLOW_ALL,B_WILL_DRAW)
|
||||||
|
{
|
||||||
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
fIcon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor
|
||||||
|
***********************************************************/
|
||||||
|
HAboutView::~HAboutView()
|
||||||
|
{
|
||||||
|
delete fIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Draw
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutView::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
BRect drawBounds(Bounds());
|
||||||
|
drawBounds.right = kBorderWidth;
|
||||||
|
SetHighColor(kDarkBorderColor);
|
||||||
|
FillRect(drawBounds);
|
||||||
|
|
||||||
|
if(fIcon != NULL)
|
||||||
|
{
|
||||||
|
BRect bitmapRect(0,0,31,31);
|
||||||
|
bitmapRect.OffsetBy(20,5);
|
||||||
|
drawing_mode mode = DrawingMode();
|
||||||
|
SetDrawingMode(B_OP_ALPHA);
|
||||||
|
DrawBitmap(fIcon,bitmapRect);
|
||||||
|
SetDrawingMode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set view bitmap
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
HAboutView::SetBitmap(BBitmap *bitmap)
|
||||||
|
{
|
||||||
|
delete fIcon;
|
||||||
|
fIcon = bitmap;
|
||||||
|
}
|
66
src/prefs/sounds/Utils/HAboutWindow.h
Normal file
66
src/prefs/sounds/Utils/HAboutWindow.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef __ABOUTWINDOW_H__
|
||||||
|
#define __ABOUTWINDOW_H__
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
#include <View.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
|
||||||
|
class CTextView;
|
||||||
|
class BitmapView;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32 v1;
|
||||||
|
uint32 v2;
|
||||||
|
uint32 v3;
|
||||||
|
uint32 status;
|
||||||
|
uint32 rel;
|
||||||
|
} app_version_info;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* HAboutView
|
||||||
|
**********************************************************************/
|
||||||
|
class HAboutView : public BView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HAboutView(BRect rect,BBitmap *icon = NULL);
|
||||||
|
virtual ~HAboutView();
|
||||||
|
void SetBitmap(BBitmap* bitmap);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void Draw(BRect);
|
||||||
|
private:
|
||||||
|
BBitmap* fIcon;
|
||||||
|
};
|
||||||
|
/**********************************************************************
|
||||||
|
* HAboutWindow
|
||||||
|
**********************************************************************/
|
||||||
|
class HAboutWindow :public BWindow {
|
||||||
|
public:
|
||||||
|
HAboutWindow(const char* app_name,
|
||||||
|
const char* built_data,
|
||||||
|
const char* comment,
|
||||||
|
const char* url = NULL,
|
||||||
|
const char* mail = NULL);
|
||||||
|
protected:
|
||||||
|
void InitGUI();
|
||||||
|
void SetAppName(const char* app_name);
|
||||||
|
void SetBuiltDate(const char* text);
|
||||||
|
void SetVersion(const char* version);
|
||||||
|
void SetComment(const char* text);
|
||||||
|
void LoadIcon();
|
||||||
|
void LoadVersion();
|
||||||
|
void CalcFontHeights();
|
||||||
|
private:
|
||||||
|
BStringView* fAppName;
|
||||||
|
BStringView* fVersion;
|
||||||
|
BStringView* fBuiltDate;
|
||||||
|
HAboutView* fAboutView;
|
||||||
|
CTextView* fComment;
|
||||||
|
float fBoldHeight;
|
||||||
|
float fPlainHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
107
src/prefs/sounds/Utils/IconMenuItem.cpp
Normal file
107
src/prefs/sounds/Utils/IconMenuItem.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "IconMenuItem.h"
|
||||||
|
|
||||||
|
#include <Bitmap.h>
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor.
|
||||||
|
***********************************************************/
|
||||||
|
IconMenuItem::IconMenuItem(const char* label,BMessage *message,char shortcut,uint32 modifiers,BBitmap *bitmap,bool copy,bool free)
|
||||||
|
:BMenuItem(label,message,shortcut,modifiers)
|
||||||
|
,fBitmap(NULL)
|
||||||
|
,fCopy(copy)
|
||||||
|
{
|
||||||
|
SetBitmap(bitmap,free);
|
||||||
|
fHeightDelta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Constructor.
|
||||||
|
***********************************************************/
|
||||||
|
IconMenuItem::IconMenuItem(BMenu *submenu,BMessage *message,char shortcut,uint32 modifiers,BBitmap *bitmap,bool copy,bool free)
|
||||||
|
:BMenuItem(submenu,message)
|
||||||
|
,fBitmap(NULL)
|
||||||
|
,fCopy(copy)
|
||||||
|
{
|
||||||
|
SetBitmap(bitmap,free);
|
||||||
|
fHeightDelta = 0;
|
||||||
|
SetShortcut(shortcut,modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Destructor.
|
||||||
|
***********************************************************/
|
||||||
|
IconMenuItem::~IconMenuItem()
|
||||||
|
{
|
||||||
|
if(fCopy)
|
||||||
|
delete fBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Draw menu icon.
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
IconMenuItem::DrawContent()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(fBitmap != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
BPoint drawPoint(ContentLocation());
|
||||||
|
// center text and icon.
|
||||||
|
drawing_mode mode = Menu()->DrawingMode();
|
||||||
|
Menu()->SetDrawingMode(B_OP_ALPHA);
|
||||||
|
//Menu()->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||||
|
Menu()->SetLowColor( Menu()->ViewColor());
|
||||||
|
//Menu()->SetHighColor(B_TRANSPARENT_32_BIT);
|
||||||
|
if( !IsEnabled() )
|
||||||
|
{
|
||||||
|
Menu()->SetDrawingMode(B_OP_BLEND);
|
||||||
|
Menu()->DrawBitmap(fBitmap,drawPoint);
|
||||||
|
Menu()->SetDrawingMode(B_OP_OVER);
|
||||||
|
}else
|
||||||
|
Menu()->DrawBitmap(fBitmap,drawPoint);
|
||||||
|
// offset to title point.
|
||||||
|
drawPoint.y += ceil( fHeightDelta/2 );
|
||||||
|
drawPoint.x += 20;
|
||||||
|
// Move draw point.
|
||||||
|
Menu()->MovePenTo(drawPoint);
|
||||||
|
Menu()->SetDrawingMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
BMenuItem::DrawContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Extruct content width
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
IconMenuItem::GetContentSize(float *width, float *height)
|
||||||
|
{
|
||||||
|
BMenuItem::GetContentSize(width,height);
|
||||||
|
(*width) += 20;
|
||||||
|
fHeightDelta = 16 - (*height);
|
||||||
|
if( (*height) < 16)
|
||||||
|
(*height) = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Set the other bitmap.
|
||||||
|
***********************************************************/
|
||||||
|
void
|
||||||
|
IconMenuItem::SetBitmap(BBitmap *bitmap,bool free)
|
||||||
|
{
|
||||||
|
if(fCopy)
|
||||||
|
delete fBitmap;
|
||||||
|
|
||||||
|
if(!fCopy)
|
||||||
|
fBitmap = bitmap;
|
||||||
|
else{
|
||||||
|
if(bitmap)
|
||||||
|
{
|
||||||
|
fBitmap = new BBitmap(bitmap);
|
||||||
|
if(free) delete bitmap;
|
||||||
|
}else
|
||||||
|
fBitmap = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
40
src/prefs/sounds/Utils/IconMenuItem.h
Normal file
40
src/prefs/sounds/Utils/IconMenuItem.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*************************************************************
|
||||||
|
* IconMenu
|
||||||
|
*
|
||||||
|
* Toolbar is a usefull UI component.
|
||||||
|
*
|
||||||
|
* @author Atsushi Takamatsu (tak_atsu@tau.bekkoame.ne.jp)
|
||||||
|
**************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ICONMENUITEM_H__
|
||||||
|
#define __ICONMENUITEM_H__
|
||||||
|
|
||||||
|
#include <MenuItem.h>
|
||||||
|
|
||||||
|
class IconMenuItem :public BMenuItem {
|
||||||
|
public:
|
||||||
|
IconMenuItem(const char* label
|
||||||
|
,BMessage *message
|
||||||
|
,char shortcut = 0
|
||||||
|
,uint32 modifiers = 0
|
||||||
|
,BBitmap *bitmap = NULL
|
||||||
|
,bool copyBitmap = true
|
||||||
|
,bool deleteInputBitmap = true);
|
||||||
|
IconMenuItem(BMenu *submenu
|
||||||
|
,BMessage *message
|
||||||
|
,char shortcut = 0
|
||||||
|
,uint32 modifiers = 0
|
||||||
|
,BBitmap *bitmap = NULL
|
||||||
|
,bool copyBitmap = true
|
||||||
|
,bool deleteInputBitmap = true);
|
||||||
|
virtual ~IconMenuItem();
|
||||||
|
void SetBitmap(BBitmap *bitmap,bool freePointer=false);
|
||||||
|
protected:
|
||||||
|
virtual void DrawContent();
|
||||||
|
virtual void GetContentSize(float *width ,float *height);
|
||||||
|
private:
|
||||||
|
BBitmap *fBitmap;
|
||||||
|
bool fCopy;
|
||||||
|
float fHeightDelta;
|
||||||
|
};
|
||||||
|
#endif
|
59
src/prefs/sounds/Utils/RectUtils.cpp
Normal file
59
src/prefs/sounds/Utils/RectUtils.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "RectUtils.h"
|
||||||
|
#include <Screen.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
BRect
|
||||||
|
RectUtils::CenterRect(float width,float height)
|
||||||
|
{
|
||||||
|
BRect frame = BScreen().Frame();
|
||||||
|
BRect rect;
|
||||||
|
|
||||||
|
rect.left = frame.Width()/2.0 - width/2.0;
|
||||||
|
rect.right = rect.left + width;
|
||||||
|
rect.top = frame.Height()/2.0 - height/2.0;
|
||||||
|
rect.bottom = rect.top + height;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load rect data from the application file attribute.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
RectUtils::LoadRectFromApp(const char* name,BRect *rect)
|
||||||
|
{
|
||||||
|
app_info info;
|
||||||
|
be_app->GetAppInfo(&info);
|
||||||
|
BEntry entry(&info.ref);
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
|
BFile appfile(&entry,B_READ_ONLY);
|
||||||
|
attr_info ainfo;
|
||||||
|
status_t err = appfile.GetAttrInfo(name,&ainfo);
|
||||||
|
if(err == B_OK)
|
||||||
|
{
|
||||||
|
appfile.ReadAttr(name,B_RECT_TYPE,0,rect,sizeof(BRect));
|
||||||
|
rc = true;
|
||||||
|
} else {
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save rect data to the application file attribute.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RectUtils::SaveRectToApp(const char* name,BRect rect)
|
||||||
|
{
|
||||||
|
app_info info;
|
||||||
|
be_app->GetAppInfo(&info);
|
||||||
|
BEntry entry(&info.ref);
|
||||||
|
|
||||||
|
BFile appfile(&entry,B_WRITE_ONLY);
|
||||||
|
appfile.WriteAttr(name,B_RECT_TYPE,0,&rect,sizeof(BRect));
|
||||||
|
}
|
14
src/prefs/sounds/Utils/RectUtils.h
Normal file
14
src/prefs/sounds/Utils/RectUtils.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __RECTUTILS_H__
|
||||||
|
#define __RECTUTILS_H__
|
||||||
|
|
||||||
|
#include <Rect.h>
|
||||||
|
|
||||||
|
class RectUtils {
|
||||||
|
public:
|
||||||
|
RectUtils(){};
|
||||||
|
~RectUtils(){};
|
||||||
|
BRect CenterRect(float width,float height);
|
||||||
|
void SaveRectToApp(const char* name,BRect rect);
|
||||||
|
bool LoadRectFromApp(const char* name,BRect *rect);
|
||||||
|
};
|
||||||
|
#endif
|
279
src/prefs/sounds/Utils/ResourceUtils.cpp
Normal file
279
src/prefs/sounds/Utils/ResourceUtils.cpp
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
#include "ResourceUtils.h"
|
||||||
|
#include <Application.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
ResourceUtils::ResourceUtils(BResources *rsrc)
|
||||||
|
:BLocker()
|
||||||
|
,fResource(NULL)
|
||||||
|
{
|
||||||
|
if(rsrc == NULL)
|
||||||
|
fResource = BApplication::AppResources();
|
||||||
|
else
|
||||||
|
fResource = rsrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceUtils::ResourceUtils(const char *path)
|
||||||
|
:BLocker()
|
||||||
|
,fResource(NULL)
|
||||||
|
{
|
||||||
|
if(path == NULL)
|
||||||
|
fResource = BApplication::AppResources();
|
||||||
|
else{
|
||||||
|
BFile file(path, B_READ_WRITE);
|
||||||
|
BResources *res = new BResources();
|
||||||
|
status_t err;
|
||||||
|
if((err = res->SetTo(&file)) != B_OK)
|
||||||
|
fResource = BApplication::AppResources();
|
||||||
|
else
|
||||||
|
fResource = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceUtils::~ResourceUtils()
|
||||||
|
{
|
||||||
|
//if(fResource != BApplication::AppResources())
|
||||||
|
// delete fResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load icon by id.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
ResourceUtils::GetIconResource(int32 id, icon_size size, BBitmap *dest)
|
||||||
|
{
|
||||||
|
if (size != B_LARGE_ICON && size != B_MINI_ICON )
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
this->Lock();
|
||||||
|
const void *data = fResource->LoadResource(size == B_LARGE_ICON ? 'ICON' : 'MICN',
|
||||||
|
id, &len);
|
||||||
|
this->Unlock();
|
||||||
|
if (data == 0 || len != (size_t)(size == B_LARGE_ICON ? 1024 : 256)) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->SetBits(data, (int32)len, 0, B_COLOR_8_BIT);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load icon by name.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
ResourceUtils::GetIconResource(const char* name, icon_size size, BBitmap *dest)
|
||||||
|
{
|
||||||
|
if (size != B_LARGE_ICON && size != B_MINI_ICON )
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
this->Lock();
|
||||||
|
const void *data = fResource->LoadResource(size == B_LARGE_ICON ? 'ICON' : 'MICN',
|
||||||
|
name, &len);
|
||||||
|
this->Unlock();
|
||||||
|
if (data == 0 || len != (size_t)(size == B_LARGE_ICON ? 1024 : 256)) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->SetBits(data, (int32)len, 0, B_COLOR_8_BIT);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load bitmap by id.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
ResourceUtils::GetBitmapResource(type_code type, int32 id, BBitmap **out)
|
||||||
|
{
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
this->Lock();
|
||||||
|
const void *data = fResource->LoadResource(type, id, &len);
|
||||||
|
this->Unlock();
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMemoryIO stream(data, len);
|
||||||
|
|
||||||
|
// Try to read as an archived bitmap.
|
||||||
|
stream.Seek(0, SEEK_SET);
|
||||||
|
BMessage archive;
|
||||||
|
status_t err = archive.Unflatten(&stream);
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
*out = new BBitmap(&archive);
|
||||||
|
if (!*out)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
err = (*out)->InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
delete *out;
|
||||||
|
*out = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load bitmap by name.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
ResourceUtils::GetBitmapResource(type_code type, const char* name, BBitmap **out)
|
||||||
|
{
|
||||||
|
*out = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
this->Lock();
|
||||||
|
const void *data = fResource->LoadResource(type, name, &len);
|
||||||
|
this->Unlock();
|
||||||
|
if (data == NULL) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMemoryIO stream(data, len);
|
||||||
|
|
||||||
|
// Try to read as an archived bitmap.
|
||||||
|
stream.Seek(0, SEEK_SET);
|
||||||
|
BMessage archive;
|
||||||
|
status_t err = archive.Unflatten(&stream);
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
*out = new BBitmap(&archive);
|
||||||
|
if (!*out)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
err = (*out)->InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
delete *out;
|
||||||
|
*out = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load bitmap by name.
|
||||||
|
*/
|
||||||
|
BBitmap*
|
||||||
|
ResourceUtils::GetBitmapResource(type_code type, const char* name)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
this->Lock();
|
||||||
|
const void *data = fResource->LoadResource(type, name, &len);
|
||||||
|
this->Unlock();
|
||||||
|
if (data == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMemoryIO stream(data, len);
|
||||||
|
|
||||||
|
// Try to read as an archived bitmap.
|
||||||
|
stream.Seek(0, SEEK_SET);
|
||||||
|
BMessage archive;
|
||||||
|
status_t err = archive.Unflatten(&stream);
|
||||||
|
if (err != B_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BBitmap* out = new BBitmap(&archive);
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
err = (out)->InitCheck();
|
||||||
|
if (err != B_OK) {
|
||||||
|
delete out;
|
||||||
|
out = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get string from resources.
|
||||||
|
*/
|
||||||
|
const char*
|
||||||
|
ResourceUtils::GetString(const char* name)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
this->Lock();
|
||||||
|
const void* data;
|
||||||
|
if(fResource->HasResource('CSTR',name))
|
||||||
|
{
|
||||||
|
data = fResource->LoadResource('CSTR', name, &len);
|
||||||
|
}else
|
||||||
|
data = name;
|
||||||
|
this->Unlock();
|
||||||
|
return (const char*)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get string from resources.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
ResourceUtils::GetString(const char* name,BString &outStr)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
this->Lock();
|
||||||
|
const void* data;
|
||||||
|
status_t err = B_OK;
|
||||||
|
if(fResource->HasResource('CSTR',name))
|
||||||
|
{
|
||||||
|
data = fResource->LoadResource('CSTR', name, &len);
|
||||||
|
outStr = (const char*)data;
|
||||||
|
}else{
|
||||||
|
err = B_ERROR;
|
||||||
|
outStr = name;
|
||||||
|
}
|
||||||
|
this->Unlock();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set resources.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ResourceUtils::SetResource(BResources *rsrc)
|
||||||
|
{
|
||||||
|
fResource = rsrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set resources.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ResourceUtils::SetResource(const char* path)
|
||||||
|
{
|
||||||
|
BFile file(path, B_READ_WRITE);
|
||||||
|
BResources *res = new BResources();
|
||||||
|
status_t err;
|
||||||
|
if((err = res->SetTo(&file)) != B_OK)
|
||||||
|
fResource = BApplication::AppResources();
|
||||||
|
else
|
||||||
|
fResource = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free fResource. But You must not free when load app resource.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ResourceUtils::FreeResource()
|
||||||
|
{
|
||||||
|
delete fResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preload resources.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ResourceUtils::Preload(type_code type)
|
||||||
|
{
|
||||||
|
fResource->PreloadResourceType(type);
|
||||||
|
}
|
37
src/prefs/sounds/Utils/ResourceUtils.h
Normal file
37
src/prefs/sounds/Utils/ResourceUtils.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __RESOURCEUTILS_H__
|
||||||
|
#define __RESOURCEUTILS_H__
|
||||||
|
|
||||||
|
#include <Resources.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <Mime.h>
|
||||||
|
#include <Errors.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
|
||||||
|
class ResourceUtils :public BLocker {
|
||||||
|
public:
|
||||||
|
ResourceUtils(BResources *rsrc = NULL);
|
||||||
|
ResourceUtils(const char* path);
|
||||||
|
~ResourceUtils();
|
||||||
|
|
||||||
|
void SetResource(BResources *rsrc);
|
||||||
|
void SetResource(const char* path);
|
||||||
|
|
||||||
|
void Preload(type_code type);
|
||||||
|
void FreeResource();
|
||||||
|
|
||||||
|
status_t GetIconResource(int32 id, icon_size size, BBitmap *dest);
|
||||||
|
status_t GetIconResource(const char* name, icon_size size, BBitmap *dest);
|
||||||
|
status_t GetBitmapResource(type_code type, int32 id, BBitmap **out);
|
||||||
|
status_t GetBitmapResource(type_code type, const char* name, BBitmap **out);
|
||||||
|
BBitmap* GetBitmapResource(type_code type, const char* name);
|
||||||
|
const char* GetString(const char* name);
|
||||||
|
status_t GetString(const char* name,BString &outStr);
|
||||||
|
|
||||||
|
BResources* Resources() {return fResource;}
|
||||||
|
protected:
|
||||||
|
BResources *fResource;
|
||||||
|
};
|
||||||
|
#endif
|
913
src/prefs/sounds/Utils/URLView.cpp
Normal file
913
src/prefs/sounds/Utils/URLView.cpp
Normal file
@ -0,0 +1,913 @@
|
|||||||
|
/* URLView 2.0
|
||||||
|
written by William Kakes of Tall Hill Software.
|
||||||
|
|
||||||
|
This class provides an underlined and clickable BStringView
|
||||||
|
that will launch the web browser, e-mail program, or FTP client
|
||||||
|
when clicked on. Other features include hover-highlighting,
|
||||||
|
right-click menus, and drag-and-drop support.
|
||||||
|
|
||||||
|
You are free to use URLView in your own programs (both open-source
|
||||||
|
and closed-source) free of charge, but a mention in your read me
|
||||||
|
file or your program's about box would be appreciated. See
|
||||||
|
http://www.tallhill.com for current contact information.
|
||||||
|
|
||||||
|
URLView is provided as-is, with no warranties of any kind. If
|
||||||
|
you use it, you are on your own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "URLView.h"
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
URLView::URLView( BRect frame, const char *name, const char *label,
|
||||||
|
const char *url, uint32 resizingMode, uint32 flags )
|
||||||
|
: BStringView( frame, name, label, resizingMode, flags ) {
|
||||||
|
|
||||||
|
// Set the instance variables.
|
||||||
|
this->url = new BString( url );
|
||||||
|
|
||||||
|
// Set the default values for the other definable instance variables.
|
||||||
|
this->color = blue;
|
||||||
|
this->clickColor = red;
|
||||||
|
this->hoverColor = dark_blue;
|
||||||
|
this->hoverEnabled = true;
|
||||||
|
this->draggable = true;
|
||||||
|
this->iconSize = 16;
|
||||||
|
this->underlineThickness = 1;
|
||||||
|
|
||||||
|
// Create the cursor to use when over the link.
|
||||||
|
this->linkCursor = new BCursor( url_cursor );
|
||||||
|
|
||||||
|
// The link is not currently selected.
|
||||||
|
selected = false;
|
||||||
|
|
||||||
|
// The URL is currently not hover-colored.
|
||||||
|
hovering = false;
|
||||||
|
|
||||||
|
// The user has not dragged out of the view.
|
||||||
|
draggedOut = false;
|
||||||
|
|
||||||
|
// The user has not yet opened the popup menu.
|
||||||
|
inPopup = false;
|
||||||
|
|
||||||
|
// Initialize the attributes list (there are 14 standard
|
||||||
|
// Person attributes).
|
||||||
|
attributes = new BList( 14 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
URLView::~URLView() {
|
||||||
|
delete url;
|
||||||
|
delete linkCursor;
|
||||||
|
|
||||||
|
// Delete all the attributes.
|
||||||
|
KeyPair *item;
|
||||||
|
for( int i = 0; (item = (KeyPair *) attributes->ItemAt(i)); i++ ) {
|
||||||
|
delete item->key;
|
||||||
|
delete item->value;
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
delete attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::AttachedToWindow() {
|
||||||
|
// When the view is first attached, we want to draw the link
|
||||||
|
// in the normal color. Also, we want to set our background color
|
||||||
|
// to meet that of our parent.
|
||||||
|
SetHighColor( color );
|
||||||
|
if( Parent() != NULL ) {
|
||||||
|
SetLowColor( Parent()->ViewColor() );
|
||||||
|
SetViewColor( Parent()->ViewColor() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::Draw( BRect updateRect ) {
|
||||||
|
BRect rect = Frame();
|
||||||
|
rect.OffsetTo( B_ORIGIN );
|
||||||
|
|
||||||
|
// We want 'g's, etc. to go below the underline. When the BeOS can
|
||||||
|
// do underlining of any font, this code can be removed.
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight( &height );
|
||||||
|
float descent = height.descent / 2;
|
||||||
|
|
||||||
|
// Draw the underline in the requested thickness.
|
||||||
|
FillRect( BRect( (float) rect.left,
|
||||||
|
(float) (rect.bottom - descent - underlineThickness + 1),
|
||||||
|
(float) StringWidth( Text() ),
|
||||||
|
(float) rect.bottom - descent ) );
|
||||||
|
|
||||||
|
// Note: DrawString() draws the text at one pixel above the pen's
|
||||||
|
// current y coordinate.
|
||||||
|
MovePenTo( BPoint( rect.left, rect.bottom - descent -
|
||||||
|
(float) underlineThickness ) );
|
||||||
|
DrawString( Text() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::MessageReceived( BMessage *message ) {
|
||||||
|
// Is this a message from Tracker in response to our drag-and-drop?
|
||||||
|
if( message->what == 'DDCP' ) {
|
||||||
|
// Tracker will send back the name and path of the created file.
|
||||||
|
// We need to read this information.
|
||||||
|
entry_ref ref;
|
||||||
|
message->FindRef( "directory", &ref );
|
||||||
|
BEntry entry( &ref );
|
||||||
|
BPath path( &entry );
|
||||||
|
BString *fullName = new BString( path.Path() );
|
||||||
|
fullName->Append( "/" );
|
||||||
|
fullName->Append( message->FindString( "name" ) );
|
||||||
|
BString *title = new BString( Text() );
|
||||||
|
|
||||||
|
// Set the new file as a bookmark or as a person as appropriate.
|
||||||
|
if( IsEmailLink() ) {
|
||||||
|
CreatePerson( fullName, title );
|
||||||
|
}
|
||||||
|
else CreateBookmark( fullName, title );
|
||||||
|
|
||||||
|
delete fullName;
|
||||||
|
delete title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::MouseDown( BPoint point ) {
|
||||||
|
// See which mouse buttons were clicked.
|
||||||
|
int32 buttons = Window()->CurrentMessage()->FindInt32( "buttons" );
|
||||||
|
|
||||||
|
// We want to highlight the text if the user clicks on
|
||||||
|
// the URL. We want to be sure to only register a click
|
||||||
|
// if the user clicks on the link text itself and not just
|
||||||
|
// anywhere in the view.
|
||||||
|
if( GetTextRect().Contains( point ) ) {
|
||||||
|
SetHighColor( clickColor );
|
||||||
|
Redraw();
|
||||||
|
|
||||||
|
// Set the link as selected and track the mouse.
|
||||||
|
selected = true;
|
||||||
|
SetMouseEventMask( B_POINTER_EVENTS );
|
||||||
|
|
||||||
|
// Remember where the user clicked.
|
||||||
|
dragOffset = point;
|
||||||
|
|
||||||
|
// Pop up the context menu?
|
||||||
|
if( buttons == B_SECONDARY_MOUSE_BUTTON ) inPopup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::MouseMoved( BPoint point, uint32 transit,
|
||||||
|
const BMessage *message ) {
|
||||||
|
|
||||||
|
// Make sure the window is the active one.
|
||||||
|
if( !Window()->IsActive() ) return;
|
||||||
|
|
||||||
|
// See which mouse buttons were clicked.
|
||||||
|
int32 buttons = Window()->CurrentMessage()->FindInt32( "buttons" );
|
||||||
|
// Is the user currently dragging the link? (i.e. is a mouse button
|
||||||
|
// currently down?)
|
||||||
|
bool alreadyDragging = (buttons != 0);
|
||||||
|
|
||||||
|
switch( transit ) {
|
||||||
|
case( B_ENTERED_VIEW ):
|
||||||
|
// Should we set the cursor to the link cursor?
|
||||||
|
if( GetTextRect().Contains( point ) && !draggedOut ) {
|
||||||
|
if( !alreadyDragging ) be_app->SetCursor( linkCursor );
|
||||||
|
|
||||||
|
// Did the user leave and re-enter the view while
|
||||||
|
// holding down the mouse button? If so, highlight
|
||||||
|
// the link.
|
||||||
|
if( selected ) {
|
||||||
|
SetHighColor( clickColor );
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
// Should we hover-highlight the link?
|
||||||
|
else if( hoverEnabled && !alreadyDragging ) {
|
||||||
|
if( buttons == 0 ) {
|
||||||
|
SetHighColor( hoverColor );
|
||||||
|
Redraw();
|
||||||
|
hovering = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case( B_EXITED_VIEW ):
|
||||||
|
// We want to restore the link to it normal color and the
|
||||||
|
// mouse cursor to the normal hand. However, we should only
|
||||||
|
// set the color and re-draw if it is needed.
|
||||||
|
if( selected && !draggedOut ) {
|
||||||
|
be_app->SetCursor( B_HAND_CURSOR );
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
|
||||||
|
// Is the user drag-and-dropping a bookmark or person?
|
||||||
|
if( draggable ) {
|
||||||
|
draggedOut = true;
|
||||||
|
if( IsEmailLink() ) DoPersonDrag();
|
||||||
|
else DoBookmarkDrag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Is the link currently hover-highlighted? If so, restore
|
||||||
|
// the normal color now.
|
||||||
|
else if( hovering && !alreadyDragging ) {
|
||||||
|
be_app->SetCursor( B_HAND_CURSOR );
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
hovering = false;
|
||||||
|
}
|
||||||
|
// Change the cursor back to the hand.
|
||||||
|
else {
|
||||||
|
be_app->SetCursor( B_HAND_CURSOR );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case( B_INSIDE_VIEW ):
|
||||||
|
// The user could either be moving out of the view or
|
||||||
|
// back into it here, so we must handle both cases.
|
||||||
|
// In the first case, the cursor is now over the link.
|
||||||
|
if( GetTextRect().Contains( point ) && !draggedOut ) {
|
||||||
|
// We only want to change the cursor if not dragging.
|
||||||
|
if( !alreadyDragging ) be_app->SetCursor( linkCursor );
|
||||||
|
if( selected ) {
|
||||||
|
if( draggable ) {
|
||||||
|
// If the user moves the mouse more than ten
|
||||||
|
// pixels, begin the drag.
|
||||||
|
if( (point.x - dragOffset.x) > 10 ||
|
||||||
|
(dragOffset.x - point.x) > 10 ||
|
||||||
|
(point.y - dragOffset.y) > 10 ||
|
||||||
|
(dragOffset.y - point.y) > 10 ) {
|
||||||
|
draggedOut = true;
|
||||||
|
// Draw the appropriate drag object, etc.
|
||||||
|
if( IsEmailLink() ) DoPersonDrag();
|
||||||
|
else DoBookmarkDrag();
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Since the link is not draggable, highlight it
|
||||||
|
// as long as the user holds the button down and
|
||||||
|
// has the mouse cursor over it (like a standard
|
||||||
|
// button).
|
||||||
|
SetHighColor( clickColor );
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The link isn't currently selected? If hover-highlighting
|
||||||
|
// is enabled, highlight the link.
|
||||||
|
else if( hoverEnabled && !alreadyDragging ) {
|
||||||
|
SetHighColor( hoverColor );
|
||||||
|
Redraw();
|
||||||
|
hovering = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// In this case, the mouse cursor is not over the link, so we
|
||||||
|
// need to restore the original link color, etc.
|
||||||
|
else if( !draggedOut ) {
|
||||||
|
be_app->SetCursor( B_HAND_CURSOR );
|
||||||
|
if( selected ) {
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
|
||||||
|
// Is the user dragging the link?
|
||||||
|
if( draggable ) {
|
||||||
|
draggedOut = true;
|
||||||
|
if( IsEmailLink() ) DoPersonDrag();
|
||||||
|
else DoBookmarkDrag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Is the mouse cursor hovering over the link?
|
||||||
|
else if( hovering ) {
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
hovering = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::MouseUp( BPoint point ) {
|
||||||
|
// Do we want to show the right-click menu?
|
||||||
|
if( inPopup && GetTextRect().Contains( point ) ) {
|
||||||
|
BPopUpMenu *popup = CreatePopupMenu();
|
||||||
|
// Work around a current bug in Be's popup menus.
|
||||||
|
point.y = point.y - 6;
|
||||||
|
|
||||||
|
// Display the popup menu.
|
||||||
|
BMenuItem *selected = popup->Go( ConvertToScreen( point ) , false, true );
|
||||||
|
|
||||||
|
// Did the user select an item?
|
||||||
|
if( selected ) {
|
||||||
|
BString label( selected->Label() );
|
||||||
|
// Did the user select the first item? If so, launch the URL.
|
||||||
|
if( label.FindFirst( "Open" ) != B_ERROR ||
|
||||||
|
label.FindFirst( "Send" ) != B_ERROR ||
|
||||||
|
label.FindFirst( "Connect" ) != B_ERROR ) {
|
||||||
|
LaunchURL();
|
||||||
|
}
|
||||||
|
// Did the user select the second item?
|
||||||
|
else if( label.FindFirst( "Copy" ) != B_ERROR ) {
|
||||||
|
CopyToClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If not, restore the normal link color.
|
||||||
|
else {
|
||||||
|
SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the link was clicked on (and not dragged), run the program
|
||||||
|
// that should handle the URL.
|
||||||
|
if( selected && GetTextRect().Contains( point ) &&
|
||||||
|
!draggedOut && !inPopup ) {
|
||||||
|
LaunchURL();
|
||||||
|
}
|
||||||
|
selected = false;
|
||||||
|
draggedOut = false;
|
||||||
|
inPopup = false;
|
||||||
|
|
||||||
|
// Should we restore the hovering-highlighted color or the original
|
||||||
|
// link color?
|
||||||
|
if( GetTextRect().Contains( point ) && !draggedOut &&
|
||||||
|
!inPopup && hoverEnabled ) {
|
||||||
|
SetHighColor( hoverColor );
|
||||||
|
}
|
||||||
|
else if( !hovering ) SetHighColor( color );
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::AddAttribute( const char *name, const char *value ) {
|
||||||
|
// Add an attribute (name and corresponding value) to the object
|
||||||
|
// that will be dragged out (i.e. to fill in Person fields, etc.)
|
||||||
|
KeyPair *newPair = new KeyPair;
|
||||||
|
newPair->key = new BString( name );
|
||||||
|
newPair->value = new BString( value );
|
||||||
|
attributes->AddItem( newPair );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetColor( rgb_color color ) {
|
||||||
|
// Set the normal link color.
|
||||||
|
this->color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetClickColor( rgb_color color ) {
|
||||||
|
// Set the link color used when the link is clicked.
|
||||||
|
clickColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetDraggable( bool draggable ) {
|
||||||
|
// Set whether or not this link is draggable.
|
||||||
|
this->draggable = draggable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetHoverColor( rgb_color color ) {
|
||||||
|
// Set the link color used when the mouse cursor is over it.
|
||||||
|
hoverColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetHoverEnabled( bool hover ) {
|
||||||
|
// Set whether or not to hover-highlight the link.
|
||||||
|
hoverEnabled = hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetIconSize( icon_size iconSize ) {
|
||||||
|
// Set the size of the icon that will be shown when the link is dragged.
|
||||||
|
if( iconSize == B_MINI_ICON ) this->iconSize = 16;
|
||||||
|
else this->iconSize = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::SetUnderlineThickness( int thickness ) {
|
||||||
|
// Set the thickness of the underline in pixels.
|
||||||
|
underlineThickness = thickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::CopyToClipboard() {
|
||||||
|
// Copy the URL to the clipboard.
|
||||||
|
BClipboard clipboard( "system" );
|
||||||
|
BMessage *clip = (BMessage *) NULL;
|
||||||
|
// Get the important URL (i.e. trim off "mailto:", etc.).
|
||||||
|
BString newclip = GetImportantURL();
|
||||||
|
|
||||||
|
// Be sure to lock the clipboard first.
|
||||||
|
if( clipboard.Lock() ) {
|
||||||
|
clipboard.Clear();
|
||||||
|
if( (clip = clipboard.Data()) ) {
|
||||||
|
clip->AddData( "text/plain", B_MIME_TYPE, newclip.String(),
|
||||||
|
newclip.Length() + 1 );
|
||||||
|
clipboard.Commit();
|
||||||
|
}
|
||||||
|
clipboard.Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::CreateBookmark( const BString *fullName, const BString *title ) {
|
||||||
|
// Read the file defined by the path and the title.
|
||||||
|
BFile *file = new BFile( fullName->String(), B_WRITE_ONLY );
|
||||||
|
|
||||||
|
// Set the file's MIME type to be a bookmark.
|
||||||
|
BNodeInfo *nodeInfo = new BNodeInfo( file );
|
||||||
|
nodeInfo->SetType( "application/x-vnd.Be-bookmark" );
|
||||||
|
delete nodeInfo;
|
||||||
|
delete file;
|
||||||
|
|
||||||
|
// Add all the attributes, both those inherrent to bookmarks and any
|
||||||
|
// the developer may have defined using AddAttribute().
|
||||||
|
DIR *d;
|
||||||
|
int fd;
|
||||||
|
d = fs_open_attr_dir( fullName->String() );
|
||||||
|
if( d ) {
|
||||||
|
fd = open( fullName->String(), O_WRONLY );
|
||||||
|
fs_write_attr( fd, "META:title", B_STRING_TYPE, 0, title->String(), title->Length() + 1 );
|
||||||
|
fs_write_attr( fd, "META:url", B_STRING_TYPE, 0, url->String(), url->Length() + 1 );
|
||||||
|
WriteAttributes( fd );
|
||||||
|
close( fd );
|
||||||
|
fs_close_attr_dir( d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::CreatePerson( const BString *fullName, const BString *title ) {
|
||||||
|
// Read the file defined by the path and the title.
|
||||||
|
BFile *file = new BFile( fullName->String(), B_WRITE_ONLY );
|
||||||
|
|
||||||
|
// Set the file's MIME type to be a person.
|
||||||
|
BNodeInfo *nodeInfo = new BNodeInfo( file );
|
||||||
|
nodeInfo->SetType( "application/x-person" );
|
||||||
|
delete nodeInfo;
|
||||||
|
delete file;
|
||||||
|
|
||||||
|
// Add all the attributes, both those inherrent to person files and any
|
||||||
|
// the developer may have defined using AddAttribute().
|
||||||
|
DIR *d;
|
||||||
|
int fd;
|
||||||
|
d = fs_open_attr_dir( fullName->String() );
|
||||||
|
if( d ) {
|
||||||
|
fd = open( fullName->String(), O_WRONLY );
|
||||||
|
fs_write_attr( fd, "META:name", B_STRING_TYPE, 0, title->String(), title->Length() + 1 );
|
||||||
|
BString email = GetImportantURL();
|
||||||
|
fs_write_attr( fd, "META:email", B_STRING_TYPE, 0, email.String(), email.Length() + 1 );
|
||||||
|
WriteAttributes( fd );
|
||||||
|
close( fd );
|
||||||
|
fs_close_attr_dir( d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BPopUpMenu * URLView::CreatePopupMenu() {
|
||||||
|
// Create the right-click popup menu.
|
||||||
|
BPopUpMenu *returnMe = new BPopUpMenu( "URLView Popup", false, false );
|
||||||
|
returnMe->SetAsyncAutoDestruct( true );
|
||||||
|
|
||||||
|
entry_ref app;
|
||||||
|
|
||||||
|
// Set the text of the first item according to the link type.
|
||||||
|
if( IsEmailLink() ) {
|
||||||
|
// Find the name of the default e-mail client.
|
||||||
|
if( be_roster->FindApp( "text/x-email", &app ) == B_OK ) {
|
||||||
|
BEntry entry( &app );
|
||||||
|
BString openLabel( "Send e-mail to this address using " );
|
||||||
|
char name[B_FILE_NAME_LENGTH];
|
||||||
|
entry.GetName( name );
|
||||||
|
openLabel.Append( name );
|
||||||
|
returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( IsFTPLink() ) {
|
||||||
|
// Find the name of the default FTP client.
|
||||||
|
if( be_roster->FindApp( "application/x-vnd.Be.URL.ftp", &app ) == B_OK ) {
|
||||||
|
BEntry entry( &app );
|
||||||
|
BString openLabel( "Connect to this server using " );
|
||||||
|
char name[B_FILE_NAME_LENGTH];
|
||||||
|
entry.GetName( name );
|
||||||
|
openLabel.Append( name );
|
||||||
|
returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Find the name of the default HTML handler (browser).
|
||||||
|
if( be_roster->FindApp( "text/html", &app ) == B_OK ) {
|
||||||
|
BEntry entry( &app );
|
||||||
|
BString openLabel( "Open this link using " );
|
||||||
|
char name[B_FILE_NAME_LENGTH];
|
||||||
|
entry.GetName( name );
|
||||||
|
openLabel.Append( name );
|
||||||
|
returnMe->AddItem( new BMenuItem( openLabel.String(), NULL ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnMe->AddItem( new BMenuItem( "Copy this link to the clipboard", NULL ) );
|
||||||
|
|
||||||
|
return returnMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::DoBookmarkDrag() {
|
||||||
|
// Handle all of the bookmark dragging. This includes setting up
|
||||||
|
// the drag message and drawing the dragged bitmap.
|
||||||
|
|
||||||
|
// Set up the drag message to support both BTextView dragging (using
|
||||||
|
// the URL) and file dropping (to Tracker).
|
||||||
|
BMessage *dragMessage = new BMessage( B_MIME_DATA );
|
||||||
|
dragMessage->AddInt32( "be:actions", B_COPY_TARGET );
|
||||||
|
dragMessage->AddString( "be:types", "application/octet-stream" );
|
||||||
|
dragMessage->AddString( "be:filetypes", "application/x-vnd.Be-bookmark" );
|
||||||
|
dragMessage->AddString( "be:type_descriptions", "bookmark" );
|
||||||
|
dragMessage->AddString( "be:clip_name", Text() );
|
||||||
|
dragMessage->AddString( "be:url", url->String() );
|
||||||
|
|
||||||
|
// This allows the user to drag the URL into a standard BTextView.
|
||||||
|
BString link = GetImportantURL();
|
||||||
|
dragMessage->AddData( "text/plain", B_MIME_DATA, link.String(),
|
||||||
|
link.Length() + 1 );
|
||||||
|
|
||||||
|
// Query for the system's icon for bookmarks.
|
||||||
|
BBitmap *bookmarkIcon = new BBitmap( BRect( 0, 0, iconSize - 1,
|
||||||
|
iconSize - 1 ), B_CMAP8 );
|
||||||
|
BMimeType mime( "application/x-vnd.Be-bookmark" );
|
||||||
|
if( iconSize == 16 ) mime.GetIcon( bookmarkIcon, B_MINI_ICON );
|
||||||
|
else mime.GetIcon( bookmarkIcon, B_LARGE_ICON );
|
||||||
|
|
||||||
|
// Find the size of the bitmap to drag. If the text is bigger than the
|
||||||
|
// icon, use that size. Otherwise, use the icon's. Center the icon
|
||||||
|
// vertically in the bitmap.
|
||||||
|
BRect urlRect = GetURLRect();
|
||||||
|
BRect rect = urlRect;
|
||||||
|
rect.right += iconSize + 4;
|
||||||
|
if( (rect.bottom - rect.top) < iconSize ) {
|
||||||
|
int adjustment = (int) ((iconSize - (rect.bottom - rect.top)) / 2) + 1;
|
||||||
|
rect.top -= adjustment;
|
||||||
|
rect.bottom += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the rectangle starts at 0,0.
|
||||||
|
rect.bottom += 0 - rect.top;
|
||||||
|
rect.top = 0;
|
||||||
|
|
||||||
|
// Create the bitmap to draw the dragged image in.
|
||||||
|
BBitmap *dragBitmap = new BBitmap( rect, B_RGBA32, true );
|
||||||
|
BView *dragView = new BView( rect, "Drag View", 0, 0 );
|
||||||
|
dragBitmap->Lock();
|
||||||
|
dragBitmap->AddChild( dragView );
|
||||||
|
|
||||||
|
BRect frameRect = dragView->Frame();
|
||||||
|
|
||||||
|
// Make the background of the dragged image transparent.
|
||||||
|
dragView->SetHighColor( B_TRANSPARENT_COLOR );
|
||||||
|
dragView->FillRect( frameRect );
|
||||||
|
|
||||||
|
// We want 'g's, etc. to go below the underline. When the BeOS can
|
||||||
|
// do underlining of any font, this code can be removed.
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight( &height );
|
||||||
|
float descent = height.descent;
|
||||||
|
|
||||||
|
// Find the vertical center of the view so we can vertically
|
||||||
|
// center everything.
|
||||||
|
int centerPixel = (int) ((frameRect.bottom - frameRect.top) / 2);
|
||||||
|
int textCenter = (int) (descent + underlineThickness) + centerPixel;
|
||||||
|
|
||||||
|
// We want to draw everything only half opaque.
|
||||||
|
dragView->SetDrawingMode( B_OP_ALPHA );
|
||||||
|
dragView->SetHighColor( color.red, color.green, color.blue, 128.0 );
|
||||||
|
dragView->SetBlendingMode( B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE );
|
||||||
|
|
||||||
|
// Center the icon in the view.
|
||||||
|
dragView->MovePenTo( BPoint( frameRect.left,
|
||||||
|
centerPixel - (iconSize / 2) ) );
|
||||||
|
dragView->DrawBitmap( bookmarkIcon );
|
||||||
|
|
||||||
|
// Draw the text in the same font (size, etc.) as the link view.
|
||||||
|
// Note: DrawString() draws the text at one pixel above the pen's
|
||||||
|
// current y coordinate.
|
||||||
|
BFont font;
|
||||||
|
GetFont( &font );
|
||||||
|
dragView->SetFont( &font );
|
||||||
|
dragView->MovePenTo( BPoint( frameRect.left + iconSize + 4, textCenter ) );
|
||||||
|
dragView->DrawString( url->String() );
|
||||||
|
|
||||||
|
// Draw the underline in the requested thickness.
|
||||||
|
dragView->FillRect( BRect( (float) frameRect.left + iconSize + 4,
|
||||||
|
(float) (textCenter + 1),
|
||||||
|
(float) StringWidth( url->String() ) + iconSize + 4,
|
||||||
|
(float) textCenter + underlineThickness ) );
|
||||||
|
|
||||||
|
// Be sure to flush the view buffer so everything is drawn.
|
||||||
|
dragView->Flush();
|
||||||
|
dragBitmap->Unlock();
|
||||||
|
|
||||||
|
// The URL's label is probably not the same size as the URL's
|
||||||
|
// address, which is what we're going to draw. So horizontally
|
||||||
|
// offset the bitmap proportionally to where the user clicked
|
||||||
|
// on the link.
|
||||||
|
float horiz = dragOffset.x / GetTextRect().Width();
|
||||||
|
dragOffset.x = horiz * frameRect.right;
|
||||||
|
|
||||||
|
DragMessage( dragMessage, dragBitmap, B_OP_ALPHA,
|
||||||
|
BPoint( dragOffset.x, (rect.Height() / 2) + 2 ), this );
|
||||||
|
delete dragMessage;
|
||||||
|
|
||||||
|
draggedOut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::DoPersonDrag() {
|
||||||
|
// Handle all of the bookmark dragging. This includes setting up
|
||||||
|
// the drag message and drawing the dragged bitmap.
|
||||||
|
|
||||||
|
// Set up the drag message to support both BTextView dragging (using
|
||||||
|
// the e-mail address) and file dropping (to Tracker).
|
||||||
|
BMessage *dragMessage = new BMessage( B_MIME_DATA );
|
||||||
|
dragMessage->AddInt32( "be:actions", B_COPY_TARGET );
|
||||||
|
dragMessage->AddString( "be:types", "application/octet-stream" );
|
||||||
|
dragMessage->AddString( "be:filetypes", "application/x-person" );
|
||||||
|
dragMessage->AddString( "be:type_descriptions", "person" );
|
||||||
|
dragMessage->AddString( "be:clip_name", Text() );
|
||||||
|
|
||||||
|
// This allows the user to drag the e-mail address into a
|
||||||
|
// standard BTextView.
|
||||||
|
BString email = GetImportantURL();
|
||||||
|
dragMessage->AddData( "text/plain", B_MIME_DATA, email.String(),
|
||||||
|
email.Length() + 1 );
|
||||||
|
|
||||||
|
// Query for the system's icon for bookmarks.
|
||||||
|
BBitmap *personIcon = new BBitmap( BRect( 0, 0, iconSize - 1,
|
||||||
|
iconSize - 1 ), B_CMAP8 );
|
||||||
|
BMimeType mime( "application/x-person" );
|
||||||
|
if( iconSize == 16 ) mime.GetIcon( personIcon, B_MINI_ICON );
|
||||||
|
else mime.GetIcon( personIcon, B_LARGE_ICON );
|
||||||
|
|
||||||
|
// Find the size of the bitmap to drag. If the text is bigger than the
|
||||||
|
// icon, use that size. Otherwise, use the icon's. Center the icon
|
||||||
|
// vertically in the bitmap.
|
||||||
|
BRect rect = GetTextRect();
|
||||||
|
rect.right += iconSize + 4;
|
||||||
|
if( (rect.bottom - rect.top) < iconSize ) {
|
||||||
|
int adjustment = (int) ((iconSize - (rect.bottom - rect.top)) / 2) + 1;
|
||||||
|
rect.top -= adjustment;
|
||||||
|
rect.bottom += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the rectangle starts at 0,0.
|
||||||
|
rect.bottom += 0 - rect.top;
|
||||||
|
rect.top = 0;
|
||||||
|
|
||||||
|
// Create the bitmap to draw the dragged image in.
|
||||||
|
BBitmap *dragBitmap = new BBitmap( rect, B_RGBA32, true );
|
||||||
|
BView *dragView = new BView( rect, "Drag View", 0, 0 );
|
||||||
|
dragBitmap->Lock();
|
||||||
|
dragBitmap->AddChild( dragView );
|
||||||
|
|
||||||
|
BRect frameRect = dragView->Frame();
|
||||||
|
|
||||||
|
// Make the background of the dragged image transparent.
|
||||||
|
dragView->SetHighColor( B_TRANSPARENT_COLOR );
|
||||||
|
dragView->FillRect( frameRect );
|
||||||
|
|
||||||
|
// We want 'g's, etc. to go below the underline. When the BeOS can
|
||||||
|
// do underlining of any font, this code can be removed.
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight( &height );
|
||||||
|
float descent = height.descent;
|
||||||
|
|
||||||
|
// Find the vertical center of the view so we can vertically
|
||||||
|
// center everything.
|
||||||
|
int centerPixel = (int) ((frameRect.bottom - frameRect.top) / 2);
|
||||||
|
int textCenter = (int) (descent + underlineThickness) + centerPixel;
|
||||||
|
|
||||||
|
// We want to draw everything only half opaque.
|
||||||
|
dragView->SetDrawingMode( B_OP_ALPHA );
|
||||||
|
dragView->SetHighColor( 0.0, 0.0, 0.0, 128.0 );
|
||||||
|
dragView->SetBlendingMode( B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE );
|
||||||
|
|
||||||
|
// Center the icon in the view.
|
||||||
|
dragView->MovePenTo( BPoint( frameRect.left,
|
||||||
|
centerPixel - (iconSize / 2) ) );
|
||||||
|
dragView->DrawBitmap( personIcon );
|
||||||
|
|
||||||
|
// Draw the text in the same font (size, etc.) as the link view.
|
||||||
|
// Note: DrawString() draws the text at one pixel above the pen's
|
||||||
|
// current y coordinate.
|
||||||
|
BFont font;
|
||||||
|
GetFont( &font );
|
||||||
|
dragView->SetFont( &font );
|
||||||
|
dragView->MovePenTo( BPoint( frameRect.left + iconSize + 4, textCenter ) );
|
||||||
|
dragView->DrawString( Text() );
|
||||||
|
|
||||||
|
// Be sure to flush the view buffer so everything is drawn.
|
||||||
|
dragView->Flush();
|
||||||
|
dragBitmap->Unlock();
|
||||||
|
|
||||||
|
// The Person icon adds some width to the bitmap that we are
|
||||||
|
// going to draw. So horizontally offset the bitmap proportionally
|
||||||
|
// to where the user clicked on the link.
|
||||||
|
float horiz = dragOffset.x / GetTextRect().Width();
|
||||||
|
dragOffset.x = horiz * frameRect.right;
|
||||||
|
|
||||||
|
DragMessage( dragMessage, dragBitmap, B_OP_ALPHA,
|
||||||
|
BPoint( dragOffset.x,
|
||||||
|
(rect.Height() + underlineThickness) / 2 + 2), this );
|
||||||
|
delete dragMessage;
|
||||||
|
|
||||||
|
draggedOut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BString URLView::GetImportantURL() {
|
||||||
|
// Return the relevant portion of the URL (i.e. strip off "mailto:" from
|
||||||
|
// e-mail address URLs).
|
||||||
|
BString returnMe;
|
||||||
|
|
||||||
|
if( IsEmailLink() ) url->CopyInto( returnMe, 7, url->CountChars() - 6 );
|
||||||
|
else url->CopyInto( returnMe, 0, url->CountChars() );
|
||||||
|
|
||||||
|
return returnMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BRect URLView::GetTextRect() {
|
||||||
|
// This function will return a BRect that contains only the text
|
||||||
|
// and the underline, so the mouse can change and the link will
|
||||||
|
// be activated only when the mouse is over the text itself, not
|
||||||
|
// just within the view.
|
||||||
|
BRect frame = Frame();
|
||||||
|
frame.OffsetTo( B_ORIGIN );
|
||||||
|
|
||||||
|
// Get the height of the current font.
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight( &height );
|
||||||
|
|
||||||
|
float stringHeight = underlineThickness + height.ascent - 1;
|
||||||
|
|
||||||
|
// Get the rectangle of just the string.
|
||||||
|
return BRect( frame.left, frame.bottom - stringHeight,
|
||||||
|
frame.left + StringWidth( Text() ), frame.bottom - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect URLView::GetURLRect() {
|
||||||
|
// This function will return a BRect that contains only the text
|
||||||
|
// and the underline, so the mouse can change and the link will
|
||||||
|
// be activated only when the mouse is over the text itself, not
|
||||||
|
// just within the view.
|
||||||
|
BRect frame = Frame();
|
||||||
|
frame.OffsetTo( B_ORIGIN );
|
||||||
|
|
||||||
|
// Get the height of the current font.
|
||||||
|
font_height height;
|
||||||
|
GetFontHeight( &height );
|
||||||
|
|
||||||
|
float stringHeight = underlineThickness + height.ascent - 1;
|
||||||
|
|
||||||
|
// Get the rectangle of just the string.
|
||||||
|
return BRect( frame.left, frame.bottom - stringHeight,
|
||||||
|
frame.left + StringWidth( url->String() ),
|
||||||
|
frame.bottom - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool URLView::IsEmailLink() {
|
||||||
|
// Is this link an e-mail link?
|
||||||
|
return( url->FindFirst( "mailto:" ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool URLView::IsFTPLink() {
|
||||||
|
// Is this link an FTP link?
|
||||||
|
return( url->FindFirst( "ftp://" ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::LaunchURL() {
|
||||||
|
// Is the URL a mail link or HTTP?
|
||||||
|
if( IsEmailLink() ) {
|
||||||
|
// Lock the string buffer and pass it to the mail program.
|
||||||
|
char *link = url->LockBuffer( 0 );
|
||||||
|
status_t result = be_roster->Launch( "text/x-email", 1, &link );
|
||||||
|
url->UnlockBuffer();
|
||||||
|
|
||||||
|
if( result == B_ALREADY_RUNNING||result == B_BAD_VALUE)
|
||||||
|
{
|
||||||
|
char app_sig[B_MIME_TYPE_LENGTH];
|
||||||
|
|
||||||
|
BMimeType("text/x-email").GetPreferredApp(app_sig);
|
||||||
|
//result = be_roster->Launch( app_sig, 1, &link );
|
||||||
|
BMessenger messenger(app_sig);
|
||||||
|
BMessage msg(B_ARGV_RECEIVED);
|
||||||
|
msg.AddInt32("argc",2);
|
||||||
|
msg.AddString("argv","app");
|
||||||
|
msg.AddString("argv",link);
|
||||||
|
msg.AddString("cmd","/");
|
||||||
|
BMessage reply;
|
||||||
|
result = messenger.SendMessage(&msg,&reply);
|
||||||
|
}
|
||||||
|
// Make sure the user has an e-mail program.
|
||||||
|
if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) {
|
||||||
|
BAlert *alert = new BAlert( "E-mail Warning",
|
||||||
|
"There is no e-mail program on your machine that is configured as the default program to send e-mail.",
|
||||||
|
"Ok", NULL, NULL, B_WIDTH_AS_USUAL,
|
||||||
|
B_WARNING_ALERT );
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle an HTTP link.
|
||||||
|
else if( (url->FindFirst( "http://" ) == 0) ||
|
||||||
|
(url->FindFirst( "file://" ) == 0) ) {
|
||||||
|
// Lock the string buffer and pass it to the web browser.
|
||||||
|
char *link = url->LockBuffer( 0 );
|
||||||
|
status_t result = be_roster->Launch( "text/html", 1, &link );
|
||||||
|
url->UnlockBuffer();
|
||||||
|
// Make sure the user has a web browser.
|
||||||
|
if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) {
|
||||||
|
BAlert *alert = new BAlert( "Web Browser Warning",
|
||||||
|
"There is no web browser on your machine that is configured as the default program to view web pages.",
|
||||||
|
"Ok", NULL, NULL, B_WIDTH_AS_USUAL,
|
||||||
|
B_WARNING_ALERT );
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle an FTP link.
|
||||||
|
else if( IsFTPLink() ) {
|
||||||
|
// Lock the string buffer and pass it to the FTP client.
|
||||||
|
char *link = url->LockBuffer( 0 );
|
||||||
|
status_t result = be_roster->Launch( "application/x-vnd.Be.URL.ftp",
|
||||||
|
1, &link );
|
||||||
|
url->UnlockBuffer();
|
||||||
|
// Make sure the user has an FTP client.
|
||||||
|
if( result != B_NO_ERROR && result != B_ALREADY_RUNNING ) {
|
||||||
|
BAlert *alert = new BAlert( "FTP Warning",
|
||||||
|
"There is no FTP client on your machine that is configured as the default program to connect to an FTP server.",
|
||||||
|
"Ok", NULL, NULL, B_WIDTH_AS_USUAL,
|
||||||
|
B_WARNING_ALERT );
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't know how to handle anything else.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::Redraw() {
|
||||||
|
// Redraw the link without flicker.
|
||||||
|
BRect frame = Frame();
|
||||||
|
frame.OffsetTo( B_ORIGIN );
|
||||||
|
Draw( frame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void URLView::WriteAttributes( int fd ) {
|
||||||
|
// Write the developer-defined attributes to the newly-created file.
|
||||||
|
KeyPair *item;
|
||||||
|
for( int i = 0; (item = (KeyPair *) attributes->ItemAt(i)); i++ ) {
|
||||||
|
fs_write_attr( fd, item->key->String(), B_STRING_TYPE, 0, item->value->String(), item->value->Length() + 1 );
|
||||||
|
}
|
||||||
|
}
|
127
src/prefs/sounds/Utils/URLView.h
Normal file
127
src/prefs/sounds/Utils/URLView.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/* URLView 2.0
|
||||||
|
written by William Kakes of Tall Hill Software.
|
||||||
|
|
||||||
|
This class provides an underlined and clickable BStringView
|
||||||
|
that will launch the web browser, e-mail program, or FTP client
|
||||||
|
when clicked on. Other features include hover-highlighting,
|
||||||
|
right-click menus, and drag-and-drop support.
|
||||||
|
|
||||||
|
You are free to use URLView in your own programs (both open-source
|
||||||
|
and closed-source) free of charge, but a mention in your read me
|
||||||
|
file or your program's about box would be appreciated. See
|
||||||
|
http://www.tallhill.com for current contact information.
|
||||||
|
|
||||||
|
URLView is provided as-is, with no warranties of any kind. If
|
||||||
|
you use it, you are on your own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TH_URL_VIEW_H
|
||||||
|
#define TH_URL_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <Cursor.h>
|
||||||
|
#include <List.h>
|
||||||
|
#include <Mime.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This is the link's mouse cursor (a replica of NetPositive's link cursor).
|
||||||
|
const uint8 url_cursor[] = { 16, 1, 1, 2,
|
||||||
|
// This is the cursor data.
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x24, 0x00, 0x24, 0x00,
|
||||||
|
0x13, 0xe0, 0x12, 0x5c, 0x09, 0x2a, 0x08, 0x01,
|
||||||
|
0x3c, 0x21, 0x4c, 0x71, 0x42, 0x71, 0x30, 0xf9,
|
||||||
|
0x0c, 0xf9, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
// This is the cursor mask.
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3c, 0x00,
|
||||||
|
0x1f, 0xe0, 0x1f, 0xfc, 0x0f, 0xfe, 0x0f, 0xff,
|
||||||
|
0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x3f, 0xff,
|
||||||
|
0x0f, 0xff, 0x03, 0xfe, 0x01, 0xf8, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The default link color, blue.
|
||||||
|
const rgb_color blue = { 0, 0, 255 };
|
||||||
|
// The default clicked-link color, red.
|
||||||
|
const rgb_color red = { 255, 0, 0 };
|
||||||
|
// The default link hover color, dark blue.
|
||||||
|
const rgb_color dark_blue = { 0, 0, 120 };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class URLView : public BStringView {
|
||||||
|
public:
|
||||||
|
URLView( BRect frame, const char *name, const char *label, const char *url,
|
||||||
|
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
|
||||||
|
uint32 flags = B_WILL_DRAW );
|
||||||
|
~URLView();
|
||||||
|
|
||||||
|
|
||||||
|
void AttachedToWindow();
|
||||||
|
void Draw( BRect updateRect );
|
||||||
|
void MessageReceived( BMessage *message );
|
||||||
|
void MouseDown( BPoint point );
|
||||||
|
void MouseMoved( BPoint point, uint32 transit, const BMessage *message );
|
||||||
|
void MouseUp( BPoint point );
|
||||||
|
|
||||||
|
void AddAttribute( const char *name, const char *value );
|
||||||
|
void SetColor( rgb_color color );
|
||||||
|
void SetClickColor( rgb_color color );
|
||||||
|
void SetDraggable( bool draggable );
|
||||||
|
void SetHoverColor( rgb_color color );
|
||||||
|
void SetHoverEnabled( bool hover );
|
||||||
|
void SetIconSize( icon_size iconSize );
|
||||||
|
void SetUnderlineThickness( int thickness );
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CopyToClipboard();
|
||||||
|
void CreateBookmark( const BString *fullName, const BString *title );
|
||||||
|
void CreatePerson( const BString *fullName, const BString *title );
|
||||||
|
BPopUpMenu *CreatePopupMenu();
|
||||||
|
void DoBookmarkDrag();
|
||||||
|
void DoPersonDrag();
|
||||||
|
BString GetImportantURL();
|
||||||
|
BRect GetTextRect();
|
||||||
|
BRect GetURLRect();
|
||||||
|
bool IsEmailLink();
|
||||||
|
bool IsFTPLink();
|
||||||
|
void LaunchURL();
|
||||||
|
void Redraw();
|
||||||
|
void WriteAttributes( int fd );
|
||||||
|
|
||||||
|
BString *url;
|
||||||
|
rgb_color color;
|
||||||
|
rgb_color clickColor;
|
||||||
|
rgb_color hoverColor;
|
||||||
|
bool hoverEnabled;
|
||||||
|
bool draggable;
|
||||||
|
int underlineThickness;
|
||||||
|
int iconSize;
|
||||||
|
|
||||||
|
bool selected;
|
||||||
|
bool hovering;
|
||||||
|
bool draggedOut;
|
||||||
|
bool inPopup;
|
||||||
|
const BCursor *linkCursor;
|
||||||
|
BPoint dragOffset;
|
||||||
|
BList *attributes;
|
||||||
|
|
||||||
|
typedef struct kp {
|
||||||
|
BString *key;
|
||||||
|
BString *value;
|
||||||
|
} KeyPair;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TH_URL_VIEW
|
8
src/prefs/sounds/main.cpp
Normal file
8
src/prefs/sounds/main.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "HApp.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
HApp app;
|
||||||
|
app.Run();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user