We're planning to associate "selection sources" with global element ids to allow arbitrary UI text to be selected in GPUI. Previously, global ids were not exposed outside the framework and we entangled management of the element id stack with element state access. This was more acceptable when element state was the only place we used global element ids, but now that we're planning to use them more places, it makes sense to deal with element identity as a first-class part of the element system. We now ensure that the stack of element ids which forms the current global element id is correctly managed in every phase of element layout and paint and make the global id available to each element method. In a subsequent PR, we'll use the global element id as part of implementing arbitrary selection for UI text. Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com>
80 lines
2.0 KiB
Rust
80 lines
2.0 KiB
Rust
use crate::{size, DevicePixels, Result, SharedString, Size};
|
|
use anyhow::anyhow;
|
|
use image::{Bgra, ImageBuffer};
|
|
use std::{
|
|
borrow::Cow,
|
|
fmt,
|
|
hash::Hash,
|
|
sync::atomic::{AtomicUsize, Ordering::SeqCst},
|
|
};
|
|
|
|
/// A source of assets for this app to use.
|
|
pub trait AssetSource: 'static + Send + Sync {
|
|
/// Load the given asset from the source path.
|
|
fn load(&self, path: &str) -> Result<Cow<'static, [u8]>>;
|
|
|
|
/// List the assets at the given path.
|
|
fn list(&self, path: &str) -> Result<Vec<SharedString>>;
|
|
}
|
|
|
|
impl AssetSource for () {
|
|
fn load(&self, path: &str) -> Result<Cow<'static, [u8]>> {
|
|
Err(anyhow!(
|
|
"load called on empty asset provider with \"{}\"",
|
|
path
|
|
))
|
|
}
|
|
|
|
fn list(&self, _path: &str) -> Result<Vec<SharedString>> {
|
|
Ok(vec![])
|
|
}
|
|
}
|
|
|
|
/// A unique identifier for the image cache
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
pub struct ImageId(usize);
|
|
|
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
|
pub(crate) struct RenderImageParams {
|
|
pub(crate) image_id: ImageId,
|
|
}
|
|
|
|
/// A cached and processed image.
|
|
pub struct ImageData {
|
|
/// The ID associated with this image
|
|
pub id: ImageId,
|
|
data: ImageBuffer<Bgra<u8>, Vec<u8>>,
|
|
}
|
|
|
|
impl ImageData {
|
|
/// Create a new image from the given data.
|
|
pub fn new(data: ImageBuffer<Bgra<u8>, Vec<u8>>) -> Self {
|
|
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
Self {
|
|
id: ImageId(NEXT_ID.fetch_add(1, SeqCst)),
|
|
data,
|
|
}
|
|
}
|
|
|
|
/// Convert this image into a byte slice.
|
|
pub fn as_bytes(&self) -> &[u8] {
|
|
&self.data
|
|
}
|
|
|
|
/// Get the size of this image, in pixels
|
|
pub fn size(&self) -> Size<DevicePixels> {
|
|
let (width, height) = self.data.dimensions();
|
|
size(width.into(), height.into())
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for ImageData {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("ImageData")
|
|
.field("id", &self.id)
|
|
.field("size", &self.data.dimensions())
|
|
.finish()
|
|
}
|
|
}
|