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:
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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++;
|
||||||
|
|||||||
Reference in New Issue
Block a user