-
Notifications
You must be signed in to change notification settings - Fork 315
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1085 from matlab2tikz/develop
Reduce git-flow to github-flow
- Loading branch information
Showing
10 changed files
with
796 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
function [value] = m2tcustom(handle, varargin) | ||
% M2TCUSTOM creates user-defined options for matlab2tikz output | ||
% | ||
% M2TCUSTOM can be used to create, get and set a properly formatted data | ||
% structure to customize the conversion of MATLAB figures to TikZ using | ||
% matlab2tikz. In particular, it allows to: | ||
% | ||
% * add blocks of LaTeX/TikZ code around any HG object, | ||
% * add blocks of comments around any HG object, | ||
% * add TikZ options to any HG object, | ||
% * add LaTeX/TikZ code inside some HG objects (e.g. axes), | ||
% * provide a custom handler to convert a particular HG object. | ||
% | ||
% Note that this provides advanced functionality. Only very basic | ||
% sanity checks are performed such that injudicious use may produce | ||
% broken TikZ figures! | ||
% | ||
% It is HIGHLY recommended that you are comfortable with: | ||
% | ||
% * writing pgfplots, TikZ and LaTeX code, | ||
% * using the Handle Graphics (HG) framework in MATLAB/Octave, and | ||
% * the inner working of matlab2tikz (for custom handlers) | ||
% | ||
% when you use this function. I.e. you should know what you are doing. | ||
% | ||
% | ||
% Usage as a GETTER: | ||
% ------------------ | ||
% | ||
% value = M2TCUSTOM(handle) | ||
% retrieves the current custom data structure from the HG object "handle" | ||
% | ||
% | ||
% Usage as a SETTER: | ||
% ------------------ | ||
% | ||
% M2TCUSTOM(handle, ...) | ||
% value = M2TCUSTOM(handle, ...) | ||
% will construct the proper data structure and try to set it to the object | ||
% |handle| if possible. The arguments (see below) are specified in | ||
% key-value pairs akin to a normal |struct|, but here we do a few checks | ||
% and data normalization. | ||
% | ||
% If we denote BLOCK to mean either a |char| or a |cellstr|, the following | ||
% options can be passed. Different entries in a cellstr are assumed | ||
% separated by a newline. The default values are empty. | ||
% | ||
% M2TCUSTOM(handle, 'commentBefore', BLOCK, ...) | ||
% M2TCUSTOM(handle, 'commentAfter' , BLOCK, ...) | ||
% to add comments before/after the object. Our code translates newlines | ||
% and adds the percentage signs for you. | ||
% | ||
% M2TCUSTOM(handle, 'codeBefore', BLOCK, ...) | ||
% M2TCUSTOM(handle, 'codeAfter', BLOCK, ...) | ||
% M2TCUSTOM(handle, 'codeInsideFirst', BLOCK, ...) | ||
% M2TCUSTOM(handle, 'codeInsideLast', BLOCK, ...) | ||
% to add raw LaTeX/TikZ code respectively before, after, as first thing | ||
% inside or as last thing inside the pgfplots representation of the object. | ||
% Note that for some HG objects, (e.g. line objects), |codeInsideFirst| | ||
% and |codeInsideLast| do not make any sense and are hence ignored. | ||
% | ||
% M2TCUSTOM(handle, 'extraOptions', OPTIONS, ...) | ||
% adds extra pgfplots/TikZ options to the end of the option list. Here, | ||
% OPTIONS is properly formatted TikZ code in | ||
% - a |char| (e.g. 'color=red, line width=1pt' ) | ||
% - a |cellstr| (e.g. {'color=red','line width=1pt'}) | ||
% | ||
% M2TCUSTOM(handle, 'customHandler', FUNCTION_HANDLE, ...) | ||
% allows you to replace the default matlab2tikz handler for this object. | ||
% This is not for the faint of heart and requires intimate knowledge of | ||
% the matlab2tikz code base! We expect a function (either as |char| or | ||
% function handle) that will be called as | ||
% | ||
% [m2t, str] = feval(handler, m2t, handle, custom) | ||
% | ||
% such that the expected function signature is: | ||
% | ||
% function [m2t, str] = handler(m2t, handle, custom) | ||
% | ||
% where |m2t| is an undocumented/unstable data structure, | ||
% |str| is a char containing TikZ code representing the | ||
% HG object |handle| as generated by your handler, | ||
% |custom| is a structure as returned by |m2tcustom| | ||
% from which you only need to handle |extraOptions|, | ||
% |codeInsideFirst| and |codeInsideLast| when applicable. | ||
% A particularly useful value for |customHandler| is 'drawNothing', | ||
% which remove the object from the output. | ||
% | ||
% | ||
% Example: | ||
% -------- | ||
% | ||
% Executing the following MATLAB code fragment: | ||
% | ||
% figure; | ||
% plot(1:10); | ||
% EOL = sprintf('\n'); | ||
% m2tCustom(gca, 'codeBefore' , ['<codeBefore>' EOL] , ... | ||
% 'codeAfter' , ['<codeAfter>' EOL] , ... | ||
% 'commentsBefore' , '<commentsBefore>' , ... | ||
% 'commentsAfter' , '<commentsAfter>' , ... | ||
% 'codeInsideFirst' , ['<codeInsideFirst>' EOL], ... | ||
% 'codeInsideLast' , ['<codeInsideLast>' EOL], ... | ||
% 'extraOptions' , '<extraOptions>'); | ||
% | ||
% matlab2tikz('test.tikz') | ||
% | ||
% Should result in a |test.tikz| file with contents that look somewhat | ||
% like this: | ||
% | ||
% \begin{tikzpicture} | ||
% %<commentsBefore> | ||
% <codeBefore> | ||
% \begin{axis}[..., <extraOptions>] | ||
% <codeInsideFirst> | ||
% \addplot{...}; | ||
% <codeInsideLast> | ||
% \end{axis} | ||
% %<commentsAfter> | ||
% <codeAfter> | ||
% \end{tikzpicture} | ||
% | ||
% See also: matlab2tikz, setappdata, getappdata | ||
|
||
%% arguments specific to this constructor function | ||
ipp = m2tInputParser(); | ||
ipp = ipp.addRequired(ipp, 'handle', @isHgObject); | ||
|
||
%% Declaration of the custom data structure | ||
ipp = ipp.addParamValue(ipp, 'codeBefore', '', @isCellstrOrChar); | ||
ipp = ipp.addParamValue(ipp, 'codeAfter', '', @isCellstrOrChar); | ||
|
||
ipp = ipp.addParamValue(ipp, 'commentsBefore', '', @isCellstrOrChar); | ||
ipp = ipp.addParamValue(ipp, 'commentsAfter', '', @isCellstrOrChar); | ||
|
||
ipp = ipp.addParamValue(ipp, 'codeInsideFirst', '', @isCellstrOrChar); | ||
ipp = ipp.addParamValue(ipp, 'codeInsideLast', '', @isCellstrOrChar); | ||
|
||
ipp = ipp.addParamValue(ipp, 'extraOptions', '', @isCellstrOrChar); | ||
ipp = ipp.addParamValue(ipp, 'customHandler', '', @isHandler); | ||
|
||
%% Parse the arguments | ||
ipp = ipp.parse(ipp, handle, varargin{:}); | ||
|
||
%% Construct custom data structure | ||
% We leverage the results from the input parser. It provides us | ||
% with validation already. We just need to remove bookkeeping fields | ||
value = ipp.Results; | ||
value = rmfield(value, {'handle'}); | ||
|
||
%% Normalize the actual values | ||
value.codeBefore = cellstr2char(value.codeBefore); | ||
value.codeAfter = cellstr2char(value.codeAfter); | ||
value.codeInsideFirst = cellstr2char(value.codeInsideFirst); | ||
value.codeInsideLast = cellstr2char(value.codeInsideLast); | ||
value.commentsBefore = cellstr2char(value.commentsBefore); | ||
value.commentsAfter = cellstr2char(value.commentsAfter); | ||
if isempty(value.customHandler) | ||
value = rmfield(value, 'customHandler'); | ||
end | ||
% extraOptions gets normalized by |opts_append_userdefined| | ||
|
||
%% Different Usage modes | ||
MATLAB2TIKZ = 'matlab2tikz'; % key used for application data storage | ||
if numel(varargin) == 0 | ||
%% GETTER MODE | ||
% syntax: value = m2tcustom(h); | ||
if ~isempty(handle) | ||
object = getappdata(handle, MATLAB2TIKZ); | ||
else | ||
object = []; | ||
end | ||
if ~isempty(object) | ||
value = object; | ||
else | ||
% |value| contains all default (empty) values | ||
end | ||
else | ||
%% SETTER MODE | ||
% syntax: m2tcustom(h , key1, val1, ...) | ||
% syntax: value = m2tcustom([], key1, val1, ...) | ||
if ~isempty(handle) | ||
setappdata(handle, MATLAB2TIKZ, value); | ||
end | ||
end | ||
end | ||
% == INPUT VALIDATORS ========================================================== | ||
function bool = isHgObject(value) | ||
% true for HG object or empty (or numeric for backwards compatibility) | ||
bool = isempty(value) || ishghandle(value) || isnumeric(value); | ||
end | ||
function bool = isCellstrOrChar(value) | ||
% true for cellstr or char | ||
bool = ischar(value) || iscellstr(value); | ||
end | ||
function bool = isHandler(value) | ||
% true for char or function handle of the form [m2t, str] = f(m2t, h, opts) | ||
bool = isempty(value) || ischar(value) || ... | ||
(isa(value, 'function_handle') && ... | ||
atLeastOrUnknown(nargin(value), 3) && ... | ||
atLeastOrUnknown(nargout(value), 2)); | ||
end | ||
function bool = atLeastOrUnknown(nargs, limit) | ||
% checks for |nargin| and |nargout| >= |limit| (or equal to -1) | ||
UNKNOWN = -1; | ||
bool = (nargs == UNKNOWN) || nargs >= limit; | ||
end | ||
% == FIELD NORMALIZATION ======================================================= | ||
function value = cellstr2char(value) | ||
% convert cellstr to char (and keep char unaffected) | ||
if iscellstr(value) | ||
EOL = sprintf('\n'); | ||
value = m2tstrjoin(value, EOL); | ||
end | ||
end | ||
% ============================================================================== |
Oops, something went wrong.