void BListView::MouseDown(BPoint where) { if (!IsFocus()) { MakeFocus(); Sync(); Window()->UpdateIfNeeded(); } BMessage* message = Looper()->CurrentMessage(); int32 index = IndexOf(where); int32 buttons = 0; if (message != NULL) message->FindInt32("buttons", &buttons); int32 modifiers = 0; if (message != NULL) message->FindInt32("modifiers", &modifiers); // If the user double (or more) clicked within the current selection, // we don't change the selection but invoke the selection. // TODO: move this code someplace where it can be shared everywhere // instead of every class having to reimplement it, once some sane // API for it is decided. BPoint delta = where - fTrack->drag_start; bigtime_t sysTime; Window()->CurrentMessage()->FindInt64("when", &sysTime); bigtime_t timeDelta = sysTime - fTrack->last_click_time; bigtime_t doubleClickSpeed; get_click_speed(&doubleClickSpeed); bool doubleClick = false; if (timeDelta < doubleClickSpeed && fabs(delta.x) < kDoubleClickThreshold && fabs(delta.y) < kDoubleClickThreshold && fTrack->item_index == index) { doubleClick = true; } if (doubleClick && index >= fFirstSelected && index <= fLastSelected) { fTrack->drag_start.Set(INT32_MAX, INT32_MAX); Invoke(); return BView::MouseDown(where); } if (!doubleClick) { fTrack->drag_start = where; fTrack->last_click_time = system_time(); fTrack->item_index = index; fTrack->was_selected = index >= 0 ? ItemAt(index)->IsSelected() : false; fTrack->try_drag = true; MouseDownThread<BListView>::TrackMouse(this, &BListView::_DoneTracking, &BListView::_Track); } if (index >= 0) { if (fListType == B_MULTIPLE_SELECTION_LIST) { if ((modifiers & B_SHIFT_KEY) != 0) { // select entire block // TODO: maybe review if we want it like in Tracker // (anchor item) if (index >= fFirstSelected && index < fLastSelected) { // clicked inside of selected items block, deselect all // but from the first selected item to the clicked item DeselectExcept(fFirstSelected, index); } else { Select(std::min(index, fFirstSelected), std::max(index, fLastSelected)); } } else { if ((modifiers & B_COMMAND_KEY) != 0) { // toggle selection state of clicked item (like in Tracker) // toggle selection state of clicked item if (ItemAt(index)->IsSelected()) Deselect(index); else Select(index, true); } else Select(index); } } else { // toggle selection state of clicked item if ((modifiers & B_COMMAND_KEY) != 0 && ItemAt(index)->IsSelected()) Deselect(index); else Select(index); } } else if ((modifiers & B_COMMAND_KEY) == 0) DeselectAll(); BView::MouseDown(where); }
void NamesView::MouseMoved (BPoint myPoint, uint32 transitcode, const BMessage *dragMessage) { if ((dragMessage != NULL) && (dragMessage->HasRef("refs"))) { // make sure the ref isn't a dir entry_ref ref; dragMessage->FindRef("refs", &ref); BDirectory dir (&ref); if (dir.InitCheck() != B_OK) { int32 nameIndex (IndexOf(myPoint)); if (nameIndex >= 0) Select(nameIndex); } } else if (fTracking) { if (transitcode == B_INSIDE_VIEW) { BListItem *item = ItemAt (IndexOf(myPoint)); if (item) { BListItem *lastitem (NULL); int32 first (CurrentSelection (0)); int32 last (first); int32 i (1); while ((last = CurrentSelection(i++)) != -1) lastitem = ItemAt(last); if (lastitem) last = IndexOf(lastitem); else last = first; int32 current (IndexOf (myPoint)); if (current >= 0) { if (current < first) { // sweep up Select (current, last, true); } else if (current > last) { // sweep down Select (first, current, true); } else if (fCurrentindex > current) { // backtrack up DeselectExcept (first, current); } else if (fCurrentindex < current) { // backtrack down DeselectExcept (current, last); } fCurrentindex = current; } } } } else BListView::MouseMoved (myPoint, transitcode, dragMessage); }