merge ui into main
commit
5d7a75de7f
2
Makefile
2
Makefile
|
@ -9,5 +9,5 @@ odin_highlighter:
|
||||||
odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
||||||
|
|
||||||
grep:
|
grep:
|
||||||
cargo b --manifest-path=plugins/grep/Cargo.toml
|
nightly-cargo b --manifest-path=plugins/grep/Cargo.toml
|
||||||
cp plugins/grep/target/debug/libgrep_plugin.dylib bin/
|
cp plugins/grep/target/debug/libgrep_plugin.dylib bin/
|
||||||
|
|
18
flake.lock
18
flake.lock
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1701680307,
|
"lastModified": 1705309234,
|
||||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -87,11 +87,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703013332,
|
"lastModified": 1705856552,
|
||||||
"narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
|
"narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
|
"rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -131,11 +131,11 @@
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704075545,
|
"lastModified": 1706235145,
|
||||||
"narHash": "sha256-L3zgOuVKhPjKsVLc3yTm2YJ6+BATyZBury7wnhyc8QU=",
|
"narHash": "sha256-3jh5nahTlcsX6QFcMPqxtLn9p9CgT9RSce5GLqjcpi4=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "a0df72e106322b67e9c6e591fe870380bd0da0d5",
|
"rev": "3a57c4e29cb2beb777b2e6ae7309a680585b8b2f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
14
flake.nix
14
flake.nix
|
@ -16,12 +16,19 @@
|
||||||
local-rust = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain).override {
|
local-rust = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain).override {
|
||||||
extensions = [ "rust-analysis" ];
|
extensions = [ "rust-analysis" ];
|
||||||
};
|
};
|
||||||
|
local-nightly-rust = (pkgs.rust-bin.fromRustupToolchainFile ./plugins/grep/rust-toolchain.toml).override {
|
||||||
|
extensions = [ "rust-analysis" ];
|
||||||
|
};
|
||||||
|
nightly-cargo = pkgs.writeShellScriptBin "nightly-cargo" ''
|
||||||
|
export RUSTC="${local-nightly-rust}/bin/rustc";
|
||||||
|
exec "${local-nightly-rust}/bin/cargo" "$@"
|
||||||
|
'';
|
||||||
fixed-odin = pkgs.odin.overrideAttrs (finalAttrs: prevAttr: rec {
|
fixed-odin = pkgs.odin.overrideAttrs (finalAttrs: prevAttr: rec {
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "pcleavelin";
|
owner = "pcleavelin";
|
||||||
repo = "Odin";
|
repo = "Odin";
|
||||||
rev = "59aa05170d54edff75aed220bb1653fc369573d7";
|
rev = "7b9ea9eca02bf5dd295439a46ed6103a0c4a44ff";
|
||||||
hash = "sha256-ZMcVugE0uRHba8jmQjTyQ9KKDUdIVSELggKDz9iSiwY=";
|
hash = "sha256-pxvU5veB1NEYPfer5roiLp/od2Pv4l1jJah0OHwb5yo=";
|
||||||
};
|
};
|
||||||
LLVM_CONFIG = "${pkgs.llvmPackages_17.llvm.dev}/bin/llvm-config";
|
LLVM_CONFIG = "${pkgs.llvmPackages_17.llvm.dev}/bin/llvm-config";
|
||||||
nativeBuildInputs = with pkgs; prevAttr.nativeBuildInputs ++ [ libcxx libcxxabi ];
|
nativeBuildInputs = with pkgs; prevAttr.nativeBuildInputs ++ [ libcxx libcxxabi ];
|
||||||
|
@ -58,7 +65,10 @@
|
||||||
buildInputs = with pkgs; (if pkgs.system == "aarch64-darwin" || pkgs.system == "x86_64-darwin" then [
|
buildInputs = with pkgs; (if pkgs.system == "aarch64-darwin" || pkgs.system == "x86_64-darwin" then [
|
||||||
fixed-odin
|
fixed-odin
|
||||||
local-rust
|
local-rust
|
||||||
|
nightly-cargo
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
|
SDL2
|
||||||
|
SDL2_ttf
|
||||||
darwin.apple_sdk.frameworks.CoreData
|
darwin.apple_sdk.frameworks.CoreData
|
||||||
darwin.apple_sdk.frameworks.Kernel
|
darwin.apple_sdk.frameworks.Kernel
|
||||||
darwin.apple_sdk.frameworks.CoreVideo
|
darwin.apple_sdk.frameworks.CoreVideo
|
||||||
|
|
|
@ -166,6 +166,145 @@ pub struct IteratorVTable {
|
||||||
pub until_end_of_word: *const c_void,
|
pub until_end_of_word: *const c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct UiInteraction {
|
||||||
|
pub hovering: bool,
|
||||||
|
pub clicked: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct InternalUiSemanticSize {
|
||||||
|
kind: isize,
|
||||||
|
value: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(isize)]
|
||||||
|
pub enum UiAxis {
|
||||||
|
Horizontal = 0,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum UiSemanticSize {
|
||||||
|
FitText,
|
||||||
|
Exact(isize),
|
||||||
|
ChildrenSum,
|
||||||
|
Fill,
|
||||||
|
PercentOfParent(isize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UiSemanticSize> for InternalUiSemanticSize {
|
||||||
|
fn from(value: UiSemanticSize) -> Self {
|
||||||
|
let (kind, value) = match value {
|
||||||
|
UiSemanticSize::FitText => (0, 0),
|
||||||
|
UiSemanticSize::Exact(value) => (1, value),
|
||||||
|
UiSemanticSize::ChildrenSum => (2, 0),
|
||||||
|
UiSemanticSize::Fill => (3, 0),
|
||||||
|
UiSemanticSize::PercentOfParent(value) => (4, value),
|
||||||
|
};
|
||||||
|
|
||||||
|
Self { kind, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct UiContext(*const c_void);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct UiBox(*const c_void);
|
||||||
|
|
||||||
|
type UiPushParentProc = extern "C" fn(ui_context: UiContext, ui_box: UiBox);
|
||||||
|
type UiPopParentProc = extern "C" fn(ui_context: UiContext);
|
||||||
|
type UiFloatingProc =
|
||||||
|
extern "C" fn(ui_context: UiContext, label: *const i8, pos: [isize; 2]) -> UiBox;
|
||||||
|
type UiRectProc = extern "C" fn(
|
||||||
|
ui_context: UiContext,
|
||||||
|
label: *const i8,
|
||||||
|
border: bool,
|
||||||
|
border: bool,
|
||||||
|
axis: UiAxis,
|
||||||
|
size: [InternalUiSemanticSize; 2],
|
||||||
|
) -> UiBox;
|
||||||
|
type UiSimpleProc = extern "C" fn(ui_context: UiContext, label: *const i8) -> UiInteraction;
|
||||||
|
type UiBufferProc = extern "C" fn(ui_context: UiContext, buffer: Buffer, show_line_numbers: bool);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct UiVTable {
|
||||||
|
ui_context: UiContext,
|
||||||
|
|
||||||
|
push_parent: UiPushParentProc,
|
||||||
|
pop_parent: UiPopParentProc,
|
||||||
|
|
||||||
|
spacer: UiSimpleProc,
|
||||||
|
floating: UiFloatingProc,
|
||||||
|
rect: UiRectProc,
|
||||||
|
|
||||||
|
button: UiSimpleProc,
|
||||||
|
label: UiSimpleProc,
|
||||||
|
|
||||||
|
buffer: UiBufferProc,
|
||||||
|
buffer_from_index: UiBufferProc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiVTable {
|
||||||
|
pub fn push_parent(&self, ui_box: UiBox) {
|
||||||
|
(self.push_parent)(self.ui_context, ui_box);
|
||||||
|
}
|
||||||
|
pub fn pop_parent(&self) {
|
||||||
|
(self.pop_parent)(self.ui_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spacer(&self, label: &CStr) -> UiInteraction {
|
||||||
|
(self.spacer)(self.ui_context, label.as_ptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_rect(
|
||||||
|
&self,
|
||||||
|
label: &CStr,
|
||||||
|
show_background: bool,
|
||||||
|
show_border: bool,
|
||||||
|
axis: UiAxis,
|
||||||
|
horizontal_size: UiSemanticSize,
|
||||||
|
vertical_size: UiSemanticSize,
|
||||||
|
inner: impl FnOnce(&UiVTable),
|
||||||
|
) {
|
||||||
|
let rect = (self.rect)(
|
||||||
|
self.ui_context,
|
||||||
|
label.as_ptr(),
|
||||||
|
show_background,
|
||||||
|
show_border,
|
||||||
|
axis,
|
||||||
|
[horizontal_size.into(), vertical_size.into()],
|
||||||
|
);
|
||||||
|
self.push_parent(rect);
|
||||||
|
|
||||||
|
inner(self);
|
||||||
|
|
||||||
|
self.pop_parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_floating(&self, label: &CStr, x: isize, y: isize, inner: impl FnOnce(&UiVTable)) {
|
||||||
|
let floating = (self.floating)(self.ui_context, label.as_ptr(), [x, y]);
|
||||||
|
self.push_parent(floating);
|
||||||
|
|
||||||
|
inner(self);
|
||||||
|
|
||||||
|
self.pop_parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn label(&self, label: &CStr) -> UiInteraction {
|
||||||
|
(self.label)(self.ui_context, label.as_ptr())
|
||||||
|
}
|
||||||
|
pub fn button(&self, label: &CStr) -> UiInteraction {
|
||||||
|
(self.button)(self.ui_context, label.as_ptr())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer(&self, buffer: Buffer, show_line_numbers: bool) {
|
||||||
|
(self.buffer)(self.ui_context, buffer, show_line_numbers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type OnColorBufferProc = extern "C" fn(plugin: Plugin, buffer: *const c_void);
|
type OnColorBufferProc = extern "C" fn(plugin: Plugin, buffer: *const c_void);
|
||||||
type OnHookProc = extern "C" fn(plugin: Plugin, buffer: Buffer);
|
type OnHookProc = extern "C" fn(plugin: Plugin, buffer: Buffer);
|
||||||
type InputGroupProc = extern "C" fn(plugin: Plugin, input_map: InputMap);
|
type InputGroupProc = extern "C" fn(plugin: Plugin, input_map: InputMap);
|
||||||
|
@ -176,8 +315,10 @@ type WindowGetBufferProc = extern "C" fn(plugin: Plugin, window: *const c_void)
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
state: *const c_void,
|
state: *const c_void,
|
||||||
|
|
||||||
pub iter_table: IteratorVTable,
|
pub iter_table: IteratorVTable,
|
||||||
pub buffer_table: BufferVTable,
|
pub buffer_table: BufferVTable,
|
||||||
|
pub ui_table: UiVTable,
|
||||||
|
|
||||||
pub register_hook: extern "C" fn(hook: Hook, on_hook: OnHookProc),
|
pub register_hook: extern "C" fn(hook: Hook, on_hook: OnHookProc),
|
||||||
pub register_highlighter:
|
pub register_highlighter:
|
||||||
|
@ -361,119 +502,246 @@ pub enum Hook {
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Key {
|
pub enum Key {
|
||||||
KeyNull = 0, // Key: NULL, used for no key pressed
|
UNKNOWN = 0,
|
||||||
// Alphanumeric keys
|
Enter = 13,
|
||||||
Apostrophe = 39, // key: '
|
ESCAPE = 27,
|
||||||
Comma = 44, // Key: ,
|
BACKSPACE = 8,
|
||||||
Minus = 45, // Key: -
|
TAB = 9,
|
||||||
Period = 46, // Key: .
|
Space = 32,
|
||||||
Slash = 47, // Key: /
|
EXCLAIM = 33,
|
||||||
Zero = 48, // Key: 0
|
QUOTEDBL = 34,
|
||||||
One = 49, // Key: 1
|
HASH = 35,
|
||||||
Two = 50, // Key: 2
|
PERCENT = 37,
|
||||||
Three = 51, // Key: 3
|
DOLLAR = 36,
|
||||||
Four = 52, // Key: 4
|
AMPERSAND = 38,
|
||||||
Five = 53, // Key: 5
|
QUOTE = 39,
|
||||||
Six = 54, // Key: 6
|
LEFTPAREN = 40,
|
||||||
Seven = 55, // Key: 7
|
RIGHTPAREN = 41,
|
||||||
Eight = 56, // Key: 8
|
ASTERISK = 42,
|
||||||
Nine = 57, // Key: 9
|
PLUS = 43,
|
||||||
Semicolon = 59, // Key: ;
|
COMMA = 44,
|
||||||
Equal = 61, // Key: =
|
MINUS = 45,
|
||||||
A = 65, // Key: A | a
|
PERIOD = 46,
|
||||||
B = 66, // Key: B | b
|
SLASH = 47,
|
||||||
C = 67, // Key: C | c
|
NUM0 = 48,
|
||||||
D = 68, // Key: D | d
|
NUM1 = 49,
|
||||||
E = 69, // Key: E | e
|
NUM2 = 50,
|
||||||
F = 70, // Key: F | f
|
NUM3 = 51,
|
||||||
G = 71, // Key: G | g
|
NUM4 = 52,
|
||||||
H = 72, // Key: H | h
|
NUM5 = 53,
|
||||||
I = 73, // Key: I | i
|
NUM6 = 54,
|
||||||
J = 74, // Key: J | j
|
NUM7 = 55,
|
||||||
K = 75, // Key: K | k
|
NUM8 = 56,
|
||||||
L = 76, // Key: L | l
|
NUM9 = 57,
|
||||||
M = 77, // Key: M | m
|
COLON = 58,
|
||||||
N = 78, // Key: N | n
|
SEMICOLON = 59,
|
||||||
O = 79, // Key: O | o
|
LESS = 60,
|
||||||
P = 80, // Key: P | p
|
EQUAL = 61,
|
||||||
Q = 81, // Key: Q | q
|
GREATER = 62,
|
||||||
R = 82, // Key: R | r
|
QUESTION = 63,
|
||||||
S = 83, // Key: S | s
|
AT = 64,
|
||||||
T = 84, // Key: T | t
|
LEFTBRACKET = 91,
|
||||||
U = 85, // Key: U | u
|
BACKSLASH = 92,
|
||||||
V = 86, // Key: V | v
|
RIGHTBRACKET = 93,
|
||||||
W = 87, // Key: W | w
|
CARET = 94,
|
||||||
X = 88, // Key: X | x
|
UNDERSCORE = 95,
|
||||||
Y = 89, // Key: Y | y
|
BACKQUOTE = 96,
|
||||||
Z = 90, // Key: Z | z
|
A = 97,
|
||||||
LeftBracket = 91, // Key: [
|
B = 98,
|
||||||
Backslash = 92, // Key: '\'
|
C = 99,
|
||||||
RightBracket = 93, // Key: ]
|
D = 100,
|
||||||
Grave = 96, // Key: `
|
E = 101,
|
||||||
// Function keys
|
F = 102,
|
||||||
Space = 32, // Key: Space
|
G = 103,
|
||||||
Escape = 256, // Key: Esc
|
H = 104,
|
||||||
Enter = 257, // Key: Enter
|
I = 105,
|
||||||
Tab = 258, // Key: Tab
|
J = 106,
|
||||||
Backspace = 259, // Key: Backspace
|
K = 107,
|
||||||
Insert = 260, // Key: Ins
|
L = 108,
|
||||||
Delete = 261, // Key: Del
|
M = 109,
|
||||||
Right = 262, // Key: Cursor right
|
N = 110,
|
||||||
Left = 263, // Key: Cursor left
|
O = 111,
|
||||||
Down = 264, // Key: Cursor down
|
P = 112,
|
||||||
Up = 265, // Key: Cursor up
|
Q = 113,
|
||||||
PageUp = 266, // Key: Page up
|
R = 114,
|
||||||
PageDown = 267, // Key: Page down
|
S = 115,
|
||||||
Home = 268, // Key: Home
|
T = 116,
|
||||||
End = 269, // Key: End
|
U = 117,
|
||||||
CapsLock = 280, // Key: Caps lock
|
V = 118,
|
||||||
ScrollLock = 281, // Key: Scroll down
|
W = 119,
|
||||||
NumLock = 282, // Key: Num lock
|
X = 120,
|
||||||
PrintScreen = 283, // Key: Print screen
|
Y = 121,
|
||||||
Pause = 284, // Key: Pause
|
Z = 122,
|
||||||
F1 = 290, // Key: F1
|
CAPSLOCK = 1073741881,
|
||||||
F2 = 291, // Key: F2
|
F1 = 1073741882,
|
||||||
F3 = 292, // Key: F3
|
F2 = 1073741883,
|
||||||
F4 = 293, // Key: F4
|
F3 = 1073741884,
|
||||||
F5 = 294, // Key: F5
|
F4 = 1073741885,
|
||||||
F6 = 295, // Key: F6
|
F5 = 1073741886,
|
||||||
F7 = 296, // Key: F7
|
F6 = 1073741887,
|
||||||
F8 = 297, // Key: F8
|
F7 = 1073741888,
|
||||||
F9 = 298, // Key: F9
|
F8 = 1073741889,
|
||||||
F10 = 299, // Key: F10
|
F9 = 1073741890,
|
||||||
F11 = 300, // Key: F11
|
F10 = 1073741891,
|
||||||
F12 = 301, // Key: F12
|
F11 = 1073741892,
|
||||||
LeftShift = 340, // Key: Shift left
|
F12 = 1073741893,
|
||||||
LeftControl = 341, // Key: Control left
|
PRINTSCREEN = 1073741894,
|
||||||
LeftAlt = 342, // Key: Alt left
|
SCROLLLOCK = 1073741895,
|
||||||
LeftSuper = 343, // Key: Super left
|
PAUSE = 1073741896,
|
||||||
RightShift = 344, // Key: Shift right
|
INSERT = 1073741897,
|
||||||
RightControl = 345, // Key: Control right
|
HOME = 1073741898,
|
||||||
RightAlt = 346, // Key: Alt right
|
PAGEUP = 1073741899,
|
||||||
RightSuper = 347, // Key: Super right
|
DELETE = 127,
|
||||||
KbMenu = 348, // Key: KB menu
|
END = 1073741901,
|
||||||
// Keypad keys
|
PAGEDOWN = 1073741902,
|
||||||
Kp0 = 320, // Key: Keypad 0
|
RIGHT = 1073741903,
|
||||||
Kp1 = 321, // Key: Keypad 1
|
LEFT = 1073741904,
|
||||||
Kp2 = 322, // Key: Keypad 2
|
DOWN = 1073741905,
|
||||||
Kp3 = 323, // Key: Keypad 3
|
UP = 1073741906,
|
||||||
Kp4 = 324, // Key: Keypad 4
|
NUMLOCKCLEAR = 1073741907,
|
||||||
Kp5 = 325, // Key: Keypad 5
|
KpDivide = 1073741908,
|
||||||
Kp6 = 326, // Key: Keypad 6
|
KpMultiply = 1073741909,
|
||||||
Kp7 = 327, // Key: Keypad 7
|
KpMinus = 1073741910,
|
||||||
Kp8 = 328, // Key: Keypad 8
|
KpPlus = 1073741911,
|
||||||
Kp9 = 329, // Key: Keypad 9
|
KpEnter = 1073741912,
|
||||||
KpDecimal = 330, // Key: Keypad .
|
Kp1 = 1073741913,
|
||||||
KpDivide = 331, // Key: Keypad /
|
Kp2 = 1073741914,
|
||||||
KpMultiply = 332, // Key: Keypad *
|
Kp3 = 1073741915,
|
||||||
KpSubtract = 333, // Key: Keypad -
|
Kp4 = 1073741916,
|
||||||
KpAdd = 334, // Key: Keypad +
|
Kp5 = 1073741917,
|
||||||
KpEnter = 335, // Key: Keypad Enter
|
Kp6 = 1073741918,
|
||||||
KpEqual = 336, // Key: Keypad =
|
Kp7 = 1073741919,
|
||||||
// Android key buttons
|
Kp8 = 1073741920,
|
||||||
Back = 4, // Key: Android back button
|
Kp9 = 1073741921,
|
||||||
VolumeUp = 24, // Key: Android volume up button
|
Kp0 = 1073741922,
|
||||||
VolumeDown = 25, // Key: Android volume down button
|
KpPeriod = 1073741923,
|
||||||
|
APPLICATION = 1073741925,
|
||||||
|
POWER = 1073741926,
|
||||||
|
KpEquals = 1073741927,
|
||||||
|
F13 = 1073741928,
|
||||||
|
F14 = 1073741929,
|
||||||
|
F15 = 1073741930,
|
||||||
|
F16 = 1073741931,
|
||||||
|
F17 = 1073741932,
|
||||||
|
F18 = 1073741933,
|
||||||
|
F19 = 1073741934,
|
||||||
|
F20 = 1073741935,
|
||||||
|
F21 = 1073741936,
|
||||||
|
F22 = 1073741937,
|
||||||
|
F23 = 1073741938,
|
||||||
|
F24 = 1073741939,
|
||||||
|
EXECUTE = 1073741940,
|
||||||
|
HELP = 1073741941,
|
||||||
|
MENU = 1073741942,
|
||||||
|
SELECT = 1073741943,
|
||||||
|
STOP = 1073741944,
|
||||||
|
AGAIN = 1073741945,
|
||||||
|
UNDO = 1073741946,
|
||||||
|
CUT = 1073741947,
|
||||||
|
COPY = 1073741948,
|
||||||
|
PASTE = 1073741949,
|
||||||
|
FIND = 1073741950,
|
||||||
|
MUTE = 1073741951,
|
||||||
|
VOLUMEUP = 1073741952,
|
||||||
|
VOLUMEDOWN = 1073741953,
|
||||||
|
KpComma = 1073741957,
|
||||||
|
KpEqualsas400 = 1073741958,
|
||||||
|
ALTERASE = 1073741977,
|
||||||
|
SYSREQ = 1073741978,
|
||||||
|
CANCEL = 1073741979,
|
||||||
|
CLEAR = 1073741980,
|
||||||
|
PRIOR = 1073741981,
|
||||||
|
RETURN2 = 1073741982,
|
||||||
|
SEPARATOR = 1073741983,
|
||||||
|
OUT = 1073741984,
|
||||||
|
OPER = 1073741985,
|
||||||
|
CLEARAGAIN = 1073741986,
|
||||||
|
CRSEL = 1073741987,
|
||||||
|
EXSEL = 1073741988,
|
||||||
|
Kp00 = 1073742000,
|
||||||
|
Kp000 = 1073742001,
|
||||||
|
THOUSANDSSEPARATOR = 1073742002,
|
||||||
|
DECIMALSEPARATOR = 1073742003,
|
||||||
|
CURRENCYUNIT = 1073742004,
|
||||||
|
CURRENCYSUBUNIT = 1073742005,
|
||||||
|
KpLeftparen = 1073742006,
|
||||||
|
KpRightparen = 1073742007,
|
||||||
|
KpLeftbrace = 1073742008,
|
||||||
|
KpRightbrace = 1073742009,
|
||||||
|
KpTab = 1073742010,
|
||||||
|
KpBackspace = 1073742011,
|
||||||
|
KpA = 1073742012,
|
||||||
|
KpB = 1073742013,
|
||||||
|
KpC = 1073742014,
|
||||||
|
KpD = 1073742015,
|
||||||
|
KpE = 1073742016,
|
||||||
|
KpF = 1073742017,
|
||||||
|
KpXor = 1073742018,
|
||||||
|
KpPower = 1073742019,
|
||||||
|
KpPercent = 1073742020,
|
||||||
|
KpLess = 1073742021,
|
||||||
|
KpGreater = 1073742022,
|
||||||
|
KpAmpersand = 1073742023,
|
||||||
|
KpDblampersand = 1073742024,
|
||||||
|
KpVerticalbar = 1073742025,
|
||||||
|
KpDblverticalbar = 1073742026,
|
||||||
|
KpColon = 1073742027,
|
||||||
|
KpHash = 1073742028,
|
||||||
|
KpSpace = 1073742029,
|
||||||
|
KpAt = 1073742030,
|
||||||
|
KpExclam = 1073742031,
|
||||||
|
KpMemstore = 1073742032,
|
||||||
|
KpMemrecall = 1073742033,
|
||||||
|
KpMemclear = 1073742034,
|
||||||
|
KpMemadd = 1073742035,
|
||||||
|
KpMemsubtract = 1073742036,
|
||||||
|
KpMemmultiply = 1073742037,
|
||||||
|
KpMemdivide = 1073742038,
|
||||||
|
KpPlusminus = 1073742039,
|
||||||
|
KpClear = 1073742040,
|
||||||
|
KpClearentry = 1073742041,
|
||||||
|
KpBinary = 1073742042,
|
||||||
|
KpOctal = 1073742043,
|
||||||
|
KpDecimal = 1073742044,
|
||||||
|
KpHexadecimal = 1073742045,
|
||||||
|
LCTRL = 1073742048,
|
||||||
|
LSHIFT = 1073742049,
|
||||||
|
LALT = 1073742050,
|
||||||
|
LGUI = 1073742051,
|
||||||
|
RCTRL = 1073742052,
|
||||||
|
RSHIFT = 1073742053,
|
||||||
|
RALT = 1073742054,
|
||||||
|
RGUI = 1073742055,
|
||||||
|
MODE = 1073742081,
|
||||||
|
AUDIONEXT = 1073742082,
|
||||||
|
AUDIOPREV = 1073742083,
|
||||||
|
AUDIOSTOP = 1073742084,
|
||||||
|
AUDIOPLAY = 1073742085,
|
||||||
|
AUDIOMUTE = 1073742086,
|
||||||
|
MEDIASELECT = 1073742087,
|
||||||
|
WWW = 1073742088,
|
||||||
|
MAIL = 1073742089,
|
||||||
|
CALCULATOR = 1073742090,
|
||||||
|
COMPUTER = 1073742091,
|
||||||
|
AcSearch = 1073742092,
|
||||||
|
AcHome = 1073742093,
|
||||||
|
AcBack = 1073742094,
|
||||||
|
AcForward = 1073742095,
|
||||||
|
AcStop = 1073742096,
|
||||||
|
AcRefresh = 1073742097,
|
||||||
|
AcBookmarks = 1073742098,
|
||||||
|
BRIGHTNESSDOWN = 1073742099,
|
||||||
|
BRIGHTNESSUP = 1073742100,
|
||||||
|
DISPLAYSWITCH = 1073742101,
|
||||||
|
KBDILLUMTOGGLE = 1073742102,
|
||||||
|
KBDILLUMDOWN = 1073742103,
|
||||||
|
KBDILLUMUP = 1073742104,
|
||||||
|
EJECT = 1073742105,
|
||||||
|
SLEEP = 1073742106,
|
||||||
|
APP1 = 1073742107,
|
||||||
|
APP2 = 1073742108,
|
||||||
|
AUDIOREWIND = 1073742109,
|
||||||
|
AUDIOFASTFORWARD = 1073742110,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
|
|
|
@ -4,7 +4,6 @@ package buffer_search;
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:path/filepath"
|
import "core:path/filepath"
|
||||||
import "vendor:raylib"
|
|
||||||
|
|
||||||
import p "../../src/plugin"
|
import p "../../src/plugin"
|
||||||
import "../../src/theme"
|
import "../../src/theme"
|
||||||
|
@ -99,34 +98,91 @@ buffer_list_iter :: proc(plugin: Plugin, buffer_index: ^int) -> (int, int, bool)
|
||||||
|
|
||||||
draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
||||||
context = runtime.default_context();
|
context = runtime.default_context();
|
||||||
|
runtime.free_all(context.temp_allocator);
|
||||||
|
|
||||||
win := cast(^BufferListWindow)win;
|
win := cast(^BufferListWindow)win;
|
||||||
if win == nil {
|
if win == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screen_width := plugin.get_screen_width();
|
||||||
|
screen_height := plugin.get_screen_height();
|
||||||
|
directory := string(plugin.get_current_directory());
|
||||||
|
|
||||||
|
canvas := plugin.ui.floating(plugin.ui.ui_context, "buffer search canvas", {0,0});
|
||||||
|
|
||||||
|
plugin.ui.push_parent(plugin.ui.ui_context, canvas);
|
||||||
|
{
|
||||||
|
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
||||||
|
|
||||||
|
plugin.ui.spacer(plugin.ui.ui_context, "left spacer");
|
||||||
|
centered_container := plugin.ui.rect(plugin.ui.ui_context, "centered container", false, false, .Vertical, {{4, 75}, {3, 0}});
|
||||||
|
plugin.ui.push_parent(plugin.ui.ui_context, centered_container);
|
||||||
|
{
|
||||||
|
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
||||||
|
|
||||||
|
plugin.ui.spacer(plugin.ui.ui_context, "top spacer");
|
||||||
|
ui_window := plugin.ui.rect(plugin.ui.ui_context, "buffer search window", true, true, .Horizontal, {{3, 0}, {4, 75}});
|
||||||
|
plugin.ui.push_parent(plugin.ui.ui_context, ui_window);
|
||||||
|
{
|
||||||
|
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
||||||
|
|
||||||
|
buffer_list_view := plugin.ui.rect(plugin.ui.ui_context, "buffer list view", false, false, .Vertical, {{4, 60}, {3, 0}});
|
||||||
|
plugin.ui.push_parent(plugin.ui.ui_context, buffer_list_view);
|
||||||
|
{
|
||||||
|
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
||||||
|
|
||||||
|
_buffer_index := 0;
|
||||||
|
for index in buffer_list_iter(plugin, &_buffer_index) {
|
||||||
|
buffer := plugin.buffer.get_buffer_info_from_index(index);
|
||||||
|
relative_file_path, _ := filepath.rel(directory, string(buffer.file_path), context.temp_allocator)
|
||||||
|
text := fmt.ctprintf("%s:%d", relative_file_path, buffer.cursor.line+1);
|
||||||
|
|
||||||
|
if index == win.selected_index {
|
||||||
|
plugin.ui.button(plugin.ui.ui_context, text);
|
||||||
|
} else {
|
||||||
|
plugin.ui.label(plugin.ui.ui_context, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_preview := plugin.ui.rect(plugin.ui.ui_context, "buffer preview", true, false, .Horizontal, {{3, 0}, {3, 0}});
|
||||||
|
plugin.ui.push_parent(plugin.ui.ui_context, buffer_preview);
|
||||||
|
{
|
||||||
|
defer plugin.ui.pop_parent(plugin.ui.ui_context);
|
||||||
|
|
||||||
|
plugin.ui.buffer_from_index(plugin.ui.ui_context, win.selected_index, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.ui.spacer(plugin.ui.ui_context, "bottom spacer");
|
||||||
|
}
|
||||||
|
plugin.ui.spacer(plugin.ui.ui_context, "right spacer");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
screen_width := plugin.get_screen_width();
|
screen_width := plugin.get_screen_width();
|
||||||
screen_height := plugin.get_screen_height();
|
screen_height := plugin.get_screen_height();
|
||||||
source_font_width := plugin.get_font_width();
|
source_font_width := plugin.get_font_width();
|
||||||
source_font_height := plugin.get_font_height();
|
source_font_height := plugin.get_font_height();
|
||||||
|
|
||||||
win_rec := raylib.Rectangle {
|
win_rec := [4]f32 {
|
||||||
x = f32(screen_width/8),
|
f32(screen_width/8),
|
||||||
y = f32(screen_height/8),
|
f32(screen_height/8),
|
||||||
width = f32(screen_width - screen_width/4),
|
f32(screen_width - screen_width/4),
|
||||||
height = f32(screen_height - screen_height/4),
|
f32(screen_height - screen_height/4),
|
||||||
};
|
};
|
||||||
plugin.draw_rect(
|
plugin.draw_rect(
|
||||||
i32(win_rec.x),
|
i32(win_rec.x),
|
||||||
i32(win_rec.y),
|
i32(win_rec.y),
|
||||||
i32(win_rec.width),
|
i32(win_rec.z),
|
||||||
i32(win_rec.height),
|
i32(win_rec.w),
|
||||||
.Background4
|
.Background4
|
||||||
);
|
);
|
||||||
|
|
||||||
win_margin := raylib.Vector2 { f32(source_font_width), f32(source_font_height) };
|
win_margin := [2]f32 { f32(source_font_width), f32(source_font_height) };
|
||||||
|
|
||||||
buffer_prev_width := (win_rec.width - win_margin.x*2) / 2;
|
buffer_prev_width := (win_rec.z - win_margin.x*2) / 2;
|
||||||
buffer_prev_height := win_rec.height - win_margin.y*2;
|
buffer_prev_height := win_rec.w - win_margin.y*2;
|
||||||
|
|
||||||
glyph_buffer_width := int(buffer_prev_width) / source_font_width - 1;
|
glyph_buffer_width := int(buffer_prev_width) / source_font_width - 1;
|
||||||
glyph_buffer_height := int(buffer_prev_height) / source_font_height;
|
glyph_buffer_height := int(buffer_prev_height) / source_font_height;
|
||||||
|
@ -134,7 +190,7 @@ draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
||||||
directory := string(plugin.get_current_directory());
|
directory := string(plugin.get_current_directory());
|
||||||
|
|
||||||
plugin.draw_rect(
|
plugin.draw_rect(
|
||||||
i32(win_rec.x + win_rec.width / 2),
|
i32(win_rec.x + win_rec.z / 2),
|
||||||
i32(win_rec.y + win_margin.y),
|
i32(win_rec.y + win_margin.y),
|
||||||
i32(buffer_prev_width),
|
i32(buffer_prev_width),
|
||||||
i32(buffer_prev_height),
|
i32(buffer_prev_height),
|
||||||
|
@ -151,7 +207,7 @@ draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
||||||
if index == win.selected_index {
|
if index == win.selected_index {
|
||||||
plugin.draw_buffer_from_index(
|
plugin.draw_buffer_from_index(
|
||||||
index,
|
index,
|
||||||
int(win_rec.x + win_margin.x + win_rec.width / 2),
|
int(win_rec.x + win_margin.x + win_rec.z / 2),
|
||||||
int(win_rec.y + win_margin.y),
|
int(win_rec.y + win_margin.y),
|
||||||
glyph_buffer_width,
|
glyph_buffer_width,
|
||||||
glyph_buffer_height,
|
glyph_buffer_height,
|
||||||
|
@ -174,4 +230,5 @@ draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
|
||||||
|
|
||||||
runtime.free_all(context.temp_allocator);
|
runtime.free_all(context.temp_allocator);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly-2024-01-24"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
ffi::OsString,
|
ffi::{CString, OsString},
|
||||||
path::Path,
|
path::Path,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::mpsc::{Receiver, Sender},
|
sync::mpsc::{Receiver, Sender},
|
||||||
|
@ -8,10 +8,10 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use grep::{
|
use grep::{
|
||||||
regex::{RegexMatcherBuilder},
|
regex::RegexMatcherBuilder,
|
||||||
searcher::{BinaryDetection, SearcherBuilder, Sink, SinkError},
|
searcher::{BinaryDetection, SearcherBuilder, Sink, SinkError},
|
||||||
};
|
};
|
||||||
use plugin_rs_bindings::{Buffer, Closure, Hook, InputMap, Key, PaletteColor, Plugin};
|
use plugin_rs_bindings::{Buffer, Closure, Hook, InputMap, Key, Plugin, UiAxis, UiSemanticSize};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
@ -213,6 +213,7 @@ pub extern "C" fn OnInitialize(plugin: Plugin) {
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if match_count > 0 {
|
||||||
let index_threshold = std::cmp::max(max_mats_to_draw-4, 0) as usize;
|
let index_threshold = std::cmp::max(max_mats_to_draw-4, 0) as usize;
|
||||||
|
|
||||||
if window.selected_match < match_count-1 {
|
if window.selected_match < match_count-1 {
|
||||||
|
@ -226,6 +227,7 @@ pub extern "C" fn OnInitialize(plugin: Plugin) {
|
||||||
window.top_index = 0;
|
window.top_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}), "move selection down\0".as_ptr());
|
}), "move selection down\0".as_ptr());
|
||||||
}), draw_window, free_window, Some(Closure!((_plugin: Plugin, window: *const std::ffi::c_void) -> Buffer => {
|
}), draw_window, free_window, Some(Closure!((_plugin: Plugin, window: *const std::ffi::c_void) -> Buffer => {
|
||||||
let window = Box::leak(unsafe { Box::<GrepWindow>::from_raw(window as *mut GrepWindow) });
|
let window = Box::leak(unsafe { Box::<GrepWindow>::from_raw(window as *mut GrepWindow) });
|
||||||
|
@ -271,62 +273,58 @@ extern "C" fn draw_window(plugin: Plugin, window: *const std::ffi::c_void) {
|
||||||
|
|
||||||
let screen_width = (plugin.get_screen_width)() as i32;
|
let screen_width = (plugin.get_screen_width)() as i32;
|
||||||
let screen_height = (plugin.get_screen_height)() as i32;
|
let screen_height = (plugin.get_screen_height)() as i32;
|
||||||
let font_width = (plugin.get_font_width)() as i32;
|
|
||||||
let font_height = (plugin.get_font_height)() as i32;
|
let font_height = (plugin.get_font_height)() as i32;
|
||||||
|
|
||||||
let x = screen_width / 8;
|
|
||||||
let y = screen_height / 8;
|
|
||||||
let width = screen_width - screen_width / 4;
|
|
||||||
let height = screen_height - screen_height / 4;
|
let height = screen_height - screen_height / 4;
|
||||||
|
|
||||||
let buffer_prev_width = (width - font_width * 2) / 2;
|
|
||||||
|
|
||||||
let glyph_buffer_width = buffer_prev_width / font_width - 1;
|
|
||||||
let glyph_buffer_height = 1;
|
|
||||||
|
|
||||||
let dir = plugin.get_current_directory();
|
let dir = plugin.get_current_directory();
|
||||||
let directory = Path::new(dir.as_ref());
|
let directory = Path::new(dir.as_ref());
|
||||||
|
|
||||||
(plugin.draw_rect)(x, y, width, height, PaletteColor::Background4);
|
plugin
|
||||||
(plugin.draw_rect)(
|
.ui_table
|
||||||
x + font_width,
|
.push_floating(c"grep canvas", 0, 0, |ui_table| {
|
||||||
y + font_height,
|
// TODO: make some primitive that centers a Box
|
||||||
width - font_width * 2,
|
ui_table.spacer(c"left spacer");
|
||||||
height - font_height * 3,
|
|
||||||
PaletteColor::Background3,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(buffer) = window.input_buffer {
|
ui_table.push_rect(
|
||||||
(plugin.draw_rect)(
|
c"centered container",
|
||||||
x + font_width,
|
|
||||||
y + height - font_height * 2,
|
|
||||||
buffer_prev_width,
|
|
||||||
font_height,
|
|
||||||
PaletteColor::Background2,
|
|
||||||
);
|
|
||||||
(plugin.draw_buffer)(
|
|
||||||
buffer,
|
|
||||||
(x + font_width) as isize,
|
|
||||||
(y + height - font_height * 2) as isize,
|
|
||||||
(glyph_buffer_width) as isize,
|
|
||||||
(glyph_buffer_height) as isize,
|
|
||||||
false,
|
false,
|
||||||
);
|
false,
|
||||||
}
|
UiAxis::Vertical,
|
||||||
|
UiSemanticSize::PercentOfParent(75),
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
|ui_table| {
|
||||||
|
ui_table.spacer(c"top spacer");
|
||||||
|
ui_table.push_rect(
|
||||||
|
c"grep window",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
UiAxis::Vertical,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
UiSemanticSize::PercentOfParent(75),
|
||||||
|
|ui_table| {
|
||||||
if let Ok(sink) = window.rx.try_recv() {
|
if let Ok(sink) = window.rx.try_recv() {
|
||||||
window.sink = Some(sink);
|
window.sink = Some(sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sink) = &window.sink {
|
ui_table.push_rect(
|
||||||
if !sink.matches.is_empty() {
|
c"results list",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
UiAxis::Vertical,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
|ui_table| match &window.sink {
|
||||||
|
Some(sink) if !sink.matches.is_empty() => {
|
||||||
let num_mats_to_draw = std::cmp::min(
|
let num_mats_to_draw = std::cmp::min(
|
||||||
(sink.matches.len() - window.top_index) as i32,
|
(sink.matches.len() - window.top_index) as i32,
|
||||||
(height - font_height * 2) / (font_height) - 1,
|
(height - font_height) / (font_height),
|
||||||
);
|
);
|
||||||
let max_mat_length = (width - font_width * 2) / font_width;
|
|
||||||
|
|
||||||
for (i, mat) in sink.matches[window.top_index..].iter().enumerate() {
|
for (i, mat) in
|
||||||
|
sink.matches[window.top_index..].iter().enumerate()
|
||||||
|
{
|
||||||
let index = i + window.top_index;
|
let index = i + window.top_index;
|
||||||
if i as i32 >= num_mats_to_draw {
|
if i as i32 >= num_mats_to_draw {
|
||||||
break;
|
break;
|
||||||
|
@ -343,37 +341,70 @@ extern "C" fn draw_window(plugin: Plugin, window: *const std::ffi::c_void) {
|
||||||
let text = match mat.line_number {
|
let text = match mat.line_number {
|
||||||
Some(line_number) => format!(
|
Some(line_number) => format!(
|
||||||
"{}:{}:{}: {}",
|
"{}:{}:{}: {}",
|
||||||
relative_file_path, line_number, mat.column, matched_text
|
relative_file_path,
|
||||||
|
line_number,
|
||||||
|
mat.column,
|
||||||
|
matched_text
|
||||||
|
),
|
||||||
|
None => format!(
|
||||||
|
"{}:{}: {}",
|
||||||
|
relative_file_path, mat.column, matched_text
|
||||||
),
|
),
|
||||||
None => format!("{}:{}: {}", relative_file_path, mat.column, matched_text),
|
|
||||||
};
|
};
|
||||||
let text = if text.len() > max_mat_length as usize {
|
|
||||||
text.as_str().split_at(max_mat_length as usize).0
|
|
||||||
} else {
|
|
||||||
&text
|
|
||||||
};
|
|
||||||
|
|
||||||
let text = format!("{text}\0");
|
|
||||||
|
|
||||||
if index == window.selected_match {
|
if index == window.selected_match {
|
||||||
(plugin.draw_rect)(
|
// TODO: don't use button here, but apply a style
|
||||||
x + font_width,
|
// to `label`
|
||||||
y + font_height + ((index - window.top_index) as i32) * font_height,
|
ui_table.button(
|
||||||
(text.chars().count() as i32) * font_width,
|
&CString::new(text).expect("valid text"),
|
||||||
font_height,
|
);
|
||||||
PaletteColor::Background2,
|
} else {
|
||||||
|
ui_table.label(
|
||||||
|
&CString::new(text).expect("valid text"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) | None => {
|
||||||
|
ui_table.spacer(c"top spacer");
|
||||||
|
ui_table.push_rect(
|
||||||
|
c"centered text container",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
UiAxis::Horizontal,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
|ui_table| {
|
||||||
|
ui_table.spacer(c"left spacer");
|
||||||
|
ui_table.label(c"no results");
|
||||||
|
ui_table.spacer(c"right spacer");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ui_table.spacer(c"bottom spacer");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
(plugin.draw_text)(
|
ui_table.push_rect(
|
||||||
text.as_ptr() as *const i8,
|
c"grep window",
|
||||||
(x + font_width) as f32,
|
true,
|
||||||
(y + font_height + ((index - window.top_index) as i32) * font_height) as f32,
|
false,
|
||||||
PaletteColor::Foreground2,
|
UiAxis::Vertical,
|
||||||
|
UiSemanticSize::Fill,
|
||||||
|
UiSemanticSize::Exact(font_height as isize),
|
||||||
|
|ui_table| {
|
||||||
|
if let Some(buffer) = window.input_buffer {
|
||||||
|
ui_table.buffer(buffer, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
);
|
||||||
}
|
ui_table.spacer(c"bottom spacer");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ui_table.spacer(c"right spacer");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn on_buffer_input(plugin: Plugin, buffer: Buffer) {
|
extern "C" fn on_buffer_input(plugin: Plugin, buffer: Buffer) {
|
||||||
|
|
|
@ -277,6 +277,9 @@ is_rust_keyword :: proc(plugin: Plugin, start: BufferIter, end: BufferIter) -> (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: split logic into single line coloring, and multi-line coloring.
|
||||||
|
// single line coloring can be done directly on the glyph buffer
|
||||||
|
// (with some edge cases, literally, the edge of the screen)
|
||||||
color_buffer_odin :: proc "c" (plugin: Plugin, buffer: rawptr) {
|
color_buffer_odin :: proc "c" (plugin: Plugin, buffer: rawptr) {
|
||||||
context = runtime.default_context();
|
context = runtime.default_context();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package core
|
||||||
|
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "vendor:raylib"
|
import "vendor:sdl2"
|
||||||
|
|
||||||
import "../plugin"
|
import "../plugin"
|
||||||
|
|
||||||
|
@ -42,12 +42,15 @@ close_window_and_free :: proc(state: ^State) {
|
||||||
|
|
||||||
State :: struct {
|
State :: struct {
|
||||||
ctx: runtime.Context,
|
ctx: runtime.Context,
|
||||||
|
sdl_renderer: ^sdl2.Renderer,
|
||||||
|
font_atlas: FontAtlas,
|
||||||
|
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
should_close: bool,
|
should_close: bool,
|
||||||
screen_height: int,
|
screen_height: int,
|
||||||
screen_width: int,
|
screen_width: int,
|
||||||
font: raylib.Font,
|
width_dpi_ratio: f32,
|
||||||
|
height_dpi_ratio: f32,
|
||||||
|
|
||||||
directory: string,
|
directory: string,
|
||||||
|
|
||||||
|
@ -86,14 +89,14 @@ Action :: struct {
|
||||||
description: string,
|
description: string,
|
||||||
}
|
}
|
||||||
InputMap :: struct {
|
InputMap :: struct {
|
||||||
key_actions: map[raylib.KeyboardKey]Action,
|
key_actions: map[plugin.Key]Action,
|
||||||
ctrl_key_actions: map[raylib.KeyboardKey]Action,
|
ctrl_key_actions: map[plugin.Key]Action,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_input_map :: proc() -> InputMap {
|
new_input_map :: proc() -> InputMap {
|
||||||
input_map := InputMap {
|
input_map := InputMap {
|
||||||
key_actions = make(map[raylib.KeyboardKey]Action),
|
key_actions = make(map[plugin.Key]Action),
|
||||||
ctrl_key_actions = make(map[raylib.KeyboardKey]Action),
|
ctrl_key_actions = make(map[plugin.Key]Action),
|
||||||
}
|
}
|
||||||
|
|
||||||
return input_map;
|
return input_map;
|
||||||
|
@ -106,7 +109,7 @@ delete_input_map :: proc(input_map: ^InputMap) {
|
||||||
// NOTE(pcleavelin): might be a bug in the compiler where it can't coerce
|
// NOTE(pcleavelin): might be a bug in the compiler where it can't coerce
|
||||||
// `EditorAction` to `InputGroup` when given as a proc parameter, that is why there
|
// `EditorAction` to `InputGroup` when given as a proc parameter, that is why there
|
||||||
// are two functions
|
// are two functions
|
||||||
register_plugin_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: PluginEditorAction, description: string = "") {
|
register_plugin_key_action_single :: proc(input_map: ^InputMap, key: plugin.Key, action: PluginEditorAction, description: string = "") {
|
||||||
if ok := key in input_map.key_actions; ok {
|
if ok := key in input_map.key_actions; ok {
|
||||||
// TODO: log that key is already registered
|
// TODO: log that key is already registered
|
||||||
fmt.eprintln("plugin key already registered with single action", key);
|
fmt.eprintln("plugin key already registered with single action", key);
|
||||||
|
@ -118,7 +121,7 @@ register_plugin_key_action_single :: proc(input_map: ^InputMap, key: raylib.Keyb
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction, description: string = "") {
|
register_key_action_single :: proc(input_map: ^InputMap, key: plugin.Key, action: EditorAction, description: string = "") {
|
||||||
if ok := key in input_map.key_actions; ok {
|
if ok := key in input_map.key_actions; ok {
|
||||||
// TODO: log that key is already registered
|
// TODO: log that key is already registered
|
||||||
fmt.eprintln("key already registered with single action", key);
|
fmt.eprintln("key already registered with single action", key);
|
||||||
|
@ -130,7 +133,7 @@ register_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
|
register_key_action_group :: proc(input_map: ^InputMap, key: plugin.Key, input_group: InputGroup, description: string = "") {
|
||||||
if ok := key in input_map.key_actions; ok {
|
if ok := key in input_map.key_actions; ok {
|
||||||
// TODO: log that key is already registered
|
// TODO: log that key is already registered
|
||||||
fmt.eprintln("key already registered with single action", key);
|
fmt.eprintln("key already registered with single action", key);
|
||||||
|
@ -142,7 +145,7 @@ register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction, description: string = "") {
|
register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: plugin.Key, action: EditorAction, description: string = "") {
|
||||||
if ok := key in input_map.key_actions; ok {
|
if ok := key in input_map.key_actions; ok {
|
||||||
// TODO: log that key is already registered
|
// TODO: log that key is already registered
|
||||||
fmt.eprintln("key already registered with single action", key);
|
fmt.eprintln("key already registered with single action", key);
|
||||||
|
@ -154,7 +157,7 @@ register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: raylib.Keyboa
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
|
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: plugin.Key, input_group: InputGroup, description: string = "") {
|
||||||
if ok := key in input_map.key_actions; ok {
|
if ok := key in input_map.key_actions; ok {
|
||||||
// TODO: log that key is already registered
|
// TODO: log that key is already registered
|
||||||
fmt.eprintln("key already registered with single action", key);
|
fmt.eprintln("key already registered with single action", key);
|
||||||
|
|
|
@ -8,7 +8,6 @@ import "core:math"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "vendor:raylib"
|
|
||||||
|
|
||||||
import "../theme"
|
import "../theme"
|
||||||
import "../plugin"
|
import "../plugin"
|
||||||
|
@ -752,7 +751,7 @@ update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, font: raylib.Font, show_line_numbers: bool = true) {
|
draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, show_line_numbers: bool = true) {
|
||||||
update_glyph_buffer(buffer);
|
update_glyph_buffer(buffer);
|
||||||
if highlighter, exists := state.highlighters[buffer.extension]; exists {
|
if highlighter, exists := state.highlighters[buffer.extension]; exists {
|
||||||
highlighter(state.plugin_vtable, buffer);
|
highlighter(state.plugin_vtable, buffer);
|
||||||
|
@ -771,9 +770,11 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, fon
|
||||||
|
|
||||||
// draw cursor
|
// draw cursor
|
||||||
if state.mode == .Normal {
|
if state.mode == .Normal {
|
||||||
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Background4));
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Background4);
|
||||||
|
//raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Background4));
|
||||||
} else if state.mode == .Insert {
|
} else if state.mode == .Insert {
|
||||||
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Green));
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Green);
|
||||||
|
// raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Green));
|
||||||
|
|
||||||
num_line_break := 0;
|
num_line_break := 0;
|
||||||
line_length := 0;
|
line_length := 0;
|
||||||
|
@ -793,14 +794,16 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, fon
|
||||||
cursor_x += line_length * state.source_font_width;
|
cursor_x += line_length * state.source_font_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Blue));
|
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Blue);
|
||||||
|
//raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), i32(state.source_font_width), i32(state.source_font_height), theme.get_palette_raylib_color(.Blue));
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in 0..<buffer.glyph_buffer_height {
|
for j in 0..<buffer.glyph_buffer_height {
|
||||||
text_y := y + state.source_font_height * j;
|
text_y := y + state.source_font_height * j;
|
||||||
|
|
||||||
if show_line_numbers {
|
if show_line_numbers {
|
||||||
raylib.DrawTextEx(font, raylib.TextFormat("%d", begin + j + 1), raylib.Vector2 { f32(x), f32(text_y) }, f32(state.source_font_height), 0, theme.get_palette_raylib_color(.Background4));
|
draw_text(state, fmt.tprintf("%d", begin + j + 1), x, text_y);
|
||||||
|
//raylib.DrawTextEx(font, raylib.TextFormat("%d", begin + j + 1), raylib.Vector2 { f32(x), f32(text_y) }, f32(state.source_font_height), 0, theme.get_palette_raylib_color(.Background4));
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..<buffer.glyph_buffer_width {
|
for i in 0..<buffer.glyph_buffer_width {
|
||||||
|
@ -809,7 +812,8 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, fon
|
||||||
|
|
||||||
if glyph.codepoint == 0 { break; }
|
if glyph.codepoint == 0 { break; }
|
||||||
|
|
||||||
raylib.DrawTextCodepoint(font, rune(glyph.codepoint), raylib.Vector2 { f32(text_x), f32(text_y) }, f32(state.source_font_height), theme.get_palette_raylib_color(glyph.color));
|
draw_codepoint(state, rune(glyph.codepoint), text_x, text_y, glyph.color);
|
||||||
|
//raylib.DrawTextCodepoint(font, rune(glyph.codepoint), raylib.Vector2 { f32(text_x), f32(text_y) }, f32(state.source_font_height), theme.get_palette_raylib_color(glyph.color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "vendor:sdl2"
|
||||||
|
import "vendor:sdl2/ttf"
|
||||||
|
|
||||||
|
import "../theme"
|
||||||
|
|
||||||
|
scale :: 2;
|
||||||
|
start_char :: ' ';
|
||||||
|
end_char :: '~';
|
||||||
|
|
||||||
|
FontAtlas :: struct {
|
||||||
|
texture: ^sdl2.Texture,
|
||||||
|
font: ^ttf.Font,
|
||||||
|
max_width: int,
|
||||||
|
max_height: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_font_atlas :: proc(state: ^State, path: cstring) -> FontAtlas {
|
||||||
|
free_font_atlas(state.font_atlas);
|
||||||
|
|
||||||
|
font_height := i32(state.source_font_height*scale);
|
||||||
|
|
||||||
|
atlas := FontAtlas {
|
||||||
|
// FIXME: check if this failed
|
||||||
|
font = ttf.OpenFont(path, font_height),
|
||||||
|
}
|
||||||
|
ttf.SetFontStyle(atlas.font, ttf.STYLE_NORMAL);
|
||||||
|
|
||||||
|
// NOTE: not sure if I like the look of this or not yet
|
||||||
|
// ttf.SetFontHinting(atlas.font, ttf.HINTING_MONO);
|
||||||
|
|
||||||
|
minx, maxx, miny, maxy: i32;
|
||||||
|
advanced: i32;
|
||||||
|
for char in start_char..=end_char {
|
||||||
|
ttf.GlyphMetrics32(atlas.font, char, &minx, &maxx, &miny, &maxy, &advanced);
|
||||||
|
|
||||||
|
width := maxx-minx;
|
||||||
|
height := maxy+miny;
|
||||||
|
|
||||||
|
if width > i32(atlas.max_width) {
|
||||||
|
atlas.max_width = int(width);
|
||||||
|
}
|
||||||
|
if height > i32(atlas.max_height) {
|
||||||
|
atlas.max_height = int(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
font_width := i32(atlas.max_width);
|
||||||
|
font_height = i32(atlas.max_height);
|
||||||
|
state.source_font_width = int(font_width/scale);
|
||||||
|
state.source_font_height = int(font_height/scale);
|
||||||
|
|
||||||
|
temp_surface: ^sdl2.Surface;
|
||||||
|
// FIXME: check if this failed
|
||||||
|
font_surface := sdl2.CreateRGBSurface(0, font_width * (end_char-start_char + 1), font_height, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||||
|
|
||||||
|
rect: sdl2.Rect;
|
||||||
|
|
||||||
|
white := sdl2.Color { 0xff, 0xff, 0xff, 0xff };
|
||||||
|
for char, index in start_char..=end_char {
|
||||||
|
|
||||||
|
rect.x = i32(index) * font_width;
|
||||||
|
rect.y = 0;
|
||||||
|
|
||||||
|
// FIXME: check if this failed
|
||||||
|
temp_surface = ttf.RenderGlyph32_Blended(atlas.font, char, white);
|
||||||
|
|
||||||
|
// NOTE(pcleavelin): holy schmoley batman, it took hours of researching to find out
|
||||||
|
// that the way to properly blend the texture atlas WAS TO DISABLE BLENDING!
|
||||||
|
// and of course it's ONE GUY on a forum that has the answer, but it's for some
|
||||||
|
// reason not even listed on the first page of Google when you search for:
|
||||||
|
// "sdl_ttf rendering antialiasing"
|
||||||
|
//
|
||||||
|
// But the reason why this is needed (I /think/) is because you want to
|
||||||
|
// directly write all the RGBA data to `font_surface` without it attempting to
|
||||||
|
// blend a surface that has pure black
|
||||||
|
sdl2.SetSurfaceBlendMode(temp_surface, .NONE);
|
||||||
|
|
||||||
|
src_rect := sdl2.Rect {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
temp_surface.w,
|
||||||
|
temp_surface.h
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: check if this failed
|
||||||
|
sdl2.BlitSurface(temp_surface, &src_rect, font_surface, &rect);
|
||||||
|
sdl2.FreeSurface(temp_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: check if this failed
|
||||||
|
atlas.texture = sdl2.CreateTextureFromSurface(state.sdl_renderer, font_surface);
|
||||||
|
sdl2.SetTextureScaleMode(atlas.texture, .Best);
|
||||||
|
return atlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_font_atlas :: proc(font_atlas: FontAtlas) {
|
||||||
|
if font_atlas.font != nil {
|
||||||
|
ttf.CloseFont(font_atlas.font);
|
||||||
|
}
|
||||||
|
if font_atlas.texture != nil {
|
||||||
|
sdl2.DestroyTexture(font_atlas.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_rect_outline :: proc(state: ^State, x,y,w,h: int, color: theme.PaletteColor) {
|
||||||
|
color := theme.get_palette_color(color);
|
||||||
|
|
||||||
|
sdl2.SetRenderDrawColor(state.sdl_renderer, color.r, color.g, color.b, color.a);
|
||||||
|
sdl2.RenderDrawRect(state.sdl_renderer, &sdl2.Rect { i32(x), i32(y), i32(w), i32(h) });
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_rect :: proc(state: ^State, x,y,w,h: int, color: theme.PaletteColor) {
|
||||||
|
color := theme.get_palette_color(color);
|
||||||
|
|
||||||
|
sdl2.SetRenderDrawColor(state.sdl_renderer, color.r, color.g, color.b, color.a);
|
||||||
|
sdl2.RenderFillRect(state.sdl_renderer, &sdl2.Rect { i32(x), i32(y), i32(w), i32(h) });
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_codepoint :: proc(state: ^State, codepoint: rune, x,y: int, color: theme.PaletteColor) {
|
||||||
|
color := theme.get_palette_color(color);
|
||||||
|
|
||||||
|
if codepoint >= start_char && codepoint <= end_char {
|
||||||
|
codepoint := codepoint - start_char;
|
||||||
|
|
||||||
|
src_rect := sdl2.Rect {
|
||||||
|
x = i32(codepoint) * i32(state.font_atlas.max_width),
|
||||||
|
y = 0,
|
||||||
|
w = i32(state.font_atlas.max_width),
|
||||||
|
h = i32(state.font_atlas.max_height),
|
||||||
|
};
|
||||||
|
|
||||||
|
dest_rect := sdl2.Rect {
|
||||||
|
x = i32(x),
|
||||||
|
y = i32(y),
|
||||||
|
w = i32(state.font_atlas.max_width/scale),
|
||||||
|
h = i32(state.font_atlas.max_height/scale),
|
||||||
|
};
|
||||||
|
|
||||||
|
sdl2.SetTextureColorMod(state.font_atlas.texture, color.r, color.g, color.b);
|
||||||
|
sdl2.RenderCopy(state.sdl_renderer, state.font_atlas.texture, &src_rect, &dest_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text :: proc(state: ^State, text: string, x,y: int, color: theme.PaletteColor = .Foreground1) {
|
||||||
|
for char, idx in text {
|
||||||
|
if char < start_char || char > end_char {
|
||||||
|
draw_codepoint(state, '?', x + idx * state.source_font_width, y, color);
|
||||||
|
} else {
|
||||||
|
draw_codepoint(state, char, x + idx * state.source_font_width, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
885
src/main.odin
885
src/main.odin
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,6 @@ package plugin;
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
import "core:dynlib"
|
import "core:dynlib"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "vendor:raylib"
|
|
||||||
|
|
||||||
import "../theme"
|
import "../theme"
|
||||||
|
|
||||||
|
@ -85,6 +84,48 @@ Iterator :: struct {
|
||||||
until_end_of_word: rawptr,
|
until_end_of_word: rawptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UiInteraction :: struct {
|
||||||
|
hovering: bool,
|
||||||
|
clicked: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
UiAxis :: enum {
|
||||||
|
Horizontal = 0,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
|
UiSemanticSize :: struct {
|
||||||
|
kind: int,
|
||||||
|
value: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
UiBox :: rawptr;
|
||||||
|
|
||||||
|
UiPushParentProc :: proc "c" (ui_context: rawptr, box: UiBox);
|
||||||
|
UiPopParentProc :: proc "c" (ui_context: rawptr);
|
||||||
|
UiFloatingProc :: proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> UiBox;
|
||||||
|
UiCreateBoxProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiBox;
|
||||||
|
UiRectProc :: proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: UiAxis, size: [2]UiSemanticSize) -> UiBox;
|
||||||
|
UiSimpleProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiInteraction;
|
||||||
|
UiBufferProc :: proc "c" (ui_context: rawptr, buffer: rawptr, show_line_numbers: bool);
|
||||||
|
UiBufferIndexProc :: proc "c" (ui_context: rawptr, buffer: int, show_line_numbers: bool);
|
||||||
|
Ui :: struct {
|
||||||
|
ui_context: rawptr,
|
||||||
|
|
||||||
|
push_parent: UiPushParentProc,
|
||||||
|
pop_parent: UiPopParentProc,
|
||||||
|
|
||||||
|
spacer: UiSimpleProc,
|
||||||
|
floating: UiFloatingProc,
|
||||||
|
rect: UiRectProc,
|
||||||
|
|
||||||
|
button: UiSimpleProc,
|
||||||
|
label: UiSimpleProc,
|
||||||
|
|
||||||
|
buffer: UiBufferProc,
|
||||||
|
buffer_from_index: UiBufferIndexProc,
|
||||||
|
}
|
||||||
|
|
||||||
OnColorBufferProc :: proc "c" (plugin: Plugin, buffer: rawptr);
|
OnColorBufferProc :: proc "c" (plugin: Plugin, buffer: rawptr);
|
||||||
InputGroupProc :: proc "c" (plugin: Plugin, input_map: rawptr);
|
InputGroupProc :: proc "c" (plugin: Plugin, input_map: rawptr);
|
||||||
InputActionProc :: proc "c" (plugin: Plugin);
|
InputActionProc :: proc "c" (plugin: Plugin);
|
||||||
|
@ -98,6 +139,7 @@ Plugin :: struct {
|
||||||
state: rawptr,
|
state: rawptr,
|
||||||
iter: Iterator,
|
iter: Iterator,
|
||||||
buffer: Buffer,
|
buffer: Buffer,
|
||||||
|
ui: Ui,
|
||||||
|
|
||||||
register_hook: proc "c" (hook: Hook, on_hook: OnHookProc),
|
register_hook: proc "c" (hook: Hook, on_hook: OnHookProc),
|
||||||
register_highlighter: proc "c" (extension: cstring, on_color_buffer: OnColorBufferProc),
|
register_highlighter: proc "c" (extension: cstring, on_color_buffer: OnColorBufferProc),
|
||||||
|
@ -127,120 +169,246 @@ Hook :: enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
Key :: enum {
|
Key :: enum {
|
||||||
KEY_NULL = 0, // Key: NULL, used for no key pressed
|
UNKNOWN = 0,
|
||||||
// Alphanumeric keys
|
ENTER = 13,
|
||||||
APOSTROPHE = 39, // Key: '
|
ESCAPE = 27,
|
||||||
COMMA = 44, // Key: ,
|
BACKSPACE = 8,
|
||||||
MINUS = 45, // Key: -
|
TAB = 9,
|
||||||
PERIOD = 46, // Key: .
|
SPACE = 32,
|
||||||
SLASH = 47, // Key: /
|
EXCLAIM = 33,
|
||||||
ZERO = 48, // Key: 0
|
QUOTEDBL = 34,
|
||||||
ONE = 49, // Key: 1
|
HASH = 35,
|
||||||
TWO = 50, // Key: 2
|
PERCENT = 37,
|
||||||
THREE = 51, // Key: 3
|
DOLLAR = 36,
|
||||||
FOUR = 52, // Key: 4
|
AMPERSAND = 38,
|
||||||
FIVE = 53, // Key: 5
|
QUOTE = 39,
|
||||||
SIX = 54, // Key: 6
|
LEFTPAREN = 40,
|
||||||
SEVEN = 55, // Key: 7
|
RIGHTPAREN = 41,
|
||||||
EIGHT = 56, // Key: 8
|
ASTERISK = 42,
|
||||||
NINE = 57, // Key: 9
|
PLUS = 43,
|
||||||
SEMICOLON = 59, // Key: ;
|
COMMA = 44,
|
||||||
EQUAL = 61, // Key: =
|
MINUS = 45,
|
||||||
A = 65, // Key: A | a
|
PERIOD = 46,
|
||||||
B = 66, // Key: B | b
|
SLASH = 47,
|
||||||
C = 67, // Key: C | c
|
NUM0 = 48,
|
||||||
D = 68, // Key: D | d
|
NUM1 = 49,
|
||||||
E = 69, // Key: E | e
|
NUM2 = 50,
|
||||||
F = 70, // Key: F | f
|
NUM3 = 51,
|
||||||
G = 71, // Key: G | g
|
NUM4 = 52,
|
||||||
H = 72, // Key: H | h
|
NUM5 = 53,
|
||||||
I = 73, // Key: I | i
|
NUM6 = 54,
|
||||||
J = 74, // Key: J | j
|
NUM7 = 55,
|
||||||
K = 75, // Key: K | k
|
NUM8 = 56,
|
||||||
L = 76, // Key: L | l
|
NUM9 = 57,
|
||||||
M = 77, // Key: M | m
|
COLON = 58,
|
||||||
N = 78, // Key: N | n
|
SEMICOLON = 59,
|
||||||
O = 79, // Key: O | o
|
LESS = 60,
|
||||||
P = 80, // Key: P | p
|
EQUAL = 61,
|
||||||
Q = 81, // Key: Q | q
|
GREATER = 62,
|
||||||
R = 82, // Key: R | r
|
QUESTION = 63,
|
||||||
S = 83, // Key: S | s
|
AT = 64,
|
||||||
T = 84, // Key: T | t
|
LEFTBRACKET = 91,
|
||||||
U = 85, // Key: U | u
|
BACKSLASH = 92,
|
||||||
V = 86, // Key: V | v
|
RIGHTBRACKET = 93,
|
||||||
W = 87, // Key: W | w
|
CARET = 94,
|
||||||
X = 88, // Key: X | x
|
UNDERSCORE = 95,
|
||||||
Y = 89, // Key: Y | y
|
BACKQUOTE = 96,
|
||||||
Z = 90, // Key: Z | z
|
A = 97,
|
||||||
LEFT_BRACKET = 91, // Key: [
|
B = 98,
|
||||||
BACKSLASH = 92, // Key: '\'
|
C = 99,
|
||||||
RIGHT_BRACKET = 93, // Key: ]
|
D = 100,
|
||||||
GRAVE = 96, // Key: `
|
E = 101,
|
||||||
// Function keys
|
F = 102,
|
||||||
SPACE = 32, // Key: Space
|
G = 103,
|
||||||
ESCAPE = 256, // Key: Esc
|
H = 104,
|
||||||
ENTER = 257, // Key: Enter
|
I = 105,
|
||||||
TAB = 258, // Key: Tab
|
J = 106,
|
||||||
BACKSPACE = 259, // Key: Backspace
|
K = 107,
|
||||||
INSERT = 260, // Key: Ins
|
L = 108,
|
||||||
DELETE = 261, // Key: Del
|
M = 109,
|
||||||
RIGHT = 262, // Key: Cursor right
|
N = 110,
|
||||||
LEFT = 263, // Key: Cursor left
|
O = 111,
|
||||||
DOWN = 264, // Key: Cursor down
|
P = 112,
|
||||||
UP = 265, // Key: Cursor up
|
Q = 113,
|
||||||
PAGE_UP = 266, // Key: Page up
|
R = 114,
|
||||||
PAGE_DOWN = 267, // Key: Page down
|
S = 115,
|
||||||
HOME = 268, // Key: Home
|
T = 116,
|
||||||
END = 269, // Key: End
|
U = 117,
|
||||||
CAPS_LOCK = 280, // Key: Caps lock
|
V = 118,
|
||||||
SCROLL_LOCK = 281, // Key: Scroll down
|
W = 119,
|
||||||
NUM_LOCK = 282, // Key: Num lock
|
X = 120,
|
||||||
PRINT_SCREEN = 283, // Key: Print screen
|
Y = 121,
|
||||||
PAUSE = 284, // Key: Pause
|
Z = 122,
|
||||||
F1 = 290, // Key: F1
|
CAPSLOCK = 1073741881,
|
||||||
F2 = 291, // Key: F2
|
F1 = 1073741882,
|
||||||
F3 = 292, // Key: F3
|
F2 = 1073741883,
|
||||||
F4 = 293, // Key: F4
|
F3 = 1073741884,
|
||||||
F5 = 294, // Key: F5
|
F4 = 1073741885,
|
||||||
F6 = 295, // Key: F6
|
F5 = 1073741886,
|
||||||
F7 = 296, // Key: F7
|
F6 = 1073741887,
|
||||||
F8 = 297, // Key: F8
|
F7 = 1073741888,
|
||||||
F9 = 298, // Key: F9
|
F8 = 1073741889,
|
||||||
F10 = 299, // Key: F10
|
F9 = 1073741890,
|
||||||
F11 = 300, // Key: F11
|
F10 = 1073741891,
|
||||||
F12 = 301, // Key: F12
|
F11 = 1073741892,
|
||||||
LEFT_SHIFT = 340, // Key: Shift left
|
F12 = 1073741893,
|
||||||
LEFT_CONTROL = 341, // Key: Control left
|
PRINTSCREEN = 1073741894,
|
||||||
LEFT_ALT = 342, // Key: Alt left
|
SCROLLLOCK = 1073741895,
|
||||||
LEFT_SUPER = 343, // Key: Super left
|
PAUSE = 1073741896,
|
||||||
RIGHT_SHIFT = 344, // Key: Shift right
|
INSERT = 1073741897,
|
||||||
RIGHT_CONTROL = 345, // Key: Control right
|
HOME = 1073741898,
|
||||||
RIGHT_ALT = 346, // Key: Alt right
|
PAGEUP = 1073741899,
|
||||||
RIGHT_SUPER = 347, // Key: Super right
|
DELETE = 127,
|
||||||
KB_MENU = 348, // Key: KB menu
|
END = 1073741901,
|
||||||
// Keypad keys
|
PAGEDOWN = 1073741902,
|
||||||
KP_0 = 320, // Key: Keypad 0
|
RIGHT = 1073741903,
|
||||||
KP_1 = 321, // Key: Keypad 1
|
LEFT = 1073741904,
|
||||||
KP_2 = 322, // Key: Keypad 2
|
DOWN = 1073741905,
|
||||||
KP_3 = 323, // Key: Keypad 3
|
UP = 1073741906,
|
||||||
KP_4 = 324, // Key: Keypad 4
|
NUMLOCKCLEAR = 1073741907,
|
||||||
KP_5 = 325, // Key: Keypad 5
|
KP_DIVIDE = 1073741908,
|
||||||
KP_6 = 326, // Key: Keypad 6
|
KP_MULTIPLY = 1073741909,
|
||||||
KP_7 = 327, // Key: Keypad 7
|
KP_MINUS = 1073741910,
|
||||||
KP_8 = 328, // Key: Keypad 8
|
KP_PLUS = 1073741911,
|
||||||
KP_9 = 329, // Key: Keypad 9
|
KP_ENTER = 1073741912,
|
||||||
KP_DECIMAL = 330, // Key: Keypad .
|
KP_1 = 1073741913,
|
||||||
KP_DIVIDE = 331, // Key: Keypad /
|
KP_2 = 1073741914,
|
||||||
KP_MULTIPLY = 332, // Key: Keypad *
|
KP_3 = 1073741915,
|
||||||
KP_SUBTRACT = 333, // Key: Keypad -
|
KP_4 = 1073741916,
|
||||||
KP_ADD = 334, // Key: Keypad +
|
KP_5 = 1073741917,
|
||||||
KP_ENTER = 335, // Key: Keypad Enter
|
KP_6 = 1073741918,
|
||||||
KP_EQUAL = 336, // Key: Keypad =
|
KP_7 = 1073741919,
|
||||||
// Android key buttons
|
KP_8 = 1073741920,
|
||||||
BACK = 4, // Key: Android back button
|
KP_9 = 1073741921,
|
||||||
MENU = 82, // Key: Android menu button
|
KP_0 = 1073741922,
|
||||||
VOLUME_UP = 24, // Key: Android volume up button
|
KP_PERIOD = 1073741923,
|
||||||
VOLUME_DOWN = 25, // Key: Android volume down button
|
APPLICATION = 1073741925,
|
||||||
|
POWER = 1073741926,
|
||||||
|
KP_EQUALS = 1073741927,
|
||||||
|
F13 = 1073741928,
|
||||||
|
F14 = 1073741929,
|
||||||
|
F15 = 1073741930,
|
||||||
|
F16 = 1073741931,
|
||||||
|
F17 = 1073741932,
|
||||||
|
F18 = 1073741933,
|
||||||
|
F19 = 1073741934,
|
||||||
|
F20 = 1073741935,
|
||||||
|
F21 = 1073741936,
|
||||||
|
F22 = 1073741937,
|
||||||
|
F23 = 1073741938,
|
||||||
|
F24 = 1073741939,
|
||||||
|
EXECUTE = 1073741940,
|
||||||
|
HELP = 1073741941,
|
||||||
|
MENU = 1073741942,
|
||||||
|
SELECT = 1073741943,
|
||||||
|
STOP = 1073741944,
|
||||||
|
AGAIN = 1073741945,
|
||||||
|
UNDO = 1073741946,
|
||||||
|
CUT = 1073741947,
|
||||||
|
COPY = 1073741948,
|
||||||
|
PASTE = 1073741949,
|
||||||
|
FIND = 1073741950,
|
||||||
|
MUTE = 1073741951,
|
||||||
|
VOLUMEUP = 1073741952,
|
||||||
|
VOLUMEDOWN = 1073741953,
|
||||||
|
KP_COMMA = 1073741957,
|
||||||
|
KP_EQUALSAS400 = 1073741958,
|
||||||
|
ALTERASE = 1073741977,
|
||||||
|
SYSREQ = 1073741978,
|
||||||
|
CANCEL = 1073741979,
|
||||||
|
CLEAR = 1073741980,
|
||||||
|
PRIOR = 1073741981,
|
||||||
|
RETURN2 = 1073741982,
|
||||||
|
SEPARATOR = 1073741983,
|
||||||
|
OUT = 1073741984,
|
||||||
|
OPER = 1073741985,
|
||||||
|
CLEARAGAIN = 1073741986,
|
||||||
|
CRSEL = 1073741987,
|
||||||
|
EXSEL = 1073741988,
|
||||||
|
KP_00 = 1073742000,
|
||||||
|
KP_000 = 1073742001,
|
||||||
|
THOUSANDSSEPARATOR = 1073742002,
|
||||||
|
DECIMALSEPARATOR = 1073742003,
|
||||||
|
CURRENCYUNIT = 1073742004,
|
||||||
|
CURRENCYSUBUNIT = 1073742005,
|
||||||
|
KP_LEFTPAREN = 1073742006,
|
||||||
|
KP_RIGHTPAREN = 1073742007,
|
||||||
|
KP_LEFTBRACE = 1073742008,
|
||||||
|
KP_RIGHTBRACE = 1073742009,
|
||||||
|
KP_TAB = 1073742010,
|
||||||
|
KP_BACKSPACE = 1073742011,
|
||||||
|
KP_A = 1073742012,
|
||||||
|
KP_B = 1073742013,
|
||||||
|
KP_C = 1073742014,
|
||||||
|
KP_D = 1073742015,
|
||||||
|
KP_E = 1073742016,
|
||||||
|
KP_F = 1073742017,
|
||||||
|
KP_XOR = 1073742018,
|
||||||
|
KP_POWER = 1073742019,
|
||||||
|
KP_PERCENT = 1073742020,
|
||||||
|
KP_LESS = 1073742021,
|
||||||
|
KP_GREATER = 1073742022,
|
||||||
|
KP_AMPERSAND = 1073742023,
|
||||||
|
KP_DBLAMPERSAND = 1073742024,
|
||||||
|
KP_VERTICALBAR = 1073742025,
|
||||||
|
KP_DBLVERTICALBAR = 1073742026,
|
||||||
|
KP_COLON = 1073742027,
|
||||||
|
KP_HASH = 1073742028,
|
||||||
|
KP_SPACE = 1073742029,
|
||||||
|
KP_AT = 1073742030,
|
||||||
|
KP_EXCLAM = 1073742031,
|
||||||
|
KP_MEMSTORE = 1073742032,
|
||||||
|
KP_MEMRECALL = 1073742033,
|
||||||
|
KP_MEMCLEAR = 1073742034,
|
||||||
|
KP_MEMADD = 1073742035,
|
||||||
|
KP_MEMSUBTRACT = 1073742036,
|
||||||
|
KP_MEMMULTIPLY = 1073742037,
|
||||||
|
KP_MEMDIVIDE = 1073742038,
|
||||||
|
KP_PLUSMINUS = 1073742039,
|
||||||
|
KP_CLEAR = 1073742040,
|
||||||
|
KP_CLEARENTRY = 1073742041,
|
||||||
|
KP_BINARY = 1073742042,
|
||||||
|
KP_OCTAL = 1073742043,
|
||||||
|
KP_DECIMAL = 1073742044,
|
||||||
|
KP_HEXADECIMAL = 1073742045,
|
||||||
|
LCTRL = 1073742048,
|
||||||
|
LSHIFT = 1073742049,
|
||||||
|
LALT = 1073742050,
|
||||||
|
LGUI = 1073742051,
|
||||||
|
RCTRL = 1073742052,
|
||||||
|
RSHIFT = 1073742053,
|
||||||
|
RALT = 1073742054,
|
||||||
|
RGUI = 1073742055,
|
||||||
|
MODE = 1073742081,
|
||||||
|
AUDIONEXT = 1073742082,
|
||||||
|
AUDIOPREV = 1073742083,
|
||||||
|
AUDIOSTOP = 1073742084,
|
||||||
|
AUDIOPLAY = 1073742085,
|
||||||
|
AUDIOMUTE = 1073742086,
|
||||||
|
MEDIASELECT = 1073742087,
|
||||||
|
WWW = 1073742088,
|
||||||
|
MAIL = 1073742089,
|
||||||
|
CALCULATOR = 1073742090,
|
||||||
|
COMPUTER = 1073742091,
|
||||||
|
AC_SEARCH = 1073742092,
|
||||||
|
AC_HOME = 1073742093,
|
||||||
|
AC_BACK = 1073742094,
|
||||||
|
AC_FORWARD = 1073742095,
|
||||||
|
AC_STOP = 1073742096,
|
||||||
|
AC_REFRESH = 1073742097,
|
||||||
|
AC_BOOKMARKS = 1073742098,
|
||||||
|
BRIGHTNESSDOWN = 1073742099,
|
||||||
|
BRIGHTNESSUP = 1073742100,
|
||||||
|
DISPLAYSWITCH = 1073742101,
|
||||||
|
KBDILLUMTOGGLE = 1073742102,
|
||||||
|
KBDILLUMDOWN = 1073742103,
|
||||||
|
KBDILLUMUP = 1073742104,
|
||||||
|
EJECT = 1073742105,
|
||||||
|
SLEEP = 1073742106,
|
||||||
|
APP1 = 1073742107,
|
||||||
|
APP2 = 1073742108,
|
||||||
|
AUDIOREWIND = 1073742109,
|
||||||
|
AUDIOFASTFORWARD = 1073742110,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package theme
|
package theme
|
||||||
|
|
||||||
import "vendor:raylib"
|
|
||||||
|
|
||||||
PaletteColor :: enum {
|
PaletteColor :: enum {
|
||||||
Background,
|
Background,
|
||||||
Foreground,
|
Foreground,
|
||||||
|
@ -97,7 +95,14 @@ light_palette := []u32 {
|
||||||
0x928374ff,
|
0x928374ff,
|
||||||
};
|
};
|
||||||
|
|
||||||
get_palette_raylib_color :: proc(palette_color: PaletteColor) -> raylib.Color {
|
get_palette_color :: proc(palette_color: PaletteColor) -> [4]u8 {
|
||||||
return raylib.GetColor(palette[palette_color]);
|
color: [4]u8;
|
||||||
|
|
||||||
|
c := palette[palette_color];
|
||||||
|
for i in 0..<4 {
|
||||||
|
color[i] = u8((c >> (8*u32(3-i)))&0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
537
src/ui/imm.odin
537
src/ui/imm.odin
|
@ -3,16 +3,29 @@ package ui
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "vendor:raylib"
|
import "vendor:sdl2"
|
||||||
|
|
||||||
|
import "../core"
|
||||||
import "../theme"
|
import "../theme"
|
||||||
|
|
||||||
root: ^Box = nil;
|
Context :: struct {
|
||||||
current_parent: ^Box = nil;
|
root: ^Box,
|
||||||
persistent: map[Key]^Box = nil;
|
current_parent: ^Box,
|
||||||
current_interaction_index: int = 0;
|
persistent: map[Key]^Box,
|
||||||
|
current_interaction_index: int,
|
||||||
|
|
||||||
clips: [dynamic]Rect = nil;
|
clips: [dynamic]Rect,
|
||||||
|
renderer: ^sdl2.Renderer,
|
||||||
|
|
||||||
|
mouse_x: int,
|
||||||
|
mouse_y: int,
|
||||||
|
|
||||||
|
mouse_left_down: bool,
|
||||||
|
last_mouse_left_down: bool,
|
||||||
|
|
||||||
|
mouse_right_down: bool,
|
||||||
|
last_mouse_right_down: bool,
|
||||||
|
}
|
||||||
|
|
||||||
Rect :: struct {
|
Rect :: struct {
|
||||||
pos: [2]int,
|
pos: [2]int,
|
||||||
|
@ -25,6 +38,7 @@ Key :: struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
Interaction :: struct {
|
Interaction :: struct {
|
||||||
|
hovering: bool,
|
||||||
clicked: bool,
|
clicked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +49,12 @@ Flag :: enum {
|
||||||
DrawText,
|
DrawText,
|
||||||
DrawBorder,
|
DrawBorder,
|
||||||
DrawBackground,
|
DrawBackground,
|
||||||
|
Floating,
|
||||||
|
CustomDrawFunc,
|
||||||
}
|
}
|
||||||
|
|
||||||
SemanticSizeKind :: enum {
|
SemanticSizeKind :: enum {
|
||||||
FitText,
|
FitText = 0,
|
||||||
Exact,
|
Exact,
|
||||||
ChildrenSum,
|
ChildrenSum,
|
||||||
Fill,
|
Fill,
|
||||||
|
@ -55,6 +71,7 @@ Axis :: enum {
|
||||||
Vertical = 1,
|
Vertical = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomDrawFunc :: proc(state: ^core.State, box: ^Box, user_data: rawptr);
|
||||||
Box :: struct {
|
Box :: struct {
|
||||||
first: ^Box,
|
first: ^Box,
|
||||||
last: ^Box,
|
last: ^Box,
|
||||||
|
@ -72,30 +89,36 @@ Box :: struct {
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
semantic_size: [2]SemanticSize,
|
semantic_size: [2]SemanticSize,
|
||||||
computed_size: [2]int,
|
computed_size: [2]int,
|
||||||
|
computed_pos: [2]int,
|
||||||
|
|
||||||
computed_pos: [2]int
|
hot: int,
|
||||||
|
active: int,
|
||||||
|
|
||||||
|
custom_draw_func: CustomDrawFunc,
|
||||||
|
user_data: rawptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
init :: proc() {
|
init :: proc(renderer: ^sdl2.Renderer) -> Context {
|
||||||
if persistent == nil {
|
root := new(Box);
|
||||||
persistent = make(map[Key]^Box);
|
root.key = gen_key(nil, "root", 69);
|
||||||
|
|
||||||
|
return Context {
|
||||||
|
root = root,
|
||||||
|
current_parent = root,
|
||||||
|
persistent = make(map[Key]^Box),
|
||||||
|
clips = make([dynamic]Rect),
|
||||||
|
renderer = renderer,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if clips == nil {
|
gen_key :: proc(ctx: ^Context, label: string, value: int) -> Key {
|
||||||
clips = make([dynamic]Rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
root = new(Box);
|
|
||||||
root.key = gen_key("root", 69);
|
|
||||||
current_parent = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_key :: proc(label: string, value: int) -> Key {
|
|
||||||
key_label := ""
|
key_label := ""
|
||||||
if current_parent == nil || len(current_parent.key.label) < 1 {
|
if ctx != nil && (ctx.current_parent == nil || len(ctx.current_parent.key.label) < 1) {
|
||||||
key_label = strings.clone(label);
|
key_label = strings.clone(label);
|
||||||
|
} else if ctx != nil {
|
||||||
|
key_label = fmt.aprintf("%s:%s", ctx.current_parent.key.label, label);
|
||||||
} else {
|
} else {
|
||||||
key_label = fmt.aprintf("%s:%s", current_parent.key.label, label);
|
key_label = fmt.aprintf("%s",label);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Key {
|
return Key {
|
||||||
|
@ -104,22 +127,23 @@ gen_key :: proc(label: string, value: int) -> Key {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
make_box :: proc(key: Key, label: string, flags: bit_set[Flag], axis: Axis, semantic_size: [2]SemanticSize) -> ^Box {
|
@(private)
|
||||||
|
make_box :: proc(ctx: ^Context, key: Key, label: string, flags: bit_set[Flag], axis: Axis, semantic_size: [2]SemanticSize) -> ^Box {
|
||||||
box: ^Box = nil;
|
box: ^Box = nil;
|
||||||
|
|
||||||
if cached_box, exists := persistent[key]; exists {
|
if cached_box, exists := ctx.persistent[key]; exists {
|
||||||
if cached_box.last_interacted_index < current_interaction_index {
|
if cached_box.last_interacted_index < ctx.current_interaction_index {
|
||||||
old_cached_box := persistent[key];
|
old_cached_box := ctx.persistent[key];
|
||||||
free(old_cached_box);
|
free(old_cached_box);
|
||||||
box = new(Box);
|
box = new(Box);
|
||||||
|
|
||||||
persistent[key] = box;
|
ctx.persistent[key] = box;
|
||||||
} else {
|
} else {
|
||||||
box = cached_box;
|
box = cached_box;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
box = new(Box);
|
box = new(Box);
|
||||||
persistent[key] = box;
|
ctx.persistent[key] = box;
|
||||||
}
|
}
|
||||||
|
|
||||||
box.key = key;
|
box.key = key;
|
||||||
|
@ -128,22 +152,20 @@ make_box :: proc(key: Key, label: string, flags: bit_set[Flag], axis: Axis, sema
|
||||||
box.first = nil;
|
box.first = nil;
|
||||||
box.last = nil;
|
box.last = nil;
|
||||||
box.next = nil;
|
box.next = nil;
|
||||||
box.prev = current_parent.last;
|
box.prev = ctx.current_parent.last;
|
||||||
box.parent = current_parent;
|
box.parent = ctx.current_parent;
|
||||||
box.flags = flags;
|
box.flags = flags;
|
||||||
box.axis = axis;
|
box.axis = axis;
|
||||||
box.semantic_size = semantic_size;
|
box.semantic_size = semantic_size;
|
||||||
box.computed_pos = {};
|
|
||||||
box.computed_size = {};
|
|
||||||
|
|
||||||
if current_parent.last != nil {
|
if ctx.current_parent.last != nil {
|
||||||
current_parent.last.next = box;
|
ctx.current_parent.last.next = box;
|
||||||
}
|
}
|
||||||
if current_parent.first == nil {
|
if ctx.current_parent.first == nil {
|
||||||
current_parent.first = box;
|
ctx.current_parent.first = box;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_parent.last = box;
|
ctx.current_parent.last = box;
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
@ -173,67 +195,99 @@ ChildrenSum :[2]SemanticSize: {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
push_box :: proc(label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText, value: int = 0) -> ^Box {
|
Fill :[2]SemanticSize: {
|
||||||
key := gen_key(label, value);
|
SemanticSize {
|
||||||
box := make_box(key, label, flags, axis, semantic_size);
|
kind = .Fill,
|
||||||
|
},
|
||||||
|
SemanticSize {
|
||||||
|
kind = .Fill,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
push_box :: proc(ctx: ^Context, label: string, flags: bit_set[Flag], axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = FitText, value: int = 0) -> ^Box {
|
||||||
|
key := gen_key(ctx, label, value);
|
||||||
|
box := make_box(ctx, key, label, flags, axis, semantic_size);
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_parent :: proc(box: ^Box) {
|
push_parent :: proc(ctx: ^Context, box: ^Box) {
|
||||||
current_parent = box;
|
ctx.current_parent = box;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_parent :: proc() {
|
pop_parent :: proc(ctx: ^Context) {
|
||||||
if current_parent.parent != nil {
|
if ctx.current_parent.parent != nil {
|
||||||
current_parent = current_parent.parent;
|
ctx.current_parent = ctx.current_parent.parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test_box :: proc(box: ^Box) -> Interaction {
|
test_box :: proc(ctx: ^Context, box: ^Box) -> Interaction {
|
||||||
|
hovering: bool;
|
||||||
|
|
||||||
|
mouse_is_clicked := !ctx.last_mouse_left_down && ctx.mouse_left_down;
|
||||||
|
|
||||||
|
if ctx.mouse_x >= box.computed_pos.x && ctx.mouse_x <= box.computed_pos.x + box.computed_size.x &&
|
||||||
|
ctx.mouse_y >= box.computed_pos.y && ctx.mouse_y <= box.computed_pos.y + box.computed_size.y
|
||||||
|
{
|
||||||
|
hovering = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if hovering {
|
||||||
|
box.hot += 1;
|
||||||
|
} else {
|
||||||
|
box.hot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return Interaction {
|
return Interaction {
|
||||||
clicked = false,
|
hovering = hovering,
|
||||||
|
clicked = hovering && mouse_is_clicked,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_box_children :: proc(box: ^Box, keep_persistent: bool = true) {
|
delete_box_children :: proc(ctx: ^Context, box: ^Box, keep_persistent: bool = true) {
|
||||||
iter := BoxIter { box.first, 0 };
|
iter := BoxIter { box.first, 0 };
|
||||||
|
|
||||||
for box in iterate_box(&iter) {
|
for box in iterate_box(&iter) {
|
||||||
delete_box(box, keep_persistent);
|
delete_box(ctx, box, keep_persistent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_box :: proc(box: ^Box, keep_persistent: bool = true) {
|
delete_box :: proc(ctx: ^Context, box: ^Box, keep_persistent: bool = true) {
|
||||||
delete_box_children(box, keep_persistent);
|
delete_box_children(ctx, box, keep_persistent);
|
||||||
|
|
||||||
if !(box.key in persistent) || !keep_persistent {
|
if !(box.key in ctx.persistent) || !keep_persistent {
|
||||||
delete(box.key.label);
|
delete(box.key.label);
|
||||||
free(box);
|
free(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prune :: proc() {
|
prune :: proc(ctx: ^Context) {
|
||||||
iter := BoxIter { root.first, 0 };
|
iter := BoxIter { ctx.root.first, 0 };
|
||||||
|
|
||||||
for box in iterate_box(&iter) {
|
for box in iterate_box(&iter) {
|
||||||
delete_box_children(box);
|
delete_box_children(ctx, box);
|
||||||
|
|
||||||
if !(box.key in persistent) {
|
if !(box.key in ctx.persistent) {
|
||||||
free(box);
|
free(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root_key := root.key;
|
computed_pos := ctx.root.computed_pos;
|
||||||
root^ = {
|
computed_size := ctx.root.computed_size;
|
||||||
key = root_key,
|
root_key := ctx.root.key;
|
||||||
};
|
|
||||||
current_parent = root;
|
ctx.root.first = nil;
|
||||||
|
ctx.root.last = nil;
|
||||||
|
ctx.root.next = nil;
|
||||||
|
ctx.root.prev = nil;
|
||||||
|
ctx.root.parent = nil;
|
||||||
|
ctx.current_parent = ctx.root;
|
||||||
}
|
}
|
||||||
|
|
||||||
ancestor_size :: proc(box: ^Box, axis: Axis) -> int {
|
// TODO: consider not using `ctx` here
|
||||||
if box == nil || box.parent == nil {
|
ancestor_size :: proc(ctx: ^Context, box: ^Box, axis: Axis) -> int {
|
||||||
return root.computed_size[axis];
|
if box == nil || box.parent == nil || .Floating in box.flags {
|
||||||
|
return ctx.root.computed_size[axis];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch box.parent.semantic_size[axis].kind {
|
switch box.parent.semantic_size[axis].kind {
|
||||||
|
@ -244,27 +298,46 @@ ancestor_size :: proc(box: ^Box, axis: Axis) -> int {
|
||||||
return box.parent.computed_size[axis];
|
return box.parent.computed_size[axis];
|
||||||
|
|
||||||
case .ChildrenSum:
|
case .ChildrenSum:
|
||||||
return ancestor_size(box.parent, axis);
|
return ancestor_size(ctx, box.parent, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1337;
|
return 1337;
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, box: ^Box = root) {
|
prev_non_floating_sibling :: proc(ctx: ^Context, box: ^Box) -> ^Box {
|
||||||
|
if box == nil {
|
||||||
|
return nil;
|
||||||
|
} else if box.prev == nil {
|
||||||
|
return nil;
|
||||||
|
} else if !(.Floating in box.prev.flags) {
|
||||||
|
return box.prev;
|
||||||
|
} else {
|
||||||
|
return prev_non_floating_sibling(ctx, box.prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compute_layout :: proc(ctx: ^Context, canvas_size: [2]int, font_width: int, font_height: int, box: ^Box) {
|
||||||
if box == nil { return; }
|
if box == nil { return; }
|
||||||
|
|
||||||
axis := Axis.Horizontal;
|
axis := Axis.Horizontal;
|
||||||
if box.parent != nil {
|
if box.parent != nil && !(.Floating in box.flags) {
|
||||||
axis = box.parent.axis;
|
axis = box.parent.axis;
|
||||||
box.computed_pos = box.parent.computed_pos;
|
box.computed_pos = box.parent.computed_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if box.prev != nil {
|
if .Floating in box.flags {
|
||||||
box.computed_pos[axis] = box.prev.computed_pos[axis] + box.prev.computed_size[axis];
|
// box.computed_pos = {0,0};
|
||||||
|
} else if box.prev != nil {
|
||||||
|
prev := prev_non_floating_sibling(ctx, box);
|
||||||
|
|
||||||
|
if prev != nil {
|
||||||
|
box.computed_pos[axis] = prev.computed_pos[axis] + prev.computed_size[axis];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post_compute_size := [2]bool { false, false };
|
||||||
compute_children := true;
|
compute_children := true;
|
||||||
if box == root {
|
if box == ctx.root {
|
||||||
box.computed_size = canvas_size;
|
box.computed_size = canvas_size;
|
||||||
} else {
|
} else {
|
||||||
switch box.semantic_size.x.kind {
|
switch box.semantic_size.x.kind {
|
||||||
|
@ -276,29 +349,30 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
box.computed_size.x = box.semantic_size.x.value;
|
box.computed_size.x = box.semantic_size.x.value;
|
||||||
}
|
}
|
||||||
case .ChildrenSum: {
|
case .ChildrenSum: {
|
||||||
compute_children = false;
|
//compute_children = false;
|
||||||
box.computed_size.x = 0;
|
post_compute_size[int(Axis.Horizontal)] = true;
|
||||||
|
// box.computed_size.x = 0;
|
||||||
|
|
||||||
iter := BoxIter { box.first, 0 };
|
// iter := BoxIter { box.first, 0 };
|
||||||
for child in iterate_box(&iter) {
|
// for child in iterate_box(&iter) {
|
||||||
compute_layout(canvas_size, font_width, font_height, child);
|
// compute_layout(canvas_size, font_width, font_height, child);
|
||||||
|
|
||||||
switch box.axis {
|
// switch box.axis {
|
||||||
case .Horizontal: {
|
// case .Horizontal: {
|
||||||
box.computed_size.x += child.computed_size.x;
|
// box.computed_size.x += child.computed_size.x;
|
||||||
}
|
// }
|
||||||
case .Vertical: {
|
// case .Vertical: {
|
||||||
if child.computed_size.x > box.computed_size.x {
|
// if child.computed_size.x > box.computed_size.x {
|
||||||
box.computed_size.x = child.computed_size.x;
|
// box.computed_size.x = child.computed_size.x;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
case .Fill: {
|
case .Fill: {
|
||||||
}
|
}
|
||||||
case .PercentOfParent: {
|
case .PercentOfParent: {
|
||||||
box.computed_size.x = int(f32(ancestor_size(box, .Horizontal))*(f32(box.semantic_size.x.value)/100.0));
|
box.computed_size.x = int(f32(ancestor_size(ctx, box, .Horizontal))*(f32(box.semantic_size.x.value)/100.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch box.semantic_size.y.kind {
|
switch box.semantic_size.y.kind {
|
||||||
|
@ -310,32 +384,34 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
box.computed_size.y = box.semantic_size.y.value;
|
box.computed_size.y = box.semantic_size.y.value;
|
||||||
}
|
}
|
||||||
case .ChildrenSum: {
|
case .ChildrenSum: {
|
||||||
compute_children = false;
|
//compute_children = false;
|
||||||
should_post_compute := false;
|
post_compute_size[Axis.Vertical] = true;
|
||||||
number_of_fills := 0;
|
|
||||||
box.computed_size.y = 0;
|
|
||||||
parent_size := ancestor_size(box, .Vertical);
|
|
||||||
|
|
||||||
iter := BoxIter { box.first, 0 };
|
// should_post_compute := false;
|
||||||
for child in iterate_box(&iter) {
|
// number_of_fills := 0;
|
||||||
compute_layout(canvas_size, font_width, font_height, child);
|
// box.computed_size.y = 0;
|
||||||
|
// parent_size := ancestor_size(box, .Vertical);
|
||||||
|
|
||||||
if child.semantic_size.y.kind == .Fill {
|
// iter := BoxIter { box.first, 0 };
|
||||||
number_of_fills += 1;
|
// for child in iterate_box(&iter) {
|
||||||
should_post_compute := true;
|
// compute_layout(canvas_size, font_width, font_height, child);
|
||||||
}
|
|
||||||
|
|
||||||
switch box.axis {
|
// if child.semantic_size.y.kind == .Fill {
|
||||||
case .Horizontal: {
|
// number_of_fills += 1;
|
||||||
if child.computed_size.y > box.computed_size.y {
|
// should_post_compute := true;
|
||||||
box.computed_size.y = child.computed_size.y;
|
// }
|
||||||
}
|
|
||||||
}
|
// switch box.axis {
|
||||||
case .Vertical: {
|
// case .Horizontal: {
|
||||||
box.computed_size.y += child.computed_size.y;
|
// if child.computed_size.y > box.computed_size.y {
|
||||||
}
|
// box.computed_size.y = child.computed_size.y;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// case .Vertical: {
|
||||||
|
// box.computed_size.y += child.computed_size.y;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// if should_post_compute {
|
// if should_post_compute {
|
||||||
// iter := BoxIter { box.first, 0 };
|
// iter := BoxIter { box.first, 0 };
|
||||||
|
@ -349,7 +425,7 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
case .Fill: {
|
case .Fill: {
|
||||||
}
|
}
|
||||||
case .PercentOfParent: {
|
case .PercentOfParent: {
|
||||||
box.computed_size.y = int(f32(ancestor_size(box, .Vertical))*(f32(box.semantic_size.y.value)/100.0));
|
box.computed_size.y = int(f32(ancestor_size(ctx, box, .Vertical))*(f32(box.semantic_size.y.value)/100.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,7 +445,9 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
our_size := box.computed_size;
|
our_size := box.computed_size;
|
||||||
|
|
||||||
for child in iterate_box(&iter) {
|
for child in iterate_box(&iter) {
|
||||||
compute_layout(canvas_size, font_width, font_height, child);
|
if .Floating in child.flags { continue; }
|
||||||
|
|
||||||
|
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
||||||
if child.semantic_size[box.axis].kind == .Fill {
|
if child.semantic_size[box.axis].kind == .Fill {
|
||||||
number_of_fills[box.axis] += 1;
|
number_of_fills[box.axis] += 1;
|
||||||
should_post_compute = true;
|
should_post_compute = true;
|
||||||
|
@ -378,12 +456,12 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if should_post_compute {
|
if true || should_post_compute {
|
||||||
iter := BoxIter { box.first, 0 };
|
iter := BoxIter { box.first, 0 };
|
||||||
for child in iterate_box(&iter) {
|
for child in iterate_box(&iter) {
|
||||||
for axis in 0..<2 {
|
for axis in 0..<2 {
|
||||||
if child.semantic_size[axis].kind == .Fill {
|
if child.semantic_size[axis].kind == .Fill {
|
||||||
if child_size[axis] >= our_size[axis] {
|
if false && child_size[axis] >= our_size[axis] {
|
||||||
child.computed_size[axis] = our_size[axis] / number_of_fills[axis];
|
child.computed_size[axis] = our_size[axis] / number_of_fills[axis];
|
||||||
} else {
|
} else {
|
||||||
child.computed_size[axis] = (our_size[axis] - child_size[axis]) / number_of_fills[axis];
|
child.computed_size[axis] = (our_size[axis] - child_size[axis]) / number_of_fills[axis];
|
||||||
|
@ -391,17 +469,56 @@ compute_layout :: proc(canvas_size: [2]int, font_width: int, font_height: int, b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_layout(canvas_size, font_width, font_height, child);
|
compute_layout(ctx, canvas_size, font_width, font_height, child);
|
||||||
|
|
||||||
|
if child.label == "2" {
|
||||||
|
fmt.println(child.label, child.computed_size, box.label, our_size, child_size, number_of_fills);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
push_clip :: proc(pos: [2]int, size: [2]int) {
|
if post_compute_size[Axis.Horizontal] {
|
||||||
|
box.computed_size[Axis.Horizontal] = 0;
|
||||||
|
|
||||||
|
iter := BoxIter { box.first, 0 };
|
||||||
|
for child in iterate_box(&iter) {
|
||||||
|
switch box.axis {
|
||||||
|
case .Horizontal: {
|
||||||
|
box.computed_size[Axis.Horizontal] += child.computed_size[Axis.Horizontal];
|
||||||
|
}
|
||||||
|
case .Vertical: {
|
||||||
|
if child.computed_size[Axis.Horizontal] > box.computed_size[Axis.Horizontal] {
|
||||||
|
box.computed_size[Axis.Horizontal] = child.computed_size[Axis.Horizontal];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if post_compute_size[Axis.Vertical] {
|
||||||
|
box.computed_size[Axis.Vertical] = 0;
|
||||||
|
|
||||||
|
iter := BoxIter { box.first, 0 };
|
||||||
|
for child in iterate_box(&iter) {
|
||||||
|
switch box.axis {
|
||||||
|
case .Horizontal: {
|
||||||
|
if child.computed_size[Axis.Vertical] > box.computed_size[Axis.Vertical] {
|
||||||
|
box.computed_size[Axis.Vertical] = child.computed_size[Axis.Vertical];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .Vertical: {
|
||||||
|
box.computed_size[Axis.Vertical] += child.computed_size[Axis.Vertical];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_clip :: proc(ctx: ^Context, pos: [2]int, size: [2]int) {
|
||||||
rect := Rect { pos, size };
|
rect := Rect { pos, size };
|
||||||
|
|
||||||
if len(clips) > 0 {
|
if len(ctx.clips) > 0 {
|
||||||
parent_rect := clips[len(clips)-1];
|
parent_rect := ctx.clips[len(ctx.clips)-1];
|
||||||
|
|
||||||
if rect.pos.x >= parent_rect.pos.x &&
|
if rect.pos.x >= parent_rect.pos.x &&
|
||||||
rect.pos.y >= parent_rect.pos.y &&
|
rect.pos.y >= parent_rect.pos.y &&
|
||||||
|
@ -421,72 +538,96 @@ push_clip :: proc(pos: [2]int, size: [2]int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
raylib.BeginScissorMode(
|
sdl2.RenderSetClipRect(ctx.renderer, &sdl2.Rect {
|
||||||
i32(rect.pos.x),
|
i32(rect.pos.x),
|
||||||
i32(rect.pos.y),
|
i32(rect.pos.y),
|
||||||
i32(rect.size.x),
|
i32(rect.size.x),
|
||||||
i32(rect.size.y)
|
i32(rect.size.y)
|
||||||
);
|
});
|
||||||
|
|
||||||
append(&clips, rect);
|
// raylib.BeginScissorMode(
|
||||||
|
// i32(rect.pos.x),
|
||||||
|
// i32(rect.pos.y),
|
||||||
|
// i32(rect.size.x),
|
||||||
|
// i32(rect.size.y)
|
||||||
|
// );
|
||||||
|
|
||||||
|
append(&ctx.clips, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_clip :: proc() {
|
pop_clip :: proc(ctx: ^Context) {
|
||||||
raylib.EndScissorMode();
|
//raylib.EndScissorMode();
|
||||||
|
|
||||||
if len(clips) > 0 {
|
if len(ctx.clips) > 0 {
|
||||||
rect := pop(&clips);
|
rect := pop(&ctx.clips);
|
||||||
|
|
||||||
raylib.BeginScissorMode(
|
sdl2.RenderSetClipRect(ctx.renderer, &sdl2.Rect {
|
||||||
i32(rect.pos.x),
|
i32(rect.pos.x),
|
||||||
i32(rect.pos.y),
|
i32(rect.pos.y),
|
||||||
i32(rect.size.x),
|
i32(rect.size.x),
|
||||||
i32(rect.size.y)
|
i32(rect.size.y)
|
||||||
);
|
});
|
||||||
|
// raylib.BeginScissorMode(
|
||||||
|
// i32(rect.pos.x),
|
||||||
|
// i32(rect.pos.y),
|
||||||
|
// i32(rect.size.x),
|
||||||
|
// i32(rect.size.y)
|
||||||
|
// );
|
||||||
|
} else {
|
||||||
|
sdl2.RenderSetClipRect(ctx.renderer, nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw :: proc(font: raylib.Font, font_width: int, font_height: int, box: ^Box = root) {
|
draw :: proc(ctx: ^Context, state: ^core.State, font_width: int, font_height: int, box: ^Box) {
|
||||||
if box == nil { return; }
|
if box == nil { return; }
|
||||||
|
|
||||||
// NOTE: for some reason if you place this right before the
|
// NOTE: for some reason if you place this right before the
|
||||||
// for loop, the clipping only works for the first child. Compiler bug?
|
// for loop, the clipping only works for the first child. Compiler bug?
|
||||||
push_clip(box.computed_pos, box.computed_size);
|
push_clip(ctx, box.computed_pos, box.computed_size);
|
||||||
defer pop_clip();
|
defer pop_clip(ctx);
|
||||||
|
|
||||||
if .DrawBorder in box.flags {
|
if .Hoverable in box.flags && box.hot > 0 {
|
||||||
raylib.DrawRectangleLines(
|
core.draw_rect(
|
||||||
i32(box.computed_pos.x),
|
state,
|
||||||
i32(box.computed_pos.y),
|
box.computed_pos.x,
|
||||||
i32(box.computed_size.x),
|
box.computed_pos.y,
|
||||||
i32(box.computed_size.y),
|
box.computed_size.x,
|
||||||
theme.get_palette_raylib_color(.Background4)
|
box.computed_size.y,
|
||||||
|
.Background2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if .DrawBackground in box.flags {
|
else if .DrawBackground in box.flags {
|
||||||
raylib.DrawRectangle(
|
core.draw_rect(
|
||||||
i32(box.computed_pos.x),
|
state,
|
||||||
i32(box.computed_pos.y),
|
box.computed_pos.x,
|
||||||
i32(box.computed_size.x),
|
box.computed_pos.y,
|
||||||
i32(box.computed_size.y),
|
box.computed_size.x,
|
||||||
theme.get_palette_raylib_color(.Background1)
|
box.computed_size.y,
|
||||||
|
.Background1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if .DrawBorder in box.flags {
|
||||||
|
core.draw_rect_outline(
|
||||||
|
state,
|
||||||
|
box.computed_pos.x,
|
||||||
|
box.computed_pos.y,
|
||||||
|
box.computed_size.x,
|
||||||
|
box.computed_size.y,
|
||||||
|
.Background4
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if .DrawText in box.flags {
|
if .DrawText in box.flags {
|
||||||
for codepoint, index in box.label {
|
core.draw_text(state, box.label, box.computed_pos.x, box.computed_pos.y);
|
||||||
raylib.DrawTextCodepoint(
|
|
||||||
font,
|
|
||||||
rune(codepoint),
|
|
||||||
raylib.Vector2 { f32(box.computed_pos.x + index * font_width), f32(box.computed_pos.y) },
|
|
||||||
f32(font_height),
|
|
||||||
theme.get_palette_raylib_color(.Foreground1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if .CustomDrawFunc in box.flags && box.custom_draw_func != nil {
|
||||||
|
box.custom_draw_func(state, box, box.user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
iter := BoxIter { box.first, 0 };
|
iter := BoxIter { box.first, 0 };
|
||||||
for child in iterate_box(&iter) {
|
for child in iterate_box(&iter) {
|
||||||
draw(font, font_width, font_height, child);
|
draw(ctx, state, font_width, font_height, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +650,7 @@ iterate_box :: proc(iter: ^BoxIter, print: bool = false) -> (box: ^Box, idx: int
|
||||||
return box, iter.index, true;
|
return box, iter.index, true;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_print :: proc(box: ^Box, depth: int = 0) {
|
debug_print :: proc(ctx: ^Context, box: ^Box, depth: int = 0) {
|
||||||
iter := BoxIter { box.first, 0 };
|
iter := BoxIter { box.first, 0 };
|
||||||
|
|
||||||
for box, idx in iterate_box(&iter, true) {
|
for box, idx in iterate_box(&iter, true) {
|
||||||
|
@ -520,50 +661,82 @@ debug_print :: proc(box: ^Box, depth: int = 0) {
|
||||||
fmt.print(">");
|
fmt.print(">");
|
||||||
}
|
}
|
||||||
fmt.println(idx, "Box", box.label, "#", box.key.label, "first", transmute(rawptr)box.first, "parent", transmute(rawptr)box.parent, box.computed_size);
|
fmt.println(idx, "Box", box.label, "#", box.key.label, "first", transmute(rawptr)box.first, "parent", transmute(rawptr)box.parent, box.computed_size);
|
||||||
debug_print(box, depth+1);
|
debug_print(ctx, box, depth+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
fmt.println("persistent");
|
fmt.println("persistent");
|
||||||
for p in persistent {
|
for p in ctx.persistent {
|
||||||
fmt.println(p);
|
fmt.println(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spacer :: proc(label: string) -> ^Box {
|
spacer :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {}, semantic_size: [2]SemanticSize = {{.Fill, 0}, {.Fill,0}}) -> Interaction {
|
||||||
return push_box(label, {}, semantic_size = {make_semantic_size(.Fill, 0), make_semantic_size(.Fill, 0)});
|
box := push_box(ctx, label, flags, semantic_size = semantic_size);
|
||||||
|
|
||||||
|
return test_box(ctx, box);
|
||||||
}
|
}
|
||||||
|
|
||||||
button :: proc(label: string) -> Interaction {
|
push_floating :: proc(ctx: ^Context, label: string, pos: [2]int, flags: bit_set[Flag] = {.Floating}, axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = Fill) -> ^Box {
|
||||||
box := push_box(label, {.Clickable, .Hoverable, .DrawText, .DrawBorder, .DrawBackground});
|
box := push_box(ctx, label, flags, semantic_size = semantic_size);
|
||||||
|
box.computed_pos = pos;
|
||||||
|
|
||||||
return test_box(box);
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
two_buttons_test :: proc(label1: string, label2: string) {
|
push_rect :: proc(ctx: ^Context, label: string, background: bool = true, border: bool = true, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> ^Box {
|
||||||
push_parent(push_box("two_button_container", {.DrawBorder}, .Vertical, semantic_size = ChildrenSum));
|
return push_box(ctx, label, {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, semantic_size = semantic_size);
|
||||||
|
}
|
||||||
|
|
||||||
button("1");
|
label :: proc(ctx: ^Context, label: string) -> Interaction {
|
||||||
button("2");
|
box := push_box(ctx, label, {.DrawText});
|
||||||
button(label1);
|
|
||||||
button(label2);
|
return test_box(ctx, box);
|
||||||
button("5");
|
}
|
||||||
button("6");
|
|
||||||
|
button :: proc(ctx: ^Context, label: string) -> Interaction {
|
||||||
|
box := push_box(ctx, label, {.Clickable, .Hoverable, .DrawText, .DrawBorder, .DrawBackground});
|
||||||
|
|
||||||
|
return test_box(ctx, box);
|
||||||
|
}
|
||||||
|
|
||||||
|
custom :: proc(ctx: ^Context, label: string, draw_func: CustomDrawFunc, user_data: rawptr) -> Interaction {
|
||||||
|
box := push_box(ctx, label, {.DrawBorder, .CustomDrawFunc}, semantic_size = { make_semantic_size(.Fill), make_semantic_size(.Fill) });
|
||||||
|
box.custom_draw_func = draw_func;
|
||||||
|
box.user_data = user_data;
|
||||||
|
|
||||||
|
return test_box(ctx, box);
|
||||||
|
}
|
||||||
|
|
||||||
|
two_buttons_test :: proc(ctx: ^Context, label1: string, label2: string) {
|
||||||
|
push_parent(ctx, push_box(ctx, "TWO BUTTONS TEST", {.DrawBorder}, .Vertical, semantic_size = {make_semantic_size(.PercentOfParent, 100), { .Fill, 256}}));
|
||||||
|
|
||||||
|
button(ctx, "Row 1");
|
||||||
|
button(ctx, "Row 2");
|
||||||
|
button(ctx, label1);
|
||||||
|
button(ctx, label2);
|
||||||
|
button(ctx, "Row 5");
|
||||||
|
button(ctx, "Row 6");
|
||||||
|
|
||||||
push_parent(push_box("two_button_container_inner", {.DrawBorder}, semantic_size = ChildrenSum));
|
|
||||||
button("second first button");
|
|
||||||
{
|
{
|
||||||
push_parent(push_box("two_button_container_inner", {.DrawBorder}, .Vertical, semantic_size = {make_semantic_size(.PercentOfParent, 50), { .Exact, 256}}));
|
push_parent(ctx, push_box(ctx, "two_button_container_inner", {.DrawBorder}, semantic_size = {make_semantic_size(.Fill, 0), { .Fill, 64}}));
|
||||||
defer pop_parent();
|
defer pop_parent(ctx);
|
||||||
|
|
||||||
button("first inner most button");
|
push_box(ctx, "1", {.DrawText, .DrawBackground, .DrawBorder}, semantic_size = {make_semantic_size(.Fill, 100), { .FitText, 256}})
|
||||||
button("inner_button2");
|
push_box(ctx, "2", {.DrawText, .DrawBackground, .DrawBorder}, semantic_size = {make_semantic_size(.Fill, 100), { .FitText, 256}})
|
||||||
button("inner_button3");
|
|
||||||
}
|
|
||||||
button("inner_button3");
|
|
||||||
|
|
||||||
pop_parent();
|
{
|
||||||
button("Help me I'm falling");
|
push_parent(ctx, push_box(ctx, "two_button_container_inner_inner", {.DrawBorder}, .Vertical, semantic_size = {make_semantic_size(.Fill, 50), { .ChildrenSum, 256}}));
|
||||||
pop_parent();
|
defer pop_parent(ctx);
|
||||||
|
|
||||||
|
button(ctx, "this is a test button");
|
||||||
|
button(ctx, "me in the middle");
|
||||||
|
button(ctx, "look at me, I'm a test button too");
|
||||||
|
}
|
||||||
|
|
||||||
|
push_box(ctx, "End", {.DrawBorder, .DrawBackground, .DrawText}, .Horizontal, semantic_size = {make_semantic_size(.Fill, 0), { .FitText, 0}})
|
||||||
|
}
|
||||||
|
button(ctx, "Help me I'm falling");
|
||||||
|
pop_parent(ctx);
|
||||||
}
|
}
|
||||||
|
|
289
src/ui/ui.odin
289
src/ui/ui.odin
|
@ -1,152 +1,151 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "vendor:raylib"
|
|
||||||
|
|
||||||
import "../core"
|
import "../core"
|
||||||
import "../theme"
|
import "../theme"
|
||||||
|
|
||||||
MenuBarItemOnClick :: proc(state: ^core.State, item: ^MenuBarItem);
|
// MenuBarItemOnClick :: proc(state: ^core.State, item: ^MenuBarItem);
|
||||||
|
//
|
||||||
text_padding :: 4;
|
// text_padding :: 4;
|
||||||
|
//
|
||||||
MenuBarItem :: struct {
|
// MenuBarItem :: struct {
|
||||||
text: string,
|
// text: string,
|
||||||
selected: bool,
|
// selected: bool,
|
||||||
sub_items: []MenuBarItem,
|
// sub_items: []MenuBarItem,
|
||||||
on_click: MenuBarItemOnClick,
|
// on_click: MenuBarItemOnClick,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
MenuBarState :: struct {
|
// MenuBarState :: struct {
|
||||||
items: []MenuBarItem,
|
// items: []MenuBarItem,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
draw_menu_bar_item :: proc(state: ^core.State, item: ^MenuBarItem, x, y: i32, parent_width, parent_height: i32, font_height: int, horizontal: bool = false) {
|
// draw_menu_bar_item :: proc(state: ^core.State, item: ^MenuBarItem, x, y: i32, parent_width, parent_height: i32, font_height: int, horizontal: bool = false) {
|
||||||
foreground_color := theme.PaletteColor.Foreground3;
|
// foreground_color := theme.PaletteColor.Foreground3;
|
||||||
if horizontal {
|
// if horizontal {
|
||||||
if item.selected {
|
// if item.selected {
|
||||||
foreground_color = theme.PaletteColor.Background4;
|
// foreground_color = theme.PaletteColor.Background4;
|
||||||
} else {
|
// } else {
|
||||||
foreground_color = theme.PaletteColor.Foreground4;
|
// foreground_color = theme.PaletteColor.Foreground4;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
item_text := raylib.TextFormat("%s", item.text);
|
// item_text := raylib.TextFormat("%s", item.text);
|
||||||
item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
||||||
|
//
|
||||||
raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(foreground_color));
|
// raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(foreground_color));
|
||||||
raylib.DrawTextEx(state.font, item_text, raylib.Vector2 { f32(x + text_padding), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Background1));
|
// raylib.DrawTextEx(state.font, item_text, raylib.Vector2 { f32(x + text_padding), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Background1));
|
||||||
|
//
|
||||||
if item.selected {
|
// if item.selected {
|
||||||
// TODO: change to parent_width
|
// // TODO: change to parent_width
|
||||||
largest_sub_item: int
|
// largest_sub_item: int
|
||||||
for sub_item in item.sub_items {
|
// for sub_item in item.sub_items {
|
||||||
largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
// largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
// this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
||||||
sub_list_x := x;
|
// sub_list_x := x;
|
||||||
if horizontal {
|
// if horizontal {
|
||||||
sub_list_x += parent_width;
|
// sub_list_x += parent_width;
|
||||||
}
|
// }
|
||||||
for _, index in item.sub_items {
|
// for _, index in item.sub_items {
|
||||||
sub_item := &item.sub_items[index];
|
// sub_item := &item.sub_items[index];
|
||||||
item_text := raylib.TextFormat("%s", sub_item.text);
|
// item_text := raylib.TextFormat("%s", sub_item.text);
|
||||||
item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
||||||
|
//
|
||||||
index_offset := 1;
|
// index_offset := 1;
|
||||||
if horizontal {
|
// if horizontal {
|
||||||
index_offset = 0;
|
// index_offset = 0;
|
||||||
}
|
// }
|
||||||
item_y := y + i32(font_height * (index+index_offset));
|
// item_y := y + i32(font_height * (index+index_offset));
|
||||||
draw_menu_bar_item(state, sub_item, sub_list_x, item_y, this_width, 0, font_height, true);
|
// draw_menu_bar_item(state, sub_item, sub_list_x, item_y, this_width, 0, font_height, true);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
draw_menu_bar :: proc(state: ^core.State, data: ^MenuBarState, x, y: i32, parent_width, parent_height: i32, font_height: int) {
|
// draw_menu_bar :: proc(state: ^core.State, data: ^MenuBarState, x, y: i32, parent_width, parent_height: i32, font_height: int) {
|
||||||
raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(.Background3));
|
// raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(.Background3));
|
||||||
|
//
|
||||||
raylib.DrawTextEx(state.font, "Editor", raylib.Vector2 { f32(x), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Foreground1));
|
// raylib.DrawTextEx(state.font, "Editor", raylib.Vector2 { f32(x), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Foreground1));
|
||||||
|
//
|
||||||
x := x + i32((len("Editor") + 4) * state.source_font_width);
|
// x := x + i32((len("Editor") + 4) * state.source_font_width);
|
||||||
|
//
|
||||||
for _, index in data.items {
|
// for _, index in data.items {
|
||||||
item := &data.items[index];
|
// item := &data.items[index];
|
||||||
item_text := raylib.TextFormat("%s", item.text);
|
// item_text := raylib.TextFormat("%s", item.text);
|
||||||
item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
||||||
|
//
|
||||||
item_x := x + (i32(item_width) + text_padding*2) * i32(index);
|
// item_x := x + (i32(item_width) + text_padding*2) * i32(index);
|
||||||
draw_menu_bar_item(state, item, item_x, y, i32(item_width + text_padding*2), i32(font_height), font_height);
|
// draw_menu_bar_item(state, item, item_x, y, i32(item_width + text_padding*2), i32(font_height), font_height);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
test_menu_item :: proc(state: ^core.State, item: ^MenuBarItem, rect: raylib.Rectangle, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int, horizontal: bool) -> bool {
|
// test_menu_item :: proc(state: ^core.State, item: ^MenuBarItem, rect: raylib.Rectangle, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int, horizontal: bool) -> bool {
|
||||||
if raylib.CheckCollisionPointRec(mouse_pos, rect) {
|
// if raylib.CheckCollisionPointRec(mouse_pos, rect) {
|
||||||
item.selected = true;
|
// item.selected = true;
|
||||||
|
//
|
||||||
if item.on_click != nil && mouse_has_clicked {
|
// if item.on_click != nil && mouse_has_clicked {
|
||||||
item.on_click(state, item);
|
// item.on_click(state, item);
|
||||||
}
|
// }
|
||||||
} else if item.selected {
|
// } else if item.selected {
|
||||||
largest_sub_item: int
|
// largest_sub_item: int
|
||||||
for sub_item in item.sub_items {
|
// for sub_item in item.sub_items {
|
||||||
largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
// largest_sub_item = math.max(len(sub_item.text), largest_sub_item);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
// this_width := i32(largest_sub_item * state.source_font_width + text_padding*2);
|
||||||
sub_list_x := rect.x;
|
// sub_list_x := rect.x;
|
||||||
if horizontal {
|
// if horizontal {
|
||||||
sub_list_x += rect.width;
|
// sub_list_x += rect.width;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
has_sub_item_selected := false;
|
// has_sub_item_selected := false;
|
||||||
for _, index in item.sub_items {
|
// for _, index in item.sub_items {
|
||||||
sub_item := &item.sub_items[index];
|
// sub_item := &item.sub_items[index];
|
||||||
item_text := raylib.TextFormat("%s", sub_item.text);
|
// item_text := raylib.TextFormat("%s", sub_item.text);
|
||||||
item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
||||||
|
//
|
||||||
index_offset := 1;
|
// index_offset := 1;
|
||||||
if horizontal {
|
// if horizontal {
|
||||||
index_offset = 0;
|
// index_offset = 0;
|
||||||
}
|
// }
|
||||||
item_y := rect.y + f32(font_height * (index+index_offset));
|
// item_y := rect.y + f32(font_height * (index+index_offset));
|
||||||
|
//
|
||||||
sub_rec := raylib.Rectangle {
|
// sub_rec := raylib.Rectangle {
|
||||||
x = sub_list_x,
|
// x = sub_list_x,
|
||||||
y = item_y,
|
// y = item_y,
|
||||||
width = f32(this_width),
|
// width = f32(this_width),
|
||||||
height = f32(font_height),
|
// height = f32(font_height),
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
if test_menu_item(state, sub_item, sub_rec, mouse_pos, mouse_has_clicked, font_height, true) {
|
// if test_menu_item(state, sub_item, sub_rec, mouse_pos, mouse_has_clicked, font_height, true) {
|
||||||
has_sub_item_selected = true;
|
// has_sub_item_selected = true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
item.selected = has_sub_item_selected;
|
// item.selected = has_sub_item_selected;
|
||||||
} else {
|
// } else {
|
||||||
item.selected = false;
|
// item.selected = false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return item.selected;
|
// return item.selected;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
test_menu_bar :: proc(state: ^core.State, menu_bar: ^MenuBarState, x, y: i32, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int) {
|
// test_menu_bar :: proc(state: ^core.State, menu_bar: ^MenuBarState, x, y: i32, mouse_pos: raylib.Vector2, mouse_has_clicked: bool, font_height: int) {
|
||||||
x := x + i32((len("Editor") + 4) * state.source_font_width);
|
// x := x + i32((len("Editor") + 4) * state.source_font_width);
|
||||||
|
//
|
||||||
for _, index in menu_bar.items {
|
// for _, index in menu_bar.items {
|
||||||
item := &menu_bar.items[index];
|
// item := &menu_bar.items[index];
|
||||||
item_text := raylib.TextFormat("%s", item.text);
|
// item_text := raylib.TextFormat("%s", item.text);
|
||||||
item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
// item_width := raylib.MeasureTextEx(state.font, item_text, f32(font_height), 0).x;
|
||||||
|
//
|
||||||
item_rec := raylib.Rectangle {
|
// item_rec := raylib.Rectangle {
|
||||||
x = f32(x) + (item_width + f32(text_padding*2)) * f32(index),
|
// x = f32(x) + (item_width + f32(text_padding*2)) * f32(index),
|
||||||
y = f32(y),
|
// y = f32(y),
|
||||||
width = f32(item_width + text_padding*2),
|
// width = f32(item_width + text_padding*2),
|
||||||
height = f32(font_height),
|
// height = f32(font_height),
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
test_menu_item(state, item, item_rec, mouse_pos, mouse_has_clicked, font_height, false);
|
// test_menu_item(state, item, item_rec, mouse_pos, mouse_has_clicked, font_height, false);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
Loading…
Reference in New Issue