Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Double)Tappable list items #4530

Closed
2 tasks done
BillBuilt opened this issue Jan 7, 2024 · 9 comments
Closed
2 tasks done

(Double)Tappable list items #4530

BillBuilt opened this issue Jan 7, 2024 · 9 comments
Labels
duplicate This issue or pull request already exists

Comments

@BillBuilt
Copy link

BillBuilt commented Jan 7, 2024

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

When a list item satisfies TappedSecondary or DoubleTapped (and possibly others) the parent list's OnSelected method is ignored.

How to reproduce

See example code. If you comment the TappedSecondary and DoubleTapped methods, the list's OnSelected method starts working, otherwise it never executes.

Screenshots

No response

Example code

package main

import (
	"fmt"
	"log"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/widget"
)

func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Clickable list items")
	myWindow.Resize(fyne.Size{
		Width:  300,
		Height: 300,
	})

	listData := binding.NewStringList()
	listData.Set([]string {"Item 1", "Item 2", "Item 3"})


	list := widget.NewListWithData(listData,
		func() fyne.CanvasObject {
			l := NewMyListItem("item name")
			return l
		},
		func(item binding.DataItem, object fyne.CanvasObject) {
			i, _ := item.(binding.String).Get()
			lbl := object.(*MyListItem)
			lbl.SetText(i)
		},
	)

	list.OnSelected = func(id widget.ListItemID) {
		log.Println(fmt.Sprintf("list item %d selected", id))
	}

	myWindow.SetContent(list)
	myWindow.ShowAndRun()
}




type MyListItem struct {
	widget.Label
}

func NewMyListItem(text string) *MyListItem {
	item := &MyListItem{}
	item.ExtendBaseWidget(item)
	item.SetText(text)
	return item
}

func (e *MyListItem) TappedSecondary(pe *fyne.PointEvent) {
	newItem := fyne.NewMenuItem("New", func(){log.Println("New clicked")})
	editItem := fyne.NewMenuItem("Edit",  func(){log.Println("Edit clicked")})
	deleteItem := fyne.NewMenuItem("Delete",  func(){log.Println("Delete clicked")})
	div := fyne.NewMenuItemSeparator()

	entryPos := fyne.CurrentApp().Driver().AbsolutePositionForObject(e)
	popUpPos := entryPos.Add(fyne.NewPos(pe.Position.X, pe.Position.Y))
	c := fyne.CurrentApp().Driver().CanvasForObject(e)

	menu := fyne.NewMenu("", newItem, div, editItem, deleteItem)

	popUp := widget.NewPopUpMenu(menu, c)
	popUp.ShowAtPosition(popUpPos)
}

func (e *MyListItem) DoubleTapped(pe *fyne.PointEvent) {
	log.Println("Double clicked")
}

Fyne version

v2.4.3

Go compiler version

1.21.5

Operating system and version

macOS Sonoma 14.2.1

Additional Information

No response

@BillBuilt BillBuilt added the unverified A bug that has been reported but not verified label Jan 7, 2024
@BillBuilt
Copy link
Author

I would like to be able to have a "right-click" menu on the list item, but also to be able to select the list item and apply logic when the user presses the DELETE key. Is this possible?

@andydotxyz
Copy link
Member

I think this is a duplicate of #2551.
We need to re-work the tap handling in the desktop/GLFW driver code to resolve this issue.

@Jacalz Jacalz added duplicate This issue or pull request already exists and removed unverified A bug that has been reported but not verified labels Jan 8, 2024
@Jacalz Jacalz closed this as not planned Won't fix, can't repro, duplicate, stale Jan 8, 2024
@Jacalz
Copy link
Member

Jacalz commented Jan 8, 2024

I agree. Looks like a duplicate. Let’s close this in favour of the other issue.

@dweymouth
Copy link
Contributor

I would like to be able to have a "right-click" menu on the list item, but also to be able to select the list item and apply logic when the user presses the DELETE key. Is this possible?

This is possible, if you have your list item implement Tappable and SecondaryTappable. In your Tapped handler, you can just call list.Select(itemID). In your TappedSecondary handler, you show the menu. For the delete key logic, you probably want to extend the List widget itself to provide a replacement for the TypedKey handler that handles DELETE specially, but delegates all other keys to the base List's TypedKey handler.

@BillBuilt
Copy link
Author

#2551 mentions assigning a reference to the list and the item ID to the list item in the updateItem() func. That would work for a regular list but I'm using an untyped list and the updateItem() func for that does not pass the ListItemID, but rather the binding.DataItem. Is there no way to reference the ListItemID in this function?

@BillBuilt
Copy link
Author

For now I'm simply creating a custom form of NewLisWithData that exposes the ListItemID to the updateItem func.

func NewListWithDataWithID(data binding.DataList, createItem func() fyne.CanvasObject, updateItem func(widget.ListItemID, binding.DataItem, fyne.CanvasObject)) *widget.List {
	l := widget.NewList(
		data.Length,
		createItem,
		func(i widget.ListItemID, o fyne.CanvasObject) {
			item, err := data.GetItem(i)
			if err != nil {
				fyne.LogError(fmt.Sprintf("Error getting data item %d", i), err)
				return
			}
			updateItem(i, item, o)
		})

	data.AddListener(binding.NewDataListener(l.Refresh))
	return l
}

@BillBuilt
Copy link
Author

BillBuilt commented Jan 10, 2024

So close. I supplied a TypedKey handler to the custom list in order to grab the DELETE keypress as suggested, but it seems that selecting a list item by clicking on it with the mouse does not also set focus to the list so the event is never captured unless I also tab into the list, even after making a selection.

@dweymouth
Copy link
Contributor

dweymouth commented Jan 10, 2024

For that last one you can focus it yourself after you call Select, using fyne.CurrentApp().Driver().CanvasForObject(theList).Focus(theList)

@andydotxyz
Copy link
Member

This seems more like a discussion, you should consider joining one of our support channels or using GitHub discussions instead of a bug report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

4 participants