{"id":20346318,"url":"https://github.com/fyne-io/fyne-x","last_synced_at":"2025-05-15T16:07:31.144Z","repository":{"id":37206881,"uuid":"318893440","full_name":"fyne-io/fyne-x","owner":"fyne-io","description":"Community extensions to the cross platform GUI in Go based on Material Design","archived":false,"fork":false,"pushed_at":"2025-04-18T20:24:16.000Z","size":3365,"stargazers_count":280,"open_issues_count":27,"forks_count":61,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-19T08:32:27.295Z","etag":null,"topics":["fyne","go","golang","gui","hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fyne-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-12-05T21:32:49.000Z","updated_at":"2025-04-18T20:24:20.000Z","dependencies_parsed_at":"2023-10-04T17:19:09.168Z","dependency_job_id":"6ca0acd4-a82f-463f-85b1-fda18f91d473","html_url":"https://github.com/fyne-io/fyne-x","commit_stats":{"total_commits":244,"total_committers":20,"mean_commits":12.2,"dds":0.7827868852459017,"last_synced_commit":"8b5b5bfe65efaa90f4a8bde186d027bf20805112"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fyne-io%2Ffyne-x","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fyne-io%2Ffyne-x/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fyne-io%2Ffyne-x/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fyne-io%2Ffyne-x/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fyne-io","download_url":"https://codeload.github.com/fyne-io/fyne-x/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254374475,"owners_count":22060611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fyne","go","golang","gui","hacktoberfest"],"created_at":"2024-11-14T22:12:42.964Z","updated_at":"2025-05-15T16:07:31.096Z","avatar_url":"https://github.com/fyne-io.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pkg.go.dev/fyne.io/x/fyne\" title=\"Go API Reference\" rel=\"nofollow\"\u003e\u003cimg src=\"https://img.shields.io/badge/go-documentation-blue.svg?style=flat\" alt=\"Go API Reference\"\u003e\u003c/a\u003e\n  \u003ca href='http://gophers.slack.com/messages/fyne'\u003e\u003cimg src='https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true\u0026logo=slack\u0026colorB=blue' alt='Join us on Slack' /\u003e\u003c/a\u003e\n  \u003cbr /\u003e\n  \u003ca href=\"https://goreportcard.com/report/fyne.io/x/fyne\"\u003e\u003cimg src=\"https://goreportcard.com/badge/fyne.io/x/fyne\" alt=\"Code Status\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/fyne-io/fyne-x/actions\"\u003e\u003cimg src=\"https://github.com/fyne-io/fyne-x/workflows/Platform%20Tests/badge.svg\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n  \u003ca href='https://coveralls.io/github/fyne-io/fyne-x?branch=master'\u003e\u003cimg src='https://coveralls.io/repos/github/fyne-io/fyne-x/badge.svg?branch=master' alt='Coverage Status' /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# About\n\nThis repository holds community extensions for the [Fyne](https://fyne.io) toolkit.\n\nThis is in early development and more information will appear soon.\n\n## Layouts\n\nCommunity contributed layouts.\n\n`import \"fyne.io/x/fyne/layout\"`\n\n### Responsive Layout\n\nThe responsive layout provides a \"bootstrap like\" configuration to automatically make containers and canvas reponsive to the window width. It reacts to  the window size to resize and move the elements. The sizes are configured with a ratio of the **container** width (`0.5` is 50% of the container size).\n\nThe responsive layout follow the [bootstrap size breakpoints](https://getbootstrap.com/docs/4.0/layout/overview/#responsive-breakpoints):\n\n- extra small for window width \u003c= 576px\n- small for window width \u003c= 768\n- medium for window width \u003c= 992\n- large for window width \u003c= 1200\n- extra large for window width \u003e 1200\n\n\u003cp align=\"center\" class=\"align:center;margin:auto\"\u003e\n    \u003cimg src=\"img/responsive-layout.png\" style=\"max-width: 100%\" alt=\"Responsive Layout\"/\u003e\n\u003c/p\u003e\n\nTo use a responsive layout:\n\n```go\nlayout := NewResponsiveLayout(fyne.CanvasObject...)\n```\n\nOptionally, Each canvas object can be encapsulated with `Responsive()` function to give the sizes:\n\n```go\nlayout := NewResponsiveLayout(\n    Responsive(object1),            // all sizes to 100%\n    Responsive(object2, 0.5, 0.75), // small to 50%, medium to 75%, all others to 100% \n)\n```\n\n\n## Widgets\n\nThis package contains a collection of community-contributed widgets for the [Fyne](https://fyne.io/) \ntoolkit. The code here is intended to be production ready, but may be lacking\nsome desirable functional features. If you have suggestions for changes to \nexisting functionality or addition of new functionality, please look at the existing\nissues in the repository to see if your idea is already on the table. If it is not,\nfeel free to open an issue. \n\nThis collection should be considered a work in progress. When changes are made,\nserious consideration will be given to backward compatibility, but compatibility\nis not guaranteed. \n\n`import \"fyne.io/x/fyne/widget\"`\n\n### Animated Gif\n\nA widget that will run animated gifs.\n\n\u003cp align=\"center\" class=\"align:center;margin:auto\" markdown=\"1\"\u003e\n\u003cimg src=\"img/gifwidget.gif\" /\u003e\n\u003c/p\u003e\n\n```go\ngif, err := NewAnimatedGif(storage.NewFileURI(\"./testdata/gif/earth.gif\"))\ngif.Start()\n```\n\n### Calendar\n\nA date picker which returns a [time](https://pkg.go.dev/time) object with the selected date.\n\n\u003cp align=\"center\" class=\"align:center;margin:auto\"\u003e\n\n\u003cimg  src=\"https://user-images.githubusercontent.com/45520351/179398051-a1f961fd-64be-4214-a565-0da85ce4a543.png\"  style=\"max-width: 100%\"  alt=\"Calendar widget\"/\u003e\n\n\u003c/p\u003e\n\n  \n\nTo use create a new calendar with a given time and a callback function:\n\n```go\n\ncalendar := widget.NewCalendar(time.Now(), onSelected, cellSize, padding)\n\n```\n[Demo](./cmd/calendar_demo/main.go) available for example usage\n\n### DiagramWidget\n\nThe DiagramWidget provides a drawing area within which a diagram can be created. The diagram itself is a collection of \nDiagramElement widgets (an interface). There are two types of DiagramElements: DiagramNode widgets and DiagramLink widgets. \nDiagramNode widgets are thin wrappers around a user-supplied CanvasObject.\nAny valid CanvasObject can be used. DiagramLinks are line-based connections between DiagramElements.\nNote that links can connect to other links as well as nodes.\n\nWhile some provisions have been made for automatic layout, layouts are for the convenience\nof the author and are on-demand only. The design intent is that users will place the diagram elements for human readability. \n\nDiagramElements are managed by the DiagramWidget from a layout perspective. DiagramNodes have no size\nconstraints imposed by the DiagramWidget and can be placed anywhere. DiagramLinks connect \nDiagramElements. The DiagramWidget keeps track of the DiagramElements to which each DiagramLink \nis connected and calls the Refresh() method on the link when the connected diagram element is moved \nor resized. \n\n* [demo](./cmd/diagramdemo/main.go)\n* [More Detail](./widget/diagramwidget/README.md)\n\n\u003cp align=\"center\" markdown=\"1\" style=\"max-width: 100%\"\u003e\n  \u003cimg src=\"img/diagramdemo.png\" width=\"1024\" alt=\"Diagram Widget\" style=\"max-width: 100%\" /\u003e\n\u003c/p\u003e\n\n\n### FileTree\n\nAn extension of widget.Tree for displaying a file system hierarchy.\n\n```go\ntree := widget.NewFileTree(storage.NewFileURI(\"~\")) // Start from home directory\ntree.Filter = storage.NewExtensionFileFilter([]string{\".txt\"}) // Filter files\ntree.Sorter = func(u1, u2 fyne.URI) bool {\n    return u1.String() \u003c u2.String() // Sort alphabetically\n}\n```\n\n\u003cp align=\"center\" markdown=\"1\" style=\"max-width: 100%\"\u003e\n  \u003cimg src=\"img/widget-filetree.png\" width=\"1024\" alt=\"FileTree Widget\" style=\"max-width: 100%\" /\u003e\n\u003c/p\u003e\n\n### CompletionEntry\n\nAn extension of widget.Entry for displaying a popup menu for completion. The \"up\" and \"down\" keys on the keyboard are used to navigate through the menu, the \"Enter\" key is used to confirm the selection. The options can also be selected with the mouse. The \"Escape\" key closes the selection list.\n\n```go\nentry := widget.NewCompletionEntry([]string{})\n\n// When the use typed text, complete the list.\nentry.OnChanged = func(s string) {\n    // completion start for text length \u003e= 3\n    if len(s) \u003c 3 {\n        entry.HideCompletion()\n        return\n    }\n\n    // Make a search on wikipedia\n    resp, err := http.Get(\n        \"https://en.wikipedia.org/w/api.php?action=opensearch\u0026search=\" + entry.Text,\n    )\n    if err != nil {\n        entry.HideCompletion()\n        return\n    }\n\n    // Get the list of possible completion\n    var results [][]string\n    json.NewDecoder(resp.Body).Decode(\u0026results)\n\n    // no results\n    if len(results) == 0 {\n        entry.HideCompletion()\n        return\n    }\n\n    // then show them\n    entry.SetOptions(results[1])\n    entry.ShowCompletion()\n}\n```\n\n\u003cp align=\"center\" markdown=\"1\" style=\"max-width: 100%\"\u003e\n  \u003cimg src=\"img/widget-completion-entry.png\" width=\"825\" height=\"634\" alt=\"CompletionEntry Widget\" style=\"max-width: 100%\" /\u003e\n\u003c/p\u003e\n\n### 7-Segment (\"Hex\") Display\n\nA skeuomorphic widget simulating a 7-segment \"hex\" display. Supports setting\ndigits by value, as well as directly controlling which segments are on or\noff.\n\nCheck out the [demo](./cmd/hexwidget_demo/main.go) for an example of usage.\n\n\n![](img/hexwidget_00abcdef.png)\n\n![](img/hexwidget_12345678.png)\n\n```go\nh := widget.NewHexWidget()\n// show the value 'F' on the display\nh.Set(0xf)\n```\n\n### Map\n\nAn OpenStreetMap widget that can the user can pan and zoom.\nTo use this in your app and be compliant with their requirements you may need to request\npermission to embed in your specific software.\n\n```go\nm := NewMap()\n```\n\n![](img/map.png)\n\n### TwoStateToolbarAction\n\nA TwoStateToolbarAction displays one of two icons based on the stored state. It is similar\nto a regular ToolbarAction except that the icon and state are toggled each time the toolbar\naction is activated. The current (new) state is passed to the `onActivated` function.\n\nOne potential use of this toolbar action is displaying the MediaPlayIcon when a media \nfile is not being played, and the MediaPauseIcon or MediaStopIcon when a media file is \nbeing played. A second use may be seen in an application where a left or right panel is \ndisplayed or not. For example, show the left panel open icon when the left panel is \nclosed, and the left panel close icon when the panel is open.\n\n\n```go\naction := NewTwoStateToolBar(theme.MediaPlayIcon(), \n    theme.MediaPauseIcon(), \n    func(on bool) {\n        // Do something with state. For example, if on is true, start playback.\n    })\n```\n\n* [Demo App](cmd/twostatetoolbaraction_demo/main.go)\n\n## Dialogs\n\n### About\n\nA cool parallax about dialog that pulls data from the app metadata and includes\nsome markup content and links at the bottom of the window/dialog.\n\n```go\n\tdocURL, _ := url.Parse(\"https://docs.fyne.io\")\n\tlinks := []*widget.Hyperlink{\n\t\twidget.NewHyperlink(\"Docs\", docURL),\n\t}\n\tdialog.ShowAboutWindow(\"Some **cool** stuff\", links, a)\n```\n\n![](img/about.png)\n\n## Data Binding\n\nCommunity contributed data sources for binding.\n\n`import fyne.io/x/fyne/data/binding`\n\n### WebString\n\nA `WebSocketString` binding creates a `String` data binding to the specified web socket URL.\nEach time a message is read the value will be converted to a `string` and set on the binding.\nIt is also `Closable` so you should be sure to call `Close()` once you are completed using it.\n\n```go\ns, err := binding.NewWebSocketString(\"wss://demo.piesocket.com/v3/channel_1?api_key=oCdCMcMPQpbvNjUIzqtvF1d2X2okWpDQj4AwARJuAgtjhzKxVEjQU6IdCjwm\u0026notify_self\")\nl := widget.NewLabelWithData(s)\n```\n\nThe code above uses a test web sockets server from \"PieSocket\", you can run the code above\nand go to [their test page](https://www.piesocket.com/websocket-tester) to send messages.\nThe widget will automatically update to the latest data sent through the socket.\n\n### MqttString\n\nA `MqttString` binding creates a `String` data binding to the specified _topic_ associated with\nthe specified **MQTT** client connection. Each time a message is received the value will be converted\nto a `string` and set on the binding. Each time the value is edited, it will be sent back over\n**MQTT** on the specified _topic_. It is also a `Closer` so you should be sure to call `Close`\nonce you are completed using it to disconnect the _topic_ handler from the **MQTT** client connection.\n\n```go\nopts := mqtt.NewClientOptions()\nopts.AddBroker(\"tcp://broker.emqx.io:1883\")\nopts.SetClientID(\"fyne_demo\")\nclient := mqtt.NewClient(opts)\n\ntoken := client.Connect()\ntoken.Wait()\nif err := token.Error(); err != nil {\n    // Handle connection error\n}\n\ns, err := binding.NewMqttString(client, \"fyne.io/x/string\")\n```\n\n## Data Validation\n\nCommunity contributed validators.\n\n`import fyne.io/x/fyne/data/validation`\n\n### Password\n\nA validator for validating passwords. Uses https://github.com/wagslane/go-password-validator\nfor validation using an entropy system.\n\n```go\npw := validation.NewPassword(70) // Minimum password entropy allowed defined as 70.\n```\n\n## Themes\n\n### Adwaita\n\nAdwaita is the theme used in new the versions of KDE and Gnome (and derivatives) on GNU/Linux.\nThis theme proposes a color-schme taken from the Adwaita scpecification.\n\nUse it with:\n\n```go\nimport \"fyne.io/x/fyne/theme\"\n//...\n\napp := app.New()\napp.Settings().SetTheme(theme.AdwaitaTheme())\n```\n\n![Adwaita Dark](./img/adwaita-theme-dark.png)\n\n![Adwaita Light](./img/adwaita-theme-light.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffyne-io%2Ffyne-x","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffyne-io%2Ffyne-x","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffyne-io%2Ffyne-x/lists"}