From 8221fd5451f094defa9866f98026b74a969f7693 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Mon, 8 Mar 2021 14:46:19 -0500 Subject: resizable widgets, default widget implementation for some functions, reimplementing meminfo in raleigh --- src/user/include/cxx/raleigh/w/button.h | 4 +-- src/user/include/cxx/raleigh/w/label.h | 12 ++++---- src/user/include/cxx/raleigh/w/padding.h | 4 +-- src/user/include/cxx/raleigh/w/vbox.h | 4 +-- src/user/include/cxx/raleigh/widget.h | 28 ++++++++++++------ src/user/include/cxx/raleigh/window.h | 6 ++++ src/user/include/cxx/structs/duple.h | 13 ++++++++ src/user/include/knob/key.h | 3 +- src/user/knob/key.c | 12 +++++++- src/user/meminfo/meminfo.c | 31 ------------------- src/user/meminfo/meminfo.cpp | 51 ++++++++++++++++++++++++++++++++ src/user/raleigh/w/button.cpp | 11 ++++--- src/user/raleigh/w/label.cpp | 27 +++++++++++------ src/user/raleigh/w/padding.cpp | 7 +++-- src/user/raleigh/w/vbox.cpp | 21 +++++++++++-- src/user/raleigh/widget.cpp | 22 ++++++++++++++ src/user/raleigh/window.cpp | 31 +++++++++++++++++-- src/user/runtimes/cxx/extra.ld | 5 +++- 18 files changed, 209 insertions(+), 83 deletions(-) create mode 100644 src/user/include/cxx/structs/duple.h delete mode 100644 src/user/meminfo/meminfo.c create mode 100644 src/user/meminfo/meminfo.cpp create mode 100644 src/user/raleigh/widget.cpp (limited to 'src') diff --git a/src/user/include/cxx/raleigh/w/button.h b/src/user/include/cxx/raleigh/w/button.h index 03e17ab..71ccae2 100644 --- a/src/user/include/cxx/raleigh/w/button.h +++ b/src/user/include/cxx/raleigh/w/button.h @@ -12,10 +12,8 @@ namespace raleigh { void notify_window_change() override; void paint(_pixel_t *pixbuf, uint32_t pitch) override; void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; + void notify_child_size_change(widget &child, coord old_size) override; void notify_has_opaque_parent(widget *parent) override; - void handle_key(struct key_packet kp) override; - void on_focus() override; - void on_unfocus() override; private: widget &inner; void (*on_click)(button &); diff --git a/src/user/include/cxx/raleigh/w/label.h b/src/user/include/cxx/raleigh/w/label.h index 4b1dae2..a78ce46 100644 --- a/src/user/include/cxx/raleigh/w/label.h +++ b/src/user/include/cxx/raleigh/w/label.h @@ -7,19 +7,17 @@ namespace raleigh { class label : public widget { public: - //this pointer is used directly, and the contents of the string should not be changed afterward + //value's data is copied label(const char *value, const char *font="fixed-10", bool bg_transparent=true, _pixel_t fg=RGB(00, 00, 00), _pixel_t bg=RGB(bf, bf, bf)); - void notify_window_change() override; + void change_value(const char *new_value); + void paint(_pixel_t *pixbuf, uint32_t pitch) override; - void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; - void handle_key(struct key_packet kp) override; - void on_focus() override; - void on_unfocus() override; private: - const char *const value; + char *value; + uint32_t v_size; const struct font_info *const fi; bool bg_transparent; const _pixel_t fg; diff --git a/src/user/include/cxx/raleigh/w/padding.h b/src/user/include/cxx/raleigh/w/padding.h index 792e204..1bdb9ee 100644 --- a/src/user/include/cxx/raleigh/w/padding.h +++ b/src/user/include/cxx/raleigh/w/padding.h @@ -12,9 +12,7 @@ namespace raleigh { void paint(_pixel_t *pixbuf, uint32_t pitch) override; void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; - void handle_key(struct key_packet kp) override; - void on_focus() override; - void on_unfocus() override; + void notify_child_size_change(widget &child, coord old_size) override; private: widget &inner; uint32_t pad_by; diff --git a/src/user/include/cxx/raleigh/w/vbox.h b/src/user/include/cxx/raleigh/w/vbox.h index 02bffd3..f715f95 100644 --- a/src/user/include/cxx/raleigh/w/vbox.h +++ b/src/user/include/cxx/raleigh/w/vbox.h @@ -14,9 +14,7 @@ namespace raleigh { void paint(_pixel_t *pixbuf, uint32_t pitch) override; void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; - void handle_key(struct key_packet kp) override; - void on_focus() override; - void on_unfocus() override; + void notify_child_size_change(widget &from, coord old_size) override; private: dllist widgets; }; diff --git a/src/user/include/cxx/raleigh/widget.h b/src/user/include/cxx/raleigh/widget.h index 54b9287..1b2cf6f 100644 --- a/src/user/include/cxx/raleigh/widget.h +++ b/src/user/include/cxx/raleigh/widget.h @@ -12,12 +12,15 @@ namespace raleigh { namespace raleigh { class widget { public: - coord size; - - //set by window class (or parent widget) + //these three are set by window class (or parent widget) + widget *parent;//set to zero when root widget window *w; coord window_offset; + //derived classes should not set this outside of the initializer + //instead, they should call widget::set_size(coord) + coord size; + //fewest steps up that a widget can be redrawn without needing its parents //if a widget is opaque, it will set this to a pointer to itself, and then call // notify_has_opaque_parent on any children, passing itself as an argument. @@ -25,14 +28,21 @@ namespace raleigh { // and then call notify_has_opaque_parent on any children (with the opaque parent). widget *closest_opaque; - //called by window class (or parent widget) - virtual void notify_window_change() = 0; + //these are called by window class (or parent widgets) + virtual void notify_window_change(); virtual void paint(_pixel_t *pixbuf, uint32_t pitch) = 0; - virtual void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) = 0; + virtual void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up); virtual void notify_has_opaque_parent(widget *parent) = 0; - virtual void handle_key(struct key_packet kp) = 0; - virtual void on_focus() = 0; - virtual void on_unfocus() = 0; + virtual void handle_key(struct key_packet kp); + virtual void on_focus(); + virtual void on_unfocus(); + //this next one is not to be called by child widgets + //they should call window::notify_widget_size_change(widget &), which will call this if necessary + virtual void notify_child_size_change(widget &child, coord old_size); + + protected: + widget(); + void set_size(coord to); }; } diff --git a/src/user/include/cxx/raleigh/window.h b/src/user/include/cxx/raleigh/window.h index 21ae511..0dd9341 100644 --- a/src/user/include/cxx/raleigh/window.h +++ b/src/user/include/cxx/raleigh/window.h @@ -7,6 +7,8 @@ namespace raleigh { #include #include +#include +#include #include #include @@ -16,7 +18,10 @@ namespace raleigh { public: //pass on_close to specify a close handler. if on_close returns false, the window will not be closed. window(widget &root, _pixel_t bg_color=RGB(bf, bf, bf), bool (*on_close)(window &)=0); + void add_keybind(struct key_packet kp, void (*handler)(window &)); + void notify_needs_paint(widget &from); + void notify_widget_size_change(widget &from, coord old_size); enum try_actions_return_t {NONE, GOOD, DELETE}; try_actions_return_t try_actions(); void show(); @@ -31,6 +36,7 @@ namespace raleigh { bool needs_repaint; void paint_full(); bool (*on_close)(window &); + dllist> keybinds; }; } diff --git a/src/user/include/cxx/structs/duple.h b/src/user/include/cxx/structs/duple.h new file mode 100644 index 0000000..874e4f6 --- /dev/null +++ b/src/user/include/cxx/structs/duple.h @@ -0,0 +1,13 @@ +#ifndef STRUCTS_DUPLE_H +#define STRUCTS_DUPLE_H + +template +class duple { +public: + duple(at a, bt b) + : a(a), b(b) {} + at a; + bt b; +}; + +#endif \ No newline at end of file diff --git a/src/user/include/knob/key.h b/src/user/include/knob/key.h index d532afd..3597e2a 100644 --- a/src/user/include/knob/key.h +++ b/src/user/include/knob/key.h @@ -7,7 +7,8 @@ extern "C" { #include -char key_to_char(struct key_packet kp) __attribute__ ((pure)); +char key_to_char(struct key_packet kp) __attribute__ ((const)); +bool match_side_agnostic(struct key_packet a, struct key_packet b) __attribute__ ((const)); #ifdef __cplusplus } diff --git a/src/user/knob/key.c b/src/user/knob/key.c index 1506f3b..b2e3f5e 100644 --- a/src/user/knob/key.c +++ b/src/user/knob/key.c @@ -1,4 +1,5 @@ #include +#include static const char no_mod[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t','\n', 0, 0, 0, 0, 0, @@ -48,7 +49,7 @@ static const char num[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '+', '\n', '-', '.', '/' }; -__attribute__ ((pure)) +__attribute__ ((const)) char key_to_char(struct key_packet kp) { if (kp.key_id < 0x80) { const char ch = (kp.modifiers & SHIFTS @@ -64,4 +65,13 @@ char key_to_char(struct key_packet kp) { else return 0; +} + +__attribute__ ((const)) +bool match_side_agnostic(struct key_packet a, struct key_packet b) { + return (a.key_id == b.key_id) && + ((bool)(a.modifiers & SHIFTS) == (bool)(b.modifiers & SHIFTS)) && + ((bool)(a.modifiers & CTRLS) == (bool)(b.modifiers & CTRLS)) && + ((bool)(a.modifiers & ALTS) == (bool)(b.modifiers & ALTS)) && + ((bool)(a.modifiers & WINS) == (bool)(b.modifiers & WINS)); } \ No newline at end of file diff --git a/src/user/meminfo/meminfo.c b/src/user/meminfo/meminfo.c deleted file mode 100644 index 3c3c45b..0000000 --- a/src/user/meminfo/meminfo.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -#include - -static const struct key_packet meminfo_quits[] = { - { .key_id = KEY_ESCAPE, .modifiers = NO_MODS }, - { .key_id = KEY_F5, .modifiers = NO_MODS }, - { .key_id = 0 } -}; - -void main() { - struct popup p; -redo: - info_popupf(&p, - "kernel memory free: %uk\n" - "userspace memory free: %uk / %uk\n" - "Escape to quit, F5 to refresh.", - (_pixel_t){.r = 0, .g = 0, .b = 0}, - (_pixel_t){.r = 0xbf, .g = 0xbf, .b = 0xbf}, - _kernel_dynamic_area_left() * 4, - _total_userspace_left() * 4, - _total_userspace_size() * 4 - ); - //hacky, i should really make info_popup take an arg - p.quit_binds = meminfo_quits; - make_modal(&p); - if (p.quit_as.key_id == KEY_F5) - //i should make popups have changable text - //(make a new pixbuf but reuse the window) - goto redo; -} \ No newline at end of file diff --git a/src/user/meminfo/meminfo.cpp b/src/user/meminfo/meminfo.cpp new file mode 100644 index 0000000..2b035a4 --- /dev/null +++ b/src/user/meminfo/meminfo.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace raleigh; + +label *kmem; +label *umem; + +void refresh(window &w) { + char *const kstr = format("kernel memory free: %uk", _kernel_dynamic_area_left() * 4); + char *const ustr = format("userspace memory free: %uk / %uk", _total_userspace_left() * 4, _total_userspace_size() * 4); + + kmem->change_value(kstr); + umem->change_value(ustr); + + free_block(kstr); + free_block(ustr); +} + +void main() { + kmem = new label(""); + umem = new label(""); + label msg("press Alt+F4 to quit, or F5 to refresh"); + + padding pkmem(*kmem, 1); + padding pumem(*umem, 1); + padding pmsg(msg, 1); + + dllist ll; + ll.add_front(pmsg); + ll.add_front(pumem); + ll.add_front(pkmem); + vbox box(ll); + + padding pbox(box, 3); + window w(pbox, RGB(bf, bf, bf), (bool (*)(window &))&__pcrt_quit); + w.add_keybind((struct key_packet){.key_id = key_packet::KEY_F5, .modifiers = key_packet::NO_MODS}, &refresh); + + refresh(w); + + w.show(); + start_runtime(); +} \ No newline at end of file diff --git a/src/user/raleigh/w/button.cpp b/src/user/raleigh/w/button.cpp index a92167e..2abf9a9 100644 --- a/src/user/raleigh/w/button.cpp +++ b/src/user/raleigh/w/button.cpp @@ -8,6 +8,7 @@ namespace raleigh { size = coord(inner.size.x + 2, inner.size.y + 2); closest_opaque = this; inner.notify_has_opaque_parent(this); + inner.parent = this; } void button::notify_window_change() { @@ -49,11 +50,9 @@ namespace raleigh { } } - void button::notify_has_opaque_parent(widget *parent) {} - - void button::handle_key(struct key_packet kp) {} - - void button::on_focus() {} + void button::notify_child_size_change(widget &child, coord old_size) { + set_size(coord(inner.size.x + 2, inner.size.y + 2)); + } - void button::on_unfocus() {} + void button::notify_has_opaque_parent(widget *parent) {} } \ No newline at end of file diff --git a/src/user/raleigh/w/label.cpp b/src/user/raleigh/w/label.cpp index 046737f..21df2a2 100644 --- a/src/user/raleigh/w/label.cpp +++ b/src/user/raleigh/w/label.cpp @@ -4,12 +4,27 @@ namespace raleigh { label::label(const char *value, const char *font, bool bg_transparent, _pixel_t fg, _pixel_t bg) - : value(value), fi(get_font(font)), bg_transparent(bg_transparent), fg(fg), bg(bg) { - size = coord(fi->space_width * (strlen(value) - 1) + fi->char_width, fi->char_height); + : fi(get_font(font)), bg_transparent(bg_transparent), fg(fg), bg(bg) { + + v_size = strlen(value) + 1; + this->value = new char[v_size]; + blockcpy(this->value, value, v_size); + size = coord(fi->space_width * (v_size - 2) + fi->char_width, fi->char_height); + closest_opaque = 0; } - void label::notify_window_change() {} + void label::change_value(const char *new_value) { + delete[] value; + const uint32_t ns = strlen(new_value) + 1; + if (ns != v_size) { + v_size = ns; + value = new char[ns]; + set_size(coord(fi->space_width * (ns - 2) + fi->char_width, fi->char_height)); + } + blockcpy(value, new_value, ns); + w->notify_needs_paint(*this); + } void label::paint(_pixel_t *pixbuf, uint32_t pitch) { if (!bg_transparent) @@ -23,13 +38,7 @@ namespace raleigh { } } - void label::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { } - void label::notify_has_opaque_parent(widget *parent) { closest_opaque = parent; } - - void label::handle_key(struct key_packet kp) {}; - void label::on_focus() {}; - void label::on_unfocus() {}; } \ No newline at end of file diff --git a/src/user/raleigh/w/padding.cpp b/src/user/raleigh/w/padding.cpp index 87167c3..c1f7b85 100644 --- a/src/user/raleigh/w/padding.cpp +++ b/src/user/raleigh/w/padding.cpp @@ -5,6 +5,7 @@ namespace raleigh { : inner(inner), pad_by(pad_by) { size = coord(inner.size.x + pad_by * 2, inner.size.y + pad_by * 2); closest_opaque = 0; + inner.parent = this; } void padding::notify_window_change() { @@ -30,7 +31,7 @@ namespace raleigh { inner.notify_has_opaque_parent(parent); } - void padding::handle_key(struct key_packet kp) {}; - void padding::on_focus() {}; - void padding::on_unfocus() {}; + void padding::notify_child_size_change(widget &child, coord old_size) { + set_size(coord(inner.size.x + pad_by * 2, inner.size.y + pad_by * 2)); + } } \ No newline at end of file diff --git a/src/user/raleigh/w/vbox.cpp b/src/user/raleigh/w/vbox.cpp index 08c2539..263da2a 100644 --- a/src/user/raleigh/w/vbox.cpp +++ b/src/user/raleigh/w/vbox.cpp @@ -4,6 +4,7 @@ namespace raleigh { vbox::vbox(dllist widgets) : widgets(widgets) { uint32_t w = 0, h = 0; for (dllist::node *n = widgets.first; n; n = n->next) { + n->d.parent = this; h += n->d.size.y; if (n->d.size.x > w) w = n->d.size.x; @@ -45,7 +46,21 @@ namespace raleigh { n->d.notify_has_opaque_parent(parent); } - void vbox::handle_key(struct key_packet kp) {}; - void vbox::on_focus() {}; - void vbox::on_unfocus() {}; + void vbox::notify_child_size_change(widget &from, coord old_size) { + if ((old_size.y == from.size.y) && (from.size.x <= size.x)) { + from.window_offset.x = window_offset.x + size.x / 2 - from.size.x / 2; + from.notify_window_change(); + } + + else {//lazy, less efficient approach + uint32_t h = 0, w = 0; + for (dllist::node *n = widgets.first; n; n = n->next) { + h += n->d.size.y; + if (n->d.size.x > w) + w = n->d.size.x; + } + set_size(coord(w, h)); + notify_window_change(); + } + } } \ No newline at end of file diff --git a/src/user/raleigh/widget.cpp b/src/user/raleigh/widget.cpp new file mode 100644 index 0000000..719cc06 --- /dev/null +++ b/src/user/raleigh/widget.cpp @@ -0,0 +1,22 @@ +#include + +#include + +namespace raleigh { + widget::widget() + : parent(0) {} + + void widget::notify_window_change() {} + void widget::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {} + void widget::handle_key(struct key_packet kp) {} + void widget::on_focus() {} + void widget::on_unfocus() {} + void widget::notify_child_size_change(widget &child, coord old_size) {} + + void widget::set_size(coord new_size) { + coord old_size = size; + size = new_size; + if (w) + w->notify_widget_size_change(*this, old_size); + } +} \ No newline at end of file diff --git a/src/user/raleigh/window.cpp b/src/user/raleigh/window.cpp index 052422e..5d1a3de 100644 --- a/src/user/raleigh/window.cpp +++ b/src/user/raleigh/window.cpp @@ -1,7 +1,6 @@ #include #include -#include -#include +#include #include @@ -44,8 +43,16 @@ namespace raleigh { root.handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, false); else if (wa.action_type == wa.MOUSE_UP) root.handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, true); - else if (wa.action_type == wa.KEY_DOWN) + else if (wa.action_type == wa.KEY_DOWN) { + for (dllist>::node *n = keybinds.first; n; n = n->next) + if (match_side_agnostic(wa.as_key, n->d.a)) { + n->d.b(*this); + goto next_loop; + } focussed->handle_key(wa.as_key); + next_loop: + ; + } else if (wa.action_type == wa.FOCUS_ENTER) focussed->on_focus(); else if (wa.action_type == wa.FOCUS_LEAVE) @@ -83,4 +90,22 @@ namespace raleigh { focussed->on_focus(); } } + + void window::notify_widget_size_change(widget &from, coord old_size) { + if (from.parent) + from.parent->notify_child_size_change(from, old_size); + else { + size = root.size; + delete[] pixbuf; + pixbuf = new _pixel_t[size.x * size.y]; + if (!pixbuf) + show_error_and_quitf("Failed to allocate %u byte buffer while\nresizing window to %ux%u pixels.", size.x * size.y, size.x, size.y); + paint_full(); + _resize_window(handle, size.x, size.y, pixbuf); + } + } + + void window::add_keybind(struct key_packet kp, void (*handler)(window &)) { + keybinds.add_front(duple(kp, handler)); + } } \ No newline at end of file diff --git a/src/user/runtimes/cxx/extra.ld b/src/user/runtimes/cxx/extra.ld index 8ce5419..048877e 100644 --- a/src/user/runtimes/cxx/extra.ld +++ b/src/user/runtimes/cxx/extra.ld @@ -5,4 +5,7 @@ _Znwj = get_block; _Znaj = get_block; /* void operator delete(void *, size_t) */ -_ZdlPvj = free_block; \ No newline at end of file +_ZdlPvj = free_block; + +/* void operator delete[](void *) */ +_ZdaPv = free_block; \ No newline at end of file -- cgit v1.2.3