nandi/cosmicnimpublic Fork 0
v0.3.0
Commits
Clone
git clone https://git.rickub.com/nandi/cosmicnim.git
git clone ssh://git@rickub.com/nandi/cosmicnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

cosmicnim.nim · 128 lines · 4.7 KBNim Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
## Nim bindings for the cosmic_ffi cdylib.
##
## The window's shape is described from Nim, once per frame, inside an
## `onView` callback. Containers are block templates, so the widget tree in
## the source has the same shape as the widget tree on screen:
##
## ```nim
## b.container:
##   b.fill(); b.alignCenter(); b.spacing(space(SpaceM))
##   b.text("Count: 3", TextTitle1)
##   b.row:
##     b.spacing(space(SpaceS))
##     b.button("−", id = 0)
##     b.button("+", id = 1, style = ButtonSuggested)
## ```

import std/os

when not defined(noSignalHandler):
  {.warning: "compile with -d:noSignalHandler: libcosmic runs threads Nim " &
             "did not create, and Nim's signal handler allocates, so a signal " &
             "delivered to one of them crashes inside the handler".}

const libCosmicFfi* {.strdefine.} = currentSourcePath().parentDir /
                                    "libcosmic_ffi.so"
  ## Absolute at compile time, so the library is found wherever nimble put
  ## the package rather than only next to the binary. Override with
  ## `-d:libCosmicFfi=/some/other/libcosmic_ffi.so`.

type
  Builder* = distinct pointer
    ## Opaque. Only valid for the duration of the `onView` call it arrived in.

  OnView* = proc (ctx: pointer; b: Builder) {.cdecl.}
  OnPress* = proc (ctx: pointer; id: int32) {.cdecl.}

  CosmicConfig* = object
    title*: cstring
    onView*: OnView
    onPress*: OnPress
    ctx*: pointer
    width*: uint32   ## 0 for a default
    height*: uint32  ## 0 for a default

  TextStyle* = enum
    TextBody, TextTitle1, TextTitle2, TextTitle3, TextTitle4,
    TextHeading, TextCaption, TextMonotext

  ButtonStyle* = enum
    ButtonStandard, ButtonSuggested, ButtonDestructive, ButtonText, ButtonLink

  SpaceStep* = enum
    SpaceNone, SpaceXxxs, SpaceXxs, SpaceXs, SpaceS, SpaceM, SpaceL, SpaceXl

proc cosmicRun*(config: ptr CosmicConfig): int32
  {.cdecl, importc: "cosmic_run", dynlib: libCosmicFfi.}

# --- raw builder calls; prefer the wrappers below ---

proc beginColumn(b: Builder) {.cdecl, importc: "cosmic_column", dynlib: libCosmicFfi.}
proc beginRow(b: Builder) {.cdecl, importc: "cosmic_row", dynlib: libCosmicFfi.}
proc beginContainer(b: Builder) {.cdecl, importc: "cosmic_container", dynlib: libCosmicFfi.}
proc endNode(b: Builder) {.cdecl, importc: "cosmic_end", dynlib: libCosmicFfi.}

proc rawSpacing(b: Builder; px: cfloat) {.cdecl, importc: "cosmic_spacing", dynlib: libCosmicFfi.}
proc rawPadding(b: Builder; px: cfloat) {.cdecl, importc: "cosmic_padding", dynlib: libCosmicFfi.}
proc rawAlignCenter(b: Builder) {.cdecl, importc: "cosmic_align_center", dynlib: libCosmicFfi.}
proc rawFill(b: Builder) {.cdecl, importc: "cosmic_fill", dynlib: libCosmicFfi.}

proc rawText(b: Builder; style: int32; text: cstring)
  {.cdecl, importc: "cosmic_text", dynlib: libCosmicFfi.}
proc rawButton(b: Builder; style: int32; label: cstring; id: int32)
  {.cdecl, importc: "cosmic_button", dynlib: libCosmicFfi.}
proc rawSpace(b: Builder; w, h: cfloat)
  {.cdecl, importc: "cosmic_space", dynlib: libCosmicFfi.}
proc rawSize(b: Builder; w, h: cfloat)
  {.cdecl, importc: "cosmic_size", dynlib: libCosmicFfi.}
proc rawSpaceUnit(step: int32): cfloat
  {.cdecl, importc: "cosmic_space_unit", dynlib: libCosmicFfi.}

# --- containers ---

template column*(b: Builder; body: untyped) =
  ## Stack the widgets built in `body` vertically.
  beginColumn(b)
  body
  endNode(b)

template row*(b: Builder; body: untyped) =
  ## Lay the widgets built in `body` out horizontally.
  beginRow(b)
  body
  endNode(b)

template container*(b: Builder; body: untyped) =
  ## Wrap the widgets built in `body`, typically to pad or centre them.
  beginContainer(b)
  body
  endNode(b)

# --- attributes of the innermost open container ---

proc spacing*(b: Builder; px: float) = rawSpacing(b, cfloat(px))
proc padding*(b: Builder; px: float) = rawPadding(b, cfloat(px))
proc alignCenter*(b: Builder) = rawAlignCenter(b)
proc fill*(b: Builder) = rawFill(b)

# --- leaves ---

proc text*(b: Builder; s: string; style = TextBody) =
  rawText(b, int32(ord(style)), s.cstring)

proc button*(b: Builder; label: string; id: int32; style = ButtonStandard;
             enabled = true) =
  ## A button that reports `id` back through `onPress`. `enabled = false`
  ## draws it inert; `id` is then never delivered.
  rawButton(b, int32(ord(style)), label.cstring, if enabled: id else: -1)

proc space*(b: Builder; w, h: float) = rawSpace(b, cfloat(w), cfloat(h))

proc size*(b: Builder; w = -1.0; h = -1.0) =
  ## Size the next leaf, in pixels. A negative dimension stays natural.
  ## Applies to one leaf only, so set it before each widget you want sized.
  rawSize(b, cfloat(w), cfloat(h))

proc space*(step: SpaceStep): float =
  ## The active COSMIC theme's spacing for `step`, in pixels.
  float(rawSpaceUnit(int32(ord(step))))