use crate::scope::{NativeScopePop, NativeScopeToken};
use crate::{Id, sys};
use super::basic_selection::BasicSelection;
use super::options::MultiSelectOptions;
use super::requests::{MultiSelectResult, MultiSelectUserData, copy_multi_select_result};
use super::storage::MultiSelectIndexStorage;
fn usize_to_i32(name: &str, value: usize) -> i32 {
i32::try_from(value).unwrap_or_else(|_| panic!("{name} exceeded ImGui's i32 range"))
}
pub struct MultiSelectScope<'ui> {
ui: &'ui crate::Ui,
begin_result: MultiSelectResult,
range_source_reset: bool,
native_scope: NativeScopeToken<'ui>,
ended: bool,
}
impl<'ui> MultiSelectScope<'ui> {
pub(super) fn new(
ui: &'ui crate::Ui,
flags: impl Into<MultiSelectOptions>,
selection_size: Option<i32>,
items_count: usize,
) -> Self {
let options = flags.into();
let selection_size = selection_size.unwrap_or(-1);
let items_count = usize_to_i32("items_count", items_count);
let native_io = ui.run_with_bound_context(|| unsafe {
sys::igBeginMultiSelect(options.raw(), selection_size, items_count)
});
let begin_result = unsafe { copy_multi_select_result(native_io) };
Self {
ui,
begin_result,
range_source_reset: false,
native_scope: ui.begin_native_scope(
NativeScopePop::EndMultiSelect {
range_source_reset: false,
},
"MultiSelectScope",
),
ended: false,
}
}
#[must_use]
pub fn begin_result(&self) -> &MultiSelectResult {
&self.begin_result
}
pub fn apply_begin_requests_indexed<S: MultiSelectIndexStorage>(&self, storage: &mut S) {
self.begin_result.apply_requests_indexed(storage);
}
pub fn apply_begin_requests_basic<G>(&self, selection: &mut BasicSelection, id_at_index: G)
where
G: FnMut(usize) -> Id,
{
self.begin_result
.apply_requests_basic(selection, id_at_index);
}
pub fn set_next_item_selection_user_data(&self, item: MultiSelectUserData) {
self.ui.run_with_bound_context(|| unsafe {
sys::igSetNextItemSelectionUserData(item);
});
}
pub fn set_range_source_reset(&mut self, reset: bool) {
self.range_source_reset = reset;
}
pub(super) fn finish(mut self) -> MultiSelectResult {
let native_io = self.end_native();
self.ended = true;
let mut result = unsafe { copy_multi_select_result(native_io) };
result.record_range_source_reset(self.range_source_reset);
result
}
fn end_native(&mut self) -> *mut sys::ImGuiMultiSelectIO {
let pop = NativeScopePop::EndMultiSelect {
range_source_reset: self.range_source_reset,
};
self.native_scope.replace_pop(pop);
let mut native_io = std::ptr::null_mut();
self.native_scope
.finish_with(|| native_io = unsafe { pop.finish_multi_select() });
native_io
}
}
impl Drop for MultiSelectScope<'_> {
fn drop(&mut self) {
if self.ended || self.native_scope.is_finished() {
return;
}
self.end_native();
self.ended = true;
}
}