GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: a tiny graphical app kit for ruby
Homepage: http://code.whytheluckystiff.net/shoes
Clone URL: git://github.com/why/shoes.git
 * static/manual.txt: added something about the `window` and `dialog` 
 methods changing self.
 * shoes/ruby.h: CHECK_HASH macro for sanitizing incoming options hashes.
why (author)
Mon Sep 29 11:31:29 -0700 2008
commit  c9a29cfa5a917e6a8b5389884abed078ba4e2d36
tree    e12c66a02128eb8aeb30afe69d3f028df26cf914
parent  97478aebbbb5ff4c8902dfea74636bcf7f1c72d6
...
116
117
118
 
119
120
121
...
116
117
118
119
120
121
122
0
@@ -116,6 +116,7 @@ shoes_app_window(int argc, VALUE *argv, VALUE self, VALUE owner)
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
   rb_iv_set(app, "@main_app", block);
0
 
0
+ CHECK_HASH(attr);
0
   app_t->owner = owner;
0
   app_t->title = ATTR(attr, title);
0
   app_t->resizable = (ATTR(attr, resizable) != Qfalse);
...
154
155
156
 
157
158
159
...
687
688
689
 
690
691
692
...
703
704
705
706
 
707
708
709
710
 
711
 
 
712
713
714
...
722
723
724
725
726
 
 
727
728
729
...
911
912
913
 
914
915
916
 
917
918
919
 
920
921
922
...
929
930
931
 
932
933
934
935
936
937
938
 
939
940
941
942
 
943
944
945
...
952
953
954
 
955
956
957
958
959
960
961
 
962
963
964
965
 
966
967
968
...
975
976
977
 
978
979
980
 
981
982
983
...
990
991
992
 
993
994
995
...
1002
1003
1004
 
1005
1006
1007
...
1010
1011
1012
1013
 
1014
1015
 
1016
1017
1018
...
1025
1026
1027
 
1028
1029
1030
 
1031
1032
1033
...
1464
1465
1466
 
1467
1468
1469
...
1480
1481
1482
 
1483
1484
1485
...
1496
1497
1498
 
1499
1500
1501
...
1513
1514
1515
1516
1517
 
1518
1519
1520
...
1529
1530
1531
 
1532
1533
1534
...
2072
2073
2074
 
2075
2076
2077
...
154
155
156
157
158
159
160
...
688
689
690
691
692
693
694
...
705
706
707
 
708
709
710
711
712
713
714
715
716
717
718
719
...
727
728
729
 
 
730
731
732
733
734
...
916
917
918
919
920
921
 
922
923
924
 
925
926
927
928
...
935
936
937
938
939
940
941
942
943
 
 
944
945
946
947
 
948
949
950
951
...
958
959
960
961
962
963
964
965
966
 
 
967
968
969
970
 
971
972
973
974
...
981
982
983
984
985
986
 
987
988
989
990
...
997
998
999
1000
1001
1002
1003
...
1010
1011
1012
1013
1014
1015
1016
...
1019
1020
1021
 
1022
1023
 
1024
1025
1026
1027
...
1034
1035
1036
1037
1038
1039
 
1040
1041
1042
1043
...
1474
1475
1476
1477
1478
1479
1480
...
1491
1492
1493
1494
1495
1496
1497
...
1508
1509
1510
1511
1512
1513
1514
...
1526
1527
1528
 
 
1529
1530
1531
1532
...
1541
1542
1543
1544
1545
1546
1547
...
2085
2086
2087
2088
2089
2090
2091
0
@@ -154,6 +154,7 @@ shoes_canvas_style(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "02", &klass, &attr);
0
+ CHECK_HASH(attr);
0
   if (!NIL_P(attr))
0
     shoes_app_style(canvas->app, klass, attr);
0
   else if (!NIL_P(klass))
0
@@ -687,6 +688,7 @@ shoes_canvas_video(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "11", &path, &attr);
0
+ CHECK_HASH(attr);
0
   video = shoes_video_new(cVideo, path, attr, self);
0
   shoes_add_ele(canvas, video);
0
   return video;
0
@@ -703,12 +705,15 @@ shoes_canvas_image(int argc, VALUE *argv, VALUE self)
0
   if (argc == 0 || (argc == 1 && rb_obj_is_kind_of(argv[0], rb_cHash)))
0
   {
0
     rb_scan_args(argc, argv, "01&", &attr, &block);
0
- if (NIL_P(attr)) attr = rb_hash_new();
0
+ CHECK_HASH(attr);
0
     _w = ATTR(attr, width);
0
     _h = ATTR(attr, height);
0
   }
0
   else
0
+ {
0
     rb_scan_args(argc, argv, "12&", &_w, &_h, &attr, &block);
0
+ CHECK_HASH(attr);
0
+ }
0
 
0
   if (NIL_P(_w) || FIXNUM_P(_w))
0
   {
0
@@ -722,8 +727,8 @@ shoes_canvas_image(int argc, VALUE *argv, VALUE self)
0
     rb_scan_args(argc, argv, "11&", &path, &attr, &block);
0
     if (!NIL_P(block))
0
     {
0
- if (NIL_P(attr)) attr = rb_hash_new();
0
- rb_hash_aset(attr, ID2SYM(s_click), block);
0
+ CHECK_HASH(attr);
0
+ ATTRSET(attr, click, block);
0
     }
0
   }
0
 
0
@@ -911,12 +916,13 @@ shoes_canvas_button(int argc, VALUE *argv, VALUE self)
0
   VALUE text, attr, block, button;
0
   SETUP();
0
   rb_scan_args(argc, argv, "11&", &text, &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (!NIL_P(text))
0
- attr = shoes_hash_set(attr, s_text, text);
0
+ ATTRSET(attr, text, text);
0
 
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_click, block);
0
+ ATTRSET(attr, click, block);
0
 
0
   button = shoes_control_new(cButton, attr, self);
0
   shoes_add_ele(canvas, button);
0
@@ -929,17 +935,17 @@ shoes_canvas_edit_line(int argc, VALUE *argv, VALUE self)
0
   VALUE phrase, attr, block, edit_line;
0
   SETUP();
0
   rb_scan_args(argc, argv, "02&", &phrase, &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (rb_obj_is_kind_of(phrase, rb_cHash))
0
     attr = phrase;
0
   else
0
   {
0
- if (NIL_P(attr)) attr = rb_hash_new();
0
- rb_hash_aset(attr, ID2SYM(s_text), phrase);
0
+ ATTRSET(attr, text, phrase);
0
   }
0
 
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_change, block);
0
+ ATTRSET(attr, change, block);
0
 
0
   edit_line = shoes_control_new(cEditLine, attr, self);
0
   shoes_add_ele(canvas, edit_line);
0
@@ -952,17 +958,17 @@ shoes_canvas_edit_box(int argc, VALUE *argv, VALUE self)
0
   VALUE phrase, attr, block, edit_box;
0
   SETUP();
0
   rb_scan_args(argc, argv, "02&", &phrase, &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (rb_obj_is_kind_of(phrase, rb_cHash))
0
     attr = phrase;
0
   else
0
   {
0
- if (NIL_P(attr)) attr = rb_hash_new();
0
- rb_hash_aset(attr, ID2SYM(s_text), phrase);
0
+ ATTRSET(attr, text, phrase);
0
   }
0
 
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_change, block);
0
+ ATTRSET(attr, change, block);
0
 
0
   edit_box = shoes_control_new(cEditBox, attr, self);
0
   shoes_add_ele(canvas, edit_box);
0
@@ -975,9 +981,10 @@ shoes_canvas_list_box(int argc, VALUE *argv, VALUE self)
0
   VALUE attr, block, list_box;
0
   SETUP();
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_change, block);
0
+ ATTRSET(attr, change, block);
0
 
0
   list_box = shoes_control_new(cListBox, attr, self);
0
   shoes_add_ele(canvas, list_box);
0
@@ -990,6 +997,7 @@ shoes_canvas_progress(int argc, VALUE *argv, VALUE self)
0
   VALUE attr, progress;
0
   SETUP();
0
   rb_scan_args(argc, argv, "01", &attr);
0
+ CHECK_HASH(attr);
0
 
0
   progress = shoes_control_new(cProgress, attr, self);
0
   shoes_add_ele(canvas, progress);
0
@@ -1002,6 +1010,7 @@ shoes_canvas_radio(int argc, VALUE *argv, VALUE self)
0
   VALUE group, attr, block, radio;
0
   SETUP();
0
   rb_scan_args(argc, argv, "02&", &group, &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (rb_obj_is_kind_of(group, rb_cHash))
0
   {
0
@@ -1010,9 +1019,9 @@ shoes_canvas_radio(int argc, VALUE *argv, VALUE self)
0
   }
0
 
0
   if (!NIL_P(group))
0
- attr = shoes_hash_set(attr, s_group, group);
0
+ ATTRSET(attr, group, group);
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_click, block);
0
+ ATTRSET(attr, click, block);
0
 
0
   radio = shoes_control_new(cRadio, attr, self);
0
   shoes_add_ele(canvas, radio);
0
@@ -1025,9 +1034,10 @@ shoes_canvas_check(int argc, VALUE *argv, VALUE self)
0
   VALUE attr, block, check;
0
   SETUP();
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
+ CHECK_HASH(attr);
0
 
0
   if (!NIL_P(block))
0
- attr = shoes_hash_set(attr, s_click, block);
0
+ ATTRSET(attr, click, block);
0
 
0
   check = shoes_control_new(cCheck, attr, self);
0
   shoes_add_ele(canvas, check);
0
@@ -1464,6 +1474,7 @@ shoes_canvas_flow(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
+ CHECK_HASH(attr);
0
   flow = shoes_flow_new(attr, self);
0
   if (!NIL_P(block))
0
   {
0
@@ -1480,6 +1491,7 @@ shoes_canvas_stack(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
+ CHECK_HASH(attr);
0
   stack = shoes_stack_new(attr, self);
0
   if (!NIL_P(block))
0
   {
0
@@ -1496,6 +1508,7 @@ shoes_canvas_mask(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "01&", &attr, &block);
0
+ CHECK_HASH(attr);
0
   mask = shoes_mask_new(attr, self);
0
   if (!NIL_P(block))
0
   {
0
@@ -1513,8 +1526,7 @@ shoes_canvas_widget(int argc, VALUE *argv, VALUE self)
0
 
0
   rb_scan_args(argc, argv, "1*", &klass, &args);
0
   attr = rb_ary_pop(args);
0
- if (!rb_obj_is_kind_of(attr, rb_cHash))
0
- attr = Qnil;
0
+ CHECK_HASH(attr);
0
 
0
   widget = shoes_widget_new(klass, attr, self);
0
   DRAW(widget, canvas->app, ts_funcall2(widget, rb_intern("initialize"), argc - 1, argv + 1));
0
@@ -1529,6 +1541,7 @@ shoes_canvas_download(int argc, VALUE *argv, VALUE self)
0
   SETUP();
0
 
0
   rb_scan_args(argc, argv, "11&", &url, &attr, &block);
0
+ CHECK_HASH(attr);
0
   if (!NIL_P(block))
0
     ATTRSET(attr, finish, block);
0
   obj = shoes_download_threaded(self, url, attr);
0
@@ -2072,6 +2085,7 @@ shoes_canvas_window(int argc, VALUE *argv, VALUE self)
0
     return shoes_app_window(argc, argv, cApp, canvas->app->self);
0
 
0
   rb_scan_args(argc, argv, "02&", &uri, &attr, &block);
0
+ CHECK_HASH(attr);
0
   if (rb_obj_is_kind_of(uri, rb_cHash))
0
   {
0
     attr = uri;
...
242
243
244
245
 
246
247
248
...
1519
1520
1521
 
1522
1523
1524
...
1720
1721
1722
 
1723
1724
1725
...
3397
3398
3399
 
3400
3401
3402
...
242
243
244
 
245
246
247
248
...
1519
1520
1521
1522
1523
1524
1525
...
1721
1722
1723
1724
1725
1726
1727
...
3399
3400
3401
3402
3403
3404
3405
0
@@ -242,7 +242,7 @@ shoes_hash_get(VALUE hsh, ID key)
0
 {
0
   VALUE v;
0
 
0
- if (!NIL_P(hsh))
0
+ if (TYPE(hsh) == T_HASH)
0
   {
0
     v = rb_hash_aref(hsh, ID2SYM(key));
0
     if (!NIL_P(v)) return v;
0
@@ -1519,6 +1519,7 @@ shoes_pattern_args(int argc, VALUE *argv, VALUE self)
0
 {
0
   VALUE source, attr;
0
   rb_scan_args(argc, argv, "11", &source, &attr);
0
+ CHECK_HASH(attr);
0
   return shoes_pattern_new(cPattern, source, attr, Qnil);
0
 }
0
 
0
@@ -1720,6 +1721,7 @@ shoes_color_gradient(int argc, VALUE *argv, VALUE self)
0
   VALUE obj, r1, r2;
0
   VALUE attr = Qnil;
0
   rb_scan_args(argc, argv, "21", &r1, &r2, &attr);
0
+ CHECK_HASH(attr);
0
 
0
   obj = shoes_pattern_alloc(cPattern);
0
   Data_Get_Struct(obj, shoes_pattern, pattern);
0
@@ -3397,6 +3399,7 @@ shoes_radio_draw(VALUE self, VALUE c, VALUE actual)
0
     VALUE attr; \
0
     GET_STRUCT(ele, self_t); \
0
     rb_scan_args(argc, argv, "01", &attr); \
0
+ CHECK_HASH(attr); \
0
     if (!NIL_P(attr)) \
0
     { \
0
       if (NIL_P(self_t->attr)) self_t->attr = rb_hash_new(); \
...
114
115
116
 
117
118
119
...
114
115
116
117
118
119
120
0
@@ -114,6 +114,7 @@ void shoes_ruby_init(void);
0
 //
0
 // Common funcs for dealing with attribute hashes
0
 //
0
+#define CHECK_HASH(hsh) if (TYPE(hsh) != T_HASH) { hsh = Qnil; }
0
 #define ATTR(attr, n) shoes_hash_get(attr, s_##n)
0
 #define PX(attr, n, dn, pn) shoes_px(shoes_hash_get(attr, s_##n), dn, pn, 1)
0
 #define PXN(attr, n, dn, pn) shoes_px(shoes_hash_get(attr, s_##n), dn, pn, 0)
...
139
140
141
 
 
 
 
 
 
 
 
 
 
 
 
 
142
143
144
...
201
202
203
204
 
205
206
207
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
214
215
216
 
217
218
219
220
0
@@ -139,6 +139,19 @@ All of the `self`s in the above example are the App object. Shoes uses Ruby's `
0
 
0
 These instance variables will all end up inside the App object.
0
 
0
+'''Whenever you create a new window, `self` is also changed.''' So, this means the [[Element.window]] and [[Element.dialog]] methods, in addition to Shoes.app.
0
+
0
+{{{
0
+ Shoes.app :title => "MAIN" do
0
+ para self
0
+ button "Spawn" do
0
+ window :title => "CHILD" do
0
+ para self
0
+ end
0
+ end
0
+ end
0
+}}}
0
+
0
 ==== Block Redirection ====
0
 
0
 The `stack` block is a different story, though. It doesn't change `self` and it's basically a regular block.
0
@@ -201,7 +214,7 @@ As you can imagine, the `app` object changes `self` to the App object.
0
 
0
 So the rules here are:
0
 
0
-1. '''Methods named "app" change self to the App object.'''[[BR]](This is true for both Shoes.app and Slot.app.)[[BR]]2. '''Blocks attached to stacks, flows or any manipulation method (such as append) do not change self. Instead, they pop the slot on to the app's editing stack.'''
0
+1. '''Methods named "app" or which create new windows alter `self` to the App object.'''[[BR]](This is true for both Shoes.app and Slot.app, as well as [[Element.window]] and [[Element.dialog]].)[[BR]]2. '''Blocks attached to stacks, flows or any manipulation method (such as append) do not change self. Instead, they pop the slot on to the app's editing stack.'''
0
 
0
 ==== Careful With Fixed Heights ====
0
 

Comments

    No one has commented yet.