From 11054d8a536937abb6c621284be7813fb6f04498 Mon Sep 17 00:00:00 2001 From: Cecil Date: Sun, 7 Oct 2018 00:15:44 -0600 Subject: [PATCH] user written layout - #410 - wip * basically a flow that calls a delegate when adding an element. * much more to do. --- Tests/layout/l1.rb | 30 +++++++++++ make/linux/minlin/env.rb | 2 +- make/linux/mxe/env.rb | 2 +- shoes/canvas.c | 37 +++++++++++++ shoes/canvas.h | 3 ++ shoes/ruby.c | 4 +- shoes/ruby.h | 2 +- shoes/types/layout.c | 111 +++++++++++++++++++++++++++++++++++++++ shoes/types/layout.h | 21 ++++++++ shoes/types/types.h | 12 +++-- 10 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 Tests/layout/l1.rb create mode 100644 shoes/types/layout.c create mode 100644 shoes/types/layout.h diff --git a/Tests/layout/l1.rb b/Tests/layout/l1.rb new file mode 100644 index 00000000..a6076f0b --- /dev/null +++ b/Tests/layout/l1.rb @@ -0,0 +1,30 @@ + +class MyLayout + attr_accessor :pos_x, :pos_y + + def initialize() + @pos_x = 25 + @pos_y = 25 + end + + def add_widget(widget) + widget.move @pos_x, @pos_y + @pos_x += 25 + @pos_y += 25 + end +end + +Shoes.app width: 350, height: 400, resizeable: true do + stack do + para "Before layout" + @ml = layout manager: MyLayout.new, width: 300, height: 300 do + background yellow + p1 = para "First Para" + a = button "one" + b = button "two" + p2 = para "I am #{self}" + end + end + para "After layout" + para "@ml is #{@ml.inspect}" +end diff --git a/make/linux/minlin/env.rb b/make/linux/minlin/env.rb index 60b1d750..5b4704fb 100644 --- a/make/linux/minlin/env.rb +++ b/make/linux/minlin/env.rb @@ -16,7 +16,7 @@ LINUX_CFLAGS << " -DRUBY_HTTP" LINUX_CFLAGS << " -DRUBY_1_9" -LINUX_CFLAGS << " -DSZBUG" +#LINUX_CFLAGS << " -DSZBUG" LINUX_CFLAGS << " -DDEBUG" if ENV['DEBUG'] LINUX_CFLAGS << " -DSHOES_GTK -fPIC -shared -Wno-unused-but-set-variable" # Following line may need handcrafting diff --git a/make/linux/mxe/env.rb b/make/linux/mxe/env.rb index 3d997d46..54cd6378 100644 --- a/make/linux/mxe/env.rb +++ b/make/linux/mxe/env.rb @@ -126,7 +126,7 @@ 'ssleay32' => "#{bindll}/ssleay32.dll", 'libepoxy-0' => "#{bindll}/libepoxy-0.dll", #'libgmp-10' => "#{basedll}/libgmp-10.dll", - 'libgcc_s_dw2-1' => "#{basedll}/libgcc_s_dw2-1.dll", + #'libgcc_s_dw2-1' => "#{basedll}/libgcc_s_dw2-1.dll", 'libgcc_s_sjlj-1' => "{basedll}/libgcc_s_sjlj-1.dll", 'libsqlite3' => "#{bindll}/libsqlite3-0.dll", 'libexpat-1' => "", diff --git a/shoes/canvas.c b/shoes/canvas.c index 8b034d9d..1f02a431 100644 --- a/shoes/canvas.c +++ b/shoes/canvas.c @@ -14,6 +14,7 @@ #include "shoes/types/pattern.h" #include "shoes/types/shape.h" #include "shoes/types/textblock.h" +#include "shoes/types/layout.h" #include "shoes/http.h" const double SHOES_PIM2 = 6.28318530717958647693; @@ -216,6 +217,9 @@ VALUE shoes_add_ele(shoes_canvas *canvas, VALUE ele) { rb_ary_insert_at(canvas->contents, canvas->insertion, 0, ele); canvas->insertion++; } + if (! NIL_P(canvas->layout_mgr) && !rb_obj_is_kind_of(ele, cLayout)) { + shoes_layout_add_ele(canvas, ele); + } return ele; } @@ -223,6 +227,7 @@ void shoes_canvas_mark(shoes_canvas *canvas) { shoes_native_slot_mark(canvas->slot); rb_gc_mark_maybe(canvas->contents); rb_gc_mark_maybe(canvas->attr); + rb_gc_mark_maybe(canvas->layout_mgr); rb_gc_mark_maybe(canvas->parent); } @@ -258,6 +263,7 @@ VALUE shoes_canvas_alloc(VALUE klass) { canvas->contents = Qnil; canvas->shape = NULL; canvas->insertion = -2; + canvas->layout_mgr = Qnil; VALUE rb_canvas = Data_Wrap_Struct(klass, shoes_canvas_mark, shoes_canvas_free, canvas); return rb_canvas; } @@ -817,6 +823,8 @@ VALUE shoes_canvas_stack(int argc, VALUE *argv, VALUE self) { return stack; } + + VALUE shoes_canvas_mask(int argc, VALUE *argv, VALUE self) { rb_arg_list args; VALUE mask; @@ -845,6 +853,34 @@ VALUE shoes_canvas_widget(int argc, VALUE *argv, VALUE self) { return widget; } +VALUE shoes_canvas_layout(int argc, VALUE *argv, VALUE self) { + rb_arg_list args; + VALUE layout; + VALUE layout_obj; + SETUP_CANVAS(); + fprintf(stderr, "canvas_layout: called\n"); + + rb_parse_args(argc, argv, "|h&", &args); + layout_obj = shoes_layout_new(args.a[0], self); + shoes_layout *self_t; + Data_Get_Struct(layout_obj, shoes_layout, self_t); + layout = self_t->canvas; // from shoes_slot_new() + if (!NIL_P(args.a[1])) { + /* expand macro by hand + DRAW(layout, canvas->app, rb_funcall(args.a[1], s_call, 0)); + */ + rb_ary_push(canvas->app->nesting, layout); + rb_funcall(args.a[1], s_call, 0); // this is the block arg + rb_ary_pop(canvas->app->nesting); + } + shoes_add_ele(canvas, layout); + + //shoes_canvas *self_t; + //Data_Get_Struct(layout, shoes_canvas, self_t); + // yes, we return the canvas, not the Layout Object + return layout; +} + void shoes_canvas_size(VALUE self, int w, int h) { SETUP_CANVAS(); canvas->place.iw = canvas->place.w = canvas->width = w; @@ -1352,6 +1388,7 @@ VALUE shoes_widget_new(VALUE klass, VALUE attr, VALUE parent) { return shoes_slot_new(klass, attr, parent); } + VALUE shoes_canvas_get_cursor(VALUE self) { SETUP_CANVAS(); return ID2SYM(canvas->app->cursor); diff --git a/shoes/canvas.h b/shoes/canvas.h index 875eda88..d6c0e910 100644 --- a/shoes/canvas.h +++ b/shoes/canvas.h @@ -258,6 +258,7 @@ typedef struct { struct _shoes_app *app; SHOES_SLOT_OS *slot; SHOES_GROUP_OS group; + VALUE layout_mgr; // we have a Layout object } shoes_canvas; VALUE shoes_app_main(int, VALUE *, VALUE); @@ -329,6 +330,7 @@ VALUE shoes_canvas_flow(int, VALUE *, VALUE); VALUE shoes_canvas_stack(int, VALUE *, VALUE); VALUE shoes_canvas_mask(int, VALUE *, VALUE); VALUE shoes_canvas_widget(int, VALUE *, VALUE); +VALUE shoes_canvas_layout(int, VALUE *, VALUE); VALUE shoes_canvas_hide(VALUE); VALUE shoes_canvas_show(VALUE); VALUE shoes_canvas_toggle(VALUE); @@ -383,6 +385,7 @@ VALUE shoes_slot_new(VALUE, VALUE, VALUE); VALUE shoes_flow_new(VALUE, VALUE); VALUE shoes_stack_new(VALUE, VALUE); VALUE shoes_mask_new(VALUE, VALUE); +VALUE shoes_layout_new(VALUE, VALUE); VALUE shoes_widget_new(VALUE, VALUE, VALUE); VALUE shoes_chart_series_new(int, VALUE *, VALUE); diff --git a/shoes/ruby.c b/shoes/ruby.c index 4deeb1db..a55b2f19 100644 --- a/shoes/ruby.c +++ b/shoes/ruby.c @@ -11,11 +11,12 @@ #include "shoes/version.h" #include "shoes/types/types.h" #include "shoes/types/settings.h" +#include "shoes/types/layout.h" #include VALUE cShoes, cApp, cDialog, cTypes, cShoesWindow, cMouse, cCanvas, cFlow; VALUE cStack, cMask, cWidget, cProgress, cColor, cResponse, ssNestSlot; -VALUE cShoesMenu, cShoesMenubar, cShoesMenuItem; +VALUE cShoesMenu, cShoesMenubar, cShoesMenuItem, cLayout; VALUE eImageError, eInvMode, eNotImpl; VALUE reHEX_SOURCE, reHEX3_SOURCE, reRGB_SOURCE, reRGBA_SOURCE, reGRAY_SOURCE, reGRAYA_SOURCE, reLF; VALUE symAltQuest, symAltSlash, symAltDot, symAltEqual, symAltSemiColon; @@ -890,6 +891,7 @@ void shoes_ruby_init() { cMask = rb_define_class_under(cTypes, "Mask", cShoes); cWidget = rb_define_class_under(cTypes, "Widget", cShoes); + rb_define_method(cApp, "method_missing", CASTHOOK(shoes_app_method_missing), -1); rb_define_method(rb_mKernel, "alert", CASTHOOK(shoes_dialog_alert), -1); diff --git a/shoes/ruby.h b/shoes/ruby.h index aa319dd9..af207b52 100644 --- a/shoes/ruby.h +++ b/shoes/ruby.h @@ -79,7 +79,7 @@ static inline void flip_endian(unsigned char* x, int length) { #undef s_host extern VALUE cShoes, cApp, cDialog, cTypes, cShoesWindow, cMouse, cCanvas; -extern VALUE cFlow, cStack, cMask; +extern VALUE cFlow, cStack, cMask, cLayout; extern VALUE cProgress, cShoesMenubar, cShoeMenu, cShoesMenuItem, cSettings; extern VALUE ssNestSlot; extern VALUE cWidget; diff --git a/shoes/types/layout.c b/shoes/types/layout.c new file mode 100644 index 00000000..e45ff91a --- /dev/null +++ b/shoes/types/layout.c @@ -0,0 +1,111 @@ +/* + * layout.c +*/ +#include "shoes/app.h" +#include "shoes/canvas.h" +#include "shoes/ruby.h" +#include "shoes/internal.h" +#include "shoes/world.h" +#include "shoes/native/native.h" +#include "shoes/version.h" +#include "shoes/types/types.h" +#include "shoes/types/settings.h" +#include "shoes/types/layout.h" +#include +// +// Shoes::Layout needs to be a class so it can be subclassed +// +extern VALUE cButton, cBackground; + +FUNC_M("+layout", layout, -1); + +void shoes_layout_init() { + cLayout = rb_define_class_under(cTypes, "Layout", cNative); + rb_define_method(cLayout, "rule", CASTHOOK(shoes_layout_add_rule), 1); + rb_define_method(cLayout, "compute", CASTHOOK(shoes_layout_compute), 1); + + RUBY_M("+layout", layout, -1); +} + +void shoes_layout_mark(shoes_layout *ly) { + rb_gc_mark_maybe(ly->canvas); + rb_gc_mark_maybe(ly->delegate); +} + +static void shoes_layout_free(shoes_layout *ly) { + RUBY_CRITICAL(SHOE_FREE(ly)); +} + +VALUE shoes_layout_alloc(VALUE klass) { + VALUE obj; + shoes_layout *ly = SHOE_ALLOC(shoes_layout); + SHOE_MEMZERO(ly, shoes_layout, 1); + obj = Data_Wrap_Struct(klass, shoes_layout_mark, shoes_layout_free, ly); + // set fields ? + ly->x = 10; + ly->y = 10; + ly->delegate = Qnil; + ly->canvas = Qnil; + return obj; +} + +VALUE shoes_layout_new(VALUE attr, VALUE parent) { + fprintf(stderr, "shoes_layout_new called\n"); + VALUE obj = shoes_layout_alloc(cLayout); + shoes_layout *ly; + Data_Get_Struct(obj, shoes_layout, ly); + // Most of shoes thinks its a Flow + VALUE canvas = shoes_slot_new(cFlow, attr, parent); + ly->canvas = canvas; + shoes_canvas *cvs; + Data_Get_Struct(canvas, shoes_canvas, cvs); + // get manager from attr, put in delegate. + VALUE mgr; + ID s_manager = rb_intern ("manager"); + mgr = ATTR(attr, manager); + if (! NIL_P(mgr)) + ly->delegate = mgr; + cvs->layout_mgr = obj; // me + return obj; +} + +// called from inside shoes (shoes_add_ele) +void shoes_layout_add_ele(shoes_canvas *canvas, VALUE ele) { + if (rb_obj_is_kind_of(ele, cBackground)) { + fprintf(stderr, "skipping background widget\n"); + return; + } + // Find a delegate or use the Toy ? + if (canvas->layout_mgr != Qnil) { + shoes_layout *ly; + Data_Get_Struct(canvas->layout_mgr, shoes_layout, ly); + if (! NIL_P(ly->delegate)) { + fprintf(stderr,"Delegating\n"); + VALUE del = ly->delegate; + ID s_addw = rb_intern("add_widget"); + if (rb_respond_to(del, s_addw)) + rb_funcall(del, s_addw, 1, ele); + //return; + } + } + if (rb_obj_is_kind_of(ele, cButton)) { + fprintf(stderr, "shoes_layout_add Button\n"); + } else if (rb_obj_is_kind_of(ele, cPara)) { + fprintf(stderr,"shoes layout_add Para\n"); + } else { + fprintf(stderr, "shoes_layout_add something\n"); + } + return; +} + +VALUE shoes_layout_delete_ele(shoes_canvas *canvas, VALUE ele) { + fprintf(stderr,"shoes_layout_delete called\n"); +} + +extern VALUE shoes_layout_add_rule(VALUE self, VALUE rule) { + fprintf(stderr,"shoes_layout_add_rule called\n"); +} + +extern VALUE shoes_layout_compute(VALUE self) { + fprintf(stderr, "shoes_layout_compute called\n"); +} diff --git a/shoes/types/layout.h b/shoes/types/layout.h new file mode 100644 index 00000000..982d4e83 --- /dev/null +++ b/shoes/types/layout.h @@ -0,0 +1,21 @@ +#ifndef SHOES_LAYOUT_TYPE_H +#define SHOES_LAYOUT_TYPE_H + +typedef struct { + VALUE delegate; + VALUE canvas; + // below belongs to the C crafted default layout manager, what ever that + // is. A Toy for now. + int x; + int y; +} shoes_layout; +extern VALUE cLayout; +extern void shoes_layout_init(); +extern VALUE shoes_layout_new(VALUE attr, VALUE parent); +extern VALUE shoes_layout_add_rule(VALUE self, VALUE rule); +extern VALUE shoes_layout_compute(VALUE self); + +extern void shoes_layout_add_ele(shoes_canvas *canvas, VALUE ele); +extern VALUE shoes_layout_delete_ele(shoes_canvas *canvas, VALUE ele); + +#endif diff --git a/shoes/types/types.h b/shoes/types/types.h index f665b0de..e3008e99 100644 --- a/shoes/types/types.h +++ b/shoes/types/types.h @@ -29,6 +29,7 @@ #include "shoes/types/menu.h" #include "shoes/types/menuitem.h" #include "shoes/types/settings.h" +#include "shoes/types/layout.h" #define SHOES_TYPES_INIT \ shoes_0_native_type_init(); \ @@ -50,15 +51,16 @@ shoes_spinner_init(); \ shoes_svg_init(); \ shoes_switch_init(); \ - shoes_systray_init(); \ + shoes_systray_init(); \ shoes_text_init(); \ shoes_text_link_init(); \ shoes_text_view_init(); \ shoes_textblock_init(); \ shoes_timerbase_init(); \ shoes_video_init(); \ - shoes_shoesevent_init(); \ - shoes_menubar_init(); \ - shoes_menu_init(); \ - shoes_menuitem_init(); + shoes_shoesevent_init(); \ + shoes_menubar_init(); \ + shoes_menu_init(); \ + shoes_menuitem_init(); \ + shoes_layout_init();