├── .gitignore ├── COPYING.LGPL.txt ├── COPYING.modifiedLGPL.txt ├── README.md ├── languages ├── res2goresources.po ├── res2goresources.pot └── res2goresources.zh_CN.po ├── res2gomain.pas ├── res2gooptions.lfm ├── res2gooptions.pas ├── res2goplugin.lpk ├── res2goplugin.pas ├── res2goresources.pas ├── ugolang.pas ├── ulangbase.pas └── usupports.pas /.gitignore: -------------------------------------------------------------------------------- 1 | /lib 2 | /backup 3 | -------------------------------------------------------------------------------- /COPYING.LGPL.txt: -------------------------------------------------------------------------------- 1 | GNU LIBRARY GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the library GPL. It is 10 | numbered 2 because it goes with version 2 of the ordinary GPL.] 11 | 12 | Preamble 13 | 14 | The licenses for most software are designed to take away your 15 | freedom to share and change it. By contrast, the GNU General Public 16 | Licenses are intended to guarantee your freedom to share and change 17 | free software--to make sure the software is free for all its users. 18 | 19 | This license, the Library General Public License, applies to some 20 | specially designated Free Software Foundation software, and to any 21 | other libraries whose authors decide to use it. You can use it for 22 | your libraries, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | this service if you wish), that you receive source code or can get it 28 | if you want it, that you can change the software or use pieces of it 29 | in new free programs; and that you know you can do these things. 30 | 31 | To protect your rights, we need to make restrictions that forbid 32 | anyone to deny you these rights or to ask you to surrender the rights. 33 | These restrictions translate to certain responsibilities for you if 34 | you distribute copies of the library, or if you modify it. 35 | 36 | For example, if you distribute copies of the library, whether gratis 37 | or for a fee, you must give the recipients all the rights that we gave 38 | you. You must make sure that they, too, receive or can get the source 39 | code. If you link a program with the library, you must provide 40 | complete object files to the recipients so that they can relink them 41 | with the library, after making changes to the library and recompiling 42 | it. And you must show them these terms so they know their rights. 43 | 44 | Our method of protecting your rights has two steps: (1) copyright 45 | the library, and (2) offer you this license which gives you legal 46 | permission to copy, distribute and/or modify the library. 47 | 48 | Also, for each distributor's protection, we want to make certain 49 | that everyone understands that there is no warranty for this free 50 | library. If the library is modified by someone else and passed on, we 51 | want its recipients to know that what they have is not the original 52 | version, so that any problems introduced by others will not reflect on 53 | the original authors' reputations. 54 | 55 | Finally, any free program is threatened constantly by software 56 | patents. We wish to avoid the danger that companies distributing free 57 | software will individually obtain patent licenses, thus in effect 58 | transforming the program into proprietary software. To prevent this, 59 | we have made it clear that any patent must be licensed for everyone's 60 | free use or not licensed at all. 61 | 62 | Most GNU software, including some libraries, is covered by the ordinary 63 | GNU General Public License, which was designed for utility programs. This 64 | license, the GNU Library General Public License, applies to certain 65 | designated libraries. This license is quite different from the ordinary 66 | one; be sure to read it in full, and don't assume that anything in it is 67 | the same as in the ordinary license. 68 | 69 | The reason we have a separate public license for some libraries is that 70 | they blur the distinction we usually make between modifying or adding to a 71 | program and simply using it. Linking a program with a library, without 72 | changing the library, is in some sense simply using the library, and is 73 | analogous to running a utility program or application program. However, in 74 | a textual and legal sense, the linked executable is a combined work, a 75 | derivative of the original library, and the ordinary General Public License 76 | treats it as such. 77 | 78 | Because of this blurred distinction, using the ordinary General 79 | Public License for libraries did not effectively promote software 80 | sharing, because most developers did not use the libraries. We 81 | concluded that weaker conditions might promote sharing better. 82 | 83 | However, unrestricted linking of non-free programs would deprive the 84 | users of those programs of all benefit from the free status of the 85 | libraries themselves. This Library General Public License is intended to 86 | permit developers of non-free programs to use free libraries, while 87 | preserving your freedom as a user of such programs to change the free 88 | libraries that are incorporated in them. (We have not seen how to achieve 89 | this as regards changes in header files, but we have achieved it as regards 90 | changes in the actual functions of the Library.) The hope is that this 91 | will lead to faster development of free libraries. 92 | 93 | The precise terms and conditions for copying, distribution and 94 | modification follow. Pay close attention to the difference between a 95 | "work based on the library" and a "work that uses the library". The 96 | former contains code derived from the library, while the latter only 97 | works together with the library. 98 | 99 | Note that it is possible for a library to be covered by the ordinary 100 | General Public License rather than by this special one. 101 | 102 | GNU LIBRARY GENERAL PUBLIC LICENSE 103 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 104 | 105 | 0. This License Agreement applies to any software library which 106 | contains a notice placed by the copyright holder or other authorized 107 | party saying it may be distributed under the terms of this Library 108 | General Public License (also called "this License"). Each licensee is 109 | addressed as "you". 110 | 111 | A "library" means a collection of software functions and/or data 112 | prepared so as to be conveniently linked with application programs 113 | (which use some of those functions and data) to form executables. 114 | 115 | The "Library", below, refers to any such software library or work 116 | which has been distributed under these terms. A "work based on the 117 | Library" means either the Library or any derivative work under 118 | copyright law: that is to say, a work containing the Library or a 119 | portion of it, either verbatim or with modifications and/or translated 120 | straightforwardly into another language. (Hereinafter, translation is 121 | included without limitation in the term "modification".) 122 | 123 | "Source code" for a work means the preferred form of the work for 124 | making modifications to it. For a library, complete source code means 125 | all the source code for all modules it contains, plus any associated 126 | interface definition files, plus the scripts used to control compilation 127 | and installation of the library. 128 | 129 | Activities other than copying, distribution and modification are not 130 | covered by this License; they are outside its scope. The act of 131 | running a program using the Library is not restricted, and output from 132 | such a program is covered only if its contents constitute a work based 133 | on the Library (independent of the use of the Library in a tool for 134 | writing it). Whether that is true depends on what the Library does 135 | and what the program that uses the Library does. 136 | 137 | 1. You may copy and distribute verbatim copies of the Library's 138 | complete source code as you receive it, in any medium, provided that 139 | you conspicuously and appropriately publish on each copy an 140 | appropriate copyright notice and disclaimer of warranty; keep intact 141 | all the notices that refer to this License and to the absence of any 142 | warranty; and distribute a copy of this License along with the 143 | Library. 144 | 145 | You may charge a fee for the physical act of transferring a copy, 146 | and you may at your option offer warranty protection in exchange for a 147 | fee. 148 | 149 | 2. You may modify your copy or copies of the Library or any portion 150 | of it, thus forming a work based on the Library, and copy and 151 | distribute such modifications or work under the terms of Section 1 152 | above, provided that you also meet all of these conditions: 153 | 154 | a) The modified work must itself be a software library. 155 | 156 | b) You must cause the files modified to carry prominent notices 157 | stating that you changed the files and the date of any change. 158 | 159 | c) You must cause the whole of the work to be licensed at no 160 | charge to all third parties under the terms of this License. 161 | 162 | d) If a facility in the modified Library refers to a function or a 163 | table of data to be supplied by an application program that uses 164 | the facility, other than as an argument passed when the facility 165 | is invoked, then you must make a good faith effort to ensure that, 166 | in the event an application does not supply such function or 167 | table, the facility still operates, and performs whatever part of 168 | its purpose remains meaningful. 169 | 170 | (For example, a function in a library to compute square roots has 171 | a purpose that is entirely well-defined independent of the 172 | application. Therefore, Subsection 2d requires that any 173 | application-supplied function or table used by this function must 174 | be optional: if the application does not supply it, the square 175 | root function must still compute square roots.) 176 | 177 | These requirements apply to the modified work as a whole. If 178 | identifiable sections of that work are not derived from the Library, 179 | and can be reasonably considered independent and separate works in 180 | themselves, then this License, and its terms, do not apply to those 181 | sections when you distribute them as separate works. But when you 182 | distribute the same sections as part of a whole which is a work based 183 | on the Library, the distribution of the whole must be on the terms of 184 | this License, whose permissions for other licensees extend to the 185 | entire whole, and thus to each and every part regardless of who wrote 186 | it. 187 | 188 | Thus, it is not the intent of this section to claim rights or contest 189 | your rights to work written entirely by you; rather, the intent is to 190 | exercise the right to control the distribution of derivative or 191 | collective works based on the Library. 192 | 193 | In addition, mere aggregation of another work not based on the Library 194 | with the Library (or with a work based on the Library) on a volume of 195 | a storage or distribution medium does not bring the other work under 196 | the scope of this License. 197 | 198 | 3. You may opt to apply the terms of the ordinary GNU General Public 199 | License instead of this License to a given copy of the Library. To do 200 | this, you must alter all the notices that refer to this License, so 201 | that they refer to the ordinary GNU General Public License, version 2, 202 | instead of to this License. (If a newer version than version 2 of the 203 | ordinary GNU General Public License has appeared, then you can specify 204 | that version instead if you wish.) Do not make any other change in 205 | these notices. 206 | 207 | Once this change is made in a given copy, it is irreversible for 208 | that copy, so the ordinary GNU General Public License applies to all 209 | subsequent copies and derivative works made from that copy. 210 | 211 | This option is useful when you wish to copy part of the code of 212 | the Library into a program that is not a library. 213 | 214 | 4. You may copy and distribute the Library (or a portion or 215 | derivative of it, under Section 2) in object code or executable form 216 | under the terms of Sections 1 and 2 above provided that you accompany 217 | it with the complete corresponding machine-readable source code, which 218 | must be distributed under the terms of Sections 1 and 2 above on a 219 | medium customarily used for software interchange. 220 | 221 | If distribution of object code is made by offering access to copy 222 | from a designated place, then offering equivalent access to copy the 223 | source code from the same place satisfies the requirement to 224 | distribute the source code, even though third parties are not 225 | compelled to copy the source along with the object code. 226 | 227 | 5. A program that contains no derivative of any portion of the 228 | Library, but is designed to work with the Library by being compiled or 229 | linked with it, is called a "work that uses the Library". Such a 230 | work, in isolation, is not a derivative work of the Library, and 231 | therefore falls outside the scope of this License. 232 | 233 | However, linking a "work that uses the Library" with the Library 234 | creates an executable that is a derivative of the Library (because it 235 | contains portions of the Library), rather than a "work that uses the 236 | library". The executable is therefore covered by this License. 237 | Section 6 states terms for distribution of such executables. 238 | 239 | When a "work that uses the Library" uses material from a header file 240 | that is part of the Library, the object code for the work may be a 241 | derivative work of the Library even though the source code is not. 242 | Whether this is true is especially significant if the work can be 243 | linked without the Library, or if the work is itself a library. The 244 | threshold for this to be true is not precisely defined by law. 245 | 246 | If such an object file uses only numerical parameters, data 247 | structure layouts and accessors, and small macros and small inline 248 | functions (ten lines or less in length), then the use of the object 249 | file is unrestricted, regardless of whether it is legally a derivative 250 | work. (Executables containing this object code plus portions of the 251 | Library will still fall under Section 6.) 252 | 253 | Otherwise, if the work is a derivative of the Library, you may 254 | distribute the object code for the work under the terms of Section 6. 255 | Any executables containing that work also fall under Section 6, 256 | whether or not they are linked directly with the Library itself. 257 | 258 | 6. As an exception to the Sections above, you may also compile or 259 | link a "work that uses the Library" with the Library to produce a 260 | work containing portions of the Library, and distribute that work 261 | under terms of your choice, provided that the terms permit 262 | modification of the work for the customer's own use and reverse 263 | engineering for debugging such modifications. 264 | 265 | You must give prominent notice with each copy of the work that the 266 | Library is used in it and that the Library and its use are covered by 267 | this License. You must supply a copy of this License. If the work 268 | during execution displays copyright notices, you must include the 269 | copyright notice for the Library among them, as well as a reference 270 | directing the user to the copy of this License. Also, you must do one 271 | of these things: 272 | 273 | a) Accompany the work with the complete corresponding 274 | machine-readable source code for the Library including whatever 275 | changes were used in the work (which must be distributed under 276 | Sections 1 and 2 above); and, if the work is an executable linked 277 | with the Library, with the complete machine-readable "work that 278 | uses the Library", as object code and/or source code, so that the 279 | user can modify the Library and then relink to produce a modified 280 | executable containing the modified Library. (It is understood 281 | that the user who changes the contents of definitions files in the 282 | Library will not necessarily be able to recompile the application 283 | to use the modified definitions.) 284 | 285 | b) Accompany the work with a written offer, valid for at 286 | least three years, to give the same user the materials 287 | specified in Subsection 6a, above, for a charge no more 288 | than the cost of performing this distribution. 289 | 290 | c) If distribution of the work is made by offering access to copy 291 | from a designated place, offer equivalent access to copy the above 292 | specified materials from the same place. 293 | 294 | d) Verify that the user has already received a copy of these 295 | materials or that you have already sent this user a copy. 296 | 297 | For an executable, the required form of the "work that uses the 298 | Library" must include any data and utility programs needed for 299 | reproducing the executable from it. However, as a special exception, 300 | the source code distributed need not include anything that is normally 301 | distributed (in either source or binary form) with the major 302 | components (compiler, kernel, and so on) of the operating system on 303 | which the executable runs, unless that component itself accompanies 304 | the executable. 305 | 306 | It may happen that this requirement contradicts the license 307 | restrictions of other proprietary libraries that do not normally 308 | accompany the operating system. Such a contradiction means you cannot 309 | use both them and the Library together in an executable that you 310 | distribute. 311 | 312 | 7. You may place library facilities that are a work based on the 313 | Library side-by-side in a single library together with other library 314 | facilities not covered by this License, and distribute such a combined 315 | library, provided that the separate distribution of the work based on 316 | the Library and of the other library facilities is otherwise 317 | permitted, and provided that you do these two things: 318 | 319 | a) Accompany the combined library with a copy of the same work 320 | based on the Library, uncombined with any other library 321 | facilities. This must be distributed under the terms of the 322 | Sections above. 323 | 324 | b) Give prominent notice with the combined library of the fact 325 | that part of it is a work based on the Library, and explaining 326 | where to find the accompanying uncombined form of the same work. 327 | 328 | 8. You may not copy, modify, sublicense, link with, or distribute 329 | the Library except as expressly provided under this License. Any 330 | attempt otherwise to copy, modify, sublicense, link with, or 331 | distribute the Library is void, and will automatically terminate your 332 | rights under this License. However, parties who have received copies, 333 | or rights, from you under this License will not have their licenses 334 | terminated so long as such parties remain in full compliance. 335 | 336 | 9. You are not required to accept this License, since you have not 337 | signed it. However, nothing else grants you permission to modify or 338 | distribute the Library or its derivative works. These actions are 339 | prohibited by law if you do not accept this License. Therefore, by 340 | modifying or distributing the Library (or any work based on the 341 | Library), you indicate your acceptance of this License to do so, and 342 | all its terms and conditions for copying, distributing or modifying 343 | the Library or works based on it. 344 | 345 | 10. Each time you redistribute the Library (or any work based on the 346 | Library), the recipient automatically receives a license from the 347 | original licensor to copy, distribute, link with or modify the Library 348 | subject to these terms and conditions. You may not impose any further 349 | restrictions on the recipients' exercise of the rights granted herein. 350 | You are not responsible for enforcing compliance by third parties to 351 | this License. 352 | 353 | 11. If, as a consequence of a court judgment or allegation of patent 354 | infringement or for any other reason (not limited to patent issues), 355 | conditions are imposed on you (whether by court order, agreement or 356 | otherwise) that contradict the conditions of this License, they do not 357 | excuse you from the conditions of this License. If you cannot 358 | distribute so as to satisfy simultaneously your obligations under this 359 | License and any other pertinent obligations, then as a consequence you 360 | may not distribute the Library at all. For example, if a patent 361 | license would not permit royalty-free redistribution of the Library by 362 | all those who receive copies directly or indirectly through you, then 363 | the only way you could satisfy both it and this License would be to 364 | refrain entirely from distribution of the Library. 365 | 366 | If any portion of this section is held invalid or unenforceable under any 367 | particular circumstance, the balance of the section is intended to apply, 368 | and the section as a whole is intended to apply in other circumstances. 369 | 370 | It is not the purpose of this section to induce you to infringe any 371 | patents or other property right claims or to contest validity of any 372 | such claims; this section has the sole purpose of protecting the 373 | integrity of the free software distribution system which is 374 | implemented by public license practices. Many people have made 375 | generous contributions to the wide range of software distributed 376 | through that system in reliance on consistent application of that 377 | system; it is up to the author/donor to decide if he or she is willing 378 | to distribute software through any other system and a licensee cannot 379 | impose that choice. 380 | 381 | This section is intended to make thoroughly clear what is believed to 382 | be a consequence of the rest of this License. 383 | 384 | 12. If the distribution and/or use of the Library is restricted in 385 | certain countries either by patents or by copyrighted interfaces, the 386 | original copyright holder who places the Library under this License may add 387 | an explicit geographical distribution limitation excluding those countries, 388 | so that distribution is permitted only in or among countries not thus 389 | excluded. In such case, this License incorporates the limitation as if 390 | written in the body of this License. 391 | 392 | 13. The Free Software Foundation may publish revised and/or new 393 | versions of the Library General Public License from time to time. 394 | Such new versions will be similar in spirit to the present version, 395 | but may differ in detail to address new problems or concerns. 396 | 397 | Each version is given a distinguishing version number. If the Library 398 | specifies a version number of this License which applies to it and 399 | "any later version", you have the option of following the terms and 400 | conditions either of that version or of any later version published by 401 | the Free Software Foundation. If the Library does not specify a 402 | license version number, you may choose any version ever published by 403 | the Free Software Foundation. 404 | 405 | 14. If you wish to incorporate parts of the Library into other free 406 | programs whose distribution conditions are incompatible with these, 407 | write to the author to ask for permission. For software which is 408 | copyrighted by the Free Software Foundation, write to the Free 409 | Software Foundation; we sometimes make exceptions for this. Our 410 | decision will be guided by the two goals of preserving the free status 411 | of all derivatives of our free software and of promoting the sharing 412 | and reuse of software generally. 413 | 414 | NO WARRANTY 415 | 416 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 417 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 418 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 419 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 420 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 421 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 422 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 423 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 424 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 425 | 426 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 427 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 428 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 429 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 430 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 431 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 432 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 433 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 434 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 435 | DAMAGES. 436 | 437 | END OF TERMS AND CONDITIONS 438 | 439 | How to Apply These Terms to Your New Libraries 440 | 441 | If you develop a new library, and you want it to be of the greatest 442 | possible use to the public, we recommend making it free software that 443 | everyone can redistribute and change. You can do so by permitting 444 | redistribution under these terms (or, alternatively, under the terms of the 445 | ordinary General Public License). 446 | 447 | To apply these terms, attach the following notices to the library. It is 448 | safest to attach them to the start of each source file to most effectively 449 | convey the exclusion of warranty; and each file should have at least the 450 | "copyright" line and a pointer to where the full notice is found. 451 | 452 | 453 | Copyright (C) 454 | 455 | This library is free software; you can redistribute it and/or 456 | modify it under the terms of the GNU Library General Public 457 | License as published by the Free Software Foundation; either 458 | version 2 of the License, or (at your option) any later version. 459 | 460 | This library is distributed in the hope that it will be useful, 461 | but WITHOUT ANY WARRANTY; without even the implied warranty of 462 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 463 | Library General Public License for more details. 464 | 465 | You should have received a copy of the GNU Library General Public 466 | License along with this library; if not, write to the Free 467 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 468 | 469 | Also add information on how to contact you by electronic and paper mail. 470 | 471 | You should also get your employer (if you work as a programmer) or your 472 | school, if any, to sign a "copyright disclaimer" for the library, if 473 | necessary. Here is a sample; alter the names: 474 | 475 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 476 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 477 | 478 | , 1 April 1990 479 | Ty Coon, President of Vice 480 | 481 | That's all there is to it! 482 | -------------------------------------------------------------------------------- /COPYING.modifiedLGPL.txt: -------------------------------------------------------------------------------- 1 | This is the file COPYING.modifiedLGPL, it applies to several units in the 2 | Lazarus sources distributed by members of the Lazarus Development Team. 3 | All files contains headers showing the appropriate license. See there if this 4 | modification can be applied. 5 | 6 | These files are distributed under the Library GNU General Public License 7 | (see the file COPYING.LGPL) with the following modification: 8 | 9 | As a special exception, the copyright holders of this library give you 10 | permission to link this library with independent modules to produce an 11 | executable, regardless of the license terms of these independent modules, 12 | and to copy and distribute the resulting executable under terms of your choice, 13 | provided that you also meet, for each linked independent module, the terms 14 | and conditions of the license of that module. An independent module is a 15 | module which is not derived from or based on this library. If you modify this 16 | library, you may extend this exception to your version of the library, but 17 | you are not obligated to do so. If you do not wish to do so, delete this 18 | exception statement from your version. 19 | 20 | 21 | If you didn't receive a copy of the file COPYING.LGPL, contact: 22 | Free Software Foundation, Inc., 23 | 675 Mass Ave 24 | Cambridge, MA 02139 25 | USA 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 图文说明:https://gitee.com/ying32/govcl/wikis/pages?sort_id=2645001&doc_id=102420 2 | 3 | #### v1.0.13 4 | 5 | * 1、修改:非Windows下强制使用CGO选项。 6 | * 2、增加:可自定义`GoPATH`变量路径。 7 | 8 | #### v1.0.12 9 | 10 | * 1、修改:非Windows下不再转换资源,因为没有windres这个东西。 11 | * 2、修复:非Windows下编译不成功。 12 | * 3、修复:非Windows下默认启用CGO选项。 13 | 14 | #### v1.0.11 15 | 16 | * 1、修复保存设置时会弹出错误问题。 17 | * 2、增加:如在GoPath中创建工程,如果包名不为main则导入以GoPath为路径的包名,反之导入相对包名。 18 | 19 | #### v1.0.10 20 | 21 | * 1、修复`Go Tags`在某些情况下会丢失。 22 | * 2、res2go选项中增加`Go Build mode`选择。 23 | 24 | #### v1.0.9 25 | 26 | * 1、优化解析lpr文件,不再直接读取lpr文件。 27 | * 2、增加:`Project -> Project Options ... -> Compiler Options -> Debugging -> Generate info for the debugger`对应go ldflags `-w`。调试符信息成控制。 28 | * 3、增加:`Project -> Project Options ... -> Compiler Options -> Debugging -> Other debugging info -> Strip symbols form executable`对应go ldflags `-s`。控制移除符号信息。 29 | * 4、增加:res2go选中增加`Enabled CGO`选项。 30 | 31 | #### v1.0.8 32 | 33 | * 1、增加`tempdll`约束选项,Windows与Linux下开启后可将liblcl打包到可执行文件中。 34 | * 2、增加`finalizerOn`约束选项,开启后非组件类可不调用`Free`方法。 35 | * 3、增加设置`tags`约束选项。 36 | 37 | #### v1.0.7 38 | 39 | * 1、增加Lazarus IDE中直接设置应用程序标题"Application.SetTitle"。 40 | * 2、增加"使用默认winappres"包选项。 41 | * 3、如果设置中"PackageName"指定了其它包名,如果main.go中未导入,则导入相对路径的包名。 42 | * 4、拦截Lazarus的编译功能,更改为go的编译行为。 43 | * 5、工程选项中`Compiler Options -> Config and Target -> Win32 gui application (-WG)`可控制去除命令行窗口。 44 | * 6、`Project -> Run Parameters -> Command line parameters`可控制运行时传入的命令行。 45 | * 7、工程选项中`Compiler Options -> Paths -> Target file name(-o)`可控制生成的可执行文件名。 46 | * 8、工程选项中`Compiler Options -> Config and Target -> Target platform`可以控制`GOOS`(Target OS)和`GOARCH`(Target CPU family)变量。 47 | 48 | #### v1.0.6 49 | 50 | * 1、默认使用fpc中自带的windres,如果未找到则使用`PATH`中的windres。 51 | * 2、执行windres出错则输出错误提示。 52 | * 3、修复未启用转换也会转换res文件。 53 | 54 | #### v1.0.5 55 | 56 | * 1、OutPath支持相对路径、绝对路径、Lazarus IDE宏。 57 | * 2、修复main.go文件创建时没有添加"vcl.Application.SetMainFormOnTaskBar(true)"语句。 58 | * 3、main.go中添加"vcl.Application.SetScaled"语句,其值取自工程选项中"Use LCL scaling(Hi-DPI)"。 59 | * 4、支持自定义go的包名(需要自己在main.go中添加包的导入)。 60 | 61 | #### v1.0.4 62 | 63 | * 1、增加利用Lazarus IDE完成Windows可执行文件的图标、Manifest、版本信息修改。 64 | * 2、main.go不再添加"winappres"包。 65 | 66 | #### v1.0.3 67 | 68 | * 1、增加保存“gfm”文件选项,默认不保存。 69 | * 2、预留输出"Rust", "Nim"语言选项(未开始编写代码)。 70 | 71 | #### v1.0.2 72 | 73 | * 1、重构全部的转换功能,不再读取lfm文件进行转换了,事件上利用RTTI转换参数。 74 | * 2、增加“使用原始单元”选中功能。 75 | 76 | #### v1.0.1 77 | 78 | * 1、修复打开工程时不加载配置问题。 -------------------------------------------------------------------------------- /languages/res2goresources.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | #: res2goresources.rsautomaticallygeneratedbytheres2go 5 | msgid "Automatically generated by the res2go IDE plug-in." 6 | msgstr "" 7 | 8 | #: res2goresources.rsautomaticallygeneratedbytheres2godonotedit 9 | msgid "Automatically generated by the res2go IDE plug-in, do not edit." 10 | msgstr "" 11 | 12 | #: res2goresources.rsbuildmode 13 | msgid "Build mode: " 14 | msgstr "" 15 | 16 | #: res2goresources.rsbuildmodehint 17 | msgid "If go version>=1.15, please select \"exe\" mode, otherwise, no need to select." 18 | msgstr "" 19 | 20 | #: res2goresources.rscomponentisnotsupported 21 | msgid "\"%s:%s\" is not supported." 22 | msgstr "" 23 | 24 | #: res2goresources.rscomponentmustbecapitalizedfirsttobeexported 25 | msgid "\"%s:%s\" must be capitalized first to be exported." 26 | msgstr "" 27 | 28 | #: res2goresources.rsdividerbevel1 29 | msgid "For Golang" 30 | msgstr "" 31 | 32 | #: res2goresources.rsenabledconvert 33 | msgid "Enabled Convert" 34 | msgstr "" 35 | 36 | #: res2goresources.rsgoenabledcgo 37 | msgid "Enabled CGO" 38 | msgstr "" 39 | 40 | #: res2goresources.rsgoenabledembed 41 | msgid "Use \"go:embed\"(go1.16+)" 42 | msgstr "" 43 | 44 | #: res2goresources.rsgoenabledfinalizeron 45 | msgid "Enabled \"finalizerOn\"" 46 | msgstr "" 47 | 48 | #: res2goresources.rsgoenabledfinalizeronhint 49 | msgid "After opening the non-component class can not call the \"Free\" method" 50 | msgstr "" 51 | 52 | #: res2goresources.rsgotags 53 | msgid "Tags:" 54 | msgstr "" 55 | 56 | #: res2goresources.rsgousetempdll 57 | msgid "Use \"tempdll\"" 58 | msgstr "" 59 | 60 | #: res2goresources.rsgousetempdllhint 61 | msgid "Package liblcl into an executable file (macOS is not supported)" 62 | msgstr "" 63 | 64 | #: res2goresources.rsmsgtransformfile 65 | msgid "Transform file: %s " 66 | msgstr "" 67 | 68 | #: res2goresources.rsoutputlang 69 | msgid "Output Lang:" 70 | msgstr "" 71 | 72 | #: res2goresources.rsoutputpath 73 | msgid "Output Path:" 74 | msgstr "" 75 | 76 | #: res2goresources.rsoutputpatheg 77 | msgid "eg: \"code\" or \"$Path($ProjectFile())code\" or \"C:\\LzUI\" " 78 | msgstr "" 79 | 80 | #: res2goresources.rspackagename 81 | msgid "Package Name:" 82 | msgstr "" 83 | 84 | #: res2goresources.rsregisterformresources 85 | msgid "Register Form Resources" 86 | msgstr "" 87 | 88 | #: res2goresources.rssavegfmfile 89 | msgid "Save gfm File" 90 | msgstr "" 91 | 92 | #: res2goresources.rsusedefaultwinappres 93 | msgid "Use Default winappres" 94 | msgstr "" 95 | 96 | #: res2goresources.rsuseoriginalfilename 97 | msgid "Use Original File Name" 98 | msgstr "" 99 | 100 | -------------------------------------------------------------------------------- /languages/res2goresources.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | #: res2goresources.rsautomaticallygeneratedbytheres2go 5 | msgid "Automatically generated by the res2go IDE plug-in." 6 | msgstr "" 7 | 8 | #: res2goresources.rsautomaticallygeneratedbytheres2godonotedit 9 | msgid "Automatically generated by the res2go IDE plug-in, do not edit." 10 | msgstr "" 11 | 12 | #: res2goresources.rsbuildmode 13 | msgid "Build mode: " 14 | msgstr "" 15 | 16 | #: res2goresources.rsbuildmodehint 17 | msgid "If go version>=1.15, please select \"exe\" mode, otherwise, no need to select." 18 | msgstr "" 19 | 20 | #: res2goresources.rscomponentisnotsupported 21 | #, object-pascal-format 22 | msgid "\"%s:%s\" is not supported." 23 | msgstr "" 24 | 25 | #: res2goresources.rscomponentmustbecapitalizedfirsttobeexported 26 | #, object-pascal-format 27 | msgid "\"%s:%s\" must be capitalized first to be exported." 28 | msgstr "" 29 | 30 | #: res2goresources.rsdividerbevel1 31 | msgid "For Golang" 32 | msgstr "" 33 | 34 | #: res2goresources.rsenabledconvert 35 | msgid "Enabled Convert" 36 | msgstr "" 37 | 38 | #: res2goresources.rsgoenabledcgo 39 | msgid "Enabled CGO" 40 | msgstr "" 41 | 42 | #: res2goresources.rsgoenabledembed 43 | msgid "Use \"go:embed\"(go1.16+)" 44 | msgstr "" 45 | 46 | #: res2goresources.rsgoenabledfinalizeron 47 | msgid "Enabled \"finalizerOn\"" 48 | msgstr "" 49 | 50 | #: res2goresources.rsgoenabledfinalizeronhint 51 | msgid "After opening the non-component class can not call the \"Free\" method" 52 | msgstr "" 53 | 54 | #: res2goresources.rsgotags 55 | msgid "Tags:" 56 | msgstr "" 57 | 58 | #: res2goresources.rsgousetempdll 59 | msgid "Use \"tempdll\"" 60 | msgstr "" 61 | 62 | #: res2goresources.rsgousetempdllhint 63 | msgid "Package liblcl into an executable file (macOS is not supported)" 64 | msgstr "" 65 | 66 | #: res2goresources.rsmsgtransformfile 67 | #, object-pascal-format 68 | msgid "Transform file: %s " 69 | msgstr "" 70 | 71 | #: res2goresources.rsoutputlang 72 | msgid "Output Lang:" 73 | msgstr "" 74 | 75 | #: res2goresources.rsoutputpath 76 | msgid "Output Path:" 77 | msgstr "" 78 | 79 | #: res2goresources.rsoutputpatheg 80 | msgid "eg: \"code\" or \"$Path($ProjectFile())code\" or \"C:\\LzUI\" " 81 | msgstr "" 82 | 83 | #: res2goresources.rspackagename 84 | msgid "Package Name:" 85 | msgstr "" 86 | 87 | #: res2goresources.rsregisterformresources 88 | msgid "Register Form Resources" 89 | msgstr "" 90 | 91 | #: res2goresources.rssavegfmfile 92 | msgid "Save gfm File" 93 | msgstr "" 94 | 95 | #: res2goresources.rsusedefaultwinappres 96 | msgid "Use Default winappres" 97 | msgstr "" 98 | 99 | #: res2goresources.rsuseoriginalfilename 100 | msgid "Use Original File Name" 101 | msgstr "" 102 | 103 | -------------------------------------------------------------------------------- /languages/res2goresources.zh_CN.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=UTF-8" 3 | 4 | #: res2goresources.rsautomaticallygeneratedbytheres2go 5 | msgid "Automatically generated by the res2go IDE plug-in." 6 | msgstr "由res2go IDE插件自动生成。" 7 | 8 | #: res2goresources.rsautomaticallygeneratedbytheres2godonotedit 9 | msgid "Automatically generated by the res2go IDE plug-in, do not edit." 10 | msgstr "由res2go IDE插件自动生成,不要编辑。" 11 | 12 | #: res2goresources.rsbuildmode 13 | msgid "Build mode: " 14 | msgstr "" 15 | 16 | #: res2goresources.rsbuildmodehint 17 | msgid "If go version>=1.15, please select \"exe\" mode, otherwise, no need to select." 18 | msgstr "如果go版本>=1.15请选择\"exe\"模式,反之无需选择。" 19 | 20 | #: res2goresources.rscomponentisnotsupported 21 | #, object-pascal-format 22 | msgid "\"%s:%s\" is not supported." 23 | msgstr "“%s:%s”不被支持。" 24 | 25 | #: res2goresources.rscomponentmustbecapitalizedfirsttobeexported 26 | #, object-pascal-format 27 | msgid "\"%s:%s\" must be capitalized first to be exported." 28 | msgstr "“%s:%s”必须首字母大写才能被导出。" 29 | 30 | #: res2goresources.rsdividerbevel1 31 | msgid "For Golang" 32 | msgstr "Golang选项" 33 | 34 | #: res2goresources.rsenabledconvert 35 | msgid "Enabled Convert" 36 | msgstr "启用转换" 37 | 38 | #: res2goresources.rsgoenabledcgo 39 | msgid "Enabled CGO" 40 | msgstr "启用CGO" 41 | 42 | #: res2goresources.rsgoenabledembed 43 | msgid "Use \"go:embed\"(go1.16+)" 44 | msgstr "使用\"go:embed\"(go1.16+)" 45 | 46 | #: res2goresources.rsgoenabledfinalizeron 47 | msgid "Enabled \"finalizerOn\"" 48 | msgstr "启用 \"finalizerOn\"约束" 49 | 50 | #: res2goresources.rsgoenabledfinalizeronhint 51 | msgid "After opening the non-component class can not call the \"Free\" method" 52 | msgstr "开启后非组件类可以不用调用“Free”方法" 53 | 54 | #: res2goresources.rsgotags 55 | msgid "Tags:" 56 | msgstr "" 57 | 58 | #: res2goresources.rsgousetempdll 59 | msgid "Use \"tempdll\"" 60 | msgstr "使用 \"tempdll\"约束" 61 | 62 | #: res2goresources.rsgousetempdllhint 63 | msgid "Package liblcl into an executable file (macOS is not supported)" 64 | msgstr "将liblcl打包到可执行文件中(不支持macOS)" 65 | 66 | #: res2goresources.rsmsgtransformfile 67 | #, object-pascal-format 68 | msgid "Transform file: %s " 69 | msgstr "转换文件:%s" 70 | 71 | #: res2goresources.rsoutputlang 72 | msgid "Output Lang:" 73 | msgstr "输出语言:" 74 | 75 | #: res2goresources.rsoutputpath 76 | msgid "Output Path:" 77 | msgstr "输出路径:" 78 | 79 | #: res2goresources.rsoutputpatheg 80 | msgid "eg: \"code\" or \"$Path($ProjectFile())code\" or \"C:\\LzUI\" " 81 | msgstr "示例:\"code\" 或 \"$Path($ProjectFile())code\" 或 \"C:\\LzUI\" " 82 | 83 | #: res2goresources.rspackagename 84 | msgid "Package Name:" 85 | msgstr "包名:" 86 | 87 | #: res2goresources.rsregisterformresources 88 | msgid "Register Form Resources" 89 | msgstr "注册Form资源 " 90 | 91 | #: res2goresources.rssavegfmfile 92 | msgid "Save gfm File" 93 | msgstr "保存gfm文件" 94 | 95 | #: res2goresources.rsusedefaultwinappres 96 | msgid "Use Default winappres" 97 | msgstr "使用默认的winappres" 98 | 99 | #: res2goresources.rsuseoriginalfilename 100 | msgid "Use Original File Name" 101 | msgstr "使用原始文件名" 102 | 103 | -------------------------------------------------------------------------------- /res2gomain.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | 9 | {$if FPC_FULLVERSION < 30200} 10 | {$ERROR 'Requires FPC version>=3.2'} 11 | {$endif} 12 | 13 | unit res2gomain; 14 | 15 | {$mode objfpc}{$H+} 16 | 17 | interface 18 | 19 | uses 20 | Classes, 21 | SysUtils, 22 | LCLType, 23 | UITypes, 24 | StdCtrls, 25 | Buttons, 26 | Forms, 27 | TypInfo, 28 | LazIDEIntf, 29 | ProjectIntf, 30 | IDEMsgIntf, 31 | IDEExternToolIntf, 32 | IDEOptEditorIntf, 33 | FormEditingIntf, 34 | CompOptsIntf, 35 | usupports, 36 | res2goresources, 37 | uLangBase, 38 | LResources, 39 | LazFileUtils, 40 | MacroIntf; 41 | 42 | type 43 | 44 | 45 | { TMyIDEIntf } 46 | 47 | TMyIDEIntf = class 48 | private const 49 | EXT_GFM = '.gfm'; 50 | EXT_RES = '.res'; 51 | private 52 | FEvents: array of TEventItem; 53 | 54 | FEnabledConvert: Boolean; 55 | FGoBuildMode: string; 56 | FGoEnabledCGO: Boolean; 57 | FGoEnabledFinalizerOn: Boolean; 58 | FGoRoot: string; 59 | FGoTags: string; 60 | FGoUseEmbed: Boolean; 61 | FGoUseTempdll: Boolean; 62 | FOutLang: TOutLang; 63 | FOutputPath: string; 64 | FPackageName: string; 65 | FReConvertRes: Boolean; 66 | FSaveGfmFile: Boolean; 67 | FUseDefaultWinAppRes: Boolean; 68 | FUseOriginalFileName: Boolean; 69 | 70 | FAddToLast: Boolean; 71 | FModalResult: TModalResult; 72 | FWithoutDebug: Boolean; 73 | 74 | 75 | function GetDefaultProjectParam: TProjParam; 76 | function GetLang: TLangBase; 77 | 78 | function GetProjectTitle: string; 79 | function GetRealOutputPackagePath: string; 80 | function GetRealOutputPath: string; 81 | function GetResFileName: string; 82 | function GetTargetDir: string; 83 | function GetTargetFile: string; 84 | function GetUseScaled: Boolean; 85 | 86 | procedure SaveComponents(ADesigner: TIDesigner; AUnitFileName, AOutPath: string); 87 | procedure OnWriteMethodProperty(Writer: TWriter; Instance: TPersistent; PropInfo: PPropInfo; 88 | const MethodValue, DefMethodValue: TMethod; var Handled: boolean); 89 | 90 | procedure CheckAndCreateDir; 91 | 92 | 93 | function GetProjectPath: string; 94 | 95 | procedure SetEnabledConvert(AValue: Boolean); 96 | procedure SetPackageName(AValue: string); 97 | public 98 | constructor Create; 99 | destructor Destroy; override; 100 | function onSaveAll(Sender: TObject): TModalResult; 101 | function onSaveEditorFile(Sender: TObject; aFile: TLazProjectFile; SaveStep: TSaveEditorFileStep; TargetFilename: string): TModalResult; 102 | function onProjectOpened(Sender: TObject; AProject: TLazProject): TModalResult; 103 | 104 | function onProjectBuilding(Sender: TObject): TModalResult; 105 | procedure onProjectBuildingFinished(Sender: TObject; BuildSuccessful: Boolean); 106 | function onProjectDependenciesCompiling(Sender: TObject): TModalResult; 107 | function onProjectDependenciesCompiled(Sender: TObject): TModalResult; 108 | function onLazarusBuilding(Sender: TObject): TModalResult; 109 | procedure onLazarusBuildingFinished(Sender: TObject; BuildSuccessful: Boolean); 110 | function onRunDebug(Sender: TObject; var Handled: boolean): TModalResult; 111 | function onRunWithoutDebugBuilding(Sender: TObject; var Handled: boolean): TModalResult; 112 | function onRunWithoutDebugInit(Sender: TObject; var Handled: boolean): TModalResult; 113 | procedure onRunFinished(Sender: TObject); 114 | procedure onChangeToolStatus(Sender: TObject; OldStatus, NewStatus: TLazToolStatus); 115 | 116 | 117 | 118 | class procedure AddHandlers; 119 | class procedure RemoveHandlers; 120 | 121 | property EnabledConvert: Boolean read FEnabledConvert write SetEnabledConvert; 122 | property OutputPath: string read FOutputPath write FOutputPath; 123 | property UseOriginalFileName: Boolean read FUseOriginalFileName write FUseOriginalFileName; 124 | property SaveGfmFile: Boolean read FSaveGfmFile write FSaveGfmFile; 125 | property OutLang: TOutLang read FOutLang write FOutLang; 126 | property PackageName: string read FPackageName write SetPackageName; 127 | property UseScaled: Boolean read GetUseScaled; 128 | property ProjectTitle: string read GetProjectTitle; 129 | property UseDefaultWinAppRes: Boolean read FUseDefaultWinAppRes write FUseDefaultWinAppRes; 130 | 131 | property GoUseTempdll: Boolean read FGoUseTempdll write FGoUseTempdll; 132 | property GoEnabledFinalizerOn: Boolean read FGoEnabledFinalizerOn write FGoEnabledFinalizerOn; 133 | property GoTags: string read FGoTags write FGoTags; 134 | property GoEnabledCGO: Boolean read FGoEnabledCGO write FGoEnabledCGO; 135 | property GoBuildMode: string read FGoBuildMode write FGoBuildMode; 136 | property GoRoot: string read FGoRoot write FGoRoot; 137 | property GoUseEmbed: Boolean read FGoUseEmbed write FGoUseEmbed; 138 | 139 | 140 | property DefaultProjectParam: TProjParam read GetDefaultProjectParam; 141 | 142 | 143 | property Lang: TLangBase read GetLang; 144 | 145 | property ProjectPath: string read GetProjectPath; 146 | property RealOutputPath: string read GetRealOutputPath; 147 | property RealOutputPackagePath: string read GetRealOutputPackagePath; 148 | 149 | property TargetFile: string read GetTargetFile; 150 | property TargetDir: string read GetTargetDir; 151 | 152 | 153 | 154 | property ReConvertRes: Boolean read FReConvertRes write FReConvertRes; 155 | property ResFileName: string read GetResFileName; 156 | end; 157 | 158 | // JITForms.pas 159 | TFakeJITMethod = class 160 | private 161 | FMethod: TMethod; 162 | FOwner: TObject;//TJITMethods; 163 | FTheClass: TClass; 164 | FTheMethodName: shortstring; 165 | public 166 | property TheMethodName: shortstring read FTheMethodName; 167 | end; 168 | 169 | 170 | var 171 | MyIDEIntf: TMyIDEIntf; 172 | 173 | procedure Register; 174 | 175 | implementation 176 | 177 | uses 178 | ugolang; 179 | 180 | 181 | procedure Register; 182 | begin 183 | //Logs('MyIDEIntf.Register'); 184 | end; 185 | 186 | procedure Init; 187 | begin 188 | MyIDEIntf := TMyIDEIntf.Create; 189 | end; 190 | 191 | procedure UnInit; 192 | begin 193 | TMyIDEIntf.RemoveHandlers; 194 | MyIDEIntf.Free; 195 | MyIDEIntf := nil; 196 | end; 197 | 198 | 199 | { TMyIDEIntf } 200 | 201 | procedure TMyIDEIntf.SaveComponents(ADesigner: TIDesigner; AUnitFileName, 202 | AOutPath: string); 203 | var 204 | LWriter: TWriter; 205 | LDestroyDriver: Boolean; 206 | LStream: TMemoryStream; 207 | LGfmFileName, LOutFileName: string; 208 | begin 209 | if Assigned(ADesigner) and Assigned(ADesigner.LookupRoot) then 210 | begin 211 | LStream := TMemoryStream.Create; 212 | try 213 | LDestroyDriver := False; 214 | LWriter := nil; 215 | try 216 | // 清空事件 217 | SetLength(FEvents, 0); 218 | LWriter := CreateLRSWriter(LStream, LDestroyDriver); 219 | LWriter.OnWriteMethodProperty := @OnWriteMethodProperty; 220 | LWriter.WriteDescendent(ADesigner.LookupRoot, nil); 221 | finally 222 | if LDestroyDriver then 223 | LWriter.Driver.Free; 224 | LWriter.Free; 225 | end; 226 | // 保存go文件及impl文件 227 | LOutFileName := AOutPath; 228 | if Self.UseOriginalFileName then 229 | LOutFileName += AUnitFileName 230 | else 231 | LOutFileName += ADesigner.LookupRoot.Name; 232 | 233 | // 234 | if OutLang = olGo then 235 | TGoLang(Lang).UseGoEmbed:= GoUseEmbed; 236 | 237 | // 保存文件 238 | Lang.SaveToFile(LOutFileName, ADesigner.LookupRoot, FEvents, LStream); 239 | 240 | // 保存gfm文件,条件为勾选启用保存Gfm文件或者使用go:embed特性 241 | if Self.SaveGfmFile or ((OutLang = olGo) and GoUseEmbed) then 242 | begin 243 | LGfmFileName := AppendPathDelim(AppendPathDelim(AOutPath) + 'resources'); 244 | if not SysUtils.DirectoryExists(LGfmFileName) then 245 | SysUtils.CreateDir(LGfmFileName); 246 | 247 | if Self.UseOriginalFileName then 248 | LGfmFileName += AUnitFileName 249 | else 250 | LGfmFileName += ADesigner.LookupRoot.Name; 251 | 252 | LGfmFileName += EXT_GFM; 253 | LStream.Position := 0; 254 | LStream.SaveToFile(LGfmFileName); 255 | end; 256 | finally 257 | LStream.Free; 258 | end; 259 | end; 260 | end; 261 | 262 | function TMyIDEIntf.GetRealOutputPath: string; 263 | begin 264 | Result := OutputPath; 265 | if Assigned(IDEMacros) then 266 | begin 267 | IDEMacros.SubstituteMacros(Result); 268 | if not FileNameIsAbsolute(Result) then 269 | Result := ProjectPath + Result; 270 | end else 271 | begin 272 | if not FileNameIsAbsolute(Result) then 273 | Result := ProjectPath + OutputPath; 274 | end; 275 | Result := AppendPathDelim(Result); 276 | end; 277 | 278 | function TMyIDEIntf.GetResFileName: string; 279 | begin 280 | Result := ChangeFileExt(LazarusIDE.ActiveProject.ProjectInfoFile, EXT_RES); 281 | end; 282 | 283 | function TMyIDEIntf.GetTargetDir: string; 284 | begin 285 | Result := RealOutputPath; 286 | if (Result <> '') and (Result[Length(Result)] in AllowDirectorySeparators) then 287 | Result := Copy(Result, 1, Length(Result) - 1); 288 | end; 289 | 290 | function TMyIDEIntf.GetTargetFile: string; 291 | begin 292 | Result := '$TargetFile()'; 293 | if not IDEMacros.SubstituteMacros(Result) then 294 | Result := LazarusIDE.ActiveProject.LazCompilerOptions.TargetFilename + LazarusIDE.ActiveProject.LazCompilerOptions.TargetFileExt; 295 | end; 296 | 297 | function TMyIDEIntf.GetUseScaled: Boolean; 298 | begin 299 | Result := True; 300 | if Assigned(LazarusIDE) and Assigned(LazarusIDE.ActiveProject) then 301 | Result := LazarusIDE.ActiveProject.Scaled; 302 | end; 303 | 304 | function TMyIDEIntf.GetLang: TLangBase; 305 | begin 306 | Result := GoLang; 307 | case Self.FOutLang of 308 | olRust: ; 309 | olNim: ; 310 | end; 311 | end; 312 | 313 | function TMyIDEIntf.GetProjectTitle: string; 314 | begin 315 | Result := ''; 316 | if Assigned(LazarusIDE) and Assigned(LazarusIDE.ActiveProject) then 317 | Result := LazarusIDE.ActiveProject.Title; 318 | end; 319 | 320 | function TMyIDEIntf.GetDefaultProjectParam: TProjParam; 321 | begin 322 | Result := TProjParam.Create(Self.RealOutputPath, Self.ProjectTitle, Self.UseScaled, Self.UseDefaultWinAppRes); 323 | end; 324 | 325 | function TMyIDEIntf.GetRealOutputPackagePath: string; 326 | begin 327 | Result := Self.RealOutputPath; 328 | if not Lang.IsMainPackage then 329 | Result := AppendPathDelim(Result + PackageName); 330 | end; 331 | 332 | // FakeIsJITMethod 333 | function FakeIsJITMethod(const aMethod: TMethod): boolean; 334 | begin 335 | Result:= (aMethod.Data <> nil) and (aMethod.Code = nil) and (TObject(aMethod.Data).ClassType.ClassNameIs('TJITMethod')); 336 | end; 337 | 338 | procedure TMyIDEIntf.OnWriteMethodProperty(Writer: TWriter; 339 | Instance: TPersistent; PropInfo: PPropInfo; const MethodValue, 340 | DefMethodValue: TMethod; var Handled: boolean); 341 | 342 | function GetTypeName: string; 343 | begin 344 | Result := PropInfo^.Name; 345 | if Result.StartsWith('On') then 346 | Result := Copy(Result, 3, Length(Result) - 2); 347 | end; 348 | 349 | var 350 | LMethodName, LComponentName: string; 351 | LEvent: TEventItem; 352 | begin 353 | Handled := False; 354 | if (DefMethodValue.Data = MethodValue.Data) and (DefMethodValue.Code = MethodValue.Code) then 355 | Exit; 356 | 357 | LMethodName := ''; 358 | LComponentName := ''; 359 | if Instance is TComponent then 360 | LComponentName := TComponent(Instance).Name; 361 | 362 | if FakeIsJITMethod(MethodValue) then 363 | LMethodName := TFakeJITMethod(MethodValue.Data).TheMethodName 364 | else if MethodValue.Code <> nil then 365 | begin 366 | LMethodName := Writer.LookupRoot.MethodName(MethodValue.Code); 367 | if LMethodName = '' then 368 | Exit; 369 | end; 370 | if LMethodName = '' then 371 | Exit; 372 | 373 | LEvent.InstanceName := LComponentName; 374 | LEvent.EventName := LMethodName; 375 | LEvent.EventTypeName := GetTypeName; 376 | LEvent.EventParams := Lang.ToEventString(PropInfo); 377 | 378 | SetLength(FEvents, Length(FEvents) + 1); 379 | FEvents[High(FEvents)] := LEvent; 380 | 381 | //if Assigned(PropInfo) then 382 | // Logs('LComponentName%s, LMethodName=%s, Event.Name=%s', [LComponentName, LMethodName, PropInfo^.Name]); 383 | end; 384 | 385 | procedure TMyIDEIntf.CheckAndCreateDir; 386 | var 387 | LOutPath: string; 388 | begin 389 | LOutPath := Self.RealOutputPath; 390 | if not SysUtils.DirectoryExists(LOutPath) then 391 | SysUtils.CreateDir(LOutPath); 392 | if not Lang.IsMainPackage then 393 | begin 394 | LOutPath := AppendPathDelim(LOutPath) + PackageName; 395 | if not SysUtils.DirectoryExists(LOutPath) then 396 | SysUtils.CreateDir(LOutPath); 397 | end; 398 | end; 399 | 400 | function TMyIDEIntf.GetProjectPath: string; 401 | begin 402 | Result := ''; 403 | if Assigned(LazarusIDE.ActiveProject) then 404 | Result := AppendPathDelim(LazarusIDE.ActiveProject.Directory); 405 | // Result := ExtractFilePath(LazarusIDE.ActiveProject.ProjectInfoFile); 406 | end; 407 | 408 | procedure TMyIDEIntf.SetEnabledConvert(AValue: Boolean); 409 | begin 410 | if FEnabledConvert=AValue then Exit; 411 | FEnabledConvert:=AValue; 412 | if FEnabledConvert then 413 | Self.AddHandlers 414 | else 415 | Self.RemoveHandlers; 416 | end; 417 | 418 | procedure TMyIDEIntf.SetPackageName(AValue: string); 419 | begin 420 | if FPackageName=AValue then Exit; 421 | FPackageName:=AValue; 422 | Lang.PackageName:=FPackageName; 423 | end; 424 | 425 | constructor TMyIDEIntf.Create; 426 | begin 427 | inherited Create; 428 | FAddToLast := False; // 测试时用,方便修改,最终要改为 False 429 | FModalResult := mrAbort;//mrOK; // 测试时用,方便修改,最终要改为 mrAbort 430 | end; 431 | 432 | destructor TMyIDEIntf.Destroy; 433 | begin 434 | inherited Destroy; 435 | end; 436 | 437 | function TMyIDEIntf.onSaveAll(Sender: TObject): TModalResult; 438 | begin 439 | if EnabledConvert then 440 | begin 441 | ClearMsg; 442 | CheckAndCreateDir; 443 | Lang.ConvertProjectFile(DefaultProjectParam); 444 | {$ifdef windows} 445 | if ReConvertRes and (not UseDefaultWinAppRes) then 446 | begin 447 | ReConvertRes := False; 448 | Lang.ConvertResource(ResFileName, RealOutputPath); 449 | end; 450 | {$else} 451 | // 暂时不持非Windows下转换资源 452 | {$endif} 453 | end; 454 | Result := mrOk; 455 | end; 456 | 457 | function TMyIDEIntf.onSaveEditorFile(Sender: TObject; aFile: TLazProjectFile; 458 | SaveStep: TSaveEditorFileStep; TargetFilename: string): TModalResult; 459 | var 460 | LDesigner: TIDesigner; 461 | begin 462 | if SaveStep = sefsAfterWrite then 463 | begin 464 | if EnabledConvert then 465 | begin 466 | ClearMsg; 467 | CheckAndCreateDir; 468 | LDesigner := LazarusIDE.GetDesignerWithProjectFile(aFile, False); 469 | if Assigned(LDesigner) and Assigned(LDesigner.LookupRoot) then 470 | SaveComponents(LDesigner, GetFileNameWithoutExt(TargetFilename), RealOutputPackagePath); 471 | end; 472 | end; 473 | Result := mrOk; 474 | end; 475 | 476 | function TMyIDEIntf.onProjectOpened(Sender: TObject; AProject: TLazProject): TModalResult; 477 | begin 478 | //Logs('ExtensionToLazSyntaxHighlighter=%d', [Integer(IDEEditorOptions.ExtensionToLazSyntaxHighlighter('.go'))]); 479 | //Logs('ExtensionToLazSyntaxHighlighter=%d', [Integer(IDEEditorOptions.ExtensionToLazSyntaxHighlighter('go'))]); 480 | //Logs('GetCompilerFilename=%s', [LazarusIDE.GetCompilerFilename]); 481 | //Logs('GetFPCompilerFilename=%s', [LazarusIDE.GetFPCompilerFilename]); 482 | //Logs('ActiveProject.Directory=%s', [LazarusIDE.ActiveProject.Directory]); 483 | //TProject.GetAutoCreatedFormsList 484 | //LazarusIDE.ActiveProject.; // TmpAutoCreatedForms 485 | //GetPropInfo(); 486 | Result := mrOk; 487 | end; 488 | 489 | function TMyIDEIntf.onProjectBuilding(Sender: TObject): TModalResult; 490 | 491 | //function GetCompileReasons: TCompileReasons; 492 | //begin 493 | // Result := []; 494 | // try 495 | // PByte(@Result)^ := Byte(GetOrdProp(LazarusIDE.ActiveProject.LazCompilerOptions, 'CompileReasons')); 496 | // except 497 | // end; 498 | //end; 499 | 500 | var 501 | LParams: TCompileParam; 502 | //LReasons: TCompileReasons; 503 | LResult: Boolean; 504 | begin 505 | //LReasons := GetCompileReasons; 506 | 507 | //if crCompile in LReasons then 508 | // Logs('crCompile'); 509 | //if crBuild in LReasons then 510 | // Logs('crBuild'); 511 | //if crRun in LReasons then 512 | // Logs('crRun'); 513 | 514 | FWithoutDebug := True; // 总是真,没得区分是哪个按钮点的了。 515 | Logs('TMyIDEIntf.onProjectBuilding: Status: ' + IntToStr(Integer(LazarusIDE.ToolStatus))); 516 | 517 | LazarusIDE.DoShowMessagesView(); 518 | 519 | LazarusIDE.ToolStatus:=itBuilder; 520 | try 521 | LParams.Input := TargetDir; 522 | LParams.Output := TargetFile; 523 | 524 | // for golang 525 | if OutLang = olGo then 526 | begin 527 | LParams.GoUseTempdll:= Self.GoUseTempdll; 528 | LParams.GoEnabledFinalizerOn:= Self.GoEnabledFinalizerOn; 529 | LParams.GoTags:=Self.GoTags; 530 | LParams.GoEnabledCGO:=Self.GoEnabledCGO; 531 | LParams.GoBuildMode:=Self.GoBuildMode; 532 | LParams.GoRoot:= Self.GoRoot; 533 | LParams.GoUseGoEmbed:= Self.GoUseEmbed; 534 | end; 535 | 536 | LResult := False; 537 | try 538 | LResult := Lang.Compile(LParams); 539 | except 540 | on E: Exception do 541 | CtlWriteln(mluError, E.Message); 542 | end; 543 | onProjectBuildingFinished(Self, LResult); 544 | finally 545 | LazarusIDE.ToolStatus:=itNone; 546 | end; 547 | Result := FModalResult; 548 | end; 549 | 550 | procedure TMyIDEIntf.onProjectBuildingFinished(Sender: TObject; 551 | BuildSuccessful: Boolean); 552 | var 553 | LTargetFile, LTargetCmd: string; 554 | begin 555 | LazarusIDE.ToolStatus := itNone; 556 | //Logs('TMyIDEIntf.onProjectBuildingFinished: ' + BoolToStr(BuildSuccessful, True)); 557 | try 558 | if BuildSuccessful and FWithoutDebug then 559 | begin 560 | LTargetFile := Self.TargetFile; 561 | if FileExists(LTargetFile) then 562 | begin 563 | LTargetCmd := '$TargetCmdLine()'; 564 | if IDEMacros.SubstituteMacros(LTargetCmd) then 565 | begin 566 | //Logs('onProjectBuildingFinished run: ' + LTargetCmd); 567 | Lang.ExecuteCommand(LTargetCmd, False, True, ExtractFileDir(LTargetFile)); 568 | onRunFinished(Self); 569 | end; 570 | end; 571 | end; 572 | finally 573 | FWithoutDebug := False; 574 | end; 575 | end; 576 | 577 | function TMyIDEIntf.onProjectDependenciesCompiling(Sender: TObject): TModalResult; 578 | begin 579 | Logs('TMyIDEIntf.onProjectDependenciesCompiling'); 580 | Result := FModalResult; 581 | end; 582 | 583 | function TMyIDEIntf.onProjectDependenciesCompiled(Sender: TObject): TModalResult; 584 | begin 585 | Logs('TMyIDEIntf.onProjectDependenciesCompiled'); 586 | Result := FModalResult; 587 | end; 588 | 589 | function TMyIDEIntf.onLazarusBuilding(Sender: TObject): TModalResult; 590 | begin 591 | Logs('TMyIDEIntf.onLazarusBuilding'); 592 | Result := FModalResult; 593 | end; 594 | 595 | procedure TMyIDEIntf.onLazarusBuildingFinished(Sender: TObject; 596 | BuildSuccessful: Boolean); 597 | begin 598 | Logs('TMyIDEIntf.onLazarusBuildingFinished'); 599 | end; 600 | 601 | function TMyIDEIntf.onRunDebug(Sender: TObject; var Handled: boolean): TModalResult; 602 | begin 603 | Logs('TMyIDEIntf.onRunDebug'); 604 | Result := FModalResult; 605 | end; 606 | 607 | function TMyIDEIntf.onRunWithoutDebugBuilding(Sender: TObject; 608 | var Handled: boolean): TModalResult; 609 | begin 610 | FWithoutDebug := True; 611 | Logs('TMyIDEIntf.onRunWithoutDebugBuilding'); 612 | Result := FModalResult; 613 | end; 614 | 615 | function TMyIDEIntf.onRunWithoutDebugInit(Sender: TObject; var Handled: boolean): TModalResult; 616 | begin 617 | Logs('TMyIDEIntf.onRunWithoutDebugInit'); 618 | Result := FModalResult; 619 | end; 620 | 621 | procedure TMyIDEIntf.onRunFinished(Sender: TObject); 622 | begin 623 | Logs('TMyIDEIntf.onRunFinished'); 624 | end; 625 | 626 | procedure TMyIDEIntf.onChangeToolStatus(Sender: TObject; OldStatus, 627 | NewStatus: TLazToolStatus); 628 | begin 629 | Logs('TMyIDEIntf.onChangeToolStatus: OldStatus=%d, NewStatus=%d', [Ord(OldStatus), Ord(NewStatus)]); 630 | end; 631 | 632 | class procedure TMyIDEIntf.AddHandlers; 633 | begin 634 | if Assigned(LazarusIDE) then 635 | begin 636 | Logs('MyIDEIntf.AddHandlers'); 637 | with MyIDEIntf do 638 | begin 639 | LazarusIDE.AddHandlerOnSavedAll(@onSaveAll, True); 640 | LazarusIDE.AddHandlerOnSaveEditorFile(@onSaveEditorFile, True); 641 | LazarusIDE.AddHandlerOnProjectOpened(@onProjectOpened, True); 642 | 643 | //// complie 644 | //[4968] TMyIDEIntf.onProjectBuilding 645 | //[4968] TMyIDEIntf.onProjectDependenciesCompiling 646 | //[4968] TMyIDEIntf.onProjectDependenciesCompiled 647 | //[4968] TMyIDEIntf.onProjectBuildingFinished 648 | // 649 | //// debug 650 | //[4968] TMyIDEIntf.onProjectBuilding 651 | //[4968] TMyIDEIntf.onProjectDependenciesCompiling 652 | //[4968] TMyIDEIntf.onProjectDependenciesCompiled 653 | //[4968] TMyIDEIntf.onProjectBuildingFinished 654 | //[4968] TMyIDEIntf.onRunDebug 655 | //[4968] TMyIDEIntf.onRunFinished 656 | // 657 | //// run without debug 658 | //[4968] TMyIDEIntf.onRunFinished 659 | //[4968] TMyIDEIntf.onRunWithoutDebugBuilding 660 | //[4968] TMyIDEIntf.onProjectBuilding 661 | //[4968] TMyIDEIntf.onProjectDependenciesCompiling 662 | //[4968] TMyIDEIntf.onProjectDependenciesCompiled 663 | //[4968] TMyIDEIntf.onProjectBuildingFinished 664 | //[4968] TMyIDEIntf.onRunWithoutDebugInit 665 | 666 | 667 | // 编译 668 | if OutLang = olGo then 669 | begin 670 | LazarusIDE.AddHandlerOnChangeToolStatus(@onChangeToolStatus, FAddToLast); 671 | LazarusIDE.AddHandlerOnProjectBuilding(@onProjectBuilding, FAddToLast); 672 | LazarusIDE.AddHandlerOnProjectBuildingFinished(@onProjectBuildingFinished, FAddToLast); 673 | LazarusIDE.AddHandlerOnProjectDependenciesCompiling(@onProjectDependenciesCompiling, FAddToLast); 674 | LazarusIDE.AddHandlerOnProjectDependenciesCompiled(@onProjectDependenciesCompiled, FAddToLast); 675 | LazarusIDE.AddHandlerOnLazarusBuilding(@onLazarusBuilding, FAddToLast); 676 | LazarusIDE.AddHandlerOnLazarusBuildingFinished(@onLazarusBuildingFinished, FAddToLast); 677 | LazarusIDE.AddHandlerOnRunDebug(@onRunDebug, FAddToLast); 678 | LazarusIDE.AddHandlerOnRunWithoutDebugBuilding(@onRunWithoutDebugBuilding, FAddToLast); 679 | LazarusIDE.AddHandlerOnRunWithoutDebugInit(@onRunWithoutDebugInit, FAddToLast); 680 | LazarusIDE.AddHandlerOnRunFinished(@onRunFinished, FAddToLast); 681 | end; 682 | end; 683 | end; 684 | end; 685 | 686 | class procedure TMyIDEIntf.RemoveHandlers; 687 | begin 688 | if Assigned(LazarusIDE) and Assigned(MyIDEIntf) then 689 | begin 690 | LazarusIDE.RemoveAllHandlersOfObject(MyIDEIntf); 691 | Logs('MyIDEIntf.Removehandlers'); 692 | end; 693 | end; 694 | 695 | 696 | initialization 697 | Init; 698 | 699 | finalization 700 | UnInit; 701 | 702 | end. 703 | 704 | -------------------------------------------------------------------------------- /res2gooptions.lfm: -------------------------------------------------------------------------------- 1 | object Res2goOptionsFrame: TRes2goOptionsFrame 2 | Left = 0 3 | Height = 628 4 | Top = 0 5 | Width = 892 6 | ClientHeight = 628 7 | ClientWidth = 892 8 | OnClick = FrameClick 9 | TabOrder = 0 10 | DesignLeft = 867 11 | DesignTop = 200 12 | object Panel1: TPanel 13 | Left = 0 14 | Height = 216 15 | Top = 0 16 | Width = 892 17 | Align = alTop 18 | BevelOuter = bvNone 19 | ClientHeight = 216 20 | ClientWidth = 892 21 | TabOrder = 0 22 | object chkEanbledConvert: TCheckBox 23 | Left = 16 24 | Height = 21 25 | Top = 23 26 | Width = 120 27 | AutoSize = False 28 | Caption = 'Enabled Convert' 29 | TabOrder = 0 30 | end 31 | object lblOutputPath: TLabeledEdit 32 | Left = 88 33 | Height = 25 34 | Top = 96 35 | Width = 786 36 | Anchors = [akTop, akLeft, akRight] 37 | EditLabel.Height = 17 38 | EditLabel.Width = 72 39 | EditLabel.Caption = 'Output Path:' 40 | EditLabel.ParentColor = False 41 | LabelPosition = lpLeft 42 | TabOrder = 1 43 | end 44 | object Label1: TLabel 45 | Left = 88 46 | Height = 17 47 | Top = 133 48 | Width = 60 49 | Caption = 'eg: code/' 50 | ParentColor = False 51 | end 52 | object chkUseOriginalFileName: TCheckBox 53 | Left = 164 54 | Height = 21 55 | Top = 23 56 | Width = 163 57 | AutoSize = False 58 | Caption = 'Use Original File Name' 59 | TabOrder = 2 60 | end 61 | object chkSaveGfmFile: TCheckBox 62 | Left = 358 63 | Height = 21 64 | Top = 23 65 | Width = 99 66 | Action = actSaveGfm 67 | TabOrder = 3 68 | end 69 | object lblOutLang: TLabel 70 | Left = 9 71 | Height = 17 72 | Top = 170 73 | Width = 75 74 | Caption = 'Output Lang:' 75 | ParentColor = False 76 | end 77 | object cbbLangs: TComboBox 78 | Left = 88 79 | Height = 25 80 | Top = 166 81 | Width = 168 82 | ItemHeight = 17 83 | ItemIndex = 0 84 | Items.Strings = ( 85 | 'Go' 86 | 'Nim' 87 | 'Rust' 88 | ) 89 | Style = csDropDownList 90 | TabOrder = 4 91 | Text = 'Go' 92 | end 93 | object lblPkgName: TLabeledEdit 94 | Left = 436 95 | Height = 25 96 | Top = 166 97 | Width = 438 98 | Anchors = [akTop, akLeft, akRight] 99 | EditLabel.Height = 17 100 | EditLabel.Width = 100 101 | EditLabel.Caption = 'Package Name:' 102 | EditLabel.ParentColor = False 103 | LabelPosition = lpLeft 104 | TabOrder = 5 105 | Text = 'main' 106 | end 107 | object chkUseDefaultWinAppRes: TCheckBox 108 | Left = 16 109 | Height = 21 110 | Top = 56 111 | Width = 152 112 | Caption = 'Use default winappres' 113 | TabOrder = 6 114 | end 115 | end 116 | object Panel2: TPanel 117 | Left = 0 118 | Height = 232 119 | Top = 216 120 | Width = 892 121 | Align = alTop 122 | BevelOuter = bvNone 123 | ClientHeight = 232 124 | ClientWidth = 892 125 | TabOrder = 1 126 | object DividerBevel1: TDividerBevel 127 | Left = 2 128 | Height = 17 129 | Top = 0 130 | Width = 888 131 | Caption = 'For Golang' 132 | Align = alTop 133 | AutoSize = False 134 | BorderSpacing.Left = 2 135 | BorderSpacing.Right = 2 136 | Font.Style = [fsBold] 137 | ParentFont = False 138 | Style = gsHorLines 139 | end 140 | object chkGoUseTempdll: TCheckBox 141 | Left = 16 142 | Height = 21 143 | Top = 30 144 | Width = 102 145 | Caption = 'Use "tempdll"' 146 | ParentShowHint = False 147 | ShowHint = True 148 | TabOrder = 0 149 | end 150 | object chkGoEnabledFinalizerOn: TCheckBox 151 | Left = 164 152 | Height = 21 153 | Top = 30 154 | Width = 145 155 | Caption = 'Enabled "finalizerOn"' 156 | ParentShowHint = False 157 | ShowHint = True 158 | TabOrder = 1 159 | end 160 | object lblGoTags: TLabeledEdit 161 | Left = 88 162 | Height = 25 163 | Top = 64 164 | Width = 786 165 | Anchors = [akTop, akLeft, akRight] 166 | EditLabel.Height = 17 167 | EditLabel.Width = 31 168 | EditLabel.Caption = 'Tags:' 169 | EditLabel.ParentColor = False 170 | LabelPosition = lpLeft 171 | TabOrder = 2 172 | end 173 | object chkGoEnabledCGO: TCheckBox 174 | Left = 344 175 | Height = 21 176 | Top = 30 177 | Width = 100 178 | Caption = 'Enabled CGO' 179 | TabOrder = 3 180 | end 181 | object Label2: TLabel 182 | Left = 16 183 | Height = 17 184 | Top = 107 185 | Width = 70 186 | Caption = 'Build mode:' 187 | ParentColor = False 188 | end 189 | object cbbGoBuildModes: TComboBox 190 | Left = 88 191 | Height = 25 192 | Top = 104 193 | Width = 168 194 | ItemHeight = 17 195 | Items.Strings = ( 196 | 'default' 197 | 'archive' 198 | 'c-archive' 199 | 'c-shared' 200 | 'shared' 201 | 'exe' 202 | 'pie' 203 | 'plugin' 204 | ) 205 | Style = csDropDownList 206 | TabOrder = 4 207 | end 208 | object lblBuildModeHint: TLabel 209 | Left = 88 210 | Height = 17 211 | Top = 136 212 | Width = 444 213 | Caption = 'If go version>=1.15, please select "exe" mode, otherwise, no need to select.' 214 | Font.Color = clGreen 215 | ParentColor = False 216 | ParentFont = False 217 | end 218 | object Label3: TLabel 219 | Left = 16 220 | Height = 17 221 | Top = 176 222 | Width = 57 223 | Caption = 'GOROOT:' 224 | ParentColor = False 225 | end 226 | object edtGoRoot: TDirectoryEdit 227 | Left = 88 228 | Height = 25 229 | Top = 175 230 | Width = 786 231 | ShowHidden = False 232 | ButtonWidth = 23 233 | NumGlyphs = 1 234 | Anchors = [akTop, akLeft, akRight] 235 | MaxLength = 0 236 | TabOrder = 5 237 | end 238 | object chkGoUseEmbed: TCheckBox 239 | Left = 480 240 | Height = 21 241 | Top = 30 242 | Width = 165 243 | Caption = 'Use go:embed(go1.16+)' 244 | TabOrder = 6 245 | end 246 | end 247 | object Panel3: TPanel 248 | Left = 0 249 | Height = 104 250 | Top = 552 251 | Width = 892 252 | Align = alTop 253 | BevelOuter = bvNone 254 | ClientHeight = 104 255 | ClientWidth = 892 256 | TabOrder = 2 257 | Visible = False 258 | object DividerBevel2: TDividerBevel 259 | Left = 2 260 | Height = 17 261 | Top = 0 262 | Width = 888 263 | Caption = 'For Rust' 264 | Align = alTop 265 | AutoSize = False 266 | BorderSpacing.Left = 2 267 | BorderSpacing.Right = 2 268 | Font.Style = [fsBold] 269 | ParentFont = False 270 | Style = gsHorLines 271 | end 272 | end 273 | object Panel4: TPanel 274 | Left = 0 275 | Height = 104 276 | Top = 448 277 | Width = 892 278 | Align = alTop 279 | BevelOuter = bvNone 280 | ClientHeight = 104 281 | ClientWidth = 892 282 | TabOrder = 3 283 | Visible = False 284 | object DividerBevel3: TDividerBevel 285 | Left = 2 286 | Height = 17 287 | Top = 0 288 | Width = 888 289 | Caption = 'For Nim' 290 | Align = alTop 291 | AutoSize = False 292 | BorderSpacing.Left = 2 293 | BorderSpacing.Right = 2 294 | Font.Style = [fsBold] 295 | ParentFont = False 296 | Style = gsHorLines 297 | end 298 | end 299 | object ActionList1: TActionList 300 | Left = 512 301 | Top = 63 302 | object actSaveGfm: TAction 303 | Caption = 'Save gfm File' 304 | OnExecute = actSaveGfmExecute 305 | OnUpdate = actSaveGfmUpdate 306 | end 307 | end 308 | end 309 | -------------------------------------------------------------------------------- /res2gooptions.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | unit res2goOptions; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | Classes, SysUtils, Forms, Controls, StdCtrls, ExtCtrls, EditBtn, ActnList, 16 | StrUtils, IDEOptionsIntf, IDEOptEditorIntf, LazIDEIntf, ProjectIntf, 17 | ProjectResourcesIntf, res2goresources, Laz2_XMLCfg, DividerBevel, uSupports; 18 | 19 | type 20 | 21 | 22 | { TProjectRes2goRes } 23 | 24 | TProjectRes2goRes = class(TAbstractProjectResource) 25 | private const 26 | DefaultCGOValue = {$ifdef windows}False{$else}True{$endif}; 27 | private 28 | FEnabled: Boolean; 29 | FGoBuildMode: string; 30 | FGoEnabledCGO: Boolean; 31 | FGoEnabledFinalizerOn: Boolean; 32 | FGoRoot: string; 33 | FGoTags: string; 34 | FGoUseEmbed: Boolean; 35 | FGoUseTempdll: Boolean; 36 | FOutLang: TOutLang; 37 | FOutputPath: string; 38 | FPakcageName: string; 39 | FSaveGfmFile: Boolean; 40 | FUseDefaultWinAppRes: Boolean; 41 | FUseOriginalFileName: Boolean; 42 | 43 | procedure Changed; 44 | 45 | procedure SetEnabled(AValue: Boolean); 46 | procedure SetGoBuildMode(AValue: string); 47 | procedure SetGoEnabledCGO(AValue: Boolean); 48 | procedure SetGoEnabledFinalizerOn(AValue: Boolean); 49 | procedure SetGoRoot(AValue: string); 50 | procedure SetGoTags(AValue: string); 51 | procedure SetGoUseEmbed(AValue: Boolean); 52 | procedure SetGoUseTempdll(AValue: Boolean); 53 | procedure SetOutLang(AValue: TOutLang); 54 | procedure SetOutputPath(AValue: string); 55 | procedure SetPackageName(AValue: string); 56 | procedure SetSaveGfmFile(AValue: Boolean); 57 | procedure SetUseDefaultWinAppRes(AValue: Boolean); 58 | procedure SetUseOriginalFileName(AValue: Boolean); 59 | 60 | public 61 | function UpdateResources(AResources: TAbstractProjectResources; const {%H-}MainFilename: string): Boolean; override; 62 | procedure WriteToProjectFile(AConfig: TObject; const Path: String); override; 63 | procedure ReadFromProjectFile(AConfig: TObject; const Path: String); override; 64 | public 65 | property Enabled: Boolean read FEnabled write SetEnabled; 66 | property OutputPath: string read FOutputPath write SetOutputPath; 67 | property UseOriginalFileName: Boolean read FUseOriginalFileName write SetUseOriginalFileName; 68 | property SaveGfmFile: Boolean read FSaveGfmFile write SetSaveGfmFile; 69 | property OutLang: TOutLang read FOutLang write SetOutLang; 70 | property PackageName: string read FPakcageName write SetPackageName; 71 | property UseDefaultWinAppRes: Boolean read FUseDefaultWinAppRes write SetUseDefaultWinAppRes; 72 | 73 | property GoUseTempdll: Boolean read FGoUseTempdll write SetGoUseTempdll; 74 | property GoEnabledFinalizerOn: Boolean read FGoEnabledFinalizerOn write SetGoEnabledFinalizerOn; 75 | property GoTags: string read FGoTags write SetGoTags; 76 | property GoEnabledCGO: Boolean read FGoEnabledCGO write SetGoEnabledCGO; 77 | property GoBuildMode: string read FGoBuildMode write SetGoBuildMode; 78 | property GoRoot: string read FGoRoot write SetGoRoot; 79 | property GoUseEmbed: Boolean read FGoUseEmbed write SetGoUseEmbed; 80 | end; 81 | 82 | { TRes2goOptionsFrame } 83 | 84 | TRes2goOptionsFrame = class(TAbstractIDEOptionsEditor) 85 | actSaveGfm: TAction; 86 | ActionList1: TActionList; 87 | cbbLangs: TComboBox; 88 | chkGoEnabledCGO: TCheckBox; 89 | chkGoUseEmbed: TCheckBox; 90 | chkGoUseTempdll: TCheckBox; 91 | chkGoEnabledFinalizerOn: TCheckBox; 92 | chkEanbledConvert: TCheckBox; 93 | chkSaveGfmFile: TCheckBox; 94 | chkUseDefaultWinAppRes: TCheckBox; 95 | chkUseOriginalFileName: TCheckBox; 96 | cbbGoBuildModes: TComboBox; 97 | edtGoRoot: TDirectoryEdit; 98 | DividerBevel1: TDividerBevel; 99 | DividerBevel2: TDividerBevel; 100 | DividerBevel3: TDividerBevel; 101 | Label1: TLabel; 102 | Label2: TLabel; 103 | Label3: TLabel; 104 | lblBuildModeHint: TLabel; 105 | lblOutLang: TLabel; 106 | lblOutputPath: TLabeledEdit; 107 | lblGoTags: TLabeledEdit; 108 | lblPkgName: TLabeledEdit; 109 | Panel1: TPanel; 110 | Panel2: TPanel; 111 | Panel3: TPanel; 112 | Panel4: TPanel; 113 | procedure actSaveGfmExecute(Sender: TObject); 114 | procedure actSaveGfmUpdate(Sender: TObject); 115 | procedure FrameClick(Sender: TObject); 116 | public 117 | constructor Create(AOwner: TComponent); override; 118 | destructor Destroy; override; 119 | 120 | function GetTitle: string; override; 121 | procedure Setup({%H-}ADialog: TAbstractOptionsEditorDialog); override; 122 | procedure ReadSettings(AOptions: TAbstractIDEOptions); override; 123 | procedure WriteSettings(AOptions: TAbstractIDEOptions); override; 124 | class function SupportedOptionsClass: TAbstractIDEOptionsClass; override; 125 | end; 126 | 127 | implementation 128 | 129 | {$R *.lfm} 130 | 131 | uses 132 | res2gomain; 133 | 134 | const 135 | ProjectOptionsRes2go = ProjectOptionsMisc + 500; 136 | 137 | 138 | { TProjectRes2goRes } 139 | 140 | procedure TProjectRes2goRes.Changed; 141 | begin 142 | Self.Modified:= True; 143 | end; 144 | 145 | procedure TProjectRes2goRes.SetEnabled(AValue: Boolean); 146 | begin 147 | if FEnabled=AValue then Exit; 148 | FEnabled:=AValue; 149 | Changed; 150 | end; 151 | 152 | procedure TProjectRes2goRes.SetGoBuildMode(AValue: string); 153 | begin 154 | if FGoBuildMode=AValue then Exit; 155 | FGoBuildMode:=AValue; 156 | Changed; 157 | end; 158 | 159 | procedure TProjectRes2goRes.SetGoEnabledCGO(AValue: Boolean); 160 | begin 161 | if FGoEnabledCGO=AValue then Exit; 162 | FGoEnabledCGO:=AValue; 163 | Changed; 164 | end; 165 | 166 | procedure TProjectRes2goRes.SetGoEnabledFinalizerOn(AValue: Boolean); 167 | begin 168 | if FGoEnabledFinalizerOn=AValue then Exit; 169 | FGoEnabledFinalizerOn:=AValue; 170 | Changed; 171 | end; 172 | 173 | procedure TProjectRes2goRes.SetGoRoot(AValue: string); 174 | begin 175 | if FGoRoot=AValue then Exit; 176 | FGoRoot:=AValue; 177 | Changed; 178 | end; 179 | 180 | procedure TProjectRes2goRes.SetGoTags(AValue: string); 181 | begin 182 | if FGoTags=AValue then Exit; 183 | FGoTags:=AValue; 184 | Changed; 185 | end; 186 | 187 | procedure TProjectRes2goRes.SetGoUseEmbed(AValue: Boolean); 188 | begin 189 | if FGoUseEmbed=AValue then Exit; 190 | FGoUseEmbed:=AValue; 191 | Changed; 192 | end; 193 | 194 | procedure TProjectRes2goRes.SetGoUseTempdll(AValue: Boolean); 195 | begin 196 | if FGoUseTempdll=AValue then Exit; 197 | FGoUseTempdll:=AValue; 198 | Changed; 199 | end; 200 | 201 | procedure TProjectRes2goRes.SetOutLang(AValue: TOutLang); 202 | begin 203 | if FOutLang=AValue then Exit; 204 | FOutLang:=AValue; 205 | Changed; 206 | end; 207 | 208 | procedure TProjectRes2goRes.SetOutputPath(AValue: string); 209 | begin 210 | if FOutputPath=AValue then Exit; 211 | FOutputPath:=AValue; 212 | Changed; 213 | end; 214 | 215 | procedure TProjectRes2goRes.SetPackageName(AValue: string); 216 | begin 217 | if FPakcageName=AValue then Exit; 218 | FPakcageName:=AValue; 219 | Changed; 220 | end; 221 | 222 | procedure TProjectRes2goRes.SetSaveGfmFile(AValue: Boolean); 223 | begin 224 | if FSaveGfmFile=AValue then Exit; 225 | FSaveGfmFile:=AValue; 226 | Changed; 227 | end; 228 | 229 | procedure TProjectRes2goRes.SetUseDefaultWinAppRes(AValue: Boolean); 230 | begin 231 | if FUseDefaultWinAppRes=AValue then Exit; 232 | FUseDefaultWinAppRes:=AValue; 233 | Changed; 234 | end; 235 | 236 | procedure TProjectRes2goRes.SetUseOriginalFileName(AValue: Boolean); 237 | begin 238 | if FUseOriginalFileName=AValue then Exit; 239 | FUseOriginalFileName:=AValue; 240 | Changed; 241 | end; 242 | 243 | function TProjectRes2goRes.UpdateResources( 244 | AResources: TAbstractProjectResources; const MainFilename: string): Boolean; 245 | begin 246 | Result := True; 247 | if Assigned(MyIDEIntf) then 248 | MyIDEIntf.ReConvertRes:= True; 249 | end; 250 | 251 | procedure TProjectRes2goRes.WriteToProjectFile(AConfig: TObject; 252 | const Path: String); 253 | begin 254 | with TXMLConfig(AConfig) do 255 | begin 256 | SetDeleteValue(Path+'Res2go/Enabled/Value', Enabled, False); 257 | SetDeleteValue(Path+'Res2go/OutputPath/Value', OutputPath, ''); 258 | SetDeleteValue(Path+'Res2go/UseOriginalFileName/Value', UseOriginalFileName, False); 259 | SetDeleteValue(Path+'Res2go/SaveGfmFile/Value', SaveGfmFile, False); 260 | SetDeleteValue(Path+'Res2go/OutLang/Value', Integer(OutLang), 0); 261 | SetDeleteValue(Path+'Res2go/PackageName/Value', PackageName, 'main'); 262 | SetDeleteValue(Path+'Res2go/UseDefaultWinAppRes/Value', UseDefaultWinAppRes, False); 263 | 264 | SetDeleteValue(Path+'Res2go/GoUseTempdll/Value', GoUseTempdll, False); 265 | SetDeleteValue(Path+'Res2go/GoEnabledFinalizerOn/Value', GoEnabledFinalizerOn, False); 266 | SetDeleteValue(Path+'Res2go/GoTags/Value', GoTags, ''); 267 | SetDeleteValue(Path+'Res2go/GoEnabledCGO/Value', GoEnabledCGO, DefaultCGOValue); 268 | SetDeleteValue(Path+'Res2go/GoBuildMode/Value', GoBuildMode, ''); 269 | SetDeleteValue(Path+'Res2go/GoRoot/Value', GoRoot, ''); 270 | SetDeleteValue(Path+'Res2go/GoUseEmbed/Value', GoUseEmbed, False); 271 | end; 272 | end; 273 | 274 | procedure TProjectRes2goRes.ReadFromProjectFile(AConfig: TObject; 275 | const Path: String); 276 | begin 277 | with TXMLConfig(AConfig) do 278 | begin 279 | Enabled := GetValue(Path+'Res2go/Enabled/Value', False); 280 | OutputPath := GetValue(Path+'Res2go/OutputPath/Value', ''); 281 | UseOriginalFileName := GetValue(Path+'Res2go/UseOriginalFileName/Value', False); 282 | SaveGfmFile := GetValue(Path+'Res2go/SaveGfmFile/Value', False); 283 | OutLang := TOutLang(GetValue(Path+'Res2go/SaveGfmFile/Value', 0)); 284 | PackageName := GetValue(Path+'Res2go/PackageName/Value', 'main'); 285 | UseDefaultWinAppRes := GetValue(Path+'Res2go/UseDefaultWinAppRes/Value', False); 286 | 287 | GoUseTempdll := GetValue(Path+'Res2go/GoUseTempdll/Value', False); 288 | GoEnabledFinalizerOn := GetValue(Path+'Res2go/GoEnabledFinalizerOn/Value', False); 289 | GoTags := GetValue(Path+'Res2go/GoTags/Value', ''); 290 | GoEnabledCGO := {$ifndef windows}True{$else}GetValue(Path+'Res2go/GoEnabledCGO/Value', False){$endif}; 291 | GoBuildMode := GetValue(Path+'Res2go/GoBuildMode/Value', ''); 292 | GoRoot := Trim(GetValue(Path+'Res2go/GoRoot/Value', GetEnvironmentVariable('GOROOT'))); 293 | GoUseEmbed := GetValue(Path+'Res2go/GoUseEmbed/Value', False); 294 | end; 295 | 296 | if Assigned(MyIDEIntf) then 297 | begin 298 | MyIDEIntf.EnabledConvert := Enabled; 299 | MyIDEIntf.OutputPath := OutputPath; 300 | MyIDEIntf.UseOriginalFileName := UseOriginalFileName; 301 | MyIDEIntf.SaveGfmFile := SaveGfmFile; 302 | MyIDEIntf.OutLang := OutLang; 303 | MyIDEIntf.PackageName := PackageName; 304 | MyIDEIntf.UseDefaultWinAppRes := UseDefaultWinAppRes; 305 | 306 | MyIDEIntf.GoUseTempdll := GoUseTempdll; 307 | MyIDEIntf.GoEnabledFinalizerOn := GoEnabledFinalizerOn; 308 | MyIDEIntf.GoTags := GoTags; 309 | MyIDEIntf.GoEnabledCGO := GoEnabledCGO; 310 | MyIDEIntf.GoBuildMode := GoBuildMode; 311 | MyIDEIntf.GoRoot := GoRoot; 312 | MyIDEIntf.GoUseEmbed := GoUseEmbed; 313 | end; 314 | end; 315 | 316 | 317 | 318 | 319 | { TRes2goOptionsFrame } 320 | 321 | procedure TRes2goOptionsFrame.FrameClick(Sender: TObject); 322 | begin 323 | 324 | end; 325 | 326 | procedure TRes2goOptionsFrame.actSaveGfmExecute(Sender: TObject); 327 | begin 328 | // 329 | end; 330 | 331 | procedure TRes2goOptionsFrame.actSaveGfmUpdate(Sender: TObject); 332 | begin 333 | TAction(Sender).Enabled:=not chkGoUseEmbed.Checked; 334 | end; 335 | 336 | constructor TRes2goOptionsFrame.Create(AOwner: TComponent); 337 | begin 338 | inherited Create(AOwner); 339 | end; 340 | 341 | destructor TRes2goOptionsFrame.Destroy; 342 | begin 343 | inherited Destroy; 344 | end; 345 | 346 | function TRes2goOptionsFrame.GetTitle: string; 347 | begin 348 | Result := 'res2go'; 349 | end; 350 | 351 | procedure TRes2goOptionsFrame.Setup(ADialog: TAbstractOptionsEditorDialog); 352 | begin 353 | chkEanbledConvert.Caption:=rsEnabledConvert; 354 | chkUseOriginalFileName.Caption:=rsUseOriginalFileName; 355 | //chkSaveGfmFile.Caption := rsSaveGfmFile; 356 | actSaveGfm.Caption:=rsSaveGfmFile; 357 | lblOutputPath.EditLabel.Caption:=rsOutputPath; 358 | Label1.Caption:=rsOutputPathEg; 359 | lblOutLang.Caption:=rsOutputLang; 360 | lblPkgName.EditLabel.Caption:=rsPackageName; 361 | chkUseDefaultWinAppRes.Caption:=rsUseDefaultWinAppRes; 362 | 363 | chkGoUseTempdll.Caption := rsGoUseTempdll; 364 | chkGoUseTempdll.Hint:=rsGoUseTempdllHint; 365 | chkGoEnabledFinalizerOn.Caption := rsGoEnabledFinalizerOn; 366 | chkGoEnabledFinalizerOn.Hint:=rsGoEnabledFinalizerOnHint; 367 | lblGoTags.EditLabel.Caption := rsGoTags; 368 | DividerBevel1.Caption := rsDividerBevel1; 369 | chkGoEnabledCGO.Caption:=rsGoEnabledCGO; 370 | Label2.Caption := rsBuildMode; 371 | lblBuildModeHint.Caption := rsBuildModeHint; 372 | chkGoUseEmbed.Caption:=rsGoEnabledEmbed; 373 | {$ifndef windows} 374 | chkGoEnabledCGO.Enabled := False; 375 | chkGoEnabledCGO.Checked := True; 376 | {$endif} 377 | end; 378 | 379 | procedure TRes2goOptionsFrame.ReadSettings(AOptions: TAbstractIDEOptions); 380 | var 381 | LRes: TProjectRes2goRes; 382 | begin 383 | if Assigned(MyIDEIntf) and Assigned(LazarusIDE) and Assigned(LazarusIDE.ActiveProject) and Assigned(LazarusIDE.ActiveProject.Resources) then 384 | begin 385 | LRes := TProjectRes2goRes(TAbstractProjectResources(LazarusIDE.ActiveProject.Resources).Resource[TProjectRes2goRes]); 386 | if Assigned(LRes) then 387 | begin 388 | MyIDEIntf.EnabledConvert := LRes.Enabled; 389 | MyIDEIntf.OutputPath := LRes.OutputPath; 390 | MyIDEIntf.UseOriginalFileName := LRes.UseOriginalFileName; 391 | MyIDEIntf.SaveGfmFile := LRes.SaveGfmFile; 392 | MyIDEIntf.OutLang := LRes.OutLang; 393 | MyIDEIntf.PackageName :=LRes.PackageName; 394 | MyIDEIntf.UseDefaultWinAppRes := LRes.UseDefaultWinAppRes; 395 | MyIDEIntf.GoUseTempdll := LRes.GoUseTempdll; 396 | MyIDEIntf.GoEnabledFinalizerOn :=LRes.GoEnabledFinalizerOn; 397 | MyIDEIntf.GoTags := LRes.GoTags; 398 | MyIDEIntf.GoEnabledCGO :=LRes.GoEnabledCGO; 399 | MyIDEIntf.GoBuildMode := LRes.GoBuildMode; 400 | MyIDEIntf.GoRoot := LRes.GoRoot; 401 | MyIDEIntf.GoUseEmbed:=LRes.GoUseEmbed; 402 | 403 | 404 | chkEanbledConvert.Checked := MyIDEIntf.EnabledConvert; 405 | lblOutputPath.Text := MyIDEIntf.OutputPath; 406 | ChkUseOriginalFileName.Checked:= MyIDEIntf.UseOriginalFileName; 407 | ChkSaveGfmFile.Checked := MyIDEIntf.SaveGfmFile; 408 | cbbLangs.ItemIndex:=Integer(MyIDEIntf.OutLang); 409 | lblPkgName.Text:=MyIDEIntf.PackageName; 410 | chkUseDefaultWinAppRes.Checked:=MyIDEIntf.UseDefaultWinAppRes; 411 | chkGoUseTempdll.Checked:=LRes.GoUseTempdll; 412 | chkGoEnabledFinalizerOn.Checked:=LRes.GoEnabledFinalizerOn; 413 | lblGoTags.Text := LRes.GoTags; 414 | chkGoEnabledCGO.Checked:=LRes.GoEnabledCGO; 415 | cbbGoBuildModes.ItemIndex:=cbbGoBuildModes.Items.IndexOf(LRes.GoBuildMode); 416 | edtGoRoot.Text := Trim(LRes.GoRoot); 417 | chkGoUseEmbed.Checked:=LRes.GoUseEmbed; 418 | end; 419 | end; 420 | end; 421 | 422 | procedure TRes2goOptionsFrame.WriteSettings(AOptions: TAbstractIDEOptions); 423 | var 424 | LRes: TProjectRes2goRes; 425 | begin 426 | if Assigned(MyIDEIntf) and Assigned(LazarusIDE) and Assigned(LazarusIDE.ActiveProject) and Assigned(LazarusIDE.ActiveProject.Resources) then 427 | begin 428 | LRes := TProjectRes2goRes(TAbstractProjectResources(LazarusIDE.ActiveProject.Resources).Resource[TProjectRes2goRes]); 429 | if Assigned(LRes) then 430 | begin 431 | MyIDEIntf.EnabledConvert := chkEanbledConvert.Checked; 432 | MyIDEIntf.OutputPath:= lblOutputPath.Text; 433 | MyIDEIntf.UseOriginalFileName:=chkUseOriginalFileName.Checked; 434 | MyIDEIntf.SaveGfmFile := chkSaveGfmFile.Checked; 435 | MyIDEIntf.OutLang:=TOutLang(cbbLangs.ItemIndex); 436 | MyIDEIntf.PackageName:=Trim(lblPkgName.Text); 437 | if (not MyIDEIntf.UseDefaultWinAppRes) and chkUseDefaultWinAppRes.Checked then 438 | MyIDEIntf.ReConvertRes:= True; 439 | MyIDEIntf.UseDefaultWinAppRes := chkUseDefaultWinAppRes.Checked; 440 | 441 | MyIDEIntf.GoUseTempdll := chkGoUseTempdll.Checked; 442 | MyIDEIntf.GoEnabledFinalizerOn := chkGoEnabledFinalizerOn.Checked; 443 | MyIDEIntf.GoTags := lblGoTags.Text; 444 | MyIDEIntf.GoEnabledCGO:=chkGoEnabledCGO.Checked; 445 | if cbbGoBuildModes.ItemIndex >= 0 then 446 | MyIDEIntf.GoBuildMode := cbbGoBuildModes.Items[cbbGoBuildModes.ItemIndex] 447 | else 448 | MyIDEIntf.GoBuildMode := ''; 449 | MyIDEIntf.GoRoot := Trim(edtGoRoot.Text); 450 | MyIDEIntf.GoUseEmbed:=chkGoUseEmbed.Checked; 451 | 452 | // MyIDEIntf.GoBuildMode:= IfThen(cbbGoBuildModes.ItemIndex >= 0, cbbGoBuildModes.Items[cbbGoBuildModes.ItemIndex], ''); ??????? 453 | 454 | 455 | LRes.OutputPath := MyIDEIntf.OutputPath; 456 | LRes.Enabled := MyIDEIntf.EnabledConvert; 457 | LRes.UseOriginalFileName := MyIDEIntf.UseOriginalFileName; 458 | LRes.SaveGfmFile := MyIDEIntf.SaveGfmFile; 459 | LRes.OutLang:=MyIDEIntf.OutLang; 460 | LRes.PackageName:=MyIDEIntf.PackageName; 461 | LRes.UseDefaultWinAppRes := MyIDEIntf.UseDefaultWinAppRes; 462 | 463 | LRes.GoUseTempdll:=MyIDEIntf.GoUseTempdll; 464 | LRes.GoEnabledFinalizerOn:=MyIDEIntf.GoEnabledFinalizerOn; 465 | LRes.GoTags := MyIDEIntf.GoTags; 466 | LRes.GoEnabledCGO:=MyIDEIntf.GoEnabledCGO; 467 | LRes.GoBuildMode:=MyIDEIntf.GoBuildMode; 468 | LRes.GoRoot:= MyIDEIntf.GoRoot; 469 | LRes.GoUseEmbed:=MyIDEIntf.GoUseEmbed; 470 | end; 471 | end; 472 | end; 473 | 474 | class function TRes2goOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass; 475 | begin 476 | Result := nil;//TProjectIDEOptions; 477 | end; 478 | 479 | 480 | 481 | initialization 482 | //RegisterIDEOptionsGroup(GroupProject, TRes2goIDEOptions); 483 | RegisterProjectResource(TProjectRes2goRes); 484 | RegisterIDEOptionsEditor(GroupProject, TRes2goOptionsFrame, ProjectOptionsRes2go); 485 | 486 | end. 487 | 488 | -------------------------------------------------------------------------------- /res2goplugin.lpk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /res2goplugin.pas: -------------------------------------------------------------------------------- 1 | { This file was automatically created by Lazarus. Do not edit! 2 | This source is only used to compile and install the package. 3 | } 4 | 5 | unit res2goplugin; 6 | 7 | {$warn 5023 off : no warning about unused units} 8 | interface 9 | 10 | uses 11 | res2gomain, res2goOptions, usupports, ugolang, uLangBase, res2goResources, 12 | LazarusPackageIntf; 13 | 14 | implementation 15 | 16 | procedure Register; 17 | begin 18 | RegisterUnit('res2gomain', @res2gomain.Register); 19 | end; 20 | 21 | initialization 22 | RegisterPackage('res2goplugin', @Register); 23 | end. 24 | -------------------------------------------------------------------------------- /res2goresources.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | unit res2goResources; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | resourceString 15 | rsMsgTransformFile = 'Transform file: %s '; 16 | rsAutomaticallyGeneratedByTheRes2go = 'Automatically generated by the res2go IDE plug-in.'; 17 | rsAutomaticallyGeneratedByTheRes2goDoNotEdit = 'Automatically generated by the res2go IDE plug-in, do not edit.'; 18 | rsComponentIsNotSupported = '"%s:%s" is not supported.'; 19 | rsComponentMustBeCapitalizedFirstToBeExported = '"%s:%s" must be capitalized first to be exported.'; 20 | rsRegisterFormResources = 'Register Form Resources'; 21 | 22 | // options frame 23 | rsEnabledConvert = 'Enabled Convert'; 24 | rsUseOriginalFileName = 'Use Original File Name'; 25 | rsSaveGfmFile = 'Save gfm File'; 26 | rsOutputPath = 'Output Path:'; 27 | rsOutputPathEg = 'eg: "code" or "$Path($ProjectFile())code" or "C:\LzUI" '; 28 | rsOutputLang = 'Output Lang:'; 29 | rsPackageName = 'Package Name:'; 30 | rsUseDefaultWinAppRes = 'Use Default winappres'; 31 | rsGoUseTempdll = 'Use "tempdll"'; 32 | rsGoUseTempdllHint = 'Package liblcl into an executable file (macOS is not supported)'; 33 | rsGoEnabledFinalizerOn = 'Enabled "finalizerOn"'; 34 | rsGoEnabledFinalizerOnHint = 'After opening the non-component class can not call the "Free" method'; 35 | rsGoTags = 'Tags:'; 36 | rsDividerBevel1 = 'For Golang'; 37 | rsGoEnabledCGO = 'Enabled CGO'; 38 | rsBuildMode = 'Build mode: '; 39 | rsBuildModeHint = 'If go version>=1.15, please select "exe" mode, otherwise, no need to select.'; 40 | rsGoEnabledEmbed = 'Use "go:embed"(go1.16+)'; 41 | 42 | implementation 43 | 44 | end. 45 | 46 | -------------------------------------------------------------------------------- /ugolang.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | unit ugolang; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | Classes, 16 | SysUtils, 17 | StrUtils, 18 | Forms, 19 | TypInfo, 20 | LazFileUtils, 21 | IDEExternToolIntf, 22 | LazIDEIntf, 23 | CompOptsIntf, 24 | uSupports, 25 | res2goResources, 26 | uLangBase; 27 | 28 | type 29 | 30 | { TGoLang } 31 | 32 | TGoLang = class(TLangBase) 33 | private 34 | FUseGoEmbed: Boolean; 35 | function ParamTypeCov(ASrc: string): string; 36 | function IsBaseType(AType: string): Boolean; 37 | function IsInterfaceType(AType: string): Boolean; 38 | procedure CreateImplFile(AFileName: string; AEvents: array of TEventItem; AFormName: string); 39 | procedure CreateNewMain(AStrs: TStrings; AParam: TProjParam); 40 | function GetPrefixPackage: string; 41 | 42 | function GetPackageImportPath(const AOutPath: string): string; 43 | 44 | procedure AddOrRemoveImports(ALists: TStrings; AAdds, ARemoves: array of string; AUIPackageName: string; AOutPath: string); 45 | procedure ProcessMainFunc(ALists: TStrings; ATitle: string; AUseScaled: Boolean; AForms: array of string); 46 | function GetOS(ATargetOS: string): string; 47 | function GetARCH(ATargetCPU: string): string; 48 | protected 49 | procedure InitTypeLists; override; 50 | procedure InitBaseTypes; override; 51 | function GetResFileExists: Boolean; override; 52 | function GetPackageName: string; override; 53 | public 54 | constructor Create; 55 | function Compile(AParams: TCompileParam): Boolean; override; 56 | 57 | procedure ConvertProjectFile(AParam: TProjParam); override; 58 | function ToEventString(AProp: PPropInfo): string; override; 59 | procedure SaveToFile(AFileName: string; ARoot: TComponent; AEvents: array of TEventItem; AMem: TMemoryStream); override; 60 | procedure ConvertResource(const AResFileName, APath: string); override; 61 | 62 | property UseGoEmbed: Boolean read FUseGoEmbed write FUseGoEmbed; 63 | end; 64 | 65 | var 66 | Golang: TGolang; 67 | 68 | implementation 69 | 70 | 71 | uses 72 | Math; 73 | 74 | { TGoLang } 75 | 76 | constructor TGoLang.Create; 77 | begin 78 | inherited Create; 79 | end; 80 | 81 | function TGoLang.Compile(AParams: TCompileParam): Boolean; 82 | var 83 | LCmd, LCmd2: string; 84 | LTool: TIDEExternalToolOptions; 85 | LOpts: TLazCompilerOptions; 86 | LARCH, LOS: string; 87 | LTags: string = ''; 88 | LIsWindows: Boolean = False; 89 | LLdFlags: string = ''; 90 | LBuildMode: string = ''; 91 | LPaths, LGoRoot: string; 92 | LIParams: string; 93 | begin 94 | Result := False; 95 | if not Assigned(RunExternalTool) then 96 | Exit; 97 | {$ifdef windows} 98 | LIsWindows := True; 99 | {$endif} 100 | 101 | // compiler options 102 | LOpts :=LazarusIDE.ActiveProject.LazCompilerOptions; 103 | LOS := GetOS(LOpts.TargetOS); 104 | LARCH := GetARCH(LOpts.TargetCPU); 105 | 106 | 107 | // -ldflags 108 | 109 | // windowsgui 110 | if LIsWindows and LOpts.Win32GraphicApp then 111 | LLdFlags += ' -H windowsgui'; 112 | // no debug info 113 | if not LOpts.GenerateDebugInfo then 114 | LLDFlags += ' -w'; 115 | // strip symbols 116 | if LOpts.StripSymbols then 117 | LLDFlags += ' -s'; 118 | 119 | LLdFlags := LLdFlags.Trim; 120 | if not LLdFlags.IsEmpty then 121 | LLdFlags := ' -ldflags="' + LLdFlags + '"'; 122 | 123 | // -tags 124 | if AParams.GoTags <> '' then 125 | LTags += AParams.GoTags; 126 | if AParams.GoUseTempdll and (LOS <> 'darwin') and (not LTags.Contains('tempdll')) then 127 | LTags += ' tempdll'; 128 | if AParams.GoEnabledFinalizerOn and (not LTags.Contains('finalizerOn')) then 129 | LTags += ' finalizerOn'; 130 | 131 | LTags := LTags.Trim; 132 | if not LTags.IsEmpty then 133 | LTags := ' -tags="' + LTags + '"'; 134 | 135 | // -buildmode 136 | if AParams.GoBuildMode <> '' then 137 | LBuildMode := ' -buildmode=' + AParams.GoBuildMode; 138 | 139 | // command line 140 | LIParams := ''; 141 | if not AParams.GoUseGoEmbed then // 1.16不支持-i参数了 142 | LIParams := '-i'; 143 | LCmd := Format('build %s%s%s%s -o "%s"', [LIParams, LBuildMode, LLdFlags, LTags, AParams.Output]); 144 | LCmd2 := 'go ' + LCmd; 145 | Logs('Complie Command: ' + LCmd2); 146 | LTool := TIDEExternalToolOptions.Create; 147 | try 148 | LTool.Title := LCmd2; 149 | LTool.Hint := LCmd2; 150 | // 这里要全路径,不然macOS下执行有问题 151 | LGoRoot := AppendPathDelim(AppendPathDelim(AParams.GoRoot) + 'bin'); 152 | if not SysUtils.DirectoryExists(LGoRoot) then 153 | LGoRoot := ''; 154 | LTool.Executable := LGoRoot + 'go'{$ifdef windows}+'.exe'{$endif}; 155 | LTool.WorkingDirectory := AParams.Input; 156 | LTool.CmdLineParams := LCmd; 157 | //Application.GetEnvironmentList(LTool.EnvironmentOverrides); 158 | 159 | if LOS <> '' then 160 | LTool.EnvironmentOverrides.Values['GOOS'] := LOS; 161 | if LARCH <> '' then 162 | LTool.EnvironmentOverrides.Values['GOARCH'] := LARCH; 163 | 164 | // cgo 165 | LTool.EnvironmentOverrides.Values['CGO_ENABLED'] := IfThen(AParams.GoEnabledCGO, '1', '0'); 166 | 167 | // GoRoot 168 | if not AParams.GoRoot.IsEmpty then 169 | begin 170 | LTool.EnvironmentOverrides.Values['GOROOT'] := AParams.GoRoot; 171 | //LPaths := LTool.EnvironmentOverrides.Values['PATH']; 172 | //if not LPaths.EndsWith(';') then 173 | // LPaths := LPaths + ';'; 174 | //LTool.EnvironmentOverrides.Values['PATH'] := LPaths + AppendPathDelim(AParams.GoRoot) + 'bin'; 175 | end; 176 | 177 | 178 | LTool.Parsers.Add(SubToolFPC); 179 | LTool.Parsers.Add(SubToolDefault); 180 | {$ifdef windows} 181 | // 非windows下不需要这个操作 182 | LTool.ShowConsole := True; 183 | LTool.HideWindow := True; 184 | {$endif} 185 | LTool.ResolveMacros := True; 186 | Result := RunExternalTool(LTool); 187 | finally 188 | LTool.Free; 189 | end; 190 | end; 191 | 192 | procedure TGoLang.ConvertProjectFile(AParam: TProjParam); 193 | 194 | function GetForms: TAutoCreateForms; 195 | var 196 | I: Integer; 197 | begin 198 | Result := Self.GetAutoCreateForms; 199 | if not Self.IsMainPackage then 200 | begin 201 | for I := 0 to High(Result) do 202 | Result[I] := Self.PackageName + '.' + Result[I]; 203 | end; 204 | end; 205 | 206 | const 207 | PkgArr: array[0..0] of string = ('_ "github.com/ying32/govcl/pkgs/winappres"'); 208 | 209 | var 210 | LMainFile: TStringList; 211 | LSaveFileName: string; 212 | LMainFileExists: boolean; 213 | begin 214 | LMainFile := TStringList.Create; 215 | try 216 | LSaveFileName := AParam.OutPath + 'main.go'; 217 | LMainFileExists := FileExists(LSaveFileName); 218 | 219 | // 如果不存在 main.go文件,则新建一个 220 | if not LMainFileExists then 221 | CreateNewMain(LMainFile, AParam) 222 | else 223 | begin 224 | // 存在则加载此文件 225 | LMainFile.LoadFromFile(LSaveFileName); 226 | 227 | if AParam.UseDefaultWinAppRes then 228 | AddOrRemoveImports(LMainFile, PkgArr, [], Self.PackageName, AParam.OutPath) 229 | else 230 | AddOrRemoveImports(LMainFile, [], PkgArr, Self.PackageName, AParam.OutPath); 231 | 232 | ProcessMainFunc(LMainFile, AParam.Title, AParam.UseScaled, GetForms); 233 | end; 234 | LMainFile.SaveToFile(LSaveFileName); 235 | finally 236 | LMainFile.Free; 237 | end; 238 | end; 239 | 240 | function TGoLang.ToEventString(AProp: PPropInfo): string; 241 | var 242 | I: Integer; 243 | LFnParam: TFnParam; 244 | LCovName: string; 245 | begin 246 | Result := ''; 247 | // 处理参数 248 | I := 0; 249 | for LFnParam in GetParams(AProp) do 250 | begin 251 | //if LFnParam.Name <> '$self' then 252 | if Pos('$', LFnParam.Name) = 0 then 253 | begin 254 | if I > 1 then 255 | Result += ', '; 256 | 257 | Result += FirstCaseChar(LFnParam.Name) + ' '; // + ' <' + LFlagsStr + '>' + ParamTypeCov(LParamType); 258 | LCovName := ParamTypeCov(LFnParam.&Type); 259 | if ((pfAddress in LFnParam.Flags) or (pfVar in LFnParam.Flags) or (pfOut in LFnParam.Flags)) and not IsInterfaceType(LCovName) then // 要加 * 号的 260 | Result += '*'; 261 | 262 | // 数组 263 | if pfArray in LFnParam.Flags then 264 | Result += '[]'; 265 | 266 | // 包名确认 267 | if pfAddress in LFnParam.Flags then 268 | Result += 'vcl.'; // 包名 269 | if (not IsBaseType(LCovName)) and (not (pfAddress in LFnParam.Flags)) then 270 | Result += 'types.'; 271 | 272 | Result += LCovName; 273 | end; 274 | Inc(I); 275 | end; 276 | end; 277 | 278 | procedure TGoLang.SaveToFile(AFileName: string; ARoot: TComponent; 279 | AEvents: array of TEventItem; AMem: TMemoryStream); 280 | var 281 | LStrStream, LBuffer: TStringStream; 282 | LLines: TStringList; 283 | 284 | procedure WLine(s: string = ''); 285 | begin 286 | LLines.Add(S); 287 | end; 288 | 289 | function GetMaxLength: integer; 290 | var 291 | I: integer; 292 | C: TComponent; 293 | begin 294 | Result := 0; 295 | for I := 0 to ARoot.ComponentCount - 1 do 296 | begin 297 | C := ARoot.Components[I]; 298 | Result := Max(Result, Length(C.Name)); 299 | end; 300 | end; 301 | 302 | function GetIsFrame: boolean; 303 | begin 304 | Result := ARoot is TCustomFrame; 305 | end; 306 | 307 | function ConvertClassName(const ASrc: string): string; 308 | begin 309 | Result := ASrc; 310 | if Result = 'TCalendar' then 311 | Result := 'TMonthCalendar'; 312 | end; 313 | 314 | var 315 | I, LMaxLen: integer; 316 | C: TComponent; 317 | LVarName, LFormName, LTempName: string; 318 | LItem: TEventItem; 319 | LFindEvent: boolean; 320 | LRealEventName: string; 321 | LIsFrame: boolean; 322 | begin 323 | LStrStream := TStringStream.Create(''); 324 | LBuffer := TStringStream.Create(''); 325 | LLines := TStringList.Create; 326 | try 327 | WLine('// ' + rsAutomaticallyGeneratedByTheRes2goDoNotEdit); 328 | WLine('package ' + PackageName); 329 | WLine; 330 | WLine('import ('); 331 | WLine(' "github.com/ying32/govcl/vcl"'); 332 | if UseGoEmbed then 333 | WLine(' _ "embed"'); 334 | WLine(')'); 335 | WLine; 336 | LFormName := ARoot.Name; 337 | 338 | LIsFrame := False; 339 | if GetIsFrame then 340 | LIsFrame := True; 341 | 342 | WLine(Format('type T%s struct {', [LFormName])); 343 | if LIsFrame then 344 | WLine(' *vcl.TFrame') 345 | else 346 | WLine(' *vcl.TForm'); 347 | LMaxLen := GetMaxLength; 348 | for I := 0 to ARoot.ComponentCount - 1 do 349 | begin 350 | C := ARoot.Components[I]; 351 | 352 | if not IsSupportsComponent(C.ClassName) then 353 | begin 354 | CtlWriteln(mluError, rsComponentIsNotSupported, [LFormName + '.' + C.Name, C.ClassName]); 355 | //Exit; 356 | end; 357 | 358 | if C.Name = '' then 359 | Continue; 360 | if CharInSet(C.Name[1], ['a'..'z', '_']) then 361 | begin 362 | CtlWriteln(mluWarning, rsComponentMustBeCapitalizedFirstToBeExported, [LFormName + '.' + C.Name, C.ClassName]); 363 | Continue; 364 | end; 365 | //CtlWriteln('%s: %s', [C^.Name, C^.ClassName]); 366 | // 这里查找下,当前组件有事件,但是这个事件是共享的。 367 | LRealEventName := ''; 368 | LFindEvent := False; 369 | for LItem in AEvents do 370 | begin 371 | if LItem.InstanceName = C.Name then 372 | begin 373 | // 当前实际关联的事件不是自己的,比如 Button2Click != Button1Click 374 | if C.Name + LItem.EventTypeName <> LItem.EventName then 375 | begin 376 | LFindEvent := True; 377 | if LRealEventName <> '' then 378 | LRealEventName := LRealEventName + ','; 379 | LRealEventName := LRealEventName + 'On' + LItem.EventName; 380 | end; 381 | end; 382 | end; 383 | // CtlWriteln('LReadEventName: %s', [LReadEventName]); 384 | 385 | LTempName := Copy(C.Name + DupeString(#32, LMaxLen), 1, LMaxLen); 386 | if LFindEvent and (LRealEventName <> '') then 387 | WLine(Format(' %s *%s.%s `events:"%s"`', 388 | [LTempName, 'vcl', ConvertClassName(C.ClassName), LRealEventName])) 389 | else 390 | WLine(Format(' %s *%s.%s', [LTempName, 'vcl', ConvertClassName(C.ClassName)])); 391 | end; 392 | WLine; 393 | // 添加一个隐式字段,用于私有,方便写一些结构定自定义的变量什么的 394 | WLine(' //' + PrivateFiledsFlagStr); // 这是一个查找标识 395 | WLine(Format(' ' + PrivateFiledsStr, [LFormName])); 396 | WLine('}'); 397 | WLine; 398 | if not LIsFrame then 399 | begin 400 | WLine(Format('var %s *T%s', [LFormName, LFormName])); 401 | WLine; 402 | WLine; 403 | WLine; 404 | end; 405 | WLine; 406 | 407 | begin 408 | 409 | LVarName := LFormName + 'Bytes'; 410 | 411 | // 包名不为main时,起始不变为小写。 412 | //if PackageName.Equals('main') or PackageName.IsEmpty then 413 | LVarName[1] := LowerCase(LVarName[1]); 414 | 415 | if not LIsFrame then 416 | begin 417 | WLine(Format('// vcl.Application.CreateForm(&%s)', [LFormName])); 418 | WLine; 419 | end; 420 | // 添加一个默认构建的,不使用Application.CreateForm 421 | WLine(Format('func New%s(owner vcl.IComponent) (root *T%s) {', 422 | [LFormName, LFormName])); 423 | if not LIsFrame then 424 | WLine(Format(' vcl.CreateResForm(owner, &root)', [])) 425 | else 426 | WLine(Format(' vcl.CreateResFrame(owner, &root)', [])); 427 | WLine(' return'); 428 | WLine('}'); 429 | WLine(''); 430 | 431 | // 嵌入资源 432 | if UseGoEmbed then 433 | begin 434 | WLine('//go:embed resources/' + ChangeFileExt(ExtractFileName(AFileName), '.gfm')); 435 | WLine(Format('var %s []byte', [LVarName])); 436 | end else 437 | begin 438 | LBuffer.WriteString(Format('var %s = []byte("', [LVarName])); 439 | for I := 0 to AMem.Size - 1 do 440 | begin 441 | LBuffer.WriteString('\x'); 442 | LBuffer.WriteString(PByte(PByte(AMem.Memory) + I)^.ToHexString(2)); 443 | end; 444 | LBuffer.WriteString('")'); 445 | WLine(LBuffer.DataString); 446 | end; 447 | 448 | WLine(''); 449 | WLine('// ' + rsRegisterFormResources); 450 | if LIsFrame then 451 | WLine(Format('var _ = vcl.RegisterFormResource(T%s{}, &%s)', 452 | [LFormName, LVarName])) 453 | else 454 | WLine(Format('var _ = vcl.RegisterFormResource(%s, &%s)', 455 | [LFormName, LVarName])); 456 | end; 457 | LStrStream.WriteString(LLines.Text); 458 | LStrStream.SaveToFile(AFileName + '.go'); 459 | finally 460 | LLines.Free; 461 | LBuffer.Free; 462 | LStrStream.Free; 463 | end; 464 | // 一定创建,因为多加了个 465 | CreateImplFile(AFileName, AEvents, LFormName); 466 | end; 467 | 468 | procedure TGoLang.ConvertResource(const AResFileName, APath: string); 469 | const 470 | PlatformStr: array[Boolean] of string = ('pe-i386', 'pe-x86-64'); 471 | 472 | var 473 | LWindResFileName: string; 474 | 475 | function GetCmdLine(AOutFileName: string; AIsAmd64: Boolean): string; 476 | begin 477 | Result := Format('%s -i "%s" -J res -o "%s%s" -F %s', [LWindResFileName, AResFileName, APath, AOutFileName, PlatformStr[AIsAmd64]]); 478 | end; 479 | 480 | begin 481 | if not FileExists(AResFileName) then 482 | Exit; 483 | LWindResFileName := WindResFileName; 484 | if FileExists(LWindResFileName) then 485 | LWindResFileName := '"' + LWindResFileName + '"' 486 | else 487 | LWindResFileName := 'windres'; 488 | ExecuteCommand([GetCmdLine('defaultRes_windows_386.syso', False), GetCmdLine('defaultRes_windows_amd64.syso', True)], True); 489 | 490 | //olRust, olNim: 491 | // if (OutLang = olNim) or ((OutLang = olRust) and (IsGNU)) then 492 | // ExecuteCommand([GetCmdLine('appres_386.o', False), GetCmdLine('appres_amd64.o', True)], True); 493 | end; 494 | 495 | procedure TGoLang.CreateImplFile(AFileName: string; AEvents: array of TEventItem; AFormName: string); 496 | var 497 | LMName, LTemp, LCode, LPrivateName, LFlags: string; 498 | LItem: TEventItem; 499 | LStream: TStringStream; 500 | LExists, LB: boolean; 501 | LListStr: TStringList; 502 | I: integer; 503 | begin 504 | AFileName += 'Impl.go'; 505 | LStream := TStringStream.Create(''); 506 | try 507 | LExists := FileExists(AFileName); 508 | LListStr := TStringList.Create; 509 | try 510 | // 不存在,则添加 511 | if not LExists then 512 | begin 513 | LListStr.Add(''); 514 | LListStr.Add('package ' + PackageName); 515 | LListStr.Add(''); 516 | if Length(AEvents) > 0 then 517 | begin 518 | LListStr.Add('import ('); 519 | LListStr.Add(' "github.com/ying32/govcl/vcl"'); 520 | LListStr.Add(')'); 521 | end; 522 | end 523 | else 524 | begin 525 | // 反之加载 526 | LStream.LoadFromFile(AFileName); 527 | LTemp := LStream.DataString; 528 | LListStr.Text := LTemp; 529 | 530 | // 有事件时检查下有没有添加govcl包 531 | if Length(AEvents) > 0 then 532 | begin 533 | if Pos('import', LTemp) = 0 then 534 | begin 535 | I := 0; 536 | while I < LListStr.Count do 537 | begin 538 | if Trim(LListStr[I]).StartsWith('package') then 539 | begin 540 | Inc(I); 541 | LListStr.Insert(I, ')'); 542 | LListStr.Insert(I, ' "github.com/ying32/govcl/vcl"'); 543 | LListStr.Insert(I, 'import ('); 544 | LListStr.Insert(I, ''); 545 | Break; 546 | end; 547 | Inc(I); 548 | end; 549 | end; 550 | end; 551 | end; 552 | 553 | 554 | // 添加事件 555 | for LItem in AEvents do 556 | begin 557 | LMName := Format('On%s', [LItem.EventName]); 558 | //CtlWriteln('method name: %s', [LMName]); 559 | LCode := Format(#13#10'func (f *T%s) %s(%s) {'#13#10#13#10'}'#13#10, 560 | [AFormName, LMName, LItem.EventParams]); 561 | // 不存在不查找了 562 | if not LExists then 563 | begin 564 | if Pos(LMName, LListStr.Text) = 0 then 565 | LListStr.Add(LCode); 566 | end else 567 | begin 568 | // 没有找到,则添加 569 | if Pos(LMName, LListStr.Text) = 0 then 570 | LListStr.Add(LCode); 571 | end; 572 | end; 573 | 574 | // 检查私有变量结构是否存在 575 | LPrivateName := Format(PrivateFiledsStr, [AFormName]); 576 | // 不存在,则添加 577 | if Pos(PrivateFiledsFlagStr, LListStr.Text) = 0 then 578 | begin 579 | I := 0; 580 | while I < LListStr.Count do 581 | begin 582 | // 在首个func前几行插入 583 | LFlags := 'import'; 584 | LB := (not LExists) and (Length(AEvents) = 0); 585 | if LB then 586 | LFlags := 'package'; 587 | if Trim(LListStr[I]).StartsWith(LFlags) then 588 | begin 589 | if not LB then 590 | begin 591 | repeat 592 | Inc(I); 593 | until Trim(LListStr[I]).StartsWith(')'); 594 | end; 595 | Inc(I); 596 | LListStr.Insert(I, ''); 597 | LListStr.Insert(I, '}'); 598 | LListStr.Insert(I, 'type ' + LPrivateName + ' struct {'); 599 | LListStr.Insert(I, '//' + PrivateFiledsFlagStr); 600 | LListStr.Insert(I, ''); 601 | Break; 602 | end; 603 | Inc(I); 604 | end; 605 | end 606 | else 607 | begin 608 | // 如果存在,则更新,因为防止把窗口名称改了,这里同步更新 609 | for I := 0 to LListStr.Count - 1 do 610 | begin 611 | // 在首个func前几行插入 612 | if LListStr[I].Contains(PrivateFiledsFlagStr) and LListStr[I].Contains('//') then 613 | begin 614 | LListStr[I + 1] := 'type ' + LPrivateName + ' struct {'; 615 | Break; 616 | end; 617 | end; 618 | end; 619 | 620 | // 这里是不是还得处理下,将窗口名称做一次替换 621 | //f *TFrmMain 622 | LStream.Clear; 623 | LStream.WriteString(LListStr.Text); 624 | finally 625 | LListStr.Free; 626 | end; 627 | LStream.SaveToFile(AFileName); 628 | finally 629 | LStream.Free; 630 | end; 631 | end; 632 | 633 | procedure TGoLang.CreateNewMain(AStrs: TStrings; AParam: TProjParam); 634 | var 635 | LForms: TAutoCreateForms; 636 | LS: string; 637 | begin 638 | with AStrs do 639 | begin 640 | Add('// ' + rsAutomaticallyGeneratedByTheRes2go); 641 | Add('package main'); // main.go文件始终都必须为main 642 | Add(''); 643 | Add('import ('); 644 | Add(' "github.com/ying32/govcl/vcl"'); 645 | // winappres 646 | if AParam.UseDefaultWinAppRes then 647 | Add(' _ "github.com/ying32/govcl/pkgs/winappres"'); 648 | 649 | // 初始添加一个本地导入包的 650 | // 还要判断当前目标目录在GOPATH中???不然要应用不同的规则 651 | if not IsMainPackage then 652 | Add(' "%s"', [GetPackageImportPath(AParam.OutPath)]); 653 | 654 | 655 | Add(')'); 656 | Add(''); 657 | Add('func main() {'); 658 | 659 | // scaled 660 | if AParam.UseScaled then 661 | Add(' vcl.Application.SetScaled(true)'); 662 | 663 | // title 664 | if AParam.Title <> '' then 665 | Add(' vcl.Application.SetTitle("%s")', [AParam.Title]); 666 | 667 | Add(' vcl.Application.Initialize()'); 668 | Add(' vcl.Application.SetMainFormOnTaskBar(true)'); 669 | 670 | // forms 671 | LForms := Self.GetAutoCreateForms; 672 | for LS in LForms do 673 | begin 674 | Add(' vcl.Application.CreateForm(&%s%s)', [GetPrefixPackage, LS]); 675 | end; 676 | 677 | Add(' vcl.Application.Run()'); 678 | Add('}'); 679 | end; 680 | end; 681 | 682 | function TGoLang.GetPrefixPackage: string; 683 | begin 684 | Result := ''; 685 | if not IsMainPackage then 686 | Result := PackageName + '.'; 687 | end; 688 | 689 | function TGoLang.GetPackageImportPath(const AOutPath: string): string; 690 | var 691 | LGoPaths, LPath, LCPath, LCOPath, LRealPath: string; 692 | LPaths: array of string; 693 | LP: Integer; 694 | begin 695 | Result := ''; 696 | if IsMainPackage then 697 | Exit; 698 | LGoPaths := GetEnvironmentVariable('GOPATH'); 699 | if not LGoPaths.IsEmpty then 700 | begin 701 | LPaths := LGoPaths.Split([';']); 702 | for LPath in LPaths do 703 | begin 704 | LCPath := AppendPathDelim(AppendPathDelim(LPath.Trim) + 'src'); 705 | LCOPath := CleanAndExpandDirectory(AOutPath); //AppendPathDelim(AOutPath); 706 | if SameText(LCPath, Copy(LCOPath, 1, Length(LCPath))) then 707 | begin 708 | LRealPath := Copy(LCOPath, Length(LCPath) + 1, Length(LCOPath) - Length(LCPath) - 1); 709 | Exit(LRealPath.Replace('\', '/') + '/' + PackageName); 710 | end; 711 | end; 712 | end; 713 | Result := './' + PackageName; 714 | end; 715 | 716 | procedure TGoLang.AddOrRemoveImports(ALists: TStrings; AAdds, 717 | ARemoves: array of string; AUIPackageName: string; AOutPath: string); 718 | const 719 | Keywords: array[0..3] of string = ('var', 'const', 'type', 'func'); 720 | 721 | type 722 | TImportItem = record 723 | Path: string; 724 | OrigPath: string; 725 | &Single: Boolean; 726 | LineNumber: Integer; 727 | end; 728 | 729 | var 730 | 731 | I: Integer; 732 | LS: string; 733 | LIsEnd: Boolean; 734 | LImports: array of TImportItem; 735 | LPkgLineNumber: Integer; // package 736 | LInsertStartIndex: Integer; 737 | LIsSingle: Boolean; 738 | 739 | procedure UpdateLineNumber(AStart: Integer; AValue: Integer); 740 | var 741 | J: Integer; 742 | begin 743 | for J := AStart to High(LImports) do 744 | LImports[J].LineNumber += AValue; 745 | end; 746 | 747 | function GetRealImportPath(const APath: string): string; 748 | var 749 | LP1, LP2: Integer; 750 | begin 751 | LP1 := Pos('"', APath); 752 | if LP1 > 0 then 753 | begin 754 | LP2 := Pos('"', APath, LP1 + 1); 755 | if LP2 > 0 then 756 | Exit(Copy(APath, LP1+1, LP2 - LP1 - 1)); 757 | end; 758 | Result := APath; 759 | end; 760 | 761 | procedure AddImportItem(APath: string; ASingle: Boolean); 762 | begin 763 | SetLength(LImports, Length(LImports) + 1); 764 | with LImports[High(LImports)] do 765 | begin 766 | OrigPath := APath; 767 | Path := GetRealImportPath(APath); 768 | &Single := ASingle; 769 | LineNumber := I; 770 | end; 771 | end; 772 | 773 | function LastItem: TImportItem; 774 | begin 775 | Result := LImports[High(LImports)]; 776 | end; 777 | 778 | function IndexPkgNameOf(APath: string): Integer; 779 | var 780 | J: Integer; 781 | begin 782 | Result := -1; 783 | for J := 0 to High(LImports) do 784 | if LImports[J].Path = GetRealImportPath(APath) then 785 | Exit(J); 786 | end; 787 | 788 | function IndexUIPkgNameOf: Integer; 789 | var 790 | J: Integer; 791 | begin 792 | Result := -1; 793 | for J := 0 to High(LImports) do 794 | if LImports[J].Path.EndsWith('/'+ AUIPackageName) then 795 | Exit(J); 796 | end; 797 | 798 | function InKeyWords: Boolean; 799 | var 800 | LKey: string; 801 | begin 802 | Result := False; 803 | for LKey in Keywords do 804 | begin 805 | if LS.StartsWith(LKey) then 806 | Exit(True); 807 | end; 808 | end; 809 | 810 | function LineStr: string; 811 | begin 812 | Result := ALists[I].Trim; 813 | end; 814 | 815 | procedure CheckComment; 816 | begin 817 | if LS.StartsWith('/*') then 818 | begin 819 | repeat 820 | Inc(I); 821 | LS := LineStr; 822 | until LS.StartsWith('*/') or LS.EndsWith('*/') or (I >= ALists.Count-1); 823 | Inc(I); 824 | LS := LineStr; 825 | end; 826 | end; 827 | 828 | begin 829 | 830 | I := 0; 831 | while I < ALists.Count do 832 | begin 833 | LS := LineStr; 834 | CheckComment; 835 | if LS.StartsWith('package') then 836 | LPkgLineNumber := I 837 | else 838 | if LS.StartsWith('import') then 839 | begin 840 | if LS.IndexOf('(') >= 6 then 841 | begin 842 | repeat 843 | Inc(I); 844 | LS := LineStr; 845 | CheckComment; 846 | LIsEnd := LS.StartsWith(')'); 847 | if (not LIsEnd) and (not LS.IsEmpty) then 848 | AddImportItem(LS, False); 849 | until LIsEnd or (I >= ALists.Count-1); 850 | end else 851 | begin 852 | AddImportItem(Copy(LS, 7, Length(LS)-6).Trim, True); 853 | end; 854 | end; 855 | if InKeyWords then 856 | Break; 857 | Inc(I); 858 | end; 859 | 860 | // 添加测试 861 | if (Length(ARemoves) > 0) and (Length(LImports) > 0) then 862 | begin 863 | // 删除 864 | for LS in ARemoves do 865 | begin 866 | I := IndexPkgNameOf(LS); 867 | if I <> -1 then 868 | begin 869 | ALists.Delete(LImports[I].LineNumber); 870 | UpdateLineNumber(I, -1); 871 | end; 872 | end; 873 | end; 874 | 875 | if Length(AAdds) > 0 then 876 | begin 877 | if Length(LImports) > 0 then 878 | begin 879 | with LastItem do 880 | begin 881 | LInsertStartIndex := LineNumber; 882 | LIsSingle := &Single; 883 | end; 884 | end else 885 | begin 886 | LInsertStartIndex := LPkgLineNumber + 2; 887 | ALists.Insert(LInsertStartIndex, ')'); 888 | ALists.Insert(LInsertStartIndex, 'import ('); 889 | LIsSingle := False; 890 | end; 891 | // 添加 892 | for LS in AAdds do 893 | begin 894 | if IndexPkgNameOf(LS) = -1 then 895 | begin 896 | if LIsSingle then 897 | ALists.Insert(LInsertStartIndex + 1, 'import ' + LS) 898 | else 899 | ALists.Insert(LInsertStartIndex + 1, ' ' + LS); 900 | UpdateLineNumber(I, 1); 901 | end; 902 | end; 903 | end; 904 | 905 | // 独立检查的 906 | if (AUIPackageName <> '') and (AUIPackageName <> 'main') and (Length(LImports) > 0) then 907 | begin 908 | I := IndexUIPkgNameOf; 909 | if I = -1 then 910 | begin 911 | with LastItem do 912 | begin 913 | LS := '"' + GetPackageImportPath(AOutPath) + '"'; 914 | if &Single then 915 | ALists.Insert(LineNumber + 1, 'import ' + LS) 916 | else 917 | ALists.Insert(LineNumber + 1, ' ' + LS); 918 | end; 919 | end; 920 | end; 921 | end; 922 | 923 | procedure TGoLang.ProcessMainFunc(ALists: TStrings; ATitle: string; 924 | AUseScaled: Boolean; AForms: array of string); 925 | type 926 | TAppItem = record 927 | Name: string; 928 | UsePkgName: Boolean; 929 | LineNumber: Integer; 930 | end; 931 | 932 | var 933 | I, N: Integer; 934 | LS: string; 935 | LUsePkgName: Boolean; 936 | LLineArr: array of string; 937 | LApps: array of TAppItem; 938 | 939 | procedure AddItem(AName: string); 940 | begin 941 | SetLength(LApps, Length(LApps) + 1); 942 | with LApps[High(LApps)] do 943 | begin 944 | Name := AName; 945 | LineNumber := I; 946 | end; 947 | end; 948 | 949 | procedure UpdateLineNumber(AStart: Integer; AValue: Integer); 950 | var 951 | J: Integer; 952 | begin 953 | for J := AStart to High(LApps) do 954 | LApps[J].LineNumber += AValue; 955 | end; 956 | 957 | function LineStr: string; 958 | begin 959 | Result := ALists[I].Trim; 960 | end; 961 | 962 | procedure CheckComment; 963 | begin 964 | if LS.StartsWith('/*') then 965 | begin 966 | repeat 967 | Inc(I); 968 | LS := LineStr; 969 | until LS.StartsWith('*/') or LS.EndsWith('*/') or (I >= ALists.Count-1); 970 | Inc(I); 971 | LS := LineStr; 972 | end; 973 | end; 974 | 975 | function IndexNameOf(const AName: string): Integer; 976 | var 977 | J: Integer; 978 | begin 979 | Result := -1; 980 | for J := 0 to High(LApps) do 981 | begin 982 | if SameText(LApps[J].Name, AName) then 983 | Exit(J); 984 | end; 985 | end; 986 | 987 | function RemoveAllCreateForm: Integer; 988 | var 989 | J: Integer; 990 | begin 991 | Result := -1; 992 | for J := 0 to High(LApps) do 993 | begin 994 | if SameText(LApps[J].Name, 'CreateForm') then 995 | begin 996 | ALists.Delete(LApps[J].LineNumber); 997 | UpdateLineNumber(J, -1); 998 | if Result = -1 then 999 | Result := LApps[J].LineNumber + 1; 1000 | end; 1001 | end; 1002 | end; 1003 | 1004 | function GetPkgName: string; 1005 | begin 1006 | Result := ''; 1007 | if LUsePkgName then 1008 | Result := 'vcl.'; 1009 | end; 1010 | 1011 | begin 1012 | I := 0; 1013 | while I < ALists.Count do 1014 | begin 1015 | LS := LineStr; 1016 | if LS.StartsWith('func main()') then 1017 | begin 1018 | Inc(I); 1019 | while I < ALists.Count do 1020 | begin 1021 | LS := LineStr; 1022 | CheckComment; 1023 | LLineArr := LS.Split(['.', '(']); 1024 | if Length(LLineArr) >= 2 then 1025 | begin 1026 | if LLineArr[0].Equals('vcl') and LLineArr[1].Equals('Application') then 1027 | begin 1028 | if Length(LLineArr) >= 3 then 1029 | begin 1030 | AddItem(LLineArr[2].Trim); 1031 | LUsePkgName := True; 1032 | end; 1033 | end 1034 | else if LLineArr[0] = 'Application' then 1035 | begin 1036 | AddItem(LLineArr[1].Trim); 1037 | LUsePkgName := False; 1038 | end; 1039 | end; 1040 | Inc(I); 1041 | end; 1042 | Break; 1043 | end; 1044 | Inc(I); 1045 | end; 1046 | 1047 | 1048 | // SetTitle 1049 | I := IndexNameOf('SetTitle'); 1050 | if ATitle = '' then 1051 | begin 1052 | if I <> -1 then 1053 | begin 1054 | ALists.Delete(LApps[I].LineNumber); 1055 | UpdateLineNumber(I, -1); 1056 | end; 1057 | end else 1058 | begin 1059 | LS := Format(' %sApplication.SetTitle("%s")', [GetPkgName, ATitle]); 1060 | if I = -1 then 1061 | begin 1062 | I := IndexNameOf('Initialize'); 1063 | ALists.Insert(LApps[I].LineNumber, LS); 1064 | UpdateLineNumber(I, 1); 1065 | end else 1066 | ALists[LApps[I].LineNumber] := LS; 1067 | end; 1068 | 1069 | 1070 | // SetScaled 1071 | I := IndexNameOf('SetScaled'); 1072 | LS := Format(' %sApplication.SetScaled(%s)', [GetPkgName, BoolToStr(AuseScaled, True).ToLower]); 1073 | if I = -1 then 1074 | begin 1075 | I := IndexNameOf('Initialize'); 1076 | ALists.Insert(LApps[I].LineNumber, LS); 1077 | UpdateLineNumber(I, 1); 1078 | end else 1079 | ALists[LApps[I].LineNumber] := LS; 1080 | 1081 | // Remove All 1082 | N := RemoveAllCreateForm; 1083 | 1084 | // Add Forms 1085 | for I := High(AForms) downto 0 do 1086 | ALists.Insert(N, Format(' %sApplication.CreateForm(&%s)', [GetPkgName, AForms[I]])); 1087 | 1088 | end; 1089 | 1090 | function TGoLang.GetOS(ATargetOS: string): string; 1091 | begin 1092 | Result := ''; 1093 | // GOOS 1094 | if SameText(ATargetOS, 'Darwin') or SameText(ATargetOS, 'MacOS') then 1095 | Result := 'darwin' 1096 | else if SameText(ATargetOS, 'Win32') or SameText(ATargetOS, 'Win64') then 1097 | Result := 'windows' 1098 | else if SameTExt(ATargetOS, 'Linux') then 1099 | Result := 'linux'; 1100 | end; 1101 | 1102 | function TGoLang.GetARCH(ATargetCPU: string): string; 1103 | begin 1104 | Result := ''; 1105 | // GOARCh 1106 | if SameText(ATargetCPU, 'arm') then 1107 | Result := 'arm' 1108 | else if SameText(ATargetCPU, 'i386') then 1109 | Result := '386' 1110 | else if SameText(ATargetCPU, 'x86_64') then 1111 | Result := 'amd64'; 1112 | end; 1113 | 1114 | procedure TGoLang.InitTypeLists; 1115 | begin 1116 | with FTypeLists do 1117 | begin 1118 | Add('TObject', 'IObject'); 1119 | Add('Boolean', 'bool'); 1120 | Add('Integer', 'int32'); 1121 | Add('Word', 'uint16'); 1122 | Add('LongInt', 'int32'); 1123 | Add('TCustomTreeView', 'TTreeView'); 1124 | Add('TCustomListView', 'TListView'); 1125 | Add('TConstraintSize', 'int32'); 1126 | Add('AnsiString', 'string'); 1127 | Add('Int64', 'int64'); 1128 | Add('UInt64', 'uint64'); 1129 | Add('WideString', 'string'); 1130 | Add('Pointer', 'uintptr'); 1131 | end; 1132 | end; 1133 | 1134 | procedure TGoLang.InitBaseTypes; 1135 | begin 1136 | with FBaseTypes do 1137 | begin 1138 | Add('bool'); 1139 | Add('int32'); 1140 | Add('uint16'); 1141 | Add('uint'); 1142 | Add('int'); 1143 | Add('int16'); 1144 | Add('byte'); 1145 | Add('uint8'); 1146 | Add('uint32'); 1147 | Add('int8'); 1148 | Add('string'); 1149 | Add('int64'); 1150 | Add('uint64'); 1151 | Add('uintptr'); 1152 | end; 1153 | end; 1154 | 1155 | function TGoLang.GetResFileExists: Boolean; 1156 | begin 1157 | Result:= FileExists('') or FileExists(''); 1158 | end; 1159 | 1160 | function TGoLang.GetPackageName: string; 1161 | begin 1162 | Result:=inherited GetPackageName; 1163 | if Result = '' then 1164 | Result := 'main'; 1165 | end; 1166 | 1167 | function TGoLang.ParamTypeCov(ASrc: string): string; 1168 | var 1169 | LV: string; 1170 | begin 1171 | Result := ASrc; 1172 | if FTypeLists.TryGetData(ASrc, LV) then 1173 | Result := LV; 1174 | end; 1175 | 1176 | function TGoLang.IsBaseType(AType: string): Boolean; 1177 | begin 1178 | Result := FBaseTypes.IndexOf(AType) <> -1; 1179 | end; 1180 | 1181 | function TGoLang.IsInterfaceType(AType: string): Boolean; 1182 | begin 1183 | Result := AType.Equals('IObject') or AType.Equals('IComponent') or AType.Equals('IControl') or AType.Equals('IWinControl'); 1184 | end; 1185 | 1186 | 1187 | initialization 1188 | GoLang := TGoLang.Create; 1189 | 1190 | finalization 1191 | FreeAndNil(GoLang); 1192 | 1193 | end. 1194 | 1195 | -------------------------------------------------------------------------------- /ulangbase.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | unit uLangBase; 9 | 10 | {$mode objfpc}{$H+} 11 | {$modeswitch advancedrecords} 12 | //{$modeswitch class} 13 | 14 | interface 15 | 16 | uses 17 | Classes, 18 | SysUtils, 19 | StrUtils, 20 | Forms, 21 | TypInfo, 22 | LazFileUtils, 23 | IDEExternToolIntf, 24 | LazIDEIntf, 25 | uSupports, 26 | res2goResources, 27 | process; 28 | 29 | type 30 | 31 | { TLangBase } 32 | 33 | TFnParam = record 34 | Name: string; 35 | &Type: string; 36 | Flags: TParamFlags; 37 | end; 38 | 39 | TFnParams = array of TFnParam; 40 | 41 | TAutoCreateForms = array of string; 42 | 43 | TCompileParam = record 44 | Input: string; 45 | Output: string; 46 | 47 | // for Golang 48 | GoUseTempdll: Boolean; 49 | GoEnabledFinalizerOn: Boolean; 50 | GoTags: string; 51 | GoEnabledCGO: Boolean; 52 | GoBuildMode: string; 53 | GoRoot: string; 54 | GoUseGoEmbed: Boolean; 55 | end; 56 | 57 | { TProjParam } 58 | 59 | TProjParam = record 60 | Title: string; 61 | UseScaled: Boolean; 62 | UseDefaultWinAppRes: Boolean; 63 | OutPath: string; 64 | public 65 | constructor Create(AOutPath, ATitle: string; AUseScaled, AUseDefaultWinAppRes: Boolean); 66 | end; 67 | 68 | TLangBase = class 69 | private 70 | FPackageName: string; 71 | 72 | function GetProjectLPRFileName: string; 73 | function GetWindResFileName: string; 74 | protected 75 | FTypeLists: TTypeLists; 76 | FBaseTypes: TTypeLists; 77 | 78 | function GetPackageName: string; virtual; 79 | procedure InitTypeLists; virtual; abstract; 80 | procedure InitBaseTypes; virtual; abstract; 81 | function GetParams(AProp: PPropInfo): TFnParams; 82 | function FirstCaseChar(Astr: string): string; 83 | function GetAutoCreateForms: TAutoCreateForms; 84 | function GetResFileExists: Boolean; virtual; 85 | public 86 | constructor Create; 87 | destructor Destroy; override; 88 | function Compile(AParams: TCompileParam): Boolean; virtual; abstract; 89 | 90 | procedure ExecuteCommand(const ACmds: array of string; AWait: Boolean; AShow: Boolean = False; AWorkDir: string = ''); overload; 91 | procedure ExecuteCommand(const ACmd: string; AWait: Boolean; AShow: Boolean = False; AWorkDir: string = ''); overload; 92 | function IsMainPackage: Boolean; 93 | 94 | property PackageName: string read GetPackageName write FPackageName; 95 | property ProjectLPRFileName: string read GetProjectLPRFileName; 96 | property WindResFileName: string read GetWindResFileName; 97 | property ResFileExists: Boolean read GetResFileExists; 98 | 99 | procedure ConvertProjectFile(AParam: TProjParam); virtual; abstract; 100 | function ToEventString(AProp: PPropInfo): string; virtual; abstract; 101 | procedure SaveToFile(AFileName: string; ARoot: TComponent; AEvents: array of TEventItem; AMem: TMemoryStream); virtual; abstract; 102 | procedure ConvertResource(const AResFileName, APath: string); virtual; abstract; 103 | end; 104 | 105 | implementation 106 | 107 | { TProjParam } 108 | 109 | constructor TProjParam.Create(AOutPath, ATitle: string; AUseScaled, 110 | AUseDefaultWinAppRes: Boolean); 111 | begin 112 | Self.OutPath := AOutPath; 113 | Self.Title:=ATitle; 114 | Self.UseScaled:=AUseScaled; 115 | Self.UseDefaultWinAppRes := AUseDefaultWinAppRes; 116 | end; 117 | 118 | { TLangBase } 119 | 120 | 121 | constructor TLangBase.Create; 122 | begin 123 | inherited Create; 124 | FTypeLists := TTypeLists.Create; 125 | FBaseTypes := TTypeLists.Create; 126 | 127 | InitTypeLists; 128 | InitBaseTypes; 129 | end; 130 | 131 | destructor TLangBase.Destroy; 132 | begin 133 | FTypeLists.Free; 134 | FBaseTypes.Free; 135 | inherited Destroy; 136 | end; 137 | 138 | function TLangBase.GetProjectLPRFileName: string; 139 | begin 140 | Result := ChangeFileExt(LazarusIDE.ActiveProject.ProjectInfoFile, '.lpr'); 141 | end; 142 | 143 | function TLangBase.GetPackageName: string; 144 | begin 145 | Result := FPackageName; 146 | end; 147 | 148 | function TLangBase.GetResFileExists: Boolean; 149 | begin 150 | Result := False; 151 | end; 152 | 153 | function TLangBase.GetWindResFileName: string; 154 | begin 155 | Result := 'windres'{$ifdef windows}+'.exe'{$endif}; 156 | Result := AppendPathDelim(ExtractFilePath(LazarusIDE.GetFPCompilerFilename)) + Result; 157 | end; 158 | 159 | function TLangBase.GetParams(AProp: PPropInfo): TFnParams; 160 | var 161 | LTypeData: PTypeData; 162 | I: Integer; 163 | 164 | LFlags: TParamFlags = []; 165 | LParamName: string = ''; 166 | LParamType: string = ''; 167 | LMem: TMemoryStream; 168 | LLen: Byte = 0; 169 | begin 170 | Result := nil; 171 | // 处理参数 172 | if AProp <> nil then 173 | begin 174 | LTypeData := GetTypeData(AProp^.PropType); 175 | if Assigned(LTypeData) then 176 | begin 177 | //mkClassProcedure,mkClassFunction 178 | LMem := TMemoryStream.Create; 179 | try 180 | LMem.Write(LTypeData^.ParamList[0], SizeOf(LTypeData^.ParamList)); 181 | LMem.Position:=0; 182 | 183 | SetLength(Result, LTypeData^.ParamCount); 184 | for I := 0 to LTypeData^.ParamCount - 1 do 185 | begin 186 | LMem.Read(LFlags, SizeOf(TParamFlags)); 187 | // name 188 | LMem.Read(LLen, 1); 189 | SetLength(LParamName, LLen); 190 | 191 | LMem.Read(LParamName[1], LLen); 192 | // type 193 | LMem.Read(LLen, 1); 194 | SetLength(LParamType, LLen); 195 | LMem.Read(LParamType[1], LLen); 196 | 197 | Result[I].Name := Trim(LParamName); 198 | Result[I].Flags := LFlags; 199 | Result[I].&Type := Trim(LParamType); 200 | end; 201 | finally 202 | LMem.Free; 203 | end; 204 | end; 205 | end; 206 | end; 207 | 208 | function TLangBase.FirstCaseChar(Astr: string): string; 209 | begin 210 | Result := Astr; 211 | if Length(Result) > 0 then 212 | Result[1] := LowerCase(Result[1]); 213 | end; 214 | 215 | function TLangBase.GetAutoCreateForms: TAutoCreateForms; 216 | var 217 | LLPRFileName, S: string; 218 | LStrs: TStringList; 219 | LP: Integer; 220 | begin 221 | Result := nil; 222 | if Assigned(LazarusIDE) and Assigned(LazarusIDE.ActiveProject) then 223 | begin 224 | LStrs := TStringList.Create; 225 | try 226 | LStrs.Text:=LazarusIDE.ActiveProject.MainFile.GetSourceText; 227 | for S in LStrs do 228 | begin 229 | // 开始提取 Application.CreateForm的 230 | if S.Trim.StartsWith('Application.CreateForm(') then 231 | begin 232 | SetLength(Result, Length(Result) + 1); 233 | LP := S.IndexOf(','); 234 | Result[High(Result)] := Trim(S.Substring(LP + 1, S.IndexOf(')') - LP - 1)); 235 | end; 236 | end; 237 | finally 238 | LStrs.Free; 239 | end; 240 | 241 | // Logs('mainSource: '#13#10 + LazarusIDE.ActiveProject.MainFile.GetSourceText); 242 | 243 | //LLPRFileName := ProjectLPRFileName; 244 | //if FileExists(LLPRFileName) then 245 | //begin 246 | // LStrs := TStringList.Create; 247 | // try 248 | // LStrs.LoadFromFile(LLPRFileName); 249 | // for S in LStrs do 250 | // begin 251 | // // 开始提取 Application.CreateForm的 252 | // if S.Trim.StartsWith('Application.CreateForm(') then 253 | // begin 254 | // SetLength(Result, Length(Result) + 1); 255 | // LP := S.IndexOf(','); 256 | // Result[High(Result)] := Trim(S.Substring(LP + 1, S.IndexOf(')') - LP - 1)); 257 | // end; 258 | // end; 259 | // finally 260 | // LStrs.Free; 261 | // end; 262 | //end; 263 | end; 264 | end; 265 | 266 | procedure TLangBase.ExecuteCommand(const ACmds: array of string; 267 | AWait, AShow: Boolean; AWorkDir: string); 268 | var 269 | LProcess: TProcess; 270 | LCmd: string; 271 | begin 272 | if Length(ACmds) = 0 then Exit; 273 | LProcess := TProcess.Create(nil); 274 | try 275 | LProcess.Options:= [];//[poWaitOnExit{, poNewProcessGroup, poStderrToOutPut}]; 276 | if AShow then 277 | LProcess.ShowWindow := swoShowDefault 278 | else 279 | LProcess.ShowWindow := swoHIDE; 280 | if AWorkDir <> '' then 281 | LProcess.CurrentDirectory:=AWorkDir; 282 | for LCmd in ACmds do 283 | begin 284 | try 285 | LProcess.CommandLine := LCmd; 286 | LProcess.Execute; 287 | if AWait then 288 | LProcess.WaitOnExit; 289 | if LProcess.ExitCode <> 0 then 290 | begin 291 | //CtlWriteln(mluError); 292 | Exit; 293 | end; 294 | except 295 | on E: Exception do 296 | begin 297 | CtlWriteln(mluError, E.Message); 298 | Exit; 299 | end; 300 | end; 301 | end; 302 | finally 303 | LProcess.Free; 304 | end; 305 | end; 306 | 307 | procedure TLangBase.ExecuteCommand(const ACmd: string; AWait, AShow: Boolean; 308 | AWorkDir: string); 309 | begin 310 | ExecuteCommand([ACmd], AWait, AShow, AWorkDir); 311 | end; 312 | 313 | function TLangBase.IsMainPackage: Boolean; 314 | begin 315 | Result := PackageName.Equals('main') or PackageName.IsEmpty 316 | end; 317 | 318 | 319 | 320 | 321 | end. 322 | 323 | -------------------------------------------------------------------------------- /usupports.pas: -------------------------------------------------------------------------------- 1 | //---------------------------------------- 2 | // 3 | // Copyright © ying32. All Rights Reserved. 4 | // 5 | // Licensed under Lazarus.modifiedLGPL 6 | // 7 | //---------------------------------------- 8 | unit usupports; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | {$ifdef windows} 16 | Windows, 17 | {$endif} 18 | Classes, SysUtils, fgl, IDEMsgIntf, IDEExternToolIntf; 19 | 20 | 21 | type 22 | TTypeLists = specialize TFPGMap; 23 | 24 | TOutLang = (olError=-1, olGo, olNim, olRust); 25 | 26 | TEventItem = record 27 | InstanceName: string; 28 | EventName: string; 29 | EventTypeName: string; 30 | EventParams: string; 31 | end; 32 | 33 | const 34 | PrivateFiledsFlagStr = '::private::'; 35 | PrivateFiledsStr = 'T%sFields'; 36 | 37 | //function IsZhLang: Boolean; 38 | function IsSupportsComponent(AClass: string): Boolean; 39 | procedure CtlWriteln(AUrgency: TMessageLineUrgency; const AFmt: string; AArgs: array of const); overload; 40 | procedure CtlWriteln(AUrgency: TMessageLineUrgency; const AFmt: string); overload; 41 | function GetFileNameWithoutExt(AFileName: string): string; 42 | function ChangeExtName(AFileName, AExt: string): string; 43 | procedure ClearMsg; 44 | procedure Logs(const AFmt: string; AArgs: array of const); overload; 45 | procedure Logs(const AStr: string); overload; 46 | 47 | implementation 48 | 49 | 50 | type 51 | TClassLists = specialize TFPGMap; 52 | 53 | var 54 | uClassLists: TClassLists; 55 | 56 | 57 | // 中文环境,不区分简/繁 58 | { 59 | "zh-CN": 2052, // 简体 60 | "zh-HK": 3076, // 繁体 61 | "zh-MO": 5124, // 繁体 62 | "zh-SG": 4100, // 简体 63 | "zh-TW": 1028, // 繁体 64 | } 65 | //function IsZhLang: Boolean; 66 | //{$IFDEF WINDOWS} 67 | //const 68 | // Langs:array[0..4] of Integer = (2052, 3076, 5124, 4100, 1028); 69 | //{$ELSE} 70 | //const 71 | // Langs:array[0..4] of string = ('zh_CN', 'zh_HK', 'zh_MO', 'zh_SG', 'zh_TW'); 72 | //{$ENDIF} 73 | //var 74 | // I: Integer; 75 | //begin 76 | // Result := False; 77 | // for I := 0 to High(Langs) do 78 | // begin 79 | // {$IFDEF MSWINDOWS} 80 | // if Langs[I] = SysLocale.DefaultLCID then 81 | // {$ELSE} 82 | // if Pos(Langs[I], GetEnvironmentVariable('LANG')) <> -1 then 83 | // {$ENDIF} 84 | // Exit(True); 85 | // end; 86 | //end; 87 | 88 | procedure CtlWriteln(AUrgency: TMessageLineUrgency; const AFmt: string; AArgs: array of const); 89 | begin 90 | AddIDEMessage(AUrgency, Format(AFmt, AArgs)); 91 | end; 92 | 93 | procedure CtlWriteln(AUrgency: TMessageLineUrgency; const AFmt: string); 94 | begin 95 | CtlWriteln(AUrgency, '%s', [AFmt]); 96 | end; 97 | 98 | function GetFileNameWithoutExt(AFileName: string): string; 99 | var 100 | LExt: string; 101 | begin 102 | Result := ExtractFileName(AFileName); 103 | LExt := ExtractFileExt(AFileName); 104 | Result := Copy(Result, 1, Length(Result) - Length(LExt)); 105 | end; 106 | 107 | function ChangeExtName(AFileName, AExt: string): string; 108 | begin 109 | Result := GetFileNameWithoutExt(AFileName) + AExt; 110 | end; 111 | 112 | procedure ClearMsg; 113 | begin 114 | if Assigned(IDEMessagesWindow) then 115 | IDEMessagesWindow.Clear; 116 | end; 117 | 118 | 119 | function IsSupportsComponent(AClass: string): Boolean; 120 | begin 121 | Result := uClassLists.IndexOf(AClass) <> -1; 122 | end; 123 | 124 | procedure AddComponentClass(AClassName: string); 125 | begin 126 | uClassLists.AddOrSetData(AClassName, ''); 127 | end; 128 | 129 | procedure MyRegisterComponents(AClassNames: array of string); 130 | var 131 | LB: string; 132 | begin 133 | for LB in AClassNames do 134 | AddComponentClass(LB); 135 | end; 136 | 137 | procedure InitClassLists; 138 | begin 139 | MyRegisterComponents([ 140 | 'TButton','TBitBtn','TMaskEdit', 'TEdit', 141 | 'TMainMenu', 'TPopupMenu', 'TMemo', 'TCheckBox', 'TRadioButton', 'TGroupBox', 142 | 'TLabel', 'TListBox', 'TComboBox', 'TPanel', 'TImage', 'TToggleBox', 143 | 'TLinkLabel', 144 | 'TSpeedButton', 'TSplitter', 'TRadioGroup', 'TStaticText', 'TColorBox', 145 | 'TColorListBox', 'TTrayIcon', 'TOpenDialog', 'TSaveDialog', 'TColorDialog', 146 | 'TFontDialog', 'TPrintDialog', 'TOpenPictureDialog', 'TSavePictureDialog', 147 | 'TRichEdit', 'TTrackBar', 'TImageList', 'TUpDown', 'TProgressBar', 148 | 'TDateTimePicker', 'TMonthCalendar', 'TListView', 'TTreeView', 149 | 'TStatusBar', 'TToolBar', 'TPageControl', 'TTabSheet', 'TStatusPanels', 150 | 'TStatusPanel', 'TActionList', 'TAction', 'TToolButton', 'TPaintBox', 'TTimer', 'TScrollBar', 151 | 'TShape', 'TBevel', 'TScrollBox', 'TCheckListBox', 'TSelectDirectoryDialog', 'TMenuItem', 152 | 'TGauge', 153 | 'TImageButton', 'TControlBar', 154 | 'TFontDialog', 'TFindDialog', 'TReplaceDialog', 'TPageSetupDialog', 155 | 'TPrinterSetupDialog', 'TStringGrid', 'TDrawGrid', 'TValueListEditor', 156 | 'THeaderControl', 'THeaderSection', 'THeaderSections', 'TLabeledEdit', 'TBoundLabel', 157 | 'TFlowPanel', 'TCoolBar', 'TSpinEdit', 'TSpinEditEx', 158 | 'TMiniWebview', 159 | 'TTaskDialog', 'TCalendar', 'TComboBoxEx', 'TTimeEdit', 160 | 'TXButton', 'TToggleBox', 'TCheckGroup', 'TColorButton', 'TFloatSpinEdit', 'TDirectoryEdit', 161 | 'TCheckComboBox' 162 | ]); 163 | end; 164 | 165 | procedure Logs(const AFmt: string; AArgs: array of const); 166 | begin 167 | {$ifdef windows} 168 | OutputDebugStringW(PWideChar(UnicodeString(Format(AFmt, AArgs)))); 169 | {$endif} 170 | end; 171 | 172 | procedure Logs(const AStr: string); 173 | begin 174 | {$ifdef windows} 175 | Logs('%s', [AStr]); 176 | {$endif} 177 | end; 178 | 179 | 180 | initialization 181 | 182 | uClassLists := TClassLists.Create; 183 | InitClassLists; 184 | 185 | finalization 186 | uClassLists.Free; 187 | 188 | end. 189 | 190 | --------------------------------------------------------------------------------