dogamak / xcbars

Bar library created with rust and xcb.
Apache License 2.0
1 stars 1 forks source link

More Flexible Architecture #8

Open dogamak opened 7 years ago

dogamak commented 7 years ago

Currently Components are streams of String values at heart. This works nicely for simple components such as clock, but a good bar is more than just text.

Ideally a component should be able to render whatever it wants on the part of the window reserved for it. This could be used to implement features like icons (#5) and progress bars (#10) and even more complicated componens.

However nobody wants to worry about individual pixels when all they want it to display a piece of text or an icon. Because of this we need higher level abstractions over the raw access to the drawing surface. Ideally components and abstractions would be chainable so that one could easily and without custom components implement things like "showing the content of file, truncated at 25 characters and refreshing every 5 seconds".

This issue is for the planning of such architecture.

dogamak commented 7 years ago

I have come up with this design, which should be pretty flexible. It is quite a lot of stuff to implement for a simple component like components::Text, but should allow for nice and easy abstractions.

trait ComponentConfig {
    type State: ComponentState = Self;
}

trait ComponentState: Future<Item=Self::Update, Error=Self::Error> {
    type Update;
    type Error: Into<Error>;
    type Config: ComponentConfig<State=Self> = Self;

    fn create(config: Self::Config) -> Result<Self>;
    fn get_size(self) -> u16;
    fn update(&mut self, update: Update) -> Result<()>;
    fn render(&mut self, surface: cairo::Surface) -> Result<()>;
}

This could be abstracted to resemble the current Component trait with a blanket impl:

trait StringComponent {
    type Stream: Stream<Item=String, Error=Self::Error>;
    type Error: Error;
    type Config: ComponentConfig<State=Self> = Self;

    fn create(config: Self::Config) -> Result<Self>;
    fn stream(self, handle: Handle) -> Self::Stream;
}
dogamak commented 7 years ago

Requiring ComponentState to implement Stream was probably a mistake. Returning a stream is probably cleaner, simpler and more flexible.