example: Add resizable feature to HTML, Markdown example. (#872)

This commit is contained in:
Jason Lee 2025-05-20 18:25:14 +08:00 committed by GitHub
parent 5658db42c7
commit e68419bc95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 49 deletions

View file

@ -2,9 +2,9 @@ use std::sync::LazyLock;
use gpui::*; use gpui::*;
use gpui_component::{ use gpui_component::{
h_flex,
highlighter::{HighlightTheme, Highlighter}, highlighter::{HighlightTheme, Highlighter},
input::{InputState, TextInput}, input::{InputState, TabSize, TextInput},
resizable::{h_resizable, resizable_panel, ResizableState},
text::TextView, text::TextView,
ActiveTheme as _, ActiveTheme as _,
}; };
@ -15,6 +15,7 @@ static DARK_THEME: LazyLock<HighlightTheme> = LazyLock::new(|| HighlightTheme::d
pub struct Example { pub struct Example {
input_state: Entity<InputState>, input_state: Entity<InputState>,
resizable_state: Entity<ResizableState>,
is_dark: bool, is_dark: bool,
_subscribe: Subscription, _subscribe: Subscription,
} }
@ -27,10 +28,16 @@ impl Example {
let input_state = cx.new(|cx| { let input_state = cx.new(|cx| {
InputState::new(window, cx) InputState::new(window, cx)
.code_editor(Some(LANG), &LIGHT_THEME) .code_editor(Some(LANG), &LIGHT_THEME)
.tab_size(TabSize {
tab_size: 4,
hard_tabs: false,
})
.default_value(EXAMPLE) .default_value(EXAMPLE)
.placeholder("Enter your HTML here...") .placeholder("Enter your HTML here...")
}); });
let resizable_state = ResizableState::new(cx);
let _subscribe = cx.subscribe( let _subscribe = cx.subscribe(
&input_state, &input_state,
|_, _, _: &gpui_component::input::InputEvent, cx| { |_, _, _: &gpui_component::input::InputEvent, cx| {
@ -40,6 +47,7 @@ impl Example {
Self { Self {
input_state, input_state,
resizable_state,
is_dark: false, is_dark: false,
_subscribe, _subscribe,
} }
@ -64,27 +72,26 @@ impl Render for Example {
}); });
} }
h_flex() h_resizable("container", self.resizable_state.clone())
.h_full()
.child( .child(
div() resizable_panel().child(
.id("source") div()
.h_full() .id("source")
.w_1_2() .size_full()
.border_r_1() .font_family("Menlo")
.border_color(cx.theme().border) .text_size(px(13.))
.font_family("Menlo") .child(TextInput::new(&self.input_state).h_full().appearance(false)),
.text_size(px(13.)) ),
.child(TextInput::new(&self.input_state).h_full().appearance(false)),
) )
.child( .child(
div() resizable_panel().child(
.id("preview") div()
.h_full() .id("preview")
.w_1_2() .size_full()
.p_5() .p_5()
.overflow_y_scroll() .overflow_y_scroll()
.child(TextView::html("preview", self.input_state.read(cx).value())), .child(TextView::html("preview", self.input_state.read(cx).value())),
),
) )
} }
} }

View file

@ -3,7 +3,8 @@ use std::{rc::Rc, sync::LazyLock};
use gpui::*; use gpui::*;
use gpui_component::{ use gpui_component::{
highlighter::{HighlightTheme, Highlighter}, highlighter::{HighlightTheme, Highlighter},
input::{InputEvent, InputState, TextInput}, input::{InputEvent, InputState, TabSize, TextInput},
resizable::{h_resizable, resizable_panel, ResizableState},
text::{TextView, TextViewStyle}, text::{TextView, TextViewStyle},
ActiveTheme as _, ActiveTheme as _,
}; };
@ -15,6 +16,7 @@ const LANG: &str = "markdown";
pub struct Example { pub struct Example {
input_state: Entity<InputState>, input_state: Entity<InputState>,
resizable_state: Entity<ResizableState>,
is_dark: bool, is_dark: bool,
} }
@ -25,15 +27,22 @@ impl Example {
let input_state = cx.new(|cx| { let input_state = cx.new(|cx| {
InputState::new(window, cx) InputState::new(window, cx)
.code_editor(Some(LANG), &LIGHT_THEME) .code_editor(Some(LANG), &LIGHT_THEME)
.line_number(false)
.tab_size(TabSize {
tab_size: 2,
..Default::default()
})
.placeholder("Enter your Markdown here...") .placeholder("Enter your Markdown here...")
.default_value(EXAMPLE) .default_value(EXAMPLE)
}); });
let resizable_state = ResizableState::new(cx);
let _subscribe = cx.subscribe(&input_state, |_, _, _: &InputEvent, cx| { let _subscribe = cx.subscribe(&input_state, |_, _, _: &InputEvent, cx| {
cx.notify(); cx.notify();
}); });
Self { Self {
resizable_state,
input_state, input_state,
is_dark: false, is_dark: false,
} }
@ -64,36 +73,31 @@ impl Render for Example {
}); });
} }
div() h_resizable("container", self.resizable_state.clone())
.flex()
.flex_row()
.h_full()
.child( .child(
div() resizable_panel().child(
.id("source") div()
.h_full() .id("source")
.w_1_2() .size_full()
.border_r_1() .child(TextInput::new(&self.input_state).h_full().appearance(false)),
.border_color(cx.theme().border) ),
.flex_1()
.child(TextInput::new(&self.input_state).h_full().appearance(false)),
) )
.child( .child(
div() resizable_panel().child(
.id("preview") div()
.h_full() .id("preview")
.w_1_2() .size_full()
.p_5() .p_5()
.flex_1() .overflow_y_scroll()
.overflow_y_scroll() .child(
.child( TextView::markdown("preview", self.input_state.read(cx).value()).style(
TextView::markdown("preview", self.input_state.read(cx).value()).style( TextViewStyle {
TextViewStyle { highlight_theme: Rc::new(theme),
highlight_theme: Rc::new(theme), ..Default::default()
..Default::default() },
}, ),
), ),
), ),
) )
} }
} }

View file

@ -1,2 +0,0 @@
[toolchain]
channel = "1.86"