coyim / coyim

coyim - a safe and secure chat client

Home Page:https://coy.im

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use custom CSS classes instead of color assignments

olabiniV2 opened this issue · comments

We are currently setting foreground and background colors in a large amount of places of the code base. But we should move towards a better use of CSS capabilities instead of manually setting colors. As one example, in the roster we currently have one part of the model that keeps track of the background color. The specific line that sets that for a group entry looks like this:

   _ = r.model.SetValue(pi, indexBackgroundColor, r.ui.currentColorSet().rosterGroupBackground.toHex())

So here we are getting the rosterGroupBackground color from the current color set. Now, if we move towards abstract colors, that would probably just return "@roster_group_background" which means the color set will not be used anymore. But this is still managing the colors directly. The mapping for the foreground looks like this in the XML definition for the roster:

              <object class="GtkCellRendererText" id="name-column-rendered"/>
              <attributes>
                <attribute name="text">1</attribute>
                <attribute name="foreground">3</attribute>
                <attribute name="background">4</attribute>
                <attribute name="weight">5</attribute>
              </attributes>
            </child>

Here we can see that index 4 in the model maps to the current background color. It would be much better if we can mark the cell in question with a different CSS class depending on what type it is, and then set the background style information based on that type. For example, if we had a class named "coyim-roster-group", it would be possible to style this. We should map out the different places we can do this, and define all the classes in one place.

After looking in to this for a bit, it's unclear if the different cells in a GTKTreeView can actually be controlled using CSS. It's possible that it's not. In that case, we should try using color references, such as "@theme_base_color" in all places, and then see if things change if we update that definition somewhere else.

For any other places, outside of TreeView, we should still use classes.

We should do #838 before this one.

After much investigation, it turns out that GtkTreeView does not expose any way of actually styling individual cells differently. The exposed classes are "cell" and "view". However, even these do not necessarily help much - because they don't allow you to control everything we want to control in different cells. One useful thing is that it does support the :selected selector, which will be true for the row that is selected:

treeview.view:selected { color: red; background-color: black; }

The roster will be exposed with the ID #roster-view.

In order to solve this problem, I have created a new CellRenderer in the coyim/gotk3extra package. This cell renderer is called CssClassCellRenderer. It has only one property of its own, called css. But it also supports (or will support) the common properties of other cell renderer. The way this works is that the CssClassCellRenderer has an internal real cell renderer which it will dispatch to. So if you set the text property for example, and the real Cell Renderer is a GtkCellRendererText, the CssClassCellRenderer will first apply the css class given in its property to the widget, and then ask the real renderer to actually render the content.

Sadly, this is not necessarily enough, since the text cell renderer doesn't actually use CSS. So the CssClassCellRenderer will also take the font properties and other aspects from the current StyleContext and set it as properties on the underlying cell renderer.

If you want to use it, for example you can do this:

              <object class="CssClassCellRenderer" id="name-column-rendered"/>
              <attributes>
                <attribute name="text">1</attribute>
                <attribute name="css">9</attribute>
              </attributes>

  <object class="GtkCellRendererText" id="roster-real-name-renderer"/>
  cssNameRenderer  gtki.CSSClassCellRenderer `gtk-widget:"name-column-rendered"`
  realNameRenderer gtki.CellRenderer         `gtk-widget:"roster-real-name-renderer"`

and then

	r.cssNameRenderer.SetReal(r.realNameRenderer)

With this, as long as the css field is set to something useful, that will be the class. And this will be specific to the cell.