// ---------------------------------------------------------------------------- void RibbonWidget::add() { assert(m_magic_number == 0xCAFEC001); assert(m_x > -10.0f); assert(m_y > -10.0f); assert(m_w > 0.0f); assert(m_h > 0.0f); m_labels.clearWithoutDeleting(); rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h); int id = (m_reserved_id == -1 ? getNewID() : m_reserved_id); IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, id, L""); m_element = btn; m_active_children.clearWithoutDeleting(); // Is just a copy of m_children without the deactivated children. m_children takes care of memory. for (unsigned int i=0; i<m_children.size(); i++) { if (m_children[i].isVisible()) { m_active_children.push_back(m_children.get(i)); } } const int subbuttons_amount = m_active_children.size(); // For some ribbon types, we can have unequal sizes depending on whether // items have labels or not int with_label = 0; int without_label = 0; // ---- check how much space each child button will take and fit // them within available space int total_needed_space = 0; for (int i=0; i<subbuttons_amount; i++) { // FIXME: why do I manually invoke the Layout Manager here? LayoutManager::readCoords(m_active_children.get(i)); LayoutManager::applyCoords(m_active_children.get(i), NULL, this); if (m_active_children[i].m_type != WTYPE_ICON_BUTTON && m_active_children[i].m_type != WTYPE_BUTTON) { Log::warn("RiggonWidget", "Ribbon widgets can only have " "(icon)button widgets as children"); continue; } // ribbon children must not be keyboard navigatable, the parent // ribbon takes care of that if (m_active_children[i].m_type == WTYPE_ICON_BUTTON) { IconButtonWidget* icon = ((IconButtonWidget*)m_active_children.get(i)); icon->m_tab_stop = false; } bool has_label_underneath = m_active_children[i].m_text.size() > 0; if (m_active_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0) { has_label_underneath = false; } if (has_label_underneath) with_label++; else without_label++; total_needed_space += m_active_children[i].m_w; } //int biggest_y = 0; const int button_y = 10; const int one_button_space = int(roundf((float)m_w / (float)subbuttons_amount)); int widget_x = -1; // ---- add children for (int i=0; i<subbuttons_amount; i++) { // ---- tab ribbons if (getRibbonType() == RIBBON_TABS) { const int large_tab = (int)((with_label + without_label) *one_button_space / (with_label + without_label/2.0f)); const int small_tab = large_tab/2; stringw& message = m_active_children[i].m_text; if (message.size() == 0) { if (widget_x == -1) widget_x = small_tab/2; else widget_x += small_tab/2; } else { if (widget_x == -1) widget_x = large_tab/2; else widget_x += large_tab/2; } IGUIButton * subbtn = NULL; rect<s32> subsize = rect<s32>(widget_x - large_tab/2+2, 0, widget_x + large_tab/2-2, m_h); if (message.size() == 0) { subsize = rect<s32>(widget_x - small_tab/2+2, 0, widget_x + small_tab/2-2, m_h); } if (m_active_children[i].m_type == WTYPE_BUTTON) { subbtn = GUIEngine::getGUIEnv() ->addButton(subsize, btn, getNewNoFocusID(), message.c_str(), L""); subbtn->setTabStop(false); subbtn->setTabGroup(false); if ((int)GUIEngine::getFont()->getDimension(message.c_str()) .Width > subsize.getWidth() && message.findFirst(L' ') == -1 && message.findFirst(L'\u00AD') == -1 ) { // if message too long and contains no space and no soft // hyphen, make the font smaller subbtn->setOverrideFont(GUIEngine::getSmallFont()); } } else if (m_active_children[i].m_type == WTYPE_ICON_BUTTON) { rect<s32> icon_part = rect<s32>(15, 0, subsize.getHeight()+15, subsize.getHeight()); if (message.size() == 0) { const int x = subsize.getWidth()/2 - subsize.getHeight()/2; // no label, only icon, so center the icon icon_part = rect<s32>(x, 0, x + subsize.getHeight(), subsize.getHeight()); } // label at the *right* of the icon (for tabs) rect<s32> label_part = rect<s32>(subsize.getHeight()+15, 0, subsize.getWidth()-15, subsize.getHeight()); // use the same ID for all subcomponents; since event handling // is done per-ID, no matter which one your hover, this // widget will get it int same_id = getNewNoFocusID(); subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn, same_id, L"", L""); IGUIButton* icon = GUIEngine::getGUIEnv()->addButton(icon_part, subbtn, same_id, L""); icon->setScaleImage(true); std::string filename = file_manager->getAsset( m_active_children[i].m_properties[PROP_ICON]); icon->setImage( irr_driver->getTexture(filename.c_str()) ); icon->setUseAlphaChannel(true); icon->setDrawBorder(false); icon->setTabStop(false); IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), label_part, false /* border */, true /* word wrap */, subbtn, same_id); if ((int)GUIEngine::getFont()->getDimension(message.c_str()) .Width > label_part.getWidth()&& message.findFirst(L' ') == -1 && message.findFirst(L'\u00AD') == -1 ) { // if message too long and contains no space and no soft // hyphen, make the font smaller label->setOverrideFont(GUIEngine::getSmallFont()); } label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); label->setTabStop(false); label->setNotClipped(true); label->setRightToLeft(translations->isRTLText(message)); m_labels.push_back(label); subbtn->setTabStop(false); subbtn->setTabGroup(false); } else { Log::error("RibbonWidget", "Invalid tab bar contents"); } m_active_children[i].m_element = subbtn; if (message.size() == 0) widget_x += small_tab/2; else widget_x += large_tab/2; } // ---- icon ribbons else if (m_active_children[i].m_type == WTYPE_ICON_BUTTON) { if (widget_x == -1) widget_x = one_button_space/2; // find how much space to keep for the label under the button. // consider font size, whether the label is multiline, etc... bool has_label = m_active_children[i].m_text.size() > 0; if (m_active_children[i].m_properties[PROP_LABELS_LOCATION].size() > 0) { has_label = false; } const int needed_space_under_button = has_label ? GUIEngine::getFontHeight() : 10; float imageRatio = (float)m_active_children[i].m_w / (float)m_active_children[i].m_h; // calculate the size of the image std::string filename = file_manager->getAsset(m_active_children[i].m_properties[PROP_ICON]); video::ITexture* image = irr_driver->getTexture((filename).c_str()); if(!image) { std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png"); image = irr_driver->getTexture(file); if(!image) Log::fatal("RibbonWidget", "Can't find fallback texture 'gui/main_help.png, aborting."); } float image_h = (float)image->getSize().Height; float image_w = image_h*imageRatio; float zoom = (float) (m_h - button_y - needed_space_under_button) / image_h; float zoom_x = (float) one_button_space / image_w; if(zoom_x < zoom) zoom = zoom_x; // ---- add bitmap button part // backup and restore position in case the same object is added // multiple times (FIXME: unclean) int old_x = m_active_children[i].m_x; int old_y = m_active_children[i].m_y; int old_w = m_active_children[i].m_w; int old_h = m_active_children[i].m_h; m_active_children[i].m_x = widget_x - int(image_w*zoom/2.0f); m_active_children[i].m_y = button_y; m_active_children[i].m_w = int(image_w*zoom); m_active_children[i].m_h = int(image_h*zoom); IconButtonWidget* icon = ((IconButtonWidget*)m_active_children.get(i)); if (icon->m_properties[PROP_EXTEND_LABEL].size() == 0) { icon->m_properties[PROP_EXTEND_LABEL] = StringUtils::toString(one_button_space - icon->m_w); } m_active_children.get(i)->m_parent = btn; m_active_children.get(i)->add(); // restore backuped size and location (see above for more info) m_active_children[i].m_x = old_x; m_active_children[i].m_y = old_y; m_active_children[i].m_w = old_w; m_active_children[i].m_h = old_h; // the label itself will be added by the icon widget. since it // adds the label outside of the widget area it is assigned to, // the label will appear in the area we want at the bottom widget_x += one_button_space; } else { Log::warn("RiggonWidget", "Invalid contents type in ribbon"); } //m_children[i].id = subbtn->getID(); m_active_children[i].m_event_handler = this; }// next sub-button id = m_element->getID(); m_element->setTabOrder(id); m_element->setTabGroup(false); updateSelection(); if (!m_is_visible) setVisible(false); } // add
// ----------------------------------------------------------------------------- void IconButtonWidget::add() { // ---- Icon if (m_texture == NULL) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { setTexture(irr_driver->getTexture(m_properties[PROP_ICON])); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { // Avoid warning about missing texture in case of e.g. // screenshot widget if(m_properties[PROP_ICON] != "") { std::string file = file_manager->getAsset(m_properties[PROP_ICON]); setTexture(irr_driver->getTexture(file)); } } } if (m_texture == NULL) { if (m_properties[PROP_ICON].size() > 0) { Log::error("icon_button", "add() : error, cannot find texture '%s' in iconbutton '%s'.", m_properties[PROP_ICON].c_str(), m_properties[PROP_ID].c_str()); } std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png"); setTexture(irr_driver->getTexture(file)); if(!m_texture) Log::fatal("IconButtonWidget", "Can't find fallback texture 'gui/main_help.png, aborting."); } if (m_properties[PROP_FOCUS_ICON].size() > 0) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { m_highlight_texture = irr_driver->getTexture(m_properties[PROP_FOCUS_ICON]); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { m_highlight_texture = irr_driver->getTexture(file_manager->getAsset( m_properties[PROP_FOCUS_ICON])); } } // irrlicht widgets don't support scaling while keeping aspect ratio // so, happily, let's implement it ourselves float useAspectRatio = -1.0f; if (m_properties[PROP_CUSTOM_RATIO] != "") { StringUtils::fromString(m_properties[PROP_CUSTOM_RATIO], m_custom_aspect_ratio); m_scale_mode = SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO; } if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO) { useAspectRatio = (float)m_texture_w / (float)m_texture_h; } else if (m_scale_mode == SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO) { useAspectRatio = m_custom_aspect_ratio; } int suggested_h = m_h; int suggested_w = (int)((useAspectRatio < 0 ? m_w : useAspectRatio * suggested_h)); if (suggested_w > m_w) { const float needed_scale_factor = (float)m_w / (float)suggested_w; suggested_w = (int)(suggested_w*needed_scale_factor); suggested_h = (int)(suggested_h*needed_scale_factor); } const int x_from = m_x + (m_w - suggested_w)/2; // center horizontally const int y_from = m_y + (m_h - suggested_h)/2; // center vertically rect<s32> widget_size = rect<s32>(x_from, y_from, x_from + suggested_w, y_from + suggested_h); IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, (m_tab_stop ? getNewID() : getNewNoFocusID()), L""); btn->setTabStop(m_tab_stop); m_element = btn; m_id = m_element->getID(); // ---- label if any const stringw& message = getText(); if (message.size() > 0) { const int label_extra_size = ( m_properties[PROP_EXTEND_LABEL].size() == 0 ? 0 : atoi(m_properties[PROP_EXTEND_LABEL].c_str()) ); const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true"); if (m_properties[PROP_LABELS_LOCATION] == "hover") { core::dimension2du text_size = GUIEngine::getFont()->getDimension(message.c_str()); core::recti pos = btn->getAbsolutePosition(); int center_x = pos.UpperLeftCorner.X + pos.getWidth() / 2; int x1 = center_x - text_size.Width / 2 - label_extra_size / 2; int y1 = pos.UpperLeftCorner.Y - (word_wrap ? GUIEngine::getFontHeight() * 2 : GUIEngine::getFontHeight()) - 15; int x2 = center_x + text_size.Width / 2 + label_extra_size / 2; int y2 = pos.UpperLeftCorner.Y - 15; if (x1 < 0) { int diff = -x1; x1 += diff; x2 += diff; } else if (x2 > (int)irr_driver->getActualScreenSize().Width) { int diff = x2 - irr_driver->getActualScreenSize().Width; x2 -= diff; x1 -= diff; } core::recti parent_pos = m_parent->getAbsolutePosition(); x1 -= parent_pos.UpperLeftCorner.X; x2 -= parent_pos.UpperLeftCorner.X; y1 -= parent_pos.UpperLeftCorner.Y; y2 -= parent_pos.UpperLeftCorner.Y; widget_size = rect<s32>(x1, y1, x2, y2); } else { // leave enough room for two lines of text if word wrap is enabled, otherwise a single line widget_size = rect<s32>(m_x - label_extra_size/2, m_y + m_h, m_x + m_w + label_extra_size/2, m_y + m_h + (word_wrap ? GUIEngine::getFontHeight()*2 : GUIEngine::getFontHeight())); } m_label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, word_wrap, m_parent); m_label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); m_label->setTabStop(false); m_label->setNotClipped(true); if (m_properties[PROP_LABELS_LOCATION] == "hover") { m_label->setVisible(false); } setLabelFont(); m_label->setRightToLeft(translations->isRTLText(message)); m_label->setTextRestrainedInside(false); } // ---- IDs m_id = m_element->getID(); if (m_tab_stop) m_element->setTabOrder(m_id); m_element->setTabGroup(false); if (!m_is_visible) m_element->setVisible(false); }
void RibbonWidget::add() { m_labels.clearWithoutDeleting(); rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h); int id = (m_reserved_id == -1 ? getNewID() : m_reserved_id); IGUIButton * btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, id, L""); m_element = btn; const int subbuttons_amount = m_children.size(); // ---- check how much space each child button will take and fit them within available space int total_needed_space = 0; for (int i=0; i<subbuttons_amount; i++) { // FIXME: a little unclean to invoke layout code here? LayoutManager::readCoords(m_children.get(i), NULL, this); if (m_children[i].m_type != WTYPE_ICON_BUTTON && m_children[i].m_type != WTYPE_BUTTON) { std::cerr << "/!\\ Warning /!\\ : ribbon widgets can only have (icon)button widgets as children " << std::endl; continue; } // ribbon children must not be keyboard navigatable, the parent ribbon takes care of that if (m_children[i].m_type == WTYPE_ICON_BUTTON) { IconButtonWidget* icon = ((IconButtonWidget*)m_children.get(i)); icon->m_tab_stop = false; } total_needed_space += m_children[i].m_w; } int free_w_space = m_w - total_needed_space; //int biggest_y = 0; const int button_y = 10; float global_zoom = 1; const int min_free_space = 50; global_zoom = (float)m_w / (float)( m_w - free_w_space + min_free_space ); //free_w_space = (int)(m_w - total_needed_space*global_zoom); const int one_button_space = (int)round((float)m_w / (float)subbuttons_amount); // ---- add children for (int i=0; i<subbuttons_amount; i++) { const int widget_x = one_button_space*(i+1) - one_button_space/2; // ---- tab ribbons if (getRibbonType() == RIBBON_TABS) { IGUIButton * subbtn = NULL; rect<s32> subsize = rect<s32>(widget_x - one_button_space/2+2, 0, widget_x + one_button_space/2-2, m_h); stringw& message = m_children[i].m_text; if (m_children[i].m_type == WTYPE_BUTTON) { subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn, getNewNoFocusID(), message.c_str(), L""); subbtn->setTabStop(false); subbtn->setTabGroup(false); } else if (m_children[i].m_type == WTYPE_ICON_BUTTON) { rect<s32> icon_part = rect<s32>(15, 0, subsize.getHeight()+15, subsize.getHeight()); // label at the *right* of the icon (for tabs) rect<s32> label_part = rect<s32>(subsize.getHeight()+15, 0, subsize.getWidth()-15, subsize.getHeight()); // use the same ID for all subcomponents; since event handling is done per-ID, no matter // which one your hover, this widget will get it int same_id = getNewNoFocusID(); subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn, same_id, L"", L""); //MyGUIButton* icon = new MyGUIButton(GUIEngine::getGUIEnv(), subbtn, same_id, icon_part, true); IGUIButton* icon = GUIEngine::getGUIEnv()->addButton(icon_part, subbtn, same_id, L""); icon->setScaleImage(true); icon->setImage( irr_driver->getTexture((file_manager->getDataDir() + "/" + m_children[i].m_properties[PROP_ICON]).c_str()) ); icon->setUseAlphaChannel(true); icon->setDrawBorder(false); icon->setTabStop(false); IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), label_part, false /* border */, true /* word wrap */, subbtn, same_id); label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); label->setTabStop(false); label->setNotClipped(true); m_labels.push_back(label); subbtn->setTabStop(false); subbtn->setTabGroup(false); } else { std::cerr << "Invalid tab bar contents\n"; } m_children[i].m_element = subbtn; } // ---- icon ribbons else if (m_children[i].m_type == WTYPE_ICON_BUTTON) { // find how much space to keep for the label under the button. // consider font size, whether the label is multiline, etc... const bool has_label = m_children[i].m_text.size() > 0; const int needed_space_under_button = has_label ? GUIEngine::getFontHeight() : 10; float imageRatio = (float)m_children[i].m_w / (float)m_children[i].m_h; // calculate the size of the image video::ITexture* image = irr_driver->getTexture((file_manager->getDataDir() + "/" + m_children[i].m_properties[PROP_ICON]).c_str()); float image_h = (float)image->getSize().Height; float image_w = image_h*imageRatio; // scale to fit (FIXME: calculate the right value directly...) float zoom = global_zoom; if (button_y + image_h*zoom + needed_space_under_button > m_h) { // scale down while (button_y + image_h*zoom + needed_space_under_button > m_h) zoom -= 0.01f; } else { // scale up while (button_y + image_h*zoom + needed_space_under_button < m_h) zoom += 0.01f; } // ---- add bitmap button part // backup and restore position in case the same object is added multiple times (FIXME: unclean) int old_x = m_children[i].m_x; int old_y = m_children[i].m_y; int old_w = m_children[i].m_w; int old_h = m_children[i].m_h; m_children[i].m_x = widget_x - (int)(image_w*zoom/2.0f); m_children[i].m_y = button_y; m_children[i].m_w = (int)(image_w*zoom); m_children[i].m_h = (int)(image_h*zoom); IconButtonWidget* icon = ((IconButtonWidget*)m_children.get(i)); icon->m_properties[PROP_EXTEND_LABEL] = StringUtils::toString(one_button_space - icon->m_w); m_children.get(i)->m_parent = btn; m_children.get(i)->add(); // restore backuped size and location (see above for more info) m_children[i].m_x = old_x; m_children[i].m_y = old_y; m_children[i].m_w = old_w; m_children[i].m_h = old_h; // the label itself will be added by the icon widget. since it adds the label outside of the // widget area it is assigned to, the label will appear in the area we want at the bottom } else { std::cerr << "/!\\ Warning /!\\ : Invalid contents type in ribbon" << std::endl; } //m_children[i].id = subbtn->getID(); m_children[i].m_event_handler = this; }// next sub-button id = m_element->getID(); m_element->setTabOrder(id); m_element->setTabGroup(false); updateSelection(); }
// ----------------------------------------------------------------------------- void IconButtonWidget::add() { // ---- Icon if (m_texture == NULL) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { m_texture = irr_driver->getTexture(m_properties[PROP_ICON].c_str()); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { m_texture = irr_driver->getTexture((file_manager->getDataDir() + "/" + m_properties[PROP_ICON]).c_str()); } } if (m_texture == NULL) { std::cerr << "IconButtonWidget::add() : error, cannot find texture " << m_properties[PROP_ICON].c_str() << std::endl; m_texture = irr_driver->getTexture((file_manager->getDataDir() + "/gui/main_help.png").c_str()); } m_texture_w = m_texture->getSize().Width; m_texture_h = m_texture->getSize().Height; if (m_properties[PROP_FOCUS_ICON].size() > 0) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { m_highlight_texture = irr_driver->getTexture(m_properties[PROP_FOCUS_ICON].c_str()); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { m_highlight_texture = irr_driver->getTexture((file_manager->getDataDir() + "/" + m_properties[PROP_FOCUS_ICON]).c_str()); } } // irrlicht widgets don't support scaling while keeping aspect ratio // so, happily, let's implement it ourselves float useAspectRatio = -1.0f; if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO) { useAspectRatio = (float)m_texture_w / (float)m_texture_h; //std::cout << "m_texture_h=" << m_texture_h << "; m_texture_w="<< m_texture_w // << "; useAspectRatio=" << useAspectRatio << std::endl; } else if (m_scale_mode == SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO) { useAspectRatio = m_custom_aspect_ratio; } int suggested_h = m_h; int suggested_w = (int)((useAspectRatio < 0 ? m_w : useAspectRatio * suggested_h)); if (suggested_w > m_w) { const float needed_scale_factor = (float)m_w / (float)suggested_w; suggested_w = (int)(suggested_w*needed_scale_factor); suggested_h = (int)(suggested_h*needed_scale_factor); } const int x_from = m_x + (m_w - suggested_w)/2; // center horizontally const int y_from = m_y + (m_h - suggested_h)/2; // center vertically rect<s32> widget_size = rect<s32>(x_from, y_from, x_from + suggested_w, y_from + suggested_h); IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, (m_tab_stop ? getNewID() : getNewNoFocusID()), L""); btn->setTabStop(m_tab_stop); m_element = btn; m_id = m_element->getID(); // ---- label if any const stringw& message = getText(); if (message.size() > 0) { //std::cout << "Adding label of icon widget, m_properties[PROP_EXTEND_LABEL] = " // << m_properties[PROP_EXTEND_LABEL] << std::endl; const int label_extra_size = ( m_properties[PROP_EXTEND_LABEL].size() == 0 ? 0 : atoi(m_properties[PROP_EXTEND_LABEL].c_str()) ); const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true"); if (m_properties[PROP_LABELS_LOCATION] == "hover") { widget_size = rect<s32>(m_x - label_extra_size/2, m_y - (word_wrap ? GUIEngine::getFontHeight()*2 : GUIEngine::getFontHeight()) - 15, m_x + m_w + label_extra_size/2, m_y - 15); } else { // leave enough room for two lines of text if word wrap is enabled, otherwise a single line widget_size = rect<s32>(m_x - label_extra_size/2, m_y + m_h, m_x + m_w + label_extra_size/2, m_y + m_h + (word_wrap ? GUIEngine::getFontHeight()*2 : GUIEngine::getFontHeight())); } m_label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, word_wrap, m_parent); m_label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); m_label->setTabStop(false); m_label->setNotClipped(true); if (m_properties[PROP_LABELS_LOCATION] == "hover") { m_label->setVisible(false); } const int max_w = m_label->getAbsolutePosition().getWidth(); if (!word_wrap && (int)GUIEngine::getFont()->getDimension(message.c_str()).Width > max_w + 4) // arbitrarily allow for 4 pixels { m_label->setOverrideFont( GUIEngine::getSmallFont() ); } #if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) m_label->setRightToLeft( translations->isRTLLanguage() ); m_label->setTextRestrainedInside(false); #endif } // ---- IDs m_id = m_element->getID(); if (m_tab_stop) m_element->setTabOrder(m_id); m_element->setTabGroup(false); }
// ----------------------------------------------------------------------------- void IconButtonWidget::add() { // ---- Icon if (m_texture == NULL) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { setTexture(irr_driver->getTexture(m_properties[PROP_ICON])); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { std::string file = file_manager->getAsset(m_properties[PROP_ICON]); setTexture(irr_driver->getTexture(file)); } } if (m_texture == NULL) { Log::error("icon_button", "add() : error, cannot find texture '%s'.", m_properties[PROP_ICON].c_str()); std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png"); setTexture(irr_driver->getTexture(file)); if(!m_texture) Log::fatal("IconButtonWidget", "Can't find fallback texture 'gui/main_help.png, aborting."); } if (m_properties[PROP_FOCUS_ICON].size() > 0) { if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE) { m_highlight_texture = irr_driver->getTexture(m_properties[PROP_FOCUS_ICON]); } else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE) { m_highlight_texture = irr_driver->getTexture(file_manager->getAsset( m_properties[PROP_FOCUS_ICON])); } } // irrlicht widgets don't support scaling while keeping aspect ratio // so, happily, let's implement it ourselves float useAspectRatio = -1.0f; if (m_scale_mode == SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO) { useAspectRatio = (float)m_texture_w / (float)m_texture_h; } else if (m_scale_mode == SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO) { useAspectRatio = m_custom_aspect_ratio; } int suggested_h = m_h; int suggested_w = (int)((useAspectRatio < 0 ? m_w : useAspectRatio * suggested_h)); if (suggested_w > m_w) { const float needed_scale_factor = (float)m_w / (float)suggested_w; suggested_w = (int)(suggested_w*needed_scale_factor); suggested_h = (int)(suggested_h*needed_scale_factor); } const int x_from = m_x + (m_w - suggested_w)/2; // center horizontally const int y_from = m_y + (m_h - suggested_h)/2; // center vertically rect<s32> widget_size = rect<s32>(x_from, y_from, x_from + suggested_w, y_from + suggested_h); IGUIButton* btn = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, (m_tab_stop ? getNewID() : getNewNoFocusID()), L""); btn->setTabStop(m_tab_stop); m_element = btn; m_id = m_element->getID(); // ---- label if any const stringw& message = getText(); if (message.size() > 0) { const int label_extra_size = ( m_properties[PROP_EXTEND_LABEL].size() == 0 ? 0 : atoi(m_properties[PROP_EXTEND_LABEL].c_str()) ); const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true"); if (m_properties[PROP_LABELS_LOCATION] == "hover") { widget_size = rect<s32>(m_x - label_extra_size/2, m_y - (word_wrap ? GUIEngine::getFontHeight()*2 : GUIEngine::getFontHeight()) - 15, m_x + m_w + label_extra_size/2, m_y - 15); } else { // leave enough room for two lines of text if word wrap is enabled, otherwise a single line widget_size = rect<s32>(m_x - label_extra_size/2, m_y + m_h, m_x + m_w + label_extra_size/2, m_y + m_h + (word_wrap ? GUIEngine::getFontHeight()*2 : GUIEngine::getFontHeight())); } m_label = GUIEngine::getGUIEnv()->addStaticText(message.c_str(), widget_size, false, word_wrap, m_parent); m_label->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT); m_label->setTabStop(false); m_label->setNotClipped(true); if (m_properties[PROP_LABELS_LOCATION] == "hover") { m_label->setVisible(false); } setLabelFont(); #if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) m_label->setRightToLeft( translations->isRTLLanguage() ); m_label->setTextRestrainedInside(false); #endif } // ---- IDs m_id = m_element->getID(); if (m_tab_stop) m_element->setTabOrder(m_id); m_element->setTabGroup(false); }