# 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