From 2faf2507ca4d1d6d153f4c2b4c4c78479d459f06 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 15 Jun 2021 03:01:03 +0000 Subject: CTAN sync 202106150301 --- .../l3pdffield-radiobutton.dtx | 835 +++++++++++++++++++++ 1 file changed, 835 insertions(+) create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx (limited to 'macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx') diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx new file mode 100644 index 0000000000..69187ec765 --- /dev/null +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx @@ -0,0 +1,835 @@ +% \iffalse meta-comment +% +%% File: l3pdfpdffield-radiobutton.dtx +% +% Copyright (C) 2021 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> +\RequirePackage{pdfmanagement-testphase} +\DeclareDocumentMetadata{} +\makeatletter +\declare@file@substitution{doc.sty}{doc-v3beta.sty} +\makeatother +\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} +% +% \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.95e, released 2021-06-14} +% +% \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} +% \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 +% default = button4 % default of the group, +% % 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 +% } +% \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| they are selected and +% unselected together, like checkboxes with the same |/Yes| state. This can be used +% to build radio groups which works \enquote{in unison}. 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. +% +% +% \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| = \meta{string} +% \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 first button. If it is missing +% the value of the first button is used as default. +% \meta{string} should be identical to a |value| of one of the buttons of the group. +% This is not checked, buttons can be created on various pages, so it would +% require a label/ref system to keep track of the names. +% \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:nn +% ,\pdf_object_ref:n +% ,\pdf_object_ref_last: +% ,\pdf_object_unnamed_write:nn +% ,\pdf_object_unnamed_write:nx +% ,\pdf_object_write:nx +% ,\pdf_object_write:nn +% ,\pdf_string_from_unicode:nnN +% ,\pdfannot_box_ref_last: +% ,\pdfannot_dict_put:nnn +% ,\pdfannot_dict_put:nnx +% ,\pdfdict_put:nnx +% ,\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_tl +% ,\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 +\tl_new:N \l_@@_radio_default_tl +\int_new:N \l_@@_radio_value_num_int +\tl_new:N \l_@@_radio_appearance_code_tl +% \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} +% 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:nn {@@/field/@@/radio-Opt/#1}{array} + \pdfdict_put:nnx { 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:nx + {@@/field/@@/radio-Opt/#1} + {\seq_use:cn {g_@@_radio_opt_#1_seq}{~}} + } +% \end{macrocode} +% The default value is always the first in the array. +% If a default has been set, it is added to the left +% of the seq. +% \begin{macrocode} + \tl_if_eq:NnF \l_@@_radio_default_tl{()} + { + \seq_gput_left:cV { g_@@_radio_opt_#1_seq }\l_@@_radio_default_tl + } + \pdfdict_put:nnx { l_@@/field }{V} { /0 } + \pdfdict_put:nnx { l_@@/field }{DV} { /0 } +% \end{macrocode} +% now we create the field and set it as parent for the following annotation. +% \begin{macrocode} + \@@_field:n { @@/radio/#1 } + } + \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{} + \keys_set:nn {pdffield} + { + fieldID= + ,name=radio + ,width = \normalbaselineskip + ,height = \normalbaselineskip + ,@@/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 {@@/radio/} + } +% \end{macrocode} +% Now we build the field +% \begin{macrocode} + \@@_radio_field:V\l_@@_fieldID_tl +% \end{macrocode} +% Retrieve the number for the label +% \begin{macrocode} + \seq_if_in:cVF { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }\l_@@_radio_value_tl + { + \seq_gput_right:cV { g_@@_radio_opt_ \l_@@_fieldID_tl _seq }\l_@@_radio_value_tl + } + \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 + } + } +% \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 } = 0 + { \pdfannot_dict_put:nnx {widget}{AS}{/0} } + { \pdfannot_dict_put:nnx {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 {utf8/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 + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{group} +% \begin{macrocode} +\keys_define:nn { pdffield } + { + group .meta:n = {T=#1} + } +% \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:nx + {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:nnx {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 +% +% \end{macrocode} +% \end{macro} +%\end{implementation} +% \PrintIndex -- cgit v1.2.3