├── .github
└── workflows
│ ├── msys2.yml
│ ├── ubuntu.yml
│ └── windows.yml
├── .gitignore
├── .gitmodules
├── 3rdparty
└── fa
│ ├── IconsFontAwesome6.h
│ ├── IconsMaterialDesign.h
│ ├── MaterialIcons-Regular.ttf
│ ├── Roboto-Bold.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ ├── fa-regular-400.ttf
│ └── fa-solid-900.ttf
├── CMakeLists.txt
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── cmake
├── fa.cmake
├── freetype.cmake
├── glfw.cmake
├── imgui.cmake
└── stb.cmake
├── doc
└── screen1.png
├── release-linux
├── src
├── CMakeLists.txt
├── app.rc
├── binding_eval.h
├── binding_input.h
├── binding_property.cpp
├── binding_property.h
├── binding_type.h
├── cpp_parser.h
├── cppgen.cpp
├── cppgen.h
├── glfw_cursor.h
├── icon.ico
├── icon.png
├── imrad.cpp
├── imrad.h
├── node_container.cpp
├── node_container.h
├── node_extra.cpp
├── node_extra.h
├── node_standard.cpp
├── node_standard.h
├── node_window.cpp
├── node_window.h
├── stx.h
├── ui_about_dlg.cpp
├── ui_about_dlg.h
├── ui_binding.cpp
├── ui_binding.h
├── ui_class_wizard.cpp
├── ui_class_wizard.h
├── ui_combo_dlg.cpp
├── ui_combo_dlg.h
├── ui_error_box.cpp
├── ui_error_box.h
├── ui_explorer.cpp
├── ui_explorer.h
├── ui_horiz_layout.cpp
├── ui_horiz_layout.h
├── ui_input_name.cpp
├── ui_input_name.h
├── ui_message_box.cpp
├── ui_message_box.h
├── ui_new_field.cpp
├── ui_new_field.h
├── ui_settings_dlg.cpp
├── ui_settings_dlg.h
├── ui_table_cols.cpp
├── ui_table_cols.h
├── uicontext.cpp
├── uicontext.h
├── utils.cpp
└── utils.h
├── style
├── dash.png
├── icon-100.png
├── icon-40.png
└── test.ini
└── template
├── android
├── AndroidManifest.xml
├── CMakeLists.txt
├── MainActivity.java
└── main.cpp
└── glfw
└── main.cpp
/.github/workflows/msys2.yml:
--------------------------------------------------------------------------------
1 | # This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
2 | # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
3 | name: msys2
4 |
5 | on:
6 | push:
7 | branches: [ "main" ]
8 | pull_request:
9 |
10 | env:
11 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
12 | BUILD_TYPE: Release
13 |
14 | jobs:
15 | build:
16 | strategy:
17 | matrix:
18 | platform: [windows-latest] # self-hosted
19 | sys: [ clang64, ucrt64, mingw32, mingw64 ] # clangarm64
20 |
21 | # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
22 | # You can convert this to a matrix build if you need cross-platform coverage.
23 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
24 | runs-on: ${{matrix.platform}}
25 |
26 | steps:
27 | - uses: actions/checkout@v4
28 | with:
29 | submodules: recursive
30 |
31 | - uses: msys2/setup-msys2@v2
32 | if: ${{ matrix.sys == 'clang32' || matrix.sys == 'clang64' || matrix.sys == 'ucrt64' }}
33 | with:
34 | msystem: ${{matrix.sys}}
35 | release: true
36 | pacboy: >-
37 | cmake:p
38 | clang:p
39 | ninja:p
40 |
41 | - uses: msys2/setup-msys2@v2
42 | if: ${{ matrix.sys == 'mingw32' || matrix.sys == 'mingw64' }}
43 | with:
44 | msystem: ${{matrix.sys}}
45 | release: true
46 | pacboy: >-
47 | cmake:p
48 | gcc:p
49 | ninja:p
50 |
51 | - name: Configure CMake
52 | shell: msys2 {0}
53 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
54 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
55 | run: cmake -B build_${{matrix.sys}}_${{env.BUILD_TYPE}} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
56 |
57 | - name: Build
58 | shell: msys2 {0}
59 | # Build your program with the given configuration
60 | run: cmake --build build_${{matrix.sys}}_${{env.BUILD_TYPE}} --config ${{env.BUILD_TYPE}}
61 |
62 | - name: Test
63 | shell: msys2 {0}
64 | working-directory: build_${{matrix.sys}}_${{env.BUILD_TYPE}}
65 | # Execute tests defined by the CMake configuration.
66 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
67 | run: ctest -C ${{env.BUILD_TYPE}}
68 |
69 |
--------------------------------------------------------------------------------
/.github/workflows/ubuntu.yml:
--------------------------------------------------------------------------------
1 | name: ubuntu
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | workflow_dispatch:
8 |
9 | env:
10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
11 | BUILD_TYPE: Release
12 |
13 | jobs:
14 | build:
15 | # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
16 | # You can convert this to a matrix build if you need cross-platform coverage.
17 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
18 | runs-on: ubuntu-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v3
22 | with:
23 | submodules: recursive
24 |
25 | - name: apt install
26 | run: |
27 | sudo apt update
28 | sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libgtk-3-dev libsystemd-dev libwebp-dev libzstd-dev
29 |
30 |
31 | - name: Configure CMake
32 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
33 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
34 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
35 |
36 | - name: Build
37 | # Build your program with the given configuration
38 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel 8
39 |
40 | - name: Test
41 | working-directory: ${{github.workspace}}/build
42 | # Execute tests defined by the CMake configuration.
43 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
44 | run: ctest -C ${{env.BUILD_TYPE}}
45 |
46 |
--------------------------------------------------------------------------------
/.github/workflows/windows.yml:
--------------------------------------------------------------------------------
1 | # This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
2 | # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
3 | name: windows
4 |
5 | on:
6 | push:
7 | branches: [ "main" ]
8 | pull_request:
9 |
10 | env:
11 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
12 | BUILD_TYPE: Release
13 |
14 | jobs:
15 | build:
16 | # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
17 | # You can convert this to a matrix build if you need cross-platform coverage.
18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
19 | runs-on: windows-latest
20 |
21 | steps:
22 | - uses: actions/checkout@v4
23 | with:
24 | submodules: recursive
25 |
26 | - name: Configure CMake
27 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
28 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
29 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
30 |
31 | - name: Build
32 | # Build your program with the given configuration
33 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
34 |
35 | - name: Test
36 | working-directory: ${{github.workspace}}/build
37 | # Execute tests defined by the CMake configuration.
38 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
39 | run: ctest -C ${{env.BUILD_TYPE}}
40 |
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /install/
3 | /build-2022/
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "3rdparty/glfw"]
2 | path = 3rdparty/glfw
3 | url = https://github.com/glfw/glfw.git
4 | branch = master
5 | [submodule "3rdparty/imgui"]
6 | path = 3rdparty/imgui
7 | url = https://github.com/ocornut/imgui.git
8 | branch = docking
9 | [submodule "3rdparty/stb"]
10 | path = 3rdparty/stb
11 | url = https://github.com/nothings/stb.git
12 | branch = master
13 | [submodule "3rdparty/nativefiledialog"]
14 | path = 3rdparty/nativefiledialog
15 | url = https://github.com/btzy/nativefiledialog-extended.git
16 | branch = master
17 | [submodule "3rdparty/freetype"]
18 | path = 3rdparty/freetype
19 | url = https://github.com/freetype/freetype.git
20 |
--------------------------------------------------------------------------------
/3rdparty/fa/MaterialIcons-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/MaterialIcons-Regular.ttf
--------------------------------------------------------------------------------
/3rdparty/fa/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/3rdparty/fa/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/3rdparty/fa/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/3rdparty/fa/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/fa-regular-400.ttf
--------------------------------------------------------------------------------
/3rdparty/fa/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/3rdparty/fa/fa-solid-900.ttf
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10)
2 | project(imrad)
3 |
4 | set(CMAKE_CXX_STANDARD 17)
5 | set(CMAKE_CXX_VISIBILITY_PRESET hidden) # linux: don't export all symbols in .so
6 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) # linux: use -fPIC on .a so they can be used by .so
7 |
8 | # make use of runtime directory
9 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
10 |
11 | set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/latest")
12 |
13 | if(MSVC)
14 | add_definitions(-D_CRT_SECURE_NO_WARNINGS)
15 | add_definitions(-D_SCL_SECURE_NO_WARNINGS)
16 | add_definitions(-D_USE_MATH_DEFINES)
17 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
19 | else()
20 | add_definitions(-DGL_SILENCE_DEPRECATION=1)
21 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer")
22 | # Disable ASAN on Debug builds as it may cause issues on arm64
23 | # If you are getting DEADLY ADDRESS error use: sudo sysctl vm.mmap_rnd_bits=28
24 | # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address")
25 | if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
26 | find_library(MISC_FRAMEWORKS UniformTypeIdentifiers)
27 | set(CMAKE_OSX_ARCHITECTURES "arm64")
28 | elseif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux")
29 | find_package(PkgConfig REQUIRED)
30 | pkg_check_modules(MISC REQUIRED gtk+-3.0 glib-2.0)
31 | set(MISC_FRAMEWORKS "${MISC_STATIC_LIBRARIES}")
32 | endif()
33 | endif()
34 |
35 | # before includes
36 | install(
37 | DIRECTORY "template/"
38 | DESTINATION "template"
39 | )
40 | install(
41 | DIRECTORY "style/"
42 | DESTINATION "style"
43 | )
44 |
45 | include(cmake/glfw.cmake)
46 | include(cmake/imgui.cmake)
47 | include(cmake/fa.cmake)
48 | include(cmake/stb.cmake)
49 | include(cmake/freetype.cmake)
50 |
51 | include(ExternalProject)
52 | set(NFD_PREFIX 3rdparty/nativefiledialog)
53 | set(NFD_BUILD_TESTS OFF)
54 | ExternalProject_Add(nativefiledialog
55 | PREFIX ${NFD_PREFIX}
56 | SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${NFD_PREFIX}
57 | INSTALL_COMMAND ""
58 | CMAKE_CACHE_ARGS
59 | -DCMAKE_OSX_ARCHITECTURES:STRING=arm64
60 | )
61 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/${NFD_PREFIX}/src/include)
62 | link_directories(${CMAKE_CURRENT_BINARY_DIR}/${NFD_PREFIX}/src/nativefiledialog-build/src/)
63 |
64 | add_subdirectory(src)
65 |
66 | file(COPY
67 | "${CMAKE_CURRENT_SOURCE_DIR}/template"
68 | DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/bin"
69 | )
70 | file(COPY
71 | "${CMAKE_CURRENT_SOURCE_DIR}/style"
72 | DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/bin"
73 | )
74 |
75 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | TLDR: The expected, merge into main, reference issues in PRs.
2 |
3 | ## Documentation
4 |
5 | Out of source (non-inline) documentation such as design diagrams should be added to the `docs` folder as should images for readmes or anything else that is not within the `docs` folder.
6 |
7 | ## Code
8 | All source code should be in C++ following best practices guidelines where possible (such as avoiding `new` and `delete`).
9 | Indentation should be done with spaces not tabs and a trailing new line should be added to the end of each file (this makes the diffs cleaner).
10 |
11 |
12 |
13 |
14 | ## PRs
15 |
16 | PRs should have a base branch of (and merge into) main with no merge conflicts. Please keep your branch as up to date as possible.
17 |
18 | Your PR should include the issue number (e.g. "closes #1234"), there is no need to do so in commit messages.
19 |
20 | ## Code of Conduct
21 | Our code of conduct is "be kind to eachother" unless otherwise stated.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 |
5 | # ImRAD
6 |
7 |

8 |
9 |
10 |
11 | ImRAD is a GUI builder for the ImGui library. It generates and parses C++ code which can be directly used in your application.
12 |
13 | Unlike other tools ImRAD can be used for continuous modification of the generated UI. Data binding, events and even manual
14 | UI code additions are well supported.
15 |
16 | ImRAD runs on Windows, Linux and MacOS.
17 |
18 |
19 |
20 | 
21 |
22 | *Take a note of the Toolbar section:*
23 | * *Configurable window style which is stored in an INI file. It contains definitions of colors, style variables and fonts. The example uses stock "Dark" style*
24 | * *Dialog units option which can also be set to DPI aware pixels useful when designing android apps*
25 | * *Code Preview for quick checks. Full generated code is saved in .h/cpp files*
26 | * *Class wizard allows to manage member variables of the generated class*
27 | * *Horizontal layout helper using invisible table. This is an alternative to the box layout functionality.*
28 |
29 | *Designed window shows:*
30 | * *Stretchable spacer between "Available fields" text and "show all" checkbox and between dialog buttons. ImRAD comes with box layout support not available in standard ImGui*
31 | * *Negative size_x/y support which makes the table widget expand vertically keeping 48px gap from the bottom edge of the dialog*
32 | * *Selectable widget bindings such as `{vars[i].first}`. Bind expressions will be put in the generated code showing content of the `vars` array*
33 |
34 | *Properties window contains:*
35 | * *Table.rowCount binding set to the `vars.size()` expression. This will generate code with a for loop over table rows. One-way or two-way binding is supported by most properties*
36 |
37 | *Events window*
38 | * *Allows to generate handlers for all kinds of events such as button click, window appearance, input text character filter etc.*
39 |
40 | # Main Features
41 |
42 | * Supports designing all kinds of windows
43 | * Floating windows, popups and modal popups. These are ImGui backend independent
44 | * MainWindow with GLFW integration. ImRAD generates GLFW calls which will synchronize ImGui window with its OS window (title bar, resizability flags, autosize etc.)
45 | * Activity. This is an undecorated window which fills the entire viewport area. Only one activity can be shown at the time. Used mainly for Android apps
46 | * contains a GLFW template for generating generic `main.cpp`
47 | * contains an android template for generating generic `MainActivity.java`, `AndroidManifest.xml`, `main.cpp` and `CMakeLists.txt`
48 |
49 | * Supports wide range of widgets
50 |
51 | * basic widgets like `Text`, `Checkbox`, `Combo`, `Button`, `Slider`, `ColorEdit` etc.
52 | * container widgets like `Child`, `Table`, `CollapsingHeader`, `TreeNode`, `TabBar`,
53 | * more exotic widgets such as `Splitter` and `DockSpace`
54 | * `MenuBar` and context menu editing
55 | * `CustomWidget` (a placeholder to user code)
56 |
57 | * Generates layout using `SameLine`/`Spacing`/`NextColumn` instead of absolute positioning
58 |
59 | * this ensures widgets respect item spacing and frame padding in a consistent way
60 | * there is a clear relationship between parent - child widget as well as children ordering which is important for container widgets like Table
61 | * alternative positioning where widget keeps relative distance from a selected parent's corner is available and can be used for overlay widgets
62 |
63 | * Supports box layout
64 |
65 | * powerful and simple to use layout mechanism implemented on top of ImGui functionality
66 | * stretch any sizeable widget in horizontal or vertical direction
67 | * insert spacers to achieve alignment
68 | * alternatively you can use Table Layout Helper to generate horizontal layout using invisible Table
69 |
70 | * Supports property binding
71 |
72 | * because ImGui is an immediate mode GUI library widget state like input text or combobox items must be set at the time of drawing from within the generated code through property binding.
73 | * class variables can be managed through simple class wizard or from binding dialog
74 | * using property binding generated UI becomes dynamic and yet it can still be designed at the same time
75 |
76 | * Supports generating event handlers and other support code
77 |
78 | * for example modal dialog will automatically generate an `OpenPopup` member function with a lambda callback called when the dialog is closed
79 | * event handlers allow event handling user code to be separated from the generated part so the designer still works
80 |
81 | * Generated code is delimited by comment markers and user can insert additional code around and continue to use ImRAD at the same time
82 |
83 | * this can be used to f.e. to call draw dependent popups or to calculate some variables
84 | * it is also possible to use `CustomWidget` which will delegate to a user callback
85 |
86 | * Target window style is fully configurable
87 | * apart from default styles provided by ImGui user can define new style and save it as an INI file under the `style` folder. Colors, style variables and used fonts can all be configured.
88 | * ImRAD will follow chosen style settings when designing your UI
89 | * stored style can be loaded in your app by using `LoadStyle` call
90 |
91 | * Generated code is ready to use in your project and depends only on ImGui library and one accompanying header file (imrad.h)
92 |
93 | * some features such as MainWindow or Image widget require GLFW dependency. Compile your code with `IMRAD_WITH_GLFW` to activate it
94 | * currently Image widget requires stb library as well. Compile your code with `IMRAD_WITH_STB` or supply your own `LoadTextureFromFile()`
95 | * in generated code `ImRad::Format` delegates to `std::format` by default but when requested popular `fmt` library can be used instead by defining `IMRAD_WITH_FMT`. If neither is available simple formatting routine which skips formatting flags will be used.
96 |
97 | * ImRAD tracks changes to the opened files so files can be designed in ImRAD and edited in your IDE of choice at the same time
98 |
99 | # License
100 |
101 | * ImRAD source code is licensed under the GPL license
102 | * Any code generated by the tool is excluded from GPL and can be included in any project either open-source or commercial and it's up to the user to decide the license for it.
103 | * Additionally since `imrad.h` is used by the generated code it is also excluded from the GPL license
104 |
105 | # Download binaries
106 |
107 | For up-to date version clone & build the repository using CMake. Don't forget to fetch submodules in the 3rdparty directory too.
108 |
109 | Somewhat older version can be downloaded from [Releases](https://github.com/tpecholt/imrad/releases)
110 |
111 | # How to build
112 |
113 | ## Windows
114 | 1. Use CMake GUI to configure and generate sln file
115 | 2. Open the generated sln file in Visual Studio 2017 or newer (you can use Express or Community editions which are downloadable for free)
116 | 3. Build the INSTALL project in Release mode. It may require running VS with admin rights
117 | 4. If you didn't alter CMAKE_INSTALL_PREFIX variable ImRAD will be installed into *C:\Program Files\imrad\latest*
118 |
119 | ## Linux, MacOS
120 | 1. *Ubuntu*: Due to the GTK FileOpen dialog dependency you need to `apt install` these packages first (exact list depends on your OS):
121 |
122 | *pkg-config gtk-3-dev libsystemd-dev libwebp-dev libzstd-dev*
123 |
124 | 3. Run the provided installation script (script parameter is the ImRAD version you want to name the folder)
125 |
126 | ```./release-linux 0.8```
127 |
128 | 4. ImRAD will be installed into *./install/imrad-0.8*
129 |
130 | # How to debug
131 |
132 | ## Windows
133 |
134 | 1. Build the INSTALL target in VS as described above
135 | 2. Set imrad as startup project, set its working directory to the installed folder
136 | 3. Debug & Run
137 |
138 | # How to use generated code
139 |
140 | * Create a new project (C++17 and up)
141 |
142 | * Based on your setup set project-wide preprocessor defines `IMRAD_WITH_GLFW`/`IMRAD_WITH_STB`/ (`STBI_WINDOWS_UTF8`). This activates additional functionality such as Main Window or Image widget.
143 |
144 | * On MSVC you need to define `/Zc:__cplusplus` as well otherwise C++ version detection in imrad.h won't work.
145 |
146 | * Add all generated code. Generated code #includes `imrad.h` so you need to set an include directory and point it to the include folder in the ImRAD installation folder.
147 |
148 | * Add your `main.cpp`. The easiest way is to auto-generate it from ImRAD (New File menu). Then call `Draw()` methods of all generated UI classes from your UI loop.
149 |
150 | * If you supply your own `main.cpp` or the one downloadable from ImGui github repository make sure you define `ImRad::IOUserData` variable and pass it to `ImGui::GetIO().UserData`. This structure is to exchange various information such as current dpi scaling, active InputText IME type or reduced display size dimensions for android apps.
151 |
152 | * Finally add ImGui and GLFW dependencies. Whether you build it as separate libraries or directly add to your project is up to you. Stb and fmt dependencies are optional.
153 |
154 | # Tutorials
155 |
156 | Please check [wiki](https://github.com/tpecholt/imrad/wiki) for tutorials and more detailed content. There is a lot to discover!
157 |
158 | # Sponsorship
159 |
160 | Development of ImRAD happens in my free time outside of my regular job, yoga, badminton, volunteering and other activities.
161 |
162 | If you like the tool and want to support its further development please do. If you use it regularly you can even setup a monthly donation if it's convenient for you.
163 |
164 | [](https://ko-fi.com/tope99)
165 |
166 | # Credits
167 |
168 | Design and implementation - [Tomas Pecholt](https://github.com/tpecholt)
169 |
170 | Thanks to [Omar Cornut for Dear ImGui](https://github.com/ocornut/imgui)
171 |
--------------------------------------------------------------------------------
/cmake/fa.cmake:
--------------------------------------------------------------------------------
1 | set(FA_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/fa)
2 |
3 | add_library(fa INTERFACE)
4 |
5 | target_include_directories(fa
6 | INTERFACE
7 | ${FA_INCLUDE_DIR})
8 |
9 | install(FILES
10 | "${FA_INCLUDE_DIR}/fa-solid-900.ttf"
11 | "${FA_INCLUDE_DIR}/fa-regular-400.ttf"
12 | "${FA_INCLUDE_DIR}/MaterialIcons-Regular.ttf"
13 | "${FA_INCLUDE_DIR}/Roboto-Medium.ttf"
14 | "${FA_INCLUDE_DIR}/Roboto-Regular.ttf"
15 | "${FA_INCLUDE_DIR}/Roboto-Bold.ttf"
16 | DESTINATION "style/")
--------------------------------------------------------------------------------
/cmake/freetype.cmake:
--------------------------------------------------------------------------------
1 | option(FT_DISABLE_BROTLI ON)
2 | option(FT_DISABLE_BZIP2 ON)
3 | option(FT_DISABLE_HARFBUZZ ON)
4 | option(FT_DISABLE_PNG ON)
5 | option(FT_DISABLE_ZLIB ON)
6 |
7 | # Force arm64 on macOS
8 | if(APPLE)
9 | set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Build architectures for macOS" FORCE)
10 | endif()
11 |
12 | add_subdirectory(${CMAKE_SOURCE_DIR}/3rdparty/freetype EXCLUDE_FROM_ALL)
13 |
--------------------------------------------------------------------------------
/cmake/glfw.cmake:
--------------------------------------------------------------------------------
1 | option(GLFW_BUILD_DOCS OFF)
2 | option(GLFW_BUILD_EXAMPLES OFF)
3 | option(GLFW_BUILD_TESTS OFF)
4 | option(GLFW_INSTALL OFF)
5 | add_subdirectory(${CMAKE_SOURCE_DIR}/3rdparty/glfw)
6 |
7 | set(GLFW_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/glfw/include)
8 | set(GLFW_DEFINITIONS -DGLFW_INCLUDE_NONE)
9 |
--------------------------------------------------------------------------------
/cmake/imgui.cmake:
--------------------------------------------------------------------------------
1 | set(IMGUI_DIR ${CMAKE_SOURCE_DIR}/3rdparty/imgui)
2 | file(GLOB IMGUI_SOURCES ${IMGUI_DIR}/*.cpp)
3 | file(GLOB IMGUI_MISC ${IMGUI_DIR}/misc/cpp/*.cpp)
4 | file(GLOB IMGUI_FT ${IMGUI_DIR}/misc/freetype/*.cpp)
5 | file(GLOB IMGUI_HEADERS ${IMGUI_DIR}/*.h)
6 |
7 | add_library(imgui STATIC
8 | ${IMGUI_SOURCES}
9 | ${IMGUI_HEADERS}
10 | ${IMGUI_MISC}
11 | ${IMGUI_FT}
12 | ${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp
13 | ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
14 | )
15 |
16 | #add_definitions(-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS)
17 | add_definitions(-DIMGUI_ENABLE_FREETYPE)
18 | #add_definitions(-DIMGUI_USE_WCHAR32)
19 |
20 | include_directories(
21 | ${IMGUI_DIR}
22 | ${OPENGL_INCLUDE_DIR}
23 | ${GLFW_INCLUDE_DIR})
24 |
25 | target_link_libraries(imgui
26 | freetype
27 | ${OPENGL_LIBRARIES}
28 | ${GLFW_LIBRARIES})
29 |
30 | set_target_properties(imgui PROPERTIES LINKER_LANGUAGE CXX)
31 |
32 | #add_custom_command(TARGET imgui POST_BUILD
33 | # COMMAND ${CMAKE_COMMAND} -E copy
34 | # "${IMGUI_DIR}/misc/fonts/Roboto-Medium.ttf"
35 | # "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$/style/"
36 | #)
37 |
--------------------------------------------------------------------------------
/cmake/stb.cmake:
--------------------------------------------------------------------------------
1 | set(STB_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/stb)
2 |
3 | add_library(stb INTERFACE)
4 |
5 | target_include_directories(stb
6 | INTERFACE
7 | ${STB_INCLUDE_DIR})
8 |
--------------------------------------------------------------------------------
/doc/screen1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tpecholt/imrad/e4a8f66438c7182f7c6f334c3c6865c68b0a8cb5/doc/screen1.png
--------------------------------------------------------------------------------
/release-linux:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | if [ "$#" -ne 1 ]; then
3 | echo "please specify release version"
4 | exit 1
5 | fi
6 |
7 | rm -rf install
8 | rm -rf build
9 | mkdir install
10 | mkdir build
11 | cd build
12 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install ..
13 | make -j8 install
14 | if [ "$?" -ne 0 ]; then
15 | exit 1
16 | fi
17 | cd ../install
18 | mv latest imrad-$1
19 | zip -r imrad-$1-linux64.zip .
20 |
21 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project (imrad)
2 |
3 | file(GLOB_RECURSE SRC "*.cpp" "*.h")
4 |
5 | if (WIN32)
6 | set(SRC ${SRC} "app.rc")
7 | endif()
8 |
9 | if (MSVC)
10 | string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus")
11 | string(APPEND CMAKE_CXX_FLAGS " /utf-8")
12 | endif()
13 |
14 | add_executable(imrad WIN32
15 | ${SRC}
16 | )
17 |
18 | set(OpenGL_GL_PREFERENCE "GLVND")
19 | find_package(OpenGL REQUIRED)
20 |
21 | add_definitions(-DIMRAD_WITH_GLFW)
22 | add_definitions(-DIMRAD_WITH_STB)
23 | add_definitions(-DSTBI_WINDOWS_UTF8)
24 |
25 | target_link_libraries(imrad
26 | fa
27 | glfw
28 | imgui
29 | nfd
30 | stb
31 | ${OPENGL_LIBRARIES}
32 | ${CMAKE_DL_LIBS}
33 | ${MISC_FRAMEWORKS}
34 | )
35 |
36 | add_dependencies(imrad nativefiledialog)
37 |
38 | install(FILES "imrad.h" DESTINATION "include/")
39 | install(TARGETS imrad DESTINATION ".")
40 |
--------------------------------------------------------------------------------
/src/app.rc:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON DISCARDABLE "icon.ico"
--------------------------------------------------------------------------------
/src/binding_eval.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "binding_property.h"
3 | #include "cppgen.h"
4 |
5 | template
6 | T bindable::eval(const UIContext& ctx) const {
7 | if (empty())
8 | return {};
9 | if (has_value())
10 | return value();
11 | const auto *var = ctx.codeGen->GetVar(str);
12 | if (var) {
13 | T val;
14 | std::istringstream is(var->init);
15 | if (is >> std::boolalpha >> val)
16 | return val;
17 | }
18 | return {};
19 | }
20 |
21 | template
22 | T field_ref::eval(const UIContext &ctx) const
23 | {
24 | if (empty())
25 | return {};
26 | const auto *var = ctx.codeGen->GetVar(str);
27 | if (!var)
28 | return {};
29 | T val;
30 | std::istringstream is(var->init);
31 | if (is >> std::boolalpha >> val)
32 | return val;
33 | return {};
34 | }
35 |
--------------------------------------------------------------------------------
/src/binding_property.cpp:
--------------------------------------------------------------------------------
1 | #include "binding_property.h"
2 | #include "cppgen.h"
3 | #include
4 |
5 | float direct_val::eval_px(const UIContext& ctx) const
6 | {
7 | return val * ctx.zoomFactor;
8 | }
9 |
10 | float direct_val::eval_px(const UIContext& ctx) const
11 | {
12 | return val * ctx.zoomFactor;
13 | }
14 |
15 | ImVec2 direct_val::eval_px(const UIContext& ctx) const
16 | {
17 | return { val[0] * ctx.zoomFactor, val[1] * ctx.zoomFactor };
18 | }
19 |
20 | float bindable::eval_px(int axis, const UIContext& ctx) const
21 | {
22 | if (empty()) {
23 | return 0;
24 | }
25 | else if (stretched()) {
26 | return ctx.stretchSize[axis];
27 | }
28 | else if (has_value()) {
29 | return value() * ctx.zoomFactor;
30 | }
31 | else if (const auto* var = ctx.codeGen->GetVar(str)) {
32 | float val;
33 | std::istringstream is(var->init);
34 | if (is >> val)
35 | return val * ctx.zoomFactor;
36 | else
37 | return 0;
38 | }
39 | else {
40 | //experimental - currently parses:
41 | //num*dp
42 | //cond ? num1*dp : num2*dp
43 | //extracts min value as that may be the preferrable one when some widgets show/hide
44 | //e.g. -1 vs -20 or 20 vs 50
45 | std::istringstream is(str);
46 | int state = 1; //0 - skip, 1 - number, 2 - *, 3 - dp
47 | float val = 0, ret = 0;
48 | for (cpp::token_iterator it(is), ite; it != ite; ++it) {
49 | if (*it == "?") {
50 | state = 1;
51 | }
52 | else if (*it == ":") {
53 | if (state >= 2)
54 | ret = std::min(ret ? ret : 1e9f, val);
55 | state = 1;
56 | }
57 | else if (state == 1) {
58 | std::istringstream iss(*it);
59 | if (iss >> val)
60 | state = 2;
61 | else
62 | state = 0;
63 | }
64 | else if (state == 2) {
65 | if (*it == "*")
66 | state = 3;
67 | else
68 | state = 0;
69 | }
70 | else if (state == 3) {
71 | if (*it != "dp")
72 | state = 0;
73 | }
74 | }
75 | if (state >= 2)
76 | ret = std::min(ret ? ret : 1e9f, val);
77 | return ret * ctx.zoomFactor;
78 | }
79 | }
80 |
81 | ImU32 bindable::eval(int defClr, const UIContext& ctx) const
82 | {
83 | if (empty()) //default color
84 | return ImGui::ColorConvertFloat4ToU32(ctx.style.Colors[defClr]);
85 |
86 | int idx = style_color();
87 | if (idx >= 0)
88 | return ImGui::ColorConvertFloat4ToU32(ctx.style.Colors[idx]);
89 |
90 | ImU32 clr;
91 | std::istringstream is(str);
92 | if (is.get() == '0' && is.get() == 'x' && is >> std::hex >> clr)
93 | return clr;
94 |
95 | return ImGui::ColorConvertFloat4ToU32(ctx.style.Colors[defClr]);
96 | }
97 |
98 | std::string bindable::eval(const UIContext&) const
99 | {
100 | if (!has_value())
101 | return "";
102 | return str.substr(22, str.size() - 22 - 2);
103 | }
104 |
--------------------------------------------------------------------------------
/src/binding_type.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #ifndef WIN32
6 | #include
7 | #endif
8 |
9 | //negative values allowed
10 | struct dimension_t {};
11 |
12 | //positive or zero dimension (so that neg values represent empty value)
13 | struct pzdimension_t {};
14 |
15 | struct pzdimension2_t {};
16 |
17 | struct font_name_t {};
18 |
19 | struct shortcut_t {};
20 |
21 | struct color_t {};
22 |
23 | //------------------------------------------------------------------
24 |
25 | template
26 | struct typeid_func_name;
27 |
28 | template
29 | std::string typeid_name()
30 | {
31 | if constexpr (std::is_const_v)
32 | return "const " + typeid_name>();
33 | else if constexpr (std::is_pointer_v)
34 | return typeid_name>() + "*";
35 | else if constexpr (std::is_lvalue_reference_v)
36 | return typeid_name>() + "&";
37 | else if constexpr (std::is_rvalue_reference_v)
38 | return typeid_name>() + "&&";
39 | else if constexpr (std::is_function_v)
40 | return typeid_func_name::str();
41 |
42 | else if constexpr (std::is_same_v)
43 | return "void";
44 | else if constexpr (std::is_same_v)
45 | return "std::string";
46 | else if constexpr (std::is_same_v)
47 | return "color4";
48 | else if constexpr (std::is_same_v)
49 | return "float";
50 | else if constexpr (std::is_same_v)
51 | return "int";
52 | else if constexpr (std::is_same_v)
53 | return "float";
54 | else if constexpr (std::is_same_v)
55 | return "double";
56 | else if constexpr (std::is_same_v)
57 | return "size_t";
58 | else if constexpr (std::is_same_v)
59 | return "bool";
60 | else if constexpr (std::is_same_v || std::is_same_v)
61 | return "ImVec2";
62 | else if constexpr (std::is_same_v)
63 | return "ImFont*";
64 | else if constexpr (std::is_same_v>)
65 | return "std::vector";
66 | else
67 | {
68 | std::string str = typeid(T).name();
69 | #ifdef WIN32
70 | auto i = str.find(' ');
71 | if (i != std::string::npos)
72 | str.erase(0, i + 1); //erase leading struct etc.
73 | #else
74 | int status;
75 | char* ptr = abi::__cxa_demangle(str.c_str(), nullptr, nullptr, &status);
76 | str = ptr;
77 | free(ptr);
78 | #endif
79 | return str;
80 | }
81 | }
82 |
83 |
84 | template
85 | struct typeid_func_name
86 | {
87 | static std::string str()
88 | {
89 | return typeid_name() + "()";
90 | }
91 | };
92 |
93 | template
94 | struct typeid_func_name
95 | {
96 | static std::string str()
97 | {
98 | return typeid_name() + "(" + typeid_name() + ")";
99 | }
100 | };
101 |
--------------------------------------------------------------------------------
/src/cppgen.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include