⛏️ index : haiku.git

author Freaxed <andrea.anzani@gmail.com> 2023-12-04 14:44:02.0 +01:00:00
committer Adrien Destugues <pulkomandy@pulkomandy.tk> 2023-12-24 13:21:41.0 +00:00:00
commit
2ad546a6bc10de9ec1d8412262cdc5843345dfbf [patch]
tree
b361ea2ea03897509a5c72c7f098638c148bad6b
parent
fab984f6062749752acb2e6a21e146848e888d1d
download
2ad546a6bc10de9ec1d8412262cdc5843345dfbf.tar.gz

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(-)

diff --git a/src/kits/interface/ColumnListView.cpp b/src/kits/interface/ColumnListView.cpp
index 7ac13c0..48f00a0 100644
--- a/src/kits/interface/ColumnListView.cpp
+++ b/src/kits/interface/ColumnListView.cpp
@@ -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 @@
//			float				fColumnsWidth;
			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

	// 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 @@
	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
//	fColumnsWidth += column->Width();
	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

	// 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()
{
#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) {
				// If this is the first column, double buffer drawing the latch
@@ -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;