This commit is contained in:
Richard Feldman
2024-08-12 12:36:13 -04:00
parent 4a90eba0da
commit bd6bb9204f
4 changed files with 135 additions and 7 deletions

View File

@@ -3073,6 +3073,8 @@ impl ContextEditor {
let selection = editor.selections.newest::<usize>(cx);
let mut copied_text = String::new();
let mut spanned_messages = 0;
let mut clipboard_entries: Vec<ClipboardEntry> = Vec::new();
for message in context.messages(cx) {
if message.offset_range.start >= selection.range().end {
break;
@@ -3090,8 +3092,16 @@ impl ContextEditor {
}
}
for image_anchor in context.image_anchors(cx) {
if let Some((render_image, _)) = context.get_image(image_anchor.image_id) {
//
} else {
log::error!("Assistant panel context had an image id of {:?} but there was no associated images entry stored for that id. This should never happen!", image_anchor.image_id);
}
}
if spanned_messages > 1 {
cx.write_to_clipboard(ClipboardItem::new_string(copied_text));
cx.write_to_clipboard(ClipboardItem::new(clipboard_entries));
return;
}
}
@@ -3155,11 +3165,13 @@ impl ContextEditor {
let new_blocks = self
.context
.read(cx)
.images(cx)
.filter_map(|image| {
.image_anchors(cx)
.filter_map(|image_anchor| {
const MAX_HEIGHT_IN_LINES: u32 = 8;
let anchor = buffer.anchor_in_excerpt(excerpt_id, image.anchor).unwrap();
let image = image.render_image.clone();
let anchor = buffer
.anchor_in_excerpt(excerpt_id, image_anchor.anchor)
.unwrap();
let image = image_anchor.render_image.clone();
anchor.is_valid(&buffer).then(|| BlockProperties {
position: anchor,
height: MAX_HEIGHT_IN_LINES,

View File

@@ -1906,10 +1906,20 @@ impl Context {
}
}
pub fn images<'a>(&'a self, _cx: &'a AppContext) -> impl 'a + Iterator<Item = ImageAnchor> {
pub fn image_anchors<'a>(
&'a self,
_cx: &'a AppContext,
) -> impl 'a + Iterator<Item = ImageAnchor> {
self.image_anchors.iter().cloned()
}
pub fn get_image(
&self,
image_id: u64,
) -> Option<&(Arc<RenderImage>, Shared<Task<Option<LanguageModelImage>>>)> {
self.images.get(&image_id)
}
pub fn split_message(
&mut self,
range: Range<usize>,

View File

@@ -26,7 +26,7 @@ use crate::{
RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Scene, SharedString, Size,
SvgSize, Task, TaskLabel, WindowContext, DEFAULT_WINDOW_SIZE,
};
use anyhow::Result;
use anyhow::{anyhow, Result};
use async_task::Runnable;
use futures::channel::oneshot;
use image::codecs::gif::GifDecoder;
@@ -987,6 +987,11 @@ pub enum ClipboardEntry {
}
impl ClipboardItem {
/// Create a new ClipboardItem with the given entries
pub fn new(entries: Vec<ClipboardEntry>) -> Self {
Self { entries }
}
/// Create a new ClipboardItem::String with no associated metadata
pub fn new_string(text: String) -> Self {
Self {
@@ -1083,6 +1088,39 @@ impl Image {
ImageSource::Image(self).use_data(cx)
}
/// Convert an `ImageData` object to a clipboard image in PNG format.
pub fn from_image_data(render_image: &RenderImage) -> Result<Self> {
// hardcode frame index 0; we don't currently support copying animated GIFs
if let Some(input_bytes) = render_image.as_bytes(0) {
let rgba_bytes = {
let mut buf = input_bytes.to_vec();
// Convert from BGRA to RGBA.
for pixel in buf.chunks_exact_mut(4) {
pixel.swap(0, 2);
}
buf
};
let mut output_bytes = Vec::with_capacity(rgba_bytes.len());
let image_buffer = RgbaIma
let cursor = Cursor::new(output_bytes);
image::DynamicImage::ImageRgba8(rgba_bytes)
.write_to(&mut cursor, image::ImageOutputFormat::Png)?;
Ok(Self {
format: ImageFormat::Png,
bytes: cursor.into_inner(),
id: rand::random(),
})
} else {
Err(anyhow!(
"RenderImage did not have a frame 0, which should never happen."
))
}
}
/// Convert the clipboard image to an `ImageData` object.
pub fn to_image_data(&self, cx: &AppContext) -> Result<Arc<RenderImage>> {
fn frames_for_image(

View File

@@ -921,6 +921,74 @@ impl Platform for MacPlatform {
}
}
/*
{
// write some images and text to the clip
// let image1 = ns_image(&bytes).unwrap();
// let image2 = ns_image(&bytes).unwrap();
let image1 = NSImage::initWithPasteboard_(nil, pasteboard);
let image2 = NSImage::initWithPasteboard_(nil, pasteboard);
// let attributed_string = text_and_images([image1, image2]);
// text_and_images([NSImage::initWithPasteboard_(, pasteboard), ns_image(&bytes).unwrap()]);
let attributed_string = {
use cocoa::appkit::NSImage;
let image: id = msg_send![class!(NSImage), alloc];
NSImage::initWithContentsOfFile_(
image,
NSString::alloc(nil).init_str("/Users/rtfeldman/Downloads/test.jpeg"),
);
let size = image.size();
let string = NSString::alloc(nil).init_str("Test String");
let attr_string =
NSMutableAttributedString::alloc(nil).init_attributed_string(string);
let hello_string = NSString::alloc(nil).init_str("Hello World");
let hello_attr_string =
NSAttributedString::alloc(nil).init_attributed_string(hello_string);
attr_string.appendAttributedString_(hello_attr_string);
let attachment = NSTextAttachment::alloc(nil);
let _: () = msg_send![attachment, setImage: image];
let image_attr_string = msg_send![class!(NSAttributedString), attributedStringWithAttachment: attachment];
attr_string.appendAttributedString_(image_attr_string);
let another_string = NSString::alloc(nil).init_str("Another String");
let another_attr_string =
NSAttributedString::alloc(nil).init_attributed_string(another_string);
attr_string.appendAttributedString_(another_attr_string);
attr_string
};
pasteboard.clearContents();
let rtfd_data = attributed_string.RTFDFromRange_documentAttributes_(
NSRange::new(0, msg_send![attributed_string, length]),
nil,
);
if rtfd_data != nil {
pasteboard.setData_forType(rtfd_data, NSPasteboardTypeRTFD);
}
// let rtf_data = attributed_string.RTFFromRange_documentAttributes_(
// NSRange::new(0, attributed_string.length()),
// nil,
// );
// if rtf_data != nil {
// pasteboard.setData_forType(rtf_data, NSPasteboardTypeRTF);
// }
// let plain_text = attributed_string.string();
// pasteboard.setString_forType(plain_text, NSPasteboardTypeString);
}
*/
buf.appendAttributedString_(to_append);
}