haiku/src/preferences/appearance/CurView.cpp
Axel Dörfler a10cf76ef5 Renamed src/prefs to "preferences", as the directory is usually called in BeOS.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13263 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-06-24 15:57:12 +00:00

490 lines
13 KiB
C++

//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: CurView.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Description: cursor handler for the app
//
//------------------------------------------------------------------------------
#include <OS.h>
#include <Directory.h>
#include <Alert.h>
#include <storage/Path.h>
#include <Entry.h>
#include <File.h>
#include <stdio.h>
#include "CursorWhichItem.h"
#include "CurView.h"
#include <PortLink.h>
#include "defs.h"
#include "ServerConfig.h"
#include <ServerProtocol.h>
#include <PortMessage.h>
#include <InterfaceDefs.h>
#include <TranslationUtils.h>
//#define DEBUG_CURSORSET
#define SAVE_CURSORSET 'svcu'
#define DELETE_CURSORSET 'dlcu'
#define LOAD_CURSORSET 'ldcu'
#define CURSOR_UPDATED 'csru'
CurView::CurView(const BRect &frame, const char *name, int32 resize, int32 flags)
:BView(frame,name,resize,flags), settings(B_SIMPLE_DATA)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
cursorset=new CursorSet("Default");
/*
// Code disabled -- cursor set management belongs in another app
BMenuBar *mb=new BMenuBar(BRect(0,0,Bounds().Width(),16),"menubar");
settings_menu=new BMenu("Settings");
settings_menu->AddItem(new BMenuItem("Save Cursor Set",new BMessage(SAVE_CURSORSET),'S'));
settings_menu->AddSeparatorItem();
settings_menu->AddItem(new BMenuItem("Delete Cursor Set",new BMessage(DELETE_CURSORSET)));
mb->AddItem(settings_menu);
cursorset_menu=LoadCursorSets();
if(cursorset_menu)
mb->AddItem(cursorset_menu);
else
{
// We should *never* be here, but just in case....
cursorset_menu=new BMenu("Cursor Sets");
mb->AddItem(cursorset_menu);
}
AddChild(mb);
*/
BRect wellrect(0,0,20,20);
wellrect.OffsetTo(10,25);
wellrect.right=wellrect.left+50;
/*
// Code disabled -- cursor set management belongs in another app
cursorset_label=new BStringView(wellrect,"cursorset_label","Cursor Set: ");
AddChild(cursorset_label);
cursorset_label->ResizeToPreferred();
cursorset_name="<untitled>";
*/
// Set up list of cursor attributes
BRect cvrect;
BRect rect;
cvrect.Set(0,0,75,75);
bmpview=new BitmapView(BPoint(10,10),new BMessage(CURSOR_UPDATED),this);
bmpview->MoveTo( (Bounds().Width()-bmpview->Bounds().Width())/2,30);
AddChild(bmpview);
rect.left=(Bounds().Width()-200)/2;
rect.right=rect.left+190;
rect.top=bmpview->Frame().bottom+30;
rect.bottom=rect.top+100;
attrlist=new BListView(rect,"AttributeList");
scrollview=new BScrollView("ScrollView",attrlist, B_FOLLOW_LEFT |
B_FOLLOW_TOP, 0, false, true);
AddChild(scrollview);
scrollview->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
attrlist->SetSelectionMessage(new BMessage(ATTRIBUTE_CHOSEN));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_DEFAULT));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_TEXT));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_MOVE));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_DRAG));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_RESIZE));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_RESIZE_NWSE));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_RESIZE_NESW));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_RESIZE_NS));
attrlist->AddItem(new CursorWhichItem(B_CURSOR_RESIZE_EW));
cvrect.Set(0,0,60,30);
cvrect.OffsetTo( (Bounds().Width()-200)/2,scrollview->Frame().bottom+20);
defaults=new BButton(cvrect,"DefaultsButton","Defaults",
new BMessage(DEFAULT_SETTINGS),B_FOLLOW_LEFT |B_FOLLOW_TOP,
B_WILL_DRAW | B_NAVIGABLE);
AddChild(defaults);
cvrect.OffsetBy(70,0);
revert=new BButton(cvrect,"RevertButton","Revert",
new BMessage(REVERT_SETTINGS),B_FOLLOW_LEFT |B_FOLLOW_TOP,
B_WILL_DRAW | B_NAVIGABLE);
AddChild(revert);
revert->SetEnabled(false);
cvrect.OffsetBy(70,0);
apply=new BButton(cvrect,"ApplyButton","Apply",
new BMessage(APPLY_SETTINGS),B_FOLLOW_LEFT |B_FOLLOW_TOP,
B_WILL_DRAW | B_NAVIGABLE);
AddChild(apply);
apply->SetEnabled(false);
BEntry entry(COLOR_SET_DIR);
entry_ref ref;
entry.GetRef(&ref);
attribute=B_PANEL_BACKGROUND_COLOR;
attrstring="Background";
LoadSettings();
}
CurView::~CurView(void)
{
delete cursorset;
}
void CurView::AllAttached(void)
{
attrlist->Select(0);
attrlist->SetTarget(this);
apply->SetTarget(this);
defaults->SetTarget(this);
revert->SetTarget(this);
bmpview->SetTarget(this);
BMessenger msgr(this);
}
void CurView::MessageReceived(BMessage *msg)
{
if(msg->WasDropped())
{
}
switch(msg->what)
{
case CURSOR_UPDATED:
{
CursorWhichItem *cwi=(CursorWhichItem*)attrlist->ItemAt(attrlist->CurrentSelection());
if(cwi)
cwi->SetBitmap(bmpview->GetBitmap());
break;
}
case ATTRIBUTE_CHOSEN:
{
CursorWhichItem *cwi=(CursorWhichItem*)attrlist->ItemAt(attrlist->CurrentSelection());
if(cwi)
{
bmpview->SetBitmap(cwi->GetBitmap());
bmpview->Invalidate();
}
break;
}
default:
BView::MessageReceived(msg);
break;
}
}
/*
// Code disabled -- cursor set management belongs in another app
BMenu *CurView::LoadCursorSets(void)
{
#ifdef DEBUG_CURSORSET
printf("Loading cursor sets from disk\n");
#endif
// This function populates the member menu *cursorset_menu with the cursor
// set files located in the cursor set directory. To ensure that there are
// no entries pointing to invalid cursor sets, they are validated before
// a menu item is added.
BDirectory dir;
BEntry entry;
BPath path;
BString name;
BMenu *menu=new BMenu("Cursor Sets");
status_t dirstat=dir.SetTo(COLOR_SET_DIR);
if(dirstat!=B_OK)
{
// We couldn't set the directory, so more than likely it just
// doesn't exist. Create it and return an empty menu.
switch(dirstat)
{
case B_NAME_TOO_LONG:
{
BAlert *a=new BAlert("OpenBeOS","Couldn't open the folder for cursor sets. "
"You will be able to change system cursors, but be unable to save them to a cursor set. "
"Please contact OpenBeOS about Appearance Preferences::CurView::"
"LoadCursorSets::B_NAME_TOO_LONG for a bugfix", "OK",
NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
a->Go();
break;
}
case B_ENTRY_NOT_FOUND:
{
create_directory(COLOR_SET_DIR,0777);
break;
}
case B_BAD_VALUE:
{
printf("CurView::LoadCursorSets(): Invalid cursorset folder path.\n");
break;
}
case B_NO_MEMORY:
{
printf("CurView::LoadCursorSets(): No memory left. We're probably going to crash now. \n");
break;
}
case B_BUSY:
{
printf("CurView::LoadCursorSets(): Busy node " CURSOR_SET_DIR "\n");
break;
}
case B_FILE_ERROR:
{
BAlert *a=new BAlert("OpenBeOS","Couldn't open the folder for cursor sets "
"because of a file error. Perhaps there is a file (instead of a folder) at " COLOR_SET_DIR
"? You will be able to change system cursors, but be unable to save them to a cursor set. ",
"OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
a->Go();
break;
}
case B_NO_MORE_FDS:
{
BAlert *a=new BAlert("OpenBeOS","Couldn't open the folder for cursor sets "
"because there are too many open files. Please close some files and restart "
" this application.", "OK",
NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
a->Go();
if(Window())
Window()->PostMessage(B_QUIT_REQUESTED);
break;
}
}
return menu;
}
int32 count=dir.CountEntries();
BMessage *msg;
CursorSet cs(NULL);
for(int32 i=0;i<count;i++)
{
dir.GetNextEntry(&entry);
entry.GetPath(&path);
if(cs.Load(path.Path())!=B_OK)
continue;
// Don't include the default set in the menu
name=path.Leaf();
if(name.Compare("Default")==0)
continue;
name=path.Path();
name.Remove(0,name.FindLast('/')+1);
msg=new BMessage(LOAD_CURSORSET);
msg->AddString("name",name);
menu->AddItem(new BMenuItem(name.String(),msg));
}
return menu;
}
void CurView::SetCursorSetName(const char *name)
{
if(!name)
return;
BString namestr("Cursor Set: ");
cursorset_name=name;
namestr+=name;
cursorset_label->SetText(namestr.String());
cursorset_label->ResizeToPreferred();
cursorset_label->Invalidate();
}
*/
void CurView::SaveSettings(void)
{
// Save the current GUI cursor settings to the GUI cursors file in the
// path specified in defs.h
BString path(SERVER_SETTINGS_DIR);
path+=CURSOR_SETTINGS_NAME;
#ifdef DEBUG_CURSORSET
printf("SaveSettings: %s\n",path.String());
#endif
cursorset->Save(path.String(),B_CREATE_FILE|B_ERASE_FILE);
// prev_set_name=cursorset_name;
revert->SetEnabled(false);
}
void CurView::LoadSettings(void)
{
// Load the current GUI cursor settings from disk. This is done instead of
// getting them from the server at this point for testing purposes. Comment
// out the #define LOAD_SETTINGS_FROM_DISK line to use the server query code
#ifdef DEBUG_CURSORSET
printf("Loading settings from disk\n");
#endif
settings.MakeEmpty();
BDirectory dir,newdir;
if(dir.SetTo(SERVER_SETTINGS_DIR)==B_ENTRY_NOT_FOUND)
{
#ifdef DEBUG_CURSORSET
printf("Cursor set folder not found. Creating %s\n",SERVER_SETTINGS_DIR);
#endif
create_directory(SERVER_SETTINGS_DIR,0777);
}
BString path(SERVER_SETTINGS_DIR);
path+=CURSOR_SETTINGS_NAME;
status_t stat=cursorset->Load(path.String());
if(stat!=B_OK)
{
#ifdef DEBUG_CURSORSET
printf("Couldn't open file %s for read\n",path.String());
#endif
SetDefaults();
SaveSettings();
}
return;
}
void CurView::SetDefaults(void)
{
// The server will perform the necessary work to set defaults, so just ask it to do the
// work for us. It is a synchronous procedure, so we will notify the server and load the cursor
// set 'Default'.
BString string(CURSOR_SET_DIR);
string+="Default";
cursorset->Load(string.String());
port_id port=find_port(SERVER_PORT_NAME);
if(port==B_NAME_NOT_FOUND)
return;
BPrivate::PortLink link(port);
int32 code;
link.StartMessage(AS_SET_SYSCURSOR_DEFAULTS);
link.Flush();
link.GetNextMessage(code);
}
BitmapView::BitmapView(const BPoint &pt,BMessage *message, const BHandler *handler, const BLooper *looper=NULL)
: BBox(BRect(0,0,75,75).OffsetToCopy(pt),"bitmapview",B_FOLLOW_NONE,B_WILL_DRAW, B_PLAIN_BORDER),
BInvoker(message,handler,looper)
{
SetFont(be_plain_font);
bitmap=NULL;
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetDrawingMode(B_OP_ALPHA);
drawrect=Bounds().InsetByCopy(5,5);
}
BitmapView::~BitmapView(void)
{
}
void BitmapView::SetBitmap(BBitmap *bmp)
{
bitmap=bmp;
}
void BitmapView::Draw(BRect r)
{
BBox::Draw(r);
if(bitmap)
DrawBitmap(bitmap, drawrect);
}
void BitmapView::MessageReceived(BMessage *msg)
{
if(msg->WasDropped())
{
entry_ref ref;
if(msg->FindRef("refs",&ref)!=B_OK)
return;
BBitmap *tmp=BTranslationUtils::GetBitmap(&ref);
if(tmp)
{
delete bitmap;
bitmap=tmp;
int32 offset;
BRect r(Bounds());
r.right-=10;
r.bottom-=10;
drawrect=bitmap->Bounds();
if(r.Contains(bitmap->Bounds()))
{
// calculate a centered rect for direct display
offset=((r.IntegerWidth()-bitmap->Bounds().IntegerWidth()) >> 1)+5;
drawrect.OffsetBy(offset,offset);
}
else
{
// calculate a scaled-down rectangle for display
drawrect.left=drawrect.top=0;
if(bitmap->Bounds().Height() > bitmap->Bounds().Width())
{
drawrect.right=(r.Height()*bitmap->Bounds().Width())/bitmap->Bounds().Height();
drawrect.bottom=r.Height();
offset=((r.IntegerWidth()-drawrect.IntegerWidth()) >> 1)+5;
drawrect.OffsetBy(offset,5);
}
else
{
drawrect.bottom=(r.Width()*bitmap->Bounds().Height())/bitmap->Bounds().Width();
drawrect.right=r.Width();
offset=((r.IntegerHeight()-drawrect.IntegerHeight()) >> 1)+5;
drawrect.OffsetBy(5,offset);
}
}
Invoke();
Invalidate();
return;
}
}
else
BBox::MessageReceived(msg);
}