Merge branch 'main' into ime-stuff
This commit is contained in:
commit
804c4c512b
153 changed files with 3045 additions and 2765 deletions
|
@ -41,7 +41,7 @@ fn compile_context_predicate_parser() {
|
|||
.compile("tree_sitter_context_predicate");
|
||||
}
|
||||
|
||||
const SHADER_HEADER_PATH: &'static str = "./src/platform/mac/shaders/shaders.h";
|
||||
const SHADER_HEADER_PATH: &str = "./src/platform/mac/shaders/shaders.h";
|
||||
|
||||
fn compile_metal_shaders() {
|
||||
let shader_path = "./src/platform/mac/shaders/shaders.metal";
|
||||
|
|
|
@ -85,11 +85,11 @@ impl gpui::Element for TextElement {
|
|||
text,
|
||||
font_size,
|
||||
&[
|
||||
(1, normal.clone()),
|
||||
(1, bold.clone()),
|
||||
(1, normal.clone()),
|
||||
(1, bold.clone()),
|
||||
(text.len() - 4, normal.clone()),
|
||||
(1, normal),
|
||||
(1, bold),
|
||||
(1, normal),
|
||||
(1, bold),
|
||||
(text.len() - 4, normal),
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
@ -35,115 +35,132 @@ enum {
|
|||
sym_parenthesized = 16,
|
||||
};
|
||||
|
||||
static const char * const ts_symbol_names[] = {
|
||||
[ts_builtin_sym_end] = "end",
|
||||
[sym_identifier] = "identifier",
|
||||
[anon_sym_BANG] = "!",
|
||||
[anon_sym_AMP_AMP] = "&&",
|
||||
[anon_sym_PIPE_PIPE] = "||",
|
||||
[anon_sym_EQ_EQ] = "==",
|
||||
[anon_sym_BANG_EQ] = "!=",
|
||||
[anon_sym_LPAREN] = "(",
|
||||
[anon_sym_RPAREN] = ")",
|
||||
[sym_source] = "source",
|
||||
[sym__expression] = "_expression",
|
||||
[sym_not] = "not",
|
||||
[sym_and] = "and",
|
||||
[sym_or] = "or",
|
||||
[sym_equal] = "equal",
|
||||
[sym_not_equal] = "not_equal",
|
||||
[sym_parenthesized] = "parenthesized",
|
||||
static const char *const ts_symbol_names[] = {
|
||||
[ts_builtin_sym_end] = "end",
|
||||
[sym_identifier] = "identifier",
|
||||
[anon_sym_BANG] = "!",
|
||||
[anon_sym_AMP_AMP] = "&&",
|
||||
[anon_sym_PIPE_PIPE] = "||",
|
||||
[anon_sym_EQ_EQ] = "==",
|
||||
[anon_sym_BANG_EQ] = "!=",
|
||||
[anon_sym_LPAREN] = "(",
|
||||
[anon_sym_RPAREN] = ")",
|
||||
[sym_source] = "source",
|
||||
[sym__expression] = "_expression",
|
||||
[sym_not] = "not",
|
||||
[sym_and] = "and",
|
||||
[sym_or] = "or",
|
||||
[sym_equal] = "equal",
|
||||
[sym_not_equal] = "not_equal",
|
||||
[sym_parenthesized] = "parenthesized",
|
||||
};
|
||||
|
||||
static const TSSymbol ts_symbol_map[] = {
|
||||
[ts_builtin_sym_end] = ts_builtin_sym_end,
|
||||
[sym_identifier] = sym_identifier,
|
||||
[anon_sym_BANG] = anon_sym_BANG,
|
||||
[anon_sym_AMP_AMP] = anon_sym_AMP_AMP,
|
||||
[anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE,
|
||||
[anon_sym_EQ_EQ] = anon_sym_EQ_EQ,
|
||||
[anon_sym_BANG_EQ] = anon_sym_BANG_EQ,
|
||||
[anon_sym_LPAREN] = anon_sym_LPAREN,
|
||||
[anon_sym_RPAREN] = anon_sym_RPAREN,
|
||||
[sym_source] = sym_source,
|
||||
[sym__expression] = sym__expression,
|
||||
[sym_not] = sym_not,
|
||||
[sym_and] = sym_and,
|
||||
[sym_or] = sym_or,
|
||||
[sym_equal] = sym_equal,
|
||||
[sym_not_equal] = sym_not_equal,
|
||||
[sym_parenthesized] = sym_parenthesized,
|
||||
[ts_builtin_sym_end] = ts_builtin_sym_end,
|
||||
[sym_identifier] = sym_identifier,
|
||||
[anon_sym_BANG] = anon_sym_BANG,
|
||||
[anon_sym_AMP_AMP] = anon_sym_AMP_AMP,
|
||||
[anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE,
|
||||
[anon_sym_EQ_EQ] = anon_sym_EQ_EQ,
|
||||
[anon_sym_BANG_EQ] = anon_sym_BANG_EQ,
|
||||
[anon_sym_LPAREN] = anon_sym_LPAREN,
|
||||
[anon_sym_RPAREN] = anon_sym_RPAREN,
|
||||
[sym_source] = sym_source,
|
||||
[sym__expression] = sym__expression,
|
||||
[sym_not] = sym_not,
|
||||
[sym_and] = sym_and,
|
||||
[sym_or] = sym_or,
|
||||
[sym_equal] = sym_equal,
|
||||
[sym_not_equal] = sym_not_equal,
|
||||
[sym_parenthesized] = sym_parenthesized,
|
||||
};
|
||||
|
||||
static const TSSymbolMetadata ts_symbol_metadata[] = {
|
||||
[ts_builtin_sym_end] = {
|
||||
.visible = false,
|
||||
.named = true,
|
||||
},
|
||||
[sym_identifier] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[anon_sym_BANG] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_AMP_AMP] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_PIPE_PIPE] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_EQ_EQ] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_BANG_EQ] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_LPAREN] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_RPAREN] = {
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[sym_source] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym__expression] = {
|
||||
.visible = false,
|
||||
.named = true,
|
||||
},
|
||||
[sym_not] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_and] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_or] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_equal] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_not_equal] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_parenthesized] = {
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[ts_builtin_sym_end] =
|
||||
{
|
||||
.visible = false,
|
||||
.named = true,
|
||||
},
|
||||
[sym_identifier] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[anon_sym_BANG] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_AMP_AMP] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_PIPE_PIPE] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_EQ_EQ] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_BANG_EQ] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_LPAREN] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[anon_sym_RPAREN] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = false,
|
||||
},
|
||||
[sym_source] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym__expression] =
|
||||
{
|
||||
.visible = false,
|
||||
.named = true,
|
||||
},
|
||||
[sym_not] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_and] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_or] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_equal] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_not_equal] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
[sym_parenthesized] =
|
||||
{
|
||||
.visible = true,
|
||||
.named = true,
|
||||
},
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -152,340 +169,378 @@ enum {
|
|||
field_right = 3,
|
||||
};
|
||||
|
||||
static const char * const ts_field_names[] = {
|
||||
[0] = NULL,
|
||||
[field_expression] = "expression",
|
||||
[field_left] = "left",
|
||||
[field_right] = "right",
|
||||
static const char *const ts_field_names[] = {
|
||||
[0] = NULL,
|
||||
[field_expression] = "expression",
|
||||
[field_left] = "left",
|
||||
[field_right] = "right",
|
||||
};
|
||||
|
||||
static const TSFieldMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = {
|
||||
[1] = {.index = 0, .length = 1},
|
||||
[2] = {.index = 1, .length = 2},
|
||||
[1] = {.index = 0, .length = 1},
|
||||
[2] = {.index = 1, .length = 2},
|
||||
};
|
||||
|
||||
static const TSFieldMapEntry ts_field_map_entries[] = {
|
||||
[0] =
|
||||
{field_expression, 1},
|
||||
[1] =
|
||||
{field_left, 0},
|
||||
[0] = {field_expression, 1},
|
||||
[1] = {field_left, 0},
|
||||
{field_right, 2},
|
||||
};
|
||||
|
||||
static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = {
|
||||
[0] = {0},
|
||||
static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT]
|
||||
[MAX_ALIAS_SEQUENCE_LENGTH] = {
|
||||
[0] = {0},
|
||||
};
|
||||
|
||||
static const uint16_t ts_non_terminal_alias_map[] = {
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static bool ts_lex(TSLexer *lexer, TSStateId state) {
|
||||
START_LEXER();
|
||||
eof = lexer->eof(lexer);
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (eof) ADVANCE(7);
|
||||
if (lookahead == '!') ADVANCE(10);
|
||||
if (lookahead == '&') ADVANCE(2);
|
||||
if (lookahead == '(') ADVANCE(15);
|
||||
if (lookahead == ')') ADVANCE(16);
|
||||
if (lookahead == '=') ADVANCE(4);
|
||||
if (lookahead == '|') ADVANCE(5);
|
||||
if (lookahead == '\t' ||
|
||||
lookahead == '\n' ||
|
||||
lookahead == '\r' ||
|
||||
lookahead == ' ') SKIP(0)
|
||||
if (lookahead == '-' ||
|
||||
('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') ||
|
||||
lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
||||
END_STATE();
|
||||
case 1:
|
||||
if (lookahead == '!') ADVANCE(9);
|
||||
if (lookahead == '(') ADVANCE(15);
|
||||
if (lookahead == '\t' ||
|
||||
lookahead == '\n' ||
|
||||
lookahead == '\r' ||
|
||||
lookahead == ' ') SKIP(1)
|
||||
if (lookahead == '-' ||
|
||||
('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') ||
|
||||
lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
||||
END_STATE();
|
||||
case 2:
|
||||
if (lookahead == '&') ADVANCE(11);
|
||||
END_STATE();
|
||||
case 3:
|
||||
if (lookahead == '=') ADVANCE(14);
|
||||
END_STATE();
|
||||
case 4:
|
||||
if (lookahead == '=') ADVANCE(13);
|
||||
END_STATE();
|
||||
case 5:
|
||||
if (lookahead == '|') ADVANCE(12);
|
||||
END_STATE();
|
||||
case 6:
|
||||
if (eof) ADVANCE(7);
|
||||
if (lookahead == '!') ADVANCE(3);
|
||||
if (lookahead == '&') ADVANCE(2);
|
||||
if (lookahead == ')') ADVANCE(16);
|
||||
if (lookahead == '=') ADVANCE(4);
|
||||
if (lookahead == '|') ADVANCE(5);
|
||||
if (lookahead == '\t' ||
|
||||
lookahead == '\n' ||
|
||||
lookahead == '\r' ||
|
||||
lookahead == ' ') SKIP(6)
|
||||
END_STATE();
|
||||
case 7:
|
||||
ACCEPT_TOKEN(ts_builtin_sym_end);
|
||||
END_STATE();
|
||||
case 8:
|
||||
ACCEPT_TOKEN(sym_identifier);
|
||||
if (lookahead == '-' ||
|
||||
('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') ||
|
||||
lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z')) ADVANCE(8);
|
||||
END_STATE();
|
||||
case 9:
|
||||
ACCEPT_TOKEN(anon_sym_BANG);
|
||||
END_STATE();
|
||||
case 10:
|
||||
ACCEPT_TOKEN(anon_sym_BANG);
|
||||
if (lookahead == '=') ADVANCE(14);
|
||||
END_STATE();
|
||||
case 11:
|
||||
ACCEPT_TOKEN(anon_sym_AMP_AMP);
|
||||
END_STATE();
|
||||
case 12:
|
||||
ACCEPT_TOKEN(anon_sym_PIPE_PIPE);
|
||||
END_STATE();
|
||||
case 13:
|
||||
ACCEPT_TOKEN(anon_sym_EQ_EQ);
|
||||
END_STATE();
|
||||
case 14:
|
||||
ACCEPT_TOKEN(anon_sym_BANG_EQ);
|
||||
END_STATE();
|
||||
case 15:
|
||||
ACCEPT_TOKEN(anon_sym_LPAREN);
|
||||
END_STATE();
|
||||
case 16:
|
||||
ACCEPT_TOKEN(anon_sym_RPAREN);
|
||||
END_STATE();
|
||||
default:
|
||||
return false;
|
||||
case 0:
|
||||
if (eof)
|
||||
ADVANCE(7);
|
||||
if (lookahead == '!')
|
||||
ADVANCE(10);
|
||||
if (lookahead == '&')
|
||||
ADVANCE(2);
|
||||
if (lookahead == '(')
|
||||
ADVANCE(15);
|
||||
if (lookahead == ')')
|
||||
ADVANCE(16);
|
||||
if (lookahead == '=')
|
||||
ADVANCE(4);
|
||||
if (lookahead == '|')
|
||||
ADVANCE(5);
|
||||
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||
lookahead == ' ')
|
||||
SKIP(0)
|
||||
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z'))
|
||||
ADVANCE(8);
|
||||
END_STATE();
|
||||
case 1:
|
||||
if (lookahead == '!')
|
||||
ADVANCE(9);
|
||||
if (lookahead == '(')
|
||||
ADVANCE(15);
|
||||
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||
lookahead == ' ')
|
||||
SKIP(1)
|
||||
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z'))
|
||||
ADVANCE(8);
|
||||
END_STATE();
|
||||
case 2:
|
||||
if (lookahead == '&')
|
||||
ADVANCE(11);
|
||||
END_STATE();
|
||||
case 3:
|
||||
if (lookahead == '=')
|
||||
ADVANCE(14);
|
||||
END_STATE();
|
||||
case 4:
|
||||
if (lookahead == '=')
|
||||
ADVANCE(13);
|
||||
END_STATE();
|
||||
case 5:
|
||||
if (lookahead == '|')
|
||||
ADVANCE(12);
|
||||
END_STATE();
|
||||
case 6:
|
||||
if (eof)
|
||||
ADVANCE(7);
|
||||
if (lookahead == '!')
|
||||
ADVANCE(3);
|
||||
if (lookahead == '&')
|
||||
ADVANCE(2);
|
||||
if (lookahead == ')')
|
||||
ADVANCE(16);
|
||||
if (lookahead == '=')
|
||||
ADVANCE(4);
|
||||
if (lookahead == '|')
|
||||
ADVANCE(5);
|
||||
if (lookahead == '\t' || lookahead == '\n' || lookahead == '\r' ||
|
||||
lookahead == ' ')
|
||||
SKIP(6)
|
||||
END_STATE();
|
||||
case 7:
|
||||
ACCEPT_TOKEN(ts_builtin_sym_end);
|
||||
END_STATE();
|
||||
case 8:
|
||||
ACCEPT_TOKEN(sym_identifier);
|
||||
if (lookahead == '-' || ('0' <= lookahead && lookahead <= '9') ||
|
||||
('A' <= lookahead && lookahead <= 'Z') || lookahead == '_' ||
|
||||
('a' <= lookahead && lookahead <= 'z'))
|
||||
ADVANCE(8);
|
||||
END_STATE();
|
||||
case 9:
|
||||
ACCEPT_TOKEN(anon_sym_BANG);
|
||||
END_STATE();
|
||||
case 10:
|
||||
ACCEPT_TOKEN(anon_sym_BANG);
|
||||
if (lookahead == '=')
|
||||
ADVANCE(14);
|
||||
END_STATE();
|
||||
case 11:
|
||||
ACCEPT_TOKEN(anon_sym_AMP_AMP);
|
||||
END_STATE();
|
||||
case 12:
|
||||
ACCEPT_TOKEN(anon_sym_PIPE_PIPE);
|
||||
END_STATE();
|
||||
case 13:
|
||||
ACCEPT_TOKEN(anon_sym_EQ_EQ);
|
||||
END_STATE();
|
||||
case 14:
|
||||
ACCEPT_TOKEN(anon_sym_BANG_EQ);
|
||||
END_STATE();
|
||||
case 15:
|
||||
ACCEPT_TOKEN(anon_sym_LPAREN);
|
||||
END_STATE();
|
||||
case 16:
|
||||
ACCEPT_TOKEN(anon_sym_RPAREN);
|
||||
END_STATE();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const TSLexMode ts_lex_modes[STATE_COUNT] = {
|
||||
[0] = {.lex_state = 0},
|
||||
[1] = {.lex_state = 1},
|
||||
[2] = {.lex_state = 1},
|
||||
[3] = {.lex_state = 1},
|
||||
[4] = {.lex_state = 1},
|
||||
[5] = {.lex_state = 1},
|
||||
[6] = {.lex_state = 6},
|
||||
[7] = {.lex_state = 0},
|
||||
[8] = {.lex_state = 0},
|
||||
[9] = {.lex_state = 0},
|
||||
[10] = {.lex_state = 0},
|
||||
[11] = {.lex_state = 0},
|
||||
[12] = {.lex_state = 0},
|
||||
[13] = {.lex_state = 0},
|
||||
[14] = {.lex_state = 0},
|
||||
[15] = {.lex_state = 0},
|
||||
[16] = {.lex_state = 0},
|
||||
[17] = {.lex_state = 0},
|
||||
[0] = {.lex_state = 0}, [1] = {.lex_state = 1}, [2] = {.lex_state = 1},
|
||||
[3] = {.lex_state = 1}, [4] = {.lex_state = 1}, [5] = {.lex_state = 1},
|
||||
[6] = {.lex_state = 6}, [7] = {.lex_state = 0}, [8] = {.lex_state = 0},
|
||||
[9] = {.lex_state = 0}, [10] = {.lex_state = 0}, [11] = {.lex_state = 0},
|
||||
[12] = {.lex_state = 0}, [13] = {.lex_state = 0}, [14] = {.lex_state = 0},
|
||||
[15] = {.lex_state = 0}, [16] = {.lex_state = 0}, [17] = {.lex_state = 0},
|
||||
};
|
||||
|
||||
static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
|
||||
[0] = {
|
||||
[ts_builtin_sym_end] = ACTIONS(1),
|
||||
[sym_identifier] = ACTIONS(1),
|
||||
[anon_sym_BANG] = ACTIONS(1),
|
||||
[anon_sym_AMP_AMP] = ACTIONS(1),
|
||||
[anon_sym_PIPE_PIPE] = ACTIONS(1),
|
||||
[anon_sym_EQ_EQ] = ACTIONS(1),
|
||||
[anon_sym_BANG_EQ] = ACTIONS(1),
|
||||
[anon_sym_LPAREN] = ACTIONS(1),
|
||||
[anon_sym_RPAREN] = ACTIONS(1),
|
||||
},
|
||||
[1] = {
|
||||
[sym_source] = STATE(15),
|
||||
[sym__expression] = STATE(13),
|
||||
[sym_not] = STATE(13),
|
||||
[sym_and] = STATE(13),
|
||||
[sym_or] = STATE(13),
|
||||
[sym_equal] = STATE(13),
|
||||
[sym_not_equal] = STATE(13),
|
||||
[sym_parenthesized] = STATE(13),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[2] = {
|
||||
[sym__expression] = STATE(7),
|
||||
[sym_not] = STATE(7),
|
||||
[sym_and] = STATE(7),
|
||||
[sym_or] = STATE(7),
|
||||
[sym_equal] = STATE(7),
|
||||
[sym_not_equal] = STATE(7),
|
||||
[sym_parenthesized] = STATE(7),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[3] = {
|
||||
[sym__expression] = STATE(14),
|
||||
[sym_not] = STATE(14),
|
||||
[sym_and] = STATE(14),
|
||||
[sym_or] = STATE(14),
|
||||
[sym_equal] = STATE(14),
|
||||
[sym_not_equal] = STATE(14),
|
||||
[sym_parenthesized] = STATE(14),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[4] = {
|
||||
[sym__expression] = STATE(11),
|
||||
[sym_not] = STATE(11),
|
||||
[sym_and] = STATE(11),
|
||||
[sym_or] = STATE(11),
|
||||
[sym_equal] = STATE(11),
|
||||
[sym_not_equal] = STATE(11),
|
||||
[sym_parenthesized] = STATE(11),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[5] = {
|
||||
[sym__expression] = STATE(12),
|
||||
[sym_not] = STATE(12),
|
||||
[sym_and] = STATE(12),
|
||||
[sym_or] = STATE(12),
|
||||
[sym_equal] = STATE(12),
|
||||
[sym_not_equal] = STATE(12),
|
||||
[sym_parenthesized] = STATE(12),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[0] =
|
||||
{
|
||||
[ts_builtin_sym_end] = ACTIONS(1),
|
||||
[sym_identifier] = ACTIONS(1),
|
||||
[anon_sym_BANG] = ACTIONS(1),
|
||||
[anon_sym_AMP_AMP] = ACTIONS(1),
|
||||
[anon_sym_PIPE_PIPE] = ACTIONS(1),
|
||||
[anon_sym_EQ_EQ] = ACTIONS(1),
|
||||
[anon_sym_BANG_EQ] = ACTIONS(1),
|
||||
[anon_sym_LPAREN] = ACTIONS(1),
|
||||
[anon_sym_RPAREN] = ACTIONS(1),
|
||||
},
|
||||
[1] =
|
||||
{
|
||||
[sym_source] = STATE(15),
|
||||
[sym__expression] = STATE(13),
|
||||
[sym_not] = STATE(13),
|
||||
[sym_and] = STATE(13),
|
||||
[sym_or] = STATE(13),
|
||||
[sym_equal] = STATE(13),
|
||||
[sym_not_equal] = STATE(13),
|
||||
[sym_parenthesized] = STATE(13),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[2] =
|
||||
{
|
||||
[sym__expression] = STATE(7),
|
||||
[sym_not] = STATE(7),
|
||||
[sym_and] = STATE(7),
|
||||
[sym_or] = STATE(7),
|
||||
[sym_equal] = STATE(7),
|
||||
[sym_not_equal] = STATE(7),
|
||||
[sym_parenthesized] = STATE(7),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[3] =
|
||||
{
|
||||
[sym__expression] = STATE(14),
|
||||
[sym_not] = STATE(14),
|
||||
[sym_and] = STATE(14),
|
||||
[sym_or] = STATE(14),
|
||||
[sym_equal] = STATE(14),
|
||||
[sym_not_equal] = STATE(14),
|
||||
[sym_parenthesized] = STATE(14),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[4] =
|
||||
{
|
||||
[sym__expression] = STATE(11),
|
||||
[sym_not] = STATE(11),
|
||||
[sym_and] = STATE(11),
|
||||
[sym_or] = STATE(11),
|
||||
[sym_equal] = STATE(11),
|
||||
[sym_not_equal] = STATE(11),
|
||||
[sym_parenthesized] = STATE(11),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
[5] =
|
||||
{
|
||||
[sym__expression] = STATE(12),
|
||||
[sym_not] = STATE(12),
|
||||
[sym_and] = STATE(12),
|
||||
[sym_or] = STATE(12),
|
||||
[sym_equal] = STATE(12),
|
||||
[sym_not_equal] = STATE(12),
|
||||
[sym_parenthesized] = STATE(12),
|
||||
[sym_identifier] = ACTIONS(3),
|
||||
[anon_sym_BANG] = ACTIONS(5),
|
||||
[anon_sym_LPAREN] = ACTIONS(7),
|
||||
},
|
||||
};
|
||||
|
||||
static const uint16_t ts_small_parse_table[] = {
|
||||
[0] = 3,
|
||||
ACTIONS(11), 1,
|
||||
anon_sym_EQ_EQ,
|
||||
ACTIONS(13), 1,
|
||||
anon_sym_BANG_EQ,
|
||||
ACTIONS(9), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[13] = 1,
|
||||
ACTIONS(15), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[20] = 1,
|
||||
ACTIONS(17), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[27] = 1,
|
||||
ACTIONS(19), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[34] = 1,
|
||||
ACTIONS(21), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[41] = 1,
|
||||
ACTIONS(23), 4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[48] = 2,
|
||||
ACTIONS(27), 1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(25), 3,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[57] = 3,
|
||||
ACTIONS(27), 1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(29), 1,
|
||||
ts_builtin_sym_end,
|
||||
ACTIONS(31), 1,
|
||||
anon_sym_PIPE_PIPE,
|
||||
[67] = 3,
|
||||
ACTIONS(27), 1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(31), 1,
|
||||
anon_sym_PIPE_PIPE,
|
||||
ACTIONS(33), 1,
|
||||
anon_sym_RPAREN,
|
||||
[77] = 1,
|
||||
ACTIONS(35), 1,
|
||||
ts_builtin_sym_end,
|
||||
[81] = 1,
|
||||
ACTIONS(37), 1,
|
||||
sym_identifier,
|
||||
[85] = 1,
|
||||
ACTIONS(39), 1,
|
||||
sym_identifier,
|
||||
[0] = 3,
|
||||
ACTIONS(11),
|
||||
1,
|
||||
anon_sym_EQ_EQ,
|
||||
ACTIONS(13),
|
||||
1,
|
||||
anon_sym_BANG_EQ,
|
||||
ACTIONS(9),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[13] = 1,
|
||||
ACTIONS(15),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[20] = 1,
|
||||
ACTIONS(17),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[27] = 1,
|
||||
ACTIONS(19),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[34] = 1,
|
||||
ACTIONS(21),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[41] = 1,
|
||||
ACTIONS(23),
|
||||
4,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_AMP_AMP,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[48] = 2,
|
||||
ACTIONS(27),
|
||||
1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(25),
|
||||
3,
|
||||
ts_builtin_sym_end,
|
||||
anon_sym_PIPE_PIPE,
|
||||
anon_sym_RPAREN,
|
||||
[57] = 3,
|
||||
ACTIONS(27),
|
||||
1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(29),
|
||||
1,
|
||||
ts_builtin_sym_end,
|
||||
ACTIONS(31),
|
||||
1,
|
||||
anon_sym_PIPE_PIPE,
|
||||
[67] = 3,
|
||||
ACTIONS(27),
|
||||
1,
|
||||
anon_sym_AMP_AMP,
|
||||
ACTIONS(31),
|
||||
1,
|
||||
anon_sym_PIPE_PIPE,
|
||||
ACTIONS(33),
|
||||
1,
|
||||
anon_sym_RPAREN,
|
||||
[77] = 1,
|
||||
ACTIONS(35),
|
||||
1,
|
||||
ts_builtin_sym_end,
|
||||
[81] = 1,
|
||||
ACTIONS(37),
|
||||
1,
|
||||
sym_identifier,
|
||||
[85] = 1,
|
||||
ACTIONS(39),
|
||||
1,
|
||||
sym_identifier,
|
||||
};
|
||||
|
||||
static const uint32_t ts_small_parse_table_map[] = {
|
||||
[SMALL_STATE(6)] = 0,
|
||||
[SMALL_STATE(7)] = 13,
|
||||
[SMALL_STATE(8)] = 20,
|
||||
[SMALL_STATE(9)] = 27,
|
||||
[SMALL_STATE(10)] = 34,
|
||||
[SMALL_STATE(11)] = 41,
|
||||
[SMALL_STATE(12)] = 48,
|
||||
[SMALL_STATE(13)] = 57,
|
||||
[SMALL_STATE(14)] = 67,
|
||||
[SMALL_STATE(15)] = 77,
|
||||
[SMALL_STATE(16)] = 81,
|
||||
[SMALL_STATE(17)] = 85,
|
||||
[SMALL_STATE(6)] = 0, [SMALL_STATE(7)] = 13, [SMALL_STATE(8)] = 20,
|
||||
[SMALL_STATE(9)] = 27, [SMALL_STATE(10)] = 34, [SMALL_STATE(11)] = 41,
|
||||
[SMALL_STATE(12)] = 48, [SMALL_STATE(13)] = 57, [SMALL_STATE(14)] = 67,
|
||||
[SMALL_STATE(15)] = 77, [SMALL_STATE(16)] = 81, [SMALL_STATE(17)] = 85,
|
||||
};
|
||||
|
||||
static const TSParseActionEntry ts_parse_actions[] = {
|
||||
[0] = {.entry = {.count = 0, .reusable = false}},
|
||||
[1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(),
|
||||
[3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6),
|
||||
[5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2),
|
||||
[7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3),
|
||||
[9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__expression, 1),
|
||||
[11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16),
|
||||
[13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17),
|
||||
[15] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not, 2, .production_id = 1),
|
||||
[17] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equal, 3, .production_id = 2),
|
||||
[19] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_not_equal, 3, .production_id = 2),
|
||||
[21] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesized, 3, .production_id = 1),
|
||||
[23] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_and, 3, .production_id = 2),
|
||||
[25] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_or, 3, .production_id = 2),
|
||||
[27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4),
|
||||
[29] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source, 1),
|
||||
[31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5),
|
||||
[33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10),
|
||||
[35] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(),
|
||||
[37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8),
|
||||
[39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9),
|
||||
[0] = {.entry = {.count = 0, .reusable = false}},
|
||||
[1] = {.entry = {.count = 1, .reusable = false}},
|
||||
RECOVER(),
|
||||
[3] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(6),
|
||||
[5] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(2),
|
||||
[7] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(3),
|
||||
[9] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym__expression, 1),
|
||||
[11] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(16),
|
||||
[13] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(17),
|
||||
[15] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_not, 2, .production_id = 1),
|
||||
[17] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_equal, 3, .production_id = 2),
|
||||
[19] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_not_equal, 3, .production_id = 2),
|
||||
[21] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_parenthesized, 3, .production_id = 1),
|
||||
[23] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_and, 3, .production_id = 2),
|
||||
[25] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_or, 3, .production_id = 2),
|
||||
[27] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(4),
|
||||
[29] = {.entry = {.count = 1, .reusable = true}},
|
||||
REDUCE(sym_source, 1),
|
||||
[31] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(5),
|
||||
[33] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(10),
|
||||
[35] = {.entry = {.count = 1, .reusable = true}},
|
||||
ACCEPT_INPUT(),
|
||||
[37] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(8),
|
||||
[39] = {.entry = {.count = 1, .reusable = true}},
|
||||
SHIFT(9),
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -497,30 +552,30 @@ extern "C" {
|
|||
|
||||
extern const TSLanguage *tree_sitter_context_predicate(void) {
|
||||
static const TSLanguage language = {
|
||||
.version = LANGUAGE_VERSION,
|
||||
.symbol_count = SYMBOL_COUNT,
|
||||
.alias_count = ALIAS_COUNT,
|
||||
.token_count = TOKEN_COUNT,
|
||||
.external_token_count = EXTERNAL_TOKEN_COUNT,
|
||||
.state_count = STATE_COUNT,
|
||||
.large_state_count = LARGE_STATE_COUNT,
|
||||
.production_id_count = PRODUCTION_ID_COUNT,
|
||||
.field_count = FIELD_COUNT,
|
||||
.max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH,
|
||||
.parse_table = &ts_parse_table[0][0],
|
||||
.small_parse_table = ts_small_parse_table,
|
||||
.small_parse_table_map = ts_small_parse_table_map,
|
||||
.parse_actions = ts_parse_actions,
|
||||
.symbol_names = ts_symbol_names,
|
||||
.field_names = ts_field_names,
|
||||
.field_map_slices = ts_field_map_slices,
|
||||
.field_map_entries = ts_field_map_entries,
|
||||
.symbol_metadata = ts_symbol_metadata,
|
||||
.public_symbol_map = ts_symbol_map,
|
||||
.alias_map = ts_non_terminal_alias_map,
|
||||
.alias_sequences = &ts_alias_sequences[0][0],
|
||||
.lex_modes = ts_lex_modes,
|
||||
.lex_fn = ts_lex,
|
||||
.version = LANGUAGE_VERSION,
|
||||
.symbol_count = SYMBOL_COUNT,
|
||||
.alias_count = ALIAS_COUNT,
|
||||
.token_count = TOKEN_COUNT,
|
||||
.external_token_count = EXTERNAL_TOKEN_COUNT,
|
||||
.state_count = STATE_COUNT,
|
||||
.large_state_count = LARGE_STATE_COUNT,
|
||||
.production_id_count = PRODUCTION_ID_COUNT,
|
||||
.field_count = FIELD_COUNT,
|
||||
.max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH,
|
||||
.parse_table = &ts_parse_table[0][0],
|
||||
.small_parse_table = ts_small_parse_table,
|
||||
.small_parse_table_map = ts_small_parse_table_map,
|
||||
.parse_actions = ts_parse_actions,
|
||||
.symbol_names = ts_symbol_names,
|
||||
.field_names = ts_field_names,
|
||||
.field_map_slices = ts_field_map_slices,
|
||||
.field_map_entries = ts_field_map_entries,
|
||||
.symbol_metadata = ts_symbol_metadata,
|
||||
.public_symbol_map = ts_symbol_map,
|
||||
.alias_map = ts_non_terminal_alias_map,
|
||||
.alias_sequences = &ts_alias_sequences[0][0],
|
||||
.lex_modes = ts_lex_modes,
|
||||
.lex_fn = ts_lex,
|
||||
};
|
||||
return &language;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
106
crates/gpui/src/app/callback_collection.rs
Normal file
106
crates/gpui/src/app/callback_collection.rs
Normal file
|
@ -0,0 +1,106 @@
|
|||
use std::sync::Arc;
|
||||
use std::{hash::Hash, sync::Weak};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use collections::{btree_map, BTreeMap, HashMap};
|
||||
|
||||
use crate::MutableAppContext;
|
||||
|
||||
pub type Mapping<K, F> = Mutex<HashMap<K, BTreeMap<usize, Option<F>>>>;
|
||||
|
||||
pub struct CallbackCollection<K: Hash + Eq, F> {
|
||||
internal: Arc<Mapping<K, F>>,
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq, F> Clone for CallbackCollection<K, F> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
internal: self.internal.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq + Copy, F> Default for CallbackCollection<K, F> {
|
||||
fn default() -> Self {
|
||||
CallbackCollection {
|
||||
internal: Arc::new(Mutex::new(Default::default())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq + Copy, F> CallbackCollection<K, F> {
|
||||
pub fn downgrade(&self) -> Weak<Mapping<K, F>> {
|
||||
Arc::downgrade(&self.internal)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.internal.lock().is_empty()
|
||||
}
|
||||
|
||||
pub fn add_callback(&mut self, id: K, subscription_id: usize, callback: F) {
|
||||
self.internal
|
||||
.lock()
|
||||
.entry(id)
|
||||
.or_default()
|
||||
.insert(subscription_id, Some(callback));
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: K) {
|
||||
self.internal.lock().remove(&id);
|
||||
}
|
||||
|
||||
pub fn add_or_remove_callback(&mut self, id: K, subscription_id: usize, callback: F) {
|
||||
match self
|
||||
.internal
|
||||
.lock()
|
||||
.entry(id)
|
||||
.or_default()
|
||||
.entry(subscription_id)
|
||||
{
|
||||
btree_map::Entry::Vacant(entry) => {
|
||||
entry.insert(Some(callback));
|
||||
}
|
||||
|
||||
btree_map::Entry::Occupied(entry) => {
|
||||
// TODO: This seems like it should never be called because no code
|
||||
// should ever attempt to remove an existing callback
|
||||
debug_assert!(entry.get().is_none());
|
||||
entry.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_and_cleanup<C: FnMut(&mut F, &mut MutableAppContext) -> bool>(
|
||||
&mut self,
|
||||
id: K,
|
||||
cx: &mut MutableAppContext,
|
||||
mut call_callback: C,
|
||||
) {
|
||||
let callbacks = self.internal.lock().remove(&id);
|
||||
if let Some(callbacks) = callbacks {
|
||||
for (subscription_id, callback) in callbacks {
|
||||
if let Some(mut callback) = callback {
|
||||
let alive = call_callback(&mut callback, cx);
|
||||
if alive {
|
||||
match self
|
||||
.internal
|
||||
.lock()
|
||||
.entry(id)
|
||||
.or_default()
|
||||
.entry(subscription_id)
|
||||
{
|
||||
btree_map::Entry::Vacant(entry) => {
|
||||
entry.insert(Some(callback));
|
||||
}
|
||||
btree_map::Entry::Occupied(entry) => {
|
||||
entry.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -389,9 +389,9 @@ impl ElementBox {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<ElementRc> for ElementBox {
|
||||
fn into(self) -> ElementRc {
|
||||
self.0
|
||||
impl From<ElementBox> for ElementRc {
|
||||
fn from(val: ElementBox) -> Self {
|
||||
val.0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,14 @@ use crate::{
|
|||
};
|
||||
use crate::{Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Empty {
|
||||
collapsed: bool,
|
||||
}
|
||||
|
||||
impl Empty {
|
||||
pub fn new() -> Self {
|
||||
Self { collapsed: false }
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn collapsed(mut self) -> Self {
|
||||
|
|
|
@ -24,13 +24,13 @@ impl Expanded {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn to_full_width(mut self) -> Self {
|
||||
pub fn full_width(mut self) -> Self {
|
||||
self.full_width = true;
|
||||
self.full_height = false;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_full_height(mut self) -> Self {
|
||||
pub fn full_height(mut self) -> Self {
|
||||
self.full_width = false;
|
||||
self.full_height = true;
|
||||
self
|
||||
|
|
|
@ -53,8 +53,8 @@ impl Element for Image {
|
|||
_: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let desired_size = vec2f(
|
||||
self.style.width.unwrap_or(constraint.max.x()),
|
||||
self.style.height.unwrap_or(constraint.max.y()),
|
||||
self.style.width.unwrap_or_else(|| constraint.max.x()),
|
||||
self.style.height.unwrap_or_else(|| constraint.max.y()),
|
||||
);
|
||||
let size = constrain_size_preserving_aspect_ratio(
|
||||
constraint.constrain(desired_size),
|
||||
|
|
|
@ -33,6 +33,7 @@ struct StateInner {
|
|||
logical_scroll_top: Option<ListOffset>,
|
||||
orientation: Orientation,
|
||||
overdraw: f32,
|
||||
#[allow(clippy::type_complexity)]
|
||||
scroll_handler: Option<Box<dyn FnMut(Range<usize>, &mut EventContext)>>,
|
||||
}
|
||||
|
||||
|
@ -311,19 +312,17 @@ impl Element for List {
|
|||
drop(cursor);
|
||||
state.items = new_items;
|
||||
|
||||
match event {
|
||||
Event::ScrollWheel(ScrollWheelEvent {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
}) => {
|
||||
if bounds.contains_point(*position) {
|
||||
if state.scroll(scroll_top, bounds.height(), *delta, *precise, cx) {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if let Event::ScrollWheel(ScrollWheelEvent {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
}) = event
|
||||
{
|
||||
if bounds.contains_point(*position)
|
||||
&& state.scroll(scroll_top, bounds.height(), *delta, *precise, cx)
|
||||
{
|
||||
handled = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
handled
|
||||
|
|
|
@ -129,7 +129,7 @@ impl Element for MouseEventHandler {
|
|||
|
||||
cx.scene.push_mouse_region(MouseRegion::from_handlers(
|
||||
cx.current_view_id(),
|
||||
Some(self.discriminant.clone()),
|
||||
Some(self.discriminant),
|
||||
hit_bounds,
|
||||
self.handlers.clone(),
|
||||
));
|
||||
|
|
|
@ -74,7 +74,7 @@ impl Element for Overlay {
|
|||
size: &mut Self::LayoutState,
|
||||
cx: &mut PaintContext,
|
||||
) {
|
||||
let mut bounds = RectF::new(self.abs_position.unwrap_or(bounds.origin()), *size);
|
||||
let mut bounds = RectF::new(self.abs_position.unwrap_or_else(|| bounds.origin()), *size);
|
||||
cx.scene.push_stacking_context(None);
|
||||
|
||||
if self.hoverable {
|
||||
|
|
|
@ -8,15 +8,14 @@ use crate::{
|
|||
SizeConstraint,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Stack {
|
||||
children: Vec<ElementBox>,
|
||||
}
|
||||
|
||||
impl Stack {
|
||||
pub fn new() -> Self {
|
||||
Stack {
|
||||
children: Vec::new(),
|
||||
}
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ impl Element for Text {
|
|||
chunks,
|
||||
&self.style,
|
||||
cx.text_layout_cache,
|
||||
&cx.font_cache,
|
||||
cx.font_cache,
|
||||
usize::MAX,
|
||||
self.text.matches('\n').count() + 1,
|
||||
);
|
||||
|
|
|
@ -45,6 +45,7 @@ pub struct LayoutState {
|
|||
pub struct UniformList {
|
||||
state: UniformListState,
|
||||
item_count: usize,
|
||||
#[allow(clippy::type_complexity)]
|
||||
append_items: Box<dyn Fn(Range<usize>, &mut Vec<ElementBox>, &mut LayoutContext)>,
|
||||
padding_top: f32,
|
||||
padding_bottom: f32,
|
||||
|
@ -310,19 +311,17 @@ impl Element for UniformList {
|
|||
handled = item.dispatch_event(event, cx) || handled;
|
||||
}
|
||||
|
||||
match event {
|
||||
Event::ScrollWheel(ScrollWheelEvent {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
}) => {
|
||||
if bounds.contains_point(*position) {
|
||||
if self.scroll(*position, *delta, *precise, layout.scroll_max, cx) {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if let Event::ScrollWheel(ScrollWheelEvent {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
}) = event
|
||||
{
|
||||
if bounds.contains_point(*position)
|
||||
&& self.scroll(*position, *delta, *precise, layout.scroll_max, cx)
|
||||
{
|
||||
handled = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
handled
|
||||
|
|
|
@ -332,7 +332,7 @@ impl Deterministic {
|
|||
|
||||
pub fn now(&self) -> std::time::Instant {
|
||||
let state = self.state.lock();
|
||||
state.now.clone()
|
||||
state.now
|
||||
}
|
||||
|
||||
pub fn advance_clock(&self, duration: Duration) {
|
||||
|
@ -681,6 +681,12 @@ impl Background {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for Background {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Scope<'a> {
|
||||
executor: Arc<Background>,
|
||||
futures: Vec<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>,
|
||||
|
|
|
@ -117,7 +117,7 @@ impl FontCache {
|
|||
.font_selections
|
||||
.entry(family_id)
|
||||
.or_default()
|
||||
.insert(properties.clone(), font_id);
|
||||
.insert(*properties, font_id);
|
||||
Ok(font_id)
|
||||
}
|
||||
}
|
||||
|
@ -257,10 +257,10 @@ mod tests {
|
|||
let arial = fonts.load_family(&["Arial"]).unwrap();
|
||||
let arial_regular = fonts.select_font(arial, &Properties::new()).unwrap();
|
||||
let arial_italic = fonts
|
||||
.select_font(arial, &Properties::new().style(Style::Italic))
|
||||
.select_font(arial, Properties::new().style(Style::Italic))
|
||||
.unwrap();
|
||||
let arial_bold = fonts
|
||||
.select_font(arial, &Properties::new().weight(Weight::BOLD))
|
||||
.select_font(arial, Properties::new().weight(Weight::BOLD))
|
||||
.unwrap();
|
||||
assert_ne!(arial_regular, arial_italic);
|
||||
assert_ne!(arial_regular, arial_bold);
|
||||
|
|
|
@ -332,8 +332,7 @@ impl<'de> Deserialize<'de> for TextStyle {
|
|||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(Self::from_json(TextStyleJson::deserialize(deserializer)?)
|
||||
.map_err(|e| de::Error::custom(e))?)
|
||||
Self::from_json(TextStyleJson::deserialize(deserializer)?).map_err(de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ enum PathVertexKind {
|
|||
Quadratic,
|
||||
}
|
||||
|
||||
impl Default for PathBuilder {
|
||||
fn default() -> Self {
|
||||
PathBuilder::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl PathBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -58,10 +64,7 @@ impl PathBuilder {
|
|||
|
||||
pub fn build(mut self, color: Color, clip_bounds: Option<RectF>) -> Path {
|
||||
if let Some(clip_bounds) = clip_bounds {
|
||||
self.bounds = self
|
||||
.bounds
|
||||
.intersection(clip_bounds)
|
||||
.unwrap_or(RectF::default());
|
||||
self.bounds = self.bounds.intersection(clip_bounds).unwrap_or_default();
|
||||
}
|
||||
Path {
|
||||
bounds: self.bounds,
|
||||
|
|
|
@ -202,7 +202,7 @@ impl Keymap {
|
|||
for (ix, binding) in bindings.iter().enumerate() {
|
||||
binding_indices_by_action_type
|
||||
.entry(binding.action.as_any().type_id())
|
||||
.or_insert_with(|| SmallVec::new())
|
||||
.or_insert_with(SmallVec::new)
|
||||
.push(ix);
|
||||
}
|
||||
Self {
|
||||
|
@ -211,10 +211,7 @@ impl Keymap {
|
|||
}
|
||||
}
|
||||
|
||||
fn bindings_for_action_type<'a>(
|
||||
&'a self,
|
||||
action_type: TypeId,
|
||||
) -> impl Iterator<Item = &'a Binding> {
|
||||
fn bindings_for_action_type(&self, action_type: TypeId) -> impl Iterator<Item = &'_ Binding> {
|
||||
self.binding_indices_by_action_type
|
||||
.get(&action_type)
|
||||
.map(SmallVec::as_slice)
|
||||
|
@ -253,7 +250,7 @@ impl Binding {
|
|||
|
||||
let keystrokes = keystrokes
|
||||
.split_whitespace()
|
||||
.map(|key| Keystroke::parse(key))
|
||||
.map(Keystroke::parse)
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
Ok(Self {
|
||||
|
@ -281,7 +278,7 @@ impl Keystroke {
|
|||
let mut function = false;
|
||||
let mut key = None;
|
||||
|
||||
let mut components = source.split("-").peekable();
|
||||
let mut components = source.split('-').peekable();
|
||||
while let Some(component) = components.next() {
|
||||
match component {
|
||||
"ctrl" => ctrl = true,
|
||||
|
@ -379,12 +376,12 @@ impl ContextPredicate {
|
|||
let kind = node.kind();
|
||||
|
||||
match kind {
|
||||
"source" => Self::from_node(node.child(0).ok_or(anyhow!(parse_error))?, source),
|
||||
"source" => Self::from_node(node.child(0).ok_or_else(|| anyhow!(parse_error))?, source),
|
||||
"identifier" => Ok(Self::Identifier(node.utf8_text(source)?.into())),
|
||||
"not" => {
|
||||
let child = Self::from_node(
|
||||
node.child_by_field_name("expression")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
.ok_or_else(|| anyhow!(parse_error))?,
|
||||
source,
|
||||
)?;
|
||||
Ok(Self::Not(Box::new(child)))
|
||||
|
@ -392,12 +389,12 @@ impl ContextPredicate {
|
|||
"and" | "or" => {
|
||||
let left = Box::new(Self::from_node(
|
||||
node.child_by_field_name("left")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
.ok_or_else(|| anyhow!(parse_error))?,
|
||||
source,
|
||||
)?);
|
||||
let right = Box::new(Self::from_node(
|
||||
node.child_by_field_name("right")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
.ok_or_else(|| anyhow!(parse_error))?,
|
||||
source,
|
||||
)?);
|
||||
if kind == "and" {
|
||||
|
@ -409,12 +406,12 @@ impl ContextPredicate {
|
|||
"equal" | "not_equal" => {
|
||||
let left = node
|
||||
.child_by_field_name("left")
|
||||
.ok_or(anyhow!(parse_error))?
|
||||
.ok_or_else(|| anyhow!(parse_error))?
|
||||
.utf8_text(source)?
|
||||
.into();
|
||||
let right = node
|
||||
.child_by_field_name("right")
|
||||
.ok_or(anyhow!(parse_error))?
|
||||
.ok_or_else(|| anyhow!(parse_error))?
|
||||
.utf8_text(source)?
|
||||
.into();
|
||||
if kind == "equal" {
|
||||
|
@ -425,7 +422,7 @@ impl ContextPredicate {
|
|||
}
|
||||
"parenthesized" => Self::from_node(
|
||||
node.child_by_field_name("expression")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
.ok_or_else(|| anyhow!(parse_error))?,
|
||||
source,
|
||||
),
|
||||
_ => Err(anyhow!(parse_error)),
|
||||
|
@ -604,7 +601,7 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn downcast<'a, A: Action>(action: &'a Option<Box<dyn Action>>) -> Option<&'a A> {
|
||||
fn downcast<A: Action>(action: &Option<Box<dyn Action>>) -> Option<&A> {
|
||||
action
|
||||
.as_ref()
|
||||
.and_then(|action| action.as_any().downcast_ref())
|
||||
|
|
|
@ -74,7 +74,7 @@ pub(crate) trait ForegroundPlatform {
|
|||
fn on_quit(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>);
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>);
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce()>);
|
||||
|
||||
fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
||||
fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
|
||||
|
@ -112,6 +112,7 @@ pub trait Window: WindowContext {
|
|||
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>);
|
||||
fn on_resize(&mut self, callback: Box<dyn FnMut()>);
|
||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>);
|
||||
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>);
|
||||
fn on_close(&mut self, callback: Box<dyn FnOnce()>);
|
||||
fn set_input_handler(&mut self, input_handler: Box<dyn InputHandler>);
|
||||
|
|
|
@ -223,7 +223,7 @@ unsafe fn parse_keystroke(native_event: id) -> Keystroke {
|
|||
let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
|
||||
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask)
|
||||
&& first_char.map_or(true, |ch| {
|
||||
ch < NSUpArrowFunctionKey || ch > NSModeSwitchFunctionKey
|
||||
!(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch)
|
||||
});
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
|
|
|
@ -53,6 +53,12 @@ impl FontSystem {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for FontSystem {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl platform::FontSystem for FontSystem {
|
||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()> {
|
||||
self.0.write().add_fonts(fonts)
|
||||
|
@ -402,7 +408,7 @@ impl FontSystemState {
|
|||
fn wrap_line(&self, text: &str, font_id: FontId, font_size: f32, width: f32) -> Vec<usize> {
|
||||
let mut string = CFMutableAttributedString::new();
|
||||
string.replace_str(&CFString::new(text), CFRange::init(0, 0));
|
||||
let cf_range = CFRange::init(0 as isize, text.encode_utf16().count() as isize);
|
||||
let cf_range = CFRange::init(0, text.encode_utf16().count() as isize);
|
||||
let font = &self.fonts[font_id.0];
|
||||
unsafe {
|
||||
string.set_attribute(
|
||||
|
@ -505,14 +511,14 @@ mod tests {
|
|||
};
|
||||
let menlo_italic = RunStyle {
|
||||
font_id: fonts
|
||||
.select_font(&menlo, &Properties::new().style(Style::Italic))
|
||||
.select_font(&menlo, Properties::new().style(Style::Italic))
|
||||
.unwrap(),
|
||||
color: Default::default(),
|
||||
underline: Default::default(),
|
||||
};
|
||||
let menlo_bold = RunStyle {
|
||||
font_id: fonts
|
||||
.select_font(&menlo, &Properties::new().weight(Weight::BOLD))
|
||||
.select_font(&menlo, Properties::new().weight(Weight::BOLD))
|
||||
.unwrap(),
|
||||
color: Default::default(),
|
||||
underline: Default::default(),
|
||||
|
@ -599,7 +605,7 @@ mod tests {
|
|||
let name = format!("/Users/as-cii/Desktop/twog-{}.png", i);
|
||||
let path = Path::new(&name);
|
||||
let file = File::create(path).unwrap();
|
||||
let ref mut w = BufWriter::new(file);
|
||||
let w = &mut BufWriter::new(file);
|
||||
|
||||
let mut encoder = png::Encoder::new(w, bounds.width() as u32, bounds.height() as u32);
|
||||
encoder.set_color(png::ColorType::Grayscale);
|
||||
|
|
|
@ -50,7 +50,7 @@ use time::UtcOffset;
|
|||
#[allow(non_upper_case_globals)]
|
||||
const NSUTF8StringEncoding: NSUInteger = 4;
|
||||
|
||||
const MAC_PLATFORM_IVAR: &'static str = "platform";
|
||||
const MAC_PLATFORM_IVAR: &str = "platform";
|
||||
static mut APP_CLASS: *const Class = ptr::null();
|
||||
static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
|
||||
|
||||
|
@ -118,7 +118,7 @@ pub struct MacForegroundPlatformState {
|
|||
validate_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
|
||||
will_open_menu: Option<Box<dyn FnMut()>>,
|
||||
open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
|
||||
finish_launching: Option<Box<dyn FnOnce() -> ()>>,
|
||||
finish_launching: Option<Box<dyn FnOnce()>>,
|
||||
menu_actions: Vec<Box<dyn Action>>,
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ impl platform::ForegroundPlatform for MacForegroundPlatform {
|
|||
self.0.borrow_mut().open_urls = Some(callback);
|
||||
}
|
||||
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>) {
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
|
||||
self.0.borrow_mut().finish_launching = Some(on_finish_launching);
|
||||
|
||||
unsafe {
|
||||
|
@ -533,7 +533,7 @@ impl platform::Platform for MacPlatform {
|
|||
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
||||
unsafe {
|
||||
if let Some(text_bytes) = self.read_from_pasteboard(NSPasteboardTypeString) {
|
||||
let text = String::from_utf8_lossy(&text_bytes).to_string();
|
||||
let text = String::from_utf8_lossy(text_bytes).to_string();
|
||||
let hash_bytes = self
|
||||
.read_from_pasteboard(self.text_hash_pasteboard_type)
|
||||
.and_then(|bytes| bytes.try_into().ok())
|
||||
|
|
|
@ -14,8 +14,7 @@ use metal::{MTLPixelFormat, MTLResourceOptions, NSRange};
|
|||
use shaders::ToFloat2 as _;
|
||||
use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, sync::Arc, vec};
|
||||
|
||||
const SHADERS_METALLIB: &'static [u8] =
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
|
||||
const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
|
||||
const INSTANCE_BUFFER_SIZE: usize = 8192 * 1024; // This is an arbitrary decision. There's probably a more optimal value.
|
||||
|
||||
pub struct Renderer {
|
||||
|
@ -385,10 +384,10 @@ impl Renderer {
|
|||
drawable_size: Vector2F,
|
||||
command_encoder: &metal::RenderCommandEncoderRef,
|
||||
) {
|
||||
let clip_bounds = (layer.clip_bounds().unwrap_or(RectF::new(
|
||||
vec2f(0., 0.),
|
||||
drawable_size / scene.scale_factor(),
|
||||
)) * scene.scale_factor())
|
||||
let clip_bounds = (layer
|
||||
.clip_bounds()
|
||||
.unwrap_or_else(|| RectF::new(vec2f(0., 0.), drawable_size / scene.scale_factor()))
|
||||
* scene.scale_factor())
|
||||
.round();
|
||||
command_encoder.set_scissor_rect(metal::MTLScissorRect {
|
||||
x: clip_bounds.origin_x() as NSUInteger,
|
||||
|
@ -438,8 +437,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
let buffer_contents = unsafe {
|
||||
(self.instances.contents() as *mut u8).offset(*offset as isize)
|
||||
as *mut shaders::GPUIShadow
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIShadow
|
||||
};
|
||||
for (ix, shadow) in shadows.iter().enumerate() {
|
||||
let shape_bounds = shadow.bounds * scale_factor;
|
||||
|
@ -451,7 +449,7 @@ impl Renderer {
|
|||
color: shadow.color.to_uchar4(),
|
||||
};
|
||||
unsafe {
|
||||
*(buffer_contents.offset(ix as isize)) = shader_shadow;
|
||||
*(buffer_contents.add(ix)) = shader_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,8 +501,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
let buffer_contents = unsafe {
|
||||
(self.instances.contents() as *mut u8).offset(*offset as isize)
|
||||
as *mut shaders::GPUIQuad
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIQuad
|
||||
};
|
||||
for (ix, quad) in quads.iter().enumerate() {
|
||||
let bounds = quad.bounds * scale_factor;
|
||||
|
@ -514,7 +511,7 @@ impl Renderer {
|
|||
size: bounds.size().round().to_float2(),
|
||||
background_color: quad
|
||||
.background
|
||||
.unwrap_or(Color::transparent_black())
|
||||
.unwrap_or_else(Color::transparent_black)
|
||||
.to_uchar4(),
|
||||
border_top: border_width * (quad.border.top as usize as f32),
|
||||
border_right: border_width * (quad.border.right as usize as f32),
|
||||
|
@ -524,7 +521,7 @@ impl Renderer {
|
|||
corner_radius: quad.corner_radius * scale_factor,
|
||||
};
|
||||
unsafe {
|
||||
*(buffer_contents.offset(ix as isize)) = shader_quad;
|
||||
*(buffer_contents.add(ix)) = shader_quad;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,9 +638,8 @@ impl Renderer {
|
|||
);
|
||||
|
||||
unsafe {
|
||||
let buffer_contents = (self.instances.contents() as *mut u8)
|
||||
.offset(*offset as isize)
|
||||
as *mut shaders::GPUISprite;
|
||||
let buffer_contents =
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUISprite;
|
||||
std::ptr::copy_nonoverlapping(sprites.as_ptr(), buffer_contents, sprites.len());
|
||||
}
|
||||
|
||||
|
@ -757,9 +753,8 @@ impl Renderer {
|
|||
);
|
||||
|
||||
unsafe {
|
||||
let buffer_contents = (self.instances.contents() as *mut u8)
|
||||
.offset(*offset as isize)
|
||||
as *mut shaders::GPUIImage;
|
||||
let buffer_contents =
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIImage;
|
||||
std::ptr::copy_nonoverlapping(images.as_ptr(), buffer_contents, images.len());
|
||||
}
|
||||
|
||||
|
@ -821,10 +816,9 @@ impl Renderer {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let buffer_contents = (self.instances.contents() as *mut u8)
|
||||
.offset(*offset as isize)
|
||||
as *mut shaders::GPUISprite;
|
||||
*buffer_contents.offset(atlas_sprite_count as isize) = sprite.shader_data;
|
||||
let buffer_contents =
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUISprite;
|
||||
*buffer_contents.add(atlas_sprite_count) = sprite.shader_data;
|
||||
}
|
||||
|
||||
atlas_sprite_count += 1;
|
||||
|
@ -917,8 +911,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
let buffer_contents = unsafe {
|
||||
(self.instances.contents() as *mut u8).offset(*offset as isize)
|
||||
as *mut shaders::GPUIUnderline
|
||||
(self.instances.contents() as *mut u8).add(*offset) as *mut shaders::GPUIUnderline
|
||||
};
|
||||
for (ix, underline) in underlines.iter().enumerate() {
|
||||
let origin = underline.origin * scale_factor;
|
||||
|
@ -935,7 +928,7 @@ impl Renderer {
|
|||
squiggly: underline.squiggly as u8,
|
||||
};
|
||||
unsafe {
|
||||
*(buffer_contents.offset(ix as isize)) = shader_underline;
|
||||
*(buffer_contents.add(ix)) = shader_underline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
const WINDOW_STATE_IVAR: &'static str = "windowState";
|
||||
const WINDOW_STATE_IVAR: &str = "windowState";
|
||||
|
||||
static mut WINDOW_CLASS: *const Class = ptr::null();
|
||||
static mut VIEW_CLASS: *const Class = ptr::null();
|
||||
|
@ -72,7 +72,7 @@ impl NSRange {
|
|||
self.location != NSNotFound as NSUInteger
|
||||
}
|
||||
|
||||
fn to_range(&self) -> Option<Range<usize>> {
|
||||
fn to_range(self) -> Option<Range<usize>> {
|
||||
if self.is_valid() {
|
||||
let start = self.location as usize;
|
||||
let end = start + self.length as usize;
|
||||
|
@ -128,6 +128,14 @@ unsafe fn build_classes() {
|
|||
sel!(windowDidResize:),
|
||||
window_did_resize as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowWillEnterFullScreen:),
|
||||
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowWillExitFullScreen:),
|
||||
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(windowDidBecomeKey:),
|
||||
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
|
||||
|
@ -276,6 +284,7 @@ struct WindowState {
|
|||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
resize_callback: Option<Box<dyn FnMut()>>,
|
||||
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
|
||||
close_callback: Option<Box<dyn FnOnce()>>,
|
||||
input_handler: Option<Box<dyn InputHandler>>,
|
||||
|
@ -369,6 +378,7 @@ impl Window {
|
|||
should_close_callback: None,
|
||||
close_callback: None,
|
||||
activate_callback: None,
|
||||
fullscreen_callback: None,
|
||||
input_handler: None,
|
||||
pending_key_down: None,
|
||||
performed_key_equivalent: false,
|
||||
|
@ -468,6 +478,10 @@ impl platform::Window for Window {
|
|||
self.0.as_ref().borrow_mut().resize_callback = Some(callback);
|
||||
}
|
||||
|
||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
|
||||
self.0.as_ref().borrow_mut().fullscreen_callback = Some(callback);
|
||||
}
|
||||
|
||||
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>) {
|
||||
self.0.as_ref().borrow_mut().should_close_callback = Some(callback);
|
||||
}
|
||||
|
@ -500,7 +514,7 @@ impl platform::Window for Window {
|
|||
};
|
||||
let _: () = msg_send![alert, setAlertStyle: alert_style];
|
||||
let _: () = msg_send![alert, setMessageText: ns_string(msg)];
|
||||
for (ix, answer) in answers.into_iter().enumerate() {
|
||||
for (ix, answer) in answers.iter().enumerate() {
|
||||
let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer)];
|
||||
let _: () = msg_send![button, setTag: ix as NSInteger];
|
||||
}
|
||||
|
@ -708,14 +722,14 @@ extern "C" fn yes(_: &Object, _: Sel) -> BOOL {
|
|||
extern "C" fn dealloc_window(this: &Object, _: Sel) {
|
||||
unsafe {
|
||||
drop_window_state(this);
|
||||
let () = msg_send![super(this, class!(NSWindow)), dealloc];
|
||||
let _: () = msg_send![super(this, class!(NSWindow)), dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn dealloc_view(this: &Object, _: Sel) {
|
||||
unsafe {
|
||||
drop_window_state(this);
|
||||
let () = msg_send![super(this, class!(NSView)), dealloc];
|
||||
let _: () = msg_send![super(this, class!(NSView)), dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -902,7 +916,7 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
|||
|
||||
extern "C" fn send_event(this: &Object, _: Sel, native_event: id) {
|
||||
unsafe {
|
||||
let () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event];
|
||||
let _: () = msg_send![super(this, class!(NSWindow)), sendEvent: native_event];
|
||||
get_window_state(this).borrow_mut().performed_key_equivalent = false;
|
||||
}
|
||||
}
|
||||
|
@ -912,6 +926,24 @@ extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
|||
window_state.as_ref().borrow().move_traffic_light();
|
||||
}
|
||||
|
||||
extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
window_fullscreen_changed(this, true);
|
||||
}
|
||||
|
||||
extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
window_fullscreen_changed(this, false);
|
||||
}
|
||||
|
||||
fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) {
|
||||
let window_state = unsafe { get_window_state(this) };
|
||||
let mut window_state_borrow = window_state.as_ref().borrow_mut();
|
||||
if let Some(mut callback) = window_state_borrow.fullscreen_callback.take() {
|
||||
drop(window_state_borrow);
|
||||
callback(is_fullscreen);
|
||||
window_state.borrow_mut().fullscreen_callback = Some(callback);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) {
|
||||
let is_active = if selector == sel!(windowDidBecomeKey:) {
|
||||
true
|
||||
|
@ -963,7 +995,7 @@ extern "C" fn close_window(this: &Object, _: Sel) {
|
|||
callback();
|
||||
}
|
||||
|
||||
let () = msg_send![super(this, class!(NSWindow)), close];
|
||||
let _: () = msg_send![super(this, class!(NSWindow)), close];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,17 +1161,22 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS
|
|||
.flatten()
|
||||
.is_some();
|
||||
|
||||
if is_composing || text.chars().count() > 1 || pending_key_down.is_none() {
|
||||
with_input_handler(this, |input_handler| {
|
||||
input_handler.replace_text_in_range(replacement_range, text)
|
||||
});
|
||||
} else {
|
||||
let mut pending_key_down = pending_key_down.unwrap();
|
||||
pending_key_down.1 = Some(InsertText {
|
||||
replacement_range,
|
||||
text: text.to_string(),
|
||||
});
|
||||
window_state.borrow_mut().pending_key_down = Some(pending_key_down);
|
||||
match pending_key_down {
|
||||
None | Some(_) if is_composing || text.chars().count() > 1 => {
|
||||
with_input_handler(this, |input_handler| {
|
||||
input_handler.replace_text_in_range(replacement_range, text)
|
||||
});
|
||||
}
|
||||
|
||||
Some(mut pending_key_down) => {
|
||||
pending_key_down.1 = Some(InsertText {
|
||||
replacement_range,
|
||||
text: text.to_string(),
|
||||
});
|
||||
window_state.borrow_mut().pending_key_down = Some(pending_key_down);
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ pub struct Window {
|
|||
event_handlers: Vec<Box<dyn FnMut(super::Event) -> bool>>,
|
||||
resize_handlers: Vec<Box<dyn FnMut()>>,
|
||||
close_handlers: Vec<Box<dyn FnOnce()>>,
|
||||
fullscreen_handlers: Vec<Box<dyn FnMut(bool)>>,
|
||||
pub(crate) active_status_change_handlers: Vec<Box<dyn FnMut(bool)>>,
|
||||
pub(crate) should_close_handler: Option<Box<dyn FnMut() -> bool>>,
|
||||
pub(crate) title: Option<String>,
|
||||
|
@ -73,7 +74,7 @@ impl super::ForegroundPlatform for ForegroundPlatform {
|
|||
|
||||
fn on_open_urls(&self, _: Box<dyn FnMut(Vec<String>)>) {}
|
||||
|
||||
fn run(&self, _on_finish_launching: Box<dyn FnOnce() -> ()>) {
|
||||
fn run(&self, _on_finish_launching: Box<dyn FnOnce()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -199,6 +200,7 @@ impl Window {
|
|||
close_handlers: Default::default(),
|
||||
should_close_handler: Default::default(),
|
||||
active_status_change_handlers: Default::default(),
|
||||
fullscreen_handlers: Default::default(),
|
||||
scale_factor: 1.0,
|
||||
current_scene: None,
|
||||
title: None,
|
||||
|
@ -253,6 +255,10 @@ impl super::Window for Window {
|
|||
self.active_status_change_handlers.push(callback);
|
||||
}
|
||||
|
||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
|
||||
self.fullscreen_handlers.push(callback)
|
||||
}
|
||||
|
||||
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
|
||||
self.resize_handlers.push(callback);
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ use crate::{
|
|||
text_layout::TextLayoutCache,
|
||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity,
|
||||
FontSystem, ModelHandle, MouseButtonEvent, MouseMovedEvent, MouseRegion, MouseRegionId,
|
||||
ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle,
|
||||
View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||
ParentId, ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle,
|
||||
UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||
};
|
||||
use collections::{HashMap, HashSet};
|
||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||
use serde_json::json;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut, Range},
|
||||
sync::Arc,
|
||||
|
@ -26,7 +26,6 @@ use std::{
|
|||
pub struct Presenter {
|
||||
window_id: usize,
|
||||
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
||||
parents: HashMap<usize, usize>,
|
||||
cursor_regions: Vec<CursorRegion>,
|
||||
mouse_regions: Vec<(MouseRegion, usize)>,
|
||||
font_cache: Arc<FontCache>,
|
||||
|
@ -52,7 +51,6 @@ impl Presenter {
|
|||
Self {
|
||||
window_id,
|
||||
rendered_views: cx.render_views(window_id, titlebar_height),
|
||||
parents: HashMap::new(),
|
||||
cursor_regions: Default::default(),
|
||||
mouse_regions: Default::default(),
|
||||
font_cache,
|
||||
|
@ -67,22 +65,22 @@ impl Presenter {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn dispatch_path(&self, app: &AppContext) -> Vec<usize> {
|
||||
let mut path = Vec::new();
|
||||
if let Some(view_id) = app.focused_view_id(self.window_id) {
|
||||
self.compute_dispatch_path_from(view_id, &mut path)
|
||||
}
|
||||
path
|
||||
}
|
||||
// pub fn dispatch_path(&self, app: &AppContext) -> Vec<usize> {
|
||||
// let mut path = Vec::new();
|
||||
// if let Some(view_id) = app.focused_view_id(self.window_id) {
|
||||
// self.compute_dispatch_path_from(view_id, &mut path)
|
||||
// }
|
||||
// path
|
||||
// }
|
||||
|
||||
pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec<usize>) {
|
||||
path.push(view_id);
|
||||
while let Some(parent_id) = self.parents.get(&view_id).copied() {
|
||||
path.push(parent_id);
|
||||
view_id = parent_id;
|
||||
}
|
||||
path.reverse();
|
||||
}
|
||||
// pub(crate) fn compute_dispatch_path_from(&self, mut view_id: usize, path: &mut Vec<usize>) {
|
||||
// path.push(view_id);
|
||||
// while let Some(parent_id) = self.parents.get(&view_id).copied() {
|
||||
// path.push(parent_id);
|
||||
// view_id = parent_id;
|
||||
// }
|
||||
// path.reverse();
|
||||
// }
|
||||
|
||||
pub fn invalidate(
|
||||
&mut self,
|
||||
|
@ -91,9 +89,8 @@ impl Presenter {
|
|||
) {
|
||||
cx.start_frame();
|
||||
for view_id in &invalidation.removed {
|
||||
invalidation.updated.remove(&view_id);
|
||||
self.rendered_views.remove(&view_id);
|
||||
self.parents.remove(&view_id);
|
||||
invalidation.updated.remove(view_id);
|
||||
self.rendered_views.remove(view_id);
|
||||
}
|
||||
for view_id in &invalidation.updated {
|
||||
self.rendered_views.insert(
|
||||
|
@ -191,7 +188,6 @@ impl Presenter {
|
|||
LayoutContext {
|
||||
window_id: self.window_id,
|
||||
rendered_views: &mut self.rendered_views,
|
||||
parents: &mut self.parents,
|
||||
font_cache: &self.font_cache,
|
||||
font_system: cx.platform().fonts(),
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
|
@ -289,7 +285,7 @@ impl Presenter {
|
|||
{
|
||||
dragged_region = Some((
|
||||
clicked_region.clone(),
|
||||
MouseRegionEvent::Drag(*prev_drag_position, e.clone()),
|
||||
MouseRegionEvent::Drag(*prev_drag_position, *e),
|
||||
));
|
||||
*prev_drag_position = *position;
|
||||
}
|
||||
|
@ -344,21 +340,11 @@ impl Presenter {
|
|||
}
|
||||
|
||||
invalidated_views.extend(event_cx.invalidated_views);
|
||||
let dispatch_directives = event_cx.dispatched_actions;
|
||||
|
||||
for view_id in invalidated_views {
|
||||
cx.notify_view(self.window_id, view_id);
|
||||
}
|
||||
|
||||
let mut dispatch_path = Vec::new();
|
||||
for directive in dispatch_directives {
|
||||
dispatch_path.clear();
|
||||
if let Some(view_id) = directive.dispatcher_view_id {
|
||||
self.compute_dispatch_path_from(view_id, &mut dispatch_path);
|
||||
}
|
||||
cx.dispatch_action_any(self.window_id, &dispatch_path, directive.action.as_ref());
|
||||
}
|
||||
|
||||
handled
|
||||
} else {
|
||||
false
|
||||
|
@ -372,9 +358,6 @@ impl Presenter {
|
|||
cx: &'a mut MutableAppContext,
|
||||
) -> (bool, EventContext<'a>) {
|
||||
let mut hover_regions = Vec::new();
|
||||
// let mut unhovered_regions = Vec::new();
|
||||
// let mut hovered_regions = Vec::new();
|
||||
|
||||
if let Event::MouseMoved(
|
||||
e @ MouseMovedEvent {
|
||||
position,
|
||||
|
@ -383,7 +366,7 @@ impl Presenter {
|
|||
},
|
||||
) = event
|
||||
{
|
||||
if let None = pressed_button {
|
||||
if pressed_button.is_none() {
|
||||
let mut style_to_assign = CursorStyle::Arrow;
|
||||
for region in self.cursor_regions.iter().rev() {
|
||||
if region.bounds.contains_point(*position) {
|
||||
|
@ -402,23 +385,17 @@ impl Presenter {
|
|||
if let Some(region_id) = region.id() {
|
||||
if !self.hovered_region_ids.contains(®ion_id) {
|
||||
invalidated_views.push(region.view_id);
|
||||
hover_regions.push((
|
||||
region.clone(),
|
||||
MouseRegionEvent::Hover(true, e.clone()),
|
||||
));
|
||||
hover_regions
|
||||
.push((region.clone(), MouseRegionEvent::Hover(true, *e)));
|
||||
self.hovered_region_ids.insert(region_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(region_id) = region.id() {
|
||||
if self.hovered_region_ids.contains(®ion_id) {
|
||||
invalidated_views.push(region.view_id);
|
||||
hover_regions.push((
|
||||
region.clone(),
|
||||
MouseRegionEvent::Hover(false, e.clone()),
|
||||
));
|
||||
self.hovered_region_ids.remove(®ion_id);
|
||||
}
|
||||
} else if let Some(region_id) = region.id() {
|
||||
if self.hovered_region_ids.contains(®ion_id) {
|
||||
invalidated_views.push(region.view_id);
|
||||
hover_regions
|
||||
.push((region.clone(), MouseRegionEvent::Hover(false, *e)));
|
||||
self.hovered_region_ids.remove(®ion_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +423,6 @@ impl Presenter {
|
|||
) -> EventContext<'a> {
|
||||
EventContext {
|
||||
rendered_views: &mut self.rendered_views,
|
||||
dispatched_actions: Default::default(),
|
||||
font_cache: &self.font_cache,
|
||||
text_layout_cache: &self.text_layout_cache,
|
||||
view_stack: Default::default(),
|
||||
|
@ -473,15 +449,9 @@ impl Presenter {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct DispatchDirective {
|
||||
pub dispatcher_view_id: Option<usize>,
|
||||
pub action: Box<dyn Action>,
|
||||
}
|
||||
|
||||
pub struct LayoutContext<'a> {
|
||||
window_id: usize,
|
||||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||
parents: &'a mut HashMap<usize, usize>,
|
||||
view_stack: Vec<usize>,
|
||||
pub font_cache: &'a Arc<FontCache>,
|
||||
pub font_system: Arc<dyn FontSystem>,
|
||||
|
@ -506,9 +476,43 @@ impl<'a> LayoutContext<'a> {
|
|||
}
|
||||
|
||||
fn layout(&mut self, view_id: usize, constraint: SizeConstraint) -> Vector2F {
|
||||
if let Some(parent_id) = self.view_stack.last() {
|
||||
self.parents.insert(view_id, *parent_id);
|
||||
let print_error = |view_id| {
|
||||
format!(
|
||||
"{} with id {}",
|
||||
self.app.name_for_view(self.window_id, view_id).unwrap(),
|
||||
view_id,
|
||||
)
|
||||
};
|
||||
match (
|
||||
self.view_stack.last(),
|
||||
self.app.parents.get(&(self.window_id, view_id)),
|
||||
) {
|
||||
(Some(layout_parent), Some(ParentId::View(app_parent))) => {
|
||||
if layout_parent != app_parent {
|
||||
panic!(
|
||||
"View {} was laid out with parent {} when it was constructed with parent {}",
|
||||
print_error(view_id),
|
||||
print_error(*layout_parent),
|
||||
print_error(*app_parent))
|
||||
}
|
||||
}
|
||||
(None, Some(ParentId::View(app_parent))) => panic!(
|
||||
"View {} was laid out without a parent when it was constructed with parent {}",
|
||||
print_error(view_id),
|
||||
print_error(*app_parent)
|
||||
),
|
||||
(Some(layout_parent), Some(ParentId::Root)) => panic!(
|
||||
"View {} was laid out with parent {} when it was constructed as a window root",
|
||||
print_error(view_id),
|
||||
print_error(*layout_parent),
|
||||
),
|
||||
(_, None) => panic!(
|
||||
"View {} did not have a registered parent in the app context",
|
||||
print_error(view_id),
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.view_stack.push(view_id);
|
||||
let mut rendered_view = self.rendered_views.remove(&view_id).unwrap();
|
||||
let size = rendered_view.layout(constraint, self);
|
||||
|
@ -615,7 +619,7 @@ impl<'a> PaintContext<'a> {
|
|||
#[inline]
|
||||
pub fn paint_layer<F>(&mut self, clip_bounds: Option<RectF>, f: F)
|
||||
where
|
||||
F: FnOnce(&mut Self) -> (),
|
||||
F: FnOnce(&mut Self),
|
||||
{
|
||||
self.scene.push_layer(clip_bounds);
|
||||
f(self);
|
||||
|
@ -637,7 +641,6 @@ impl<'a> Deref for PaintContext<'a> {
|
|||
|
||||
pub struct EventContext<'a> {
|
||||
rendered_views: &'a mut HashMap<usize, ElementBox>,
|
||||
dispatched_actions: Vec<DispatchDirective>,
|
||||
pub font_cache: &'a FontCache,
|
||||
pub text_layout_cache: &'a TextLayoutCache,
|
||||
pub app: &'a mut MutableAppContext,
|
||||
|
@ -692,10 +695,8 @@ impl<'a> EventContext<'a> {
|
|||
}
|
||||
|
||||
pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
|
||||
self.dispatched_actions.push(DispatchDirective {
|
||||
dispatcher_view_id: self.view_stack.last().copied(),
|
||||
action,
|
||||
});
|
||||
self.app
|
||||
.dispatch_any_action_at(self.window_id, *self.view_stack.last().unwrap(), action)
|
||||
}
|
||||
|
||||
pub fn dispatch_action<A: Action>(&mut self, action: A) {
|
||||
|
|
|
@ -107,6 +107,7 @@ pub struct MouseRegionId {
|
|||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct HandlerSet {
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub set: HashMap<
|
||||
(Discriminant<MouseRegionEvent>, Option<MouseButton>),
|
||||
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
|
||||
|
@ -115,6 +116,7 @@ pub struct HandlerSet {
|
|||
|
||||
impl HandlerSet {
|
||||
pub fn handle_all() -> Self {
|
||||
#[allow(clippy::type_complexity)]
|
||||
let mut set: HashMap<
|
||||
(Discriminant<MouseRegionEvent>, Option<MouseButton>),
|
||||
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
executor, platform, Entity, FontCache, Handle, LeakDetector, MutableAppContext, Platform,
|
||||
Subscription, TestAppContext,
|
||||
elements::Empty, executor, platform, Element, ElementBox, Entity, FontCache, Handle,
|
||||
LeakDetector, MutableAppContext, Platform, RenderContext, Subscription, TestAppContext, View,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use parking_lot::Mutex;
|
||||
|
@ -162,3 +162,19 @@ where
|
|||
|
||||
Observation { rx, _subscription }
|
||||
}
|
||||
|
||||
pub struct EmptyView;
|
||||
|
||||
impl Entity for EmptyView {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl View for EmptyView {
|
||||
fn ui_name() -> &'static str {
|
||||
"empty view"
|
||||
}
|
||||
|
||||
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
||||
Element::boxed(Empty::new())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ impl TextLayoutCache {
|
|||
let mut curr_frame = RwLockUpgradableReadGuard::upgrade(curr_frame);
|
||||
if let Some((key, layout)) = self.prev_frame.lock().remove_entry(key) {
|
||||
curr_frame.insert(key, layout.clone());
|
||||
Line::new(layout.clone(), runs)
|
||||
Line::new(layout, runs)
|
||||
} else {
|
||||
let layout = Arc::new(self.fonts.layout_line(text, font_size, runs));
|
||||
let key = CacheKeyValue {
|
||||
|
@ -81,7 +81,7 @@ impl TextLayoutCache {
|
|||
}
|
||||
|
||||
trait CacheKey {
|
||||
fn key<'a>(&'a self) -> CacheKeyRef<'a>;
|
||||
fn key(&self) -> CacheKeyRef;
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for (dyn CacheKey + 'a) {
|
||||
|
@ -98,7 +98,7 @@ impl<'a> Hash for (dyn CacheKey + 'a) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Eq)]
|
||||
struct CacheKeyValue {
|
||||
text: String,
|
||||
font_size: OrderedFloat<f32>,
|
||||
|
@ -106,15 +106,21 @@ struct CacheKeyValue {
|
|||
}
|
||||
|
||||
impl CacheKey for CacheKeyValue {
|
||||
fn key<'a>(&'a self) -> CacheKeyRef<'a> {
|
||||
fn key(&self) -> CacheKeyRef {
|
||||
CacheKeyRef {
|
||||
text: &self.text.as_str(),
|
||||
text: self.text.as_str(),
|
||||
font_size: self.font_size,
|
||||
runs: self.runs.as_slice(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CacheKeyValue {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.key().eq(&other.key())
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for CacheKeyValue {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.key().hash(state);
|
||||
|
@ -135,7 +141,7 @@ struct CacheKeyRef<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CacheKey for CacheKeyRef<'a> {
|
||||
fn key<'b>(&'b self) -> CacheKeyRef<'b> {
|
||||
fn key(&self) -> CacheKeyRef {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
@ -242,6 +248,10 @@ impl Line {
|
|||
self.layout.len
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.layout.len == 0
|
||||
}
|
||||
|
||||
pub fn index_for_x(&self, x: f32) -> Option<usize> {
|
||||
if x >= self.layout.width {
|
||||
None
|
||||
|
@ -300,7 +310,7 @@ impl Line {
|
|||
),
|
||||
Underline {
|
||||
color: Some(run_underline.color.unwrap_or(*run_color)),
|
||||
thickness: run_underline.thickness.into(),
|
||||
thickness: run_underline.thickness,
|
||||
squiggly: run_underline.squiggly,
|
||||
},
|
||||
));
|
||||
|
@ -484,7 +494,7 @@ impl LineWrapper {
|
|||
let mut prev_c = '\0';
|
||||
let mut char_indices = line.char_indices();
|
||||
iter::from_fn(move || {
|
||||
while let Some((ix, c)) = char_indices.next() {
|
||||
for (ix, c) in char_indices.by_ref() {
|
||||
if c == '\n' {
|
||||
continue;
|
||||
}
|
||||
|
@ -746,7 +756,7 @@ mod tests {
|
|||
let mut wrapper = LineWrapper::new(font_id, 16., font_system);
|
||||
assert_eq!(
|
||||
wrapper
|
||||
.wrap_shaped_line(&text, &line, 72.0)
|
||||
.wrap_shaped_line(text, &line, 72.0)
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
ShapedBoundary {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue