Skip to content

Commit

Permalink
Initial Hello World Tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonyirwin82 committed Dec 10, 2024
1 parent ead37a8 commit 0c0f020
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 1 deletion.
3 changes: 2 additions & 1 deletion docs/docfx.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json",
"metadata": [
{
"src": [
Expand All @@ -20,7 +21,7 @@
],
"resource": [
{
"files": ["img/**"]
"files": ["img/**", "docs/tutorial/gtk/img/**"]
}
],
"output": "../_site",
Expand Down
83 changes: 83 additions & 0 deletions docs/docs/tutorial/gtk/hello_world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Hello World Gtk Tutorial

In this hello world tutorial you will learn how to build a basic C# Gtk Application with a single Gtk Button widget inside it.

We will begin by creating a `GtkTutorials` directory to contain the Gtk tutorials you do and create the HelloWorld project using the command line.

```
mkdir GtkTutorials
cd GtkTutorials
dotnet new console -f net8.0 -o HelloWorld
dotnet new gitignore
dotnet new sln
dotnet sln add HelloWorld/
```

The above commands will create a new console project, a gitignore file and a solution file for the project with the HelloWorld project added to the solution file so that people using ide's can open the project easily. As you follow more Gtk tutorials you can create the projects in the `GtkTutorials` directory by using `dotnet new console -f net8.0 -o NewProject` and add the projects to the solution file by using `dotnet sln add NewProject` to have multiple projects in the same solution file.

Next we will download the GirCore.Gtk-4.0 nuget package into the project.

> [!TIP]
> You can check for newer versions by visiting the nuget website at [https://www.nuget.org/packages/GirCore.Gtk-4.0/#versions-body-tab](https://www.nuget.org/packages/GirCore.Gtk-4.0/#versions-body-tab).
```
cd HelloWorld
dotnet add package GirCore.Gtk-4.0 --version 0.5.0
```

The above commands will change to the HelloWorld directory then add the `GirCore.Gtk-4.0` package to the `HelloWorld.csproj` file.

We will now create a new class file to use to make the HelloWorld window in Gtk. This will later be loaded from the `Program.cs` file.

```
dotnet new class -n HelloWorld
```

Next open the `HelloWorld` directory in your favourite code editor or ide so we can edit the `HelloWorld.cs` and `Program.cs` files.

> [!NOTE]
> The code is commented to tell you what is happening. In addition to these comments the highlighted lines will be discussed further after the code block to give you more information.
**Filename: HelloWorld.cs**
[!code-csharp[](src/HelloWorld/HelloWorld.cs?highlight=37)]

**Line 37:**

On line 37 you set the `Child` of the `HelloWorld Gtk.Window` to be the `HelloWorld Gtk.Button`.

It may be easier to understand visually by looking at the diagram below.

```mermaid
graph TB
parent[HelloWorld Gtk.Window]
subgraph parent [HelloWorld Gtk.Window]
n1[helloButton Gtk.Button]
end
```

As you can see the window is entirely made up of the `helloButton Gtk.Button` widget. In a real application you will use a `Layout Widget` like the `Gtk.Box` widget to have multiple widgets inside the window.

**Filename: Program.cs**
[!code-csharp[](src/HelloWorld/Program.cs)]

**Run the HelloWorld Application:**

Now we have completed the code for the hello world tutorial we can run the project.

```
dotnet run
```

If you have entered the code correctly and have the Gtk 4 runtime libraries installed correctly on your computer then you will see the Hello World application window appear on the screen.

> [!TIP]
> Try resizing the window to see that the `helloButton Gtk.Button` widget takes up the entire window with a 10 pixel margin around it.
# [Linux](#tab/linux)
![Linux hello world screenshot](img/HelloWorld/Linux.png)

# [Windows](#tab/windows)
![Windows hello world screenshot](img/HelloWorld/Windows.png)

# [MacOS](#tab/mac)
![MacOS hello world screenshot](img/HelloWorld/MacOS.png)
Binary file added docs/docs/tutorial/gtk/img/HelloWorld/Linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/tutorial/gtk/img/HelloWorld/MacOS.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions docs/docs/tutorial/gtk/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Gtk Tutorial

When learning GUI frameworks like GTK, QT and wxWidgets it is common to teach the basics using code to make the learning experience easier. In a real life GTK application you will probably want to create a ui file using either [GTK Builder XML](https://docs.gtk.org/gtk4/class.Builder.html) or [Blueprint](https://jwestman.pages.gitlab.gnome.org/blueprint-compiler/) to build the UI.

On the internet you will often see Glade mentioned for building GUIs in a user friendly wysiwyg editor. Glade does not work with Gtk 4 however there is a new project [Cambalache](https://gitlab.gnome.org/jpu/cambalache) which will build GUIs in a similar way to the old Glade project that was used in GTK 2/3.

If you want to use Blueprint to build your UI then you can use [Workbench](https://apps.gnome.org/en-GB/Workbench/) to see a preview as you write the blueprint.

## Tutorials
- [Hello World](hello_world.md)
48 changes: 48 additions & 0 deletions docs/docs/tutorial/gtk/src/HelloWorld/HelloWorld.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
namespace HelloWorld
{
// Define a class named HelloWorld that extends Gtk.Window.
// Gtk.Window represents a top-level window in a GTK application.
public class HelloWorld : Gtk.Window
{
// Constructor for the HelloWorld class.
// This method sets up the window and its contents.
public HelloWorld()
{
// Set the title of the window.
Title = "Hello World App";

// Set the default size of the window to 300 pixels wide and 30 pixels tall.
// This is the initial size when the window is first displayed.
SetDefaultSize(300, 30);

// Create a new button widget.
// Gtk.Button is a clickable UI element.
var helloButton = Gtk.Button.New();

// Set the text label displayed on the button.
helloButton.Label = "Say Hello";

// Add margins around the button to create spacing from the edges of the window.
// Margins are specified in pixels.
helloButton.SetMarginStart(10); // Left margin
helloButton.SetMarginEnd(10); // Right margin
helloButton.SetMarginTop(10); // Top margin
helloButton.SetMarginBottom(10); // Bottom margin

// Add the button to the window.
// The `Child` property represents the main widget contained in the window.
// Here, we set the button as the only child of the window.
// In a real application you would set the child to be one of the Gtk Layout widgets
// so you can have multiple widgets in the window.
Child = helloButton;

// Attach an event handler to the button's "OnClicked" event.
// This event is triggered when the user clicks the button.
helloButton.OnClicked += (_, _) =>
{
// Print "Hello World!" to the console when the button is clicked.
Console.WriteLine("Hello World!\n");
};
}
}
}
14 changes: 14 additions & 0 deletions docs/docs/tutorial/gtk/src/HelloWorld/HelloWorld.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="gircore.gtk-4.0" Version="0.5.0" />
</ItemGroup>

</Project>
29 changes: 29 additions & 0 deletions docs/docs/tutorial/gtk/src/HelloWorld/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Create a new GTK application instance.
// "com.example.helloworld" is the unique application ID used to identify the app.
// The application ID should be a domain name you control.
// If you don't own a domain name you can use a project specific domain such as github pages.
// e.g. io.github.projectname
// Gio.ApplicationFlags.FlagsNone indicates no special flags are being used.
var application = Gtk.Application.New("com.example.helloworld", Gio.ApplicationFlags.FlagsNone);

// Attach an event handler to the application's "OnActivate" event.
// This event is triggered when the application is started or activated.
application.OnActivate += (sender, args) =>
{
// Create a new instance of the main application window.
var window = new HelloWorld.HelloWorld();

// Set the "Application" property of the window to the current application instance.
// This links the window to the application, allowing them to work together.
window.Application = (Gtk.Application) sender;

// Show the window on the screen.
// This makes the window visible to the user.
window.Show();
};

// Start the application's event loop and process user interactions.
// RunWithSynchronizationContext ensures proper thread synchronization for GTK.
// The "null" parameter takes the arguments from the commandline. As there are no arguments
// supported in this tutorial the parameter is not filled and thus null.
return application.RunWithSynchronizationContext(null);
2 changes: 2 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ items:
items:
- name: Use
href: docs/use.md
- name: Gtk Tutorial
href: docs/tutorial/gtk/index.md
- name: Apps
href: docs/apps.md
- name: Libraries
Expand Down
43 changes: 43 additions & 0 deletions src/GirCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,29 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "api", "api", "{23ED17AC-703
..\docs\api\index.md = ..\docs\api\index.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tutorial", "tutorial", "{5098D869-1B0D-4B56-B09E-0B51991F97B3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gtk", "gtk", "{1B7181FA-9317-4919-A013-A2C48950F1A6}"
ProjectSection(SolutionItems) = preProject
..\docs\docs\tutorial\gtk\hello_world.md = ..\docs\docs\tutorial\gtk\hello_world.md
..\docs\docs\tutorial\gtk\index.md = ..\docs\docs\tutorial\gtk\index.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "img", "img", "{10020C8D-E65C-4AC5-A625-AF99C9FB9822}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HelloWorld", "HelloWorld", "{979E4BB1-4549-4FF8-9CD8-9BC89771A68E}"
ProjectSection(SolutionItems) = preProject
..\docs\docs\tutorial\gtk\img\HelloWorld\Windows.png = ..\docs\docs\tutorial\gtk\img\HelloWorld\Windows.png
..\docs\docs\tutorial\gtk\img\HelloWorld\Linux.png = ..\docs\docs\tutorial\gtk\img\HelloWorld\Linux.png
..\docs\docs\tutorial\gtk\img\HelloWorld\MacOS.png = ..\docs\docs\tutorial\gtk\img\HelloWorld\MacOS.png
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{47FFBA4C-08BD-4A7A-B595-C31F376CFD70}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HelloWorld", "HelloWorld", "{B51AA1C6-C974-49A5-89D3-9929106E8BF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "..\docs\docs\tutorial\gtk\src\HelloWorld\HelloWorld.csproj", "{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -865,6 +888,18 @@ Global
{EE13D29A-42BC-4694-9980-D0498AA15115}.Release|x64.Build.0 = Release|Any CPU
{EE13D29A-42BC-4694-9980-D0498AA15115}.Release|x86.ActiveCfg = Release|Any CPU
{EE13D29A-42BC-4694-9980-D0498AA15115}.Release|x86.Build.0 = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|x64.ActiveCfg = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|x64.Build.0 = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|x86.ActiveCfg = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Debug|x86.Build.0 = Debug|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|Any CPU.Build.0 = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|x64.ActiveCfg = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|x64.Build.0 = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|x86.ActiveCfg = Release|Any CPU
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BF7F9B0B-CB43-4161-BFAD-C6EE479FC86B} = {386AE10F-B7AC-4C97-AC5C-202D3662A868}
Expand Down Expand Up @@ -939,5 +974,13 @@ Global
{3F6B722F-5192-46BC-A389-5E40ABA9041B} = {7B70E5ED-C5E7-4F32-A458-E5A10F39DA00}
{EE13D29A-42BC-4694-9980-D0498AA15115} = {7B70E5ED-C5E7-4F32-A458-E5A10F39DA00}
{23ED17AC-703E-40D6-8B4C-0DAE232E1E33} = {0D9C5C7E-F81B-4E0E-B203-22D558E6D7F1}
{5098D869-1B0D-4B56-B09E-0B51991F97B3} = {4EE9860B-6684-4369-A7F3-E0975E34F249}
{1B7181FA-9317-4919-A013-A2C48950F1A6} = {5098D869-1B0D-4B56-B09E-0B51991F97B3}
{10020C8D-E65C-4AC5-A625-AF99C9FB9822} = {1B7181FA-9317-4919-A013-A2C48950F1A6}
{47FFBA4C-08BD-4A7A-B595-C31F376CFD70} = {1B7181FA-9317-4919-A013-A2C48950F1A6}
{B51AA1C6-C974-49A5-89D3-9929106E8BF6} = {47FFBA4C-08BD-4A7A-B595-C31F376CFD70}
{30BC3641-AA77-4A17-91CF-6F3ECABB54EC} = {B51AA1C6-C974-49A5-89D3-9929106E8BF6}
{838AF1E5-D6B1-4F4F-BD58-AD9011D82486} = {10020C8D-E65C-4AC5-A625-AF99C9FB9822}
{979E4BB1-4549-4FF8-9CD8-9BC89771A68E} = {10020C8D-E65C-4AC5-A625-AF99C9FB9822}
EndGlobalSection
EndGlobal

0 comments on commit 0c0f020

Please sign in to comment.