Skip to content

MaslOS2 GUI‐Framework

Masl edited this page Dec 31, 2023 · 48 revisions

Here are the most important things surrounding the GUI-Framework in MaslOS2.

If you have not read the Application Development Guide for MaslOS2, please read it now.

(This page is still heavily WIP)

For now the best way would be just to look at some GUI programs that are already implemented in MaslOS2.

Basics

Important Classes

For GUI Framework dev important classes are:

Please also take a closer look at important functions related to windows if you have not.

Color

All colors are 32 bit ARGB colors.

There is a color struct with some premade colors which you can find in <libm/rendering/Cols.h>.

NOTE: The GUI System supports basic transparency, with either full transparency or no transparency depending on the alpha channel.

Components

Components all derive from a Base Component class. All Components have Base Attributes and Specific Attributes.

NOTE: They should also have a unique ID!

Some IDs are reserved or used by default, which you should change.

Reserved/Default IDs

The screen component has a default id of 1234.

Button Components create Subcomponents.

  • The inner rectangle component will have the id of 123401.
  • The inner text component will have the id of 123402.
  • When creating buttons, you should update the Subcomponent ids.

Creating Components

You can create a component in two ways:

Creating a component manually

An Example would be:

// Create the component
TextComponent* txt = new TextComponent(
    gui->screen, // parent
    Colors.black, // background color
    Colors.white, // foreground color
    "Hello!\nThis is an amazing test.", // text, which has several lines
    Position(200, 90) // a position
);

// Add the component to the main screen
gui->screen->children->Add(txt);

Creating a component using the GUI Instance (recommended)

An Example would be:

// Create the component
// NOTE: You will need to give it a unique ID!
gui->CreateComponentWithId(123456, ComponentType::BUTTON);
ButtonComponent* button = (ButtonComponent*)gui->GetComponentFromId(123456);

// Set the position and size
button->position.x = 52;
button->position.y = 0;
button->size.FixedX = 50;
button->size.FixedY = 20;

// Set the text
_Free(button->textComp->text);
button->textComp->text = StrCopy("Click me");

Deleting Components

In contrast to most libm classes, components don't have a Free function, but rather a Destroy function.

The important difference is that Destroy also deletes the instance itself!

You can delete a component in two ways:

Deleting a component manually

The function looks like this:

bool Destroy(bool destroyChildren, void (*callBackFunc)(BaseComponent* comp));

Here is an example of creating and deleting a component:

// Create the component
TextComponent* txt = new TextComponent(
    gui->screen, // parent
    Colors.black, // background color
    Colors.white, // foreground color
    "Hello!\nThis is an amazing test.", // text, which has several lines
    Position(200, 90) // a position
);

// Add the component to the main screen
gui->screen->children->Add(txt);

// ...

// Destroy
txt->Destroy(true, NULL);

Deleting a component using the GUI Instance (recommended)

Alternative you can also delete components from the GUI Instance using the ID.

There the function looks similar:

bool GuiInstance::DeleteComponentWithId(int64_t id, bool destroyChildren);

Here is an example of creating and deleting a component:

// Create the component
// NOTE: You will need to give it a unique ID!
gui->CreateComponentWithId(123456, ComponentType::BUTTON);
ButtonComponent* button = (ButtonComponent*)gui->GetComponentFromId(123456);

// Set the position and size
button->position.x = 52;
button->position.y = 0;
button->size.FixedX = 50;
button->size.FixedY = 20;

// Set the text
_Free(button->textComp->text);
button->textComp->text = StrCopy("Click me");

// ...

// Destroy
gui->DeleteComponentWithId(123456, true);

The Render-Loop

All Windows with a GUI will need to process events and display things and changes, which is why you will need a Render-Loop of some sorts.

The Gui Instance comes with 2 methods:

void Update();
// This will just process the packets/updates received from the desktop.
// This includes:
//  - Keyboard Inputs
//  - Mouse Inputs
//  - Window Updates (Moved, Resized, Activated, Closed, etc)

void Render(bool update);
// This will go through each component, check for changes and then render them.
// This will also send those updates to the desktop.
// NOTE: If you already call the `Update` function, you can set update to false.

You can have two kinds of Render-Loops:

Render-Loop with no manual updates

This is useful if your application has barely any changes and uses events to do things.

while (!CheckForWindowClosed(window))
{
    gui->Render(true);

    programWaitMsg();
}

Render-Loop with manual updates

This is useful if you have things you might need to update/move every frame.

while (!CheckForWindowClosed(window))
{
    guiInstance->Update();
    UpdateSizes(); // External method
    HandleFrame(); // External method
    guiInstance->Render(false);

    programWaitMsg();
}

Waiting between frames.

Most apps will not need to render at thousands of frames per second.

Especially if the app is mostly waiting for any sort of user interaction.

If that is the case you can use programWaitMsg(); between frames to wait until any sort of interaction occurs.

If your app does something in fixed time intervals, you can use programWait(int timeMs);.

Or if it is supposed to run as fast as possible, you can use programYield();.

Just please remember to not be too greedy with the processor time as there are other apps trying to run as well!

Event Handling

All components can receive events.

Mainly these are Mouse and KeyHit events.

They look like this:

void BaseComponent::MouseClicked(MouseClickEventInfo info);
// The Function that handles the Mouse event.

struct MouseClickEventInfo
{   
    Position MousePosition;
    // Position of the mouse relative to the window.

    bool LeftClickPressed;
    bool RightClickPressed;
    bool MiddleClickPressed;
};
void BaseComponent::KeyHit(KeyHitEventInfo info);
// The Function that handles the key event.

struct KeyHitEventInfo
{
    uint8_t Scancode;
    // PS-2 Scancode.

    char Chr;
    // Scancode as a character, if possible.
};

A few components need those events to function!

Catching events from the outside

Some components provide extra callbacks (actually a function pointer you can set) which you can use.

An Example for the Button Component:

class ButtonComponent : public BaseComponent
{
    // ...

    void (*mouseClickedCallBack)(BaseComponent*, MouseClickEventInfo);
    // Will get called when a mouse event happens

    void (*keyHitCallBack)(BaseComponent*, KeyHitEventInfo);
    // Will get called when a key hit event happens.

    // ...
}

But not every class has these callbacks.

What if you want to handle a rectangle being clicked?

Well for that you can actually overwrite the internal handlers of any component.

These function pointers exist in all Base Components.

You can overwrite them with your own function pointers.

Here is an example to catch and process all key inputs in a canvas component:

void HandleKey(void* baseComponentInstance, KeyHitEventInfo event)
{
    // When a key event occurs, this function will be called 
    // with the instance of the class which received the click 
    // and the actual event information.
}

// -------------------------------------------------

// ...

// Create canvas
guiInstance->CreateComponentWithId(1400, ComponentType::CANVAS);
canvas = (CanvasComponent*)guiInstance->GetComponentFromId(1400);

// Set properties
canvas->position.x = 0;
canvas->position.y = 0;
canvas->size.IsXFixed = false;
canvas->size.ScaledX = 1;
canvas->size.IsYFixed = false;
canvas->size.ScaledY = 1;
canvas->bgColor = Colors.white;

// Update and Clear
canvas->CheckUpdates();
canvas->Clear();

// Overwrite the default KeyHandler for the canvas.
canvas->KeyHitFunc = HandleKey;

// ...

Be careful as some components like the screen component will pass their event down to other components.

Overwriting these components will cause them to not do that anymore.

SelectedComponent and TempSelected Component

The Screen Component has two special variables:

  • selectedComponent
  • tempSelectedComponent

Temp Selected Component

Each frame, this variable will get set to NULL.

If any component feels that it is selected (mouse is hovering over it, some variable set, etc), it can set the screens tempSelectedComponent to itself.

This will be needed to determine the Selected Component.

Only a interactable components require this feature. (An Example would be the button and canvas components)

Selected Component

Once the GUI receives a click event, it will send that to the active screen.

The screen will look at the tempSelectedComponent variable and see if it has been set to anything.

If it has been set, it will get the component and let it handle the event.

The GUI Instance

class GuiInstance
{
    GuiComponentStuff::ScreenComponent* screen;
    // The main screen component connected to the gui instance.

    MouseState mouseState;
    // The current mouse state.
    // Should not be modified!


    GuiInstance(Window* window);
    // Creates a new instance connected to a window.

    void Init();
    // Will properly initialize the gui instance.
    // NOTE: You NEED to call this function to set it up properly!
    // This a remainder from MaslOS where windows and gui instances were connected both ways.

    void Free();
    // Will free all the data and components created.
    // Note: You will need to free the instance itself too though!


    void Update();
    // This will just process the packets/updates received from the desktop.
    // This includes:
    //  - Keyboard Inputs
    //  - Mouse Inputs
    //  - Window Updates (Moved, Resized, Activated, Closed, etc)

    void Render(bool update);
    // This will go through each component, check for changes and then render them.
    // This will also send those updates to the desktop.
    // NOTE: If you already call the `Update` function, you can set update to false.


    bool CreateComponentWithId(int64_t id, GuiComponentStuff::ComponentType type);
    // This will create a new component given an id and type.
    // NOTE: This will use the screen component as the parent.

    bool CreateComponentWithIdAndParent(int64_t id, GuiComponentStuff::ComponentType type, int64_t parentId);
    // This will create a new component given an id, type and a parent.

    bool DeleteComponentWithId(int64_t id, bool destroyChildren);
    // This will delete a component with an id. (This means completely free it and the instance connected to it)


    GuiComponentStuff::BaseComponent* GetComponentFromId(uint64_t id);
    // This will attempt to get a component given its id.

    GuiComponentStuff::BaseComponent* GetChildFromComponentWithId(uint64_t id, int index);
    // This will attempt to get the nth child from any container component. (Screen, Box, Button, Textfield, etc.)
    // NOTE: Some container components like button actually have one child component which itself is a box component!


    int GetIndexOfChildFromComponentWithId(uint64_t id, uint64_t childId);
    // This will get the index of a child in a container component and return it or -1.

    bool RemoveChildFromComponentWithId(uint64_t id, int index);
    // This will attempt to remove a child from a specific component using the index.
    // NOTE: Please just use the `DeleteComponentWithId` function instead!

    bool ComponentRemoveChild(int64_t id, int64_t childId);
    // This essentially combines `GetIndexOfChildFromComponentWithId` and `RemoveChildFromComponentWithId` into one function.


    bool ComponentAddChild(int64_t id, GuiComponentStuff::BaseComponent* childComp);
    // This will attempt to add a child to a container component.
};

Creating your first GUI program

You can learn how to create a simple program here.

Here is the code for a simple GUI program:

#include <libm/gui/guiInstance.h>
#include <libm/gui/guiStuff/components/rectangle/rectangleComponent.h>
#include <libm/wmStuff/wmStuff.h>
#include <libm/cstrTools.h>
#include <libm/heap/heap.h>

using namespace GuiComponentStuff;

int main(int argc, char** argv)
{
    initWindowManagerStuff();
 
    // Request Window
    Window* window = requestWindow();
    if (window == NULL)
        return -1;
    
    // Set the title
    _Free(window->Title);
    window->Title = StrCopy("Hello World!");

    // Set the width and height to 200x200
    window->Dimensions.width = 200;
    window->Dimensions.height = 200;

    // Actually send the changes to the desktop
    setWindow(window);

    // Create the GUI Instance and initialize it
    GuiInstance* gui = new GuiInstance(window);
    testGui->Init();

    // Create a purple rectangle with the size 60x20 which is a child of the main screen component.
    RectangleComponent* testRect = new RectangleComponent(Colors.purple, ComponentSize(60, 20), gui->screen);
    // Set the position to (100, 20)
    testRect->position = Position(100, 20);
    
    // Add the rectangle to the actual screen component.
    gui->screen->children->Add(testRect);

    // Our program should run as long as our main window is open
    while (!CheckForWindowClosed(window))
    {
        // Update and render the frame
        gui->Render(true);

        // Wait until we get a message
        programWaitMsg();
    }

    return 0;
}

Components

Base Component

This component should not exist in it of itself but all components derive from it.

The class is located in <libm/gui/guiStuff/components/base/baseComponent.h>.

It looks like this:

class BaseComponent
{
    // Basic Attributes
    BaseComponent* parent;
    ComponentSize size;
    Position position;
    ComponentType componentType;
    ComponentRenderer* renderer;
    bool hidden;
    int64_t id;


    // Function Pointers, which can be overridden from the outside too
    void (*RenderFunc)(void* bruh, Field);
    void (*CheckUpdatesFunc)(void* bruh);
    void (*MouseClickedFunc)(void* bruh, MouseClickEventInfo);
    void (*KeyHitFunc)(void* bruh, KeyHitEventInfo);
    void (*DestroyFunc)(void* bruh, bool, void (*)(BaseComponent* comp));
    ComponentSize (*GetActualComponentSizeFunc)(void* bruh);
    bool (*SetAttributeFunc)(void* bruh, int32_t, uint64_t);
    uint64_t (*GetAttributeFunc)(void* bruh, int32_t);
    int (*GetAttributeSizeFunc)(void* bruh, int32_t);


    // The actual functions
    ComponentSize GetActualComponentSize();
    Position GetAbsoluteComponentPosition();
    void* GetGuiInstance();
    void* GetScreen();
    bool IsVisible();

    void MouseClicked(MouseClickEventInfo info);
    void KeyHit(KeyHitEventInfo info);

    void Render(Field field);
    void CheckUpdates();
    bool Destroy(bool destroyChildren, void (*callBackFunc)(BaseComponent* comp));

    Field GetFieldWithPos();
};

Component Type

The Component Type enum looks like this:

enum ComponentType : uint8_t
{
    NONE = 0,
    SCREEN = 1,
    RECT = 2,
    BOX = 3,
    TEXT = 4,
    BUTTON = 5,
    TEXTFIELD = 6,
    IMAGE_RECT = 7,
    CANVAS = 8,
    ADVANCED_TEXT = 9
};

Component Position

This describes the position of the component.

struct Position
{
    int x, y;
    // Position in pixels.


    Position(int x, int y);
    // Position at x,y.

    Position();
    // Position at 0,0.

    Position(ComponentSize fixedSize);
    // Position taking the fixed size properties of the provided component size.
};

Component Size

The component size describes the size of the component. It is special, because it does not just support fixed sizes, but also scaled sizes.

NOTE: you can change if any side is fixed or scaled at any point and you can have one size be fixed and one be scaled.

struct ComponentSize
{
    bool IsXFixed, IsYFixed;
    // Is The (X/Y) Size fixed or does it depend on the parent.

    int FixedX, FixedY;
    // Size in pixels.

    double ScaledX, ScaledY;
    // Size in percent of the parent size.
    // 1.0 -> 100%, 0 -> 0%, 0.5 -> 50%.


    ComponentSize(int x, int y);
    // Constructor that creates a fully fixed size.

    ComponentSize(double x, double y) // percent like 0.9 for 90%
    // Constructor that creates a fully scaled size.

    ComponentSize();
    // Will create a fixed size of 0x0.
};

Rectangle Component

Rectangle components are very basic components.

They have a color, size and position.

The class is located in <libm/gui/guiStuff/components/rectangle/rectangleComponent.h>.

It looks like this:

class RectangleComponent
{
    uint32_t fillColor;

    RectangleComponent(uint32_t fillColor, ComponentSize size, BaseComponent* parent);
};

Box Component

A box component is a simple container object that holds other components in no particular way.

Each components position will be relative to the box components position.

Content out of bounds will not be displayed.

A box component also has a background color.

The class is located in <libm/gui/guiStuff/components/box/boxComponent.h>.

It looks like this:

class BoxComponent
{
    uint32_t backgroundColor = 0;
    List<BaseComponent*>* children;

    BoxComponent(BaseComponent* parent, ComponentSize size, uint32_t bgCol);
};

Button Component

A Button component is a component made up of several other components.

Its actually component which uses a box component internally which has a text and a rectangle component.

NOTE: To get or set the text, you need to access the internal text component!

The class is located in <libm/gui/guiStuff/components/button/buttonComponent.h>.

It looks like this:

class ButtonComponent
{
    // Internal components
    BoxComponent* actualButtonStuff;
    TextComponent* textComp;
    RectangleComponent* rectComp;
    

    // Text Foreground Color
    uint32_t textColDef;
    uint32_t textColHover;
    uint32_t textColClick;
    

    // Text Background Color
    uint32_t bgColDef;
    uint32_t bgColHover; 
    uint32_t bgColClick;

    // Properties
    bool stickToDefaultColor = false;
    bool mouseHover = false;
    bool mouseClick = false;


    // Generic Function callbacks for when the button is clicked. (These are recommended to use)
    void (*mouseClickedCallBack)(BaseComponent*, MouseClickEventInfo);
    void (*keyHitCallBack)(BaseComponent*, KeyHitEventInfo);
  

    // A specialized Function callback for when the button is clicked.
    // These are remains from MaslOS, where they were used along with subinstances.
    // NOTE: Please do not use this callback anymore. I will try to refactor and remove it from the codebase soon.
    void* OnMouseClickHelp; 
    // This is a pointer to an instance (can be set to NULL if you are using a static func)
    void (*OnMouseClickedCallBack)(void*, BaseComponent*, MouseClickEventInfo); 
    // This is a pointer to a member function with 2 arguments. (You would set the `OnMouseClickHelp` to the instance.
    // Or a normal function with 3 arguments. (where you can ignore the first arg)

    ButtonComponent(const char* text, uint32_t textColDef, uint32_t textColHover, uint32_t textColClick, uint32_t bgColDef, uint32_t bgColHover, 
};

Text Components

(Simple) Text Component

A very simple text component that displays text.

The class is located in <libm/gui/guiStuff/components/text/textComponent.h>.

It looks like this:

class TextComponent
{
    // Colors
    uint32_t bgColor;
    uint32_t fgColor;

    const char* text;
    // The actual text.

    bool center = false;
    // Defines if the text should be centered.

    bool useFixedSize = false;
    // Defines if the text component should use the fixed size or should scale according to the text content.


    TextComponent(BaseComponent* parent, uint32_t bgColor, uint32_t fgColor, const char* text, Position position);
};

Advanced Text Component

The class is located in <libm/gui/guiStuff/components/advancedText/advancedTextComponent.h>.

It looks like this:

class AdvancedTextComponent
{
    AdvancedTextComponent(uint32_t foregroundColor, uint32_t backgroundColor, ComponentSize size, BaseComponent* parent);

    bool redirectToSerial;
    int32_t scrollX, scrollY, oldScrollX, oldScrollY, oldHeight, oldWidth;
    uint32_t backgroundColor;
    uint32_t foregroundColor;
    List<List<ConsoleChar>*> textData;
    ConsoleChar* tempPixels;
    ConsoleChar* tempPixels2;

    void WriteText(const char* text);
    bool RenderCalled;
    void Reload();
    void DoRender();
    void RenderCharChanges();
    void Clear();
    void SetWindow(Window* window);

    void Println();
    void Print(const char* msg);
    void Print(const char* chrs, const char* var);
    void Print(char chr);
    void Print(const char* chrs, uint32_t col);
    void Print(const char* chrs, const char* var, uint32_t col);
    void DeleteLastCharInLine();

    void Println(const char* msg);
    void Println(const char* chrs, const char* var);
    void Println(const char* chrs, uint32_t col);
    void Println(const char* chrs, const char* var, uint32_t col);
};

Textfield Component

This is a component where users can input text into.

Internally it uses a box component with a simple text component and a rectangle component. (Similar to the button component)

Other than that it has a text foreground and background color.

NOTE: To get or set the text, you need to access the internal text component!

The class is located in <libm/gui/guiStuff/components/textField/textFieldComponent.h>.

It looks like this:

class TextFieldComponent
{
    // Internal components
    BoxComponent* actualTextFieldStuff;
    TextComponent* textComp;
    RectangleComponent* rectComp;
    
    // Colors
    uint32_t textCol;
    uint32_t bgCol;


    // A simple callback for mouse and key events.
    void (*mouseClickedCallBack)(BaseComponent*, MouseClickEventInfo);
    void (*keyHitCallBack)(BaseComponent*, KeyHitEventInfo);


    // A specialized Function callback for when the textfield is typed into.
    // These are remains from MaslOS, where such functions were used along with subinstances.
    // NOTE: You can use this function, because it offers a small advantage over the normal callback:
    //       -> Mainly that you can decide if the key event should be ignored by the component 
    //       -> by return false to ignore and yes to let it get handled.
    void* AdvancedKeyHitCallBackHelp;
    // This is a pointer to an instance (can be set to NULL if you are using a static func)
    bool (*AdvancedKeyHitCallBack)(void* bruh, BaseComponent*, KeyHitEventInfo); // true if print
    // This is a pointer to a member function with 2 arguments. (You would set the `AdvancedKeyHitCallBackHelp` to the instance.
    // Or a normal function with 3 arguments. (where you can ignore the first arg)


    TextFieldComponent(uint32_t textCol, uint32_t bgCol, ComponentSize size, Position position, BaseComponent* parent);
};

Image Rectangle Component

The class is located in <libm/gui/guiStuff/components/imageRect/imageRectangleComponent.h>.

It looks like this:

class ImageRectangleComponent
{
    const char* imagePath = "";
    const char* oldPath = "";
    ImageStuff::BitmapImage* image = NULL;
    
    void RenderImg();
    void GetImageFromPath(const char* path);

    ImageRectangleComponent(const char* path, ComponentSize size, BaseComponent* parent);
};

Canvas Component

The class is located in <libm/gui/guiStuff/components/canvas/canvasComponent.h>.

It looks like this:

class CanvasComponent
{
    uint32_t bgColor;
    PSF1_FONT* font;

    CanvasComponent(uint32_t bgColor, ComponentSize size, BaseComponent* parent);


    void Clear();
    void Clear(bool update);
    void UpdateCanvas();
    void UpdateCanvas(int x, int y);
    void UpdateCanvas(int x, int y, int w, int h);
    void UpdateCanvas(Field field);
    

    void DrawPixel(int x, int y, uint32_t col, bool update);
    void DrawBlob(int x, int y, uint32_t col, int size);
    void DrawLine(int x1, int y1, int x2, int y2, uint32_t col, int size);
    void DrawSquare(int x, int y, int size, uint32_t col, bool fillInside);
    void DrawRect(int x, int y, int w, int h, uint32_t col, bool fillInside);
    void DrawSquare(int x, int y, int size, uint32_t col, bool fillInside, bool update);
    void DrawRect(int x, int y, int w, int h, uint32_t col, bool fillInside, bool update);
    void DrawChar(int sX, int sY, uint32_t fg,  int size, char c);
    void DrawChar(int sX, int sY, uint32_t fg, uint32_t bg, int size, char c);
    void DrawText(int sX, int sY, uint32_t fg, uint32_t bg, int size, const char* text);
    void DrawText(int sX, int sY, uint32_t col, int size, const char* text);
    void DrawTri(int x1, int y1, int x2, int y2, int x3, int y3, uint32_t col, int size);
};

Screen Component

The class is located in <libm/gui/guiStuff/components/screenComponent/screenComponent.h>.

It looks like this:

class ScreenComponent
{
    public:
    BaseComponent* selectedComponent = NULL;
    Window* window;
    List<BaseComponent*>* children;
    uint32_t backgroundColor = 0;
    BaseComponent* tempSelectedComponent = NULL;
    List<Field>* finalUpdatedFields;
    List<Field>* childrenFields;
    List<bool>* childrenHidden;
    GuiInstance* guiInstance;
};

Component Renderer

The component renderer is used internally by the components to render things.

Under normal circumstances you should not need it.

The class is located in <libm/gui/guiStuff/componentRenderer.h>.

It looks like this:

class ComponentRenderer
{
    ComponentFramebuffer* componentFrameBuffer;
    // The framebuffer that the renderer uses and the component displays.

    uint32_t bgCol = 0;
    // the background color.

    PSF1_FONT* font;
    // The psf1 it uses to render.


    ComponentRenderer(ComponentSize size);
    // Constructs a component renderer with a size and a framebuffer.

    void Free();
    // Frees the renderer, framebuffer, etc.
    // NOTE: You still need to free the instance itself!


    void Resize(ComponentSize size, bool paint);
    // Resizes the framebuffer.
    // If `paint` is true, it will actually paint the old buffer into the newly sized one.

    void Fill(uint32_t col);
    // Will fill the whole framebuffer with one color.

    void Fill(uint32_t col, Field field);
    // Will fill a specifief field of a component with one color.


    Position PrintString(char chr, Position pos, uint32_t fgCol, uint32_t bgCol, bool transparent);
    // Will print a char at a specified position.
    // It will have a foreground color and a background color 
    // Or only a foreground color and it will ignore the background color if `transparent` is true.
    // It will also return the position you would draw the next character at.

    Position PrintString(char chr, Position pos, uint32_t fgCol);
    // Will print a char at a specified position.
    // It will only have a foreground color.
    // It will also return the position you would draw the next character at.


    Position PrintString(const char *chrs, Position pos, uint32_t fgCol, uint32_t bgCol, bool transparent, bool center);
    // Will print a string with a foreground color and maybe a background color (see function above) at a specified position.
    // If center is set, it will try to center the text.
    // It will also return the position you would draw the next character at.

    Position PrintString(const char *chrs, Position pos, uint32_t fgCol);
    // Will print a string with a foreground color and maybe a background color (see function above) at a specified position.
    // It will also return the position you would draw the next character at.


    void Render(Position componentPosition, Field field, ComponentFramebuffer* to);
    // Will render a field of this component framebuffer into another one starting at some position.
};

MAAB Bindings

MAAB also has access to the GUI Framework, same as in MaslOS.

You can find the documentation for that stuff in the Wiki for MaslOS.

Clone this wiki locally