BColumnListView: Resolve column resizing drawing glitch (wider than 600px)

* use of a shared bitmap buffer in OutlineView and TitleView
* dynamically increase of the bitmap buffer after adding a column or a row

Change-Id: I4feddf636fb1446c29e60353b8f70fc084833731
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7176
Reviewed-by: John Scipione <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
Reviewed-by: Stefano Ceccherini <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Freaxed
2023-12-11 08:19:08 +00:00
committed by Adrien Destugues
parent 4f9df95dc8
commit 5014ac9392
+167 -52
View File
@@ -144,10 +144,34 @@ static const float kDropHighlightLineHeight = 2.0;
static const uint32 kToggleColumn = 'BTCL';
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
class ColumnResizeBufferView : public BView
{
public:
ColumnResizeBufferView();
virtual ~ColumnResizeBufferView();
void UpdateMaxWidth(float width);
void UpdateMaxHeight(float height);
bool Lock();
void Unlock();
const BBitmap* Bitmap();
private:
void _InitBitmap();
void _FreeBitmap();
BBitmap* fDrawBuffer;
};
#endif
class BRowContainer : public BObjectList<BRow>
{
};
class TitleView : public BView {
typedef BView _inherited;
public:
@@ -198,10 +222,6 @@ private:
// float fColumnsWidth;
BRect fVisibleRect;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
BBitmap* fDrawBuffer;
BView* fDrawBufferView;
#endif
enum {
INACTIVE,
@@ -292,6 +312,10 @@ public:
virtual void MouseUp(BPoint where);
virtual void MessageReceived(BMessage* message);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
ColumnResizeBufferView* ResizeBufferView();
#endif
private:
bool SortList(BRowContainer* list, bool isVisible);
static int32 DeepSortThreadEntry(void* outlineView);
@@ -311,8 +335,7 @@ private:
BRect fVisibleRect;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
BBitmap* fDrawBuffer;
BView* fDrawBufferView;
ColumnResizeBufferView* fResizeBufferView;
#endif
BRow* fFocusRow;
@@ -391,6 +414,101 @@ private:
using namespace BPrivate;
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
ColumnResizeBufferView::ColumnResizeBufferView()
: BView(BRect(0, 0, 600, 35), "double_buffer_view", B_FOLLOW_ALL_SIDES, 0), fDrawBuffer(NULL)
{
_InitBitmap();
}
ColumnResizeBufferView::~ColumnResizeBufferView()
{
_FreeBitmap();
}
void
ColumnResizeBufferView::UpdateMaxWidth(float width)
{
Lock();
BRect bounds = Bounds();
Unlock();
if (width > bounds.Width()) {
Lock();
ResizeTo(width, bounds.Height());
Unlock();
_InitBitmap();
}
}
void
ColumnResizeBufferView::UpdateMaxHeight(float height)
{
Lock();
BRect bounds = Bounds();
Unlock();
if (height > bounds.Height()) {
Lock();
ResizeTo(bounds.Width(), height);
Unlock();
_InitBitmap();
}
}
bool
ColumnResizeBufferView::Lock()
{
return fDrawBuffer->Lock();
}
void
ColumnResizeBufferView::Unlock()
{
fDrawBuffer->Unlock();
}
const BBitmap*
ColumnResizeBufferView::Bitmap()
{
return fDrawBuffer;
}
void
ColumnResizeBufferView::_InitBitmap()
{
_FreeBitmap();
fDrawBuffer = new BBitmap(Bounds(), B_RGB32, true);
fDrawBuffer->Lock();
fDrawBuffer->AddChild(this);
fDrawBuffer->Unlock();
}
void
ColumnResizeBufferView::_FreeBitmap()
{
if (fDrawBuffer) {
fDrawBuffer->Lock();
fDrawBuffer->RemoveChild(this);
fDrawBuffer->Unlock();
delete fDrawBuffer;
fDrawBuffer = NULL;
}
}
#endif
BField::BField()
{
}
@@ -2223,17 +2341,6 @@ TitleView::TitleView(BRect rect, OutlineView* horizontalSlave,
{
SetViewColor(B_TRANSPARENT_COLOR);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
// xxx this needs to be smart about the size of the backbuffer.
BRect doubleBufferRect(0, 0, 600, 35);
fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true);
fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view",
B_FOLLOW_ALL_SIDES, 0);
fDrawBuffer->Lock();
fDrawBuffer->AddChild(fDrawBufferView);
fDrawBuffer->Unlock();
#endif
fUpSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_CMAP8);
fDownSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_CMAP8);
@@ -2254,9 +2361,6 @@ TitleView::~TitleView()
delete fColumnPop;
fColumnPop = NULL;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
delete fDrawBuffer;
#endif
delete fUpSortArrow;
delete fDownSortArrow;
@@ -2270,6 +2374,9 @@ TitleView::~TitleView()
void
TitleView::ColumnAdded(BColumn* column)
{
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
fOutlineView->ResizeBufferView()->UpdateMaxWidth(column->MaxWidth());
#endif
// fColumnsWidth += column->Width();
FixScrollBar(false);
Invalidate();
@@ -2481,13 +2588,14 @@ TitleView::ResizeSelectedColumn(BPoint position, bool preferred)
destRect.OffsetBy(fSelectedColumnRect.left, 0);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
fDrawBuffer->Lock();
DrawTitle(fDrawBufferView, sourceRect, fSelectedColumn, false);
fDrawBufferView->Sync();
fDrawBuffer->Unlock();
ColumnResizeBufferView* bufferView = fOutlineView->ResizeBufferView();
bufferView->Lock();
DrawTitle(bufferView, sourceRect, fSelectedColumn, false);
bufferView->Sync();
bufferView->Unlock();
CopyBits(originalRect, movedRect);
DrawBitmap(fDrawBuffer, sourceRect, destRect);
DrawBitmap(bufferView->Bitmap(), sourceRect, destRect);
#else
CopyBits(originalRect, movedRect);
DrawTitle(this, destRect, fSelectedColumn, false);
@@ -3113,15 +3221,7 @@ OutlineView::OutlineView(BRect rect, BList* visibleColumns, BList* sortColumns,
SetViewColor(B_TRANSPARENT_COLOR);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
// TODO: This needs to be smart about the size of the buffer.
// Also, the buffer can be shared with the title's buffer.
BRect doubleBufferRect(0, 0, 600, 35);
fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true);
fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view",
B_FOLLOW_ALL_SIDES, 0);
fDrawBuffer->Lock();
fDrawBuffer->AddChild(fDrawBufferView);
fDrawBuffer->Unlock();
fResizeBufferView = new ColumnResizeBufferView();
#endif
FixScrollBar(true);
@@ -3133,7 +3233,7 @@ OutlineView::OutlineView(BRect rect, BList* visibleColumns, BList* sortColumns,
OutlineView::~OutlineView()
{
#if DOUBLE_BUFFERED_COLUMN_RESIZE
delete fDrawBuffer;
delete fResizeBufferView;
#endif
Clear();
@@ -3275,15 +3375,15 @@ OutlineView::RedrawColumn(BColumn* column, float leftEdge, bool isFirstColumn)
#if DOUBLE_BUFFERED_COLUMN_RESIZE
fDrawBuffer->Lock();
fResizeBufferView->Lock();
fDrawBufferView->SetHighColor(highColor);
fDrawBufferView->SetLowColor(lowColor);
fResizeBufferView->SetHighColor(highColor);
fResizeBufferView->SetLowColor(lowColor);
BFont font;
GetFont(&font);
fDrawBufferView->SetFont(&font);
fDrawBufferView->FillRect(sourceRect, B_SOLID_LOW);
fResizeBufferView->SetFont(&font);
fResizeBufferView->FillRect(sourceRect, B_SOLID_LOW);
if (isFirstColumn) {
// If this is the first column, double buffer drawing the latch
@@ -3299,7 +3399,7 @@ OutlineView::RedrawColumn(BColumn* column, float leftEdge, bool isFirstColumn)
BRect latchRect(sourceRect);
latchRect.right = latchRect.left + fMasterView->LatchWidth();
fMasterView->DrawLatch(fDrawBufferView, latchRect, pos, row);
fMasterView->DrawLatch(fResizeBufferView, latchRect, pos, row);
}
BField* field = row->GetField(column->fFieldID);
@@ -3310,33 +3410,33 @@ OutlineView::RedrawColumn(BColumn* column, float leftEdge, bool isFirstColumn)
#if CONSTRAIN_CLIPPING_REGION
BRegion clipRegion(fieldRect);
fDrawBufferView->PushState();
fDrawBufferView->ConstrainClippingRegion(&clipRegion);
fResizeBufferView->PushState();
fResizeBufferView->ConstrainClippingRegion(&clipRegion);
#endif
fDrawBufferView->SetHighColor(fMasterView->Color(
fResizeBufferView->SetHighColor(fMasterView->Color(
row->fNextSelected ? B_COLOR_SELECTION_TEXT
: B_COLOR_TEXT));
float baseline = floor(fieldRect.top + fh.ascent
+ (fieldRect.Height() + 1 - (fh.ascent+fh.descent)) / 2);
fDrawBufferView->MovePenTo(fieldRect.left + 8, baseline);
column->DrawField(field, fieldRect, fDrawBufferView);
fResizeBufferView->MovePenTo(fieldRect.left + 8, baseline);
column->DrawField(field, fieldRect, fResizeBufferView);
#if CONSTRAIN_CLIPPING_REGION
fDrawBufferView->PopState();
fResizeBufferView->PopState();
#endif
}
if (fFocusRow == row && !fEditMode && fMasterView->IsFocus()
&& Window()->IsActive()) {
fDrawBufferView->SetHighColor(fMasterView->Color(
fResizeBufferView->SetHighColor(fMasterView->Color(
B_COLOR_ROW_DIVIDER));
fDrawBufferView->StrokeRect(BRect(-1, sourceRect.top,
fResizeBufferView->StrokeRect(BRect(-1, sourceRect.top,
10000.0, sourceRect.bottom));
}
fDrawBufferView->Sync();
fDrawBuffer->Unlock();
fResizeBufferView->Sync();
fResizeBufferView->Unlock();
SetDrawingMode(B_OP_COPY);
DrawBitmap(fDrawBuffer, sourceRect, destRect);
DrawBitmap(fResizeBufferView->Bitmap(), sourceRect, destRect);
#else
@@ -4013,6 +4113,17 @@ OutlineView::MessageReceived(BMessage* message)
}
#if DOUBLE_BUFFERED_COLUMN_RESIZE
ColumnResizeBufferView*
OutlineView::ResizeBufferView()
{
return fResizeBufferView;
}
#endif
void
OutlineView::ChangeFocusRow(bool up, bool updateSelection,
bool addToCurrentSelection)
@@ -4381,6 +4492,10 @@ OutlineView::AddRow(BRow* row, int32 Index, BRow* parentRow)
}
}
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
ResizeBufferView()->UpdateMaxHeight(row->Height());
#endif
if (parentRow == 0 || parentRow->fIsExpanded)
fItemsHeight += row->Height() + 1;