Struct thyme::WindowBuilder

source ·
pub struct WindowBuilder<'a> { /* private fields */ }
Expand description

A WidgetBuilder specifically for creating windows.

Windows can have a titlebar, close button, move, and resizing capabilities. Each window is automatically part of its own render group and will automatically come on top of other widgets when clicked on. You can create a WindowBuilder from a WidgetBuilder by calling window after any calls to general purpose widget layout.

There is also a window method on Frame as a convenience for simple cases.

Once you are finished setting up the window, you call children to add children and add the widget to the frame.

Example

fn create_window(ui: &mut Frame, unique_id: &str) {
    ui.start("window")
    .window(unique_id)
    .title("My Window")
    .resizable(false)
    .children(|ui| {
        // window content here
    });
}

Theme definition

An example of a theme definition for a window:

  window:
    background: gui/window_bg
    wants_mouse: true
    layout: Vertical
    layout_spacing: [5, 5]
    border: { left: 5, right: 5, top: 35, bot: 5 }
    size: [300, 400]
    child_align: Top
    children:
      titlebar:
        wants_mouse: true
        background: gui/small_button
        size: [10, 30]
        pos: [-6, -36]
        border: { all: 5 }
        width_from: Parent
        child_align: Center
        align: TopLeft
        children:
          title:
            from: label
            text: "Main Window"
            font: medium
            width_from: Parent
          close:
            wants_mouse: true
            background: gui/small_button
            foreground: gui/close_icon
            size: [20, 20]
            border: { all: 4 }
            align: TopRight
      handle:
        wants_mouse: true
        background: gui/window_handle
        size: [12, 12]
        align: BotRight
        pos: [-1, -1]

Implementations§

source§

impl<'a> WindowBuilder<'a>

source

pub fn cancel_render_group(self) -> WindowBuilder<'a>

Specifies that this window will not use a new render group. This can be useful in some cases where you want to handle grouping yourself. See WidgetBuilder.new_render_group

source

pub fn with_titlebar(self, with_titlebar: bool) -> WindowBuilder<'a>

Specifies whether the created window should show a titlebar.

source

pub fn title<T: Into<String>>(self, title: T) -> WindowBuilder<'a>

Specify a title to show in the window’s titlebar, if it is present. If the titlebar is not present, does nothing. This will override any text set in the theme.

source

pub fn with_close_button(self, with_close_button: bool) -> WindowBuilder<'a>

Specifies whether the created window should have a close button.

Examples found in repository?
examples/demo.rs (line 221)
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
pub fn build_ui(ui: &mut Frame, party: &mut Party) {
    match party.theme_choice {
        ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
            // show a custom cursor.  it automatically inherits mouse presses in its state
            ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
        },
        ThemeChoice::NoImage => {
            // don't show a custom cursor
        }
    }

    ui.label("bench", format!(
        "{}\n{}\n{}",
        bench::short_report("thyme"),
        bench::short_report("frame"),
        bench::short_report("draw"),
    ));

    ui.start("theme_panel").children(|ui| {
        if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
            party.live_reload_disabled = !party.live_reload_disabled;
        }

        if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
            party.old_theme_choice = Some(party.theme_choice);
            party.theme_choice = *choice;
            party.reload_assets = true;
        }
    });

    ui.start("party_window")
    .window("party_window")
    .with_close_button(false)
    .moveable(false)
    .resizable(false)
    .children(|ui| {
        ui.scrollpane("members_panel", "party_content", |ui| {
            party_members_panel(ui, party);
        });
    });

    if let Some(index) = party.editing_index {
        let character = &mut party.members[index];

        ui.window("character_window", |ui| {
            ui.scrollpane("pane", "character_content", |ui| {
                ui.start("name_panel")
                .children(|ui| {
                    if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
                        character.name = new_name;
                    }
                });

                ui.gap(10.0);
                ui.label("age_label", format!("Age: {}", character.age.round() as u32));
                if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
                    character.age = age;
                }

                for stat in Stat::iter() {
                    let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
                    let key = format!("{:?}", stat);
                    ui.set_variable(key, value);
                }

                ui.scrollpane("description_panel", "description_pane", |ui| {
                    ui.text_area("description_box");
                });

                ui.gap(10.0);

                if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
                    character.race = *race;
                }
    
                ui.gap(10.0);
    
                ui.tree("stats_panel", "stats_panel", true,
                |ui| {
                    ui.child("title");
                },|ui| {
                    stats_panel(ui, character);
                });
                
                ui.gap(10.0);
    
                ui.tree("inventory_panel", "inventory_panel", true,
                |ui| {
                    ui.child("title");
                }, |ui| {
                    inventory_panel(ui, character);
                });
            });
        });

        ui.window("item_picker", |ui| {
            let display_size = ui.display_size();

            ui.start("greyed_out")
            .unclip()
            .unparent()
            .size(display_size.x, display_size.y)
            .screen_pos(0.0, 0.0).finish();

            item_picker(ui, character);
        });
    }
}
source

pub fn moveable(self, moveable: bool) -> WindowBuilder<'a>

Specifies whether the user should be able to move the created window by dragging the mouse. Note that if the titlebar is not shown, there will be no way to move the window regardless of this setting.

Examples found in repository?
examples/demo.rs (line 222)
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
pub fn build_ui(ui: &mut Frame, party: &mut Party) {
    match party.theme_choice {
        ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
            // show a custom cursor.  it automatically inherits mouse presses in its state
            ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
        },
        ThemeChoice::NoImage => {
            // don't show a custom cursor
        }
    }

    ui.label("bench", format!(
        "{}\n{}\n{}",
        bench::short_report("thyme"),
        bench::short_report("frame"),
        bench::short_report("draw"),
    ));

    ui.start("theme_panel").children(|ui| {
        if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
            party.live_reload_disabled = !party.live_reload_disabled;
        }

        if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
            party.old_theme_choice = Some(party.theme_choice);
            party.theme_choice = *choice;
            party.reload_assets = true;
        }
    });

    ui.start("party_window")
    .window("party_window")
    .with_close_button(false)
    .moveable(false)
    .resizable(false)
    .children(|ui| {
        ui.scrollpane("members_panel", "party_content", |ui| {
            party_members_panel(ui, party);
        });
    });

    if let Some(index) = party.editing_index {
        let character = &mut party.members[index];

        ui.window("character_window", |ui| {
            ui.scrollpane("pane", "character_content", |ui| {
                ui.start("name_panel")
                .children(|ui| {
                    if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
                        character.name = new_name;
                    }
                });

                ui.gap(10.0);
                ui.label("age_label", format!("Age: {}", character.age.round() as u32));
                if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
                    character.age = age;
                }

                for stat in Stat::iter() {
                    let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
                    let key = format!("{:?}", stat);
                    ui.set_variable(key, value);
                }

                ui.scrollpane("description_panel", "description_pane", |ui| {
                    ui.text_area("description_box");
                });

                ui.gap(10.0);

                if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
                    character.race = *race;
                }
    
                ui.gap(10.0);
    
                ui.tree("stats_panel", "stats_panel", true,
                |ui| {
                    ui.child("title");
                },|ui| {
                    stats_panel(ui, character);
                });
                
                ui.gap(10.0);
    
                ui.tree("inventory_panel", "inventory_panel", true,
                |ui| {
                    ui.child("title");
                }, |ui| {
                    inventory_panel(ui, character);
                });
            });
        });

        ui.window("item_picker", |ui| {
            let display_size = ui.display_size();

            ui.start("greyed_out")
            .unclip()
            .unparent()
            .size(display_size.x, display_size.y)
            .screen_pos(0.0, 0.0).finish();

            item_picker(ui, character);
        });
    }
}
source

pub fn resizable(self, resizable: bool) -> WindowBuilder<'a>

Specifies whether the user should be able to resize the created window. If false, the resize handle will not be shown.

Examples found in repository?
examples/demo.rs (line 223)
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
pub fn build_ui(ui: &mut Frame, party: &mut Party) {
    match party.theme_choice {
        ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
            // show a custom cursor.  it automatically inherits mouse presses in its state
            ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
        },
        ThemeChoice::NoImage => {
            // don't show a custom cursor
        }
    }

    ui.label("bench", format!(
        "{}\n{}\n{}",
        bench::short_report("thyme"),
        bench::short_report("frame"),
        bench::short_report("draw"),
    ));

    ui.start("theme_panel").children(|ui| {
        if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
            party.live_reload_disabled = !party.live_reload_disabled;
        }

        if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
            party.old_theme_choice = Some(party.theme_choice);
            party.theme_choice = *choice;
            party.reload_assets = true;
        }
    });

    ui.start("party_window")
    .window("party_window")
    .with_close_button(false)
    .moveable(false)
    .resizable(false)
    .children(|ui| {
        ui.scrollpane("members_panel", "party_content", |ui| {
            party_members_panel(ui, party);
        });
    });

    if let Some(index) = party.editing_index {
        let character = &mut party.members[index];

        ui.window("character_window", |ui| {
            ui.scrollpane("pane", "character_content", |ui| {
                ui.start("name_panel")
                .children(|ui| {
                    if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
                        character.name = new_name;
                    }
                });

                ui.gap(10.0);
                ui.label("age_label", format!("Age: {}", character.age.round() as u32));
                if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
                    character.age = age;
                }

                for stat in Stat::iter() {
                    let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
                    let key = format!("{:?}", stat);
                    ui.set_variable(key, value);
                }

                ui.scrollpane("description_panel", "description_pane", |ui| {
                    ui.text_area("description_box");
                });

                ui.gap(10.0);

                if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
                    character.race = *race;
                }
    
                ui.gap(10.0);
    
                ui.tree("stats_panel", "stats_panel", true,
                |ui| {
                    ui.child("title");
                },|ui| {
                    stats_panel(ui, character);
                });
                
                ui.gap(10.0);
    
                ui.tree("inventory_panel", "inventory_panel", true,
                |ui| {
                    ui.child("title");
                }, |ui| {
                    inventory_panel(ui, character);
                });
            });
        });

        ui.window("item_picker", |ui| {
            let display_size = ui.display_size();

            ui.start("greyed_out")
            .unclip()
            .unparent()
            .size(display_size.x, display_size.y)
            .screen_pos(0.0, 0.0).finish();

            item_picker(ui, character);
        });
    }
}
source

pub fn children<F: FnOnce(&mut Frame)>(self, children: F) -> WidgetState

Consumes the builder and adds a widget to the current frame. The returned data includes information about the animation state and mouse interactions of the created element. The provided closure is called to enable adding children to this window.

Examples found in repository?
examples/demo.rs (lines 224-228)
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
pub fn build_ui(ui: &mut Frame, party: &mut Party) {
    match party.theme_choice {
        ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
            // show a custom cursor.  it automatically inherits mouse presses in its state
            ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
        },
        ThemeChoice::NoImage => {
            // don't show a custom cursor
        }
    }

    ui.label("bench", format!(
        "{}\n{}\n{}",
        bench::short_report("thyme"),
        bench::short_report("frame"),
        bench::short_report("draw"),
    ));

    ui.start("theme_panel").children(|ui| {
        if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
            party.live_reload_disabled = !party.live_reload_disabled;
        }

        if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
            party.old_theme_choice = Some(party.theme_choice);
            party.theme_choice = *choice;
            party.reload_assets = true;
        }
    });

    ui.start("party_window")
    .window("party_window")
    .with_close_button(false)
    .moveable(false)
    .resizable(false)
    .children(|ui| {
        ui.scrollpane("members_panel", "party_content", |ui| {
            party_members_panel(ui, party);
        });
    });

    if let Some(index) = party.editing_index {
        let character = &mut party.members[index];

        ui.window("character_window", |ui| {
            ui.scrollpane("pane", "character_content", |ui| {
                ui.start("name_panel")
                .children(|ui| {
                    if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
                        character.name = new_name;
                    }
                });

                ui.gap(10.0);
                ui.label("age_label", format!("Age: {}", character.age.round() as u32));
                if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
                    character.age = age;
                }

                for stat in Stat::iter() {
                    let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
                    let key = format!("{:?}", stat);
                    ui.set_variable(key, value);
                }

                ui.scrollpane("description_panel", "description_pane", |ui| {
                    ui.text_area("description_box");
                });

                ui.gap(10.0);

                if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
                    character.race = *race;
                }
    
                ui.gap(10.0);
    
                ui.tree("stats_panel", "stats_panel", true,
                |ui| {
                    ui.child("title");
                },|ui| {
                    stats_panel(ui, character);
                });
                
                ui.gap(10.0);
    
                ui.tree("inventory_panel", "inventory_panel", true,
                |ui| {
                    ui.child("title");
                }, |ui| {
                    inventory_panel(ui, character);
                });
            });
        });

        ui.window("item_picker", |ui| {
            let display_size = ui.display_size();

            ui.start("greyed_out")
            .unclip()
            .unparent()
            .size(display_size.x, display_size.y)
            .screen_pos(0.0, 0.0).finish();

            item_picker(ui, character);
        });
    }
}

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for WindowBuilder<'a>

§

impl<'a> !Send for WindowBuilder<'a>

§

impl<'a> !Sync for WindowBuilder<'a>

§

impl<'a> Unpin for WindowBuilder<'a>

§

impl<'a> !UnwindSafe for WindowBuilder<'a>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>