# Nuake UI
> This is a work-in-progress document that serves as a documentation for NuakeUI.

NuakeUI is a library that is meant to create user interfaces that are flexible and responsive. It uses NuakeRenderer as a rendering back-end but work is done to allow users to define their own rendering back-ends. It also uses Yoga Layout as a layout engine and is planned to support Skia for SVGs and iconography rendering.
UI layouts defined in a pseudo-html-like language and styling is done in pseudo-css. Both should be familiar to any web developer. The behaviour of the UI is defined in C++ code using callbacks and data structure to store the state of the UI. Some primitive binding is possible with basic expression evaluation inlined in the HTML.

## Customization
Users can define their own HTML nodes with custom behaviour through C++

## How-to use
First, you will need to create a `CanvasParser` which is an object that allows to create the internal data structure of the UI. If you wish to use custom node, you need to register them in the `CanvasParser` before you can parse your HTML file.

You need to include `NuakeUI/NuakeUI.h` to have access to the `CanvasParser`.

### Registering Custom Nodes
> You can skip this part if you do not wish to use any custom nodes

To register custom nodes, you can call `RegisterNodeType` on the CanvasParser.

```cpp
#include <NuakeUI/NuakeUI.h>

#include "MyCustomNode.h"

void main()
{
    auto parser = NuakeUI::CanvasParser();    
    parser.RegisterNodeType("MyCustomNode", std::make_shared<MyCustomNode>());
    
    ...
}
```

`RegisterNodeType` takes in the name you wish to use in your HTML file as the first parameter and a function pointer to a method that returns a `std::shared_ptr` of your node type.

### Parsing your HTML
After registering your custom nodes, you can follow through with the parsing. Simply call the method `Parse` on the `CanvasParser` with the path to your html file.

```cpp
void main()
{
    auto parser = NuakeUI::CanvasParser();
    // registering of custom nodes...
    
    std::shared_ptr<Canvas> canvas = parser.Parse("path_to_html.html");
    ...
}
```

The `Parse` method returns a shared pointer to a `Canvas` object.

## Rendering your canvas
To render your canvas to the window or a framebuffer. You need to call 3 methods in your main rendering loop.

You need to call the following methods in order:
1. canvas->ComputeLayout
2. canvas->Tick
3. canvas->Draw

`ComputeLayout` takes in a vector2 which should contain the size in pixel of your texture.
`Tick` is the main update method
`Draw` does the rendering.

#### The canvas
The canvas serves as a container to your interface. You can think of the Canvas as being the Root node of your UI. It is through the Canvas that you can find your nodes and interact with them.

The canvas always has a Root node that you can access through the `GetRoot()` method. It returns a shared pointer to the first node of your canvas.

### Accessing Nodes
There are multiple ways to access nodes in your tree. The most common way is to set an id to your node and then using `FindNodeByID<T>(id)` method on the canvas.
To set an id on your node, simply use the `id` tag in your HTML file like so:

```html
<!-- files: layout.html -->
<node id="myId"></node>
```

You can then get a pointer to that node like so:

```cpp
void main() 
{
   auto parser = NuakeUI::CanvasParser();
    // registering of custom nodes...
    std::shared_ptr<Canvas> canvas = parser.Parse("path_to_html.html");
    
    auto myNode = canvas.FindNodeByID<NuakeUI::Node>("myId");
}
```

`FindNodeByID` is a templated method and the typename passed in the template should be the correct type for your node.

So if you registered a custom node and you want to find it by id. You need to pass the type of your custom node to the template like so:

```cpp
void main() 
{
    auto parser = NuakeUI::CanvasParser();
    parser.RegisterNodeType("MyCustomNode", std::make_shared<MyCustomNode>()); // Custom node type.
    
    std::shared_ptr<Canvas> canvas = parser.Parse("path_to_html.html");
    
    auto myNode = canvas.FindNodeByID<MyCustomNode>("myId");
}
```

## Buttons
NuakeUI offers a basic button implementation which has a click callback. The click callback is essentially an `std::function`.
In order to be able to use buttons, you need to define an inputManager implementation. You need to create a class that derives from `NuakeUI::InputManager` and implements the following methods:

```cpp
virtual bool IsMouseInputDown() = 0;
virtual float GetMouseX() = 0;
virtual float GetMouseY() = 0;

virtual float GetScrollX() = 0;
virtual float GetScrollY() = 0;

virtual bool IsKeyPressed(uint32_t key, uint32_t state) = 0;
```

You can then register the InputManager on the `Canvas` object directly like so:
```cpp
void main() 
{
    auto parser = NuakeUI::CanvasParser();
    auto canvas = parser.Parse("path_to_html.html");
    canvas.SetInputManager(new MyInputManager()); // takes in a raw pointer.
}
```

After you've set the InputManager, mouse events should now work properly.
You can now set the button callback like so:

> In this example, we are using a lamda, but you can also use a function pointer with the same signature.
```cpp
void main()
{
    ...
    auto button = canvas.FindNodeByID<NuakeUI::Button>("myButton");
    button->SetClickCallback([this](NuakeUI::Button& btn)
		{
			std::cout << "I have been clicked!" << std::endl;
		};
	);
    ...
}
```



