Struct thyme::WidgetBuilder
source · pub struct WidgetBuilder<'a> { /* private fields */ }
Expand description
A WidgetBuilder
is used to customize widgets within your UI tree, following a builder pattern.
Although there are several convenience methods on
Frame
for simple buttons
, labels
,
etc, widgets with more complex behavior will usually be created via Frame.start
and then
customized using the methods here. Note also that many methods here have an equivalent in the widget’s theme
definition.
Each method here takes the WidgetBuilder by value, modifies it, and then returns it, allowing you to use a builder pattern.
The window
method will transform this into a WindowBuilder
, while the
finish
and children
methods will complete the widget and add it to the frame’s widget tree.
Implementations§
source§impl<'a> WidgetBuilder<'a>
impl<'a> WidgetBuilder<'a>
sourcepub fn parent(&self) -> &Widget
pub fn parent(&self) -> &Widget
Returns the parent widget for this WidgetBuilder, which can be used to directly query the attributes of the parent
sourcepub fn widget(&self) -> &Widget
pub fn widget(&self) -> &Widget
Returns the current Widget for this WidgetBuilder. This can be used to query directly the various attributes of the widget. Further methods on this WidgetBuilder will modify the widget.
sourcepub fn frame(&self) -> &Frame
pub fn frame(&self) -> &Frame
Returns a reference to the current frame, (the ui
object), which is currently
stored by this builder
sourcepub fn always_top(self) -> WidgetBuilder<'a>
pub fn always_top(self) -> WidgetBuilder<'a>
Specifies that this widget and its children should be part of a new Render Group that is always shown on top of other groups.
See new_render_group
sourcepub fn always_bottom(self) -> WidgetBuilder<'a>
pub fn always_bottom(self) -> WidgetBuilder<'a>
Specifies that this widget and its children should be part of a new Render Group that is always shown below other groups.
See new_render_group
sourcepub fn new_render_group(self) -> WidgetBuilder<'a>
pub fn new_render_group(self) -> WidgetBuilder<'a>
Specifies that this widget and its children should be part of a new Render Group. Render groups are used to handle cases where
widgets may overlap, and determine input routing and draw order in those cases. If your UI doesn’t have moveable elements such as
windows, you should generally be ok to draw your entire UI in one render group, with the exception of modal popups.
Windows
make use of render groups.
Render groups allow a widget that is created later in your UI code to pick up input instead of a widget that is created earlier, even if
those widgets overlap. Note that the system internally relies on the render group ordering. In particular, having your layout create
a new render group earlier in the UI code as a result of an action on a later render group will cause that later render group to lose
input focus.
sourcepub fn wants_mouse(self, wants_mouse: bool) -> WidgetBuilder<'a>
pub fn wants_mouse(self, wants_mouse: bool) -> WidgetBuilder<'a>
Sets whether this widget will interact with the mouse. By default, widgets will not interact with the mouse, so this is set to true
for buttons and similar.
This may also be specified in the widget’s theme
.
sourcepub fn wants_scroll(self, wants_scroll: bool) -> WidgetBuilder<'a>
pub fn wants_scroll(self, wants_scroll: bool) -> WidgetBuilder<'a>
Sets whether this widget will receive mouse scrollwheel events. By default, widgets will not receive scroll wheel events, so this is set
to true
for scrollpanes.
This may also be specified in the widget’s theme
.
sourcepub fn id<T: Into<String>>(self, id: T) -> WidgetBuilder<'a>
pub fn id<T: Into<String>>(self, id: T) -> WidgetBuilder<'a>
Sets an id
for this widget. This id
is used internally to associate the widget with its PersistentState
.
You will need to specify an id
if you want to make changes to the PersistentState
. Otherwise,
Thyme can usually generate a unique internal ID for most elements.
sourcepub fn initially_open(self, open: bool) -> WidgetBuilder<'a>
pub fn initially_open(self, open: bool) -> WidgetBuilder<'a>
Specify whether this widget is initially open
, or visible
. By default,
widgets are initially open. If set to false, the widget will not be shown until it is set to open
using one of the methods on Frame
to modify its PersistentState
.
sourcepub fn text_color(self, color: Color) -> WidgetBuilder<'a>
pub fn text_color(self, color: Color) -> WidgetBuilder<'a>
sourcepub fn text_align(self, align: Align) -> WidgetBuilder<'a>
pub fn text_align(self, align: Align) -> WidgetBuilder<'a>
sourcepub fn text_indent(self, indent: f32) -> WidgetBuilder<'a>
pub fn text_indent(self, indent: f32) -> WidgetBuilder<'a>
Specify the indent of the first line of text rendered by this widget, in logical pixels. Useful for multi-line (or potentially multi-line) text where the starting position is indented.
sourcepub fn text<T: Into<String>>(self, text: T) -> WidgetBuilder<'a>
pub fn text<T: Into<String>>(self, text: T) -> WidgetBuilder<'a>
Specify text
to display for this widget. The widget must have a font
specified to render text.
This may also be specified in the widget’s theme
.
Examples found in repository?
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
fn party_members_panel(ui: &mut Frame, party: &mut Party) {
for (index, member) in party.members.iter_mut().enumerate() {
let clicked = ui.start("filled_slot_button")
.text(&member.name)
.active(Some(index) == party.editing_index)
.finish().clicked;
if clicked {
set_active_character(ui, member);
party.editing_index = Some(index);
}
}
if ui.start("add_character_button").finish().clicked {
let new_member = Character::generate(party.members.len());
set_active_character(ui, &new_member);
party.members.push(new_member);
party.editing_index = Some(party.members.len() - 1);
}
}
sourcepub fn tooltip_text<T: Into<String>>(self, tooltip: T) -> WidgetBuilder<'a>
pub fn tooltip_text<T: Into<String>>(self, tooltip: T) -> WidgetBuilder<'a>
Specify tooltip
to display as a simple tooltip if this widget is hovered with the mouse.
The tooltip will use the “tooltip” theme which must be present in the theme.
This may also be specified in the widget’s theme
.
sourcepub fn font(self, font: &str) -> WidgetBuilder<'a>
pub fn font(self, font: &str) -> WidgetBuilder<'a>
Specify a font
for any text rendered by this widget. A widget must have a font
specified to render text. The font
must be registered in the theme’s font definitions.
This may also be specified in the widget’s theme
.
sourcepub fn image_color(self, color: Color) -> WidgetBuilder<'a>
pub fn image_color(self, color: Color) -> WidgetBuilder<'a>
sourcepub fn foreground(self, fg: &str) -> WidgetBuilder<'a>
pub fn foreground(self, fg: &str) -> WidgetBuilder<'a>
Specify a foreground image for this widget. The image ID, fg
must be registered in the theme’s
image definitions. The ID consists of “{image_set_id}/{image_id}”.
Foreground images are drawn below text but above the background.
This may also be specified in the widget’s theme
.
sourcepub fn background(self, bg: &str) -> WidgetBuilder<'a>
pub fn background(self, bg: &str) -> WidgetBuilder<'a>
Specify a background image for this widget. The image ID, bg
must be registered in the theme’s
image definitions. The ID consists of “{image_set_id}/{image_id}”.
Background images are drawn below text and any children.
This may also be specified in the widget’s theme
.
sourcepub fn child_align(self, align: Align) -> WidgetBuilder<'a>
pub fn child_align(self, align: Align) -> WidgetBuilder<'a>
sourcepub fn layout_spacing(self, spacing: Point) -> WidgetBuilder<'a>
pub fn layout_spacing(self, spacing: Point) -> WidgetBuilder<'a>
Specifies the spacing, in logical pixels, to use between children that are laid out in this widget.
This may also be specified in the widget’s theme
.
sourcepub fn layout_horizontal(self) -> WidgetBuilder<'a>
pub fn layout_horizontal(self) -> WidgetBuilder<'a>
sourcepub fn layout_vertical(self) -> WidgetBuilder<'a>
pub fn layout_vertical(self) -> WidgetBuilder<'a>
sourcepub fn layout(self, layout: Layout) -> WidgetBuilder<'a>
pub fn layout(self, layout: Layout) -> WidgetBuilder<'a>
sourcepub fn screen_pos(self, x: f32, y: f32) -> WidgetBuilder<'a>
pub fn screen_pos(self, x: f32, y: f32) -> WidgetBuilder<'a>
Manually specify a position for this widget, basedon the specified
x
and y
logical pixel positions. This position ignores alignment
or any other considerations.
This may also be specified in the widget’s theme
.
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 render_as_tooltip(self) -> WidgetBuilder<'a>
pub fn render_as_tooltip(self) -> WidgetBuilder<'a>
Helper to treat this widget as a tooltip. The widget will be placed on top
of other widgets in its own render group. Positioning will be based on the mouse
cursor position. See new_render_group
.
sourcepub fn pos(self, x: f32, y: f32) -> WidgetBuilder<'a>
pub fn pos(self, x: f32, y: f32) -> WidgetBuilder<'a>
sourcepub fn align(self, align: Align) -> WidgetBuilder<'a>
pub fn align(self, align: Align) -> WidgetBuilder<'a>
sourcepub fn border(self, border: Border) -> WidgetBuilder<'a>
pub fn border(self, border: Border) -> WidgetBuilder<'a>
sourcepub fn size(self, x: f32, y: f32) -> WidgetBuilder<'a>
pub fn size(self, x: f32, y: f32) -> WidgetBuilder<'a>
Specify the widget’s size
in logical pixels. This may or may not be an
absolute size, depending on WidthRelative
and
HeightRelative
This may also be specified in the widget’s theme
.
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 width(self, x: f32) -> WidgetBuilder<'a>
pub fn width(self, x: f32) -> WidgetBuilder<'a>
sourcepub fn height(self, y: f32) -> WidgetBuilder<'a>
pub fn height(self, y: f32) -> WidgetBuilder<'a>
sourcepub fn width_from(self, from: WidthRelative) -> WidgetBuilder<'a>
pub fn width_from(self, from: WidthRelative) -> WidgetBuilder<'a>
Specify how to compute the widget’s width from its size
.
See WidthRelative
.
This may also be specified in the widget’s theme
. You may also
specify this using size_from
.
sourcepub fn height_from(self, from: HeightRelative) -> WidgetBuilder<'a>
pub fn height_from(self, from: HeightRelative) -> WidgetBuilder<'a>
Specify how to compute the widget’s height from its size
.
See HeightRelative
This may also be specified in the widget’s theme
. You may also
specify this using size_from
.
sourcepub fn size_from(
self,
width_from: WidthRelative,
height_from: HeightRelative
) -> WidgetBuilder<'a>
pub fn size_from( self, width_from: WidthRelative, height_from: HeightRelative ) -> WidgetBuilder<'a>
Specify how to compute the widget’s height and width from its size
.
See WidthRelative
and HeightRelative
.
This may also be specified in the widget’s theme
. You may also specify this
using width_from
and height_from
sourcepub fn clip(self, clip: Rect) -> WidgetBuilder<'a>
pub fn clip(self, clip: Rect) -> WidgetBuilder<'a>
Sets the widget’s clip Rectangle
. By default,
a widget will have a clip rectangle set from its size
and position
,
calculated based on the theme and the various methods such as size
,
pos
, width_from
, height_from
,
etc. You can override that behavior with this method. This is useful to display part of an image,
such as in a progress bar
, or to limit the size of child
content, such as in a scrollpane
.
Widgets always inherit their clip
as the minimum extent of their parent’s clip and their own clip.
See Rect.min
.
sourcepub fn unclip(self) -> WidgetBuilder<'a>
pub fn unclip(self) -> WidgetBuilder<'a>
Removes all constraints from the widget’s clip Rectangle
. This will
allow the widget to render outside of its parent’s area. See clip
.
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 unparent(self) -> WidgetBuilder<'a>
pub fn unparent(self) -> WidgetBuilder<'a>
If called, the current parent widget will not treat this widget as a child for the purposes
of computing its child bounds. This is useful for popups and similar which are not
neccesarily children of the widgets that create them. You usually will also want
unclip
and new_render_group
.
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 force_hover(self, hover: bool) -> WidgetBuilder<'a>
pub fn force_hover(self, hover: bool) -> WidgetBuilder<'a>
Forces this widget’s AnimState
to
have the specified value
for its hover
AnimStateKey
sourcepub fn force_pressed(self, pressed: bool) -> WidgetBuilder<'a>
pub fn force_pressed(self, pressed: bool) -> WidgetBuilder<'a>
Forces this widget’s AnimState
to
have the specified value
for its pressed
AnimStateKey
sourcepub fn active(self, active: bool) -> WidgetBuilder<'a>
pub fn active(self, active: bool) -> WidgetBuilder<'a>
Sets whether the widget’s AnimState
will
include the active
AnimStateKey
.
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 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
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);
});
}
}
fn party_members_panel(ui: &mut Frame, party: &mut Party) {
for (index, member) in party.members.iter_mut().enumerate() {
let clicked = ui.start("filled_slot_button")
.text(&member.name)
.active(Some(index) == party.editing_index)
.finish().clicked;
if clicked {
set_active_character(ui, member);
party.editing_index = Some(index);
}
}
if ui.start("add_character_button").finish().clicked {
let new_member = Character::generate(party.members.len());
set_active_character(ui, &new_member);
party.members.push(new_member);
party.editing_index = Some(party.members.len() - 1);
}
}
sourcepub fn visible(self, visible: bool) -> WidgetBuilder<'a>
pub fn visible(self, visible: bool) -> WidgetBuilder<'a>
Sets whether this widget will be visible
. If the widget is not
visible, it will not be shown and any child closures (such as passed in
children
) will not be run.
sourcepub fn enabled(self, enabled: bool) -> WidgetBuilder<'a>
pub fn enabled(self, enabled: bool) -> WidgetBuilder<'a>
Sets whether this widget will be enabled
. If the widget is not
enabled, it will not interact with any user input.
Examples found in repository?
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
fn stats_panel(ui: &mut Frame, character: &mut Character) {
let points_used: u32 = character.stats.values().sum();
let points_available: u32 = STAT_POINTS - points_used;
let frac = ((ui.cur_time_millis() - ui.base_time_millis("stat_roll")) as f32 / 1000.0).min(1.0);
let roll = ui.start("roll_button")
.enabled(frac > 0.99)
.children(|ui| {
ui.progress_bar("progress_bar", frac);
});
if roll.clicked {
ui.set_base_time_now("stat_roll");
}
for stat in Stat::iter() {
let value = character.stats.entry(stat).or_insert(10);
ui.tree(
"stat_panel",
&format!("stat_panel_{:?}", stat),
false,
|ui| {
ui.label("label", format!("{:?}", stat));
match ui.spinner("spinner", *value, MIN_STAT, if points_available == 0 { *value } else { MAX_STAT }) {
1 => *value += 1,
-1 => *value -= 1,
_ => (),
}
}, |ui| {
ui.child("description");
});
}
ui.label("points_available", format!("Points Remaining: {}", points_available));
}
fn item_picker(ui: &mut Frame, character: &mut Character) {
for item in ITEMS.iter() {
let clicked = ui.start("item_button")
.enabled(character.gp >= item.price)
.children(|ui| {
ui.label("name", item.name);
// TODO icon image
ui.child("icon");
ui.label("price", format!("{} Gold", item.price));
}).clicked;
if clicked {
character.gp -= item.price;
character.items.push(item.clone());
ui.close("item_picker");
}
}
}
sourcepub fn trigger_layout(self, rect: &mut Rect) -> WidgetBuilder<'a>
pub fn trigger_layout(self, rect: &mut Rect) -> WidgetBuilder<'a>
Force the widget to layout its size
and position
immediately.
Assuming these attributes are not changed after this method is
called, these attributes will have their final values after this
method returns. The size and position are written to the passed
in Rect
.
sourcepub fn trigger_layout_inner(self, rect: &mut Rect) -> WidgetBuilder<'a>
pub fn trigger_layout_inner(self, rect: &mut Rect) -> WidgetBuilder<'a>
Force the widget to layout its size
and position
immediately.
Assuming these attributes are not changed after this is method is
called, they will have their final values after this method returns.
The inner size and position (size and position adjusted by the
Border
) are written to the passed in
Rect
sourcepub fn trigger_text_layout(self, cursor: &mut Point) -> WidgetBuilder<'a>
pub fn trigger_text_layout(self, cursor: &mut Point) -> WidgetBuilder<'a>
Causes this widget to layout its current text. The final position of the text
cursor is written into cursor
. If this widget does not have a font or has no text,
nothing is written into cursor
.
sourcepub fn window(self, id: &str) -> WindowBuilder<'a>
pub fn window(self, id: &str) -> WindowBuilder<'a>
Turns this builder into a WindowBuilder. You should use all WidgetBuilder
methods
you need before calling this method. The window must still be completed with one of the
WindowBuilder
methods. You must pass a unique id
for each window
created by your application.
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 scrollpane(self, content_id: &str) -> ScrollpaneBuilder<'a>
pub fn scrollpane(self, content_id: &str) -> ScrollpaneBuilder<'a>
Turns this builder into a ScrollpaneBuilder
. You should use all
WidgetBuilder
methods you need before calling this method. The scrollpane must still be completed
with one of the methods on ScrollpaneBuilder
. You must pass a unique
content_id
for the scrollpane’s content.
Examples found in repository?
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
fn inventory_panel(ui: &mut Frame, character: &mut Character) {
ui.start("top_panel")
.children(|ui| {
if ui.child("buy").clicked {
ui.open_modal("item_picker");
}
ui.label("gold", format!("{} Gold", character.gp));
});
ui.start("items_panel")
.scrollpane("items_content")
.show_vertical_scrollbar(ShowElement::Always)
.children(|ui| {
items_panel(ui, character);
});
}
sourcepub fn edit<F: FnOnce(WidgetBuilder<'_>) -> WidgetBuilder<'_>>(
self,
f: F
) -> WidgetBuilder<'a>
pub fn edit<F: FnOnce(WidgetBuilder<'_>) -> WidgetBuilder<'_>>( self, f: F ) -> WidgetBuilder<'a>
Executes the passed in closure on this WidgetBuilder
, returning the resulting value.
This allows you to insert arbitrary control flow while continuing to chain the
WidgetBuilder methods. Without this method, you might need to save the builder in a
variable, check some condition (possibly calling another WidgetBuilder
method),
and then continue on with the usual method chaining.
Example
fn hover_button(ui: &mut Frame, force_hover: bool) -> WidgetState {
ui.start("hover_button")
.edit(|builder| {
if force_hover {
builder.force_hover(true)
} else {
builder
}
}).finish()
}
sourcepub fn finish(self) -> WidgetState
pub fn finish(self) -> 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.
If you wish this widget to have one or more child widgets, you should
call children
instead.
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 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
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);
});
}
}
fn party_members_panel(ui: &mut Frame, party: &mut Party) {
for (index, member) in party.members.iter_mut().enumerate() {
let clicked = ui.start("filled_slot_button")
.text(&member.name)
.active(Some(index) == party.editing_index)
.finish().clicked;
if clicked {
set_active_character(ui, member);
party.editing_index = Some(index);
}
}
if ui.start("add_character_button").finish().clicked {
let new_member = Character::generate(party.members.len());
set_active_character(ui, &new_member);
party.members.push(new_member);
party.editing_index = Some(party.members.len() - 1);
}
}
sourcepub fn children<F: FnOnce(&mut Frame)>(self, f: F) -> WidgetState
pub fn children<F: FnOnce(&mut Frame)>(self, f: 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 widget.
If you don’t want to add children, you can just call
finish
instead.
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 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
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);
});
}
}
fn party_members_panel(ui: &mut Frame, party: &mut Party) {
for (index, member) in party.members.iter_mut().enumerate() {
let clicked = ui.start("filled_slot_button")
.text(&member.name)
.active(Some(index) == party.editing_index)
.finish().clicked;
if clicked {
set_active_character(ui, member);
party.editing_index = Some(index);
}
}
if ui.start("add_character_button").finish().clicked {
let new_member = Character::generate(party.members.len());
set_active_character(ui, &new_member);
party.members.push(new_member);
party.editing_index = Some(party.members.len() - 1);
}
}
fn set_active_character(ui: &mut Frame, character: &Character) {
ui.open("character_window");
ui.modify("name_input", |state| {
state.text = Some(character.name.clone());
});
ui.close("item_picker");
}
fn stats_panel(ui: &mut Frame, character: &mut Character) {
let points_used: u32 = character.stats.values().sum();
let points_available: u32 = STAT_POINTS - points_used;
let frac = ((ui.cur_time_millis() - ui.base_time_millis("stat_roll")) as f32 / 1000.0).min(1.0);
let roll = ui.start("roll_button")
.enabled(frac > 0.99)
.children(|ui| {
ui.progress_bar("progress_bar", frac);
});
if roll.clicked {
ui.set_base_time_now("stat_roll");
}
for stat in Stat::iter() {
let value = character.stats.entry(stat).or_insert(10);
ui.tree(
"stat_panel",
&format!("stat_panel_{:?}", stat),
false,
|ui| {
ui.label("label", format!("{:?}", stat));
match ui.spinner("spinner", *value, MIN_STAT, if points_available == 0 { *value } else { MAX_STAT }) {
1 => *value += 1,
-1 => *value -= 1,
_ => (),
}
}, |ui| {
ui.child("description");
});
}
ui.label("points_available", format!("Points Remaining: {}", points_available));
}
fn item_picker(ui: &mut Frame, character: &mut Character) {
for item in ITEMS.iter() {
let clicked = ui.start("item_button")
.enabled(character.gp >= item.price)
.children(|ui| {
ui.label("name", item.name);
// TODO icon image
ui.child("icon");
ui.label("price", format!("{} Gold", item.price));
}).clicked;
if clicked {
character.gp -= item.price;
character.items.push(item.clone());
ui.close("item_picker");
}
}
}
fn inventory_panel(ui: &mut Frame, character: &mut Character) {
ui.start("top_panel")
.children(|ui| {
if ui.child("buy").clicked {
ui.open_modal("item_picker");
}
ui.label("gold", format!("{} Gold", character.gp));
});
ui.start("items_panel")
.scrollpane("items_content")
.show_vertical_scrollbar(ShowElement::Always)
.children(|ui| {
items_panel(ui, character);
});
}
sourcepub fn custom_int(&self, key: &str, default_value: i32) -> i32
pub fn custom_int(&self, key: &str, default_value: i32) -> i32
Queries the theme for the specified custom int, in the custom
field for the
theme with the specified key
. Returns the default_value
if the theme or key cannot
be found, or if the key is specified but is not a float
sourcepub fn custom_float(&self, key: &str, default_value: f32) -> f32
pub fn custom_float(&self, key: &str, default_value: f32) -> f32
Queries the theme for the specified custom float, in the custom
field for the
theme with the specified key
. Returns the default_value
if the theme or key cannot
be found, or if the key is specified but is not a float
sourcepub fn custom_string(&self, key: &str, default_value: String) -> String
pub fn custom_string(&self, key: &str, default_value: String) -> String
Queries the theme for the specified custom String, in the custom
field for the
theme with the specified key
. Returns the default_value
if the theme or key
cannot be found, or if the key is specified but is not a String