Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the opposite of open to arrow tips definitions #1348

Open
muzimuzhi opened this issue Jul 9, 2024 Discussed in #1347 · 21 comments · May be fixed by #1352
Open

Adding the opposite of open to arrow tips definitions #1348

muzimuzhi opened this issue Jul 9, 2024 Discussed in #1347 · 21 comments · May be fixed by #1352

Comments

@muzimuzhi
Copy link
Member

Discussed in #1347

Originally posted by Rmano July 9, 2024
Good morning!

If I define a new arrow tip that by default is open, like this (which is still somehow buggy, I can't see exactly why)

%% Jack Tap, see
%% https://github.com/circuitikz/circuitikz/issues/806
\pgfdeclarearrow{name=Jack Tap,
    parameters = {%
    \the\pgfarrowlength,%
    \the\pgfarrowwidth,%
    \ifpgfarrowswap s\fi%
    \ifpgfarrowopen o\fi%
    },
    setup code = {
        \pgfarrowssettipend{.5\pgfarrowlength}
        \pgfarrowssetlineend{-.6\pgfarrowlength}
        \pgfarrowssetvisualbackend{-.6\pgfarrowlength}
        \pgfarrowssetbackend{-.6\pgfarrowlength}
        % hull
        \pgfarrowshullpoint{.5\pgfarrowlength}{0pt}
        \pgfarrowshullpoint{0pt}{\pgfarrowwidth}
        \pgfarrowshullpoint{-.6\pgfarrowlength}{0pt}
        % Saves: Only the length:
        \pgfarrowssavethe\pgfarrowlength
        \pgfarrowssavethe\pgfarrowwidth
    },
    drawing code = {
        \pgfpathmoveto{\pgfqpoint{.5\pgfarrowlength}{0pt}}
        \pgfpathlineto{\pgfqpoint{0pt}{\pgfarrowwidth}}
        \pgfpathlineto{\pgfqpoint{-.5\pgfarrowlength}{0pt}}
        \pgfpathlineto{\pgfqpoint{-.6\pgfarrowlength}{0pt}}
        \ifpgfarrowopen
            \pgfusepathqstroke
        \else
            \pgfpathclose\pgfusepathqfillstroke
        \fi
    },
    defaults = {length = 0.3cm, width=0.15cm,open},
    % cache=false, % breaks everything
}
\tikzset{v/.tip={Jack Tap[swap]}, ^/.tip={Jack Tap}}

then I can't switch to the not-open (closed, filled?) version without knowing the color, i.e., using Jack Barb[fill=black]. Wouldn't it be useful to add a "complementary" switch for open, like, for example:

\pgfkeys{/pgf/arrow keys/filled/.code=\pgfarrowsaddtooptions{\pgfarrowopenfalse}}

Or maybe closed, to convey the not-open thing?

I tried to search for a complementary flag without success, but if it's already there, please tell me ;-)

@Rmano
Copy link

Rmano commented Jul 10, 2024

Notice that the code of the arrow has been fixed; you can see it here: https://github.com/circuitikz/circuitikz/pull/810/files

I am not posting it because it really isn't that relevant --- the matter is adding a "not open" flag argument. I am using filled for circuitikz, but I'll happily adapt to what is felt to be better.

@hmenke
Copy link
Member

hmenke commented Jul 10, 2024

I think Jack Tap[fill=.] does what you want.

@Rmano
Copy link

Rmano commented Jul 10, 2024

I think Jack Tap[fill=.] does what you want.

Ah, yes, probably it does. Hmmm... I still like more of a "flag" type, but yes, that's a good solution.

@muzimuzhi
Copy link
Member Author

Nope generally one needs Jack Tap[fill=pgfstrokecolor], in which pgfstrokecolor color name is never mentioned in the pgfmanual. But its corresponding pgffillcolor is mentioned in the doc of /pgf/arrow keys/fill.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

\begin{document}

\pgfkeys{/pgf/arrow keys/filled/.code=\pgfarrowsaddtooptions{\pgfarrowopenfalse}}

\begin{tikzpicture}[nodes={anchor=west}, arrows={[scale=2]}]
  \draw[draw=red, fill=gray, -{Stealth}]
    (0, 0) -- (1, 0) -- (2,.5) node {default};
  \draw[draw=red, fill=gray, yshift=-0.5cm, -{Stealth[cyan]}]
    (0, 0) -- (1, 0) -- (2,.5) node {+ cyan};
  \draw[draw=red, fill=gray, yshift=-1.0cm, -{Stealth[open, cyan]}]
    (0, 0) -- (1, 0) -- (2,.5) node {+ open};
  \draw[draw=red, fill=gray, yshift=-1.5cm, -{Stealth[open, cyan, fill=.]}]
    (0, 0) -- (1, 0) -- (2,.5) node {current color ``.''};
  \draw[draw=red, fill=gray, yshift=-2.0cm, -{Stealth[open, cyan, fill=pgffillcolor]}]
    (0, 0) -- (1, 0) -- (2,.5) node {pgffillcolor};
  \draw[draw=red, fill=gray, yshift=-2.5cm, -{Stealth[open, cyan, fill=pgfstrokecolor]}]
    (0, 0) -- (1, 0) -- (2,.5) node {pgfstrokecolor};
  \draw[draw=red, fill=gray, yshift=-3.0cm, -{Stealth[open, cyan, filled]}]
    (0, 0) -- (1, 0) -- (2,.5) node {filled};
\end{tikzpicture}

\end{document}

image

@Rmano
Copy link

Rmano commented Jul 11, 2024

Well, the behavior is not really the same. Look at this (contrived) example:

\documentclass[]{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

%% Jack Tap, see
%% https://github.com/circuitikz/circuitikz/issues/806
\pgfdeclarearrow{name=Jack Tap,
    parameters = {%
    \the\pgfarrowlength,%
    \the\pgfarrowwidth,%
    \ifpgfarrowswap s\fi%
    \ifpgfarrowopen o\fi%
    \ifpgfarrowroundjoin j\fi
    \ifpgfarrowroundcap c\fi%
    },
    setup code = {
        \pgfarrowssettipend{.5\pgfarrowlength}
        \pgfarrowssetlineend{-.6\pgfarrowlength}
        \pgfarrowssetvisualbackend{-.6\pgfarrowlength}
        \pgfarrowssetbackend{-.6\pgfarrowlength}
        % hull
        \pgfarrowshullpoint{.5\pgfarrowlength}{0pt}
        \pgfarrowshullpoint{0pt}{\pgfarrowwidth}
        \pgfarrowshullpoint{-.6\pgfarrowlength}{0pt}
        % Saves: Only the length:
        \pgfarrowssavethe\pgfarrowlength
        \pgfarrowssavethe\pgfarrowwidth
    },
    drawing code = {
        \pgfsetdash{}{+0pt}
        \pgfarrowlinewidth=\pgflinewidth
        \ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi
        \ifpgfarrowroundcap\pgfsetroundcap\else\pgfsetbuttcap\fi
        \pgfpathmoveto{\pgfqpoint{-.6\pgfarrowlength}{0pt}}
        \pgfpathlineto{\pgfqpoint{-.5\pgfarrowlength}{0pt}}
        \pgfpathlineto{\pgfqpoint{0pt}{\pgfarrowwidth}}
        \pgfpathlineto{\pgfqpoint{.5\pgfarrowlength}{0pt}}
        \ifpgfarrowopen
            \pgfusepathqstroke
        \else
            \pgfpathclose
            \ifdim\pgfarrowlinewidth>0pt\pgfusepathqfillstroke\else\pgfusepathqfill\fi
        \fi
    },
    defaults = {length = 0.3cm, width=0.15cm,open},
    % cache=false, % breaks everything
}
\pgfkeys{/pgf/arrow keys/filled/.code=\pgfarrowsaddtooptions{\pgfarrowopenfalse}}
\tikzset{v/.tip={Jack Tap[swap]}, ^/.tip={Jack Tap},
    vf/.tip={Jack Tap[swap,filled]}, ^f/.tip={Jack Tap[filled]}}

\begin{document}
\begin{tikzpicture}[color=blue]
    \draw[-{Jack Tap}] (0,2) edge ++(2,0) -- ++(0,1);
    \draw[red, -{Jack Tap[filled]}] (0,0) edge ++(2,0) -- ++(0,1);
    \draw[red, -{Jack Tap[fill=.]}] (0,-2) edge ++(2,0) -- ++(0,1);
\end{tikzpicture}
\end{document}

image

@hmenke
Copy link
Member

hmenke commented Jul 11, 2024

I would like to avoid adding new keys. Currently Jack Tap[fill] (without argument) gives an error. We could make that work and make it behave like your proposed filled.

@Rmano
Copy link

Rmano commented Jul 11, 2024

Yes, that would be possible too --- although I think that having on/off for binary switch is also a clean interface.

My feeling would be to let fill as it is and add the possibility for open (and probably, for symmetry, swap) to take a boolean, like open=false (default to true).

@Rmano
Copy link

Rmano commented Jul 15, 2024

...thinking about it a bit more, probably the filled flag would be the easiest to add and document. It's just a sentence in the description of open ;-). I know it's a key more, but it's quite buried in the arrow tip hierarchy...

@hmenke hmenke linked a pull request Jul 15, 2024 that will close this issue
2 tasks
@Rmano
Copy link

Rmano commented Jul 15, 2024

Nice @hmenke, thank you. One little thing: I was trying to provide the fill with no argument for circuitikz now, and I was thinking something like checking for the version of tikz, and then if it's older than 3.1.11 install the code. But (apart from finding how to check the version, which I'll do ;-) later), there is a little problem: is it possible to "undo" the ...fill/.value required?

@muzimuzhi
Copy link
Member Author

@Rmano To undo /.value required, currently one has to make use of implementation details of pgfkeys: \cs_undefine:c {pgfk@/pgf/arrow~keys/fill/.@def} does the trick.

\pgfkeys{/handlers/.value required/.code=\pgfkeyssetvalue{\pgfkeyscurrentpath/.@def}{\pgfkeysvaluerequired}}

Example undoing /.value required

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

\begin{document}
\tikzset{/pgf/arrow keys/fill} % errors

\ExplSyntaxOn
\cs_undefine:c {pgfk@/pgf/arrow~keys/fill/.@def}
\ExplSyntaxOff
\tikzset{/pgf/arrow keys/fill} % passes
\end{document}

@Rmano
Copy link

Rmano commented Jul 15, 2024

Thanks @muzimuzhi ! I had managed to arrive at \pgfkeyssetvalue{/pgf/arrow keys/fill/.@def}{}% --- is that equivalent? It seems to work, and should work also for older formats without expl3...

@Rmano
Copy link

Rmano commented Jul 15, 2024

Also, I think that \expandafter\let\csname pgfk@/pgf/arrow keys/fill/.@def\endcsname\@undefined is doing the same thing as the \cs_undefine:c; am I correct?

@Skillmon
Copy link
Member

Also, I think that \expandafter\let\csname pgfk@/pgf/arrow keys/fill/.@def\endcsname\@undefined is doing the same thing as the \cs_undefine:c; am I correct?

Yes, that's correct.

@muzimuzhi
Copy link
Member Author

@Rmano

I had managed to arrive at \pgfkeyssetvalue{/pgf/arrow keys/fill/.@def}{}% --- is that equivalent?

From the point of view of pgfkeys, \pgfkeyssetvalue{/pgf/arrow keys/fill/.@def}{} is equivalent to setting /pgf/arrow keys/fill/.default={}, hence slightly different than just undoing effect of /.value required. But it might be the right final form, depending on how #1352 will be modified, see my review https://github.com/pgf-tikz/pgf/pull/1352/files#r1678191162.

Possible final form of workaround for tikz v3.1.10 or older

\IfPackageAtLeastTF{tikz}{2023/01/16}{}{% one day after v3.1.10 (2023-01-15)
  \pgfkeys{
    /pgf/arrow keys/fill/.code={...}, % new code in v3.1.11 pasted here
    /pgf/arrow keys/fill/.default={}
  }%
}

@Rmano
Copy link

Rmano commented Jul 15, 2024

@muzimuzhi Thanks - I suppose that the code in your last answer needs LaTeX, am I right? I mean, it would not work in ConTeXt for example...

@muzimuzhi
Copy link
Member Author

@Rmano Yes, \IfPackageAtLeastTF needs LaTeX (sorry). For a portable solution, it seems you have to parse the date or version stored in pgf.revision.tex yourself.

$ cat `kpsewhich pgf.revision.tex`
\def\pgfrevision{3.1.10}
\def\pgfversion{3.1.10}
\def\pgfrevisiondate{2023-01-15}
\def\pgfversiondate{2023-01-15}

@Rmano
Copy link

Rmano commented Jul 16, 2024

Thanks @muzimuzhi. Unfortunately, I found that the format of the date changed between 2021 and 2022 --- it was separated by / before... :-(

@Rmano
Copy link

Rmano commented Jul 16, 2024

Maybe I could just check if /pgf/arrow keys/fill/.@def is defined, and if yes, apply the change. Or surrender and just add the filled key and be done...

@Skillmon
Copy link
Member

Skillmon commented Jul 16, 2024

@Rmano Here is a parser that parses three numbers separated by a single arbitrary non-digit token (or group). It assumes YYYY<sep>MM<sep>dd (optionally followed by another <sep>, <sep> doesn't have to be uniform, it's just gobbled).

\newcount\pdYear
\newcount\pdMonth
\newcount\pdDay
\begingroup
\catcode`\@=11
\unexpanded{\endgroup
% pgfutil replacement code >>>
\let\pgfutil@protected\protected
% <<<

\pgfutil@protected\def\parsedate#1%
  {%
    \afterassignment\parsedate@month
    \pdYear=#1\relax
  }
\pgfutil@protected\def\parsedate@month#1%
  {%
    \afterassignment\parsedate@day
    \pdMonth=%
  }
\pgfutil@protected\def\parsedate@day#1%
  {%
    \afterassignment\parsedate@cleanup
    \pdDay=%
  }
\def\parsedate@cleanup#1\relax{}
}

\def\test#1{\parsedate{#1}\the\pdYear-\the\pdMonth-\the\pdDay\par}

\test{2024-02-01}
\test{2024/02/01}
\test{2024.02.01}
\bye

Keep in mind that you don't have to alter the category code, so don't need the \unexpanded (and if you did, you'd want to use \pgfutil@unexpanded instead for Context support).

@Rmano
Copy link

Rmano commented Jul 17, 2024

@Skillmon thanks again. I was not sure about the \unexpanded thing and grouping there, but it seems that it works ok:

https://github.com/circuitikz/circuitikz/blob/5537c8f2420f43e49fb23887e8d417b96e4313bd/tex/pgfcirc.defines.tex#L269-L319

@Skillmon
Copy link
Member

Skillmon commented Jul 18, 2024

@Rmano Your code looks good. The \begingroup\catcode`\@=11 \unravel{\endgroup...} is just a scoped \makeatletter...\makeatother and not necessary in package code (since your setup for your code level should already deal with @ being a letter).

Rmano added a commit to circuitikz/circuitikz that referenced this issue Jul 19, 2024
Add a new type of arrow to help drawing Jack connectors

Fixes #806 

See also  pgf-tikz/pgf#1352
Thanks to @Skillmon
pgf-tikz/pgf#1348 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants