Add drawing functionality to new ui
This commit is contained in:
113
src/wayland.rs
113
src/wayland.rs
@@ -5,7 +5,10 @@ use smithay_client_toolkit::{
|
|||||||
output::{OutputHandler, OutputState},
|
output::{OutputHandler, OutputState},
|
||||||
registry::{RegistryState, ProvidesRegistryState},
|
registry::{RegistryState, ProvidesRegistryState},
|
||||||
registry_handlers,
|
registry_handlers,
|
||||||
seat::{SeatState, SeatHandler, Capability},
|
seat::{
|
||||||
|
pointer::{PointerEvent, PointerEventKind, PointerHandler},
|
||||||
|
SeatState, SeatHandler, Capability
|
||||||
|
},
|
||||||
shell::{
|
shell::{
|
||||||
xdg::{
|
xdg::{
|
||||||
window::{WindowHandler, Window, WindowConfigure, WindowDecorations},
|
window::{WindowHandler, Window, WindowConfigure, WindowDecorations},
|
||||||
@@ -17,13 +20,14 @@ use smithay_client_toolkit::{
|
|||||||
Shm, ShmHandler
|
Shm, ShmHandler
|
||||||
},
|
},
|
||||||
delegate_registry, delegate_compositor, delegate_seat, delegate_output,
|
delegate_registry, delegate_compositor, delegate_seat, delegate_output,
|
||||||
delegate_xdg_shell, delegate_shm, delegate_activation, delegate_xdg_window
|
delegate_xdg_shell, delegate_shm, delegate_activation, delegate_xdg_window,
|
||||||
|
delegate_pointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
Connection, QueueHandle,
|
Connection, QueueHandle,
|
||||||
globals::registry_queue_init,
|
globals::registry_queue_init,
|
||||||
protocol::{wl_surface, wl_output, wl_seat, wl_shm},
|
protocol::{wl_surface, wl_output, wl_seat, wl_shm, wl_pointer},
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -31,10 +35,9 @@ use std::time::Duration;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
mod pixel;
|
|
||||||
mod app;
|
mod app;
|
||||||
|
|
||||||
use ui::{ButtonBuilder, DrawAreaBuilder, TextAreaBuilder};
|
use ui::{ButtonBuilder, DrawAreaBuilder, TextAreaBuilder, DrawPath, Position};
|
||||||
|
|
||||||
|
|
||||||
const WINDOW_HEIGHT: u32 = 256;
|
const WINDOW_HEIGHT: u32 = 256;
|
||||||
@@ -83,15 +86,21 @@ pub(super) fn run() -> Result<()> {
|
|||||||
registry_state: RegistryState::new(&globals),
|
registry_state: RegistryState::new(&globals),
|
||||||
seat_state: SeatState::new(&globals, &qh),
|
seat_state: SeatState::new(&globals, &qh),
|
||||||
output_state: OutputState::new(&globals, &qh),
|
output_state: OutputState::new(&globals, &qh),
|
||||||
|
xdg_activation,
|
||||||
|
|
||||||
shm,
|
shm,
|
||||||
buffer: None,
|
buffer: None,
|
||||||
pool,
|
pool,
|
||||||
window,
|
window,
|
||||||
width: WINDOW_WIDTH,
|
width: WINDOW_WIDTH,
|
||||||
height: WINDOW_HEIGHT,
|
height: WINDOW_HEIGHT,
|
||||||
|
cursor_down: false,
|
||||||
exit: false,
|
exit: false,
|
||||||
first_configure: true,
|
first_configure: true,
|
||||||
|
pointer: None,
|
||||||
_loop_handle: event_loop.handle(),
|
_loop_handle: event_loop.handle(),
|
||||||
|
|
||||||
|
draw_path: DrawPath::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -112,14 +121,20 @@ struct SimpleWindow {
|
|||||||
seat_state: SeatState,
|
seat_state: SeatState,
|
||||||
output_state: OutputState,
|
output_state: OutputState,
|
||||||
shm: Shm,
|
shm: Shm,
|
||||||
|
xdg_activation: Option<ActivationState>,
|
||||||
|
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
pool: SlotPool,
|
pool: SlotPool,
|
||||||
window: Window,
|
window: Window,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
cursor_down: bool,
|
||||||
exit: bool,
|
exit: bool,
|
||||||
first_configure: bool,
|
first_configure: bool,
|
||||||
_loop_handle: LoopHandle<'static, SimpleWindow>
|
pointer: Option<wl_pointer::WlPointer>,
|
||||||
|
_loop_handle: LoopHandle<'static, SimpleWindow>,
|
||||||
|
|
||||||
|
draw_path: DrawPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompositorHandler for SimpleWindow {
|
impl CompositorHandler for SimpleWindow {
|
||||||
@@ -142,14 +157,15 @@ impl CompositorHandler for SimpleWindow {
|
|||||||
_: &wl_surface::WlSurface,
|
_: &wl_surface::WlSurface,
|
||||||
_: u32
|
_: u32
|
||||||
) {
|
) {
|
||||||
self.draw(conn, qh);
|
self.draw(conn, qh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SeatHandler for SimpleWindow {
|
impl SeatHandler for SimpleWindow {
|
||||||
fn seat_state(&mut self) -> &mut SeatState {
|
fn seat_state(&mut self) -> &mut SeatState {
|
||||||
&mut self.seat_state
|
&mut self.seat_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_seat(
|
fn new_seat(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
@@ -159,17 +175,28 @@ impl SeatHandler for SimpleWindow {
|
|||||||
fn new_capability(
|
fn new_capability(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
_: &QueueHandle<Self>,
|
qh: &QueueHandle<Self>,
|
||||||
_: wl_seat::WlSeat,
|
seat: wl_seat::WlSeat,
|
||||||
_: Capability,
|
capability: Capability,
|
||||||
) {}
|
) {
|
||||||
|
if capability == Capability::Pointer && self.pointer.is_none() {
|
||||||
|
println!("Set pointer capability");
|
||||||
|
let pointer = self.seat_state.get_pointer(qh, &seat).expect("Failed to create pointer");
|
||||||
|
self.pointer = Some(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn remove_capability(
|
fn remove_capability(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
_: &QueueHandle<Self>,
|
_: &QueueHandle<Self>,
|
||||||
_: wl_seat::WlSeat,
|
_: wl_seat::WlSeat,
|
||||||
_: Capability,
|
capability: Capability,
|
||||||
) {}
|
) {
|
||||||
|
if capability == Capability::Pointer && self.pointer.is_some() {
|
||||||
|
println!("Unset pointer capability");
|
||||||
|
self.pointer.take().unwrap().release();
|
||||||
|
}
|
||||||
|
}
|
||||||
fn remove_seat(
|
fn remove_seat(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &Connection,
|
_: &Connection,
|
||||||
@@ -236,7 +263,57 @@ impl ShmHandler for SimpleWindow {
|
|||||||
impl ActivationHandler for SimpleWindow {
|
impl ActivationHandler for SimpleWindow {
|
||||||
type RequestData = RequestData;
|
type RequestData = RequestData;
|
||||||
|
|
||||||
fn new_token(&mut self, _: String, _: &Self::RequestData) {}
|
fn new_token(&mut self, token: String, _: &Self::RequestData) {
|
||||||
|
self.xdg_activation
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.activate::<SimpleWindow>(self.window.wl_surface(), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerHandler for SimpleWindow {
|
||||||
|
fn pointer_frame(
|
||||||
|
&mut self,
|
||||||
|
_conn: &Connection,
|
||||||
|
_qh: &QueueHandle<Self>,
|
||||||
|
_pointer: &wl_pointer::WlPointer,
|
||||||
|
events: &[PointerEvent],
|
||||||
|
) {
|
||||||
|
use PointerEventKind::*;
|
||||||
|
for event in events {
|
||||||
|
// Ignore events for other surfaces
|
||||||
|
if &event.surface != self.window.wl_surface() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.kind {
|
||||||
|
Enter { .. } => {
|
||||||
|
println!("Pointer entered @{:?}", event.position);
|
||||||
|
}
|
||||||
|
Leave { .. } => {
|
||||||
|
println!("Pointer left");
|
||||||
|
}
|
||||||
|
Motion { .. } => {
|
||||||
|
if self.cursor_down {
|
||||||
|
self.draw_path.add_point(Position::new(event.position.0 as f32, event.position.1 as f32), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Press { button, .. } => {
|
||||||
|
println!("Press {:x} @ {:?}", button, event.position);
|
||||||
|
self.cursor_down = true;
|
||||||
|
self.draw_path.add_point(Position::new(event.position.0 as f32, event.position.1 as f32), true)
|
||||||
|
}
|
||||||
|
Release { button, .. } => {
|
||||||
|
println!("Release {:x} @ {:?}", button, event.position);
|
||||||
|
self.cursor_down = false;
|
||||||
|
self.draw_path.add_point(Position::new(event.position.0 as f32, event.position.1 as f32), false)
|
||||||
|
}
|
||||||
|
Axis { horizontal, vertical, .. } => {
|
||||||
|
println!("Scroll H:{horizontal:?}, V:{vertical:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleWindow {
|
impl SimpleWindow {
|
||||||
@@ -280,13 +357,12 @@ impl SimpleWindow {
|
|||||||
button.position(self.width as f32 - 100.0, 50.0);
|
button.position(self.width as f32 - 100.0, 50.0);
|
||||||
button.width(100.0);
|
button.width(100.0);
|
||||||
button.height(50.0);
|
button.height(50.0);
|
||||||
button.color(0x33, 0x33, 0x33);
|
|
||||||
let button = button.finish();
|
let button = button.finish();
|
||||||
|
|
||||||
draw_area.position(0.0, 50.0);
|
draw_area.position(0.0, 50.0);
|
||||||
draw_area.width(self.width as f32 - 100.0);
|
draw_area.width(self.width as f32 - 100.0);
|
||||||
draw_area.height(self.height as f32 - 50.0);
|
draw_area.height(self.height as f32 - 50.0);
|
||||||
draw_area.color(0x15, 0x15, 0x15);
|
draw_area.path(&self.draw_path);
|
||||||
let draw_area = draw_area.finish();
|
let draw_area = draw_area.finish();
|
||||||
|
|
||||||
|
|
||||||
@@ -294,7 +370,6 @@ impl SimpleWindow {
|
|||||||
text_area.position(0.0, 0.0);
|
text_area.position(0.0, 0.0);
|
||||||
text_area.width(self.width as f32);
|
text_area.width(self.width as f32);
|
||||||
text_area.height(50.0);
|
text_area.height(50.0);
|
||||||
text_area.color(0x22, 0x22, 0x22);
|
|
||||||
let text_area = text_area.finish();
|
let text_area = text_area.finish();
|
||||||
|
|
||||||
window.add_widget(button);
|
window.add_widget(button);
|
||||||
@@ -322,6 +397,8 @@ delegate_xdg_shell!(SimpleWindow);
|
|||||||
delegate_xdg_window!(SimpleWindow);
|
delegate_xdg_window!(SimpleWindow);
|
||||||
delegate_activation!(SimpleWindow);
|
delegate_activation!(SimpleWindow);
|
||||||
|
|
||||||
|
delegate_pointer!(SimpleWindow);
|
||||||
|
|
||||||
delegate_registry!(SimpleWindow);
|
delegate_registry!(SimpleWindow);
|
||||||
|
|
||||||
impl ProvidesRegistryState for SimpleWindow {
|
impl ProvidesRegistryState for SimpleWindow {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::wayland::pixel::{Pixel, Box, BoxMut, PixelEncoding};
|
|
||||||
use raqote::{DrawTarget, PathBuilder, Source, StrokeStyle, DrawOptions, SolidSource, Color};
|
use raqote::{DrawTarget, PathBuilder, Source, StrokeStyle, DrawOptions, SolidSource, Color};
|
||||||
|
|
||||||
struct UIColor {
|
struct UIColor {
|
||||||
@@ -72,11 +71,77 @@ impl<'a, 'b> Window<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub(super) struct Position {
|
pub(super) struct Position {
|
||||||
pub(super) x: f32,
|
pub(super) x: f32,
|
||||||
pub(super) y: f32,
|
pub(super) y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) struct Path(Vec<Position>);
|
||||||
|
|
||||||
|
impl IntoIterator for Path {
|
||||||
|
type Item = Position;
|
||||||
|
type IntoIter = std::vec::IntoIter<Position>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a Path {
|
||||||
|
type Item = &'a Position;
|
||||||
|
type IntoIter = std::slice::Iter<'a, Position>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct DrawPath {
|
||||||
|
pub(super) paths: Vec<Path>,
|
||||||
|
pub(super) newline: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrawPath {
|
||||||
|
pub(super) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
paths: Vec::new(),
|
||||||
|
newline: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn add_point(&mut self, point: Position, newline: bool) {
|
||||||
|
if newline {
|
||||||
|
self.paths.push(Path(vec![point]))
|
||||||
|
} else if self.paths.len() > 0 {
|
||||||
|
self.paths
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.push(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for DrawPath {
|
||||||
|
type Item = Path;
|
||||||
|
type IntoIter = std::vec::IntoIter<Path>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.paths.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a DrawPath {
|
||||||
|
type Item = &'a Path;
|
||||||
|
type IntoIter = std::slice::Iter<'a, Path>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.paths.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
pub(super) fn new(x: f32, y: f32) -> Self {
|
pub(super) fn new(x: f32, y: f32) -> Self {
|
||||||
Position { x, y }
|
Position { x, y }
|
||||||
@@ -84,40 +149,60 @@ impl Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) enum Widget<'a> {
|
pub(super) enum Widget<'a> {
|
||||||
Button(Button<'a>),
|
Button(Button),
|
||||||
DrawArea(DrawArea<'a>),
|
DrawArea(DrawArea<'a>),
|
||||||
TextArea(TextArea<'a>)
|
TextArea(TextArea)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) trait Draw {
|
pub(super) trait Draw {
|
||||||
fn render(&self, area: &mut DrawTarget<&mut [u32]>);
|
fn render(&self, area: &mut DrawTarget<&mut [u32]>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct Button<'a> {
|
pub(super) struct ButtonColors {
|
||||||
|
background: Color,
|
||||||
|
border: Color,
|
||||||
|
glyph: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ButtonColors {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
background: Color::new(0xff, 0x25, 0x2c, 0x33),
|
||||||
|
border: Color::new(0xff, 0x77, 0x7f, 0x97),
|
||||||
|
glyph: Color::new(0xff, 0xea, 0xea, 0xe6),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct Button {
|
||||||
pub(super) width: f32,
|
pub(super) width: f32,
|
||||||
pub(super) height: f32,
|
pub(super) height: f32,
|
||||||
pub(super) position: Position,
|
pub(super) position: Position,
|
||||||
pub(super) source: Source<'a>,
|
pub(super) colors: ButtonColors,
|
||||||
pub(super) options: DrawOptions,
|
pub(super) options: DrawOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct ButtonBuilder<'a> {
|
impl Button {
|
||||||
|
fn background_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.background.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct ButtonBuilder {
|
||||||
pub(super) width: Option<f32>,
|
pub(super) width: Option<f32>,
|
||||||
pub(super) height: Option<f32>,
|
pub(super) height: Option<f32>,
|
||||||
pub(super) position: Option<Position>,
|
pub(super) position: Option<Position>,
|
||||||
pub(super) source: Option<Source<'a>>,
|
pub(super) colors: Option<ButtonColors>,
|
||||||
pub(super) color: Option<Color>,
|
|
||||||
pub(super) options: Option<DrawOptions>,
|
pub(super) options: Option<DrawOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ButtonBuilder<'a> {
|
impl<'a> ButtonBuilder {
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: None,
|
width: None,
|
||||||
height: None,
|
height: None,
|
||||||
position: None,
|
position: None,
|
||||||
source: None,
|
colors: None,
|
||||||
color: None,
|
|
||||||
options: None,
|
options: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,12 +219,8 @@ impl<'a> ButtonBuilder<'a> {
|
|||||||
self.position = Some(Position::new(x, y))
|
self.position = Some(Position::new(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn source(&mut self, source: Source<'a>) {
|
pub(super) fn colors(&mut self, colors: ButtonColors) {
|
||||||
self.source = Some(source);
|
self.colors = Some(colors)
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn color(&mut self, r: u8, g: u8, b: u8) {
|
|
||||||
self.color = Some(Color::new(0xff, r, g, b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn finish(self) -> Widget<'a> {
|
pub(super) fn finish(self) -> Widget<'a> {
|
||||||
@@ -148,18 +229,14 @@ impl<'a> ButtonBuilder<'a> {
|
|||||||
width: self.width.expect("Button must have width"),
|
width: self.width.expect("Button must have width"),
|
||||||
height: self.height.expect("Button must have height"),
|
height: self.height.expect("Button must have height"),
|
||||||
position: self.position.expect("Button must have a position"),
|
position: self.position.expect("Button must have a position"),
|
||||||
source: self.source.unwrap_or(
|
colors: self.colors.unwrap_or_default(),
|
||||||
Source::Solid(
|
|
||||||
self.color.unwrap_or(Color::new(0xff, 0x00, 0x00, 0x00)).into()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
options: self.options.unwrap_or(DrawOptions::new()),
|
options: self.options.unwrap_or(DrawOptions::new()),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Draw for Button<'a> {
|
impl Draw for Button {
|
||||||
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
||||||
|
|
||||||
(*area).fill_rect(
|
(*area).fill_rect(
|
||||||
@@ -167,26 +244,58 @@ impl<'a> Draw for Button<'a> {
|
|||||||
self.position.y,
|
self.position.y,
|
||||||
self.width,
|
self.width,
|
||||||
self.height,
|
self.height,
|
||||||
&self.source,
|
&self.background_source(),
|
||||||
&self.options,
|
&self.options,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) struct DrawAreaColors {
|
||||||
|
background_color: Color,
|
||||||
|
drawing_color: Color,
|
||||||
|
border_color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DrawAreaColors {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
background_color: Color::new(0xff, 0x4a, 0x4e, 0x64),
|
||||||
|
drawing_color: Color::new(0xff, 0xea, 0xea, 0xe6),
|
||||||
|
border_color: Color::new(0xff, 0x77, 0x7f, 0x97),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct DrawArea<'a> {
|
pub(super) struct DrawArea<'a> {
|
||||||
pub(super) width: f32,
|
pub(super) width: f32,
|
||||||
pub(super) height: f32,
|
pub(super) height: f32,
|
||||||
pub(super) position: Position,
|
pub(super) position: Position,
|
||||||
pub(super) source: Source<'a>,
|
pub(super) path: &'a DrawPath,
|
||||||
|
pub(super) colors: DrawAreaColors,
|
||||||
pub(super) options: DrawOptions,
|
pub(super) options: DrawOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DrawArea<'_> {
|
||||||
|
fn background_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.background_color.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawing_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.drawing_color.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn border_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.border_color.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) struct DrawAreaBuilder<'a> {
|
pub(super) struct DrawAreaBuilder<'a> {
|
||||||
pub(super) width: Option<f32>,
|
pub(super) width: Option<f32>,
|
||||||
pub(super) height: Option<f32>,
|
pub(super) height: Option<f32>,
|
||||||
pub(super) position: Option<Position>,
|
pub(super) position: Option<Position>,
|
||||||
pub(super) source: Option<Source<'a>>,
|
pub(super) path: Option<&'a DrawPath>,
|
||||||
pub(super) color: Option<Color>,
|
pub(super) colors: Option<DrawAreaColors>,
|
||||||
pub(super) options: Option<DrawOptions>,
|
pub(super) options: Option<DrawOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,8 +305,8 @@ impl<'a> DrawAreaBuilder<'a> {
|
|||||||
width: None,
|
width: None,
|
||||||
height: None,
|
height: None,
|
||||||
position: None,
|
position: None,
|
||||||
source: None,
|
path: None,
|
||||||
color: None,
|
colors: None,
|
||||||
options: None,
|
options: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,12 +323,12 @@ impl<'a> DrawAreaBuilder<'a> {
|
|||||||
self.position = Some(Position::new(x, y))
|
self.position = Some(Position::new(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn source(&mut self, source: Source<'a>) {
|
pub(super) fn colors(&mut self, colors: DrawAreaColors) {
|
||||||
self.source = Some(source);
|
self.colors = Some(colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn color(&mut self, r: u8, g: u8, b: u8) {
|
pub(super) fn path(&mut self, path: &'a DrawPath) {
|
||||||
self.color = Some(Color::new(0xff, r, g, b))
|
self.path = Some(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn finish(self) -> Widget<'a> {
|
pub(super) fn finish(self) -> Widget<'a> {
|
||||||
@@ -228,56 +337,104 @@ impl<'a> DrawAreaBuilder<'a> {
|
|||||||
width: self.width.expect("Draw area must have width"),
|
width: self.width.expect("Draw area must have width"),
|
||||||
height: self.height.expect("Draw area must have height"),
|
height: self.height.expect("Draw area must have height"),
|
||||||
position: self.position.expect("Draw area must have a position"),
|
position: self.position.expect("Draw area must have a position"),
|
||||||
source: self.source.unwrap_or(
|
path: self.path.expect("Draw must have a path"),
|
||||||
Source::Solid(
|
colors: self.colors.unwrap_or_default(),
|
||||||
self.color.unwrap_or(Color::new(0xff, 0x00, 0x00, 0x00)).into()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
options: self.options.unwrap_or(DrawOptions::new()),
|
options: self.options.unwrap_or(DrawOptions::new()),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Draw for DrawArea<'a> {
|
impl Draw for DrawArea<'_> {
|
||||||
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
||||||
|
let mut draw_path = PathBuilder::new();
|
||||||
|
|
||||||
|
for path in self.path.into_iter() {
|
||||||
|
if path.0.len() > 1 {
|
||||||
|
let mut path = path.into_iter();
|
||||||
|
|
||||||
|
let first_point = path
|
||||||
|
.by_ref()
|
||||||
|
.next();
|
||||||
|
|
||||||
|
draw_path.move_to(first_point.unwrap().x, first_point.unwrap().y);
|
||||||
|
|
||||||
|
for point in path {
|
||||||
|
draw_path.line_to(point.x, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let path = draw_path.finish();
|
||||||
area.fill_rect(
|
area.fill_rect(
|
||||||
self.position.x,
|
self.position.x,
|
||||||
self.position.y,
|
self.position.y,
|
||||||
self.width,
|
self.width,
|
||||||
self.height,
|
self.height,
|
||||||
&self.source,
|
&self.background_source(),
|
||||||
&self.options,
|
&self.options,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
area.stroke(
|
||||||
|
&path,
|
||||||
|
&self.drawing_source(),
|
||||||
|
&StrokeStyle {width: 3.0, ..StrokeStyle::default()},
|
||||||
|
&self.options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) struct TextArea<'a> {
|
pub(super) struct TextAreaColors {
|
||||||
|
pub(super) background: Color,
|
||||||
|
pub(super) text: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TextAreaColors {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
background: Color::new(0xff, 0x25, 0x2c, 0x33),
|
||||||
|
text: Color::new(0xff, 0xfc, 0xf8, 0xef),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct TextArea {
|
||||||
pub(super) width: f32,
|
pub(super) width: f32,
|
||||||
pub(super) height: f32,
|
pub(super) height: f32,
|
||||||
pub(super) position: Position,
|
pub(super) position: Position,
|
||||||
pub(super) source: Source<'a>,
|
pub(super) colors: TextAreaColors,
|
||||||
pub(super) options: DrawOptions,
|
pub(super) options: DrawOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct TextAreaBuilder<'a> {
|
impl TextArea {
|
||||||
|
pub(super) fn text_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.text.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn background_source(&self) -> Source {
|
||||||
|
Source::Solid(self.colors.background.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct TextAreaBuilder {
|
||||||
pub(super) width: Option<f32>,
|
pub(super) width: Option<f32>,
|
||||||
pub(super) height: Option<f32>,
|
pub(super) height: Option<f32>,
|
||||||
pub(super) position: Option<Position>,
|
pub(super) position: Option<Position>,
|
||||||
pub(super) source: Option<Source<'a>>,
|
pub(super) colors: Option<TextAreaColors>,
|
||||||
pub(super) color: Option<Color>,
|
|
||||||
pub(super) options: Option<DrawOptions>,
|
pub(super) options: Option<DrawOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TextAreaBuilder<'a> {
|
impl<'a> TextAreaBuilder {
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: None,
|
width: None,
|
||||||
height: None,
|
height: None,
|
||||||
position: None,
|
position: None,
|
||||||
source: None,
|
colors: None,
|
||||||
color: None,
|
|
||||||
options: None,
|
options: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,12 +451,9 @@ impl<'a> TextAreaBuilder<'a> {
|
|||||||
self.position = Some(Position::new(x, y))
|
self.position = Some(Position::new(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn source(&mut self, source: Source<'a>) {
|
|
||||||
self.source = Some(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn color(&mut self, r: u8, g: u8, b: u8) {
|
pub(super) fn colors(&mut self, colors: TextAreaColors) {
|
||||||
self.color = Some(Color::new(0xff, r, g, b))
|
self.colors = Some(colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn finish(self) -> Widget<'a> {
|
pub(super) fn finish(self) -> Widget<'a> {
|
||||||
@@ -308,28 +462,27 @@ impl<'a> TextAreaBuilder<'a> {
|
|||||||
width: self.width.expect("Button must have width"),
|
width: self.width.expect("Button must have width"),
|
||||||
height: self.height.expect("Button must have height"),
|
height: self.height.expect("Button must have height"),
|
||||||
position: self.position.expect("Button must have a position"),
|
position: self.position.expect("Button must have a position"),
|
||||||
source: self.source.unwrap_or(
|
colors: self.colors.unwrap_or_default(),
|
||||||
Source::Solid(
|
|
||||||
self.color.unwrap_or(Color::new(0xff, 0x00, 0x00, 0x00)).into()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
options: self.options.unwrap_or(DrawOptions::new()),
|
options: self.options.unwrap_or(DrawOptions::new()),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Draw for TextArea<'a> {
|
impl Draw for TextArea {
|
||||||
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
fn render(&self, area: &mut DrawTarget<&mut [u32]>) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(*area).fill_rect(
|
area.fill_rect(
|
||||||
self.position.x,
|
self.position.x,
|
||||||
self.position.y,
|
self.position.y,
|
||||||
self.width,
|
self.width,
|
||||||
self.height,
|
self.height,
|
||||||
&self.source,
|
&self.background_source(),
|
||||||
&self.options,
|
&self.options,
|
||||||
)
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user