SimpleExample/
demo.rs

1use rust_page_system::{
2    Button, Renderer,
3    misc::{center_elements::get_center, vec::GetOrCreate},
4    system::{
5        input_handler::InputHandler,
6        page_system::{Page, PageData, PersistentElements},
7        renderer::RendererConfig,
8        state::AppState,
9        window::{WindowConfig, create_window, get_monitor_refresh_rate}
10    }
11};
12use sdl3::{pixels::Color, rect::Rect, sys::render::SDL_LOGICAL_PRESENTATION_STRETCH};
13use std::{env, rc::Rc, time::Duration};
14
15// To Be Ignored, Just An Setup To Configure The Build
16use crate::build::setup_build;
17mod build;
18
19//==========================================================================================================================================================================
20//=======================================================================# main function recommended setup #===============================================================
21//==========================================================================================================================================================================
22fn main()
23{
24    // To Be Ignored, Just An Setup To Configure The Build
25    setup_build();
26    let window_config = WindowConfig {
27        window_title: "SimpleExample".to_string(),
28        icon: (None, None),
29        // Recommended to start with 16:9 aspect ratio
30        start_window_size: (800, 450),
31        // Recommended to have minimum size with 16:9 aspect ratio
32        window_minimum_size: (800, 450),
33        resizable: true,
34        centered: true,
35        // By Default SDL_LOGICAL_PRESENTATION_STRETCH Is Set, Only Setting It Here For Demonstration Purpose
36        different_sdl_presentation_mode: Some(SDL_LOGICAL_PRESENTATION_STRETCH),
37        font: ("JetBrainsMono".to_string(), Some("Bold".to_string()))
38    };
39
40    let mut window_modules = create_window(window_config);
41    let mut input_handler = InputHandler::new(true);
42    let mut app_state = AppState::new(PageId::Page1, window_modules.canvas.window().size(), window_modules.stretch_mode_status);
43    let mut page_data = PageData::new(&app_state);
44    let renderer_config = RendererConfig { canvas: window_modules.canvas, texture_creator: &window_modules.texture_creator, ttf_context: &window_modules.ttf_context, font_path: &window_modules.font_path, decrease_color_when_selected: Some((25, 25, 25)), selection_color: Some((0, 0, 200, 125)), assets_dir: None };
45    let mut renderer = Renderer::new(renderer_config);
46
47    populate_page_data(&mut page_data);
48
49    // Wrap the button_action function in a mutable closure so it can capture
50    // additional context if needed. Passing a closure here allows the
51    // button handler API to accept additional arguments beyond the default.
52    let mut button_action_closure = |app_state: &mut AppState<PageId, ButtonId>, button_id: &ButtonId, page_data: &mut PageData<PageId, ButtonId>| button_action(app_state, button_id, page_data);
53
54    loop
55    {
56        //using 900 / your_refresh_rate to a very crispy experience
57        std::thread::sleep(Duration::from_millis(900 / get_monitor_refresh_rate()));
58        app_state.update_window_size(renderer.canvas.window().size().0, renderer.canvas.window().size().1);
59        input_handler.handle_input(&mut window_modules.event_pump, &mut window_modules.clipboard_system, &mut page_data, &mut app_state, &mut button_action_closure);
60        page_data.create_current_page(&mut app_state);
61        renderer.render(&page_data, &mut app_state, &input_handler);
62    }
63}
64
65//==========================================================================================================================================================================
66//===============================================================# can be a different file, like: buttons_actions.rs #======================================================
67//==========================================================================================================================================================================
68pub fn button_action(app_state: &mut AppState<PageId, ButtonId>, button_id: &ButtonId, app_data: &mut PageData<PageId, ButtonId>)
69{
70    if !app_state.capturing_input.0
71    {
72        if &ButtonId::ButtonPage1 == button_id
73        {
74            app_state.change_current_page(app_data, PageId::Page1, button_id);
75            return;
76        };
77        if &ButtonId::ButtonSubPage == button_id
78        {
79            app_state.change_current_page(app_data, PageId::Page1SubPage, button_id);
80            return;
81        };
82        if &ButtonId::ButtonBack == button_id
83        {
84            println!("button back clicked");
85            app_state.change_current_page(app_data, PageId::Page1, button_id);
86            return;
87        };
88        // Non Handle Buttons Will Be Considered User Input Buttons
89        app_state.capturing_input = (true, Some(*button_id));
90    }
91}
92
93//==========================================================================================================================================================================
94//===============================================================# can be a different file, like: setup_page_data.rs #======================================================
95//==========================================================================================================================================================================
96pub fn populate_page_data(page_data: &mut PageData<PageId, ButtonId>)
97{
98    page_data.populate_rps_data(Some(vec![Rc::new(subpage_page1)]), Some(vec![Rc::new(|input: &mut Vec<String>| page_1(input, 13))]));
99}
100
101//==========================================================================================================================================================================
102//====================================================================# can be a different file, like: style.rs (or not even exist) #=======================================
103//==========================================================================================================================================================================
104pub const BACKGROUND_COLOR: Color = Color::RGB(30, 30, 46);
105pub const TEXT_COLOR: Color = Color::RGB(255, 255, 255);
106pub const SUBTEXT_COLOR: Color = Color::RGB(186, 194, 222);
107pub const PURPLE_COLOR: Color = Color::RGB(203, 166, 247);
108pub const PINK_COLOR: Color = Color::RGB(243, 139, 168);
109pub const ORANGE_COLOR: Color = Color::RGB(250, 179, 135);
110pub const BLACK_COLOR: Color = Color::RGB(17, 17, 27);
111pub const RED_COLOR: Color = Color::RGB(255, 0, 0);
112
113//==========================================================================================================================================================================
114//===============================================================# can be a different file, like: pages.rs #================================================================
115//==========================================================================================================================================================================
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117/// Defines The ID for your Pages
118pub enum PageId
119{
120    Persistent,
121    Page1,
122    Page1SubPage
123}
124#[derive(Eq, PartialEq, Clone, Copy, Debug)]
125#[repr(usize)]
126/// Defines The ID for your Buttons
127pub enum ButtonId
128{
129    ButtonPage1,
130    ButtonPurpleInputStartPage1,
131    ButtonSubPage,
132    ButtonBack
133}
134
135// Define Your Pages Here:
136pub fn persistent_elements(_string: String) -> PersistentElements<PageId, ButtonId>
137{
138    //"persistent_elements now can also receive extra args without affecting the functionality of the app"
139    // like the parsed = _string
140    //===================== rects =========================
141    let all_rects = vec![(BLACK_COLOR, (Rect::new(0, 0, 1920, 100), 0))];
142
143    //===================== texts =========================
144    let all_text = vec![(17.0, (825, 34), "This Is A Persistent Element".to_string(), TEXT_COLOR)];
145
146    //===================== images =========================
147    let all_images = vec![((10, 10), (50, 50), format!("{}/.cache/page_system/example_1.jpg", env::home_dir().unwrap().display()))];
148
149    //===================== page creation =========================
150    PersistentElements { id: PageId::Persistent, background_color: None, rects: Some(all_rects), buttons: None, texts: Some(all_text), images: Some(all_images) }
151}
152
153pub fn page_1(user_input: &mut Vec<String>, _int: i32) -> Page<PageId, ButtonId>
154{
155    //"pages now can also receive extra args without affecting the functionality of the app"
156    // like the parsed = _int
157    //===================== variables =========================
158    let purple_button_data = get_center((600, 100), (1920, 1080));
159    let subpage_button_data = get_center((235, 40), (1920, 1080));
160
161    //===================== buttons =========================
162    let all_buttons = vec![Button { enabled: true, color: PURPLE_COLOR, rect: Rect::new(subpage_button_data.pos_x, 150, subpage_button_data.w, subpage_button_data.h), radius: 20, id: ButtonId::ButtonSubPage, has_transition: None }, Button { enabled: true, color: PURPLE_COLOR, rect: Rect::new(purple_button_data.pos_x, purple_button_data.pos_y, purple_button_data.w, purple_button_data.h), radius: 5, id: ButtonId::ButtonPurpleInputStartPage1, has_transition: None }];
163
164    //===================== texts =========================
165    let all_text = vec![(18.0, (all_buttons[0].rect.x + 10, all_buttons[0].rect.y + 7), "Go To subpage_page1".to_string(), TEXT_COLOR), (18.0, (all_buttons[1].rect.x + 75, all_buttons[1].rect.y - 25), "Click the Button To Start Getting Input".to_string(), SUBTEXT_COLOR), (25.0, (all_buttons[1].rect.x + 15, all_buttons[1].rect.y + 35), user_input.get_or_create(0), BLACK_COLOR)];
166
167    //===================== page creation =========================
168    Page { has_userinput: Some(vec![(PageId::Page1, ButtonId::ButtonPurpleInputStartPage1)]), has_persistent_elements: Some(vec![(PageId::Persistent, Rc::new(|| persistent_elements("a".to_string())))]), id: PageId::Page1, background_color: Some(BACKGROUND_COLOR), rects: None, buttons: Some(all_buttons), texts: Some(all_text), images: None }
169}
170
171pub fn subpage_page1() -> Page<PageId, ButtonId>
172{
173    //===================== buttons =========================
174    let all_buttons = vec![Button { enabled: true, color: PINK_COLOR, rect: Rect::new(200, 0, 50, 150), radius: 0, id: ButtonId::ButtonBack, has_transition: None }];
175
176    //===================== texts =========================
177    let all_text = vec![(18.0, (all_buttons[0].rect.x + 10, all_buttons[0].rect.y + 7), "<-".to_string(), TEXT_COLOR)];
178
179    //===================== page creation =========================
180    Page { has_userinput: None, has_persistent_elements: None, id: PageId::Page1SubPage, background_color: Some(BACKGROUND_COLOR), rects: None, buttons: Some(all_buttons), texts: Some(all_text), images: None }
181}