Skip to content

Stalker2106x/MenuFramework

Repository files navigation

MenuFramework

Travis CI Coverage Status Coverity Status Codacy Badge Language grade: C/C++ Average time to resolve an issue

About

MenuFramework is a rich extendable XML menu engine with LUA integrated script engine (C++ exposition capabilities) It gives an easy way to add interactive interfaces to your program without hassle. Code is cross-platform, tested and compiled on Windows, Linux and MacOS !

Contributors

  • Stabax
  • Stalker2106

How to Build

Dependencies

  • CMake
  • Nlhomann's json
  • Pugixml
  • Lua
  • Sol2

You need to grab dependencies if they are not installed on your machine (which is probably the case), you can do so with the following command-line:

git submodule update --init --recursive

The project itself is based on CMake, which means you have to generate the build tools for it. You can generate Makefiles, Visual studio solutions, etc with the following commands (when at repository root)

mkdir build && cd build
cmake ..

That procedure should generate the correct build tools based on what your cmake is configured for. You can then just build the library (statically is preferred) and link against it! The library has been tested on C++14 compliant MinGW, GCC, and MSBuild.

Menu system

Getting started

The menu framework is component-driven, the core components are the GraphicsRenderer, and the InputManager. They allow to use any rendering system to render Menus, and any user input mechanism to interact with user interface.

Menu framework uses a specific XML markup for menu, which can be supplied either through C++ Strings, or Filesystem. A basic example of a program that shows a menu is the following:

  std::string menuDocument = "<Menu>"
                " <Text>Menu Example</Text>"
                " <Sep/>"
                " <Button Type='Intern' Target='alert(\"Stop pressing me!\")'>Press me!</Button>"
                " <Button Type='Intern' Target=''>Do nothing</Button>"
                "</Menu>";
Menu::init(); //Load library
Menu::goTo("", menuDocument, DataSource::Document);
Menu::run();

By default, the framework uses a NativeRenderer and NativeInput, which uses respectively system standard output and input (raw mode). If you want, you can provide implementation for both of them through the following methods:

static void Menu::setRenderer(std::shared_ptr<GraphicsRenderer> renderer);
static void Menu::setInputManager(std::shared_ptr<InputManager> inputmgr);

To do so, just create your own renderer and inputmanager, inherit from GraphicsRenderer and InputManager classes, and implement pure virtual functions. Examples can be found here

Menu XML elements

All of the following tag/attributes are writable in MenuFramework markup, and will generate the corresponding widget, based on the position in the hierarchy of the XML Document.

Tag Attribute Description
All Every element implements these attributes
Id Sets id of element for interaction in script
Menu Container for menu items
OnLoad scriptId to execute when creating menu
Text Non selectable entry of characters
Lang Substitutes the whole tag with the corresponding lang unit from locale file (Matching Ids)
Sep Non selectable horizontal separator
Button Clickable entry
Type Can be any of: { Intern, Goto, Script }
Target Source, function or scriptId to execute
Path Path where the source is located if extern
Input Field to input characters
Select Multi-value selector
Option Selectable value option for select
Value Sets value corresponding to text
Script Lua script. Can be defined outside of a menu to be called by Id, or inside Menu, will be called when parsed.
Alert Menu embedded alert message

Examples

This is an example of a basic menu that has a button "Print!" which when pressed trigger an alert saying "amazing":

<Menu Id="ExampleMenu">
  <Text>Example label</Text>
  <Sep/>
  <Button Type='Intern' Target='alert("amazing")'>Print!</Button>
</Menu>

an advanced menu example that shows text, two dropdowns with values using localization, buttons, alerts... :

<Menu Id="NewGame">
  <Text>Game Creation Menu</Text>
  <Select Text="Select difficulty">
    <Option Value="0"><Lang Id="difficulty.easy"/></Option>
    <Option Value="1"><Lang Id="difficulty.medium"/></Option>
  </Select>
  <Select Id="Locale" Text="Locale">
    <Option Value="en-US">en-US</Option>
    <Option Value="fr-FR">fr-FR</Option>
  </Select>
  <Input Id="Profile"><Lang Id="global.name"/></Input>
  <Button Type="Intern" Target='alert("ok")'>Create Profile</Button>
  <Button Type="Goto" Target="Home">Back</Button>
</Menu>

Script Engine (lua)

You may want to have custom behaviour inside your menus, thats why the framework implements its own script engine. The language of the script is lua, which allow very simple learning for easy customization, and exposes C++ Data easily (C++ binding is explained in next chapter)

Script C++ Binding

If you need to access/alter menu, or manipulate back-end data, the following lua functions are implemented and callable in any script:

Function Description
alert(string) add an alert with given string to current menu
tostring(int) converts given integer and returns it in string form
getCursor() returns integer position of cursor (Only hovereable items count)
getInputData(id) returns string contained in input of given string Id (id)
setInputData(id, value) sets string data (value) in input of given string Id (id)
getSelectValue(id) returns string data (value) of selected option in select of given string Id (id)
setSelectValue(id, value) sets option data (value) to select inside select of given string Id (id)
addMenuItem(pos, xml) add Item in menu at position (pos) with XML Data (xml)

Adding lua to your menus

This is an example of a menu implementing a script that prints a menu that lists items and allows to select one:

<Menu Id="Test" OnLoad="TestOnLoad">
  <Text>Select an item</Text>
  <Sep/>
  <!-- Items will be inserted here -->
  <Sep/>
  <Button Type="Intern" Target="exit()">Quit</Button>
</Menu>
<Script Id="TestOnLoad"><![CDATA[
  i = 0
  while (i < 5) do
    addMenuItem(2 + i, "<Button Type='Intern' Target='alert(\"selected: "..i.." !\")'>Item "..i.."</Button>")
    i = i + 1
  end
]]></Script>

Will output:

Select an item

Item 1
Item 2
Item 3
Item 4

Internationalization

By default, the menu framework does not uses the "locale" system. You can load any locale when starting the program, using the static "load" function in localization where langCode is the locale JSON file name.

Localization::load("en-US"); //Loads english locale

Now, the program will look inside the current working directory for a file named "./en-US.json", which will contains a JSON formatted translated units like so:

{
  "localization": "English",
  "data": {
    "any.key": "Translated value"
  }
}

You can change the folder where the localization looks for by altering the following variable

Localization::langLocation = "./my/localization/folder/";

You can insert "Localized" strings in your menus through the "Lang" XML element, which will be substitued by the corresponding text of lang Id in the locale file. If the langId has no translation, it will be shown as is. For example, the following menu will show the previous "any.key" defined unit.

<Menu>
  <Lang Id="any.key">
</Menu>

Styling

MenuFramework is highly customizable, every item element comes with a default style applied, but the whole system allow stylesheets to override default styles. These stylesheets are written in json, but use more or less CSS syntax. For instance, this is a valid stylesheet:

{
    "Text": {
        "margin-left": 10
    },
    "Separator": {
        "string": "-=-=-",
        "margin-top": 1,
        "margin-down": 1
    }
}

Styling attributes are grouped by Item, and are extendable, which means you can add your own as long as you handle them inside the renderer or through lua scripts. Any MenuItem can be overriden, just type their name as defined here. The following table shows the existing rules for styling:

Rule Value Description
color #FFFFFF set foreground (text) color of item
bgcolor #00FF00 set background color of item
string "-=-" set the character or string to be rendered for this item
margin-left margin-top margin-right margin-down 5 adds spaces for horizontal spacing, and lines to vertical
spacing 2 set the spacing (in space chars) between the label and the control
bracing-left bracing-right "<<" set the string to print at left of value bracing or element bracing

About

XML/Lua Text oriented Menu Framework with internationalization support

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages