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

Settings API for Toga #90

Open
Ocupe opened this issue Dec 5, 2016 · 4 comments
Open

Settings API for Toga #90

Ocupe opened this issue Dec 5, 2016 · 4 comments
Labels
enhancement New features, or improvements to existing features. not quite right The idea or PR has been reviewed, but more work is needed.

Comments

@Ocupe
Copy link
Contributor

Ocupe commented Dec 5, 2016

Settings API for Toga

I wrote this short text after a brief discussion with @freakboy3742. My intention is to kick off a conversation about a possible 'Settings API' for the toga project. This text is badly written and possibly full of bad ideas. But it is a start! :)

Settings API

The settings API is the attempt to provide us programmers with a abstract interface to easily create settings/preferences panels that work on all platforms. A Mac user should feel just as 'at home' as a windows or linux user. On top of that, it should be possible to port a desktop settings window to mobile without the need of rewriting it.

Native desktop settings in the wild

To get a better understanding about how native settings look like on different platforms I added this small overview.

Desktop Examples:

macos_settings

windows_settings

Mobile Examples:

ios_settings

android_settings

Basic Structure

I think that all settings representations, no matter on what platform, have a common structure. They try to group settings which are related into some kind of settings group. On desktop platforms they use some sort of tab functionality, on mobile the use nested table views. These groups are then again grouped into a settings menu. On desktop often represented in form of a single settings window and on mobile in form of a settings view which holds a table view with navigation.

Basic Hierarchy:

  • Settings Window/View
    • Settings Group
      • Settings Item

Write once, use everywhere

I see the future of the toga settings API as write one, use everywhere! The translation from a desktop settings window to a mobile settings table view shouldn't be the problem as long as all settings items are implemented on all platforms.

'Translations'

In this section I describes possible 'translations' from desktop to mobile.

on Mobile on Desktop
root view independent settings window
root structure TableView with subsections + Navigation Tabs
Settings Group TableView + Navigation Area of the active tab
Settings Items switch checkbox
slider slider
... ...

Settings Items

A list of possible settings items that one can use with the settings api.
I don't see a problem if we allow the user to use all input widgets defined in the toga documentations. Again, as long as we make the settings items available on all platforms or find fitting 'translations' from desktop to mobile and vice versa.

Under the Hood

I don't know a clever way of implementing a Settings API. But at least I can share how I would like to interact with a potential Settings API and what things I would expect from it.

import toga

# Instantiating the settings class takes care of creating the settings window/view.
# All the platform specific bootstrapping should be taken care of and set to native defaults.
settings = toga.Settings()
# A the settings group should have a label and the possibility to add a icon to it.
group = toga.SettingsGroup('General'. icon='icon.png')

# creating setting item
switch = Switch(label='Show line numbers')

# adding setting item to the setting group
group.add(switch)

# adding group to settings
settings.add(group)

# you should be able to open the settings window/view by just calling the open() function.
settings.open()

Notes

  • I'm mostly focused on desktop and mobile. Other platforms should become a part of the equation.
  • Sorry for the spelling :/
  • After some feedback and discussion, I would like to get going with the OSX implementation followed by the iOS version.
  • Basic functionality like callbacks on settings changes and getting the values of settings must be addressed as well.
@freakboy3742
Copy link
Member

Hells yes. This is exactly the sort of thing I had in my head! Thanks for the great writeup.

A couple more ideas to throw into your thoughts:

  • Persistence: Once I've defined a settings object, I should be able to save those settings in a platform appropriate way - dot files/directories, Application Support/ directories, or whatever is appropriate.
  • Project settings: Some apps - especially those that fall into the "developer tool" category - will need both application settings and project settings. For example, you might want to configure exactly how cricket runs a test suite, and have those settings for this project persisted into a configuration file in this project. This is more likely to be a universal file format (.rc file in the project home directory style)
  • Extraction: I should be able to easily extract settings from the app object. "What is the current value of the 'privacy' setting?" I should also be able to register to be notified if a settings are changed (call this method if the user modifies the privacy setting)
  • Versioning: When I put out version 2.0, I should be able to tell that the current settings are from version 1.0, update any existing settings, backfill any new settings, maybe perform any migrations that are required.
  • Opening settings: The app settings should appear automatically in the appropriate application menu (if platform appropriate). On some platforms (e.g., iOS) this means opening the actual settings app, not just a dialog/slide in panel.

@Ocupe
Copy link
Contributor Author

Ocupe commented Mar 9, 2017

@freakboy3742 and everyone else. Before I run in the completely wrong direction I would like to get your feedback on this.
Especially the part of 'The Normalized Settings Structure'

@Ocupe
Copy link
Contributor Author

Ocupe commented Mar 9, 2017

Lowest Common Denominator (work in progress)

In this section we really go deep and try to find the lowest common denominator for a general settings API.
It is clear that the integration of settings on iOS and Android is similar but still different. Because we try to provide a common interface, that works for all platforms, we are left with the challenging and tedious job to compare all the existing API's and then find a good way to generalise them into a toga settings API.
The following table shows what platform specific 'things'/widgets your specified toga SettingsItem would resolves to.
For example, when you specify a toga toggle, you get a Toggle Switch on iOS and something called SwitchPreference on Android.

Links to the official documentations:

toga iOS android macOS Windows Linux
toggle Toggle Switch Element CheckBoxPreference, SwitchPreference  
text field Text Field Element EditTextPreference  
pick one Radio Group Element ListPreference  
multi value Multi Value Element MultiSelectListPreference  
slider Slider Element  

The Normalized Settings Structure

This is a proposal how the interface between toga.core and the respective system integrations of toga could look like. The following idea is derived from the fact that iOS and android store their settings in a .plist and .xml files. I though we could translate the in code specified settings to a normalised from. This agreed upon normalized form than acts as the base of all the system specific integrations.

Example (simplified)
# defining the settings
settings = toga.Settings(version='1.0.0')
switch = toga.SettingsItem('switch', label='My Switch', default=True)
slider = toga.SettingsItem('slider', label='My Slider', default=5, min=0, max=10)
group = toga.SettingsGroup('My Settings', [switch, slider])
settings.add_group(group)

# When printing the normalized form we end up whit something like this.
pprint(settings.get_normal_form())
{'settings': 
    {
    'version': '1.0.0',
    'groups': 
        [{'group':
            {
            'title': 'My Settings',
            'items':
                [{  
                    'default': True,
                    'key': 'my_switch',
                    'label': 'My Switch',
                    'type': 'switch'},
                {   
                    'default': 5,
                    'key': 'my_slider',
                    'label': 'My Slider',
                    'max': 10,
                    'min': 0,
                    'type': 'slider'
                }]
            }
        }]
    }
}

This normalized form, here proposed as a dictionary, can now be passed to the platform specific integration of toga.
As a nice side effect we end up with something that can easily be stored in a xml or similar file format and is platform independent.

@freakboy3742
Copy link
Member

YES - this looks almost exactly what I had in mind. No particular feedback, other than "MOAR OF THIS". 😸

@freakboy3742 freakboy3742 added enhancement New features, or improvements to existing features. up-for-grabs not quite right The idea or PR has been reviewed, but more work is needed. labels Mar 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New features, or improvements to existing features. not quite right The idea or PR has been reviewed, but more work is needed.
Projects
None yet
Development

No branches or pull requests

2 participants