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:
Oliver Tappe
2011-08-24 22:06:24 +00:00
parent fdecfdb35c
commit f6102c6fba
3 changed files with 109 additions and 38 deletions
+81 -23
View File
@@ -62,25 +62,21 @@ void
LanguageListItem::DrawItemWithTextOffset(BView* owner, BRect frame, LanguageListItem::DrawItemWithTextOffset(BView* owner, BRect frame,
bool complete, float textOffset) 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) { if (IsSelected() || complete) {
rgb_color color; rgb_color color;
if (IsSelected()) if (IsSelected())
color = kHighlight; color = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR);
else else
color = owner->ViewColor(); color = owner->ViewColor();
owner->SetHighColor(color); owner->SetHighColor(color);
owner->SetLowColor(color); owner->SetLowColor(color);
owner->FillRect(frame); owner->FillRect(frame);
owner->SetHighColor(kBlack);
} else } else
owner->SetLowColor(owner->ViewColor()); owner->SetLowColor(owner->ViewColor());
BString text = Text(); BString text = Text();
if (IsEnabled()) if (IsEnabled())
owner->SetHighColor(kBlack); owner->SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
else { else {
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT)); owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT));
text << " [" << B_TRANSLATE("already chosen") << "]"; text << " [" << B_TRANSLATE("already chosen") << "]";
@@ -168,6 +164,8 @@ LanguageListView::LanguageListView(const char* name, list_view_type type)
: :
BOutlineListView(name, type), BOutlineListView(name, type),
fDropIndex(-1), fDropIndex(-1),
fDropTargetHighlightFrame(),
fGlobalDropTargetIndicator(false),
fDeleteMessage(NULL), fDeleteMessage(NULL),
fDragMessage(NULL) fDragMessage(NULL)
{ {
@@ -231,6 +229,13 @@ LanguageListView::SetDragMessage(BMessage* message)
} }
void
LanguageListView::SetGlobalDropTargetIndicator(bool isGlobal)
{
fGlobalDropTargetIndicator = isGlobal;
}
void void
LanguageListView::AttachedToWindow() LanguageListView::AttachedToWindow()
{ {
@@ -247,13 +252,24 @@ LanguageListView::MessageReceived(BMessage* message)
BMessage dragMessage(*message); BMessage dragMessage(*message);
dragMessage.AddInt32("drop_index", fDropIndex); dragMessage.AddInt32("drop_index", fDropIndex);
dragMessage.AddPointer("drop_target", this); dragMessage.AddPointer("drop_target", this);
Messenger().SendMessage(&dragMessage);
Invoke(&dragMessage);
} else } else
BOutlineListView::MessageReceived(message); 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 bool
LanguageListView::InitiateDrag(BPoint point, int32 dragIndex, LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
bool /*wasSelected*/) bool /*wasSelected*/)
@@ -261,7 +277,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
if (fDragMessage == NULL) if (fDragMessage == NULL)
return false; return false;
BListItem* item = FullListItemAt(CurrentSelection(0)); BListItem* item = ItemAt(CurrentSelection(0));
if (item == NULL) { if (item == NULL) {
// workaround for a timing problem // workaround for a timing problem
// TODO: this should support extending the selection // TODO: this should support extending the selection
@@ -276,7 +292,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
message.AddPointer("listview", this); message.AddPointer("listview", this);
for (int32 i = 0;; i++) { for (int32 i = 0;; i++) {
int32 index = FullListCurrentSelection(i); int32 index = CurrentSelection(i);
if (index < 0) if (index < 0)
break; break;
@@ -292,7 +308,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
// figure out, how many items fit into our bitmap // figure out, how many items fit into our bitmap
for (int32 i = 0, index; message.FindInt32("index", i, &index) == B_OK; for (int32 i = 0, index; message.FindInt32("index", i, &index) == B_OK;
i++) { i++) {
BListItem* item = FullListItemAt(index); BListItem* item = ItemAt(index);
if (item == NULL) if (item == NULL)
break; break;
@@ -318,7 +334,7 @@ LanguageListView::InitiateDrag(BPoint point, int32 dragIndex,
for (int32 i = 0; i < numItems; i++) { for (int32 i = 0; i < numItems; i++) {
int32 index = message.FindInt32("index", i); int32 index = message.FindInt32("index", i);
LanguageListItem* item LanguageListItem* item
= static_cast<LanguageListItem*>(FullListItemAt(index)); = static_cast<LanguageListItem*>(ItemAt(index));
itemBounds.bottom = itemBounds.top + ceilf(item->Height()); itemBounds.bottom = itemBounds.top + ceilf(item->Height());
if (itemBounds.bottom > dragRect.bottom) if (itemBounds.bottom > dragRect.bottom)
itemBounds.bottom = dragRect.bottom; itemBounds.bottom = dragRect.bottom;
@@ -378,21 +394,63 @@ LanguageListView::MouseMoved(BPoint where, uint32 transit,
case B_ENTERED_VIEW: case B_ENTERED_VIEW:
case B_INSIDE_VIEW: case B_INSIDE_VIEW:
{ {
// set drop target through virtual function BRect highlightFrame;
// offset where by half of item height
BRect r = ItemFrame(0);
where.y += r.Height() / 2.0;
int32 index = FullListIndexOf(where); if (fGlobalDropTargetIndicator) {
if (index < 0) highlightFrame = Bounds();
index = FullListCountItems(); fDropIndex = 0;
if (fDropIndex != index) } 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; 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 SetDeleteMessage(BMessage* message);
void SetDragMessage(BMessage* message); void SetDragMessage(BMessage* message);
void SetGlobalDropTargetIndicator(bool isGlobal);
virtual void Draw(BRect updateRect);
virtual bool InitiateDrag(BPoint point, int32 index, virtual bool InitiateDrag(BPoint point, int32 index,
bool wasSelected); bool wasSelected);
virtual void MouseMoved(BPoint where, uint32 transit, virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage); const BMessage* dragMessage);
virtual void MouseUp(BPoint point);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void KeyDown(const char* bytes, int32 numBytes); virtual void KeyDown(const char* bytes, int32 numBytes);
@@ -89,6 +92,8 @@ private:
private: private:
int32 fDropIndex; int32 fDropIndex;
BRect fDropTargetHighlightFrame;
bool fGlobalDropTargetIndicator;
BMessage* fDeleteMessage; BMessage* fDeleteMessage;
BMessage* fDragMessage; BMessage* fDragMessage;
}; };
+23 -15
View File
@@ -89,6 +89,7 @@ LocaleWindow::LocaleWindow()
fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked)); fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked));
fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged)); fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged));
fLanguageListView->SetGlobalDropTargetIndicator(true);
BFont font; BFont font;
fLanguageListView->GetFont(&font); fLanguageListView->GetFont(&font);
@@ -335,7 +336,7 @@ LocaleWindow::MessageReceived(BMessage* message)
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK; for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
i++) { i++) {
LanguageListItem* item = static_cast<LanguageListItem*>( LanguageListItem* item = static_cast<LanguageListItem*>(
fLanguageListView->FullListItemAt(index)); fLanguageListView->ItemAt(index));
_InsertPreferredLanguage(item, dropIndex++); _InsertPreferredLanguage(item, dropIndex++);
} }
break; break;
@@ -363,15 +364,18 @@ LocaleWindow::MessageReceived(BMessage* message)
// change ordering // change ordering
int32 dropIndex = message->FindInt32("drop_index"); int32 dropIndex = message->FindInt32("drop_index");
int32 index = 0; int32 index = 0;
if (message->FindInt32("index", &index) == B_OK for (int32 i = 0;
&& dropIndex != index) { message->FindInt32("index", i, &index) == B_OK;
i++, dropIndex++) {
if (dropIndex > index) {
dropIndex--;
index -= i;
}
BListItem* item = fPreferredListView->RemoveItem(index); BListItem* item = fPreferredListView->RemoveItem(index);
if (dropIndex > index)
index--;
fPreferredListView->AddItem(item, dropIndex); fPreferredListView->AddItem(item, dropIndex);
_PreferredLanguagesChanged();
} }
_PreferredLanguagesChanged();
break; break;
} }
@@ -385,13 +389,18 @@ LocaleWindow::MessageReceived(BMessage* message)
// Remove from preferred languages // Remove from preferred languages
int32 index = 0; int32 index = 0;
if (message->FindInt32("index", &index) == B_OK) { for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK;
delete fPreferredListView->RemoveItem(index); i++) {
_PreferredLanguagesChanged(); delete fPreferredListView->RemoveItem(index - i);
if (message->what == kMsgPreferredLanguageDeleted) if (message->what == kMsgPreferredLanguageDeleted) {
fPreferredListView->Select(index); int32 count = fPreferredListView->CountItems();
fPreferredListView->Select(
index < count ? index : count - 1);
}
} }
_PreferredLanguagesChanged();
break; break;
} }
@@ -495,10 +504,9 @@ LocaleWindow::_PreferredLanguagesChanged()
{ {
BMessage preferredLanguages; BMessage preferredLanguages;
int index = 0; int index = 0;
while (index < fPreferredListView->FullListCountItems()) { while (index < fPreferredListView->CountItems()) {
// only include subitems: we can guess the superitem from them anyway
LanguageListItem* item = static_cast<LanguageListItem*>( LanguageListItem* item = static_cast<LanguageListItem*>(
fPreferredListView->FullListItemAt(index)); fPreferredListView->ItemAt(index));
if (item != NULL) if (item != NULL)
preferredLanguages.AddString("language", item->ID()); preferredLanguages.AddString("language", item->ID());
index++; index++;