Implemented a function to allow for R1's prefs to work like R5's

Serious speedups on redraw - needs a little more work
Added the beginnings of thumb tracking
Implemented rapid-fire small-step scrolling when holding down a scroll button
Tweaks to button-drawing code


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5385 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm 2003-11-15 20:47:53 +00:00
parent d5be31007e
commit 745d0b4a95

View File

@ -30,16 +30,23 @@
#include <Rect.h>
#include <stdio.h>
#include <string.h>
#include <ScrollBar.h>
#include <OS.h>
#include <Window.h>
#include "ScrollBar.h"
#define TEST_MODE
typedef enum
{
ARROW_LEFT=0,
ARROW_RIGHT,
ARROW_UP,
ARROW_DOWN
ARROW_DOWN,
ARROW_NONE
} arrow_direction;
#define SBC_SCROLLBYVALUE 0
class BScrollArrowButton : public BView
{
public:
@ -67,20 +74,99 @@ public:
BScrollBarPrivateData(void)
{
thumbframe.Set(0,0,0,0);
get_scroll_bar_info(&sbinfo);
enabled=true;
tracking=false;
mousept.Set(0,0);
thumbinc=1.0;
repeaterid=-1;
exit_repeater=false;
arrowdown=ARROW_NONE;
#ifdef TEST_MODE
sbinfo.proportional=true;
sbinfo.double_arrows=false;
sbinfo.knob=0;
sbinfo.min_knob_size=14;
#else
get_scroll_bar_info(&sbinfo);
#endif
}
~BScrollBarPrivateData(void)
{
if(repeaterid!=-1)
{
exit_repeater=false;
kill_thread(repeaterid);
}
}
static int32 ButtonRepeaterThread(void *data);
thread_id repeaterid;
scroll_bar_info sbinfo;
BRect thumbframe;
bool enabled;
bool tracking;
BPoint mousept;
float thumbinc;
bool exit_repeater;
arrow_direction arrowdown;
};
int32 BScrollBarPrivateData::ButtonRepeaterThread(void *data)
{
BScrollBar *sb=(BScrollBar *)data;
BRect oldframe(sb->privatedata->thumbframe);
// BRect update(sb->privatedata->thumbframe);
snooze(250000);
bool exitval=false;
status_t returnval;
sb->Window()->Lock();
exitval=sb->privatedata->exit_repeater;
sb->Window()->Unlock();
float scrollvalue;
if(sb->privatedata->arrowdown==ARROW_LEFT || sb->privatedata->arrowdown==ARROW_UP)
scrollvalue=-sb->fSmallStep;
else
if(sb->privatedata->arrowdown!=ARROW_NONE)
scrollvalue=sb->fSmallStep;
else
exitval=true;
while(!exitval)
{
oldframe=sb->privatedata->thumbframe;
returnval=control_scrollbar(SBC_SCROLLBYVALUE, &scrollvalue, sb);
snooze(50000);
sb->Window()->Lock();
exitval=sb->privatedata->exit_repeater;
if(returnval==B_OK)
{
sb->CopyBits(oldframe,sb->privatedata->thumbframe);
// TODO: Redraw the old area here
sb->ValueChanged(sb->fValue);
}
sb->Window()->Unlock();
}
sb->Window()->Lock();
sb->privatedata->exit_repeater=false;
sb->privatedata->repeaterid=-1;
sb->Window()->Unlock();
return 0;
exit_thread(0);
}
BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
float max,orientation direction)
: BView(frame, name, B_FOLLOW_NONE, B_WILL_DRAW)
@ -94,7 +180,6 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
fLargeStep=10.0;
fTarget=target;
privatedata=new BScrollBarPrivateData;
privatedata->thumbframe=Bounds();
if(fTarget)
{
@ -111,6 +196,7 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
{
if(frame.Width()>B_V_SCROLL_BAR_WIDTH)
ResizeTo(B_V_SCROLL_BAR_WIDTH,frame.Height());
privatedata->thumbframe=Bounds().InsetByCopy(0,1);
BPoint buttonpt(1,1);
BScrollArrowButton *arrow;
@ -131,6 +217,7 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
AddChild(arrow);
privatedata->thumbframe.bottom=privatedata->sbinfo.min_knob_size;
privatedata->thumbframe.right=privatedata->sbinfo.min_knob_size;
privatedata->thumbframe.OffsetBy(0,arrow->Bounds().Height()+1);
if(privatedata->sbinfo.double_arrows)
@ -146,6 +233,7 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
{
if(frame.Height()>B_H_SCROLL_BAR_HEIGHT)
ResizeTo(frame.Width()+1,B_H_SCROLL_BAR_HEIGHT);
privatedata->thumbframe=Bounds().InsetByCopy(1,0);
BPoint buttonpt(1,1);
BScrollArrowButton *arrow;
@ -158,7 +246,7 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
buttonpt.x+=arrow->Bounds().Width();
arrow=new BScrollArrowButton(buttonpt,"right2",ARROW_RIGHT);
AddChild(arrow);
}
}
privatedata->thumbframe.right=privatedata->sbinfo.min_knob_size;
privatedata->thumbframe.OffsetBy(arrow->Bounds().Width()+1,0);
@ -190,9 +278,9 @@ BScrollBar::BScrollBar(BMessage *data)
BScrollBar::~BScrollBar()
{
delete privatedata;
if(fTargetName)
delete fTargetName;
delete privatedata;
}
BArchivable *BScrollBar::Instantiate(BMessage *data)
@ -356,6 +444,7 @@ void BScrollBar::MouseDown(BPoint pt)
privatedata->tracking=true;
privatedata->mousept=pt;
SetMouseEventMask(0,B_LOCK_WINDOW_FOCUS);
Draw(privatedata->thumbframe);
}
else
{
@ -386,14 +475,18 @@ void BScrollBar::MouseUp(BPoint pt)
{
privatedata->tracking=false;
SetMouseEventMask(0,0);
Draw(privatedata->thumbframe);
}
}
void BScrollBar::MouseMoved(BPoint pt, uint32 code, const BMessage *msg)
void BScrollBar::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg)
{
if(!privatedata->enabled)
return;
if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW)
MouseUp(privatedata->mousept);
if(privatedata->tracking)
{
float delta;
@ -411,7 +504,7 @@ void BScrollBar::MouseMoved(BPoint pt, uint32 code, const BMessage *msg)
return;
delta=pt.x-privatedata->mousept.x;
}
DoScroll(delta);
control_scrollbar(SBC_SCROLLBYVALUE, &delta, this);
ValueChanged(fValue);
Draw(Bounds());
privatedata->mousept=pt;
@ -466,8 +559,10 @@ void BScrollBar::Draw(BRect updateRect)
dark=tint_color(c,B_DARKEN_3_TINT);
normal=c;
}
SetHighColor(normal);
FillRect(Bounds());
FillRect(updateRect);
SetHighColor(dark);
StrokeRect(Bounds());
@ -485,7 +580,10 @@ void BScrollBar::Draw(BRect updateRect)
StrokeLine(r.LeftTop(),r.LeftBottom());
r.InsetBy(1,1);
SetHighColor(normal);
if(privatedata->tracking)
SetHighColor(tint_color(normal,B_DARKEN_1_TINT));
else
SetHighColor(normal);
FillRect(r);
}
@ -562,7 +660,7 @@ BScrollBar &BScrollBar::operator=(const BScrollBar &)
BScrollArrowButton::BScrollArrowButton(BPoint location,
const char *name, arrow_direction dir)
:BView(BRect(0,0,B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT).OffsetToCopy(location),name, B_FOLLOW_NONE, B_WILL_DRAW)
:BView(BRect(0,0,B_V_SCROLL_BAR_WIDTH-1,B_H_SCROLL_BAR_HEIGHT-1).OffsetToCopy(location),name, B_FOLLOW_NONE, B_WILL_DRAW)
{
fDirection=dir;
enabled=true;
@ -615,47 +713,27 @@ void BScrollArrowButton::MouseDown(BPoint pt)
Draw(Bounds());
// Test for which button clicked here
status_t returnval=B_ERROR;
if(parent && parent->fTarget)
{
if(fDirection==ARROW_LEFT || fDirection==ARROW_UP)
if(parent)
{
parent->privatedata->arrowdown=fDirection;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&parent->fSmallStep,parent);
if(returnval==B_OK)
{
if(parent->fValue - parent->fSmallStep >= parent->fMin)
{
parent->fValue -= parent->fSmallStep;
if(fDirection==ARROW_UP)
{
parent->fTarget->ScrollBy(0,-parent->fSmallStep);
parent->privatedata->thumbframe.OffsetBy(0,-parent->fSmallStep);
}
else
{
parent->fTarget->ScrollBy(-parent->fSmallStep,0);
parent->privatedata->thumbframe.OffsetBy(-parent->fSmallStep,0);
}
parent->fValue--;
}
parent->Draw(parent->Bounds());
}
else // right or down
if(parent->fValue + parent->fSmallStep <= parent->fMax)
{
parent->fValue += parent->fSmallStep;
if(fDirection==ARROW_DOWN)
parent->ValueChanged(parent->fValue);
if(parent->privatedata->repeaterid==-1)
{
parent->fTarget->ScrollBy(0,parent->fSmallStep);
parent->privatedata->thumbframe.OffsetBy(0,parent->fSmallStep);
parent->privatedata->exit_repeater=false;
parent->privatedata->repeaterid=spawn_thread(parent->privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,parent);
resume_thread(parent->privatedata->repeaterid);
}
else
{
parent->fTarget->ScrollBy(parent->fSmallStep,0);
parent->privatedata->thumbframe.OffsetBy(parent->fSmallStep,0);
}
parent->fValue++;
parent->Draw(parent->Bounds());
}
}
}
void BScrollArrowButton::MouseUp(BPoint pt)
@ -663,12 +741,17 @@ void BScrollArrowButton::MouseUp(BPoint pt)
if(enabled)
{
mousedown=false;
if(parent)
{
parent->privatedata->arrowdown=ARROW_NONE;
parent->privatedata->exit_repeater=true;
}
Draw(Bounds());
}
}
void BScrollArrowButton::MouseMoved(BPoint pt, uint32 transit, const
BMessage *msg)
void BScrollArrowButton::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg)
{
if(enabled==false)
return;
@ -686,11 +769,9 @@ BMessage *msg)
mousedown=true;
Draw(Bounds());
}
if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW)
{
mousedown=false;
Draw(Bounds());
}
MouseUp(Bounds().LeftTop());
}
void BScrollArrowButton::Draw(BRect update)
@ -698,25 +779,28 @@ void BScrollArrowButton::Draw(BRect update)
rgb_color c=ui_color(B_PANEL_BACKGROUND_COLOR);
BRect r(Bounds());
rgb_color light, dark, normal,arrow;
rgb_color light, dark, normal,arrow,arrow2;
if(mousedown)
{
light=tint_color(c,B_DARKEN_3_TINT);
dark=tint_color(c,B_LIGHTEN_MAX_TINT);
arrow2=dark=tint_color(c,B_LIGHTEN_MAX_TINT);
normal=c;
arrow=tint_color(c,B_DARKEN_MAX_TINT);
}
else
if(enabled)
{
light=tint_color(c,B_LIGHTEN_MAX_TINT);
arrow2=light=tint_color(c,B_LIGHTEN_MAX_TINT);
dark=tint_color(c,B_DARKEN_3_TINT);
normal=c;
arrow=tint_color(c,B_DARKEN_MAX_TINT);
}
else
{
// haven't gotten this far yet - disabled button
arrow2=light=tint_color(c,B_LIGHTEN_1_TINT);
dark=tint_color(c,B_DARKEN_1_TINT);
normal=c;
arrow=tint_color(c,B_DARKEN_1_TINT);
}
r.InsetBy(1,1);
@ -736,6 +820,8 @@ void BScrollArrowButton::Draw(BRect update)
SetHighColor(light);
StrokeLine(r.LeftTop(),r.RightTop());
StrokeLine(r.LeftTop(),r.LeftBottom());
SetHighColor(arrow2);
StrokeLine(tri1,tri2);
}
@ -754,3 +840,150 @@ void BScrollArrowButton::SetEnabled(bool value)
{
enabled=value;
}
/*
This cheat function will allow the scrollbar prefs app to act exactly like R5's and
perform other stuff without mucking around with the virtual tables B_BAD_VALUE is
returned when a NULL scrollbar pointer is passed to it
Command list:
0: Scroll By Value: increment or decrement scrollbar's value by a certain amount.
data parameter is cast to a float * and used to modify the value.
Returns B_OK if everthing went well and the caller is to redraw the scrollbar
B_ERROR is returned if the caller doesn't need to do anything
B_BAD_VALUE is returned if data is NULL
*/
status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
{
if(!sb)
return B_BAD_VALUE;
switch(command)
{
case 0:
{
if(!data)
return B_BAD_VALUE;
float datavalue=*((float *)data);
if(datavalue==0)
return B_ERROR;
/* if(sb->privatedata->arrowdown==ARROW_LEFT || sb->privatedata->arrowdown==ARROW_UP)
{
if(sb->fValue - datavalue >= sb->fMin)
{
sb->fValue -= datavalue;
if(sb->privatedata->arrowdown==ARROW_UP)
{
if(sb->fTarget)
sb->fTarget->ScrollBy(0,-datavalue);
sb->privatedata->thumbframe.OffsetBy(0,-datavalue);
}
else
{
if(sb->fTarget)
sb->fTarget->ScrollBy(-datavalue,0);
sb->privatedata->thumbframe.OffsetBy(-datavalue,0);
}
sb->fValue--;
return B_OK;
}
}
else
{
if(sb->fValue + datavalue <= sb->fMax)
{
sb->fValue += datavalue;
if(sb->privatedata->arrowdown==ARROW_DOWN)
{
if(sb->fTarget)
sb->fTarget->ScrollBy(0,datavalue);
sb->privatedata->thumbframe.OffsetBy(0,datavalue);
}
else
{
if(sb->fTarget)
sb->fTarget->ScrollBy(datavalue,0);
sb->privatedata->thumbframe.OffsetBy(datavalue,0);
}
sb->fValue++;
return B_OK;
}
}
*/
if(sb->fOrientation==B_VERTICAL)
{
if(datavalue<0)
{
if(sb->fValue + datavalue >= sb->fMin)
{
sb->fValue += datavalue;
if(sb->fTarget)
sb->fTarget->ScrollBy(0,datavalue);
sb->privatedata->thumbframe.OffsetBy(0,datavalue);
sb->fValue--;
return B_OK;
}
// fall through to return B_ERROR
}
else
{
if(sb->fValue + datavalue <= sb->fMax)
{
sb->fValue += datavalue;
if(sb->fTarget)
sb->fTarget->ScrollBy(0,datavalue);
sb->privatedata->thumbframe.OffsetBy(0,datavalue);
sb->fValue++;
return B_OK;
}
// fall through to return B_ERROR
}
}
else
{
if(datavalue<0)
{
if(sb->fValue + datavalue >= sb->fMin)
{
sb->fValue += datavalue;
if(sb->fTarget)
sb->fTarget->ScrollBy(datavalue,0);
sb->privatedata->thumbframe.OffsetBy(datavalue,0);
sb->fValue--;
return B_OK;
}
// fall through to return B_ERROR
}
else
{
if(sb->fValue + datavalue <= sb->fMax)
{
sb->fValue += datavalue;
if(sb->fTarget)
sb->fTarget->ScrollBy(datavalue,0);
sb->privatedata->thumbframe.OffsetBy(datavalue,0);
sb->fValue++;
return B_OK;
}
// fall through to return B_ERROR
}
}
return B_ERROR;
}// end case 0 (Scroll By Value)
default:
{
printf("Unknown command value %d in control_scrollbar\n",command);
break;
}
} // end command switch
// We should never get here unless I've done something dumb in calling the function
return B_BAD_VALUE;
}