From ffec6c95bd28c68daa9503bb7d140be723c7cb23 Mon Sep 17 00:00:00 2001 From: Cecil Date: Tue, 9 Oct 2018 11:53:22 -0600 Subject: [PATCH] more work - changes to api, expect more. --- Tests/layout/l1.rb | 20 +++++-- Tests/layout/l2.rb | 77 +++++++++++++++++++++++++ make/linux/minlin/env.rb | 2 +- shoes/canvas.c | 32 +++++++---- shoes/types/layout.c | 119 +++++++++++++++++++++++++++++++-------- shoes/types/layout.h | 26 ++++++--- 6 files changed, 225 insertions(+), 51 deletions(-) create mode 100644 Tests/layout/l2.rb diff --git a/Tests/layout/l1.rb b/Tests/layout/l1.rb index a6076f0b..d0b9a5f7 100644 --- a/Tests/layout/l1.rb +++ b/Tests/layout/l1.rb @@ -1,13 +1,22 @@ class MyLayout - attr_accessor :pos_x, :pos_y + attr_accessor :pos_x, :pos_y, :w, :h + attr_accessor :contents def initialize() @pos_x = 25 @pos_y = 25 + @contents = [] end - def add_widget(widget) + def setup(attr) + @w = attr[:width] + @h = attr[:height] + puts "setup #{@w} X #{@h}" + end + + def add(widget) + @contents << widget widget.move @pos_x, @pos_y @pos_x += 25 @pos_y += 25 @@ -17,14 +26,15 @@ def add_widget(widget) Shoes.app width: 350, height: 400, resizeable: true do stack do para "Before layout" - @ml = layout manager: MyLayout.new, width: 300, height: 300 do + @ml = MyLayout.new + layout manager: @ml, width: 300, height: 300 do background yellow p1 = para "First Para" a = button "one" b = button "two" - p2 = para "I am #{self}" + p2 = para "I am #{self.class}" end end para "After layout" - para "@ml is #{@ml.inspect}" + para "@ml is #{@ml.class}" end diff --git a/Tests/layout/l2.rb b/Tests/layout/l2.rb new file mode 100644 index 00000000..63217f27 --- /dev/null +++ b/Tests/layout/l2.rb @@ -0,0 +1,77 @@ + +class MyLayout + attr_accessor :pos_x, :pos_y, :w, :h + attr_accessor :incr_x, :incr_y + + def initialize() + puts "initialized" + clear + end + + def setup(canvas, attr) + @w = attr[:width] + @h = attr[:height] + puts "callback: setup #{@w} X #{@h}" + end + + def add(canvas, widget) + puts "callback add: #{widget.inspect} #{canvas.contents.size}" + @pos_x += @incr_x + if @pos_x < 0 + @pos_x = 0 + @incr_x = 25 + end + if @pos_x >= @w + @pos_x = @w + @incr_x = -25 + end + @pos_y += @incr_y + if @pos_y <= 0 + @pos_y = 0 + @incr_y = +25 + end + if @pos_y >= @h + @pos_y = @h - 25 + @incr_y = -25 + end + widget.move @pos_x, @pos_y + end + + def clear + @pos_x = -20 + @pos_y = -20 + @incr_x = 25 + @incr_y = 25 + puts "callback: clear" + end + +end + +Shoes.app width: 350, height: 450, resizeable: true do + stack do + @p = para "Before layout" + @ml = MyLayout.new + @lay =layout manager: @ml, width: 340, height: 380 do + background yellow + p1 = para "First Para" + a = button "one" + b = button "two" + p2 = para "I am #{self.class}" + end + @p.text = @lay.inspect + @lay.finish + end + button "Append" do + @lay.append { para "appended" } + end + button "Clear" do + @lay.clear { background white } + end + button "Prepend" do + # problem here? + @lay.prepend { para "prepended" } + end + button "refresh" do + @lay.refresh + end +end diff --git a/make/linux/minlin/env.rb b/make/linux/minlin/env.rb index 5b4704fb..a918526b 100644 --- a/make/linux/minlin/env.rb +++ b/make/linux/minlin/env.rb @@ -6,7 +6,7 @@ APP['GDB'] = "true" # true => compile -g, don't strip symbols if APP['GDB'] - LINUX_CFLAGS = "-g -O0" + LINUX_CFLAGS = "-ggdb3 -O0" else LINUX_CFLAGS = "-O -Wall" end diff --git a/shoes/canvas.c b/shoes/canvas.c index 1f02a431..5bb7cfe5 100644 --- a/shoes/canvas.c +++ b/shoes/canvas.c @@ -281,6 +281,10 @@ static void shoes_canvas_empty(shoes_canvas *canvas, int extras) { canvas->stage = CANVAS_EMPTY; shoes_ele_remove_all(canvas->contents); if (extras) shoes_extras_remove_all(canvas); + if (! NIL_P(canvas->layout_mgr)) { + shoes_layout_clear(canvas); + } + canvas->stage = stage; } @@ -715,7 +719,7 @@ void shoes_canvas_compute(VALUE self) { cairo_restore(cr); } -static void shoes_canvas_insert(VALUE self, long i, VALUE ele, VALUE block) { +void shoes_canvas_insert(VALUE self, long i, VALUE ele, VALUE block) { SETUP_CANVAS(); if (canvas->insertion != -2) @@ -727,8 +731,15 @@ static void shoes_canvas_insert(VALUE self, long i, VALUE ele, VALUE block) { canvas->insertion = i; if (rb_respond_to(block, s_widget)) rb_funcall(block, s_widget, 1, self); - else + else { + if (! NIL_P(canvas->layout_mgr)) { + shoes_layout *lay; + Data_Get_Struct(canvas->layout_mgr, shoes_layout, lay); + fprintf(stderr, "Insert into Layout\n"); + + } else shoes_canvas_memdraw(self, block); + } canvas->insertion = -2; shoes_canvas_repaint_all(self); } @@ -855,30 +866,29 @@ VALUE shoes_canvas_widget(int argc, VALUE *argv, VALUE self) { VALUE shoes_canvas_layout(int argc, VALUE *argv, VALUE self) { rb_arg_list args; - VALUE layout; + VALUE layout_canvas; 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() + shoes_layout *lay; + Data_Get_Struct(layout_obj, shoes_layout, lay); + layout_canvas = lay->canvas; 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_ary_push(canvas->app->nesting, layout_canvas); 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_add_ele(canvas, layout_canvas); // Shoes tracks the canvas - //shoes_canvas *self_t; - //Data_Get_Struct(layout, shoes_canvas, self_t); // yes, we return the canvas, not the Layout Object - return layout; + //return layout_canvas; + return layout_obj; } void shoes_canvas_size(VALUE self, int w, int h) { diff --git a/shoes/types/layout.c b/shoes/types/layout.c index e45ff91a..82723c61 100644 --- a/shoes/types/layout.c +++ b/shoes/types/layout.c @@ -13,17 +13,33 @@ #include "shoes/types/layout.h" #include // -// Shoes::Layout needs to be a class so it can be subclassed +// Shoes::Layout needs to be a slot-like class - same api? // extern VALUE cButton, cBackground; +/* FUNC_M generate two functions here + * shoes_canvas_c_layout(int argc, VALUE *argv, VALUE self) { ..} + * + means call shoes_canvas_repaint_all() at end + * shoes_app_c_layout(int argc, VALUE *argv, VALUE self) {...} + */ 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); + cLayout = rb_define_class_under(cTypes, "Layout", cShoes); + //cLayout = rb_define_class_under(cFlow, "Layout", cShoes); + rb_define_method(cLayout, "append", CASTHOOK(shoes_layout_append), -1); // crash in shoes_canvas_memdraw + //rb_define_method(cLayout, "append", CASTHOOK(shoes_canvas_append), -1); // slot is being modified + rb_define_method(cLayout, "clear", CASTHOOK(shoes_canvas_clear_contents), -1); + rb_define_method(cLayout, "prepend", CASTHOOK(shoes_canvas_prepend), -1); + rb_define_method(cLayout, "before", CASTHOOK(shoes_canvas_before), -1); + rb_define_method(cLayout, "after", CASTHOOK(shoes_canvas_after), -1); + rb_define_method(cLayout, "rule", CASTHOOK(shoes_layout_add_rule), -1); + rb_define_method(cLayout, "finish", CASTHOOK(shoes_layout_compute), -1); + /* RUBY_M generates defines (allow Ruby to call the FUNC_M funtions + rb_define_method(cCanvas, "layout", CASTHOOK(shoes_canvas_c_layout), -1); + rb_define_method(cApp, "layout", CASTHOOK(shoes_app_c_layout), -1) + */ RUBY_M("+layout", layout, -1); } @@ -54,7 +70,7 @@ VALUE shoes_layout_new(VALUE attr, VALUE parent) { VALUE obj = shoes_layout_alloc(cLayout); shoes_layout *ly; Data_Get_Struct(obj, shoes_layout, ly); - // Most of shoes thinks its a Flow + // Most of shoes thinks its a Flow (cFlow or cLayout ?) VALUE canvas = shoes_slot_new(cFlow, attr, parent); ly->canvas = canvas; shoes_canvas *cvs; @@ -63,49 +79,102 @@ VALUE shoes_layout_new(VALUE attr, VALUE parent) { VALUE mgr; ID s_manager = rb_intern ("manager"); mgr = ATTR(attr, manager); - if (! NIL_P(mgr)) + if (! NIL_P(mgr)) { ly->delegate = mgr; + ID s_setup = rb_intern("setup"); + if (rb_respond_to(mgr, s_setup)) + rb_funcall(mgr, s_setup, 2, canvas, attr); + } cvs->layout_mgr = obj; // me + //return cvs; return obj; } -// called from inside shoes (shoes_add_ele) +VALUE shoes_layout_append(int argc, VALUE *argv, VALUE self) { + shoes_layout *lay; + Data_Get_Struct(self, shoes_layout, lay); + VALUE canvas = lay->canvas; + rb_arg_list args; + rb_parse_args(argc, argv, "o,&", &args); + shoes_canvas_insert(canvas, -1, Qnil, args.a[0]); + return self; +} + +VALUE shoes_layout_prepend(VALUE self, VALUE ele) { + shoes_layout *ly; + Data_Get_Struct(self, shoes_layout, ly); + shoes_canvas *canvas; + Data_Get_Struct(ly->canvas, shoes_canvas, canvas); + shoes_layout_add_ele(canvas, ele); +} + +// called from shoes_add_ele (def in canvas.c) by widget creators +// The ele has already been added to canvas->contents void shoes_layout_add_ele(shoes_canvas *canvas, VALUE ele) { if (rb_obj_is_kind_of(ele, cBackground)) { - fprintf(stderr, "skipping background widget\n"); + //fprintf(stderr, "skipping background widget\n"); return; } - // Find a delegate or use the Toy ? + // Find a delegate or use the internal default? 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"); + //printf(stderr,"Delegating\n"); VALUE del = ly->delegate; - ID s_addw = rb_intern("add_widget"); + ID s_addw = rb_intern("add"); if (rb_respond_to(del, s_addw)) - rb_funcall(del, s_addw, 1, ele); - //return; + rb_funcall(del, s_addw, 2, ly->canvas, ele); + else { + rb_raise( rb_eArgError, "'add' not implment in Layout"); + } + 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"); - } + } + // here if no delgate or no manager object + shoes_layout_default_add(canvas, ele); return; } -VALUE shoes_layout_delete_ele(shoes_canvas *canvas, VALUE ele) { - fprintf(stderr,"shoes_layout_delete called\n"); +// called from inside shoes (shoes_canvas_clear) +void shoes_layout_clear(shoes_canvas *canvas) { + fprintf(stderr,"shoes_layout_clear called\n"); + if (canvas->layout_mgr != Qnil) { + shoes_layout *ly; + Data_Get_Struct(canvas->layout_mgr, shoes_layout, ly); + if (! NIL_P(ly->delegate)) { + //printf(stderr,"Delegating\n"); + VALUE del = ly->delegate; + ID s_clear = rb_intern("clear"); + if (rb_respond_to(del, s_clear)) + rb_funcall(del, s_clear, 0); + else { + rb_raise( rb_eArgError, "'clear' not implment in Layout"); + } + return; + } + } + // here if no delgate or no manager object + shoes_layout_default_clear(canvas); + return; +} + +/* + * Methods to call the default layout manager - + * Might be a cassawory variant? grid_bag? Something Gtk or Cocoa? +*/ +void shoes_layout_default_add(shoes_canvas *canvas, VALUE ele) { + fprintf(stderr, "default layout add\n"); +} + +void shoes_layout_default_clear(shoes_canvas *canvas) { + fprintf(stderr, "default layout clear\n"); } -extern VALUE shoes_layout_add_rule(VALUE self, VALUE rule) { +VALUE shoes_layout_add_rule(VALUE self, VALUE rule) { fprintf(stderr,"shoes_layout_add_rule called\n"); } -extern VALUE shoes_layout_compute(VALUE self) { +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 index 982d4e83..d3d7132b 100644 --- a/shoes/types/layout.h +++ b/shoes/types/layout.h @@ -3,19 +3,27 @@ typedef struct { VALUE delegate; - VALUE canvas; - // below belongs to the C crafted default layout manager, what ever that - // is. A Toy for now. + VALUE canvas; // TODO is this used? + // fields below belong to the C crafted default layout manager, what ever that + // is. 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); +void shoes_layout_init(); +VALUE shoes_layout_new(VALUE attr, VALUE parent); +// slot like methods: +VALUE shoes_layout_append(int argc, VALUE *argv, VALUE self); +VALUE shoes_layout_prepend(VALUE self, VALUE ele); +VALUE shoes_layout_add_rule(VALUE self, VALUE rule); +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); +void shoes_layout_add_ele(shoes_canvas *canvas, VALUE ele); +void shoes_layout_clear(shoes_canvas *canvas); +VALUE shoes_layout_delete_ele(shoes_canvas *canvas, VALUE ele); +// methods for the default manager. TODO: Write it. +void shoes_layout_default_add(shoes_canvas *canvas, VALUE ele); +void shoes_layout_default_clear(shoes_canvas *canvas); #endif