#![allow(unused_must_use)]
use everything_plugin::ui::winio::prelude::*;
use crate::{App, HANDLER};
#[allow(dead_code)]
pub fn main() {
winio::ui::App::new("rs.compio.winio.widgets")
.unwrap()
.run::<MainModel>(())
.unwrap();
}
pub struct MainModel {
window: Child<View>,
ulabel: Child<Label>,
plabel: Child<Label>,
uentry: Child<Edit>,
pentry: Child<Edit>,
pcheck: Child<CheckBox>,
canvas: Child<Canvas>,
combo: Child<ComboBox>,
list: Child<ObservableVec<String>>,
index: Option<usize>,
radio_group: Child<RadioButtonGroup>,
rindex: usize,
push_button: Child<Button>,
pop_button: Child<Button>,
show_button: Child<Button>,
progress: Child<Progress>,
mltext: Child<TextBox>,
}
#[derive(Debug)]
pub enum MainMessage {
Noop,
List(ObservableVecEvent<String>),
Select,
Push,
Pop,
Show,
RSelect(usize),
PasswordCheck,
OptionsPage(OptionsPageMessage<App>),
}
impl From<OptionsPageMessage<App>> for MainMessage {
fn from(value: OptionsPageMessage<App>) -> Self {
Self::OptionsPage(value)
}
}
impl Component for MainModel {
type Event = ();
type Init<'a> = OptionsPageInit<'a, App>;
type Message = MainMessage;
type Error = Error;
async fn init(
mut init: Self::Init<'_>,
sender: &ComponentSender<Self>,
) -> Result<Self, Self::Error> {
let mut window = init.window(sender).await?;
window.set_size(Size::new(800.0, 600.0));
let canvas = Child::<Canvas>::init(&window).await?;
let mut ulabel = Child::<Label>::init(&window).await?;
ulabel.set_text("Username:");
ulabel.set_halign(HAlign::Right);
let mut plabel = Child::<Label>::init(&window).await?;
plabel.set_text("Password:");
plabel.set_halign(HAlign::Right);
let mut uentry = Child::<Edit>::init(&window).await?;
uentry.set_text("AAA");
let mut pentry = Child::<Edit>::init(&window).await?;
pentry.set_text("123456");
pentry.set_password(true);
let mut pcheck = Child::<CheckBox>::init(&window).await?;
pcheck.set_text("Show");
pcheck.set_checked(false);
let combo = Child::<ComboBox>::init(&window).await?;
let mut list = Child::<ObservableVec<String>>::init(Vec::new())
.await
.unwrap();
list.push("烫烫烫".to_string());
list.push("昍昍昍".to_string());
list.push("フフフフフフ".to_string());
list.push("쳌쳌쳌".to_string());
let mut r1 = Child::<RadioButton>::init(&window).await?;
r1.set_text("屯屯屯");
r1.set_checked(true);
let mut r2 = Child::<RadioButton>::init(&window).await?;
r2.set_text("锟斤拷");
let mut r3 = Child::<RadioButton>::init(&window).await?;
r3.set_text("╠╠╠");
let radio_group = Child::<RadioButtonGroup>::init(vec![r1, r2, r3]).await?;
let mut push_button = Child::<Button>::init(&window).await?;
push_button.set_text("Push");
let mut pop_button = Child::<Button>::init(&window).await?;
pop_button.set_text("Pop");
let mut show_button = Child::<Button>::init(&window).await?;
show_button.set_text("Show");
let mut progress = Child::<Progress>::init(&window).await?;
progress.set_indeterminate(true);
let mut mltext = Child::<TextBox>::init(&window).await?;
HANDLER.with_app(|a| mltext.set_text(&a.config().s));
window.show();
Ok(Self {
window,
ulabel,
plabel,
uentry,
pentry,
pcheck,
canvas,
combo,
list,
index: None,
radio_group,
rindex: 0,
push_button,
pop_button,
show_button,
progress,
mltext,
})
}
async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
start! {
sender, default: MainMessage::Noop,
self.pcheck => {
CheckBoxEvent::Click => MainMessage::PasswordCheck,
},
self.combo => {
ComboBoxEvent::Select => MainMessage::Select,
},
self.push_button => {
ButtonEvent::Click => MainMessage::Push,
},
self.pop_button => {
ButtonEvent::Click => MainMessage::Pop,
},
self.show_button => {
ButtonEvent::Click => MainMessage::Show,
},
self.list => {
e => MainMessage::List(e),
},
self.radio_group => {
RadioButtonGroupEvent::Click(i) => MainMessage::RSelect(i)
}
}
}
async fn update_children(&mut self) -> Result<bool, Self::Error> {
update_children!(self.window, self.canvas, self.radio_group)
}
async fn update(
&mut self,
message: Self::Message,
sender: &ComponentSender<Self>,
) -> Result<bool, Self::Error> {
Ok(match message {
MainMessage::Noop => false,
MainMessage::PasswordCheck => {
self.pentry.set_password(!self.pcheck.is_checked()?);
true
}
MainMessage::List(e) => {
self.pop_button.set_enabled(!self.list.is_empty());
self.combo
.emit(ComboBoxMessage::from_observable_vec_event(e))
.await?
}
MainMessage::Select => {
self.index = self.combo.selection()?;
false
}
MainMessage::Push => {
self.list.push(self.radio_group[self.rindex].text()?);
false
}
MainMessage::Pop => {
self.list.pop();
false
}
MainMessage::RSelect(i) => {
self.rindex = i;
false
}
MainMessage::Show => {
MessageBox::new()
.title("Show selected item")
.message(
self.index
.and_then(|index| self.list.get(index))
.map(|s| s.as_str())
.unwrap_or("No selection."),
)
.buttons(MessageBoxButton::Ok)
.show(unsafe { BorrowedWindow::win32(self.window.as_container().as_win32()) })
.await;
false
}
MainMessage::OptionsPage(m) => {
tracing::debug!(?m, "Options page message");
match m {
OptionsPageMessage::Redraw => true,
OptionsPageMessage::Close => {
sender.output(());
false
}
OptionsPageMessage::Save(config, tx) => {
config.s = self.mltext.text()?;
tx.send(config).unwrap();
false
}
}
}
})
}
fn render(&mut self, _sender: &ComponentSender<Self>) -> Result<(), Self::Error> {
let csize = self.window.size()?;
{
let mut cred_panel = layout! {
Grid::from_str("auto,1*,auto", "1*,auto,auto,1*").unwrap(),
self.ulabel => { column: 0, row: 1, valign: VAlign::Center },
self.uentry => { column: 1, row: 1, margin: Margin::new_all_same(4.0) },
self.plabel => { column: 0, row: 2, valign: VAlign::Center },
self.pentry => { column: 1, row: 2, margin: Margin::new_all_same(4.0) },
self.pcheck => { column: 2, row: 2 },
};
let mut rgroup_panel = Grid::from_str("auto", "1*,auto,auto,auto,1*").unwrap();
for (i, rb) in self.radio_group.iter_mut().enumerate() {
rgroup_panel.push(rb).row(i + 1).finish();
}
let mut buttons_panel = layout! {
StackPanel::new(Orient::Vertical),
self.push_button => { margin: Margin::new_all_same(4.0) },
self.pop_button => { margin: Margin::new_all_same(4.0) },
self.show_button => { margin: Margin::new_all_same(4.0) },
};
let mut root_panel = layout! {
Grid::from_str("1*,1*,1*", "1*,auto,1*").unwrap(),
cred_panel => { column: 1, row: 0 },
rgroup_panel => { column: 2, row: 0, halign: HAlign::Center },
self.canvas => { column: 0, row: 1, row_span: 2 },
self.combo => { column: 1, row: 1, halign: HAlign::Center },
self.progress => { column: 2, row: 1 },
self.mltext => { column: 1, row: 2, margin: Margin::new_all_same(8.0) },
buttons_panel => { column: 2, row: 2 },
};
root_panel.set_size(csize);
}
let size = self.canvas.size()?;
let is_dark = ColorTheme::current()? == ColorTheme::Dark;
let back_color = if is_dark {
Color::new(255, 255, 255, 255)
} else {
Color::new(0, 0, 0, 255)
};
let brush = SolidColorBrush::new(back_color);
let pen = BrushPen::new(&brush, 1.0);
let mut ctx = self.canvas.context()?;
let cx = size.width / 2.0;
let cy = size.height / 2.0;
let r = cx.min(cy) - 2.0;
ctx.draw_pie(
&pen,
Rect::new(Point::new(cx - r, cy - r), Size::new(r * 2.0, r * 2.0)),
std::f64::consts::PI,
std::f64::consts::PI * 2.0,
);
let brush2 = LinearGradientBrush::new(
[
GradientStop::new(Color::new(0x87, 0xCE, 0xEB, 0xFF), 0.0),
GradientStop::new(back_color, 1.0),
],
RelativePoint::zero(),
RelativePoint::new(0.0, 1.0),
);
let pen2 = BrushPen::new(&brush2, 1.0);
ctx.draw_round_rect(
&pen2,
Rect::new(
Point::new(cx - r - 1.0, cy - r - 1.0),
Size::new(r * 2.0 + 2.0, r * 1.618 + 2.0),
),
Size::new(r / 10.0, r / 10.0),
);
let mut path = ctx.create_path_builder(Point::new(cx + r + 1.0 - r / 10.0, cy))?;
path.add_arc(
Point::new(cx, cy + r * 0.618 + 1.0),
Size::new(r + 1.0 - r / 10.0, r * 0.382 / 2.0),
0.0,
std::f64::consts::PI,
true,
);
path.add_line(Point::new(cx - r - 1.0 + r / 10.0, cy));
let path = path.build(false)?;
ctx.draw_path(&pen, &path);
let brush3 = RadialGradientBrush::new(
[
GradientStop::new(Color::new(0xF5, 0xF5, 0xF5, 0xFF), 0.0),
GradientStop::new(
Color::accent().unwrap_or(Color::new(0xFF, 0xC0, 0xCB, 0xFF)),
1.0,
),
],
RelativePoint::new(0.5, 0.5),
RelativePoint::new(0.2, 0.5),
RelativeSize::new(0.5, 0.5),
);
let font = DrawingFontBuilder::new()
.family("Arial")
.size(r / 5.0)
.halign(HAlign::Center)
.valign(VAlign::Bottom)
.build();
ctx.draw_str(&brush3, font, Point::new(cx, cy), "Hello world!");
Ok(())
}
}