=========================================
Proposal for a versatile GTK+ knob widget
=========================================

.. contents::

Introduction
------------

The purpose of the present document is to specify and describe the
features that could be implemented in a new GTK+ rotary control widget,
also called a *knob*.

The goal is to provide a highly reusable widget, which supports a good
set of customization options, so that developers can adapt both its
Rendering_ and Behavior_ to their needs and preferences.

Another goal is to ease integration in a variety of desktop environments,
by trying to support visual user themes.

Eventually, a certain level of accessibility should be provided by
the widget.

Design overview
---------------

First of all, knob is just a nickname here. This widget is actually
a slider, with a circular shape. What this means is that a particular
attention is given to visual feedback: the widget should not only allow
to control a given parameter, but also to represent it graphically,
as any slider do.

The question of the aesthetics is not left aside. Whether the widget
renders as a rather abstract shape, or looks like a pseudo-realistic
potentiometer, could be part of the customization options.

In regard to interaction, there are quite a few possibilities and tastes
around, and the idea is to try and offer support for all of the ones that
we've heard about. There are several aspects here, but they are highly
determined by whether the widget should respond to rotary or to linear
pointer motion. Also, keyboard-based control should be properly supported.

Rendering
---------

Functional aspects
~~~~~~~~~~~~~~~~~~

The rendering has a role to play on the functional side of things,
especially about visual feedback. Here are possible features:

* graphical visualization of the current level/value, with a circular
  slider showing a *full* part and an *empty* part, represented as
  two colors

* customizable *ground*: the so-called ground is the position of the knob
  where it visually looks totally empty. This should be customizable
  so that this ground value can be any of the actual values allowed in
  the range. Most obvious cases are the ground value being equal to the
  lowest value (volume), and to the average value (balance).

* customizable color: having different knobs use different colors can
  be very efficient in certain complex interfaces. Therefore, the color
  representing the *full* part of the slider should be customizable by
  the developer.

* current value as label: the knob should allow to display the
  current value near the actual circular shape. This would be
  customizable: the label would need to be made explicitly visible by
  the developer. Other options would include the choice of the unit
  displayed, and of the position of the label: centered, mostly for
  integers not taking too much space, or under the knob.

* scale as labels: another option would allow to display several points
  of the scale as small labels around the circular shape. The displayed
  points should be fully customizable by the developer, using a step
  parameter, or alternatively a enumeration of values.

Accessibility
~~~~~~~~~~~~~

For visually impaired users, there should be a high contrast between
the *full* and the *empty* colors, and the visual slider should not
be too small/thin.

Aesthetics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

There are several constraints here:

* In the context of music applications, the aesthetic aspect of a widget
  can play an important role. A musician is not necessarily a scientist,
  and so might be sensible to the way the user interface looks and feels
  (and well.. a scientist might too).
  
* On the other side, there are quite a few rules and practices to follow
  to ensure proper integration in user-customized desktop environments.
  Ordered by priority, we believe that the first rule is scaling ability,
  and the second theme adaptability
  
* We have also mentioned that the knob-specific color can play a role in
  regard to `Functional aspects`_. The color and shape should also take
  Accessibility_ into account.

Here follows a proposal which tries to draw a path between these 
constraints:

* the knob should be able to render in two flavours: a rather abstract
  version, and a pseudo-realistic one. This last one would make quite
  an extensive use of gradients. This feature could be generalized 
  with knob *renderers*, to support additional flavours.

* in both flavours the *full* color would be based on the GTK+
  GDK_STATE_SELECTED background color, which often (but not always)
  renders as a high intensity color, such as blue, orange, etc.. Where
  other colors are generally shades of gray. In the pseudo-realistic
  version, this color would be used as a base for computing a gradient.
  
* but the widget should try and detect if this color has a high intensity
  or not. If it detects that it's just another gray, the widget should
  use a hard-coded default color instead
  
* given that the base *full* color has been determined as mentionned
  above, the developer could still configure it by changing its hue,
  understood as in the HSV color model, but not the saturation or
  value. This would allow to:
  
    1. try and stay compatible with the default theme colors,
    2. to specify an absolute hue, such as red, green, in order to respect 
       some convention 
    3. to easily compute color gradients accordingly
  
* apart from the *full* color, the other colors used in the knob should
  be somehow based on the other colors configured in the GTK+ theme.


Behavior
--------

As mentioned above, there are mainly two schools about how the knob
should react to pointer motion.

* linear: the pointer moves up and down, or right and left, which results
  in a rotation of the knob with a fixed precision
  
* rotary: the rotation of the knob is determined by rotary motion. This
  result in a higher precision when the pointer is far from the widget,
  but also cause sudden jumps when the pointer is near the widget,
  which necessarily happens right after mouse-down
  
In our experience, the rotary variant is suited for touch screen 
environments. On small touch screen, the finger moves on the knob 
itself, following its circular shape.

These given, here are possible features:

* The widget should allow the developer to choose one of these two
  interaction variants, and also the orientation (horizontal or vertical)
  in the case of the linear one.
  
* There could also be a global setting, for example in GTK+ rc styles,
  for the user to override the default behavior chosen by the developer.
  
* To support the linear variant in a variety of setups and applications,
  the pointer should be made invisible and centered on the screen while
  moving. This would workaround reaching screen borders, especially for
  those knobs located at one of the edges of the interface.
  
* Quantization: the step parameter in the underlying GtkAdjustment should
  be taken into account

* A keyboard modifier, certainly Ctrl, could allow to enter fine-tuning
  mode in the linear variant.
  
* A double-click on the value label would allow to enter a value manually,
  only if this label is visible, by temporarily replacing the label with
  an input field (in-place editing)

* Interpolation: the knob could be configured for either logarithmic or
  linear variation. However, in our experience, almost every piece of 
  software has a different understanding of how a volume control
  should behave. Therefore, the API should also allow to set an interpolation
  callback. 





