GUI programming

General discussion about Visopsys.
Post Reply
DropKickXxs
Posts: 2
Joined: Fri Sep 20, 2013 8:43 pm

GUI programming

Post by DropKickXxs »

Hi some help with making a GUI driver in ASM(if can C++/C is fine).

And i pmode and it must use the entire screen.
User avatar
andymc
Posts: 589
Joined: Tue Nov 16, 2010 7:20 pm

Re: GUI programming

Post by andymc »

Hi DropKickXxs, welcome 8-)

Thanks for posting your question. I've been thinking for a while that I should post a tutorial about how to program the Visopsys GUI.

This seems like as good a time as any, so I'll try to answer your specific needs, but also provide general guidance, later in the thread.

So far, all of the GUI programs (and just about everything else) are written in C. The operating system doesn't really have runtime C++ support yet - it's not so difficult to add - I just haven't needed to do it yet.

So, C would be the easiest choice. You could code in assembler if you want; I've never tried making an application program that way, but there's no reason it couldn't be done. You'd just have to code a couple of simple support routines that would help you to interface with the rest of the system. I can write another post to tell you about that.

The operating system runs in protected mode all the time.

The GUI's "root window" is an example of a full-screen window. Would you want to do something like that - using the GUI's controls (buttons, menus, etc., etc.) - or would you want to do raw screen-drawing, like programming a game?
DropKickXxs
Posts: 2
Joined: Fri Sep 20, 2013 8:43 pm

Re: GUI programming

Post by DropKickXxs »

Both Please.
User avatar
andymc
Posts: 589
Joined: Tue Nov 16, 2010 7:20 pm

Re: GUI programming

Post by andymc »

I'll start with some general background.

A lot of the GUI basics of Visopsys are built right into the kernel (it is intended to be a "visual" operating system, after all). So, much of what you'll need comes directly from kernel API calls. These calls are for creating and laying out windows, creating the basic GUI components, and interacting with the windowing system. Here's a link to the documentation for these functions:

http://visopsys.org/developers/kernel_API.php#window

To use the API functions in C, you need

Code: Select all

#include <sys/api.h>
There is some additional functionality that comes from a window library. The library has code for things like dialog boxes, composite window components, and runtime event dispatching. Here's the documentation for the library functions:

http://visopsys.org/developers/window_library.php

To use the window library in C, you need

Code: Select all

#include <sys/window.h>
and you'll need to link the library into your executable with -lwindow, i.e.

Code: Select all

gcc myprog.c -lwindow -o myprog
Here's a simple example. To get started, you'll probably want to create a main window, and make it visible. We'll need 2 function calls
objectKey windowNew(int processId, const char *title)
Create a new window, owned by the process 'processId', and with the title 'title'. Returns an object key to reference the window, needed by most other window functions below (such as adding components to the window)

int windowSetVisible(objectKey window, int visible)
Tell the windowing system whether to make 'window' visible or not. Non-zero 'visible' means make the window visible. When windows are created, they are not visible by default so you can add components, do layout, set the size, etc.
Here's the code

Code: Select all

#include <sys/api.h>

objectKey window;

void main(void)
{
	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	windowSetVisible(window, 1);

	while (1);
}
And here's what we get:
emptywindow.png
emptywindow.png (8.56 KiB) Viewed 30171 times
Cute, but not too useful yet. :lol: We'll have to start putting some components in there.

There are several different types of basic components:
  • button
  • canvas
  • checkbox
  • divider
  • icon
  • image
  • list (and list item)
  • menu (and menu item)
  • menu bar
  • password field
  • progress bar
  • radio button
  • scrollbar
  • slider
  • text area
  • text field
  • text label
We'll start with a label and a button. Here are the functions for creating them:
objectKey windowNewTextLabel(objectKey parent, const char *text, componentParameters *params)
Get a new text labelComponent to be placed inside the parent object 'parent', with the given component parameters 'params', and using the text string 'text'. If the params 'font' is NULL, the default font will be used.

objectKey windowNewButton(objectKey parent, const char *label, image *buttonImage, componentParameters *params)
Get a new button component to be placed inside the parent object 'parent', with the given component parameters, and with the (optional) label 'label', or the (optional) image 'buttonImage'. Either 'label' or 'buttonImage' can be used, but not both.
When we create a component, we need to supply some component parameters (defined in <sys/window.h>)

Code: Select all

// This structure is needed to describe parameters consistent to all
// window components
typedef struct {
	int gridX;							// Grid X coordinate
	int gridY;							// Grid Y coordinate
	int gridWidth;						// Grid span width
	int gridHeight;						// Grid span height
	int padLeft;						//
	int padRight;						// Pixels of empty space (padding)
	int padTop;						// around each side of the component
	int padBottom;						//
	int flags;							// Attributes - See WINDOW_COMPFLAG_*
	componentXOrientation orientationX;		// orient_left, orient_center, orient_right
	componentYOrientation orientationY;		// orient_top, orient_middle, orient_bottom
	color foreground;					// Foreground drawing color
	color background;					// Background frawing color
	objectKey font;						// Font for text

} componentParameters;
Windows are laid out somewhat like tables in HTML. Each component occupies one grid cell. The gridX and gridY values specify which cell. If the cell should span the width or height of adjacent cells, then gridWidth and gridHeight are used for that. Here's the code now when we add our components:

Code: Select all

#include <sys/api.h>
#include <sys/window.h>
#include <string.h>

objectKey window;
objectKey okButton;

void main(void)
{
	componentParameters params;

	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	// Set up the parameters for our label
	memset(&params, 0, sizeof(componentParameters));
	params.gridX = 0;
	params.gridY = 0;
	params.gridWidth = 1;
	params.gridHeight = 1;

	// Create the label
	windowNewTextLabel(window, "Welcome to my program", &params);

	// Reuse the parameters from the label, but change the grid coordinate
	params.gridY = 1;

	// Create the button, and save a global reference to it
	okButton = windowNewButton(window, "OK", NULL, &params);

	windowSetVisible(window, 1);

	while (1);
}
It doesn't look great, but at least our window now has something in it:
label+button.png
label+button.png (9.52 KiB) Viewed 30171 times
The following function can help us to see how the grid layout is being interpreted:
void windowDebugLayout(objectKey window)
This function draws grid boxes around all the grid cells containing components (or parts thereof).
Lets add some more to our component parameters to fix the layout:

Code: Select all

#include <sys/api.h>
#include <sys/window.h>
#include <string.h>

objectKey window;
objectKey okButton;

void main(void)
{
	componentParameters params;

	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	// Set up the parameters for our label
	memset(&params, 0, sizeof(componentParameters));
	params.gridX = 0;
	params.gridY = 0;
	params.gridWidth = 1;
	params.gridHeight = 1;
	params.padTop = 5;		// Add some padding
	params.padLeft = 5;		// around the top,
	params.padRight = 5;	// left, and bottom
	params.orientationX = orient_center;	// Center of the cell
	params.orientationY = orient_middle;	// middle of the cell

	// Create the label
	windowNewTextLabel(window, "Welcome to my program", &params);

	// Reuse the parameters from the label, but change the grid coordinate,
	// add some padding on the bottom, and prevent the button from expanding
	// to fill its cell
	params.gridY = 1;
	params.padBottom = 5;
	params.flags = (WINDOW_COMPFLAG_FIXEDHEIGHT | WINDOW_COMPFLAG_FIXEDWIDTH);

	// Create the button, and save a global reference to it
	okButton = windowNewButton(window, "OK", NULL, &params);

	//windowDebugLayout(window);
	windowSetVisible(window, 1);

	while (1);
}
Here's how it looks now (with and without grid debugging):
debug-layout.png
debug-layout.png (9.43 KiB) Viewed 30171 times
improved-layout.png
improved-layout.png (9.24 KiB) Viewed 30171 times
So there we have some basic window creation. In the next installment, I'll talk about how the runtime event handling works (so that we can make that button do something useful).
oscar
Posts: 22
Joined: Thu Aug 15, 2013 4:23 pm

Re: GUI programming

Post by oscar »

Hi Andy,

I think your last post here about how to program the Visopsys GUI is just great! :D

It would be nice to know more about this topic. Thank you! :dance:

Oscar
fosforito

Re: GUI programming

Post by fosforito »

Hi! How can I use text files to store data and select data from it for display? I need something like a database.

Example text file:
Name1*Value1*Value2
Name2*Value1*Value2
Name3*Value1*Value2
Name4*Value1*Value2
Now I want to add a new Name5 with values, delete Name1 with its values, edit Value1 of Name3 and display the values of Name2.

I hope you understand me...
User avatar
andymc
Posts: 589
Joined: Tue Nov 16, 2010 7:20 pm

Re: GUI programming

Post by andymc »

Sorry for the slow reply, I had to take an un-planned trip!

The kernel has several functions for reading and writing configuration files:

Code: Select all

int kernelConfigRead(const char *, variableList *);
int kernelConfigWrite(const char *, variableList *);
int kernelConfigGet(const char *, const char *, char *, unsigned);
int kernelConfigSet(const char *, const char *, const char *);
int kernelConfigUnset(const char *, const char *);
These are exported to user programs in src/include/sys/api.h:

Code: Select all

int configRead(const char *, variableList *);
int configWrite(const char *, variableList *);
int configGet(const char *, const char *, char *, unsigned);
int configSet(const char *, const char *, const char *);
int configUnset(const char *, const char *);
The functions are documented here: http://visopsys.org/developers/kernel_A ... cellaneous. 'variableList' is defined in src/include/sys/variable.h

The current format expects name=value pairs in the file, but this is fairly extensible when used with the concept of name-spaces. For example, in the file dist/system/config/desktop.conf:

Code: Select all

icon.name.computer=Computer
icon.computer.image=/system/icons/compicon.ico
icon.computer.command=/programs/computer
I define an icon.name.<whatever>=..., and then define properties for that thing with lines that say icon.<whatever>.<propertyname>=...

It's somewhat primitive, but also kind of elegant and simple IMHO :ugeek: :lol:
User avatar
ap0r
Posts: 105
Joined: Tue Feb 14, 2012 12:40 am

Re: GUI programming

Post by ap0r »

andymc wrote:I'll start with some general background.

A lot of the GUI basics of Visopsys are built right into the kernel (it is intended to be a "visual" operating system, after all). So, much of what you'll need comes directly from kernel API calls. These calls are for creating and laying out windows, creating the basic GUI components, and interacting with the windowing system. Here's a link to the documentation for these functions:

http://visopsys.org/developers/kernel_API.php#window

To use the API functions in C, you need

Code: Select all

#include <sys/api.h>
There is some additional functionality that comes from a window library. The library has code for things like dialog boxes, composite window components, and runtime event dispatching. Here's the documentation for the library functions:

http://visopsys.org/developers/window_library.php

To use the window library in C, you need

Code: Select all

#include <sys/window.h>
and you'll need to link the library into your executable with -lwindow, i.e.

Code: Select all

gcc myprog.c -lwindow -o myprog
Here's a simple example. To get started, you'll probably want to create a main window, and make it visible. We'll need 2 function calls
objectKey windowNew(int processId, const char *title)
Create a new window, owned by the process 'processId', and with the title 'title'. Returns an object key to reference the window, needed by most other window functions below (such as adding components to the window)

int windowSetVisible(objectKey window, int visible)
Tell the windowing system whether to make 'window' visible or not. Non-zero 'visible' means make the window visible. When windows are created, they are not visible by default so you can add components, do layout, set the size, etc.
Here's the code

Code: Select all

#include <sys/api.h>

objectKey window;

void main(void)
{
	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	windowSetVisible(window, 1);

	while (1);
}
And here's what we get:
emptywindow.png
Cute, but not too useful yet. :lol: We'll have to start putting some components in there.

There are several different types of basic components:
  • button
  • canvas
  • checkbox
  • divider
  • icon
  • image
  • list (and list item)
  • menu (and menu item)
  • menu bar
  • password field
  • progress bar
  • radio button
  • scrollbar
  • slider
  • text area
  • text field
  • text label
We'll start with a label and a button. Here are the functions for creating them:
objectKey windowNewTextLabel(objectKey parent, const char *text, componentParameters *params)
Get a new text labelComponent to be placed inside the parent object 'parent', with the given component parameters 'params', and using the text string 'text'. If the params 'font' is NULL, the default font will be used.

objectKey windowNewButton(objectKey parent, const char *label, image *buttonImage, componentParameters *params)
Get a new button component to be placed inside the parent object 'parent', with the given component parameters, and with the (optional) label 'label', or the (optional) image 'buttonImage'. Either 'label' or 'buttonImage' can be used, but not both.
When we create a component, we need to supply some component parameters (defined in <sys/window.h>)

Code: Select all

// This structure is needed to describe parameters consistent to all
// window components
typedef struct {
	int gridX;							// Grid X coordinate
	int gridY;							// Grid Y coordinate
	int gridWidth;						// Grid span width
	int gridHeight;						// Grid span height
	int padLeft;						//
	int padRight;						// Pixels of empty space (padding)
	int padTop;						// around each side of the component
	int padBottom;						//
	int flags;							// Attributes - See WINDOW_COMPFLAG_*
	componentXOrientation orientationX;		// orient_left, orient_center, orient_right
	componentYOrientation orientationY;		// orient_top, orient_middle, orient_bottom
	color foreground;					// Foreground drawing color
	color background;					// Background frawing color
	objectKey font;						// Font for text

} componentParameters;
Windows are laid out somewhat like tables in HTML. Each component occupies one grid cell. The gridX and gridY values specify which cell. If the cell should span the width or height of adjacent cells, then gridWidth and gridHeight are used for that. Here's the code now when we add our components:

Code: Select all

#include <sys/api.h>
#include <sys/window.h>
#include <string.h>

objectKey window;
objectKey okButton;

void main(void)
{
	componentParameters params;

	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	// Set up the parameters for our label
	memset(&params, 0, sizeof(componentParameters));
	params.gridX = 0;
	params.gridY = 0;
	params.gridWidth = 1;
	params.gridHeight = 1;

	// Create the label
	windowNewTextLabel(window, "Welcome to my program", &params);

	// Reuse the parameters from the label, but change the grid coordinate
	params.gridY = 1;

	// Create the button, and save a global reference to it
	okButton = windowNewButton(window, "OK", NULL, &params);

	windowSetVisible(window, 1);

	while (1);
}
It doesn't look great, but at least our window now has something in it:
label+button.png
The following function can help us to see how the grid layout is being interpreted:
void windowDebugLayout(objectKey window)
This function draws grid boxes around all the grid cells containing components (or parts thereof).
Lets add some more to our component parameters to fix the layout:

Code: Select all

#include <sys/api.h>
#include <sys/window.h>
#include <string.h>

objectKey window;
objectKey okButton;

void main(void)
{
	componentParameters params;

	// Create a new window, and save a global reference to it
	window = windowNew(multitaskerGetCurrentProcessId(), "MyProg");
	if (window == NULL)
		return;

	// Set up the parameters for our label
	memset(&params, 0, sizeof(componentParameters));
	params.gridX = 0;
	params.gridY = 0;
	params.gridWidth = 1;
	params.gridHeight = 1;
	params.padTop = 5;		// Add some padding
	params.padLeft = 5;		// around the top,
	params.padRight = 5;	// left, and bottom
	params.orientationX = orient_center;	// Center of the cell
	params.orientationY = orient_middle;	// middle of the cell

	// Create the label
	windowNewTextLabel(window, "Welcome to my program", &params);

	// Reuse the parameters from the label, but change the grid coordinate,
	// add some padding on the bottom, and prevent the button from expanding
	// to fill its cell
	params.gridY = 1;
	params.padBottom = 5;
	params.flags = (WINDOW_COMPFLAG_FIXEDHEIGHT | WINDOW_COMPFLAG_FIXEDWIDTH);

	// Create the button, and save a global reference to it
	okButton = windowNewButton(window, "OK", NULL, &params);

	//windowDebugLayout(window);
	windowSetVisible(window, 1);

	while (1);
}
Here's how it looks now (with and without grid debugging):
debug-layout.png
improved-layout.png
So there we have some basic window creation. In the next installment, I'll talk about how the runtime event handling works (so that we can make that button do something useful).
This was nice to read... :) Still waiting for the next installment, whenever you have the time :pray:
Image
Image
User avatar
andymc
Posts: 589
Joined: Tue Nov 16, 2010 7:20 pm

Re: GUI programming

Post by andymc »

Heheh, yes, I will. But ... the time :-)
fosforito

Re: GUI programming

Post by fosforito »

So there we have some basic window creation. In the next installment, I'll talk about how the runtime event handling works (so that we can make that button do something useful).
Hello Andy, when you have time, can you please explain how to do that? It would be very useful. ;)
Post Reply