Improve drag'n'drop in Locale preflet:
* following a hint by Stephan: implement drawing of a drop target indicator, a global one (bounds) for the available languages and an individual drop target indicator ("between" the items) for the preferred languages * fix drag'n'drop within preferred languages listview * finish support for manipulating multiple items in preferred languages listview git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42686 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fdecfdb35c
commit
f6102c6fba
|
@ -62,25 +62,21 @@ void
|
|||
LanguageListItem::DrawItemWithTextOffset(BView* owner, BRect frame,
|
||||
bool complete, float textOffset)
|
||||
{
|
||||
static const rgb_color kHighlight = {140, 140, 140, 0};
|
||||
static const rgb_color kBlack = {0, 0, 0, 0};
|
||||
|
||||
if (IsSelected() || complete) {
|
||||
rgb_color color;
|
||||
if (IsSelected())
|
||||
color = kHighlight;
|
||||
color = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR);
|
||||
else
|
||||
color = owner->ViewColor();
|
||||
owner->SetHighColor(color);
|
||||
owner->SetLowColor(color);
|
||||
owner->FillRect(frame);
|
||||
owner->SetHighColor(kBlack);
|
||||
} else
|
||||
owner->SetLowColor(owner->ViewColor());
|
||||
|
||||
BString text = Text();
|
||||
if (IsEnabled())
|
||||
owner->SetHighColor(kBlack);
|
||||
owner->SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
||||
else {
|
||||
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT));
|
||||
text << " [" << B_TRANSLATE("already chosen") << "]";
|
||||
|
@ -168,6 +164,8 @@ LanguageListView::LanguageListView(const char* name, list_view_type type)
|
|||
:
|
||||
BOutlineListView(name, type),
|
||||
fDropIndex(-1),
|
||||
fDropTargetHighlightFrame(),
|
||||
fGlobalDropTargetIndicator(false),
|
||||
fDeleteMessage(NULL),
|
||||
fDragMessage(NULL)
|
||||
{
|
||||
|
@ -231,6 +229,13 @@ LanguageListView::SetDragMessage(BMessage* message)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageListView::SetGlobalDropTargetIndicator(bool isGlobal)
|
||||
{
|
||||
fGlobalDropTargetIndicator = isGlobal;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageListView::AttachedToWindow()
|
||||
{
|
||||
|
@ -247,13 +252,24 @@ LanguageListView::MessageReceived(BMessage* message)
|
|||
BMessage dragMessage(*message);
|
||||
dragMessage.AddInt32("drop_index", fDropIndex);
|
||||
dragMessage.AddPointer("drop_target", this);
|
||||
|
||||
Invoke(&dragMessage);
|
||||
Messenger().SendMessage(&dragMessage);
|
||||
} else
|
||||
BOutlineListView::MessageReceived(message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageListView::Draw(BRect updateRect)
|
||||
{
|
||||
BOutlineListView::Draw(updateRect);
|
||||
|
||||
if (fDropIndex >= 0 && fDropTargetHighlightFrame.IsValid()) {
|
||||
SetHighColor(ui_color(B_CONTROL_HIGHLIGHT_COLOR));
|
||||
StrokeRect(fDropTargetHighlightFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
|
||||
bool /*wasSelected*/)
|
||||
|
@ -261,7 +277,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
|
|||
if (fDragMessage == NULL)
|
||||
return false;
|
||||
|
||||
BListItem* item = FullListItemAt(CurrentSelection(0));
|
||||
BListItem* item = ItemAt(CurrentSelection(0));
|
||||
if (item == NULL) {
|
||||
// workaround for a timing problem
|
||||
// TODO: this should support extending the selection
|
||||
|
@ -276,7 +292,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
|
|||
message.AddPointer("listview", this);
|
||||
|
||||
for (int32 i = 0;; i++) {
|
||||
int32 index = FullListCurrentSelection(i);
|
||||
int32 index = CurrentSelection(i);
|
||||
if (index < 0)
|
||||
break;
|
||||
|
||||
|
@ -292,7 +308,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
|
|||
// figure out, how many items fit into our bitmap
|
||||
for (int32 i = 0, index; message.FindInt32("index", i, &index) == B_OK;
|
||||
i++) {
|
||||
BListItem* item = FullListItemAt(index);
|
||||
BListItem* item = ItemAt(index);
|
||||
if (item == NULL)
|
||||
break;
|
||||
|
||||
|
@ -318,7 +334,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
|
|||
for (int32 i = 0; i < numItems; i++) {
|
||||
int32 index = message.FindInt32("index", i);
|
||||
LanguageListItem* item
|
||||
= static_cast<LanguageListItem*>(FullListItemAt(index));
|
||||
= static_cast<LanguageListItem*>(ItemAt(index));
|
||||
itemBounds.bottom = itemBounds.top + ceilf(item->Height());
|
||||
if (itemBounds.bottom > dragRect.bottom)
|
||||
itemBounds.bottom = dragRect.bottom;
|
||||
|
@ -378,21 +394,63 @@ LanguageListView::MouseMoved(BPoint where, uint32 transit,
|
|||
case B_ENTERED_VIEW:
|
||||
case B_INSIDE_VIEW:
|
||||
{
|
||||
// set drop target through virtual function
|
||||
// offset where by half of item height
|
||||
BRect r = ItemFrame(0);
|
||||
where.y += r.Height() / 2.0;
|
||||
BRect highlightFrame;
|
||||
|
||||
int32 index = FullListIndexOf(where);
|
||||
if (index < 0)
|
||||
index = FullListCountItems();
|
||||
if (fDropIndex != index)
|
||||
if (fGlobalDropTargetIndicator) {
|
||||
highlightFrame = Bounds();
|
||||
fDropIndex = 0;
|
||||
} else {
|
||||
// offset where by half of item height
|
||||
BRect r = ItemFrame(0);
|
||||
where.y += r.Height() / 2.0;
|
||||
|
||||
int32 index = IndexOf(where);
|
||||
if (index < 0)
|
||||
index = CountItems();
|
||||
highlightFrame = ItemFrame(index);
|
||||
if (highlightFrame.IsValid())
|
||||
highlightFrame.bottom = highlightFrame.top;
|
||||
else {
|
||||
highlightFrame = ItemFrame(index - 1);
|
||||
if (highlightFrame.IsValid())
|
||||
highlightFrame.top = highlightFrame.bottom;
|
||||
else {
|
||||
// empty view, show indicator at top
|
||||
highlightFrame = Bounds();
|
||||
highlightFrame.bottom = highlightFrame.top;
|
||||
}
|
||||
}
|
||||
fDropIndex = index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fDropTargetHighlightFrame != highlightFrame) {
|
||||
Invalidate(fDropTargetHighlightFrame);
|
||||
fDropTargetHighlightFrame = highlightFrame;
|
||||
Invalidate(fDropTargetHighlightFrame);
|
||||
}
|
||||
|
||||
BOutlineListView::MouseMoved(where, transit, dragMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
BOutlineListView::MouseMoved(where, transit, dragMessage);
|
||||
}
|
||||
|
||||
if (fDropTargetHighlightFrame.IsValid()) {
|
||||
Invalidate(fDropTargetHighlightFrame);
|
||||
fDropTargetHighlightFrame = BRect();
|
||||
}
|
||||
BOutlineListView::MouseMoved(where, transit, dragMessage);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LanguageListView::MouseUp(BPoint point)
|
||||
{
|
||||
BOutlineListView::MouseUp(point);
|
||||
if (fDropTargetHighlightFrame.IsValid()) {
|
||||
Invalidate(fDropTargetHighlightFrame);
|
||||
fDropTargetHighlightFrame = BRect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -74,11 +74,14 @@ public:
|
|||
|
||||
void SetDeleteMessage(BMessage* message);
|
||||
void SetDragMessage(BMessage* message);
|
||||
void SetGlobalDropTargetIndicator(bool isGlobal);
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual bool InitiateDrag(BPoint point, int32 index,
|
||||
bool wasSelected);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
virtual void MouseUp(BPoint point);
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void KeyDown(const char* bytes, int32 numBytes);
|
||||
|
@ -89,6 +92,8 @@ private:
|
|||
|
||||
private:
|
||||
int32 fDropIndex;
|
||||
BRect fDropTargetHighlightFrame;
|
||||
bool fGlobalDropTargetIndicator;
|
||||
BMessage* fDeleteMessage;
|
||||
BMessage* fDragMessage;
|
||||
};
|
||||
|
|
|
@ -89,6 +89,7 @@ LocaleWindow::LocaleWindow()
|
|||
|
||||
fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked));
|
||||
fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged));
|
||||
fLanguageListView->SetGlobalDropTargetIndicator(true);
|
||||
|
||||
BFont font;
|
||||
fLanguageListView->GetFont(&font);
|
||||
|
@ -335,7 +336,7 @@ LocaleWindow::MessageReceived(BMessage* message)
|
|||
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
|
||||
i++) {
|
||||
LanguageListItem* item = static_cast<LanguageListItem*>(
|
||||
fLanguageListView->FullListItemAt(index));
|
||||
fLanguageListView->ItemAt(index));
|
||||
_InsertPreferredLanguage(item, dropIndex++);
|
||||
}
|
||||
break;
|
||||
|
@ -363,15 +364,18 @@ LocaleWindow::MessageReceived(BMessage* message)
|
|||
// change ordering
|
||||
int32 dropIndex = message->FindInt32("drop_index");
|
||||
int32 index = 0;
|
||||
if (message->FindInt32("index", &index) == B_OK
|
||||
&& dropIndex != index) {
|
||||
for (int32 i = 0;
|
||||
message->FindInt32("index", i, &index) == B_OK;
|
||||
i++, dropIndex++) {
|
||||
if (dropIndex > index) {
|
||||
dropIndex--;
|
||||
index -= i;
|
||||
}
|
||||
BListItem* item = fPreferredListView->RemoveItem(index);
|
||||
if (dropIndex > index)
|
||||
index--;
|
||||
fPreferredListView->AddItem(item, dropIndex);
|
||||
|
||||
_PreferredLanguagesChanged();
|
||||
}
|
||||
|
||||
_PreferredLanguagesChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -385,13 +389,18 @@ LocaleWindow::MessageReceived(BMessage* message)
|
|||
|
||||
// Remove from preferred languages
|
||||
int32 index = 0;
|
||||
if (message->FindInt32("index", &index) == B_OK) {
|
||||
delete fPreferredListView->RemoveItem(index);
|
||||
_PreferredLanguagesChanged();
|
||||
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
|
||||
i++) {
|
||||
delete fPreferredListView->RemoveItem(index - i);
|
||||
|
||||
if (message->what == kMsgPreferredLanguageDeleted)
|
||||
fPreferredListView->Select(index);
|
||||
if (message->what == kMsgPreferredLanguageDeleted) {
|
||||
int32 count = fPreferredListView->CountItems();
|
||||
fPreferredListView->Select(
|
||||
index < count ? index : count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
_PreferredLanguagesChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -495,10 +504,9 @@ LocaleWindow::_PreferredLanguagesChanged()
|
|||
{
|
||||
BMessage preferredLanguages;
|
||||
int index = 0;
|
||||
while (index < fPreferredListView->FullListCountItems()) {
|
||||
// only include subitems: we can guess the superitem from them anyway
|
||||
while (index < fPreferredListView->CountItems()) {
|
||||
LanguageListItem* item = static_cast<LanguageListItem*>(
|
||||
fPreferredListView->FullListItemAt(index));
|
||||
fPreferredListView->ItemAt(index));
|
||||
if (item != NULL)
|
||||
preferredLanguages.AddString("language", item->ID());
|
||||
index++;
|
||||
|
|
Loading…
Reference in New Issue