diff --git a/ROADMAP.md b/ROADMAP.md index de92370027..9b24a153fc 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -43,8 +43,9 @@ - [ ] 64/32 bit int depending on arch (will remove array.len limitation on 64 bit systems) - [ ] `copy()` builtin function (e.g. for easier conversion from `[]Foo` to `[4]Foo`) - [x] Lambdas: `a.sort(|a, b| a > b)` -- [ ] Custom attributes. +- [ ] Custom attributes - [ ] `arr.first() or { }` like `arr[0] or { }` +- [ ] ORM migrations ## [Version 1.0] diff --git a/vlib/gg/draw.c.v b/vlib/gg/draw.c.v index 7ad122cf75..876aad3850 100644 --- a/vlib/gg/draw.c.v +++ b/vlib/gg/draw.c.v @@ -219,7 +219,7 @@ pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) { sgl.end() } -enum PaintStyle { +pub enum PaintStyle { fill stroke } diff --git a/vlib/gg/gg.c.v b/vlib/gg/gg.c.v index 71776d364e..eecb238093 100644 --- a/vlib/gg/gg.c.v +++ b/vlib/gg/gg.c.v @@ -720,6 +720,11 @@ pub fn window_size() Size { return Size{int(sapp.width() / s), int(sapp.height() / s)} } +// set_window_title sets main window's title +pub fn set_window_title(title string) { + C.sapp_set_window_title(title.str) +} + // window_size_real_pixels returns the `Size` of the active window without scale pub fn window_size_real_pixels() Size { return Size{sapp.width(), sapp.height()} diff --git a/vlib/gg/image.c.v b/vlib/gg/image.c.v index 596a637472..6f8d12ffc6 100644 --- a/vlib/gg/image.c.v +++ b/vlib/gg/image.c.v @@ -283,45 +283,47 @@ pub struct StreamingImageConfig { // provided image should be drawn onto the screen pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) { $if macos { - unsafe { - mut img := config.img - if config.img == nil { - // Get image by id - if config.img_id > 0 { - img = &ctx.image_cache[config.img_id] - } else { - eprintln('gg: failed to get image to draw natively') + if ctx.native_rendering { + unsafe { + mut img := config.img + if config.img == nil { + // Get image by id + if config.img_id > 0 { + img = &ctx.image_cache[config.img_id] + } else { + eprintln('gg: failed to get image to draw natively') + return + } + } + if img.id >= ctx.image_cache.len { + eprintln('gg: draw_image() bad img id ${img.id} (img cache len = ${ctx.image_cache.len})') return } - } - if img.id >= ctx.image_cache.len { - eprintln('gg: draw_image() bad img id ${img.id} (img cache len = ${ctx.image_cache.len})') - return - } - if ctx.native_rendering { - if img.width == 0 { - println('w=0') + if ctx.native_rendering { + if img.width == 0 { + println('w=0') + return + } + if !os.exists(img.path) { + println('not exist path') + return + } + x := config.img_rect.x + y := config.img_rect.y + width := if config.img_rect.width == 0 { + f32(img.width) + } else { + config.img_rect.width + } + height := if config.img_rect.height == 0 { + f32(img.height) + } else { + config.img_rect.height + } + C.darwin_draw_image(x, ctx.height - (y + config.img_rect.height), + width, height, img) return } - if !os.exists(img.path) { - println('not exist path') - return - } - x := config.img_rect.x - y := config.img_rect.y - width := if config.img_rect.width == 0 { - f32(img.width) - } else { - config.img_rect.width - } - height := if config.img_rect.height == 0 { - f32(img.height) - } else { - config.img_rect.height - } - C.darwin_draw_image(x, ctx.height - (y + config.img_rect.height), width, - height, img) - return } } } diff --git a/vlib/gg/text_rendering.c.v b/vlib/gg/text_rendering.c.v index 70a0f2de59..0f7b37709b 100644 --- a/vlib/gg/text_rendering.c.v +++ b/vlib/gg/text_rendering.c.v @@ -147,6 +147,37 @@ pub fn (ctx &Context) set_text_cfg(cfg gx.TextCfg) { ctx.ft.fons.vert_metrics(&ascender, &descender, &lh) } +@[params] +pub struct DrawTextParams { + x int + y int + text string + + color Color = gx.black + size int = 16 + align gx.HorizontalAlign = .left + vertical_align gx.VerticalAlign = .top + max_width int + family string + bold bool + mono bool + italic bool +} + +pub fn (ctx &Context) draw_text2(p DrawTextParams) { + ctx.draw_text(p.x, p.y, p.text, gx.TextCfg{ + color: p.color + size: p.size + align: p.align + vertical_align: p.vertical_align + max_width: p.max_width + family: p.family + bold: p.bold + mono: p.mono + italic: p.italic + }) // TODO perf once it's the only function to draw text +} + // draw_text draws the string in `text_` starting at top-left position `x`,`y`. // Text settings can be provided with `cfg`. pub fn (ctx &Context) draw_text(x int, y int, text_ string, cfg gx.TextCfg) { diff --git a/vlib/gx/color.v b/vlib/gx/color.v index 8f72a27777..f30d8f8cf9 100644 --- a/vlib/gx/color.v +++ b/vlib/gx/color.v @@ -123,6 +123,7 @@ pub mut: } // hex takes in a 32 bit integer and splits it into 4 byte values +/* pub fn hex(color int) Color { return Color{ r: u8((color >> 24) & 0xFF) @@ -131,6 +132,14 @@ pub fn hex(color int) Color { a: u8(color & 0xFF) } } +*/ +pub fn hex(color int) Color { + return Color{ + r: u8((color >> 16) & 0xFF) + g: u8((color >> 8) & 0xFF) + b: u8((color >> 0) & 0xFF) + } +} // rgb builds a Color instance from given r, g, b values pub fn rgb(r u8, g u8, b u8) Color { @@ -298,9 +307,14 @@ const ( ) // color_from_string returns a Color, corresponding to the given string -// or black Color if string is not found in lookup table +// or black Color if string is not found in lookup table, or a hex color if starting with # pub fn color_from_string(s string) Color { - return gx.string_colors[s] + if s.starts_with('#') { + mut hex_str := '0x' + s[1..] + return hex(hex_str.int()) + } else { + return gx.string_colors[s] + } } // to_css_string returns a CSS compatible string e.g. `rgba(10,11,12,13)` of the color `c`. diff --git a/vlib/gx/color_test.v b/vlib/gx/color_test.v index 603af884d4..93836aac47 100644 --- a/vlib/gx/color_test.v +++ b/vlib/gx/color_test.v @@ -2,13 +2,13 @@ import gx fn test_hex() { // valid colors - a := gx.hex(0x6c5ce7ff) - b := gx.rgba(108, 92, 231, 255) - assert a == b + // a := gx.hex(0x6c5ce7ff) + // b := gx.rgba(108, 92, 231, 255) + assert gx.hex(0xff6600) == gx.rgb(255, 102, 0) // orange // doesn't give right value with short hex value short := gx.hex(0xfff) assert short != gx.white - assert short == gx.Color{0, 0, 15, 255} + // assert short == gx.Color{0, 0, 15, 255} } fn test_add() { diff --git a/vlib/strings/builder.c.v b/vlib/strings/builder.c.v index fdf3c94192..ef3823aa79 100644 --- a/vlib/strings/builder.c.v +++ b/vlib/strings/builder.c.v @@ -141,6 +141,13 @@ pub fn (mut b Builder) write_string(s string) { // b.buf << []u8(s) // TODO } +// writeln appends the string `s`+`\n` to the buffer +@[inline] +pub fn (mut b Builder) writeln_string(s string) { + b.write_string(s) + b.write_string('\n') +} + // go_back discards the last `n` bytes from the buffer pub fn (mut b Builder) go_back(n int) { b.trim(b.len - n) diff --git a/vlib/v/preludes/test_runner_normal.v b/vlib/v/preludes/test_runner_normal.v index 3a01856047..89e3271794 100644 --- a/vlib/v/preludes/test_runner_normal.v +++ b/vlib/v/preludes/test_runner_normal.v @@ -136,6 +136,12 @@ fn (mut runner NormalTestRunner) assert_fail(i &VAssertMetaInfo) { mut rvtitle := ' Right value:' mut slvalue := '${i.lvalue}' mut srvalue := '${i.rvalue}' + // Do not print duplicate values to avoid confusion. In mosts tests the developer does + // `assert foo() == [1, 2, 3]` + // There's no need to print "[1, 2, 3]" again (left: [1,2,3,4] right:[1,2,3]) + // It makes it harded to understand what is what. + // So if "[1,2,3]" is already mentioned in the source, we don't print it. + need_to_print_right := !final_src.contains('== ' + srvalue) if runner.use_color { slvalue = term.yellow(slvalue) srvalue = term.yellow(srvalue) @@ -147,12 +153,16 @@ fn (mut runner NormalTestRunner) assert_fail(i &VAssertMetaInfo) { eprintln(' > ${final_src}') eprintln(lvtitle) eprintln(' ${slvalue}') - eprintln(rvtitle) - eprintln(' ${srvalue}') + if need_to_print_right { + eprintln(rvtitle) + eprintln(' ${srvalue}') + } } else { eprintln(' > ${final_src}') eprintln(' ${lvtitle} ${slvalue}') - eprintln('${rvtitle} ${srvalue}') + if need_to_print_right { + eprintln('${rvtitle} ${srvalue}') + } } } else { eprintln(' ${final_src}')