Thank you for your help and to spend so much time on my problem.
I've already think of a similar solution but what I would like to avoid is to have a RenderTrait that propose all the rendering method because they depend on the rendering engine. You don't render the same way if you use a vector lib or OpenGL. I have a generic API for the UI behavior like you did with trait and for the rendering I call specific method of the rendering engine. If I update your example the widget draw is :
impl Widget for GTKContainer {
    fn draw(&self, renderer: &mut rendering::Renderer) {
        let myrender = renderer as gtkgraphicAPI  //doesn't work
        myrenderer.gtkdraw_line();
        myrenderer.gtkdraw_rectangle();
    }
}

or

impl Widget for SFMLContainer {
    fn draw(&self, renderer: &mut rendering::Renderer) {
        let myrender = renderer as SFMLrenderer //doesn't work
        myrenderer.sfmldraw_linedRectangle();
    }
}

I have to do a draw method for every renderer but I can draw as I want.
Depending on what renderer you create at the beginning, it isn't the same Widget implementation that it's created.

I didn't manage to make the cast work and I don't see how to use static renderer. As I think about it I'm wandering if I didn't do it the wrong way. The simpler perhaps is to have an GUI API like you did without any drawing function and a renderer API that draw everything behind the scene. Like

trait Widget {
    fn moved(&self, newpos: (int, int));
}

Struct MyWidget;

impl Widget for MyWidget {
fn moved(&self, newpos: (int, int)) {
    update_widget_position();
  }
}

mod SFMLRenderer        {

    fn draw(&my_widget: MyWidget, renderer: SFMLRenderer)   {
        myrenderer.sfmldraw_linedRectangle(MyWidget.get_widget_position());
    }
  }

I have to put the glue that call the right draw but I think I don't have to keep a reference to a renderer visible everywhere.
I'll try to change my code in this way to see if it works.

Philippe




Le 23/02/2014 11:57, Maciej Piechotka a écrit :
On Sat, 2014-02-22 at 22:48 +0100, Philippe Delrieu wrote:
Thank for you reply. But I don't see any solution to my problem.. I'll
explain it a little more.

I want to develop a sort of GUI. The GUI has its own logic and use a
rendering engine to do the work. I want my GUI separate of the
rendering engine.
In the first solution I use a trait that hide the renderer. So I have
a struct that old the renderer that implement the trait. It is created
at the start of ther application and  passed to every GUI call. At the
end the trait is casted to the effective renderer to do the work:

trait Renderer{}
struct MyRender{
     API_render: ~effectiveRenderer,
}

impl Renderer for MyRender{}

struct MyGUIWidget;

impl MyGUIWidget {
     fn draw(&self, renderer: &renderer)    {  //here I know what type
of renderer to use.
         let myrender  = render as &MyRender; //error: non-scalar cast:
`&Renderer<no-bounds>` as `&MyRender`
         myrender.API_render.render();
     }
}

#[main]
fn main() {
     let render = MyRender{API_render: ~...}; //init with user choice
renderer
     let widget = MyGUIWidget;
     widget.draw(render); //draw
}

I didn't find a way to send specific Renderer to an API with a generic
trait and to polymorph it when I know which struct it is.

I can use a singleton or a static variable but static allocation
doesn't seem to be allowed (as I undersdant the documentation).

So I try with closure and I have a sort of example working using a
renderer :
trait Renderer{} //

struct MyRender{
     API_render: ~effectiveRenderer,
}

impl Renderer for MyRender{}


trait Container{
     fn draw(&self, draw_render: ||);
}

struct MyContainer    {
     value :~str,
}

impl Container for MyContainer {
     fn draw(&self, draw_render: ||)    {
         draw_render();
     }
}

#[main]
fn main() {
      let render = MyRender{API_render: ~StringRender}; //init with
user choice renderer
     let container = MyContainer{value: ~"value"};
     container.draw(||    {
         render.API_render.render(container.value);
     }); //draw
}

To extend my API I need to use more closure and if I don't what to
construct every thing in the main I have to return closure constructed
by each widget for example.

My last idea is to use a spawned task that hold the renderer and send
it the widget to draw but It seems to me a little complicated.

So I don't see any simple to do it. If anybody can help, it would be
very helpful.

Philippe

I believe you want something like:

pub mod rendering {
     trait RendererTrait {
         fn draw_line(&mut self);
     }

     pub struct Renderer {
         renderer: ~RendererTrait
     }

     impl Renderer {
         pub fn draw_line(&mut self) {
             self.renderer.draw_line()
         }
     }

     pub fn get_renderer() -> Renderer {
         // TODO: Choose correct renderer
         Renderer {renderer: ~gtk::GtkRenderer}
     }

     mod gtk {
         pub struct GtkRenderer;

         impl ::rendering::RendererTrait for GtkRenderer {
             fn draw_line(&mut self) {}
         }
     }
}

struct Container;

trait Widget {
     fn draw(&self, renderer: &mut rendering::Renderer);
}

impl Widget for Container {
     fn draw(&self, renderer: &mut rendering::Renderer) {
         renderer.draw_line()
     }
}

pub fn main() {
     let mut renderer = rendering::get_renderer();
     let container = Container;
     container.draw(&mut renderer);
}


I'm not expert in rust so I hope I got visibility right - the
rendering::Renderer and rendering::gtk are suppose to be hidden from
user.

Although if user have choice of renderer IMHO something like that would
be better:

pub mod rendering {
     pub trait Renderer {
         fn draw_line(&mut self);
     }

     pub mod gtk {
         pub struct GtkRenderer;

         impl GtkRenderer {
             pub fn new() -> GtkRenderer {
                 GtkRenderer
             }
         }

         impl ::rendering::Renderer for GtkRenderer {
             fn draw_line(&mut self) {}
         }
     }
}

struct Container;

trait Widget {
     fn draw<Renderer : rendering::Renderer>(&self, renderer: &mut
Renderer);
}

impl Widget for Container {
     fn draw<Renderer : rendering::Renderer>(&self, renderer: &mut
Renderer) {
         renderer.draw_line()
     }
}

pub fn main() {
     let mut renderer = rendering::gtk::GtkRenderer::new();
     let container = Container;
     container.draw(&mut renderer);
}

The change is similar to change from lambdas to typeclasses in say
Haskell. YMMV if it is good style in Haskell but it has nice properties
in rust (like static dispatch).

Le 20/02/2014 04:14, Jack Moffitt a écrit :

I'am learning the functional programming paradigm with rust and to help me I
decide to translate the pattern of the book "Functional Programming Patterns
in Scala and Clojure" in Rust. In this work I have a problem to return a
closure (or a function) as a return value and I didn't find any solution. I
understand the problem but I can't find a solution. The code is :
Closures in Rust are stack allocated, so you can't return them from a
function since the function's stack will be gone. You can use either a
proc() or a ~Trait object. A proc can only be called once, but a trait
object can be called many times. If you don't need to close over any
state (which it appears you don't from your example), then you can
return bare functions.

Here's a trait object example (untested and incomplete):

trait Comparison {
   fn compare(&self, p1: &Person, p2: &Person) -> Ordering;
}

fn make_comparison() -> ~Comparison {
   struct ClosedOverState {
      ...
   }
   impl Comparison for ClosedOverState {
     fn compare(...) -> Ordering {
        .... // access state through self.foo
     }
   }

   ~ClosedOverState {
     foo: 0,
   }
}

It can be simplified with macros.

jack.




_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to