mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-13 09:49:11 +03:00
Merge branch 'trunk' into constrain_expr2_small_int
This commit is contained in:
commit
eec7a9db55
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -37,6 +37,17 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
@ -1376,7 +1387,7 @@ checksum = "e8a70f1e87a3840ed6a3e99e02c2b861e4dbdf26f0d07e38f42ea5aff46cfce2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gpu-descriptor-types",
|
||||
"hashbrown",
|
||||
"hashbrown 0.9.1",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@ -1401,7 +1412,17 @@ version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.4.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
dependencies = [
|
||||
"ahash 0.7.2",
|
||||
"bumpalo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1497,7 +1518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"hashbrown",
|
||||
"hashbrown 0.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2950,6 +2971,7 @@ name = "roc_collections"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"hashbrown 0.11.2",
|
||||
"im 14.3.0",
|
||||
"im-rc 14.3.0",
|
||||
"wyhash",
|
||||
@ -3181,6 +3203,7 @@ name = "roc_mono"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"hashbrown 0.11.2",
|
||||
"indoc 0.3.6",
|
||||
"linked-hash-map",
|
||||
"maplit",
|
||||
|
@ -23,7 +23,7 @@ roc_gen = { path = "../gen" }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1.0"
|
||||
libloading = "0.6"
|
||||
tempfile = "3.1.0"
|
||||
|
@ -167,7 +167,7 @@ joinWith : List Str, Str -> Str
|
||||
## >>> Str.padGraphemesStart "0" 5 "12345"
|
||||
##
|
||||
## >>> Str.padGraphemesStart "✈️"" 5 "👩👩👦👦👩👩👦👦👩👩👦👦"
|
||||
padGraphemesStart : Str, Int, Str -> Str
|
||||
padGraphemesStart : Str, Nat, Str -> Str
|
||||
|
||||
## Add to the end of a string until it has at least the given number of
|
||||
## graphemes.
|
||||
@ -179,7 +179,7 @@ padGraphemesStart : Str, Int, Str -> Str
|
||||
## >>> Str.padGraphemesStart "0" 5 "12345"
|
||||
##
|
||||
## >>> Str.padGraphemesStart "✈️"" 5 "👩👩👦👦👩👩👦👦👩👩👦👦"
|
||||
padGraphemesEnd : Str, Int, Str -> Str
|
||||
padGraphemesEnd : Str, Nat, Str -> Str
|
||||
|
||||
## Graphemes
|
||||
|
||||
|
@ -16,7 +16,7 @@ roc_builtins = { path = "../builtins" }
|
||||
ven_graph = { path = "../../vendor/pathfinding" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -9,4 +9,5 @@ edition = "2018"
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
wyhash = "0.3"
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
hashbrown = { version = "0.11.2", features = [ "bumpalo" ] }
|
||||
|
@ -28,6 +28,8 @@ pub type SendMap<K, V> = im::hashmap::HashMap<K, V, BuildHasher>;
|
||||
|
||||
pub type SendSet<K> = im::hashset::HashSet<K, BuildHasher>;
|
||||
|
||||
pub type BumpMap<'a, K, V> = hashbrown::HashMap<K, V, BuildHasher, hashbrown::BumpWrapper<'a>>;
|
||||
|
||||
pub fn arena_join<'a, I>(arena: &'a Bump, strings: &mut I, join_str: &str) -> String<'a>
|
||||
where
|
||||
I: Iterator<Item = &'a str>,
|
||||
|
@ -12,7 +12,7 @@ roc_module = { path = "../module" }
|
||||
roc_parse = { path = "../parse" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -17,7 +17,7 @@ roc_solve = { path = "../solve" }
|
||||
roc_mono = { path = "../mono" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
either = "1.6.1"
|
||||
# NOTE: rtfeldman/inkwell is a fork of TheDan64/inkwell which does not change anything.
|
||||
@ -53,5 +53,5 @@ indoc = "0.3.3"
|
||||
quickcheck = "0.8"
|
||||
quickcheck_macros = "0.8"
|
||||
tokio = { version = "0.2", features = ["blocking", "fs", "sync", "rt-threaded"] }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
libc = "0.2"
|
||||
|
@ -19,7 +19,7 @@ roc_solve = { path = "../solve" }
|
||||
roc_mono = { path = "../mono" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
target-lexicon = "0.10"
|
||||
libloading = "0.6"
|
||||
@ -37,7 +37,7 @@ indoc = "0.3.3"
|
||||
quickcheck = "0.8"
|
||||
quickcheck_macros = "0.8"
|
||||
tokio = { version = "0.2", features = ["blocking", "fs", "sync", "rt-threaded"] }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
libc = "0.2"
|
||||
tempfile = "3.1.0"
|
||||
itertools = "0.9"
|
||||
|
@ -20,7 +20,7 @@ roc_solve = { path = "../solve" }
|
||||
roc_mono = { path = "../mono" }
|
||||
roc_reporting = { path = "../reporting" }
|
||||
ven_pretty = { path = "../../vendor/pretty" }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
parking_lot = { version = "0.11", features = ["deadlock_detection"] }
|
||||
crossbeam = "0.7"
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::docs::DocTypeAnnotation::{Apply, BoundVariable, TagUnion};
|
||||
use crate::docs::TypeAnnotation::{Apply, BoundVariable, TagUnion};
|
||||
use inlinable_string::InlinableString;
|
||||
use roc_module::ident::ModuleName;
|
||||
use roc_module::symbol::IdentIds;
|
||||
use roc_parse::ast::{Def, Tag, TypeAnnotation};
|
||||
use roc_parse::ast;
|
||||
use roc_region::all::Located;
|
||||
|
||||
// Documentation generation requirements
|
||||
@ -26,33 +26,33 @@ pub struct ModuleDocumentation {
|
||||
pub struct DocEntry {
|
||||
pub name: String,
|
||||
pub type_vars: Vec<String>,
|
||||
pub type_annotation: Option<DocTypeAnnotation>,
|
||||
pub type_annotation: Option<TypeAnnotation>,
|
||||
pub docs: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DocTypeAnnotation {
|
||||
pub enum TypeAnnotation {
|
||||
TagUnion {
|
||||
tags: Vec<DocTag>,
|
||||
extension: Option<Box<DocTypeAnnotation>>,
|
||||
tags: Vec<Tag>,
|
||||
extension: Option<Box<TypeAnnotation>>,
|
||||
},
|
||||
BoundVariable(String),
|
||||
Apply {
|
||||
name: String,
|
||||
parts: Vec<DocTypeAnnotation>,
|
||||
parts: Vec<TypeAnnotation>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DocTag {
|
||||
pub struct Tag {
|
||||
pub name: String,
|
||||
pub values: Vec<DocTypeAnnotation>,
|
||||
pub values: Vec<TypeAnnotation>,
|
||||
}
|
||||
|
||||
pub fn generate_module_docs<'a>(
|
||||
module_name: ModuleName,
|
||||
exposed_ident_ids: &'a IdentIds,
|
||||
parsed_defs: &'a [Located<Def<'a>>],
|
||||
parsed_defs: &'a [Located<ast::Def<'a>>],
|
||||
) -> ModuleDocumentation {
|
||||
let (entries, _) =
|
||||
parsed_defs
|
||||
@ -72,7 +72,7 @@ fn generate_module_doc<'a>(
|
||||
exposed_ident_ids: &'a IdentIds,
|
||||
mut acc: Vec<DocEntry>,
|
||||
before_comments_or_new_lines: Option<&'a [roc_parse::ast::CommentOrNewline<'a>]>,
|
||||
def: &'a Def<'a>,
|
||||
def: &'a ast::Def<'a>,
|
||||
) -> (
|
||||
Vec<DocEntry>,
|
||||
Option<&'a [roc_parse::ast::CommentOrNewline<'a>]>,
|
||||
@ -162,14 +162,14 @@ fn generate_module_doc<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
fn type_to_docs(type_annotation: TypeAnnotation) -> Option<DocTypeAnnotation> {
|
||||
fn type_to_docs(type_annotation: ast::TypeAnnotation) -> Option<TypeAnnotation> {
|
||||
match type_annotation {
|
||||
TypeAnnotation::TagUnion {
|
||||
ast::TypeAnnotation::TagUnion {
|
||||
tags,
|
||||
ext,
|
||||
final_comments: _,
|
||||
} => {
|
||||
let mut tags_to_render: Vec<DocTag> = Vec::new();
|
||||
let mut tags_to_render: Vec<Tag> = Vec::new();
|
||||
|
||||
let mut any_tags_are_private = false;
|
||||
|
||||
@ -204,8 +204,8 @@ fn type_to_docs(type_annotation: TypeAnnotation) -> Option<DocTypeAnnotation> {
|
||||
})
|
||||
}
|
||||
}
|
||||
TypeAnnotation::BoundVariable(var_name) => Some(BoundVariable(var_name.to_string())),
|
||||
TypeAnnotation::Apply(module_name, type_name, type_ann_parts) => {
|
||||
ast::TypeAnnotation::BoundVariable(var_name) => Some(BoundVariable(var_name.to_string())),
|
||||
ast::TypeAnnotation::Apply(module_name, type_name, type_ann_parts) => {
|
||||
let mut name = String::new();
|
||||
|
||||
if !module_name.is_empty() {
|
||||
@ -215,7 +215,7 @@ fn type_to_docs(type_annotation: TypeAnnotation) -> Option<DocTypeAnnotation> {
|
||||
|
||||
name.push_str(type_name);
|
||||
|
||||
let mut parts: Vec<DocTypeAnnotation> = Vec::new();
|
||||
let mut parts: Vec<TypeAnnotation> = Vec::new();
|
||||
|
||||
for type_ann_part in type_ann_parts {
|
||||
if let Some(part) = type_to_docs(type_ann_part.value) {
|
||||
@ -235,9 +235,9 @@ fn type_to_docs(type_annotation: TypeAnnotation) -> Option<DocTypeAnnotation> {
|
||||
|
||||
// The Option here represents if it is private. Private tags
|
||||
// evaluate to `None`.
|
||||
fn tag_to_doc(tag: Tag) -> Option<DocTag> {
|
||||
fn tag_to_doc(tag: ast::Tag) -> Option<Tag> {
|
||||
match tag {
|
||||
Tag::Global { name, args } => Some(DocTag {
|
||||
ast::Tag::Global { name, args } => Some(Tag {
|
||||
name: name.value.to_string(),
|
||||
values: {
|
||||
let mut type_vars = Vec::new();
|
||||
@ -257,10 +257,10 @@ fn tag_to_doc(tag: Tag) -> Option<DocTag> {
|
||||
type_vars
|
||||
},
|
||||
}),
|
||||
Tag::Private { .. } => None,
|
||||
Tag::SpaceBefore(&sub_tag, _) => tag_to_doc(sub_tag),
|
||||
Tag::SpaceAfter(&sub_tag, _) => tag_to_doc(sub_tag),
|
||||
Tag::Malformed(_) => None,
|
||||
ast::Tag::Private { .. } => None,
|
||||
ast::Tag::SpaceBefore(&sub_tag, _) => tag_to_doc(sub_tag),
|
||||
ast::Tag::SpaceAfter(&sub_tag, _) => tag_to_doc(sub_tag),
|
||||
ast::Tag::Malformed(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ license = "Apache-2.0"
|
||||
[dependencies]
|
||||
roc_region = { path = "../region" }
|
||||
roc_collections = { path = "../collections" }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
lazy_static = "1.4"
|
||||
|
||||
|
@ -15,7 +15,8 @@ roc_unify = { path = "../unify" }
|
||||
roc_solve = { path = "../solve" }
|
||||
roc_problem = { path = "../problem" }
|
||||
ven_pretty = { path = "../../vendor/pretty" }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
hashbrown = { version = "0.11.2", features = [ "bumpalo" ] }
|
||||
ven_ena = { path = "../../vendor/ena" }
|
||||
linked-hash-map = "0.5.4"
|
||||
|
||||
|
@ -6,7 +6,7 @@ use crate::layout::{
|
||||
};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
||||
use roc_collections::all::{default_hasher, BumpMap, MutMap, MutSet};
|
||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
@ -126,8 +126,8 @@ pub struct Proc<'a> {
|
||||
pub enum HostExposedLayouts<'a> {
|
||||
NotHostExposed,
|
||||
HostExposed {
|
||||
rigids: MutMap<Lowercase, Layout<'a>>,
|
||||
aliases: MutMap<Symbol, Layout<'a>>,
|
||||
rigids: BumpMap<'a, Lowercase, Layout<'a>>,
|
||||
aliases: BumpMap<'a, Symbol, Layout<'a>>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1833,7 +1833,8 @@ fn specialize_external<'a>(
|
||||
let host_exposed_layouts = if host_exposed_variables.is_empty() {
|
||||
HostExposedLayouts::NotHostExposed
|
||||
} else {
|
||||
let mut aliases = MutMap::default();
|
||||
let mut aliases =
|
||||
hashbrown::HashMap::with_hasher_in(default_hasher(), hashbrown::BumpWrapper(env.arena));
|
||||
|
||||
for (symbol, variable) in host_exposed_variables {
|
||||
let layout = layout_cache
|
||||
@ -1843,7 +1844,10 @@ fn specialize_external<'a>(
|
||||
}
|
||||
|
||||
HostExposedLayouts::HostExposed {
|
||||
rigids: MutMap::default(),
|
||||
rigids: hashbrown::HashMap::with_hasher_in(
|
||||
default_hasher(),
|
||||
hashbrown::BumpWrapper(env.arena),
|
||||
),
|
||||
aliases,
|
||||
}
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ edition = "2018"
|
||||
roc_collections = { path = "../collections" }
|
||||
roc_region = { path = "../region" }
|
||||
roc_module = { path = "../module" }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
encode_unicode = "0.3"
|
||||
|
||||
|
@ -11,7 +11,7 @@ cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
libfuzzer-sys = "0.3"
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
||||
[dependencies.roc_parse]
|
||||
path = ".."
|
||||
|
@ -20,7 +20,7 @@ inlinable_string = "0.1"
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
distance = "0.4.0"
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
||||
[dev-dependencies]
|
||||
roc_constrain = { path = "../constrain" }
|
||||
|
@ -25,4 +25,4 @@ indoc = "0.3.3"
|
||||
tempfile = "3.1.0"
|
||||
quickcheck = "0.8"
|
||||
quickcheck_macros = "0.8"
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
@ -13,7 +13,7 @@ roc_types = { path = "../types" }
|
||||
roc_can = { path = "../can" }
|
||||
roc_unify = { path = "../unify" }
|
||||
roc_problem = { path = "../problem" }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
||||
[dev-dependencies]
|
||||
roc_constrain = { path = "../constrain" }
|
||||
|
@ -25,7 +25,7 @@ roc_build = { path = "../build" }
|
||||
roc_std = { path = "../../roc_std" }
|
||||
im = "14" # im and im-rc should always have the same version!
|
||||
im-rc = "14" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
either = "1.6.1"
|
||||
indoc = "0.3.3"
|
||||
@ -58,4 +58,4 @@ maplit = "1.0.1"
|
||||
quickcheck = "0.8"
|
||||
quickcheck_macros = "0.8"
|
||||
tokio = { version = "0.2", features = ["blocking", "fs", "sync", "rt-threaded"] }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
|
@ -1,8 +1,8 @@
|
||||
extern crate pulldown_cmark;
|
||||
use roc_builtins::std::StdLib;
|
||||
use roc_can::builtins::builtin_defs_map;
|
||||
use roc_load::docs::DocTypeAnnotation;
|
||||
use roc_load::docs::ModuleDocumentation;
|
||||
use roc_load::docs::TypeAnnotation;
|
||||
use roc_load::file::LoadingProblem;
|
||||
|
||||
use std::fs;
|
||||
@ -112,7 +112,7 @@ fn render_main_content(module: &ModuleDocumentation) -> String {
|
||||
buf.push_str(html_node("h3", vec![("id", name)], content.as_str()).as_str());
|
||||
|
||||
if let Some(docs) = &entry.docs {
|
||||
buf.push_str(docs.as_str());
|
||||
buf.push_str(markdown_to_html(docs.to_string()).as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,9 +291,9 @@ fn indent(buf: &mut String, times: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &DocTypeAnnotation) {
|
||||
fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &TypeAnnotation) {
|
||||
match type_ann {
|
||||
DocTypeAnnotation::TagUnion { tags, extension } => {
|
||||
TypeAnnotation::TagUnion { tags, extension } => {
|
||||
buf.push_str("<br>");
|
||||
|
||||
let tag_union_indent = indent_level + 1;
|
||||
@ -336,10 +336,10 @@ fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &Doc
|
||||
type_annotation_to_html(indent_level, buf, ext);
|
||||
}
|
||||
}
|
||||
DocTypeAnnotation::BoundVariable(var_name) => {
|
||||
TypeAnnotation::BoundVariable(var_name) => {
|
||||
buf.push_str(var_name);
|
||||
}
|
||||
DocTypeAnnotation::Apply { name, parts } => {
|
||||
TypeAnnotation::Apply { name, parts } => {
|
||||
if parts.is_empty() {
|
||||
buf.push_str(name);
|
||||
} else {
|
||||
@ -356,12 +356,12 @@ fn type_annotation_to_html(indent_level: usize, buf: &mut String, type_ann: &Doc
|
||||
}
|
||||
|
||||
fn markdown_to_html(markdown: String) -> String {
|
||||
use pulldown_cmark::CodeBlockKind::*;
|
||||
use pulldown_cmark::CowStr::*;
|
||||
use pulldown_cmark::Event::*;
|
||||
use pulldown_cmark::CodeBlockKind;
|
||||
use pulldown_cmark::CowStr;
|
||||
use pulldown_cmark::Event;
|
||||
use pulldown_cmark::Tag::*;
|
||||
|
||||
let markdown_options = pulldown_cmark::Options::all();
|
||||
let markdown_options = pulldown_cmark::Options::empty();
|
||||
let mut docs_parser = vec![];
|
||||
let (_, _) = pulldown_cmark::Parser::new_ext(&markdown, markdown_options).fold(
|
||||
(0, 0),
|
||||
@ -372,16 +372,18 @@ fn markdown_to_html(markdown: String) -> String {
|
||||
// Start(BlockQuote)
|
||||
// Start(Paragraph)
|
||||
// For `Start(CodeBlock(Fenced(Borrowed("roc"))))`
|
||||
Start(BlockQuote) => {
|
||||
Event::Start(BlockQuote) => {
|
||||
docs_parser.push(event);
|
||||
(start_quote_count + 1, 0)
|
||||
}
|
||||
Start(Paragraph) => {
|
||||
Event::Start(Paragraph) => {
|
||||
if start_quote_count == 3 {
|
||||
docs_parser.pop();
|
||||
docs_parser.pop();
|
||||
docs_parser.pop();
|
||||
docs_parser.push(Start(CodeBlock(Fenced(Borrowed("roc")))));
|
||||
docs_parser.push(Event::Start(CodeBlock(CodeBlockKind::Fenced(
|
||||
CowStr::Borrowed("roc"),
|
||||
))));
|
||||
} else {
|
||||
docs_parser.push(event);
|
||||
}
|
||||
@ -393,16 +395,18 @@ fn markdown_to_html(markdown: String) -> String {
|
||||
// End(BlockQuote)
|
||||
// End(BlockQuote)
|
||||
// For `End(CodeBlock(Fenced(Borrowed("roc"))))`
|
||||
End(Paragraph) => {
|
||||
Event::End(Paragraph) => {
|
||||
docs_parser.push(event);
|
||||
(0, 1)
|
||||
}
|
||||
End(BlockQuote) => {
|
||||
Event::End(BlockQuote) => {
|
||||
if end_quote_count == 3 {
|
||||
docs_parser.pop();
|
||||
docs_parser.pop();
|
||||
docs_parser.pop();
|
||||
docs_parser.push(End(CodeBlock(Fenced(Borrowed("roc")))));
|
||||
docs_parser.push(Event::End(CodeBlock(CodeBlockKind::Fenced(
|
||||
CowStr::Borrowed("roc"),
|
||||
))));
|
||||
(0, 0)
|
||||
} else {
|
||||
docs_parser.push(event);
|
||||
@ -415,7 +419,9 @@ fn markdown_to_html(markdown: String) -> String {
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let mut docs_html = String::new();
|
||||
pulldown_cmark::html::push_html(&mut docs_html, docs_parser.into_iter());
|
||||
|
||||
docs_html
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ roc_solve = { path = "../compiler/solve" }
|
||||
ven_graph = { path = "../vendor/pathfinding" }
|
||||
im = "15" # im and im-rc should always have the same version!
|
||||
im-rc = "15" # im and im-rc should always have the same version!
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||
inlinable_string = "0.1"
|
||||
arraystring = "0.3.0"
|
||||
libc = "0.2"
|
||||
|
@ -37,12 +37,19 @@ pub struct EdModel<'a> {
|
||||
pub has_focus: bool,
|
||||
// Option<MarkNodeId>: MarkupNode that corresponds to caret position, Option because this MarkNodeId is only calculated when it needs to be used.
|
||||
pub caret_w_select_vec: NonEmpty<(CaretWSelect, Option<MarkNodeId>)>,
|
||||
pub selected_expr2_tup: Option<(NodeId<Expr2>, MarkNodeId)>,
|
||||
pub selected_expr_opt: Option<SelectedExpression>,
|
||||
pub show_debug_view: bool,
|
||||
// EdModel is dirty if it has changed since the previous render.
|
||||
pub dirty: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SelectedExpression {
|
||||
pub ast_node_id: NodeId<Expr2>,
|
||||
pub mark_node_id: MarkNodeId,
|
||||
pub type_str: String,
|
||||
}
|
||||
|
||||
pub fn init_model<'a>(
|
||||
code_str: &'a BumpString,
|
||||
file_path: &'a Path,
|
||||
@ -91,7 +98,7 @@ pub fn init_model<'a>(
|
||||
glyph_dim_rect_opt: None,
|
||||
has_focus: true,
|
||||
caret_w_select_vec: NonEmpty::new((CaretWSelect::default(), None)),
|
||||
selected_expr2_tup: None,
|
||||
selected_expr_opt: None,
|
||||
show_debug_view: false,
|
||||
dirty: true,
|
||||
})
|
||||
|
@ -9,6 +9,7 @@ use crate::editor::markup::nodes;
|
||||
use crate::editor::markup::nodes::MarkupNode;
|
||||
use crate::editor::mvc::app_update::InputOutcome;
|
||||
use crate::editor::mvc::ed_model::EdModel;
|
||||
use crate::editor::mvc::ed_model::SelectedExpression;
|
||||
use crate::editor::mvc::lookup_update::update_invalid_lookup;
|
||||
use crate::editor::mvc::record_update::start_new_record;
|
||||
use crate::editor::mvc::record_update::update_empty_record;
|
||||
@ -47,7 +48,7 @@ impl<'a> EdModel<'a> {
|
||||
caret_tup.0 = move_fun(&self.code_lines, caret_tup.0, modifiers)?;
|
||||
caret_tup.1 = None;
|
||||
}
|
||||
self.selected_expr2_tup = None;
|
||||
self.selected_expr_opt = None;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -147,8 +148,8 @@ impl<'a> EdModel<'a> {
|
||||
// select all MarkupNodes that refer to specific ast node and its children.
|
||||
pub fn select_expr(&mut self) -> EdResult<()> {
|
||||
// include parent in selection if an `Expr2` was already selected
|
||||
if let Some((_sel_expr2_id, mark_node_id)) = self.selected_expr2_tup {
|
||||
let expr2_level_mark_node = self.markup_node_pool.get(mark_node_id);
|
||||
if let Some(selected_expr) = &self.selected_expr_opt {
|
||||
let expr2_level_mark_node = self.markup_node_pool.get(selected_expr.mark_node_id);
|
||||
|
||||
if let Some(parent_id) = expr2_level_mark_node.get_parent_id_opt() {
|
||||
let parent_mark_node = self.markup_node_pool.get(parent_id);
|
||||
@ -164,7 +165,11 @@ impl<'a> EdModel<'a> {
|
||||
})?;
|
||||
|
||||
self.set_caret(expr_start_pos);
|
||||
self.selected_expr2_tup = Some((ast_node_id, parent_id));
|
||||
self.selected_expr_opt = Some(SelectedExpression {
|
||||
ast_node_id,
|
||||
mark_node_id: parent_id,
|
||||
type_str: "Str".to_owned(), // TODO get this String from type inference
|
||||
});
|
||||
|
||||
self.dirty = true;
|
||||
}
|
||||
@ -181,7 +186,11 @@ impl<'a> EdModel<'a> {
|
||||
})?;
|
||||
|
||||
self.set_caret(expr_start_pos);
|
||||
self.selected_expr2_tup = Some((ast_node_id, mark_node_id));
|
||||
self.selected_expr_opt = Some(SelectedExpression {
|
||||
ast_node_id,
|
||||
mark_node_id,
|
||||
type_str: "Str".to_owned(), // TODO get this String from type inference
|
||||
});
|
||||
|
||||
self.dirty = true;
|
||||
}
|
||||
@ -226,32 +235,40 @@ impl<'a> EdModel<'a> {
|
||||
}
|
||||
|
||||
fn replace_slected_expr_with_blank(&mut self) -> EdResult<()> {
|
||||
if let Some((sel_expr2_id, mark_node_id)) = self.selected_expr2_tup {
|
||||
let expr2_level_mark_node = self.markup_node_pool.get(mark_node_id);
|
||||
let expr_mark_node_id_opt = if let Some(sel_expr) = &self.selected_expr_opt {
|
||||
let expr2_level_mark_node = self.markup_node_pool.get(sel_expr.mark_node_id);
|
||||
|
||||
let blank_replacement = MarkupNode::Blank {
|
||||
ast_node_id: sel_expr2_id,
|
||||
ast_node_id: sel_expr.ast_node_id,
|
||||
attributes: Attributes::new(),
|
||||
syn_high_style: HighlightStyle::Blank,
|
||||
parent_id_opt: expr2_level_mark_node.get_parent_id_opt(),
|
||||
};
|
||||
|
||||
self.markup_node_pool
|
||||
.replace_node(mark_node_id, blank_replacement);
|
||||
.replace_node(sel_expr.mark_node_id, blank_replacement);
|
||||
|
||||
let active_selection = self.get_selection().context(MissingSelection {})?;
|
||||
self.code_lines.del_selection(active_selection)?;
|
||||
self.grid_node_map.del_selection(active_selection)?;
|
||||
|
||||
self.module.env.pool.set(sel_expr.ast_node_id, Expr2::Blank);
|
||||
|
||||
Some(sel_expr.mark_node_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// have to split the previous `if` up to prevent borrowing issues
|
||||
if let Some(expr_mark_node_id) = expr_mark_node_id_opt {
|
||||
let caret_pos = self.get_caret();
|
||||
|
||||
self.insert_between_line(
|
||||
caret_pos.line,
|
||||
caret_pos.column,
|
||||
nodes::BLANK_PLACEHOLDER,
|
||||
mark_node_id,
|
||||
expr_mark_node_id,
|
||||
)?;
|
||||
|
||||
self.module.env.pool.set(sel_expr2_id, Expr2::Blank)
|
||||
}
|
||||
|
||||
self.set_sel_none();
|
||||
@ -352,7 +369,7 @@ impl<'a> SelectableLines for EdModel<'a> {
|
||||
|
||||
fn set_sel_none(&mut self) {
|
||||
self.caret_w_select_vec.first_mut().0.selection_opt = None;
|
||||
self.selected_expr2_tup = None;
|
||||
self.selected_expr_opt = None;
|
||||
}
|
||||
|
||||
fn set_caret_w_sel(&mut self, caret_w_sel: CaretWSelect) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::ed_model::EdModel;
|
||||
use crate::editor::config::Config;
|
||||
use crate::editor::ed_error::EdResult;
|
||||
use crate::editor::mvc::ed_model::SelectedExpression;
|
||||
use crate::editor::render_ast::build_code_graphics;
|
||||
use crate::editor::render_debug::build_debug_graphics;
|
||||
use crate::graphics::primitives::rect::Rect;
|
||||
@ -8,6 +9,7 @@ use crate::ui::text::caret_w_select::make_caret_rect;
|
||||
use crate::ui::text::caret_w_select::make_selection_rect;
|
||||
use crate::ui::text::caret_w_select::CaretWSelect;
|
||||
use crate::ui::text::selection::Selection;
|
||||
use crate::ui::tooltip::ToolTip;
|
||||
use crate::ui::ui_error::MissingGlyphDims;
|
||||
use cgmath::Vector2;
|
||||
use snafu::OptionExt;
|
||||
@ -19,6 +21,32 @@ pub struct RenderedWgpu {
|
||||
pub rects: Vec<Rect>,
|
||||
}
|
||||
|
||||
impl RenderedWgpu {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_sections: Vec::new(),
|
||||
rects: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_text(&mut self, new_text_section: glyph_brush::OwnedSection) {
|
||||
self.text_sections.push(new_text_section);
|
||||
}
|
||||
|
||||
pub fn add_rect(&mut self, new_rect: Rect) {
|
||||
self.rects.push(new_rect);
|
||||
}
|
||||
|
||||
pub fn add_rects(&mut self, new_rects: Vec<Rect>) {
|
||||
self.rects.extend(new_rects);
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, rendered_wgpu: RenderedWgpu) {
|
||||
self.text_sections.extend(rendered_wgpu.text_sections);
|
||||
self.rects.extend(rendered_wgpu.rects);
|
||||
}
|
||||
}
|
||||
|
||||
// create text and rectangles based on EdModel's markup_root
|
||||
pub fn model_to_wgpu<'a>(
|
||||
ed_model: &'a mut EdModel,
|
||||
@ -28,9 +56,9 @@ pub fn model_to_wgpu<'a>(
|
||||
) -> EdResult<RenderedWgpu> {
|
||||
let glyph_dim_rect = ed_model.glyph_dim_rect_opt.context(MissingGlyphDims {})?;
|
||||
|
||||
let mut all_text_sections = Vec::new();
|
||||
let mut all_rendered = RenderedWgpu::new();
|
||||
|
||||
let (code_section, mut rects) = build_code_graphics(
|
||||
let rendered_code_graphics = build_code_graphics(
|
||||
ed_model.markup_node_pool.get(ed_model.markup_root_id),
|
||||
size,
|
||||
txt_coords,
|
||||
@ -39,7 +67,7 @@ pub fn model_to_wgpu<'a>(
|
||||
&ed_model.markup_node_pool,
|
||||
)?;
|
||||
|
||||
all_text_sections.push(code_section);
|
||||
all_rendered.extend(rendered_code_graphics);
|
||||
|
||||
let caret_w_sel_vec = ed_model
|
||||
.caret_w_select_vec
|
||||
@ -47,28 +75,31 @@ pub fn model_to_wgpu<'a>(
|
||||
.map(|(caret_w_sel, _)| *caret_w_sel)
|
||||
.collect();
|
||||
|
||||
let mut sel_rects =
|
||||
build_selection_graphics(caret_w_sel_vec, txt_coords, config, glyph_dim_rect)?;
|
||||
let rendered_selection = build_selection_graphics(
|
||||
caret_w_sel_vec,
|
||||
&ed_model.selected_expr_opt,
|
||||
txt_coords,
|
||||
config,
|
||||
glyph_dim_rect,
|
||||
)?;
|
||||
|
||||
rects.append(&mut sel_rects);
|
||||
all_rendered.extend(rendered_selection);
|
||||
|
||||
if ed_model.show_debug_view {
|
||||
all_text_sections.push(build_debug_graphics(size, txt_coords, config, ed_model)?);
|
||||
all_rendered.add_text(build_debug_graphics(size, txt_coords, config, ed_model)?);
|
||||
}
|
||||
|
||||
Ok(RenderedWgpu {
|
||||
text_sections: all_text_sections,
|
||||
rects,
|
||||
})
|
||||
Ok(all_rendered)
|
||||
}
|
||||
|
||||
pub fn build_selection_graphics(
|
||||
caret_w_select_vec: Vec<CaretWSelect>,
|
||||
selected_expr_opt: &Option<SelectedExpression>,
|
||||
txt_coords: Vector2<f32>,
|
||||
config: &Config,
|
||||
glyph_dim_rect: Rect,
|
||||
) -> EdResult<Vec<Rect>> {
|
||||
let mut rects = Vec::new();
|
||||
) -> EdResult<RenderedWgpu> {
|
||||
let mut all_rendered = RenderedWgpu::new();
|
||||
let char_width = glyph_dim_rect.width;
|
||||
let char_height = glyph_dim_rect.height;
|
||||
|
||||
@ -90,16 +121,31 @@ pub fn build_selection_graphics(
|
||||
let width =
|
||||
((end_pos.column as f32) * char_width) - ((start_pos.column as f32) * char_width);
|
||||
|
||||
rects.push(make_selection_rect(
|
||||
all_rendered.add_rect(make_selection_rect(
|
||||
sel_rect_x,
|
||||
sel_rect_y,
|
||||
width,
|
||||
&glyph_dim_rect,
|
||||
&config.ed_theme.ui_theme,
|
||||
));
|
||||
|
||||
// render tooltip showing type
|
||||
if let Some(selected_expr) = selected_expr_opt {
|
||||
let tooltip = ToolTip {
|
||||
position_x: sel_rect_x,
|
||||
position_y: sel_rect_y - glyph_dim_rect.height,
|
||||
text: selected_expr.type_str.clone(),
|
||||
};
|
||||
|
||||
let (tip_rect, tip_text) =
|
||||
tooltip.render_tooltip(&glyph_dim_rect, &config.ed_theme.ui_theme);
|
||||
|
||||
all_rendered.add_rect(tip_rect);
|
||||
all_rendered.add_text(tip_text);
|
||||
}
|
||||
}
|
||||
|
||||
rects.push(make_caret_rect(
|
||||
all_rendered.add_rect(make_caret_rect(
|
||||
top_left_x,
|
||||
top_left_y,
|
||||
&glyph_dim_rect,
|
||||
@ -107,5 +153,5 @@ pub fn build_selection_graphics(
|
||||
));
|
||||
}
|
||||
|
||||
Ok(rects)
|
||||
Ok(all_rendered)
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::markup::nodes::{MarkupNode, BLANK_PLACEHOLDER};
|
||||
use crate::editor::mvc::ed_view::RenderedWgpu;
|
||||
use crate::editor::slow_pool::SlowPool;
|
||||
use crate::editor::{ed_error::EdResult, theme::EdTheme, util::map_get};
|
||||
use crate::graphics::primitives::rect::Rect;
|
||||
@ -15,9 +16,10 @@ pub fn build_code_graphics<'a>(
|
||||
config: &Config,
|
||||
glyph_dim_rect: Rect,
|
||||
markup_node_pool: &'a SlowPool,
|
||||
) -> EdResult<(glyph_brush::OwnedSection, Vec<Rect>)> {
|
||||
) -> EdResult<RenderedWgpu> {
|
||||
let area_bounds = (size.width as f32, size.height as f32);
|
||||
let layout = wgpu_glyph::Layout::default().h_align(wgpu_glyph::HorizontalAlign::Left);
|
||||
let mut rendered_wgpu = RenderedWgpu::new();
|
||||
|
||||
let (glyph_text_vec, rects) = markup_to_wgpu(
|
||||
markup_node,
|
||||
@ -30,10 +32,17 @@ pub fn build_code_graphics<'a>(
|
||||
markup_node_pool,
|
||||
)?;
|
||||
|
||||
let section =
|
||||
gr_text::section_from_glyph_text(glyph_text_vec, txt_coords.into(), area_bounds, layout);
|
||||
let section = gr_text::owned_section_from_glyph_texts(
|
||||
glyph_text_vec,
|
||||
txt_coords.into(),
|
||||
area_bounds,
|
||||
layout,
|
||||
);
|
||||
|
||||
Ok((section, rects))
|
||||
rendered_wgpu.add_rects(rects);
|
||||
rendered_wgpu.add_text(section);
|
||||
|
||||
Ok(rendered_wgpu)
|
||||
}
|
||||
|
||||
struct CodeStyle<'a> {
|
||||
|
@ -47,7 +47,7 @@ pub fn build_debug_graphics(
|
||||
.with_color(colors::to_slice(from_hsb(211, 80, 100)))
|
||||
.with_scale(config.code_font_size);
|
||||
|
||||
let section = gr_text::section_from_glyph_text(
|
||||
let section = gr_text::owned_section_from_glyph_texts(
|
||||
vec![
|
||||
grid_node_map_text,
|
||||
code_lines_text,
|
||||
|
@ -1 +1 @@
|
||||
pub const CODE_TXT_XY: (f32, f32) = (30.0, 30.0);
|
||||
pub const CODE_TXT_XY: (f32, f32) = (40.0, 60.0);
|
||||
|
@ -16,7 +16,7 @@ pub struct EdTheme {
|
||||
impl Default for EdTheme {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
background: from_hsb(240, 10, 19),
|
||||
background: from_hsb(240, 10, 19), // #2C2C35
|
||||
syntax_high_map: default_highlight_map(),
|
||||
ui_theme: UITheme::default(),
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use crate::graphics::colors::RgbaTup;
|
||||
use crate::graphics::style::DEFAULT_FONT_SIZE;
|
||||
use ab_glyph::{FontArc, Glyph, InvalidFont};
|
||||
use cgmath::{Vector2, Vector4};
|
||||
use glyph_brush::OwnedSection;
|
||||
use wgpu_glyph::{ab_glyph, GlyphBrush, GlyphBrushBuilder, GlyphCruncher, Section};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -83,7 +84,24 @@ fn section_from_text<'a>(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn section_from_glyph_text(
|
||||
pub fn owned_section_from_text(
|
||||
text: &Text,
|
||||
layout: wgpu_glyph::Layout<wgpu_glyph::BuiltInLineBreaker>,
|
||||
) -> OwnedSection {
|
||||
OwnedSection {
|
||||
screen_position: text.position.into(),
|
||||
bounds: text.area_bounds.into(),
|
||||
layout,
|
||||
..OwnedSection::default()
|
||||
}
|
||||
.add_text(
|
||||
glyph_brush::OwnedText::new(text.text)
|
||||
.with_color(Vector4::from(text.color))
|
||||
.with_scale(text.size),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn owned_section_from_glyph_texts(
|
||||
text: Vec<glyph_brush::OwnedText>,
|
||||
screen_position: (f32, f32),
|
||||
area_bounds: (f32, f32),
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod text;
|
||||
pub mod theme;
|
||||
pub mod tooltip;
|
||||
pub mod ui_error;
|
||||
pub mod util;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use gr_colors::{from_hsba, RgbaTup};
|
||||
use gr_colors::{from_hsb, from_hsba, RgbaTup};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::graphics::colors as gr_colors;
|
||||
@ -13,6 +13,9 @@ pub struct UITheme {
|
||||
pub text: RgbaTup,
|
||||
pub caret: RgbaTup,
|
||||
pub select_highlight: RgbaTup,
|
||||
pub tooltip_bg: RgbaTup,
|
||||
pub tooltip_text: RgbaTup,
|
||||
pub default_font_size: f32,
|
||||
}
|
||||
|
||||
impl Default for UITheme {
|
||||
@ -23,6 +26,9 @@ impl Default for UITheme {
|
||||
text: gr_colors::WHITE,
|
||||
caret: gr_colors::WHITE,
|
||||
select_highlight: from_hsba(240, 55, 100, 0.3),
|
||||
tooltip_bg: from_hsb(240, 60, 50),
|
||||
tooltip_text: gr_colors::WHITE,
|
||||
default_font_size: 30.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
81
editor/src/ui/tooltip.rs
Normal file
81
editor/src/ui/tooltip.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use crate::graphics::primitives::rect::Rect;
|
||||
use crate::graphics::primitives::text as gr_text;
|
||||
use crate::graphics::primitives::text::layout_from_text;
|
||||
use crate::graphics::primitives::text::Text;
|
||||
use crate::ui::theme::UITheme;
|
||||
|
||||
pub struct ToolTip {
|
||||
pub position_x: f32,
|
||||
pub position_y: f32,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
impl ToolTip {
|
||||
fn make_tooltip_rect(
|
||||
&self,
|
||||
width: f32,
|
||||
height: f32,
|
||||
height_padding: f32,
|
||||
y_margin: f32,
|
||||
ui_theme: &UITheme,
|
||||
) -> Rect {
|
||||
Rect {
|
||||
top_left_coords: (
|
||||
self.position_x,
|
||||
self.position_y - (height_padding + y_margin),
|
||||
)
|
||||
.into(),
|
||||
height: height + height_padding,
|
||||
width,
|
||||
color: ui_theme.tooltip_bg,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_tooltip_text<'a>(
|
||||
&'a self,
|
||||
x_offset: f32,
|
||||
y_offset: f32,
|
||||
y_margin: f32,
|
||||
ui_theme: &UITheme,
|
||||
) -> Text<'a> {
|
||||
Text {
|
||||
position: (
|
||||
self.position_x + x_offset,
|
||||
self.position_y - (y_offset + y_margin),
|
||||
)
|
||||
.into(),
|
||||
color: ui_theme.tooltip_text,
|
||||
text: &self.text,
|
||||
size: ui_theme.default_font_size,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_tooltip(
|
||||
&self,
|
||||
glyph_dim_rect: &Rect,
|
||||
ui_theme: &UITheme,
|
||||
) -> (Rect, glyph_brush::OwnedSection) {
|
||||
let width_padding = glyph_dim_rect.height / 1.3;
|
||||
let height_padding = width_padding / 1.3;
|
||||
|
||||
let text_x_offset = width_padding / 2.0;
|
||||
let text_y_offset = height_padding / 2.0;
|
||||
|
||||
let y_margin = glyph_dim_rect.height / 4.0;
|
||||
|
||||
let text = self.make_tooltip_text(text_x_offset, text_y_offset, y_margin, ui_theme);
|
||||
let text_layout = layout_from_text(&text);
|
||||
let text_section = gr_text::owned_section_from_text(&text, text_layout);
|
||||
|
||||
let rect = self.make_tooltip_rect(
|
||||
glyph_dim_rect.width * (text.text.len() as f32) + width_padding,
|
||||
glyph_dim_rect.height,
|
||||
height_padding,
|
||||
y_margin,
|
||||
ui_theme,
|
||||
);
|
||||
|
||||
(rect, text_section)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user