순환
패널은 view(state)를 정의하고, 필요하면 initial(), on_open(state), on_action(action, state)도 정의합니다. Clink는 시작 상태를 위해 initial()을 한 번, 패널이 나타날 때마다 on_open을 부르고, 이어서 view(state)로 화면을 만듭니다. 컨트롤은 쓰고 있는 자리에 글자를 넣거나, 새 상태를 정하거나, on_action이 처리할 액션 이름을 갖습니다. 그때마다 화면이 다시 만들어집니다.
def initial():
return {"count": 0, "step": 1}
def view(state):
return vstack([
text(f"{state['count']}", size=34, weight="bold", align="center"),
segmented(["1", "5", "10"], value=str(state["step"]), action="step"),
hstack([
button("−", "bump", value=-1),
button("+", "bump", value=1, style="primary"),
]),
button("Type it", "type", icon="keyboard"),
])
def on_action(action, value, state):
if action == "bump":
state["count"] = state["count"] + value * state["step"]
elif action == "step":
state["step"] = int(value)
elif action == "type":
insert(str(state["count"]))
close()
return state계산기, 스니펫 모음, 피커: 내가 만든 패널은 키보드의 패널 버튼 뒤에 나타나요.
빌더
view(state)는 이 19개의 함수가 만든 노드를 돌려줍니다. 자유롭게 중첩하세요. 스택과 그리드는 자식 목록을 받습니다.
| 빌더 | 그리는 것 |
|---|---|
vstack(children, spacing=6, align="leading") | 자식을 아래로 쌓습니다. |
hstack(children, spacing=6, align="center") | 자식을 가로로 늘어놓습니다. |
grid(children, columns=4, spacing=6) | 자식을 고른 열로 흘려 배치합니다. |
wrap(children, spacing=6) | 자식 요소를 패널 너비에 늘어놓고 넘치면 다음 줄로 넘깁니다. |
scroll(children, spacing=6) | 자체 스크롤 영역입니다. 패널보다 긴 목록에 씁니다. |
card(children, padding=10, color="") | 자식 요소를 한 면에 모으고 주위에 여백을 둡니다. |
spacer(size=0) | 뒤따르는 것을 끝까지 밀어냅니다. |
divider() | 행 사이의 가는 선입니다. |
text(s, size=17, weight="regular", color="", align="leading", lines=0, mono=False) | 한 줄의 텍스트입니다. weight는 regular, medium, semibold, bold, heavy, light, thin을 받고, align은 leading, center, trailing을 받습니다. lines는 줄바꿈 줄 수를 제한하고, color는 색 이름이나 #RRGGBB를 받습니다. |
icon(name, size=20, color="") | SF Symbol을 이름으로 넣습니다. |
badge(s, color="") | 짧은 낱말을 색을 입힌 캡슐에 담습니다. |
progress(value, total=1, label="") | total 중 value 만큼 채워지는 막대입니다. |
button(label, action="", value=None, insert="", set=None, style="plain", icon="", enabled=True) | 버튼입니다. insert는 지금 쓰고 있는 곳에 그 글자를 입력하고, set은 상태에 키를 합치며, action은 on_action이 받을 이름을 지정합니다. style은 plain, primary, tinted, quiet, destructive를 받습니다. |
row(title, subtitle="", detail="", icon="", action="", value=None, insert="") | 탭할 수 있는 행입니다. 제목, 둘째 줄, 아이콘, 오른쪽 부가 정보로 이루어집니다. |
toggle(label, on=False, key="", action="") | 스위치입니다. key를 주면 해당 상태 키에 True 또는 False를 씁니다. |
slider(value, min=0, max=100, step=1, label="", key="", action="") | min에서 max 사이의 슬라이더입니다. key를 주면 위치를 해당 상태 키에 씁니다. |
stepper(value, min=0, max=100, step=1, label="", key="", action="") | − 와 + 가 붙은 값입니다. min에서 max 사이에서 움직입니다. |
segmented(options, value=None, key="", action="") | 목록에서 하나를 고릅니다. key를 주면 고른 항목을 해당 상태 키에 씁니다. |
field(key, placeholder="", action="", submit="") | state[key]에 묶인 텍스트 상자입니다. 탭하면 키 입력이 그 키로 향하고, submit은 Return이 실행할 처리기의 이름입니다. |
평범한 문자열도 노드가 놓이는 자리라면 그대로 쓸 수 있습니다. 기본 크기의 텍스트로 그려집니다.
탭에 반응하기
무언가를 계산해야 하는 컨트롤은 고정된 set 대신 action 이름을 지정합니다. 그러면 Clink가 on_action(action, state)를 호출합니다. 컨트롤이 지닌 값까지 쓰고 싶으면 on_action(action, value, state)로 받습니다. state는 평범한 딕셔너리라서 그 자리에서 고치고 아무것도 반환하지 않아도 되고, 새 딕셔너리를 반환해도 됩니다.
def initial():
return {"items": [], "draft": ""}
def view(state):
return vstack([
field("draft", placeholder="Add one…", submit="add"),
scroll([row(item, action="use", value=item) for item in state["items"]]),
])
def on_action(action, value, state):
if action == "add" and value:
state["items"].append(value)
state["draft"] = ""
elif action == "use":
insert(value)
close()
return stateon_open(state)는 패널이 나타날 때마다 실행됩니다. 지금 쓰고 있는 글에서 초깃값을 가져오는 자리입니다.
키보드에 요청하기
on_action과 on_open에서는 반환값으로 표현할 수 없는 일을 키보드에 요청할 수 있습니다. 호출은 일단 기록해 두었다가 함수가 끝난 뒤에 적용하므로, 패널이 자기 화면을 만드는 도중에 입력란을 건드리는 일은 없습니다.
명령
insert()backspace()delete_word()replace()move_cursor()copy()close()haptic()toast()
def on_action(action, state):
if action == "quote":
word = context()["word"]
replace(len(word), "“" + word + "”")
haptic("light")
return statecontext()는 커서 주변을 읽습니다. before, selected, after, word, clipboard, locale, language, full_access, time입니다. 호출이 시작될 때 찍은 스냅샷이라 렌더링 도중에 바뀌지 않습니다.
상태
state는 평범한 딕셔너리이며 스크립트가 만들 수 있는 것은 무엇이든 담습니다. 숫자, 문자열, 불리언, None, 그리고 그것들의 리스트와 딕셔너리입니다. 호출할 때마다 되돌려 주므로, 한 번 탭에서 덧붙인 리스트는 다음 탭에도 그대로 있습니다.
def initial():
return {"name": ""}
def view(state):
return vstack([
field("name", placeholder="Who?"),
button("Greet", insert="Hi " + state["name"] + "!", style="primary"),
])‘상태 기억’을 켜면 패널 내용이 다시 열어도, 키보드를 다시 켜도 남습니다. 계산기라면 꺼 두고, 목록이라면 켜 두세요.
state는 키보드가 화면에 있는 동안 살아 있고, 패널이 기억하도록 해 두었다면 더 오래 남습니다. 패널은 context()로 커서 주변 글자를 읽을 수 있을 뿐, 당신에 대한 다른 것은 읽지 못합니다.
한계
키보드가 받는 메모리는 앱의 일부에 불과하므로, 패널은 신뢰가 아니라 한계로 묶여 있습니다. 화면을 한 번 그릴 때마다 인터프리터 2,000,000단계가 주어지고, 폭주한 반복문은 키보드가 멎는 대신 화면의 오류로 끝납니다.
파일이나 저장소에서 온 패널은 저장하기 전에 검사합니다. 48,000 바이트와 1,200 줄을 넘지 않아야 하고, def view( 를 정의해야 하며, 모든 import는 샌드박스 안의 네임스페이스 중 하나를 가리켜야 합니다. 그리고 다음 조각은 그 자리에서 거부됩니다:
공유된 패널에서 거부
__exec(eval(open(compile(
공유 패널에서 가져올 수 있는 것
jsonmathrandomresystime
앱 안에서 직접 쓰는 패널은 그 목록의 적용을 받지 않습니다. 그럴 때 폭주하는 반복을 멈추는 것은 단계 예산뿐이니, 빠져나갈 길을 남겨 두세요.
위치
패널마다 피커에 각자의 버튼을 주고, 하나의 패널 버튼 안에 몰아넣지 않아요. 개별 패널은 자신의 에디터에서 이 설정을 덮어쓸 수 있어요.
기본값은 그 스위치를 따르고, 단독은 항상 자기 버튼을 가지며, 그룹은 항상 안쪽에 들어갑니다.
직접 만들기
- Clink에서 맞춤 패널을 열고 새 패널을 누릅니다.
- 스크립트를 씁니다. 옆에서 진짜 패널이 미리보기로 돌아가고, 오류는 입력하는 대로 표시됩니다.
- 저장하고 패널을 켠 다음, 키보드의 패널 버튼을 엽니다.
공유 패널은 JSON인 .clinkpanel 파일을 만듭니다. Clink에서 다시 열면 새 id로 저장되므로, 같은 패널을 두 번 가져와도 처음 것을 덮어쓰지 않습니다.
크리에이터 ›