* Fixed Select(), and Deselect*() to only send notifications if the selection
really changed - this fixes bug #519. * Archiving the object now returns an appropriate error message if something goes wrong (instead of B_OK). * Cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17347 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
630e0d5f82
commit
0e836b16bd
@ -1,23 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2006, Haiku, Inc.
|
* Copyright (c) 2001-2006, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT license.
|
* Distributed under the terms of the MIT license.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Ulrich Wimboeck
|
* Ulrich Wimboeck
|
||||||
* Marc Flerackers (mflerackers@androme.be)
|
* Marc Flerackers (mflerackers@androme.be)
|
||||||
* Stephan Assmus <superstippi@gmx.de>
|
* Stephan Assmus <superstippi@gmx.de>
|
||||||
|
* Axel Dörfler, axeld@pinc-software.de
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <ListView.h>
|
#include <ListView.h>
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
|
#include <PropertyInfo.h>
|
||||||
#include <ScrollBar.h>
|
#include <ScrollBar.h>
|
||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <support/Errors.h>
|
|
||||||
#include <PropertyInfo.h>
|
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
struct track_data {
|
struct track_data {
|
||||||
BPoint drag_start;
|
BPoint drag_start;
|
||||||
int32 item_index;
|
int32 item_index;
|
||||||
@ -25,9 +28,7 @@ struct track_data {
|
|||||||
bool try_drag;
|
bool try_drag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static property_info sProperties[] = {
|
||||||
static property_info prop_list[] =
|
|
||||||
{
|
|
||||||
{ "Item", { B_COUNT_PROPERTIES, 0 }, { B_DIRECT_SPECIFIER, 0 },
|
{ "Item", { B_COUNT_PROPERTIES, 0 }, { B_DIRECT_SPECIFIER, 0 },
|
||||||
"Returns the number of BListItems currently in the list." },
|
"Returns the number of BListItems currently in the list." },
|
||||||
{ "Item", { B_EXECUTE_PROPERTY, 0 }, { B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER,
|
{ "Item", { B_EXECUTE_PROPERTY, 0 }, { B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER,
|
||||||
@ -48,16 +49,17 @@ static property_info prop_list[] =
|
|||||||
"selection or deselection." },
|
"selection or deselection." },
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
BListView::BListView(BRect frame, const char *name, list_view_type type,
|
BListView::BListView(BRect frame, const char* name, list_view_type type,
|
||||||
uint32 resizingMode, uint32 flags)
|
uint32 resizingMode, uint32 flags)
|
||||||
: BView(frame, name, resizingMode, flags)
|
: BView(frame, name, resizingMode, flags)
|
||||||
{
|
{
|
||||||
_InitObject(type);
|
_InitObject(type);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
BListView::BListView(BMessage *archive)
|
|
||||||
: BView(archive)
|
BListView::BListView(BMessage* archive)
|
||||||
|
: BView(archive)
|
||||||
{
|
{
|
||||||
int32 listType;
|
int32 listType;
|
||||||
|
|
||||||
@ -77,86 +79,84 @@ BListView::BListView(BMessage *archive)
|
|||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
BMessage subData;
|
BMessage subData;
|
||||||
|
|
||||||
while (archive->FindMessage("_l_items", i++, &subData))
|
while (archive->FindMessage("_l_items", i++, &subData)) {
|
||||||
{
|
|
||||||
BArchivable *object = instantiate_object(&subData);
|
BArchivable *object = instantiate_object(&subData);
|
||||||
|
|
||||||
if (!object)
|
if (!object)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BListItem *item = dynamic_cast<BListItem*>(object);
|
BListItem *item = dynamic_cast<BListItem*>(object);
|
||||||
|
|
||||||
if (!item)
|
if (!item)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddItem(item);
|
AddItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (archive->HasMessage("_msg"))
|
if (archive->HasMessage("_msg")) {
|
||||||
{
|
|
||||||
BMessage *invokationMessage = new BMessage;
|
BMessage *invokationMessage = new BMessage;
|
||||||
|
|
||||||
archive->FindMessage("_msg", invokationMessage);
|
archive->FindMessage("_msg", invokationMessage);
|
||||||
SetInvocationMessage(invokationMessage);
|
SetInvocationMessage(invokationMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (archive->HasMessage("_2nd_msg"))
|
if (archive->HasMessage("_2nd_msg")) {
|
||||||
{
|
|
||||||
BMessage *selectionMessage = new BMessage;
|
BMessage *selectionMessage = new BMessage;
|
||||||
|
|
||||||
archive->FindMessage("_2nd_msg", selectionMessage);
|
archive->FindMessage("_2nd_msg", selectionMessage);
|
||||||
SetSelectionMessage(selectionMessage);
|
SetSelectionMessage(selectionMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BListView::~BListView()
|
BListView::~BListView()
|
||||||
{
|
{
|
||||||
SetSelectionMessage(NULL);
|
SetSelectionMessage(NULL);
|
||||||
|
delete fSelectMessage;
|
||||||
if (fSelectMessage)
|
|
||||||
delete fSelectMessage;
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
BArchivable *BListView::Instantiate(BMessage *archive)
|
|
||||||
|
BArchivable *
|
||||||
|
BListView::Instantiate(BMessage *archive)
|
||||||
{
|
{
|
||||||
if (validate_instantiation(archive, "BListView"))
|
if (validate_instantiation(archive, "BListView"))
|
||||||
return new BListView(archive);
|
return new BListView(archive);
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
status_t BListView::Archive(BMessage *archive, bool deep) const
|
|
||||||
|
status_t
|
||||||
|
BListView::Archive(BMessage *archive, bool deep) const
|
||||||
{
|
{
|
||||||
BView::Archive ( archive, deep );
|
status_t status = BView::Archive(archive, deep);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
archive->AddInt32("_lv_type", fListType);
|
status = archive->AddInt32("_lv_type", fListType);
|
||||||
|
if (status == B_OK && deep) {
|
||||||
if (deep)
|
|
||||||
{
|
|
||||||
int32 i = 0;
|
|
||||||
BListItem *item;
|
BListItem *item;
|
||||||
|
int32 i = 0;
|
||||||
|
|
||||||
while ((item = ItemAt(i++)))
|
while ((item = ItemAt(i++))) {
|
||||||
{
|
|
||||||
BMessage subData;
|
BMessage subData;
|
||||||
|
status = item->Archive(&subData, true);
|
||||||
|
if (status >= B_OK)
|
||||||
|
status = archive->AddMessage("_l_items", &subData);
|
||||||
|
|
||||||
if (item->Archive(&subData, true) != B_OK)
|
if (status < B_OK)
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
archive->AddMessage("_l_items", &subData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InvocationMessage())
|
if (status >= B_OK && InvocationMessage() != NULL)
|
||||||
archive->AddMessage("_msg", InvocationMessage());
|
status = archive->AddMessage("_msg", InvocationMessage());
|
||||||
|
|
||||||
if (fSelectMessage)
|
if (status == B_OK && fSelectMessage != NULL)
|
||||||
archive->AddMessage("_2nd_msg", fSelectMessage);
|
status = archive->AddMessage("_2nd_msg", fSelectMessage);
|
||||||
|
|
||||||
return B_OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
|
||||||
void
|
void
|
||||||
BListView::Draw(BRect updateRect)
|
BListView::Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
@ -168,7 +168,7 @@ BListView::Draw(BRect updateRect)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageReceived
|
|
||||||
void
|
void
|
||||||
BListView::MessageReceived(BMessage* msg)
|
BListView::MessageReceived(BMessage* msg)
|
||||||
{
|
{
|
||||||
@ -178,98 +178,99 @@ BListView::MessageReceived(BMessage* msg)
|
|||||||
case B_GET_PROPERTY:
|
case B_GET_PROPERTY:
|
||||||
case B_SET_PROPERTY:
|
case B_SET_PROPERTY:
|
||||||
{
|
{
|
||||||
BPropertyInfo propInfo ( prop_list );
|
BPropertyInfo propInfo(sProperties);
|
||||||
BMessage specifier;
|
BMessage specifier;
|
||||||
const char *property;
|
const char *property;
|
||||||
|
|
||||||
if ( msg->GetCurrentSpecifier ( NULL, &specifier ) != B_OK ||
|
if (msg->GetCurrentSpecifier(NULL, &specifier) != B_OK
|
||||||
specifier.FindString ( "property", &property ) != B_OK )
|
|| specifier.FindString("property", &property) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch ( propInfo.FindMatch ( msg, 0, &specifier, msg->what, property ) )
|
switch (propInfo.FindMatch(msg, 0, &specifier, msg->what, property)) {
|
||||||
{
|
|
||||||
case B_ERROR:
|
case B_ERROR:
|
||||||
BView::MessageReceived ( msg );
|
BView::MessageReceived(msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
BMessage reply ( B_REPLY );
|
BMessage reply(B_REPLY);
|
||||||
|
reply.AddInt32("result", CountItems());
|
||||||
|
reply.AddInt32("error", B_OK);
|
||||||
|
|
||||||
reply.AddInt32 ( "result", CountItems () );
|
msg->SendReply(&reply);
|
||||||
reply.AddInt32 ( "error", B_OK );
|
|
||||||
|
|
||||||
msg->SendReply ( &reply );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
BMessage reply ( B_REPLY );
|
|
||||||
|
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
|
|
||||||
for ( int32 i = 0; i < CountItems (); i++ )
|
for (int32 i = 0; i < CountItems(); i++) {
|
||||||
if ( ItemAt ( i )->IsSelected () )
|
if (ItemAt(i)->IsSelected())
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
reply.AddInt32 ( "result", count );
|
BMessage reply(B_REPLY);
|
||||||
reply.AddInt32 ( "error", B_OK );
|
reply.AddInt32("result", count);
|
||||||
|
reply.AddInt32("error", B_OK);
|
||||||
|
|
||||||
msg->SendReply ( &reply );
|
msg->SendReply(&reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
BMessage reply ( B_REPLY );
|
BMessage reply (B_REPLY);
|
||||||
|
|
||||||
for ( int32 i = 0; i < CountItems (); i++ )
|
for (int32 i = 0; i < CountItems(); i++) {
|
||||||
if ( ItemAt ( i )->IsSelected () )
|
if (ItemAt(i)->IsSelected())
|
||||||
reply.AddInt32 ( "result", i );
|
reply.AddInt32("result", i);
|
||||||
|
}
|
||||||
|
|
||||||
reply.AddInt32 ( "error", B_OK );
|
reply.AddInt32("error", B_OK);
|
||||||
|
|
||||||
msg->SendReply ( &reply );
|
msg->SendReply(&reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
BMessage reply ( B_REPLY );
|
BMessage reply(B_REPLY);
|
||||||
|
|
||||||
bool select;
|
bool select;
|
||||||
|
if (msg->FindBool("data", &select) == B_OK && select)
|
||||||
msg->FindBool ( "data", &select );
|
Select(0, CountItems() - 1, false);
|
||||||
|
|
||||||
if ( select )
|
|
||||||
Select ( 0, CountItems () - 1, false );
|
|
||||||
else
|
else
|
||||||
DeselectAll ();
|
DeselectAll();
|
||||||
|
|
||||||
reply.AddInt32 ( "error", B_OK );
|
reply.AddInt32("error", B_OK);
|
||||||
|
|
||||||
msg->SendReply ( &reply );
|
msg->SendReply(&reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_SELECT_ALL:
|
case B_SELECT_ALL:
|
||||||
{
|
|
||||||
Select(0, CountItems() - 1, false);
|
Select(0, CountItems() - 1, false);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
BView::MessageReceived(msg);
|
BView::MessageReceived(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MouseDown
|
|
||||||
void
|
void
|
||||||
BListView::MouseDown(BPoint point)
|
BListView::MouseDown(BPoint point)
|
||||||
{
|
{
|
||||||
@ -780,23 +781,23 @@ BListView::ScrollToSelection()
|
|||||||
void
|
void
|
||||||
BListView::Select(int32 index, bool extend)
|
BListView::Select(int32 index, bool extend)
|
||||||
{
|
{
|
||||||
_Select(index, extend);
|
if (_Select(index, extend)) {
|
||||||
|
SelectionChanged();
|
||||||
SelectionChanged();
|
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
||||||
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BListView::Select(int32 start, int32 finish, bool extend)
|
BListView::Select(int32 start, int32 finish, bool extend)
|
||||||
{
|
{
|
||||||
_Select(start, finish, extend);
|
if (_Select(start, finish, extend)) {
|
||||||
|
SelectionChanged();
|
||||||
SelectionChanged();
|
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
||||||
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsItemSelected
|
|
||||||
bool
|
bool
|
||||||
BListView::IsItemSelected(int32 index) const
|
BListView::IsItemSelected(int32 index) const
|
||||||
{
|
{
|
||||||
@ -874,59 +875,30 @@ BListView::Invoke(BMessage *message)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeselectAll
|
|
||||||
void
|
void
|
||||||
BListView::DeselectAll()
|
BListView::DeselectAll()
|
||||||
{
|
{
|
||||||
if (fFirstSelected == -1)
|
if (_DeselectAll(-1, -1)) {
|
||||||
return;
|
SelectionChanged();
|
||||||
|
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
||||||
for (int32 index = fFirstSelected; index <= fLastSelected; index++) {
|
|
||||||
BListItem *item = ItemAt(index);
|
|
||||||
if (item && item->IsSelected()) {
|
|
||||||
item->Deselect();
|
|
||||||
InvalidateItem(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fFirstSelected = fLastSelected = -1;
|
|
||||||
|
|
||||||
SelectionChanged();
|
|
||||||
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeselectExcept
|
|
||||||
void
|
void
|
||||||
BListView::DeselectExcept(int32 start, int32 finish)
|
BListView::DeselectExcept(int32 exceptFrom, int32 exceptTo)
|
||||||
{
|
{
|
||||||
if (fFirstSelected == -1 || finish < start)
|
if (exceptFrom > exceptTo || exceptFrom < 0 || exceptTo < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32 index;
|
if (_DeselectAll(exceptFrom, exceptTo)) {
|
||||||
|
SelectionChanged();
|
||||||
// TODO: check if the items from start to finish are
|
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
||||||
// supposed to be selected if not already
|
|
||||||
for (index = fFirstSelected; index < start; index++) {
|
|
||||||
BListItem *item = ItemAt(index);
|
|
||||||
if (item && item->IsSelected()) {
|
|
||||||
item->Deselect();
|
|
||||||
InvalidateItem(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (index = finish + 1; index <= fLastSelected; index++) {
|
|
||||||
BListItem *item = ItemAt(index);
|
|
||||||
if (item && item->IsSelected()) {
|
|
||||||
item->Deselect();
|
|
||||||
InvalidateItem(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fFirstSelected = max_c(fFirstSelected, start);
|
|
||||||
fLastSelected = min_c(fLastSelected, finish);
|
|
||||||
|
|
||||||
SelectionChanged();
|
|
||||||
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deselect
|
|
||||||
void
|
void
|
||||||
BListView::Deselect(int32 index)
|
BListView::Deselect(int32 index)
|
||||||
{
|
{
|
||||||
@ -936,12 +908,14 @@ BListView::Deselect(int32 index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectionChanged
|
|
||||||
void BListView::SelectionChanged()
|
void
|
||||||
|
BListView::SelectionChanged()
|
||||||
{
|
{
|
||||||
|
// Hook method to be implemented by subclasses
|
||||||
}
|
}
|
||||||
|
|
||||||
// SortItems
|
|
||||||
void
|
void
|
||||||
BListView::SortItems(int (*cmp)(const void *, const void *))
|
BListView::SortItems(int (*cmp)(const void *, const void *))
|
||||||
{
|
{
|
||||||
@ -1028,27 +1002,26 @@ BListView::ItemFrame(int32 index)
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveSpecifier
|
|
||||||
BHandler*
|
|
||||||
BListView::ResolveSpecifier(BMessage *msg, int32 index,
|
|
||||||
BMessage *specifier, int32 form,
|
|
||||||
const char *property)
|
|
||||||
{
|
|
||||||
BPropertyInfo propInfo(prop_list);
|
|
||||||
|
|
||||||
if (propInfo.FindMatch(msg, 0, specifier, form, property) < 0)
|
BHandler*
|
||||||
return BView::ResolveSpecifier(msg, index, specifier, form, property);
|
BListView::ResolveSpecifier(BMessage* message, int32 index,
|
||||||
|
BMessage* specifier, int32 form, const char* property)
|
||||||
|
{
|
||||||
|
BPropertyInfo propInfo(sProperties);
|
||||||
|
|
||||||
|
if (propInfo.FindMatch(message, 0, specifier, form, property) < 0)
|
||||||
|
return BView::ResolveSpecifier(message, index, specifier, form, property);
|
||||||
|
|
||||||
// TODO: msg->AddInt32("_match_code_", );
|
// TODO: msg->AddInt32("_match_code_", );
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSupportedSuites
|
|
||||||
status_t
|
status_t
|
||||||
BListView::GetSupportedSuites(BMessage *data )
|
BListView::GetSupportedSuites(BMessage* data)
|
||||||
{
|
{
|
||||||
BPropertyInfo propertyInfo(prop_list);
|
BPropertyInfo propertyInfo(sProperties);
|
||||||
|
|
||||||
data->AddString("suites", "suite/vnd.Be-list-view");
|
data->AddString("suites", "suite/vnd.Be-list-view");
|
||||||
data->AddFlat("messages", &propertyInfo);
|
data->AddFlat("messages", &propertyInfo);
|
||||||
@ -1234,64 +1207,74 @@ BListView::_FontChanged()
|
|||||||
ItemAt(i)->Update(this, &font);
|
ItemAt(i)->Update(this, &font);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Select
|
|
||||||
|
/*!
|
||||||
|
Selects the item at the specified \a index, and returns \c true in
|
||||||
|
case the selection was changed because of this method.
|
||||||
|
If \a extend is \c false, all previously selected items are deselected.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
BListView::_Select(int32 index, bool extend)
|
BListView::_Select(int32 index, bool extend)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= CountItems())
|
if (index < 0 || index >= CountItems())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((fFirstSelected != -1) && (!extend)) {
|
// only lock the window when there is one
|
||||||
for (int32 i = fFirstSelected; i <= fLastSelected; ++i) {
|
BAutolock locker(Window());
|
||||||
BListItem *item = ItemAt(i);
|
if (Window() && !locker.IsLocked())
|
||||||
if (item && item->IsSelected() && (i != index)) {
|
return false;
|
||||||
item->Deselect();
|
|
||||||
InvalidateItem(i);
|
bool changed = false;
|
||||||
}
|
|
||||||
}
|
if (fFirstSelected != -1 && !extend)
|
||||||
fFirstSelected = -1;
|
changed = _DeselectAll(index, index);
|
||||||
|
|
||||||
|
BListItem* item = ItemAt(index);
|
||||||
|
if (!item->IsEnabled() || item->IsSelected()) {
|
||||||
|
// if the item is already selected, or can't be selected, we're done here
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fFirstSelected == -1) {
|
if (fFirstSelected == -1) {
|
||||||
fFirstSelected = index;
|
fFirstSelected = index;
|
||||||
fLastSelected = index;
|
fLastSelected = index;
|
||||||
}
|
} else if (index < fFirstSelected)
|
||||||
else if (index < fFirstSelected)
|
|
||||||
fFirstSelected = index;
|
fFirstSelected = index;
|
||||||
else if (index > fLastSelected)
|
else if (index > fLastSelected)
|
||||||
fLastSelected = index;
|
fLastSelected = index;
|
||||||
|
|
||||||
if (ItemAt(index) && !ItemAt(index)->IsSelected()) {
|
ItemAt(index)->Select();
|
||||||
ItemAt(index)->Select();
|
if (Window())
|
||||||
InvalidateItem(index);
|
InvalidateItem(index);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Select
|
|
||||||
|
/*!
|
||||||
|
Selects the items between \a from and \a to, and returns \c true in
|
||||||
|
case the selection was changed because of this method.
|
||||||
|
If \a extend is \c false, all previously selected items are deselected.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
BListView::_Select(int32 from, int32 to, bool extend)
|
BListView::_Select(int32 from, int32 to, bool extend)
|
||||||
{
|
{
|
||||||
if (to < from)
|
if (to < from)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((fFirstSelected != -1) && (!extend)) {
|
BAutolock locker(Window());
|
||||||
for (int32 i = fFirstSelected; i <= fLastSelected; ++i) {
|
if (Window() && !locker.IsLocked())
|
||||||
BListItem *item = ItemAt(i);
|
return false;
|
||||||
if (item && item->IsSelected() && (i < from || i > to)) {
|
|
||||||
item->Deselect();
|
bool changed = false;
|
||||||
InvalidateItem(i);
|
|
||||||
}
|
if (fFirstSelected != -1 && !extend)
|
||||||
}
|
changed = _DeselectAll(from, to);
|
||||||
fFirstSelected = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fFirstSelected == -1) {
|
if (fFirstSelected == -1) {
|
||||||
fFirstSelected = from;
|
fFirstSelected = from;
|
||||||
fLastSelected = to;
|
fLastSelected = to;
|
||||||
}
|
} else if (from < fFirstSelected)
|
||||||
else if (from < fFirstSelected)
|
|
||||||
fFirstSelected = from;
|
fFirstSelected = from;
|
||||||
else if (to > fLastSelected)
|
else if (to > fLastSelected)
|
||||||
fLastSelected = to;
|
fLastSelected = to;
|
||||||
@ -1300,21 +1283,24 @@ BListView::_Select(int32 from, int32 to, bool extend)
|
|||||||
BListItem *item = ItemAt(i);
|
BListItem *item = ItemAt(i);
|
||||||
if (item && !item->IsSelected()) {
|
if (item && !item->IsSelected()) {
|
||||||
item->Select();
|
item->Select();
|
||||||
InvalidateItem(i);
|
if (Window())
|
||||||
|
InvalidateItem(i);
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _Deselect
|
|
||||||
bool
|
bool
|
||||||
BListView::_Deselect(int32 index)
|
BListView::_Deselect(int32 index)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= CountItems())
|
if (index < 0 || index >= CountItems())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Window()->Lock())
|
BAutolock locker(Window());
|
||||||
|
if (Window() && !locker.IsLocked())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BListItem *item = ItemAt(index);
|
BListItem *item = ItemAt(index);
|
||||||
@ -1340,40 +1326,43 @@ BListView::_Deselect(int32 index)
|
|||||||
DrawItem(ItemAt(index), frame, true);
|
DrawItem(ItemAt(index), frame, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window()->Unlock();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// _Deselect
|
|
||||||
void
|
bool
|
||||||
BListView::_Deselect(int32 from, int32 to)
|
BListView::_DeselectAll(int32 exceptFrom, int32 exceptTo)
|
||||||
{
|
{
|
||||||
if (from < 0 || from >= CountItems() || to < 0 || to >= CountItems())
|
if (fFirstSelected == -1)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
|
BAutolock locker(Window());
|
||||||
|
if (Window() && !locker.IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
for (int32 i = from; i <= to; i++)
|
for (int32 index = fFirstSelected; index <= fLastSelected; index++) {
|
||||||
{
|
// don't deselect the items we shouldn't deselect
|
||||||
if (_Deselect(i))
|
if (exceptFrom != -1 && exceptFrom <= index && exceptTo >= index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BListItem *item = ItemAt(index);
|
||||||
|
if (item && item->IsSelected()) {
|
||||||
|
item->Deselect();
|
||||||
|
InvalidateItem(index);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (!changed)
|
||||||
{
|
return false;
|
||||||
SelectionChanged();
|
|
||||||
InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
|
if (exceptFrom != -1) {
|
||||||
}
|
fFirstSelected = _CalcFirstSelected(fFirstSelected);
|
||||||
}
|
fLastSelected = _CalcLastSelected(fLastSelected);
|
||||||
*/
|
} else
|
||||||
// _DeselectAll
|
fFirstSelected = fLastSelected = -1;
|
||||||
bool
|
|
||||||
BListView::_DeselectAll(int32 except_from, int32 except_to)
|
|
||||||
{
|
|
||||||
if (fFirstSelected == -1)
|
|
||||||
return true;
|
|
||||||
// TODO...
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user