Be careful when pulling from this repository. It is in beta and the API may change frequently. As a result the documentation can be out of date.
This is a widget toolkit I created for my game engine. (I will also write implementations for all OpenGL versions)
The goals are to be
- Easily embeddable in game engines
- Have controller support without having to do a lot of work
- Easy to build and dependency free (mostly)
- Elegant
The goals are not
- To fit into the desktop environment
- Make widgets more customizable
- Add a "Style" class?
- Use nicer font rendering and text setting
- Software render font to bitmaps
- Add functionality for line breaks, following paths etc.
- Allow the canvas to draw bitmap fonts directly
- Implement the better attribute API
- Create a makro for the set function
- Make most widgets move assignable and move constructable
Button myButton = { myButtonParent, "button text", Padding(10, 10), Align(Right) }; myButton.set( Position{15, 15}, Text{"Live long and prosper"}, //< Note: this is a full widget Image{"spock.png"}, //< Note: this is a full widget []() { // On click puts("This isn't a high five."); } );
- Add controller support
- ? Text input ?
- Virtual keyboard as overlay?
- ? Text input ?
- Update documentation
- Create widget layouts
- Section (Collapsable widget)
- Table
- Create widgets
- Color picker
- File selector
- File browser
- Regex matching text field (Only allows content that matches the regex)
- Number field
- Make compatible with MSVC and properly export classes (dllexport etc.)
- Optionally integrate with the desktop environment for dialogues
- Add a software renderer
- Can be used for expensive graphics operations in another thread e.g.
- Data visualization (Audio waveforms etc.)
- High quality scaling
- Also can be used to create a software-only Canvas implementation
- Can be used for expensive graphics operations in another thread e.g.
- (Implement scripting? Probably lua?)
- Look forward to the C++ 2D graphics TS
- Make a Widgets smaller (as of writing a widget is 160 bytes large with clang, tendency growing)
- Use TinyString wherever possible
- Use packing where sensible
- Add partial redraws
- Add a different file loading backend (stb has some issues, esp. with jpegs)
- Focus somehow can't block clicks?
- List and WrappedList doesn't balance the remaining space between children with AlignFill
- WrappedList doesn't fill gaps
- Padding is sometimes ignored
- Where?
- Positions should be rounded
- Preferred size is rounded, the values should be integer in the first place
- Caveat 0: No. It is WIP and the documentation consists of lies. LIEEES I SAY!
- Caveat 1: It requires C++17 or higher
- Caveat 2: It uses RTTI, so that's that. Feel free to implement a fallback ;)
- Caveat 3: It uses some exceptions.
Mostly for:
- Errors while loading files
- Invalid operations and values (Adding a widget to itself, negative sizes etc.)
- When you use a function that is supposed to
- e.g.
Widget::find
throws an exception if a widget isn't found, in contrast toWidget::search
which returns anullptr
- e.g.
You can build it with premake5 or, preferably, integrate it with your own build system:
You just have to build all the source files in src/
and link with glfw3 and OpenGL.
You can build this library with (almost) full functionality without any dependencies! (See list preprocessor definitions)
e.g. to build the examples
git clone --depth 1 https://github.com/Cannedfood/WonkyWidgets.git
cd WonkyWidgets
c++ `find ./src/ -name *.cpp` `find ./example/ -name *.cpp` -lglfw -lGL -lstdc++fs -lpthread --std=c++17 -o example.bin
./example.bin
On arch-like systems you can also install the library with makepkg (as wwidgets)
cd /tmp
mkdir wwidgets-git
cd wwidgets-git
curl https://raw.githubusercontent.com/Cannedfood/WonkyWidgets/master/PKGBUILD > PKGBUILD
makepkg --noconfirm -i
cd ..
rm -Rf wwidgets-git
List of preprocessor definitions:
WIDGET_NO_WINDOWS
: Disable the Window class. (Also removes the dependency on glfw3 and OpenGL.)TODOWIDGET_CANVAS_NO_NANOVG
: Compile without nanovgTODOWIDGET_CANVAS_NANOVG_EXTERNAL_IMPLEMENATION
: Only link to nanovgTODOWIDGET_CANVAS_CAIRO
: Compile with cairo support (Uses cairo for windows)
You can find the "full" manual here
With C++ only (Objects on stack):
int main(int argc, const char** argv) {
using namespace wwidget;
Window window = {"MyTitle", 800, 600};
List layout = {window};
Button b1 = {layout, "Like"};
Button b2 = {layout, "Dislike", Padding(50, 50)};
}
With C++ only (Objects on heap, xml forms uses this):
int main(int argc, const char** argv) {
using namespace wwidget;
Window window = {"MyTitle", 800, 600};
List* layout = window.create<List>();
Button* b1 = layout.create<Button>("Shiat!");
Button* b2 = layout.create<Button>("Shiet!", Padding(50, 50));
}
With XML forms + C++:
<!-- In file Test.ui.xml -->
<form>
<window title="Window1" width='800', height='600'>
<list>
<button name='b1'>
Shiat!
</button>
<button name='b2' padding='50 50'>
Shiet!
</button>
</list>
</window>
</form>
int main(int argc, const char** argv) {
using namespace wwidget;
// Form is a widget that loads it's children from an xml file
Form form("Test.ui.xml");
// There are two functions to retrieve a widget:
// Widget::search and Widget::find.
// They have the same syntax, but Widget::find throws an exception when
// the widget isn't found
// When no name is specified, Widget::find searches for the first object
// safely castable to the specified type (via dynamic_cast).
Window* window = form.find<Window>();
List* list = window->find<List>();
//
Button* b1 = list->find<Button>("b1");
Button* b2 = list->find<Button>("b2");
}