Skip to content

Commit

Permalink
Work on tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Dec 19, 2024
1 parent 5ca9067 commit 0ec5c73
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 23 deletions.
3 changes: 3 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ doc_him_pdf:
tutorial_book:
cd tutorial && jupyter-book build .

tutorial_book_pdf:
cd tutorial && jupyter-book build --builder pdfhtml .

# Create a new tutorial page from the template (pass a name relative to tutorial/)
tutorial_new name:
python tutorial/_tpl/instantiate_tutorial_template.py {{name}}
6 changes: 3 additions & 3 deletions tutorial/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ format: jb-book
root: discover_immediate

chapters:
- file: discover/intro
- file: discover/hello_world
sections:
- file: discover/hello_world
- file: discover/button
- file: discover/widget_edit

- file: discover/layout_advices
- file: discover/whats_next
2 changes: 1 addition & 1 deletion tutorial/_tpl/instantiate_tutorial_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _process(tutorial_name: str):
shutil.copyfile(f"{TPL_DIR}/tpl.py",f"{TUTORIAL_DIR}/{tutorial_name}.py")

# Read content of TPL_DIR/tpl.md
with open(f"{TPL_DIR}/tpl.md", "r") as f:
with open(f"{TPL_DIR}/tpl_md", "r") as f:
tpl_md = f.read()
basename = os.path.basename(tutorial_name)
tpl_md = tpl_md.replace("tpl", basename)
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion tutorial/discover/button.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Handling button events
# Handling button events

We will now create an application which handles clicks on a button, and updates a counter each time the button is clicked:

Expand Down
6 changes: 5 additions & 1 deletion tutorial/discover/hello_world.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Hello, World!
# Discover Immediate Mode GUIs

We'll start by creating a simple applications, where we will demonstrate several aspects of ImGui and Hello ImGui.

## Hello, World!

We will start by running a simple Hello World application, which displays:
![](hello_world.jpg)
Expand Down
3 changes: 0 additions & 3 deletions tutorial/discover/intro.md

This file was deleted.

14 changes: 14 additions & 0 deletions tutorial/discover/layout_advices.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "imgui.h"
#include <hello_imgui/hello_imgui.h>

class AppState {
};

void Gui(AppState& appState) {
}

int main() {
AppState appState;
auto gui_fn = [&]() { Gui(appState); };
HelloImGui::Run(gui_fn, "TEMPLATE", true);
}
Binary file added tutorial/discover/layout_advices.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions tutorial/discover/layout_advices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Advices to layout your GUI

* Widget labels need to be unique, so you can use a suffix to create a unique identifier for a widget by adding a suffix "##some_suffix", which will not be displayed : see [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system)
* You can use horizontal and vertical layouts to create columns and rows.
* You can use the `imgui.set_next_item_with` function to set the width of the next widget.

**Using em units**

It is important to use em units (see https://en.wikipedia.org/wiki/Em_(typography) ), in order to create application whose layout adapts to the font size, and does not depend on the screen resolution and scaling.

Hello ImGui provides several helper functions to convert between pixels and em units:

*In Python*
```python
hello_imgui.em_to_vec2(em_width: float, em_height: float) -> ImVec2
hello_imgui.em_size(em: float = 1.0) -> float
hello_imgui.pixels_to_em(px_width: float, px_height: float) -> ImVec2
```

*In C++*
```cpp
ImVec2 HelloImGui::EmToVec2(float em_width, float em_height);
float HelloImGui::EmSize(float em = 1.0f);
ImVec2 HelloImGui::PixelsToEm(float px_width, float px_height);
```
The code below demonstrates these advices and create this application:
![](layout_advices.jpg)
**Python**
```{literalinclude} layout_advices.py
```


**C++**
```{literalinclude} layout_advices.cpp
```
66 changes: 66 additions & 0 deletions tutorial/discover/layout_advices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from imgui_bundle import imgui, hello_imgui, imgui_ctx


class AppState:
"""Our application state"""
name: str = ""
first_name: str = ""
city: str = ""
age: int = 0


def input_text_aligned(label: str, value: str, width_pixel: float) -> tuple[bool, str]:
"""A helper function to create a label and an input text field in the same row,
where the label is placed to the left, and the input field is right-aligned.
It returns a tuple of (changed: bool, value: str), following the pattern of imgui.input_text.
"""
# We will use a horizontal layout to place the label and the input field in the same row
# (by default, imgui places widgets vertically)
with imgui_ctx.begin_horizontal(label):
# Display the label on the left side
imgui.text(label)
# Add a spring, which will occupy all remaining space:
# this will push the input field to the right
imgui.spring()
imgui.set_next_item_width(width_pixel)
# Note: by default, imgui.input_text will place the label to the right of the input field.
# We do not want that, so we will use "##" to hide the label. We still need to make it unique,
# so we append the user provided label to it (which will not be displayed).
changed, value = imgui.input_text("##" + label, value)
return changed, value


def gui(app_state: AppState):
# Set the width of the widgets: we will use 10 em for most widgets
widgets_width = hello_imgui.em_size(10)

# Add some spacing at the top: we will skip 1 line of text
imgui.dummy(hello_imgui.em_to_vec2(0, 1))

# Enclose the widgets in a vertical layout: this is important, so that
# the inner horizontal layouts use their parent's layout width.
with imgui_ctx.begin_vertical("main"):
imgui.separator_text("Personal information")
imgui.dummy(hello_imgui.em_to_vec2(20, 0))
_, app_state.name = input_text_aligned("Name", app_state.name, widgets_width)
_, app_state.first_name = input_text_aligned("First name", app_state.first_name, widgets_width)
_, app_state.city = input_text_aligned("City", app_state.city, widgets_width)

# Add a slider to input the age: we enclose it in a horizontal layout
with imgui_ctx.begin_horizontal("Age"):
imgui.text("Age")
# Add a spring to push the slider to the right
imgui.spring()
# Set the width of the slider to 10 em (by default, it would be the full width of the window)
imgui.set_next_item_width(widgets_width)
# use imgui.slider_int with a hidden label, and a range from 0 to 120
_, app_state.age = imgui.slider_int("##Age", app_state.age, 0, 120)


def main():
app_state = AppState()
hello_imgui.run(lambda: gui(app_state), window_size=(400, 200))


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions tutorial/discover/whats_next.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# What's next?

- There are **many** other widgets in Dear ImGui, and Dear ImGui Bundle. Look at the next pages of this tutorial for more examples.
- Look at [Dear ImGui Manual](https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html)
15 changes: 14 additions & 1 deletion tutorial/discover/widget_edit.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Widgets in Python and C++
# Edition widgets in Python and C++

We will now create an application which allows to interactively change the size of an image.
We will use a slider to change this size, and store it in the application state.
Expand All @@ -15,6 +15,7 @@ We will use a slider to change this size, and store it in the application state.
Here, we use Hello ImGui to display images. See the doc about Hello ImGui for more information.
image_from_asset will keep the aspect ratio of the image if one of the dimensions is set to 0.


**Python**
```{literalinclude} widget_edit.py
```
Expand All @@ -23,3 +24,15 @@ image_from_asset will keep the aspect ratio of the image if one of the dimension
**C++**
```{literalinclude} widget_edit.cpp
```

## Looking for more widgets?
**Other widgets?**
There are **many** widgets in Dear ImGui, and Dear ImGui Bundle. Look at the next pages of this tutorial for more examples.

If you are in a hurry, you can look at the [Dear ImGui Manual](https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html),
for which you can find a preview below:

<video controls width="600">
<source src="https://github.com/pthom/imgui_bundle/releases/download/v1.6.1/imgui_manual.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
17 changes: 7 additions & 10 deletions tutorial/discover_immediate.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Discover Immediate Mode GUIs
# Intro

## Intro
## What is an Immediate Mode GUI

Graphical User Interfaces (GUIs) handle how your application is presented to the user.

Expand All @@ -10,17 +10,15 @@ Most GUI frameworks rely on complex patterns like **MVC**, which separate applic

The example below illustrates this concept, where an application could display a counter, together with a button to increase it:

![example](images/demo_immediate.png)
![example](discover/button.jpg)

**Python**:
```python
# on_frame is called at each frame
def on_frame():
# Display a text widget
imgui.text(f"Counter: {counter}")
# Display a button, and return true if clicked
if imgui.button("Increment"):
counter += 1 # Perform an action immediately on interaction
imgui.text(f"Counter: {counter}") # Display a text widget
if imgui.button("Increment"): # Display a button, and return true if clicked
counter += 1 # Perform an action immediately on interaction
```

**C++**:
Expand Down Expand Up @@ -68,5 +66,4 @@ Let’s dive in and explore the straightforward yet powerful world of Immediate

## Deploy web applications in Python with Dear ImGui Bundle

![Jack](images/jack_tangled_frameworks.jpg)
![Tom](images/tom_tangled_frameworks.webp)
TODO: Add content
3 changes: 0 additions & 3 deletions tutorial/intro.md

This file was deleted.

0 comments on commit 0ec5c73

Please sign in to comment.