1
- function mlapp2classdef(pathToMLapp )
1
+ function mlapp2classdef(pathToMLapp , varargin )
2
2
% MLAPP2CLASSDEF converts an App Designer GUI's class definition, packaged
3
3
% as a *.mlapp file, from XML to a standalone *.m class definition.
4
4
%
@@ -9,6 +9,12 @@ function mlapp2classdef(pathToMLapp)
9
9
% pathToMLapp can be a string for a single file or a cell array of strings
10
10
% for multiple files. Filepaths should be absolute.
11
11
%
12
+ % MLAPP2CLASSDEF(..., 'ReplaceAppUI', flag) replaces App Designer UI
13
+ % elements with their "regular" MATLAB equivalents (e.g. App Designer uses
14
+ % UIFIGURE where MATLAB uses FIGURE). flag is a boolean value, the default
15
+ % is false. To prompt the user to select an app file with this syntax, pass
16
+ % an empty first argument (e.g. MLAPP2CLASSDEF([], 'ReplaceAppUI', True)).
17
+ %
12
18
% The class definition for an App Designer GUI is embedded in an XML file
13
19
% located in a subfolder of the packaged *.mlapp file, which can be
14
20
% accessed like a *.zip file. MLAPP2CLASSDEF strips the XML header & footer
@@ -25,13 +31,17 @@ function mlapp2classdef(pathToMLapp)
25
31
end
26
32
27
33
% Choose appropriate behavior based on number of inputs
28
- if nargin == 0
34
+ if nargin == 0 || ~exist( ' pathToMLapp ' , ' var ' ) || isempty( pathToMLapp )
29
35
% No input selected, prompt user to select a MATLAB app to process
30
36
% Currently limited to single file selection
31
- [filename , pathname ] = uigetfile(' *.mlapp' , ' Select MATLAB App' );
37
+ [filename , pathname ] = uigetfile(' *.mlapp' , ' Select MATLAB App' , ' MultiSelect' , ' on' );
38
+ pathToMLapp = fullfile(pathname , filename );
32
39
if ~filename
33
40
error(' mlapp2classdef:NoFileSelected' , ' No file selected, exiting...' );
34
41
else
42
+ % uigetfile's multiselect doesn't currently allow to select files
43
+ % in different directories, so we can inherit the pathname(s) from
44
+ % the uigetfile call.
35
45
[~ , appname , ext ] = fileparts(filename );
36
46
end
37
47
else
@@ -48,63 +58,27 @@ function mlapp2classdef(pathToMLapp)
48
58
filename = strcat(appname , ext );
49
59
end
50
60
61
+ % Check varargin for optional processing flags
62
+ % Placeholder logic to be replaced by inputparser instance
63
+ if isempty(varargin )
64
+ uielementflag = false ;
65
+ else
66
+ uielementflag = false ;
67
+ end
68
+
51
69
if iscell(pathToMLapp )
52
70
for indF = 1 : numel(pathToMLapp )
53
71
checkfile(pathname{indF }, filename{indF }, ext{indF });
54
- processMlapp (pathname{indF }, filename{indF }, appname{indF });
72
+ processapp (pathname{indF }, filename{indF }, appname{indF }, uielementflag )
55
73
% TODO: Add a counter of successfully converted files.
56
74
end
57
75
else
58
76
checkfile(pathname , filename , ext );
59
- processMlapp (pathname , filename , appname );
77
+ processapp (pathname , filename , appname , uielementflag )
60
78
end
61
79
62
80
end
63
81
64
- function processMlapp(pathname , filename , appname )
65
- % Unzip user selected MATLAB App, which are packaged in a renamed zip file
66
- tmpdir = fullfile(pathname , sprintf(' %s _tmp' , appname ));
67
- unzip(fullfile(pathname , filename ), tmpdir );
68
-
69
- % Read in XML file
70
- % Since there isn't really much XML-ness to this XML file, no need to
71
- % utilize a full-fledged parser. MATLAB's won't open it anyway...
72
- xmlfile = fullfile(tmpdir , ' matlab' , ' document.xml' );
73
-
74
- % Get a count of lines in the xml file to preallocate the cell array in
75
- % memory. If no count can be made, revert to growing the array in memory
76
- nlines = countlines(xmlfile );
77
- if ~isempty(nlines )
78
- A = cell(nlines , 1 );
79
- else
80
- A = {};
81
- end
82
-
83
- % Read XML file line-by-line into a cell array to make later export simpler
84
- fID = fopen(xmlfile , ' r' );
85
- ii = 1 ;
86
- while ~feof(fID )
87
- A{ii } = fgetl(fID );
88
- ii = ii + 1 ;
89
- end
90
- fclose(fID );
91
-
92
- % Strip out header & footer, then save to a *.m file
93
- % Limit search to first & last lines of file, currently all that is
94
- % modified by MATLAB to wrap the class definition in XML
95
- A([1 ,end ]) = regexprep(A([1 ,end ]), ' (^.*)\[(?=classdef)|(?<=end)(\].*$)' , ' ' );
96
-
97
- fID = fopen(fullfile(pathname , sprintf(' %s .m' , appname )), ' w' );
98
- for ii = 1 : length(A )
99
- fprintf(fID , ' %s\n ' , A{ii });
100
- end
101
- fclose(fID );
102
-
103
- rmdir(tmpdir , ' s' );
104
-
105
- disp([' Successfully unpacked ' filename ' !' ]);
106
- end
107
-
108
82
109
83
function A = validateattributes_wrapped(A , classes , attributes )
110
84
% Wrap validateattributes with try-catch block for more verbose error
@@ -152,6 +126,74 @@ function checkfile(pathname, filename, ext)
152
126
end
153
127
154
128
129
+ function processapp(pathname , filename , appname , uielementflag )
130
+ tmpdir = unpackapp(pathname , filename , appname );
131
+ rawXML = loadXML(tmpdir );
132
+ mymcode = stripXML(rawXML );
133
+
134
+ if uielementflag
135
+ % Convert App Designer UI elements to "regular" MATLAB UI elements
136
+ end
137
+
138
+ writemfile(mymcode , pathname , appname );
139
+ rmdir(tmpdir , ' s' );
140
+ disp([' Successfully converted ' filename ' !' ]);
141
+ end
142
+
143
+
144
+ function [tmpdir ] = unpackapp(pathname , filename , appname )
145
+ % Unzip user selected MATLAB App, which are packaged in a renamed zip file
146
+ tmpdir = fullfile(pathname , sprintf(' %s _tmp' , appname ));
147
+ unzip(fullfile(pathname , filename ), tmpdir );
148
+ end
149
+
150
+
151
+ function [rawXML ] = loadXML(tmpdir )
152
+ % Read in XML file
153
+ % Since there isn't really much XML-ness to this XML file, no need to
154
+ % utilize a full-fledged parser. MATLAB's won't open it anyway...
155
+ xmlfile = fullfile(tmpdir , ' matlab' , ' document.xml' );
156
+
157
+ % Get a count of lines in the xml file to preallocate the cell array in
158
+ % memory. If no count can be made, revert to growing the array in memory
159
+ nlines = countlines(xmlfile );
160
+ if ~isempty(nlines )
161
+ rawXML = cell(nlines , 1 );
162
+ else
163
+ rawXML = {};
164
+ end
165
+
166
+ % Read XML file line-by-line into a cell array to make later export simpler
167
+ fID = fopen(xmlfile , ' r' );
168
+ ii = 1 ;
169
+ while ~feof(fID )
170
+ rawXML{ii } = fgetl(fID );
171
+ ii = ii + 1 ;
172
+ end
173
+ fclose(fID );
174
+ end
175
+
176
+
177
+ function [mymcode ] = stripXML(rawXML )
178
+ % Strip out XML header & footer
179
+ % Limit search to first & last lines of file, currently all that is
180
+ % modified by MATLAB to wrap the class definition in XML
181
+ mymcode = rawXML ;
182
+ mymcode([1 ,end ]) = regexprep(mymcode([1 ,end ]), ' (^.*)\[(?=classdef)|(?<=end)(\].*$)' , ' ' );
183
+ end
184
+
185
+
186
+ function writemfile(mymcode , pathname , appname )
187
+ % Write a cell array of strings to a *.m file.
188
+ % Assumes each cell is a separate line.
189
+ fID = fopen(fullfile(pathname , sprintf(' %s .m' , appname )), ' w' );
190
+ for ii = 1 : length(mymcode )
191
+ fprintf(fID , ' %s\n ' , mymcode{ii });
192
+ end
193
+ fclose(fID );
194
+ end
195
+
196
+
155
197
function nlines = countlines(filepath )
156
198
% Count the number of lines present in the specified file.
157
199
% filepath should be an absolute path
0 commit comments