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

Combobox enhancement: add add_option and extract_options functions to allow easier addition/removal of options #2684

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Adam-Ladd
Copy link

Added add_option and extract_options functions to combobox and split build_matcher (the logic to build a single matcher) out from build_matchers

Add option adds a single option to a combobox while extract_options extracts all options in the current combobox replacing the state with an empty combobox. The intention of these two function is to make it easier and more efficient to add/remove options from a combobox (unfortunately the loose type bounds on T make it impossible to implement a way to remove a chosen option from a combobox) .

By way of example the code below allows the user to enter and remove languages from a combobox

use iced::widget::{button, center, column, combo_box, text_input, vertical_space};
use iced::{Center, Element, Fill};

pub fn main() -> iced::Result {
    iced::run("Combo Box - Iced", Example::update, Example::view)
}

struct Example {
    languages: combo_box::State<Language>,
    selected_language: Option<Language>,
    new_language: String,
}

#[derive(Debug, Clone)]
enum Message {
    Selected(Language),
    AddLanguage,
    ClearLanguages,
    NewLangaugeContentChanged(String),
}

impl Example {
    fn new(langs: Vec<Language>) -> Self {
        Self {
            languages: combo_box::State::new(langs.clone()),
            selected_language: None,
            new_language: String::new(),
        }
    }

    fn add_language(&mut self, lang: Language) {
        // * --- inefficient version using existing crate --- *
        // let mut current_options: Vec<Language> = self.languages.options().iter().map(|x| x.clone()).collect();
        // current_options.push(lang);
        // self.languages = combo_box::State::new(current_options);
        
        // * --- using add_option --- *
        self.languages.add_option(lang);
    }

    fn update(&mut self, message: Message) {
        match message {
            Message::Selected(language) => {
                self.selected_language = Some(language);
            }
            Message::AddLanguage => {
                self.add_language(Language { name: self.new_language.clone() });
                self.new_language = String::new();
            },
            Message::NewLangaugeContentChanged(content) => {
                self.new_language = content
            }
            Message::ClearLanguages => {
                // * --- using existing functions
                // let current_options: Vec<Language> = self.languages.options().iter().map(|x| x.clone()).collect();
                // println!("languages that were in the combobox: {:?}", current_options);
                // self.languages = combo_box::State::new(current_options);
                // self.selected_language = None;

                // * --- using extract_options
                println!("languages that were in the combobox: {:?}", self.languages.extract_options());
                self.selected_language = None;
            }
        }
    }

    fn view(&self) -> Element<Message> {
        let combo_box = combo_box(
            &self.languages,
            "Type a language...",
            self.selected_language.as_ref(),
            Message::Selected,
        )
        .width(250);

        let add_lanauge = button("add language").on_press(Message::AddLanguage);
        let clear_languages = button("clear languages").on_press(Message::ClearLanguages);
        let new_language_input = text_input("Enter new language...", &self.new_language).on_input(Message::NewLangaugeContentChanged);

        let content = column![ add_lanauge, combo_box, new_language_input, clear_languages, vertical_space().height(150),]
            .width(Fill)
            .align_x(Center)
            .spacing(10);

        let interface = column![
            content,
        ];

        center(interface).into()
    }
}

impl Default for Example {
    fn default() -> Self {
        Example::new(Vec::from([
            Language {
                name: "English".to_owned(),
            },
            Language {
                name: "Spanish".to_owned(),
            },
        ]))
    }
}

#[derive(Debug, Clone, Default)]
pub struct Language {
    name: String,
}

impl std::fmt::Display for Language {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.name)
    }
}

…build_matcher (the logic to build a single matcher) out from build matchers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant