Decorator::ResizeBy tells you the dirty region, DefaultDecorator::Draw() pays attention to the update rect, small clean ups along the way

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15778 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-01-02 01:03:31 +00:00
parent 3155f89a0c
commit e067fed541
5 changed files with 171 additions and 118 deletions
+3 -3
View File
@@ -94,10 +94,10 @@ class Decorator {
virtual click_type Clicked(BPoint pt, int32 buttons,
int32 modifiers);
virtual void MoveBy(float x, float y);
void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
void ResizeBy(float x, float y, BRegion* dirty);
virtual void ResizeBy(BPoint pt, BRegion* dirty) = 0;
virtual void SetTabLocation(float location) {}
virtual float TabLocation() const
+11 -24
View File
@@ -374,14 +374,7 @@ Decorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
void
Decorator::MoveBy(float x, float y)
{
_zoomrect.OffsetBy(x, y);
_closerect.OffsetBy(x, y);
_minimizerect.OffsetBy(x, y);
_minimizerect.OffsetBy(x, y);
_tabrect.OffsetBy(x, y);
_frame.OffsetBy(x, y);
_resizerect.OffsetBy(x, y);
_borderrect.OffsetBy(x, y);
MoveBy(BPoint(x, y));
}
/*!
@@ -395,7 +388,14 @@ Decorator::MoveBy(float x, float y)
void
Decorator::MoveBy(BPoint pt)
{
MoveBy(pt.x, pt.y);
_zoomrect.OffsetBy(pt);
_closerect.OffsetBy(pt);
_minimizerect.OffsetBy(pt);
_minimizerect.OffsetBy(pt);
_tabrect.OffsetBy(pt);
_frame.OffsetBy(pt);
_resizerect.OffsetBy(pt);
_borderrect.OffsetBy(pt);
}
/*!
@@ -409,22 +409,9 @@ Decorator::MoveBy(BPoint pt)
are not inverted.
*/
void
Decorator::ResizeBy(float x, float y)
{
}
/*!
\brief Resizes the decorator frame
\param pt Point containing the offsets
This is a required function for subclasses to implement - the default does nothing.
Note that window resize flags should be followed and _frame should be resized
accordingly. It would also be a wise idea to ensure that the window's rectangles
are not inverted.
*/
void
Decorator::ResizeBy(BPoint pt)
Decorator::ResizeBy(float x, float y, BRegion* dirty)
{
ResizeBy(BPoint(x, y), dirty);
}
/*!
+147 -71
View File
@@ -25,8 +25,6 @@
#include <stdio.h>
//#define USE_VIEW_FILL_HACK
//#define DEBUG_DECORATOR
#ifdef DEBUG_DECORATOR
# include <stdio.h>
@@ -156,13 +154,6 @@ DefaultDecorator::SetFlags(uint32 flags, BRegion* updateRegion)
}
void
DefaultDecorator::MoveBy(float x, float y)
{
MoveBy(BPoint(x, y));
}
void
DefaultDecorator::MoveBy(BPoint pt)
{
@@ -181,21 +172,53 @@ DefaultDecorator::MoveBy(BPoint pt)
fBottomBorder.OffsetBy(pt);
}
void
DefaultDecorator::ResizeBy(float x, float y)
{
ResizeBy(BPoint(x, y));
}
void
DefaultDecorator::ResizeBy(BPoint pt)
DefaultDecorator::ResizeBy(BPoint pt, BRegion* dirty)
{
STRACE(("DefaultDecorator: Resize By (%.1f, %.1f)\n", pt.x, pt.y));
// Move all internal rectangles the appropriate amount
_frame.right += pt.x;
_frame.bottom += pt.y;
// handle invalidation of resize rect
if (dirty && !(fFlags & B_NOT_RESIZABLE)) {
BRect realResizeRect;
switch (fLook) {
case B_DOCUMENT_WINDOW_LOOK:
realResizeRect = _resizerect;
// resize rect at old location
dirty->Include(realResizeRect);
realResizeRect.OffsetBy(pt);
// resize rect at new location
dirty->Include(realResizeRect);
break;
case B_TITLED_WINDOW_LOOK:
case B_FLOATING_WINDOW_LOOK:
case B_MODAL_WINDOW_LOOK:
realResizeRect.Set(fRightBorder.right - 22, fBottomBorder.top,
fRightBorder.right - 22, fBottomBorder.bottom - 1);
// resize rect at old location
dirty->Include(realResizeRect);
realResizeRect.OffsetBy(pt);
// resize rect at new location
dirty->Include(realResizeRect);
realResizeRect.Set(fRightBorder.left, fBottomBorder.bottom - 22,
fRightBorder.right - 1, fBottomBorder.bottom - 22);
// resize rect at old location
dirty->Include(realResizeRect);
realResizeRect.OffsetBy(pt);
// resize rect at new location
dirty->Include(realResizeRect);
break;
default:
break;
}
}
_resizerect.OffsetBy(pt);
_borderrect.right += pt.x;
_borderrect.bottom += pt.y;
@@ -208,6 +231,32 @@ DefaultDecorator::ResizeBy(BPoint pt)
fBottomBorder.OffsetBy(0.0, pt.y);
fBottomBorder.right += pt.x;
if (dirty) {
if (pt.x > 0.0) {
BRect t(fRightBorder.left - pt.x, fTopBorder.top,
fRightBorder.right, fTopBorder.bottom);
dirty->Include(t);
t.Set(fRightBorder.left - pt.x, fBottomBorder.top,
fRightBorder.right, fBottomBorder.bottom);
dirty->Include(t);
dirty->Include(fRightBorder);
} else if (pt.x < 0.0) {
dirty->Include(BRect(fRightBorder.left, fTopBorder.top,
fRightBorder.right, fBottomBorder.bottom));
}
if (pt.y > 0.0) {
BRect t(fLeftBorder.left, fLeftBorder.bottom - pt.y,
fLeftBorder.right, fLeftBorder.bottom);
dirty->Include(t);
t.Set(fRightBorder.left, fRightBorder.bottom - pt.y,
fRightBorder.right, fRightBorder.bottom);
dirty->Include(t);
dirty->Include(fBottomBorder);
} else if (pt.y < 0.0) {
dirty->Include(fBottomBorder);
}
}
// resize tab and layout tab items
if (_tabrect.IsValid()) {
float tabWidth = fRightBorder.right - fLeftBorder.left;
@@ -218,8 +267,15 @@ DefaultDecorator::ResizeBy(BPoint pt)
tabWidth = fMaxTabWidth;
if (tabWidth != _tabrect.Width()) {
// NOTE: the tab rect becoming smaller is handled
// by the Desktop anyways, so it is sufficient
// to include it into the dirty region in it's
// final state only once at the end
_tabrect.right = _tabrect.left + tabWidth;
_LayoutTabItems(_tabrect);
if (dirty)
dirty->Include(_tabrect);
}
}
}
@@ -476,10 +532,8 @@ DefaultDecorator::_DrawFrame(BRect invalid)
STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
invalid.right, invalid.bottom));
#ifdef USE_VIEW_FILL_HACK
fDrawState.SetHighColor(RGBColor(192, 192, 192 ));
_driver->FillRect(_frame, fDrawState.HighColor());
#endif
// NOTE: the DrawingEngine needs to be locked for the entire
// time for the clipping to stay valid for this decorator
if (fLook == B_NO_BORDER_WINDOW_LOOK)
return;
@@ -494,58 +548,73 @@ STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
case B_DOCUMENT_WINDOW_LOOK:
case B_MODAL_WINDOW_LOOK: {
//top
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.right - i, r.top + i),
fFrameColors[i]);
if (invalid.Intersects(fTopBorder)) {
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.right - i, r.top + i),
fFrameColors[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),
fFrameColors[i]);
if (invalid.Intersects(fLeftBorder)) {
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.left + i, r.bottom - i),
fFrameColors[i]);
}
}
//bottom
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.bottom - i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]);
if (invalid.Intersects(fBottomBorder)) {
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.bottom - i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]);
}
}
//right
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.right - i, r.top + i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]);
if (invalid.Intersects(fRightBorder)) {
for (int8 i = 0; i < 5; i++) {
_driver->StrokeLine(BPoint(r.right - i, r.top + i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(4 - i) == 4 ? 5 : (4 - i)]);
}
}
break;
}
case B_FLOATING_WINDOW_LOOK: {
//top
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.right - i, r.top + i),
fFrameColors[i * 2]);
if (invalid.Intersects(fTopBorder)) {
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.right - i, r.top + i),
fFrameColors[i * 2]);
}
}
//left
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.left + i, r.bottom - i),
fFrameColors[i * 2]);
if (invalid.Intersects(fLeftBorder)) {
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.left + i, r.bottom - i),
fFrameColors[i * 2]);
}
}
//bottom
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.bottom - i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
if (invalid.Intersects(fBottomBorder)) {
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.left + i, r.bottom - i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
}
}
//right
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.right - i, r.top + i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
if (invalid.Intersects(fRightBorder)) {
for (int8 i = 0; i < 3; i++) {
_driver->StrokeLine(BPoint(r.right - i, r.top + i),
BPoint(r.right - i, r.bottom - i),
fFrameColors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
}
}
break;
break;
}
case B_BORDERED_WINDOW_LOOK: {
_driver->StrokeRect(r, fFrameColors[5]);
@@ -563,33 +632,37 @@ STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
switch (fLook){
case B_DOCUMENT_WINDOW_LOOK: {
// 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 draw correctly if we didn't do so.
float x = r.right - 3;
float y = r.bottom - 3;
_driver->Lock();
_driver->FillRect(BRect(x-13, y-13, x, y), fFrameColors[2]);
_driver->StrokeLine(BPoint(x-15, y-15), BPoint(x-15, y-2), fFrameColors[0]);
_driver->StrokeLine(BPoint(x-14, y-14), BPoint(x-14, y-1), fFrameColors[1]);
_driver->StrokeLine(BPoint(x-15, y-15), BPoint(x-2, y-15), fFrameColors[0]);
_driver->StrokeLine(BPoint(x-14, y-14), BPoint(x-1, y-14), fFrameColors[1]);
if (!invalid.Intersects(r))
break;
_driver->FillRect(BRect(x - 13, y - 13, x, y), fFrameColors[2]);
_driver->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 15, y - 2), fFrameColors[0]);
_driver->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 14, y - 1), fFrameColors[1]);
_driver->StrokeLine(BPoint(x - 15, y - 15), BPoint(x - 2, y - 15), fFrameColors[0]);
_driver->StrokeLine(BPoint(x - 14, y - 14), BPoint(x - 1, y - 14), fFrameColors[1]);
for (int8 i = 1; i <= 4; i++) {
for (int8 j = 1; j <= i; j++) {
BPoint pt1(x-(3*j)+1, y-(3*(5-i))+1);
BPoint pt2(x-(3*j)+2, y-(3*(5-i))+2);
BPoint pt1(x - (3 * j) + 1, y - (3 * (5 - i)) + 1);
BPoint pt2(x - (3 * j) + 2, y - (3 * (5 - i)) + 2);
_driver->StrokePoint(pt1, fFrameColors[0]);
_driver->StrokePoint(pt2, fFrameColors[1]);
}
}
_driver->Unlock();
break;
}
case B_TITLED_WINDOW_LOOK:
case B_FLOATING_WINDOW_LOOK:
case B_MODAL_WINDOW_LOOK: {
if (!invalid.Intersects(BRect(fRightBorder.right - 22, fBottomBorder.bottom - 22,
fRightBorder.right - 1, fBottomBorder.bottom - 1)))
break;
_driver->StrokeLine(BPoint(fRightBorder.left, fBottomBorder.bottom - 22),
BPoint(fRightBorder.right - 1, fBottomBorder.bottom - 22),
fFrameColors[0]);
@@ -609,17 +682,20 @@ STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
// _DrawTab
void
DefaultDecorator::_DrawTab(BRect r)
DefaultDecorator::_DrawTab(BRect invalid)
{
STRACE(("_DrawTab(%f,%f,%f,%f)\n", r.left, r.top, r.right, r.bottom));
STRACE(("_DrawTab(%.1f,%.1f,%.1f,%.1f)\n",
invalid.left, invalid.top, invalid.right, invalid.bottom));
// If a window has a tab, this will draw it and any buttons which are
// in it.
if (!_tabrect.IsValid())
if (!_tabrect.IsValid() || !invalid.Intersects(_tabrect))
return;
// TODO: cache these
RGBColor tabColorLight = RGBColor(tint_color(fTabColor.GetColor32(), (B_LIGHTEN_2_TINT + B_LIGHTEN_MAX_TINT) / 2));
RGBColor tabColorShadow = RGBColor(tint_color(fTabColor.GetColor32(), B_DARKEN_2_TINT));
RGBColor tabColorLight = RGBColor(tint_color(fTabColor.GetColor32(),
(B_LIGHTEN_2_TINT + B_LIGHTEN_MAX_TINT) / 2));
RGBColor tabColorShadow = RGBColor(tint_color(fTabColor.GetColor32(),
B_DARKEN_2_TINT));
// outer frame
_driver->StrokeLine(_tabrect.LeftTop(), _tabrect.LeftBottom(), fFrameColors[0]);
@@ -650,9 +726,9 @@ DefaultDecorator::_DrawTab(BRect r)
_DrawTitle(_tabrect);
// Draw the buttons if we're supposed to
if (!(fFlags & B_NOT_CLOSABLE))
if (!(fFlags & B_NOT_CLOSABLE) && invalid.Intersects(_closerect))
_DrawClose(_closerect);
if (!(fFlags & B_NOT_ZOOMABLE))
if (!(fFlags & B_NOT_ZOOMABLE) && invalid.Intersects(_zoomrect))
_DrawZoom(_zoomrect);
}
+1 -3
View File
@@ -27,10 +27,8 @@ public:
window_look look, BRegion* updateRegion = NULL);
virtual void SetFlags(uint32 flags, BRegion* updateRegion = NULL);
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
virtual void ResizeBy(BPoint pt, BRegion* dirty);
virtual void Draw(BRect r);
virtual void Draw();
+9 -17
View File
@@ -375,24 +375,16 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESIZED);
// put the previous border region into the dirty region as well
// to handle the part that was overlapping a layer
if (dirtyRegion)
dirtyRegion->Include(&fBorderRegion);
fBorderRegionValid = false;
fContentRegionValid = false;
fEffectiveDrawingRegionValid = false;
if (fDecorator)
fDecorator->ResizeBy(x, y);
// the border is dirty, put it into
// dirtyRegion for a start
BRegion newBorderRegion;
GetBorderRegion(&newBorderRegion);
if (dirtyRegion) {
dirtyRegion->Include(&newBorderRegion);
if (fDecorator) {
fDecorator->ResizeBy(x, y, dirtyRegion);
//if (dirtyRegion) {
//fDrawingEngine->FillRegion(*dirtyRegion, RGBColor(255, 255, 0, 255));
//snooze(40000);
//}
}
if (fTopLayer != NULL)
@@ -1603,11 +1595,11 @@ WindowLayer::_DrawBorder()
// intersect with the dirty region
dirtyBorderRegion.IntersectWith(&fDirtyRegion);
if (dirtyBorderRegion.CountRects() > 0) {
// TODO: decorator drawing with update region...
if (dirtyBorderRegion.CountRects() > 0 && fDrawingEngine->Lock()) {
fDrawingEngine->ConstrainClippingRegion(&dirtyBorderRegion);
fDecorator->Draw(dirtyBorderRegion.Frame());
fDrawingEngine->ConstrainClippingRegion(NULL);
fDrawingEngine->Unlock();
}
}