Skip to content

Commit

Permalink
Add speaker edit modal
Browse files Browse the repository at this point in the history
  • Loading branch information
bigfoodK committed Oct 26, 2024
1 parent 4f00a96 commit 7bb3078
Showing 1 changed file with 286 additions and 1 deletion.
287 changes: 286 additions & 1 deletion luda-editor/new-client/src/episode_editor/speaker_selector.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::*;
use list_view::AutoListView;
use luda_rpc::Scene;
use namui::*;
use namui_prebuilt::*;
Expand All @@ -25,6 +26,7 @@ impl Component for SpeakerSelector<'_> {
let (speakers, set_speakers) =
ctx.state::<Option<BTreeMap<String, Option<String>>>>(|| None);
let (error_msg, set_error_msg) = ctx.state::<Option<String>>(|| None);
let (show_edit_speaker_modal, set_show_edit_speaker_modal) = ctx.state(|| false);

ctx.async_effect(
"load speaker ids",
Expand Down Expand Up @@ -79,6 +81,24 @@ impl Component for SpeakerSelector<'_> {
},
);

let add_speaker = |name: &str| {
todo!();
};
let close_modal = move || {
set_show_edit_speaker_modal.set(false);
};

ctx.compose(|ctx| {
if !*show_edit_speaker_modal {
return;
}
ctx.add(EditSpeakerModal {
speakers: speakers.as_ref(),
add_speaker: &add_speaker,
close: &close_modal,
});
});

ctx.compose(|ctx| {
let items = {
let mut items = vec![];
Expand Down Expand Up @@ -114,7 +134,9 @@ impl Component for SpeakerSelector<'_> {
stroke_width: 1.px(),
fill_color: Color::BLACK,
mouse_buttons: vec![MouseButton::Left],
on_mouse_up_in: |_event| todo!(),
on_mouse_up_in: |_event| {
set_show_edit_speaker_modal.set(true);
},
});
}));

Expand All @@ -124,3 +146,266 @@ impl Component for SpeakerSelector<'_> {
});
}
}

struct EditSpeakerModal<'a> {
speakers: &'a Option<BTreeMap<String, Option<String>>>,
add_speaker: &'a dyn Fn(&str),
close: &'a dyn Fn(),
}
impl Component for EditSpeakerModal<'_> {
fn render(self, ctx: &RenderCtx) {
let Self {
speakers,
add_speaker,
close,
} = self;
const MODAL_WH: Wh<Px> = Wh::new(px(512.0), px(480.0));

let screen_wh = screen::size().map(|x| x.into_px());
let (new_speaker_name, set_new_speaker_name) = ctx.state(|| "".to_string());
let (left_selected_speaker_id, set_left_selected_speaker_id) = ctx.state(|| None);
let (right_selected_speaker_id, set_right_selected_speaker_id) = ctx.state(|| None);

let select_left_speaker = |speaker_id: &str| {
set_left_selected_speaker_id.set(Some(speaker_id.to_string()));
};

let select_right_speaker = |speaker_id: &str| {
set_right_selected_speaker_id.set(Some(speaker_id.to_string()));
};

ctx.compose(move |ctx| {
let ctx = ctx.on_top().absolute((0.px(), 0.px()));

let left_top = (screen_wh / 2.0) - MODAL_WH / 2.0;
ctx.translate(left_top.as_xy()).compose(|ctx| {
ctx.compose(|ctx| {
table::padding(
8.px(),
vertical([
table::ratio(
1,
horizontal([
ratio(1, |wh, ctx| {
ctx.add(SpeakerList {
wh,
speakers,
select_speaker: &select_left_speaker,
selected_speaker_id: left_selected_speaker_id.as_ref(),
});
}),
fixed(
96.px(),
padding(
8.px(),
vertical([
ratio(1, |_wh, _ctx| {}),
fixed(36.px(), |wh, ctx| {
ctx.add(button::TextButton {
rect: wh.to_rect(),
text: ">>>>>",
text_color: Color::WHITE,
stroke_color: Color::BLACK,
stroke_width: 1.px(),
fill_color: Color::BLUE,
mouse_buttons: vec![MouseButton::Left],
on_mouse_up_in: |_event| {
todo!("");
},
});
}),
table::fixed(8.px(), |_wh, _ctx| {}),
fixed(36.px(), |wh, ctx| {
ctx.add(button::TextButton {
rect: wh.to_rect(),
text: "<<<<<",
text_color: Color::WHITE,
stroke_color: Color::BLACK,
stroke_width: 1.px(),
fill_color: Color::BLUE,
mouse_buttons: vec![MouseButton::Left],
on_mouse_up_in: |_event| {
todo!("");
},
});
}),
ratio(1, |_wh, _ctx| {}),
]),
),
),
ratio(1, |wh, ctx| {
ctx.add(SpeakerList {
wh,
speakers,
select_speaker: &select_right_speaker,
selected_speaker_id: right_selected_speaker_id.as_ref(),
});
}),
]),
),
table::fixed(8.px(), |_wh, _ctx| {}),
table::fixed(
36.px(),
horizontal([
ratio(1, |wh, ctx| {
ctx.add(TextInput {
rect: Rect::zero_wh(wh),
start_text: new_speaker_name.as_ref(),
text_align: TextAlign::Center,
text_baseline: TextBaseline::Middle,
font: Font {
size: 16.int_px(),
name: "NotoSansKR-Regular".to_string(),
},
style: Style {
rect: RectStyle {
stroke: Some(RectStroke {
color: Color::WHITE,
width: 1.px(),
border_position: BorderPosition::Middle,
}),
fill: Some(RectFill {
color: Color::grayscale_f01(0.3),
}),
round: Some(RectRound { radius: 4.px() }),
},
text: TextStyle {
color: Color::WHITE,
..Default::default()
},
padding: Ltrb::all(8.px()),
},
prevent_default_codes: &[Code::Enter],
focus: None,
on_edit_done: &|text| {
set_new_speaker_name.set(text);
},
});
}),
fixed(8.px(), |_wh, _ctx| {}),
fixed(192.px(), |wh, ctx| {
ctx.add(button::TextButton {
rect: wh.to_rect(),
text: "새 캐릭터 추가하기",
text_color: Color::WHITE,
stroke_color: Color::BLACK,
stroke_width: 1.px(),
fill_color: Color::BLUE,
mouse_buttons: vec![MouseButton::Left],
on_mouse_up_in: |_event| {
if new_speaker_name.is_empty() {
toast::negative("이름을 입력해주세요.");
return;
}
add_speaker(new_speaker_name.as_ref());
},
});
}),
]),
),
]),
)(MODAL_WH, ctx);
});

ctx.add(simple_rect(
MODAL_WH,
Color::from_u8(0xEE, 0xEE, 0xEE, 0xFF),
1.px(),
Color::from_u8(0x55, 0x55, 0x55, 0xFF),
));

ctx.add(
simple_rect(
MODAL_WH,
Color::TRANSPARENT,
0.px(),
Color::from_u8(0xDD, 0xDD, 0xDD, 0xFF),
)
.attach_event(|event| {
let Event::MouseDown { event } = event else {
return;
};
if event.is_local_xy_in() {
event.stop_propagation();
}
}),
);
});

ctx.add(
simple_rect(
screen_wh,
Color::TRANSPARENT,
0.px(),
Color::grayscale_alpha_f01(0.0, 0.5),
)
.attach_event(|event| {
let Event::MouseDown { event } = event else {
return;
};
if !event.is_local_xy_in() {
return;
}
event.stop_propagation();
close();
}),
);
});
}
}

struct SpeakerList<'a> {
wh: Wh<Px>,
speakers: &'a Option<BTreeMap<String, Option<String>>>,
select_speaker: &'a dyn Fn(&str),
selected_speaker_id: &'a Option<String>,
}
impl Component for SpeakerList<'_> {
fn render(self, ctx: &RenderCtx) {
let Self {
wh,
speakers,
select_speaker,
selected_speaker_id: selected_speaker,
} = self;

const SCROLL_BAR_WIDTH: Px = px(4.0);

let item_wh = Wh::new(wh.width - SCROLL_BAR_WIDTH, 36.px());

ctx.compose(|ctx| {
let Some(speakers) = speakers else {
return;
};
ctx.add(AutoListView {
height: wh.height,
scroll_bar_width: 4.px(),
item_wh,
items: speakers.iter().map(|(speaker_id, name)| {
let is_on = selected_speaker
.as_ref()
.map(|x| x == speaker_id)
.unwrap_or_default();
(
speaker_id.to_string(),
simple_toggle_button(
item_wh,
name.clone().unwrap_or_default(),
is_on,
|_event| {
select_speaker(speaker_id);
},
),
)
}),
});
});

ctx.add(simple_rect(
wh,
Color::from_u8(0xEE, 0xEE, 0xEE, 0xFF),
1.px(),
Color::from_u8(0x44, 0x44, 0x44, 0xFF),
));
}
}

0 comments on commit 7bb3078

Please sign in to comment.