# PlayXwordColumn
**Status**: implemented
For better or worse, we cannot get the layout we want with stock GTK
widgets with gtk4. The main problem is that there's no way to have the
grid swindow expand vertically to a maximum size, but no more. As a
result, we need a custom widget to handle the sizing of the grid on
the left. See this diagram for an illustration of this:
![PlayXwordColumn sizing](play-xword-column.png)
_The expansion that requires a custom widget_
This is what the `PlayXwordColumn` widget is for. Note, that despite
the name, it's more than just a column, but contains essentially the
full widgetry for the Crossword playing area.
As we started adding more animations to handle multiple sizes better,
this widget became a lot more complex, and increasingly
specialized. We've made a conscious decision to lose the generality of
gtk containers. Instead, we are focusing on precise control over the
layout and behaviours (and animations).
Here's a sketch as how it is laid out:
![PlayXwordColumn overview](play-xword-column-overview.jpg)
_sketch of `PlayXwordColumn`_
## Sizing
The only size that matters in the `PlayXwordColumn` is the width of
the grid. That (plus any spacing) sets the minimum size of the
game. The `intro`, `notes`, and `clue` labels are all
height-for-width, and are anchored to this width.
Not surprisingly, the majority of the widget code is in the
`::size_allocate` method. Be careful when touching it.
## Animations
We have two animations we run, _primary_ and _secondary_. They are
both triggered by the horizontal sizing. We don't do animations based
on the internal state of the crossword (yet — see below), and we don't
do animations based on any changes in vertical sizing. Events that can
cause these are window resize events, or font / css changes (aka,
zooming, but also system-wide ones).
Both animations are tracked by a float who's value ranges between 0.0
and 1.0:
* `primary_value`
* `secondary_value`
The animation will just queue and allocation, which will update below
as appropriate
### Primary Animation
**Affects:** primary, clue, grid-swindow, notes
* `primary_value` == 0.0: clue is visible; opacity is 1.0
* `primary_value` == 0.0: primary is hidden; opacity is 0.0
* `primary_value` == 0.0: grid-swindow and notes allocation ends below
clue.
* `primary_value` == 1.0: clue is hidden; opacity is 0.0
* `primary_value` == 1.0: primary is visible; opacity is 1.0
* `primary_value` == 1.0: grid-swindow and notes allocation extends
into clue, if necessary
### Secondary Animation
**Affects:** secondary
* `secondary_value` == 0.0: secondary is hidden; opacity is 0.0
* `secondary_value` == 1.0: secondary is visible; opacity is 1.0