Piggyback on the existing mechanism to set individual properties.
This doesn't cover layouts or child widgets, but the per-widget own
properties can be set this way.
Any property can now be set in JSON GUI, all you need to do is handle
it in the relevant Core::Object::set_property() override. :^)
This is our first client of the new JSON GUI declaration thingy.
The skeleton of the TextEditor app GUI is now declared separately from
the C++ logic, and we use the Core::Object::name() of widgets to locate
them once they have been instantiated by the GUI builder.
My original idea for GUI building tools was to have the "VisualBuilder"
app generate C++ code which in turn programmatically instantiated UI.
That never really materialized in any useful way beyond static UIs.
This is a fresh, new approach: using JSON to declare the UI and parsing
and constructing this UI at runtime. This will allow for way more
dynamic and flexible approaches to GUI development (I think.)
The basic idea is that you pass a JSON string to Widget::load_from_json
and it takes care of the rest.
This first version supports basic box layouts and instantiation of
arbitrary widgets, as long as those widgets have been registered.
This code has some pretty rough edges right now as it's evolving and
we need to figure out a lot of things about how it should work.
Nevertheless, it feels pretty cool. :^)
This is a little bit messy since the left-side treeview also has a
delete action. Because of that, we have to put a focus-dependent action
that delegates to the relevant view-specific action in the tool bar
and menu bar.
I'm not sure yet what a good abstraction would be for this. We'll see
what we can think of.
Since the CPU already does almost all necessary validation steps
for us, we don't really need to attempt to do this. Doing it
ourselves doesn't really work very reliably, because we'd have to
account for other processors modifying virtual memory, and we'd
have to account for e.g. pages not being able to be allocated
due to insufficient resources.
So change the copy_to/from_user (and associated helper functions)
to use the new safe_memcpy, which will return whether it succeeded
or not. The only manual validation step needed (which the CPU
can't perform for us) is making sure the pointers provided by user
mode aren't pointing to kernel mappings.
To make it easier to read/write from/to either kernel or user mode
data add the UserOrKernelBuffer helper class, which will internally
either use copy_from/to_user or directly memcpy, or pass the data
through directly using a temporary buffer on the stack.
Last but not least we need to keep syscall params trivial as we
need to copy them from/to user mode using copy_from/to_user.
These special functions can be used to safely copy/set memory or
determine the length of a string, e.g. provided by user mode.
In the event of a page fault, safe_memcpy/safe_memset will return
false and safe_strnlen will return -1.
Else, we store an empty but allocated string for each Attribute after a
href was emitted (since it's ended by a non-null empty string), which
makes Line objects very expensive to destroy and to modify.
Reduces `disasm /bin/id` from 414ms to 380ms (min-of-5). There's
a lot more perf wins to be had with better href handling (most
lines don't have any hrefs, so instead of storing a string per
Attr, maybe we could have a vector of hrefs per line and int offsets
into that in each Attr for example), but this is a simple, obvious,
and effective improvement, so let's start with this.
Moves Bitmap backing store creation to the static create() methods.
This backing store is then passed into the Bitmap constructor. This
allows us correctly return nullptr from create() in the event that
memory allocation fails.
Following in the footsteps of <input type=checkbox>, this patch adds
LayoutButton which implements a basic push button using LibGfx styling
primitives.
- After letting a LayoutNode handle a mouseup, re-do the hit test
since things may have changed.
- Make sure we always update the document's hovered node.
This was previously used to defer handling disconnections until the
next event loop iteration. We now achieve the same with simple use
of deferred_invoke(). :^)