diff --git a/.gitignore b/.gitignore index 1adec08..20b13c9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ _build *.log *.install default.profraw +.vscode diff --git a/renderer-macos/lib/Brisk_macos.re b/renderer-macos/lib/Brisk_macos.re index 0ee1a71..8bcea80 100644 --- a/renderer-macos/lib/Brisk_macos.re +++ b/renderer-macos/lib/Brisk_macos.re @@ -12,6 +12,7 @@ module Cocoa = { module BriskButton = BriskButton; module BriskImage = BriskImage; module BriskTextView = BriskTextView; + module BriskTextInput = BriskTextInput; module GCD = GCD; module BriskEffectView = BriskEffectView; @@ -24,3 +25,4 @@ module Text = Text; module Image = Image; module Button = Button; module EffectView = EffectView; +module TextInput = TextInput; diff --git a/renderer-macos/lib/bindings/BriskTextInput.re b/renderer-macos/lib/bindings/BriskTextInput.re new file mode 100644 index 0000000..045f744 --- /dev/null +++ b/renderer-macos/lib/bindings/BriskTextInput.re @@ -0,0 +1,52 @@ +type t = CocoaTypes.view; + +[@noalloc] external make: unit => t = "ml_BriskTextInput_make"; + +[@noalloc] +external getTextWidth: t => [@unboxed] float = + "ml_BriskTextInput_getTextWidth_bc" "ml_BriskTextInput_getTextWidth"; + +[@noalloc] +external getTextHeight: t => [@unboxed] float = + "ml_BriskTextInput_getTextHeight_bc" "ml_BriskTextInput_getTextHeight"; + +[@noalloc] +external setStringValue: (t, string) => unit = + "ml_BriskTextInput_setStringValue"; + +[@noalloc] +external setPlaceholder: (t, string) => unit = + "ml_BriskTextInput_setPlaceholder"; + +[@noalloc] +external setBackgroundColor: + ( + t, + [@unboxed] float, + [@unboxed] float, + [@unboxed] float, + [@unboxed] float + ) => + unit = + "ml_BriskTextInput_setBackgroundColor_bc" + "ml_BriskTextInput_setBackgroundColor"; + +[@noalloc] +external setPadding: + ( + t, + [@unboxed] float, + [@unboxed] float, + [@unboxed] float, + [@unboxed] float + ) => + unit = + "ml_BriskTextInput_setPadding_bc" "ml_BriskTextInput_setPadding"; + +let make = (value, placeholder) => { + let input = make(); + + setStringValue(input, value); + setPlaceholder(input, placeholder); + input; +}; diff --git a/renderer-macos/lib/components/TextInput.re b/renderer-macos/lib/components/TextInput.re new file mode 100644 index 0000000..4cbd9d9 --- /dev/null +++ b/renderer-macos/lib/components/TextInput.re @@ -0,0 +1,49 @@ +open Brisk; + +type attribute = [ Layout.style | Styles.textStyle | Styles.viewStyle]; + +type style = list(attribute); + +let component = nativeComponent("Text"); + +let measure = (node, _, _, _, _) => { + open Layout.FlexLayout.LayoutSupport.LayoutTypes; + + let {context: input}: node = node; + + let width = BriskTextInput.getTextWidth(input) |> int_of_float; + let height = BriskTextInput.getTextHeight(input) |> int_of_float; + + {width, height}; +}; + +let make = (~style=[], ~value, ~placeholder, children) => + component((_: Hooks.empty) => + { + make: () => { + let view = BriskTextInput.make(value, placeholder); + {view, layoutNode: Layout.Node.make(~measure, ~style, view)}; + }, + configureInstance: (~isFirstRender as _, {view} as node) => { + open Layout; + style + |> List.iter(attribute => + switch (attribute) { + | `Padding({left, top, right, bottom}) => + BriskTextInput.setPadding(view, left, top, right, bottom) + | `Background(({r, g, b, a}: Color.t)) => + BriskTextInput.setBackgroundColor(view, r, g, b, a) + | #Styles.textStyle => Styles.setTextStyle(view, attribute) + | #Styles.viewStyle => Styles.setViewStyle(view, attribute) + | #Layout.style => () + } + ); + Styles.commitTextStyle(view); + node; + }, + children, + } + ); + +let createElement = (~style=[], ~value, ~placeholder, ~children, ()) => + element(make(~style, ~value, ~placeholder, listToElement(children))); diff --git a/renderer-macos/lib/dune b/renderer-macos/lib/dune index 4e42776..8248fa6 100644 --- a/renderer-macos/lib/dune +++ b/renderer-macos/lib/dune @@ -25,6 +25,7 @@ BriskButton GCD BriskEffectView + BriskTextInput ) (c_flags (:standard -Wextra -Wall -Werror -O -g -std=c99 -pedantic-errors -Wsign-compare -Wshadow diff --git a/renderer-macos/lib/stubs/BriskTextInput.c b/renderer-macos/lib/stubs/BriskTextInput.c new file mode 100644 index 0000000..709b01e --- /dev/null +++ b/renderer-macos/lib/stubs/BriskTextInput.c @@ -0,0 +1,130 @@ +#import "BriskTextInput.h" + +@interface BriskTextInput : NSTextView + +@end + +@implementation BriskTextInput + +@synthesize attributedString; +@synthesize attributedProps; +@synthesize paragraphStyle; +@synthesize placeholder; + +- (id)init { + self = [super init]; + if (self) { + self.attributedString = [[NSMutableAttributedString alloc] init]; + self.attributedProps = [NSMutableDictionary dictionary]; + self.paragraphStyle = + [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + + self.attributedProps[NSParagraphStyleAttributeName] = self.paragraphStyle; + self.placeholder = [[NSMutableAttributedString alloc] init]; + } + return self; +} + +- (BOOL)isEditable { + return YES; +} + +- (BOOL)isSelectable { + return YES; +} + +- (void)applyTextStyle { + NSRange range = NSMakeRange(0, self.attributedString.length); + + [self.attributedString setAttributes:self.attributedProps range:range]; + [[self textStorage] setAttributedString:self.attributedString]; +} + +@end + +BriskTextInput *ml_BriskTextInput_make() { + BriskTextInput *input = [BriskTextInput new]; + retainView(input); + + return input; +} + +double ml_BriskTextInput_getTextWidth(BriskTextInput *input) { + return (double)[input.attributedString size].width; +} + +double ml_BriskTextInput_getTextHeight(BriskTextInput *input) { + return (double)[input.attributedString size].height; +} + +CAMLprim value ml_BriskTextInput_getTextWidth_bc(BriskTextInput *input) { + CAMLparam0(); + CAMLreturn(caml_copy_double(ml_BriskTextInput_getTextWidth(input))); +} + +CAMLprim value ml_BriskTextInput_getTextHeight_bc(BriskTextInput *input) { + CAMLparam0(); + CAMLreturn(caml_copy_double(ml_BriskTextInput_getTextHeight(input))); +} + +CAMLprim value ml_BriskTextInput_setStringValue(BriskTextInput *input, + value str_v) { + CAMLparam1(str_v); + + NSString *str = [NSString stringWithUTF8String:String_val(str_v)]; + + [input.attributedString.mutableString setString:str]; + [input applyTextStyle]; + + CAMLreturn(Val_unit); +} + +CAMLprim value ml_BriskTextInput_setPlaceholder(BriskTextInput *input, + value str_v) { + CAMLparam1(str_v); + + NSString *str = [NSString stringWithUTF8String:String_val(str_v)]; + + [input.placeholder.mutableString setString:str]; + [input applyTextStyle]; + + CAMLreturn(Val_unit); +} + +void ml_BriskTextInput_setBackgroundColor(BriskTextInput *input, double red, + double green, double blue, + double alpha) { + NSColor *color = [NSColor colorWithRed:red green:green blue:blue alpha:alpha]; + [input setBackgroundColor:color]; +} + +CAMLprim value ml_BriskTextInput_setBackgroundColor_bc(BriskTextInput *input, + value red_v, + value green_v, + value blue_v, + value alpha_v) { + CAMLparam4(red_v, blue_v, green_v, alpha_v); + + ml_BriskTextInput_setBackgroundColor(input, Double_val(red_v), + Double_val(blue_v), Double_val(green_v), + Double_val(alpha_v)); + + CAMLreturn(Val_unit); +} + +void ml_BriskTextInput_setPadding(BriskTextInput *input, double left, double top, + __unused double right, + __unused double bottom) { + input.textContainerInset = CGSizeMake(left, top); +} + +CAMLprim value ml_BriskTextInput_setPadding_bc(BriskTextInput *input, value left_v, + value top_v, value right_v, + value bottom_v) { + CAMLparam4(left_v, top_v, right_v, bottom_v); + + ml_BriskTextInput_setPadding(input, Double_val(left_v), Double_val(top_v), + Double_val(right_v), Double_val(bottom_v)); + + CAMLreturn(Val_unit); +} diff --git a/renderer-macos/lib/stubs/BriskTextInput.h b/renderer-macos/lib/stubs/BriskTextInput.h new file mode 100644 index 0000000..a08f11b --- /dev/null +++ b/renderer-macos/lib/stubs/BriskTextInput.h @@ -0,0 +1,12 @@ +#import "BriskCocoa.h" + +@protocol BriskTextInputProtocol + +@property(nonatomic, retain) NSMutableAttributedString *attributedString; +@property(nonatomic, retain) NSMutableDictionary *attributedProps; +@property(nonatomic, retain) NSMutableParagraphStyle *paragraphStyle; +@property(nonatomic, retain) NSMutableAttributedString *placeholder; + +- (void)applyTextStyle; + +@end