Icon-O-Matic: Fix crashes while auto-scrolling

This fixes crashes that happen when scrolling list views in Icon-O-Matic
triggered by the BListView auto-scroll feature reintroduced in hrev57439.

Take out the auto-scrolling code from Icon-O-Matic, call BListView's
MouseMoved() instead since BListView's can scroll now. The BListView auto-
scroll feature has been updated to work with draggable multi-select.

ScrollTo(index) method has been moved from Icon-O-matic to BListView and
is used to scroll to an index instead of a selection since the selection
doesn't change while you are dragging.

Override BListItem's DrawItem() method to prevent it from drawing. I've
hijacked DrawItem()'s complete param to mean even or odd instead.

Everybody draws the same background PathListView.cpp and StyleListView.cpp
now push the frame over and draw text using SimpleListView parent class
DrawItem() instead of repeating the drawing code.

InitiateDrag got moved from the abstract DragSortableListView class to the
SimpleListView implementation class.

The following color constants have been added:
rgb_color kDropIndicatorColor = make_color(255, 65, 54, 255);
rgb_color kDragFrameColor = make_color(17, 17, 17, 255);

First one is the red drop target indicator line. It has been changed to
clrs.cc red which is the same as B_FAILURE_COLOR, but I didn't want to use
that InterfaceDef constant as it doesn't indicate failure in this case,
it's just a slightly different red.

Second one is the drag selection outline, it has been changed from pure
black to clrs.cc black which is a shade lighter than pure black.

Fixes #18707

Change-Id: Ib0b375d7d5641d458a6ce004a6dfeac551636698
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7215
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
John Scipione 2023-12-23 10:42:20 -05:00 committed by waddlesplash
parent 2f719499aa
commit f99596f4e3
4 changed files with 233 additions and 372 deletions

View File

@ -33,9 +33,9 @@
#define ALPHA 170
#define TEXT_OFFSET 5.0
enum {
MSG_TICK = 'tick',
};
static const rgb_color kDropIndicatorColor = make_color(255, 65, 54, 255);
static const rgb_color kDragFrameColor = make_color(17, 17, 17, 255);
// #pragma mark - SimpleItem
@ -54,9 +54,10 @@ SimpleItem::~SimpleItem()
void
SimpleItem::Draw(BView *owner, BRect frame, uint32 flags)
SimpleItem::DrawItem(BView* owner, BRect itemFrame, bool even)
{
DrawBackground(owner, frame, flags);
DrawBackground(owner, itemFrame, even);
// label
if (IsSelected())
owner->SetHighUIColor(B_LIST_SELECTED_ITEM_TEXT_COLOR);
@ -69,13 +70,13 @@ SimpleItem::Draw(BView *owner, BRect frame, uint32 flags)
const char* text = Text();
BString truncatedString(text);
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
frame.Width() - TEXT_OFFSET - 4);
itemFrame.Width() - TEXT_OFFSET - 4);
float height = frame.Height();
float height = itemFrame.Height();
float textHeight = fh.ascent + fh.descent;
BPoint textPoint;
textPoint.x = frame.left + TEXT_OFFSET;
textPoint.y = frame.top
textPoint.x = itemFrame.left + TEXT_OFFSET;
textPoint.y = itemFrame.top
+ ceilf(height / 2 - textHeight / 2 + fh.ascent);
owner->DrawString(truncatedString.String(), textPoint);
@ -83,25 +84,27 @@ SimpleItem::Draw(BView *owner, BRect frame, uint32 flags)
void
SimpleItem::DrawBackground(BView *owner, BRect frame, uint32 flags)
SimpleItem::DrawBackground(BView* owner, BRect itemFrame, bool even)
{
// stroke a blue frame around the item if it's focused
if (flags & FLAGS_FOCUSED) {
owner->SetLowColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
owner->StrokeRect(frame, B_SOLID_LOW);
frame.InsetBy(1.0, 1.0);
}
// figure out bg-color
rgb_color color = ui_color(B_LIST_BACKGROUND_COLOR);
rgb_color bgColor;
if (!IsEnabled()) {
rgb_color textColor = ui_color(B_LIST_ITEM_TEXT_COLOR);
rgb_color disabledColor;
if (textColor.red + textColor.green + textColor.blue > 128 * 3)
disabledColor = tint_color(textColor, B_DARKEN_2_TINT);
else
disabledColor = tint_color(textColor, B_LIGHTEN_2_TINT);
bgColor = disabledColor;
} else if (IsSelected())
bgColor = ui_color(B_LIST_SELECTED_BACKGROUND_COLOR);
else
bgColor = ui_color(B_LIST_BACKGROUND_COLOR);
if (IsSelected())
color = ui_color(B_LIST_SELECTED_BACKGROUND_COLOR);
if (even)
bgColor = tint_color(bgColor, 1.06);
if (flags & FLAGS_TINTED_LINE)
color = tint_color(color, 1.06);
owner->SetLowColor(color);
owner->FillRect(frame, B_SOLID_LOW);
owner->SetLowColor(bgColor);
owner->FillRect(itemFrame, B_SOLID_LOW);
}
@ -131,7 +134,6 @@ DragSortableListView::DragSortableListView(BRect frame, const char* name,
DragSortableListView::~DragSortableListView()
{
delete fMouseWheelFilter;
delete fScrollPulse;
SetSelection(NULL);
}
@ -166,54 +168,6 @@ DragSortableListView::FrameResized(float width, float height)
}
void
DragSortableListView::Draw(BRect updateRect)
{
int32 firstIndex = IndexOf(updateRect.LeftTop());
int32 lastIndex = IndexOf(updateRect.RightBottom());
if (firstIndex >= 0) {
if (lastIndex < firstIndex)
lastIndex = CountItems() - 1;
// update rect contains items
BRect r = updateRect;
for (int32 i = firstIndex; i <= lastIndex; i++) {
r = ItemFrame(i);
DrawListItem(this, i, r);
}
updateRect.top = r.bottom + 1.0;
if (updateRect.IsValid()) {
SetLowColor(ui_color(B_LIST_BACKGROUND_COLOR));
FillRect(updateRect, B_SOLID_LOW);
}
} else {
SetLowColor(ui_color(B_LIST_BACKGROUND_COLOR));
FillRect(updateRect, B_SOLID_LOW);
}
// drop anticipation indication
if (fDropRect.IsValid()) {
SetHighColor(255, 0, 0, 255);
StrokeRect(fDropRect);
}
/* // focus indication
if (IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(Bounds());
}*/
}
void
DragSortableListView::ScrollTo(BPoint where)
{
uint32 buttons;
BPoint point;
GetMouse(&point, &buttons, false);
uint32 transit = Bounds().Contains(point) ? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
MouseMoved(point, transit, &fDragMessageCopy);
BListView::ScrollTo(where);
}
void
DragSortableListView::TargetedByScrollView(BScrollView* scrollView)
{
@ -222,103 +176,6 @@ DragSortableListView::TargetedByScrollView(BScrollView* scrollView)
}
bool
DragSortableListView::InitiateDrag(BPoint point, int32 index, bool)
{
// supress drag&drop while an item is focused
if (fFocusedIndex >= 0)
return false;
bool success = false;
BListItem* item = ItemAt(CurrentSelection(0));
if (!item) {
// workarround a timing problem
Select(index);
item = ItemAt(index);
}
if (item) {
// create drag message
BMessage msg(fDragCommand);
MakeDragMessage(&msg);
// figure out drag rect
float width = Bounds().Width();
BRect dragRect(0.0, 0.0, width, -1.0);
// figure out, how many items fit into our bitmap
int32 numItems;
bool fade = false;
for (numItems = 0; BListItem* item = ItemAt(CurrentSelection(numItems)); numItems++) {
dragRect.bottom += ceilf(item->Height()) + 1.0;
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
fade = true;
dragRect.bottom = MAX_DRAG_HEIGHT;
numItems++;
break;
}
}
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
if (dragBitmap && dragBitmap->IsValid()) {
if (BView *v = new BView(dragBitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW)) {
dragBitmap->AddChild(v);
dragBitmap->Lock();
BRect itemBounds(dragRect) ;
itemBounds.bottom = 0.0;
// let all selected items, that fit into our drag_bitmap, draw
for (int32 i = 0; i < numItems; i++) {
int32 index = CurrentSelection(i);
BListItem* item = ItemAt(index);
itemBounds.bottom = itemBounds.top + ceilf(item->Height());
if (itemBounds.bottom > dragRect.bottom)
itemBounds.bottom = dragRect.bottom;
DrawListItem(v, index, itemBounds);
itemBounds.top = itemBounds.bottom + 1.0;
}
// make a black frame arround the edge
v->SetHighColor(0, 0, 0, 255);
v->StrokeRect(v->Bounds());
v->Sync();
uint8 *bits = (uint8 *)dragBitmap->Bits();
int32 height = (int32)dragBitmap->Bounds().Height() + 1;
int32 width = (int32)dragBitmap->Bounds().Width() + 1;
int32 bpr = dragBitmap->BytesPerRow();
if (fade) {
for (int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
for (int32 y = height - ALPHA / 2; y < height; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = (height - y) << 1;
}
} else {
for (int32 y = 0; y < height; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
}
dragBitmap->Unlock();
}
} else {
delete dragBitmap;
dragBitmap = NULL;
}
if (dragBitmap)
DragMessage(&msg, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
else
DragMessage(&msg, dragRect.OffsetToCopy(point), this);
SetDragMessage(&msg);
success = true;
}
return success;
}
void
DragSortableListView::WindowActivated(bool active)
{
@ -339,37 +196,6 @@ DragSortableListView::MessageReceived(BMessage* message)
fDropIndex = -1;
} else {
switch (message->what) {
case MSG_TICK: {
float scrollV = 0.0;
BRect rect(Bounds());
BPoint point;
uint32 buttons;
GetMouse(&point, &buttons, false);
if (rect.Contains(point)) {
// calculate the vertical scrolling offset
float hotDist = rect.Height() * SCROLL_AREA;
if (point.y > rect.bottom - hotDist)
scrollV = hotDist - (rect.bottom - point.y);
else if (point.y < rect.top + hotDist)
scrollV = (point.y - rect.top) - hotDist;
}
// scroll
if (scrollV != 0.0 && fScrollView) {
if (BScrollBar* scrollBar = fScrollView->ScrollBar(B_VERTICAL)) {
float value = scrollBar->Value();
scrollBar->SetValue(scrollBar->Value() + scrollV);
if (scrollBar->Value() != value) {
// update mouse position
uint32 buttons;
BPoint point;
GetMouse(&point, &buttons, false);
uint32 transit = Bounds().Contains(point) ? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
MouseMoved(point, transit, &fDragMessageCopy);
}
}
}
break;
}
case B_MOUSE_WHEEL_CHANGED:
{
BListView::MessageReceived(message);
@ -405,35 +231,34 @@ DragSortableListView::KeyDown(const char* bytes, int32 numBytes)
void
DragSortableListView::MouseDown(BPoint where)
{
int32 clicks = 1;
uint32 buttons = 0;
Window()->CurrentMessage()->FindInt32("clicks", &clicks);
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
int32 clickedIndex = -1;
for (int32 i = 0; BListItem* item = ItemAt(i); i++) {
if (ItemFrame(i).Contains(where)) {
if (clicks == 2) {
// only do something if user clicked the same item twice
if (fLastClickedItem == item)
DoubleClicked(i);
} else {
// remember last clicked item
fLastClickedItem = item;
}
clickedIndex = i;
break;
}
}
if (clickedIndex == -1)
fLastClickedItem = NULL;
int32 index = IndexOf(where);
BListItem* item = ItemAt(index);
BListItem* item = ItemAt(clickedIndex);
if (ListType() == B_MULTIPLE_SELECTION_LIST && item != NULL
&& (buttons & B_SECONDARY_MOUSE_BUTTON)) {
// bail out if item not found
if (index < 0 || item == NULL) {
fLastClickedItem = NULL;
return BListView::MouseDown(where);
}
int32 clicks = 1;
int32 buttons = 0;
Window()->CurrentMessage()->FindInt32("clicks", &clicks);
Window()->CurrentMessage()->FindInt32("buttons", &buttons);
if (clicks == 2 && item == fLastClickedItem) {
// only do something if user clicked the same item twice
DoubleClicked(index);
} else {
// remember last clicked item
fLastClickedItem = item;
}
if (ListType() == B_MULTIPLE_SELECTION_LIST
&& (buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
if (item->IsSelected())
Deselect(clickedIndex);
Deselect(index);
else
Select(clickedIndex, true);
Select(index, true);
} else
BListView::MouseDown(where);
}
@ -442,40 +267,42 @@ DragSortableListView::MouseDown(BPoint where)
void
DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage* msg)
{
if (msg && AcceptDragMessage(msg)) {
int32 buttons = 0;
Window()->CurrentMessage()->FindInt32("buttons", &buttons);
// only start a drag if a button is down and we have a drag message
if (buttons > 0 && msg && AcceptDragMessage(msg)) {
// we have dragged off the mouse down item
// turn on auto-scrolling and drag and drop
switch (transit) {
case B_ENTERED_VIEW:
case B_INSIDE_VIEW: {
// remember drag message
// this is needed to react on modifier changes
case B_INSIDE_VIEW:
// remember drag message to react on modifier changes
SetDragMessage(msg);
// set drop target through virtual function
SetDropTargetRect(msg, where);
// go into autoscrolling mode
BRect r = Bounds();
r.InsetBy(0.0, r.Height() * SCROLL_AREA);
SetAutoScrolling(!r.Contains(where));
break;
}
break;
case B_EXITED_VIEW:
// forget drag message
SetDragMessage(NULL);
SetAutoScrolling(false);
// fall through
case B_OUTSIDE_VIEW:
// don't draw drop rect indicator
InvalidateDropRect();
case B_OUTSIDE_VIEW:
break;
}
} else {
InvalidateDropRect();
BListView::MouseMoved(where, transit, msg);
// be sure to forget drag message
SetDragMessage(NULL);
SetAutoScrolling(false);
// don't draw drop rect indicator
InvalidateDropRect();
// restore hand cursor
BCursor cursor(B_HAND_CURSOR);
SetViewCursor(&cursor, true);
}
fLastMousePos = where;
BListView::MouseMoved(where, transit, msg);
}
@ -494,17 +321,6 @@ DragSortableListView::MouseUp(BPoint where)
}
void
DragSortableListView::DrawItem(BListItem *item, BRect itemFrame, bool complete)
{
DrawListItem(this, IndexOf(item), itemFrame);
/* if (IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(Bounds());
}*/
}
bool
DragSortableListView::MouseWheelChanged(float x, float y)
{
@ -654,46 +470,10 @@ DragSortableListView::HandleDropMessage(const BMessage* message,
}
void
DragSortableListView::SetAutoScrolling(bool enable)
{
if (fScrollPulse && enable)
return;
if (enable) {
BMessenger messenger(this, Window());
BMessage message(MSG_TICK);
fScrollPulse = new BMessageRunner(messenger, &message, 40000LL);
} else {
delete fScrollPulse;
fScrollPulse = NULL;
}
}
bool
DragSortableListView::DoesAutoScrolling() const
{
return fScrollPulse;
}
void
DragSortableListView::ScrollTo(int32 index)
{
if (index < 0)
index = 0;
if (index >= CountItems())
index = CountItems() - 1;
if (ItemAt(index)) {
BRect itemFrame = ItemFrame(index);
BRect bounds = Bounds();
if (itemFrame.top < bounds.top) {
ScrollTo(itemFrame.LeftTop());
} else if (itemFrame.bottom > bounds.bottom) {
ScrollTo(BPoint(0.0, itemFrame.bottom - bounds.Height()));
}
}
return true;
}
@ -974,6 +754,152 @@ SimpleListView::DetachedFromWindow()
}
void
SimpleListView::Draw(BRect updateRect)
{
BRect emptyRect = updateRect;
int32 firstIndex = IndexOf(updateRect.LeftTop());
int32 lastIndex = IndexOf(updateRect.RightBottom());
if (firstIndex >= 0) {
BListItem* item;
BRect itemFrame(0, 0, -1, -1);
if (lastIndex < firstIndex)
lastIndex = CountItems() - 1;
// update rect contains items
for (int32 i = firstIndex; i <= lastIndex; i++) {
item = ItemAt(i);
if (item == NULL)
continue;
itemFrame = ItemFrame(i);
item->DrawItem(this, itemFrame, (i % 2) == 0);
// drop indicator
if (i == fDropIndex) {
SetHighColor(kDropIndicatorColor);
StrokeLine(fDropRect.LeftTop(), fDropRect.RightTop());
}
}
emptyRect.top = itemFrame.bottom + 1;
}
if (emptyRect.IsValid()) {
SetLowUIColor(B_LIST_BACKGROUND_COLOR);
FillRect(emptyRect, B_SOLID_LOW);
}
#if 0
// focus indicator
if (IsFocus()) {
SetHighUIColor(B_KEYBOARD_NAVIGATION_COLOR);
StrokeRect(Bounds());
}
#endif
}
bool
SimpleListView::InitiateDrag(BPoint where, int32 index, bool)
{
// supress drag & drop while an item is focused
if (fFocusedIndex >= 0)
return false;
BListItem* item = ItemAt(CurrentSelection(0));
if (item == NULL) {
// work-around a timing problem
Select(index);
item = ItemAt(index);
}
if (item == NULL)
return false;
// create drag message
BMessage msg(fDragCommand);
MakeDragMessage(&msg);
// figure out drag rect
float width = Bounds().Width();
BRect dragRect(0, 0, width, -1);
// figure out how many items fit into our bitmap
int32 numItems;
bool fade = false;
for (numItems = 0; BListItem* item = ItemAt(CurrentSelection(numItems)); numItems++) {
dragRect.bottom += ceilf(item->Height()) + 1;
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
fade = true;
dragRect.bottom = MAX_DRAG_HEIGHT;
numItems++;
break;
}
}
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGBA32, true);
if (dragBitmap && dragBitmap->IsValid()) {
if (BView* view = new BView(dragBitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW)) {
dragBitmap->AddChild(view);
dragBitmap->Lock();
BRect itemFrame(dragRect) ;
itemFrame.bottom = 0.0;
BListItem* item;
// let all selected items, that fit into our drag_bitmap, draw
for (int32 i = 0; i < numItems; i++) {
item = ItemAt(CurrentSelection(i));
if (item == NULL)
continue;
itemFrame.bottom = itemFrame.top + ceilf(item->Height());
if (itemFrame.bottom > dragRect.bottom)
itemFrame.bottom = dragRect.bottom;
item->DrawItem(view, itemFrame, (i % 2) == 0);
itemFrame.top = itemFrame.bottom + 1;
}
// stroke a black frame around the edge
view->SetHighColor(kDragFrameColor);
view->StrokeRect(view->Bounds());
view->Sync();
uint8* bits = (uint8*)dragBitmap->Bits();
int32 height = (int32)dragBitmap->Bounds().Height() + 1;
int32 width = (int32)dragBitmap->Bounds().Width() + 1;
int32 bpr = dragBitmap->BytesPerRow();
if (fade) {
for (int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr) {
uint8* line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
for (int32 y = height - ALPHA / 2; y < height; y++, bits += bpr) {
uint8* line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = (height - y) << 1;
}
} else {
for (int32 y = 0; y < height; y++, bits += bpr) {
uint8* line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
}
dragBitmap->Unlock();
}
} else {
delete dragBitmap;
dragBitmap = NULL;
}
if (dragBitmap)
DragMessage(&msg, dragBitmap, B_OP_ALPHA, B_ORIGIN);
else
DragMessage(&msg, dragRect.OffsetToCopy(where), this);
SetDragMessage(&msg);
return true;
}
void
SimpleListView::MessageReceived(BMessage* message)
{
@ -1026,20 +952,6 @@ SimpleListView::CloneItem(int32 atIndex) const
}
void
SimpleListView::DrawListItem(BView* owner, int32 index, BRect frame) const
{
if (SimpleItem* item = dynamic_cast<SimpleItem*>(ItemAt(index))) {
uint32 flags = FLAGS_NONE;
if (index == fFocusedIndex)
flags |= FLAGS_FOCUSED;
if (index % 2)
flags |= FLAGS_TINTED_LINE;
item->Draw(owner, frame, flags);
}
}
void
SimpleListView::MakeDragMessage(BMessage* message) const
{

View File

@ -17,13 +17,6 @@
#include "MouseWheelFilter.h"
#include "Observer.h"
enum
{
FLAGS_NONE = 0x00,
FLAGS_TINTED_LINE = 0x01,
FLAGS_FOCUSED = 0x02,
};
// portion of the listviews height that triggers autoscrolling
// when the mouse is over it with a dragmessage
#define SCROLL_AREA 0.1
@ -41,10 +34,8 @@ class SimpleItem : public BStringItem
SimpleItem(const char* name);
virtual ~SimpleItem();
virtual void Draw(BView* owner, BRect frame,
uint32 flags);
virtual void DrawBackground(BView* owner, BRect frame,
uint32 flags);
virtual void DrawItem(BView*, BRect, bool even = false);
virtual void DrawBackground(BView*, BRect, bool even);
};
@ -65,20 +56,13 @@ class DragSortableListView : public BListView,
virtual void DetachedFromWindow();
virtual void FrameResized(float width, float height);
// virtual void MakeFocus(bool focused);
virtual void Draw(BRect updateRect);
virtual void ScrollTo(BPoint where);
virtual void TargetedByScrollView(BScrollView* scrollView);
virtual bool InitiateDrag(BPoint point, int32 index,
bool wasSelected);
virtual void TargetedByScrollView(BScrollView*);
virtual void MessageReceived(BMessage* message);
virtual void KeyDown(const char* bytes, int32 numBytes);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MouseMoved(BPoint where, uint32, const BMessage*);
virtual void MouseUp(BPoint where);
virtual void WindowActivated(bool active);
virtual void DrawItem(BListItem *item, BRect itemFrame,
bool complete = false);
// MouseWheelTarget interface
virtual bool MouseWheelChanged(float x, float y);
@ -99,12 +83,9 @@ class DragSortableListView : public BListView,
virtual void SetDropTargetRect(const BMessage* message,
BPoint where);
// autoscrolling
void SetAutoScrolling(bool enable);
bool DoesAutoScrolling() const;
BScrollView* ScrollView() const
{ return fScrollView; }
void ScrollTo(int32 index);
virtual void MoveItems(BList& items, int32 toIndex);
virtual void CopyItems(BList& items, int32 toIndex);
@ -125,8 +106,6 @@ class DragSortableListView : public BListView,
virtual void SelectionChanged();
virtual BListItem* CloneItem(int32 atIndex) const = 0;
virtual void DrawListItem(BView* owner, int32 index,
BRect itemFrame) const = 0;
virtual void MakeDragMessage(BMessage* message) const = 0;
protected:
@ -170,11 +149,11 @@ class SimpleListView : public DragSortableListView {
// BListView
virtual void DetachedFromWindow();
virtual void Draw(BRect updateRect);
virtual bool InitiateDrag(BPoint, int32, bool);
virtual void MessageReceived(BMessage* message);
virtual BListItem* CloneItem(int32 atIndex) const;
virtual void DrawListItem(BView* owner, int32 index,
BRect itemFrame) const;
/*! Archive the selected items.
The information should be sufficient for \c InstantiateSelection to

View File

@ -70,27 +70,12 @@ public:
// SimpleItem interface
virtual void Draw(BView* owner, BRect itemFrame, uint32 flags)
virtual void DrawItem(BView* owner, BRect itemFrame, bool even)
{
SimpleItem::DrawBackground(owner, itemFrame, flags);
SimpleItem::DrawBackground(owner, itemFrame, even);
// text
if (IsSelected())
owner->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR));
else
owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
font_height fh;
owner->GetFontHeight(&fh);
BString truncatedString(Text());
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
itemFrame.Width() - kBorderOffset - kMarkWidth - kTextOffset
- kBorderOffset);
float height = itemFrame.Height();
float textHeight = fh.ascent + fh.descent;
BPoint pos;
pos.x = itemFrame.left + kBorderOffset + kMarkWidth + kTextOffset;
pos.y = itemFrame.top + ceilf((height - textHeight) / 2.0 + fh.ascent);
owner->DrawString(truncatedString.String(), pos);
float offset = kBorderOffset + kMarkWidth + kTextOffset;
SimpleItem::DrawItem(owner, itemFrame.OffsetByCopy(offset, 0), even);
if (!fMarkEnabled)
return;

View File

@ -76,27 +76,12 @@ public:
}
// SimpleItem interface
virtual void Draw(BView* owner, BRect itemFrame, uint32 flags)
virtual void DrawItem(BView* owner, BRect itemFrame, bool even)
{
SimpleItem::DrawBackground(owner, itemFrame, flags);
SimpleItem::DrawBackground(owner, itemFrame, even);
// text
if (IsSelected())
owner->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR));
else
owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
font_height fh;
owner->GetFontHeight(&fh);
BString truncatedString(Text());
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
itemFrame.Width() - kBorderOffset - kMarkWidth - kTextOffset
- kBorderOffset);
float height = itemFrame.Height();
float textHeight = fh.ascent + fh.descent;
BPoint pos;
pos.x = itemFrame.left + kBorderOffset + kMarkWidth + kTextOffset;
pos.y = itemFrame.top + ceilf((height - textHeight) / 2.0 + fh.ascent);
owner->DrawString(truncatedString.String(), pos);
float offset = kBorderOffset + kMarkWidth + kTextOffset;
SimpleItem::DrawItem(owner, itemFrame.OffsetByCopy(offset, 0), even);
if (!fMarkEnabled)
return;