.. _styles:

Styles and Themes 
-----------------

My understanding is that the motivation and attraction of ttk is that
one may compose a GUI and it will look "normal" when run in any of the
common OS's - Linux, UNIX, Windows, or OS X.  Also, it is possible to
create new themes which are more pleasing because of a more modern
appearance of a GUI. However, I think ttk is a mess in terms of
architecture, implementation, and especially documentation.  However,
there are several much needed widgets available in ttk including
ttk::notebook, ttk::progressbar, ttk::treeview, ttk::panedwindow,
ttk::separator, and ttk::sizegrip. PAGE supports those ttk widgets as
well as a few others. To get a better appreciation of some of the
difficulties in working with styles and themes, see the `difficulties
page <https://tkdocs.com/tutorial/styles.html#whydifficult>`_ for
info.

The Tk problem that PAGE addresses is that there are two sets of
widgets, tk widgets and ttk widgets, but neither set is complete and
so a GUI will probably combine widgets from each set.  For example,
the set of tk widgets lack widgets such as tabbed notebooks, combo
boxes, and separators while ttk widgets lack a message widget, text
widgets, and canvas widgets.  In earlier versions of PAGE projects ttk
widgets mimicked tk widgets. Version 8.0, introduces support of ttk
themes and that requires that the appearance of tk widgets mimic ttk
widgets.  Also, I try to have the generated GUI sport the PAGE
preferences. And finally, I wish to respect PAGE preferences which
allow one set of preferences for PAGE windows and different
preferences for the GUI under development.



In other words,I have tried to manipulate the Themes and Styles in a
way that the PAGE user can mix ttk widgets with tk widgets and have a
reasonably consistent appearance. This is very much a case of evolving
understanding and appreciation. This usage of Themes and Styles is
different from orthodox usage which would replace tk widgets with ttk
widgets but it seems to work pretty well as shown by
:ref:`widgetdemo`. There are still issues related to menus which will
be addressed in a future release.
	 

I received a great deal of help from Guilherme Polo which got me to
the point I am at now. Also, Maksim Korzh was instrumental in
providing the Style coding for the PNotebook widget.


First I would like to automatically generate code for the user which
would follow his color scheme as expressed in the preferences window.
Consider the following code for a GUI window that contains a tabbed
notebook with a background color of wheat:

.. sourcecode:: python



    _style_code_ran = 0
    def _style_code():
        global _style_code_ran
        if _style_code_ran: return            
        try: note_support.root.tk.call('source',
                    os.path.join(_location, 'themes', 'page-wheat.tcl'))
        except: pass
        style = ttk.Style()
        style.theme_use('page-wheat')
        style.configure('.', font = "-family {DejaVu Sans} -size 14")
        _style_code_ran = 1


The module level function _style_code sets up the theme to be
used with the ttk widgets. This code will vary with the theme and the
ttk widgets used. It is only executed once. It reads the specified
theme, if it is not one of the ttk builtin themes and sets the font to
the default text font specified in the preferences.




The following code in the __init__ fixes the background color of the
Toplevel window.

.. sourcecode:: python

        top.configure(background=_bgcolor)
        top.configure(highlightbackground="wheat")
        top.configure(highlightcolor="black")

		

.. I came across some code which purports to calculate the complement and
.. analogs of a color and used that to calculate the above colors.  I also
.. used similar code to translate the RGB coding to the name of the
.. closest X11 color so that the user can get some idea of the color and
.. easily change them if desired.

.. Next comes one of the special cases, note book tabs.  Here I have
.. specified background and foreground colors for the tabs since they are
.. not inherited from the "." ttk object.

.. .. sourcecode:: python

..           self.style.configure('TNotebook.Tab',background=_bgcolor)
..           self.style.configure('TNotebook.Tab',foreground=_fgcolor)
.. 
.. And finally I make the color of the selected tab the complement of the
.. background color as defined above, and the color of the tab under the
.. mouse one of the analog colors from above.  This is sort of automating
.. the theme color selection and I really didn't want to do that.  It just
.. seemed necessary to compete the task.  I hope the user is able to
.. derive from the example, the changes he wishes to make.
.. 
.. .. sourcecode:: python
.. 
..            self.style.map('TNotebook.Tab',background=
..                [('selected', _compcolor), ('active',_ana2color)])
.. 
.. The above shows the code I added to make the notebook widget look
.. consistent. Similar tricks can be seen for treeview widgets,
.. scrollbars, labeled frames, etc.  Again, if you see better or clearer
.. ways of handling style components please let me know.


I did all of my development work on Linux.  As an illustration of the
same PAGE-generated GUI running under different systems, let me
present the following screens shots of vrex.py (vrex is one of the
examples discussed later in the examples section):

.. image:: vrex-linux.png

Above: Running vrex running on Linux.  This is what I built using PAGE
on Linux..



.. image:: vrex-windows10.png


Above: Running vrex running on Windows 10 using the "winnative"
theme. This looks pretty good except for the background color in the
menubar and the sizegrep. 

.. image:: vrex-osx.jpg

Above: Running vrex running on OS X.


.. As one can see there are differences in appearance but on the whole it
.. seems to work reasonable well for this example.  That is fortunate
.. because the main feature of the example is the use of paned windows
.. and scrolled text widgets and they are certainly important for GUI
.. building. 
.. 
.. 
.. I concluded that it would be better if I generated code which forces
.. the "winnative" theme when the generated GUI is run on Windows.  It
.. seems preferable to me to have the sizegrip with an incorrect
.. background but a better rendering of the notebook widget than the
.. other way around.  Any comments, help, or suggestions will be very
.. welcome.
.. 
.. From the above and similar experiences, for my own use, I avoid ttk
.. widgets which are also implemented as tk widgets such as buttons,
.. labels, frames, checkboxs, and radiobuttons,  but use
.. notebook, paned window, progress bar, and treeview, because of their
.. convenience. I intend to keep looking at the ttk problems and if I can
.. learn how to avoid them I will certainly do so.

.. _v8:

Version 8 Additions
```````````````````

There are two sets of windows presented in PAGE - PAGE windows like
the Attribute Editor and the Widget Tree and GUI windows being
constructed. Themes are only active or imposed on the GUI windows
while the appearance of PAGE windows follows the Preferences window.

PAGE version 8 introduces the ability to use ttk themes other than the
built in "default" theme. Previously, PAGE supported only the
"default" theme and it was perverted to make the ttk widgets resemble
the tk widgets. I had in mind that one would use tk widgets and still
have consistent access to needed widgets that have no counterpart in
tk widget set such as notebooks and progress bars.  Since Version 8
makes available all of the builtin themes including "default" which
should be left untouched, it seemed best to create a new theme, named
"page-legacy".  If one selects "page-legacy" as the theme in
preferences and sticks with it, PAGE will behave as previously.

.. 
.. The reason that I have made a serious attempt at supporting themes is
.. that I learned about the function "tk_setPalette". I have yet to find
.. any comprehensive documentation of the function but it appears to
.. allow one to modify aspects of the appearance of tk widgets to
.. coincide with ttk widgets. This allows an application to have a
.. reasonable appearing mixture of tk and ttk widgets. This is almost
.. necessary because ttk support for menu or popup widgets. 

In theory, if one wishes to exploit the appearance of another theme, he
selects one of the other supported themes and confines himself to ttk
widgets. 

Themes impose geometric features, color schemes, and fonts. Typically,
the font size is 10 point. Since I strain to read 10 point fonts, I
have attempted to respect the GUI font preferences. That is, GUI fonts
specified in the PAGE Preferences Window will be imposed with ttk
widgets.

Default is not default Unless it is
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Ttk has several builtin themes and the list of those available is
dependent on the OS where Tk or tkinter is running. For example, on
Linux the builtin themes are clam, alt, default, and classic. With
Windows the list is winnative, clam, alt, default, classic, vista, and
xpnative. Finally, OSX the builtin themes are aqua, clam, alt,
default, and classic.  If the program does not specify the theme to be
used, on Linux "default" is used, on Windows "vista", and on OSX
"aqua". The Preferences window allows the user allows the user to
specify the initial theme to be used; if unspecified, then "default"
is the initial theme.

Third Party Themes
~~~~~~~~~~~~~~~~~~

I distinguish two groups of themes: builtin themes and third-party
themes. The builtin themes are those which are part of tcl/tk and are
contained in the tcl code. Third party themes are user written. I was
able to find no documentation, guidance, or even suggestions on
creating themes. It's bedlam out there! Third party themes available
in PAGE are contained in the themes subdirectory of PAGE installation
directory. Any third party themes used by the generated Python code
must be in a themes subdirectory of his project directory.

I have modified the "default" theme in order to support
legacy projects and named the theme "page-legacy". These are projects
that were built with earlier versions of PAGE and work with PAGE
version 7.6. If you open a legacy project PAGE will do what is
necessary to have all widgets use the background and foreground colors
and fonts specified at creation. And if you modify and save the
project it will be saved as a legacy project. Thus, even if you wish
to update a legacy project you are drawn into the world of Themes and
Styles. And you will need to have a "themes" subdirectory in your
project directory containing the "page-legacy" theme for execution of
the generated code. The "page-legacy" is not suitable for use anywhere
other than PAGE and PAGE generated Python GUI's.




PAGE supports some third party themes. We have looked at a number of
third party themes and found most disappointing. We have created
several themes which we will try to support. They are "notsodark",
"page-notsodark", "page-dark", "page-light", "page-wheat", and
"page-legacy". Also, several other third party themes are included but
if problems are encountered with either a theme itself or changes
needed by the way we access it, we will not touch it.

Supported third party themes are stored in a new subdirectory, themes,
of the PAGE installation directory. the themes direcctory contains;

+ tcl theme files, eg. notsodark.tcl, which define a theme.
+ theme support directories, eg. notsodark which contains support
  files, including a bunch of images. Not all themes require such a
  directory.
+ themes.tcl, a file of my creation which causes the themes in this
  directory to be loaded and active.

Of course, PAGE users can include other themes in the same way as the
included themes.

.. It is a requirement for execution of the generated Python modules that any
.. third party themes actually used be included in a "themes"
.. subdirectory of the project directory. If you stick to one of the ttk
.. builtin themes then this subdirectory is not required, However, if
.. you use a third-party theme then you will have to create a "themes"
.. directory in the project directory and populate it with the theme and
.. any related support directories, you are using. Again, third party
.. themes must be in the "themes" subdirectory of the PAGE installation
.. directory for PAGE to use them, and in the "themes" subdirectory of your
.. project for the generate Python modules to access them.
.. 
.. PAGE supports a small number of select third party themes. Since there
.. is almost no documentation or standards for creating ttk themes,
.. several themes were discarded and others required some experimental
.. modification in order to work with PAGE. For that reason, when
.. starting a new project that may use themes, it is recommended that a
.. project directory be creatAdding to the confusion is the facted and
.. that themes subdirectory from the install directory be copied into the
.. new project directory.

Remember that PAGE uses the themes directory in the install directory
for creating the GUI and the Python modules, while execution of the
generated modules relies on the themes directory of the project
directory.

Legacy Projects and Themes
~~~~~~~~~~~~~~~~~~~~~~~~~~


Legacy has multiple meanings in PAGE. One, legacy can refer to
projects created prior to version 8.0.  Legacy can refer to PAGE
functionality available before 8.0 specifically the ability to specify
GUI color preferences. Also, there is the "page-legacy" theme which
attempts to provide some of the legacy functionality. 

The project files in PAGE now include the project theme. When PAGE
opens a project but does not contain theme information, it is assigned
the "page-legacy" theme. This allows the user to bring legacy projects
forward into version 8 and beyond. It also allows the user to use the
borrow function from legacy projects.

When borrowing from a legacy project, you might see some weird color
combinations. If so try changing to a different theme and back.

It is highly recommended that if you are in the legacy theme that you
use only those ttk widgets that have are missing from the tk widget
set. Similarly if you are in one of the other themes use only those tk
themes that are lacking in the ttk set of themes. 



Changing Themes
~~~~~~~~~~~~~~~

It is easy in PAGE to visualize and switch themes. The easiest way to
change themes is by selecting a new theme from the Combobox in the
main PAGE window. Just select the new theme and the GUI will change to
that theme.

One can also use the Theme Chooser from the Button-3 context menu,
from the Main Menu -> Theme Chooser, or by the Control-T shortcut. The
Theme Chooser shows the appearance of most ttk widgets in the current
theme.

In addition, the Preference window allows you to specify a preferred
theme as the theme when PAGE starts.

When a project is saved, the current theme is saved in the .tcl
file. If the theme is then opened, not as a lender, its theme becomes
the current theme.

Toolbutton Style
~~~~~~~~~~~~~~~~

Ttk::button widgets support the Toolbutton style in all standard
themes, which is useful for creating widgets for toolbars.  To use it,
select and place a ttk::button and specify "Toolbutton" as the style
in the Attribute Editor.

This style is available in a consistent implementation for all the
builtin themes. However, this style is implemented in a hit or miss
fashion for third party themes. I think that for both page-notsodark
and page-wheat themes the Toolbutton style is correctly implemented.



One can change the menubar colors and fonts in Linux but not
in Windows or OS X. The reason is that the menubar is drawn using
native widgets that aren't managed by tk or tkinter, so you're limited
to what the platform allows. `For more information
<https://stackoverflow.com/questions/49088785/changing-the-colour-of-tkinter-menubar>`_. Specifying
menu colors via the color preferences in Windows the menubar will be
the Windows colors and font, but the sub element will carry the
specified preferences including the preferred font.