Skip to content

Commit 062385c

Browse files
committed
Merge pull request #662 from mitchmindtree/scrolling_refactor
Scrolling refactoring and Bug fixes. Add `Axis` enum arg to `Edge::Position` in graph.
2 parents 935ee46 + d7dbfea commit 062385c

File tree

13 files changed

+822
-766
lines changed

13 files changed

+822
-766
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "conrod"
4-
version = "0.28.0"
4+
version = "0.29.0"
55
authors = [
66
"Mitchell Nordine <mitchell.nordine@gmail.com>",
77
"Sven Nilsen <bvssvni@gmail.com>"

examples/all_widgets.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use conrod::{
3737
};
3838
use conrod::color::{self, rgb};
3939
use piston_window::{EventLoop, Glyphs, PistonWindow, UpdateEvent, WindowSettings};
40+
use std::sync::mpsc;
4041

4142

4243
type Ui = conrod::Ui<Glyphs>;
@@ -76,12 +77,16 @@ struct DemoApp {
7677
circle_pos: Point,
7778
/// Envelope for demonstration of EnvelopeEditor.
7879
envelopes: Vec<(Vec<Point>, String)>,
80+
/// A channel for sending results from the `WidgetMatrix`.
81+
elem_sender: mpsc::Sender<(usize, usize, bool)>,
82+
elem_receiver: mpsc::Receiver<(usize, usize, bool)>,
7983
}
8084

8185
impl DemoApp {
8286

8387
/// Constructor for the Demonstration Application model.
8488
fn new() -> DemoApp {
89+
let (elem_sender, elem_receiver) = mpsc::channel();
8590
DemoApp {
8691
bg_color: rgb(0.2, 0.35, 0.45),
8792
show_button: false,
@@ -114,6 +119,8 @@ impl DemoApp {
114119
[0.3, 0.2],
115120
[0.6, 0.6],
116121
[1.0, 0.0], ], "Envelope B".to_string())],
122+
elem_sender: elem_sender,
123+
elem_receiver: elem_receiver,
117124
}
118125
}
119126

@@ -173,11 +180,16 @@ fn main() {
173180
fn set_widgets(ui: &mut Ui, app: &mut DemoApp) {
174181

175182
// We can use this `Canvas` as a parent Widget upon which we can place other widgets.
176-
Canvas::new().frame(app.frame_width).color(app.bg_color).scrolling(true).set(CANVAS, ui);
183+
Canvas::new()
184+
.frame(app.frame_width)
185+
.pad(30.0)
186+
.color(app.bg_color)
187+
.scroll_kids()
188+
.set(CANVAS, ui);
177189

178190
// Text example.
179191
Text::new("Widget Demonstration")
180-
.top_left_with_margins_on(CANVAS, 25.0, app.title_pad)
192+
.top_left_with_margins_on(CANVAS, 0.0, app.title_pad)
181193
.font_size(32)
182194
.color(app.bg_color.plain_contrast())
183195
.set(TITLE, ui);
@@ -187,7 +199,7 @@ fn set_widgets(ui: &mut Ui, app: &mut DemoApp) {
187199
// Button widget example button.
188200
Button::new()
189201
.w_h(200.0, 50.0)
190-
.mid_left_with_margin_on(CANVAS, 30.0)
202+
.mid_left_of(CANVAS)
191203
.down_from(TITLE, 45.0)
192204
.rgb(0.4, 0.75, 0.6)
193205
.frame(app.frame_width)
@@ -212,7 +224,7 @@ fn set_widgets(ui: &mut Ui, app: &mut DemoApp) {
212224
// Slider widget example slider(value, min, max).
213225
Slider::new(pad as f32, 30.0, 700.0)
214226
.w_h(200.0, 50.0)
215-
.mid_left_with_margin_on(CANVAS, 30.0)
227+
.mid_left_of(CANVAS)
216228
.down_from(TITLE, 45.0)
217229
.rgb(0.5, 0.3, 0.6)
218230
.frame(app.frame_width)
@@ -327,14 +339,20 @@ fn set_widgets(ui: &mut Ui, app: &mut DemoApp) {
327339
// You can return any type that implements `Widget`.
328340
// The returned widget will automatically be positioned and sized to the matrix
329341
// element's rectangle.
330-
let elem = &mut app.bool_matrix[col][row];
331-
Toggle::new(*elem)
342+
let elem = app.bool_matrix[col][row];
343+
let elem_sender = app.elem_sender.clone();
344+
Toggle::new(elem)
332345
.rgba(r, g, b, a)
333346
.frame(app.frame_width)
334-
.react(move |new_val: bool| *elem = new_val)
347+
.react(move |new_val: bool| elem_sender.send((col, row, new_val)).unwrap())
335348
})
336349
.set(TOGGLE_MATRIX, ui);
337350

351+
// Receive updates to the matrix from the `WidgetMatrix`.
352+
while let Ok((col, row, value)) = app.elem_receiver.try_recv() {
353+
app.bool_matrix[col][row] = value;
354+
}
355+
338356
// A demonstration using a DropDownList to select its own color.
339357
let mut ddl_color = app.ddl_color;
340358
DropDownList::new(&mut app.ddl_colors, &mut app.selected_idx)

examples/canvas.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn set_widgets(ui: &mut Ui) {
5252
(MIDDLE_COLUMN, Canvas::new().color(color::ORANGE)),
5353
(RIGHT_COLUMN, Canvas::new().color(color::DARK_ORANGE).pad(20.0)),
5454
])),
55-
(FOOTER, Canvas::new().color(color::BLUE).vertical_scrolling(true)),
55+
(FOOTER, Canvas::new().color(color::BLUE).scroll_kids_vertically()),
5656
]).set(MASTER, ui);
5757

5858
// Now we'll make a couple floating `Canvas`ses.

src/backend/graphics.rs

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,29 @@ pub fn draw_from_graph<G, C>(context: Context,
5353

5454
// If the current widget is some scrollable widget, we need to add a context
5555
// for it to the top of the stack.
56-
if let Some(scrolling) = container.maybe_scrolling {
57-
let context = crop_context(context, scrolling.visible);
56+
//
57+
// TODO: Make this more generic than just "if scrolling crop to kid_area".
58+
if container.maybe_x_scroll_state.is_some()
59+
|| container.maybe_y_scroll_state.is_some() {
60+
let context = crop_context(context, container.kid_area.rect);
5861
scroll_stack.push(context);
5962
}
6063
}
6164
},
6265

6366
Visitable::Scrollbar(idx) => {
64-
if let Some(scrolling) = graph.widget_scroll_state(idx) {
67+
if let Some(widget) = graph.widget(idx) {
6568

6669
// Now that we've come across a scrollbar, we'll pop its Context from the
6770
// scroll_stack and draw it if necessary.
6871
let context = scroll_stack.pop().unwrap_or(context);
6972

7073
// Draw the scrollbar(s)!
71-
draw_scrolling(&context, graphics, scrolling);
74+
draw_scrolling(&context,
75+
graphics,
76+
widget.kid_area.rect,
77+
widget.maybe_x_scroll_state,
78+
widget.maybe_y_scroll_state);
7279
}
7380
}
7481

@@ -174,10 +181,6 @@ pub fn draw_from_container<G, C>(context: &Context,
174181
ShapeStyle::Fill(_) => {
175182
let color = rectangle.style.get_color(theme);
176183
draw_rectangle(context, graphics, container.rect, color);
177-
// let (l, b, w, h) = container.rect.l_b_w_h();
178-
// let lbwh = [l, b, w, h];
179-
// let rectangle = graphics::Rectangle::new(color);
180-
// rectangle.draw(lbwh, &context.draw_state, context.transform, graphics);
181184
},
182185
ShapeStyle::Outline(line_style) => {
183186
let (l, r, b, t) = container.rect.l_r_b_t();
@@ -350,48 +353,48 @@ pub fn draw_lines<G, I>(context: &Context,
350353
/// Draw the scroll bars (if necessary) for the given widget's scroll state.
351354
pub fn draw_scrolling<G>(context: &Context,
352355
graphics: &mut G,
353-
scroll_state: &widget::scroll::State)
356+
kid_area_rect: Rect,
357+
maybe_x_scroll_state: Option<widget::scroll::StateX>,
358+
maybe_y_scroll_state: Option<widget::scroll::StateY>)
354359
where G: Graphics,
355360
{
356361
use widget::scroll;
357362

358-
let color = scroll_state.color;
359-
let track_color = color.alpha(0.2);
360-
let thickness = scroll_state.thickness;
361-
let visible = scroll_state.visible;
362-
363-
let draw_bar = |g: &mut G, bar: scroll::Bar, track: Rect, handle: Rect| {
364-
// We only want to see the scrollbar if it's highlighted or clicked.
365-
if let scroll::Interaction::Normal = bar.interaction {
366-
return;
367-
}
368-
let color = bar.interaction.color(color);
369-
draw_rectangle(context, g, track, track_color);
370-
draw_rectangle(context, g, handle, color);
371-
};
372-
373-
// The element for a vertical scroll Bar.
374-
let vertical = |g: &mut G, bar: scroll::Bar| {
375-
let track = scroll::vertical_track(visible, thickness);
376-
let handle = scroll::vertical_handle(&bar, track, scroll_state.total_dim[1]);
377-
draw_bar(g, bar, track, handle);
378-
};
363+
fn draw_axis<G, A>(context: &Context,
364+
graphics: &mut G,
365+
kid_area_rect: Rect,
366+
scroll_state: &scroll::State<A>)
367+
where G: Graphics,
368+
A: scroll::Axis,
369+
{
370+
use widget::scroll::Elem::{Handle, Track};
371+
use widget::scroll::Interaction::{Highlighted, Clicked};
372+
373+
let color = scroll_state.color;
374+
let track_color = match scroll_state.interaction {
375+
Clicked(Track) => color.highlighted(),
376+
Highlighted(_) | Clicked(_) => color,
377+
_ if scroll_state.is_scrolling => color,
378+
_ => return,
379+
}.alpha(0.2);
380+
let handle_color = match scroll_state.interaction {
381+
Clicked(Handle(_)) => color.clicked(),
382+
Highlighted(_) | Clicked(_) => color,
383+
_ if scroll_state.is_scrolling => color,
384+
_ => return,
385+
};
386+
let thickness = scroll_state.thickness;
387+
let track = scroll::track::<A>(kid_area_rect, thickness);
388+
let handle = scroll::handle::<A>(track, &scroll_state);
389+
draw_rectangle(context, graphics, track, track_color);
390+
draw_rectangle(context, graphics, handle, handle_color);
391+
}
379392

380-
// An element for a horizontal scroll Bar.
381-
let horizontal = |g: &mut G, bar: scroll::Bar| {
382-
let track = scroll::horizontal_track(visible, thickness);
383-
let handle = scroll::horizontal_handle(&bar, track, scroll_state.total_dim[0]);
384-
draw_bar(g, bar, track, handle);
385-
};
393+
if let Some(ref scroll_state) = maybe_y_scroll_state {
394+
draw_axis::<G, scroll::Y>(context, graphics, kid_area_rect, scroll_state)
395+
}
386396

387-
// Whether we draw horizontal or vertical or both depends on our state.
388-
match (scroll_state.maybe_vertical, scroll_state.maybe_horizontal) {
389-
(Some(v_bar), Some(h_bar)) => {
390-
horizontal(graphics, h_bar);
391-
vertical(graphics, v_bar);
392-
},
393-
(Some(bar), None) => vertical(graphics, bar),
394-
(None, Some(bar)) => horizontal(graphics, bar),
395-
(None, None) => (),
397+
if let Some(ref scroll_state) = maybe_x_scroll_state {
398+
draw_axis::<G, scroll::X>(context, graphics, kid_area_rect, scroll_state)
396399
}
397400
}

0 commit comments

Comments
 (0)