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
Fixes #14888
Change-Id: I4feddf636fb1446c29e60353b8f70fc084833731
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7176
Reviewed-by: John Scipione <jscipione@gmail.com>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Reviewed-by: Stefano Ceccherini <stefano.ceccherini@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
(cherry picked from commit 94b4024f220b3b329b702b8a151493492d4be4d0)
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7216
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
Diff
src/kits/interface/ColumnListView.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 167 insertions(+), 52 deletions(-)
@@ -144,9 +144,33 @@
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;
@@ -198,10 +222,6 @@
BRect fVisibleRect;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
BBitmap* fDrawBuffer;
BView* fDrawBufferView;
#endif
enum {
INACTIVE,
@@ -291,6 +311,10 @@
const BMessage* dragMessage);
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);
@@ -311,8 +335,7 @@
BRect fVisibleRect;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
BBitmap* fDrawBuffer;
BView* fDrawBufferView;
ColumnResizeBufferView* fResizeBufferView;
#endif
BRow* fFocusRow;
@@ -389,8 +412,103 @@
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()
{
}
@@ -2222,17 +2340,6 @@
| B_ALLOW_COLUMN_POPUP | B_ALLOW_COLUMN_REMOVE)
{
SetViewColor(B_TRANSPARENT_COLOR);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
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 @@
delete fColumnPop;
fColumnPop = NULL;
#if DOUBLE_BUFFERED_COLUMN_RESIZE
delete fDrawBuffer;
#endif
delete fUpSortArrow;
delete fDownSortArrow;
@@ -2270,6 +2374,9 @@
void
TitleView::ColumnAdded(BColumn* column)
{
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
fOutlineView->ResizeBufferView()->UpdateMaxWidth(column->MaxWidth());
#endif
FixScrollBar(false);
Invalidate();
@@ -2481,13 +2588,14 @@
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 @@
SetViewColor(B_TRANSPARENT_COLOR);
#if DOUBLE_BUFFERED_COLUMN_RESIZE
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()
{
#if DOUBLE_BUFFERED_COLUMN_RESIZE
delete fDrawBuffer;
delete fResizeBufferView;
#endif
Clear();
@@ -3275,15 +3375,15 @@
#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) {
@@ -3299,7 +3399,7 @@
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 @@
#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
@@ -4010,8 +4110,19 @@
} else {
BView::MessageReceived(message);
}
}
#if DOUBLE_BUFFERED_COLUMN_RESIZE
ColumnResizeBufferView*
OutlineView::ResizeBufferView()
{
return fResizeBufferView;
}
#endif
void
OutlineView::ChangeFocusRow(bool up, bool updateSelection,
@@ -4380,6 +4491,10 @@
fRows.AddItem(row, Index);
}
}
#ifdef DOUBLE_BUFFERED_COLUMN_RESIZE
ResizeBufferView()->UpdateMaxHeight(row->Height());
#endif
if (parentRow == 0 || parentRow->fIsExpanded)
fItemsHeight += row->Height() + 1;