📜 ⬆️ ⬇️

YaUI - Buddhist Cross-Platform Native JavaScript UI Library

This story began when my friend and colleague, Yap Chae-shen, told me the following:

- I no longer want to write in Delphi in my life! I swore: no more line! From today, all my projects and libraries are being translated into JavaScript!

Yap is Chinese, with a classic mentality peculiar to his people. For many years I have been working with him on humanitarian projects in the field of digitization of ancient literature, first of all, the Buddhist Bible - Tipitaki. Yap's knowledge, both in the field of the most ancient texts and the most modern programming, has not ceased to amaze me for more than ten years - since we began to cooperate and communicate on various topics. For myself, I have long understood that if Yap says something, and I do not agree or do not understand, then this only means that we need to continue the discussion, and the whole mass of causes and effects in my friend’s thoughts will come to the surface, and as always It turns out that Yap is right. The seeming emotionality of the Chinese is, in fact, extraordinarily rational.

It happened that time. And, although I was very surprised by the statement of a friend, but I was not in a hurry with the conclusions and listened carefully. Usually Yap invented his brilliant ideas, testing them at Delphi, and my job was to rewrite all this in C ++, optimizing the speed of execution. After all, ancient texts require many programs, which are uncountable file formats, many encodings for many languages, work with bitmaps and vectors, input and display systems ... We have created more than one dozen unique rich text editors.
')
The first thing that came to mind was speed. Yap - who is interested in optimization and always knows how many microseconds this or that operation is performed, speaks about the interpreted language ?! The second is my love for C ++: OOP, overload, expressiveness and flexibility, because it was because of the power of this language that I switched to it from Delphi / Pascal 10 years ago. Is it possible to seriously write in JavaScript? Does it allow to structure complex projects, beautifully express their ideas? However, I didn’t know for sure: my previous experiences with JavaScript were limited to only small patches of websites ...

It turned out - all seriously! Here, in brief, what was discovered after studying the question:

A significant contribution to the revolution was made by Lars Buck, whom Google asked to apply his expert knowledge in the field of virtual machines and language optimization. Prior to that, he was known in narrow circles, creating very fast versions of Java and Smalltalk. Moving to Google from Sun, Lars moved from Denmark to the United States and led the development of a new JavaScipt engine for Chromium. Just-in-time compilation, garbage collector, deeply optimized object model. Just a few megabytes: the compiled binary engine includes a parser, the compiler - the entire virtual machine. Lars called the new V8 engine to associate with a powerful engine under the hood of the car, that is, the browser you are traveling on the Internet.

Very skeptical, I installed Chrome and wrote the first few tests for speed in index.html ... The very first cycle of adding numbers in the array made me raise my eyebrows. I must say that I myself wrote in my time several interpreters and compilers for my own invented languages. When I see code in a high-level language, like a = b + c, I immediately have pictures of how this code turns into a sequence of bits and how the CPU executes them. (It just so happened that Mom explained to me what bits are and CPA, on the way to kindergarten, in the distant seventies). Therefore, the more I learned about the V8, the sooner my skepticism turned into respect. I note that when working with one-dimensional or flat structures, like an integer array, the C ++ / O3 compiled code remains an order of magnitude faster than JavaScript, but the more complex the hierarchy of operated objects, the smaller the difference in execution speed.

Having understood what it does with the V8 input source code, I began to understand the essence of JavaScript as a language; it became clear why it is exactly what it is, why there are no pointers, why VMT (virtual method tables) are not needed, how to use metaprogramming without templates (template), why the garbage collector allows closures ... and the process has started!

JavaScript is not necessarily part of the browser, there are many command line interpreters based on different engines: JScript, V8, SpiderMonkey, TinyJS, quad-wheels, etc. The most famous Node-js.

nodejs.org - "platform for creating scalable network applications", based on the V8 engine. Node is launched from the command line, the first parameter is the name of the .js file. Node gives access to files, networks, processes. Working screen: Notepad ++ / SciTE and Far Manager or xterm window. It works almost identically on Windows, Linux, FreeBSD, MacOS, even iphone (after jailbreak).

More than a year has passed at work and studying new opportunities. Finally, I came to China (more precisely, Taiwan) to communicate with humanities volunteers directly. And these are programmers, linguists and ... monks. Still, our main goal is the complete digitization of the Buddhist Bible. And when I say "complete", this does not mean the OCR of all these volumes from the monastery cabinets. This is a great job of proofreading, comparing versions and translations, indexing, various search modes, tools for grammatical, syntactic and semantic analysis. Suffice it to say that Tipitaka is 100 times the Bible and still does not even have a clear paragraph numbering system. The Tibetan version is only scanned and not even recognized by OCR. As for the translations, the Tipitaka is translated only into Sanskrit, Chinese and Tibetan. Some small parts are translated into other languages. As far as I know, less than 10% is translated into English, less than 1% into Russian.

Such a huge amount of work to be! And all this unthinkable work can be done only by volunteers, hundreds and thousands of volunteers. But they need tools. In addition to the open libraries that we do for indexing, searching, converting formats, we also need visual tools. And it is also necessary that they work on different devices.

JavaScript on the phone enables the user interface in the WebView component, a wrapper over the browser machine. A browser is a restriction on access to local files and other system resources. Several applications created on the basis of WebView have shown that the launch speed and speed of response to user actions leaves much to be desired, and the amount of memory needed for the DOM is surprising - even powerful PCs still have difficulty opening many web pages at the same time. It would be great to have a native, that is, native, JavaScript interface.

They began to look, it turned out, they are. First tried PhoneGap, a curious thing, but inside the same browser, with all that it implies. I remember when I was just learning JavaScript, I tried to use an IDE called Aptana. This is a fork of Eclipse, specialized for javascript. However, Aptana later disappeared, it turned out she was acquired by Titanuim and entered into their project. Appcelerator Titanuim is a framework for creating native applications for iOS and Android.

We began to make the first projects on Titanium. But joy was replaced by disappointment. More cumbersome tool can not imagine! Even downloading and running Titanium Studio was a problem. It would seem that simpler than javascript? Changed the source in a text editor - restarted the program, that's all? But with the "Titanic" it did not work. In addition, the promised PC version titanium-Desktop did not work at all. Then also plugins for native extensions were limited in features and speed. It was necessary to rebuild the entire project after each modified line and reinstall it into the phone. No, this is not our method, we would need something quick and small, and that it would definitely work on the desktop, not just on the phone, and preferably work quickly and without ifdef (platform), and other cross-platform torment.

So, after long conversations, endless searches on the Internet, tests of various frameworks and libraries, it became clear: it does not exist. Cross-platform library or framework for creating native GUI applications in JavaScript, where is it? No her! However, after killing several months for searches and trials, I was so clear about what we needed and what was not needed, I understood what the complexity of such a library was, and, having already written many test applications for all existing platforms, I decided: we can do it yourself. Moreover, we don’t need much: buttons, input fields, pictures, tags, access to files, font selection, the ability to group and scroll. All these components are used even by a beginner. It is only necessary to correctly assemble all this and give access from JavaScript.

After several hours of brainstorming, it was decided to take it up. Yap then told me:

“Everything converges, components need a little, they should be simple, then we can cope with our modest forces - without millions of investments and large teams of developers, and the flexibility of JavaScript will enable us to make GUIs of any complexity even with a limited number of controls available.

They decided to call it simple: “Yet-another User Interface library” or “YaUI library” (in English “wye-hey-yu-ay”).

So, for a start, it was decided to limit to three platforms: Windows on i386, Android and iOS * (iPhone / iPad).

* For iOS, using V8 is not possible by Apple design. The fact is that JIT compilation requires re-marking virtual memory pages from data type to executable code, but this operation is blocked in iOS. True, if you get root, then this restriction can be eliminated (so you can run node.js in the jailbroken iphone console), but so far it has been decided to use SpiderMonkey. SpiderMonkey is, according to them, the very first JavaScript engine in the world, all Mozilla projects run on it, including the Firefox browser. I managed to find the iMonkey project - a specially trimmed SpiderMonkey port for iOS and rebuild it myself. iMonkey is distinguished by manually deleting the files and code lines responsible for the JIT. I must say that this is an extremely difficult matter, and what it cost a person to make this fork from the main branch (after all, there is such a chaos! Forgive me for the Mozilla developers). Although, logically, it would be enough to have the key DISABLE_JIT before running make, but alas, he had to patch a lot of handles. Hence the problem that iMonkey is Spidermonkey 1.8.0., And the latest version of SpiderMonkey is already 1.8.7. Rebuilding V8 for any platform turned out to be much easier. Alas, no one is already compiled. (Maybe you, dear reader?)

Basic principles of YaUI:


Currently (April 2013) Yaui can work with files, manipulate buttons, labels, input lines and plain text editors, pictures loaded from jpg or png, pixmap controls that provide access to individual pixels in JavaScript. ScrollView, vertical and horizontal, also work. Other controls can be placed in a ScrollView, and one ScrollView can be placed in another (if they are multidirectional, that is, vertical to horizontal or vice versa). On phones, ScrollView scrolls by touching the screen, on Windows, by pressing Control or Alt (for horizontal and vertical scrolling, respectively). I spent about a week trying to do without the use of Control / Alt, but it was a fiasco, apparently it is required to use low-level WinAPI, system hook or code injection.

What is Yaui in the form of files on Windows? This is the minimum set of files to run “Hello World”.
yaui/hello.yaui 88 bytes -   yaui/bootstrap.js 6,377 bytes -  , require(), setTimeout(), log() yaui/yaui.js 10,008 bytes -  API    GUI- yaui/v8.dll 3,193,344 bytes -  JavaScript  Google yaui/boot_win.js 3,989 bytes -     yaui/yaui.exe 189,440 bytes -      WinAPI 


Run like this:
 >cd yaui >yaui hello.yaui 


On Android:
 libdJS.so - 70,820 bytes libv8.so - 6,640,280 bytes classes.dex - 21,780 bytes AndroidManifest.xml - 3,964 bytes /js/bootstrap.js 6,377 bytes -  , require(), setTimeout(), log() /js/boot_droid.js 4,135 bytes -     /js/main.js -  , (     ,     main.js) /js/yaui.js 10,008 bytes -  API    GUI- 

(yaui.js, bootstrap.js - the same as in the Windows version.)

I don’t quote an iPhone so as not to overload the article.

Internal device. Conventionally, the source code YaUI can be divided into three levels. Native, binding and high-level.

Level 0 is a native code, a set of functions for creating controls and manipulating them. Of course, for each platform the code of this level is its own, in its own language and compiled with its own tools. Creation control functions return handles (some values ​​of undefined type). The same level - functions for accessing files: fopen () fread (), etc. Level 0 is Java and C ++ (via JNI) on Android, C ++ on Windows, Objective-C and C ++ on iOS.

Here is an example of the same low-level label creation function on three platforms.

Windows - yaui.cpp

 ADD_V8_FUNCTION(winapi_make_label) { window * v = (window*) args[0].toNumber(); Label *L = new Label; L->data["type"] = "label"; L->create(*v, "_undefined"); L->owner = v; return Number::New((int)L); } 


iOS - main.m

 if (code == ya_make_label) { OBJECT_ARG(UIView, 0, parrent); UILabel *L = [UILabel alloc]; [parent addSubview:L]; return convert_to_handle(L); } 


Android - Yaui.java

 if (code == ya_make_label) { int id = -1; TextView t = new TextView(this); if (t != null) { t.setGravity(Gravity.TOP); t.setMovementMethod(new ScrollingMovementMethod()); id = id_count++; t.setId(id); VG.addView(t); } return Integer.toString(id); } 


There are about 30 such functions in total, so porting to new platforms should be a relatively low-cost exercise. (And I will fight to ensure that they remain as small as possible, see paragraph 1.)

Level 1 is already JavaScript; here we directly bind native code to JavaScript, a function to a function, for example, how the same label creation function is bound in Level 1.

Windows - boot_win.js

 yaui.make_label = function(parent) { return winapi_make_label(parent) } 


iOS - boot_ios.js

 yaui.make_label = function(parent) { return ijs_control_call(ya_make_label, parent) } 


Android - boot_droid.js

 yaui.make_label = function(parent) { return yadroid(ya_make_label, parent) } 


The purpose of this binding is to obtain the same function for all platforms:

  yaui.make_label = function(parent) 


Level 2 is actually the API that the developer can use. He does not need to know about levels 0-1. At level 2, all low-level functions are wrapped in objects whose functionality is uniform, for example, they all represent the .set_xy (x, y) method, and all methods return this, that is, you can call them with a chain:

 yaui.create('button').set_text('hello world').set_xy(0, 0).set_wh(200, 30).show().apply() 


Same “HelloWorld” on YaUI!

You can of course write and "postarinka":

 var l = yaui.create('label') l.set_text('hello world') 


The main means of increasing the level of abstraction in yaui is selectors (approximately as in jQuery.) The selector, sampling, is the ability to work with arrays of controls as with one. You can choose controls by name (id), by class or by specifying your filter function. Here is a simple example, a “race game” that shows some of the features of selectors, YaUI, and JavaScript in general.

 // race.yaui var wh = yaui.get_app_size(), w = wh[0]*0.01, h = wh[1]*0.01, y = h, track = w*90 var team = ['ferrari', 'mclaren', 'williams'], car = [']=>', '}=]', '[=)'] function play() { select({cls:['car']}).each(function(c) { with(c.race) { accel += Math.random() * 0.01 pos += accel c.set_xy(pos % track) if (pos > track * 5) { clearInterval(clock) c.text += ' !WINNER!' return true } }}).apply() } function row(cls, txt) { var R = yaui.create('label').set_cls([cls, 'all']).set_text(txt).set_xy(0, y).set_wh(w*100, h*7) y += h*7; return R } for (var i = 0; i < team.length; i++) { row('team', team[i]) row('car', car[i]) row('car', car[i]) } yaui.create('button').set_id('start').set_cls('all').set_text('start') .set_xy(0, h*100-h*7).set_wh(w*100, h*7) .bind('button', function() { clock = setInterval(play, 10) }) select({cls:['car']}).each(function(c) { c.race = {accel: 0, lap: 1, pos: 0} } ) select({cls:['all']}).show().apply() 


Screenshots, sorry for the quality of the photos, made from live devices. (As you can see in different races won different "race cars.")
imageimageimage

To run this program in Windows, you must specify it as the first parameter for Yaui.exe.

 C:\yaui\yaui.exe race.yaui 


The .yaui file extension is a convention useful for file association, you could call the file race.js. Where to get yaui.exe? Two ways - either download the already compiled "ekzeshnik" or build yourself. Both are on Sourceforge.

How to install and run yaui on a mobile phone is a separate story that would require extensive explanations. And I can say that it is not my fault that it is so difficult (especially on iOS). I would like to provide fully binary solutions so that anyone can program for all supported platforms.

What is not yet?

There is no good Yaui documentation for a wide audience of JavaScript developers, documentation for those who want to develop Yaui and port to new platforms. Few example programs (and they are terrible).
No ports for X (Linux, FreeBSD), MacOS, Windows Phone, no port for browser. Yes, the browser could easily execute Yaui, and this would give the opportunity to use the browser debugger.
There is a lack of wealth of the framework: that is, it is necessary to write new controls and functions based on what Yaui already can. For example, ComboBox, GridView, CalendarView based on a textview, scrollview that already exists ...
You can even improve the native part with the expansion of functionality, performance, compatibility and reliability, spend a lot of testing, debugging, and create automated tools for testing and debugging

In short, programmers and Buddhists of all countries, unite or join - if you are attracted by the ideas of Open Source, openness, practicality and pragmatism, cross-platform, love of gadgets, JavaScript, minimalism and nanomalism in software, a new fascinating unique framework, a desire to help the Buddha, Sange and Dharma or you liked this article - write, download, make Comits in repo, fork, tell friends.

Link to repositories and binary distributions.
sourceforge.net/projects/yaui

Source: https://habr.com/ru/post/176669/


All Articles