Converted display and interaction with scrollbar buttons from using BViews to having them be part of the scrollbar itself

Double and single modes should look the right way


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5388 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm
2003-11-16 17:52:05 +00:00
parent bf461dbeb4
commit 9107dffadc
+496 -344
View File
@@ -46,34 +46,26 @@ typedef enum
} arrow_direction; } arrow_direction;
#define SBC_SCROLLBYVALUE 0 #define SBC_SCROLLBYVALUE 0
#define SBC_SETDOUBLE 1
#define SBC_SETPROPORTIONAL 2
#define SBC_SETSTYLE 3
class BScrollArrowButton : public BView // Quick constants for determining which arrow is down and are defined with respect
{ // to double arrow mode. ARROW1 and ARROW4 refer to the outer pair of arrows and
public: // ARROW2 and ARROW3 refer to the inner ones. ARROW1 points left/up and ARROW4
BScrollArrowButton(BPoint location, const char *name, // points right/down.
arrow_direction dir); #define ARROW1 0
~BScrollArrowButton(void); #define ARROW2 1
void AttachedToWindow(void); #define ARROW3 2
void DetachedToWindow(void); #define ARROW4 3
void MouseDown(BPoint pt); #define NOARROW -1
void MouseUp(BPoint pt);
void MouseMoved(BPoint pt, uint32 code, const BMessage *msg);
void Draw(BRect update);
void SetEnabled(bool value);
private:
arrow_direction fDirection;
BPoint tri1,tri2,tri3;
BScrollBar *parent;
bool mousedown;
bool enabled;
};
class BScrollBarPrivateData class BScrollBarPrivateData
{ {
public: public:
BScrollBarPrivateData(void) BScrollBarPrivateData(void)
{ {
thumbframe.Set(0,0,0,0); thumbframe.Set(0,0,B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT);
enabled=true; enabled=true;
tracking=false; tracking=false;
mousept.Set(0,0); mousept.Set(0,0);
@@ -81,6 +73,7 @@ public:
repeaterid=-1; repeaterid=-1;
exit_repeater=false; exit_repeater=false;
arrowdown=ARROW_NONE; arrowdown=ARROW_NONE;
buttondown=NOARROW;
#ifdef TEST_MODE #ifdef TEST_MODE
sbinfo.proportional=true; sbinfo.proportional=true;
@@ -100,7 +93,11 @@ public:
kill_thread(repeaterid); kill_thread(repeaterid);
} }
} }
void DrawScrollBarButton(BScrollBar *owner, arrow_direction direction,
const BPoint &offset, bool down=false);
static int32 ButtonRepeaterThread(void *data); static int32 ButtonRepeaterThread(void *data);
thread_id repeaterid; thread_id repeaterid;
scroll_bar_info sbinfo; scroll_bar_info sbinfo;
BRect thumbframe; BRect thumbframe;
@@ -110,6 +107,7 @@ public:
float thumbinc; float thumbinc;
bool exit_repeater; bool exit_repeater;
arrow_direction arrowdown; arrow_direction arrowdown;
int8 buttondown;
}; };
int32 BScrollBarPrivateData::ButtonRepeaterThread(void *data) int32 BScrollBarPrivateData::ButtonRepeaterThread(void *data)
@@ -195,74 +193,24 @@ BScrollBar::BScrollBar(BRect frame,const char *name,BView *target,float min,
if(direction==B_VERTICAL) if(direction==B_VERTICAL)
{ {
if(frame.Width()>B_V_SCROLL_BAR_WIDTH) if(frame.Width()>B_V_SCROLL_BAR_WIDTH)
ResizeTo(B_V_SCROLL_BAR_WIDTH,frame.Height()); ResizeTo(B_V_SCROLL_BAR_WIDTH,frame.Height()+1);
privatedata->thumbframe=Bounds().InsetByCopy(0,1);
BPoint buttonpt(1,1);
BScrollArrowButton *arrow;
arrow=new BScrollArrowButton(buttonpt,"up",ARROW_UP);
AddChild(arrow);
if(privatedata->sbinfo.double_arrows)
{
buttonpt.y+=arrow->Bounds().Height();
arrow=new BScrollArrowButton(BPoint(1,
B_V_SCROLL_BAR_WIDTH+2),"down2",ARROW_DOWN);
AddChild(arrow);
}
buttonpt.y=Bounds().bottom-B_H_SCROLL_BAR_HEIGHT-1;
arrow=new BScrollArrowButton(buttonpt,"down",ARROW_DOWN);
AddChild(arrow);
privatedata->thumbframe.bottom=privatedata->sbinfo.min_knob_size; 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) if(privatedata->sbinfo.double_arrows)
{ privatedata->thumbframe.OffsetBy(0,(B_H_SCROLL_BAR_HEIGHT+1)*2);
buttonpt.y-=arrow->Bounds().Height()+1; else
arrow=new BScrollArrowButton(buttonpt,"up2",ARROW_UP); privatedata->thumbframe.OffsetBy(0,B_H_SCROLL_BAR_HEIGHT+1);
AddChild(arrow);
privatedata->thumbframe.OffsetBy(0,arrow->Bounds().Height()+1);
}
} }
else else
{ {
if(frame.Height()>B_H_SCROLL_BAR_HEIGHT) if(frame.Height()>B_H_SCROLL_BAR_HEIGHT)
ResizeTo(frame.Width()+1,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;
arrow=new BScrollArrowButton(buttonpt,"left",ARROW_LEFT);
AddChild(arrow);
if(privatedata->sbinfo.double_arrows)
{
buttonpt.x+=arrow->Bounds().Width();
arrow=new BScrollArrowButton(buttonpt,"right2",ARROW_RIGHT);
AddChild(arrow);
}
privatedata->thumbframe.right=privatedata->sbinfo.min_knob_size; privatedata->thumbframe.right=privatedata->sbinfo.min_knob_size;
privatedata->thumbframe.OffsetBy(arrow->Bounds().Width()+1,0);
arrow=new BScrollArrowButton(BPoint(Bounds().right-B_V_SCROLL_BAR_WIDTH+1,1),
"right",ARROW_RIGHT);
AddChild(arrow);
if(privatedata->sbinfo.double_arrows) if(privatedata->sbinfo.double_arrows)
{ privatedata->thumbframe.OffsetBy((B_V_SCROLL_BAR_WIDTH+1)*2,0);
buttonpt.x-=arrow->Bounds().Width()+1; else
arrow=new BScrollArrowButton(buttonpt,"left2",ARROW_LEFT); privatedata->thumbframe.OffsetBy(B_V_SCROLL_BAR_WIDTH+1,0);
AddChild(arrow);
privatedata->thumbframe.OffsetBy(arrow->Bounds().Width()+1,0);
}
} }
SetResizingMode( (direction==B_VERTICAL)? SetResizingMode( (direction==B_VERTICAL)?
@@ -325,32 +273,6 @@ void BScrollBar::ValueChanged(float newValue)
void BScrollBar::SetRange(float min, float max) void BScrollBar::SetRange(float min, float max)
{ {
if(min==0 && max==0 && privatedata->enabled)
{
BScrollArrowButton *arrow;
int32 i=0;
arrow=(BScrollArrowButton *)ChildAt(i++);
while(arrow)
{
arrow->SetEnabled(false);
arrow=(BScrollArrowButton *)ChildAt(i++);
}
privatedata->enabled=false;
}
else
if(fMin==0 && fMax==0 && privatedata->enabled==false)
{
BScrollArrowButton *arrow;
int32 i=0;
arrow=(BScrollArrowButton *)ChildAt(i++);
while(arrow)
{
arrow->SetEnabled(true);
arrow=(BScrollArrowButton *)ChildAt(i++);
}
privatedata->enabled=true;
}
fMin=min; fMin=min;
fMax=max; fMax=max;
@@ -360,6 +282,7 @@ void BScrollBar::SetRange(float min, float max)
if(fValue<fMin) if(fValue<fMin)
fValue=fMin; fValue=fMin;
Draw(Bounds());
// Just a sort-of hack for now. ValueChanged is called, but with // Just a sort-of hack for now. ValueChanged is called, but with
// what value?? // what value??
@@ -437,40 +360,287 @@ void BScrollBar::MessageReceived(BMessage *msg)
void BScrollBar::MouseDown(BPoint pt) void BScrollBar::MouseDown(BPoint pt)
{ {
if(privatedata->enabled) if(!(fMin==0 && fMax==0)) // if enabled
{ {
// Hit test for thumb
if(privatedata->thumbframe.Contains(pt)) if(privatedata->thumbframe.Contains(pt))
{ {
privatedata->tracking=true; privatedata->tracking=true;
privatedata->mousept=pt; privatedata->mousept=pt;
SetMouseEventMask(0,B_LOCK_WINDOW_FOCUS); SetMouseEventMask(0,B_LOCK_WINDOW_FOCUS);
Draw(privatedata->thumbframe); Draw(privatedata->thumbframe);
return;
} }
else
{ BRect buttonrect(0,0,B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT);
// figure out which way to scroll by fLargeStep float scrollval=0;
status_t returnval=B_ERROR;
// Hit test for arrow buttons
if(fOrientation==B_VERTICAL) if(fOrientation==B_VERTICAL)
{ {
if(buttonrect.Contains(pt))
{
scrollval= -fSmallStep;
privatedata->arrowdown=ARROW_UP;
privatedata->buttondown=ARROW1;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
buttonrect.OffsetTo(0,Bounds().Height() - (B_H_SCROLL_BAR_HEIGHT));
if(buttonrect.Contains(pt))
{
scrollval= fSmallStep;
privatedata->arrowdown=ARROW_DOWN;
privatedata->buttondown=ARROW4;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
if(privatedata->sbinfo.double_arrows)
{
buttonrect.OffsetTo(0,B_H_SCROLL_BAR_HEIGHT+1);
if(buttonrect.Contains(pt))
{
scrollval= fSmallStep;
privatedata->arrowdown=ARROW_DOWN;
privatedata->buttondown=ARROW2;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
buttonrect.OffsetTo(0,Bounds().Height()-( (B_H_SCROLL_BAR_HEIGHT*2)+1 ));
if(buttonrect.Contains(pt))
{
scrollval= -fSmallStep;
privatedata->arrowdown=ARROW_UP;
privatedata->buttondown=ARROW3;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
}
// TODO: add a repeater thread for large stepping and a call to it
if(pt.y<privatedata->thumbframe.top) if(pt.y<privatedata->thumbframe.top)
DoScroll(-fLargeStep); {
else scrollval=-fLargeStep;
DoScroll(fLargeStep); control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
} }
else else
{ {
if(pt.x<privatedata->thumbframe.left) scrollval=fLargeStep;
DoScroll(-fLargeStep); control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
}
}
else else
DoScroll(fLargeStep); {
if(buttonrect.Contains(pt))
{
scrollval= -fSmallStep;
privatedata->arrowdown=ARROW_LEFT;
privatedata->buttondown=ARROW1;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
buttonrect.OffsetTo(Bounds().Width() - (B_V_SCROLL_BAR_WIDTH),0);
if(buttonrect.Contains(pt))
{
scrollval= fSmallStep;
privatedata->arrowdown=ARROW_RIGHT;
privatedata->buttondown=ARROW4;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
if(privatedata->sbinfo.proportional)
{
buttonrect.OffsetTo(B_V_SCROLL_BAR_WIDTH+1,0);
if(buttonrect.Contains(pt))
{
scrollval= fSmallStep;
privatedata->buttondown=ARROW2;
privatedata->arrowdown=ARROW_LEFT;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
buttonrect.OffsetTo(Bounds().Width()-( (B_V_SCROLL_BAR_WIDTH*2)+1 ),0);
if(buttonrect.Contains(pt))
{
scrollval= -fSmallStep;
privatedata->buttondown=ARROW3;
privatedata->arrowdown=ARROW_RIGHT;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
if(returnval==B_OK)
{
Draw(buttonrect);
ValueChanged(fValue);
if(privatedata->repeaterid==-1)
{
privatedata->exit_repeater=false;
privatedata->repeaterid=spawn_thread(privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,this);
resume_thread(privatedata->repeaterid);
}
}
return;
}
}
// We got this far, so apparently the user has clicked on something
// that isn't the thumb or a scroll button, so scroll by a large step
// TODO: add a repeater thread for large stepping and a call to it
if(pt.x<privatedata->thumbframe.left)
{
scrollval=-fLargeStep;
control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
}
else
{
scrollval=fLargeStep;
control_scrollbar(SBC_SCROLLBYVALUE,&scrollval,this);
}
} }
ValueChanged(fValue); ValueChanged(fValue);
Draw(Bounds()); Draw(Bounds());
} }
} }
}
void BScrollBar::MouseUp(BPoint pt) void BScrollBar::MouseUp(BPoint pt)
{ {
privatedata->arrowdown=ARROW_NONE;\
privatedata->buttondown=NOARROW;
privatedata->exit_repeater=true;
// We'll be lazy here and just draw all the possible arrow regions for now...
// TODO: optimize
BRect r(0,0,B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT);
if(fOrientation==B_VERTICAL)
{
r.bottom+=B_H_SCROLL_BAR_HEIGHT+1;
Draw(r);
r.OffsetTo(0,Bounds().Height()-((B_H_SCROLL_BAR_HEIGHT*2)+1) );
Draw(r);
}
else
{
r.bottom+=B_V_SCROLL_BAR_WIDTH+1;
Draw(r);
r.OffsetTo(0,Bounds().Height()-((B_V_SCROLL_BAR_WIDTH*2)+1) );
Draw(r);
}
if(privatedata->tracking) if(privatedata->tracking)
{ {
privatedata->tracking=false; privatedata->tracking=false;
@@ -560,18 +730,69 @@ void BScrollBar::Draw(BRect updateRect)
normal=c; normal=c;
} }
// Draw main area
SetHighColor(normal); SetHighColor(normal);
FillRect(updateRect); FillRect(updateRect);
SetHighColor(dark); SetHighColor(dark);
StrokeRect(Bounds()); StrokeRect(Bounds());
// Draw arrows
BPoint buttonpt(0,0);
if(fOrientation==B_HORIZONTAL)
{
privatedata->DrawScrollBarButton(this, ARROW_LEFT, buttonpt,
privatedata->buttondown==ARROW1);
if(privatedata->sbinfo.double_arrows)
{
buttonpt.Set(B_V_SCROLL_BAR_WIDTH+1,0);
privatedata->DrawScrollBarButton(this, ARROW_RIGHT, buttonpt,
privatedata->buttondown==ARROW2);
buttonpt.Set(Bounds().Width()-( (B_V_SCROLL_BAR_WIDTH*2)+1 ),0);
privatedata->DrawScrollBarButton(this, ARROW_LEFT, buttonpt,
privatedata->buttondown==ARROW3);
}
buttonpt.Set(Bounds().Width()-(B_V_SCROLL_BAR_WIDTH),0);
privatedata->DrawScrollBarButton(this, ARROW_RIGHT, buttonpt,
privatedata->buttondown==ARROW4);
}
else
{
privatedata->DrawScrollBarButton(this, ARROW_UP, buttonpt,
privatedata->buttondown==ARROW1);
if(privatedata->sbinfo.double_arrows)
{
buttonpt.Set(0,B_H_SCROLL_BAR_HEIGHT+1);
privatedata->DrawScrollBarButton(this, ARROW_DOWN, buttonpt,
privatedata->buttondown==ARROW2);
buttonpt.Set(0,Bounds().Height()-( (B_H_SCROLL_BAR_HEIGHT*2)+1 ));
privatedata->DrawScrollBarButton(this, ARROW_UP, buttonpt,
privatedata->buttondown==ARROW3);
}
buttonpt.Set(0,Bounds().Height()-(B_H_SCROLL_BAR_HEIGHT));
privatedata->DrawScrollBarButton(this, ARROW_DOWN, buttonpt,
privatedata->buttondown==ARROW4);
}
// Draw scroll thumb // Draw scroll thumb
if(privatedata->enabled)
{
BRect r(privatedata->thumbframe); BRect r(privatedata->thumbframe);
SetHighColor(dark);
StrokeRect(privatedata->thumbframe); StrokeRect(privatedata->thumbframe);
r.InsetBy(1,1); r.InsetBy(1,1);
SetHighColor(tint_color(c,B_DARKEN_2_TINT));
StrokeLine(r.LeftBottom(),r.RightBottom()); StrokeLine(r.LeftBottom(),r.RightBottom());
StrokeLine(r.RightTop(),r.RightBottom()); StrokeLine(r.RightTop(),r.RightBottom());
@@ -587,6 +808,9 @@ void BScrollBar::Draw(BRect updateRect)
FillRect(r); FillRect(r);
} }
// TODO: Add the other thumb styles - dots and lines
}
void BScrollBar::FrameMoved(BPoint new_position) void BScrollBar::FrameMoved(BPoint new_position)
{ {
} }
@@ -658,189 +882,6 @@ BScrollBar &BScrollBar::operator=(const BScrollBar &)
return *this; return *this;
} }
BScrollArrowButton::BScrollArrowButton(BPoint location,
const char *name, arrow_direction dir)
: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;
BRect r=Bounds();
switch(fDirection)
{
case ARROW_LEFT:
{
tri1.Set(r.left+3,(r.top+r.bottom)/2);
tri2.Set(r.right-3,r.top+3);
tri3.Set(r.right-3,r.bottom-3);
break;
}
case ARROW_RIGHT:
{
tri1.Set(r.left+3,r.bottom-3);
tri2.Set(r.left+3,r.top+3);
tri3.Set(r.right-3,(r.top+r.bottom)/2);
break;
}
case ARROW_UP:
{
tri1.Set(r.left+3,r.bottom-3);
tri2.Set((r.left+r.right)/2,r.top+3);
tri3.Set(r.right-3,r.bottom-3);
break;
}
default:
{
tri1.Set(r.left+3,r.top+3);
tri2.Set(r.right-3,r.top+3);
tri3.Set((r.left+r.right)/2,r.bottom-3);
break;
}
}
mousedown=false;
}
BScrollArrowButton::~BScrollArrowButton(void)
{
}
void BScrollArrowButton::MouseDown(BPoint pt)
{
if(enabled==false)
return;
mousedown=true;
Draw(Bounds());
// Test for which button clicked here
status_t returnval=B_ERROR;
if(parent)
{
parent->privatedata->arrowdown=fDirection;
returnval=control_scrollbar(SBC_SCROLLBYVALUE,&parent->fSmallStep,parent);
if(returnval==B_OK)
{
parent->Draw(parent->Bounds());
parent->ValueChanged(parent->fValue);
if(parent->privatedata->repeaterid==-1)
{
parent->privatedata->exit_repeater=false;
parent->privatedata->repeaterid=spawn_thread(parent->privatedata->ButtonRepeaterThread,
"scroll repeater",B_NORMAL_PRIORITY,parent);
resume_thread(parent->privatedata->repeaterid);
}
}
}
}
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)
{
if(enabled==false)
return;
if(transit==B_ENTERED_VIEW)
{
BPoint point;
uint32 buttons;
GetMouse(&point,&buttons);
if( (buttons & B_PRIMARY_MOUSE_BUTTON)==0 &&
(buttons & B_SECONDARY_MOUSE_BUTTON)==0 &&
(buttons & B_PRIMARY_MOUSE_BUTTON)==0 )
mousedown=false;
else
mousedown=true;
Draw(Bounds());
}
if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW)
MouseUp(Bounds().LeftTop());
}
void BScrollArrowButton::Draw(BRect update)
{
rgb_color c=ui_color(B_PANEL_BACKGROUND_COLOR);
BRect r(Bounds());
rgb_color light, dark, normal,arrow,arrow2;
if(mousedown)
{
light=tint_color(c,B_DARKEN_3_TINT);
arrow2=dark=tint_color(c,B_LIGHTEN_MAX_TINT);
normal=c;
arrow=tint_color(c,B_DARKEN_MAX_TINT);
}
else
if(enabled)
{
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
{
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);
SetHighColor(normal);
FillRect(r);
SetHighColor(arrow);
FillTriangle(tri1,tri2,tri3);
r.InsetBy(-1,-1);
SetHighColor(dark);
StrokeLine(r.LeftBottom(),r.RightBottom());
StrokeLine(r.RightTop(),r.RightBottom());
StrokeLine(tri2,tri3);
StrokeLine(tri1,tri3);
SetHighColor(light);
StrokeLine(r.LeftTop(),r.RightTop());
StrokeLine(r.LeftTop(),r.LeftBottom());
SetHighColor(arrow2);
StrokeLine(tri1,tri2);
}
void BScrollArrowButton::AttachedToWindow(void)
{
parent=(BScrollBar*)Parent();
}
void BScrollArrowButton::DetachedToWindow(void)
{
parent=NULL;
}
void BScrollArrowButton::SetEnabled(bool value)
{
enabled=value;
}
/* /*
This cheat function will allow the scrollbar prefs app to act exactly like R5's and 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 perform other stuff without mucking around with the virtual tables B_BAD_VALUE is
@@ -853,7 +894,18 @@ void BScrollArrowButton::SetEnabled(bool value)
Returns B_OK if everthing went well and the caller is to redraw the scrollbar 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_ERROR is returned if the caller doesn't need to do anything
B_BAD_VALUE is returned if data is NULL B_BAD_VALUE is returned if data is NULL
1: Set Double: set usage mode to either single or double.
data parameter is cast to a bool. true sets it to double, false sets to single
B_OK is always returned
B_BAD_VALUE is returned if data is NULL
2: Set Proportional: set usage mode to either proportional or fixed thumbsize.
data parameter is cast to a bool. true sets it to proportional, false sets to fixed
B_OK is always returned
B_BAD_VALUE is returned if data is NULL
3: Set Style: set thumb style to blank, 3 dots, or 3 lines
data parameter is cast to an int8. 0 is blank, 1 is dotted, 2 is lined
B_ERROR is returned for values != 0, 1, or 2
B_BAD_VALUE is returned if data is NULL
*/ */
status_t control_scrollbar(int8 command, void *data, BScrollBar *sb) status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
{ {
@@ -862,7 +914,7 @@ status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
switch(command) switch(command)
{ {
case 0: case 0: // Scroll By Value
{ {
if(!data) if(!data)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -871,49 +923,6 @@ status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
if(datavalue==0) if(datavalue==0)
return B_ERROR; 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(sb->fOrientation==B_VERTICAL)
{ {
if(datavalue<0) if(datavalue<0)
@@ -975,6 +984,46 @@ status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
return B_ERROR; return B_ERROR;
}// end case 0 (Scroll By Value) }// end case 0 (Scroll By Value)
case 1: // Set Double
{
// TODO: Implement code to add or remove the inside pair of arrow buttons
if(!data)
return B_BAD_VALUE;
bool datavalue=*((bool *)data);
sb->privatedata->sbinfo.double_arrows=datavalue;
return B_OK;
}
case 2: // Set Proportional
{
// TODO: Figure out how proportional relates to the size of the thumb
if(!data)
return B_BAD_VALUE;
bool datavalue=*((bool *)data);
sb->privatedata->sbinfo.proportional=datavalue;
return B_OK;
}
case 3: // Set Style
{
// TODO: Add redraw code to reflect the changes
if(!data)
return B_BAD_VALUE;
int8 datavalue=*((int8 *)data);
if(datavalue!=0 && datavalue!=1 && datavalue!=2)
return B_BAD_VALUE;
sb->privatedata->sbinfo.knob=datavalue;
return B_OK;
}
default: default:
{ {
printf("Unknown command value %d in control_scrollbar\n",command); printf("Unknown command value %d in control_scrollbar\n",command);
@@ -987,3 +1036,106 @@ status_t control_scrollbar(int8 command, void *data, BScrollBar *sb)
return B_BAD_VALUE; return B_BAD_VALUE;
} }
void BScrollBarPrivateData::DrawScrollBarButton(BScrollBar *owner, arrow_direction direction,
const BPoint &offset, bool down)
{
// Another hack for code size
BRect r(offset.x,offset.y,offset.x+14,offset.y+14);
rgb_color c=ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color light, dark, normal,arrow,arrow2;
if(down)
{
light=tint_color(c,B_DARKEN_3_TINT);
arrow2=dark=tint_color(c,B_LIGHTEN_MAX_TINT);
normal=c;
arrow=tint_color(c,B_DARKEN_MAX_TINT);
}
else
{
bool use_enabled_colors=enabled;
// Add a usability perk - disable buttons if they would not do anything -
// like a left arrow if the value==fMin
if( (direction==ARROW_LEFT || direction==ARROW_UP) &&
(owner->fValue==owner->fMin) )
use_enabled_colors=false;
else
if( (direction==ARROW_RIGHT || direction==ARROW_DOWN) &&
(owner->fValue==owner->fMax) )
use_enabled_colors=false;
if(use_enabled_colors)
{
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
{
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);
}
}
BPoint tri1,tri2,tri3;
switch(direction)
{
case ARROW_LEFT:
{
tri1.Set(r.left+3,(r.top+r.bottom)/2);
tri2.Set(r.right-3,r.top+3);
tri3.Set(r.right-3,r.bottom-3);
break;
}
case ARROW_RIGHT:
{
tri1.Set(r.left+3,r.bottom-3);
tri2.Set(r.left+3,r.top+3);
tri3.Set(r.right-3,(r.top+r.bottom)/2);
break;
}
case ARROW_UP:
{
tri1.Set(r.left+3,r.bottom-3);
tri2.Set((r.left+r.right)/2,r.top+3);
tri3.Set(r.right-3,r.bottom-3);
break;
}
default:
{
tri1.Set(r.left+3,r.top+3);
tri2.Set(r.right-3,r.top+3);
tri3.Set((r.left+r.right)/2,r.bottom-3);
break;
}
}
r.InsetBy(1,1);
owner->SetHighColor(normal);
owner->FillRect(r);
owner->SetHighColor(arrow);
owner->FillTriangle(tri1,tri2,tri3);
r.InsetBy(-1,-1);
owner->SetHighColor(dark);
owner->StrokeLine(r.LeftBottom(),r.RightBottom());
owner->StrokeLine(r.RightTop(),r.RightBottom());
owner->StrokeLine(tri2,tri3);
owner->StrokeLine(tri1,tri3);
owner->SetHighColor(light);
owner->StrokeLine(r.LeftTop(),r.RightTop());
owner->StrokeLine(r.LeftTop(),r.LeftBottom());
owner->SetHighColor(arrow2);
owner->StrokeLine(tri1,tri2);
}