{"id":19989638,"url":"https://github.com/wavesoft/marblebar","last_synced_at":"2025-07-28T09:08:02.448Z","repository":{"id":34846633,"uuid":"38839347","full_name":"wavesoft/marblebar","owner":"wavesoft","description":"A minimal footprint Web GUI for C++11 with a tiny embedded web server","archived":false,"fork":false,"pushed_at":"2015-07-23T12:23:14.000Z","size":488,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-01T20:02:12.246Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wavesoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-09T18:56:47.000Z","updated_at":"2016-01-14T15:41:12.000Z","dependencies_parsed_at":"2022-09-15T07:12:29.175Z","dependency_job_id":null,"html_url":"https://github.com/wavesoft/marblebar","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wavesoft/marblebar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wavesoft%2Fmarblebar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wavesoft%2Fmarblebar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wavesoft%2Fmarblebar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wavesoft%2Fmarblebar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wavesoft","download_url":"https://codeload.github.com/wavesoft/marblebar/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wavesoft%2Fmarblebar/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267489790,"owners_count":24095804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T04:48:46.340Z","updated_at":"2025-07-28T09:08:02.417Z","avatar_url":"https://github.com/wavesoft.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The MarbleBar GUI (Alpha)\n\nEver wanted a simple, quick, cross-platform GUI with no additional dependencies for your C++11 application? Was that UI mainly for providing some configuration or to see some results in real-time? Then say hello to MarbleBar!\n\nMarbleBar is a minimal footprint Web GUI library for C++11 with a tiny embedded web browser. I wrote this library because I wanted a cross-platform GUI without the need to drag along massive SDKs.\n\nThe concept is very simple: The library includes a tiny web server, it's static resources to serve and the core logic required in order to crate simple views. It comes complete, with Twitter Bootstrap for nice GUIs (offline of course), and a modular appropach on writing custom widgets.\n\nDon't expect to see something like [Wt](http://www.webtoolkit.eu/). Here there are no sessions, no complex widgets nor advanced lay-outing. As a trade-off to the simplicity you are given a single session (synchronised along all browser instances) and a property page-based layout. \n\n## Building\n\nMarbleBar is statically built along with your project. If you are using `CMake`, you can integrate it in your project like this:\n\n```cmake\n# Before you define your target:\nadd_subdirectory( \"/path/to/marblebar/sources\" marblebar )\ninclude_directories( ${MarbleBar_INCLUDE_DIRS} )\n\n# After you have defined your target:\ntarget_link_libraries( ${PROJECT_NAME} ${MarbleBar_LIBS} )\n```\n\nIf you are not using CMake, well... currently you are on your own. (But definitely, have a look at CMake, it could make our life way easier!)\n\n## Example\n\nUntil I come with a complete documentation, have a look on this example:\n\n```cpp\n#include \u003cmarblebar.hpp\u003e\n#include \u003ciostream\u003e\n#include \u003cthread\u003e\n\nusing namespace mb;\nusing namespace std;\n\nint main(int argc, char ** argv) {\n\n    // Create a MarbleBar Kernel\n    KernelPtr kernel = createKernel( defaultConfig() );\n\n    // Create our first view, titled 'Primary'\n    ViewPtr view = kernel-\u003ecreateView( \"Primary\" );\n\n    // Create a couple of properties\n    PStringPtr p1 = view-\u003eaddProperty( make_shared\u003cPString\u003e(\"Iterations\", \"value\") );\n    PStringPtr p2 = view-\u003eaddProperty( make_shared\u003cPString\u003e(\"Second Value\", \"value\") );\n    PBoolPtr p3 = view-\u003eaddProperty( make_shared\u003cPBool\u003e(\"Toggler\", false) );\n    PIntPtr p4 = view-\u003eaddProperty( make_shared\u003cPInt\u003e(\"Range\", 0) );\n    PImagePtr p5 = view-\u003eaddProperty( make_shared\u003cPImage\u003e(\"Preview\", 128, -1, \"about:blank\") );\n\n    // Most of the properies offer overloads that behave like\n    // a regular underlaying variable (ex. int, bool, string).\n    //\n    // Changes to these properties are instantly reflected in the UI\n    // and likewise, changes in the UI instantly affect the value of\n    // the properties.\n    //\n    *p1 = \"test\";\n    *p1 += \"ing\";\n\n    // Ask kernel to open the GUI (open system's web browser)\n    kernel-\u003eopenGUI();\n\n    // Start kerne's invinite loop\n    while (true) {\n\n        // .. Do your single-threaded work here ..\n\n        // Just remember to let kernel process it's I/O\n        kernel-\u003epoll();\n    }\n\n    // Optionally you might wish to start the kernel thread\n    // in a different thread, and to run it's start() method\n    thread kernelThread( \u0026mb::Kernel::start, marbleKernel );\n\n    return 0;\n};\n```\n\nAnd here is an example `CMakeLists.txt` file for building that sample project:\n\n```cmake\ncmake_minimum_required (VERSION 2.8)\nproject ( marblebar-example )\n# Include MarbleBar\nadd_subdirectory( \"/path/to/marblebar/sources\" marblebar )\ninclude_directories( ${MarbleBar_INCLUDE_DIRS} )\n# Compile Project (With C++11)\nadd_definitions(-std=c++11)\nadd_executable( ${PROJECT_NAME} example.cpp )\n# Link MarbleBar\ntarget_link_libraries( ${PROJECT_NAME} ${MarbleBar_LIBS} )\n```\n\n## Built-in properties\n\nThe following property types are currently provided by the MarbleBar GUI:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eClass\u003c/th\u003e\n        \u003ctd\u003eWidget\u003c/td\u003e\n        \u003cth\u003eInternal type\u003c/th\u003e\n        \u003cth\u003eDescription\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PBool\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003etoggle\u003c/td\u003e\n        \u003cth\u003ebool\u003c/th\u003e\n        \u003ctd\u003eA boolean property represented by a toggle-able push button\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PImage\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003eimage\u003c/td\u003e\n        \u003cth\u003estring\u003c/th\u003e\n        \u003ctd\u003eAn image field. The string value is the URL of the image. You can use the \u003ccode\u003esetBinary()\u003c/code\u003e method to define an image by it's contents.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PInt\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003eslider\u003c/td\u003e\n        \u003cth\u003eint\u003c/th\u003e\n        \u003ctd\u003eAn integer value that is selected by a slider.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PFloat\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003eslider\u003c/td\u003e\n        \u003cth\u003efloat\u003c/th\u003e\n        \u003ctd\u003eAn float value that is selected by a slider.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PDouble\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003eslider\u003c/td\u003e\n        \u003cth\u003edouble\u003c/th\u003e\n        \u003ctd\u003eAn double value that is selected by a slider.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PLabel\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003elabel\u003c/td\u003e\n        \u003cth\u003estring\u003c/th\u003e\n        \u003ctd\u003eA string value rendered with a non-editable text field.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003cth\u003e\u003ccode\u003emb::PString\u003c/code\u003e\u003c/th\u003e\n        \u003ctd\u003etext\u003c/td\u003e\n        \u003cth\u003estring\u003c/th\u003e\n        \u003ctd\u003eA string value rendered with an editable text field.\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n## Quick Terminology Intro\n\nFrom the C++ point of view, you are operating on view one or more `Property` objects in a `View`. This property is rendered in the javascript interface using a corresponding `Widget`. You can specify the widget in the property's specifications description. \n\nHave a look on the `PString::getUISpecs` method:\n\n```cpp\nJson::Value PString::getUISpecs()\n{\n    Json::Value data;\n    data[\"id\"] = id;\n    data[\"widget\"] = \"text\";    // You select your widget here\n    data[\"value\"] = value;\n    data[\"meta\"] = metadata;\n    return data;\n}\n```\n\nOn the javascript side, the `MarbleBar` GUI will expect to find the specified view in the `MarbleBar.Widgets` global object. Each widget should be a subclass of the `MarbleBar.Widget` global class.\n\nThere is a helper function that automatically does this subclassing and method overloading so you can only focus to the widget development. Have a look on the respective widget for the `PString` property:\n\n```javascript\nMarbleBar.Widgets['text'] = MarbleBar.Widget.create(\n    //\n    // First argument to the create function\n    // is the constructor function.\n    //\n    function( hostDOM, specs ) {\n        // Initialize widget\n        var id = MarbleBar.new_id();\n        this.label = $('\u003clabel class=\"col-sm-2 control-label\" for=\"'+id+'\"\u003e\u003c/label\u003e').text( specs['meta']['title'] ).appendTo( hostDOM );\n        this.input = $('\u003cinput class=\"form-control\" id=\"'+id+'\"\u003e\u003c/input\u003e').appendTo(\n            $('\u003cdiv class=\"col-sm-10\"\u003e\u003c/div\u003e').appendTo(hostDOM)\n        );\n        // Register updates\n        $(this.input).on(\"click blur keyup\", (function() {\n            // Trigger value update\n            this.trigger(\"update\", { \"value\": this.input.val() });\n        }).bind(this));\n    }, \n\n    //\n    // The second argument is an object\n    // with the additional functions to inject\n    // in the widget's prototype class.\n    //\n    {\n        // Update widget value\n        update: function(value) {\n            // Set to text field value\n            this.input.attr(\"value\", value);\n        }\n    }\n);\n``` \n\nThe `update` function is triggered when the property is changed by the C++ code. Respectively, the widget can trigger arbitrary events to the C++ code. In this case the `update` event updates the value of the property.\n\nYou can see how this event is handled in the `PString::handleUIEvent` function:\n\n```cpp\nvoid PString::handleUIEvent( const string \u0026 event, const Json::Value \u0026 data )\n{\n    if (event == \"update\") {\n        value = data[\"value\"].asString();\n        this-\u003emarkAsDirty();\n    }\n}\n```\n\nRemember to call the `Property::markAsDirty` function in order to propagate the changes to the other GUI instances.\n\n## License\n\nMarbleBar is licensed under GNU GPL Version 2.0, Open-Source license.\n\n```\nlibMarbleBar is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nlibMarbleBar is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with libMarbleBar. If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\nDeveloped by Ioannis Charalampidis 2015\nContact: \u003cioannis.charalampidis[at]cern.ch\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwavesoft%2Fmarblebar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwavesoft%2Fmarblebar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwavesoft%2Fmarblebar/lists"}