From: Alan Knowles Date: Sat, 27 Jan 2024 23:06:44 +0000 (+0800) Subject: fix #7989 - add support for extended classes (partial) X-Git-Tag: release-5.0.2~27 X-Git-Url: http://git.roojs.org/?p=roobuilder;a=commitdiff_plain;h=7cd1dfe18b9c072b577304efbf67cd39791fd079 fix #7989 - add support for extended classes (partial) --- diff --git a/.roobuilder.jcfg b/.roobuilder.jcfg index 1dc1f9cfe..235a9ea20 100644 --- a/.roobuilder.jcfg +++ b/.roobuilder.jcfg @@ -66,7 +66,10 @@ "src/Palete/LanguageClientJavascript.vala", "src/Lsp.vala", "src/Palete/LanguageClientDummy.vala", - "src/Palete/ValaCompileRequest.vala" + "src/Palete/ValaCompileRequest.vala", + "src/JsRender/NodeWriter.vala", + "src/JsRender/NodeToValaExtended.vala", + "src/JsRender/NodeToValaWrapped.vala" ] } ], diff --git a/ChangeLog b/ChangeLog index e69de29bb..4ae3111d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -0,0 +1 @@ +See debian/changelog \ No newline at end of file diff --git a/INSTALL b/INSTALL deleted file mode 100644 index e82fd21de..000000000 --- a/INSTALL +++ /dev/null @@ -1,368 +0,0 @@ -Installation Instructions -************************* - - Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free -Software Foundation, Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell command './configure && make && make install' -should configure, build, and install this package. The following -more-detailed instructions are generic; see the 'README' file for -instructions specific to this package. Some packages provide this -'INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The 'configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a 'Makefile' in each directory of the package. -It may also create one or more '.h' files containing system-dependent -definitions. Finally, it creates a shell script 'config.status' that -you can run in the future to recreate the current configuration, and a -file 'config.log' containing compiler output (useful mainly for -debugging 'configure'). - - It can also use an optional file (typically called 'config.cache' and -enabled with '--cache-file=config.cache' or simply '-C') that saves the -results of its tests to speed up reconfiguring. Caching is disabled by -default to prevent problems with accidental use of stale cache files. - - If you need to do unusual things to compile the package, please try -to figure out how 'configure' could check whether to do them, and mail -diffs or instructions to the address given in the 'README' so they can -be considered for the next release. If you are using the cache, and at -some point 'config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file 'configure.ac' (or 'configure.in') is used to create -'configure' by a program called 'autoconf'. You need 'configure.ac' if -you want to change it or regenerate 'configure' using a newer version of -'autoconf'. - - The simplest way to compile this package is: - - 1. 'cd' to the directory containing the package's source code and type - './configure' to configure the package for your system. - - Running 'configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type 'make' to compile the package. - - 3. Optionally, type 'make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type 'make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the 'make install' phase executed with root - privileges. - - 5. Optionally, type 'make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior 'make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing 'make clean'. To also remove the - files that 'configure' created (so you can compile the package for - a different kind of computer), type 'make distclean'. There is - also a 'make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type 'make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide 'make - distcheck', which can by used by developers to test that all other - targets like 'make install' and 'make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the 'configure' script does not know about. Run './configure --help' -for details on some of the pertinent environment variables. - - You can give 'configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here is -an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU 'make'. 'cd' to the -directory where you want the object files and executables to go and run -the 'configure' script. 'configure' automatically checks for the source -code in the directory that 'configure' is in and in '..'. This is known -as a "VPATH" build. - - With a non-GNU 'make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use 'make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple '-arch' options to the -compiler but only a single '-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the 'lipo' tool if you have problems. - -Installation Names -================== - - By default, 'make install' installs the package's commands under -'/usr/local/bin', include files under '/usr/local/include', etc. You -can specify an installation prefix other than '/usr/local' by giving -'configure' the option '--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option '--exec-prefix=PREFIX' to 'configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like '--bindir=DIR' to specify different values for particular -kinds of files. Run 'configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the default -for these options is expressed in terms of '${prefix}', so that -specifying just '--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to 'configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -'make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, 'make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -'${prefix}'. Any directories that were specified during 'configure', -but not in terms of '${prefix}', must each be overridden at install time -for the entire installation to be relocated. The approach of makefile -variable overrides for each directory variable is required by the GNU -Coding Standards, and ideally causes no recompilation. However, some -platforms have known limitations with the semantics of shared libraries -that end up requiring recompilation when using this method, particularly -noticeable in packages that use GNU Libtool. - - The second method involves providing the 'DESTDIR' variable. For -example, 'make install DESTDIR=/alternate/directory' will prepend -'/alternate/directory' before all installation names. The approach of -'DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of '${prefix}' -at 'configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving 'configure' the -option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. - - Some packages pay attention to '--enable-FEATURE' options to -'configure', where FEATURE indicates an optional part of the package. -They may also pay attention to '--with-PACKAGE' options, where PACKAGE -is something like 'gnu-as' or 'x' (for the X Window System). The -'README' should mention any '--enable-' and '--with-' options that the -package recognizes. - - For packages that use the X Window System, 'configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the 'configure' options '--x-includes=DIR' and -'--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of 'make' will be. For these packages, running './configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with 'make V=1'; while running './configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with 'make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC -is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - HP-UX 'make' updates targets which have the same timestamps as their -prerequisites, which makes it generally unusable when shipped generated -files such as 'configure' are involved. Use GNU 'make' instead. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its '' header file. The option '-nodtk' can be used as a -workaround. If GNU CC is not installed, it is therefore recommended to -try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put '/usr/ucb' early in your 'PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in '/usr/bin'. So, if you need '/usr/ucb' -in your 'PATH', put it _after_ '/usr/bin'. - - On Haiku, software installed for all users goes in '/boot/common', -not '/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features 'configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, 'configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -'--build=TYPE' option. TYPE can either be a short name for the system -type, such as 'sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file 'config.sub' for the possible values of each field. If -'config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option '--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with '--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for 'configure' scripts to share, -you can create a site shell script called 'config.site' that gives -default values for variables like 'CC', 'cache_file', and 'prefix'. -'configure' looks for 'PREFIX/share/config.site' if it exists, then -'PREFIX/etc/config.site' if it exists. Or, you can set the -'CONFIG_SITE' environment variable to the location of the site script. -A warning: not all 'configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to 'configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the 'configure' command line, using 'VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified 'gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an -Autoconf limitation. Until the limitation is lifted, you can use this -workaround: - - CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash - -'configure' Invocation -====================== - - 'configure' recognizes the following options to control how it -operates. - -'--help' -'-h' - Print a summary of all of the options to 'configure', and exit. - -'--help=short' -'--help=recursive' - Print a summary of the options unique to this package's - 'configure', and exit. The 'short' variant lists options used only - in the top level, while the 'recursive' variant lists options also - present in any nested packages. - -'--version' -'-V' - Print the version of Autoconf used to generate the 'configure' - script, and exit. - -'--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally 'config.cache'. FILE defaults to '/dev/null' to - disable caching. - -'--config-cache' -'-C' - Alias for '--cache-file=config.cache'. - -'--quiet' -'--silent' -'-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to '/dev/null' (any error - messages will still be shown). - -'--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - 'configure' can determine that directory automatically. - -'--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: for - more details, including other options available for fine-tuning the - installation locations. - -'--no-create' -'-n' - Run the configure checks, but stop before creating any output - files. - -'configure' also accepts some other, not widely useful, options. Run -'configure --help' for more details. diff --git a/debian/changelog b/debian/changelog index 2d2bb1061..dc0d47b88 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,16 @@ -roobuilder (5.0.1) UNRELEASED; urgency=medium +roobuilder (5.0.2) UNRELEASED; urgency=medium + + * support for extended writing of vala applications + Note that sealed classes causes issues, so generally it's not usable yet + * Move Node (drag with shift pressed) + * Changing property key now triggers save/language server + * Fixed sending wrong 'save' to language-server (caused LS to crash) + * Fixed Gtkview - uses toSource(), rather than file.get_contents() + + + -- Alan Knowles Sun, 28 Jan 2024 06:54:56 +0800 + +roobuilder (5.0.1) unstable; urgency=medium * switch to meson build * remove internal compiler - switch to call meson/ninja diff --git a/meson.build b/meson.build index 2d108d50f..6e12dd8c8 100644 --- a/meson.build +++ b/meson.build @@ -145,6 +145,9 @@ roobuilder_src = files([ 'src/Lsp.vala', 'src/Palete/LanguageClientDummy.vala', 'src/Palete/ValaCompileRequest.vala', + 'src/JsRender/NodeWriter.vala', + 'src/JsRender/NodeToValaExtended.vala', + 'src/JsRender/NodeToValaWrapped.vala', ]) roobuilder = executable('roobuilder', diff --git a/src/Application.vala b/src/Application.vala index 84260d572..a6638b881 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -411,16 +411,18 @@ var oldfn = file.targetName(); print("\n\n\n\nFile : %s\n", oldfn); - //GLib.FileUtils.get_contents(oldfn, out oldstr); + var outstr = file.toSourceCode(); + + /* line number checking var bad = false; // check line numbers: var bits = outstr.split("\n"); var end = bits.length; for(var i = 0;i < end; i++) { print("%i : %s\n", i+1 , bits[i]); - if (!bad && bits[i].has_prefix("/*") && !bits[i].has_prefix("/*%d*/".printf(i+1))) { + if (!bad && bits[i].has_prefix("/*") && !bits[i].has_prefix(("/*%d*" +"/").printf(i+1))) { end = i + 5 > bits.length ? bits.length: (i + 5); print ("^^^^ mismatch\null"); bad = true; @@ -431,14 +433,16 @@ if (bad) { GLib.error("got bad file"); } - /* + */ + // compare files. + string oldstr; + GLib.FileUtils.get_contents(oldfn, out oldstr); if (outstr != oldstr) { GLib.FileUtils.set_contents("/tmp/" + file.name + ".out", outstr); print("meld %s /tmp/%s\n", oldfn, file.name + ".out"); //GLib.Process.exit(Posix.EXIT_SUCCESS); - } -*.* */ + } //print("# Files match %s\n", file.name); } } catch (FileError e) { @@ -797,5 +801,4 @@ flutter-project - was try and read flutter data (but desnt work.) - - + \ No newline at end of file diff --git a/src/Builder4/About.bjs b/src/Builder4/About.bjs index 8f560d888..9737a508c 100644 --- a/src/Builder4/About.bjs +++ b/src/Builder4/About.bjs @@ -1,6 +1,6 @@ { "build_module" : "builder", - "gen_extended" : true, + "gen_extended" : false, "items" : [ { "$ authors" : "{ \"Alan Knowles\" }", @@ -25,4 +25,4 @@ } ], "name" : "About" -} \ No newline at end of file +} diff --git a/src/Builder4/DialogConfirm.bjs b/src/Builder4/DialogConfirm.bjs index 551f4538e..306efab16 100644 --- a/src/Builder4/DialogConfirm.bjs +++ b/src/Builder4/DialogConfirm.bjs @@ -1,6 +1,6 @@ { "build_module" : "builder", - "gen_extended" : true, + "gen_extended" : false, "items" : [ { "$ buttons" : "Gtk.ButtonsType.YES_NO", @@ -41,4 +41,4 @@ } ], "name" : "DialogConfirm" -} \ No newline at end of file +} diff --git a/src/JsRender/Gtk.vala b/src/JsRender/Gtk.vala index caee6c71b..2a3451c1b 100644 --- a/src/JsRender/Gtk.vala +++ b/src/JsRender/Gtk.vala @@ -135,7 +135,9 @@ namespace JsRender { this.tree.loadFromJson(tree_base, int.parse(bjs_version_str)); } - NodeToVala.mungeFile(this); // force line numbering.. + this.gen_extended ? + NodeToValaExtended.mungeFile(this) : + NodeToValaWrapped.mungeFile(this); // force line numbering..?? should we call toSourceCode??? this.loaded = true; } @@ -156,8 +158,11 @@ namespace JsRender { GLib.debug("toSource - using Cache"); return this.last_source; } - GLib.debug("toSource - generating"); - this.last_source = NodeToVala.mungeFile(this); + GLib.debug("toSource - generating %s", this.gen_extended ? "Extended": "Wrapped"); + + this.last_source = this.gen_extended ? + NodeToValaExtended.mungeFile(this) : + NodeToValaWrapped.mungeFile(this); this.last_source_version = this.version; return this.last_source; @@ -216,7 +221,7 @@ namespace JsRender { var fn = this.targetName(); GLib.debug("WRITE :%s\n " , fn); try { - this.writeFile(fn, NodeToVala.mungeFile(this)); + this.writeFile(fn, this.toSourceCode()); } catch (GLib.Error e) {} diff --git a/src/JsRender/Node.vala b/src/JsRender/Node.vala index a06076a62..8d64b09ab 100644 --- a/src/JsRender/Node.vala +++ b/src/JsRender/Node.vala @@ -99,9 +99,9 @@ public class JsRender.Node : GLib.Object { private Gee.ArrayList items; // child items.. public GLib.ListStore childstore; // must be kept in sync with items public GLib.ListStore? propstore; // must be kept in sync with items - public string xvala_cls; - public string xvala_xcls; // 'Xcls_' + id; - public string xvala_id; // item id or "" + public string xvala_cls; // set by node to vala + public string xvala_xcls; // 'Xcls_' + id; // set by nodetoVala + public string xvala_id; // item id or "" // set by nodetovala // line markers.. public int line_start; diff --git a/src/JsRender/NodeToVala.vala b/src/JsRender/NodeToVala.vala index 76480eed6..b96e8f97d 100644 --- a/src/JsRender/NodeToVala.vala +++ b/src/JsRender/NodeToVala.vala @@ -21,48 +21,42 @@ */ -public class JsRender.NodeToVala : Object { +public abstract class JsRender.NodeToVala : NodeWriter { - Node node; - - int depth; - string inpad; - string pad; - string ipad; - string cls; // node fqn() - string xcls; - - string ret; + protected string this_el = "??"; + + int child_count = 1; // used to number the children. + public string cls; // node fqn() + public string xcls; - int cur_line; - Gee.ArrayList ignoreList; Gee.ArrayList ignoreWrappedList; Gee.ArrayList myvars; - Gee.ArrayList vitems; // top level items - NodeToVala top; - JsRender file; - int pane_number = 0; + + + + int pane_number = 0;// ?? used when generating Gtk.Pane tabs + + + static construct { + NodeWriter.globalIgnore("pack"); + NodeWriter.globalIgnore("init"); + NodeWriter.globalIgnore("xns"); + NodeWriter.globalIgnore("xtype"); + NodeWriter.globalIgnore("id"); + } /* * ctor - just initializes things * - wraps a render node */ - public NodeToVala( JsRender file, Node node, int depth, NodeToVala? parent) + protected NodeToVala( JsRender file, Node node, int depth, NodeToVala? parent) { + base (file, node, depth, parent); + + this.initPadding('\t', 1); - this.node = node; - this.depth = depth; - if (file.name.contains(".")) { // namespaced.. - this.inpad = string.nfill(depth > 0 ? 2 : 1, '\t'); - } else { - this.inpad = string.nfill(depth > 0 ? 1 : 0, '\t'); - } - this.pad = this.inpad + "\t"; - - this.node.node_pad = this.inpad; - this.ipad = this.inpad + "\t\t"; this.cls = node.xvala_cls; this.xcls = node.xvala_xcls; if (depth == 0 && this.xcls.contains(".")) { @@ -70,180 +64,26 @@ public class JsRender.NodeToVala : Object { this.xcls = ar[ar.length-1]; } - - this.ret = ""; - this.cur_line = parent == null ? 0 : parent.cur_line; - - - this.top = parent == null ? this : parent.top; - this.ignoreList = new Gee.ArrayList(); + this.ignoreWrappedList = new Gee.ArrayList(); this.myvars = new Gee.ArrayList(); - this.vitems = new Gee.ArrayList(); - this.file = file; - - // initialize line data.. - node.line_start = this.cur_line; - node.line_end = this.cur_line; - node.lines = new Gee.ArrayList(); - node.line_map = new Gee.HashMap(); - if (parent == null) { - node.node_lines = new Gee.ArrayList(); - node.node_lines_map = new Gee.HashMap(); - } - - } - - public int vcnt = 0; - string toValaNS(Node item) - { - var ns = item.get("xns") ; - //if (ns == "GtkSource") { technically on Gtk3? - // return "Gtk.Source"; - //} - return ns + "."; - } - public void toValaName(Node item, int depth =0) - { - this.vcnt++; - - var ns = this.toValaNS(item) ; - var cls = ns + item.get("xtype"); - - - item.xvala_cls = cls; - - - string id = item.get("id").length > 0 ? - item.get("id") : "%s%d".printf(item.get("xtype"), this.vcnt); - - - - - if (id[0] == '*' || id[0] == '+') { - item.xvala_xcls = "Xcls_" + id.substring(1); - } else { - item.xvala_xcls = "Xcls_" + id; - } - - - item.xvala_id = id; - if (depth > 0) { - this.vitems.add(item); - - // setting id on top level class changes it classname.. - // oddly enough we havent really thought about namespacing here. - - } else if (!item.props.has_key("id")) { - // use the file name.. - item.xvala_xcls = this.file.file_without_namespace; - // is id used? - item.xvala_id = this.file.file_without_namespace; - - } - // loop children.. - - if (item.readItems().size < 1) { - return; - } - for(var i =0;i 0 || this.file.file_namespace == "") { return; - } + } this.addLine("namespace " + this.file.file_namespace); this.addLine("{"); @@ -256,82 +96,33 @@ public class JsRender.NodeToVala : Object { this.addLine("}"); } - public void globalVars() - { - if (this.depth > 0) { - return; - } - // Global Vars..??? when did this get removed..? - //this.ret += this.inpad + "public static " + this.xcls + " " + this.node.xvala_id+ ";\n\n"; + - this.addLine(this.inpad + "static " + this.xcls + " _" + this.node.xvala_id+ ";"); - this.addLine(); - - } + protected abstract void classHeader(); + - void classHeader() - { - - // class header.. - // class xxx { WrappedGtk el; } - this.node.line_start = this.cur_line; - - this.top.node.setNodeLine(this.cur_line, this.node); - - this.addLine(this.inpad + "public class " + this.xcls + " : Object"); - this.addLine(this.inpad + "{"); - - - this.addLine(this.pad + "public " + this.cls + " el;"); - - this.addLine(this.pad + "private " + this.top.xcls + " _this;"); - this.addLine(); - - - - // singleton - } - void addSingleton() - { - if (depth > 0) { - return; - } - this.addLine(pad + "public static " + xcls + " singleton()"); - this.addLine(this.pad + "{"); - this.addLine(this.ipad + "if (_" + this.node.xvala_id + " == null) {"); - this.addLine(this.ipad + " _" + this.node.xvala_id + "= new "+ this.xcls + "();"); // what about args? - this.addLine(this.ipad + "}"); - this.addLine(this.ipad + "return _" + this.node.xvala_id +";"); - this.addLine(this.pad + "}"); - } /** * when ID is used... on an element, it registeres a property on the top level... * so that _this.ID always works.. * */ - void addTopProperties() + protected void addTopProperties() { if (this.depth > 0) { return; } // properties - global..?? + foreach(var n in this.top_level_items) { - var iter = this.vitems.list_iterator(); - while(iter.next()) { - var n = iter.get(); - - if (!n.props.has_key("id") || n.xvala_id.length < 0) { continue; } - if (n.xvala_id[0] == '*') { - continue; - } - if (n.xvala_id[0] == '+') { + if (n.xvala_id[0] == '*' || n.xvala_id[0] == '+') { continue; } + this.addLine(this.pad + "public " + n.xvala_xcls + " " + n.xvala_id + ";"); } @@ -343,7 +134,7 @@ public class JsRender.NodeToVala : Object { * */ - void addMyVars() + protected void addMyVars() { GLib.debug("callinged addMhyVars"); @@ -362,11 +153,8 @@ public class JsRender.NodeToVala : Object { // Key = TYPE:name - var iter = this.node.props.map_iterator(); - while (iter.next()) { - - var prop = iter.get_value(); - + foreach(var prop in this.node.props.values) { + if (this.shouldIgnore(prop.name)) { continue; } @@ -414,7 +202,7 @@ public class JsRender.NodeToVala : Object { } // if id of child is '+' then it's a property of this.. - void addPlusProperties() + protected void addPlusProperties() { if (this.node.readItems().size < 1) { return; @@ -436,48 +224,11 @@ public class JsRender.NodeToVala : Object { /** * add the constructor definition.. */ - void addValaCtor() - { - - - // .vala props.. - - - var cargs_str = ""; - // ctor.. - this.addLine(); - this.addLine(this.pad + "// ctor"); - - if (this.node.has("* args")) { - // not sure what this is supposed to be ding.. - - cargs_str = this.node.get("* args"); - //var ar = this.node.get("* args");.split(","); - //for (var ari =0; ari < ar.length; ari++) { - // cargs += (ar[ari].trim().split(" ").pop(); - // } - } - - if (this.depth < 1) { - - // top level - does not pass the top level element.. - this.addLine(this.pad + "public " + this.xcls + "(" + cargs_str +")"); - this.addLine(this.pad + "{"); - } else { - if (cargs_str.length > 0) { - cargs_str = ", " + cargs_str; - } - // for sub classes = we passs the top level as _owner - this.addLine(this.pad + "public " + this.xcls + "(" + this.top.xcls + " _owner " + cargs_str + ")"); - this.addLine(this.pad + "{"); - } - - - } + protected abstract void addValaCtor(); /** * make sure _this is defined.. */ - void addUnderThis() + protected void addUnderThis() { // public static? if (depth < 1) { @@ -502,206 +253,9 @@ public class JsRender.NodeToVala : Object { } - /** - * Initialize this.el to point to the wrapped element. - * - * - */ - - void addWrappedCtor() - { - // wrapped ctor.. - // this may need to look up properties to fill in the arguments.. - // introspection does not workk..... - as things like gtkmessagedialog - /* - if (cls == 'Gtk.Table') { - - var methods = this.palete.getPropertiesFor(cls, 'methods'); - - print(JSON.stringify(this.palete.proplist[cls], null,4)); - Seed.quit(); - } - */ - - // ctor can still override. - if (this.node.has("* ctor")) { - this.node.setLine(this.cur_line, "p", "* ctor"); - this.addLine(this.ipad + "this.el = " + this.node.get("* ctor")+ ";"); - return; - } - - this.node.setLine(this.cur_line, "p", "* xtype");; - - // is the wrapped element a struct? - - var ncls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn()); - if (ncls != null && ncls.nodetype == "Struct") { - // we can use regular setters to apply the values. - this.addLine(this.ipad + "this.el = " + this.node.fqn() + "();"); - return; - - - } - - var ctor = ".new"; - var args_str = ""; - switch(this.node.fqn()) { - - // FIXME -- these are all GTK3 - can be removed when I get rid of them.. - case "Gtk.ComboBox": - var is_entry = this.node.has("has_entry") && this.node.get_prop("has_entry").val.down() == "true"; - if (!is_entry) { - break; // regular ctor. - } - this.ignoreWrapped("has_entry"); - ctor = ".with_entry"; - break; - - - case "Gtk.ListStore": - case "Gtk.TreeStore": - - // not sure if this works.. otherwise we have to go with varargs and count + vals... - if (this.node.has("* types")) { - args_str = this.node.get_prop("* types").val; - } - if (this.node.has("n_columns") && this.node.has("columns")) { // old value? - args_str = " { " + this.node.get_prop("columns").val + " } "; - this.ignoreWrapped("columns"); - this.ignoreWrapped("n_columns"); - } - - this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ".newv( " + args_str + " );"); - return; - - - case "Gtk.LinkButton": // args filled with values. - if (this.node.has("label")) { - ctor = ".with_label"; - } - break; - - default: - break; - } - var default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ctor); - - - // use the default ctor - with arguments (from properties) - - if (default_ctor != null && default_ctor.paramset != null && default_ctor.paramset.params.size > 0) { - string[] args = {}; - foreach(var param in default_ctor.paramset.params) { - - var n = param.name; - GLib.debug("building CTOR ARGS: %s, %s", n, param.is_varargs ? "VARARGS": ""); - if (n == "___") { // for some reason our varargs are converted to '___' ... - continue; - } - - if (this.node.has(n)) { // node does not have a value - - this.ignoreWrapped(n); - this.ignore(n); - - var v = this.node.get(n); - - if (param.type == "string") { - v = "\"" + v.escape("") + "\""; - } - if (v == "TRUE" || v == "FALSE") { - v = v.down(); - } - - - args += v; - continue; - } - var propnode = this.node.findProp(n); - if (propnode != null) { - // assume it's ok.. - - var pname = this.addPropSet(propnode, propnode.has("id") ? propnode.get_prop("id").val : ""); - args += (pname + ".el") ; - if (!propnode.has("id")) { - this.addLine(this.ipad + pname +".ref();"); - } - - - - this.ignoreWrapped(n); - - continue; - } - - - - - - if (param.type.contains("int")) { - args += "0"; - continue; - } - if (param.type.contains("float")) { - args += "0f"; - continue; - } - if (param.type.contains("bool")) { - args += "true"; // always default to true? - continue; - } - // any other types??? - - - - - args += "null"; - - - - } - this.node.setLine(this.cur_line, "p", "* xtype"); - this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "( "+ string.joinv(", ",args) + " );") ; - return; - - } - // default ctor with no params.. - if (default_ctor != null && ctor != ".new" ) { - this.node.setLine(this.cur_line, "p", "* xtype"); - - this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ctor + "( );") ; - return; - } - - - this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "(" + args_str + ");"); - - - - - } - public static Gee.ArrayList menuitem_children = null; - void addAutoShow() - { - if (menuitem_children == null) { - menuitem_children = new Gee.ArrayList(); - menuitem_children.add("Gtk.MenuItem"); - var gir = this.file.project.palete.getClass("Gtk.MenuItem"); - if (gir != null) { - foreach(var impl in gir.implementations) { - menuitem_children.add(impl); - } - } - } - - if (menuitem_children.contains(this.node.fqn())) { - this.addLine(this.ipad + "this.el.show();"); - - } - } - - void addInitMyVars() + + protected void addInitMyVars() { //var meths = this.palete.getPropertiesFor(item['|xns'] + '.' + item.xtype, 'methods'); //print(JSON.stringify(meths,null,4));Seed.quit(); @@ -744,7 +298,7 @@ public class JsRender.NodeToVala : Object { - void addWrappedProperties() + protected void addWrappedProperties() { var cls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn()); if (cls == null) { @@ -755,10 +309,8 @@ public class JsRender.NodeToVala : Object { this.addLine(); this.addLine(this.ipad + "// set gobject values"); - - var iter = cls.props.map_iterator(); - while (iter.next()) { - var p = iter.get_key(); + foreach(var p in cls.props.keys) { + var val = cls.props.get(p); //print("Check Write %s\n", p); if (!this.node.has(p)) { continue; @@ -783,25 +335,24 @@ public class JsRender.NodeToVala : Object { var is_raw = prop.ptype == NodePropType.RAW; // what's the type.. - if it's a string.. then we quote it.. - if (iter.get_value().type == "string" && !is_raw) { + if (val.type == "string" && !is_raw) { v = "\"" + v.escape("") + "\""; } if (v == "TRUE" || v == "FALSE") { v = v.down(); } - if (iter.get_value().type == "float" && v[v.length-1] != 'f') { + if (val.type == "float" && v[v.length-1] != 'f') { v += "f"; } prop.start_line = this.cur_line; - this.addLine("%sthis.el.%s = %s;".printf(ipad,p,v)); // // %s, iter.get_value().type); + this.addLine("%s%s%s = %s;".printf(ipad,this.this_el,p,v)); // // %s, iter.get_value().type); prop.end_line = this.cur_line; // got a property.. } - - } + } /** * pack the children into the parent. * @@ -809,7 +360,7 @@ public class JsRender.NodeToVala : Object { * - this allows you to define children and add them manually.. */ - void addChildren() + protected void addChildren() { //code if (this.node.readItems().size < 1) { @@ -856,12 +407,13 @@ public class JsRender.NodeToVala : Object { this.ignoreWrapped(child.get_prop("* prop").val); + var el_name = this.this_el == "this.el." ? ".el" : ""; + this.addLine(ipad + this.this_el + child.get_prop("* prop").val + " = " + childname + el_name +";"); - this.addLine(ipad + "this.el." + child.get_prop("* prop").val + " = " + childname + ".el;"); continue; } - if (!child.has("id")) { - this.addLine(this.ipad + childname +".ref();"); + if (!child.has("id") && this.this_el == "this.el.") { + this.addLine(this.ipad + childname +".ref();"); } this.packChild(child, childname, cols, colpos); @@ -878,7 +430,7 @@ public class JsRender.NodeToVala : Object { } } - string addPropSet(Node child, string child_name) + protected string addPropSet(Node child, string child_name) { @@ -897,8 +449,19 @@ public class JsRender.NodeToVala : Object { if (child_name == "") { prefix = "var " + childname + " = "; } + var cls = child.xvala_xcls; + /* + if (this.this_el == "this.") { + var clsdata = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn()); + //if (clsdata.is_sealed) { + cls = this.node.fqn(); // need ctor data... + this.addLine(this.ipad + @"$(prefix)new $cls( _this $xargs);" ); + return child_name == "" ? childname : ("_this." + child_name); + } + } + */ - this.addLine(this.ipad + prefix + "new " + child.xvala_xcls + "( _this " + xargs + ");" ); + this.addLine(this.ipad + @"$(prefix)new $cls( _this $xargs);" ); // add a ref... (if 'id' is not set... to a '+' ?? what does that mean? - fake ids? // remove '+' support as I cant remember what it does!!! @@ -917,7 +480,7 @@ public class JsRender.NodeToVala : Object { - void packChild(Node child, string childname, int cols, int colpos, string propname= "") + protected void packChild(Node child, string childname, int cols, int colpos, string propname= "") { GLib.debug("packChild %s=>%s", this.node.fqn(), child.fqn()); @@ -928,7 +491,8 @@ public class JsRender.NodeToVala : Object { if (child.has("* pack") && child.get("* pack").down() == "true") { return; // force no packing } - + var el_name = this.this_el == "this.el." ? ".el" : ""; + var this_el = this.this_el; // BC really - don't want to support this anymore. if (child.has("* pack")) { @@ -938,12 +502,10 @@ public class JsRender.NodeToVala : Object { } var pack = packing[0]; - this.addLine(this.ipad + "this.el." + pack.strip() + " ( " + childname + ".el " + + this.addLine(this.ipad + this.this_el + pack.strip() + " ( " + childname + el_name + " " + (packing.length > 1 ? (", " + string.joinv(",", packing).substring(pack.length+1)) - : - "" - ) + " );"); + : "" ) + " );"); return; } var childcls = this.file.project.palete.getClass(child.fqn()); // very trusting.. @@ -953,7 +515,7 @@ public class JsRender.NodeToVala : Object { // GTK4 var is_event = childcls.inherits.contains("Gtk.EventController") || childcls.implements.contains("Gtk.EventController"); if (is_event) { - this.addLine(this.ipad + "this.el.add_controller( %s.el );".printf(childname) ); + this.addLine(this.ipad + this.this_el + "add_controller( %s.el );".printf(childname) ); return; } @@ -966,7 +528,7 @@ public class JsRender.NodeToVala : Object { case "Gtk.Layout": var x = child.has("x") ? child.get_prop("x").val : "0"; var y = child.has("y") ? child.get_prop("y").val : "0"; - this.addLine(this.ipad + "this.el.put( %s.el, %s, %s );".printf(childname,x,y) ); + this.addLine(@"$(ipad)$(this_el)put( $(childname)$(el_name), $(x), $(y) );"); return; @@ -975,15 +537,16 @@ public class JsRender.NodeToVala : Object { var named = child.has("stack_name") ? child.get_prop("stack_name").val.escape() : ""; var title = child.has("stack_title") ? child.get_prop("stack_title").val.escape() : ""; if (title.length > 0) { - this.addLine(this.ipad + "this.el.add_titled( %s.el, \"%s\", \"%s\" );".printf(childname,named,title)); - } else { - this.addLine(this.ipad + "this.el.add_named( %s.el, \"%s\" );".printf(childname,named)); - } + this.addLine(@"$(ipad)$(this_el)add_titled( $(childname)$(el_name), \"$(named)\", \"$(title)\" );"); + return; + } + this.addLine(@"$(ipad)$(this_el)add_named( $(childname)$(el_name), \"$(named)\");"); return; case "Gtk.Notebook": // use label var label = child.has("notebook_label") ? child.get_prop("notebook_label").val.escape() : ""; - this.addLine(this.ipad + "this.el.append_page( %s.el, new Gtk.Label(\"%s\"));".printf(childname, label)); + this.addLine(@"$(ipad)$(this_el)append_page( $(childname)$(el_name), new Gtk.Label(\"$(label)\");"); + return; @@ -993,36 +556,42 @@ public class JsRender.NodeToVala : Object { case "Gtk.TreeViewColumn": //adding Renderers - I think these are all proprerties of the renderer used... if (child.has("markup_column") && int.parse(child.get_prop("markup_column").val) > -1) { - this.addLine(this.ipad + "this.el.add_attribute( %s.el, \"markup\", %s );".printf(childname, child.get_prop("markup_column").val)); + var val = child.get_prop("markup_column").val; + this.addLine(@"$(ipad)$(this_el)add_attribute( $(childname)$(el_name), \"markup\", $(val) );"); + } if (child.has("text_column") && int.parse(child.get_prop("text_column").val) > -1) { - this.addLine(this.ipad + "this.el.add_attribute( %s.el, \"text\", %s );".printf(childname, child.get_prop("text_column").val)); + var val = child.get_prop("text_column").val; + this.addLine(@"$(ipad)$(this_el)add_attribute( $(childname)$(el_name), \"text\", $(val) );"); } if (child.has("pixbuf_column") && int.parse(child.get_prop("pixbuf_column").val) > -1) { - this.addLine(this.ipad + "this.el.add_attribute( %s.el, \"pixbuf\", %s );".printf(childname, child.get_prop("pixbuf_column").val)); + var val = child.get_prop("pixbuf_column").val; + this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"pixbuf\", $(val) );"); } if (child.has("pixbuf_column") && int.parse(child.get_prop("active_column").val) > -1) { - this.addLine(this.ipad + "this.el.add_attribute( %s.el, \"active\", %s );".printf(childname, child.get_prop("active_column").val)); + var val = child.get_prop("active_column").val; + this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"active\", $(val) );"); } if (child.has("background_column") && int.parse(child.get_prop("background_column").val) > -1) { - this.addLine(this.ipad + "this.el.add_attribute( %s.el, \"background-rgba\", %s );".printf(childname, child.get_prop("background_column").val)); + var val = child.get_prop("background_column").val; + this.addLine(@"$(ipad)$(this_el).add_attribute( $(childname)$(el_name), \"background-rgba\", $(val) );"); } this.addLine(this.ipad + "this.el.add( " + childname + ".el );"); // any more!? return; - + case "Gtk.Dialog": if (propname == "buttons[]") { var resp_id = int.parse(childname.replace("child_", "")); if (child.has("* response_id")) { resp_id = int.parse(child.get_prop("* response_id").val); } - this.addLine(this.ipad + "this.el.add_action_widget( %s.el, %d);".printf(childname,resp_id) ); + this.addLine(@"$(ipad)$(this_el).add_action_widget( $(childname)$(el_name), $(resp_id) );"); + return; } - - this.addLine(this.ipad + "this.el.get_content_area().add( " + childname + ".el );"); + this.addLine(@"$(ipad)$$(this_el)get_content_area().add( $(childname)$(el_name) );"); return; @@ -1031,22 +600,22 @@ public class JsRender.NodeToVala : Object { // known working with GTK4 ! - case "Gtk.HeaderBar": // it could be end... - not sure how to hanle that other than overriding the pack method? - this.addLine(this.ipad + "this.el.pack_start( "+ childname + ".el );"); + case "Gtk.HeaderBar": // it could be end... - not sure how to hanle that other than overriding this.addLine(this.ipad + "this.el.add_action_widget( %s.el, %d);".printf(childname,resp_id) ); the pack method? + this.addLine(@"$(ipad)$(this_el)pack_start( $(childname)$(el_name) );"); return; case "GLib.Menu": - this.addLine(this.ipad + "this.el.append_item( "+ childname + ".el );"); + this.addLine(@"$(ipad)$(this_el)append_item( $(childname)$(el_name) );"); return; case "Gtk.Paned": this.pane_number++; switch(this.pane_number) { case 1: - this.addLine(this.ipad + "this.el.pack_start( %s.el );".printf(childname)); + this.addLine(@"$(ipad)$(this_el)pack_start( $(childname)$(el_name) );"); return; - case 2: - this.addLine(this.ipad + "this.el.pack_end( %s.el );".printf(childname)); + case 2: + this.addLine(@"$(ipad)$(this_el)pack_end( $(childname)$(el_name) );"); return; default: // do nothing @@ -1055,7 +624,7 @@ public class JsRender.NodeToVala : Object { return; case "Gtk.ColumnView": - this.addLine(this.ipad + "this.el.append_column( "+ childname + ".el );"); + this.addLine(@"$(ipad)$(this_el)append_column( $(childname)$(el_name) );"); return; case "Gtk.Grid": @@ -1063,12 +632,12 @@ public class JsRender.NodeToVala : Object { var y = "%d".printf(( colpos - (colpos % cols) ) / cols); var w = child.has("colspan") ? child.get_prop("colspan").val : "1"; var h = "1"; - this.addLine(this.ipad + "this.el.attach( %s.el, %s, %s, %s, %s );".printf(childname ,x,y, w, h) ); + this.addLine(@"$(ipad)$(this_el)attach( $(childname)$(el_name), $x, $y, $w, $h );"); return; default: + this.addLine(@"$(ipad)$(this_el)append( $(childname)$(el_name) );"); // gtk4 uses append!!!! - gtk3 - uses add.. - this.addLine(this.ipad + "this.el.append( "+ childname + ".el );"); return; @@ -1083,7 +652,7 @@ public class JsRender.NodeToVala : Object { - void addInit() + protected void addInit() { @@ -1100,7 +669,7 @@ public class JsRender.NodeToVala : Object { this.addMultiLine(ipad + this.padMultiline(ipad, init.val) ); init.end_line = this.cur_line; } - void addListeners() + protected void addListeners() { if (this.node.listeners.size < 1) { return; @@ -1119,12 +688,12 @@ public class JsRender.NodeToVala : Object { prop.start_line = this.cur_line; this.node.setLine(this.cur_line, "l", k); - this.addMultiLine(this.ipad + "this.el." + k + ".connect( " + + this.addMultiLine(this.ipad + this.this_el + k + ".connect( " + this.padMultiline(this.ipad,v) +");"); prop.end_line = this.cur_line; } } - void addEndCtor() + protected void addEndCtor() { // end ctor.. @@ -1174,7 +743,7 @@ public class JsRender.NodeToVala : Object { * */ - void addUserMethods() + protected void addUserMethods() { this.addLine(); this.addLine(this.pad + "// user defined functions"); @@ -1204,7 +773,7 @@ public class JsRender.NodeToVala : Object { } } - void iterChildren() + protected void iterChildren() { this.node.line_end = this.cur_line; this.node.sortLines(); @@ -1225,26 +794,15 @@ public class JsRender.NodeToVala : Object { } } + - string padMultiline(string pad, string str) - { - var ar = str.strip().split("\n"); - return string.joinv("\n" + pad , ar); - } - void ignore(string i) { - this.ignoreList.add(i); - - } - void ignoreWrapped(string i) { + protected void ignoreWrapped(string i) { this.ignoreWrappedList.add(i); } - bool shouldIgnore(string i) - { - return ignoreList.contains(i); - } - bool shouldIgnoreWrapped(string i) + + protected bool shouldIgnoreWrapped(string i) { return ignoreWrappedList.contains(i); } diff --git a/src/JsRender/NodeToValaExtended.vala b/src/JsRender/NodeToValaExtended.vala new file mode 100644 index 000000000..0dcad4b01 --- /dev/null +++ b/src/JsRender/NodeToValaExtended.vala @@ -0,0 +1,244 @@ +/* + +This coverts nodes to vala code (but unlike the original) does it by extending the original wrapped class + +*/ + +public class JsRender.NodeToValaExtended : NodeToVala { + + + + + /* + * ctor - just initializes things + * - wraps a render node + */ + public NodeToValaExtended( JsRender file, Node node, int depth, NodeToValaExtended? parent) + { + base (file, node, depth, parent); + this.this_el = "this."; + } + /** + * Main entry point to convert a file into a string.. + */ + public static string mungeFile(JsRender file) + { + if (file.tree == null) { + return ""; + } + + var n = new NodeToValaExtended(file, file.tree, 0, null); + n.toValaName(file.tree); + + + GLib.debug("top cls %s / xlcs %s\n ",file.tree.xvala_cls,file.tree.xvala_cls); + n.initCls(); + return n.munge(); + + + } + int child_count = 1; // used to number the children. + public override string munge ( ) + { + //return this.mungeToString(this.node); + this.child_count = 1; + + + this.namespaceHeader(); + + this.classHeader(); + + this.addTopProperties(); /// properties set with 'id' + this.addMyVars(); // user defined properties. + + // skip '+' properties?? not sure where they are used. + this.addValaCtor(); + + + this.addInitMyVars(); + this.addWrappedProperties(); + this.addChildren(); // to constructor code + //this.addSealedChildren(); + //this.addAutoShow(); // not needed gtk4 autoshow menuitems + + this.addInit(); + this.addListeners(); + this.addEndCtor(); + this.addUserMethods(); + this.iterChildren(); // add children class definitions. + this.namespaceFooter(); + + return this.ret; + + + } + + public override string mungeChild( Node cnode) + { + var x = new NodeToValaExtended(this.file, cnode, this.depth+1, this); + return x.munge(); + } + + + protected override void classHeader() + { + + var top = this.top as NodeToVala; + if (top == null) { + return; + } + // class header.. + // class xxx { WrappedGtk el; } + this.node.line_start = this.cur_line; + + this.top.node.setNodeLine(this.cur_line, this.node); + + this.addLine(this.inpad + "public class " + this.xcls + " : " + this.cls); + this.addLine(this.inpad + "{"); + + this.addLine(this.pad + "private " + top.xcls + " _this;"); /// or protected?? + this.addLine(); + + + + // singleton + } + + /** + * add the constructor definition.. + * this probably has to match the parent constructor.. + **?? NO SUPPORT FOR * ARGS? + ** for child elements we have to add '_owner to the ctor arguments. + for most elements we have to call object ( a: a, b: b) if the parent requires properties.. + eg. like Gtk.Box + + + */ + + protected override void addValaCtor() + { + + + + var ncls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn()); + if (ncls == null || ncls.nodetype != "Class") { + this.addLine(this.ipad + "** classname is invalid - can not make ctor " + this.node.fqn()); + return; + } + var ctor = ".new"; + var default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ctor); + + if (default_ctor == null) { + this.addLine(this.ipad + "** classname is invalid - can not find ctor " + this.node.fqn() + ".new"); + return; + } + // simple ctor...(will not need ctor params.. + + + // now we can skip ctor arguments if we have actually set them? + string[] args = {}; + if (default_ctor.paramset != null && default_ctor.paramset.params.size > 0) { + foreach(var param in default_ctor.paramset.params) { + + var n = param.name; + GLib.debug("building CTOR ARGS: %s, %s", n, param.is_varargs ? "VARARGS": ""); + // not sure if it's even worth warning on this... + if (n == "___") { // for some reason our varargs are converted to '___' ... + continue; + } + if (this.node.has(n)) { + continue; + } + var propnode = this.node.findProp(n); + if (propnode != null) { + continue; + } + // finally + args += (param.type + " " + n); + + + } + } + // create the ctor method + + + if (this.depth < 1) { + + // top level - does not pass the top level element.. + this.addLine(this.pad + "public " + this.xcls + "()"); + this.addLine(this.pad + "{"); + + } else { + var top = this.top as NodeToVala; + var tcls = top == null ? "???" : top.xcls; + args += (tcls + " _owner" ); + // for sub classes = we passs the top level as _owner + this.addLine(this.pad + "public " + this.xcls + "(" + tcls + " _owner )"); + this.addLine(this.pad + "{"); + + } + this.addUnderThis(); // set up '_this = _owner or _this = this; + + // if there are no ctor args, then we do not need to call object // or create props. + if (default_ctor.paramset == null || default_ctor.paramset.params.size < 1) { + return; + } + // .vala props.. + var obj_args = new Gee.HashMap(); + foreach(var param in default_ctor.paramset.params) { + var n = param.name; + if (n == "___") { // for some reason our varargs are converted to '___' ... + continue; + } + if (this.node.has(n)) { // node does not have a value + + this.ignoreWrapped(n); + this.ignore(n); + + var v = this.node.get(n); + + if (param.type == "string") { + v = "\"" + v.escape("") + "\""; + } + if (v == "TRUE" || v == "FALSE") { + v = v.down(); + } + obj_args.set(n, v); + + continue; + } + var propnode = this.node.findProp(n); + if (propnode != null) { + // assume it's ok.. + + var pname = this.addPropSet(propnode, propnode.has("id") ? propnode.get_prop("id").val : ""); + obj_args.set(n, pname); + + if (!propnode.has("id")) { + this.addLine(this.ipad + pname +".ref();"); + } + + this.ignoreWrapped(n); //??? not sure why we dont ignore it as well. + + continue; + } + } + if (obj_args.keys.size < 1) { + return; + } + this.addLine(this.ipad + "Object("); + // at this point we might have object... + var ks = obj_args.keys.to_array(); + for(var i = 0; i < ks.length; i++ ) { + var k = ks[i]; + var v = obj_args.get(k); + this.addLine(this.ipad + "\t" + k + ": " + v + (i == (ks.length-1) ? "" : ",")); + } + this.addLine(this.ipad + ");"); + + } + + + + +} diff --git a/src/JsRender/NodeToValaWrapped.vala b/src/JsRender/NodeToValaWrapped.vala new file mode 100644 index 000000000..5ddf32f2e --- /dev/null +++ b/src/JsRender/NodeToValaWrapped.vala @@ -0,0 +1,367 @@ +/** + this is the code to write the 'classic' node to vala output + */ + /** + * + * Code to convert node tree to Vala... + * + * usage : x = (new JsRender.NodeToVala(node)).munge(); + * + * Fixmes? + * + * pack - can we come up with a replacement? + - parent.child == child_widget -- actually uses getters and effectively does 'add'? + (works on most)? + + + * args -- vala constructor args (should really only be used at top level - we did use it for clutter originally( + * ctor -- different ctor argument + + * + + * + * +*/ + + +public class JsRender.NodeToValaWrapped : NodeToVala { + + + + + public NodeToValaWrapped( JsRender file, Node node, int depth, NodeToVala? parent) + { + base (file, node, depth, parent); + this.this_el = "this.el."; + } + + /** + * Main entry point to convert a file into a string.. + */ + public static string mungeFile(JsRender file) + { + if (file.tree == null) { + return ""; + } + + var n = new NodeToValaWrapped(file, file.tree, 0, null); + n.toValaName(file.tree); + + GLib.debug("top cls %s / xlcs %s\n ",file.tree.xvala_cls,file.tree.xvala_cls); + n.initCls(); + return n.munge(); + + + } + public override string munge ( ) + { + //return this.mungeToString(this.node); + + + + this.namespaceHeader(); + this.globalVars(); + this.classHeader(); + this.addSingleton(); + this.addTopProperties(); + this.addMyVars(); + this.addPlusProperties(); // (this is child properties whos 'id' starts with '+' ??? not sure.. + this.addValaCtor(); + this.addUnderThis(); + this.addWrappedCtor(); // var this.el = new XXXXX() + + this.addInitMyVars(); + this.addWrappedProperties(); + this.addChildren(); + //this.addAutoShow(); // not needed gtk4 autoshow menuitems + + this.addInit(); + this.addListeners(); + this.addEndCtor(); + this.addUserMethods(); + this.iterChildren(); + this.namespaceFooter(); + + return this.ret; + + + } + public override string mungeChild( Node cnode) + { + var x = new NodeToValaWrapped(this.file, cnode, this.depth+1, this); + return x.munge(); + } + + protected override void classHeader() + { + var top = this.top as NodeToVala; + if (top == null) { + + return; + } + // class header.. + // class xxx { WrappedGtk el; } + this.node.line_start = this.cur_line; + + this.top.node.setNodeLine(this.cur_line, this.node); + + this.addLine(this.inpad + "public class " + this.xcls + " : Object"); + this.addLine(this.inpad + "{"); + + + this.addLine(this.pad + "public " + this.cls + " el;"); + + this.addLine(this.pad + "private " + top.xcls + " _this;"); + this.addLine(); + + + + // singleton + } + public void globalVars() + { + if (this.depth > 0) { + return; + } + // Global Vars..??? when did this get removed..? + //this.ret += this.inpad + "public static " + this.xcls + " " + this.node.xvala_id+ ";\n\n"; + + this.addLine(this.inpad + "static " + this.xcls + " _" + this.node.xvala_id+ ";"); + this.addLine(); + + } + protected void addSingleton() + { + if (depth > 0) { + return; + } + this.addLine(pad + "public static " + xcls + " singleton()"); + this.addLine(this.pad + "{"); + this.addLine(this.ipad + "if (_" + this.node.xvala_id + " == null) {"); + this.addLine(this.ipad + " _" + this.node.xvala_id + "= new "+ this.xcls + "();"); // what about args? + this.addLine(this.ipad + "}"); + this.addLine(this.ipad + "return _" + this.node.xvala_id +";"); + this.addLine(this.pad + "}"); + } + /** + * add the constructor definition.. + */ + protected override void addValaCtor() + { + + + // .vala props.. + + + var cargs_str = ""; + // ctor.. + this.addLine(); + this.addLine(this.pad + "// ctor"); + + if (this.node.has("* args")) { + // not sure what this is supposed to be ding.. + + cargs_str = this.node.get("* args"); + //var ar = this.node.get("* args");.split(","); + //for (var ari =0; ari < ar.length; ari++) { + // cargs += (ar[ari].trim().split(" ").pop(); + // } + } + + if (this.depth < 1) { + + // top level - does not pass the top level element.. + this.addLine(this.pad + "public " + this.xcls + "(" + cargs_str +")"); + this.addLine(this.pad + "{"); + } else { + if (cargs_str.length > 0) { + cargs_str = ", " + cargs_str; + } + var top = this.top as NodeToVala; + var tcls = top == null ? "???" : top.xcls; + // for sub classes = we passs the top level as _owner + this.addLine(this.pad + "public " + this.xcls + "(" + tcls + " _owner " + cargs_str + ")"); + this.addLine(this.pad + "{"); + } + + + } + /** + * Initialize this.el to point to the wrapped element. + * + * + */ + + void addWrappedCtor() + { + // wrapped ctor.. + // this may need to look up properties to fill in the arguments.. + // introspection does not workk..... - as things like gtkmessagedialog + /* + if (cls == 'Gtk.Table') { + + var methods = this.palete.getPropertiesFor(cls, 'methods'); + + print(JSON.stringify(this.palete.proplist[cls], null,4)); + Seed.quit(); + } + */ + + // ctor can still override. + if (this.node.has("* ctor")) { + this.node.setLine(this.cur_line, "p", "* ctor"); + this.addLine(this.ipad + "this.el = " + this.node.get("* ctor")+ ";"); + return; + } + + this.node.setLine(this.cur_line, "p", "* xtype");; + + // is the wrapped element a struct? + + var ncls = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn()); + if (ncls != null && ncls.nodetype == "Struct") { + // we can use regular setters to apply the values. + this.addLine(this.ipad + "this.el = " + this.node.fqn() + "();"); + return; + + + } + + var ctor = ".new"; + var args_str = ""; + switch(this.node.fqn()) { + + // FIXME -- these are all GTK3 - can be removed when I get rid of them.. + case "Gtk.ComboBox": + var is_entry = this.node.has("has_entry") && this.node.get_prop("has_entry").val.down() == "true"; + if (!is_entry) { + break; // regular ctor. + } + this.ignoreWrapped("has_entry"); + ctor = ".with_entry"; + break; + + + case "Gtk.ListStore": + case "Gtk.TreeStore": + + // not sure if this works.. otherwise we have to go with varargs and count + vals... + if (this.node.has("* types")) { + args_str = this.node.get_prop("* types").val; + } + if (this.node.has("n_columns") && this.node.has("columns")) { // old value? + args_str = " { " + this.node.get_prop("columns").val + " } "; + this.ignoreWrapped("columns"); + this.ignoreWrapped("n_columns"); + } + + this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ".newv( " + args_str + " );"); + return; + + + case "Gtk.LinkButton": // args filled with values. + if (this.node.has("label")) { + ctor = ".with_label"; + } + break; + + default: + break; + } + var default_ctor = Palete.Gir.factoryFqn((Project.Gtk) this.file.project, this.node.fqn() + ctor); + + + // use the default ctor - with arguments (from properties) + + if (default_ctor != null && default_ctor.paramset != null && default_ctor.paramset.params.size > 0) { + string[] args = {}; + foreach(var param in default_ctor.paramset.params) { + + var n = param.name; + GLib.debug("building CTOR ARGS: %s, %s", n, param.is_varargs ? "VARARGS": ""); + if (n == "___") { // for some reason our varargs are converted to '___' ... + continue; + } + + if (this.node.has(n)) { // node does not have a value + + this.ignoreWrapped(n); + this.ignore(n); + + var v = this.node.get(n); + + if (param.type == "string") { + v = "\"" + v.escape("") + "\""; + } + if (v == "TRUE" || v == "FALSE") { + v = v.down(); + } + + + args += v; + continue; + } + var propnode = this.node.findProp(n); + if (propnode != null) { + // assume it's ok.. + + var pname = this.addPropSet(propnode, propnode.has("id") ? propnode.get_prop("id").val : ""); + args += (pname + ".el") ; + if (!propnode.has("id")) { + this.addLine(this.ipad + pname +".ref();"); + } + + + + this.ignoreWrapped(n); + + continue; + } + + + + + + if (param.type.contains("int")) { + args += "0"; + continue; + } + if (param.type.contains("float")) { + args += "0f"; + continue; + } + if (param.type.contains("bool")) { + args += "true"; // always default to true? + continue; + } + // any other types??? + + + + + args += "null"; + + + + } + this.node.setLine(this.cur_line, "p", "* xtype"); + this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "( "+ string.joinv(", ",args) + " );") ; + return; + + } + // default ctor with no params.. + if (default_ctor != null && ctor != ".new" ) { + this.node.setLine(this.cur_line, "p", "* xtype"); + + this.addLine(this.ipad + "this.el = new " + this.node.fqn() + ctor + "( );") ; + return; + } + + + this.addLine(this.ipad + "this.el = new " + this.node.fqn() + "(" + args_str + ");"); + + } + + + +} diff --git a/src/JsRender/NodeWriter.vala b/src/JsRender/NodeWriter.vala new file mode 100644 index 000000000..235a0462c --- /dev/null +++ b/src/JsRender/NodeWriter.vala @@ -0,0 +1,193 @@ + +namespace JsRender { + public abstract class NodeWriter : Object { + + + protected JsRender file; + protected Node node; + + protected int depth; + protected string inpad; // the pad for the class outer + protected string pad; // the padd for the methods / properties. + protected string ipad; + + protected Gee.ArrayList top_level_items; // top level items (was vitems) + protected int cur_line; + protected NodeWriter top; + + public string ret { + get { + return this.output; + } + private set { + GLib.error("set called on nodewriter ret"); + } + } + + string output = ""; // the result of outputing.. + + Gee.ArrayList ignoreList; + static Gee.ArrayList? globalIgnoreList = null; + static construct { + globalIgnoreList = new Gee.ArrayList(); + } + + /* + * ctor - just initializes things + * - wraps a render node + */ + protected NodeWriter( JsRender file, Node node, int depth, NodeWriter? parent) + { + this.file = file; + this.node = node; + this.depth = depth; + if (parent == null) { + this.var_name_count = 0; + } + this.top_level_items = new Gee.ArrayList(); + this.cur_line = parent == null ? 0 : parent.cur_line; + this.top = parent == null ? this : parent.top; + + // initialize line data.. + node.line_start = this.cur_line; + node.line_end = this.cur_line; + node.lines = new Gee.ArrayList(); + node.line_map = new Gee.HashMap(); + if (parent == null) { + node.node_lines = new Gee.ArrayList(); + node.node_lines_map = new Gee.HashMap(); + } + + this.ignoreList = new Gee.ArrayList(); + + } + + int var_name_count = 0; // was vcnt + + string toValaNS(Node item) + { + return item.get("xns") + "."; + } + /** + fills in all the xvala_cls names into the nodes + + */ + + + public void initPadding(char pad, int len) + { + + var has_ns = this.file.xtype == "Gtk" && this.file.file_namespace.length > 0; + + if (has_ns) { // namespaced.. + this.inpad = string.nfill((depth > 0 ? 2 : 1)* len, pad); + } else { + this.inpad = string.nfill((depth > 0 ? 1 : 0) * len , pad); + } + this.pad = this.inpad + string.nfill(len, pad); + this.node.node_pad = this.inpad; + this.ipad = this.inpad + string.nfill(2* len, pad);; + + + } + + public void toValaName(Node item, int depth =0) + { + this.var_name_count++; + + var ns = this.toValaNS(item) ; + var cls = ns + item.get("xtype"); + + item.xvala_cls = cls; + + string id = item.get("id").length > 0 ? + item.get("id") : "%s%d".printf(item.get("xtype"), this.var_name_count); + + + + + if (id[0] == '*' || id[0] == '+') { + item.xvala_xcls = "Xcls_" + id.substring(1); + } else { + item.xvala_xcls = "Xcls_" + id; + } + + + item.xvala_id = id; + if (depth > 0) { + this.top_level_items.add(item); + + // setting id on top level class changes it classname.. + // oddly enough we havent really thought about namespacing here. + + } else if (!item.props.has_key("id")) { + // use the file name.. + item.xvala_xcls = this.file.file_without_namespace; + // is id used? + item.xvala_id = this.file.file_without_namespace; + + } + // loop children.. + + if (item.readItems().size < 1) { + return; + } + for(var i =0;i(); // should not happend.. but dont know about ctor process.. + } + globalIgnoreList.add(i); + } + + protected void ignore(string i) { + this.ignoreList.add(i); + + } + + protected bool shouldIgnore(string i) + { + return globalIgnoreList.contains(i) || ignoreList.contains(i); + } + + + // interface + public abstract string munge(); + + + + } +} \ No newline at end of file diff --git a/src/Palete/GirObject.vala b/src/Palete/GirObject.vala index cb08c8f9f..5a8361c62 100644 --- a/src/Palete/GirObject.vala +++ b/src/Palete/GirObject.vala @@ -36,6 +36,7 @@ namespace Palete { public bool is_writable = true; public bool is_readable = true; public bool is_abstract = false; + public bool is_sealed = false; public string parent; public string value; // to be filled in... diff --git a/src/Palete/VapiParser.vala b/src/Palete/VapiParser.vala index 3d63c2f3e..a805377ab 100644 --- a/src/Palete/VapiParser.vala +++ b/src/Palete/VapiParser.vala @@ -184,6 +184,7 @@ namespace Palete { c.parent = cls.base_class == null ? "" : cls.base_class.get_full_name() ; // extends... c.gparent = parent; c.is_abstract = cls.is_abstract; + c.is_sealed = cls.is_sealed; foreach(var p in cls.get_properties()) { this.add_property(c, p); }