% \iffalse meta-comment
%
%% File: l3pdfpdffield-radiobutton.dtx
%
% Copyright (C) 2021-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    http://www.latex-project.org/lppl.txt
%
% This file is part of the "LaTeX PDF management testphase bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/pdfresources
%
% for those people who are interested.
%
%<*driver>
\DocumentMetadata{}
\documentclass[full]{l3doc}
\usepackage{array,booktabs}
\usepackage{l3pdffield-testphase,bearwear,tikzlings,tikzducks}
\hypersetup{pdfauthor=The LaTeX Project,
 pdftitle=l3pdffield (LaTeX PDF management testphase bundle)}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \providecommand\hook[1]{\texttt{#1}}
% \ExplSyntaxOn
% \box_new:N\l_pdffield_bear_box
% \box_new:N\l_pdffield_hippo_box
% \box_new:N\l_pdffield_duck_box
% \hbox_set:Nn \l_pdffield_bear_box  {\tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Yes};}];}
% \hbox_set:Nn \l_pdffield_hippo_box {\vphantom{\tikz\bear;}\tikz\hippo;}
% \hbox_set:Nn \l_pdffield_duck_box  {\vphantom{\tikz\bear;}\tikz\duck;}
%
%
% \pdffield_appearance:nn {pdffield/bear/Yes}
%  {
%    \fbox{\box_use:N \l_pdffield_bear_box}
%  }
% \pdffield_appearance:nn {pdffield/bear/Off}
%  {
%    \fbox{\phantom{\box_use:N \l_pdffield_bear_box}}
%  }
% \pdffield_appearance:nn {pdffield/hippo/Yes}
%  {
%    \fbox{\box_use:N \l_pdffield_hippo_box}
%  }
% \pdffield_appearance:nn {pdffield/hippo/Off}
%  {
%    \fbox{\phantom{\box_use:N \l_pdffield_hippo_box}}
%  }%
% \pdffield_appearance:nn {pdffield/duck/Yes}
%  {
%    \fbox{\box_use:N \l_pdffield_duck_box}
%  }
% \pdffield_appearance:nn {pdffield/duck/Off}
%  {
%    \fbox{\phantom{\box_use:N \l_pdffield_duck_box}}
%  }%
% \ExplSyntaxOff
% \title{^^A
%   The \pkg{l3pdffield-radiobutton} module\\ Commands to create radio form fields   ^^A
%   \\ \LaTeX{} PDF management testphase bundle
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Version 0.96l, released 2024-09-13}
%
% \maketitle
% \begin{documentation}
% \section{\pkg{l3pdffield-radiobutton} Introduction}
% This is the documentation for radio buttons fields, for general information about form fields
% check the documentation l3pdffield.
%
% \begin{center}
%  Choose your favorite
%
%  \medskip
% \ExplSyntaxOn
% \begin{tabular}{ccc}
% \pdffield_radio:n{name=A,value=Bär,default=B,appearance=pdffield/bear,width=\box_wd:N\l_pdffield_bear_box,height=\box_ht:N\l_pdffield_bear_box}&
% \pdffield_radio:n{name=A,value=Sieglinde,appearance=pdffield/hippo,width=\box_wd:N\l_pdffield_hippo_box,height=\box_ht:N\l_pdffield_hippo_box}&
% \pdffield_radio:n{name=A,value=Duck,appearance=pdffield/duck,width=\box_wd:N\l_pdffield_duck_box,height=\box_ht:N\l_pdffield_duck_box}\\[1ex]
% \pdffield_radio:n{name=A,value=Bär}&
% \pdffield_radio:n{name=A,value=Sieglinde}&
% \pdffield_radio:n{name=A,value=Duck}
% \end{tabular}
% \par not in unison: \par
%
% \begin{tabular}{ccc}
% \pdffield_radio:n{inunison=false,name=C,value=Bär,appearance=pdffield/bear,width=\box_wd:N\l_pdffield_bear_box,height=\box_ht:N\l_pdffield_bear_box}&
% \pdffield_radio:n{name=C,value=Sieglinde,default,appearance=pdffield/hippo,width=\box_wd:N\l_pdffield_hippo_box,height=\box_ht:N\l_pdffield_hippo_box}&
% \pdffield_radio:n{name=C,value=Duck,appearance=pdffield/duck,width=\box_wd:N\l_pdffield_duck_box,height=\box_ht:N\l_pdffield_duck_box}\\[1ex]
% \pdffield_radio:n{name=C,value=Bär}&
% \pdffield_radio:n{name=C,value=Sieglinde}&
% \pdffield_radio:n{name=C,value=Duck}
% \end{tabular}
% \ExplSyntaxOff
% \end{center}
%
% Please keep in mind
% \begin{itemize}
% \item Not every PDF viewer supports radio buttons.
% \item The handling can depend on settings in the PDF viewer. In adobe reader for
% example I had to disable an option to avoid that it tries to create an appearance
% itself
% \item Standards like pdf/A disable features of form fields too
% (as you typically can't change the PDF).
% \end{itemize}
% \section{Radio buttons}
% Click me:
% \ExplSyntaxOn
%  ^^A \pdffield_radio:n{name=bear,appearance=pdffield/bear,width=23pt,height=30pt,depth=10pt}
% \ExplSyntaxOff
%
% Radio buttons are similar to checkboxes and
% they have like checkboxes two \enquote{states}:
% checked and unchecked.
%
% The difference is that multiple checkboxes are either \enquote{clones} of each other
% which  are checked and unchecked together,
% or they are independent of each other.
% Radio buttons on the other side build \emph{groups}
% where checking one of the buttons unchecks all other buttons.
% The elements of a such a radio button group are annotations of one field which
% has a flag set which makes it into a radio button group.
%
% In a checkbox field the two states have the
% fix names |/Yes| and |/Off|.
%
% \begin{center}
%  \begin{tikzpicture}[level 2/.style={level distance=7mm},
%  level 1/.style={sibling distance=25mm},
%  level 2/.style={sibling distance=15mm}]
%   \node[draw] {checkbox field}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /Yes\\
%               /Off
%             }}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /Yes\\
%               /Off
%             }}
%   ;
%   \end{tikzpicture}
% \end{center}
%
% In radio buttons
% the off state should still always have the name |/Off|\footnote{%
% the PDF reference doesn't say anything about this, but various tests showed that
% one better should stick to this name, with other names the buttons disappeared.}
% but the on state should be a specific value for every button.
% The field dictionary should then set
% in the |/V| key as the value of one of the button.
% This button is then set as selected and all the other are deselected when the
% PDF is opened or reset.
%
% It is theoretically possible to control the start appearance state for every
% button so e.g. all buttons could have the \enquote{selected} state when the PDF is opened.
% But as soon as one button is clicked
% you get one selected button and the other are unselected. You can't select or
% deselect all buttons. The PDF reference mentions an flag |NoToggleToOff| but this
% doesn't do anything, at least not in the PDF viewers I tried. For this
% reason setting special start states is currently not supported: it complicates the code and the
% input for no real gain.
%
%
% The values of the individual buttons can be coded as annotation state names:
%
% \begin{center}
%    \begin{tikzpicture}[level 2/.style={level distance=7mm},
%  level 1/.style={sibling distance=25mm},
%  level 2/.style={sibling distance=15mm}]
%   \node[draw,align=left,font=\ttfamily] {\textrm{radio button field}\\/V /value1 }
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /value0 \\
%               /Off
%             }}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /value1 \\
%               /Off
%             }}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /value2 \\
%               /Off
%             }}
%   ;
%   \end{tikzpicture}
% \end{center}
%
% But it can be awkward to have to use the values also as names of appearances states, it
% makes it for example difficult to use unicode for the value names, so there is another
% option: One can set up an |/Opt| array which contains the values as strings,
% and used \enquote{named numbers} as appearance state name: The numbers
% |/0|, |/1| point then to the index position in the array.
%
% \begin{center}
%  \begin{tikzpicture}[level 2/.style={level distance=7mm},
%  level 1/.style={sibling distance=25mm},
%  level 2/.style={sibling distance=15mm}]
%   \node[draw,align=left,font=\ttfamily] {\textrm{radio button field}\\
%           /Opt [(value0) (value1) (value2)]
%           /V /0 }
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /0 \\
%               /Off
%             }}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /1 \\
%               /Off
%             }}
%           child {node[draw,dashed,align=left,font=\ttfamily]
%             {\textrm{annotation}\\ /2 \\
%               /Off
%             }}
%   ;
%   \end{tikzpicture}
% \end{center}
%
% This method is clearly more flexible, and so it is used in this module.
%
% As radio buttons build a group of buttons, there is more interaction going on,
% and more values have to be set. Also the first command, which initializes the field,
% has to set the default value of the group.
%
% This means a typical setup should do something like this
%
% \begin{verbatim}
% \pdffield_radio:n
%   {
%     group   = A,         % required, can also be given as name=A or T=A
%     value   = button1,   % required,  on-state of this button
%                          % if not given choice (button1) is used
%                          % should refer to an existing button!
%                          % It will set the V and the DV key
%                          % button4 will be checked
%   }
% \pdffield_radio:n
%   {
%     group   = A,        % required, can also be given as name=A or T=A
%     value   = button2   % required,  export value of this button
%     default             % this button is default of the group,
%   }
% \pdffield_radio:n
%   {
%     group   = A,        % required, can also be given as name=A or T=A
%     value   = button3,  % required,  choice/export value of this button
%   }
% \pdffield_radio:n
%   {
%     group   = A,        % required, can also be given as name=A or T=A
%     value   = button4   % required,  choice/export value of this button
%   }
% \end{verbatim}
%
%
% If two radio field annotations use the same |value| this value can be mapped either
% to the same index or to two different indices in the \texttt{/Opt} array.
% In the first case they are selected and unselected together (\enquote{in unison}),
% like checkboxes with the same |/Yes| state. The key |inunison| below allows to switch
% between the two cases. The flag |RadiosInUnison|
% is neither needed for this (but doesn't harm either) nor
% does it change the behaviour, at least again not in the PDF viewers I tried,
% nevertheless the key will set it accordingly just in case. The two examples at
% the begin of the document show the two variants.
%
%
% The button with the key |default| will be selected at the start (together with the
% buttons with the same value). If no default is set this is the first button.
%
% \bigskip
% \subsection{Commands}
% \begin{function}{\pdffield_radio:n}
% \begin{syntax}
%  \cs{pdffield_radio:n}\Arg{key val list}
% \end{syntax}
% This creates a radio button to check and uncheck.
% The list of allowed keys is described below.
% The \meta{key val list} should at least set the group name,
% without it the default group
% |radio| is used. Radiobuttons with the same
% group name belong to the same field and if checked, the others are unchecked.
% The default appearance
% is a circle frame with a black bullet in it for the checked case.
% The default appearance is setup at the first use. Its geometry is quadratic.
%
% The first radio button setups the field and should also set the button which
% should be shown as selected when the PDF is opened.
% \end{function}
%
%
% \subsection{Keys}
%
% The new radio command accept all field and annot keys from l3pdffield.
% A few keys are disabled or are forced to specific values.
% The |appearance| keys have a more radio specific
% behaviour, other keys have other defaults than with the basic commands.
% Additionally there
% are a small number of keys specific to a radio button.
% |value| and |default| have a special meaning.
%
%
% Disabled keys are
%  \begin{itemize}
%  \item |V|, |DV|, |AS|: they are set by the other keys.
%  \item |FT| is overwritten.
%  \item For radio buttons only the field flags  |ReadOnly|, |Required|, |NoExport|,
%  |NoToggleToOff| and |RadiosInUnison| make sense. The last two are as mentioned
%  above probably useless.
%  |Radio| is set automatically automatically by the code
% as this is required for a radio button set.
%  \end{itemize}
%
%
% \begin{function}{preset-radiobutton}
%  \begin{syntax}
%   |preset-radiobutton| = \Arg{key-val-list}
%  \end{syntax}
% This allows to set default keys for a radio button.
% \end{function}
%
% \begin{function}{group,name,T}
%  \begin{syntax}
%   |group| = \meta{partial name}\\
%   |name| = \meta{partial name}\\
%   |T| = \meta{partial name}
%  \end{syntax}
% These keys set the partial name of the field. They all do the same
% thing, use the one you are more comfortable with. The value
% shouldn't contain a period, be not empty and sensibly consist of simple chars.
% Additionally the value is used to create the field ID.
% This means that radio buttons with the same partial name are annotations
% with the same field as parent and so build a radio button group.
% The field ID is then internal and can not be used to
% attach another annotation.
% For explicit control of the field ID  use the |fieldID| key.
% \end{function}
%
%  \begin{function}{value}
%  \begin{syntax}
%   |value| = \meta{string}
%  \end{syntax}
%  With this key you set the export value name for the individual buttons.
%  Every button should have a value.
%  buttons with the same value are checked in unison. The value can use unicode.
%  \end{function}
%
%  \begin{function}{default}
%  \begin{syntax}
%   |default|
%  \end{syntax}
%  With this key you set the button which is checked when the PDF is opened.
%  The key must be used in the command of the button which should be the default.
%  If it is missing the first button is used as default.
%  A label-ref system is used to get the right numbers, so normally two compilations
%  are needed if the first button is not the default
%  \end{function}
%
%  \begin{function}{inunison}
%  \begin{syntax}
%   |inunison| = |true|\verb+|+|false|
%  \end{syntax}
%  As described above this handle the \enquote{inunison} behaviour.
%  If set to true (the default)
%  buttons with the same value will be selected and unselected together.
%  The keys sets or unsets also the flag |RadiosInUnison| accordingly
%  (but it is unknown  if it has any effect). The key should be set on the first
%  field. Normally it should be unneeded to use the key:
%  to avoid the unison effect it makes more sense to use different values.
%  \end{function}
%
% \begin{function}{fieldID}
%  \begin{syntax}
%   |fieldID| = \meta{field ID}\\
%  \end{syntax}
% \emph{For experts only!}
% This allows to give the radio field a specific ID. This is only useful
% in the context of a larger fieldset or if you want to attach another annotation
% to the field with \cs{pdffield_annot:n}. If used wrongly you can
% easily create invalid fieldset. It allows you to create to fields with the
% same partial name, but if you want to see both
% you need to ensure that their full names are
% different---for example by adding some parent fields.
% \end{function}
%
% \begin{function}{parent}
%  \begin{syntax}
%   |parent| = \meta{field ID}\\
%  \end{syntax}
% This is only needed if the field should be part
% of a larger fieldset. The value should be a field ID of a field created previously
% with \cs{pdffield_field:nn}.
% \end{function}
%
%
% \begin{function}{width,height,depth}
% \begin{syntax}
% |width| = \meta{dim expression}\\
% |height| = \meta{dim expression}\\
% |depth| = \meta{dim expression}
% \end{syntax}
% These keys allow to set the dimensions of radio button.
% The value should be a dimension expression. By default
% |width| and |height| use \cs{normalbaselineskip}, the |depth| is zero.
% \end{function}
%
% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance}
%  \begin{syntax}
%   |AP/N| = \meta{partial appearance name}\\
%   |appearance| = \meta{partial appearance name}\\
%   |AP/R| = \meta{partial appearance name}\\
%   |rollover-appearance| = \meta{partial appearance name}\\
%   |AP/D| = \meta{partial appearance name}\\
%   |down-appearance| = \meta{partial appearance name}
%  \end{syntax}
% This keys sets the normal appearance, the rollover appearance (when the
% mouse hovers over the checkbox) and the down appearance (when the
% mouse clicks). They take as value a
% \meta{partial appearance name} and expects that \emph{two} form Xobjects
% \meta{partial appearance name}|/Yes| and \meta{partial appearance name}|/Off|
% has been created. The initial value is |pdffield/radio/default|
% for the normal appearance and shows a button.
% The down appearance enlarges the middle button a bit to give a visual feed back.
% \end{function}
%
% \subsection{Using with hyperref}
% Radio buttons in hyperref are created with \cs{ChoiceMenu} command, and
% they also print a label. choices are actually a different field type and
% so created with different commands. It is not quite clear yet,
% how this could be mapped.
%
%
% \end{documentation}
%
% \begin{implementation}
% % \DoNotIndex
%  {\\
% ,\bitset_clear:N
% ,\bitset_new:Nn
% ,\bitset_set_false:Nn
% ,\bitset_set_true:Nn
% ,\bitset_to_arabic:N
% ,\bitset_item:Nn
% ,\bool_new:N
% ,\box_dp:N
% ,\box_ht:N
% ,\clist_map_inline:nn
% ,\color_export:nnN
% ,\color_set:nn
% ,\color_set:nnn
% ,\color_select:n
% ,\cs_new_protected:Npn
% ,\cs_new_protected:cpn
% ,\cs_set_eq:NN
% ,\cs_gset_eq:cN
% ,\cs_set_protected:Npn
% ,\cs_generate_variant:Nn
% ,\cs_gset_eq:NN
% ,\c_space_tl
% ,\csname
% ,\dim_eval:n
% ,\dim_new:N
% ,\dim_to_decimal_in_bp:n
% ,\endcsname
% ,\exp_args:Ne
% ,\exp_args:Nc
% ,\fboxsep
% ,\fp_eval:n
% ,\f@size
% ,\group_begin:
% ,\group_end:
% ,\hbox_to_wd:nn
% ,\hfill
% ,\hook_gput_code:nnn
% ,\int_eval:n
% ,\int_compare:nNnT
% ,\int_compare:nNnTF
% ,\int_incr:N
% ,\int_new:N
% ,\int_use:N
% ,\int_zero:N
% ,\l_keys_choice_int
% ,\keys_define:nn
% ,\keys_set:nn
% ,\mode_leave_vertical:
% ,\msg_error:nnn
% ,\msg_error:nnnn
% ,\msg_new:nnn
% ,\msg_warning:nn
% ,\msg_warning:nnn
% ,\msg_warning:nnnnn
% ,\NeedsTeXFormat
% ,\normalsize
% ,\paperheight
% ,\paperwidth
% ,\pdf_name_from_unicode_e:n
% ,\pdf_object_if_exist:nTF
% ,\pdf_object_if_exist:nF
% ,\pdf_object_new:n
% ,\pdf_object_ref:n
% ,\pdf_object_ref_last:
% ,\pdf_object_unnamed_write:nn
% ,\pdf_object_unnamed_write:ne
% ,\pdf_object_write:nne
% ,\pdf_object_write:nnn
% ,\pdf_string_from_unicode:nnN
% ,\pdfannot_box_ref_last:
% ,\pdfannot_dict_put:nnn
% ,\pdfannot_dict_put:nne
% ,\pdfdict_put:nne
% ,\pdfannot_dict_remove:nn
% ,\pdfannot_widget_box:nnn
% ,\pdfdict_if_empty:nTF
% ,\pdfdict_get:nnN
% ,\pdfdict_new:n
% ,\pdfdict_put:nnn
% ,\pdfdict_remove:nn
% ,\pdfdict_use:n
% ,\pdfmanagement_add:nnn
% ,\pdfmeta_standard_verify:nTF
% ,\pdfxform_if_exist:nTF
% ,\pdfxform_new:nnn
% ,\pdfxform_ref:n
% ,\phantom
% ,\prg_do_nothing:
% ,\ProvidesExplPackage
% ,\quark_if_no_value:NT
% ,\raisebox
% ,\RequirePackage
% ,\rule
% ,\seq_gput_right:Nn
% ,\seq_gput_right:cV
% ,\seq_gput_left:cV
% ,\seq_if_in:cVF
% ,\seq_map_break:
% ,\seq_map_inline:Nn
% ,\seq_new:c
% ,\seq_use:cn
% ,\seq_if_exist:NTF
% ,\seq_new:N
% ,\seq_use:Nn
% ,\smash
% ,\str_if_empty:NTF
% ,\str_if_in:NnTF
% ,\str_if_eq:nVTF
% ,\str_new:N
% ,\strut
% ,\strutbox
% ,\tl_put_right:Nn
% ,\tl_if_empty:NTF
% ,\tl_if_empty:NT
% ,\tl_if_empty:NF
% ,\tl_put_left:Nn
% ,\tl_if_eq:NnF
% ,\tl_if_empty:nTF
% ,\tl_if_head_eq_charcode:nNTF
% ,\tl_new:N
% ,\tl_set:Nn
% ,\tl_to_str:n
% ,\use:c
%   }
% \section{\pkg{l3pdffield-radiobutton} Implementation}
%    \begin{macrocode}
%<*package>
%<@@=pdffield>
\RequirePackage{l3draw}
%    \end{macrocode}
% \subsection{Variables}
% \begin{variable}
%  {
%      \l_@@_radio_value_tl
%     ,\l_@@_radio_default_bool
%     ,\l_@@_radio_value_num_int
%     ,\l_@@_radio_appearance_code_tl
%  }
% variables to hold the value, its index numbers and the default value.
% radio buttons can setup the appearance only after the value is known,
% so the code is stored and executed later.
%    \begin{macrocode}
\tl_new:N  \l_@@_radio_value_tl
\bool_new:N  \l_@@_radio_default_bool
\int_new:N \l_@@_radio_value_num_int
\tl_new:N  \l_@@_radio_appearance_code_tl
\bool_new:N \l_@@_radio_unison_bool % if true use same name (e.g. /1) for same value
\bool_set_true:N \l_@@_radio_unison_bool
%    \end{macrocode}
% \end{variable}
%
% \subsection{Appearances}
% The default appearances are a circle with button in it.
% Every appearance should have two versions and follow the naming
% module/\meta{name}/Yes and module/\meta{name}/Off.
%
%  \begin{macro}
%   {
%     \@@_radio_default_appearances:,
%     pdffield/radio/default/Yes,
%     pdffield/radio/default/Off,
%     pdffield/radio/defaultdown/Yes,
%     pdffield/radio/defaultdown/Off
%   }
%  This defines the standard appearances. They are setup at the first
%  use of a radiobutton.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_radio_default_appearances:
  {
    \pdffield_appearance:nn {pdffield/radio/default/Yes}
       {
         \normalsize
         \draw_begin:
         \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
         \draw_path_use_clear:n { stroke }
         \draw_path_circle:nn {0pt,0pt}{0.2\normalbaselineskip}
         \draw_path_use_clear:n { fill }
         \draw_end:
       }
     \pdffield_appearance:nn {pdffield/radio/default/Off}
       {
         \normalsize
         \draw_begin:
         \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
         \draw_path_use_clear:n { stroke }
         \draw_end:
      }

    \pdffield_appearance:nn {pdffield/radio/defaultdown/Yes}
       {
         \normalsize
         \draw_begin:
         \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
         \draw_path_use_clear:n { stroke }
         \draw_path_circle:nn {0pt,0pt}{0.25\normalbaselineskip}
         \draw_path_use_clear:n { fill }
         \draw_end:
       }
     \pdffield_appearance:nn {pdffield/radio/defaultdown/Off}
       {
         \normalsize
         \draw_begin:
         \draw_path_circle:nn {0pt,0pt}{0.5\normalbaselineskip}
         \draw_path_use_clear:n { stroke }
         \draw_path_circle:nn {0pt,0pt}{0.25\normalbaselineskip}
         \draw_path_use_clear:n { fill }
         \draw_end:
      }
    \cs_gset_eq:NN \@@_radio_default_appearances: \prg_do_nothing:
  }
%    \end{macrocode}
% \end{macro}
%
%\subsection{Creating the field}
% We need to retrieve the index of the default through a
% label, so we need an ref attribute or with newer LaTeX
% a property:
%
%    \begin{macrocode}
\cs_if_exist:NTF \property_new:nnnn
 {
   \property_new:nnnn {pdfradioindex}{now}
     {0}
     {
       \int_use:N\l_@@_radio_value_num_int
     }
   \cs_new_eq:NN \@@_property_record:nn \property_record:nn
   \cs_new_eq:NN \@@_property_ref:nn    \property_ref:nn  
 }
 {
   \ref_attribute_gset:nnnn {pdfradioindex}{0}{now}
    {
     \int_use:N\l_@@_radio_value_num_int
    }
   \cs_new_eq:NN \@@_property_record:nn \ref_label:nn
   \cs_new_eq:NN \@@_property_ref:nn    \ref_value:nn  
 } 
 
 \cs_generate_variant:Nn \@@_property_record:nn {V}
 \cs_generate_variant:Nn \@@_property_ref:nn {V}
  
%    \end{macrocode}
% A field should be created if the name doesn't exist yet
%  \begin{macro}{\@@_radio_field:n}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_radio_field:n #1 %name
  {
    \pdf_object_if_exist:nF {@@/field/@@/radio/#1}
      {
%    \end{macrocode}
% We need an object and a seq for the Opt array.
% The object is written at the end of the document.
%    \begin{macrocode}
        \pdf_object_new:n {@@/field/@@/radio-Opt/#1}
        \pdfdict_put:nne { l_@@/field }{Opt} { \pdf_object_ref:n {@@/field/@@/radio-Opt/#1} }
        \seq_new:c { g_@@_radio_opt_#1_seq }
        \hook_gput_code:nnn {shipout/lastpage}{pdffield/radio}
          {
            \pdf_object_write:nne
              {@@/field/@@/radio-Opt/#1} { array }
              {\seq_use:cn {g_@@_radio_opt_#1_seq}{~}}
          }
%    \end{macrocode}
% The default value is retrieved through a label:
%    \begin{macrocode}
        \pdfdict_put:nne { l_@@/field }{V}  { /\@@_property_ref:nn{#1}{pdfradioindex} }
        \pdfdict_put:nne { l_@@/field }{DV} { /\@@_property_ref:nn{#1}{pdfradioindex} }
%    \end{macrocode}
% now we create the field and set it as parent for the following annotation.
%    \begin{macrocode}
        \@@_field:n { @@/radio/#1 }
%    \end{macrocode}
% If the inunison bool has been set to false we need to pass this to the
% kids.
%    \begin{macrocode}
    \bool_if:NF \l_@@_radio_unison_bool
      {
        \cs_new:cpn {g_@@_radio_unison_state_#1_tl}
         {
           \bool_set_false:N \l_@@_radio_unison_bool
         }
      }
      }
    \keys_set:nn {pdffield}{parent=@@/radio/#1}
  }
\cs_generate_variant:Nn \@@_radio_field:n {V}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Assembling the radio}
%
% \begin{macro}{\@@_radio:n}
% The argument are key-val settings.
% At first we map the handlers. To setup the appearance we need the
% Opt array, so the appearance handler only stores the code.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_radio:n #1
  {
    \group_begin:
    \cs_set_eq:NN\@@_appearance_handler:nnn \@@_radio_appearance_handler:nnn
    \cs_set_eq:NN\@@_value_handler:n      \@@_radio_value_handler:n
    \cs_set_eq:NN\@@_default_handler:n    \@@_radio_default_handler:n
%    \end{macrocode}
% Setting up the defaults.
%   \begin{macrocode}
    \tl_set:Nn\l_@@_radio_appearance_code_tl{}
    \bool_set_false:N\l_@@_radio_default_bool
    \keys_set:nn {pdffield}
      {
         fieldID=
        ,name=radio
        ,width  = \normalbaselineskip
        ,height = \normalbaselineskip
        ,inunison
        ,@@/preset/radiobutton
        ,#1
        ,unsetFf={Pushbutton}
        ,setFf={Radio}
        ,FT= Btn
      }
%    \end{macrocode}
% If the fieldID has not been set explicitly, we use the name/T key
%    \begin{macrocode}
   \tl_if_empty:NT\l_@@_fieldID_tl
      {
        \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl
        \tl_put_left:Nn \l_@@_fieldID_tl {@pdffield/radio/}
      }
%    \end{macrocode}
% If unison has been set for the field pass it on:
%    \begin{macrocode}
   \cs_if_exist_use:c {g_@@_radio_unison_state_ \l_@@_fieldID_tl _tl}
%    \end{macrocode}
% Now we build the field
%    \begin{macrocode}
    \@@_radio_field:V\l_@@_fieldID_tl
%    \end{macrocode}
% Put the value into the seq
%    \begin{macrocode}
    \seq_gput_right:cV { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }\l_@@_radio_value_tl
%    \end{macrocode}
%  Retrieve the number for the label
%    \begin{macrocode}
  \bool_if:NTF \l_@@_radio_unison_bool
    {
     \int_zero:N \l_@@_radio_value_num_int
     \exp_args:Nc
     \seq_map_inline:Nn { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }
      {
       \str_if_eq:nVTF { ##1 } \l_@@_radio_value_tl
        {
          \seq_map_break:
        }
        {
          \int_incr:N \l_@@_radio_value_num_int
        }
      }
     }
     {
       \int_set:Nn \l_@@_radio_value_num_int
         {\seq_count:c { g_@@_radio_opt_ \l_@@_fieldID_tl _seq } -1 }
     }
     \bool_if:NT\l_@@_radio_default_bool
      {
        \@@_property_record:Vn\l_@@_fieldID_tl{pdfradioindex}
      }

%    \end{macrocode}
% Annotations with the default value are set to on, the rest to off
%    \begin{macrocode}
   \int_compare:nNnTF { \l_@@_radio_value_num_int } =
       {
         \@@_property_ref:Vn\l_@@_fieldID_tl{pdfradioindex}
       }
     { \pdfannot_dict_put:nne {widget}{AS}{/\@@_property_ref:Vn\l_@@_fieldID_tl{pdfradioindex}} }
     { \pdfannot_dict_put:nne {widget}{AS}{/Off} }
%    \end{macrocode}
% Now we set the appearances, if no key has been use we take the default.
%    \begin{macrocode}
    \tl_if_empty:NT\l_@@_radio_appearance_code_tl
      {
        \@@_radio_default_appearances:
        \keys_set:nn {pdffield}
          {
            appearance      = pdffield/radio/default,
            down-appearance = pdffield/radio/defaultdown,
          }
      }
    \l_@@_radio_appearance_code_tl
    \@@_annot:
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Keys and handlers}
% Most keys are inherited simply the ones from the generic field and annot keys.
% We define a group key, as the name is better.
% The value key sets the export value. default the button which is checked on.
% At first the two handlers
% \begin{macro}{\@@_radio_value_handler:n,\@@_radio_default_handler:n}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_radio_value_handler:n #1
  {
    \pdf_string_from_unicode:nnN {utf16/string}{#1}\l_@@_radio_value_tl
  }
\cs_new_protected:Npn \@@_radio_default_handler:n #1
  {
    %\pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_radio_default_tl
    \bool_set_true:N \l_@@_radio_default_bool
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{group}
%    \begin{macrocode}
\keys_define:nn { pdffield }
 {
    group .meta:n = {T=#1}
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{inunison}
%    \begin{macrocode}
\keys_define:nn { pdffield }
 {
    inunison .choice:
   ,inunison / true .code:n =
     {
       \bool_set_true:N  \l_@@_radio_unison_bool
       \bitset_set_true:Nn \l_@@_Ff_bitset {RadiosInUnison}
     }
   ,inunison / false .code:n =
     {
       \bool_set_false:N  \l_@@_radio_unison_bool
       \bitset_set_false:Nn \l_@@_Ff_bitset {RadiosInUnison}
     }
   ,inunison .default:n = {true}
 }
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_radio_appearance_handler:nnn}
% The handler for the appearances stores only the code
% as it must be executed rather late.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_radio_appearance_handler:nnn #1 #2 #3 %name, type, text
  {
    \tl_put_right:Nn \l_@@_radio_appearance_code_tl
      {
         \pdfxform_if_exist:nTF {  #1 / Yes }
           {
             \pdf_object_unnamed_write:ne
               {dict}
               {
                  /\int_use:N \l_@@_radio_value_num_int
                   \c_space_tl   \pdfxform_ref:n  { #1/Yes}
                  /Off ~ \pdfxform_ref:n { #1/Off}
               }
            \pdfannot_dict_put:nne {widget/AP}{#2}{\pdf_object_ref_last:}
           }
           {
              \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3}
           }
       }
   }

%    \end{macrocode}
%
% \end{macro}
%
% \subsection{User commands}
% \begin{macro}{\pdffield_radio:n}
%    \begin{macrocode}
\cs_set_eq:NN \pdffield_radio:n \@@_radio:n
%</package>
%    \end{macrocode}
% \end{macro}
%\end{implementation}
% \PrintIndex
