void menu_barcode_reader::populate() { if (current_device()) { std::string buffer; const char *new_barcode; // selected device item_append(current_display_name(), "", current_display_flags(), ITEMREF_SELECT_READER); // append the "New Barcode" item if (get_selection_ref() == ITEMREF_NEW_BARCODE) { buffer.append(m_barcode_buffer); new_barcode = buffer.c_str(); } else { new_barcode = m_barcode_buffer; } item_append(_("New Barcode:"), new_barcode, 0, ITEMREF_NEW_BARCODE); // finish up the menu item_append(menu_item_type::SEPARATOR); item_append(_("Enter Code"), "", 0, ITEMREF_ENTER_BARCODE); customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; } }
void menu_software_list::handle() { const entry_info *selected_entry = nullptr; int bestmatch = 0; // process the menu const event *event = process(0); if (event && event->itemref) { if ((uintptr_t)event->itemref == 1 && event->iptkey == IPT_UI_SELECT) { m_ordered_by_shortname = !m_ordered_by_shortname; // reset the char buffer if we change ordering criterion m_filename_buffer.clear(); // reload the menu with the new order reset(reset_options::REMEMBER_REF); machine().popmessage(_("Switched Order: entries now ordered by %s"), m_ordered_by_shortname ? _("shortname") : _("description")); } // handle selections else if (event->iptkey == IPT_UI_SELECT) { entry_info *info = (entry_info *) event->itemref; m_result = info->short_name; stack_pop(); } else if (event->iptkey == IPT_SPECIAL) { if (input_character(m_filename_buffer, event->unichar, &is_valid_softlist_part_char)) { // display the popup ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer); // identify the selected entry entry_info const *const cur_selected = (uintptr_t(event->itemref) != 1) ? reinterpret_cast<entry_info const *>(get_selection_ref()) : nullptr; // loop through all entries for (auto &entry : m_entrylist) { // is this entry the selected entry? if (cur_selected != &entry) { auto &compare_name = m_ordered_by_shortname ? entry.short_name : entry.long_name; int match = 0; for (int i = 0; i < m_filename_buffer.size() + 1; i++) { if (core_strnicmp(compare_name.c_str(), m_filename_buffer.c_str(), i) == 0) match = i; } if (match > bestmatch) { bestmatch = match; selected_entry = &entry; } } } if (selected_entry != nullptr && selected_entry != cur_selected) { set_selection((void *)selected_entry); centre_selection(); } } } else if (event->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case m_filename_buffer.clear(); m_result = m_filename_buffer; stack_pop(); } } }
void menu_file_selector::handle() { osd_file::error err; const file_selector_entry *selected_entry = nullptr; int bestmatch = 0; // process the menu const event *event = process(0); if (event != nullptr && event->itemref != nullptr) { // handle selections if (event->iptkey == IPT_UI_SELECT) { auto entry = (const file_selector_entry *) event->itemref; switch (entry->type) { case SELECTOR_ENTRY_TYPE_EMPTY: // empty slot - unload m_result = result::EMPTY; stack_pop(); break; case SELECTOR_ENTRY_TYPE_CREATE: // create m_result = result::CREATE; stack_pop(); break; case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST: m_result = result::SOFTLIST; stack_pop(); break; case SELECTOR_ENTRY_TYPE_DRIVE: case SELECTOR_ENTRY_TYPE_DIRECTORY: // drive/directory - first check the path err = util::zippath_opendir(entry->fullpath, nullptr); if (err != osd_file::error::NONE) { // this path is problematic; present the user with an error and bail ui().popup_time(1, "Error accessing %s", entry->fullpath); break; } m_current_directory.assign(entry->fullpath); reset(reset_options::SELECT_FIRST); break; case SELECTOR_ENTRY_TYPE_FILE: // file m_current_file.assign(entry->fullpath); m_result = result::FILE; stack_pop(); break; } // reset the char buffer when pressing IPT_UI_SELECT m_filename.clear(); } else if (event->iptkey == IPT_SPECIAL) { // if it's any other key and we're not maxed out, update if (input_character(m_filename, event->unichar, uchar_is_printable)) { ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str()); file_selector_entry const *const cur_selected(reinterpret_cast<file_selector_entry const *>(get_selection_ref())); // check for entries which matches our m_filename_buffer: for (auto &entry : m_entrylist) { if (cur_selected != &entry) { int match = 0; for (int i = 0; i < m_filename.size() + 1; i++) { if (core_strnicmp(entry.basename.c_str(), m_filename.c_str(), i) == 0) match = i; } if (match > bestmatch) { bestmatch = match; selected_entry = &entry; } } } if (selected_entry != nullptr && selected_entry != cur_selected) { set_selection((void *)selected_entry); centre_selection(); } } } else if (event->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case m_filename.clear(); } } }
void menu_dats_view::draw(uint32_t flags) { auto line_height = ui().get_line_height(); auto ud_arrow_width = line_height * machine().render().ui_aspect(); auto gutter_width = 0.52f * line_height * machine().render().ui_aspect(); mouse_x = -1, mouse_y = -1; float visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER; float visible_left = (1.0f - visible_width) * 0.5f; draw_background(); hover = item.size() + 1; visible_items = item.size() - 2; float extra_height = 2.0f * line_height; float visible_extra_menu_height = customtop + custombottom + extra_height; // locate mouse mouse_hit = false; mouse_button = false; mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); if (mouse_target != nullptr) if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, container(), mouse_x, mouse_y)) mouse_hit = true; // account for extra space at the top and bottom float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height; m_visible_lines = int(std::trunc(visible_main_menu_height / line_height)); visible_main_menu_height = float(m_visible_lines) * line_height; // compute top/left of inner menu area by centering float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; // if the menu is at the bottom of the extra, adjust visible_top += customtop; // compute left box size float x1 = visible_left; float y1 = visible_top - UI_BOX_TB_BORDER; float x2 = x1 + visible_width; float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height; float line = visible_top + float(m_visible_lines) * line_height; ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR); m_visible_lines = (std::min)(visible_items, m_visible_lines); top_line = (std::max)(0, top_line); if (top_line + m_visible_lines >= visible_items) top_line = visible_items - m_visible_lines; // determine effective positions taking into account the hilighting arrows float effective_width = visible_width - 2.0f * gutter_width; float effective_left = visible_left + gutter_width; int const n_loop = (std::min)(visible_items, m_visible_lines); for (int linenum = 0; linenum < n_loop; linenum++) { float line_y = visible_top + (float)linenum * line_height; int itemnum = top_line + linenum; const menu_item &pitem = item[itemnum]; const char *itemtext = pitem.text.c_str(); rgb_t fgcolor = UI_TEXT_COLOR; rgb_t bgcolor = UI_TEXT_BG_COLOR; float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; float line_y0 = line_y; float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; float line_y1 = line_y + line_height; // if we're on the top line, display the up arrow if (linenum == 0 && top_line != 0) { draw_arrow(0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0); if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y) { fgcolor = UI_MOUSEOVER_COLOR; bgcolor = UI_MOUSEOVER_BG_COLOR; highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); hover = HOVER_ARROW_UP; } } // if we're on the bottom line, display the down arrow else if (linenum == m_visible_lines - 1 && itemnum != visible_items - 1) { draw_arrow(0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y) { fgcolor = UI_MOUSEOVER_COLOR; bgcolor = UI_MOUSEOVER_BG_COLOR; highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); hover = HOVER_ARROW_DOWN; } } // draw dats text else if (pitem.subtext.empty()) { ui().draw_text_full(container(), itemtext, effective_left, line_y, effective_width, ui::text_layout::LEFT, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr); } } for (size_t count = visible_items; count < item.size(); count++) { const menu_item &pitem = item[count]; const char *itemtext = pitem.text.c_str(); float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; float line_y0 = line; float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; float line_y1 = line + line_height; rgb_t fgcolor = UI_SELECTED_COLOR; rgb_t bgcolor = UI_SELECTED_BG_COLOR; if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem)) hover = count; if (pitem.type == menu_item_type::SEPARATOR) container().add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height, UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); else { highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); ui().draw_text_full(container(), itemtext, effective_left, line, effective_width, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr); } line += line_height; } // if there is something special to add, do it by calling the virtual method custom_render(get_selection_ref(), customtop, custombottom, x1, y1, x2, y2); // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items); }
void menu_barcode_reader::handle() { // rebuild the menu (so to update the selected device, if the user has pressed L or R) reset(reset_options::REMEMBER_POSITION); populate(); // process the menu const event *event = process(PROCESS_LR_REPEAT); // process the event if (event) { // handle selections switch (event->iptkey) { case IPT_UI_LEFT: if (event->itemref == ITEMREF_SELECT_READER) previous(); break; case IPT_UI_RIGHT: if (event->itemref == ITEMREF_SELECT_READER) next(); break; case IPT_UI_SELECT: if (event->itemref == ITEMREF_ENTER_BARCODE) { std::string tmp_file(m_barcode_buffer); //printf("code %s\n", m_barcode_buffer); if (!current_device()->is_valid(tmp_file.length())) ui().popup_time(5, "%s", _("Barcode length invalid!")); else { current_device()->write_code(tmp_file.c_str(), tmp_file.length()); // if sending was successful, reset char buffer if (m_barcode_buffer[0] != '\0') memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer)); reset(reset_options::REMEMBER_POSITION); } } break; case IPT_SPECIAL: if (get_selection_ref() == ITEMREF_NEW_BARCODE) { auto const buflen = std::strlen(m_barcode_buffer); // if it's a backspace and we can handle it, do so if ((event->unichar == 8) || (event->unichar == 0x7f)) { if (0 < buflen) *const_cast<char *>(utf8_previous_char(&m_barcode_buffer[buflen])) = 0; } else if ((event->unichar >= '0') && (event->unichar <= '9')) { event->append_char(m_barcode_buffer, buflen); } reset(reset_options::REMEMBER_POSITION); } break; case IPT_UI_CANCEL: // reset the char buffer also in this case if (m_barcode_buffer[0] != '\0') memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer)); break; } } }
void menu_file_selector::type_search_char(char32_t ch) { std::string const current(m_filename); if (input_character(m_filename, ch, uchar_is_printable)) { ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str()); file_selector_entry const *const cur_selected(reinterpret_cast<file_selector_entry const *>(get_selection_ref())); // if it's a perfect match for the current selection, don't move it if (!cur_selected || core_strnicmp(cur_selected->basename.c_str(), m_filename.c_str(), m_filename.size())) { std::string::size_type bestmatch(0); file_selector_entry const *selected_entry(cur_selected); for (auto &entry : m_entrylist) { // TODO: more efficient "common prefix" code std::string::size_type match(0); for (std::string::size_type i = 1; m_filename.size() >= i; ++i) { if (!core_strnicmp(entry.basename.c_str(), m_filename.c_str(), i)) match = i; else break; } if (match > bestmatch) { bestmatch = match; selected_entry = &entry; } } if (selected_entry && (selected_entry != cur_selected)) { set_selection((void *)selected_entry); centre_selection(); } } } }