From 183ff21c91c594d5dbbabee39259968262d5b899 Mon Sep 17 00:00:00 2001 From: auria Date: Fri, 23 Apr 2010 19:47:17 +0000 Subject: [PATCH] 1) Added warp-around feature to spinners, made player ident spinners warp-around. 2) Moved GUI engine documentation from .hpp file to .cpp file, so that a documentation change doesn't trigger large re-compilations of everything 3) Formatted GUI engine documentation for Doxygen, now Doxygen will generate us a nice documentation about the GUI engine git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5248 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/guiengine/engine.cpp | 352 +++++++++++++++++++++++ src/guiengine/engine.hpp | 202 ------------- src/guiengine/screen_loader.cpp | 3 +- src/guiengine/widget.hpp | 14 +- src/guiengine/widgets/spinner_widget.cpp | 22 +- src/guiengine/widgets/spinner_widget.hpp | 61 +++- src/states_screens/kart_selection.cpp | 2 + 7 files changed, 441 insertions(+), 215 deletions(-) diff --git a/src/guiengine/engine.cpp b/src/guiengine/engine.cpp index 0b6fb3504..bd2b6f0ba 100644 --- a/src/guiengine/engine.cpp +++ b/src/guiengine/engine.cpp @@ -15,6 +15,358 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** + + + \page gui_overview GUI Module Overview + + In XML files, widgets are declared in the following fashion : + + \code + + \endcode + + or, for widgets of "spawn" type, with children : + + \code + + + + + \endcode + + The first section of this document describes the widgets you can use; the second describes the properties + widgets can take. Not all properties can be applied to all widgets, see the docs for a given widget and a + given property for full information. + + \section toc Table of Contents + \ref widgets + \li \ref widget1 + \li \ref widget2 + \li \ref widget3 + \li \ref widget4 + \li \ref widget5 + \li \ref widget6 + \li \ref widget7 + \li \ref widget8 + \li \ref widget9 + \li \ref widget10 + \li \ref widget11 + + \ref props + \li \ref prop1 + \li \ref prop2 + \li \ref prop3 + \li \ref prop4 + \li \ref prop5 + \li \ref prop6 + \li \ref prop7 + \li \ref prop8 + \li \ref prop9 + \li \ref prop10 + \li \ref prop11 + \li \ref prop12 + \li \ref prop13 + \li \ref prop14 + \li \ref prop15 + \li \ref prop16 + \li \ref prop17 + \li \ref prop18 + + \ref code + + \n + \n + \section widgets Widgets + + This section describes the widgets you can use in STK's GUI XML files. The upper-case name starting with + WTYPE_* is the internal name of the widget (see the GUIEngine::WidgetType enum). + + + \subsection widget1 WTYPE_RIBBON + Names in XML files: \c "ribbon", \c "buttonbar", \c "tabs" + + Appears as an horizontal bar containing elements laid in a row, each being and icon and/or a label + + \li The "ribbon" subcategory will behave a bit like a radio button group, i.e. one element must selected. + events are triggered as soon as a choice is selected (can be simply by hovering). + \li The "buttonbar" subcategory treats children buttons as action buttons, which means they can't have a + 'selected' state, only focused or not (i.e. there is no selection that remains if you leave this area). + events are triggered only on enter/fire. + \li The "tabs" subcategory will show a tab bar. behaviour is same as normal ribbon, only looks are different. + Orientation of tabs (up or down) is automatically inferred from on-screen position + + \note Ribbon widgets are of spawn type (\ ... \) and may contain icon-buttons or buttons as children. + \note Property PROP_SQUARE can be set to tell the engine if the ribbon's contents are rectangular or not (this will + affect the type of highlighting used) + \note All elements within a ribbon must have an 'ID' property + + \n + \subsection widget2 WTYPE_SPINNER + Names in XML files: \c "spinner", \c "gauge" + + A spinner component (lets you choose numbers). + + Specify PROP_MIN_VALUE and PROP_MAX_VALUE to have control over values (default will be from 0 to 10). + You can specify an icon; then, include a sprintf format string like %i in the name, and at runtime the + current number will be inserted into the given name to find the + right file for each possible value the spinner can take. It may also display arbitrary text instead of + numbers, though this cannot be achieve in the XML file; use the -\>addLabel(...) method in code to do this. + It can also display arbitrary text containing the value; just define the PROP_TEXT property to contain + the text you want, including a format string %i where the value should appear. + \note The "gauge" variant behaves similarly, but a fill band shows how close to the max the value is. + + \n + \subsection widget3 WTYPE_BUTTON + Name in XML files: \c "button" + + A plain text button. + + \n + \subsection widget4 WTYPE_ICON_BUTTON + Names in XML files: \c "icon-button", \c "icon" + + A component with an image, and optional text to go under it. + + \note The "icon" variant will have no border and will not be clickable. PROP_ICON is mandatory for this component. + There are three ways to place the texture within the allocated space; the default (and only way currently accessible + through xml files) is to scale the texture to fit, while preserving its aspect ratio; other methods, currently only + accessible through C++ code, are to stretch the texture to fill the area without caring for aspect ratio, and another + to respect an aspect ratio other than the texture's (useful for track screenshots, which are 4:3 compressed to fit + in a power-of-two 256x256 texture) + + \n + \subsection widget5 WTYPE_CHECKBOX + Name in XML files: \c "checkbox" + + A checkbox. + + \n + \subsection widget6 WTYPE_LABEL + Names in XML files: \c "label", \c "header" + + A plain label. + + Supports properties PROP_WORD_WRAP and PROP_TEXT_ALIGN. + \note The "Header" variant uses a bigger and more colourful font. + + \n + \subsection widget7 WTYPE_SPACER + Name in XML files: \c "spacer" + + Some blank space; not visible on screen. + + \n + \subsection widget8 WTYPE_DIV + Name sin XML files: \c "div", \c "box" + + An invisible container. + + \li Divs do not do much on themselves, but are useful to lay out children automatically (Supports property PROP_LAYOUT) + \li Divs can be nested. + \li Of spawn type (\...\, place children within) + \note "box" is a variant that acts exactly the same but is visible on-screen + + \n + \subsection widget9 WTYPE_DYNAMIC_RIBBON + Names in XML files: \c "ribbon_grid", \c "scrollable_ribbon", \c "scrollable_toolbar" + + Builds upon the basic Ribbon to be more dynamic (dynamics contents, possibly with scrolling, possibly multi-line) + + \li NOT of spawn type (\), i.e. children are not specified in the XML file but + programmatically at runtime. + \li PROP_CHILD_WIDTH and PROP_CHILD_HEIGHT are mandatory (so at least aspect ratio of elements that will later be + added is known) An interesting aspect of PROP_CHILD_WIDTH and PROP_CHILD_HEIGHT is that you can use them to + show textures to any aspect ratio you want (so you can e.g. save textures to a power-of-two size like 256x256, + but then show it in 4:3 ratio). + \li Property PROP_SQUARE can be set to tell the engine if the ribbon's contents are rectangular or icons (this will + affect the type of highlighting used). + \li Supports an optional label at the bottom if PROP_LABELS_LOCATION is set (see more on PROP_LABELS_LOCATION below). + \note The "scrollable_ribbon" and "scrollable_toolbar" subtypes are single-line scrollable ribbons. + The difference between both is that 'scrollable_ribbon' always has a value selected (like in + a combo box, or radio buttons), while 'scrollable_toolbar' is a scrollable list of buttons that can be + pressed to trigger actions. + + \n + \subsection widget10 WTYPE_MODEL_VIEW + Name in XML files: \c "model" + + Displays a 3D model. + + \note Contents must be set programmatically. + + \n + \subsection widget11 WTYPE_LIST + Name in XML files: \c "list" + + Displays a list. + + \note Contents must be set programmatically. + + + \n + \n + \section props Properties + + \subsection prop1 PROP_ID + Name in XML files: \c "id" + + Gives a unique internal name to each object using this property. It will be + used in events callbacks to determine what action occurred. Can be omitted + on components that do not trigger events (e.g. labels) + + \n + \subsection prop2 PROP_TEXT + Name in XML files: \c "text" + + gives text (a label) to the widget where supported. Ribbon-grids give a special meaning + to this parameter, see ribbon-grid docs above. + + \n + \subsection prop3 PROP_ICON + Name in XML files: \c "icon" + + give an icon to the widget. Property contents is the path to the file, by default relative + relative to the /data directory of STK (several methods of IconButtonWidget and DynamicRibbon + can enable you to use absolute paths if you wish, however). + + \n + \subsection prop4 PROP_TEXT_ALIGN + Name in XML files: \c "text_align" + + used exclusively by label components. Value can be "right" or "center" (left used if not specified). + + \n + \subsection prop5 PROP_WORD_WRAP + Name in XML files: \c "word_wrap" + + used exclusively by label components. Value can be "true" to indicate that long text should spawn on + multiple lines. + + \n + \subsection prop6 PROP_MIN_VALUE, PROP_MAX_VALUE + Name in XML files: \c "min_value", \c "max_value" + + used to specify a minimum and maximum value for numeric widgets (c.f. spinner) + + \n + \subsection prop7 PROP_X, PROP_Y + Name in XML files: \c "x", "y" + + sets the position (location) of a widget, relative to its parent (container \ or screen if none). + A plain number will be interpreted as an aabsolute position in pixels. A '%' sign may be added to the + given number to mean that the location is specified in terms of a percentage of parent size (parent size + means the parent \ or the whole screen if none). A negative value can also be passed to start coordinate + from right and/or bottom, instead of starting from top-left corner as usual. + Note that in many cases, it is not necessary to manually a position. Div layouts will often manage that + for you (see PROP_LAYOUT). Other widgets will also automativally manage the position and size of their children, + for instance ribbons. + + \n + \subsection prop8 PROP_WIDTH, PROP_HEIGHT + Name in XML files: \c "width", \c "height" + + give dimensions to the widget. A plain number will be interpreted as an aabsolute position in pixels. + A '%' sign may be added to the given number to mean that the size is specified in terms of a percentage + of parent size (parent size means the parent \ or the whole screen if none). + Note that in many cases, it is not necessary to manually a size. Div layouts will often manage that + for you (see PROP_LAYOUT). In addition, sizes are automatically calculated for widgets made of icons + and/or text like labels and plain icons. Other widgets will also automativally manage the position and + size of their children, for instance ribbons. + + \n + \subsection prop9 PROP_MAX_WIDTH, PROP_MAX_HEIGHT + Names in XML files: \c "max_width", \c "max_height" + + The maximum size a widget can take; especially useful when using percentages and proportions. + + \n + \subsection prop10 PROP_CHILD_WIDTH, PROP_CHILD_HEIGHT + Names in XML files: \c "child_width", \c "child_height" + + Used exclusively by the ribbon grid widget. See docs for this widget above. + + \n + \subsection prop11 PROP_LAYOUT + Name in XML files: \c "layout" + + Valid on 'div' containers. Value can be "horizontal-row" or "vertical-row". This means x and y coordinates + of all children will automatically be calculated at runtime, so they are laid in a row. Width and height can + be set absolutely as usual, but can also be determined dynamically according to available screen space. Also + see PROP_ALIGN and PROP_PROPORTION to known more about controlling layouts. Note that all components within a + layed-out div will ignore all x/y coordinates you may give them as parameter. + + \n + \subsection prop12 PROP_ALIGN + Name in XML files: \c "align" + + For widgets located inside a vertical-row layout div : Changes how the x coord of the widget is determined. + value can be "left", "center" or "right". + For widgets located inside a horizontal-row layout div : Changes how the y coord of the widget is determined. + value can be "top", "center" or "bottom". + + \n + \subsection prop13 PROP_PROPORTION + Name in XML files: \c "proportion" + + Helps determining widget size dynamically (according to available screen space) in layed-out divs. In a + vertical row layout, proportion sets the height of the item. In an horizontal row, it sets the width of + the item. Proportions are always evaluated relative to the proportions of other widgets in the same div. + If one div contains 4 widgets, and their proportions are 1-2-1-1, it means the second must take twice as + much space as the 3 others. In this case, 10-20-10-10 would do the exact same effect. 1-1-1-1 would mean + all take 1/4 of the available space. Note that it is allowed to mix absolute widget sizes and proportions; + in this case, widgets with absolute size are evaluated first, and the dynamically-sized ones split the + remaining space according to their proportions. + + \n + \subsection prop14 PROP_SQUARE + Name in XML files: \c "square_items" + + Valid on Ribbons or RibbonGrids. Can be "true" (omitting it means "false"). Indicates whether the contents + use rectangular icons as opposed to "round" icons (this will affect the type of focus/highlighting used) + + \n + \subsection prop15 PROP_EXTEND_LABEL + Name in XML files: \c "extend_label" + + How many pixels the label is allowed to expand beyond the boundaries of the widget itself. Currently only + allowed on icon widgets. + + \n + \subsection prop16 PROP_LABELS_LOCATION + Name in XML files: \c "label_location" + + Currently only used by dynamic ribbons. Decides where the label is. Value can be "each", "bottom", or "none" + (if ommitted, "none" is the default). "each" means that every item has its own label. "bottom" means there + is a single label for all at the bottom, that displays the name of the current item. + + \n + \subsection prop17 PROP_MAX_ROWS + Name in XML files: \c "max_rows" + + Currently used for ribbon grids only. Indicates the maximum amount of rows this ribbon can have. + + \n + \subsection prop18 PROP_WARP_AROUND + Name in XML files: \c "warp_around" + + Currently used for spinners only. Value can be "true" or "false" + + + \n + \section code Using the engine in code + + The first thing to do is to derive a class of your own from AbstractStateManager. There are a few callbacks + you will need to override. Once it's done, you have all AbstractStateManager methods ready to be used to + push/pop/set menus on the screen stack. + Once you have instanciated your state manager class, call GUIEngine::init and pass it as argument. + One of the most important callbacks is 'eventCallback', which will be called everytime sometimes happens. + Events are generally a widget state change. In this case, a pointer to the said widget is passed along its + name, so you get its new state and/or act. There are two special events, passed with a NULL widget, and which + bear the anmes "init" and "tearDown", called respectively when a screen is being made visible and when it's + being left, allowing for setup/clean-up. + + */ #include "guiengine/engine.hpp" diff --git a/src/guiengine/engine.hpp b/src/guiengine/engine.hpp index 6b7ecf3f4..9d952e9f6 100644 --- a/src/guiengine/engine.hpp +++ b/src/guiengine/engine.hpp @@ -16,208 +16,6 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -/* -+---------+ -+ Widgets + -+---------+ - -_______________________________________________________ -Internal constant Name in XML files -_______________________________________________________ - -WTYPE_RIBBON "ribbon", "buttonbar", "tabs" -appears an horizontal bar containing elements laid in a row, each being and icon and/or a label -the "ribbon" subcategory will behave a bit like a radio button group, i.e. one element must selected. -events are triggered as soon as a choice is selected (can be simply by hovering). -the "buttonbar" subcategory treats children buttons as action buttons, which means they can't have a -'selected' state, only focused or not (i.e. there is no selection that remains if you leave this area). -events are triggered only on enter/fire. -the "tabs" subcategory will show a tab bar. behaviour is same as normal ribbon, only looks are different. -Orientation of tabs (up or down) is automatically inferred from on-screen position -Ribbon widgets are of spawn type ( ... ) and may contain icon-buttons or buttons as children. -Property PROP_SQUARE can be set to tell the engine if the ribbon's contents are rectangular or not (this will -affect the type of highlighting used) - * Note : all elements within a ribbon must have an 'ID' property - -WTYPE_SPINNER "spinner", "gauge" -A spinner component (lets you choose numbers). Sprecify PROP_MIN_VALUE and PROP_MAX_VALUE to have control -over values (default will be from 0 to 10). You can specify an icon; then, include a sprintf format string -like %i in the name, and at runtime the current number will be inserted into the given name to find the -right file for each possible value the spinner can take. It may also display arbitrary text instead of -numbers, though this cannot be achieve in the XML file; use the ->addLabel(...) method in code to do this. -It can also display arbitrary text containing the value; just define the PROP_TEXT property to contain -the text you want, including a format string %i where the value should appear. -The "gauge" variant behaves similarly, but a fill band shows how close to the max the value is. - - -WTYPE_BUTTON "button" -A plain text buttons. - -WTYPE_ICON_BUTTON "icon-button", "icon" -A component with an image, and optional text to go under it. The "icon" variant will have no border and will not -be clickable. PROP_ICON is mandatory for this component. -There are three ways to place the texture within the allocated space; the default (and only way currently accessible -through xml files) is to scale the texture to fit, while preserving its aspect ratio; other methods, currently only -accessible through C++ code, are to stretch the texture to fill the area without caring for aspect ratio, and another -to respect an aspect ratio other than the texture's (useful for track screenshots, which are 4:3 compressed to fit -in a power-of-two 256x256 texture) - -WTYPE_CHECKBOX "checkbox" -A checkbox. Not used at the moment. - -WTYPE_LABEL "label" "header" -A plain label. Supports properties PROP_WORD_WRAP and PROP_TEXT_ALIGN. -The "Header" variant uses a bigger and more colourful font. - -WTYPE_SPACER "spacer" -Some blank space; not visible on screen. - -WTYPE_DIV "div", "box" -A container. Does not do much on itself, but is useful to lay out children automatically. Divs can be nested. -Supports property PROP_LAYOUT. Of spawn type (
...
, place children within) - "box" is a variant that acts exactly the same but is visible on-screen - -WTYPE_DYNAMIC_RIBBON "ribbon_grid", "scrollable_ribbon", "scrollable_toolbar" -Builds upon the basic Ribbon to be more dynamic (dynamics contents, possibly with scrolling, possibly multi-line) -NOT of spawn type (), contents must be programmatically set at runtime. -Property PROP_SQUARE can be set to tell the engine if the ribbon's contents are rectangular or icons (this will -affect the type of highlighting used). -PROP_CHILD_WIDTH and PROP_CHILD_HEIGHT are mandatory (so at least aspect ratio of elements that will later be -added is known) An interesting aspect of PROP_CHILD_WIDTH and PROP_CHILD_HEIGHT is that you can use them to -show textures to any aspect ratio you want (so you can e.g. save textures to a power-of-two size like 256x256, -but then show it in 4:3 ratio). -Supports an optional label at the bottom if PROP_LABELS_LOCATION is set (see more on PROP_LABELS_LOCATION below). -The "scrollable_ribbon" and "scrollable_toolbar" subtypes are single-line -scrollable ribbons. The difference between both is that 'scrollable_ribbon' always has a value selected (like in -a combo box, or radio buttons), while 'scrollable_toolbar' is a scrollable list of buttons that can be pressed to -trigger actions. - -WTYPE_MODEL_VIEW "model" -Displays a model. Currently incomplete. Contents must be set programmatically. - -WTYPE_LIST "list" -Displays a list. Currently incomplete. Contents must be set programmatically. - -+------------+ -+ Properties + -+------------+ - -_______________________________________________________ -Internal constant Name in XML files -_______________________________________________________ - -PROP_ID "id" -gives a unique internal name to each object using this property. It will be -used in events callbacks to determine what action occurred. Can be omitted -on components that do not trigger events (e.g. labels) - -PROP_TEXT "text" -gives text (a label) to the widget where supported. Ribbon-grids give a special meaning -to this parameter, see ribbon-grid docs above. - -PROP_ICON "icon" -give an icon to the widget. Property contents is the path to the file, by default relative -relative to the /data directory of STK (several methods of IconButtonWidget and DynamicRibbon -can enable you to use absolute paths if you wish). - -PROP_TEXT_ALIGN "text_align" -used exclusively by label components. Value can be "right" or "center" (left used if not specified). - -PROP_WORD_WRAP "word_wrap" -used exclusively by label components. Value can be "true" to indicate that long text should spawn on -multiple lines. - -PROP_MIN_VALUE "min_value" -PROP_MAX_VALUE "max_value" -used to specify a minimum and maximum value for numeric widgets (c.f. spinner) - -PROP_X "x" -PROP_Y "y" -sets the position (location) of a widget, relative to its parent (container
or screen if none). -A plain number will be interpreted as an aabsolute position in pixels. A '%' sign may be added to the -given number to mean that the location is specified in terms of a percentage of parent size (parent size -means the parent
or the whole screen if none). A negative value can also be passed to start coordinate -from right and/or bottom, instead of starting from top-left corner as usual. -Note that in many cases, it is not necessary to manually a position. Div layouts will often manage that -for you (see PROP_LAYOUT). Other widgets will also automativally manage the position and size of their children, -for instance ribbons. - -PROP_WIDTH "width" -PROP_HEIGHT "height" -give dimensions to the widget. A plain number will be interpreted as an aabsolute position in pixels. -A '%' sign may be added to the given number to mean that the size is specified in terms of a percentage -of parent size (parent size means the parent
or the whole screen if none). -Note that in many cases, it is not necessary to manually a size. Div layouts will often manage that -for you (see PROP_LAYOUT). In addition, sizes are automatically calculated for widgets made of icons -and/or text like labels and plain icons. Other widgets will also automativally manage the position and -size of their children, for instance ribbons. - -PROP_MAX_WIDTH "max_width" -PROP_MAX_HEIGHT "max_height" -The maximum size a widget can take; especially useful when using percentages and proportions. - -PROP_CHILD_WIDTH "child_width" -PROP_CHILD_HEIGHT "child_height" -Used exclusively by the ribbon grid widget. See docs for this widget above. - -PROP_GROW_WITH_TEXT "grow_with_text" -Reserved, but currently unimplemented and unused. - -PROP_LAYOUT "layout" -Valid on 'div' containers. Value can be "horizontal-row" or "vertical-row". This means x and y coordinates -of all children will automatically be calculated at runtime, so they are laid in a row. Width and height can -be set absolutely as usual, but can also be determined dynamically according to available screen space. Also -see PROP_ALIGN and PROP_PROPORTION to known more about controlling layouts. Note that all components within a -layed-out div will ignore all x/y coordinates you may give them as parameter. - -PROP_ALIGN "align" -For widgets located inside a vertical-row layout div : Changes how the x coord of the widget is determined. - value can be "left", "center" or "right". -For widgets located inside a horizontal-row layout div : Changes how the y coord of the widget is determined. - value can be "top", "center" or "bottom". - -PROP_PROPORTION "proportion" -Helps determining widget size dynamically (according to available screen space) in layed-out divs. In a -vertical row layout, proportion sets the height of the item. In an horizontal row, it sets the width of -the item. Proportions are always evaluated relative to the proportions of other widgets in the same div. -If one div contains 4 widgets, and their proportions are 1-2-1-1, it means the second must take twice as -much space as the 3 others. In this case, 10-20-10-10 would do the exact same effect. 1-1-1-1 would mean -all take 1/4 of the available space. Note that it is allowed to mix absolute widget sizes and proportions; -in this case, widgets with absolute size are evaluated first, and the dynamically-sized ones split the -remaining space according to their proportions. - -PROP_SQUARE "square_items" -Valid on Ribbons or RibbonGrids. Can be "true" (omitting it means "false"). Indicates whether the contents -use rectangular icons as opposed to "round" icons (this will affect the type of focus/highlighting used) - -PROP_EXTEND_LABEL "extend_label" -How many pixels the label is allowed to expand beyond the boundaries of the widget itself. Currently only -allowed on icon widgets. - -PROP_LABELS_LOCATION "label_location" -Currently only used by dynamic ribbons. Decides where the label is. Value can be "each", "bottom", or "none" -(if ommitted, "none" is the default). "each" means that every item has its own label. "bottom" means there -is a single label for all at the bottom, that displays the name of the current item. - -PROP_MAX_ROWS "max_rows" -Currently used for ribbon grids only. Indicates the maximum amount of rows this ribbon can have. - -+--------------------------+ -+ Using the Engine in Code + -+--------------------------+ - -The first thing to do is to derive a class of your own from AbstractStateManager. There are a few callbacks -you will need to override. Once it's done, you have all AbstractStateManager methods ready to be used to -push/pop/set menus on the screen stack. -Once you have instanciated your state manager class, call GUIEngine::init and pass it as argument. -One of the most important callbacks is 'eventCallback', which will be called everytime sometimes happens. -Events are generally a widget state change. In this case, a pointer to the said widget is passed along its -name, so you get its new state and/or act. There are two special events, passed with a NULL widget, and which -bear the anmes "init" and "tearDown", called respectively when a screen is being made visible and when it's -being left, allowing for setup/clean-up. - -*/ - #ifndef HEADER_ENGINE_HPP #define HEADER_ENGINE_HPP diff --git a/src/guiengine/screen_loader.cpp b/src/guiengine/screen_loader.cpp index 0ec9f775b..60e05b07e 100644 --- a/src/guiengine/screen_loader.cpp +++ b/src/guiengine/screen_loader.cpp @@ -166,7 +166,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = prop_name; else widget.m_ READ_PROPERTY(child_width, PROP_CHILD_WIDTH); READ_PROPERTY(child_height, PROP_CHILD_HEIGHT); READ_PROPERTY(word_wrap, PROP_WORD_WRAP); - READ_PROPERTY(grow_with_text, PROP_GROW_WITH_TEXT); + //READ_PROPERTY(grow_with_text, PROP_GROW_WITH_TEXT); READ_PROPERTY(x, PROP_X); READ_PROPERTY(y, PROP_Y); READ_PROPERTY(layout, PROP_LAYOUT); @@ -183,6 +183,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = prop_name; else widget.m_ READ_PROPERTY(extend_label, PROP_EXTEND_LABEL); READ_PROPERTY(label_location, PROP_LABELS_LOCATION); READ_PROPERTY(max_rows, PROP_MAX_ROWS); + READ_PROPERTY(warp_around, PROP_WARP_AROUND); #undef READ_PROPERTY const char* text = xml->getAttributeValue( "text" ); diff --git a/src/guiengine/widget.hpp b/src/guiengine/widget.hpp index 9a7213ad8..781ea645d 100644 --- a/src/guiengine/widget.hpp +++ b/src/guiengine/widget.hpp @@ -65,7 +65,7 @@ namespace GUIEngine PROP_CHILD_WIDTH, PROP_CHILD_HEIGHT, PROP_WORD_WRAP, - PROP_GROW_WITH_TEXT, // yet unused + //PROP_GROW_WITH_TEXT, // yet unused PROP_X, PROP_Y, PROP_LAYOUT, @@ -80,7 +80,8 @@ namespace GUIEngine PROP_SQUARE, PROP_EXTEND_LABEL, PROP_LABELS_LOCATION, - PROP_MAX_ROWS + PROP_MAX_ROWS, + PROP_WARP_AROUND }; bool isWithinATextBox(); @@ -127,12 +128,19 @@ namespace GUIEngine bool m_check_inside_me; /** - * called when left/right keys pressed and focus is on widget. + * called when right key is pressed and focus is on widget. * Returns 'EVENT_LET' if user's event handler should be notified of a change. * Override in children to be notified of left/right events and/or make * the event propagate to the user's event handler. */ virtual EventPropagation rightPressed(const int playerID) { return EVENT_BLOCK; } + + /** + * called when left key is pressed and focus is on widget. + * Returns 'EVENT_LET' if user's event handler should be notified of a change. + * Override in children to be notified of left/right events and/or make + * the event propagate to the user's event handler. + */ virtual EventPropagation leftPressed (const int playerID) { return EVENT_BLOCK; } /** used when you set eventSupervisors - see m_event_handler explainations below diff --git a/src/guiengine/widgets/spinner_widget.cpp b/src/guiengine/widgets/spinner_widget.cpp index 4b21c107a..8b0f45f1f 100644 --- a/src/guiengine/widgets/spinner_widget.cpp +++ b/src/guiengine/widgets/spinner_widget.cpp @@ -36,6 +36,7 @@ SpinnerWidget::SpinnerWidget(const bool gauge) : Widget(WTYPE_SPINNER) m_check_inside_me = true; //FIXME: not sure this is necessary m_supports_multiplayer = true; + } // ----------------------------------------------------------------------------- @@ -46,6 +47,9 @@ void SpinnerWidget::add() std::string min_s = m_properties[PROP_MIN_VALUE]; std::string max_s = m_properties[PROP_MAX_VALUE]; + m_warp_around = (m_properties[PROP_WARP_AROUND] == "true"); + std::cout << "SpinnerWidget::add() : m_warp_around=" << m_warp_around << " (" << m_properties[PROP_WARP_AROUND].c_str() << ")"<< std::endl; + { int i; std::istringstream myStream(min_s); @@ -195,7 +199,14 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID) if (m_deactivated) return EVENT_BLOCK; //std::cout << "Right pressed\n"; - if (m_value+1 <= m_max) setValue(m_value+1); + if (m_value+1 <= m_max) + { + setValue(m_value+1); + } + else if (m_warp_around) + { + setValue(m_min); + } //GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID ); @@ -210,7 +221,14 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID) if (m_deactivated) return EVENT_BLOCK; //std::cout << "Left pressed\n"; - if (m_value-1 >= m_min) setValue(m_value-1); + if (m_value-1 >= m_min) + { + setValue(m_value-1); + } + else if (m_warp_around) + { + setValue(m_max); + } //GUIEngine::transmitEvent( this, m_properties[PROP_ID], playerID ); diff --git a/src/guiengine/widgets/spinner_widget.hpp b/src/guiengine/widgets/spinner_widget.hpp index a177e27d0..4f0cf70ef 100644 --- a/src/guiengine/widgets/spinner_widget.hpp +++ b/src/guiengine/widgets/spinner_widget.hpp @@ -31,13 +31,30 @@ namespace GUIEngine class SpinnerWidget : public Widget { int m_value, m_min, m_max; + + /** If each value the spinner can take has an associated text, this vector will be non-empty */ std::vector m_labels; + + /** Whether the value of this spinner is displayed using an icon rather than with a plain label */ bool m_graphical; + + /** \brief Whether this widget is a gauge + * the behaviour is the same but the look is a bit different, instead of displaying a number, + * it displays how close the value is to the maximum by filling a line + */ bool m_gauge; - EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID); - EventPropagation rightPressed(const int playerID); - EventPropagation leftPressed(const int playerID); + /** \brief Whether to warp back to the first value when going "beyond" the last value */ + bool m_warp_around; + + /** \brief implementing method from base class Widget */ + virtual EventPropagation transmitEvent(Widget* w, std::string& originator, const int playerID); + + /** \brief implementing method from base class Widget */ + virtual EventPropagation rightPressed(const int playerID); + + /** \brief implementing method from base class Widget */ + virtual EventPropagation leftPressed(const int playerID); /** When inferring widget size from its label length, this method will be called to * if/how much space must be added to the raw label's size for the widget to be large enough */ @@ -58,19 +75,49 @@ namespace GUIEngine void addLabel(irr::core::stringw label); void clearLabels(); - irr::core::stringw getStringValue() const; + - void add(); - void setValue(const int new_value); + /** \brief implement method from base class Widget */ + virtual void add(); /** - * @precondition the 'new_value' string passed must be the name of an item in the spinner + * \brief sets the current value of the spinner + * \param new_value the new value that will be become the current value of this spinner. + */ + void setValue(const int new_value); + + /** + * \brief sets the current value of the spinner + * \precondition the 'new_value' string passed must be the name of an item + * (added through SpinnerWidget::addLabel)in the spinner */ void setValue(irr::core::stringw new_value); + /** + * \return whether this spinner is of "gauge" type + */ bool isGauge() const { return m_gauge; } + + /** + * \brief retrieve the current value of the spinner + * \return the current value of the spinner, in a int form + */ int getValue() const { return m_value; } + + /** + * \brief retrieve the current value of the spinner + * \return the current value of the spinner, in a string form + */ + irr::core::stringw getStringValue() const; + + /** + * \return the maximum value the spinner can take + */ int getMax() const { return m_max; } + + /** + * \return the minimum value the spinner can take + */ int getMin() const { return m_min; } }; diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp index 9acfb2f2b..4bb3bc965 100644 --- a/src/states_screens/kart_selection.cpp +++ b/src/states_screens/kart_selection.cpp @@ -269,6 +269,8 @@ public: playerName->m_properties[PROP_MIN_VALUE] = "0"; playerName->m_properties[PROP_MAX_VALUE] = (playerAmount-1); playerName->m_properties[PROP_ID] = spinnerID; + playerName->m_properties[PROP_WARP_AROUND] = "true"; + //playerName->m_event_handler = this; m_children.push_back(playerName);