<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// The task that handles all rendering/painting.

use azure::azure_hl::{B8G8R8A8, Color, DrawTarget, StolenGLResources};
use azure::AzFloat;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
use layers::platform::surface::{NativeSurfaceMethods};
use layers;
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet};
use servo_msg::compositor_msg::{RenderListener, RenderingRenderState};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg};
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
use servo_util::task::spawn_named;

use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc;

use buffer_map::BufferMap;
use font_context::{FontContext, FontContextInfo};
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo};
use opts::Opts;
use render_context::RenderContext;

pub struct RenderLayer<T> {
    display_list_collection: Arc<DisplayListCollection<T>>,
    size: Size2D<uint>,
    color: Color
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Chan<()>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

// FIXME(rust#9155): this should be a newtype struct, but
// generic newtypes ICE when compiled cross-crate
pub struct RenderChan<T> {
    chan: SharedChan<Msg<T>>,
}

impl<T: Send> Clone for RenderChan<T> {
    fn clone(&self) -> RenderChan<T> {
        RenderChan {
            chan: self.chan.clone(),
        }
    }
}

impl<T: Send> RenderChan<T> {
    pub fn new() -> (Port<Msg<T>>, RenderChan<T>) {
        let (port, chan) = SharedChan::new();
        let render_chan = RenderChan {
            chan: chan,
        };
        (port, render_chan)
    }

    pub fn send(&self, msg: Msg<T>) {
        assert!(self.try_send(msg), "RenderChan.send: render port closed")
    }

    pub fn try_send(&self, msg: Msg<T>) -> bool {
        self.chan.try_send(msg)
    }
}

/// If we're using GPU rendering, this provides the metadata needed to create a GL context that
/// is compatible with that of the main thread.
enum GraphicsContext {
    CpuGraphicsContext,
    GpuGraphicsContext,
}

pub struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    constellation_chan: ConstellationChan,
    font_ctx: ~FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    /// The graphics context to use.
    graphics_context: GraphicsContext,

    /// The native graphics context.
    native_graphics_context: Option<NativePaintingGraphicsContext>,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,

    /// Permission to send paint messages to the compositor
    paint_permission: bool,

    /// A counter for epoch messages
    epoch: Epoch,

    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

// If we implement this as a function, we get borrowck errors from borrowing
// the whole RenderTask struct.
macro_rules! native_graphics_context(
    ($task:expr) => (
        $task.native_graphics_context.as_ref().expect("Need a graphics context to do rendering")
    )
)

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  constellation_chan: ConstellationChan,
                  opts: Opts,
                  profiler_chan: ProfilerChan,
                  shutdown_chan: Chan<()>) {
        spawn_named("RenderTask", proc() {

            { // Ensures RenderTask and graphics context are destroyed before shutdown msg
                let native_graphics_context = compositor.get_graphics_metadata().map(
                    |md| NativePaintingGraphicsContext::from_metadata(&md));
                let cpu_painting = opts.cpu_painting;

                // FIXME: rust/#5967
                let mut render_task = RenderTask {
                    id: id,
                    port: port,
                    compositor: compositor,
                    constellation_chan: constellation_chan,
                    font_ctx: ~FontContext::new(FontContextInfo {
                        backend: opts.render_backend.clone(),
                        needs_font_list: false,
                        profiler_chan: profiler_chan.clone(),
                    }),
                    opts: opts,
                    profiler_chan: profiler_chan,

                    graphics_context: if cpu_painting {
                        CpuGraphicsContext
                    } else {
                        GpuGraphicsContext
                    },

                    native_graphics_context: native_graphics_context,

                    render_layer: None,

                    paint_permission: false,
                    epoch: Epoch(0),
                    buffer_map: BufferMap::new(10000000),
                };

                render_task.start();

                // Destroy all the buffers.
                render_task.native_graphics_context.as_ref().map(
                    |ctx| render_task.buffer_map.clear(ctx));
            }

            debug!("render_task: shutdown_chan send");
            shutdown_chan.send(());
        });
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                    } else {
                        debug!("render_task: render ready msg");
                        self.constellation_chan.send(RendererReadyMsg(self.id));
                    }
                    self.render_layer = Some(render_layer);
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: {:?} != {:?}", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(native_graphics_context!(self), buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                        }
                        None => {}
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    debug!("render_task: exitmsg response send");
                    response_ch.send(());
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        let render_layer;
        match self.render_layer {
            Some(ref r_layer) => {
                render_layer = r_layer;
            }
            _ => return, // nothing to do
        }

        self.compositor.set_render_state(RenderingRenderState);
        time::profile(time::RenderingCategory, self.profiler_chan.clone(), || {
            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone(), || {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let size = Size2D(width as i32, height as i32);
                    let draw_target = match self.graphics_context {
                        CpuGraphicsContext => {
                            DrawTarget::new(self.opts.render_backend, size, B8G8R8A8)
                        }
                        GpuGraphicsContext => {
                            // FIXME(pcwalton): Cache the components of draw targets
                            // (texture color buffer, renderbuffers) instead of recreating them.
                            let draw_target =
                                DrawTarget::new_with_fbo(self.opts.render_backend,
                                                         native_graphics_context!(self),
                                                         size,
                                                         B8G8R8A8);
                            draw_target.make_current();
                            draw_target
                        }
                    };

                    {
                        // Build the render context.
                        let mut ctx = RenderContext {
                            draw_target: &draw_target,
                            font_ctx: &mut self.font_ctx,
                            opts: &self.opts,
                            page_rect: tile.page_rect,
                            screen_rect: tile.screen_rect,
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
                                                      -(tile.page_rect.origin.y) as AzFloat);

                        ctx.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
                            render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
                            ctx.draw_target.flush();
                        });
                    }

                    // Extract the texture from the draw target and place it into its slot in the
                    // buffer. If using CPU rendering, upload it first.
                    //
                    // FIXME(pcwalton): We should supply the texture and native surface *to* the
                    // draw target in GPU rendering mode, so that it doesn't have to recreate it.
                    let buffer = match self.graphics_context {
                        CpuGraphicsContext => {
                            let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                                Some(buffer) => {
                                    let mut buffer = buffer;
                                    buffer.rect = tile.page_rect;
                                    buffer.screen_pos = tile.screen_rect;
                                    buffer.resolution = scale;
                                    buffer.native_surface.mark_wont_leak();
                                    buffer
                                }
                                None => {
                                    // Create an empty native surface. We mark it as not leaking
                                    // in case it dies in transit to the compositor task.
                                    let mut native_surface: NativeSurface =
                                        layers::platform::surface::NativeSurfaceMethods::new(
                                            native_graphics_context!(self),
                                            Size2D(width as i32, height as i32),
                                            width as i32 * 4);
                                    native_surface.mark_wont_leak();

                                    ~LayerBuffer {
                                        native_surface: native_surface,
                                        rect: tile.page_rect,
                                        screen_pos: tile.screen_rect,
                                        resolution: scale,
                                        stride: (width * 4) as uint
                                    }
                                }
                            };

                            draw_target.snapshot().get_data_surface().with_data(|data| {
                                buffer.native_surface.upload(native_graphics_context!(self), data);
                                debug!("RENDERER uploading to native surface {:d}",
                                       buffer.native_surface.get_id() as int);
                            });

                            buffer
                        }
                        GpuGraphicsContext => {
                            draw_target.make_current();
                            let StolenGLResources {
                                surface: native_surface
                            } = draw_target.steal_gl_resources().unwrap();

                            // We mark the native surface as not leaking in case the surfaces
                            // die on their way to the compositor task.
                            let mut native_surface: NativeSurface =
                                NativeSurfaceAzureMethods::from_azure_surface(native_surface);
                            native_surface.mark_wont_leak();

                            ~LayerBuffer {
                                native_surface: native_surface,
                                rect: tile.page_rect,
                                screen_pos: tile.screen_rect,
                                resolution: scale,
                                stride: (width * 4) as uint
                            }
                        }
                    };

                    new_buffers.push(buffer);
                }
            });

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set, self.epoch);
            } else {
                debug!("render_task: RendererReadyMsg send");
                self.constellation_chan.send(RendererReadyMsg(self.id));
            }
            self.compositor.set_render_state(IdleRenderState);
        })
    }
}

<commit_msg>auto merge of #1606 : Ms2ger/servo/unused-import, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// The task that handles all rendering/painting.

use azure::azure_hl::{B8G8R8A8, Color, DrawTarget, StolenGLResources};
use azure::AzFloat;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
use layers::platform::surface::{NativeSurfaceMethods};
use layers;
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet};
use servo_msg::compositor_msg::{RenderListener, RenderingRenderState};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg};
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
use servo_util::task::spawn_named;

use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc;

use buffer_map::BufferMap;
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo};
use opts::Opts;
use render_context::RenderContext;

pub struct RenderLayer<T> {
    display_list_collection: Arc<DisplayListCollection<T>>,
    size: Size2D<uint>,
    color: Color
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Chan<()>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

// FIXME(rust#9155): this should be a newtype struct, but
// generic newtypes ICE when compiled cross-crate
pub struct RenderChan<T> {
    chan: SharedChan<Msg<T>>,
}

impl<T: Send> Clone for RenderChan<T> {
    fn clone(&self) -> RenderChan<T> {
        RenderChan {
            chan: self.chan.clone(),
        }
    }
}

impl<T: Send> RenderChan<T> {
    pub fn new() -> (Port<Msg<T>>, RenderChan<T>) {
        let (port, chan) = SharedChan::new();
        let render_chan = RenderChan {
            chan: chan,
        };
        (port, render_chan)
    }

    pub fn send(&self, msg: Msg<T>) {
        assert!(self.try_send(msg), "RenderChan.send: render port closed")
    }

    pub fn try_send(&self, msg: Msg<T>) -> bool {
        self.chan.try_send(msg)
    }
}

/// If we're using GPU rendering, this provides the metadata needed to create a GL context that
/// is compatible with that of the main thread.
enum GraphicsContext {
    CpuGraphicsContext,
    GpuGraphicsContext,
}

pub struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    constellation_chan: ConstellationChan,
    font_ctx: ~FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    /// The graphics context to use.
    graphics_context: GraphicsContext,

    /// The native graphics context.
    native_graphics_context: Option<NativePaintingGraphicsContext>,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,

    /// Permission to send paint messages to the compositor
    paint_permission: bool,

    /// A counter for epoch messages
    epoch: Epoch,

    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

// If we implement this as a function, we get borrowck errors from borrowing
// the whole RenderTask struct.
macro_rules! native_graphics_context(
    ($task:expr) => (
        $task.native_graphics_context.as_ref().expect("Need a graphics context to do rendering")
    )
)

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  constellation_chan: ConstellationChan,
                  opts: Opts,
                  profiler_chan: ProfilerChan,
                  shutdown_chan: Chan<()>) {
        spawn_named("RenderTask", proc() {

            { // Ensures RenderTask and graphics context are destroyed before shutdown msg
                let native_graphics_context = compositor.get_graphics_metadata().map(
                    |md| NativePaintingGraphicsContext::from_metadata(&md));
                let cpu_painting = opts.cpu_painting;

                // FIXME: rust/#5967
                let mut render_task = RenderTask {
                    id: id,
                    port: port,
                    compositor: compositor,
                    constellation_chan: constellation_chan,
                    font_ctx: ~FontContext::new(FontContextInfo {
                        backend: opts.render_backend.clone(),
                        needs_font_list: false,
                        profiler_chan: profiler_chan.clone(),
                    }),
                    opts: opts,
                    profiler_chan: profiler_chan,

                    graphics_context: if cpu_painting {
                        CpuGraphicsContext
                    } else {
                        GpuGraphicsContext
                    },

                    native_graphics_context: native_graphics_context,

                    render_layer: None,

                    paint_permission: false,
                    epoch: Epoch(0),
                    buffer_map: BufferMap::new(10000000),
                };

                render_task.start();

                // Destroy all the buffers.
                render_task.native_graphics_context.as_ref().map(
                    |ctx| render_task.buffer_map.clear(ctx));
            }

            debug!("render_task: shutdown_chan send");
            shutdown_chan.send(());
        });
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                    } else {
                        debug!("render_task: render ready msg");
                        self.constellation_chan.send(RendererReadyMsg(self.id));
                    }
                    self.render_layer = Some(render_layer);
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: {:?} != {:?}", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(native_graphics_context!(self), buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                        }
                        None => {}
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    debug!("render_task: exitmsg response send");
                    response_ch.send(());
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        let render_layer;
        match self.render_layer {
            Some(ref r_layer) => {
                render_layer = r_layer;
            }
            _ => return, // nothing to do
        }

        self.compositor.set_render_state(RenderingRenderState);
        time::profile(time::RenderingCategory, self.profiler_chan.clone(), || {
            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone(), || {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let size = Size2D(width as i32, height as i32);
                    let draw_target = match self.graphics_context {
                        CpuGraphicsContext => {
                            DrawTarget::new(self.opts.render_backend, size, B8G8R8A8)
                        }
                        GpuGraphicsContext => {
                            // FIXME(pcwalton): Cache the components of draw targets
                            // (texture color buffer, renderbuffers) instead of recreating them.
                            let draw_target =
                                DrawTarget::new_with_fbo(self.opts.render_backend,
                                                         native_graphics_context!(self),
                                                         size,
                                                         B8G8R8A8);
                            draw_target.make_current();
                            draw_target
                        }
                    };

                    {
                        // Build the render context.
                        let mut ctx = RenderContext {
                            draw_target: &draw_target,
                            font_ctx: &mut self.font_ctx,
                            opts: &self.opts,
                            page_rect: tile.page_rect,
                            screen_rect: tile.screen_rect,
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
                                                      -(tile.page_rect.origin.y) as AzFloat);

                        ctx.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
                            render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
                            ctx.draw_target.flush();
                        });
                    }

                    // Extract the texture from the draw target and place it into its slot in the
                    // buffer. If using CPU rendering, upload it first.
                    //
                    // FIXME(pcwalton): We should supply the texture and native surface *to* the
                    // draw target in GPU rendering mode, so that it doesn't have to recreate it.
                    let buffer = match self.graphics_context {
                        CpuGraphicsContext => {
                            let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                                Some(buffer) => {
                                    let mut buffer = buffer;
                                    buffer.rect = tile.page_rect;
                                    buffer.screen_pos = tile.screen_rect;
                                    buffer.resolution = scale;
                                    buffer.native_surface.mark_wont_leak();
                                    buffer
                                }
                                None => {
                                    // Create an empty native surface. We mark it as not leaking
                                    // in case it dies in transit to the compositor task.
                                    let mut native_surface: NativeSurface =
                                        layers::platform::surface::NativeSurfaceMethods::new(
                                            native_graphics_context!(self),
                                            Size2D(width as i32, height as i32),
                                            width as i32 * 4);
                                    native_surface.mark_wont_leak();

                                    ~LayerBuffer {
                                        native_surface: native_surface,
                                        rect: tile.page_rect,
                                        screen_pos: tile.screen_rect,
                                        resolution: scale,
                                        stride: (width * 4) as uint
                                    }
                                }
                            };

                            draw_target.snapshot().get_data_surface().with_data(|data| {
                                buffer.native_surface.upload(native_graphics_context!(self), data);
                                debug!("RENDERER uploading to native surface {:d}",
                                       buffer.native_surface.get_id() as int);
                            });

                            buffer
                        }
                        GpuGraphicsContext => {
                            draw_target.make_current();
                            let StolenGLResources {
                                surface: native_surface
                            } = draw_target.steal_gl_resources().unwrap();

                            // We mark the native surface as not leaking in case the surfaces
                            // die on their way to the compositor task.
                            let mut native_surface: NativeSurface =
                                NativeSurfaceAzureMethods::from_azure_surface(native_surface);
                            native_surface.mark_wont_leak();

                            ~LayerBuffer {
                                native_surface: native_surface,
                                rect: tile.page_rect,
                                screen_pos: tile.screen_rect,
                                resolution: scale,
                                stride: (width * 4) as uint
                            }
                        }
                    };

                    new_buffers.push(buffer);
                }
            });

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set, self.epoch);
            } else {
                debug!("render_task: RendererReadyMsg send");
                self.constellation_chan.send(RendererReadyMsg(self.id));
            }
            self.compositor.set_render_state(IdleRenderState);
        })
    }
}

<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]

#[repr(packed)]
struct Foo {
    x: i32,
    y: i32,
}

fn main() {
    let foo = Foo {
        x: 42,
        y: 99,
    };
    let p: *const i32 = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
    let x = unsafe { *p + foo.x };
}
<commit_msg>remove redundant test<commit_after><|endoftext|>


<commit_before>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

pub mod path;
pub mod tag;

#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self
    where
        T: Into<String>,
    {
        Element {
            name: name.into(),
            attributes: Attributes::new(),
            children: Children::new(),
        }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                }
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                }
                _ => {}
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T)
    where
        T: Node,
    {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident)*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        impl $struct_name {
            /// Create a node.
            #[inline]
            pub fn new() -> Self {
                $struct_name {
                    inner: Element::new(tag::$struct_name),
                }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`animate`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateElement"]
    struct Animate

    #[doc = "An [`animateColor`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateColorElement"]
    struct AnimateColor

    #[doc = "An [`animateMotion`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement"]
    struct AnimateMotion

    #[doc = "An [`animateTransform`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement"]
    struct AnimateTransform

    #[doc = "A [`circle`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#CircleElement"]
    struct Circle

    #[doc = "A [`clipPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#ClipPathElement"]
    struct ClipPath

    #[doc = "A [`defs`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DefsElement"]
    struct Definitions

    #[doc = "A [`desc`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DescElement"]
    struct Description

    #[doc = "An [`ellipse`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#EllipseElement"]
    struct Ellipse

    #[doc = "A [`filter`][1] element.
    [1]: https://www.w3.org/TR/SVG/filters.html#FilterElement"]
    struct Filter

    #[doc = "A [`g`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#GElement"]
    struct Group

    #[doc = "An [`image`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#ImageElement"]
    struct Image

    #[doc = "A [`line`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#LineElement"]
    struct Line

    #[doc = "A [`linearGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement"]
    struct LinearGradient

    #[doc = "An [`a`][1] element.
    [1]: https://www.w3.org/TR/SVG/linking.html#AElement"]
    struct Link

    #[doc = "A [`marker`][1] element.
    [1]: https://www.w3.org/TR/SVG/painting.html#MarkerElement"]
    struct Marker

    #[doc = "A [`mask`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#MaskElement"]
    struct Mask

    #[doc = "An [`mpath`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#MPathElement"]
    struct MotionPath

    #[doc = "A [`path`][1] element.
    [1]: https://www.w3.org/TR/SVG/paths.html#PathElement"]
    struct Path

    #[doc = "A [`pattern`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#PatternElement"]
    struct Pattern

    #[doc = "A [`polygon`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolygonElement"]
    struct Polygon

    #[doc = "A [`polyline`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolylineElement"]
    struct Polyline

    #[doc = "A [`radialGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement"]
    struct RadialGradient

    #[doc = "A [`rect`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#RectElement"]
    struct Rectangle

    #[doc = "A [`stop`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#StopElement"]
    struct Stop

    #[doc = "A [`symbol`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SymbolElement"]
    struct Symbol

    #[doc = "A [`text`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextElement"]
    struct Text

    #[doc = "A [`textPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextPathElement"]
    struct TextPath

    #[doc = "A [`title`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#TitleElement"]
    struct Title

    #[doc = "A [`use`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#UseElement"]
    struct Use
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    ($(
        #[$doc:meta]
        struct $struct_name:ident
        [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
    )*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        implement! { @itemize
            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                    #[inline(always)]
                    fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                    let mut inner = Element::new(tag::$struct_name);
                    initialize(&mut inner $(, $an)*);
                    $struct_name {
                        inner: inner,
                    }
                }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`svg`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SVGElement"]
    struct SVG [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`][1] element.
    [1]: https://www.w3.org/TR/SVG/script.html#ScriptElement"]
    struct Script [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`][1] element.
    [1]: https://www.w3.org/TR/SVG/styling.html#StyleElement"]
    struct Style [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));

        assert_eq!(
            element.to_string(),
            "<foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
             <bar/>\n\
             </foo>\
             "
        );
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);

        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");

        assert_eq!(
            element.to_string(),
            "<style>\n\
             * { font-family: foo; }\n\
             </style>\
             "
        );
    }
}
<commit_msg>Fix the links in the element module<commit_after>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

pub mod path;
pub mod tag;

#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self
    where
        T: Into<String>,
    {
        Element {
            name: name.into(),
            attributes: Attributes::new(),
            children: Children::new(),
        }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                }
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                }
                _ => {}
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T)
    where
        T: Node,
    {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U)
    where
        T: Into<String>,
        U: Into<Value>,
    {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident)*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        impl $struct_name {
            /// Create a node.
            #[inline]
            pub fn new() -> Self {
                $struct_name {
                    inner: Element::new(tag::$struct_name),
                }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`animate`](https://www.w3.org/TR/SVG/animate.html#AnimateElement) element."]
    struct Animate

    #[doc = "An [`animateColor`](https://www.w3.org/TR/SVG/animate.html#AnimateColorElement) element."]
    struct AnimateColor

    #[doc = "An [`animateMotion`](https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement) element."]
    struct AnimateMotion

    #[doc = "An [`animateTransform`](https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement) element."]
    struct AnimateTransform

    #[doc = "A [`circle`](https://www.w3.org/TR/SVG/shapes.html#CircleElement) element."]
    struct Circle

    #[doc = "A [`clipPath`](https://www.w3.org/TR/SVG/masking.html#ClipPathElement) element."]
    struct ClipPath

    #[doc = "A [`defs`](https://www.w3.org/TR/SVG/struct.html#DefsElement) element."]
    struct Definitions

    #[doc = "A [`desc`](https://www.w3.org/TR/SVG/struct.html#DescElement) element."]
    struct Description

    #[doc = "An [`ellipse`](https://www.w3.org/TR/SVG/shapes.html#EllipseElement) element."]
    struct Ellipse

    #[doc = "A [`filter`](https://www.w3.org/TR/SVG/filters.html#FilterElement) element."]
    struct Filter

    #[doc = "A [`g`](https://www.w3.org/TR/SVG/struct.html#GElement) element."]
    struct Group

    #[doc = "An [`image`](https://www.w3.org/TR/SVG/struct.html#ImageElement) element."]
    struct Image

    #[doc = "A [`line`](https://www.w3.org/TR/SVG/shapes.html#LineElement) element."]
    struct Line

    #[doc = "A [`linearGradient`](https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement) element."]
    struct LinearGradient

    #[doc = "An [`a`](https://www.w3.org/TR/SVG/linking.html#AElement) element."]
    struct Link

    #[doc = "A [`marker`](https://www.w3.org/TR/SVG/painting.html#MarkerElement) element."]
    struct Marker

    #[doc = "A [`mask`](https://www.w3.org/TR/SVG/masking.html#MaskElement) element."]
    struct Mask

    #[doc = "An [`mpath`](https://www.w3.org/TR/SVG/animate.html#MPathElement) element."]
    struct MotionPath

    #[doc = "A [`path`](https://www.w3.org/TR/SVG/paths.html#PathElement) element."]
    struct Path

    #[doc = "A [`pattern`](https://www.w3.org/TR/SVG/pservers.html#PatternElement) element."]
    struct Pattern

    #[doc = "A [`polygon`](https://www.w3.org/TR/SVG/shapes.html#PolygonElement) element."]
    struct Polygon

    #[doc = "A [`polyline`](https://www.w3.org/TR/SVG/shapes.html#PolylineElement) element."]
    struct Polyline

    #[doc = "A [`radialGradient`](https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement) element."]
    struct RadialGradient

    #[doc = "A [`rect`](https://www.w3.org/TR/SVG/shapes.html#RectElement) element."]
    struct Rectangle

    #[doc = "A [`stop`](https://www.w3.org/TR/SVG/pservers.html#StopElement) element."]
    struct Stop

    #[doc = "A [`symbol`](https://www.w3.org/TR/SVG/struct.html#SymbolElement) element."]
    struct Symbol

    #[doc = "A [`text`](https://www.w3.org/TR/SVG/text.html#TextElement) element."]
    struct Text

    #[doc = "A [`textPath`](https://www.w3.org/TR/SVG/text.html#TextPathElement) element."]
    struct TextPath

    #[doc = "A [`title`](https://www.w3.org/TR/SVG/struct.html#TitleElement) element."]
    struct Title

    #[doc = "A [`use`](https://www.w3.org/TR/SVG/struct.html#UseElement) element."]
    struct Use
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    ($(
        #[$doc:meta]
        struct $struct_name:ident
        [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
    )*) => ($(
        #[$doc]
        #[derive(Clone, Debug)]
        pub struct $struct_name {
            inner: Element,
        }

        implement! { @itemize
            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                    #[inline(always)]
                    fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                    let mut inner = Element::new(tag::$struct_name);
                    initialize(&mut inner $(, $an)*);
                    $struct_name {
                        inner: inner,
                    }
                }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`svg`](https://www.w3.org/TR/SVG/struct.html#SVGElement) element."]
    struct SVG [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`](https://www.w3.org/TR/SVG/script.html#ScriptElement) element."]
    struct Script [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`](https://www.w3.org/TR/SVG/styling.html#StyleElement) element."]
    struct Style [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));

        assert_eq!(
            element.to_string(),
            "<foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
             <bar/>\n\
             </foo>\
             "
        );
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);

        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");

        assert_eq!(
            element.to_string(),
            "<style>\n\
             * { font-family: foo; }\n\
             </style>\
             "
        );
    }
}
<|endoftext|>


<commit_before>//! Extension trait and implementation for observing and action on streamed data.

use Data;
use dataflow::channels::pact::Pipeline;
use dataflow::{Stream, Scope};
use dataflow::operators::generic::unary::Unary;

/// Methods to inspect records and batches of records on a stream.
pub trait Inspect<G: Scope, D: Data>: Sized {
    /// Runs a supplied closure on each observed data element.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect(|x| println!("seen: {:?}", x));
    /// });
    /// ```
    fn inspect(&self, mut func: impl FnMut(&D)+'static) -> Self {
        self.inspect_batch(move |_, data| {
            for datum in data.iter() { func(datum); }
        })
    }

    /// Runs a supplied closure on each observed data element and associated time.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_time(|t, x| println!("seen at: {:?}\t{:?}", t, x));
    /// });
    /// ```
    fn inspect_time(&self, mut func: impl FnMut(&G::Timestamp, &D)+'static) -> Self {
        self.inspect_batch(move |time, data| {
            for datum in data.iter() {
                func(&time, &datum);
            }
        })
    }

    /// Runs a supplied closure on each observed data batch (time and data slice).
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_batch(|t,xs| println!("seen at: {:?}\t{:?} records", t, xs.len()));
    /// });
    /// ```
    fn inspect_batch(&self, func: impl FnMut(&G::Timestamp, &[D])+'static) -> Self;
}

impl<G: Scope, D: Data> Inspect<G, D> for Stream<G, D> {
    fn inspect_batch(&self, mut func: impl FnMut(&G::Timestamp, &[D])+'static) -> Stream<G, D> {
        self.unary_stream(Pipeline, "InspectBatch", move |input, output| {
            input.for_each(|time, data| {
                func(&time, &data[..]);
                output.session(&time).give_content(data);
            });
        })
    }
}
<commit_msg>Return Stream<G, D> in Inspect trait, remove Sized<commit_after>//! Extension trait and implementation for observing and action on streamed data.

use Data;
use dataflow::channels::pact::Pipeline;
use dataflow::{Stream, Scope};
use dataflow::operators::generic::unary::Unary;

/// Methods to inspect records and batches of records on a stream.
pub trait Inspect<G: Scope, D: Data> {
    /// Runs a supplied closure on each observed data element.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect(|x| println!("seen: {:?}", x));
    /// });
    /// ```
    fn inspect(&self, mut func: impl FnMut(&D)+'static) -> Stream<G, D> {
        self.inspect_batch(move |_, data| {
            for datum in data.iter() { func(datum); }
        })
    }

    /// Runs a supplied closure on each observed data element and associated time.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_time(|t, x| println!("seen at: {:?}\t{:?}", t, x));
    /// });
    /// ```
    fn inspect_time(&self, mut func: impl FnMut(&G::Timestamp, &D)+'static) -> Stream<G, D> {
        self.inspect_batch(move |time, data| {
            for datum in data.iter() {
                func(&time, &datum);
            }
        })
    }

    /// Runs a supplied closure on each observed data batch (time and data slice).
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_batch(|t,xs| println!("seen at: {:?}\t{:?} records", t, xs.len()));
    /// });
    /// ```
    fn inspect_batch(&self, func: impl FnMut(&G::Timestamp, &[D])+'static) -> Stream<G, D>;
}

impl<G: Scope, D: Data> Inspect<G, D> for Stream<G, D> {
    fn inspect_batch(&self, mut func: impl FnMut(&G::Timestamp, &[D])+'static) -> Stream<G, D> {
        self.unary_stream(Pipeline, "InspectBatch", move |input, output| {
            input.for_each(|time, data| {
                func(&time, &data[..]);
                output.session(&time).give_content(data);
            });
        })
    }
}
<|endoftext|>


<commit_before>#![crate_type = "bin"]
#![feature(collections)]

extern crate gtk;
extern crate glib;
extern crate sysinfo;

use gtk::{WindowTrait, ContainerTrait, WidgetTrait, ButtonSignals, BoxTrait};
use gtk::{Orientation};
use sysinfo::*;
use gtk::signal::Inhibit;
use gtk::signal::{WidgetSignals, TreeViewSignals};
use std::collections::VecMap;
use std::str::FromStr;
use std::rc::Rc;
use std::cell::{RefCell};

struct NoteBook {
    notebook: gtk::NoteBook,
    tabs: Vec<gtk::Box>
}

impl NoteBook {
    fn new() -> NoteBook {
        NoteBook {
            notebook: gtk::NoteBook::new().unwrap(),
            tabs: Vec::new()
        }
    }

    fn create_tab<'a, Widget: gtk::WidgetTrait>(&mut self, title: &'a str, widget: &Widget) -> Option<u32> {
        let label = gtk::Label::new(title).unwrap();
        let tab = gtk::Box::new(Orientation::Horizontal, 0).unwrap();

        tab.pack_start(&label, false, false, 0);
        tab.show_all();

        let index = match self.notebook.append_page(widget, Some(&tab)) {
            Some(index) => index,
            _ => return None
        };

        self.tabs.push(tab);

        Some(index)
    }
}

struct Procs {
    left_tree: gtk::TreeView,
    scroll: gtk::ScrolledWindow,
    current_pid: Rc<RefCell<Option<String>>>,
    kill_button: Rc<RefCell<gtk::Button>>,
    vertical_layout: gtk::Box,
    list_store: gtk::ListStore
}

impl Procs {
    pub fn new<'a>(proc_list: &VecMap<Processus>) -> Procs {
        let left_tree = gtk::TreeView::new().unwrap();
        let scroll = gtk::ScrolledWindow::new(None, None).unwrap();
        let current_pid = Rc::new(RefCell::new(None));
        let kill_button = Rc::new(RefCell::new(gtk::Button::new_with_label("End task").unwrap()));
        let current_pid1 = current_pid.clone();
        let current_pid2 = current_pid.clone();
        let kill_button1 = kill_button.clone();

        scroll.set_min_content_height(800);
        scroll.set_min_content_width(600);

        let mut columns : Vec<gtk::TreeViewColumn> = Vec::new();

        append_column("pid", &mut columns);
        append_column("process name", &mut columns);
        append_column("cpu usage", &mut columns);
        append_column("memory usage", &mut columns);

        for i in columns {
            left_tree.append_column(&i);
        }

        let mut list_store = gtk::ListStore::new(&[glib::Type::String, glib::Type::String, glib::Type::String, glib::Type::String]).unwrap();
        for (_, pro) in proc_list {
            create_and_fill_model(&mut list_store, pro.pid, &pro.name, pro.cpu_usage, pro.memory);
        }

        left_tree.set_model(&list_store.get_model().unwrap());
        left_tree.set_headers_visible(true);
        scroll.add(&left_tree);
        let vertical_layout = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();

        left_tree.connect_cursor_changed(move |tree_view| {
            match tree_view.get_selection() {
                Some(selection) => {
                    let model = tree_view.get_model().unwrap();
                    let mut iter = gtk::TreeIter::new();

                    if selection.get_selected(&model, &mut iter) {
                        let pid = model.get_value(&iter, 0).get_string();
                        let mut tmp = current_pid1.borrow_mut();
                        *tmp = pid;
                    }
                    (*kill_button1.borrow_mut()).set_sensitive((*current_pid.borrow()).is_some());
                }
                None => {
                    let mut tmp = current_pid1.borrow_mut();
                    *tmp = None;
                }
            }
        });
        (*kill_button.borrow_mut()).set_sensitive(false);

        vertical_layout.add(&scroll);
        vertical_layout.add(&(*kill_button.borrow_mut()));
        Procs {
            left_tree: left_tree,
            scroll: scroll,
            current_pid: current_pid2.clone(),
            kill_button: kill_button,
            vertical_layout: vertical_layout,
            list_store: list_store
        }
    }
}

fn append_column(title: &str, v: &mut Vec<gtk::TreeViewColumn>) {
    let l = v.len();
    let renderer = gtk::CellRendererText::new().unwrap();

    v.push(gtk::TreeViewColumn::new().unwrap());
    let tmp = v.get_mut(l).unwrap();

    tmp.set_title(title);
    tmp.pack_start(&renderer, true);
    tmp.add_attribute(&renderer, "text", l as i32);
}

fn create_and_fill_model(list_store: &mut gtk::ListStore, pid: i64, name: &str, cpu: f32, memory: u64) {
    if name.len() < 1 {
        return;
    }
    let mut top_level = gtk::TreeIter::new();

    list_store.append(&mut top_level);
    list_store.set_string(&top_level, 0, &format!("{}", pid));
    list_store.set_string(&top_level, 1, name);
    list_store.set_string(&top_level, 2, &format!("{}", cpu));
    list_store.set_string(&top_level, 3, &format!("{}", memory));
}

fn update_window(w: &mut (&mut gtk::ListStore, Rc<RefCell<sysinfo::System>>, Rc<RefCell<DisplaySysInfo>>)) -> i32 {
    let model = w.0.get_model().unwrap();
    let mut iter = gtk::TreeIter::new();

    (*w.1.borrow_mut()).refresh();
    let mut entries : VecMap<Processus> = ((*w.1.borrow()).get_processus_list()).clone();
    let mut nb = model.iter_n_children(None);

    let sys = w.1.clone();
    (*w.2.borrow_mut()).update_ram_display(sys.clone());
    (*w.2.borrow_mut()).update_process_display(sys);

    let mut i = 0;
    while i < nb {
        if model.iter_nth_child(&mut iter, None, i) {
            let pid : i64 = i64::from_str(&model.get_value(&iter, 0).get_string().unwrap()).unwrap();
            let mut to_delete = false;

            match entries.get(&(pid as usize)) {
                Some(p) => {
                    //w.0.set_string(&iter, 1, &p.name);
                    w.0.set_string(&iter, 2, &format!("{}", p.cpu_usage));
                    w.0.set_string(&iter, 3, &format!("{}", p.memory));
                    to_delete = true;
                }
                None => {
                    w.0.remove(&iter);
                }
            }
            if to_delete {
                entries.remove(&(pid as usize));
                nb = model.iter_n_children(None);
                i += 1;
            }
        } else {
            i += 1;
        }
    }
    for (_, pro) in entries {
        create_and_fill_model(&mut w.0, pro.pid, &pro.name, pro.cpu_usage, pro.memory);
    }
    1
}

struct DisplaySysInfo {
    procs : Rc<RefCell<Vec<gtk::ProgressBar>>>,
    ram : Rc<RefCell<gtk::ProgressBar>>,
    swap : Rc<RefCell<gtk::ProgressBar>>,
    vertical_layout : gtk::Box
}

impl DisplaySysInfo {
    pub fn new(sys1: Rc<RefCell<sysinfo::System>>) -> DisplaySysInfo {
        let mut tmp = DisplaySysInfo {
            procs: Rc::new(RefCell::new(Vec::new())),
            ram: Rc::new(RefCell::new(gtk::ProgressBar::new().unwrap())),
            swap: Rc::new(RefCell::new(gtk::ProgressBar::new().unwrap())),
            vertical_layout: gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap()
        };

        let sys2 = sys1.clone();
        let v = tmp.procs.clone();

        (*tmp.ram.borrow_mut()).set_show_text(true);
        (*tmp.swap.borrow_mut()).set_show_text(true);

        tmp.vertical_layout.set_spacing(5);
        let mut i = 0;
        let mut total = false;

        tmp.vertical_layout.pack_start(&gtk::Label::new("Memory usage").unwrap(), false, false, 15);
        tmp.vertical_layout.add(&(*tmp.ram.borrow()));
        tmp.vertical_layout.pack_start(&gtk::Label::new("Swap usage").unwrap(), false, false, 15);
        tmp.vertical_layout.add(&(*tmp.swap.borrow()));
        tmp.vertical_layout.pack_start(&gtk::Label::new("Total CPU usage").unwrap(), false, false, 15);
        for pro in (*sys1.borrow()).get_process_list() {
            if total {
                (*v.borrow_mut()).push(gtk::ProgressBar::new().unwrap());
                let p : &gtk::ProgressBar = &(*v.borrow())[i];
                let l = gtk::Label::new(&format!("{}", i)).unwrap();
                let horizontal_layout = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();

                p.set_text(&format!("{:.2} %", pro.get_cpu_usage() * 100.));
                p.set_show_text(true);
                p.set_fraction(pro.get_cpu_usage() as f64);
                horizontal_layout.pack_start(&l, false, false, 5);
                horizontal_layout.pack_start(p, true, true, 5);
                tmp.vertical_layout.add(&horizontal_layout);
            } else {
                (*v.borrow_mut()).push(gtk::ProgressBar::new().unwrap());
                let p : &gtk::ProgressBar = &(*v.borrow())[i];

                p.set_text(&format!("{:.2} %", pro.get_cpu_usage() * 100.));
                p.set_show_text(true);
                p.set_fraction(pro.get_cpu_usage() as f64);

                tmp.vertical_layout.add(p);
                tmp.vertical_layout.pack_start(&gtk::Label::new("Process usage").unwrap(), false, false, 15);
                total = true;
            }
            i += 1;
        }
        tmp.update_ram_display(sys2);
        tmp
    }

    pub fn update_ram_display(&mut self, sys: Rc<RefCell<sysinfo::System>>) {
        let total = (*sys.borrow()).get_total_memory();
        let used = (*sys.borrow()).get_used_memory();
        let disp = if total < 100000 {
            format!("{} / {}B", used, total)
        } else if total < 10000000 {
            format!("{} / {}KB", used / 1000, total / 1000)
        } else if total < 10000000000 {
            format!("{} / {}MB", used / 1000000, total / 1000000)
        } else {
            format!("{} / {}GB", used / 1000000000, total / 1000000000)
        };

        (*self.ram.borrow_mut()).set_text(&disp);
        (*self.ram.borrow_mut()).set_fraction(used as f64 / total as f64);

        let total = (*sys.borrow()).get_total_swap();
        let used = total - (*sys.borrow()).get_used_swap();
        let disp = if total < 100000 {
            format!("{} / {}B", used, total)
        } else if total < 10000000 {
            format!("{} / {}KB", used / 1000, total / 1000)
        } else if total < 10000000000 {
            format!("{} / {}MB", used / 1000000, total / 1000000)
        } else {
            format!("{} / {}GB", used / 1000000000, total / 1000000000)
        };

        (*self.swap.borrow_mut()).set_text(&disp);
        (*self.swap.borrow_mut()).set_fraction(used as f64 / total as f64);
    }

    pub fn update_process_display(&mut self, sys: Rc<RefCell<sysinfo::System>>) {
        let v = &*self.procs.borrow_mut();
        let mut i = 0;

        for pro in (*sys.borrow()).get_process_list() {
            v[i].set_text(&format!("{:.1} %", pro.get_cpu_usage() * 100.));
            v[i].set_show_text(true);
            v[i].set_fraction(pro.get_cpu_usage() as f64);
            i += 1;
        }
    }
}

fn main() {
    gtk::init();

    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let sys : Rc<RefCell<sysinfo::System>> = Rc::new(RefCell::new(sysinfo::System::new()));
    let mut note = NoteBook::new();
    (*sys.borrow_mut()).refresh();
    let mut procs = Procs::new((*sys.borrow()).get_processus_list());
    let current_pid2 = procs.current_pid.clone();
    let sys1 = sys.clone();
    let sys2 = sys.clone();

    window.set_title("Processus viewer");
    window.set_window_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });

    (*procs.kill_button.borrow_mut()).connect_clicked(move |_| {
        let tmp = (*current_pid2.borrow_mut()).is_some() ;

        if tmp {
            let s = (*current_pid2.borrow()).clone();
            match (*sys.borrow_mut()).get_processus(i64::from_str(&s.unwrap()).unwrap()) {
                Some(p) => {
                    p.kill(Signal::Kill);
                },
                None => {}
            };
        }
    });

    let display_tab = Rc::new(RefCell::new(DisplaySysInfo::new(sys2)));

    glib::timeout::add(1500, update_window, &mut (&mut procs.list_store, sys1.clone(), display_tab.clone()));
    //window.add(&vertical_layout);
    note.create_tab("Processus list", &procs.vertical_layout);
    //let t = gtk::Button::new_with_label("test").unwrap();
    note.create_tab("System usage", &(*display_tab.borrow()).vertical_layout);
    window.add(&note.notebook);
    window.show_all();
    gtk::main();
}
<commit_msg>Few updates<commit_after>#![crate_type = "bin"]
#![feature(collections)]

extern crate gtk;
extern crate glib;
extern crate sysinfo;

use gtk::{WindowTrait, ContainerTrait, WidgetTrait, ButtonSignals, BoxTrait};
use gtk::{Orientation};
use sysinfo::*;
use gtk::signal::Inhibit;
use gtk::signal::{WidgetSignals, TreeViewSignals};
use std::collections::VecMap;
use std::str::FromStr;
use std::rc::Rc;
use std::cell::{RefCell};

struct NoteBook {
    notebook: gtk::NoteBook,
    tabs: Vec<gtk::Box>
}

impl NoteBook {
    fn new() -> NoteBook {
        NoteBook {
            notebook: gtk::NoteBook::new().unwrap(),
            tabs: Vec::new()
        }
    }

    fn create_tab<'a, Widget: gtk::WidgetTrait>(&mut self, title: &'a str, widget: &Widget) -> Option<u32> {
        let label = gtk::Label::new(title).unwrap();
        let tab = gtk::Box::new(Orientation::Horizontal, 0).unwrap();

        tab.pack_start(&label, false, false, 0);
        tab.show_all();

        let index = match self.notebook.append_page(widget, Some(&tab)) {
            Some(index) => index,
            _ => return None
        };

        self.tabs.push(tab);

        Some(index)
    }
}

struct Procs {
    left_tree: gtk::TreeView,
    scroll: gtk::ScrolledWindow,
    current_pid: Rc<RefCell<Option<String>>>,
    kill_button: Rc<RefCell<gtk::Button>>,
    vertical_layout: gtk::Box,
    list_store: gtk::ListStore
}

impl Procs {
    pub fn new<'a>(proc_list: &VecMap<Processus>) -> Procs {
        let left_tree = gtk::TreeView::new().unwrap();
        let scroll = gtk::ScrolledWindow::new(None, None).unwrap();
        let current_pid = Rc::new(RefCell::new(None));
        let kill_button = Rc::new(RefCell::new(gtk::Button::new_with_label("End task").unwrap()));
        let current_pid1 = current_pid.clone();
        let current_pid2 = current_pid.clone();
        let kill_button1 = kill_button.clone();

        scroll.set_min_content_height(800);
        scroll.set_min_content_width(600);

        let mut columns : Vec<gtk::TreeViewColumn> = Vec::new();

        append_column("pid", &mut columns);
        append_column("process name", &mut columns);
        append_column("cpu usage", &mut columns);
        append_column("memory usage", &mut columns);

        for i in columns {
            left_tree.append_column(&i);
        }

        let mut list_store = gtk::ListStore::new(&[glib::Type::String, glib::Type::String, glib::Type::String, glib::Type::String]).unwrap();
        for (_, pro) in proc_list {
            create_and_fill_model(&mut list_store, pro.pid, &pro.name, pro.cpu_usage, pro.memory);
        }

        left_tree.set_model(&list_store.get_model().unwrap());
        left_tree.set_headers_visible(true);
        scroll.add(&left_tree);
        let vertical_layout = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();

        left_tree.connect_cursor_changed(move |tree_view| {
            match tree_view.get_selection() {
                Some(selection) => {
                    let model = tree_view.get_model().unwrap();
                    let mut iter = gtk::TreeIter::new();

                    if selection.get_selected(&model, &mut iter) {
                        let pid = model.get_value(&iter, 0).get_string();
                        let mut tmp = current_pid1.borrow_mut();
                        *tmp = pid;
                    }
                    (*kill_button1.borrow_mut()).set_sensitive((*current_pid.borrow()).is_some());
                }
                None => {
                    let mut tmp = current_pid1.borrow_mut();
                    *tmp = None;
                }
            }
        });
        (*kill_button.borrow_mut()).set_sensitive(false);

        vertical_layout.add(&scroll);
        vertical_layout.add(&(*kill_button.borrow_mut()));
        Procs {
            left_tree: left_tree,
            scroll: scroll,
            current_pid: current_pid2.clone(),
            kill_button: kill_button,
            vertical_layout: vertical_layout,
            list_store: list_store
        }
    }
}

fn append_column(title: &str, v: &mut Vec<gtk::TreeViewColumn>) {
    let l = v.len();
    let renderer = gtk::CellRendererText::new().unwrap();

    v.push(gtk::TreeViewColumn::new().unwrap());
    let tmp = v.get_mut(l).unwrap();

    tmp.set_title(title);
    tmp.pack_start(&renderer, true);
    tmp.add_attribute(&renderer, "text", l as i32);
}

fn create_and_fill_model(list_store: &mut gtk::ListStore, pid: i64, name: &str, cpu: f32, memory: u64) {
    if name.len() < 1 {
        return;
    }
    let mut top_level = gtk::TreeIter::new();

    list_store.append(&mut top_level);
    list_store.set_string(&top_level, 0, &format!("{}", pid));
    list_store.set_string(&top_level, 1, name);
    list_store.set_string(&top_level, 2, &format!("{:.1}", cpu));
    list_store.set_string(&top_level, 3, &format!("{}", memory));
}

fn update_window(w: &mut (&mut gtk::ListStore, Rc<RefCell<sysinfo::System>>, Rc<RefCell<DisplaySysInfo>>)) -> i32 {
    let model = w.0.get_model().unwrap();
    let mut iter = gtk::TreeIter::new();

    (*w.1.borrow_mut()).refresh();
    let mut entries : VecMap<Processus> = ((*w.1.borrow()).get_processus_list()).clone();
    let mut nb = model.iter_n_children(None);

    let sys = w.1.clone();
    (*w.2.borrow_mut()).update_ram_display(sys.clone());
    (*w.2.borrow_mut()).update_process_display(sys);

    let mut i = 0;
    while i < nb {
        if model.iter_nth_child(&mut iter, None, i) {
            let pid : i64 = i64::from_str(&model.get_value(&iter, 0).get_string().unwrap()).unwrap();
            let mut to_delete = false;

            match entries.get(&(pid as usize)) {
                Some(p) => {
                    w.0.set_string(&iter, 2, &format!("{:.1}", p.cpu_usage));
                    w.0.set_string(&iter, 3, &format!("{}", p.memory));
                    to_delete = true;
                }
                None => {
                    w.0.remove(&iter);
                }
            }
            if to_delete {
                entries.remove(&(pid as usize));
                nb = model.iter_n_children(None);
                i += 1;
            }
        } else {
            i += 1;
        }
    }
    for (_, pro) in entries {
        create_and_fill_model(&mut w.0, pro.pid, &pro.name, pro.cpu_usage, pro.memory);
    }
    1
}

struct DisplaySysInfo {
    procs : Rc<RefCell<Vec<gtk::ProgressBar>>>,
    ram : Rc<RefCell<gtk::ProgressBar>>,
    swap : Rc<RefCell<gtk::ProgressBar>>,
    vertical_layout : gtk::Box
}

impl DisplaySysInfo {
    pub fn new(sys1: Rc<RefCell<sysinfo::System>>) -> DisplaySysInfo {
        let mut tmp = DisplaySysInfo {
            procs: Rc::new(RefCell::new(Vec::new())),
            ram: Rc::new(RefCell::new(gtk::ProgressBar::new().unwrap())),
            swap: Rc::new(RefCell::new(gtk::ProgressBar::new().unwrap())),
            vertical_layout: gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap()
        };

        let sys2 = sys1.clone();
        let v = tmp.procs.clone();

        (*tmp.ram.borrow_mut()).set_show_text(true);
        (*tmp.swap.borrow_mut()).set_show_text(true);

        tmp.vertical_layout.set_spacing(5);
        let mut i = 0;
        let mut total = false;

        tmp.vertical_layout.pack_start(&gtk::Label::new("Memory usage").unwrap(), false, false, 15);
        tmp.vertical_layout.add(&(*tmp.ram.borrow()));
        tmp.vertical_layout.pack_start(&gtk::Label::new("Swap usage").unwrap(), false, false, 15);
        tmp.vertical_layout.add(&(*tmp.swap.borrow()));
        tmp.vertical_layout.pack_start(&gtk::Label::new("Total CPU usage").unwrap(), false, false, 15);
        for pro in (*sys1.borrow()).get_process_list() {
            if total {
                (*v.borrow_mut()).push(gtk::ProgressBar::new().unwrap());
                let p : &gtk::ProgressBar = &(*v.borrow())[i];
                let l = gtk::Label::new(&format!("{}", i)).unwrap();
                let horizontal_layout = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();

                p.set_text(&format!("{:.2} %", pro.get_cpu_usage() * 100.));
                p.set_show_text(true);
                p.set_fraction(pro.get_cpu_usage() as f64);
                horizontal_layout.pack_start(&l, false, false, 5);
                horizontal_layout.pack_start(p, true, true, 5);
                tmp.vertical_layout.add(&horizontal_layout);
            } else {
                (*v.borrow_mut()).push(gtk::ProgressBar::new().unwrap());
                let p : &gtk::ProgressBar = &(*v.borrow())[i];

                p.set_text(&format!("{:.2} %", pro.get_cpu_usage() * 100.));
                p.set_show_text(true);
                p.set_fraction(pro.get_cpu_usage() as f64);

                tmp.vertical_layout.add(p);
                tmp.vertical_layout.pack_start(&gtk::Label::new("Process usage").unwrap(), false, false, 15);
                total = true;
            }
            i += 1;
        }
        tmp.update_ram_display(sys2);
        tmp
    }

    pub fn update_ram_display(&mut self, sys: Rc<RefCell<sysinfo::System>>) {
        let total = (*sys.borrow()).get_total_memory();
        let used = (*sys.borrow()).get_used_memory();
        let disp = if total < 100000 {
            format!("{} / {}KB", used, total)
        } else if total < 10000000 {
            format!("{} / {}MB", used / 1000, total / 1000)
        } else if total < 10000000000 {
            format!("{} / {}GB", used / 1000000, total / 1000000)
        } else {
            format!("{} / {}TB", used / 1000000000, total / 1000000000)
        };

        (*self.ram.borrow_mut()).set_text(&disp);
        (*self.ram.borrow_mut()).set_fraction(used as f64 / total as f64);

        let total = (*sys.borrow()).get_total_swap();
        let used = total - (*sys.borrow()).get_used_swap();
        let disp = if total < 100000 {
            format!("{} / {}KB", used, total)
        } else if total < 10000000 {
            format!("{} / {}MB", used / 1000, total / 1000)
        } else if total < 10000000000 {
            format!("{} / {}GB", used / 1000000, total / 1000000)
        } else {
            format!("{} / {}TB", used / 1000000000, total / 1000000000)
        };

        (*self.swap.borrow_mut()).set_text(&disp);
        (*self.swap.borrow_mut()).set_fraction(used as f64 / total as f64);
    }

    pub fn update_process_display(&mut self, sys: Rc<RefCell<sysinfo::System>>) {
        let v = &*self.procs.borrow_mut();
        let mut i = 0;

        for pro in (*sys.borrow()).get_process_list() {
            v[i].set_text(&format!("{:.1} %", pro.get_cpu_usage() * 100.));
            v[i].set_show_text(true);
            v[i].set_fraction(pro.get_cpu_usage() as f64);
            i += 1;
        }
    }
}

fn main() {
    gtk::init();

    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let sys : Rc<RefCell<sysinfo::System>> = Rc::new(RefCell::new(sysinfo::System::new()));
    let mut note = NoteBook::new();
    (*sys.borrow_mut()).refresh();
    let mut procs = Procs::new((*sys.borrow()).get_processus_list());
    let current_pid2 = procs.current_pid.clone();
    let sys1 = sys.clone();
    let sys2 = sys.clone();

    window.set_title("Processus viewer");
    window.set_window_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });

    (*procs.kill_button.borrow_mut()).connect_clicked(move |_| {
        let tmp = (*current_pid2.borrow_mut()).is_some() ;

        if tmp {
            let s = (*current_pid2.borrow()).clone();
            match (*sys.borrow_mut()).get_processus(i64::from_str(&s.unwrap()).unwrap()) {
                Some(p) => {
                    p.kill(Signal::Kill);
                },
                None => {}
            };
        }
    });

    let display_tab = Rc::new(RefCell::new(DisplaySysInfo::new(sys2)));

    glib::timeout::add(1500, update_window, &mut (&mut procs.list_store, sys1.clone(), display_tab.clone()));
    //window.add(&vertical_layout);
    note.create_tab("Processus list", &procs.vertical_layout);
    //let t = gtk::Button::new_with_label("test").unwrap();
    note.create_tab("System usage", &(*display_tab.borrow()).vertical_layout);
    window.add(&note.notebook);
    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};
use hyper::server::Http;
use core::net::TcpListener;
use core::reactor::Core;

pub use hyper::header as headers;
pub use hyper::{StatusCode, Error, Method, Body};
pub use hyper::server::{Request, Response};
pub use core::reactor::Handle;
pub use tokio::{Service, NewService};

pub fn serve<T, Fut, F>(routes: F) -> io::Result<()>
where
    T: NewService<Request = Request, Response = Response, Error = Error> + 'static,
    T::Instance: 'static,
    Fut: Future<Item = T, Error = io::Error>,
    F: FnOnce(&Handle) -> (SocketAddr, Fut),
{
    // TODO shutdown
    let mut core = Core::new()?;
    let protocol = Http::new();
    let handle = core.handle();
    let (addr, routes) = routes(&handle);
    let listener = TcpListener::bind(&addr, &handle)?;
    let srv = routes.and_then(|routes| {
        let handle = &handle;
        let protocol = &protocol;
        listener.incoming().for_each(move |(socket, remote_addr)| {
            routes.new_service().map(move |service| {
                protocol.bind_connection(handle, socket, remote_addr, service);
            })
        })
    });
    core.run(srv)
}

pub type BoxFuture = Box<Future<Item = Response, Error = Error>>;
<commit_msg>Support the ability to override port number.<commit_after>use std::env;
use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};
use hyper::server::Http;
use core::net::TcpListener;
use core::reactor::Core;

pub use hyper::header as headers;
pub use hyper::{StatusCode, Error, Method, Body};
pub use hyper::server::{Request, Response};
pub use core::reactor::Handle;
pub use tokio::{Service, NewService};

pub fn serve<T, Fut, F>(routes: F) -> io::Result<()>
where
    T: NewService<Request = Request, Response = Response, Error = Error> + 'static,
    T::Instance: 'static,
    Fut: Future<Item = T, Error = io::Error>,
    F: FnOnce(&Handle) -> (SocketAddr, Fut),
{
    // TODO shutdown
    let mut core = Core::new()?;
    let protocol = Http::new();
    let handle = core.handle();
    let (mut addr, routes) = routes(&handle);
    set_port(&mut addr);
    let listener = TcpListener::bind(&addr, &handle)?;
    let srv = routes.and_then(|routes| {
        let handle = &handle;
        let protocol = &protocol;
        listener.incoming().for_each(move |(socket, remote_addr)| {
            routes.new_service().map(move |service| {
                protocol.bind_connection(handle, socket, remote_addr, service);
            })
        })
    });
    core.run(srv)
}

fn set_port(addr: &mut SocketAddr) {
    if let Ok(port) = env::var("PORT") {
        let port = port.parse().expect("PORT variable not a valid port number.");
        addr.set_port(port);
    }
}

pub type BoxFuture = Box<Future<Item = Response, Error = Error>>;
<|endoftext|>