vurtun / nuklear Goto Github PK
View Code? Open in Web Editor NEWA single-header ANSI C gui library
A single-header ANSI C gui library
I noticed that widgets can be placed in a layout in the panel, but is there an option to add widgets at an x, y location? (and to specify width and height) Like sort of a null layout.
Can this feature be added? (or does it already exist?)
Thanks!
I have found a small glitch in zr_user_font_glyphs_fitting_in_space. It is easy to run into an endless loop, since glyph_len can get zero and there is no test for that in:
while ((width <= space) && text_len) {
I guess it should read:
while ((width <= space) && text_en && glyph_len) {
Another problem can occur if offset is not getting incremented and the function therefore returns 0. This will result in an endless loop for example in zr_widget_edit_box.
Really great work!
Cheers, richi
Hey, I have the following code currently running:
#include "Utilities/Themis.h" #define MEMORY_SIZE (64 * 1024) using namespace std; Themis *main_controller; zr_style style; zr_user_font font; zr_command_queue queue; zr_window window; enum {EASY, HARD}; zr_size option; zr_float value; struct zr_input input; MouseInfo temp; static zr_size font_get_text_width(zr_handle handle, const zr_char *t, zr_size l) { return main_controller->graphics_handle->getStringLength(t, l); } int main(int argc, char **argv) { main_controller = new Themis(); main_controller->Init(argc, argv); //initializes everything for you //Frame frame(main_controller, 50, 50, 220, 180); font.userdata.ptr = this; font.height = 10; font.width = font_get_text_width; zr_style_default(&style, ZR_DEFAULT_ALL, &font); /* allocate memory to hold draw commands */ zr_command_queue_init_fixed(&queue, malloc(MEMORY_SIZE), MEMORY_SIZE); /* initialize window */ zr_window_init(&window, zr_rect(50, 50, 220, 180), ZR_WINDOW_BORDER, &queue, &style, &input); /* setup widget data */ option = EASY; value = 0.6f; temp.x.data = 0; temp.y.data = 0; while (true) { //frame.handle_input(); zr_input_begin(&input); // record input /* if (main_controller->mouseInfo.button.data == 0) { zr_input_button(&input, ZR_BUTTON_LEFT, main_controller->mouseInfo.x.data, main_controller->mouseInfo.y.data, zr_true); } else { zr_input_button(&input, ZR_BUTTON_LEFT, main_controller->mouseInfo.x.data, main_controller->mouseInfo.y.data, zr_false); } if (main_controller->mouseInfo.x.data != temp.x.data || main_controller->mouseInfo.y.data != temp.y.data) { zr_input_motion(&input, temp.x.data, temp.y.data); temp.x.data = main_controller->mouseInfo.x.data; temp.y.data = main_controller->mouseInfo.y.data; } if (main_controller->keyboardInfo.c != 0 && main_controller->keyboardInfo.state.data != 0) zr_input_char(&input, main_controller->keyboardInfo.c); else if (main_controller->keyboardInfo.code.data == 14) if (main_controller->keyboardInfo.state.data != 0) zr_input_key(&input, ZR_KEY_BACKSPACE, zr_true); else zr_input_key(&input, ZR_KEY_BACKSPACE, zr_false); */ zr_input_end(&input); //frame.construct(); zr_context context; zr_begin(&context, &window); const char *items[] = {"Fist", "Pistol", "Railgun", "BFG"}; zr_header(&context, "Show", 0, 0, ZR_HEADER_LEFT); /* zr_layout_row_static(&context, 30, 80, 1); if (zr_button_text(&context, "button", ZR_BUTTON_DEFAULT)) { // event handling } zr_layout_row_dynamic(&context, 30, 2); if (zr_option(&context, "easy", option == EASY)) option = EASY; if (zr_option(&context, "hard", option == HARD)) option = HARD; zr_layout_row_begin(&context, ZR_STATIC, 30, 2); { zr_layout_row_push(&context, 50); zr_label(&context, "Volume:", ZR_TEXT_LEFT); zr_layout_row_push(&context, 110); value = zr_slider(&context, 0, value, 1.0f, 0.1f); } zr_layout_row_end(&context); */ zr_end(&context, &window); //frame.draw(); while (!main_controller->render) {} main_controller->graphics_handle->SetPriority(0); //just a formality, doesn't do anything considering the entire array is filled with -1 fill_n(main_controller->graphics_handle->buffer_i, main_controller->screen_width.data * main_controller->screen_height.data, -1); const struct zr_command *cmd; Integer colorC; main_controller->graphics_handle->SetPriority(2); zr_foreach_command(cmd, &queue) { switch (cmd->type) { case ZR_COMMAND_SCISSOR: { const struct zr_command_scissor *s = zr_command(scissor, cmd); main_controller->graphics_handle->setClip(s->x, s->y, s->w, s->h); break; } case ZR_COMMAND_LINE: { const struct zr_command_line *l = zr_command(line, cmd); colorC.bytes[3] = 2; // setting priority colorC.bytes[0] = l->color.r; colorC.bytes[1] = l->color.g; colorC.bytes[2] = l->color.b; main_controller->graphics_handle->drawLine(l->begin.x, l->begin.y, l->end.x, l->end.y, colorC.data); break; } case ZR_COMMAND_RECT: { const struct zr_command_rect *r = zr_command(rect, cmd); colorC.bytes[3] = 2; // setting priority colorC.bytes[0] = r->color.r; colorC.bytes[1] = r->color.g; colorC.bytes[2] = r->color.b; main_controller->graphics_handle->fillSquare(r->x, r->y, r->w, r->h, colorC.data); break; } case ZR_COMMAND_CIRCLE: { const struct zr_command_circle *c = zr_command(circle, cmd); colorC.bytes[3] = 2; // setting priority colorC.bytes[0] = c->color.r; colorC.bytes[1] = c->color.g; colorC.bytes[2] = c->color.b; main_controller->graphics_handle->fillCircle(c->x + (c->w / 2), c->y + (c->w / 2), c->w / 2, colorC.data); break; } case ZR_COMMAND_TRIANGLE: { const struct zr_command_triangle *t = zr_command(triangle, cmd); colorC.bytes[3] = 2; // setting priority colorC.bytes[0] = t->color.r; colorC.bytes[1] = t->color.g; colorC.bytes[2] = t->color.b; Polygon tri; tri.addPoint(t->a.x, t->a.y); tri.addPoint(t->b.x, t->b.y); tri.addPoint(t->c.x, t->c.y); main_controller->graphics_handle->fillPolygon(tri, colorC.data); break; } case ZR_COMMAND_TEXT: { const struct zr_command_text *t = zr_command(text, cmd); main_controller->graphics_handle->drawString(t->string, t->x, t->y + 10, _WHITE); break; } } } main_controller->graphics_handle->setClip(-1, -1, -1, -1); main_controller->render = false; cout << "drew" << endl; } return 0; }
Please make a note that most of the code is commented out. I have been looking through all of my code and I can't find anything wrong with it. Anyways the error here is that the window shows up for a very temporary time and then disappears. However the program itself does not crash. It's almost as if the algorithm just stops generating squares and such to generate. If you get a chance could you please take a look? I originally thought maybe the window was closing but closing is set to 0 in the header and input isn't even being processed. Thanks!
Hey! Thanks as always for fixing these issues so quickly. I've got a few more for you.
scroll.w = scroll.w;
scroll.x = scroll.x;
Were you trying to do something else?
void clipboard_set(const char text){UNUSED(text);}
zr_bool clipboard_is_filled(void){return zr_false;}
const char clipboard_get(void) {return NULL;}
I've found it doesn't compile without this (at least on Windows).
bool flag = false;
if (mouse.clicked_on_Scrollbar()) { flag = true; }
if (flag && mouse.unclicked) { flag = false; }
if (flag) {
//scroll scroll bar distance mouse has moved in the y direction regardless of x
scrollbar.scroll(mouse.prev_x - mouse.curr_x);
}
Anyways thanks for reading and I look forward to an update!
Please don't consider this as nitpicking. I would just like Zahnrad to be the best imgui written in C with stable API.
Except for few spelling mistakes in the documentation (which is not a big deal - I want to issue a pull request during the next 7 days and as I'm not a native speaker, I'll definitely unintentionally skip some typos), I'm more concerned about ones in the API - e.g. functions containing glyphes
should rather contain glyphs
(some internal structures and variables contain this typo as well). In addition, today I found modifyable
-> modifiable
.
I am right now toying around building an interface for iOS and Android and potentially other touch screen devices. Getting a rough port up running on iOS was pretty easy, thanks to the clean structure of zahnrad. I have discovered only one major show stopper and this is the mouse pointer centric approach. On a touch screen there is no concept of hovering for example. And most widgets (those that do not involve dragging) do fire on touch up and not down.
As a workaround I am sending a motion event right before a touch down.
zr_clear(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_motion(&gui.ctx, location.x, location.y);
zr_input_end(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_button(&gui.ctx, b, location.x, location.y, zr_true);
zr_input_end(&gui.ctx);
run_demo(&gui);
and again a motion event right after a touch up
zr_clear(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_button(&gui.ctx, b, location.x, location.y, zr_false);
zr_input_end(&gui.ctx);
zr_input_begin(&gui.ctx);
zr_input_motion(&gui.ctx, 0, 0);
zr_input_end(&gui.ctx);
run_demo(&gui);
This does work surprisingly well, but of course feels quite hackish and does not solve the touch up vs. down issue.
Another issue is the hit test. On a touch screen it is rather difficult to hit small widgets and the solution usually is to extend the hit area virtually to at least 40 x 40 pixel.
I see a huge potential for zahnrad on touch devices.
What do you think?
Cheers, richi
Just cloned the latest revision and I'm getting these on the GLFW/SDL files:
clang -std=c99 -pedantic -O2 -o bin/node_editor node_editor.c -lglfw3 -lopengl32 -lm -lGLU32 -lGLEW32
In file included from node_editor.c:36:
./../nuklear.h:11384:5: error: use of undeclared identifier 'pad'
pad.x = style->padding.x + style->border;
^
./../nuklear.h:11385:5: error: use of undeclared identifier 'pad'
pad.y = style->padding.y + style->border;
^
2 errors generated.
Makefile:16: recipe for target 'node_editor' failed
make: *** [node_editor] Error 1
Hey! There are some errors when compiling the library right now in c++. Here are the errors:
Frame.cpp:(.text+0x1fc): undefined reference to zr_label' /tmp/ccJldMxt.o: In function
zr_tooltip':
zahnrad.c:(.text+0x311c7): undefined reference to `zr_text'
collect2: error: ld returned 1 exit status
Also your demo is off as well, should be zr_panel as opposed to zr_layout.
Thanks!
The demo Makefile tries to use "MakefileDebug" which doesn't exist. There is a "Makefile" for each platform rather than a "MakefileDebug" file.
Would it be possible to add a zr_canvas_clear()
to the very beginning of zr_convert()
?
This would give the ability to run zr_draw_foreach()
as a kind of 3rd level cache without always running the ui code first. Another option would be to simply make zr_canvas_clear() public.
I ran the "make.bat" file (in the win32 demo section) using the "Developer Command Prompt for VS2015" using administrator privileges, but encountered two errors in the win32.c
win32.c(404): error C2065: 'zr_float': undeclared identifier
win32.c(404): error C2146: syntax error: missing ';' before identifier 'xw'
It fails to create the executable in the bin folder
[Visual studio 2015, Windows 10]
Right now, compiling with Clang LLVM in 32 or 64 bit gives some minor type issues.
ZR_COMPILE_WITH_FIXED_TYPES 1
ILP32: zr__check_size
failed.
LP64:
a lot of warnings (demo.c) because size_t* ('unsigned long * ') is incompatible to zr_size* ('unsigned long long *'). (stupid compiler...)
changing:
typedef uint64_t zr_size;
to:
typedef uintptr_t zr_size;
would solve 32 and 64 bit issues.
ZR_COMPILE_WITH_FIXED_TYPES 0
ILP32:
zr__check_ulong
failed.
LP64:
No problems.
changing:
typedef unsigned long zr_ulong;
to:
typedef unsigned long long zr_ulong;
would solve 32 bit issues, without generating 64 bit ones :)
Cheers, richi
I have a menu item that is supposed to make a window focused (basically it's a window menu that will list all the open windows)
I am trying to achieve a sort of MDI interface and I want to use the Window menu to regain focus on windows that are on the background, so when I click Window->Demo Window
I'm doing zr_window_set_focus(ctx, "Demo Window"); but nothing really happens.
I also logged zr_window_has_focus on the Demo Window and it prints 1 so I don't really know what's going on.
Hey! So do you think you'll have copy and paste functionality built into this soon?
Thank you so much for all the time you are putting into this by the way!
Add support for multiple pointing cursors (in text, two cursors are enough - think of mobile devices). It's getting more and more common, that the user has more pointing devices - such az touchpad, trackpoint, external mouse, eye gaze, gamepad, etc.
Is there any simple way to scale the whole UI in a "vector" way (i.e. not scaling the resulting bitmap, but every single part of the UI separately in a consistent way)? I found just several scaling options, but only for some containers (e.g. panel).
Without scaling, the whole UI is currently not suitable for many deployments (high-res displays of wildly varying sizes - e.g. 5" mobile devices having higher resolution than my 15.4" notebook display).
Also, the sizes differ in the pixel shapes etc., so a separate scaling factor for x and y would be much better than just one common scaling factor.
In most interfaces, menus are left aligned, in zahnrad they are centered and it looks a bit weird.
I added my own method that makes the menu alignment configurable here:
libretro/RetroArch@1b1b596
Should I make a pull request or do you have a better idea than duplicating code like this?
Yesterday i wrote a few lines of code to test your library, I've updated the code, and well It no longer compiles.GUI_PANEL_CLOSEABLE GUI_PANEL_MINIMIZABLE were gone. gui_panel_begin had different arguments.
Is the library in a rapid development stage, or I am doing something wrong?
Hi vurtun. You just direct messaged me (Krakenrad2) on twitter about using github to contact you.
I'll be brief:
-Right now I'm drawing my GUI to the SDL surface of my window (rendering text, bitmap buttons, mouse events, etc...)
-I would rather use zahnrad but the examples in the demo folder are very long.
-A simple tutorial on making the simple example below work in SDL would be good.
-I could make one, but I'm guessing it requires much more code to make it work with SDL.
Could you give me some general advice about what I should focus on to make the example below work in SDL?
Thanks.
/* init gui state */
struct zr_context ctx;
zr_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
enum {EASY, HARD};
int op = EASY;
float value = 0.6f;
int i = 20;
struct zr_layout layout;
zr_begin(&ctx, &layout, "Show", zr_rect(50, 50, 220, 220),
ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_CLOSEABLE);
{
/* fixed widget pixel width /
zr_layout_row_static(&ctx, 30, 80, 1);
if (zr_button_text(&ctx, "button", ZR_BUTTON_DEFAULT)) {
/ event handling */
}
/* fixed widget window ratio width */
zr_layout_row_dynamic(&ctx, 30, 2);
if (zr_option(&ctx, "easy", op == EASY)) op = EASY;
if (zr_option(&ctx, "hard", op == HARD)) op = HARD;
/* custom widget pixel width */
zr_layout_row_begin(&ctx, ZR_STATIC, 30, 2);
{
zr_layout_row_push(&ctx, 50);
zr_label(&ctx, "Volume:", ZR_TEXT_LEFT);
zr_layout_row_push(&ctx, 110);
zr_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
}
zr_layout_row_end(&ctx);
}
zr_end(ctx);
Imagine you want to control certain aspects of the backend renderer from inside the UI. Right now it is rather difficult to get any kind user data down to the draw loop.
Would it be possible to append a zr_handle user_data
to struct zr_context
, struct zr_draw_command
and struct zr_command
. The handling could be similar to zr_set_font
.
With zr_set_user_data(struct zr_context*,zr_handle user_data);
one would set the user data in the context and this data would get passed down to zr_foreach
or zr_draw_foreach
through struct zr_command
and struct zr_draw_command
.
Until zr_set_user_data
is called again, always the same user data should end up in the draw loops.
RetroArch tries to use C89 whenever is possible too, like zahnrad itself.
When testing a C89 build we got the following error:
zahnrad.c:10772:30: error: ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]
Might be something you want to look at since you're striving for C89 compatibility
Hey
First of all, thanks a lot for this toolkit, it's great, I've been looking for a cross platform gui toolkit for a while and this fits the bill correctly and this one does.
I'm implementing zahnrad in RetroArch as a new menu driver (retroarch is a sort of multi system emulator and we have several menu drivers but we don't have a traditional mouse + kb driver).
Now I made a basic implementation on our menu driver and I'm wondering, is it possible to navigate the controls with keyboard only or a gamepad? maybe assign an ID to each control and have a selected property that highlights the selected widget? reacting to the click keyevent should be doable already but I'm not sure about the navigation.
If you move a button (or any other widget with centered text) out of the left side of the screen, x will get negative and the "center" calculation will give wrong results.
zr_widget_text, line ~3808
label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x)/2));
if (label.x >= label.w/2) label.x -= (label.w/2);
replacing those two lines with:
label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
might (maybe) solve the problem?
Hey! I was looking through the OpenGL example and its not entirely clear to me how exactly I change fonts during runtime. Could you show me how to do this?
I think this would be better for a forum since I don't think it's really an issue, just a difference, but it's the only place were I can ask so here it is.
I have noticed some subtle differences in the GLFW and Allegro samples, I was wondering if it was possible to have a similar end result on GL (Allegro looks better, sharper in my opinion but opinions are subjective)
Check the uppercase E in node editor
It's very subtle but the colors look better and the fonts look better too.
We're using this for RetroArch as I mentioned before and I felt the text was a bit blurry.
I'll start creating new issues for you :)
Anyways I'd like to also get the functionality to remove/add the minimize button on windows as well as program in exactly what happens when these buttons are clicked. Also I noticed that occasionally clicking on the status bar at the top of the window will close the window (even though I'm pretty sure I'm not clicking on the X).
Thanks!
Hey! There is an issue with Spaces on the Windows demo code. It looks like it adds two spaces whenever I hit the space bar once.
Shouldn't the zr_tooltip_end()
call be rather only in case some tooltip was created? In
/* execute tooltip and fill with text */
if (zr_tooltip_begin(ctx, &layout, (float)text_width)) {
zr_layout_row_dynamic(ctx, (float)text_height, 1);
zr_text(ctx, text, text_len, ZR_TEXT_LEFT);
}
zr_tooltip_end(ctx);
it seems to be quite dagerous. Solution might look like the following:
/* execute tooltip and fill with text */
if (zr_tooltip_begin(ctx, &layout, (float)text_width)) {
zr_layout_row_dynamic(ctx, (float)text_height, 1);
zr_text(ctx, text, text_len, ZR_TEXT_LEFT);
zr_tooltip_end(ctx);
}
I didn't check other similar places, but it's worth taking a careful look at.
Currently the first use of demos might discourage new users, because they will notice CPU rendering is utterly slow on low-power machines (e.g. Raspberry Pi series). I'm proposing using -O2
by default (because gcc uses -O0
by default).
MacOS demos build failing with:
demo.c:32:10: fatal error: 'GL/glew.h' file not found
#include <GL/glew.h>
Compilation fails under VS2013, there are a lot of errors, primarily typecasts.
It seems chart
would be more suitable instead of graph
for API (zr_graph_type, ZR_GRAPH_LINES, ZR_GRAPH_COLUMN, ZR_GRAPH_MAX, zr_graph_event, ZR_GRAPH_HOVERING, ZR_GRAPH_CLICKED, etc.) as the API has nothing to do neither with mathematical graphs nor with graph data structures. Even though nowadays these terms are used sometimes interchangeably, graph is ambiguous and it's usage in a UI library is misleading (not even mentioning the scenario when using Zahnrad for graph visualization).
Just for reference:
https://en.wikipedia.org/wiki/Graph
https://en.wikipedia.org/wiki/Chart
https://en.wikipedia.org/wiki/Wikipedia:Graphs_and_charts
As some may know I added the functionality to record
UI and replay
it at a later point of time some time ago. The main premise is that since the recorded UI is fixed allows for a lot more control like the ability to check if the UI needs to redrawn or even a lot more widget depended information. Internally this is achieved by serializing function call and parameter into a buffer that later can be executed again. State changes are signaled in contrast to the typical immediate mode API by using events while also providing an API to change the serialized widget state. So in the end not much is lost while a lot is achieved.
So far this would already allow things like an editor comparable to Qt but more powerful since dynamic widgets like combo boxes, charts or any highly dynamic UI code which are tedious to work with in classic retain mode APIs could be generated by recording or using the immediate mode API. So in theory this alone could be a huge win.
I thought about it a little more and I noticed that the step between just serializing widgets and a custom script language is not far fetched. I am not talking about bindings to other languages which can already be done, but something more aligned to shader languages in graphics APIs. The basic idea would be that the language (If it even could called that since it probably does not have to be turing complete) would call different widget just like you would with the default immediate mode API (which will still be usable like before) but would generate custom events as output (since you cannot directly access your program). So far example this script:
Script (pseudo code):
event changed_mouse_sensitivity {
float value;
}
event mouse_sensitivity_greater_two {
float value;
}
void main()
{
s = slider("mouse_sensitivity", 0, 5, 10);
if (s.isModified()) {
event changed_mouse_sensitivity evt;
evt.value = s.value;
generateEvent(evt);
}
if (s.value > 2) {
event mouse_sensitivity_greater_two evt;
evt.value = s.value;
generateEvent(evt);
}
}
Native code:
/* register custom event types here */
zr_exec(...); /* run 'script' */
/* first way to check for changes */
zr_foreach_event(....) {
if (evt.type == CUSTOM_EVENT_CHANGE_MOUSE_SENSITIVITY) {
/* handle mouse sensitivity change */
}
}
/* second way to access and check for UI changes directly */
zr_element mouse_sensitivity = zr_lookup_string(program, "mouse_sensitivity");
if (zr_element_is_modified(mouse_sensitivity)) {
/* handle mouse sensitivity change */
zr_element_clear_modified(mouse_sensitivity);
}
So in script you would create a slider and check if the current slider value is greater than two and would generate a custom event if so. So in your native code you wouldn't have to check for each slider if it has been modified but instead you would only listen to custom events. It would be especially helpful for button events. In addition you could also access the widget by handle and check for changes directly as well. While this script could have logic like I described it could also just define each widget as data (used by editors) like so (still pseudo code):
begin("Demo")
layout_row_dynamic(30, 2);
slider("mouse_sensitivity", 0, 0.5, 1.0);
button("ok_button", "ok");
end()
So this would look more like the bytecode generated currently by recording
and would just use default events for clicking, hovering, etc but could be extended by modifying the generated editor textual output to have custom events.
What I described up to this point would stand as three different APIs that would support each other. First the default immediate mode API which is the base for and runs everything. Then above that would be UI recording which allows to use the immediate mode API to turn dynamic frame based UI to a fixed bytecode UI script and with that more control and information and finally the bytecode script layer.
These three could be used interchangeably.
So for example you have an UI which means in most cases that most of its layout is quite fixed and is not required to change a lot but you still update and redraw it every frame. Instead you could turn that into script and run that from data.
Lets extend the use case and say your UI has a combo box which needs to be filled at the beginning of the program. In classical retain mode APIs you would have to fill a data structure and pass that to the combo box which is quite tedious for more advanced changes like removing and in using the immediate mode API you would have to call and redraw the combo box every frame.
Now in this case the recording API would become handy since it would generate the combo box for you at the beginning of the program and could then be combined with the fixed UI script.
Finally lets extend it a third time and say we have some highly dynamic data used for charts. In this case we would use the immediate mode API.
This is basically the high level idea I had. There are of course a lot of problem related to this like how to extend the script language with custom widgets, the best way to combine recorded and normal script, what script language with what syntax, what control statements should the language support, etc.
So finally I want to head to my question. I personally don't have much experience with languages I wrote an emulators once so I know a little bit how to write bytecode but I have no experience about if what I described could be or even should be done by using a script language. I suspect no since what the language would actually do is very limited it is barley more than just data. For example it wouldn't need functions or probably even variables and is therefore quite simple. I know for example that bitcoin uses a very basic interpreter for something related and I will take another look into that.
So for my question I would ask if what I am thinking about even made sense or is just over engineered bullshit that could be done by using a script language, should it even be done? or should the library stay simple and if it is worth it then if it should be done by only using bytecode inside the library and provide a way to generate the bytecode outside the library or since the language is so simple would even make sense to actually implement everything inside the library?
So in general feedback would be appreciated.
Hey! So I was using "zr_layout_row_space_begin" and "...end" today and I noticed that the scroll bar that is added is incorrect. I want to add like a sub-section in the window where the scroll bar is in the middle of the window. I'm trying to add lots of data to the window but I don't want the entire window to scroll down I just want a certain portion of it it (hopefully that makes sense).
As usual thanks for the support!
Hey! Just wanted to list here some issues with your sample code:
"zr_combo(&context, items, LEN(items), &item, 20, &active);"
zr_combo isn't a function.
"zr_window_init(&window, 50, 50, 220, 180,
ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE,
&queue, &style, &input);"
This function actually requires a "zr_rect"
Just wanted to mention these! Thanks for all your hard work here.
Don't know if this is a bug per-se or some error in my implementation, I tried to reproduce on the demos a lot and only managed once to get a click to register.
Basically it seems that resizing a window causes some unintended clics on some elements when you hover over them (or the place were the elements would be after resizing.
May be related to this other issue? #54
I'll revert this
win->flags &= ~(zr_flags)ZR_WINDOW_ROM
In my code and do some more testing
Probably the last code-related thing I'm concerned with is the use of Zahnrad in multi-threaded applications, because some functions still contain non-const variables which are static (zr_draw_list_path_arc_to_fast()
, zr_font_japanese_glyph_range()
, zr_style_property()
, zr_style_color()
). It would be better to add them to some external state structure and/or to API.
I receive the following error when compiling when I set ZR_COMPILE_WITH_VERTEX_BUFFER and
ZR_COMPILE_WITH_FONT to zero:
"/opt/lib/GUI/zahnrad.c: In function ‘zr_uint zr_color32(zr_color)’:
/opt/lib/GUI/zahnrad.c:363:20: error: ‘zr_draw_vertex_color’ was not declared in this scope
/opt/lib/GUI/zahnrad.c:363:41: error: expected ‘,’ or ‘;’ before ‘in’
/opt/lib/GUI/zahnrad.c:364:35: error: expected ‘)’ before ‘in’
/opt/lib/GUI/zahnrad.c:365:35: error: expected ‘)’ before ‘in’
/opt/lib/GUI/zahnrad.c:366:35: error: expected ‘)’ before ‘in’"
On our project we will have several windows, settings, dialogs, etc.
Right now I have a sort of main function that controls everything:
static void zrmenu_frame(struct zrmenu *gui, int width, int height)
{
struct zr_context *ctx = &gui->ctx;
zrmenu_wnd_control(ctx, width, height, gui);
zrmenu_wnd_main(ctx, width, height, gui);
zrmenu_wnd_demo(ctx, width, height, gui);
zr_buffer_info(&gui->status, &gui->ctx.memory);
}
Actually opening a window later is not a problem, for instance I added a button to open wnd_control and then in my function I did this
static void zrmenu_frame(struct zrmenu *gui, int width, int height)
{
struct zr_context *ctx = &gui->ctx;
if (wnd_control)
zrmenu_wnd_control(ctx, width, height, gui);
zrmenu_wnd_main(ctx, width, height, gui);
zrmenu_wnd_demo(ctx, width, height, gui);
zr_buffer_info(&gui->status, &gui->ctx.memory);
}
But after closing it and opening it several times the gui got somewhat stuck.
Now I'm just drawing the window offscreen which "works" but I would assume doing this would waste memory and CPU resources.
Is there a correct way to handle this?
ZR_POOL_DEFAULT_CAPACTIY
-> ZR_POOL_DEFAULT_CAPACITY
(I could not write it directly to the line using GitHub line comments feature, because the commit diff was huge and GitHub didn't show it)
Clicking an item on a window that is out of focus doesn't produce any result.
While that might be ok, there is no hint that the window is indeed out of focus so it feels a bit odd.
I see two ways to solve this:
Hey, I have many questions/comments about your sample code under the README. (this is all c++)
If a minimized window is on top of another one, the maximize button (as well as the close button) won't work. Probably because of:
if (!(layout->flags & ZR_WINDOW_ROM)) {
In zr_header_button.
If a maximized window is on top of another one and the minimize button is clicked, this window gets send to the background in the next run after releasing the mouse button with zr_input_button.
Cheers, richi
Hi,
First of all I congratulate you on your innovative work. While I was looking for a gui toolkit apart from gtk, I found your project. I am impressed with the introductory animations. I wanted to try it.
I downloaded the zip package and exracted it in ~/Downloads folder. I navigated to ../zahnrad-master/demo/linuxgl
and opened command prompt and run make
Here is the output
kenn@kenn:~/Downloads/zahnrad-master/zahnrad-master/demo/linuxgl$ make
rm -f bin/zahnrad
gcc linuxgl.c ../../zahnrad.c -std=c89 -pedantic -O2 -o bin/zahnrad -lX11 -lm -lGL -lm -lGLU
In file included from linuxgl.c:31:0:
../demo.c: In function ‘show_test_window’:
../demo.c:145:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&menu, &prog, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:292:9: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&menu, &prog, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:480:13: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&layout, &prog_value, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:582:13: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘size_t’ [-Wformat=]
sprintf(buffer, "%lu", sum);
^
../demo.c:586:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&combo, &x, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:587:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&combo, &y, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:588:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&combo, &z, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:589:17: warning: passing argument 2 of ‘zr_progress’ from incompatible pointer type [enabled by default]
zr_progress(&combo, &w, 100, ZR_MODIFIABLE);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2894:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable);
^
In file included from linuxgl.c:31:0:
../demo.c:595:13: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘size_t’ [-Wformat=]
sprintf(buffer, "%lu", sum);
^
../demo.c:644:27: warning: assignment from incompatible pointer type [enabled by default]
clip.copy = copy_callback;
^
../demo.c:652:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[0], &text_len[0], 64, &text_active[0], &text_cursor[0], ZR_INPUT_DEFAULT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:652:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[0], &text_len[0], 64, &text_active[0], &text_cursor[0], ZR_INPUT_DEFAULT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:654:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[1], &text_len[1], 64, &text_active[1], &text_cursor[1], ZR_INPUT_DEC);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:654:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[1], &text_len[1], 64, &text_active[1], &text_cursor[1], ZR_INPUT_DEC);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:656:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[2], &text_len[2], 64, &text_active[2], &text_cursor[2], ZR_INPUT_FLOAT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:656:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[2], &text_len[2], 64, &text_active[2], &text_cursor[2], ZR_INPUT_FLOAT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:658:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[4], &text_len[4], 64, &text_active[4], &text_cursor[4], ZR_INPUT_HEX);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:658:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[4], &text_len[4], 64, &text_active[4], &text_cursor[4], ZR_INPUT_HEX);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:660:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[5], &text_len[5], 64, &text_active[5], &text_cursor[5], ZR_INPUT_OCT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:660:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[5], &text_len[5], 64, &text_active[5], &text_cursor[5], ZR_INPUT_OCT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:662:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[6], &text_len[6], 64, &text_active[6], &text_cursor[6], ZR_INPUT_BIN);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:662:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[6], &text_len[6], 64, &text_active[6], &text_cursor[6], ZR_INPUT_BIN);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:672:17: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, buffer, &text_len[8], 64, &text_active[8], NULL, ZR_INPUT_DEFAULT);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:682:13: warning: passing argument 3 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[7], &text_len[7], 64, &text_active[7], &text_cursor[7], ZR_INPUT_ASCII);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
In file included from linuxgl.c:31:0:
../demo.c:682:13: warning: passing argument 6 of ‘zr_edit’ from incompatible pointer type [enabled by default]
zr_edit(&layout, text[7], &text_len[7], 64, &text_active[7], &text_cursor[7], ZR_INPUT_ASCII);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:2908:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_edit(struct zr_context*, char *buffer, zr_size *len, zr_size max,
^
linuxgl.c: In function ‘font_bake_and_upload’:
linuxgl.c:384:9: warning: passing argument 1 of ‘zr_font_bake_memory’ from incompatible pointer type [enabled by default]
zr_font_bake_memory(&tmp_size, &glyph_count, &config, 1);
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:1513:6: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
void zr_font_bake_memory(zr_size *temporary_memory, int *glyph_count,
^
linuxgl.c:390:9: warning: passing argument 1 of ‘zr_font_bake_pack’ from incompatible pointer type [enabled by default]
if (!zr_font_bake_pack(&img_size, &img_width,&img_height,&custom,tmp,tmp_size,&config, 1))
^
In file included from linuxgl.c:24:0:
../../zahnrad.h:1523:5: note: expected ‘zr_size *’ but argument is of type ‘size_t *’
int zr_font_bake_pack(zr_size *img_memory, int *img_width, int *img_height,
^
linuxgl.c: In function ‘main’:
linuxgl.c:845:17: warning: assignment from incompatible pointer type [enabled by default]
alloc.alloc = mem_alloc;
^
linuxgl.c: In function ‘file_load’:
linuxgl.c:206:10: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
fread(buf, *siz, 1, fd);
^
../../zahnrad.c:110:13: error: size of array ‘zr__check_size’ is negative
typedef int zr__check_size[(sizeof(void*) == sizeof(zr_size)) ? 1 : -1];
^
../../zahnrad.c: In function ‘zr_hash’:
../../zahnrad.c:514:5: warning: integer constant is too large for ‘unsigned long’ type [-Wlong-long]
const zr_ulong m = 0xc6a4a7935bd1e995UL;
^
In file included from ../../zahnrad.c:3278:0:
../../stb_truetype.h: In function ‘stbtt__rasterize_sorted_edges’:
../../stb_truetype.h:2048:4: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
stbtt__hheap hh = { 0 };
^
../../zahnrad.c: In function ‘zr_begin’:
../../zahnrad.c:92:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
#define ZR_OFFSETOF(st, m) ((zr_size)(&((st *)0)->m))
^
../../zahnrad.c:94:56: note: in expansion of macro ‘ZR_OFFSETOF’
((const type*)((const void*)((const zr_byte*)ptr - ZR_OFFSETOF(type, member))))
^
../../zahnrad.c:6557:27: note: in expansion of macro ‘ZR_CONTAINER_OF_CONST’
cur = ZR_CONTAINER_OF_CONST(iter, struct zr_window, buffer);
^
make: *** [zahnrad] Error 1
I hope you help me work it.
Regards.
Kenn
Hey! The input box is still not working quite right, am I doing something wrong or has that not yet been perfected? In specific I cannot select my own index in the input box an make modifications. I am using the windows example. Thanks for taking a look!
Hi, is there is a way to hide text input as you type it in, in the same way when you enter passwords when logging into a website (for example)? If not, could you make a feature for this, or explain how one would make/do one?
Thanks a lot!
Hello,
zahnrad looks really interesting.
But to use it, it seems like one needs to copy paste most of the demo code, before a GUI can be drawn. I know, that this is by design - but what's the benefit?
How about adding all the mainloops from the demo as normal code base? (in separate files, so the user can choose which ones are needed)?
For me, the most obvious way would be something like this:
zr_mainloop_x11(my_zahnrad_gui_function);
zr_mainloop_sdl2(my_zahnrad_gui_function);
zr_mainloop_wayland(my_zahnrad_gui_function);
...
... instead of:
run_demo(&gui);
Thanks for making this project!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.