Merge branch 'master' of github.com:supertuxkart/stk-code
This commit is contained in:
commit
768d843cfe
@ -1512,13 +1512,13 @@ void Skin::drawIconButton(const core::recti &rect, Widget* widget,
|
||||
SColor(100,255,255,255),
|
||||
SColor(100,255,255,255) };
|
||||
core::recti r(0,0,icon_widget->m_texture_w, icon_widget->m_texture_h);
|
||||
draw2DImage(icon_widget->m_texture, sized_rect,
|
||||
draw2DImage(icon_widget->getTexture(), sized_rect,
|
||||
r, 0 /* no clipping */, colors,
|
||||
true /* alpha */);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::ITexture* t = icon_widget->m_texture;
|
||||
const video::ITexture* t = icon_widget->getTexture();
|
||||
|
||||
const bool mouseInside =
|
||||
rect.isPointInside(irr_driver->getDevice()->getCursorControl()
|
||||
|
@ -16,6 +16,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
@ -53,10 +54,14 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
|
||||
m_selected_item[0] = 0; // only player 0 has a selection by default
|
||||
|
||||
m_item_count_hint = 0;
|
||||
|
||||
m_font = GUIEngine::getFont()->getHollowCopy();
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
DynamicRibbonWidget::~DynamicRibbonWidget()
|
||||
{
|
||||
m_font->drop();
|
||||
if (m_animated_contents)
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
@ -379,6 +384,13 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
ribbon->m_properties[PROP_ID] = name.str();
|
||||
ribbon->m_event_handler = this;
|
||||
|
||||
// calculate font size
|
||||
if (m_col_amount > 0)
|
||||
{
|
||||
m_font->setScale(GUIEngine::getFont()->getScale() *
|
||||
getFontScale((ribbon->m_w / m_col_amount) - 30));
|
||||
}
|
||||
|
||||
// add columns
|
||||
for (int i=0; i<m_col_amount; i++)
|
||||
{
|
||||
@ -392,6 +404,7 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT];
|
||||
icon->m_w = atoi(icon->m_properties[PROP_WIDTH].c_str());
|
||||
icon->m_h = atoi(icon->m_properties[PROP_HEIGHT].c_str());
|
||||
icon->setLabelFont(m_font);
|
||||
|
||||
// If we want each icon to have its own label, we must make it non-empty, otherwise
|
||||
// it will assume there is no label and none will be created (FIXME: that's ugly)
|
||||
@ -438,14 +451,14 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
assert(childrenCount == (int)m_items.size());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badges,
|
||||
IconButtonWidget::IconPathType image_path_type)
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_sshot_file = image_file;
|
||||
desc.m_badges = badges;
|
||||
@ -453,6 +466,8 @@ void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const st
|
||||
desc.m_image_path_type = image_path_type;
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -462,7 +477,7 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
const unsigned int badges, IconButtonWidget::IconPathType image_path_type )
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_all_images = image_files;
|
||||
desc.m_badges = badges;
|
||||
@ -473,6 +488,8 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
|
||||
if (!m_animated_contents)
|
||||
{
|
||||
m_animated_contents = true;
|
||||
@ -498,6 +515,7 @@ void DynamicRibbonWidget::clearItems()
|
||||
m_items.clear();
|
||||
m_animated_contents = false;
|
||||
m_scroll_offset = 0;
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::elementRemoved()
|
||||
@ -1097,7 +1115,9 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
propagateSelection();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated)
|
||||
@ -1117,4 +1137,29 @@ bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void DynamicRibbonWidget::setLabelSize(const irr::core::stringw& text)
|
||||
{
|
||||
int w = GUIEngine::getFont()->getDimension(text.c_str()).Width;
|
||||
if (w > m_max_label_width)
|
||||
m_max_label_width = w;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
float DynamicRibbonWidget::getFontScale(int icon_width) const
|
||||
{
|
||||
if (m_max_label_width <= icon_width || m_max_label_width == 0 || icon_width == 0)
|
||||
return 1.0f;
|
||||
else
|
||||
return std::max (0.5f, ((float)icon_width / (float)m_max_label_width));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
irr::core::stringw DynamicRibbonWidget::getUserName(const irr::core::stringw& user_name) const
|
||||
{
|
||||
if (user_name.size() < MAX_LABEL_LENGTH)
|
||||
return user_name;
|
||||
else
|
||||
return (user_name.subString(0, MAX_LABEL_LENGTH - 3) + L"...");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
namespace GUIEngine
|
||||
{
|
||||
class IconButtonWidget;
|
||||
|
||||
|
||||
/**
|
||||
* Even if you have a ribbon that only acts on click/enter, you may wish to know which
|
||||
* item is currently highlighted. In this case, create a listener and pass it to the ribbon.
|
||||
@ -44,7 +44,7 @@ namespace GUIEngine
|
||||
const irr::core::stringw& selectionText,
|
||||
const int playerID) = 0;
|
||||
};
|
||||
|
||||
|
||||
/** The description of an item added to a DynamicRibbonWidget */
|
||||
struct ItemDescription
|
||||
{
|
||||
@ -52,16 +52,16 @@ namespace GUIEngine
|
||||
std::string m_code_name;
|
||||
std::string m_sshot_file;
|
||||
IconButtonWidget::IconPathType m_image_path_type;
|
||||
|
||||
|
||||
bool m_animated;
|
||||
/** used instead of 'm_sshot_file' if m_animated is true */
|
||||
std::vector<std::string> m_all_images;
|
||||
float m_curr_time;
|
||||
float m_time_per_frame;
|
||||
|
||||
|
||||
unsigned int m_badges;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief An extended version of RibbonWidget, with more capabilities.
|
||||
* A dynamic ribbon builds upon RibbonWidget, adding dynamic contents creation and sizing,
|
||||
@ -73,55 +73,55 @@ namespace GUIEngine
|
||||
class DynamicRibbonWidget : public Widget, public RibbonWidget::IRibbonListener
|
||||
{
|
||||
friend class RibbonWidget;
|
||||
|
||||
|
||||
/** A list of all listeners that registered to be notified on hover/selection */
|
||||
PtrVector<DynamicRibbonHoverListener> m_hover_listeners;
|
||||
|
||||
|
||||
virtual ~DynamicRibbonWidget();
|
||||
|
||||
|
||||
/** Used for ribbon grids that have a label at the bottom */
|
||||
bool m_has_label;
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
|
||||
|
||||
/** Height of ONE label text line (if label is multiline only one line is measured here).
|
||||
* If there is no label, will be 0.
|
||||
*/
|
||||
int m_label_height;
|
||||
|
||||
|
||||
/** Whether this ribbon contains at least one animated item */
|
||||
bool m_animated_contents;
|
||||
|
||||
|
||||
/** Whether there are more items than can fit in a single screen; arrows will then appear
|
||||
* on each side of the ribbon to scroll the contents
|
||||
*/
|
||||
bool m_scrolling_enabled;
|
||||
|
||||
|
||||
/** Used to keep track of item count changes */
|
||||
int m_previous_item_count;
|
||||
|
||||
|
||||
/** List of items in the ribbon */
|
||||
std::vector<ItemDescription> m_items;
|
||||
|
||||
|
||||
/** Width of the scrolling arrows on each side */
|
||||
int m_arrows_w;
|
||||
|
||||
|
||||
/** Current scroll offset within items */
|
||||
int m_scroll_offset;
|
||||
|
||||
|
||||
/** Width and height of children as declared in the GUI file */
|
||||
int m_child_width, m_child_height;
|
||||
|
||||
|
||||
/** Number of rows and columns. Number of columns can dynamically change, number of row is
|
||||
determined at creation */
|
||||
int m_row_amount;
|
||||
int m_col_amount;
|
||||
|
||||
|
||||
/** The total number of columns given item count and row count (even counting not visible with current scrolling) */
|
||||
int m_needed_cols;
|
||||
|
||||
|
||||
/** Whether this ribbon can have multiple rows (i.e. ribbon grid) or is a single line */
|
||||
bool m_multi_row;
|
||||
|
||||
|
||||
/** irrlicht relies on consecutive IDs to perform keyboard navigation between widgets. However, since this
|
||||
widget is dynamic, irrlicht widgets are not created as early as all others, so by the time we're ready
|
||||
to create the full contents of this widget, the ID generator is already incremented, thus messing up
|
||||
@ -129,65 +129,81 @@ namespace GUIEngine
|
||||
number of IDs (the number of rows) and store them here. Then, when we're finally ready to create the
|
||||
contents dynamically, we can re-use these IDs and get correct navigation order. */
|
||||
std::vector<int> m_ids;
|
||||
|
||||
|
||||
/** Whether this is a "combo" style ribbon grid widget */
|
||||
bool m_combo;
|
||||
|
||||
|
||||
/* reference pointers only, the actual instances are owned by m_children */
|
||||
IconButtonWidget* m_left_widget;
|
||||
IconButtonWidget* m_right_widget;
|
||||
|
||||
|
||||
/** Returns the currently selected row */
|
||||
RibbonWidget* getSelectedRibbon(const int playerID);
|
||||
|
||||
|
||||
/** Returns the row */
|
||||
RibbonWidget* getRowContaining(Widget* w);
|
||||
|
||||
|
||||
/** Updates the visible label to match the currently selected item */
|
||||
void updateLabel(RibbonWidget* from_this_ribbon=NULL);
|
||||
|
||||
|
||||
/** Even though the ribbon grid widget looks like a grid, it is really a vertical stack of
|
||||
independant ribbons. When moving selection horizontally, this method is used to notify
|
||||
other rows above and below of which column is selected, so that moving vertically to
|
||||
another row keeps the same selected column. */
|
||||
void propagateSelection();
|
||||
|
||||
|
||||
/** Callback called widget is focused */
|
||||
EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
/** Removes all previously added contents icons, and re-adds them (calculating the new amount) */
|
||||
void buildInternalStructure();
|
||||
|
||||
/** Call this to scroll within a scrollable ribbon */
|
||||
void scroll(const int x_delta);
|
||||
|
||||
|
||||
/** Used for combo ribbons, to contain the ID of the currently selected item for each player */
|
||||
int m_selected_item[MAX_PLAYER_COUNT];
|
||||
|
||||
|
||||
/** Callbacks */
|
||||
virtual void add();
|
||||
virtual EventPropagation mouseHovered(Widget* child, const int playerID);
|
||||
virtual EventPropagation transmitEvent(Widget* w, const std::string& originator, const int playerID);
|
||||
|
||||
|
||||
bool findItemInRows(const char* name, int* p_row, int* p_id);
|
||||
|
||||
|
||||
int m_item_count_hint;
|
||||
|
||||
|
||||
float getFontScale(int icon_width) const;
|
||||
void setLabelSize(const irr::core::stringw& text);
|
||||
irr::core::stringw getUserName(const irr::core::stringw& user_name) const;
|
||||
|
||||
/**
|
||||
* Font used to write the labels, can be scaled down depending on the
|
||||
* length of the text
|
||||
*/
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
/** Max width of a label, in pixels */
|
||||
int m_max_label_width;
|
||||
|
||||
/** Max length of a label, in characters */
|
||||
static const int MAX_LABEL_LENGTH = 30;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/**
|
||||
* \param combo Whether this is a "combo" ribbon, i.e. whether there is always one selected item.
|
||||
* If set to false, will behave more like a toolbar.
|
||||
* \param multi_row Whether this ribbon can have more than one row
|
||||
*/
|
||||
DynamicRibbonWidget(const bool combo, const bool multi_row);
|
||||
|
||||
|
||||
/** Reference pointers only, the actual instances are owned by m_children. Used to create mtultiple-row
|
||||
ribbons (what appears to be a grid of icons is actually a vector of stacked basic ribbons) */
|
||||
PtrVector<RibbonWidget, REF> m_rows;
|
||||
|
||||
|
||||
/** Dynamically add an item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add').
|
||||
*
|
||||
@ -200,7 +216,7 @@ namespace GUIEngine
|
||||
void addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badge=0,
|
||||
IconButtonWidget::IconPathType image_path_type=IconButtonWidget::ICON_PATH_TYPE_RELATIVE);
|
||||
|
||||
|
||||
/** Dynamically add an animated item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add'). Animated means it has many images that will be shown in
|
||||
* a slideshown fashion.
|
||||
@ -220,7 +236,7 @@ namespace GUIEngine
|
||||
/** Clears all items added through 'addItem'. You can then add new items with 'addItem' and call
|
||||
'updateItemDisplay' to update the display. */
|
||||
void clearItems();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Register a listener to be notified of selection changes within the ribbon.
|
||||
* \note The ribbon takes ownership of this listener and will delete it.
|
||||
@ -228,26 +244,26 @@ namespace GUIEngine
|
||||
* want to add a listener in the "init" callback of your screen.
|
||||
*/
|
||||
void registerHoverListener(DynamicRibbonHoverListener* listener);
|
||||
|
||||
|
||||
/** Called when right key is pressed */
|
||||
EventPropagation rightPressed(const int playerID);
|
||||
|
||||
|
||||
/** Called when left key is pressed */
|
||||
EventPropagation leftPressed(const int playerID);
|
||||
|
||||
|
||||
/** Updates icons/labels given current items and scrolling offset, taking care of resizing
|
||||
the dynamic ribbon if the number of items changed */
|
||||
void updateItemDisplay();
|
||||
|
||||
|
||||
/** Get the internal name (ID) of the selected item */
|
||||
const std::string& getSelectionIDString(const int playerID);
|
||||
|
||||
|
||||
/** Get the user-visible text of the selected item */
|
||||
irr::core::stringw getSelectionText(const int playerID);
|
||||
|
||||
|
||||
/** Returns a read-only list of items added to this ribbon */
|
||||
const std::vector<ItemDescription>& getItems() const { return m_items; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its numerical ID. Only for [1-row] combo ribbons.
|
||||
*
|
||||
@ -255,7 +271,7 @@ namespace GUIEngine
|
||||
* \return Whether setting the selection was successful (whether the item exists)
|
||||
*/
|
||||
bool setSelection(int item_id, const int playerID, const bool focusIt, bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its codename.
|
||||
*
|
||||
@ -264,26 +280,26 @@ namespace GUIEngine
|
||||
bool setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/** \brief Callback from parent class Widget. */
|
||||
virtual void elementRemoved();
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetScroll(const int delta_x);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetFocus(RibbonWidget* emitter, const int playerID);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onSelectionChange(){}
|
||||
|
||||
virtual void update(float delta);
|
||||
|
||||
|
||||
/** Set approximately how many items are expected to be in this ribbon; will help the layout
|
||||
* algorithm next time add() is called */
|
||||
void setItemCountHint(int hint) { m_item_count_hint = hint; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::video;
|
||||
@ -39,10 +40,15 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
const bool focusable, IconPathType pathType) : Widget(WTYPE_ICON_BUTTON)
|
||||
{
|
||||
m_label = NULL;
|
||||
m_font = NULL;
|
||||
m_texture = NULL;
|
||||
m_highlight_texture = NULL;
|
||||
m_deactivated_texture = NULL;
|
||||
m_custom_aspect_ratio = 1.0f;
|
||||
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
|
||||
m_tab_stop = tab_stop;
|
||||
m_focusable = focusable;
|
||||
m_scale_mode = scale_mode;
|
||||
@ -50,6 +56,12 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
m_icon_path_type = pathType;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
IconButtonWidget::~IconButtonWidget()
|
||||
{
|
||||
if (m_deactivated_texture != NULL)
|
||||
m_deactivated_texture->drop();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::add()
|
||||
{
|
||||
// ---- Icon
|
||||
@ -57,12 +69,12 @@ void IconButtonWidget::add()
|
||||
{
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
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]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,13 +84,11 @@ void IconButtonWidget::add()
|
||||
"add() : error, cannot find texture '%s'.",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
if(!m_texture)
|
||||
Log::fatal("IconButtonWidget",
|
||||
"Can't find fallback texture 'gui/main_help.png, aborting.");
|
||||
}
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
|
||||
if (m_properties[PROP_FOCUS_ICON].size() > 0)
|
||||
{
|
||||
@ -174,13 +184,7 @@ void IconButtonWidget::add()
|
||||
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() );
|
||||
}
|
||||
setLabelFont();
|
||||
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
m_label->setRightToLeft( translations->isRTLLanguage() );
|
||||
@ -207,12 +211,12 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
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]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
if (!m_texture)
|
||||
@ -220,11 +224,8 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
Log::error("icon_button", "Texture '%s' not found!\n",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -233,39 +234,28 @@ void IconButtonWidget::setImage(ITexture* texture)
|
||||
{
|
||||
if (texture != NULL)
|
||||
{
|
||||
m_texture = texture;
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
setTexture(texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("icon_button",
|
||||
"setImage invoked with NULL image pointer\n");
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabel(stringw new_label)
|
||||
void IconButtonWidget::setLabel(const stringw& new_label)
|
||||
{
|
||||
if (m_label == NULL) return;
|
||||
|
||||
m_label->setText( new_label.c_str() );
|
||||
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(new_label.c_str()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
setLabelFont();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont(irr::gui::ScalableFont* font)
|
||||
{
|
||||
m_font = font;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation IconButtonWidget::focused(const int playerID)
|
||||
@ -288,4 +278,78 @@ void IconButtonWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
|
||||
{
|
||||
SColor c;
|
||||
u32 g;
|
||||
|
||||
video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
video::IImage* image = driver->createImageFromData (texture->getColorFormat(),
|
||||
texture->getSize(), texture->lock(), false);
|
||||
texture->unlock();
|
||||
|
||||
//Turn the image into grayscale
|
||||
for (u32 x = 0; x < image->getDimension().Width; x++)
|
||||
{
|
||||
for (u32 y = 0; y < image->getDimension().Height; y++)
|
||||
{
|
||||
c = image->getPixel(x, y);
|
||||
g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
|
||||
c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
|
||||
image->setPixel(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
texture = driver->addTexture(texture->getName().getPath() + "_disabled", image);
|
||||
texture->grab();
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setTexture(video::ITexture* texture)
|
||||
{
|
||||
m_texture = texture;
|
||||
if (texture == NULL)
|
||||
{
|
||||
if (m_deactivated_texture != NULL)
|
||||
m_deactivated_texture->drop();
|
||||
|
||||
m_deactivated_texture = NULL;
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_deactivated_texture = getDeactivatedTexture(texture);
|
||||
m_texture_w = texture->getSize().Width;
|
||||
m_texture_h = texture->getSize().Height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont()
|
||||
{
|
||||
if (m_font != NULL)
|
||||
{
|
||||
m_label->setOverrideFont( m_font );
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(m_label->getText()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,16 @@
|
||||
#include <irrString.h>
|
||||
namespace irr
|
||||
{
|
||||
namespace gui { class IGUIStaticText; }
|
||||
namespace gui
|
||||
{
|
||||
class IGUIStaticText;
|
||||
class ScalableFont;
|
||||
}
|
||||
namespace video { class ITexture; }
|
||||
}
|
||||
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
@ -38,6 +41,15 @@ namespace GUIEngine
|
||||
*/
|
||||
class IconButtonWidget : public Widget
|
||||
{
|
||||
private:
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::video::ITexture* m_highlight_texture;
|
||||
irr::video::ITexture* m_deactivated_texture;
|
||||
int m_texture_w, m_texture_h;
|
||||
|
||||
video::ITexture* getDeactivatedTexture(video::ITexture* texture);
|
||||
void setLabelFont();
|
||||
|
||||
public:
|
||||
enum ScaleMode
|
||||
{
|
||||
@ -54,42 +66,41 @@ namespace GUIEngine
|
||||
* the path type as it currently is */
|
||||
ICON_PATH_TYPE_NO_CHANGE
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::video::ITexture* m_highlight_texture;
|
||||
|
||||
int m_texture_w, m_texture_h;
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
ScaleMode m_scale_mode;
|
||||
float m_custom_aspect_ratio;
|
||||
|
||||
|
||||
void setTexture(video::ITexture* texture);
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/** Whether to make the widget included in keyboard navigation order when adding */
|
||||
bool m_tab_stop;
|
||||
|
||||
IconButtonWidget(ScaleMode scale_mode=SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, const bool tab_stop=true,
|
||||
const bool focusable=true, IconPathType pathType=ICON_PATH_TYPE_RELATIVE);
|
||||
virtual ~IconButtonWidget() {}
|
||||
|
||||
virtual ~IconButtonWidget();
|
||||
|
||||
/** \brief Implement callback from base class Widget */
|
||||
virtual void add();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Call this if scale mode is SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO.
|
||||
* \param custom_aspect_ratio The width/height aspect ratio
|
||||
*/
|
||||
void setCustomAspectRatio(float custom_aspect_ratio) { m_custom_aspect_ratio = custom_aspect_ratio; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Temporarily change the text label if there is a label (next time this screen is
|
||||
* visited, the previous label will be back. For a permanent change, edit the 'text'
|
||||
@ -98,8 +109,15 @@ namespace GUIEngine
|
||||
* \pre Must be called after this widget is add()ed to have any effect
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabel(irr::core::stringw new_label);
|
||||
|
||||
void setLabel(const irr::core::stringw& new_label);
|
||||
|
||||
/**
|
||||
* \brief Sets the font used to draw the label.
|
||||
*
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabelFont(irr::gui::ScalableFont* font);
|
||||
|
||||
/**
|
||||
* Change the texture used for this icon.
|
||||
* \pre At the moment, the new texture must have the same aspct ratio
|
||||
@ -109,7 +127,7 @@ namespace GUIEngine
|
||||
*/
|
||||
void setImage(const char* path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE);
|
||||
// --------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
/** Convenience function taking std::string. */
|
||||
void setImage(const std::string &path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE)
|
||||
@ -126,23 +144,24 @@ namespace GUIEngine
|
||||
* \note May safely be called no matter if the widget is add()ed or not
|
||||
*/
|
||||
void setImage(irr::video::ITexture* texture);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void setHighlightedImage(irr::video::ITexture* texture)
|
||||
{
|
||||
m_highlight_texture = texture;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
virtual void unfocused(const int playerID, Widget* new_focus);
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the texture of this button. */
|
||||
const video::ITexture* getTexture() const { return m_texture; }
|
||||
const video::ITexture* getTexture() const {
|
||||
return (Widget::isActivated() ? m_texture : m_deactivated_texture); }
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user