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>
impl<'a> WindowBuilder<'a>
sourcepub fn cancel_render_group(self) -> WindowBuilder<'a>
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
sourcepub fn with_titlebar(self, with_titlebar: bool) -> WindowBuilder<'a>
pub fn with_titlebar(self, with_titlebar: bool) -> WindowBuilder<'a>
Specifies whether the created window should show a titlebar.
sourcepub fn title<T: Into<String>>(self, title: T) -> WindowBuilder<'a>
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.
Specifies whether the created window should have a close button.
Examples found in repository?
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);
});
}
}
sourcepub fn moveable(self, moveable: bool) -> WindowBuilder<'a>
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?
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);
});
}
}
sourcepub fn resizable(self, resizable: bool) -> WindowBuilder<'a>
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?
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);
});
}
}
sourcepub fn children<F: FnOnce(&mut Frame)>(self, children: F) -> WidgetState
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?
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);
});
}
}