diff --git a/.gitignore b/.gitignore index bb211efd..bde49e86 100644 --- a/.gitignore +++ b/.gitignore @@ -15,14 +15,10 @@ Makefile VERSION.txt *-custom.yaml Shoes3.2.geany -crosscompile bin/main.c shoes/version.h -deps -dist pkg notes -/i686-linux /x86_64-linux /xarmv6hf /xwin7 @@ -40,3 +36,4 @@ req/json /qtifw *.orig cshoes +Gemfile.lock diff --git a/Tests/plot/manual.rb b/Tests/plot/manual.rb new file mode 100644 index 00000000..3519ecfa --- /dev/null +++ b/Tests/plot/manual.rb @@ -0,0 +1,40 @@ +# two graphs - line and bar +Shoes.app width: 800, height: 500 do + @values1 = [24, 22, 10, 13, 20, 8, 22] + @x_axis1 = ['a','b','c','d','e','f', 'g'] + @values2 = [200, 150, 75, 125, 75, 225, 125] + @x_axis2 = ['a','b','c','d','e','f', 'g'] + stack do + para "Plot Demo Line and Column" + flow do + button "quit" do Shoes.quit end + end + widget_width = 400 + widget_height = 300 + stack do + flow do + @grf = plot widget_width, widget_height, title: "My Graph", caption: + "Look at that! Booyah!!" , font: "Helvetica", auto_grid: true, + default: "skip", background: honeydew + @grf2 = plot widget_width, widget_height+100, title: "Column Graph", caption: + "Amazing!!" , font: "Mono", auto_grid: false, + default: "skip", background: cornsilk, chart: "column", boundary_box: false + end + end + @grf.add values: @values1, labels: @x_axis1, + name: "foobar", min: 6, max: 26 , desc: "foobar Yy", color: dodgerblue, + points: true + @grf.add values: @values2, labels: @x_axis2, + name: "Tab", min: @values2.min, max: @values2.max, desc: "BarTab", color: coral, + points: true, strokewidth: 2 + + @grf2.add values: @values1, labels: @x_axis1, + name: "Bar", min: 0, max: 30, desc: "foobar Yy", color: rgb(220, 20, 60), + points: true, strokewidth: 12 + cs2 = chart_series values: @values2, labels: @x_axis2, + name: "Tab", min: 50, max: 230, desc: "BarTab", color: green, + points: true, strokewidth: 6 + @grf2.add cs2 + end +end + diff --git a/shoes/native/cocoa.h b/shoes/native/cocoa.h index 1804add5..633be9fd 100644 --- a/shoes/native/cocoa.h +++ b/shoes/native/cocoa.h @@ -51,7 +51,7 @@ void create_window_menu(NSMenu *main); void create_help_menu(NSMenu *main); void shoes_native_view_supplant(NSView *from, NSView *to); void gettimeofday(void *ts, void *extra); - +NSMutableDictionary *shoes_attr_dict(VALUE attr); #define VK_ESCAPE 53 #define VK_DELETE 117 diff --git a/shoes/native/cocoa.m b/shoes/native/cocoa.m index f50b14c9..765b15c8 100644 --- a/shoes/native/cocoa.m +++ b/shoes/native/cocoa.m @@ -1373,3 +1373,71 @@ void shoes_native_app_window_move(shoes_app *app, int x, int y) { //NSLog(@"real pos %i,%i return y: %i", (int)frame.origin.x, (int)frame.origin.y, app->y); } + +/* + * Helper function to return a NSDict for use in AttributedString creation + * input is the Shoes attrs (font and stroke) +*/ +NSMutableDictionary *shoes_attr_dict(VALUE attr) { + char *fntstr = 0; + VALUE fgclr = Qnil; // Could be hex color string or Shoes color object + NSInteger fsize = 0; + NSArray *fontsettings; + NSMutableDictionary *dict = NULL; + NSMutableString *fontname = [[NSMutableString alloc] initWithCapacity: 40]; + + + // get the Shoes attributes + if (!NIL_P(shoes_hash_get(attr, rb_intern("font")))) { + fntstr = RSTRING_PTR(shoes_hash_get(attr, rb_intern("font"))); + NSString *fstr = [NSString stringWithUTF8String: fntstr]; + fontsettings = [fstr componentsSeparatedByString:@" "]; + // in OSX there is font name - may include Bold etc, and size + int cnt = fontsettings.count; + fsize = [fontsettings[cnt-1] integerValue]; + if (fsize > 0 && fsize < 24) { + //we probably have a size spec - everything before that is fontname + int i; + for (i = 0; i < cnt-1; i++) { + [fontname appendString: fontsettings[i]]; + if (i < cnt-2) { + [fontname appendString:@" "]; + } + } + } else { + // have to assume they didn't give a point size so + [fontname appendString: fstr]; + fsize = 10; + } + } + if (!NIL_P(shoes_hash_get(attr, rb_intern("stroke")))) { + fgclr = shoes_hash_get(attr, rb_intern("stroke")); + } + if (fntstr || !NIL_P(fgclr)) { + dict = [[NSMutableDictionary alloc] initWithCapacity: 5]; + //NSString *title = [NSString stringWithUTF8String: msg]; + if (fntstr) { + NSFont *font = [NSFont fontWithName: fontname size: fsize]; + if (font == nil) + // Don't do this : rb_raise(rb_eArgError, "Font \"%s\" not found", fntstr); + font = [NSFont fontWithName: @"arial" size: 12]; + [dict setObject: font forKey: NSFontAttributeName]; + } + if (! NIL_P(fgclr)) { + // convert Shoes color to NSColor + if (TYPE(fgclr) == T_STRING) + fgclr = shoes_color_parse(cColor, fgclr); // convert string to cColor + if (rb_obj_is_kind_of(fgclr, cColor)) + { + shoes_color *color; + Data_Get_Struct(fgclr, shoes_color, color); + CGFloat rg = (CGFloat)color->r / 255; + CGFloat gb = (CGFloat)color->g / 255; + CGFloat bb = (CGFloat)color->b / 255; + NSColor *clr = [NSColor colorWithCalibratedRed: rg green: gb blue: bb alpha: 1.0]; + [dict setObject: clr forKey: NSForegroundColorAttributeName]; + } + } + } + return dict; +} diff --git a/shoes/native/cocoa/listbox.h b/shoes/native/cocoa/listbox.h index c5d2f297..003278df 100644 --- a/shoes/native/cocoa/listbox.h +++ b/shoes/native/cocoa/listbox.h @@ -2,5 +2,7 @@ @interface ShoesPopUpButton : NSPopUpButton { VALUE object; +@public + NSMutableDictionary *attrs; } @end diff --git a/shoes/native/cocoa/listbox.m b/shoes/native/cocoa/listbox.m index 193643ac..ba234770 100644 --- a/shoes/native/cocoa/listbox.m +++ b/shoes/native/cocoa/listbox.m @@ -28,6 +28,7 @@ - (id)initWithFrame: (NSRect)frame andObject: (VALUE)o if ((self = [super initWithFrame: frame pullsDown: NO])) { object = o; + attrs = NULL; [self setTarget: self]; [self setAction: @selector(handleChange:)]; } @@ -49,6 +50,9 @@ -(IBAction)handleChange: (id)sender NSMakeRect(place->ix + place->dx, place->iy + place->dy, place->ix + place->dx + place->iw, place->iy + place->dy + place->ih) andObject: self]; + + pop->attrs = shoes_attr_dict(attr); + // Tooltip VALUE vtip = shoes_hash_get(attr, rb_intern("tooltip")); if (! NIL_P(vtip)) { @@ -66,16 +70,38 @@ -(IBAction)handleChange: (id)sender { long i; ShoesPopUpButton *pop = (ShoesPopUpButton *)ref; - COCOA_DO({ + INIT; + if (pop->attrs) { + // Need to use menu_items to set AttributedStrings + // TODO: probably too complicated - but it works [pop removeAllItems]; - for (i = 0; i < RARRAY_LEN(ary); i++) - { + NSString *emptystr = @""; + int icnt = RARRAY_LEN(ary); + NSArray *itemAry = [pop itemArray]; + for (i = 0; i < icnt; i++) { VALUE msg_s = shoes_native_to_s(rb_ary_entry(ary, i)); char *msg = RSTRING_PTR(msg_s); - [[pop menu] insertItemWithTitle: [NSString stringWithUTF8String: msg] action: nil - keyEquivalent: @"" atIndex: i]; + NSString *str = [NSString stringWithUTF8String: msg]; + NSAttributedString *astr = [[NSAttributedString alloc] initWithString: str + attributes: pop->attrs]; + //printf(stderr,"Colorize %s\n", msg); // C string + [[pop menu] insertItemWithTitle: str action: nil + keyEquivalent: @"" atIndex: i]; + itemAry = [pop itemArray]; + NSMenuItem *mitem = itemAry[i]; + [mitem setAttributedTitle: astr]; } - }); + } else { + [pop removeAllItems]; + for (i = 0; i < RARRAY_LEN(ary); i++) { + VALUE msg_s = shoes_native_to_s(rb_ary_entry(ary, i)); + char *msg = RSTRING_PTR(msg_s); + NSString *str = [NSString stringWithUTF8String: msg]; + [[pop menu] insertItemWithTitle: str action: nil + keyEquivalent: @"" atIndex: i]; + } + } + RELEASE; } VALUE diff --git a/shoes/native/cocoa/switch.h b/shoes/native/cocoa/switch.h index 3ee9edf6..0f4e478c 100644 --- a/shoes/native/cocoa/switch.h +++ b/shoes/native/cocoa/switch.h @@ -2,5 +2,7 @@ @interface ShoesSwitch : NSButton { VALUE object; +@public + NSMutableDictionary *attrs; } @end diff --git a/shoes/native/cocoa/switch.m b/shoes/native/cocoa/switch.m index b7629925..46417420 100644 --- a/shoes/native/cocoa/switch.m +++ b/shoes/native/cocoa/switch.m @@ -36,6 +36,7 @@ - (id)initWithType: (NSButtonType)t andObject: (VALUE)o if ((self = [super init])) { object = o; + attrs = NULL; [self setButtonType: t]; [self setBezelStyle: NSRoundedBezelStyle]; [self setTarget: self]; @@ -61,14 +62,31 @@ -(IBAction)handleClick: (id)sender INIT; ShoesSwitch *button = [[ShoesSwitch alloc] initWithType: NSToggleButton andObject: self]; - [button setTitle: @"Off"]; - [button setAlternateTitle: @"On"]; + button->attrs = shoes_attr_dict(attr); + if (button->attrs) { + [button setAttributedTitle: [[NSAttributedString alloc] initWithString: @"Off" + attributes: button->attrs]]; + [button setAttributedAlternateTitle: [[NSAttributedString alloc] initWithString: @"On" + attributes: button->attrs]]; + } + else { + [button setTitle: @"Off"]; + [button setAlternateTitle: @"On"]; + } if (!NIL_P(shoes_hash_get(attr, rb_intern("active")))) { VALUE bstv = shoes_hash_get(attr, rb_intern("active")); button.state = !NIL_P(bstv) ? NSOnState : NSOffState; //fprintf(stderr, "have a initial active %li\n",button.state); } - //button->sw_state = button.state; //property -> instance_var + + // Tooltip + VALUE vtip = shoes_hash_get(attr, rb_intern("tooltip")); + if (! NIL_P(vtip)) { + char *cstr = RSTRING_PTR(vtip); + NSString *tip = [NSString stringWithUTF8String: cstr]; + [button setToolTip:tip]; + } + RELEASE; return (SHOES_CONTROL_REF) button; } diff --git a/shoes/native/gtk.c b/shoes/native/gtk.c index 8fd45f29..84052c76 100644 --- a/shoes/native/gtk.c +++ b/shoes/native/gtk.c @@ -1476,3 +1476,47 @@ void shoes_css_parse_error (GtkCssProvider *provider, { fprintf(stderr,"css parse error\n"); } + +void shoes_css_apply(GtkWidget *widget, VALUE attr, char *css_template) +{ + // default css values + char *font = "Arial 12"; + char color[40] = "black"; + int do_sub = 0; + int have_color = 0; + VALUE vclr = Qnil; + VALUE vfont = ATTR(attr, font); + if (! NIL_P(vfont)) { + font = RSTRING_PTR(vfont); + do_sub = 1; + } + if (RTEST(ATTR(attr, stroke))) { + vclr = (ATTR(attr, stroke)); + // That's a Shoes color turn it into a css rgba + + shoes_color *scolor; + Data_Get_Struct(vclr, shoes_color, scolor); + sprintf(color, "rgba(%d,%d,%d,%d)", scolor->r, scolor->g, scolor->b, + scolor->a); + do_sub = 1; + } + if (do_sub) { + /* Change default font and color through widget css */ + GtkCssProvider *provider; + GtkStyleContext *context; + char new_css[100]; + sprintf(new_css, css_template, font, color); + //printf("css: %s", new_css); + provider = gtk_css_provider_new (); + g_signal_connect(G_OBJECT(provider), "parsing-error", + G_CALLBACK(shoes_css_parse_error), + (gpointer)NULL); + gtk_css_provider_load_from_data(provider, new_css, -1, NULL); + context = gtk_widget_get_style_context (widget); + gtk_style_context_add_provider (context, + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + // check what's really in provider ? + //printf("provider has: %s\n", gtk_css_provider_to_string(provider)); + } +} diff --git a/shoes/native/gtk.h b/shoes/native/gtk.h index 82ad2feb..70954fb0 100644 --- a/shoes/native/gtk.h +++ b/shoes/native/gtk.h @@ -6,3 +6,4 @@ void shoes_css_parse_error (GtkCssProvider *provider, GtkCssSection *section, GError *error, gpointer user_data); +void shoes_css_apply(GtkWidget *widget, VALUE attr, char *css_template); diff --git a/shoes/native/gtk/gtkeditbox.c b/shoes/native/gtk/gtkeditbox.c index 09502523..3513dbf5 100644 --- a/shoes/native/gtk/gtkeditbox.c +++ b/shoes/native/gtk/gtkeditbox.c @@ -24,81 +24,16 @@ SHOES_CONTROL_REF shoes_native_edit_box(VALUE self, shoes_canvas *canvas, shoes_ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ref), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(ref), textview); - // default css values - char *font = "Arial 12"; - char color[40] = "black"; - int do_sub = 0; - int have_color = 0; - VALUE vclr = Qnil; - VALUE vfont = ATTR(attr, font); - if (! NIL_P(vfont)) { - font = RSTRING_PTR(vfont); - do_sub = 1; - } - if (RTEST(ATTR(attr, stroke))) { - vclr = (ATTR(attr, stroke)); - // That's a Shoes color turn it into a css rgba + // change font and color/stroke + shoes_css_apply((GtkWidget*)textview, attr, css_template); - shoes_color *scolor; - Data_Get_Struct(vclr, shoes_color, scolor); - sprintf(color, "rgba(%d,%d,%d,%d)", scolor->r, scolor->g, scolor->b, - scolor->a); - do_sub = 1; - } - if (do_sub) { - /* Change default font and color through widget css */ - GtkCssProvider *provider; - GtkStyleContext *context; - char new_css[100]; - sprintf(new_css, css_template, font, color); - //printf("css: %s", new_css); - provider = gtk_css_provider_new (); - g_signal_connect(G_OBJECT(provider), "parsing-error", - G_CALLBACK(shoes_css_parse_error), - (gpointer)self); - gtk_css_provider_load_from_data(provider, new_css, -1, NULL); - context = gtk_widget_get_style_context (textview); - gtk_style_context_add_provider (context, - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - // check what's really in provider ? - //printf("provider has: %s\n", gtk_css_provider_to_string(provider)); - } -#if 0 // old code - if (RTEST(ATTR(attr, font))) { - char *fontstr = RSTRING_PTR(ATTR(attr, font)); - PangoFontDescription *fontdesc = NULL; - fontdesc = pango_font_description_from_string(fontstr); - // deprecated in gtk 3.16 - use private css - ugh. - gtk_widget_override_font(ref, fontdesc); - - } - if (RTEST(ATTR(attr, stroke))) { - VALUE fgclr = ATTR(attr, stroke); - if (TYPE(fgclr) == T_STRING) - fgclr = shoes_color_parse(cColor, fgclr); // convert string to cColor - if (rb_obj_is_kind_of(fgclr, cColor)) { - shoes_color *color; - Data_Get_Struct(fgclr, shoes_color, color); - GdkRGBA gclr; - gclr.red = color->r / 255.0; - gclr.green = color->g / 255.0; - gclr.blue = color->b / 255.0; - gclr.alpha = color->a / 255.0; - // override color doesn't work, deprecated if it did. - gtk_widget_override_color(ref, GTK_STATE_FLAG_NORMAL, &gclr); - } - } -#endif if (!NIL_P(shoes_hash_get(attr, rb_intern("tooltip")))) { gtk_widget_set_tooltip_text(GTK_WIDGET(ref), RSTRING_PTR(shoes_hash_get(attr, rb_intern("tooltip")))); } - g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(shoes_widget_changed), (gpointer)self); - return ref; } diff --git a/shoes/native/gtk/gtkeditline.c b/shoes/native/gtk/gtkeditline.c index 9a43c273..9924d175 100644 --- a/shoes/native/gtk/gtkeditline.c +++ b/shoes/native/gtk/gtkeditline.c @@ -6,37 +6,18 @@ #include "shoes/types/native.h" #include "shoes/types/color.h" #include "shoes/internal.h" - +#include "shoes/native/gtk.h" #include "shoes/native/gtk/gtkentryalt.h" #include "shoes/native/gtk/gtkeditline.h" extern VALUE cColor; +static char *css_template = "GtkEntry {\n font: %s;\n color: %s;\n}\n"; + SHOES_CONTROL_REF shoes_native_edit_line(VALUE self, shoes_canvas *canvas, shoes_place *place, VALUE attr, char *msg) { SHOES_CONTROL_REF ref = gtk_entry_alt_new(); if (RTEST(ATTR(attr, secret))) shoes_native_secrecy(ref); - - if (RTEST(ATTR(attr, font))) { - char *fontstr = RSTRING_PTR(ATTR(attr, font)); - PangoFontDescription *fontdesc = NULL; - fontdesc = pango_font_description_from_string(fontstr); - // deprecated in gtk 3.16 - use private css - ugh. - gtk_widget_override_font(ref, fontdesc); - } - if (RTEST(ATTR(attr, stroke))) { - VALUE fgclr = ATTR(attr, stroke); - if (TYPE(fgclr) == T_STRING) - fgclr = shoes_color_parse(cColor, fgclr); // convert string to cColor - if (rb_obj_is_kind_of(fgclr, cColor)) { - shoes_color *color; - Data_Get_Struct(fgclr, shoes_color, color); - GdkRGBA gclr; - gclr.red = color->r / 255.0; - gclr.green = color->g / 255.0; - gclr.blue = color->b / 255.0; - gclr.alpha = color->a / 255.0; - gtk_widget_override_color(ref, GTK_STATE_FLAG_NORMAL, &gclr); - } - } + // appy font and stoke color via css + shoes_css_apply((GtkWidget*)ref, attr, css_template); if (!NIL_P(shoes_hash_get(attr, rb_intern("tooltip")))) { gtk_widget_set_tooltip_text(GTK_WIDGET(ref), RSTRING_PTR(shoes_hash_get(attr, rb_intern("tooltip")))); diff --git a/shoes/native/gtk/gtkswitch.c b/shoes/native/gtk/gtkswitch.c index e3218ca1..045f7a3c 100644 --- a/shoes/native/gtk/gtkswitch.c +++ b/shoes/native/gtk/gtkswitch.c @@ -18,46 +18,8 @@ SHOES_CONTROL_REF shoes_native_switch(VALUE self, shoes_canvas *canvas, shoes_pl gtk_switch_set_active(GTK_SWITCH(ref), shoes_hash_get(attr, rb_intern("active")) == Qtrue); } // change font and color/stroke + shoes_css_apply((GtkWidget*)ref, attr, css_template); - // default css values - char *font = "Arial 12"; - char color[40] = "black"; - int do_sub = 0; - int have_color = 0; - VALUE vclr = Qnil; - VALUE vfont = ATTR(attr, font); - if (! NIL_P(vfont)) { - font = RSTRING_PTR(vfont); - do_sub = 1; - } - if (RTEST(ATTR(attr, stroke))) { - vclr = (ATTR(attr, stroke)); - // Thatis a Shoes color, turn it into a css rgba - shoes_color *scolor; - Data_Get_Struct(vclr, shoes_color, scolor); - sprintf(color, "rgba(%d,%d,%d,%d)", scolor->r, scolor->g, scolor->b, - scolor->a); - do_sub = 1; - } - if (do_sub) { - /* Change default font and color through widget css */ - GtkCssProvider *provider; - GtkStyleContext *context; - char new_css[100]; - sprintf(new_css, css_template, font, color); - //printf("css: %s", new_css); - provider = gtk_css_provider_new (); - g_signal_connect(G_OBJECT(provider), "parsing-error", - G_CALLBACK(shoes_css_parse_error), - (gpointer)self); - gtk_css_provider_load_from_data(provider, new_css, -1, NULL); - context = gtk_widget_get_style_context ((GtkWidget *)ref); - gtk_style_context_add_provider (context, - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - // check what's really in provider ? - //printf("provider has: %s\n", gtk_css_provider_to_string(provider)); - } if (!NIL_P(shoes_hash_get(attr, rb_intern("tooltip")))) { gtk_widget_set_tooltip_text(GTK_WIDGET(ref), RSTRING_PTR(shoes_hash_get(attr, rb_intern("tooltip")))); }