YaUI-仏教徒のクロスプラットフォームネイティブJavaScript UIライブラリ

この話は、友人であり仲間のヤップ・チェシェンが次のことを教えてくれたときに始まりました。



「私の人生で二度とDelphiを書きたくない!」 私は誓った:もう一行はありません! 今日から、すべてのプロジェクトとライブラリをJavaScriptに翻訳します!



ヤップは中国人であり、彼の人々の典型的なメンタリティを特徴としています。 長年、私は彼と一緒に古代文学のデジタル化の分野、主に「仏教の聖書」であるティピタキの人道的プロジェクトに取り組んできました。 ヤップの知識は、最も古いテキストの分野と最新のプログラミングの両方で、さまざまなトピックについて協力してコミュニケーションを取り始めてから10年以上も私を驚かせていました。 私自身、ヤップが何かを言っても同意しない、または理解しない場合、それは議論を続ける必要があることを意味するだけであり、友人の考えの原因と結果のすべてが表面化すること、そしていつものように、ヤップが正しいことがわかりました。 実際、中国人の見かけの感情は異常に合理的です。



それがその時起こりました。 そして、私は友人の声明に非常に驚いたが、結論を急ぐことはなく、注意深く耳を傾けた。 通常Yapは彼のすばらしいアイデアを思いつき、Delphiでテストしました。私の仕事は、これをすべてC ++で書き直し、実行速度を最適化することでした。 結局のところ、古代のテキストには多くのプログラムが必要であり、これらは数え切れないほどのファイル形式、多くの言語の多くのエンコーディング、ビットマップとベクター、入力および表示システムで動作します...



最初に思いついたのはスピードでした。 ヤップ-最適化に熱心で、操作が実行されるマイクロ秒数を常に知っている人は、インタープリター言語について話しますか?! 2つ目はC ++に対する私の愛です。OOP、オーバーロード、表現力、柔軟性。これは、10年前にDelphi / Pascalからこの言語に切り替えたためです。 JavaScriptで真剣に書くことは可能ですか?! 複雑なプロジェクトを構築し、アイデアを美しく表現できますか? しかし、私はこれを確かに知りませんでした。以前のJavaScriptの実験は、小さな点在するサイトに限定されていました...



それは判明した-すべてが深刻です! ここで、要するに、問題を研究した後に発見されたもの:



革命に大きく貢献したのはラース・バックでした。ラース・バックは、仮想マシンと言語の最適化の分野で専門知識を活用するようGoogleに求められました。 それ以前は、狭い範囲で知られており、JavaとSmalltalkの非常に高速なバージョンを作成していました。 SunからGoogleに移り、Larsはデンマークから米国に移り、Chromiumの新しいJavaSciptエンジンの作業を主導しました。 ジャストインタイムコンパイル、ガベージコレクター、深く最適化されたオブジェクトモデル。 ほんの数メガバイト:コンパイルされたエンジンバイナリには、パーサー、コンパイラ、仮想マシン全体が含まれます。 Larsは、新しいV8エンジンを、車のボンネットの下にある強力なエンジン、つまり、インターネットをサーフィンするブラウザーとの関連付けがあると呼びました。



非常に懐疑的で、Chromeをインストールし、index.htmlに最初のいくつかの速度テストを書きました...配列に数値を追加する最初のサイクルは、眉をひそめました。 私は自分で発明した言語用にいくつかのインタプリタとコンパイラを書いたと言わなければなりません。 a = b + cのような高水準言語のコードを見ると、このコードがビットシーケンスにどのように変化し、CPUがどのようにそれらを実行するかがすぐにわかります。 (たまたま、70年代の幼稚園に向かう途中で、お母さんが私にビットとCPUとは何かを説明してくれました)。 したがって、V8について学べば学ぶほど、私の懐疑心はすぐに尊敬されました。 整数配列などの1次元または平面構造で作業する場合、コンパイルされたC ++ / O3コードはJavaScriptよりも1桁高速ですが、操作されるオブジェクトの階層が複雑になるほど、実行速度の差は小さくなります。



V8が入力ソースコードを使用して何を行うかを理解したので、私はJavaScriptの言語としての本質を理解し始めました。 なぜそれがまさにそうであるのか、なぜポインターがないのか、VMT(仮想メソッドテーブル)が不要なのか、テンプレートなしでメタプログラミングを使用するのか、ガベージコレクターがクロージャーを許可するのか、そしてプロセスが開始された理由が明らかになりました!



JavaScriptは必ずしもブラウザーの一部ではなく、さまざまなエンジン(JScript、V8、SpiderMonkey、TinyJS、クアッドホイールなど)に基づいたコマンドラインインタープリターが多数あります。 最も有名なNode-js。



nodejs.org-V8エンジンに基づく「スケーラブルなネットワークアプリケーションを作成するためのプラットフォーム」。 ノードはコマンドラインから起動され、最初のパラメーターは.jsファイルの名前です。 ノードは、ファイル、ネットワーク、プロセスへのアクセスを提供します。 作業画面:メモ帳++ / SciTEおよびFar Managerまたはxtermウィンドウ。 Windows、Linux、FreeBSD、MacOS、iphone(ジェイルブレイク後)でもほぼ同じように動作します。



仕事をして新しい機会を探求するために1年以上が経過しました。 最後に、私は中国(より正確には台湾)に来て、人文科学ボランティアと直接コミュニケーションを取りました。 そして、これらはプログラマー、言語学者、そして修道士です。 それでも、私たちの主な目標は、仏教の聖書を完全にデジタル化することです。 そして、私が「完全」と言うとき、これは修道院のクローゼットからのこれらすべてのボリュームのOCRを意味しません。 これは、校正、バージョンと翻訳の比較、インデックス作成、さまざまな検索モード、文法ツール、構文解析および意味解析の大きな仕事です。 ティピタカは聖書の100倍のサイズであり、明確な段落番号付けシステムさえ持っていないと言うだけで十分です。 チベット語バージョンはスキャンされるだけで、OCRによって認識されません。 翻訳に関しては、ティピタカはサンスクリット語、中国語、チベット語にのみ翻訳されています。 一部の小さな部品は他の言語に翻訳されています。 私の知る限り、英語に翻訳されているのは10%未満、ロシア語に翻訳されているのは1%未満です。



膨大な量の作業を行う必要があります! そして、この考えられないすべての作業は、ボランティア、数百、数千人のボランティアのみが行うことができます。 しかし、彼らにはツールが必要です。 インデックスの作成、検索、形式の変換のために作成するオープンライブラリに加えて、ビジュアルツールも必要です。 また、異なるデバイスで動作するためにも必要です。



電話機のJavaScriptは、ブラウザマシンのラッパーであるWebViewコンポーネントのユーザーインターフェイスを有効にします。 ブラウザは、ローカルファイルおよびその他のシステムリソースへのアクセスの制限です。 いくつかのWebViewベースのアプリケーションは、起動速度とユーザーアクションへの反応速度が望まれていることを示しており、DOMに必要なメモリ量は驚くべきものです-強力なPCでさえ、多くのWebページを同時に開くことは依然として難しいと感じています。 ネイティブ、つまりネイティブのJavaScriptインターフェースを持つことは素晴らしいことです。



彼らは捜索し始めました、それは判明しました、彼らはそうです。 最初に、不思議なことにPhoneGapを試しましたが、同じブラウザー内で、それが意味するすべてを試しました。 JavaScriptを学んでいたとき、Aptanaと呼ばれるIDEを使用しようとしました。 これは、JavaScriptに特化したEclipseのフォークです。 しかし、後にAptanaは姿を消し、Titanuimに買収されてプロジェクトに参加したことが判明しました。 Appcelerator Titanuimは、iOSおよびAndroid用のネイティブアプリケーションを作成するためのフレームワークです。



Titaniumで最初のプロジェクトを開始しました。 しかし、喜びは失望に変わりました。 面倒なツールはもうありません! Titanium Studioをダウンロードして実行することさえ問題でした。 JavaScriptよりも簡単に思えますか? テキストエディタでソースを変更しました-プログラムを再起動しました、それだけですか? しかし、タイタニック号では、これはうまくいきませんでした。 さらに、約束されたチタン製デスクトップPCバージョンはまったく機能しませんでした。 次に、ネイティブ拡張のプラグインも機能と速度が制限されていることが判明しました。 行を変更するたびに、プロジェクト全体を再構築し、電話に再インストールする必要がありました。 いいえ、これは私たちの方法ではありません。高速で小さいものが必要であり、電話だけでなくデスクトップで作業することを確認する必要があります.ifdef(プラットフォーム)や他のクロスプラットフォームの苦痛なしで迅速に作業することが望ましいでしょう。



それで、長い会話、インターネットでの無限の検索、あらゆる種類のフレームワークとライブラリのテストの後、それは存在しませんでした。 ネイティブJavaScript GUIアプリケーションを作成するためのクロスプラットフォームライブラリまたはフレームワーク、どこにありますか? 彼女じゃない! しかし、検索とテストのためにすでに数か月を殺してしまったため、必要なものとそうでないものについて明確な考えがあり、そのようなライブラリの複雑さを理解し、既存のすべてのプラットフォーム用に多くのテストアプリケーションをすでに作成していたので、私たちは決めました:自分でできる。 さらに、ボタン、入力フィールド、画像、ラベル、ファイルアクセス、フォント選択、グループ化およびスクロール機能など、必要ありません。 これらのコンポーネントはすべて、初心者でも使用されます。 これらすべてを適切に収集し、JavaScriptからアクセスできるようにするだけです。



数時間のブレーンストーミングの後、これに取り組むことが決定されました。 ヤップは私に言った:



-すべて一緒に収まります、いくつかのコンポーネントが必要です、それらはシンプルでなければなりません、そして私たちは控えめな力に対処することができます-何百万もの投資と大規模な開発チームなしで、そしてJavaScriptの柔軟性により、限られた数のコントロールで複雑なGUIを作ることができます



これまでのところ、彼らは単に「もう1つのユーザーインターフェイスライブラリ」または「YaUIライブラリ」(英語では「wai-hey-yu-ah」)という名前を付けることにしました。



そのため、まず、3つのプラットフォーム(i386上のWindows、Android、iOS *(iPhone / iPad))に限定することにしました。



* iOSの場合、Appleの設計により、V8を使用することはできません。 実際、JITコンパイルでは、仮想メモリページを「データ」タイプから「実行可能コード」タイプに再マーキングする必要がありますが、この操作はiOSではブロックされます。 確かに、ルート権限を取得すれば、この制限を排除できます(したがって、ジェイルブレイクされたiphoneコンソールでnode.jsを実行できます)が、これまでのところSpiderMonkeyを使用することが決定されました。 彼らによると、SpiderMonkeyは世界で最初のJavaScriptエンジンであり、Firefoxブラウザーを含むすべてのMozillaプロジェクトがそれに取り組んでいます。 私はiMonkeyプロジェクトを見つけました-iOS用のSpiderMonkeyポートを特別に削減し、自分で再構築しました。 iMonkeyは、手動で削除されたファイルとJITを担当するコード行によって区別されます。 これは非常に難しい問題であり、メインブランチからこの分岐を作成するのに人にかかる費用(結局、このような混乱があります!Mozilla開発者が私を許してくれますように)と言わなければなりません。 論理的には、makeを実行する前にDISABLE_JITキーで十分ですが、残念ながら、彼はハンドルで多くのパッチを適用する必要がありました。 したがって、iMonkeyがSpidermonkey 1.8.0であるという問題、およびSpiderMonkeyの最新バージョンはすでに1.8.7です。 任意のプラットフォーム向けにV8を再構築するのははるかに簡単でした。 残念ながら、すでにコンパイルされたものをホストしている人はいません。 (多分あなた、親愛なる読者?)



YaUIの基本原則:





現在(2013年4月)、Yauiはファイルの操作、ボタン、ラベル、入力行、プレーンテキストエディター、jpgまたはpngから読み込まれた画像、JavaScriptの個々のピクセルへのアクセスを提供するpixmapコントロールを操作できます。 ScrollViewも、垂直および水平に機能します。 他のコントロールはScrollViewに配置でき、1つのScrollViewは別のコントロールに配置できます(多方向、つまり垂直から水平、またはその逆の場合)。 電話機では、ScrollViewは、Windowsで画面をタップして、CtrlキーまたはAltキーを押しながらスクロールします(それぞれ水平および垂直スクロール用)。 Control / Altを使用せずに1週間ほど試してみましたが、失敗しました。明らかに、低レベルのWinAPI、システムフック、またはコードインジェクションを使用する必要があります。



WindowsファイルとしてのYauiとは何ですか? これは、「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
      
      







次のように始めます。

 >cd yaui >yaui hello.yaui
      
      







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はWindowsバージョンと同じです。)



記事を読み過ぎないように、iPhoneを持っていません。



内部デバイス。 条件付きで、YaUIのソースコードは3つのレベルに分けることができます。 ネイティブ、バインディング、および高レベル。



レベル0-ネイティブコード、コントロールを作成して操作するための一連の関数。 もちろん、各プラットフォームでは、このレベルのコードは独自の言語で異なり、独自のツールでコンパイルされています。 コントロールを作成するための関数は、ハンドル(未定義タイプの値)を返します。 同じレベル-ファイルにアクセスするための関数:fopen()fread()など レベル0は、AndroidではJavaおよびC ++(JNI経由)、WindowsではC ++、Objective-C、およびiOSではC ++です。



以下は、3つのプラットフォームでの同じ低レベルラベル作成関数の例です。



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); }
      
      







合計で、このような関数は約30個あるため、新しいプラットフォームへの移植は比較的低コストのイベントです。 (そして、私はそれらを可能な限り小さくするために戦います。段落1を参照してください。)



レベル1はすでにJavaScriptです。ここでは、関数に関数であるネイティブコードをJavaScriptに直接アタッチします。たとえば、同じラベル作成関数をレベル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) }
      
      







このバインディングの目的は、すべてのプラットフォームで同じ機能を取得することです:



  yaui.make_label = function(parent)
      
      







レベル2は、実際には開発者が使用できるAPIです。 彼はレベル0-1について知る必要はありません。 レベル2では、すべての低レベル関数は機能が統一されたオブジェクトでラップされます。たとえば、すべて.set_xy(x、y)メソッドを使用し、すべてのメソッドがこれを返します。つまり、チェーンで呼び出すことができます。



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







これはYaUIの「HelloWorld」です!



もちろん、「老婦人」を書き留めることができます。



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







yauiの抽象化レベルを上げる主な方法はセレクターです(jQueryとほぼ同じです)。セレクター、セレクションは、コントロールの配列を操作する機能です。 名前(id)、クラス、またはフィルター関数を指定して、コントロールを選択できます。 以下に、セレクター、YaUI、およびJavaScriptの一般的な機能の一部を示すレースゲームの簡単な例を示します。



 // 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()
      
      







スクリーンショットは、ライブデバイスで作成された写真の品質にごめんなさい。 (異なるレースで見ることができるように、異なる「車」が勝ちました。)

画像画像画像



このプログラムをWindowsで実行するには、Yaui.exeの最初のパラメーターとして指定する必要があります。



 C:\yaui\yaui.exe race.yaui
      
      







.yauiファイル拡張子は、ファイルの関連付けに役立つ規則です。ファイルにrace.jsという名前を付けることができます。 yaui.exeはどこで入手できますか? 2つの方法-コンパイル済みの「exe」をダウンロードするか、自分でビルドします。 どちらもSourceforgeにあります。



携帯電話にyauiをインストールして実行する方法は、詳細な説明が必要な別の話です。 そして、それがとても難しいのは私のせいではないと言うことができます(特にiOSで)。 誰でもサポートされているすべてのプラットフォームでプログラムできるように、完全にバイナリソリューションを提供したいと思います。



まだないのは何ですか?



幅広いJavaScript開発者向けの優れたYauiドキュメント、Yauiの開発と新しいプラットフォームへの移植を希望する人向けのドキュメントはありません。 サンプルプログラムはほとんどありません(ひどいです)。

X(Linux、FreeBSD)、MacOS、Windows Phone用のポートはありません。ブラウザーポートはありません。 はい、ブラウザでYauiを実行できます。これにより、ブラウザデバッガを使用できるようになります。

フレームワークの豊かさだけでは十分ではありません。つまり、Yauiが既にできることを基に、新しいコントロールと関数を作成する必要があります。 たとえば、ComboBox、GridView、textviewに基づくCalendarView、すでに存在するscrollview ...

機能、パフォーマンス、互換性、信頼性の拡張によりネイティブ部分を改善し、多くのテスト、デバッグを実施し、テストおよびデバッグ用の自動化ツールを作成できます。



要するに、すべての国のプログラマーと仏教徒は、オープンソースのアイデア、オープン性の実用性と実用性、クロスプラットフォーム、ガジェットの愛、JavaScript、ミニマリズムとソフトウェアのナノマリズム、新しいエキサイティングなユニークなフレームワーク、ブッダ、サンガを助けたいという願望に惹かれたら接続または参加しますDharmaまたはあなたがこの記事を気に入った-書き込み、ダウンロード、レポジトリでのコミット、フォーク、友達への投稿。



リポジトリおよびバイナリ配布へのリンク。

sourceforge.net/projects/yaui



All Articles