* rewritten big parts to blend with the new clipping code

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7091 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adi Oanca
2004-03-28 15:03:34 +00:00
parent 82cc45c032
commit 1610897948
+91 -366
View File
@@ -36,7 +36,7 @@
#include <stdio.h> #include <stdio.h>
#define USE_VIEW_FILL_HACK //#define USE_VIEW_FILL_HACK
//#define DEBUG_DECORATOR //#define DEBUG_DECORATOR
#ifdef DEBUG_DECORATOR #ifdef DEBUG_DECORATOR
@@ -53,12 +53,13 @@ DefaultDecorator::DefaultDecorator(BRect rect, int32 wlook, int32 wfeel, int32 w
taboffset=0; taboffset=0;
titlepixelwidth=0; titlepixelwidth=0;
framecolors=new RGBColor[5]; framecolors=new RGBColor[6];
framecolors[0].SetColor(255,255,255); framecolors[0].SetColor(152,152,152);
framecolors[1].SetColor(216,216,216); framecolors[1].SetColor(255,255,255);
framecolors[2].SetColor(152,152,152); framecolors[2].SetColor(216,216,216);
framecolors[3].SetColor(136,136,136); framecolors[3].SetColor(136,136,136);
framecolors[4].SetColor(96,96,96); framecolors[4].SetColor(152,152,152);
framecolors[5].SetColor(96,96,96);
// Set appropriate colors based on the current focus value. In this case, each decorator // Set appropriate colors based on the current focus value. In this case, each decorator
// defaults to not having the focus. // defaults to not having the focus.
@@ -67,9 +68,6 @@ DefaultDecorator::DefaultDecorator(BRect rect, int32 wlook, int32 wfeel, int32 w
// Do initial decorator setup // Do initial decorator setup
_DoLayout(); _DoLayout();
// This flag is used to determine whether or not we're moving the tab
slidetab=false;
// tab_highcol=_colors->window_tab; // tab_highcol=_colors->window_tab;
// tab_lowcol=_colors->window_tab; // tab_lowcol=_colors->window_tab;
@@ -153,14 +151,14 @@ click_type DefaultDecorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
} }
// We got this far, so user is clicking on the border? // We got this far, so user is clicking on the border?
BRect brect(_frame); if (leftborder.Contains(pt) || rightborder.Contains(pt)
brect.top+=19; || topborder.Contains(pt) || bottomborder.Contains(pt))
BRect clientrect(brect.InsetByCopy(3,3));
if(brect.Contains(pt) && !clientrect.Contains(pt))
{ {
if(_resizerect.Contains(pt)) if (_look == B_TITLED_WINDOW_LOOK || _look == B_FLOATING_WINDOW_LOOK){
BRect temp(BPoint(bottomborder.right-18, bottomborder.bottom-18), bottomborder.RightBottom());
if (temp.Contains(pt))
return DEC_RESIZE; return DEC_RESIZE;
}
return DEC_DRAG; return DEC_DRAG;
} }
@@ -178,13 +176,6 @@ STRACE(("DefaultDecorator: Do Layout\n"));
{ {
case B_FLOATING_WINDOW_LOOK: case B_FLOATING_WINDOW_LOOK:
case B_MODAL_WINDOW_LOOK: case B_MODAL_WINDOW_LOOK:
// We're going to make the frame 5 pixels wide, no matter what. R5's decorator frame
// requires the skills of a gaming master to click on the tiny frame if resizing is necessary,
// and there *are* apps which do this
// borderwidth=3;
// break;
case B_BORDERED_WINDOW_LOOK: case B_BORDERED_WINDOW_LOOK:
case B_TITLED_WINDOW_LOOK: case B_TITLED_WINDOW_LOOK:
case B_DOCUMENT_WINDOW_LOOK: case B_DOCUMENT_WINDOW_LOOK:
@@ -202,7 +193,7 @@ STRACE(("DefaultDecorator: Do Layout\n"));
_frame.top - borderwidth - 19.0, _frame.top - borderwidth - 19.0,
((_frame.right - _frame.left) < 35.0 ? ((_frame.right - _frame.left) < 35.0 ?
_frame.left + 35.0 : _frame.right) + borderwidth, _frame.left + 35.0 : _frame.right) + borderwidth,
_frame.top - (borderwidth-1) ); _frame.top - borderwidth );
// make it text width sensitive // make it text width sensitive
if(strlen(GetTitle())>1) if(strlen(GetTitle())>1)
@@ -225,19 +216,17 @@ STRACE(("DefaultDecorator: Do Layout\n"));
// calculate left/top/right/bottom borders // calculate left/top/right/bottom borders
if ( borderwidth != 0 ){ if ( borderwidth != 0 ){
_borderrect = _frame.InsetByCopy( -borderwidth, -borderwidth ); leftborder.Set( _frame.left - borderwidth, _frame.top,
leftborder.Set( _borderrect.left, _frame.top - borderwidth, _frame.left - 1, _frame.bottom);
_frame.left, _frame.bottom + borderwidth ); rightborder.Set(_frame.right + 1, _frame.top ,
rightborder.Set( _frame.right, _frame.top - borderwidth, _frame.right + borderwidth, _frame.bottom);
_borderrect.right, _frame.bottom + borderwidth ); topborder.Set( _frame.left - borderwidth, _frame.top - borderwidth,
topborder.Set( _borderrect.left, _borderrect.top, _frame.right + borderwidth, _frame.top - 1);
_borderrect.right, _frame.top ); bottomborder.Set( _frame.left - borderwidth, _frame.bottom + 1,
bottomborder.Set( _borderrect.left, _frame.bottom, _frame.right + borderwidth, _frame.bottom + borderwidth);
_borderrect.right, _borderrect.bottom );
} }
else{ else{
// no border ... (?) useful when displaying windows that are just images // no border ... (?) useful when displaying windows that are just images
_borderrect = _frame;
leftborder.Set( 0.0, 0.0, -1.0, -1.0 ); leftborder.Set( 0.0, 0.0, -1.0, -1.0 );
rightborder.Set( 0.0, 0.0, -1.0, -1.0 ); rightborder.Set( 0.0, 0.0, -1.0, -1.0 );
topborder.Set( 0.0, 0.0, -1.0, -1.0 ); topborder.Set( 0.0, 0.0, -1.0, -1.0 );
@@ -245,8 +234,8 @@ STRACE(("DefaultDecorator: Do Layout\n"));
} }
// calculate resize rect // calculate resize rect
_resizerect.Set( _borderrect.right - 19.0, _borderrect.bottom - 19.0, _resizerect.Set( bottomborder.right - 18.0, bottomborder.bottom - 18.0,
_borderrect.right, _borderrect.bottom); bottomborder.right - 3, bottomborder.bottom - 3);
// format tab rect for a floating window - make the rect smaller // format tab rect for a floating window - make the rect smaller
if ( _look == B_FLOATING_WINDOW_LOOK ){ if ( _look == B_FLOATING_WINDOW_LOOK ){
@@ -284,8 +273,8 @@ void DefaultDecorator::MoveBy(BPoint pt)
_closerect.OffsetBy(pt); _closerect.OffsetBy(pt);
_tabrect.OffsetBy(pt); _tabrect.OffsetBy(pt);
_resizerect.OffsetBy(pt); _resizerect.OffsetBy(pt);
_borderrect.OffsetBy(pt);
_zoomrect.OffsetBy(pt); _zoomrect.OffsetBy(pt);
_borderrect.OffsetBy(pt);
leftborder.OffsetBy(pt); leftborder.OffsetBy(pt);
rightborder.OffsetBy(pt); rightborder.OffsetBy(pt);
@@ -302,20 +291,26 @@ void DefaultDecorator::GetFootprint(BRegion *region)
if(!region) if(!region)
return; return;
region->MakeEmpty();
if(_look == B_NO_BORDER_WINDOW_LOOK) if(_look == B_NO_BORDER_WINDOW_LOOK)
{ {
region->Set(_frame);
return; return;
} }
region->Include(leftborder);
region->Include(rightborder);
region->Include(topborder);
region->Include(bottomborder);
if(_look == B_BORDERED_WINDOW_LOOK) if(_look == B_BORDERED_WINDOW_LOOK)
{
region->Set(_borderrect);
return; return;
}
region->Set(_borderrect);
region->Include(_tabrect); region->Include(_tabrect);
if(_look == B_DOCUMENT_WINDOW_LOOK)
region->Include(BRect(_frame.right - 13.0f, _frame.bottom - 13.0f,
_frame.right, _frame.bottom));
} }
BRect DefaultDecorator::SlideTab(float dx, float dy=0) BRect DefaultDecorator::SlideTab(float dx, float dy=0)
@@ -387,7 +382,7 @@ void DefaultDecorator::Draw(void)
// Easy way to draw everything - no worries about drawing only certain // Easy way to draw everything - no worries about drawing only certain
// things // things
_DrawFrame(_borderrect); _DrawFrame(BRect(topborder.LeftTop(), bottomborder.RightBottom()));
_DrawTab(_tabrect); _DrawTab(_tabrect);
} }
@@ -423,16 +418,27 @@ void DefaultDecorator::_DrawTab(BRect r)
if(_look == B_NO_BORDER_WINDOW_LOOK || _look == B_BORDERED_WINDOW_LOOK) if(_look == B_NO_BORDER_WINDOW_LOOK || _look == B_BORDERED_WINDOW_LOOK)
return; return;
_driver->FillRect(_tabrect,(GetFocus())?_colors->window_tab:_colors->inactive_window_tab); RGBColor tabColor = (GetFocus())?_colors->window_tab:_colors->inactive_window_tab;
_driver->FillRect(_tabrect, tabColor);
_driver->StrokeLine(_tabrect.LeftTop(),_tabrect.LeftBottom(),framecolors[2]); _driver->StrokeLine(_tabrect.LeftTop(),_tabrect.LeftBottom(),framecolors[0]);
_driver->StrokeLine(_tabrect.LeftTop(),_tabrect.RightTop(),framecolors[2]); _driver->StrokeLine(_tabrect.LeftTop(),_tabrect.RightTop(),framecolors[0]);
_driver->StrokeLine(_tabrect.RightTop(),_tabrect.RightBottom(),framecolors[5]);
_driver->StrokeLine( BPoint( _tabrect.left + 2, _tabrect.bottom+1 ),
BPoint( _tabrect.right - 2, _tabrect.bottom+1 ),
framecolors[2]);
_driver->StrokeLine(_tabrect.RightTop(),_tabrect.RightBottom(),framecolors[4]);
_driver->StrokeLine( BPoint( _tabrect.left + 2, _tabrect.bottom ), _driver->StrokeLine( BPoint( _tabrect.left + 1, _tabrect.top + 1 ),
BPoint( _tabrect.right - 2, _tabrect.bottom ), BPoint( _tabrect.left + 1, _tabrect.bottom ),
framecolors[1]); framecolors[1]);
_driver->StrokeLine( BPoint( _tabrect.left + 1, _tabrect.top + 1 ),
BPoint( _tabrect.right - 1, _tabrect.top + 1 ),
framecolors[1]);
_driver->StrokeLine( BPoint( _tabrect.right - 1, _tabrect.top + 2 ),
BPoint( _tabrect.right - 1, _tabrect.bottom ),
framecolors[3]);
_DrawTitle(_tabrect); _DrawTitle(_tabrect);
@@ -506,8 +512,6 @@ void DefaultDecorator::_DrawFrame(BRect invalid)
{ {
STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top, STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
invalid.right, invalid.bottom)); invalid.right, invalid.bottom));
// We need to test each side to determine whether or not it needs drawn. Additionally,
// we must clip the lines drawn by this function to the invalid rectangle we are given
#ifdef USE_VIEW_FILL_HACK #ifdef USE_VIEW_FILL_HACK
_drawdata.highcolor = RGBColor( 192, 192, 192 ); _drawdata.highcolor = RGBColor( 192, 192, 192 );
@@ -520,350 +524,71 @@ STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
if(!borderwidth) if(!borderwidth)
return; return;
// Data specifically for the StrokeLineArray call. { // a block start
int32 numlines=0, maxlines=20;
BPoint points[maxlines*2]; BRect r = BRect(topborder.LeftTop(), bottomborder.RightBottom());
RGBColor colors[maxlines],temprgbcol; //top
for (int8 i=0; i<5; i++){
// For quick calculation of gradients for each side. Top is same as left, right is same as _driver->StrokeLine(BPoint(r.left+i, r.top+i), BPoint(r.right-i, r.top+i), framecolors[i]);
}
//left
for (int8 i=0; i<5; i++){
_driver->StrokeLine(BPoint(r.left+i, r.top+i), BPoint(r.left+i, r.bottom-i), framecolors[i]);
}
//bottom //bottom
// int8 rightindices[borderwidth],leftindices[borderwidth]; for (int8 i=0; i<5; i++){
int8 *rightindices=new int8[borderwidth], _driver->StrokeLine(BPoint(r.left+i, r.bottom-i), BPoint(r.right-i, r.bottom-i), framecolors[(4-i)==4? 5: (4-i)]);
*leftindices=new int8[borderwidth];
if(borderwidth==5)
{
leftindices[0]=2;
leftindices[1]=0;
leftindices[2]=1;
leftindices[3]=3;
leftindices[4]=2;
rightindices[0]=2;
rightindices[1]=0;
rightindices[2]=1;
rightindices[3]=3;
rightindices[4]=4;
} }
else //right
{ for (int8 i=0; i<5; i++){
// TODO: figure out border colors for floating window look _driver->StrokeLine(BPoint(r.right-i, r.top+i), BPoint(r.right-i, r.bottom-i), framecolors[(4-i)==4? 5: (4-i)]);
leftindices[0]=2;
leftindices[1]=2;
leftindices[2]=1;
leftindices[3]=1;
leftindices[4]=4;
rightindices[0]=2;
rightindices[1]=2;
rightindices[2]=1;
rightindices[3]=1;
rightindices[4]=4;
} }
// Variables used in each calculation } // end of the block/
int32 startx,endx,starty,endy,i;
bool topcorner,bottomcorner,leftcorner,rightcorner;
int8 step,colorindex;
BRect r;
BPoint start, end;
// Right side
if(TestRectIntersection(rightborder,invalid))
{
// We may not have to redraw the entire width of the frame itself. Rare case, but
// it must be accounted for.
startx=(int32) MAX(invalid.left,rightborder.left);
endx=(int32) MIN(invalid.right,rightborder.right);
// We'll need these flags to see if we must include the corners in final line
// calculations
r=(rightborder);
r.bottom=r.top+borderwidth;
topcorner=TestRectIntersection(invalid,r);
r=rightborder;
r.top=r.bottom-borderwidth;
bottomcorner=TestRectIntersection(invalid,r);
step=(borderwidth==5)?1:2;
colorindex=0;
// Generate the lines for this side
for(i=startx+1; i<=endx; i++)
{
start.x=end.x=i;
if(topcorner)
{
start.y=rightborder.top+(borderwidth-(i-rightborder.left));
start.y=MAX(start.y,invalid.top);
}
else
start.y=MAX(start.y+borderwidth,invalid.top);
if(bottomcorner)
{
end.y=rightborder.bottom-(borderwidth-(i-rightborder.left));
end.y=MIN(end.y,invalid.bottom);
}
else
end.y=MIN(end.y-borderwidth,invalid.bottom);
// Make the appropriate
points[numlines*2]=start;
points[(numlines*2)+1]=end;
colors[numlines]=framecolors[rightindices[colorindex]];
colorindex+=step;
numlines++;
}
}
// Left side
if(TestRectIntersection(leftborder,invalid))
{
// We may not have to redraw the entire width of the frame itself. Rare case, but
// it must be accounted for.
startx=(int32) MAX(invalid.left,leftborder.left);
endx=(int32) MIN(invalid.right,leftborder.right);
// We'll need these flags to see if we must include the corners in final line
// calculations
r=leftborder;
r.bottom=r.top+borderwidth;
topcorner=TestRectIntersection(invalid,r);
r=leftborder;
r.top=r.bottom-borderwidth;
bottomcorner=TestRectIntersection(invalid,r);
step=(borderwidth==5)?1:2;
colorindex=0;
// Generate the lines for this side
for(i=startx; i<endx; i++)
{
start.x=end.x=i;
if(topcorner)
{
start.y=leftborder.top+(i-leftborder.left);
start.y=MAX(start.y,invalid.top);
}
else
start.y=MAX(start.y+borderwidth,invalid.top);
if(bottomcorner)
{
end.y=leftborder.bottom-(i-leftborder.left);
end.y=MIN(end.y,invalid.bottom);
}
else
end.y=MIN(end.y-borderwidth,invalid.bottom);
// Make the appropriate
points[numlines*2]=start;
points[(numlines*2)+1]=end;
colors[numlines]=framecolors[leftindices[colorindex]];
colorindex+=step;
numlines++;
}
}
// Top side
if(TestRectIntersection(topborder,invalid))
{
// We may not have to redraw the entire width of the frame itself. Rare case, but
// it must be accounted for.
starty=(int32) MAX(invalid.top,topborder.top);
endy=(int32) MIN(invalid.bottom,topborder.bottom);
// We'll need these flags to see if we must include the corners in final line
// calculations
r=topborder;
r.bottom=r.top+borderwidth;
r.right=r.left+borderwidth;
leftcorner=TestRectIntersection(invalid,r);
r=topborder;
r.top=r.bottom-borderwidth;
r.left=r.right-borderwidth;
rightcorner=TestRectIntersection(invalid,r);
step=(borderwidth==5)?1:2;
colorindex=0;
// Generate the lines for this side
for(i=starty; i<endy; i++)
{
start.y=end.y=i;
if(leftcorner)
{
start.x=topborder.left+(i-topborder.top);
start.x=MAX(start.x,invalid.left);
}
else
start.x=MAX(start.x+borderwidth,invalid.left);
if(rightcorner)
{
end.x=topborder.right-(i-topborder.top);
end.x=MIN(end.x,invalid.right);
}
else
end.x=MIN(end.x-borderwidth,invalid.right);
// Make the appropriate
points[numlines*2]=start;
points[(numlines*2)+1]=end;
// Top side uses the same color order as the left one
colors[numlines]=framecolors[leftindices[colorindex]];
colorindex+=step;
numlines++;
}
}
// Bottom side
if(TestRectIntersection(bottomborder,invalid))
{
// We may not have to redraw the entire width of the frame itself. Rare case, but
// it must be accounted for.
starty=(int32) MAX(invalid.top,bottomborder.top);
endy=(int32) MIN(invalid.bottom,bottomborder.bottom);
// We'll need these flags to see if we must include the corners in final line
// calculations
r=bottomborder;
r.bottom=r.top+borderwidth;
r.right=r.left+borderwidth;
leftcorner=TestRectIntersection(invalid,r);
r=bottomborder;
r.top=r.bottom-borderwidth;
r.left=r.right-borderwidth;
rightcorner=TestRectIntersection(invalid,r);
step=(borderwidth==5)?1:2;
colorindex=0;
// Generate the lines for this side
for(i=starty+1; i<=endy; i++)
{
start.y=end.y=i;
if(leftcorner)
{
start.x=bottomborder.left+(borderwidth-(i-bottomborder.top));
start.x=MAX(start.x,invalid.left);
}
else
start.x=MAX(start.x+borderwidth,invalid.left);
if(rightcorner)
{
end.x=bottomborder.right-(borderwidth-(i-bottomborder.top));
end.x=MIN(end.x,invalid.right);
}
else
end.x=MIN(end.x-borderwidth,invalid.right);
// Make the appropriate
points[numlines*2]=start;
points[(numlines*2)+1]=end;
// Top side uses the same color order as the left one
colors[numlines]=framecolors[rightindices[colorindex]];
colorindex+=step;
numlines++;
}
}
if(_feel == B_NO_BORDER_WINDOW_LOOK){
//do(draw) nothing!
}
else{
_driver->StrokeLineArray(points,numlines,&_drawdata,colors);
}
delete rightindices;
delete leftindices;
// Draw the resize thumb if we're supposed to // Draw the resize thumb if we're supposed to
if(!(_flags & B_NOT_RESIZABLE)) if(!(_flags & B_NOT_RESIZABLE))
{ {
r=_resizerect; BRect r = _resizerect;
// int32 w=r.IntegerWidth(), h=r.IntegerHeight();
switch(_look){ switch(_look){
// This code is strictly for B_DOCUMENT_WINDOW looks // This code is strictly for B_DOCUMENT_WINDOW looks
case B_DOCUMENT_WINDOW_LOOK:{ case B_DOCUMENT_WINDOW_LOOK:{
r.right-=4;
r.bottom-=4;
_driver->StrokeLine(r.LeftTop(),r.RightTop(),framecolors[2]);
_driver->StrokeLine(r.LeftTop(),r.LeftBottom(),framecolors[2]);
r.OffsetBy(1,1);
_driver->StrokeLine(r.LeftTop(),r.RightTop(),framecolors[0]);
_driver->StrokeLine(r.LeftTop(),r.LeftBottom(),framecolors[0]);
r.OffsetBy(1,1);
_driver->FillRect(r,framecolors[1]);
/* r.left+=2;
r.top+=2;
r.right-=3;
r.bottom-=3;
*/
r.right-=2;
r.bottom-=2;
int32 w=r.IntegerWidth(), h=r.IntegerHeight();
rgb_color halfcol, startcol, endcol;
float rstep,gstep,bstep,i;
int steps=(w<h)?w:h;
startcol=framecolors[0].GetColor32();
endcol=framecolors[4].GetColor32();
halfcol=framecolors[0].MakeBlendColor(framecolors[4],0.5).GetColor32();
rstep=(startcol.red-halfcol.red)/steps;
gstep=(startcol.green-halfcol.green)/steps;
bstep=(startcol.blue-halfcol.blue)/steps;
// Explicitly locking the driver is normally unnecessary. However, we need to do // Explicitly locking the driver is normally unnecessary. However, we need to do
// this because we are rapidly drawing a series of calls which would not necessarily // this because we are rapidly drawing a series of calls which would not necessarily
// draw correctly if we didn't do so. // draw correctly if we didn't do so.
float x = r.right;
float y = r.bottom;
_driver->Lock(); _driver->Lock();
for(i=0;i<=steps; i++) _driver->FillRect(BRect(x-13, y-13, x, y), framecolors[2]);
{ _driver->StrokeLine(BPoint(x-15, y-15), BPoint(x-15, y-2), framecolors[0]);
temprgbcol.SetColor(uint8(startcol.red-(i*rstep)), _driver->StrokeLine(BPoint(x-14, y-14), BPoint(x-14, y-1), framecolors[1]);
uint8(startcol.green-(i*gstep)), _driver->StrokeLine(BPoint(x-15, y-15), BPoint(x-2, y-15), framecolors[0]);
uint8(startcol.blue-(i*bstep))); _driver->StrokeLine(BPoint(x-14, y-14), BPoint(x-1, y-14), framecolors[1]);
_driver->StrokeLine(BPoint(r.left,r.top+i), for(int8 i=1; i <= 4; i++){
BPoint(r.left+i,r.top),temprgbcol); for(int8 j=1; j<=i; j++){
BPoint pt1(x-(3*j)+1, y-(3*(5-i))+1);
temprgbcol.SetColor(uint8(halfcol.red-(i*rstep)), BPoint pt2(x-(3*j)+2, y-(3*(5-i))+2);
uint8(halfcol.green-(i*gstep)), _driver->StrokePoint(pt1, framecolors[0]);
uint8(halfcol.blue-(i*bstep))); _driver->StrokePoint(pt2, framecolors[1]);
_driver->StrokeLine(BPoint(r.left+steps,r.top+i),
BPoint(r.left+i,r.top+steps),temprgbcol);
} }
}
// RGBColor c(255,128,0);
// _driver->FillRect(BRect(50,50,600,400), c);
_driver->Unlock(); _driver->Unlock();
break; break;
} }
case B_TITLED_WINDOW_LOOK: case B_TITLED_WINDOW_LOOK:
case B_FLOATING_WINDOW_LOOK:{ case B_FLOATING_WINDOW_LOOK:{
_driver->StrokeLine(BPoint(r.right-4,r.top),BPoint(r.right-2,r.top), _driver->StrokeLine(BPoint(rightborder.left, rightborder.bottom-13),
BPoint(rightborder.right, rightborder.bottom-13),
framecolors[2]); framecolors[2]);
_driver->StrokeLine(BPoint(r.left,r.bottom-4),BPoint(r.left,r.bottom-2), _driver->StrokeLine(BPoint(bottomborder.left-18, bottomborder.top),
BPoint(bottomborder.right-18, bottomborder.bottom),
framecolors[2]); framecolors[2]);
break; break;
} }