-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Global Color Scheme #1030
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
Global Color Scheme #1030
Conversation
|
Hi @mjhershfield ! And thank you for this analysis and pull-request! UI is not my domain of expertise, but I hope other contributors will provide feedback regarding the color scheme, which color to add,... One thing to keep in mind, especially if you plan on adding settings in InfiniTime to select the color is to keep it simple. Creating a setting app to select 12 colors will probably be cumbersome and not a great experience for the user. Should we allow the user to select say 3 colors? Or provide 4-5 pre-defined presets?
Yes, SettingController is the class that contains all the settings that must be written and read from the flash memory.
Mhm yes, indeed, every class that draws (Screen and all its derivatives) will need a reference to the setting controller to know the color. Another solution would be to implement the setting controller as a global (singleton?) object (I'm not a huge fan of singletons, but that could be a valid use of that pattern). Also, note that LVGL also uses 'themes' (https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/displayapp/lv_pinetime_theme.c) to define the colors and attribute of all the UI widgets. IIRC, if the theme is correctly configured and specified, the apps don't need to specify any colors : the ones from the theme will be automatically applied. That might be something to look into!
I think that a single PR that implements the color scheme, applies it to a few screen and adds the settings menu will be easier to test. |
|
I think our focus should be to make InfiniTime look as good as possible out of the box. Making everything customizable will be a complicated thing that not many people will use the full potential of. Changing something will most likely result in a worse experience than the default theme, and if it doesn't, we should just improve the default theme. For the customizer to work well, a lot of work and sacrifices would have to be made on the default theme. Because of this I don't think making everything customizable is a good idea. I do think that letting the user pick a single accent color is fine, and I proposed this half a year ago in #584, but to this day I haven't figured out how to implement it well. It will probably require more work to be done on the default theme. |
|
Thank you for the feedback! Taking advantage of the LVGL default system theme seems to be a smart approach. I believe all that we would need to do to update accent colors, etc. with this system would be to create a new lv_theme_t object and call lv_theme_set_act() to set it as the system theme (bottom function call of https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/displayapp/LittleVgl.cpp). We could also just modify the current system theme object. I'll look into it, as it seems like the best way to avoid reinventing the wheel. I agree with your point about the default theme @Riksu9000. I think that tweaking the default theme to make it look better is a good place for me to start. Once the default theme is more reasonable, I'll start working on removing some of the places where it is unnecessarily overridden by individual applications. For example, the Quick Settings menu overrides the default theme to use gray buttons while the detailed list of settings menus uses the default semi-transparent aqua color for its buttons. Ideally, both menus would just follow a reasonable default theme. Making more of the interface rely on the default theme rather than on local styling would also make the interface appear more cohesive by using the same coloring throughout the entire UI. Regarding the number of colors that the user should be able to choose, I think that four colors would be a good balance between choice and simplicity: a background color, a button color, a primary accent color, and a secondary accent color. We could then generate any other necessary color dynamically, such as whether white or black text should be used on a button for readability or tinting the button color for disabled buttons. Using LVGL's system theme, we would only have to generate these colors once and then we could use them throughout the entire UI. I'll work on the default theme this week and post screenshots once I've made some progress. |
|
I had missed this PR, it's certainly something that needs attention, I just made #1043 with a much more modest goal, but if the color picker code is useful to you, feel free to reuse it. I'm not sure if the opacity of the settings menu is important, cyan at 20% opa looks pretty similar to teal at 100%. I think fitting more than 3 selectors on one screen while making it usable is going to take some creativity, but the color selector could always span 2 pages/screens if necessary. One screen with 4 color selectors and no margins could work. I personally like the ability to change colors, some preset themes would be acceptable or a good default + customisation, but seeing the number of different color options PTS users have come up with I think the ability to change stuff is important, even if it gets hidden behind the initial theme selection. As far as lvgl themes go, my first question is, can they be changed on the fly or would it require a reboot to apply? That wouldn't be the end of the world but it's not quite as pleasant as choosing some colors and immediately seeing the result. I'm fairly sure if you implement a theme you can apply it in lv_conf.h. You could even try enable/adapt the stock material theme as a base to work from... |
UpdatesHere's some screenshots and a summary of my progress since the last update: I updated the default theme for buttons, labels, and lines. These are the most common UI elements in Infinitime, so I figured that I would tackle them first. LVGL doesn't have a CSS-style class system that we can use for defining if a UI element should use the primary or secondary color, but I was able to use their state system to achieve similar results. I chose two states that are never used in Infinitime that we can use as styling classes. I chose LV_STATE_HOVERED (currently unsupported in LVGL) to represent an element that uses the primary color and LV_STATE_EDITED (editing an entry with an encoder) to represent an element that uses the secondary color. I made some For example, WatchFaceDigital uses the following two lines to color the date and the steps icon: lv_obj_set_state(label_date, PT_STATE_PRIMARY);
lv_obj_set_state(stepIcon, PT_STATE_SECONDARY);This system seems simple but a little hacky. Any feedback on how this could be improved is appreciated. I have started updating some applications to use the default color scheme rather than local theming. So far, I have adjusted WatchFaceDigital, Notifications, QuickSettings, Tile (applications list), and have started work on PineTimeStyle. I started integrating @kieranc's excellent color picker UI from #1043 to use for selecting the primary and secondary accent colors. I have quite a bit of cleanup to do for my changes to it, but it is able to change the primary and secondary accent colors of the default theme on the fly by regenerating the global LVGL theme when the app is closed. Since the accent colors are saved in the settings controller, the custom theming persists over reboots. The reset to default option also works properly. Future WorkFor my next steps, I plan on doing some cleanup of what I've worked on so far (remove commented out/obsolete code) and update the settings UI and PTS to use the default theme's primary and secondary accent colors. I also want to update the color picker to support 4 colors by adding a second page to it. Once the theming system is complete, I will write up some documentation on how to use the LVGL states to apply accent colors throughout the UI. Thank you all for your feedback! If you have any questions or suggestions, please let me know. |
UpdatesI've updated the color picker to have multiple pages so that the user can now pick a primary accent, secondary accent, and button color. I haven't implemented the background color in any apps yet, so it can be ignored from the menu for now. To allow more user choice, I added a tinting system to the color picker. Users can choose a base color that they like and then lighten it or darken it across a range. That way, they can make darker colors more pastel for use as an accent color or make lighter colors darker for use as a button color. You can see some sample themes made with this color picker below. From left to right: Watermelon, Lemon, Blueberry, Monochrome I still have work to do on generating text colors so that the UI is legible with all color combinations (eg. Monochrome's notifier toggle is illegible) FeedbackI have tried two approaches to the tinting/accent color system. One uses the default LVGL colors and calls lv_color_lighten() or lv_color_darken() to tint the color. The other one uses a lookup table to fetch Material Design color tints that are defined by the developer at compile time. I personally think that the lookup table system is better for the future because it allows us to fine-tune the colors provided by the color picker so that they all look good with the PineTime's uncalibrated display. However, I know that any changes to the color picker's tinting options is largely a matter of personal taste and some people might not agree with my decisions. It will also take a while to figure out what colors should be put into the lookup table. At the moment, the light tints get too light and the dark tints do not get dark enough. I'll work on selecting better colors for the LUT if you all think its the better approach. I'm attaching two zip fiiles if you all want to try each system and give feedback on which one we should use and what could be changed/improved. I've been running material-colors-LUT.zip on my sealed PineTime for a few days now. Thank you for your feedback! |
|
I'm writing to express my support for this important development and to offer to assist as a designer (not a coder). If we agree that making the PT as aesthetically pleasing as possible OOTB, I think it would be great to provide a handful of nicely designed colour "themes" that are bundled with the OS when shipped. I would like to help design some of these, as I'm an illustrator, animator and have worked on game/app design projects in the past. I'm not a coder... though I understand enough to comprehend the limitations programmers face, especially on low-spec hardware like the PineTime uses. A question for @mjhershfield ... what would be the best way for me to test your theming and @kieranc 's colour picker in tandem, to arrive at a few contrasting and appealing themes for potential future use? Please keep in mind that I only have a single PineTime (sealed unit) and I don't want to brick my watch. Obviously my preference is to test on the Pinetime itself, though the TFT Simulator that you've used in the .GIF files above looks like a worthwhile starting point too. |
|
I should clarify, that when I said to improve the theme, I meant to improve the overall look of InfiniTime, not to specifically edit By having to make sacrifices for a customizer, I mean the general oversimplification of the UI required to accept just four or so customizable colors. All watchface icons being the same color, which isn't white, seems wrong for many reasons for example. I think the watchface should be where the user can personalize the watch, and the rest of the UI should just be inoffensive enough that it doesn't need to be adjusted, and at most the accent color can be selected. |
|
As a comparison, older Nokia phones offered a selection of first screen background graphics and a single accent color, that was it. I guess they came to the same conclusion as @Riksu9000. |
|
I agree with @Riksu9000 and @Avamander 's inferred preference to limit menu/UI customisation to perhaps just choosing an accent colour. I'm totally fine with customising the colours of a watchface within that app specifically. It would be nice to be able to save and load a few favourite colour combos for watchfaces though. |
|
@Danimations if you want to test the changes (global theming + color picker), you can just flash one of the zip files I attached in my previous comment to your Pinetime. The colors in the color picker are not final and many of the colors look washed out or illegible at the moment. I would appreciate any feedback you have for me if you decide to take a look. @Riksu9000 I agree that we should adapt the theming to the UI and not try to bend the UI to work with my theming system. I'll keep that in mind for the future. My goal with removing style overrides in the code is just to make the entire UI look more coherent and allow its appearance to be adjusted globally based on the user's taste. It is ultimately up to us how far we go in making the entire UI follow the default theme. I probably oversimplified WatchFaceDigital, but I would argue that the rest of the UI looks much more coherent than before this PR. The Infinitime UI is not very complex, and in most cases applying the three colors I have implemented so far will not require any sacrifices to be made. Top: 1.8.0 default settings menu. Bottom: my changes to the default theme. For now, I'm going to revert my changes to some of the icons on WatchFaceDigital so that most icons retain their original coloring. Left: Infinitime 1.8.0 default. Right: My changes to the default theme Thanks for your feedback! Please let me know if you all have any other comments, questions, or suggestions. |
|
I've flashed a build with this PR and I have a few initial thoughts, although I'll continue playing with it for a few days.
On a more personal note I do like being able to set a wild color scheme on PTS and not have it impact the UI too much, but if having a solid coherent set of themes for the whole UI means losing a bit of customisation per watchface, it seems worthwhile. This seems like solid work towards that goal. Edit: the music app should pick up the global button color |
|
Sorry for the lack of communication and progress, I've been kind of swamped the past few weeks. I'll have more time to work on this PR soon. Regarding @kieranc 's feedback:
Here are my priorities for getting this PR ready to be merged:
Thank you for your feedback! I'll post progress updates as I put more work in. |
I have an idea which I'm going to try and flesh out as soon as possible, the PTS picker is certainly confusing to look at but as soon as you press a button and see the result, I feel it explains itself.
Seems reasonable. There's no accounting for taste however and some people might want a light mode, I have to admit I didn't hate it when my watch spontaneously inverted all colours so, not a priority, but maybe not totally ruled out?
If my idea for #1 works out it might resolve this too. Mockup incoming.
I love this plan, perhaps I could make the reset button in PTS use the colors from the current theme so it works both ways? |
|
I've thrown together what was in my brain for a theme selector as LVGL code, it needs some tidying still but if the concept is interesting, I'll keep working on it. Each entry shows the primary/secondary/accent color for a given theme, pressing on the left 2/3 of the button will apply the theme, pressing on the right 1/3 where the paintbrush icon is will open the color picker with the colors from that theme selected to allow the user to tweak the colors if they want to. I've used a mask to make the diagonal line, it's not currently enabled in our lv_conf and I'm not sure of the memory impact yet. |
|
@kieranc That looks amazing! If you can share the source with me once you have it cleaned to your liking, I would like to integrate it into my branch to hopefully finalize the theming system soon. |
|
I'm glad you like it, the code is here: the button handler needs hooking back in and as yet I haven't tested it on a real watch to see if the lv_mask feature will cause a problem, I'll keep tinkering with it today if I get a chance |
|
I'll close this as making everything customizable isn't aligning with our current goals. We'd like to improve the default theme instead if the colors are too clashing, basically to fix the root cause and not make the user fix it for themselves. |
I was hoping I would be able to make a set of themes the user could switch to; like make a Dracula theme for the software that users could switch to that would not require much changes. |
|
I also feel that some sort of global theming is a popular and interesting medium term goal. Given that a fair amount of groundwork and ideas has been started here, can it not remain open until either it is functional, the author decides they don't want to pursue it, or a better alternative is proposed? |
|
It's been a few months since the last commit. PRs aren't really to show off things people have done, but to add code to the codebase. If a PR isn't going to be merged, then it's not really useful to keep it open. It's not stopping people from working on something on their own, or reforming it into something that can be merged. |
|
Hi everyone! Thanks for all of the interest all of a sudden. I agree that this PR should be closed. I bit off more than I could chew with this PR and I ran out of time and motivation to see it to completion. There were just too many goals that I had for this PR and even if it made it to the review stage it would be a pain to look through all of the changes to get it merge ready. I still have a few commits on my local machine that I'll push to my fork with the beginnings of the color picker interface. I don't plan on abandoning the global color picker completely, though. Since there's interest in having this feature, I think I'm going to open a fresh PR based on 1.10 with only the default theming improvements. It will include all of my work on the default theming of every app and the groundwork for custom themes (the PRIMARY_STATE/SECONDARY_STATE workaround for having CSS-like classes for styling), but no color picker. If that PR gets merged, I'll finish up the color picker and theme selector code and add that as a separate PR. I just want the scope of each PR to be smaller so that it's more manageable for me and for the reviewers and the debate over how deep custom themes should be doesn't hold back the improvements to the default appearance of the watch. Thanks for the interest, and I'll get back to work on this soon. :) |
|
Leaving a comment here that I am working on a color redesign with catppuccin mocha palette, and it's going along very well. Now that we have the ability to write to the 4MB storage, reading from a theme file may just be possible. Here's the post with most recent update, and where I post updates quasi-nightly: |














Introduction
Hello everyone! I've thought that creating a global color scheme would be a good feature for Infinitime so that users could modify the background, accent, and text colors of the interface. This will be useful for accessibility (#972) and personalization (#559, #684). I'm opening this pull request so that I can get community feedback on how this feature should be developed and to provide progress reports. This pull request is only a proof of concept, I am not asking for it to be merged. I'll likely make new pull requests for this feature as it reaches completion.
Current Progress
For this initial version, I am following the Material Color Guidelines for which colors should be included in this color scheme. So far, I've added a struct to the settings controller that contains the colors for the global color scheme that will eventually be stored within the settings data file. I've chosen the following defaults for the color scheme based on the current Infinitime UI:
I've also started modifying commonly used screens to use this global color scheme. So far, I've made changes to the digital and PTS watchfaces, the quick settings menu, and the application menu. Here are some screenshots from the simulator:
Future Work
In the future, I would like to implement a settings menu for setting the primary accent, secondary accent, background, and button colors. We could then programmatically generate the variants and text colors. I would also like to spread the global color scheme throughout the entire UI.
Feedback
I have a few questions for the community about how this should be implemented:
Is using the settings controller the best way to implement this feature? The main downside of this approach is that the settings controller object will have to be passed into every function that draws to the screen, which will require a lot of refactoring of current code. Is there a different place where I could store the color scheme to minimize refactoring?
An alternative strategy to implement this is to define the global colors with
#definedirectives (like #559), however this means that you would have to rebuild the firmware whenever you want to change the color scheme, which is not a good experience for end users unless we create a web app or something so that users could choose their theme and download a firmware without needing to set up a local dev environment. It would require less work for restructuring the firmware codebase, but I believe that it would require much more work to maintain in the future.What colors should be included in the global color scheme? I've used the Material Color Guidelines as a baseline, but I feel that we probably need more options such as a disabled button/surface color, and we may not need certain colors such as the background color if we want the background to always be black for example.
Should I split this feature over multiple pull requests, such as one that implements a global color scheme system, a few that implements the global color scheme in various screens, and one to add the settings menu to change the accent colors?
Thank you for considering my feature idea! I'm new to contributing to open source software, so any feedback you have for me will be greatly appreciated.