Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add a way to specify user data for rust #4539

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions api/rs/build/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ impl CompilerConfiguration {
};
Self { config }
}

/// The generated component will take an argument of the type in its new() function.
/// The component will aldo have a have a `user_data()` function that returns a reference to it
#[must_use]
pub fn with_user_data_type(mut self, type_name: &str) -> CompilerConfiguration {
self.config.user_data_type = Some(type_name.to_string());
self
}
}

/// Error returned by the `compile` function
Expand Down Expand Up @@ -374,8 +382,11 @@ pub fn compile_with_config(
let syntax_node = syntax_node.expect("diags contained no compilation errors");

// 'spin_on' is ok here because the compiler in single threaded and does not block if there is no blocking future
let (doc, diag) =
spin_on::spin_on(i_slint_compiler::compile_syntax_node(syntax_node, diag, compiler_config));
let (doc, diag) = spin_on::spin_on(i_slint_compiler::compile_syntax_node(
syntax_node,
diag,
compiler_config.clone(),
));

if diag.has_error() {
let vec = diag.to_string_vec();
Expand All @@ -393,7 +404,7 @@ pub fn compile_with_config(

let file = std::fs::File::create(&output_file_path).map_err(CompileError::SaveError)?;
let mut code_formatter = CodeFormatter::new(BufWriter::new(file));
let generated = i_slint_compiler::generator::rust::generate(&doc);
let generated = i_slint_compiler::generator::rust::generate(&doc, &compiler_config);

for x in &diag.all_loaded_files {
if x.is_absolute() {
Expand Down
4 changes: 2 additions & 2 deletions api/rs/macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,13 @@ pub fn slint(stream: TokenStream) -> TokenStream {
compiler_config.include_paths = include_paths;
compiler_config.library_paths = library_paths;
let (root_component, diag) =
spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config));
spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config.clone()));
//println!("{:#?}", tree);
if diag.has_error() {
return diag.report_macro_diagnostic(&tokens);
}

let mut result = generator::rust::generate(&root_component);
let mut result = generator::rust::generate(&root_component, &compiler_config);

// Make sure to recompile if any of the external files changes
let reload = diag
Expand Down
5 changes: 3 additions & 2 deletions examples/printerdemo/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT

fn main() {
slint_build::compile("../ui/printerdemo.slint").unwrap();
slint_build::print_rustc_flags().unwrap();
let config =
slint_build::CompilerConfiguration::new().with_user_data_type("crate::PrinterQueueData");
slint_build::compile_with_config("../ui/printerdemo.slint", config).unwrap();
}
43 changes: 23 additions & 20 deletions examples/printerdemo/rust/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn current_time() -> slint::SharedString {
return "".into();
}

struct PrinterQueueData {
pub struct PrinterQueueData {
data: Rc<slint::VecModel<PrinterQueueItem>>,
print_progress_timer: slint::Timer,
}
Expand All @@ -43,7 +43,11 @@ pub fn main() {
#[cfg(all(debug_assertions, target_arch = "wasm32"))]
console_error_panic_hook::set_once();

let main_window = MainWindow::new().unwrap();
let printer_queue = PrinterQueueData {
data: Rc::new(slint::VecModel::default()),
print_progress_timer: Default::default(),
};
let main_window = MainWindow::new(printer_queue).unwrap();
main_window.set_ink_levels(
[
InkLevel { color: slint::Color::from_rgb_u8(0, 255, 255), level: 0.40 },
Expand All @@ -56,45 +60,44 @@ pub fn main() {

let default_queue: Vec<PrinterQueueItem> =
main_window.global::<PrinterQueue>().get_printer_queue().iter().collect();
let printer_queue = Rc::new(PrinterQueueData {
data: Rc::new(slint::VecModel::from(default_queue)),
print_progress_timer: Default::default(),
});
main_window.global::<PrinterQueue>().set_printer_queue(printer_queue.data.clone().into());
main_window.user_data().data.set_vec(default_queue);
main_window
.global::<PrinterQueue>()
.set_printer_queue(main_window.user_data().data.clone().into());

main_window.on_quit(move || {
#[cfg(not(target_arch = "wasm32"))]
std::process::exit(0);
});

let printer_queue_copy = printer_queue.clone();
let weak = main_window.as_weak();
main_window.global::<PrinterQueue>().on_start_job(move |title| {
printer_queue_copy.push_job(title);
weak.unwrap().user_data().push_job(title);
});

let printer_queue_copy = printer_queue.clone();
let weak = main_window.as_weak();
main_window.global::<PrinterQueue>().on_cancel_job(move |idx| {
printer_queue_copy.data.remove(idx as usize);
weak.unwrap().user_data().data.remove(idx as usize);
});

let printer_queue_weak = Rc::downgrade(&printer_queue);
printer_queue.print_progress_timer.start(
let weak = main_window.as_weak();
main_window.user_data().print_progress_timer.start(
slint::TimerMode::Repeated,
std::time::Duration::from_secs(1),
move || {
if let Some(printer_queue) = printer_queue_weak.upgrade() {
if printer_queue.data.row_count() > 0 {
let mut top_item = printer_queue.data.row_data(0).unwrap();
if let Some(main_window) = weak.upgrade() {
if main_window.user_data().data.row_count() > 0 {
let mut top_item = main_window.user_data().data.row_data(0).unwrap();
top_item.progress += 1;
top_item.status = JobStatus::Waiting;
if top_item.progress > 100 {
printer_queue.data.remove(0);
if printer_queue.data.row_count() == 0 {
main_window.user_data().data.remove(0);
if main_window.user_data().data.row_count() == 0 {
return;
}
top_item = printer_queue.data.row_data(0).unwrap();
top_item = main_window.user_data().data.row_data(0).unwrap();
}
printer_queue.data.set_row_data(0, top_item);
main_window.user_data().data.set_row_data(0, top_item);
} else {
// FIXME: stop this timer?
}
Expand Down
4 changes: 3 additions & 1 deletion examples/slide_puzzle/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
// SPDX-License-Identifier: MIT

fn main() {
slint_build::compile("slide_puzzle.slint").unwrap();
let config = slint_build::CompilerConfiguration::new()
.with_user_data_type("std::cell::RefCell<crate::AppState>");
slint_build::compile_with_config("slide_puzzle.slint", config).unwrap();
}
79 changes: 39 additions & 40 deletions examples/slide_puzzle/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ fn shuffle() -> Vec<i8> {
vec
}

struct AppState {
// This is pub because otherwise there is a warning: "type `AppState` is more private than the item `MainWindow::new`"
pub struct AppState {
pieces: Rc<slint::VecModel<Piece>>,
main_window: slint::Weak<MainWindow>,
/// An array of 16 values which represent a 4x4 matrix containing the piece number in that
/// position. -1 is no piece.
positions: Vec<i8>,
Expand All @@ -60,22 +60,22 @@ impl AppState {
}
}

fn randomize(&mut self) {
fn randomize(&mut self, main_window: &MainWindow) {
self.positions = shuffle();
for (i, p) in self.positions.iter().enumerate() {
self.set_pieces_pos(*p, i as _);
}
self.main_window.unwrap().set_moves(0);
self.apply_tiles_left();
main_window.set_moves(0);
self.apply_tiles_left(main_window);
}

fn apply_tiles_left(&mut self) {
fn apply_tiles_left(&mut self, main_window: &MainWindow) {
let left = 15 - self.positions.iter().enumerate().filter(|(i, x)| *i as i8 == **x).count();
self.main_window.unwrap().set_tiles_left(left as _);
main_window.set_tiles_left(left as _);
self.finished = left == 0;
}

fn piece_clicked(&mut self, p: i8) -> bool {
fn piece_clicked(&mut self, p: i8, main_window: &MainWindow) -> bool {
let piece = self.pieces.row_data(p as usize).unwrap_or_default();
assert_eq!(self.positions[(piece.pos_x * 4 + piece.pos_y) as usize], p);

Expand All @@ -94,10 +94,8 @@ impl AppState {
);
return false;
};
self.apply_tiles_left();
if let Some(x) = self.main_window.upgrade() {
x.set_moves(x.get_moves() + 1);
}
self.apply_tiles_left(main_window);
main_window.set_moves(main_window.get_moves() + 1);
true
}

Expand All @@ -110,7 +108,7 @@ impl AppState {
}
}

fn random_move(&mut self) {
fn random_move(&mut self, main_window: &MainWindow) {
let mut rng = rand::thread_rng();
let hole = self.positions.iter().position(|x| *x == -1).unwrap() as i8;
let mut p;
Expand All @@ -123,7 +121,7 @@ impl AppState {
}
}
let p = self.positions[p as usize];
self.piece_clicked(p);
self.piece_clicked(p, main_window);
}

/// Advance the kick animation
Expand Down Expand Up @@ -171,63 +169,64 @@ pub fn main() {
#[cfg(all(debug_assertions, target_arch = "wasm32"))]
console_error_panic_hook::set_once();

let main_window = MainWindow::new().unwrap();

let state = Rc::new(RefCell::new(AppState {
let state = RefCell::new(AppState {
pieces: Rc::new(slint::VecModel::<Piece>::from(vec![Piece::default(); 15])),
main_window: main_window.as_weak(),
positions: vec![],
auto_play_timer: Default::default(),
kick_animation_timer: Default::default(),
speed_for_kick_animation: Default::default(),
finished: false,
}));
state.borrow_mut().randomize();
main_window.set_pieces(state.borrow().pieces.clone().into());
});
let main_window = MainWindow::new(state).unwrap();
main_window.user_data().borrow_mut().randomize(&main_window);
main_window.set_pieces(main_window.user_data().borrow().pieces.clone().into());

let state_copy = state.clone();
let weak = main_window.as_weak();
main_window.on_piece_clicked(move |p| {
state_copy.borrow().auto_play_timer.stop();
state_copy.borrow().main_window.unwrap().set_auto_play(false);
if state_copy.borrow().finished {
let main_window = weak.unwrap();
main_window.user_data().borrow().auto_play_timer.stop();
main_window.set_auto_play(false);
if main_window.user_data().borrow().finished {
return;
}
if !state_copy.borrow_mut().piece_clicked(p as i8) {
let state_weak = Rc::downgrade(&state_copy);
state_copy.borrow().kick_animation_timer.start(
if !main_window.user_data().borrow_mut().piece_clicked(p as i8, &main_window) {
let weak = weak.clone();
main_window.user_data().borrow().kick_animation_timer.start(
slint::TimerMode::Repeated,
std::time::Duration::from_millis(16),
move || {
if let Some(state) = state_weak.upgrade() {
state.borrow_mut().kick_animation();
if let Some(main_window) = weak.upgrade() {
main_window.user_data().borrow_mut().kick_animation();
}
},
);
}
});

let state_copy = state.clone();
let weak = main_window.as_weak();
main_window.on_reset(move || {
state_copy.borrow().auto_play_timer.stop();
state_copy.borrow().main_window.unwrap().set_auto_play(false);
state_copy.borrow_mut().randomize();
let main_window = weak.unwrap();
main_window.user_data().borrow().auto_play_timer.stop();
main_window.set_auto_play(false);
main_window.user_data().borrow_mut().randomize(&main_window);
});

let state_copy = state;
let weak = main_window.as_weak();
main_window.on_enable_auto_mode(move |enabled| {
let main_window = weak.unwrap();
if enabled {
let state_weak = Rc::downgrade(&state_copy);
state_copy.borrow().auto_play_timer.start(
let weak = weak.clone();
main_window.user_data().borrow().auto_play_timer.start(
slint::TimerMode::Repeated,
std::time::Duration::from_millis(200),
move || {
if let Some(state) = state_weak.upgrade() {
state.borrow_mut().random_move();
if let Some(main_window) = weak.upgrade() {
main_window.user_data().borrow_mut().random_move(&main_window);
}
},
);
} else {
state_copy.borrow().auto_play_timer.stop();
main_window.user_data().borrow().auto_play_timer.stop();
}
});
main_window.run().unwrap();
Expand Down
4 changes: 3 additions & 1 deletion internal/compiler/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::expression_tree::{BindingExpression, Expression};
use crate::langtype::ElementType;
use crate::namedreference::NamedReference;
use crate::object_tree::{Component, Document, ElementRc};
use crate::CompilerConfiguration;

#[cfg(feature = "cpp")]
mod cpp;
Expand Down Expand Up @@ -63,6 +64,7 @@ pub fn generate(
format: OutputFormat,
destination: &mut impl std::io::Write,
doc: &Document,
config: &CompilerConfiguration,
) -> std::io::Result<()> {
#![allow(unused_variables)]
#![allow(unreachable_code)]
Expand All @@ -80,7 +82,7 @@ pub fn generate(
}
#[cfg(feature = "rust")]
OutputFormat::Rust => {
let output = rust::generate(doc);
let output = rust::generate(doc, config);
write!(destination, "{}", output)?;
}
OutputFormat::Interpreter => {
Expand Down
Loading
Loading