Changed: Switched ImGUI implementation
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
First Name,Last Name,Sex,Tutorial 1,Tutorial 2,Extended Applications,Numpy & MatPlotLib,SciPy,Monte Carlo,Pandas & Seaborn,Folium
 | 
			
		||||
Abdalaziz,Abunjaila,Male,30.5,15,18,28,17,17,17,22
 | 
			
		||||
Marleen,Adolphi,Female,29.5,15,18,32,19,0,17,24
 | 
			
		||||
Skofiare,Berisha,Female,29.5,13,18,34,20,17,20,26
 | 
			
		||||
Aurela,Brahimi,Female,17.5,15,15.5,26,16,17,19,16
 | 
			
		||||
Cam Thu,Do,Female,31,15,18,34,19,20,21.5,22
 | 
			
		||||
Nova,Eib,Female,31,15,15,34,20,20,21,27
 | 
			
		||||
 
 | 
			
		||||
		
		
			
  | 
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/test.db
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/test.db
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,5 +1,4 @@
 | 
			
		||||
import imgui 
 | 
			
		||||
 | 
			
		||||
from imgui_bundle import imgui, imgui_ctx
 | 
			
		||||
from model import *
 | 
			
		||||
 | 
			
		||||
class ClassEditor:
 | 
			
		||||
@@ -11,7 +10,7 @@ class ClassEditor:
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        classes = Class.select()
 | 
			
		||||
 | 
			
		||||
        with imgui.begin("Class Editor", False, imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE):
 | 
			
		||||
        with imgui_ctx.begin("Class Editor"):
 | 
			
		||||
            imgui.text("Add Class")
 | 
			
		||||
 | 
			
		||||
            _, self.add_name = imgui.input_text(" ", self.add_name)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										261
									
								
								database_editor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								database_editor.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,261 @@
 | 
			
		||||
from imgui_bundle import imgui, imgui_ctx, ImVec2
 | 
			
		||||
from model import *
 | 
			
		||||
import random
 | 
			
		||||
 | 
			
		||||
class DatabaseEditor:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.add_name = str()
 | 
			
		||||
        self.select_class = 0
 | 
			
		||||
        self.select_lecture = 0
 | 
			
		||||
        self.select_student = 0
 | 
			
		||||
        self.select_submission = 0
 | 
			
		||||
 | 
			
		||||
        self.class_name = str()
 | 
			
		||||
        self.add_class_name = str()
 | 
			
		||||
 | 
			
		||||
        self.student_prename = str()
 | 
			
		||||
        self.student_surname = str()
 | 
			
		||||
        self.student_sex = False
 | 
			
		||||
        self.add_student_prename = str()
 | 
			
		||||
        self.add_student_surname = str()
 | 
			
		||||
        self.add_student_sex = False
 | 
			
		||||
 | 
			
		||||
        self.lecture_title = str()
 | 
			
		||||
        self.lecture_points = 0
 | 
			
		||||
        self.add_lecture_title = str()
 | 
			
		||||
        self.add_lecture_points = 0
 | 
			
		||||
 | 
			
		||||
        self.submission_points = 0.0
 | 
			
		||||
        self.add_submission_lecture = 0
 | 
			
		||||
        self.add_submission_points = 0.0
 | 
			
		||||
 | 
			
		||||
    def content_list(self, content: list, selector: int, id: str, height: int) -> int:
 | 
			
		||||
        w = imgui.get_window_size().x
 | 
			
		||||
        with imgui_ctx.begin_child(str(id), ImVec2(w*0.3, height)):
 | 
			
		||||
            for n, c in enumerate(content, start = 1):
 | 
			
		||||
                _, clicked = imgui.selectable(f"{n}. {c}", selector == n-1)
 | 
			
		||||
                if clicked:
 | 
			
		||||
                    selector = n-1
 | 
			
		||||
        return selector
 | 
			
		||||
 | 
			
		||||
    def class_editor(self):
 | 
			
		||||
        w, h = imgui.get_window_size()
 | 
			
		||||
        classes = Class.select()
 | 
			
		||||
        content = [f"{c.name}" for c in classes]
 | 
			
		||||
        self.select_class = self.content_list(content, self.select_class, "class_content", h*0.15)
 | 
			
		||||
        imgui.same_line()
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_child("Class", ImVec2(w*0.25, h*0.15)):
 | 
			
		||||
            imgui.text("Edit Class")
 | 
			
		||||
            _, self.class_name = imgui.input_text_with_hint("##class_edit1", content[self.select_class], self.class_name)
 | 
			
		||||
            
 | 
			
		||||
            if imgui.button("Update"):
 | 
			
		||||
                id = classes[self.select_class].id
 | 
			
		||||
                Class.update(name=self.class_name).where(Class.id == id).execute()
 | 
			
		||||
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Delete"):
 | 
			
		||||
                id = classes[self.select_class].id
 | 
			
		||||
                students = Student.select().where(Student.class_id == id)
 | 
			
		||||
                for student in students:
 | 
			
		||||
                    Submission.delete().where(Submission.student_id == student.id).execute()
 | 
			
		||||
                Student.delete().where(Student.class_id == id).execute()
 | 
			
		||||
                Lecture.delete().where(Lecture.class_id == id).execute()
 | 
			
		||||
                Class.delete().where(Class.id == id).execute()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            imgui.text("Add Class")
 | 
			
		||||
            _, self.add_class_name = imgui.input_text_with_hint("##class_edit2", "Class Name", self.add_class_name)
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Add"):
 | 
			
		||||
                Class.create(name=self.add_class_name)
 | 
			
		||||
 | 
			
		||||
        return classes[self.select_class].id
 | 
			
		||||
 | 
			
		||||
    def student_editor(self, class_id: int): 
 | 
			
		||||
        w, h = imgui.get_window_size()
 | 
			
		||||
        students = Student.select().where(Student.class_id == class_id)
 | 
			
		||||
        content = [f"{s.prename} {s.surname}" for s in students]
 | 
			
		||||
        self.select_student = self.content_list(content, self.select_student, "student_content", h*0.45)
 | 
			
		||||
        imgui.same_line()
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_child("Student", ImVec2(w*0.25, h*0.4)):    
 | 
			
		||||
            imgui.text("Edit Student")
 | 
			
		||||
 | 
			
		||||
            prename = students[self.select_student].prename
 | 
			
		||||
            _, self.student_prename = imgui.input_text_with_hint("##student_edit1", prename, self.student_prename)
 | 
			
		||||
 | 
			
		||||
            surname = students[self.select_student].surname
 | 
			
		||||
            _, self.student_surname = imgui.input_text_with_hint("##student_edit2", surname, self.student_surname)
 | 
			
		||||
 | 
			
		||||
            if imgui.radio_button("Male##1", not self.student_sex):
 | 
			
		||||
                self.student_sex = not self.student_sex
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
            if imgui.radio_button("Female##1", self.student_sex):
 | 
			
		||||
                self.student_sex = not self.student_sex
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Update"):
 | 
			
		||||
                Student.update(
 | 
			
		||||
                    prename = self.student_prename,
 | 
			
		||||
                    surname = self.student_surname,
 | 
			
		||||
                    sex = "Female" if self.student_sex else "Male"
 | 
			
		||||
                ).where(Student.id == students[self.select_student].id).execute()
 | 
			
		||||
            
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Delete"):
 | 
			
		||||
                id = students[self.select_student].id
 | 
			
		||||
                Student.delete().where(Student.id == id).execute()
 | 
			
		||||
                Submission.delete().where(Submission.student_id == id).execute()
 | 
			
		||||
                self.select_student = 0
 | 
			
		||||
           
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            imgui.text("Add Student")
 | 
			
		||||
            _, self.add_student_prename = imgui.input_text_with_hint("##student_edit3", "First Name", self.add_student_prename)
 | 
			
		||||
            _, self.add_student_surname = imgui.input_text_with_hint("##student_edit4", "Last Name", self.add_student_surname)
 | 
			
		||||
            
 | 
			
		||||
            if imgui.radio_button("Male##2", not self.add_student_sex):
 | 
			
		||||
                self.add_student_sex = not self.add_student_sex
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
            if imgui.radio_button("Female##2", self.add_student_sex):
 | 
			
		||||
                self.add_student_sex = not self.add_student_sex
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Add"):
 | 
			
		||||
                Student.create(
 | 
			
		||||
                    prename=self.add_student_prename,
 | 
			
		||||
                    surname=self.add_student_surname,
 | 
			
		||||
                    sex="Female" if self.add_student_sex else "Male",
 | 
			
		||||
                    class_id=class_id
 | 
			
		||||
                )
 | 
			
		||||
                self.add_student_prename = str()
 | 
			
		||||
                self.add_student_surname = str()
 | 
			
		||||
                self.add_student_sex = False
 | 
			
		||||
 | 
			
		||||
        return students[self.select_student].id
 | 
			
		||||
 | 
			
		||||
    def lecture_editor(self, class_id: int):
 | 
			
		||||
        w, h = imgui.get_window_size()
 | 
			
		||||
        lectures = Lecture.select().where(Lecture.class_id == class_id)
 | 
			
		||||
        content = [f"{l.title}" for l in lectures]
 | 
			
		||||
        self.select_lecture = self.content_list(content, self.select_lecture, "lecture_content", h*0.15)
 | 
			
		||||
        imgui.same_line()
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_child("Lecture", ImVec2(w*0.25, h*0.15)):
 | 
			
		||||
            imgui.text("Edit Lecture")
 | 
			
		||||
            _, self.lecture_title = imgui.input_text_with_hint("##lecture_edit1", content[self.select_lecture], self.lecture_title)
 | 
			
		||||
            _, self.lecture_points = imgui.input_int("##lecture_points1", self.lecture_points)
 | 
			
		||||
            if self.lecture_points < 0:
 | 
			
		||||
                self.lecture_points = 0
 | 
			
		||||
        
 | 
			
		||||
            if imgui.button("Update"):
 | 
			
		||||
                Lecture.update(title=self.lecture_title, points=self.lecture_points).where(Lecture.id == lectures[self.select_lecture].id).execute()
 | 
			
		||||
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Delete"):
 | 
			
		||||
                id = lectures[self.select_lecture].id 
 | 
			
		||||
                Submission.delete().where(Submission.lecture_id == id).execute()
 | 
			
		||||
                Lecture.delete().where(Lecture.id == id).execute()
 | 
			
		||||
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            imgui.text("Add Lecture")
 | 
			
		||||
            _, self.add_lecture_title = imgui.input_text_with_hint("##lecture_edit2", "Lecture Title", self.add_lecture_title)
 | 
			
		||||
            _, self.add_lecture_points = imgui.input_int("##lecture_points2", self.add_lecture_points)
 | 
			
		||||
            if self.add_lecture_points < 0:
 | 
			
		||||
                self.add_lecture_points = 0
 | 
			
		||||
        
 | 
			
		||||
            if imgui.button("Add"):
 | 
			
		||||
                Lecture.create(title=self.add_lecture_title, points=self.add_lecture_points, class_id=class_id)
 | 
			
		||||
 | 
			
		||||
        return lectures[self.select_lecture].id
 | 
			
		||||
 | 
			
		||||
    def submission_editor(self, student_id: int):
 | 
			
		||||
        w, h = imgui.get_window_size()
 | 
			
		||||
        submissions = Submission.select().where(Submission.student_id == student_id)
 | 
			
		||||
        lectures = [Lecture.get_by_id(sub.lecture_id) for sub in submissions]
 | 
			
		||||
        content = [l.title for l in lectures]
 | 
			
		||||
        self.select_submission = self.content_list(content, self.select_submission, "submission_content", h*0.2)
 | 
			
		||||
        imgui.same_line()
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_child("Submission", ImVec2(w*0.25, h*0.2)):
 | 
			
		||||
            imgui.text("Edit Submission")
 | 
			
		||||
            imgui.text(content[self.select_submission])
 | 
			
		||||
            
 | 
			
		||||
            points = submissions[self.select_submission].points
 | 
			
		||||
            if points.is_integer():
 | 
			
		||||
                points = int(points)
 | 
			
		||||
 | 
			
		||||
            max_points = lectures[self.select_submission].points
 | 
			
		||||
 | 
			
		||||
            _, self.submission_points = imgui.input_float(f"{points}/{max_points}", self.submission_points, 0.5, 10, "%.1f")
 | 
			
		||||
            if self.submission_points < 0:
 | 
			
		||||
                self.submission_points = 0
 | 
			
		||||
            
 | 
			
		||||
            if imgui.button("Update"):
 | 
			
		||||
                Submission.update(points=self.submission_points).where(Submission.id == submissions[self.select_submission].id).execute()
 | 
			
		||||
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Delete"):
 | 
			
		||||
                Submission.delete().where(Submission.id == submissions[self.select_submission].id).execute()
 | 
			
		||||
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            imgui.text("Add Submission")
 | 
			
		||||
            available_lectures = Lecture.select().where(Lecture.class_id == Student.get_by_id(student_id).class_id)
 | 
			
		||||
            combo_items = [l.title for l in available_lectures]
 | 
			
		||||
            _, self.add_submission_lecture = imgui.combo("##lecture_combo", self.add_submission_lecture, combo_items, len(combo_items))
 | 
			
		||||
            _, self.add_submission_points = imgui.input_float("##lecture_title", self.add_submission_points, 0.5, 10, "%.1f")
 | 
			
		||||
            if self.add_submission_points < 0:
 | 
			
		||||
                self.add_submission_points = 0
 | 
			
		||||
            
 | 
			
		||||
            if imgui.button("Add"):
 | 
			
		||||
                Submission.create(
 | 
			
		||||
                    points=self.add_submission_points,
 | 
			
		||||
                    lecture_id=available_lectures[self.add_submission_lecture].id,
 | 
			
		||||
                    student_id=student_id
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
        return submissions[self.select_submission].id
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        with imgui_ctx.begin("Database Editor"):
 | 
			
		||||
            class_id = self.class_editor()
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
            self.lecture_editor(class_id)
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
            student_id = self.student_editor(class_id)
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
            self.submission_editor(student_id)
 | 
			
		||||
        return
 | 
			
		||||
        classes = Class.select()
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin("Database Editor"):
 | 
			
		||||
            imgui.text("Add Class")
 | 
			
		||||
 | 
			
		||||
            _, self.add_name = imgui.input_text(" ", self.add_name)
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Add"):
 | 
			
		||||
                if self.add_name:
 | 
			
		||||
                    Class.create(name=self.add_name)
 | 
			
		||||
                    self.add_name = str()
 | 
			
		||||
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            if not classes:
 | 
			
		||||
                imgui.text("No Dataset could be queried")
 | 
			
		||||
                return 
 | 
			
		||||
    
 | 
			
		||||
            for n, c in enumerate(classes, start=1):
 | 
			
		||||
                display = f"{n}. {c.name}"
 | 
			
		||||
                opened, _ = imgui.selectable(display, self.select == n-1)
 | 
			
		||||
                if opened:
 | 
			
		||||
                    self.select = n-1
 | 
			
		||||
 | 
			
		||||
        return classes[self.select]    
 | 
			
		||||
							
								
								
									
										926
									
								
								demo_docking.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										926
									
								
								demo_docking.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,926 @@
 | 
			
		||||
# A more complex app demo
 | 
			
		||||
#
 | 
			
		||||
# It demonstrates how to:
 | 
			
		||||
# - set up a complex docking layouts (with several possible layouts):
 | 
			
		||||
# - load additional fonts, possibly colored, and with emojis
 | 
			
		||||
# - display a log window
 | 
			
		||||
# - use the status bar
 | 
			
		||||
# - use default menus (App and view menu), and how to customize them
 | 
			
		||||
# - use a specific application state (instead of using static variables)
 | 
			
		||||
# - save some additional user settings within imgui ini file
 | 
			
		||||
# - use borderless windows, that are movable and resizable
 | 
			
		||||
import json
 | 
			
		||||
from enum import Enum
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from imgui_bundle import hello_imgui, icons_fontawesome_6, imgui, immapp, imgui_ctx, ImVec4, ImVec2
 | 
			
		||||
from imgui_bundle.demos_python import demo_utils
 | 
			
		||||
from typing import List, Any
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Our Application State
 | 
			
		||||
##########################################################################
 | 
			
		||||
class MyAppSettings:
 | 
			
		||||
    motto: hello_imgui.InputTextData
 | 
			
		||||
    value: int = 10
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.motto = hello_imgui.InputTextData(
 | 
			
		||||
            "Hello, Dear ImGui\n"
 | 
			
		||||
            "Unleash your creativity!\n",
 | 
			
		||||
            True, # multiline
 | 
			
		||||
            (14.0, 3.0) # initial size (in em)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
class RocketState(Enum):
 | 
			
		||||
    Init = 0
 | 
			
		||||
    Preparing = 1
 | 
			
		||||
    Launched = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Struct that holds the application's state
 | 
			
		||||
class AppState:
 | 
			
		||||
    f: float
 | 
			
		||||
    counter: int
 | 
			
		||||
    rocket_progress: float
 | 
			
		||||
    my_app_settings: MyAppSettings
 | 
			
		||||
    rocket_state: RocketState
 | 
			
		||||
    rocket_launch_time: float
 | 
			
		||||
 | 
			
		||||
    title_font: imgui.ImFont
 | 
			
		||||
    color_font: imgui.ImFont
 | 
			
		||||
    emoji_font: imgui.ImFont
 | 
			
		||||
    large_icon_font: imgui.ImFont
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.f = 0
 | 
			
		||||
        self.counter = 0
 | 
			
		||||
        self.rocket_progress = 0.0
 | 
			
		||||
        self.rocket_launch_time = 0.0
 | 
			
		||||
        self.my_app_settings = MyAppSettings()
 | 
			
		||||
        self.rocket_state = RocketState.Init
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Additional fonts handling
 | 
			
		||||
##########################################################################
 | 
			
		||||
def load_fonts(app_state: AppState):  # This is called by runnerParams.callbacks.LoadAdditionalFonts
 | 
			
		||||
    # First, load the default font (the default font should be loaded first)
 | 
			
		||||
    # In this example, we instruct HelloImGui to use FontAwesome6 instead of FontAwesome4
 | 
			
		||||
    hello_imgui.get_runner_params().callbacks.default_icon_font = hello_imgui.DefaultIconFont.font_awesome6
 | 
			
		||||
    hello_imgui.imgui_default_settings.load_default_font_with_font_awesome_icons()
 | 
			
		||||
 | 
			
		||||
    # Load the title font
 | 
			
		||||
    # app_state.title_font = hello_imgui.load_font("fonts/DroidSans.ttf", 18.0)
 | 
			
		||||
    font_loading_params_title_icons = hello_imgui.FontLoadingParams()
 | 
			
		||||
    font_loading_params_title_icons.merge_font_awesome = True
 | 
			
		||||
    app_state.title_font = hello_imgui.load_font("fonts/Roboto/Roboto-BoldItalic.ttf", 18, font_loading_params_title_icons)
 | 
			
		||||
 | 
			
		||||
    # Load the emoji font
 | 
			
		||||
    font_loading_params_emoji = hello_imgui.FontLoadingParams()
 | 
			
		||||
    font_loading_params_emoji.use_full_glyph_range = True
 | 
			
		||||
    app_state.emoji_font = hello_imgui.load_font("fonts/NotoEmoji-Regular.ttf", 24., font_loading_params_emoji)
 | 
			
		||||
 | 
			
		||||
    # Load a large icon font
 | 
			
		||||
    font_loading_params_large_icon = hello_imgui.FontLoadingParams()
 | 
			
		||||
    font_loading_params_large_icon.use_full_glyph_range = True
 | 
			
		||||
    app_state.large_icon_font = hello_imgui.load_font("fonts/fontawesome-webfont.ttf", 24., font_loading_params_large_icon)
 | 
			
		||||
 | 
			
		||||
    # Load a colored font
 | 
			
		||||
    font_loading_params_color = hello_imgui.FontLoadingParams()
 | 
			
		||||
    font_loading_params_color.load_color = True
 | 
			
		||||
    app_state.color_font = hello_imgui.load_font("fonts/Playbox/Playbox-FREE.otf", 24., font_loading_params_color)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Save additional settings in the ini file
 | 
			
		||||
##########################################################################
 | 
			
		||||
# This demonstrates how to store additional info in the application settings
 | 
			
		||||
# Use this sparingly!
 | 
			
		||||
# This is provided as a convenience only, and it is not intended to store large quantities of text data.
 | 
			
		||||
 | 
			
		||||
# Warning, the save/load function below are quite simplistic!
 | 
			
		||||
def my_app_settings_to_string(settings: MyAppSettings) -> str:
 | 
			
		||||
    as_dict: dict[str, Any] = {}
 | 
			
		||||
    as_dict["motto"] = hello_imgui.input_text_data_to_dict(settings.motto)
 | 
			
		||||
    as_dict["value"] = settings.value
 | 
			
		||||
    return json.dumps(as_dict)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def string_to_my_app_settings(s: str) -> MyAppSettings:
 | 
			
		||||
    r = MyAppSettings()
 | 
			
		||||
    try:
 | 
			
		||||
        as_dict = json.loads(s)
 | 
			
		||||
        r.motto = hello_imgui.input_text_data_from_dict(as_dict["motto"])
 | 
			
		||||
        r.value = as_dict["value"]
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.error, f"Error while loading user settings: {e}")
 | 
			
		||||
    return r
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def load_my_app_settings(app_state: AppState):
 | 
			
		||||
    """
 | 
			
		||||
    Note: load_my_app_settings() and save_my_app_settings() will be called in the callbacks `post_init` & `before_exit`
 | 
			
		||||
         runner_params.callbacks.post_init = lambda: load_user_settings(app_state)
 | 
			
		||||
         runner_params.callbacks.before_exit = lambda: save_user_settings(app_state)
 | 
			
		||||
    """
 | 
			
		||||
    app_state.my_app_settings = string_to_my_app_settings(
 | 
			
		||||
        hello_imgui.load_user_pref("MyAppSettings")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def save_my_app_settings(app_state: AppState):
 | 
			
		||||
    hello_imgui.save_user_pref(
 | 
			
		||||
        "MyAppSettings", my_app_settings_to_string(app_state.my_app_settings)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Gui functions used in this demo
 | 
			
		||||
##########################################################################
 | 
			
		||||
@immapp.static(last_hide_time=1)
 | 
			
		||||
def demo_hide_window(app_state: AppState):
 | 
			
		||||
    # Display a button that will hide the application window
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Hide app window")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    if imgui.button("Hide"):
 | 
			
		||||
        demo_hide_window.last_hide_time = time.time()
 | 
			
		||||
        hello_imgui.get_runner_params().app_window_params.hidden = True
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("By clicking this button, you can hide the window for 3 seconds.")
 | 
			
		||||
    if demo_hide_window.last_hide_time > 0.0:
 | 
			
		||||
        now = time.time()
 | 
			
		||||
        if now - demo_hide_window.last_hide_time > 3.0:
 | 
			
		||||
            demo_hide_window.last_hide_time = -1.0
 | 
			
		||||
            hello_imgui.get_runner_params().app_window_params.hidden = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Display a button that will add another dockable window during execution
 | 
			
		||||
def demo_show_additional_window(app_state: AppState):
 | 
			
		||||
    # In order to add a dockable window during execution, you should use
 | 
			
		||||
    #     hello_imgui.add_dockable_window()
 | 
			
		||||
    # Note: you should not modify manually the content of runnerParams.docking_params.dockable_windows
 | 
			
		||||
    #       (since HelloImGui is constantly looping on it)
 | 
			
		||||
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Dynamically add window")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    window_name = "Additional Window"
 | 
			
		||||
    if imgui.button("Show additional window"):
 | 
			
		||||
        additional_window = hello_imgui.DockableWindow()
 | 
			
		||||
        additional_window.label = window_name
 | 
			
		||||
        additional_window.include_in_view_menu = False  # this window is not shown in the view menu,
 | 
			
		||||
        additional_window.remember_is_visible = False  # its visibility is not saved in the settings file,
 | 
			
		||||
        additional_window.dock_space_name = "MiscSpace"  # when shown, it will appear in MiscSpace.
 | 
			
		||||
        additional_window.gui_function = lambda: imgui.text("This is the additional window")
 | 
			
		||||
        hello_imgui.add_dockable_window(
 | 
			
		||||
            additional_window,
 | 
			
		||||
            force_dockspace=False  # means that the window will be docked to the last space it was docked to
 | 
			
		||||
                                   # i.e. dock_space_name is ignored if the user previously moved the window to another space
 | 
			
		||||
        )
 | 
			
		||||
    imgui.set_item_tooltip("By clicking this button, you can show an additional window")
 | 
			
		||||
 | 
			
		||||
    if imgui.button("Remove additional window"):
 | 
			
		||||
        hello_imgui.remove_dockable_window(window_name)
 | 
			
		||||
    imgui.set_item_tooltip("By clicking this button, you can remove the additional window")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_basic_widgets(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Basic widgets demo")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    imgui.begin_group()
 | 
			
		||||
    # Edit a float using a slider from 0.0 to 1.0
 | 
			
		||||
    changed, app_state.f = imgui.slider_float("float", app_state.f, 0.0, 1.0)
 | 
			
		||||
    if changed:
 | 
			
		||||
        hello_imgui.log(
 | 
			
		||||
            hello_imgui.LogLevel.warning, f"state.f was changed to {app_state.f}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # Buttons return true when clicked (most widgets return true when edited/activated)
 | 
			
		||||
    if imgui.button("Button"):
 | 
			
		||||
        app_state.counter += 1
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Button was pressed")
 | 
			
		||||
    imgui.same_line()
 | 
			
		||||
    imgui.text(f"counter = {app_state.counter}")
 | 
			
		||||
    imgui.end_group()
 | 
			
		||||
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("These widgets will interact with the log window")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_user_settings(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("User settings")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    imgui.begin_group()
 | 
			
		||||
 | 
			
		||||
    imgui.set_next_item_width(hello_imgui.em_size(7.0))
 | 
			
		||||
    _, app_state.my_app_settings.value = imgui.slider_int(
 | 
			
		||||
        "Value", app_state.my_app_settings.value, 0, 100
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    _ = hello_imgui.input_text_resizable("Motto", app_state.my_app_settings.motto)
 | 
			
		||||
    imgui.text("(this text widget is resizable)")
 | 
			
		||||
 | 
			
		||||
    imgui.end_group()
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("The values below are stored in the application settings ini file and restored at startup")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_rocket(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Rocket demo")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    imgui.begin_group()
 | 
			
		||||
    if app_state.rocket_state == RocketState.Init:
 | 
			
		||||
        if imgui.button(f"{icons_fontawesome_6.ICON_FA_ROCKET} Launch rocket"):
 | 
			
		||||
            app_state.rocket_launch_time = time.time()
 | 
			
		||||
            app_state.rocket_state = RocketState.Preparing
 | 
			
		||||
            hello_imgui.log(hello_imgui.LogLevel.warning, "Rocket is being prepared")
 | 
			
		||||
    elif app_state.rocket_state == RocketState.Preparing:
 | 
			
		||||
        imgui.text("Please Wait")
 | 
			
		||||
        app_state.rocket_progress = (time.time() - app_state.rocket_launch_time) / 3.0
 | 
			
		||||
        if app_state.rocket_progress >= 1.0:
 | 
			
		||||
            app_state.rocket_state = RocketState.Launched
 | 
			
		||||
            hello_imgui.log(hello_imgui.LogLevel.warning, "Rocket was launched")
 | 
			
		||||
    elif app_state.rocket_state == RocketState.Launched:
 | 
			
		||||
        imgui.text(f"{icons_fontawesome_6.ICON_FA_ROCKET} Rocket launched")
 | 
			
		||||
        if imgui.button("Reset Rocket"):
 | 
			
		||||
            app_state.rocket_state = RocketState.Init
 | 
			
		||||
            app_state.rocket_progress = 0.0
 | 
			
		||||
    imgui.end_group()
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("Look at the status bar after clicking")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_docking_flags(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Main dock space node flags")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
    imgui.text_wrapped(
 | 
			
		||||
        """
 | 
			
		||||
This will edit the ImGuiDockNodeFlags for "MainDockSpace".
 | 
			
		||||
Most flags are inherited by children dock spaces.
 | 
			
		||||
        """
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class DockFlagWithInfo:
 | 
			
		||||
        def __init__(self, flag, label, tip):
 | 
			
		||||
            self.flag = flag
 | 
			
		||||
            self.label = label
 | 
			
		||||
            self.tip = tip
 | 
			
		||||
 | 
			
		||||
    all_flags = [
 | 
			
		||||
        DockFlagWithInfo(
 | 
			
		||||
            imgui.DockNodeFlags_.no_docking_split,
 | 
			
		||||
            "NoSplit",
 | 
			
		||||
            "prevent Dock Nodes from being split",
 | 
			
		||||
        ),
 | 
			
		||||
        DockFlagWithInfo(
 | 
			
		||||
            imgui.DockNodeFlags_.no_resize,
 | 
			
		||||
            "NoResize",
 | 
			
		||||
            "prevent Dock Nodes from being resized",
 | 
			
		||||
        ),
 | 
			
		||||
        DockFlagWithInfo(
 | 
			
		||||
            imgui.DockNodeFlags_.auto_hide_tab_bar,
 | 
			
		||||
            "AutoHideTabBar",
 | 
			
		||||
            "show tab bar only if multiple windows\n"
 | 
			
		||||
            + 'You will need to restore the layout after changing (Menu "View/Restore Layout")',
 | 
			
		||||
        ),
 | 
			
		||||
        DockFlagWithInfo(
 | 
			
		||||
            imgui.DockNodeFlags_.no_docking_over_central_node,
 | 
			
		||||
            "NoDockingInCentralNode",
 | 
			
		||||
            "prevent docking in central node\n(only works with the main dock space)",
 | 
			
		||||
        ),
 | 
			
		||||
        # DockFlagWithInfo(imgui.DockNodeFlags_.passthru_central_node, "PassthruCentralNode", "advanced"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    main_dock_space_node_flags = (
 | 
			
		||||
        hello_imgui.get_runner_params().docking_params.main_dock_space_node_flags
 | 
			
		||||
    )
 | 
			
		||||
    for flag_with_info in all_flags:
 | 
			
		||||
        _, main_dock_space_node_flags = imgui.checkbox_flags(
 | 
			
		||||
            flag_with_info.label, main_dock_space_node_flags, flag_with_info.flag
 | 
			
		||||
        )
 | 
			
		||||
        if imgui.is_item_hovered():
 | 
			
		||||
            imgui.set_tooltip("%s" % flag_with_info.tip)
 | 
			
		||||
 | 
			
		||||
    hello_imgui.get_runner_params().docking_params.main_dock_space_node_flags = (
 | 
			
		||||
        main_dock_space_node_flags
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gui_window_layout_customization(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Switch between layouts")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
    imgui.text('with the menu "View/Layouts"')
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip(
 | 
			
		||||
            "Each layout remembers separately the modifications applied by the user, \n"
 | 
			
		||||
            + "and the selected layout is restored at startup"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Change the theme")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
    imgui.text('with the menu "View/Theme"')
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("The selected theme is remembered and restored at startup")
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
 | 
			
		||||
    demo_docking_flags(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gui_window_alternative_theme(app_state: AppState):
 | 
			
		||||
    # Since this window applies a theme, We need to call "imgui.begin" ourselves so
 | 
			
		||||
    # that we can apply the theme before opening the window.
 | 
			
		||||
    #
 | 
			
		||||
    # In order to obtain this, we applied the following option to the window
 | 
			
		||||
    # that displays this Gui:
 | 
			
		||||
    #     alternative_theme_window.call_begin_end = False
 | 
			
		||||
 | 
			
		||||
    # emulate C/C++ static variable: we will store some static variables
 | 
			
		||||
    # as attributes of the function
 | 
			
		||||
    statics = gui_window_alternative_theme
 | 
			
		||||
 | 
			
		||||
    # Apply the theme before opening the window
 | 
			
		||||
    tweaked_theme = hello_imgui.ImGuiTweakedTheme()
 | 
			
		||||
    tweaked_theme.theme = hello_imgui.ImGuiTheme_.white_is_white
 | 
			
		||||
    tweaked_theme.tweaks.rounding = 0.0
 | 
			
		||||
    hello_imgui.push_tweaked_theme(tweaked_theme)
 | 
			
		||||
 | 
			
		||||
    # Open the window
 | 
			
		||||
    window_opened = imgui.begin("Alternative Theme")
 | 
			
		||||
    if window_opened:
 | 
			
		||||
        # Display some widgets
 | 
			
		||||
        imgui.push_font(app_state.title_font)
 | 
			
		||||
        imgui.text("Alternative Theme")
 | 
			
		||||
        imgui.pop_font()
 | 
			
		||||
        imgui.text("This window uses a different theme")
 | 
			
		||||
        imgui.set_item_tooltip("""
 | 
			
		||||
            tweaked_theme = hello_imgui.ImGuiTheme.ImGuiTweakedTheme()
 | 
			
		||||
            tweaked_theme.theme = hello_imgui.ImGuiTheme_.white_is_white.value
 | 
			
		||||
            tweaked_theme.tweaks.rounding = 0.0
 | 
			
		||||
            hello_imgui.apply_tweaked_theme(tweaked_theme)
 | 
			
		||||
        """
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if imgui.collapsing_header("Basic Widgets", imgui.TreeNodeFlags_.default_open.value):
 | 
			
		||||
            if not hasattr(statics, "checked"):
 | 
			
		||||
                statics.checked = True
 | 
			
		||||
            _, statics.checked = imgui.checkbox("Checkbox", statics.checked)
 | 
			
		||||
 | 
			
		||||
            if imgui.button("Button"):
 | 
			
		||||
                hello_imgui.log(hello_imgui.LogLevel.info, "Button was pressed")
 | 
			
		||||
            imgui.set_item_tooltip("This is a button")
 | 
			
		||||
 | 
			
		||||
            if not hasattr(statics, "radio"):
 | 
			
		||||
                statics.radio = 0
 | 
			
		||||
            if imgui.radio_button("Radio 1", statics.radio == 0):
 | 
			
		||||
                statics.radio = 0
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
            if imgui.radio_button("Radio 2", statics.radio == 1):
 | 
			
		||||
                statics.radio = 1
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
            if imgui.radio_button("Radio 3", statics.radio == 2):
 | 
			
		||||
                statics.radio = 2
 | 
			
		||||
 | 
			
		||||
            # Haiku
 | 
			
		||||
            # Display a image of the haiku below with Japanese characters
 | 
			
		||||
            # with an informative tooltip
 | 
			
		||||
            haiku_image_height = hello_imgui.em_size(5.0)
 | 
			
		||||
            hello_imgui.image_from_asset("images/haiku.png", (0.0, haiku_image_height))
 | 
			
		||||
            imgui.set_item_tooltip("""
 | 
			
		||||
Extract from Wikipedia
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
In early 1686, Bashō composed one of his best-remembered haiku:
 | 
			
		||||
 | 
			
		||||
        furu ike ya / kawazu tobikomu / mizu no oto
 | 
			
		||||
 | 
			
		||||
   an ancient pond / a frog jumps in / the splash of water
 | 
			
		||||
 | 
			
		||||
This poem became instantly famous.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
This haiku is here rendered as an image, mainly to preserve space,
 | 
			
		||||
because adding a Japanese font to the project would enlarge its size.
 | 
			
		||||
Handling Japanese font is of course possible within ImGui / Hello ImGui!
 | 
			
		||||
            """)
 | 
			
		||||
 | 
			
		||||
            # Display the haiku text as an InputTextMultiline
 | 
			
		||||
            if not hasattr(statics, "poem"):
 | 
			
		||||
                statics.poem = (
 | 
			
		||||
                    "   Old Pond\n"
 | 
			
		||||
                    "  Frog Leaps In\n"
 | 
			
		||||
                    " Water's Sound\n"
 | 
			
		||||
                    "\n"
 | 
			
		||||
                    "      Matsuo Bashō - 1686"
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            _, statics.poem = imgui.input_text_multiline("##Poem", statics.poem, hello_imgui.em_to_vec2(15.0, 5.5))
 | 
			
		||||
 | 
			
		||||
            # a popup with a modal window
 | 
			
		||||
            if imgui.button("Open Modal"):
 | 
			
		||||
                imgui.open_popup("MyModal")
 | 
			
		||||
            popup_opened, _ = imgui.begin_popup_modal("MyModal", None, imgui.WindowFlags_.always_auto_resize.value)
 | 
			
		||||
            if popup_opened:
 | 
			
		||||
                imgui.text("This is a modal window")
 | 
			
		||||
                if imgui.button("Close"):
 | 
			
		||||
                    imgui.close_current_popup()
 | 
			
		||||
                imgui.end_popup()
 | 
			
		||||
 | 
			
		||||
            if not hasattr(statics, "text"):
 | 
			
		||||
                statics.text = "Hello, world!"
 | 
			
		||||
            _, statics.text = imgui.input_text("Input text", statics.text)
 | 
			
		||||
 | 
			
		||||
            if imgui.tree_node("Text Display"):
 | 
			
		||||
                imgui.text("Hello, world!")
 | 
			
		||||
                imgui.text_colored((1.0, 0.5, 0.5, 1.0), "Some text")
 | 
			
		||||
                imgui.text_disabled("Disabled text")
 | 
			
		||||
                imgui.text_wrapped("This is a long text that will be wrapped in the window")
 | 
			
		||||
                imgui.tree_pop()
 | 
			
		||||
 | 
			
		||||
    # Close the window
 | 
			
		||||
    imgui.end()
 | 
			
		||||
 | 
			
		||||
    # Restore the theme
 | 
			
		||||
    hello_imgui.pop_tweaked_theme()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_assets(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Image From Assets")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
    hello_imgui.begin_group_column()
 | 
			
		||||
    imgui.dummy(hello_imgui.em_to_vec2(0.0, 0.45))
 | 
			
		||||
    imgui.text("Hello")
 | 
			
		||||
    hello_imgui.end_group_column()
 | 
			
		||||
    hello_imgui.image_from_asset("images/world.png", hello_imgui.em_to_vec2(2.5, 2.5))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_fonts(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Fonts - " + icons_fontawesome_6.ICON_FA_ROCKET)
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    imgui.text_wrapped("Mix icons " + icons_fontawesome_6.ICON_FA_FACE_SMILE + " and text " + icons_fontawesome_6.ICON_FA_ROCKET)
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("Example with Font Awesome Icons")
 | 
			
		||||
 | 
			
		||||
    imgui.text("Emojis")
 | 
			
		||||
 | 
			
		||||
    with imgui_ctx.begin_group():
 | 
			
		||||
        imgui.push_font(app_state.emoji_font)
 | 
			
		||||
        imgui.text("✌❤🌴🚀")
 | 
			
		||||
        imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("Example with NotoEmoji font")
 | 
			
		||||
 | 
			
		||||
    imgui.text("Colored Fonts")
 | 
			
		||||
    imgui.push_font(app_state.color_font)
 | 
			
		||||
    imgui.text("COLOR!")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip("Example with Playbox-FREE.otf font")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo_themes(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.title_font)
 | 
			
		||||
    imgui.text("Themes")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
    tweaked_theme = hello_imgui.get_runner_params().imgui_window_params.tweaked_theme
 | 
			
		||||
 | 
			
		||||
    imgui.begin_group()
 | 
			
		||||
    button_size = hello_imgui.em_to_vec2(7.0, 0.0)
 | 
			
		||||
    if imgui.button("Cherry", button_size):
 | 
			
		||||
        tweaked_theme.theme = hello_imgui.ImGuiTheme_.cherry
 | 
			
		||||
        hello_imgui.apply_tweaked_theme(tweaked_theme)
 | 
			
		||||
    if imgui.button("DarculaDarker", button_size):
 | 
			
		||||
        tweaked_theme.theme = hello_imgui.ImGuiTheme_.darcula_darker
 | 
			
		||||
        hello_imgui.apply_tweaked_theme(tweaked_theme)
 | 
			
		||||
    imgui.end_group()
 | 
			
		||||
    if imgui.is_item_hovered():
 | 
			
		||||
        imgui.set_tooltip(
 | 
			
		||||
            "There are lots of other themes: look at the menu View/Theme\n"
 | 
			
		||||
            "The selected theme is remembered and restored at startup"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gui_window_demo_features(app_state: AppState):
 | 
			
		||||
    demo_fonts(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_assets(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_basic_widgets(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_rocket(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_user_settings(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_hide_window(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_show_additional_window(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
    demo_themes(app_state)
 | 
			
		||||
    imgui.separator()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def status_bar_gui(app_state: AppState):
 | 
			
		||||
    if app_state.rocket_state == RocketState.Preparing:
 | 
			
		||||
        imgui.text("Rocket completion: ")
 | 
			
		||||
        imgui.same_line()
 | 
			
		||||
        imgui.progress_bar(app_state.rocket_progress, hello_imgui.em_to_vec2(7.0, 1.0))  # type: ignore
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def show_menu_gui(runner_params: hello_imgui.RunnerParams):
 | 
			
		||||
    hello_imgui.show_app_menu(runner_params)
 | 
			
		||||
    hello_imgui.show_view_menu(runner_params)
 | 
			
		||||
    if imgui.begin_menu("My Menu"):
 | 
			
		||||
        clicked, _ = imgui.menu_item("Test me", "", False)
 | 
			
		||||
        if clicked:
 | 
			
		||||
            hello_imgui.log(hello_imgui.LogLevel.warning, "It works")
 | 
			
		||||
        imgui.end_menu()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def show_app_menu_items():
 | 
			
		||||
    clicked, _ = imgui.menu_item("A Custom app menu item", "", False)
 | 
			
		||||
    if clicked:
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on A Custom app menu item")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def show_top_toolbar(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.large_icon_font)
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_POWER_OFF):
 | 
			
		||||
        hello_imgui.get_runner_params().app_shall_exit = True
 | 
			
		||||
 | 
			
		||||
    imgui.same_line(imgui.get_window_width() - hello_imgui.em_size(7.0))
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_HOUSE):
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on Home in the top toolbar")
 | 
			
		||||
    imgui.same_line()
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_FLOPPY_DISK):
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on Save in the top toolbar")
 | 
			
		||||
    imgui.same_line()
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_ADDRESS_BOOK):
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on Address Book in the top toolbar")
 | 
			
		||||
 | 
			
		||||
    imgui.same_line(imgui.get_window_width() - hello_imgui.em_size(2.0))
 | 
			
		||||
    imgui.text(icons_fontawesome_6.ICON_FA_BATTERY_THREE_QUARTERS)
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def show_right_toolbar(app_state: AppState):
 | 
			
		||||
    imgui.push_font(app_state.large_icon_font)
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_CIRCLE_ARROW_LEFT):
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on Circle left in the right toolbar")
 | 
			
		||||
    if imgui.button(icons_fontawesome_6.ICON_FA_CIRCLE_ARROW_RIGHT):
 | 
			
		||||
        hello_imgui.log(hello_imgui.LogLevel.info, "Clicked on Circle right in the right toolbar")
 | 
			
		||||
    imgui.pop_font()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Docking Layouts and Docking windows
 | 
			
		||||
##########################################################################
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# 1. Define the Docking splits (two versions are available)
 | 
			
		||||
#
 | 
			
		||||
def create_default_docking_splits() -> List[hello_imgui.DockingSplit]:
 | 
			
		||||
    # Define the default docking splits,
 | 
			
		||||
    # i.e. the way the screen space is split in different target zones for the dockable windows
 | 
			
		||||
    # We want to split "MainDockSpace" (which is provided automatically) into three zones, like this:
 | 
			
		||||
    #
 | 
			
		||||
    #    ___________________________________________
 | 
			
		||||
    #    |        |                                |
 | 
			
		||||
    #    | Command|                                |
 | 
			
		||||
    #    | Space  |    MainDockSpace               |
 | 
			
		||||
    #    |------- |                                |
 | 
			
		||||
    #    |        |--------------------------------|
 | 
			
		||||
    #    |        |       CommandSpace2            |
 | 
			
		||||
    #    -------------------------------------------
 | 
			
		||||
    #    |     MiscSpace                           |
 | 
			
		||||
    #    -------------------------------------------
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    # Uncomment the next line if you want to always start with this layout.
 | 
			
		||||
    # Otherwise, modifications to the layout applied by the user layout will be remembered.
 | 
			
		||||
    # runner_params.docking_params.layout_condition = hello_imgui.DockingLayoutCondition.ApplicationStart
 | 
			
		||||
 | 
			
		||||
    # Then, add a space named "MiscSpace" whose height is 25% of the app height.
 | 
			
		||||
    # This will split the preexisting default dockspace "MainDockSpace" in two parts.
 | 
			
		||||
    split_main_misc = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_misc.initial_dock = "MainDockSpace"
 | 
			
		||||
    split_main_misc.new_dock = "MiscSpace"
 | 
			
		||||
    split_main_misc.direction = imgui.Dir.down
 | 
			
		||||
    split_main_misc.ratio = 0.25
 | 
			
		||||
 | 
			
		||||
    # Then, add a space to the left which occupies a column whose width is 25% of the app width
 | 
			
		||||
    split_main_command = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_command.initial_dock = "MainDockSpace"
 | 
			
		||||
    split_main_command.new_dock = "CommandSpace"
 | 
			
		||||
    split_main_command.direction = imgui.Dir.left
 | 
			
		||||
    split_main_command.ratio = 0.25
 | 
			
		||||
 | 
			
		||||
    # Then, add CommandSpace2 below MainDockSpace
 | 
			
		||||
    split_main_command2 = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_command2.initial_dock = "MainDockSpace"
 | 
			
		||||
    split_main_command2.new_dock = "CommandSpace2"
 | 
			
		||||
    split_main_command2.direction = imgui.Dir.down
 | 
			
		||||
    split_main_command2.ratio = 0.5
 | 
			
		||||
 | 
			
		||||
    splits = [split_main_misc, split_main_command, split_main_command2]
 | 
			
		||||
    return splits
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_alternative_docking_splits() -> List[hello_imgui.DockingSplit]:
 | 
			
		||||
    # Define alternative docking splits for the "Alternative Layout"
 | 
			
		||||
    #    ___________________________________________
 | 
			
		||||
    #    |                |                        |
 | 
			
		||||
    #    | Misc           |                        |
 | 
			
		||||
    #    | Space          |    MainDockSpace       |
 | 
			
		||||
    #    |                |                        |
 | 
			
		||||
    #    -------------------------------------------
 | 
			
		||||
    #    |                       |                 |
 | 
			
		||||
    #    |                       | Command         |
 | 
			
		||||
    #    |     CommandSpace      | Space2          |
 | 
			
		||||
    #    -------------------------------------------
 | 
			
		||||
 | 
			
		||||
    split_main_command = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_command.initial_dock = "MainDockSpace"
 | 
			
		||||
    split_main_command.new_dock = "CommandSpace"
 | 
			
		||||
    split_main_command.direction = imgui.Dir.down
 | 
			
		||||
    split_main_command.ratio = 0.5
 | 
			
		||||
 | 
			
		||||
    split_main_command2 = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_command2.initial_dock = "CommandSpace"
 | 
			
		||||
    split_main_command2.new_dock = "CommandSpace2"
 | 
			
		||||
    split_main_command2.direction = imgui.Dir.right
 | 
			
		||||
    split_main_command2.ratio = 0.4
 | 
			
		||||
 | 
			
		||||
    split_main_misc = hello_imgui.DockingSplit()
 | 
			
		||||
    split_main_misc.initial_dock = "MainDockSpace"
 | 
			
		||||
    split_main_misc.new_dock = "MiscSpace"
 | 
			
		||||
    split_main_misc.direction = imgui.Dir.left
 | 
			
		||||
    split_main_misc.ratio = 0.5
 | 
			
		||||
 | 
			
		||||
    splits = [split_main_command, split_main_command2, split_main_misc]
 | 
			
		||||
    return splits
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# 2. Define the Dockable windows
 | 
			
		||||
#
 | 
			
		||||
def create_dockable_windows(app_state: AppState) -> List[hello_imgui.DockableWindow]:
 | 
			
		||||
    # A features demo window named "FeaturesDemo" will be placed in "CommandSpace".
 | 
			
		||||
    # Its Gui is provided by "gui_window_demo_features"
 | 
			
		||||
    features_demo_window = hello_imgui.DockableWindow()
 | 
			
		||||
    features_demo_window.label = "Features Demo"
 | 
			
		||||
    features_demo_window.dock_space_name = "CommandSpace"
 | 
			
		||||
    features_demo_window.gui_function = lambda: gui_window_demo_features(app_state)
 | 
			
		||||
 | 
			
		||||
    # A layout customization window will be placed in "MainDockSpace".
 | 
			
		||||
    # Its Gui is provided by "gui_window_layout_customization"
 | 
			
		||||
    layout_customization_window = hello_imgui.DockableWindow()
 | 
			
		||||
    layout_customization_window.label = "Layout customization"
 | 
			
		||||
    layout_customization_window.dock_space_name = "MainDockSpace"
 | 
			
		||||
    layout_customization_window.gui_function = lambda: gui_window_layout_customization(app_state)
 | 
			
		||||
 | 
			
		||||
    # A Log window named "Logs" will be placed in "MiscSpace". It uses the HelloImGui logger gui
 | 
			
		||||
    logs_window = hello_imgui.DockableWindow()
 | 
			
		||||
    logs_window.label = "Logs"
 | 
			
		||||
    logs_window.dock_space_name = "MiscSpace"
 | 
			
		||||
    logs_window.gui_function = hello_imgui.log_gui
 | 
			
		||||
 | 
			
		||||
    # A Window named "Dear ImGui Demo" will be placed in "MainDockSpace"
 | 
			
		||||
    dear_imgui_demo_window = hello_imgui.DockableWindow()
 | 
			
		||||
    dear_imgui_demo_window.label = "Dear ImGui Demo"
 | 
			
		||||
    dear_imgui_demo_window.dock_space_name = "MainDockSpace"
 | 
			
		||||
    dear_imgui_demo_window.imgui_window_flags = imgui.WindowFlags_.menu_bar.value
 | 
			
		||||
    dear_imgui_demo_window.gui_function = imgui.show_demo_window  # type: ignore
 | 
			
		||||
 | 
			
		||||
    # alternativeThemeWindow
 | 
			
		||||
    alternative_theme_window = hello_imgui.DockableWindow()
 | 
			
		||||
    # Since this window applies a theme, We need to call "imgui.begin" ourselves so
 | 
			
		||||
    # that we can apply the theme before opening the window.
 | 
			
		||||
    alternative_theme_window.call_begin_end = False
 | 
			
		||||
    alternative_theme_window.label = "Alternative Theme"
 | 
			
		||||
    alternative_theme_window.dock_space_name = "CommandSpace2"
 | 
			
		||||
    alternative_theme_window.gui_function = lambda: gui_window_alternative_theme(app_state)
 | 
			
		||||
 | 
			
		||||
    dockable_windows = [
 | 
			
		||||
        features_demo_window,
 | 
			
		||||
        layout_customization_window,
 | 
			
		||||
        logs_window,
 | 
			
		||||
        dear_imgui_demo_window,
 | 
			
		||||
        alternative_theme_window,
 | 
			
		||||
    ]
 | 
			
		||||
    return dockable_windows
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# 3. Define the layouts:
 | 
			
		||||
# A layout is stored inside DockingParams, and stores the splits + the dockable windows.
 | 
			
		||||
# Here, we provide the default layout, and two alternative layouts.
 | 
			
		||||
def create_default_layout(app_state: AppState) -> hello_imgui.DockingParams:
 | 
			
		||||
    docking_params = hello_imgui.DockingParams()
 | 
			
		||||
    # By default, the layout name is already "Default"
 | 
			
		||||
    # docking_params.layout_name = "Default"
 | 
			
		||||
    docking_params.docking_splits = create_default_docking_splits()
 | 
			
		||||
    docking_params.dockable_windows = create_dockable_windows(app_state)
 | 
			
		||||
    return docking_params
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_alternative_layouts(app_state: AppState) -> List[hello_imgui.DockingParams]:
 | 
			
		||||
    alternative_layout = hello_imgui.DockingParams()
 | 
			
		||||
    alternative_layout.layout_name = "Alternative Layout"
 | 
			
		||||
    alternative_layout.docking_splits = create_alternative_docking_splits()
 | 
			
		||||
    alternative_layout.dockable_windows = create_dockable_windows(app_state)
 | 
			
		||||
 | 
			
		||||
    tabs_layout = hello_imgui.DockingParams()
 | 
			
		||||
    tabs_layout.layout_name = "Tabs Layout"
 | 
			
		||||
    tabs_layout.dockable_windows = create_dockable_windows(app_state)
 | 
			
		||||
    # Force all windows to be presented in the MainDockSpace
 | 
			
		||||
    for window in tabs_layout.dockable_windows:
 | 
			
		||||
        window.dock_space_name = "MainDockSpace"
 | 
			
		||||
    # In "Tabs Layout", no split is created
 | 
			
		||||
    tabs_layout.docking_splits = []
 | 
			
		||||
 | 
			
		||||
    return [alternative_layout, tabs_layout]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    Define the app initial theme
 | 
			
		||||
##########################################################################
 | 
			
		||||
def setup_my_theme():
 | 
			
		||||
    """Example of theme customization at App startup
 | 
			
		||||
    This function is called in the callback `setup_imgui_style` in order to apply a custom theme:
 | 
			
		||||
        runner_params.callbacks.setup_imgui_style = setup_my_theme()
 | 
			
		||||
    """
 | 
			
		||||
    # Apply default style
 | 
			
		||||
    hello_imgui.imgui_default_settings.setup_default_imgui_style()
 | 
			
		||||
    # Create a tweaked theme
 | 
			
		||||
    tweaked_theme = hello_imgui.ImGuiTweakedTheme()
 | 
			
		||||
    tweaked_theme.theme = hello_imgui.ImGuiTheme_.material_flat
 | 
			
		||||
    tweaked_theme.tweaks.rounding = 10.0
 | 
			
		||||
    # Apply the tweaked theme
 | 
			
		||||
    hello_imgui.apply_tweaked_theme(tweaked_theme)  # Note: you can also push/pop the theme in order to apply it only to a specific part of the Gui:  hello_imgui.push_tweaked_theme(tweaked_theme) / hello_imgui.pop_tweaked_theme()
 | 
			
		||||
    # Then apply further modifications to ImGui style
 | 
			
		||||
    imgui.get_style().item_spacing = ImVec2(6, 4)  # Reduce spacing between items ((8, 4) by default)
 | 
			
		||||
    imgui.get_style().set_color_(imgui.Col_.text.value, (0.8, 0.8, 0.85, 1.0))  # Change text color
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##########################################################################
 | 
			
		||||
#    main(): here, we simply fill RunnerParams, then run the application
 | 
			
		||||
##########################################################################
 | 
			
		||||
def main():
 | 
			
		||||
    # By default, an assets folder is installed via pip inside site-packages/lg_imgui_bundle/assets
 | 
			
		||||
    # and provides two fonts (fonts/DroidSans.ttf and fonts/fontawesome-webfont.ttf)
 | 
			
		||||
    # If you need to add more assets, make a copy of this assets folder and add your own files,
 | 
			
		||||
    # and call set_assets_folder
 | 
			
		||||
    hello_imgui.set_assets_folder(demo_utils.demos_assets_folder())
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Part 1: Define the application state, fill the status and menu bars, and load additional font
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    # Our application state
 | 
			
		||||
    app_state = AppState()
 | 
			
		||||
 | 
			
		||||
    # Hello ImGui params (they hold the settings as well as the Gui callbacks)
 | 
			
		||||
    runner_params = hello_imgui.RunnerParams()
 | 
			
		||||
    runner_params.app_window_params.window_title = "Docking Demo"
 | 
			
		||||
    runner_params.imgui_window_params.menu_app_title = "Docking Demo"
 | 
			
		||||
    runner_params.app_window_params.window_geometry.size = (1000, 900)
 | 
			
		||||
    runner_params.app_window_params.restore_previous_geometry = True
 | 
			
		||||
    runner_params.app_window_params.borderless = True
 | 
			
		||||
    runner_params.app_window_params.borderless_movable = True
 | 
			
		||||
    runner_params.app_window_params.borderless_resizable = True
 | 
			
		||||
    runner_params.app_window_params.borderless_closable = True
 | 
			
		||||
 | 
			
		||||
    # Set LoadAdditionalFonts callback
 | 
			
		||||
    runner_params.callbacks.load_additional_fonts = lambda: load_fonts(app_state)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Status bar
 | 
			
		||||
    #
 | 
			
		||||
    # We use the default status bar of Hello ImGui
 | 
			
		||||
    runner_params.imgui_window_params.show_status_bar = True
 | 
			
		||||
    # Add custom widgets in the status bar
 | 
			
		||||
    runner_params.callbacks.show_status = lambda: status_bar_gui(app_state)
 | 
			
		||||
    # uncomment next line in order to hide the FPS in the status bar
 | 
			
		||||
    # runner_params.im_gui_window_params.show_status_fps = False
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Menu bar
 | 
			
		||||
    #
 | 
			
		||||
    # Here, we fully customize the menu bar:
 | 
			
		||||
    # by setting `show_menu_bar` to True, and `show_menu_app` and `show_menu_view` to False,
 | 
			
		||||
    # HelloImGui will display an empty menu bar, which we can fill with our own menu items via the callback `show_menus`
 | 
			
		||||
    runner_params.imgui_window_params.show_menu_bar = True
 | 
			
		||||
    runner_params.imgui_window_params.show_menu_app = False
 | 
			
		||||
    runner_params.imgui_window_params.show_menu_view = False
 | 
			
		||||
    # Inside `show_menus`, we can call `hello_imgui.show_view_menu` and `hello_imgui.show_app_menu` if desired
 | 
			
		||||
    runner_params.callbacks.show_menus = lambda: show_menu_gui(runner_params)
 | 
			
		||||
    # Optional: add items to Hello ImGui default App menu
 | 
			
		||||
    runner_params.callbacks.show_app_menu_items = show_app_menu_items
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Top and bottom toolbars
 | 
			
		||||
    #
 | 
			
		||||
    # toolbar options
 | 
			
		||||
    edge_toolbar_options = hello_imgui.EdgeToolbarOptions()
 | 
			
		||||
    edge_toolbar_options.size_em = 2.5
 | 
			
		||||
    edge_toolbar_options.window_bg = ImVec4(0.8, 0.8, 0.8, 0.35)
 | 
			
		||||
    # top toolbar
 | 
			
		||||
    runner_params.callbacks.add_edge_toolbar(
 | 
			
		||||
        hello_imgui.EdgeToolbarType.top,
 | 
			
		||||
        lambda: show_top_toolbar(app_state),
 | 
			
		||||
        edge_toolbar_options,
 | 
			
		||||
    )
 | 
			
		||||
    # right toolbar
 | 
			
		||||
    edge_toolbar_options.window_bg.w = 0.4
 | 
			
		||||
    runner_params.callbacks.add_edge_toolbar(
 | 
			
		||||
        hello_imgui.EdgeToolbarType.right,
 | 
			
		||||
        lambda: show_right_toolbar(app_state),
 | 
			
		||||
        edge_toolbar_options,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Load user settings at callbacks `post_init` and save them at `before_exit`
 | 
			
		||||
    #
 | 
			
		||||
    runner_params.callbacks.post_init = lambda: load_my_app_settings(app_state)
 | 
			
		||||
    runner_params.callbacks.before_exit = lambda: save_my_app_settings(app_state)
 | 
			
		||||
 | 
			
		||||
    # Change style
 | 
			
		||||
    runner_params.callbacks.setup_imgui_style = setup_my_theme
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Part 2: Define the application layout and windows
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
    # First, tell HelloImGui that we want full screen dock space (this will create "MainDockSpace")
 | 
			
		||||
    runner_params.imgui_window_params.default_imgui_window_type = (
 | 
			
		||||
        hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
 | 
			
		||||
    )
 | 
			
		||||
    # In this demo, we also demonstrate multiple viewports: you can drag windows outside
 | 
			
		||||
    # out the main window in order to put their content into new native windows
 | 
			
		||||
    runner_params.imgui_window_params.enable_viewports = True
 | 
			
		||||
    # Set the default layout (this contains the default DockingSplits and DockableWindows)
 | 
			
		||||
    runner_params.docking_params = create_default_layout(app_state)
 | 
			
		||||
    # Add alternative layouts
 | 
			
		||||
    runner_params.alternative_docking_layouts = create_alternative_layouts(app_state)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Part 3: Where to save the app settings
 | 
			
		||||
    #
 | 
			
		||||
    # tag::app_settings[]
 | 
			
		||||
    # By default, HelloImGui will save the settings in the current folder.
 | 
			
		||||
    # This is convenient when developing, but not so much when deploying the app.
 | 
			
		||||
    # You can tell HelloImGui to save the settings in a specific folder: choose between
 | 
			
		||||
    #         current_folder
 | 
			
		||||
    #         app_user_config_folder
 | 
			
		||||
    #         app_executable_folder
 | 
			
		||||
    #         home_folder
 | 
			
		||||
    #         temp_folder
 | 
			
		||||
    #         documents_folder
 | 
			
		||||
    #
 | 
			
		||||
    # Note: app_user_config_folder is:
 | 
			
		||||
    #         AppData under Windows (Example: C:\Users\[Username]\AppData\Roaming)
 | 
			
		||||
    #         ~/.config under Linux
 | 
			
		||||
    #         "~/Library/Application Support" under macOS or iOS
 | 
			
		||||
    runner_params.ini_folder_type = hello_imgui.IniFolderType.app_user_config_folder
 | 
			
		||||
 | 
			
		||||
    # runnerParams.ini_filename: this will be the name of the ini file in which the settings
 | 
			
		||||
    # will be stored.
 | 
			
		||||
    # In this example, the subdirectory Docking_Demo will be created under the folder defined
 | 
			
		||||
    # by runnerParams.ini_folder_type.
 | 
			
		||||
    #
 | 
			
		||||
    # Note: if ini_filename is left empty, the name of the ini file will be derived
 | 
			
		||||
    # from app_window_params.window_title
 | 
			
		||||
    runner_params.ini_filename = "Docking_Demo/Docking_demo.ini"
 | 
			
		||||
    # end::app_settings[]
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Part 4: Run the app
 | 
			
		||||
    #
 | 
			
		||||
    hello_imgui.run(runner_params)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										66
									
								
								gui.py
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								gui.py
									
									
									
									
									
								
							@@ -1,54 +1,24 @@
 | 
			
		||||
import imgui
 | 
			
		||||
from imgui_bundle import imgui, immapp
 | 
			
		||||
import glfw
 | 
			
		||||
import OpenGL.GL as gl
 | 
			
		||||
from imgui.integrations.glfw import GlfwRenderer
 | 
			
		||||
from datatypes import *
 | 
			
		||||
from view import View
 | 
			
		||||
 | 
			
		||||
def impl_glfw_init(window_name="Grapher Tool", width=1280, height=720):
 | 
			
		||||
    if not glfw.init():
 | 
			
		||||
        print("Could not initialize OpenGL context")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    # OS X supports only forward-compatible core profiles from 3.2
 | 
			
		||||
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
 | 
			
		||||
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
 | 
			
		||||
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
 | 
			
		||||
 | 
			
		||||
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, gl.GL_TRUE)
 | 
			
		||||
 | 
			
		||||
    # Create a windowed mode window and its OpenGL context
 | 
			
		||||
    window = glfw.create_window(int(width), int(height), window_name, None, None)
 | 
			
		||||
    glfw.make_context_current(window)
 | 
			
		||||
 | 
			
		||||
    if not window:
 | 
			
		||||
        glfw.terminate()
 | 
			
		||||
        print("Could not initialize Window")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    return window
 | 
			
		||||
 | 
			
		||||
class GUI(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__() 
 | 
			
		||||
    
 | 
			
		||||
        # Window States
 | 
			
		||||
        self.window = impl_glfw_init()
 | 
			
		||||
        gl.glClearColor(*COLOR_BACKGROUND)
 | 
			
		||||
        imgui.create_context()
 | 
			
		||||
        self.impl = GlfwRenderer(self.window)
 | 
			
		||||
        self.io = imgui.get_io()
 | 
			
		||||
        #        self.io = imgui.get_io()
 | 
			
		||||
 | 
			
		||||
        # Global GUI Setting
 | 
			
		||||
        win_w, win_h = glfw.get_window_size(self.window)
 | 
			
		||||
        '''win_w, win_h = glfw.get_window_size(self.window)
 | 
			
		||||
        fb_w, fb_h = glfw.get_framebuffer_size(self.window)
 | 
			
		||||
        font_scaling_factor = max(float(fb_w) / win_w, float(fb_h) / win_h) 
 | 
			
		||||
        font_size_in_pixels = 30
 | 
			
		||||
        self.io.fonts.add_font_from_file_ttf("assets/MPLUSRounded1c-Regular.ttf", font_size_in_pixels * font_scaling_factor)
 | 
			
		||||
        self.io.font_global_scale /= font_scaling_factor
 | 
			
		||||
        self.io.font_global_scale /= font_scaling_factor'''
 | 
			
		||||
 | 
			
		||||
        self.view = View()
 | 
			
		||||
        self.loop()
 | 
			
		||||
    
 | 
			
		||||
    def header(self):
 | 
			
		||||
        imgui.set_next_window_size(io.display_size.x, io.display_size.y*0.03)
 | 
			
		||||
@@ -62,28 +32,16 @@ class GUI(object):
 | 
			
		||||
            imgui.set_cursor_pos_x((ww - tw) * 0.5)
 | 
			
		||||
            imgui.text("Student Analyzer")
 | 
			
		||||
 
 | 
			
		||||
    def loop(self):
 | 
			
		||||
        while not glfw.window_should_close(self.window):
 | 
			
		||||
            glfw.poll_events()
 | 
			
		||||
            self.impl.process_inputs()
 | 
			
		||||
            imgui.new_frame()
 | 
			
		||||
            
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
            self.view()
 | 
			
		||||
 | 
			
		||||
            #imgui.show_test_window()
 | 
			
		||||
 | 
			
		||||
            imgui.render()
 | 
			
		||||
 | 
			
		||||
            gl.glClearColor(*COLOR_BACKGROUND)
 | 
			
		||||
            gl.glClear(gl.GL_COLOR_BUFFER_BIT)
 | 
			
		||||
 | 
			
		||||
            self.impl.render(imgui.get_draw_data())
 | 
			
		||||
            glfw.swap_buffers(self.window)
 | 
			
		||||
 | 
			
		||||
        self.impl.shutdown()
 | 
			
		||||
        glfw.terminate()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
 | 
			
		||||
    gui = GUI()
 | 
			
		||||
    immapp.run(
 | 
			
		||||
        gui_function=GUI(),
 | 
			
		||||
        window_title="Student Analyzer",
 | 
			
		||||
        window_size_auto=True,
 | 
			
		||||
        with_implot=True,
 | 
			
		||||
        with_markdown=True
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import imgui
 | 
			
		||||
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
from datatypes import *
 | 
			
		||||
 | 
			
		||||
from model import *
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								main_menu.py
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								main_menu.py
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
import imgui
 | 
			
		||||
from imgui_bundle import imgui, imgui_ctx
 | 
			
		||||
 | 
			
		||||
from datatypes import *
 | 
			
		||||
 | 
			
		||||
@@ -13,23 +13,23 @@ class MainMenu:
 | 
			
		||||
        if self.new:
 | 
			
		||||
            self.create_new_file()
 | 
			
		||||
 | 
			
		||||
        with imgui.begin_main_menu_bar() as main_menu_bar:
 | 
			
		||||
        with imgui_ctx.begin_main_menu_bar() as main_menu_bar:
 | 
			
		||||
            if main_menu_bar:
 | 
			
		||||
                with imgui.begin_menu("File", True) as file_menu:
 | 
			
		||||
                    if file_menu.opened:
 | 
			
		||||
                with imgui_ctx.begin_menu("File", True) as file_menu:
 | 
			
		||||
                    if file_menu.visible:
 | 
			
		||||
                        new, _ = imgui.menu_item("New", " ", False, True)
 | 
			
		||||
                        if new:
 | 
			
		||||
                            self.new = True
 | 
			
		||||
                        imgui.menu_item("Open", " ", False, True)
 | 
			
		||||
                        imgui.menu_item("Save", " ", False, True)
 | 
			
		||||
                        imgui.menu_item("Save as", " ", False, True)
 | 
			
		||||
                with imgui.begin_menu("View", True) as view_menu:
 | 
			
		||||
                    if view_menu.opened:
 | 
			
		||||
                        with imgui.begin_menu("Change Layout", True) as open_layout_menu:
 | 
			
		||||
                            if open_layout_menu.opened:
 | 
			
		||||
                with imgui_ctx.begin_menu("View", True) as view_menu:
 | 
			
		||||
                    if view_menu.visible:
 | 
			
		||||
                        with imgui_ctx.begin_menu("Change Layout", True) as open_layout_menu:
 | 
			
		||||
                            if open_layout_menu.visible:
 | 
			
		||||
                                layout_options = list(LayoutOptions)
 | 
			
		||||
                                for n, l in enumerate(layout_options):
 | 
			
		||||
                                    clicked, _ = imgui.menu_item(l.name.title(), None, False, True)
 | 
			
		||||
                                    clicked = imgui.menu_item_simple(l.name.title())
 | 
			
		||||
                                    if clicked:
 | 
			
		||||
                                        return l
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import imgui
 | 
			
		||||
 | 
			
		||||
from model import *
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
 | 
			
		||||
class StudentEditor:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import imgui
 | 
			
		||||
import numpy as np
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
import random
 | 
			
		||||
 | 
			
		||||
from datatypes import *
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								student_info.py
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								student_info.py
									
									
									
									
									
								
							@@ -1,60 +1,77 @@
 | 
			
		||||
import imgui
 | 
			
		||||
from datatypes import *
 | 
			
		||||
from imgui_bundle import imgui, imgui_ctx, imgui_md, implot, ImVec2
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
from model import *
 | 
			
		||||
 | 
			
		||||
class StudentInfo:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.select_class = 0
 | 
			
		||||
        self.select_student = 0
 | 
			
		||||
 | 
			
		||||
    def __call__(self, student: Student):
 | 
			
		||||
        submissions = Submission.select().where(Submission.student_id == student.id) if student else None
 | 
			
		||||
    def student_graph(self, student_id: int) -> None:
 | 
			
		||||
        student = Student.get_by_id(student_id)
 | 
			
		||||
        clas = Class.get_by_id(student.class_id)
 | 
			
		||||
        lectures = Lecture.select().where(Lecture.class_id == clas.id)
 | 
			
		||||
        submissions = Submission.select().where(Submission.student_id == student.id)
 | 
			
		||||
        
 | 
			
		||||
        with imgui.begin("Student Info", False, imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_COLLAPSE):
 | 
			
		||||
            if not student:
 | 
			
		||||
                imgui.text("No Student selected")
 | 
			
		||||
                return
 | 
			
		||||
             
 | 
			
		||||
            w, h = imgui.get_window_size()
 | 
			
		||||
            imgui.text_colored(f"{student.prename} {student.surname}", *COLOR_TEXT)
 | 
			
		||||
            
 | 
			
		||||
            content = Class.get_by_id(student.class_id).name
 | 
			
		||||
            text_size = imgui.calc_text_size(content)
 | 
			
		||||
            imgui.same_line(position=w-1.5*text_size.x)
 | 
			
		||||
            imgui.text(content)
 | 
			
		||||
 | 
			
		||||
            if submissions:
 | 
			
		||||
                overall_points = sum([s.points for s in submissions])
 | 
			
		||||
                if overall_points.is_integer():
 | 
			
		||||
                    overall_points = int(overall_points)
 | 
			
		||||
                overall_max = sum([lectures.points for lectures in [Lecture.get_by_id(s.lecture_id) for s in submissions]])
 | 
			
		||||
                percentile = overall_points / overall_max
 | 
			
		||||
                imgui.progress_bar(percentile, (w*0.5, h*0.05), f"{overall_points}/{overall_max} {percentile:.1%}")
 | 
			
		||||
            
 | 
			
		||||
            content = "Delete"
 | 
			
		||||
            if submissions:
 | 
			
		||||
                text_size = imgui.calc_text_size(content)
 | 
			
		||||
                imgui.same_line(position=w-2*text_size.x)
 | 
			
		||||
            if imgui.button(content):
 | 
			
		||||
                # Delete all Submissions related to that Student
 | 
			
		||||
                #for submission in submissions:
 | 
			
		||||
                #    submission.delete().execute()
 | 
			
		||||
                # Delete Student
 | 
			
		||||
                #student.delete().execute()
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
            imgui.separator()
 | 
			
		||||
 | 
			
		||||
            if not submissions:
 | 
			
		||||
                 imgui.text("No Submission for this Student")
 | 
			
		||||
 | 
			
		||||
            for n, submission in enumerate(submissions, start=1):
 | 
			
		||||
                lecture = Lecture.get_by_id(submission.lecture_id)
 | 
			
		||||
                
 | 
			
		||||
                points = submission.points
 | 
			
		||||
        overall_points = np.sum([l.points for l in lectures])
 | 
			
		||||
        points = np.sum([sub.points for sub in submissions])
 | 
			
		||||
        if points.is_integer():
 | 
			
		||||
            points = int(points)
 | 
			
		||||
 | 
			
		||||
                display = f"{n}. {lecture.title} {points}/{lecture.points}"
 | 
			
		||||
                COLOR = COLOR_TEXT_PASSED if points > lecture.points*0.3 else COLOR_TEXT_FAILED
 | 
			
		||||
                imgui.text_colored(display, *COLOR) 
 | 
			
		||||
        subs_data = np.array([sub.points/l.points for sub, l in zip(submissions, lectures)])*100
 | 
			
		||||
        subs_labels = [str(l.title) for l in lectures]
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_group():
 | 
			
		||||
            imgui_md.render(f"# {student.prename} {student.surname}")
 | 
			
		||||
            imgui_md.render(f"### {clas.name}")
 | 
			
		||||
 | 
			
		||||
            pb_content = f"{points}/{overall_points} {points/overall_points:.1%}"
 | 
			
		||||
            imgui.progress_bar(points/overall_points, overlay=pb_content)
 | 
			
		||||
                
 | 
			
		||||
            implot.push_colormap(implot.Colormap_.deep.value)
 | 
			
		||||
            if implot.begin_plot("Performance"):
 | 
			
		||||
                implot.setup_axes("Lectures", "Percentage")
 | 
			
		||||
                implot.setup_axes_limits(-1, len(subs_data), 0, 110)
 | 
			
		||||
                implot.setup_axis_ticks(implot.ImAxis_.x1.value, 0, len(subs_labels), len(subs_labels), subs_labels, False)
 | 
			
		||||
                implot.plot_bars("Submissions", subs_data)
 | 
			
		||||
                implot.end_plot()
 | 
			
		||||
 | 
			
		||||
    def student_list(self) -> int:
 | 
			
		||||
        classes = Class.select()
 | 
			
		||||
        content = [f"{n}. {c.name}" for n, c in enumerate(classes, start=1)]
 | 
			
		||||
        students = Student.select().where(Student.class_id == classes[self.select_class].id)
 | 
			
		||||
        lectures = Lecture.select().where(Lecture.class_id == classes[self.select_class].id)
 | 
			
		||||
 | 
			
		||||
        overall_points = np.sum([l.points for l in lectures])
 | 
			
		||||
        points = list()
 | 
			
		||||
        for student in students:
 | 
			
		||||
            submissions = Submission.select().where(Submission.student_id == student.id)
 | 
			
		||||
            cummultative = [sub.points for sub in submissions]
 | 
			
		||||
            passed = np.sum([p > overall_points*0.3 for p in cummultative])
 | 
			
		||||
            points.append((student, np.sum(cummultative)/overall_points, passed > 1))
 | 
			
		||||
 | 
			
		||||
        students = sorted(points, key=lambda x: x[1], reverse=True)
 | 
			
		||||
 | 
			
		||||
        with imgui_ctx.begin_group():
 | 
			
		||||
            _, self.select_class = imgui.combo("##class_list", self.select_class, content, len(content))
 | 
			
		||||
            for n, student in enumerate(students, start=1):
 | 
			
		||||
                s = student[0]
 | 
			
		||||
                display = f"{n}. {s.prename} {s.surname}"
 | 
			
		||||
                _, clicked = imgui.selectable(display, self.select_student == n-1)
 | 
			
		||||
                if clicked:
 | 
			
		||||
                    self.select_student = n-1
 | 
			
		||||
 | 
			
		||||
        return students[self.select_student][0].id
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        with imgui_ctx.begin("Student Info"):
 | 
			
		||||
            w, h = imgui.get_window_size()
 | 
			
		||||
            with imgui_ctx.begin_child("Student Selector", ImVec2(w*0.25, h*0.9)):
 | 
			
		||||
                id = self.student_list()
 | 
			
		||||
            imgui.same_line()
 | 
			
		||||
            with imgui_ctx.begin_child("Student Graph", ImVec2(w*0.7, h*0.9)):
 | 
			
		||||
                self.student_graph(id)
 | 
			
		||||
           
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import imgui
 | 
			
		||||
 | 
			
		||||
from model import *
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
 | 
			
		||||
class StudentList:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import imgui
 | 
			
		||||
import numpy as np
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
 | 
			
		||||
from model import *
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import imgui
 | 
			
		||||
 | 
			
		||||
from imgui_bundle import imgui
 | 
			
		||||
from model import *
 | 
			
		||||
 | 
			
		||||
class SubmissionEditor:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								view.py
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								view.py
									
									
									
									
									
								
							@@ -1,84 +1,58 @@
 | 
			
		||||
import imgui
 | 
			
		||||
from imgui_bundle import imgui, ImVec2
 | 
			
		||||
 | 
			
		||||
from datatypes import *
 | 
			
		||||
 | 
			
		||||
from main_menu import MainMenu
 | 
			
		||||
 | 
			
		||||
from student_editor import StudentEditor
 | 
			
		||||
from student_list import StudentList
 | 
			
		||||
from student_info import StudentInfo
 | 
			
		||||
from class_editor import ClassEditor
 | 
			
		||||
from lecture_editor import LectureEditor
 | 
			
		||||
from submission_editor import SubmissionEditor
 | 
			
		||||
from database_editor import DatabaseEditor
 | 
			
		||||
 | 
			
		||||
from student_graph import StudentGraph
 | 
			
		||||
from student_ranking import StudentRanking
 | 
			
		||||
from student_info import StudentInfo
 | 
			
		||||
 | 
			
		||||
def set_layout(size: tuple, pos: tuple) -> None:
 | 
			
		||||
    io = imgui.get_io()
 | 
			
		||||
    imgui.set_next_window_size(
 | 
			
		||||
        io.display_size.x*size[0],
 | 
			
		||||
        io.display_size.y*size[1]
 | 
			
		||||
    )
 | 
			
		||||
    imgui.set_next_window_position(
 | 
			
		||||
        io.display_size.x*pos[0],
 | 
			
		||||
        io.display_size.y*pos[1]
 | 
			
		||||
    )
 | 
			
		||||
    size = imgui.ImVec2(*size)
 | 
			
		||||
    pos = imgui.ImVec2(*pos)
 | 
			
		||||
    imgui.set_next_window_size(size)
 | 
			
		||||
    imgui.set_next_window_pos(pos)
 | 
			
		||||
 | 
			
		||||
class GrapherLayout:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
 | 
			
		||||
        self.student_graph = StudentGraph()
 | 
			
		||||
        self.student_ranking = StudentRanking()
 | 
			
		||||
        self.student_info = StudentInfo()
 | 
			
		||||
 | 
			
		||||
    def set_layout(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        set_layout((1, 0.4), (0, 0.02))
 | 
			
		||||
        self.student_graph()
 | 
			
		||||
 | 
			
		||||
        set_layout((0.3, 0.6), (0, 0.42))
 | 
			
		||||
        self.student_ranking()
 | 
			
		||||
        self.student_info()
 | 
			
		||||
 | 
			
		||||
class EditorLayout:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.io = imgui.get_io()
 | 
			
		||||
        self.database_editor = DatabaseEditor()
 | 
			
		||||
 | 
			
		||||
        self.student_editor = StudentEditor()
 | 
			
		||||
        self.student_list = StudentList()
 | 
			
		||||
        self.student_info = StudentInfo()
 | 
			
		||||
        self.class_editor = ClassEditor()
 | 
			
		||||
        self.lecture_editor = LectureEditor()
 | 
			
		||||
        self.submission_editor = SubmissionEditor()
 | 
			
		||||
    def set_layout(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        set_layout((0.3, 0.3), (0.7, 0.4))
 | 
			
		||||
        clas = self.class_editor()
 | 
			
		||||
        
 | 
			
		||||
        set_layout((0.5, 0.3), (0.2, 0.4))
 | 
			
		||||
        self.student_editor()
 | 
			
		||||
 | 
			
		||||
        set_layout((0.2, 0.98), (0, 0.02))
 | 
			
		||||
        student = self.student_list(clas)
 | 
			
		||||
 | 
			
		||||
        set_layout((0.3, 0.38), (0.7, 0.02))
 | 
			
		||||
        self.student_info(student)
 | 
			
		||||
 | 
			
		||||
        set_layout((0.5, 0.3), (0.2, 0.7))
 | 
			
		||||
        self.lecture_editor(clas)
 | 
			
		||||
    
 | 
			
		||||
        set_layout((0.5, 0.3), (0.2, 0.1))
 | 
			
		||||
        self.submission_editor(clas)
 | 
			
		||||
        self.database_editor()
 | 
			
		||||
        
 | 
			
		||||
class View:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.io = imgui.get_io()
 | 
			
		||||
        self.current = LayoutOptions.GRAPHER
 | 
			
		||||
        self.main_menu = MainMenu()
 | 
			
		||||
        self.editor = EditorLayout()
 | 
			
		||||
        self.grapher = GrapherLayout()
 | 
			
		||||
 | 
			
		||||
    def switch_context(self, ctx: LayoutOptions) -> None:
 | 
			
		||||
        match ctx:
 | 
			
		||||
            case LayoutOptions.EDITOR:
 | 
			
		||||
                self.editor.set_layout()
 | 
			
		||||
            case LayoutOptions.GRAPHER:
 | 
			
		||||
                self.grapher.set_layout()
 | 
			
		||||
 | 
			
		||||
    def __call__(self):
 | 
			
		||||
        option = self.main_menu()
 | 
			
		||||
        if option:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user