Difference between revisions of "GUI Themes/TODO"

From ScummVM :: Wiki
Jump to navigation Jump to search
(fixes link to mockups.)
(→‎Dialogs: Showing hidden files is already possible.)
 
(90 intermediate revisions by 13 users not shown)
Line 1: Line 1:
{{Infobox_TODO|
taskname=GUI Themes TODO|
techcontact=The ScummVM Team|
subsystem=Generic|
}}
We plan to implement a new GUI look & feel in ScummVM, roughly based on the
We plan to implement a new GUI look & feel in ScummVM, roughly based on the
new look of our web site.
new look of our web site. Some concept drafts of the new look can be found here:
 
http://kressline.de/wip/scummvm/
== Current state ==
No real coding (besides some quick and dirty proof-of-concept hacks) has been done yet. Some concept drafts of the new look can be found here:
http://www.thekrest.de/wip/scummvm/
 
 
 
== Ideas & plans ==
The new GUI will rely on bitmaps / pixmaps for drawing the GUI widgets,
like buttons, edit fields, tabs etc. This poses various problems and
challenges but also some nice benefits (besides the obvious one, the
improved look and feel :-).
 
Some random thoughts, ideas and statements:
* Using pixmaps has the drawback of taking more memory, and possibly more CPU power. So as a fallback, it would be good if we could still work w/o the pixmaps (possibly reverting to the current UI).
* To make that easy, use a kind of "ThemeManager" or "AppearanceManager", which is used by widgets to render themselves
* This means we should try to seperate widget logic (what happens if a click occurs, managing data contained in the widget etc.) from widget drawing as much as possible. Ideally, widgets only know how to react to events etc. and whenever they need to draw something, they invoke suitable methods of the AppearanceManager
* We'd provide two basic apperances: The current one, re-tooled to use a special AppearanceManager "plugin"/"module", and a new one, which uses pixmaps to render all widgets. Care should be taken to make it possible to add new ones or disable the pixmap based ones (for ports that are low on memory)
* Anti-aliased fonts: Some of the concept drafts use anti-aliased fonts; while that looks nice and nifty, it also adds a lot to the complexity of text rendering. For now we'll try to work without it.
* Image data can both be stored in external files as well as be compiled into the executable, or generated on-the-fly. To this end, we have a ImageManager class which helps separate the code using image data from the code used to loading the image data.
* We should support all our primary resolutions: 320x200, 320x240, 640x400, 640x480. Ideally, we should support all resolutions (not just the ones I mentioned). Also, ideally every theme should support all, but if that is not possible, at least we should smoothly degrade to another theme (e.g. the 'classic' theme which doesn't use pixmaps to render itself), instead of e.g. crashing
* ...
 
== Customizability ==
We have been asked several times in the past to offer skinning support in ScummVM. With the new GUI code, this would be possible...
 
However, I (Fingolfin) think that this is a bad idea, and currently am opposed to this. IMHO, skinning is an excuse for not being able / willing to design a proper, nice, and usable default UI for your application (and in fact, the first famous skinable app, a certain MP3 player you may know, added skins precisely because of this).
 
Actually, "opposed" may not be the right word: I think that skinning should be very last thing we worry about. If we can add skinning w/o much hassle, w/o wasting resources that could otherwise be used to design and implement a great new default UI, we can consider it. But I am not willing to compromise our code design or the quality of the new GUI just to allow for skinning. I want ScummVM to look good and be easy to use "out of the box", this is the first (and the second and third :-) priority, IMNSHO...
 
 
 
== Data formats ==
We probably will use BMP as the format for our pixmaps, optionally compressed using zlib / gzip. Reason: It's very easy to read BMPs (or at least certain BMPs, we don't have to implement a fully generic BMP loader), and we already use zlib. So this causes the least overhead (compared to using e.g. libpng for PNG support), and the resulting file sizes are not much bigger than those of PNGs.
 
It will also be possible to integrate pixmaps into the array, in the form of global/static arrays. We'll probably provide a tool that takes a BMP and generates a C++ source file from it. Note that here, zlib compression can be used, too (to reduce the size of the ScummVM binary).
 
Some pages that contain information about the BMP format:
* http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
* http://astronomy.swin.edu.au/~pbourke/dataformats/bmp/
* http://atlc.sourceforge.net/bmp.html (contains information on the 16 bpp BMP extension)
 
The BMP "standard" doesn't really cover 16 bit data (the bit depth normally used by ScummVM). Sometimes, 15 and 16 are used to indicate 555 and 565 mode.
 
== Some components of the new GUI code ==
 
=== ImageManager / GraphicsManager (singleton) ===
* a singleton (?) which manages a set of graphic objects
* client code can register graphics by name / ID
  imageMan->registerGraphic("button_leftSide", surface);
* client code can query for a graphic by a name and/or an ID
  surface = imageMan->getGraphic("button_leftSide");
* data stored/returned as a Graphics::Surface
* client code must unregister images when the corresponding surface is deleted, else crashes may occur!
* The idea of being able to "register" images is that it makes it possible to load image data both from files and from static arrays, as part of the executable
* If an image is request which has not been registered, the ImageManager will search for image files matching the name, e.g. in the above example it might search for
  button_leftSide.bmp
  button_leftSide.bmp.gz
 
The precise list of supported file types could be hardcoded (easier to write, maintain, port, takes up less resources, but also is less flexible); or we could make it plugable so that arbitrary formats can be supported. My oppinion: Let's start simple, if we need multiple formats we already have an abstraction layer in place and can safely rewrite the internals of ImageManager later on
 
 
=== ImageLoader / ImageDecoder ===
Not sure whether we really need this class; it could encapsulate
the code used to load & decode BMPs, and would in the future
allow loading other formats, too (if desired), like PNG


See also [[GUI Themes/Specs|specs]]


=== AppearanceManager ===
== To Do ==
This could be a very simple singleton which only manages a list of "Appearances" or "Themes". The real work would be then done by instances / subclasses of GUI::Theme or so...


  class Theme {
=== General ===
  public:
* Add tab-focus support, i.e. make it at least possible to use the "tab" key (and also "shift-tab" to cycle through the edit fields.
    virtual int getButtonHeight();
* Even nicer would be general "tab cycle" support, allowing tab to cycle the focus for all items where it makes sense (buttons, checkboxes, etc.), to make the GUI fully keyboard controllable
    virtual void drawButton(Rect r, String label);
* SPEED: The GUI is relatively sluggish these days on my 1.5 GHz PowerBook :-/. I'll try to list some bottle necks and possible solutions:
    virtual void drawDialogBackground(Rect r);
** A lot of time is spent in ThemeModern::openDialog for dimming the screen.
    virtual void drawCheckbox(Rect r, String label, bool checked);
*** The code calls a function pointer for each pixel of the screen, which results in code which the compiler can't properly optimize, essentially doing a couple hundred thousand tight read-call-write ops, which can't be inlined / improved upon.
    ...
*** Better: change _dialogShadingCallback to not work on a single pixel but on the whole better
  };
*** Even better: Get rid of the _system->RGBToColor / _system->colorToRGB which are terrible for performance, too (can't be inlined). So, at least provide a 555 / 565 color mode version, which works efficient on targets using these color modes, and only fall back to the OSystem API if an unsupported color mode is in use
* Implemented better layouting code. It should be possible to layout widgets in a grid (typical example: a 2 by n "grid", each row contains a label on the left side (to be right aligned) and a widget on the right side (to be left aligned).
* Change the monolithic DrawStep struct into a class hierarchy. To this end, we probably should also change the XML format (which sadly closely mirrors this monolithic struct). Namely, replace the <drawstep> element by one element for each kind of drawstep. In each of these specialized "drawsteps", allow only those attributes that make sense.


=== Widgets ===
* EditableWidget: Make it possible to specify a min/max length for the text
* EditableWidget: Let setEditString filter the string it gets
* EditableWidget: Right now, custom filtering requires the user to subclass; it would be nice if there was simply a "validator hook" or so. Maybe take some inspiration from Java's Swing in this matter.
* List widget
** get mock-up from Krest
** Glitches when entering very long strings. The cursor overlaps the scrollbar. Possibly the scroll bar width should be automatically added to the right-side paddings, but I don't have the time to experiment with it right now.
* PopUp widget (aka drop-down list)
** get mock-up from Krest
* Scrollbar widget - The handle leaves trails in 320xY resolution. Possibly, the shadow of the handle is drawn too wide.
** Can't replicate in latest git master. Fixed by 1b2485f4af2010f262bd4f6e149a8c2d96b893cc?
* Add a new "BoxWidget" / "GroupBoxWidget", which can be used to group other widgets
** This widget makes it easy to group widgets and control them together; e.g. disable the box widget, and all children get disabled, too
** Here is the equivalent of this control in Qt: http://doc.trolltech.com/4.3/widgets-groupbox.html
** (optionally) draws a border around itself
** (optionally) draws a title
** The ideal version of this would also support a checkbox in the title, and would automatically disable/enable all contained widgets if the checkbox gets activated (this is also demonstrated in the above Qt example)
** Clearly this widget would be of great use for the options dialogs, for the "Override XYZ" checkboxes
* ButtonWidget: Allow drawing the 'default' button in a visually distinct way


=== Widget ===
=== Wizards ===
We need to modify all Widget subclasses to use the active Theme to draw themselves.
* To make ScummVM as friendly as possible, we would like to introduce wizards that would help with essential tasks.
* No Games Wizard: when there are no games in the config file, a wizard will come up saying something like
Welcome to ScummVM!


Please tell us where your point and click games can be found:


Path Edit Box


"Find My Games" button (uses Mass Add)


== How to render widgets ==
"Cancel Wizard" button, "Don't show again" Checkbox


TODO: Include graphics in each subsection to demonstrate how the corresponding widget would look
* Rare game options wizard: it was suggested that we implement a wizard to tell the user about rare options such as dithering in SCI games. For example, when an SCI0 game is added either directly or through mass add, we could show:
You have added an SCI0 game. This game can use the 'undithering' option to enhance the original look.


=== Dialog background ===
Checkbox "Turn this feature on"
TODO


Remember that you can turn this feature on or off through the XXXX tab.


=== Dialog tabs ===
OK button.
TODO


=== Dialogs ===
* About dialog
** looks bad. Probably add some shadows and text padding
** fix glitch at the top of the dialog where part of the characters get stuck (see FIXME in about.cpp)
** [Classic theme] Text seems to be drawn over the dialog frame. At least at the top of the dialog.
** The grey text (color 2, kStateDisabled) is hard to read in both the new and the classic theme.
*** Reported as {{Tracker|id=5833}}. Fixed in Modern by fee19d. Fix for classic still needed? i.e. make lighter there as background is black (as opposed to Modern, which has almost white background).
** Add a "fade" effect for the top/bottom text lines
** Maybe prerender all of the text into another surface, and then simply compose that over the screen surface in the right way.
* Options dialog
** There is currently no way to unset/reset-to-default the path settings from the GUIsettings.
*** To this end. maybe add an (optional) "reset to default" button to the browser dialog. (This would save space in the options dialog)
*** Alternatively, add "Reset to Default" buttons to each path setting, possible similar to the one used with the soundfont (which is a rather too cryptic, IMO)
** Several texts, e.g. vcMusicText, have their alignment set to kTextAlignRight, but are still drawn as left-aligned.
** Add ability to adjust debuglevel (int). Useful for command line less ports i.e. Android.
* Engine Options Dialog
** Currently only bool (checkbox) options are supported. Add support for int (slider) options. Needed for:
*** walkspeed (int)
*** gfx_details (int - SWORD2)
*** t7g_speed (int - GROOVIE)
** reverse_stereo (bool - SWORD2) is also currently missing. Make this a global option as it is likely to apply to a number of engines?
* The sliding action of the debug console takes a lot more CPU now than it used to. On my 450 MHz P3, I don't even see it slide in 2x mode. It seems to appear/disappear all at once.
* File browser dialog
** Right now we "visualize" that an entry is a folder/directory by appending a slash "/" to the name. This is not really intuitive for non-Unix users. Maybe we could add small file / directory icons? And maybe also an up-arrow for the "up" button.


=== Buttons ===
=== Fonts ===
We should limit ourselves to buttons of a single height, that makes UI design more consistent, and rendering them simpler. To render a button using pixmaps, one needs at least three pixmaps: one of the left border, one for the right border, and one (which can be replicated and tiled) for the middle part. To draw a button, you first place the left/right borders, then tile the middle image, and finally render the label atop it.
* The BDF fonts can have characters that are both wider and taller than expected. For instance, the letter Ã… extends one pixel above the top of the line. This can lead to glitches since we update the screen based on font height and character width, not bounding boxes. The List widget is one example of this.
* <s>Antialiased fonts</s>
** <s>This could be tricky, since the BDF fonts are bitmaps. Is it even possible, within this format, to store the alpha channel needed (?) to represent an anti-aliased glyph? One possibility might be to store a larger version of the font and scale it down to the desired size, but that seems wasteful.</s>
*** <s>BDF fonts aren't suitable here since they're 1bpp. It could be done if font data would be 8bpp and thus, contain just the alpha channel, i.e. shades of gray which will be blended on rendering stage.</s>
*** <s>It's *still* possible to use 1bpp fonts for antialiasing, by implementing oversampling: By downscaling a 4x fold or 8x too big character, one can compute & render the antialiased output on the fly -- this worked even on some old 90 MHz PowerPC Macs, so it should be doable. Main concern would be memory usage, and the need to have a big version of all fonts around. Or we switch to a vector based font system (TrueType plus [http://www.freetype.org/index2.html Freetype]), at the cost of resources and possibly some portability -- we would have to research this a bit. Another advantage of using FreeType: Unicode support in the GUI would be possible.</s>


One needs different pixmaps for the basic states a button can be in: Normal, pressed/clicked, disabled.
=== Collaborative work with the OpenUsability Project ===
Given that usability is one of the primary driving forces behind the design of user interfaces, it seems logical to pay close to attention to it while redesigning ScummVM's GUI.


The slow way is to do all of this every time the button is drawn. The fast (but memory intensive) way is to cache the button in a graphic surface (all of its three states). We only generate the cached version of the button once it is used (e.g. a disabled button doesn't need to cache the normal/clicked version)
The OpenUsability project (http://openusability.org/) provides usability consulting and advice for open sourced applications. It would be a sensible opportunity to contact them, seeking assistance to improve ScummVM in the usability front.


== Some ideas about theme caching ==


=== Checkboxes ===
Solution will look something like this:
TODO


  ./scummvm --gui-theme=classic  --create-gui-cache 320x200


=== Slider ===
you get classic-320x200.tcc file
TODO


  ./scummvm --gui-theme=classic  --create-gui-cache 320x240


=== Popup buttons ===
you get classic-320x240.tcc file
TODO


Then concatenate the two and probably dump it into C array. Porters should do that by themselves for all resolutions supported by their platform. I.e. we have generic XxY theme, and all specific resolutions are derived from it.


=== Lists ===
=== tcc (theme cache) file format ===
TODO


This theme cache will be plainly a dump of all evaluated variables from HashMap. They will be loaded with loadAll() method in HashMap.


=== Scrollbars ===
  'RESL', length, "320x200", number of vars, dumped vars
TODO -- concept art is missing, too


dumped vars are:


=== Input fields ===
  "varname", int16 value,...
TODO


This format will let easily concatenate several generated theme cache files.


=== Radio buttons ===
Probably there will be some optimisations in loadAll() method, which will malloc one big chunk of those vars, and since we have their keys as ''const char *'', then it can alloc one big chunk for variables name as well and then pass pointers inside of it to respective members. Of course, that will be specially flagged as it will not be possible to free() any of those chunks deliberately.
TODO -- this widget actually doesn't exist currently

Latest revision as of 19:13, 11 March 2016

TODO List
Name GUI Themes TODO
Technical Contact(s) The ScummVM Team
Subsystem Generic

We plan to implement a new GUI look & feel in ScummVM, roughly based on the new look of our web site. Some concept drafts of the new look can be found here: http://kressline.de/wip/scummvm/

See also specs

To Do

General

  • Add tab-focus support, i.e. make it at least possible to use the "tab" key (and also "shift-tab" to cycle through the edit fields.
  • Even nicer would be general "tab cycle" support, allowing tab to cycle the focus for all items where it makes sense (buttons, checkboxes, etc.), to make the GUI fully keyboard controllable
  • SPEED: The GUI is relatively sluggish these days on my 1.5 GHz PowerBook :-/. I'll try to list some bottle necks and possible solutions:
    • A lot of time is spent in ThemeModern::openDialog for dimming the screen.
      • The code calls a function pointer for each pixel of the screen, which results in code which the compiler can't properly optimize, essentially doing a couple hundred thousand tight read-call-write ops, which can't be inlined / improved upon.
      • Better: change _dialogShadingCallback to not work on a single pixel but on the whole better
      • Even better: Get rid of the _system->RGBToColor / _system->colorToRGB which are terrible for performance, too (can't be inlined). So, at least provide a 555 / 565 color mode version, which works efficient on targets using these color modes, and only fall back to the OSystem API if an unsupported color mode is in use
  • Implemented better layouting code. It should be possible to layout widgets in a grid (typical example: a 2 by n "grid", each row contains a label on the left side (to be right aligned) and a widget on the right side (to be left aligned).
  • Change the monolithic DrawStep struct into a class hierarchy. To this end, we probably should also change the XML format (which sadly closely mirrors this monolithic struct). Namely, replace the <drawstep> element by one element for each kind of drawstep. In each of these specialized "drawsteps", allow only those attributes that make sense.

Widgets

  • EditableWidget: Make it possible to specify a min/max length for the text
  • EditableWidget: Let setEditString filter the string it gets
  • EditableWidget: Right now, custom filtering requires the user to subclass; it would be nice if there was simply a "validator hook" or so. Maybe take some inspiration from Java's Swing in this matter.
  • List widget
    • get mock-up from Krest
    • Glitches when entering very long strings. The cursor overlaps the scrollbar. Possibly the scroll bar width should be automatically added to the right-side paddings, but I don't have the time to experiment with it right now.
  • PopUp widget (aka drop-down list)
    • get mock-up from Krest
  • Scrollbar widget - The handle leaves trails in 320xY resolution. Possibly, the shadow of the handle is drawn too wide.
    • Can't replicate in latest git master. Fixed by 1b2485f4af2010f262bd4f6e149a8c2d96b893cc?
  • Add a new "BoxWidget" / "GroupBoxWidget", which can be used to group other widgets
    • This widget makes it easy to group widgets and control them together; e.g. disable the box widget, and all children get disabled, too
    • Here is the equivalent of this control in Qt: http://doc.trolltech.com/4.3/widgets-groupbox.html
    • (optionally) draws a border around itself
    • (optionally) draws a title
    • The ideal version of this would also support a checkbox in the title, and would automatically disable/enable all contained widgets if the checkbox gets activated (this is also demonstrated in the above Qt example)
    • Clearly this widget would be of great use for the options dialogs, for the "Override XYZ" checkboxes
  • ButtonWidget: Allow drawing the 'default' button in a visually distinct way

Wizards

  • To make ScummVM as friendly as possible, we would like to introduce wizards that would help with essential tasks.
  • No Games Wizard: when there are no games in the config file, a wizard will come up saying something like

Welcome to ScummVM!

Please tell us where your point and click games can be found:

Path Edit Box

"Find My Games" button (uses Mass Add)

"Cancel Wizard" button, "Don't show again" Checkbox

  • Rare game options wizard: it was suggested that we implement a wizard to tell the user about rare options such as dithering in SCI games. For example, when an SCI0 game is added either directly or through mass add, we could show:

You have added an SCI0 game. This game can use the 'undithering' option to enhance the original look.

Checkbox "Turn this feature on"

Remember that you can turn this feature on or off through the XXXX tab.

OK button.

Dialogs

  • About dialog
    • looks bad. Probably add some shadows and text padding
    • fix glitch at the top of the dialog where part of the characters get stuck (see FIXME in about.cpp)
    • [Classic theme] Text seems to be drawn over the dialog frame. At least at the top of the dialog.
    • The grey text (color 2, kStateDisabled) is hard to read in both the new and the classic theme.
      • Reported as [Bug #5833]. Fixed in Modern by fee19d. Fix for classic still needed? i.e. make lighter there as background is black (as opposed to Modern, which has almost white background).
    • Add a "fade" effect for the top/bottom text lines
    • Maybe prerender all of the text into another surface, and then simply compose that over the screen surface in the right way.
  • Options dialog
    • There is currently no way to unset/reset-to-default the path settings from the GUIsettings.
      • To this end. maybe add an (optional) "reset to default" button to the browser dialog. (This would save space in the options dialog)
      • Alternatively, add "Reset to Default" buttons to each path setting, possible similar to the one used with the soundfont (which is a rather too cryptic, IMO)
    • Several texts, e.g. vcMusicText, have their alignment set to kTextAlignRight, but are still drawn as left-aligned.
    • Add ability to adjust debuglevel (int). Useful for command line less ports i.e. Android.
  • Engine Options Dialog
    • Currently only bool (checkbox) options are supported. Add support for int (slider) options. Needed for:
      • walkspeed (int)
      • gfx_details (int - SWORD2)
      • t7g_speed (int - GROOVIE)
    • reverse_stereo (bool - SWORD2) is also currently missing. Make this a global option as it is likely to apply to a number of engines?
  • The sliding action of the debug console takes a lot more CPU now than it used to. On my 450 MHz P3, I don't even see it slide in 2x mode. It seems to appear/disappear all at once.
  • File browser dialog
    • Right now we "visualize" that an entry is a folder/directory by appending a slash "/" to the name. This is not really intuitive for non-Unix users. Maybe we could add small file / directory icons? And maybe also an up-arrow for the "up" button.

Fonts

  • The BDF fonts can have characters that are both wider and taller than expected. For instance, the letter Ã… extends one pixel above the top of the line. This can lead to glitches since we update the screen based on font height and character width, not bounding boxes. The List widget is one example of this.
  • Antialiased fonts
    • This could be tricky, since the BDF fonts are bitmaps. Is it even possible, within this format, to store the alpha channel needed (?) to represent an anti-aliased glyph? One possibility might be to store a larger version of the font and scale it down to the desired size, but that seems wasteful.
      • BDF fonts aren't suitable here since they're 1bpp. It could be done if font data would be 8bpp and thus, contain just the alpha channel, i.e. shades of gray which will be blended on rendering stage.
      • It's *still* possible to use 1bpp fonts for antialiasing, by implementing oversampling: By downscaling a 4x fold or 8x too big character, one can compute & render the antialiased output on the fly -- this worked even on some old 90 MHz PowerPC Macs, so it should be doable. Main concern would be memory usage, and the need to have a big version of all fonts around. Or we switch to a vector based font system (TrueType plus Freetype), at the cost of resources and possibly some portability -- we would have to research this a bit. Another advantage of using FreeType: Unicode support in the GUI would be possible.

Collaborative work with the OpenUsability Project

Given that usability is one of the primary driving forces behind the design of user interfaces, it seems logical to pay close to attention to it while redesigning ScummVM's GUI.

The OpenUsability project (http://openusability.org/) provides usability consulting and advice for open sourced applications. It would be a sensible opportunity to contact them, seeking assistance to improve ScummVM in the usability front.

Some ideas about theme caching

Solution will look something like this:

 ./scummvm --gui-theme=classic  --create-gui-cache 320x200

you get classic-320x200.tcc file

 ./scummvm --gui-theme=classic  --create-gui-cache 320x240

you get classic-320x240.tcc file

Then concatenate the two and probably dump it into C array. Porters should do that by themselves for all resolutions supported by their platform. I.e. we have generic XxY theme, and all specific resolutions are derived from it.

tcc (theme cache) file format

This theme cache will be plainly a dump of all evaluated variables from HashMap. They will be loaded with loadAll() method in HashMap.

 'RESL', length, "320x200", number of vars, dumped vars

dumped vars are:

 "varname", int16 value,...

This format will let easily concatenate several generated theme cache files.

Probably there will be some optimisations in loadAll() method, which will malloc one big chunk of those vars, and since we have their keys as const char *, then it can alloc one big chunk for variables name as well and then pass pointers inside of it to respective members. Of course, that will be specially flagged as it will not be possible to free() any of those chunks deliberately.