-
Notifications
You must be signed in to change notification settings - Fork 8
MaslOS2 GUI‐Framework
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.
For GUI Framework dev important classes are:
- The Window class
- The GuiInstance class
- The Component classes
Please also take a closer look at important functions related to windows if you have not.
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 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.
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.
You can create a component in two ways:
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);
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");
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:
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);
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);
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:
This is useful if your application has barely any changes and uses events to do things.
while (!CheckForWindowClosed(window))
{
gui->Render(true);
programWaitMsg();
}
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();
}
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!
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!
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.
The Screen Component has two special variables:
selectedComponent
tempSelectedComponent
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)
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.
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.
};
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;
}
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();
};
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
};
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.
};
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 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);
};
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);
};
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,
};
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);
};
The advanced text component is an evolution from the simple text component. It provides a lot more features and is less update intensive.
It also provides a console-like interface to write text.
Essentially you write the text into the component using the print functions.
The component also supports scrolling!
NOTE: If you want to scroll the text, you will need to alter the variables manually!
NOTE: This component does not support printf style prints yet. (I will work on that soon-ish)
The class is located in <libm/gui/guiStuff/components/advancedText/advancedTextComponent.h>
.
It looks like this:
class AdvancedTextComponent
{
int32_t scrollX, scrollY;
// Scroll Position.
uint32_t foregroundColor;
// Foreground Color.
uint32_t backgroundColor;
// Background Color.
List<List<ConsoleChar>*> textData;
// The actual text data used internally.
void Reload();
// Will fully refresh the component. Will cause one big update.
void DoRender();
// Will check for text updates updates and render them
void Clear();
// Will clear all the text and update.
void Print(char chr);
// Will print a character.
void Print(const char* msg);
// Will print a message.
void Print(const char* msg, uint32_t col);
// Will print a message in a color.
void Print(const char* msg, const char* var);
// Will print a message and replace {} with another string.
// An example: Print("Hello, {}!", "Person") -> "Hello, Person!"
void Print(const char* msg, const char* var, uint32_t col);
// Will print a message in color and replace {} with another string.
// An example: Print("Hello, {}!", "Person") -> "Hello, Person!"
void Println();
// Will print a new line.
void Println(const char* msg);
// Will print a message and a new line.
void Println(const char* msg, uint32_t col);
// Will print a message in a color and a new line.
void Println(const char* msg, const char* var);
// Will print a message and replace {} with another string and then print a new line.
// An example: Print("Hello, {}!", "Person") -> "Hello, Person!"
void Println(const char* msg, const char* var, uint32_t col);
// Will print a message in a color and replace {} with another string and then print a new line.
// An example: Print("Hello, {}!", "Person") -> "Hello, Person!"
void DeleteLastCharInLine();
// This will delete the last char in the line if possible.
// NOTE: This can also be achieved by printing '\b'.
AdvancedTextComponent(uint32_t foregroundColor, uint32_t backgroundColor, ComponentSize size, BaseComponent* parent);
// This will construct a new instance with a given default foreground and background color, size and parent.
};
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);
};
The Image rectangle is like a rectangle that holds an image.
NOTE: The image will be stretched to fit into the rectangle.
You can get the actual image size by looking into the image
variable.
The class is located in <libm/gui/guiStuff/components/imageRect/imageRectangleComponent.h>
.
It looks like this:
class ImageRectangleComponent
{
const char* imagePath;
// This holds the absolute path to the image file.
// NOTE: This currently only supports MBIF images!
ImageStuff::BitmapImage* image;
// This is the BitmapImage instance used internally by the component.
// Note: You should not edit this, but you CAN use it to get the size.
// -> The instance can be NULL!
void RenderImg();
// Will Render the image to the component framebuffer.
void GetImageFromPath(const char* path);
// This will attempt to load image from a given path.
ImageRectangleComponent(const char* path, ComponentSize size, BaseComponent* parent);
// This constructs an image component with a path, size and parent.
// NOTE: The path will be copied and you need to provide a const string or free your dynamic string after use!
};
The canvas component provides a way to draw simple lines, points, shapes and text without you having to hijack any components and while having a reasonable performance.
NOTE: The canvas does not fully update after changes and only tries to update important parts. It does provide functions, where you can set the update
variable manually. If you choose to set it to false, you will have to update it manually.
The class is located in <libm/gui/guiStuff/components/canvas/canvasComponent.h>
.
It looks like this:
class CanvasComponent
{
uint32_t bgColor;
// The background color
PSF1_FONT* font;
// The psf1 font it uses internally for rendering text.
CanvasComponent(uint32_t bgColor, ComponentSize size, BaseComponent* parent);
// This will construct a canvas component with a given size and background color.
void Clear();
// This will clear and update the entire screen
void Clear(bool update);
// This will clear and maybe update the entire screen.
void DrawPixel(int x, int y, uint32_t col, bool update);
// This will draw a singular pixel with a color at a specific location and maybe update the pixel.
void DrawBlob(int x, int y, uint32_t col, int size);
// This will draw a square blob at a specified position with a given color and size.
// NOTE: The size starts at 0! 0 -> 1x1, 1 -> 3x3, 2 -> 5x5, ...
void DrawLine(int x1, int y1, int x2, int y2, uint32_t col, int size);
// This will draw a line from one point to another with a color and size.
// NOTE: The size starts at 0! 0 -> 1x1, 1 -> 3x3, 2 -> 5x5, ...
void DrawSquare(int x, int y, int size, uint32_t col, bool fillInside);
// Will draw a square with a given size, color and which is either filled or has a 1 px border.
void DrawSquare(int x, int y, int size, uint32_t col, bool fillInside, bool update);
// Will draw a square with a given size, color and which is either filled or has a 1 px border and might update the screen.
void DrawRect(int x, int y, int w, int h, uint32_t col, bool fillInside);
// Will draw a rectangle with a given size, color and which is either filled or has a 1 px border.
void DrawRect(int x, int y, int w, int h, uint32_t col, bool fillInside, bool update);
// Will draw a rectangle with a given size, color and which is either filled or has a 1 px border and might update the screen.
void DrawChar(int sX, int sY, uint32_t fg, int size, char c);
// This will draw a character at a specified position (sX, sY), a foreground color, no background color and with a size.
// NOTE: The size is an integer scale multiplier. 1 -> 100% of the original size, 2 -> 200%, 3 -> 300%, ...
void DrawChar(int sX, int sY, uint32_t fg, uint32_t bg, int size, char c);
// This will draw a character at a specified position (sX, sY), a foreground color, a background color and with a size.
// NOTE: The size is an integer scale multiplier. 1 -> 100% of the original size, 2 -> 200%, 3 -> 300%, ...
void DrawText(int sX, int sY, uint32_t fg, uint32_t bg, int size, const char* text);
// This will draw text at a specified position (sX, sY), a foreground color, no background color and with a size.
// NOTE: The size is an integer scale multiplier. 1 -> 100% of the original size, 2 -> 200%, 3 -> 300%, ...
void DrawText(int sX, int sY, uint32_t col, int size, const char* text);
// This will draw text at a specified position (sX, sY), a foreground color, a background color and with a size.
// NOTE: The size is an integer scale multiplier. 1 -> 100% of the original size, 2 -> 200%, 3 -> 300%, ...
void DrawTri(int x1, int y1, int x2, int y2, int x3, int y3, uint32_t col, int size);
// This will draw a triangle between three points with a color and a size.
// NOTE: The size is for each point on the line and starts at 0! 0 -> 1x1, 1 -> 3x3, 2 -> 5x5, ...
void UpdateCanvas();
// Will update the entire canvas.
void UpdateCanvas(int x, int y);
// Will update a pixel at a specified location.
void UpdateCanvas(int x, int y, int w, int h);
// Will update a rectangle at a specified location.
void UpdateCanvas(Field field);
// Will update a rectangle, defined by a field, at a specified location.
};
The screen component is like the scene, which holds all currently relevant components.
It stands between the gui instance and all other components.
The class is located in <libm/gui/guiStuff/components/screenComponent/screenComponent.h>
.
It looks like this:
class ScreenComponent
{
Window* window;
// Window instance.
GuiInstance* guiInstance;
// Gui Instance.
List<BaseComponent*>* children;
// All children of the screen component
uint32_t backgroundColor = 0;
// The background color.
// Selected and TempSelected components
// For more info take a look at https://github.com/marceldobehere/MaslOS-2/wiki/MaslOS2-GUI‐Framework#selectedcomponent-and-tempselected-component
BaseComponent* tempSelectedComponent;
BaseComponent* selectedComponent;
};
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 also has access to the GUI Framework, same as in MaslOS.
You can find the documentation for that stuff in the Wiki for MaslOS.