pub struct DrawMgr<'a> { /* private fields */ }
Expand description
Draw interface
This interface is provided to widgets in crate::Layout::draw
.
Lower-level interfaces may be accessed through Self::draw_device
.
DrawMgr
is not a Copy
or Clone
type; instead it may be “reborrowed”
via Self::re_id
or Self::re_clone
.
draw.check_box(&*self, self.state);
— note&*self
to convert from to&W
from&mut W
, since the latter would cause borrow conflicts
Implementations§
source§impl<'a> DrawMgr<'a>
impl<'a> DrawMgr<'a>
sourcepub fn re_id<'b>(&'b mut self, id: WidgetId) -> DrawMgr<'b>where
'a: 'b,
pub fn re_id<'b>(&'b mut self, id: WidgetId) -> DrawMgr<'b>where
'a: 'b,
Reborrow with a new lifetime and new id
Rust allows references like &T
or &mut T
to be “reborrowed” through
coercion: essentially, the pointer is copied under a new, shorter, lifetime.
Until rfcs#1403 lands, reborrows on user types require a method call.
sourcepub fn re_clone<'b>(&'b mut self) -> DrawMgr<'b>where
'a: 'b,
pub fn re_clone<'b>(&'b mut self) -> DrawMgr<'b>where
'a: 'b,
Reborrow with a new lifetime and same id
Rust allows references like &T
or &mut T
to be “reborrowed” through
coercion: essentially, the pointer is copied under a new, shorter, lifetime.
Until rfcs#1403 lands, reborrows on user types require a method call.
Examples found in repository?
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 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
fn draw(&mut self, mut draw: DrawMgr) {
for child in &mut self.children {
child.draw(draw.re_clone());
}
}
}
/// Float layout
struct Float<'a, I>
where
I: DoubleEndedIterator<Item = Visitor<'a>>,
{
children: I,
}
impl<'a, I> Layout for Float<'a, I>
where
I: DoubleEndedIterator<Item = Visitor<'a>>,
{
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let mut rules = SizeRules::EMPTY;
for child in &mut self.children {
rules = rules.max(child.size_rules(mgr.re(), axis));
}
rules
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
for child in &mut self.children {
child.set_rect(mgr, rect);
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
self.children.find_map(|child| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
let mut iter = (&mut self.children).rev();
if let Some(first) = iter.next() {
first.draw(draw.re_clone());
}
for child in iter {
draw.with_pass(|draw| child.draw(draw));
}
}
}
/// A row/column over a slice
struct Slice<'a, W: Widget, D: Directional> {
data: &'a mut DynRowStorage,
direction: D,
children: &'a mut [W],
}
impl<'a, W: Widget, D: Directional> Layout for Slice<'a, W, D> {
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let dim = (self.direction, self.children.len());
let mut solver = RowSolver::new(axis, dim, self.data);
for (n, child) in self.children.iter_mut().enumerate() {
solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
}
solver.finish(self.data)
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
let dim = (self.direction, self.children.len());
let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);
for (n, child) in self.children.iter_mut().enumerate() {
child.set_rect(mgr, setter.child_rect(self.data, n));
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
let solver = RowPositionSolver::new(self.direction);
solver
.find_child_mut(self.children, coord)
.and_then(|child| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
let solver = RowPositionSolver::new(self.direction);
solver.for_children(self.children, draw.get_clip_rect(), |w| draw.recurse(w));
}
}
/// Implement grid layout for children
struct Grid<'a, S, I> {
data: &'a mut S,
dim: GridDimensions,
children: I,
}
impl<'a, S: GridStorage, I> Layout for Grid<'a, S, I>
where
I: Iterator<Item = (GridChildInfo, Visitor<'a>)>,
{
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let mut solver = GridSolver::<Vec<_>, Vec<_>, _>::new(axis, self.dim, self.data);
for (info, child) in &mut self.children {
solver.for_child(self.data, info, |axis| child.size_rules(mgr.re(), axis));
}
solver.finish(self.data)
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
let mut setter = GridSetter::<Vec<_>, Vec<_>, _>::new(rect, self.dim, self.data);
for (info, child) in &mut self.children {
child.set_rect(mgr, setter.child_rect(self.data, info));
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
// TODO(opt): more efficient search strategy?
self.children.find_map(|(_, child)| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
for (_, child) in &mut self.children {
child.draw(draw.re_clone());
}
}
sourcepub fn recurse(&mut self, child: &mut dyn Widget)
pub fn recurse(&mut self, child: &mut dyn Widget)
Recurse drawing to a child
Examples found in repository?
More examples
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 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
fn draw_(&mut self, mut draw: DrawMgr) {
match &mut self.layout {
LayoutType::None => (),
LayoutType::Component(component) => component.draw(draw),
LayoutType::BoxComponent(layout) => layout.draw(draw),
LayoutType::Single(child) | LayoutType::AlignSingle(child, _) => draw.recurse(*child),
LayoutType::Align(layout, _) => layout.draw_(draw),
LayoutType::Pack(layout, _, _) => layout.draw_(draw),
LayoutType::Margins(layout, _, _) => layout.draw_(draw),
LayoutType::Frame(child, storage, style) => {
draw.frame(storage.rect, *style, Background::Default);
child.draw_(draw);
}
LayoutType::Button(child, storage, color) => {
let bg = match color {
Some(rgb) => Background::Rgb(*rgb),
None => Background::Default,
};
draw.frame(storage.rect, FrameStyle::Button, bg);
child.draw_(draw);
}
}
}
}
/// Implement row/column layout for children
struct List<'a, S, D, I> {
data: &'a mut S,
direction: D,
children: I,
}
impl<'a, S: RowStorage, D: Directional, I> Layout for List<'a, S, D, I>
where
I: ExactSizeIterator<Item = Visitor<'a>>,
{
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let dim = (self.direction, self.children.len());
let mut solver = RowSolver::new(axis, dim, self.data);
for (n, child) in (&mut self.children).enumerate() {
solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
}
solver.finish(self.data)
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
let dim = (self.direction, self.children.len());
let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);
for (n, child) in (&mut self.children).enumerate() {
child.set_rect(mgr, setter.child_rect(self.data, n));
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
// TODO(opt): more efficient search strategy?
self.children.find_map(|child| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
for child in &mut self.children {
child.draw(draw.re_clone());
}
}
}
/// Float layout
struct Float<'a, I>
where
I: DoubleEndedIterator<Item = Visitor<'a>>,
{
children: I,
}
impl<'a, I> Layout for Float<'a, I>
where
I: DoubleEndedIterator<Item = Visitor<'a>>,
{
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let mut rules = SizeRules::EMPTY;
for child in &mut self.children {
rules = rules.max(child.size_rules(mgr.re(), axis));
}
rules
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
for child in &mut self.children {
child.set_rect(mgr, rect);
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
self.children.find_map(|child| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
let mut iter = (&mut self.children).rev();
if let Some(first) = iter.next() {
first.draw(draw.re_clone());
}
for child in iter {
draw.with_pass(|draw| child.draw(draw));
}
}
}
/// A row/column over a slice
struct Slice<'a, W: Widget, D: Directional> {
data: &'a mut DynRowStorage,
direction: D,
children: &'a mut [W],
}
impl<'a, W: Widget, D: Directional> Layout for Slice<'a, W, D> {
fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
let dim = (self.direction, self.children.len());
let mut solver = RowSolver::new(axis, dim, self.data);
for (n, child) in self.children.iter_mut().enumerate() {
solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
}
solver.finish(self.data)
}
fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
let dim = (self.direction, self.children.len());
let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);
for (n, child) in self.children.iter_mut().enumerate() {
child.set_rect(mgr, setter.child_rect(self.data, n));
}
}
fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
let solver = RowPositionSolver::new(self.direction);
solver
.find_child_mut(self.children, coord)
.and_then(|child| child.find_id(coord))
}
fn draw(&mut self, mut draw: DrawMgr) {
let solver = RowPositionSolver::new(self.direction);
solver.for_children(self.children, draw.get_clip_rect(), |w| draw.recurse(w));
}
sourcepub fn ev_state(&mut self) -> &EventState
pub fn ev_state(&mut self) -> &EventState
Access event-management state
sourcepub fn config_mgr<F: FnMut(&mut ConfigMgr<'_>) -> T, T>(&mut self, f: F) -> T
pub fn config_mgr<F: FnMut(&mut ConfigMgr<'_>) -> T, T>(&mut self, f: F) -> T
Access a ConfigMgr
Access a DrawShared
sourcepub fn draw_device(&mut self) -> &mut dyn Draw
pub fn draw_device(&mut self) -> &mut dyn Draw
Access the low-level draw device
Note: this drawing API is modular, with limited functionality in the
base trait Draw
. To access further functionality, it is necessary
to downcast with crate::draw::DrawIface::downcast_from
.
sourcepub fn draw_iface<DS: DrawSharedImpl>(&mut self) -> Option<DrawIface<'_, DS>>
pub fn draw_iface<DS: DrawSharedImpl>(&mut self) -> Option<DrawIface<'_, DS>>
Access the low-level draw device (implementation type)
The implementing type must be specified. See DrawIface::downcast_from
.
sourcepub fn with_pass<F: FnOnce(DrawMgr<'_>)>(&mut self, f: F)
pub fn with_pass<F: FnOnce(DrawMgr<'_>)>(&mut self, f: F)
Draw to a new pass
Adds a new draw pass for purposes of enforcing draw order. Content of the new pass will be drawn after content in the parent pass.
sourcepub fn with_clip_region<F: FnOnce(DrawMgr<'_>)>(
&mut self,
rect: Rect,
offset: Offset,
f: F
)
pub fn with_clip_region<F: FnOnce(DrawMgr<'_>)>(
&mut self,
rect: Rect,
offset: Offset,
f: F
)
Draw to a new pass with clipping and offset (e.g. for scrolling)
Adds a new draw pass of type PassType::Clip
, with draw operations
clipped to rect
and translated by `offset.
sourcepub fn with_overlay<F: FnOnce(DrawMgr<'_>)>(&mut self, rect: Rect, f: F)
pub fn with_overlay<F: FnOnce(DrawMgr<'_>)>(&mut self, rect: Rect, f: F)
Draw to a new pass as an overlay (e.g. for pop-up menus)
Adds a new draw pass of type PassType::Overlay
, with draw operations
clipped to rect
.
The theme is permitted to enlarge the rect
for the purpose of drawing
a frame or shadow around this overlay, thus the
Self::get_clip_rect
may be larger than expected.
sourcepub fn get_clip_rect(&mut self) -> Rect
pub fn get_clip_rect(&mut self) -> Rect
Target area for drawing
Drawing is restricted to this Rect
, which may be the whole window, a
clip region or an
overlay. This may be used to cull hidden
items from lists inside a scrollable view.
sourcepub fn frame(&mut self, rect: Rect, style: FrameStyle, bg: Background)
pub fn frame(&mut self, rect: Rect, style: FrameStyle, bg: Background)
Draw a frame inside the given rect
The frame dimensions are given by SizeMgr::frame
.
Examples found in repository?
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
fn draw_(&mut self, mut draw: DrawMgr) {
match &mut self.layout {
LayoutType::None => (),
LayoutType::Component(component) => component.draw(draw),
LayoutType::BoxComponent(layout) => layout.draw(draw),
LayoutType::Single(child) | LayoutType::AlignSingle(child, _) => draw.recurse(*child),
LayoutType::Align(layout, _) => layout.draw_(draw),
LayoutType::Pack(layout, _, _) => layout.draw_(draw),
LayoutType::Margins(layout, _, _) => layout.draw_(draw),
LayoutType::Frame(child, storage, style) => {
draw.frame(storage.rect, *style, Background::Default);
child.draw_(draw);
}
LayoutType::Button(child, storage, color) => {
let bg = match color {
Some(rgb) => Background::Rgb(*rgb),
None => Background::Default,
};
draw.frame(storage.rect, FrameStyle::Button, bg);
child.draw_(draw);
}
}
}
sourcepub fn selection_box(&mut self, rect: Rect)
pub fn selection_box(&mut self, rect: Rect)
Draw a selection box
This appears as a dashed box or similar around this rect
. Note that
the selection indicator is drawn outside of this rect, within a margin
of size SizeMgr::inner_margins
that is expected to be present around this box.
sourcepub fn text(&mut self, rect: Rect, text: impl AsRef<TextDisplay>, class: TextClass)
pub fn text(&mut self, rect: Rect, text: impl AsRef<TextDisplay>, class: TextClass)
Draw text
Text is drawn from rect.pos
and clipped to rect
. If the text
scrolls, rect
should be the size of the whole text, not the window.
ConfigMgr::text_set_size
should be called prior to this method to
select a font, font size and wrap options (based on the TextClass
).
sourcepub fn text_effects(&mut self, rect: Rect, text: &dyn TextApi, class: TextClass)
pub fn text_effects(&mut self, rect: Rect, text: &dyn TextApi, class: TextClass)
Draw text with effects
Text is drawn from rect.pos
and clipped to rect
. If the text
scrolls, rect
should be the size of the whole text, not the window.
Self::text
already supports font effects: bold,
emphasis, text size. In addition, this method supports underline and
strikethrough effects.
ConfigMgr::text_set_size
should be called prior to this method to
select a font, font size and wrap options (based on the TextClass
).
sourcepub fn text_selected<R: RangeBounds<usize>>(
&mut self,
rect: Rect,
text: impl AsRef<TextDisplay>,
range: R,
class: TextClass
)
pub fn text_selected<R: RangeBounds<usize>>(
&mut self,
rect: Rect,
text: impl AsRef<TextDisplay>,
range: R,
class: TextClass
)
Draw some text using the standard font, with a subset selected
Other than visually highlighting the selection, this method behaves
identically to Self::text
. It is likely to be replaced in the
future by a higher-level API.
sourcepub fn text_cursor(
&mut self,
rect: Rect,
text: impl AsRef<TextDisplay>,
class: TextClass,
byte: usize
)
pub fn text_cursor(
&mut self,
rect: Rect,
text: impl AsRef<TextDisplay>,
class: TextClass,
byte: usize
)
Draw an edit marker at the given byte
index on this text
The text cursor is draw from rect.pos
and clipped to rect
. If the text
scrolls, rect
should be the size of the whole text, not the window.
ConfigMgr::text_set_size
should be called prior to this method to
select a font, font size and wrap options (based on the TextClass
).
sourcepub fn check_box(
&mut self,
rect: Rect,
checked: bool,
last_change: Option<Instant>
)
pub fn check_box(
&mut self,
rect: Rect,
checked: bool,
last_change: Option<Instant>
)
Draw UI element: check box (without label)
The check box is a small visual element, typically a distinctive square box with or without a “check” selection mark.
The theme may animate transitions. To achieve this, last_change
should be
the time of the last state change caused by the user, or none when the
last state change was programmatic.
sourcepub fn radio_box(
&mut self,
rect: Rect,
checked: bool,
last_change: Option<Instant>
)
pub fn radio_box(
&mut self,
rect: Rect,
checked: bool,
last_change: Option<Instant>
)
Draw UI element: radio box (without label)
The radio box is a small visual element, typically a disinctive circular box with or without a “radio” selection mark.
The theme may animate transitions. To achieve this, last_change
should be
the time of the last state change caused by the user, or none when the
last state change was programmatic.
sourcepub fn scroll_bar<W: Widget>(
&mut self,
track_rect: Rect,
handle: &W,
dir: Direction
)
pub fn scroll_bar<W: Widget>(
&mut self,
track_rect: Rect,
handle: &W,
dir: Direction
)
Draw UI element: scroll bar
sourcepub fn slider<W: Widget>(&mut self, track_rect: Rect, handle: &W, dir: Direction)
pub fn slider<W: Widget>(&mut self, track_rect: Rect, handle: &W, dir: Direction)
Draw UI element: slider
sourcepub fn progress_bar(&mut self, rect: Rect, dir: Direction, value: f32)
pub fn progress_bar(&mut self, rect: Rect, dir: Direction, value: f32)
Draw UI element: progress bar
rect
: area of whole widgetdir
: direction of progress barstate
: highlighting informationvalue
: progress value, between 0.0 and 1.0
Trait Implementations§
source§impl<'a> BitOrAssign<TkAction> for DrawMgr<'a>
impl<'a> BitOrAssign<TkAction> for DrawMgr<'a>
source§fn bitor_assign(&mut self, action: TkAction)
fn bitor_assign(&mut self, action: TkAction)
|=
operation. Read more