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?
189pub fn build_ui(ui: &mut Frame, party: &mut Party) {
190 match party.theme_choice {
191 ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
192 // show a custom cursor. it automatically inherits mouse presses in its state
193 ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
194 },
195 ThemeChoice::NoImage => {
196 // don't show a custom cursor
197 }
198 }
199
200 ui.label("bench", format!(
201 "{}\n{}\n{}",
202 bench::short_report("thyme"),
203 bench::short_report("frame"),
204 bench::short_report("draw"),
205 ));
206
207 ui.start("theme_panel").children(|ui| {
208 if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
209 party.live_reload_disabled = !party.live_reload_disabled;
210 }
211
212 if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
213 party.old_theme_choice = Some(party.theme_choice);
214 party.theme_choice = *choice;
215 party.reload_assets = true;
216 }
217 });
218
219 ui.start("party_window")
220 .window("party_window")
221 .with_close_button(false)
222 .moveable(false)
223 .resizable(false)
224 .children(|ui| {
225 ui.scrollpane("members_panel", "party_content", |ui| {
226 party_members_panel(ui, party);
227 });
228 });
229
230 if let Some(index) = party.editing_index {
231 let character = &mut party.members[index];
232
233 ui.window("character_window", |ui| {
234 ui.scrollpane("pane", "character_content", |ui| {
235 ui.start("name_panel")
236 .children(|ui| {
237 if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
238 character.name = new_name;
239 }
240 });
241
242 ui.gap(10.0);
243 ui.label("age_label", format!("Age: {}", character.age.round() as u32));
244 if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
245 character.age = age;
246 }
247
248 for stat in Stat::iter() {
249 let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
250 let key = format!("{:?}", stat);
251 ui.set_variable(key, value);
252 }
253
254 ui.scrollpane("description_panel", "description_pane", |ui| {
255 ui.text_area("description_box");
256 });
257
258 ui.gap(10.0);
259
260 if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
261 character.race = *race;
262 }
263
264 ui.gap(10.0);
265
266 ui.tree("stats_panel", "stats_panel", true,
267 |ui| {
268 ui.child("title");
269 },|ui| {
270 stats_panel(ui, character);
271 });
272
273 ui.gap(10.0);
274
275 ui.tree("inventory_panel", "inventory_panel", true,
276 |ui| {
277 ui.child("title");
278 }, |ui| {
279 inventory_panel(ui, character);
280 });
281 });
282 });
283
284 ui.window("item_picker", |ui| {
285 let display_size = ui.display_size();
286
287 ui.start("greyed_out")
288 .unclip()
289 .unparent()
290 .size(display_size.x, display_size.y)
291 .screen_pos(0.0, 0.0).finish();
292
293 item_picker(ui, character);
294 });
295 }
296}
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?
189pub fn build_ui(ui: &mut Frame, party: &mut Party) {
190 match party.theme_choice {
191 ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
192 // show a custom cursor. it automatically inherits mouse presses in its state
193 ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
194 },
195 ThemeChoice::NoImage => {
196 // don't show a custom cursor
197 }
198 }
199
200 ui.label("bench", format!(
201 "{}\n{}\n{}",
202 bench::short_report("thyme"),
203 bench::short_report("frame"),
204 bench::short_report("draw"),
205 ));
206
207 ui.start("theme_panel").children(|ui| {
208 if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
209 party.live_reload_disabled = !party.live_reload_disabled;
210 }
211
212 if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
213 party.old_theme_choice = Some(party.theme_choice);
214 party.theme_choice = *choice;
215 party.reload_assets = true;
216 }
217 });
218
219 ui.start("party_window")
220 .window("party_window")
221 .with_close_button(false)
222 .moveable(false)
223 .resizable(false)
224 .children(|ui| {
225 ui.scrollpane("members_panel", "party_content", |ui| {
226 party_members_panel(ui, party);
227 });
228 });
229
230 if let Some(index) = party.editing_index {
231 let character = &mut party.members[index];
232
233 ui.window("character_window", |ui| {
234 ui.scrollpane("pane", "character_content", |ui| {
235 ui.start("name_panel")
236 .children(|ui| {
237 if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
238 character.name = new_name;
239 }
240 });
241
242 ui.gap(10.0);
243 ui.label("age_label", format!("Age: {}", character.age.round() as u32));
244 if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
245 character.age = age;
246 }
247
248 for stat in Stat::iter() {
249 let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
250 let key = format!("{:?}", stat);
251 ui.set_variable(key, value);
252 }
253
254 ui.scrollpane("description_panel", "description_pane", |ui| {
255 ui.text_area("description_box");
256 });
257
258 ui.gap(10.0);
259
260 if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
261 character.race = *race;
262 }
263
264 ui.gap(10.0);
265
266 ui.tree("stats_panel", "stats_panel", true,
267 |ui| {
268 ui.child("title");
269 },|ui| {
270 stats_panel(ui, character);
271 });
272
273 ui.gap(10.0);
274
275 ui.tree("inventory_panel", "inventory_panel", true,
276 |ui| {
277 ui.child("title");
278 }, |ui| {
279 inventory_panel(ui, character);
280 });
281 });
282 });
283
284 ui.window("item_picker", |ui| {
285 let display_size = ui.display_size();
286
287 ui.start("greyed_out")
288 .unclip()
289 .unparent()
290 .size(display_size.x, display_size.y)
291 .screen_pos(0.0, 0.0).finish();
292
293 item_picker(ui, character);
294 });
295 }
296}
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?
189pub fn build_ui(ui: &mut Frame, party: &mut Party) {
190 match party.theme_choice {
191 ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
192 // show a custom cursor. it automatically inherits mouse presses in its state
193 ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
194 },
195 ThemeChoice::NoImage => {
196 // don't show a custom cursor
197 }
198 }
199
200 ui.label("bench", format!(
201 "{}\n{}\n{}",
202 bench::short_report("thyme"),
203 bench::short_report("frame"),
204 bench::short_report("draw"),
205 ));
206
207 ui.start("theme_panel").children(|ui| {
208 if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
209 party.live_reload_disabled = !party.live_reload_disabled;
210 }
211
212 if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
213 party.old_theme_choice = Some(party.theme_choice);
214 party.theme_choice = *choice;
215 party.reload_assets = true;
216 }
217 });
218
219 ui.start("party_window")
220 .window("party_window")
221 .with_close_button(false)
222 .moveable(false)
223 .resizable(false)
224 .children(|ui| {
225 ui.scrollpane("members_panel", "party_content", |ui| {
226 party_members_panel(ui, party);
227 });
228 });
229
230 if let Some(index) = party.editing_index {
231 let character = &mut party.members[index];
232
233 ui.window("character_window", |ui| {
234 ui.scrollpane("pane", "character_content", |ui| {
235 ui.start("name_panel")
236 .children(|ui| {
237 if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
238 character.name = new_name;
239 }
240 });
241
242 ui.gap(10.0);
243 ui.label("age_label", format!("Age: {}", character.age.round() as u32));
244 if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
245 character.age = age;
246 }
247
248 for stat in Stat::iter() {
249 let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
250 let key = format!("{:?}", stat);
251 ui.set_variable(key, value);
252 }
253
254 ui.scrollpane("description_panel", "description_pane", |ui| {
255 ui.text_area("description_box");
256 });
257
258 ui.gap(10.0);
259
260 if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
261 character.race = *race;
262 }
263
264 ui.gap(10.0);
265
266 ui.tree("stats_panel", "stats_panel", true,
267 |ui| {
268 ui.child("title");
269 },|ui| {
270 stats_panel(ui, character);
271 });
272
273 ui.gap(10.0);
274
275 ui.tree("inventory_panel", "inventory_panel", true,
276 |ui| {
277 ui.child("title");
278 }, |ui| {
279 inventory_panel(ui, character);
280 });
281 });
282 });
283
284 ui.window("item_picker", |ui| {
285 let display_size = ui.display_size();
286
287 ui.start("greyed_out")
288 .unclip()
289 .unparent()
290 .size(display_size.x, display_size.y)
291 .screen_pos(0.0, 0.0).finish();
292
293 item_picker(ui, character);
294 });
295 }
296}
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?
189pub fn build_ui(ui: &mut Frame, party: &mut Party) {
190 match party.theme_choice {
191 ThemeChoice::Pixels | ThemeChoice::Fantasy | ThemeChoice::Transparent | ThemeChoice::Golden => {
192 // show a custom cursor. it automatically inherits mouse presses in its state
193 ui.set_mouse_cursor("gui/cursor", thyme::Align::TopLeft);
194 },
195 ThemeChoice::NoImage => {
196 // don't show a custom cursor
197 }
198 }
199
200 ui.label("bench", format!(
201 "{}\n{}\n{}",
202 bench::short_report("thyme"),
203 bench::short_report("frame"),
204 bench::short_report("draw"),
205 ));
206
207 ui.start("theme_panel").children(|ui| {
208 if ui.start("live_reload").active(!party.live_reload_disabled).finish().clicked {
209 party.live_reload_disabled = !party.live_reload_disabled;
210 }
211
212 if let Some(choice) = ui.combo_box("theme_choice", "theme_choice", &party.theme_choice, &THEME_CHOICES) {
213 party.old_theme_choice = Some(party.theme_choice);
214 party.theme_choice = *choice;
215 party.reload_assets = true;
216 }
217 });
218
219 ui.start("party_window")
220 .window("party_window")
221 .with_close_button(false)
222 .moveable(false)
223 .resizable(false)
224 .children(|ui| {
225 ui.scrollpane("members_panel", "party_content", |ui| {
226 party_members_panel(ui, party);
227 });
228 });
229
230 if let Some(index) = party.editing_index {
231 let character = &mut party.members[index];
232
233 ui.window("character_window", |ui| {
234 ui.scrollpane("pane", "character_content", |ui| {
235 ui.start("name_panel")
236 .children(|ui| {
237 if let Some(new_name) = ui.input_field("name_input", "name_input", None) {
238 character.name = new_name;
239 }
240 });
241
242 ui.gap(10.0);
243 ui.label("age_label", format!("Age: {}", character.age.round() as u32));
244 if let Some(age) = ui.horizontal_slider("age_slider", MIN_AGE, MAX_AGE, character.age) {
245 character.age = age;
246 }
247
248 for stat in Stat::iter() {
249 let value = format!("{}", character.stats.get(&stat).unwrap_or(&10));
250 let key = format!("{:?}", stat);
251 ui.set_variable(key, value);
252 }
253
254 ui.scrollpane("description_panel", "description_pane", |ui| {
255 ui.text_area("description_box");
256 });
257
258 ui.gap(10.0);
259
260 if let Some(race) = ui.combo_box("race_selector", "race_selector", &character.race, Race::all()) {
261 character.race = *race;
262 }
263
264 ui.gap(10.0);
265
266 ui.tree("stats_panel", "stats_panel", true,
267 |ui| {
268 ui.child("title");
269 },|ui| {
270 stats_panel(ui, character);
271 });
272
273 ui.gap(10.0);
274
275 ui.tree("inventory_panel", "inventory_panel", true,
276 |ui| {
277 ui.child("title");
278 }, |ui| {
279 inventory_panel(ui, character);
280 });
281 });
282 });
283
284 ui.window("item_picker", |ui| {
285 let display_size = ui.display_size();
286
287 ui.start("greyed_out")
288 .unclip()
289 .unparent()
290 .size(display_size.x, display_size.y)
291 .screen_pos(0.0, 0.0).finish();
292
293 item_picker(ui, character);
294 });
295 }
296}