NiGui入門(v0.1.0)

初投稿。

注 : 
・この記事は不完全であり、まだ追加の必要な部分も多くあります。
・非公式です。
・これはあくまで使い方のほんの一部の基本を日本語で表したものです。
もっと多くの機能を利用する場合は、GitHub等に公開されているexampleをみたり、ソースコードを見るなどしてご自身で習得していただきたいです。
#[ 0 ] NiGuiとは？
Nim用に作られたGUIライブラリです。
(GitHub : https://github.com/trustable-code/NiGui )

#### 利点

<dl>
 <dt>とにかく軽量</dt>
 <dd>Windows用はWin32API、MacOS・Linux用はGTK+3上で動作します。<br>
 それだけでもかなり軽量ですが、当然使用言語はNimですから...もはや軽量性はほぼ文句なしです。<br>
 (一方nimxはSDLベースなのでちょっとそこらへん心配です。)<br>
 </dd>
 <dt>クロスプラットフォーム</dt>
 <dd>
 現在実装が出来ているかどうかはまだわかりませんが、上記の通りWin32API、MacOS・Linux系で動作します(少なくともする予定だそうです)。
 </dd>
 <dt>使いやすい</dt>
 <dd>
 非常に使いやすいです。<br>
 使いやすいのに、超軽量なGUI環境の構築ができる...最高！！！！
 </dd>
</dl>

ほかにもnimxやiup、ui(libui)なども有名ですが、NiGuiは中でも個人的に一番使いやすかった(そもそもnimx以外どう足掻いてもエラーしか吐かなかっただけ)ので、今回はこちらを紹介します。

ただし、NiGuiの開発はいまだ進行中です。
まだいろいろ抜けている機能も多くあります。(今回は **0.1.0** 前提でお話しします。)
(開発者自身"The project is in a very early stage."と言っているので、紹介するには早すぎたかもしれません。言語もライブラリも未完成の環境なんてなかなかロマンあるでしょ？)

nimxも悪くないので、そちらを試すのもおすすめです。

#[ 1 ] はじめの一歩
##{0} NiGuiをインストールする
インストールには2つの方法があります。
###(0) nimbleからのインストール
こちらが一番簡単な方法だと思います。
nimbleが使える環境にしたうえで、
```$ nimble install nigui```
とコマンドを打ち、実行してください。
```Success: nigui installed successfully.```
と出たらOKです。簡単 !
![E-1.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/e9e8a86d-328f-74d8-3f6a-b8f626299486.jpeg)

一応ですが、アンインストールするときは、
```$ nimble uninstall nigui```
を実行してください。
###(1) 手動インストール
実はやったことありません。readmeに書いてあったことを丸コピしただけなので、間違えていたら教えてください。

1 : ソースコードをGitHubからダウンロードします。
(GitからクローンするのもOK)
2 : Nimの設定ファイル(nim configuration files)で、
```--path:"<path_to_nigui>/src"```と実行します。


##{1} 試しに動かしてみる
では、実際にNiGuiを動かしてみましょう。
お好きなエディタから

```nim:Sample.nim
import nigui
app.init()
let Win=newWindow("Hello,World!")
Win.show()
app.run()
```
上記をコピー&ペーストして、
```$ nim c -r Sample.nim```
で実行します。
![E0.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/d2d889d5-b6a2-8a12-8c7f-4e7abac1c6cc.jpeg)

空っぽのウィンドウが作成されたら成功です!

#[ 2 ] ウィンドウを作成・いじる
実用的な部分に入ります。
(ここからは「Widget」という言葉をちょこちょこ使いますが、ここではButtonやLabelなどのGUIアプリケーションの部品を指します。)
##{0} ウィンドウの作成 - Window
まずは何もないウィンドウの作成をマスターしましょう。

```nim:newindow.nim
import nigui
app.init()

#window
let Win=newWindow("NiGui is cross-platform, desktop GUI toolkit written in Nim.")
Win.width=600
Win.height=500
Win.x=100
Win.y=200
Win.iconPath="(ファイル名).png"

Win.show()
app.run()
```
を実行すると、
![E1.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/382fc612-fdec-fb21-679e-8e4fe784ca1f.jpeg)

このようなウィンドウが生成されます。

== 説明 ==

|文法|内容|補足|
|:-:|:-:|:-:|
|app.init()|アプリケーションの初期化|必須。|
|app.run()|アプリケーションの実行|-|
|newWindow("タイトル名")|Windowの宣言|タイトルは「[window].title」でも指定可能。|
|[window].width (height)|Windowの横幅(縦幅)指定|使用する際はどちらも指定しないと動きません。|
|[window].x (y)|Windowの横(縦)の位置の指定|-|
|[window].iconPath|アイコンの設定|PNGファイルを使用してください。|
|[window].show()|Windowの表示|忘れがち (・_・ ; )|

##{1} LayoutContainerの設置・文字の挿入 - Label
文字を表示してみましょう。
LayoutContainerは、今後も色々使うので使い方は覚えておきましょう。

```nim:labelbel.nim
import nigui
app.init()
let Win=newWindow("LabelTest")

# Container
let Con=newLayoutContainer(Layout_Vertical)
Con.setPosition(100,130)
Win.add(Con)

# Label1
let Lab=newLabel("Welcome to the next label")
Lab.fontSize=20
Con.add(Lab)

# Label2
let La2=newLabel("SG MegaDrive")
La2.fontSize=40
La2.fontFamily="Consolas"
Con.add(La2)

Win.show()
app.run()
```
![E2.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/a083bde7-7a32-6b85-9017-5a8ba9d559ee.jpeg)

== 説明 ==

|文法|内容|補足|
|:-:|:-:|:-:|
|newLayoutContainer([layout])|LayoutContainerの宣言|[layout]の中身は下記参照。|
|[window].add([widget])|WindowへのWidgetの追加|-|
|[layoutContainer].setPosition(x,y : int)|位置の指定|-|
|[layoutContainer].add([widget])|LayoutContainerへのWidgetの追加|-|
|newLabel("テキスト")|Labelの宣言|テキストは「[label].text」でも可能。|
|[label].fontSize|文字の大きさの指定|デフォルトの値は15。|
|[label].fontFamily|フォントの指定|-|


LayoutContainerに設置したWidgetは、
上から下( Layout_Vertical )に、もしくは左から右( Layout_Horizontal )に並んで設置されます。

##{2} ボタンの配置・イベントの実装 - Button
ボタンを設置しましょう。

```nim:Oseyo.nim
import nigui
app.init()
let Win=newWindow("ButtonTest")
let Con=newLayoutContainer(Layout_Vertical)
Win.add(Con)
Con.setPosition(40,50)

# Event
proc Func(Ev:ClickEvent)=
  echo "AAAAAHHHHH!!!"

# Button
let Bt=newButton("Osunayo...Osunayo...Zettaini...Osunayo....")
Bt.fontSize=20
Bt.onClick=Func
Bt.width=300
Bt.height=50
Con.add(Bt)

Win.show()
app.run()
```

![E4.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/293a7563-ff84-c0db-a66c-73ec99117b32.jpeg)


配置の方法はLabelと似た感じですね。LayoutContainerを使用します。

== 説明 ==

|文法|内容|補足|
|:-:|:-:|:-:|
|newButton("テキスト")|Buttonの宣言|テキストは「[button].text」でも指定可能。|
|[button].onClick|Buttonのイベントの設定|値は関数。無名関数も使用可能(下記参照)|

onClickでは無名関数をそのまま使用することもできます。
上のプログラムを引用すると、

```nim
Bt.onClick=proc(Ev:ClickEvent)=
  echo "AAAAAHHHHH!!!"
```
こんな感じです。
これを応用すれば、引数のある関数を呼び出したかったりするときにも便利です。

```nim
var n="AHH...Ii yuzyaneka!!!"
proc say(x:string)=
  echo x
Bt.onclick=proc(Ev:ClickEvent)=
  say(n)
```

##{3} 入力ボックスの作成 - TextArea / TextBox
テキストを入力できるスペースを作りましょう。
TextAreaとTextBoxの2つがありますが、違いは次の通りです。

TextArea : 改行を含むテキストを入力できる。
TextBox : 一行のみのテキストを入力できる。

```nim:TextAB.nim
import nigui
app.init()
let Win=newWindow("InputTest")
let Con=newLayoutContainer(Layout_Vertical)
Win.add(Con)

let Ta=newTextArea("Text")
Con.add(Ta)
Ta.editable=true
Ta.addText("Area")
Ta.width=300
Ta.height=100

let Tb=newTextBox("TextBox")
Con.add(Tb)

let Bt=newButton("Print out")
Con.add(Bt)
Bt.onClick=proc(e:ClickEvent)=
  echo Ta.text
  echo Tb.text

Win.show()
app.run()
```
![E5.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/ad4bc38c-83f8-b631-e2d7-2ebd0f6df9ec.jpeg)


== 説明 ==

|文法|内容|補足|
|:-:|:-:|:-:|
|newTextArea("テキスト")/newTextBox("テキスト")|textArea/textBoxの宣言|テキストは「[textArea/textBox].text」でも可能。|
|[textArea/textBox].editable|入力の制限|falseで入力できなくする|
|[textArea].addText("テキスト")|textAreaへの文字の追加|[textArea].addLine("テキスト")でも可能。違いは...分からない。だれか教えて|
|[textArea/textBox].text|textArea/textBoxの内容|上記のコードのように出力したり、[].text=(string)で直接値を入力することもできる。|

##{4} お絵かき大好き - Control
絵や図形、写真もGUIアプリケーションを彩る重要なものです。
これは少し難しいですが、慣れればちょっと文を覚えておくだけで自由自在に操れます。

```nim:Canvas.nim
import nigui
app.init()
let Win=newWindow("CanvasTest")
let Ctl=newControl()

Ctl.widthMode=WidthMode_Fill
Ctl.heightMode=HeightMode_Fill

Ctl.onClick=proc(c:ClickEvent)=
   echo "Canvas"

let Img = newImage()
Img.loadFromFile("(ファイル名).png")

Ctl.onDraw=proc(e:DrawEvent)=
  let Cv=e.control.canvas

  Cv.areaColor=rgb(255,240,180)
  Cv.fill()

  Cv.textColor=rgb(0,255,0) # green
  Cv.fontSize=20
  Cv.drawText("text",10,180)

  Cv.areaColor=rgb(0,0,255) # blue
  Cv.drawRectArea(120,120,180,200)

  Cv.lineColor=rgb(255,0,0) # red
  Cv.drawLine(30,150,180,40)

  Cv.drawImage(Img,10,10,65)

Win.add(Ctl)
Win.show()
app.run()
```
![E6.JPG](https://qiita-image-store.s3.amazonaws.com/0/238002/1ef7fa74-8342-3c89-7d78-13cf4c5a43d1.jpeg)



== 説明 ==

|文法|内容|補足|
|:-:|:-:|:-:|
|newControl()|Controlの宣言||
|[control].widthMode(heightMode)|WidthMode(HeightMode)の設定|下記参照|
|newImage()|Imageの宣言||
|Img.loadFromFile("(ファイル名).png")|Imageの読み込み||
|[control].onDraw|Controlへの描写||
|rgb(byte,byte,byte)|Niguiで使われる色指定用type(Color)|数字の型はbyteかuint8である必要がある|
|[DrawEvent].control.canvas.areaColor|使用する色の設定|areaColorの他にもlineColorやtextColor等があり、色の指定の対象によって使い分ける必要がある|
|[DrawEvent].control.canvas.fill()|Controlの塗りつぶし|areaColorで色を指定|
|[DrawEvent].control.canvas.drawtext("テキスト" ; x座標,y座標)|テキストの描写|textColorで色を指定|
|[DrawEvent].control.canvas.drawRectArea(始点x座標,始点y座標,終点x座標,終点y座標)|四角形の描写|areaColorで色を指定|
|[DrawEvent].control.canvas.drawLine(始点x座標,始点y座標,終点x座標,終点y座標)|線の描写|lineColorで色を指定|
|[DrawEvent].control.canvas.drawImage([Image],x座標,y座標,大きさ)|Imageの表示|大きさのデフォルトは65|

controlはwidth・height及びsetSizeの使用により縦・横幅を指定することができますが、変わった挙動がほしい場合はWidthMode・HeightModeも使えます。
WidthMode_Auto
WidthMode_Static
WidthMode_Expand
WidthMode_Fill 
の4種類から選べますが、違いは正直よくわかってません。
(無知ですいません。教えていただけるとありがたいです)
# [ 2 ] その他もろもろん
・コンパイルしてできたバイナリを実行すると、通常アプリケーションと同時にコマンドラインが出てきますが、
```$ nim c -r --app:gui Sample.nim``` とすることでコマンドラインをなくすことができます。
いざ完成 ! って時に忘れないようにしましょう。

・アプリケーションは、```app.quit()```で終了させることができます。

・Windowは、```[window].minimize```で最小化できます。

・Controlに描写されているCanvasは、```[control].forceRedraw``` で表示の更新をすることができます。入力で表示を変更したい時などに便利です。



# [ 3 ] 終わりに
[ 0 ]でも言いましたが、まだ未完成のライブラリです。
ですがそれでも非常に使いやすく、未来の明るいライブラリなので、知って損はない...かも？

Nimで利用できるGUIライブラリは純Nim製のnimxをはじめ、他に他言語のライブラリ由来のui、ipu、gtk2(正確にはそれらのラッパー)などいろいろありますが、僕はNiGuiが好きです。

確かに他と比べてもNiGuiはまだ機能が少なく、かゆいところに手が届きませんが、僕はNiGuiの方が愛着があり、また純Nim製のGUIツールとしてはコンパイルも非常に高速(使用してるModuleが最小限であるが故)で効率的な作業が望めるため、僕はこれからもNiGuiを使い続けていく方針です。

(というか、NiGuiとnimx以外はいろいろあって環境の構築が非常に困難で手間手間いし、できてもあまりよろしいとはいえないものばっかりな気がする)

.

あと、僕は以前にNiGuiで( 機械学習への用途を意識した )グラフツールを制作したことがあります。
あくまで個人用として作ったものですが、せっかくなので公開しました。自由に使用・改造してください。
https://github.com/mzteruru52/NmiLine
- 低学歴渾身の英語力をご堪能あれ。(訂正していただける方大歓迎) -