On each release, we try to have generic Kv rules that use properties for expressing the theming.
I'm thinking from a long time about how theming could be configurable.
The theme property would contain the name of a theme referenced by a ThemeManager. Then, instead of writing the default value manually, we could write in kv, and use the self.theme to get the theme name. Ie:
background_normal: 'atlas://data/themes/%s/button-normal' % self.theme
I think that we could have a "theme" by giving the possibility to load a different set of default values, such as:
'size': ('72pt', '72pt')
Plus, with the combinaison of the kv, you could specify a different font size for label or button (something you cannot do by changing just the defaultvalue, because it's shared between thoses 2 widgets).
The Kv could be generated automatically if the property we try to change in the json doesn't exist on the target class (like font_size on Button).
On the usage, i see:
I'm in favor of proposal B. But i'm open to others solution.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
I think more the problem is that in the default kv, we dont have all resources cvonfigurable. e.g. look at Slider / Progress Bar:
rgb: 1, 1, 1
border: (0, 18, 0, 18) if self.orientation == 'horizontal' else (18, 0, 18, 0)
pos: (self.x, self.center_y - 18) if self.orientation == 'horizontal' else (self.center_x - 18, self.y)
size: (self.width, 37) if self.orientation == 'horizontal' else (37, self.height)
source: 'atlas://data/images/defaulttheme/slider%s_background' % self.orientation
pos: (self.value_pos - 16, self.center_y - 17) if self.orientation == 'horizontal' else (self.center_x - 16, self.value_pos - 16)
size: (32, 32)
rgb: 1, 1, 1
border: (12, 12, 12, 12)
pos: self.x, self.center_y - 12
size: self.width, 24
border: [int(min(self.width * (self.value / float(self.max)), 12))] * 4
pos: self.x, self.center_y - 12
size: self.width * (self.value / float(self.max)), 24
no way to change appearance without, completely overwriting canvas rule.
Otherwise I aggree on second part...but why make it json, instead of just another KV to load?
we can install default style.kv into ~/.kivy/themes/default.kv which will be loaded by default, then user can have multiple kv files in this directory also and either load at start/runtime or whatever, or switch global theme on install by changing/symlinking .kivy/themes/default.kv to other theme file...
its just a matter of which file Builder loads as default right?
Yes, few widget still need to have their theming exported into property.
About using Kv, you still have default value from Kivy, and then, you'll have more processing: if you change the default font_size of a Label, it's one rule that will be applied everytime a Label, Button etc.. is created. Plus the parsing from the start :/
Plus, you never really know that's the real default value, because it will be changed at each instance done. You might also have issue at initialization (like if you have a first rule that use self.font_size, it will be used. Then when the next rule is applied and change the font_size too, the associated callback will be called again) -> that can be avoided if the defaultvalue is good from the start.
That's why i wanted to seperate both.
right, but anyway it will always load at least one default kv (right now data/style.kv) right? why not just make this the theme file and expose all settings via it. it's just a matter of user knowing where to look to change the values no?
if you want all image names, colors etc in one place, we can just use #set default_button_background_image "/atals/..." at the top of the file?
if you want to have default values to save performance..we can cache it in json like you suggest easily after processing kv once no? Just nbot sure about having seperate theme files in different format...users will be confused on how to change widget looks...whats theme vs widget style, rule etc...
But if you do that, you loose the ability to have different themes right ?
what do you mean no ability to have different theme? theme != default kv ?
you mean individual application have different themes? can still be env var, command line option, or function call before builder is initialized?
Using different style.kv for custtom themes sounds interesting and a straight forward approach to global themes.This would also give the user more control and be simple and intuitive.
As for individual app themes, maybe we could lookup app_dir/data/style.kv before loading kivy_install_dir/kivy/data/style.kv?
Not really sure I understand the propasal B clearly though.
Mostly, the B approach involve the changes of default values of widget properties.
For example, if you want to change the background_normal + border in Button:
Maybe we could create a type of rule for the "defaults" ? But it seem weird.
What about convention over configuration? If you don't have a 'theme' folder with 'theme.kv' and 'theme.atlas' in your main project directory, the default theme will be loaded from the installation directory. Otherwise the custom theme will be loaded from the 'theme' folder.
I like the convention over configuration approach, but what if you want to have different themes, and switching them, like gtk/qt themes, would kivy be able to do such thing? would we be able to provide a subset of rule that it's safe to redefine and not break existing applications?
We could allow for multiple themes by creating sub-directories in the 'theme' folder. (If there are none, the theme will be loaded normally from there.) Let's say we have the following:
If that's the case we either automatically load the theme which is returned by sorted(theme_subdirs) when no theme configuration is set OR if the new configuration option "kivy:theme_dir: string" is set, we load the theme from the specified directory.
You'd also be able to change to a different theme while the application is running by calling "Builder.load_theme_from()".
^ I don't think this would break existing applications. Although it's a rough draft. What do you think?
>>> sorted(['2_nuts', '0_pretty', '1_cookie'])
It'd be nice to have the option to turn off the image based theme entirely. Often times, I end up loading an empty image into a subclass of button and then defining the style of my UI entirely with canvas drawing commands.
It'd be nice if I didn't have to load an image in for my buttons at all. Using canvas commands it becomes much easier to achieve a variety of button shapes and styles out of the box. Right now kivy will not allow background_normal or background_down on button to be None, which means that an empty 1 pixel image must be loaded.
@Kovak If you set the background_normal/down to '', there is no 1px image loaded, the default texture (white square) will be binded instead... if you use the default rule. If not, nothing will be done.
regarding default themes,
they can be sub divided into platform specific.
like, on android, the button looks more like android, and
on ios, it could give a more look and feel like ios.
on Desktop with mouse, buttons dont need to be that much large (compared to touchscreen's). so space can be utilized more efficiently.