I am trying to use a vector instead of the enum specified in the docs but I have no clue how to implement the selected part. My current code is
egui::ComboBox::from_label("Take your pick")
.selected_text(format!("{}", self.radio[0]))
.show_ui(ui, |ui| {
for i in 0..self.radio.len() {
ui.selectable_value(&mut &self.radio, &self.radio, &self.radio[i]);
}
});
can anyone give me an idea. I do not mind using enum but I do not know how many things will be in it.
I stumbled on the same problem, and I have found a solution. The solution is to add a new Variable to the self. Here is a basic example on the Enum select and the Vector select. Hope this helps out anyone who has run into the same problem.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use eframe::egui;
fn main() {
let options = eframe::NativeOptions::default();
eframe::run_native(
"Test Select with Enum and Vector",
options,
Box::new(|_cc| Box::new(MyApp::default())),
);
}
#[derive(PartialEq)]
#[derive(Debug)]
enum OS_Select {
First,
Second,
Third,
}
struct MyApp {
selected: usize,
radio: OS_Select,
selector_vec: Vec<String>,
}
impl Default for MyApp {
fn default() -> Self {
Self {
selected: 0,
radio: OS_Select::First,
selector_vec: get_vec(),
}
}
}
fn get_vec() -> Vec<String> {
let vecs = [
"1".to_string(),
"2".to_string(),
"3".to_string(),
].to_vec();
return vecs;
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Select with enum");
ui.horizontal(|ui| {
ui.radio_value(&mut self.radio, OS_Select::First, "First");
ui.radio_value(&mut self.radio, OS_Select::Second, "Second");
ui.radio_value(&mut self.radio, OS_Select::Third, "Third");
});
ui.end_row();
ui.heading("Select with Vectors");
egui::ComboBox::from_label("Take your pick")
.selected_text(format!("{}", &self.selector_vec[self.selected]))
.show_ui(ui, |ui| {
for i in 0..self.selector_vec.len() {
let value = ui.selectable_value(&mut &self.selector_vec[i], &self.selector_vec[self.selected], &self.selector_vec[i]);
if (value.clicked()) {
self.selected = i;
}
}
});
ui.end_row();
});
}
fn save(&mut self, _storage: &mut dyn eframe::Storage) {}
fn on_close_event(&mut self) -> bool {
true
}
fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {}
fn auto_save_interval(&self) -> std::time::Duration {
std::time::Duration::from_secs(30)
}
fn max_size_points(&self) -> egui::Vec2 {
egui::Vec2::INFINITY
}
fn clear_color(&self, _visuals: &egui::Visuals) -> egui::Rgba {
// NOTE: a bright gray makes the shadows of the windows look weird.
// We use a bit of transparency so that if the user switches on the
// `transparent()` option they get immediate results.
egui::Color32::from_rgba_unmultiplied(12, 12, 12, 180).into()
// _visuals.window_fill() would also be a natural choice
}
fn persist_native_window(&self) -> bool {
true
}
fn persist_egui_memory(&self) -> bool {
true
}
fn warm_up_enabled(&self) -> bool {
false
}
fn post_rendering(&mut self, _window_size_px: [u32; 2], _frame: &eframe::Frame) {}
}
Related
Specifically, what is the correct way to initialize the CompositionTarget member in the following Rust Crate for Windows CoreApp code excerpt?
#[implement(Windows::ApplicationModel::Core::IFrameworkView)]
struct AppView {
target: CompositionTarget,
}
#[allow(non_snake_case)]
impl AppView {
fn new() -> Self { //
Self {
//target: std::ptr::null_mut(),
//target: CompositionTarget(0),
}
}
fn Initialize(&self, _: &Option<CoreApplicationView>) -> Result<()> {
Ok(())
}
fn Load(&self, _: &HSTRING) -> Result<()> {
Ok(())
}
fn Uninitialize(&self) -> Result<()> {
Ok(())
}
fn Run(&self) -> Result<()> {
let window = CoreWindow::GetForCurrentThread()?;
window.Activate()?;
let dispatcher = window.Dispatcher()?;
dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit)?;
Ok(())
}
fn SetWindow(&self, _: &Option<CoreWindow>) -> Result<()> {
let compositor = Compositor::new()?;
let root = compositor.CreateContainerVisual()?;
//...
Ok(())
}
}
fn main() -> Result<()> {
unsafe {
CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED)?;
}
let app: IFrameworkViewSource = App().into();
CoreApplication::Run(app)?;
Ok(())
}
Rust does not have null. Instead, you should use Option:
struct AppView {
target: Option<CompositionTarget>,
}
impl AppView {
fn new() -> Self {
Self {
target: None,
}
}
...
This works well since in the windows crate a CompositionTarget cannot be null, any function that would return a null value will return an Option::None or Err(Error::Ok) instead. See this issue.
I'm creating subsets of std::sync::atomic::Ordering:
use std::sync::atomic::Ordering;
pub enum StoreOrdering {
Relaxed,
Release,
SeqCst
}
impl Into<Ordering> for StoreOrdering {
fn into(self) -> Ordering {
match self {
Self::Relaxed => Ordering::Relaxed,
Self::Release => Ordering::Release,
Self::SeqCst => Ordering::SeqCst
}
}
}
impl std::convert::TryFrom<Ordering> for StoreOrdering {
type Error = (); // HACK
fn try_from(ord: Ordering) -> Result<Self, Self::Error> {
match ord {
Ordering::Relaxed => Ok(Self::Relaxed),
Ordering::Release => Ok(Self::Release),
Ordering::SeqCst => Ok(Self::SeqCst),
_ => Err(())
}
}
}
enum LoadOrdering {
Acquire,
Relaxed,
SeqCst
}
// ???
As you can see, now I need to write those two impls with matches again for StoreOrdering <-> LoadOrdering and maybe even for StoreOrdering <-> LoadOrdering - as well as for any enum subset. How to avoid such boilerplate?
Rust doesn't support duck typing like C++ does with templates. The only functionality that generics can access is determined by the trait bounds.
So any duck-type-like behaviour must be done with macros.
For this, you could use the given macro below.
It only works for simple C-style macros. It creates the enum and auto-generates the conversions to the given super-enum.
use std::sync::atomic::Ordering;
use std::convert::TryInto;
// Create the store ordering
sub_enum!(StoreOrdering of Ordering {
Relaxed,
Release,
SeqCst
});
// Create the load ordering
sub_enum!(LoadOrdering of Ordering {
Acquire,
Relaxed,
SeqCst
});
#[macro_export]
macro_rules! sub_enum {
($sub_enum_name:ident of $super_enum_name:ty {
$($variant:ident),* $(,)?
}) => {
pub enum $sub_enum_name {
$($variant,)*
}
impl From<$sub_enum_name> for $super_enum_name {
fn from(val: $sub_enum_name) -> $super_enum_name {
match val {
$(<$sub_enum_name>::$variant => <$super_enum_name>::$variant,)*
}
}
}
impl std::convert::TryFrom<$super_enum_name> for $sub_enum_name {
type Error = ();
fn try_from(val: $super_enum_name) -> Result<Self, Self::Error> {
match val {
$(<$super_enum_name>::$variant => Ok(Self::$variant),)*
_ => Err(())
}
}
}
}
}
fn main() {
let store = StoreOrdering::SeqCst;
let general: Ordering = store.into();
let load: LoadOrdering = general.try_into().unwrap();
}
Playground link
A lot could be improved still, of course.
However, this should do for your problem right now.
Deriving PartialEq on an enum with a unit variant of an Rc trait object seems to trigger a Cannot move out of an 'Rc' error.
I've been able to create a small code sample that reproduces the error. Is there a way to fix the error without manually implementing PartialEq for the enum? This happens in 5 places in a codebase.
Code Example:
use failure::Error;
use serde_derive::{Deserialize,Serialize};
use std::rc::Rc;
trait MyTrait {
}
impl PartialEq for MyTrait {
fn eq(&self, rhs: &Self) -> bool {
true
}
}
impl MyTrait for String {
}
#[derive(PartialEq)]
enum MyEnum {
A,
B(Rc<dyn MyTrait>),
}
fn main() -> Result<(), Error> {
println!("{}",MyEnum::A == MyEnum::B(Rc::new(String::from("whee"))));
Ok(())
}
Here's the generated PartialEq:
#[inline]
fn eq(&self, other: &MyEnum) -> bool {
{
let __self_vi =
unsafe { ::std::intrinsics::discriminant_value(&*self) } as
isize;
let __arg_1_vi =
unsafe { ::std::intrinsics::discriminant_value(&*other) } as
isize;
if true && __self_vi == __arg_1_vi {
match (&*self, &*other) {
(&MyEnum::B(ref __self_0), &MyEnum::B(ref __arg_1_0)) =>
(*__self_0) == (*__arg_1_0),
_ => true,
}
} else { false }
}
}
And here's a link to the issue:
https://github.com/rust-lang/rust/issues/31740
So this might just be a language bug right now. Manually implementing PartialEq for all the enums this is an issue for isn't feasible right now, so I'd be curious if there's a workaround.
I have an enum with two variants:
enum DatabaseType {
Memory,
RocksDB,
}
What do I need in order to make a conditional if inside a function that checks if an argument is DatabaseType::Memory or DatabaseType::RocksDB?
fn initialize(datastore: DatabaseType) -> Result<V, E> {
if /* Memory */ {
//..........
} else if /* RocksDB */ {
//..........
}
}
First have a look at the free, official Rust book The Rust Programming Language, specifically the chapter on enums.
match
fn initialize(datastore: DatabaseType) {
match datastore {
DatabaseType::Memory => {
// ...
}
DatabaseType::RocksDB => {
// ...
}
}
}
if let
fn initialize(datastore: DatabaseType) {
if let DatabaseType::Memory = datastore {
// ...
} else {
// ...
}
}
==
#[derive(PartialEq)]
enum DatabaseType {
Memory,
RocksDB,
}
fn initialize(datastore: DatabaseType) {
if DatabaseType::Memory == datastore {
// ...
} else {
// ...
}
}
matches!
This is available since Rust 1.42.0
fn initialize(datastore: DatabaseType) {
if matches!(datastore, DatabaseType::Memory) {
// ...
} else {
// ...
}
}
See also:
How to compare enum without pattern matching
Read from an enum without pattern matching
Compare enums only by variant, not value
https://doc.rust-lang.org/std/macro.matches.html
// A simple example that runs in rust 1.58:
enum Aap {
Noot(i32, char),
Mies(String, f64),
}
fn main() {
let aap: Aap = Aap::Noot(42, 'q');
let noot: Aap = Aap::Mies(String::from("noot"), 422.0);
println!("{}", doe(aap));
println!("{}", doe(noot));
}
fn doe(a: Aap) -> i32 {
match a {
Aap::Noot(i, _) => i,
Aap::Mies(_, f) => f as i32,
}
}
My enum looks like this:
#[derive(Clone, Debug)]
pub enum Type {
GLnull,
GLenum(GLenum),
GLboolean(GLboolean),
GLint(GLint),
GLbyte(GLbyte),
GLshort(GLshort),
GLclampx(GLclampx),
GLubyte(GLubyte),
GLushort(GLushort),
GLuint(GLuint),
GLsizei(GLsizei),
GLclampf(GLclampf),
GLdouble(GLdouble),
GLclampd(GLclampd),
GLfloat_4fv((GLfloat, GLfloat, GLfloat, GLfloat)),
GLfloat(GLfloat),
GLintptr(GLintptr),
GLsizeiptr(GLsizeiptr),
GLbitfield(GLbitfield),
GLchar_ptr(String),
}
macro_rules! get{
($e:expr) => {
match $e {
Type::GLsizei(x) => { x }
Type::GLbitfield(x) => { x }
_ => { 0 }
}
}
}
Now how do I create a macro that gets the value of the enum type?
Like #aochagavia say there is no point to have a macro if you must do specific stuff with your enum.
The following macro could help you, the purpose is to have a macro that create a enum and generate some method. This only work if all variant have one type.
macro_rules! foo {
($($(#[$meta:meta])* foo $name:ident($ty:ty),)*) => {
#[derive(Debug, Clone)]
pub enum Foo {
$($(#[$meta])* $name($ty),)*
}
impl Foo {
pub fn display(&self) {
match *self {
$(Foo::$name(x) => println!("{}", x),)*
}
}
}
}
}
foo! {
foo A(i32),
foo B(i64),
}
fn main() {
let a = Foo::A(32);
let b = Foo::B(64);
a.display();
b.display();
}
The original macro is from #koka-el-kiwi, I take it as an example and modification for your case.
The following method is also available
pub enum Type<T> {
gli32(T),
gli64(T),
glfloat4fv(T),
glString(T),
glVec(T),
}
impl<T> Type<T> {
pub fn unwarp(&self) -> &T {
match *self {
Type::gli32(ref x) => x,
Type::gli64(ref x) => x,
Type::glfloat4fv(ref x) => x,
Type::glString(ref x) => x,
Type::glVec(ref x) => x,
}
}
}
fn main() {
println!("Hello, world!");
let f = Type::gli32(32 as i32);
let ff64 = Type::gli64((64, 32));
let f4fv = Type::glfloat4fv((0.1, 0.2, 0.0));
let cstr = Type::glString(CString::new("glstring").unwrap());
let ve = [1, 2, 3, 5];
let glve = Type::glVec(ve);
println!("f ={} {:?} {:?} {:?}",
f.unwarp(),
f4fv.unwarp(),
cstr.unwarp(),
glve.unwarp());
}