This commit is contained in:
		
					parent
					
						
							
								11bbb2500f
							
						
					
				
			
			
				commit
				
					
						a7f3c12018
					
				
			
		
					 5 changed files with 460 additions and 498 deletions
				
			
		
							
								
								
									
										482
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										482
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										14
									
								
								Cargo.toml
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								Cargo.toml
									
										
									
									
									
								
							|  | @ -7,8 +7,10 @@ rust-version = "1.72" | |||
| 
 | ||||
| 
 | ||||
| [dependencies] | ||||
| cosmic-jotdown = { git = "https://git.nations.lol/fnmain/cosmic-jotdown" } | ||||
| eframe = { version = "0.26.2", default-features = false, features = [ | ||||
| # cosmic-jotdown = { git = "https://git.nations.lol/fnmain/cosmic-jotdown" } | ||||
| cosmic-jotdown = {path = "../cosmic-jotdown"} | ||||
| jotdown = { git = "https://git.nations.lol/fnmain/jotdown" } | ||||
| eframe = { version = "0.27.2", default-features = false, features = [ | ||||
|     "accesskit",     # Make egui comptaible with screen readers. NOTE: adds a lot of dependencies. | ||||
|     # "default_fonts", | ||||
|     "wgpu",          # Use the glow rendering backend. Alternative: "wgpu". | ||||
|  | @ -16,17 +18,17 @@ eframe = { version = "0.26.2", default-features = false, features = [ | |||
|     "wayland", | ||||
| ] } | ||||
| egui-glyphon = { git = "https://git.nations.lol/fnmain/egui-glyphon" } | ||||
| egui_extras = { version = "0.26.2", features = ["image", "http", "file"] } | ||||
| egui_extras = { version = "0.27.2", features = ["image", "http", "file"] } | ||||
| encase = { version = "0.7.0", features = ["glam"] } | ||||
| glam = "0.25.0" | ||||
| image = { version = "0.24.9", features = ["jpeg", "png"] } | ||||
| image = { version = "0.24.9", features = ["jpeg", "png"], defaut-features = false } | ||||
| keyframe = { version = "1.1.1", default-features = false } | ||||
| log = "0.4" | ||||
| range-map = "0.2.0" | ||||
| rangemap = "1.5.1" | ||||
| 
 | ||||
| # native: | ||||
| [target.'cfg(not(target_arch = "wasm32"))'.dependencies] | ||||
| env_logger = "0.10" | ||||
| env_logger = "0.11" | ||||
| 
 | ||||
| # web: | ||||
| [target.'cfg(target_arch = "wasm32")'.dependencies] | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.7 MiB | 
|  | @ -12,4 +12,4 @@ | |||
| - I balance the time I spend at my computer with outdoor activities like, camping, hiking, and backpacking | ||||
| - I know how to both write code for computers, as well as whip them into shape when they start having problems. I am the IT guy in my family | ||||
| 
 | ||||
| \*Special thanks to _meico_ from Shadertoy for the GLSL version of your Spectrum Ring shader | ||||
| \*Special thanks to _meico_ from Shadertoy for the GLSL version of your [Spectrum Ring shader](https://www.shadertoy.com/view/XssXWH) | ||||
|  |  | |||
							
								
								
									
										344
									
								
								src/app.rs
									
										
									
									
									
								
							
							
						
						
									
										344
									
								
								src/app.rs
									
										
									
									
									
								
							|  | @ -13,12 +13,11 @@ use std::sync::Arc; | |||
| 
 | ||||
| #[cfg(target_arch = "wasm32")] | ||||
| use arc_swap::ArcSwapAny; | ||||
| use cosmic_jotdown::jotdown::{self, Event, ListKind}; | ||||
| use cosmic_jotdown::{Indent, INDENT_AMOUNT}; | ||||
| use cosmic_jotdown::Indent; | ||||
| use eframe::egui::mutex::{Mutex, RwLock}; | ||||
| use eframe::egui::{ | ||||
|     self, lerp, Align2, Id, Image, ImageSize, ImageSource, LayerId, OpenUrl, Pos2, Rect, Rounding, | ||||
|     Sense, Stroke, Vec2, | ||||
|     Sense, Vec2, | ||||
| }; | ||||
| use eframe::egui_wgpu::{self, wgpu}; | ||||
| use egui::{Color32, Frame}; | ||||
|  | @ -28,8 +27,9 @@ use egui_glyphon::{BufferWithTextArea, GlyphonRenderer, GlyphonRendererCallback} | |||
| use encase::ShaderType; | ||||
| use glam::Mat2; | ||||
| use glyphon::{Buffer, FontSystem, Metrics}; | ||||
| use jotdown::Event; | ||||
| use keyframe::functions; | ||||
| use range_map::RangeMap; | ||||
| use rangemap::RangeMap; | ||||
| use wgpu::util::DeviceExt; | ||||
| 
 | ||||
| /// We derive Deserialize/Serialize so we can persist app state on shutdown.
 | ||||
|  | @ -68,7 +68,7 @@ pub enum State { | |||
| #[derive(Default)] | ||||
| pub struct ContextWindow { | ||||
|     pub size: Vec2, | ||||
|     pub text: Vec<(Rect, Indent, ContextBlock)>, | ||||
|     pub text: Vec<ResolvedItem<'static>>, | ||||
|     #[cfg(target_arch = "wasm32")] | ||||
|     pub name: &'static str, | ||||
| } | ||||
|  | @ -80,16 +80,6 @@ pub struct ContextIcon { | |||
|     pub name: &'static str, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub enum ContextBlock { | ||||
|     Buffer(Arc<RwLock<Buffer>>, Option<RangeMap<usize, &'static str>>), | ||||
|     Image { | ||||
|         alt_text: Arc<RwLock<Buffer>>, | ||||
|         image: Image<'static>, | ||||
|         hi_image: Image<'static>, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| const CONTEXT_METRICS: Metrics = Metrics::new(16.0, 18.0); | ||||
| const HOVER_TIME: f64 = 0.5; | ||||
| 
 | ||||
|  | @ -231,6 +221,14 @@ const NAME_PLATE: [&str; 3] = [ | |||
|     "My portfolio", | ||||
| ]; | ||||
| 
 | ||||
| pub struct ResolvedItem<'a> { | ||||
|     pub indent: Indent, | ||||
|     pub buffer: Arc<RwLock<Buffer>>, | ||||
|     pub relative_bounds: Rect, | ||||
|     pub url_map: Option<RangeMap<usize, Cow<'a, str>>>, | ||||
|     pub image_urls: Option<(String, String)>, | ||||
| } | ||||
| 
 | ||||
| impl ContextWindow { | ||||
|     pub fn set_content( | ||||
|         &mut self, | ||||
|  | @ -238,119 +236,34 @@ impl ContextWindow { | |||
|         #[cfg(target_arch = "wasm32")] transform: Option<Mat2>, | ||||
|         #[cfg(target_arch = "wasm32")] name: Option<&'static str>, | ||||
|         font_system: &mut FontSystem, | ||||
|         mut max_width: f32, | ||||
|         max_width: f32, | ||||
|         #[cfg(target_arch = "wasm32")] states: &mut Vec<State>, | ||||
|     ) { | ||||
|         self.size = Vec2::new(max_width / 1.5, 0.0); | ||||
|         let mut last_indent = None; | ||||
|         let mut last_image_size: Option<Vec2> = None; | ||||
|         max_width /= 1.5; | ||||
|         self.text = cosmic_jotdown::jotdown_into_buffers( | ||||
|             content.iter().cloned(), | ||||
|         let text = | ||||
|             cosmic_jotdown::jotdown_into_buffers(content.iter().cloned()).collect::<Vec<_>>(); | ||||
| 
 | ||||
|         let (size, text) = cosmic_jotdown::resolve_paragraphs( | ||||
|             &text, | ||||
|             self.size, | ||||
|             font_system, | ||||
|             CONTEXT_METRICS, | ||||
|             max_width, | ||||
|         ) | ||||
|         .map(|buffer| { | ||||
|             let measurement = measure_buffer(&buffer.buffer, self.size); | ||||
|             let paragraph_height = if last_indent.is_none() || buffer.indent.modifier.is_none() { | ||||
|                 CONTEXT_METRICS.line_height * 1.5 | ||||
|             } else { | ||||
|                 8.0 | ||||
|             }; | ||||
|             last_indent = buffer.indent.modifier; | ||||
|             let buffer = if let Some(url) = buffer.image_url { | ||||
|                 let image; | ||||
|                 let hi_image; | ||||
|                 let url = url.split_once('#').unwrap(); | ||||
|                 let size = url.1.split_once('x').unwrap(); | ||||
|                 let size = Vec2::new(size.0.parse().unwrap(), size.1.parse().unwrap()); | ||||
|                 #[cfg(target_arch = "wasm32")] | ||||
|                 { | ||||
|                     image = Image::from_uri(format!(concat!(env!("PHOST"), "/{}"), url.0)); | ||||
|                     let split = url.0.rsplit_once('.').unwrap(); | ||||
|                     hi_image = Image::from_uri(format!( | ||||
|                         concat!(env!("PHOST"), "/{}_hi.{}"), | ||||
|                         split.0, split.1 | ||||
|                     )); | ||||
|                 } | ||||
|                 #[cfg(not(target_arch = "wasm32"))] | ||||
|                 { | ||||
|                     image = Image::from_uri(format!("file://assets/{}", url.0)); | ||||
|                     let split = url.0.rsplit_once('.').unwrap(); | ||||
|                     hi_image = Image::from_uri(format!("file://assets/{}_hi.{}", split.0, split.1)); | ||||
|                 } | ||||
|                 let mut res = ( | ||||
|                     Rect::from_min_size( | ||||
|                         Pos2::new(buffer.indent.indent, self.size.y + paragraph_height), | ||||
|                         size, | ||||
|                     ), | ||||
|                     buffer.indent, | ||||
|                     ContextBlock::Image { | ||||
|                         alt_text: Arc::new(RwLock::new(buffer.buffer)), | ||||
|                         image, | ||||
|                         hi_image, | ||||
|                     }, | ||||
|             None, | ||||
|             1.0, | ||||
|             env!("PHOST"), | ||||
|         ); | ||||
|                 const IMAGE_PADDING: f32 = 8.0; | ||||
|                 if let Some(last_size) = last_image_size.as_mut() { | ||||
|                     let ls = *last_size; | ||||
|                     last_size.x += size.x + IMAGE_PADDING; | ||||
| 
 | ||||
|                     if last_size.x > max_width { | ||||
|                         self.size.y += last_size.y + paragraph_height; | ||||
|                         last_size.x = size.x + IMAGE_PADDING; | ||||
|                         last_size.y = size.y; | ||||
|                         res.0 = Rect::from_min_size( | ||||
|                             Pos2::new(buffer.indent.indent, self.size.y + paragraph_height), | ||||
|                             size, | ||||
|                         ); | ||||
|                     } else { | ||||
|                         last_size.y = last_size.y.max(size.y); | ||||
|                         res.0 = res.0.translate(Vec2::new(ls.x, 0.0)); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if size.x > max_width { | ||||
|                         let max_size = Vec2::new(max_width, size.y); | ||||
|                         let new_size = ImageSize { | ||||
|                             max_size, | ||||
|                             ..Default::default() | ||||
|                         } | ||||
|                         .calc_size(max_size, size); | ||||
|                         res.0 = Rect::from_min_size( | ||||
|                             Pos2::new(buffer.indent.indent, self.size.y + paragraph_height), | ||||
|                             new_size, | ||||
|                         ); | ||||
|                         self.size.y += new_size.y + paragraph_height; | ||||
|                     } else { | ||||
|                         last_image_size = Some(size + Vec2::new(IMAGE_PADDING, 0.0)); | ||||
|                     } | ||||
|                 } | ||||
|                 res | ||||
|             } else { | ||||
|                 if let Some(size) = last_image_size { | ||||
|                     self.size.y += size.y + paragraph_height; | ||||
|                 } | ||||
|                 let res = ( | ||||
|                     Rect::from_min_size( | ||||
|                         Pos2::new(buffer.indent.indent, self.size.y + paragraph_height), | ||||
|                         measurement.size(), | ||||
|                     ), | ||||
|                     buffer.indent, | ||||
|                     ContextBlock::Buffer(Arc::new(RwLock::new(buffer.buffer)), buffer.url_map), | ||||
|                 ); | ||||
|                 last_image_size = None; | ||||
|                 self.size.y += measurement.height() + paragraph_height; | ||||
|                 res | ||||
|             }; | ||||
|             self.size.x = self.size.x.max(measurement.width()); | ||||
|             buffer | ||||
|         self.text = text | ||||
|             .into_iter() | ||||
|             .map(|t| ResolvedItem { | ||||
|                 indent: t.indent, | ||||
|                 buffer: Arc::new(RwLock::new(t.buffer)), | ||||
|                 relative_bounds: t.relative_bounds, | ||||
|                 url_map: t.url_map, | ||||
|                 image_urls: t.image_urls, | ||||
|             }) | ||||
|             .collect(); | ||||
| 
 | ||||
|         if let Some(size) = last_image_size { | ||||
|             self.size.y += size.y; | ||||
|         } | ||||
|         self.size = size; | ||||
| 
 | ||||
|         #[cfg(target_arch = "wasm32")] | ||||
|         if let Some(name) = name { | ||||
|  | @ -743,113 +656,19 @@ impl eframe::App for Portfolio { | |||
|                         Rounding::same(25.0), | ||||
|                         Color32::BLACK.gamma_multiply(lerp(0.0..=0.5, zoom_view_opacity)), | ||||
|                     ); | ||||
|                     self.window | ||||
|                         .text | ||||
|                         .iter() | ||||
|                         .for_each(|context_block| match &context_block.2 { | ||||
|                             ContextBlock::Buffer(buffer, url_map) => { | ||||
|                                 let text_rect = context_block.0.translate(rect.min.to_vec2()); | ||||
|                                 // ui.painter().debug_rect(text_rect, Color32::GREEN, "");
 | ||||
|                                 if let Some(url_map) = url_map { | ||||
|                                     let text_response = ui.allocate_rect(text_rect, Sense::click()); | ||||
|                                     let mut buffer = buffer.write(); | ||||
|                                     let mut editor = | ||||
|                                         Editor::new(BufferRef::Borrowed(buffer.deref_mut())); | ||||
|                                     if text_response.hovered() | ||||
|                                         && ui.input(|i| i.raw_scroll_delta == Vec2::ZERO) | ||||
|                                     { | ||||
|                                         let mouse_pos = ui | ||||
|                                             .input(|i| i.pointer.latest_pos().unwrap_or_default()) | ||||
|                                             - text_rect.min.to_vec2(); | ||||
| 
 | ||||
|                                         editor.action( | ||||
|                                             self.font_system.lock().deref_mut(), | ||||
|                                             glyphon::Action::Click { | ||||
|                                                 x: mouse_pos.x as i32, | ||||
|                                                 y: mouse_pos.y as i32 - 3, | ||||
|                                             }, | ||||
|                                         ); | ||||
| 
 | ||||
|                                         let mut location = editor.cursor(); | ||||
|                                         match location.affinity { | ||||
|                                             glyphon::Affinity::After => location.index += 1, | ||||
|                                             glyphon::Affinity::Before => {} | ||||
|                                         } | ||||
| 
 | ||||
|                                         if url_map.get(location.index).is_some() { | ||||
|                                             ctx.set_cursor_icon(egui::CursorIcon::PointingHand); | ||||
|                                         } | ||||
|                                     } | ||||
|                                     if text_response.clicked() && !self.image_zoomed { | ||||
|                                         let mouse_click = ui.input(|i| { | ||||
|                                             i.pointer.interact_pos().unwrap_or_default() | ||||
|                                         }) - text_rect.min.to_vec2(); | ||||
| 
 | ||||
|                                         editor.action( | ||||
|                                             self.font_system.lock().deref_mut(), | ||||
|                                             glyphon::Action::Click { | ||||
|                                                 x: mouse_click.x as i32, | ||||
|                                                 y: mouse_click.y as i32, | ||||
|                                             }, | ||||
|                                         ); | ||||
| 
 | ||||
|                                         let mut location = editor.cursor(); | ||||
|                                         match location.affinity { | ||||
|                                             glyphon::Affinity::After => location.index += 1, | ||||
|                                             glyphon::Affinity::Before => {} | ||||
|                                         } | ||||
|                                         if let Some(url) = url_map.get(location.index) { | ||||
|                                             link_clicked = true; | ||||
|                                             if url.starts_with('#') { | ||||
|                                                 if let Some(icon) = CONTEXT_ICONS | ||||
|                                                     .iter() | ||||
|                                                     .find(|i| i.name == &url[1..]) | ||||
|                                                 { | ||||
|                                                     icon_link = Some(icon); | ||||
|                                                 } | ||||
|                                             } else { | ||||
|                                                 ui.ctx().open_url(OpenUrl::new_tab(url)); | ||||
|                                             } | ||||
|                                             // clicked = false;
 | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 buffers.push(BufferWithTextArea::new( | ||||
|                                     buffer.clone(), | ||||
|                                     text_rect, | ||||
|                                     zoom_view_opacity, | ||||
|                                     Color::rgb(255, 255, 255), | ||||
|                                     ui.ctx(), | ||||
|                                 )); | ||||
|                                 match context_block.1.modifier { | ||||
|                                     Some(ListKind::Unordered) => { | ||||
|                                         ui.painter().circle( | ||||
|                                             text_rect.min | ||||
|                                                 + Vec2::new( | ||||
|                                                     -INDENT_AMOUNT, | ||||
|                                                     CONTEXT_METRICS.line_height / 2.0, | ||||
|                                                 ), | ||||
|                                             2.5, | ||||
|                                             Color32::WHITE.gamma_multiply(zoom_view_opacity), | ||||
|                                             Stroke::NONE, | ||||
|                                         ); | ||||
|                                     } | ||||
|                                     _ => {} | ||||
|                                 } | ||||
|                             } | ||||
|                             ContextBlock::Image { | ||||
|                                 image, hi_image, .. | ||||
|                             } => { | ||||
|                                 let image_rect = context_block.0.translate(rect.min.to_vec2()); | ||||
|                     self.window.text.iter().for_each(|context_block| { | ||||
|                         if let Some(image_urls) = &context_block.image_urls { | ||||
|                             let image_rect = | ||||
|                                 context_block.relative_bounds.translate(rect.min.to_vec2()); | ||||
| 
 | ||||
|                             let image_response = ui.allocate_rect(image_rect, Sense::click()); | ||||
|                             let image_response_clicked = image_response.clicked(); | ||||
| 
 | ||||
|                             let time_offset = ui.memory_mut(|m| { | ||||
|                                 let time_offset = | ||||
|                                     m.data.get_temp_mut_or_default::<f64>(image_response.id); | ||||
| 
 | ||||
|                                     if image_response.clicked() && !self.image_zoomed && self.zoomed | ||||
|                                     { | ||||
|                                 if image_response_clicked && !self.image_zoomed && self.zoomed { | ||||
|                                     link_clicked = true; | ||||
|                                     *time_offset = time; | ||||
|                                     self.last_image_zoomed = image_response.id; | ||||
|  | @ -895,27 +714,24 @@ impl eframe::App for Portfolio { | |||
|                                 ui.painter().rect_filled( | ||||
|                                     ui.max_rect(), | ||||
|                                     Rounding::default(), | ||||
|                                         Color32::BLACK.gamma_multiply( | ||||
|                                             keyframe::ease_with_scaled_time( | ||||
|                                     Color32::BLACK.gamma_multiply(keyframe::ease_with_scaled_time( | ||||
|                                         functions::EaseInOutCubic, | ||||
|                                         if self.image_zoomed { 0.0 } else { 0.6 }, | ||||
|                                         if self.image_zoomed { 0.6 } else { 0.0 }, | ||||
|                                         time - time_offset, | ||||
|                                         0.5, | ||||
|                                             ), | ||||
|                                         ), | ||||
|                                     )), | ||||
|                                 ); | ||||
| 
 | ||||
|                                 if t > 0.0 { | ||||
|                                         hi_image.clone() | ||||
|                                     Image::from_uri(&image_urls.1) | ||||
|                                 } else { | ||||
|                                         image.clone() | ||||
|                                     Image::from_uri(&image_urls.0) | ||||
|                                 } | ||||
|                                 .tint(Color32::WHITE.gamma_multiply(zoom_view_opacity)) | ||||
|                                 .paint_at(&ui, image_rect.lerp_towards(&fs_rect, t)); | ||||
|                             } else { | ||||
|                                     image | ||||
|                                         .clone() | ||||
|                                 Image::from_uri(&image_urls.0) | ||||
|                                     .tint(Color32::WHITE.gamma_multiply(zoom_view_opacity)) | ||||
|                                     .paint_at( | ||||
|                                         ui, | ||||
|  | @ -931,6 +747,80 @@ impl eframe::App for Portfolio { | |||
|                                         ), | ||||
|                                     ); | ||||
|                             } | ||||
|                         } else { | ||||
|                             let text_rect = | ||||
|                                 context_block.relative_bounds.translate(rect.min.to_vec2()); | ||||
|                             // ui.painter().debug_rect(text_rect, Color32::GREEN, "");
 | ||||
|                             if let Some(url_map) = &context_block.url_map { | ||||
|                                 let text_response = ui.allocate_rect(text_rect, Sense::click()); | ||||
|                                 let mut buffer = context_block.buffer.write(); | ||||
|                                 let mut editor = | ||||
|                                     Editor::new(BufferRef::Borrowed(buffer.deref_mut())); | ||||
|                                 if text_response.hovered() | ||||
|                                     && ui.input(|i| i.raw_scroll_delta == Vec2::ZERO) | ||||
|                                 { | ||||
|                                     let mouse_pos = ui | ||||
|                                         .input(|i| i.pointer.latest_pos().unwrap_or_default()) | ||||
|                                         - text_rect.min.to_vec2(); | ||||
| 
 | ||||
|                                     editor.action( | ||||
|                                         self.font_system.lock().deref_mut(), | ||||
|                                         glyphon::Action::Click { | ||||
|                                             x: mouse_pos.x as i32, | ||||
|                                             y: mouse_pos.y as i32 - 3, | ||||
|                                         }, | ||||
|                                     ); | ||||
| 
 | ||||
|                                     let mut location = editor.cursor(); | ||||
|                                     match location.affinity { | ||||
|                                         glyphon::Affinity::After => location.index += 1, | ||||
|                                         glyphon::Affinity::Before => {} | ||||
|                                     } | ||||
| 
 | ||||
|                                     if url_map.get(&location.index).is_some() { | ||||
|                                         ctx.set_cursor_icon(egui::CursorIcon::PointingHand); | ||||
|                                     } | ||||
|                                 } | ||||
|                                 if text_response.clicked() && !self.image_zoomed { | ||||
|                                     let mouse_click = ui | ||||
|                                         .input(|i| i.pointer.interact_pos().unwrap_or_default()) | ||||
|                                         - text_rect.min.to_vec2(); | ||||
| 
 | ||||
|                                     editor.action( | ||||
|                                         self.font_system.lock().deref_mut(), | ||||
|                                         glyphon::Action::Click { | ||||
|                                             x: mouse_click.x as i32, | ||||
|                                             y: mouse_click.y as i32, | ||||
|                                         }, | ||||
|                                     ); | ||||
| 
 | ||||
|                                     let mut location = editor.cursor(); | ||||
|                                     match location.affinity { | ||||
|                                         glyphon::Affinity::After => location.index += 1, | ||||
|                                         glyphon::Affinity::Before => {} | ||||
|                                     } | ||||
|                                     if let Some(url) = url_map.get(&location.index) { | ||||
|                                         link_clicked = true; | ||||
|                                         if url.starts_with('#') { | ||||
|                                             if let Some(icon) = | ||||
|                                                 CONTEXT_ICONS.iter().find(|i| i.name == &url[1..]) | ||||
|                                             { | ||||
|                                                 icon_link = Some(icon); | ||||
|                                             } | ||||
|                                         } else { | ||||
|                                             ui.ctx().open_url(OpenUrl::new_tab(url)); | ||||
|                                         } | ||||
|                                         // clicked = false;
 | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             buffers.push(BufferWithTextArea::new( | ||||
|                                 context_block.buffer.clone(), | ||||
|                                 text_rect, | ||||
|                                 zoom_view_opacity, | ||||
|                                 Color::rgb(255, 255, 255), | ||||
|                                 ui.ctx(), | ||||
|                             )); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue