diff --git a/spago.lock b/spago.lock index 26f6df4..f396f9a 100644 --- a/spago.lock +++ b/spago.lock @@ -12,6 +12,7 @@ workspace: - nullable - prelude - record + - record-studio - untagged-union - web-encoding test_dependencies: [] @@ -38,6 +39,7 @@ workspace: - functions - functors - gen + - heterogeneous - identity - integers - invariant @@ -59,6 +61,7 @@ workspace: - profunctor - psci-support - record + - record-studio - refs - safe-coerce - st @@ -71,6 +74,7 @@ workspace: - unfoldable - unsafe-coerce - untagged-union + - variant - web-encoding package_set: address: @@ -812,6 +816,17 @@ packages: - tailrec - tuples - unfoldable + heterogeneous: + type: registry + version: 0.6.0 + integrity: sha256-cfNYSK6yYmjTrkzk95Otpv6TUUkeBreexwqG/tBvUyg= + dependencies: + - either + - functors + - prelude + - record + - tuples + - variant identity: type: registry version: 6.0.0 @@ -1013,6 +1028,16 @@ packages: - functions - prelude - unsafe-coerce + record-studio: + type: registry + version: 1.0.4 + integrity: sha256-9v6qpUrGa17Im/F/vWODjKlmD3ZuUXYIKCpz5OI9seM= + dependencies: + - heterogeneous + - lists + - prelude + - record + - typelevel-prelude refs: type: registry version: 6.0.0 @@ -1139,6 +1164,19 @@ packages: - psci-support - tuples - unsafe-coerce + variant: + type: registry + version: 8.0.0 + integrity: sha256-SR//zQDg2dnbB8ZHslcxieUkCeNlbMToapvmh9onTtw= + dependencies: + - enums + - lists + - maybe + - partial + - prelude + - record + - tuples + - unsafe-coerce web-encoding: type: registry version: 3.0.0 diff --git a/spago.yaml b/spago.yaml index 1de265e..0172989 100644 --- a/spago.yaml +++ b/spago.yaml @@ -10,6 +10,7 @@ package: - nullable - prelude - record + - record-studio - untagged-union - web-encoding test: diff --git a/src/AGS/Binding.purs b/src/AGS/Binding.purs index 2cb2f19..a144cde 100644 --- a/src/AGS/Binding.purs +++ b/src/AGS/Binding.purs @@ -1,33 +1,27 @@ module AGS.Binding ( Binding - , SelfOrBinding , class BindProp , bindProp , unsafeBindProp + , ValueOrBinding + , overValue + , overBinding + , overBoth ) where import Prelude import Control.Apply (lift2) +import Data.Either (either) import Data.Symbol (class IsSymbol, reflectSymbol) import Type.Proxy (Proxy(..)) -import Untagged.Union (OneOf) +import Untagged.TypeCheck (class HasRuntimeType) +import Untagged.Union (OneOf, asOneOf, toEither1) foreign import data Binding ∷ Type → Type type role Binding representational -type SelfOrBinding a = OneOf a (Binding a) - -class BindProp ∷ ∀ k. Type → k → Type → Constraint -class BindProp o p t | o p → t where - bindProp ∷ o → Binding t - -unsafeBindProp ∷ ∀ @p @o @t. IsSymbol p ⇒ BindProp o p t ⇒ o → Binding t -unsafeBindProp = unsafeBindPropImpl (reflectSymbol (Proxy @p)) - -foreign import unsafeBindPropImpl ∷ ∀ o t. String → o → Binding t - -- | Transform the value streamed in a `Binding`. instance Functor Binding where map = transform @@ -62,3 +56,46 @@ foreign import applyBinding ∷ ∀ a b. Binding (a → b) → Binding a → Bin foreign import pureBinding ∷ ∀ a. a → Binding a foreign import bindBinding ∷ ∀ a b. Binding a → (a → Binding b) → Binding b +class BindProp ∷ ∀ k. Type → k → Type → Constraint +class BindProp o p t | o p → t where + bindProp ∷ o → Binding t + +unsafeBindProp ∷ ∀ @p @o @t. IsSymbol p ⇒ BindProp o p t ⇒ o → Binding t +unsafeBindProp = unsafeBindPropImpl (reflectSymbol (Proxy @p)) + +foreign import unsafeBindPropImpl ∷ ∀ o t. String → o → Binding t + +-- * ValueOrBinding + +type ValueOrBinding a = OneOf a (Binding a) + +-- | Transform a *value* inside a `ValueOrBinding`. +-- | If `ValueOrBinding` is a binding, it stays unmodified. +overValue + ∷ ∀ a + . HasRuntimeType a + ⇒ (a → a) + → ValueOrBinding a + → ValueOrBinding a +overValue = flip overBoth identity + +-- | Transform a *binding* inside a `ValueOrBinding`. +-- | If `ValueOrBinding` is a plain value, it stays unmodified. +overBinding + ∷ ∀ a + . HasRuntimeType a + ⇒ (Binding a → Binding a) + → ValueOrBinding a + → ValueOrBinding a +overBinding = overBoth identity + +-- | Transform both a plain value and a binding in `ValueOrBinding`. +overBoth + ∷ ∀ a b + . HasRuntimeType a + ⇒ (a → b) + → (Binding a → Binding b) + → ValueOrBinding a + → ValueOrBinding b +overBoth f g sob = either (asOneOf <<< f) (asOneOf <<< g) $ toEither1 sob + diff --git a/src/AGS/Widget.js b/src/AGS/Widget.js new file mode 100644 index 0000000..9084aba --- /dev/null +++ b/src/AGS/Widget.js @@ -0,0 +1,10 @@ +export const grabFocus = + widget => () => + widget.grab_focus() + +export const withInterval = + interval => handler => widget => () => + { widget.poll(interval, _ => handler()) + return + } + diff --git a/src/AGS/Widget.purs b/src/AGS/Widget.purs index 074f0c4..836980c 100644 --- a/src/AGS/Widget.purs +++ b/src/AGS/Widget.purs @@ -1,46 +1,86 @@ -module AGS.Widget (module Exports) where +module AGS.Widget + ( grabFocus + , withInterval + , module Exports + ) where -import AGS.Binding (Binding, SelfOrBinding, bindProp) as Exports -import AGS.Widget.Box (BoxProps, box) as Exports -import AGS.Widget.Button (ButtonProps, button, buttonImpl) as Exports -import AGS.Widget.CenterBox (CenterBoxProps, centerBox) as Exports -import AGS.Widget.CircularProgress (CircularProgressProps, circularProgress) as Exports -import AGS.Widget.Entry (EntryProps, entry) as Exports -import AGS.Widget.EventBox (EventBoxProps, eventBox) as Exports -import AGS.Widget.Icon (IconProps, icon) as Exports +import AGS.Binding + ( class BindProp + , Binding + , ValueOrBinding + , bindProp + , overBinding + , overBoth + , overValue + ) as Exports +import AGS.Widget.Box (BoxProps, UpdateBoxProps, box, box') as Exports +import AGS.Widget.Button (ButtonProps, UpdateButtonProps, button, button') as Exports +import AGS.Widget.CenterBox + ( CenterBoxProps + , UpdateCenterBoxProps + , centerBox + , centerBox' + ) as Exports +import AGS.Widget.CircularProgress + ( CircularProgressProps + , UpdateCircularProgressProps + , circularProgress + , circularProgress' + ) as Exports +import AGS.Widget.Entry (EntryProps, UpdateEntryProps, entry, entry') as Exports +import AGS.Widget.EventBox + ( EventBoxProps + , UpdateEventBoxProps + , eventBox + , eventBox' + ) as Exports +import AGS.Widget.Icon (IconProps, UpdateIconProps, icon, icon') as Exports import AGS.Widget.Internal ( AGSWidgetProps , Any , AnyF - , grabFocus , mkAny - , unsafeSetProperty - , withInterval + , unsafeWidgetUpdate ) as Exports -import AGS.Widget.Label (LabelProps, label) as Exports -import AGS.Widget.Menu (MenuProps, menu) as Exports +import AGS.Widget.Label (LabelProps, label, label') as Exports +import AGS.Widget.Menu (MenuProps, UpdateMenuProps, menu, menu') as Exports import AGS.Widget.Menu.Item (MenuItem, MenuItemProps, menuItem, menuItemImpl) as Exports -import AGS.Widget.Overlay (OverlayProps, overlay) as Exports -import AGS.Widget.ProgressBar (ProgressBarProps, progressBar) as Exports +import AGS.Widget.Overlay (OverlayProps, UpdateOverlayProps, overlay, overlay') as Exports +import AGS.Widget.ProgressBar + ( ProgressBarProps + , UpdateProgressBarProps + , progressBar + , progressBar' + ) as Exports import AGS.Widget.Revealer ( GtkRevealerTransitionType , RevealerProps + , UpdateRevealerProps , revealer + , revealer' , transitions ) as Exports -import AGS.Widget.Scrollable (ScrollableProps, scrollable) as Exports +import AGS.Widget.Scrollable + ( ScrollableProps + , UpdateScrollableProps + , scrollable + , scrollable' + ) as Exports import AGS.Widget.Slider ( Mark , MarkPosition , SliderProps + , UpdateSliderProps , markPositionBottom , markPositionLeft , markPositionRight , markPositionTop , slider + , slider' ) as Exports -import AGS.Widget.Stack (StackProps, stack) as Exports +import AGS.Widget.Stack (StackProps, stack, stack') as Exports import AGS.Widget.Window (Window, WindowProps, window) as Exports +import Effect (Effect) import Effect.Uncurried ( EffectFn1 , EffectFn2 @@ -50,10 +90,14 @@ import Effect.Uncurried , mkEffectFn2 , mkEffectFn3 , mkEffectFn4 - , runEffectFn1 - , runEffectFn2 - , runEffectFn3 - , runEffectFn4 ) as Exports -import Untagged.Union (UndefinedOr, asOneOf) as Exports +import Gtk.Widget (Widget) +import Gtk.Widget (Widget) as Exports +import Prelude (Unit) +import Untagged.Union (asOneOf) as Exports + +-- * Methods + +foreign import grabFocus ∷ Widget → Effect Unit +foreign import withInterval ∷ Int → Effect Unit → Widget → Effect Unit diff --git a/src/AGS/Widget/Box.purs b/src/AGS/Widget/Box.purs index 798bf04..541ee2d 100644 --- a/src/AGS/Widget/Box.purs +++ b/src/AGS/Widget/Box.purs @@ -1,15 +1,23 @@ module AGS.Widget.Box ( BoxProps + , UpdateBoxProps , box + , box' ) where -import AGS.Binding (SelfOrBinding) -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Binding (ValueOrBinding) +import AGS.Widget.Internal + ( AGSWidgetProps + , unsafeWidgetUpdate + ) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Box (GtkBoxProps) import Gtk.Container (GtkContainerProps) import Gtk.Orientable (GtkOrientableProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -21,7 +29,7 @@ type BoxProps r = + GtkBoxProps + ( vertical ∷ Boolean - , children ∷ SelfOrBinding (Array Widget) + , children ∷ ValueOrBinding (Array Widget) | r ) @@ -30,3 +38,17 @@ box = boxImpl <<< unsafeCoerce foreign import boxImpl ∷ Record (BoxProps ()) → Widget +type UpdateBoxProps = Record (BoxProps ()) → Record (BoxProps ()) + +box' + ∷ ∀ r r' + . Union r r' (BoxProps ()) + ⇒ Record r + → Widget /\ (UpdateBoxProps → Effect Unit) +box' props = + let + widget = box props + update = unsafeWidgetUpdate @(BoxProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Button.purs b/src/AGS/Widget/Button.purs index 36ac2f1..cd12c49 100644 --- a/src/AGS/Widget/Button.purs +++ b/src/AGS/Widget/Button.purs @@ -1,9 +1,15 @@ -module AGS.Widget.Button where +module AGS.Widget.Button + ( ButtonProps + , UpdateButtonProps + , button + , button' + ) where import Prelude -import AGS.Binding (SelfOrBinding) -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Binding (ValueOrBinding) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Gtk.Button (GtkButtonProps) import Gtk.Container (GtkContainerProps) @@ -17,7 +23,7 @@ type ButtonProps r = + GtkContainerProps + GtkButtonProps + - ( child ∷ SelfOrBinding Widget + ( child ∷ ValueOrBinding Widget , onClicked ∷ Effect Unit , onPrimaryClick ∷ Effect Unit , onSecondaryClick ∷ Effect Unit @@ -37,3 +43,17 @@ button = buttonImpl <<< unsafeCoerce foreign import buttonImpl ∷ Record (ButtonProps ()) → Widget +type UpdateButtonProps = Record (ButtonProps ()) → Record (ButtonProps ()) + +button' + ∷ ∀ r r' + . Union r r' (ButtonProps ()) + ⇒ Record r + → Widget /\ (UpdateButtonProps → Effect Unit) +button' props = + let + widget = button props + update = unsafeWidgetUpdate @(ButtonProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/CenterBox.purs b/src/AGS/Widget/CenterBox.purs index 00dae54..e2aa72f 100644 --- a/src/AGS/Widget/CenterBox.purs +++ b/src/AGS/Widget/CenterBox.purs @@ -1,20 +1,26 @@ module AGS.Widget.CenterBox ( CenterBoxProps + , UpdateCenterBoxProps , centerBox + , centerBox' ) where -import AGS.Binding (SelfOrBinding) +import Prelude + +import AGS.Binding (ValueOrBinding) import AGS.Widget.Box (BoxProps) +import AGS.Widget.Internal (unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Unsafe.Coerce (unsafeCoerce) type CenterBoxProps r = BoxProps - ( startWidget ∷ SelfOrBinding Widget - , centerWidget ∷ SelfOrBinding Widget - , endWidget ∷ SelfOrBinding Widget + ( startWidget ∷ ValueOrBinding Widget + , centerWidget ∷ ValueOrBinding Widget + , endWidget ∷ ValueOrBinding Widget | r ) @@ -27,3 +33,18 @@ centerBox = centerBoxImpl <<< unsafeCoerce foreign import centerBoxImpl ∷ Record (CenterBoxProps ()) → Widget +type UpdateCenterBoxProps = + Record (CenterBoxProps ()) → Record (CenterBoxProps ()) + +centerBox' + ∷ ∀ r r' + . Union r r' (CenterBoxProps ()) + ⇒ Record r + → Widget /\ (UpdateCenterBoxProps → Effect Unit) +centerBox' props = + let + widget = centerBox props + update = unsafeWidgetUpdate @(CenterBoxProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/CircularProgress.purs b/src/AGS/Widget/CircularProgress.purs index 8f967ee..e3542f2 100644 --- a/src/AGS/Widget/CircularProgress.purs +++ b/src/AGS/Widget/CircularProgress.purs @@ -1,12 +1,17 @@ module AGS.Widget.CircularProgress ( CircularProgressProps + , UpdateCircularProgressProps , circularProgress + , circularProgress' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Container (GtkContainerProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -29,3 +34,18 @@ circularProgress = circularProgressImpl <<< unsafeCoerce foreign import circularProgressImpl ∷ Record (CircularProgressProps ()) → Widget +type UpdateCircularProgressProps = + Record (CircularProgressProps ()) → Record (CircularProgressProps ()) + +circularProgress' + ∷ ∀ r r' + . Union r r' (CircularProgressProps ()) + ⇒ Record r + → Widget /\ (UpdateCircularProgressProps → Effect Unit) +circularProgress' props = + let + widget = circularProgress props + update = unsafeWidgetUpdate @(CircularProgressProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Entry.purs b/src/AGS/Widget/Entry.purs index 39edb5d..365a5fe 100644 --- a/src/AGS/Widget/Entry.purs +++ b/src/AGS/Widget/Entry.purs @@ -1,11 +1,15 @@ module AGS.Widget.Entry ( EntryProps + , UpdateEntryProps , entry + , entry' ) where import Prelude -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Effect.Uncurried (EffectFn1) import Gtk.Entry (GtkEntryProps) import Gtk.Widget (Widget) @@ -27,3 +31,17 @@ entry = entryImpl <<< unsafeCoerce foreign import entryImpl ∷ Record (EntryProps ()) → Widget +type UpdateEntryProps = Record (EntryProps ()) → Record (EntryProps ()) + +entry' + ∷ ∀ r r' + . Union r r' (EntryProps ()) + ⇒ Record r + → Widget /\ (UpdateEntryProps → Effect Unit) +entry' props = + let + widget = entry props + update = unsafeWidgetUpdate @(EntryProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/EventBox.purs b/src/AGS/Widget/EventBox.purs index 29c6076..b6e9b59 100644 --- a/src/AGS/Widget/EventBox.purs +++ b/src/AGS/Widget/EventBox.purs @@ -1,11 +1,14 @@ module AGS.Widget.EventBox ( EventBoxProps + , UpdateEventBoxProps , eventBox + , eventBox' ) where import Prelude -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Gtk.Container (GtkContainerProps) import Gtk.Widget (Widget) @@ -39,3 +42,17 @@ eventBox = eventBoxImpl <<< unsafeCoerce foreign import eventBoxImpl ∷ Record (EventBoxProps ()) → Widget +type UpdateEventBoxProps = Record (EventBoxProps ()) → Record (EventBoxProps ()) + +eventBox' + ∷ ∀ r r' + . Union r r' (EventBoxProps ()) + ⇒ Record r + → Widget /\ (UpdateEventBoxProps → Effect Unit) +eventBox' props = + let + widget = eventBox props + update = unsafeWidgetUpdate @(EventBoxProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Icon.purs b/src/AGS/Widget/Icon.purs index 27b0bc2..48bf408 100644 --- a/src/AGS/Widget/Icon.purs +++ b/src/AGS/Widget/Icon.purs @@ -1,13 +1,18 @@ module AGS.Widget.Icon ( IconProps + , UpdateIconProps , icon + , icon' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Image (GtkImageProps) import Gtk.Misc (GtkMiscProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -27,3 +32,17 @@ icon = iconImpl <<< unsafeCoerce foreign import iconImpl ∷ Record (IconProps ()) → Widget +type UpdateIconProps = Record (IconProps ()) → Record (IconProps ()) + +icon' + ∷ ∀ r r' + . Union r r' (IconProps ()) + ⇒ Record r + → Widget /\ (UpdateIconProps → Effect Unit) +icon' props = + let + widget = icon props + update = unsafeWidgetUpdate @(IconProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Internal.js b/src/AGS/Widget/Internal.js index 585554d..25cceb9 100644 --- a/src/AGS/Widget/Internal.js +++ b/src/AGS/Widget/Internal.js @@ -1,14 +1,11 @@ -export const unsafeSetProperty = - prop => value => widget => () => - widget[prop] = value +export const unsafeGetwidgetPropsImpl = + ks => widget => + Object.fromEntries(ks.map(k => [k, widget[k]])) -export const grabFocus = - widget => () => - widget.grab_focus() - -export const withInterval = - interval => handler => widget => () => - { widget.poll(interval, _ => handler()) - return - } +export const unsafeUpdateWidgetProps = + props => widget => () => + Object.entries(props).forEach(([k, v]) => { + if (widget[k] != v) + widget[k] = v + }) diff --git a/src/AGS/Widget/Internal.purs b/src/AGS/Widget/Internal.purs index 9ebd7c3..45c23b4 100644 --- a/src/AGS/Widget/Internal.purs +++ b/src/AGS/Widget/Internal.purs @@ -3,25 +3,25 @@ module AGS.Widget.Internal , AnyF , Any , mkAny - , unsafeSetProperty - , grabFocus - , withInterval + , unsafeWidgetUpdate ) where import Prelude -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) import Data.Exists (Exists, mkExists) import Effect (Effect) import Effect.Uncurried (EffectFn1) import Gtk.Widget (GtkWidgetProps, Widget) +import Record.Studio.Keys (class Keys, keys) +import Type.Proxy (Proxy(..)) import Type.Row (type (+)) type AGSWidgetProps r = GtkWidgetProps + ( setup ∷ EffectFn1 Widget Unit - , className ∷ SelfOrBinding String + , className ∷ ValueOrBinding String , classNames ∷ Array String , css ∷ String , hpack ∷ String {- TODO make it a proper type -} @@ -35,14 +35,27 @@ newtype AnyF a = AnyF a type Any = Exists AnyF +-- TODO move out of the internal module mkAny ∷ ∀ a. a → Any mkAny = mkExists <<< AnyF --- * Methods - -foreign import unsafeSetProperty ∷ ∀ a. String → a → Widget → Effect Unit - -foreign import grabFocus ∷ Widget → Effect Unit - -foreign import withInterval ∷ Int → Effect Unit → Widget → Effect Unit +-- * Utils for widgets updates + +unsafeWidgetUpdate + ∷ ∀ @r + . Keys r + ⇒ Widget + → ((Record r → Record r) → Effect Unit) +unsafeWidgetUpdate widget = + let + getProps = unsafeGetWidgetProps @r + update f = unsafeUpdateWidgetProps (f (getProps widget)) widget + in + update + +unsafeGetWidgetProps ∷ ∀ @r. Keys r ⇒ Widget → Record r +unsafeGetWidgetProps = unsafeGetwidgetPropsImpl (keys (Proxy @r)) + +foreign import unsafeGetwidgetPropsImpl ∷ ∀ r. Array String → Widget → Record r +foreign import unsafeUpdateWidgetProps ∷ ∀ r. Record r → Widget → Effect Unit diff --git a/src/AGS/Widget/Label.purs b/src/AGS/Widget/Label.purs index 16411bc..f5a85bf 100644 --- a/src/AGS/Widget/Label.purs +++ b/src/AGS/Widget/Label.purs @@ -1,12 +1,16 @@ module AGS.Widget.Label ( LabelProps , label + , label' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Label (GtkLabelProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -28,3 +32,17 @@ foreign import labelImpl . Record r → Widget +type UpdateLabelProps = Record (LabelProps ()) → Record (LabelProps ()) + +label' + ∷ ∀ r r' + . Union r r' (LabelProps ()) + ⇒ Record r + → Widget /\ (UpdateLabelProps → Effect Unit) +label' props = + let + widget = label props + update = unsafeWidgetUpdate @(LabelProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Menu.purs b/src/AGS/Widget/Menu.purs index 6a11f7e..f0d5169 100644 --- a/src/AGS/Widget/Menu.purs +++ b/src/AGS/Widget/Menu.purs @@ -1,12 +1,14 @@ module AGS.Widget.Menu ( MenuProps + , UpdateMenuProps , menu + , menu' , module AGS.Widget.Menu.Item ) where -import AGS.Widget.Menu.Item - -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import AGS.Widget.Menu.Item (MenuItem, MenuItemProps, menuItem, menuItemImpl) +import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Effect.Uncurried (EffectFn1) import Gtk.Container (GtkContainerProps) @@ -36,3 +38,17 @@ menu = menuImpl <<< unsafeCoerce foreign import menuImpl ∷ Record (MenuProps ()) → Widget +type UpdateMenuProps = Record (MenuProps ()) → Record (MenuProps ()) + +menu' + ∷ ∀ r r' + . Union r r' (MenuProps ()) + ⇒ Record r + → Widget /\ (UpdateMenuProps → Effect Unit) +menu' props = + let + widget = menu props + update = unsafeWidgetUpdate @(MenuProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Overlay.purs b/src/AGS/Widget/Overlay.purs index 251115c..65e49cf 100644 --- a/src/AGS/Widget/Overlay.purs +++ b/src/AGS/Widget/Overlay.purs @@ -1,11 +1,16 @@ module AGS.Widget.Overlay ( OverlayProps + , UpdateOverlayProps , overlay + , overlay' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -24,3 +29,17 @@ overlay = overlayImpl <<< unsafeCoerce foreign import overlayImpl ∷ Record (OverlayProps ()) → Widget +type UpdateOverlayProps = Record (OverlayProps ()) → Record (OverlayProps ()) + +overlay' + ∷ ∀ r r' + . Union r r' (OverlayProps ()) + ⇒ Record r + → Widget /\ (UpdateOverlayProps → Effect Unit) +overlay' props = + let + widget = overlay props + update = unsafeWidgetUpdate @(OverlayProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/ProgressBar.purs b/src/AGS/Widget/ProgressBar.purs index 5024081..947c679 100644 --- a/src/AGS/Widget/ProgressBar.purs +++ b/src/AGS/Widget/ProgressBar.purs @@ -1,13 +1,18 @@ module AGS.Widget.ProgressBar ( ProgressBarProps + , UpdateProgressBarProps , progressBar + , progressBar' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Orientable (GtkOrientableProps) import Gtk.ProgressBar (GtkProgressBarProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -27,3 +32,18 @@ progressBar = progressBarImpl <<< unsafeCoerce foreign import progressBarImpl ∷ Record (ProgressBarProps ()) → Widget +type UpdateProgressBarProps = + Record (ProgressBarProps ()) → Record (ProgressBarProps ()) + +progressBar' + ∷ ∀ r r' + . Union r r' (ProgressBarProps ()) + ⇒ Record r + → Widget /\ (UpdateProgressBarProps → Effect Unit) +progressBar' props = + let + widget = progressBar props + update = unsafeWidgetUpdate @(ProgressBarProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Revealer.purs b/src/AGS/Widget/Revealer.purs index 1b73f5c..9886516 100644 --- a/src/AGS/Widget/Revealer.purs +++ b/src/AGS/Widget/Revealer.purs @@ -1,11 +1,16 @@ module AGS.Widget.Revealer ( RevealerProps + , UpdateRevealerProps , revealer + , revealer' , module Gtk.RevealerTransition ) where -import AGS.Widget.Internal (AGSWidgetProps) -import Control.Category ((<<<)) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Container (GtkContainerProps) import Gtk.Revealer (GtkRevealerProps) import Gtk.RevealerTransition (GtkRevealerTransitionType, transitions) @@ -25,3 +30,17 @@ revealer = revealerImpl <<< unsafeCoerce foreign import revealerImpl ∷ ∀ r. Record r → Widget +type UpdateRevealerProps = Record (RevealerProps ()) → Record (RevealerProps ()) + +revealer' + ∷ ∀ r r' + . Union r r' (RevealerProps ()) + ⇒ Record r + → Widget /\ (UpdateRevealerProps → Effect Unit) +revealer' props = + let + widget = revealer props + update = unsafeWidgetUpdate @(RevealerProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Scrollable.purs b/src/AGS/Widget/Scrollable.purs index fd58ca7..ab27d46 100644 --- a/src/AGS/Widget/Scrollable.purs +++ b/src/AGS/Widget/Scrollable.purs @@ -1,11 +1,15 @@ module AGS.Widget.Scrollable ( ScrollableProps + , UpdateScrollableProps , scrollable + , scrollable' ) where import Prelude -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Gtk.Container (GtkContainerProps) import Gtk.ScrolledWindow (GtkScrolledWindowProps) import Gtk.Widget (Widget) @@ -28,3 +32,18 @@ scrollable = scrollableImpl <<< unsafeCoerce foreign import scrollableImpl ∷ Record (ScrollableProps ()) → Widget +type UpdateScrollableProps = + Record (ScrollableProps ()) → Record (ScrollableProps ()) + +scrollable' + ∷ ∀ r r' + . Union r r' (ScrollableProps ()) + ⇒ Record r + → Widget /\ (UpdateScrollableProps → Effect Unit) +scrollable' props = + let + widget = scrollable props + update = unsafeWidgetUpdate @(ScrollableProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Slider.purs b/src/AGS/Widget/Slider.purs index a6bfb36..64cc4c6 100644 --- a/src/AGS/Widget/Slider.purs +++ b/src/AGS/Widget/Slider.purs @@ -1,8 +1,10 @@ module AGS.Widget.Slider ( SliderProps + , UpdateSliderProps , Mark , MarkPosition , slider + , slider' , markPositionTop , markPositionLeft , markPositionRight @@ -11,8 +13,9 @@ module AGS.Widget.Slider import Prelude -import AGS.Widget.Internal (AGSWidgetProps) +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) import Data.Maybe (Maybe, maybe) +import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Effect.Uncurried (mkEffectFn1) import Gtk.Orientable (GtkOrientableProps) @@ -77,3 +80,17 @@ slider = sliderImpl <<< prepare foreign import sliderImpl ∷ ∀ r. Record r → Widget +type UpdateSliderProps = Record (SliderProps ()) → Record (SliderProps ()) + +slider' + ∷ ∀ r r' + . Union r r' (SliderProps ()) + ⇒ Record r + → Widget /\ (UpdateSliderProps → Effect Unit) +slider' props = + let + widget = slider props + update = unsafeWidgetUpdate @(SliderProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Stack.purs b/src/AGS/Widget/Stack.purs index 49a3ea2..8fcd5fc 100644 --- a/src/AGS/Widget/Stack.purs +++ b/src/AGS/Widget/Stack.purs @@ -1,14 +1,18 @@ module AGS.Widget.Stack ( StackProps , stack + , stack' ) where -import AGS.Widget.Internal (AGSWidgetProps) +import Prelude + +import AGS.Widget.Internal (AGSWidgetProps, unsafeWidgetUpdate) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) import Foreign.Object (Object) import Gtk.Container (GtkContainerProps) import Gtk.Stack (GtkStackProps) import Gtk.Widget (Widget) -import Prelude ((<<<)) import Prim.Row (class Union) import Type.Row (type (+)) import Unsafe.Coerce (unsafeCoerce) @@ -28,3 +32,17 @@ stack = stackImpl <<< unsafeCoerce foreign import stackImpl ∷ Record (StackProps ()) → Widget +type UpdateStackProps = Record (StackProps ()) → Record (StackProps ()) + +stack' + ∷ ∀ r r' + . Union r r' (StackProps ()) + ⇒ Record r + → Widget /\ (UpdateStackProps → Effect Unit) +stack' props = + let + widget = stack props + update = unsafeWidgetUpdate @(StackProps ()) widget + in + widget /\ update + diff --git a/src/AGS/Widget/Window.purs b/src/AGS/Widget/Window.purs index 5d01332..1ba5487 100644 --- a/src/AGS/Widget/Window.purs +++ b/src/AGS/Widget/Window.purs @@ -2,7 +2,7 @@ module AGS.Widget.Window (WindowProps, Window, window) where import Prelude -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) import AGS.Widget.Window.Anchor as Anchor import AGS.Widget.Window.Exclusivity as Exclusivity import AGS.Widget.Window.Layer as WindowLayer @@ -13,7 +13,7 @@ import Unsafe.Coerce (unsafeCoerce) type WindowProps = ( name ∷ String - , child ∷ SelfOrBinding Widget + , child ∷ ValueOrBinding Widget , anchor ∷ Array Anchor.Anchor , layer ∷ WindowLayer.WindowLayer , exclusivity ∷ Exclusivity.Exclusivity diff --git a/src/Gtk/Button.purs b/src/Gtk/Button.purs index d2ff094..b947b9a 100644 --- a/src/Gtk/Button.purs +++ b/src/Gtk/Button.purs @@ -1,13 +1,13 @@ module Gtk.Button where -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) import Gtk.Widget (Widget) -- https://gjs-docs.gnome.org/gtk30~3.0/gtk.button -- Inherited: GObject.Object (1), Gtk.Widget (69), Gtk.Container (4) type GtkButtonProps r = ( alwaysShowImage ∷ Boolean - , image ∷ SelfOrBinding Widget + , image ∷ ValueOrBinding Widget -- , imagePosition ∷ Gtk.PositionType , label ∷ String -- , relief ∷ Gtk.ReliefStyle diff --git a/src/Gtk/Container.purs b/src/Gtk/Container.purs index 5d0b829..a4c897b 100644 --- a/src/Gtk/Container.purs +++ b/src/Gtk/Container.purs @@ -1,13 +1,13 @@ module Gtk.Container where -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) import Gtk.Widget (Widget) -- https://gjs-docs.gnome.org/gtk30~3.0/gtk.container -- Inherited: Gtk.Widget (39) type GtkContainerProps r = ( borderWidth ∷ Number - , child ∷ SelfOrBinding Widget + , child ∷ ValueOrBinding Widget -- , resizeMode ∷ Gtk.ResizeMode | r ) diff --git a/src/Gtk/Label.purs b/src/Gtk/Label.purs index cbdf007..f1dbf68 100644 --- a/src/Gtk/Label.purs +++ b/src/Gtk/Label.purs @@ -1,6 +1,6 @@ module Gtk.Label where -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) import Gtk.Widget (Widget) -- https://gjs-docs.gnome.org/gtk30~3.0/gtk.label @@ -11,11 +11,11 @@ type GtkLabelProps r = , cursorPosition ∷ Number -- , ellipsize ∷ Pango.EllipsizeMode -- , justify ∷ Gtk.Justification - , label ∷ SelfOrBinding String + , label ∷ ValueOrBinding String , lines ∷ Number , maxWidthChars ∷ Number , mnemonicKeyval ∷ Number - , mnemonicWidget ∷ SelfOrBinding Widget + , mnemonicWidget ∷ ValueOrBinding Widget , pattern ∷ String , selectable ∷ Boolean , selectionBound ∷ Number diff --git a/src/Gtk/Widget.purs b/src/Gtk/Widget.purs index 245beb3..106917d 100644 --- a/src/Gtk/Widget.purs +++ b/src/Gtk/Widget.purs @@ -1,48 +1,48 @@ module Gtk.Widget where -import AGS.Binding (SelfOrBinding) +import AGS.Binding (ValueOrBinding) data Widget type GtkWidgetProps r = - ( appPaintable ∷ SelfOrBinding Boolean - , canDefault ∷ SelfOrBinding Boolean - , canFocus ∷ SelfOrBinding Boolean - , compositeChild ∷ SelfOrBinding Boolean - , doubleBuffered ∷ SelfOrBinding Boolean + ( appPaintable ∷ ValueOrBinding Boolean + , canDefault ∷ ValueOrBinding Boolean + , canFocus ∷ ValueOrBinding Boolean + , compositeChild ∷ ValueOrBinding Boolean + , doubleBuffered ∷ ValueOrBinding Boolean -- , events ∷ Gdk.EventMask - , expand ∷ SelfOrBinding Boolean - , focusOnClick ∷ SelfOrBinding Boolean + , expand ∷ ValueOrBinding Boolean + , focusOnClick ∷ ValueOrBinding Boolean -- , halign ∷ Gtk.Align - , hasDefault ∷ SelfOrBinding Boolean - , hasFocus ∷ SelfOrBinding Boolean - , hasTooltip ∷ SelfOrBinding Boolean - , heightRequest ∷ SelfOrBinding Number - , hexpand ∷ SelfOrBinding Boolean - , hexpandSet ∷ SelfOrBinding Boolean - , isFocus ∷ SelfOrBinding Boolean - , margin ∷ SelfOrBinding Number - , marginBottom ∷ SelfOrBinding Number - , marginEnd ∷ SelfOrBinding Number - , marginLeft ∷ SelfOrBinding Number - , marginRight ∷ SelfOrBinding Number - , marginStart ∷ SelfOrBinding Number - , marginTop ∷ SelfOrBinding Number - , name ∷ SelfOrBinding String - , noShowAll ∷ SelfOrBinding Boolean - , opacity ∷ SelfOrBinding Number + , hasDefault ∷ ValueOrBinding Boolean + , hasFocus ∷ ValueOrBinding Boolean + , hasTooltip ∷ ValueOrBinding Boolean + , heightRequest ∷ ValueOrBinding Number + , hexpand ∷ ValueOrBinding Boolean + , hexpandSet ∷ ValueOrBinding Boolean + , isFocus ∷ ValueOrBinding Boolean + , margin ∷ ValueOrBinding Number + , marginBottom ∷ ValueOrBinding Number + , marginEnd ∷ ValueOrBinding Number + , marginLeft ∷ ValueOrBinding Number + , marginRight ∷ ValueOrBinding Number + , marginStart ∷ ValueOrBinding Number + , marginTop ∷ ValueOrBinding Number + , name ∷ ValueOrBinding String + , noShowAll ∷ ValueOrBinding Boolean + , opacity ∷ ValueOrBinding Number -- , parent ∷ Gtk.Container - , receivesDefault ∷ SelfOrBinding Boolean - , scaleFactor ∷ SelfOrBinding Number - , sensitive ∷ SelfOrBinding Boolean + , receivesDefault ∷ ValueOrBinding Boolean + , scaleFactor ∷ ValueOrBinding Number + , sensitive ∷ ValueOrBinding Boolean -- , style ∷ Gtk.Style - , tooltipMarkup ∷ SelfOrBinding String - , tooltipText ∷ SelfOrBinding String + , tooltipMarkup ∷ ValueOrBinding String + , tooltipText ∷ ValueOrBinding String -- , valign ∷ Gtk.Align - , vexpand ∷ SelfOrBinding Boolean - , vexpandSet ∷ SelfOrBinding Boolean - , visible ∷ SelfOrBinding Boolean - , widthRequest ∷ SelfOrBinding Number + , vexpand ∷ ValueOrBinding Boolean + , vexpandSet ∷ ValueOrBinding Boolean + , visible ∷ ValueOrBinding Boolean + , widthRequest ∷ ValueOrBinding Number -- , window ∷ Gdk.Window | r )