0

I'm trying to write code using conrod with a winit/glium backend. Conrod is an intermediate mode graphical user interface library for Rust while wininit provides an event model and glium the OpenGL bindings.

My code draws a grid of values onto a screen with a (row,col), i.e. "text1" at (0,0), "text2", (1,0), "text3" at (0,1) etc. where (row,col) is translated to an absolute (x,y) coordinate.

Basic flow is this:

  1. For each value I want to render as text
  2. Calculate the column / row of the value, i.e. (idx % num_cols, idx / num_cols)
  3. Calculate an x and y from the column and row. i.e. (col * WIDTH, ROW * HEIGHT).
  4. Create a widget::Text at (x, y) containing the value

The code that does this is shown below in a slightly simplified form. The entire file is online here.

This should be simple code to implement but when I run it, the text boxes are not drawn from x=0, y=0 but instead somewhere but not exactly offset from the centre of the view in both axes.

As far as I can tell this shouldn't happen because I am explicitly setting the absolute position and have confirmed the coordinates are correct. So I would expect them to render from the top left of the screen. I don't understand what causes the offset.

Any ideas?

The code that calculates position is this:

fn draw_ui(ui: &mut Ui, model: &mut UiModel) {
    let ui = &mut ui.set_widgets();

    // Canvas is the backdrop to the view
    widget::Canvas::new()
        .color(BACKGROUND_COLOUR)
        .set(model.static_ids.canvas, ui);

    // Create text widgets for each value
    let state = model.session_state.read().unwrap();

    // Create / update the widgets
    if state.values.is_empty() {
        // ... removed
    } else {
        let num_cols: usize = 2;

        state.values.iter().enumerate().for_each(|(i, v)| {
            // Create / update the cell and its state
            let (node_id, value) = v;
            if let Some(id) = model.value_ids.get(node_id) {
                let (col, row) = (i % num_cols, i / num_cols);
                let valid = value.is_valid();
                let value = if let Some(ref value) = value.value {
                    value.to_string()
                } else {
                    "None".to_string()
                };
                // Turn the value into a string to render it
                let (x, y) = (col as f64 * (CELL_WIDTH + PADDING), row as f64 * (CELL_HEIGHT + PADDING));
                value_widget(&value, valid, x, y, CELL_WIDTH, CELL_HEIGHT, model.static_ids.canvas)
                    .set(*id, ui);
            }
        });
    }
}

fn value_widget(value: &str, valid: bool, x: f64, y: f64, w: f64, h: f64, canvas_id: conrod::widget::Id) -> widget::Text {
    let color = if valid { GOOD_COLOUR } else { BAD_COLOUR };
    widget::Text::new(value)
        .x_y(x, y)
        .w(w).h(h)
        .color(color)
}
locka
  • 5,809
  • 3
  • 33
  • 38

1 Answers1

0

I think the 0,0 position is in the center of the window. The slight offset you are seeing comes from the text box position specifying the corner of the text box. To get something in the top left of the window you would want to do something like x_position - 0.5 * window_width + x_margin (similar for y).