Skip to content

Commit

Permalink
Merge pull request #228 from kas-gui/work
Browse files Browse the repository at this point in the history
Window icons; some docs
  • Loading branch information
dhardy authored Aug 2, 2021
2 parents 6faa9db + 3a3b506 commit 07ceb97
Show file tree
Hide file tree
Showing 15 changed files with 111 additions and 39 deletions.
17 changes: 12 additions & 5 deletions kas-theme/src/draw_shaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,24 @@ use kas::geom::Quad;
///
/// All methods draw some feature.
///
/// Methods are parameterised via a pair of normals, `(inner, outer)`. These may
/// have values from the closed range `[-1, 1]`, where -1 points inwards,
/// 0 is perpendicular to the screen towards the viewer, and 1 points outwards.
/// Methods are parameterised via a pair of normals, `(inner, outer)`, which
/// specify the surface normal direction at inner and outer edges of the feature
/// respectively (with interpolation between these edges). These have values
/// from the closed range `[-1, 1]`, where -1 points towards the inside of the
/// feature, 1 points away from the feature, and 0 is perpendicular to the
/// screen towards the viewer.
pub trait DrawShaded {
/// Add a shaded square to the draw buffer
///
/// For shading purposes, the mid-point is considered the inner edge.
fn shaded_square(&mut self, rect: Quad, norm: (f32, f32), col: Rgba);

/// Add a shaded circle to the draw buffer
///
/// For shading purposes, the mid-point is considered the inner edge.
fn shaded_circle(&mut self, rect: Quad, norm: (f32, f32), col: Rgba);

/// Add a square shaded frame to the draw buffer.
/// Add a shaded frame with square corners to the draw buffer
fn shaded_square_frame(
&mut self,
outer: Quad,
Expand All @@ -33,7 +40,7 @@ pub trait DrawShaded {
inner_col: Rgba,
);

/// Add a rounded shaded frame to the draw buffer.
/// Add a shaded frame with rounded corners to the draw buffer
fn shaded_round_frame(&mut self, outer: Quad, inner: Quad, norm: (f32, f32), col: Rgba);
}

Expand Down
15 changes: 7 additions & 8 deletions kas-theme/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@

//! KAS theme support
//!
//! This crate allows widget rendering to be customised via themes,
//! and provides mid-level draw implementations for widgets.
//! This crate provides the [`Theme`] trait, [`MultiTheme`] adapter, color
//! schemes, some supporting items, and the themes [`FlatTheme`] and
//! [`ShadedTheme`].
//!
//! Each [`Theme`] is expected to have [`Window`]-specific data,
//! and provides an implementation of [`kas::draw::DrawHandle`].
//!
//! Two themes are provided by this trait: [`FlatTheme`] and [`ShadedTheme`].
//! Additionally, a meta-theme, [`MultiTheme`], allows run-time switching
//! between themes.
//! Custom themes may be built over this crate, optionally including custom draw
//! routines (e.g. [`DrawShaded`]), provided that the shell implements support.
//! Alternatively this crate may be skipped altogether, especially for a
//! minimal shell with a custom fixed theme.
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(feature = "gat", feature(generic_associated_types))]
Expand Down
5 changes: 4 additions & 1 deletion kas-wgpu/examples/gallery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ fn main() -> Result<(), kas_wgpu::Error> {
}
};

let window = Window::new(
let mut window = Window::new(
"Widget Gallery",
make_widget! {
#[layout(column)]
Expand Down Expand Up @@ -332,6 +332,9 @@ fn main() -> Result<(), kas_wgpu::Error> {
}
},
);
if let Err(err) = window.load_icon_from_path("res/gallery.png") {
println!("Failed to load window icon: {}", err);
}

toolkit.add(window)?;
toolkit.run()
Expand Down
3 changes: 1 addition & 2 deletions kas-wgpu/src/draw/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ pub trait CustomPipeBuilder {
/// [`crate::Toolkit::new_custom`].
///
/// Note that `kas-wgpu` accepts only a single custom pipe. To use more than
/// one, you will have to implement your own multiplexer (presumably using an
/// enum for the `Param` type).
/// one custom graphics pipeline, you must implement your own multiplexer.
pub trait CustomPipe: 'static {
/// Associated per-window state for the custom pipe
type Window: CustomWindow;
Expand Down
3 changes: 3 additions & 0 deletions kas-wgpu/src/draw/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::mem::size_of;
use std::num::NonZeroU32;

use super::{atlases, ShaderManager};
use kas::cast::Conv;
use kas::draw::{ImageError, ImageFormat, ImageId, PassId};
use kas::geom::{Quad, Vec2};

Expand All @@ -32,6 +33,8 @@ impl Image {
) {
// TODO(opt): use StagingBelt for upload (when supported)? Or our own equivalent.
let size = self.size;
assert!(data.len() > 0);
assert_eq!(data.len(), 4 * usize::conv(size.0) * usize::conv(size.1));
queue.write_texture(
wgpu::ImageCopyTexture {
texture: atlas_pipe.get_texture(self.atlas),
Expand Down
1 change: 0 additions & 1 deletion kas-wgpu/src/draw/shaded_round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ impl Pipeline {
}

impl Window {
/// Bounds on input: `0 ≤ inner_radius ≤ 1`.
pub fn circle(&mut self, pass: PassId, rect: Quad, mut norm: Vec2, col: Rgba) {
let aa = rect.a;
let bb = rect.b;
Expand Down
15 changes: 11 additions & 4 deletions kas-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@

//! KAS shell over [winit] and [WebGPU]
//!
//! This crate provides an implementation of KAS, using [WebGPU] for
//! GPU-accelerated rendering.
//! This crate implements a KAS shell (backend) using [WebGPU] for
//! GPU-accelerated rendering and [winit] for windowing, thus it should be
//! portable to most desktop and potentially also mobile platforms.
//!
//! Windowing is provided by [winit].
//! Clipboard functionality is (currently) provided by the [clipboard] crate.
//! This crate supports themes via the [`kas_theme`] crate, including shaded
//! drawing.
//!
//! Custom GPU-accelerated drawing is supported via [`draw::CustomPipe`]
//! (see the [Mandlebrot example](https://github.com/kas-gui/kas/blob/master/kas-wgpu/examples/mandlebrot.rs)).
//!
//! By default, some environment variables are read for configuration.
//! See [`options::Options::from_env`] for documentation.
//!
//! [WebGPU]: https://github.com/gfx-rs/wgpu-rs
//! [winit]: https://github.com/rust-windowing/winit
Expand Down
10 changes: 4 additions & 6 deletions kas-wgpu/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Options {
///
/// The following environment variables are read, in case-insensitive mode.
///
/// ### Config
/// # Config files
///
/// WARNING: file formats are not stable and may not be compatible across
/// KAS versions (aside from patch versions)!
Expand All @@ -83,22 +83,20 @@ impl Options {
///
/// - `Read` (default): read-only
/// - `ReadWrite`: read on start-up, write on exit
/// - `WriteDefault`: generate platform-default configuration, and write
/// it to the config path, overwriting any existing config
/// - `WriteDefault`: generate platform-default configuration and write
/// it to the config path(s) specified, overwriting any existing config
///
/// Note: in the future, the default will likely change to a read-write mode,
/// allowing changes to be written out.
///
/// ### Power preference
/// # Graphics options
///
/// The `KAS_POWER_PREFERENCE` variable supports:
///
/// - `Default`
/// - `LowPower`
/// - `HighPerformance`
///
/// ### Backend
///
/// The `KAS_BACKENDS` variable supports:
///
/// - `Vulkan`
Expand Down
5 changes: 4 additions & 1 deletion kas-wgpu/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ impl<C: CustomPipe, T: Theme<DrawPipe<C>>> Window<C, T> {
if restrict_dimensions.1 {
builder = builder.with_max_inner_size(ideal);
}
let window = builder.with_title(widget.title()).build(elwt)?;
let window = builder
.with_title(widget.title())
.with_window_icon(widget.icon())
.build(elwt)?;

shared.init_clipboard(&window);

Expand Down
4 changes: 4 additions & 0 deletions src/core/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ pub trait Window: Widget<Msg = event::VoidMsg> {
/// Get the window title
fn title(&self) -> &str;

/// Get the window icon, if any
#[cfg(feature = "winit")]
fn icon(&self) -> Option<winit::window::Icon>;

/// Whether to limit the maximum size of a window
///
/// All widgets' size rules allow calculation of two sizes: the minimum
Expand Down
4 changes: 4 additions & 0 deletions src/draw/draw_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ pub trait DrawShared {
///
/// This should be called at least once on each image before display. May be
/// called again to update the image contents.
///
/// `id` must refer to an allocation of some size `(w, h)`, such that
/// `data.len() == b * w * h` where `b` is the number of bytes per pixel,
/// according to `format`. Data must be in row-major order.
fn image_upload(&mut self, id: ImageId, data: &[u8], format: ImageFormat);

/// Load an image from a path, autodetecting file type
Expand Down
6 changes: 4 additions & 2 deletions src/draw/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl ImageId {
/// Image formats available for upload
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ImageFormat {
/// 8-bit RGBA values
/// 8-bit unsigned RGBA values (4 bytes per pixel)
Rgba8,
}

Expand Down Expand Up @@ -77,7 +77,9 @@ impl Images {
return Ok(*id);
}

let image = image::io::Reader::open(path)?.decode()?;
let image = image::io::Reader::open(path)?
.with_guessed_format()?
.decode()?;
// TODO(opt): we convert to RGBA8 since this is the only format common
// to both the image crate and WGPU. It may not be optimal however.
// It also assumes that the image colour space is sRGB.
Expand Down
13 changes: 7 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@

//! KAS GUI Toolkit
//!
//! KAS is a GUI library. This crate provides the following:
//! This is the main KAS crate, featuring:
//!
//! - the [`Widget`] trait family, with [`macros`] to implement them
//! - a [`layout`] solver and [`event`] handling for widgets
//! - building blocks including [`geom`] types and a [`draw`] API
//! - some pre-build widgets: the [`widget`] module
//! - high-level themable and mid-level [`draw`] APIs
//! - [`event`] handling code
//! - [`geom`]-etry types and widget [`layout`] solvers
//! - a [`widget`] library
//!
//! See also these external crates:
//!
//! - [`kas-theme`](https://crates.io/crates/kas-theme) - [docs.rs](https://docs.rs/kas-theme) - theme API + themes
//! - [`kas-wgpu`](https://crates.io/crates/kas-wgpu) - [docs.rs](https://docs.rs/kas-wgpu) - WebGPU + winit integration
//! - `kas-theme` - [crates.io](https://crates.io/crates/kas-theme) - [docs.rs](https://docs.rs/kas-theme) - theme API + themes
//! - `kas-wgpu` - [crates.io](https://crates.io/crates/kas-wgpu) - [docs.rs](https://docs.rs/kas-wgpu) - WebGPU + winit integration
//!
//! Also refer to:
//!
Expand Down
5 changes: 5 additions & 0 deletions src/widget/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ impl<T: FormattableText + 'static> kas::Window for MessageBox<T> {
&self.title
}

#[cfg(feature = "winit")]
fn icon(&self) -> Option<winit::window::Icon> {
None // TODO
}

fn restrict_dimensions(&self) -> (bool, bool) {
(true, true)
}
Expand Down
44 changes: 41 additions & 3 deletions src/widget/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@

//! Window widgets
use smallvec::SmallVec;
use std::fmt::{self, Debug};

use kas::layout;
use kas::prelude::*;
use kas::{Future, WindowId};
use smallvec::SmallVec;
#[cfg(feature = "winit")]
use std::error::Error;
use std::fmt::{self, Debug};
#[cfg(feature = "winit")]
use std::path::Path;
#[cfg(feature = "winit")]
use winit::window::Icon;

/// The main instantiation of the [`Window`] trait.
#[derive(Widget)]
Expand All @@ -24,6 +29,8 @@ pub struct Window<W: Widget + 'static> {
w: W,
popups: SmallVec<[(WindowId, kas::Popup); 16]>,
drop: Option<(Box<dyn FnMut(&mut W)>, UpdateHandle)>,
#[cfg(feature = "winit")]
icon: Option<winit::window::Icon>,
}

impl<W: Widget> Debug for Window<W> {
Expand All @@ -47,6 +54,8 @@ impl<W: Widget + Clone> Clone for Window<W> {
w: self.w.clone(),
popups: Default::default(), // these are temporary; don't clone
drop: None, // we cannot clone this!
#[cfg(feature = "winit")]
icon: self.icon.clone(),
}
}
}
Expand All @@ -61,6 +70,8 @@ impl<W: Widget> Window<W> {
w,
popups: Default::default(),
drop: None,
#[cfg(feature = "winit")]
icon: None,
}
}

Expand Down Expand Up @@ -109,6 +120,28 @@ impl<W: Widget> Window<W> {
self.drop = Some((finish, update));
(future, update)
}

/// Set the window icon
#[cfg(feature = "winit")]
pub fn set_icon(&mut self, icon: Option<Icon>) {
self.icon = icon;
}

/// Load the window icon from a path
///
/// On error the icon is not set. The window may still be used.
#[cfg(feature = "winit")]
pub fn load_icon_from_path<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Box<dyn Error>> {
// TODO(opt): image loading could be de-duplicated with
// DrawShared::image_from_path, but this may not be worthwhile.
let im = image::io::Reader::open(path)?
.with_guessed_format()?
.decode()?
.into_rgba8();
let (w, h) = im.dimensions();
self.icon = Some(Icon::from_rgba(im.into_vec(), w, h)?);
Ok(())
}
}

impl<W: Widget> Layout for Window<W> {
Expand Down Expand Up @@ -165,6 +198,11 @@ impl<M: Into<VoidMsg>, W: Widget<Msg = M> + 'static> kas::Window for Window<W> {
&self.title
}

#[cfg(feature = "winit")]
fn icon(&self) -> Option<winit::window::Icon> {
self.icon.clone()
}

fn restrict_dimensions(&self) -> (bool, bool) {
self.restrict_dimensions
}
Expand Down

0 comments on commit 07ceb97

Please sign in to comment.