Skip to content

Commit 24fbb7a

Browse files
authored
Merge pull request #12 from gri-gus/feature/property_inspector
v1.1.0
2 parents 6c5c648 + 80f175e commit 24fbb7a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+5666
-14
lines changed

README-PYPI.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Library for creating Stream Deck plugins in Python.
4848
* A complete protocol for interaction with the Stream Deck application has been implemented.
4949
* Quick start of a project via the console command `streamdeck_sdk startproject`.
5050
* Build the project using the `streamdeck_sdk build` console command.
51+
* Property Inspector Generator. Write code in Python and get html and js for PI.
5152

5253
## Examples
5354

README.md

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pip install streamdeck_sdk
6767
* A complete protocol for interaction with the Stream Deck application has been implemented.
6868
* Quick start of a project via the console command `streamdeck_sdk startproject`.
6969
* Build the project using the `streamdeck_sdk build` console command.
70+
* Property Inspector Generator. Write code in Python and get html and js for PI.
7071

7172
## Quick Start
7273

@@ -205,6 +206,363 @@ $PI.onSendToPropertyInspector("com.ggusev.keyboard.write", jsn => {
205206

206207
Instead of `"com.ggusev.keyboard.write"` you need to substitute the name of your `action`.
207208

209+
## Property Inspector Generator
210+
211+
With this tool you can quickly write your Property Inspector in Python.
212+
HTML and JS code will be generated.
213+
214+
In the application template from the `Quick Start` section there is a file
215+
`com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.py`,
216+
which provides an example of generating a Property Inspector into the file
217+
``com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.html``.
218+
219+
Here are the elements available for generation in Python:
220+
221+
```python
222+
from pathlib import Path
223+
224+
from streamdeck_sdk.property_inspector import *
225+
226+
OUTPUT_DIR = Path(__file__).parent
227+
TEMPLATE = Path(__file__).parent / "pi_template.html"
228+
229+
230+
class LoremFlickrStatus(BasePIElement):
231+
def get_html_element(self) -> str:
232+
res = """
233+
<div class="sdpi-item" style="max-height: 60px">
234+
<div class="sdpi-item-label">Website status</div>
235+
<div class="sdpi-item-value"
236+
style="background: #3D3D3D; height:26px; max-width: 56px; margin: 0 0 0 5px; padding: 0">
237+
<img src="https://img.shields.io/website?down_color=%233d3d3d&down_message=offline&label=&style=flat-square&up_color=%233d3d3d&up_message=online&url=https%3A%2F%2Floremflickr.com%2F"
238+
alt="" style="height: 26px; max-width: 56px; margin: 0">
239+
</div>
240+
</div>
241+
"""
242+
return res
243+
244+
245+
def main():
246+
pi = PropertyInspector(
247+
action_uuid="com.ggusev.example.exampleaction",
248+
elements=[
249+
Heading(label="TEXT"),
250+
Textfield(
251+
label="Name",
252+
uid="name",
253+
required=True,
254+
pattern=".{2,}",
255+
placeholder="Input your name",
256+
),
257+
Textfield(
258+
label="Text with default",
259+
uid="text_with_default",
260+
placeholder="Input default",
261+
default_value="default"
262+
),
263+
Textfield(
264+
label="IP-Address",
265+
uid="my_ip_address",
266+
required=True,
267+
pattern=r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",
268+
placeholder="e.g. 192.168.61.1",
269+
),
270+
Textarea(
271+
label="Textarea",
272+
uid="textarea",
273+
placeholder="Input",
274+
max_length=100,
275+
info_text="100 max"
276+
),
277+
Textarea(label="Textarea", uid="textarea_1", placeholder="Input", ),
278+
Password(
279+
label="Password",
280+
uid="password_input",
281+
required=True,
282+
pattern=".{2,}",
283+
placeholder="Input password",
284+
default_value="kitten",
285+
),
286+
Heading(label="CHECKBOX & RADIO"),
287+
Radio(
288+
label="Union type",
289+
uid="union_type",
290+
items=[
291+
RadioItem(
292+
value="or",
293+
label="or",
294+
checked=False,
295+
),
296+
RadioItem(
297+
value="and",
298+
label="and",
299+
checked=True,
300+
)
301+
]
302+
),
303+
Checkbox(
304+
label="Grayscale",
305+
items=[
306+
CheckboxItem(
307+
uid="grayscale_flag",
308+
label="on",
309+
checked=False,
310+
),
311+
],
312+
),
313+
Heading(label="FILE"),
314+
File(
315+
label="Select file",
316+
uid="my_file",
317+
accept=[".jpg", ".jpeg", ".png"],
318+
),
319+
Heading(label="DATE & TIME"),
320+
DateTimeLocal(
321+
label="Select datetime",
322+
uid="my_datetime",
323+
default_value="2024-09-13T19:39",
324+
),
325+
Date(
326+
label="Select date",
327+
uid="my_date",
328+
default_value="2019-01-15",
329+
),
330+
Date(
331+
label="Select date",
332+
uid="my_date_1",
333+
),
334+
Month(
335+
label="Select month",
336+
uid="my_month",
337+
default_value="2024-07",
338+
),
339+
Week(
340+
label="Select week",
341+
uid="my_week",
342+
default_value="2024-W38",
343+
),
344+
Time(
345+
label="Select time",
346+
uid="my_time",
347+
default_value="19:39",
348+
),
349+
Heading(label="GROUP"),
350+
Group(
351+
label="My group",
352+
items=[
353+
Radio(
354+
label="Union type",
355+
uid="my_group_union_type",
356+
items=[
357+
RadioItem(
358+
value="or",
359+
label="or",
360+
checked=True,
361+
),
362+
RadioItem(
363+
value="and",
364+
label="and",
365+
checked=False,
366+
)
367+
]
368+
),
369+
Date(
370+
label="Select date",
371+
uid="my_group_my_date",
372+
default_value="2019-01-15",
373+
),
374+
]
375+
),
376+
Heading(label="LINE"),
377+
Line(),
378+
Heading(label="COLOR"),
379+
Color(
380+
label="Color",
381+
uid="my_color",
382+
default_value="#240bda",
383+
),
384+
Heading(label="PROGRESS & METER"),
385+
Meter(
386+
label="Meter",
387+
uid="my_meter_2",
388+
default_value=8,
389+
max_value=100,
390+
),
391+
Meter(
392+
label="Meter",
393+
uid="my_meter_1",
394+
default_value=0.5,
395+
left_label="0",
396+
right_label="100",
397+
),
398+
Progress(
399+
label="Progress",
400+
uid="my_progress_1",
401+
default_value=0.5,
402+
),
403+
Progress(
404+
label="Progress",
405+
uid="my_progress_2",
406+
left_label="Min",
407+
right_label="Max",
408+
default_value=0.5,
409+
),
410+
Heading(label="RANGE"),
411+
Range(
412+
label="Range",
413+
uid="my_range_2",
414+
min_value=0,
415+
max_value=50,
416+
default_value=20,
417+
),
418+
Range(
419+
label="Range (+ll + rl)",
420+
uid="my_range_1",
421+
left_label="0",
422+
right_label="50",
423+
min_value=0,
424+
max_value=50,
425+
default_value=20,
426+
),
427+
Range(
428+
label="Range(+stp)",
429+
uid="my_range_3",
430+
min_value=0,
431+
max_value=50,
432+
default_value=25,
433+
step=25,
434+
),
435+
Range(
436+
label="Range(+dl +stp)",
437+
uid="my_range_4",
438+
min_value=0,
439+
max_value=50,
440+
default_value=25,
441+
datalist=["", "", "", ],
442+
step=25,
443+
),
444+
Range(
445+
label="Range(+dl +lbl)",
446+
uid="my_range_5",
447+
min_value=0,
448+
max_value=100,
449+
default_value=25,
450+
datalist=["0", "50", "100", ],
451+
),
452+
Heading(label="DETAILS"),
453+
Details(
454+
uid="my_full_width_details",
455+
full_width=True,
456+
heading="Full width details",
457+
text="""
458+
default open
459+
""",
460+
default_open=True,
461+
),
462+
Details(
463+
uid="my_details_with_label",
464+
label="Details",
465+
heading="Info",
466+
text="My test info\nMy test info"
467+
),
468+
Heading(label="MESSAGE"),
469+
Message(
470+
uid="my_message",
471+
heading="Example message",
472+
message_type=MessageTypes.INFO,
473+
text="Example message text",
474+
),
475+
Message(
476+
uid="last_error",
477+
heading="Last error",
478+
message_type=MessageTypes.CAUTION,
479+
text="",
480+
),
481+
Heading(label="SELECT"),
482+
Select(
483+
uid="my_select_1",
484+
label="Select",
485+
values=["1", "2", "3", "4"],
486+
default_value="2",
487+
),
488+
Select(
489+
uid="my_select_2",
490+
label="Select 2",
491+
values=[],
492+
),
493+
Heading(label="CUSTOM"),
494+
LoremFlickrStatus(),
495+
]
496+
)
497+
pi.build(output_dir=OUTPUT_DIR, template=TEMPLATE)
498+
499+
500+
if __name__ == '__main__':
501+
main()
502+
503+
```
504+
505+
> You can write your custom elements, for example as `LoremFlickrStatus`, and also edit `pi_template.html`
506+
> at your discretion.
507+
508+
> `uid` is a future key in the `obj.payload.settings` dictionary.
509+
510+
> The same rules apply to `uid` as to variable naming in Python.
511+
512+
> `uid` must be unique within a single file for Property Inspector generation.
513+
514+
> All elements that contain `uid` are manipulable.
515+
516+
### Example of creating a Property Inspector and managing a field
517+
518+
For example, you made a Property Inspector like this and generated it:
519+
520+
```python
521+
from pathlib import Path
522+
523+
from streamdeck_sdk.property_inspector import *
524+
525+
OUTPUT_DIR = Path(__file__).parent
526+
TEMPLATE = Path(__file__).parent / "pi_template.html"
527+
528+
529+
def main():
530+
pi = PropertyInspector(
531+
action_uuid="com.bestdeveloper.mytestplugin.myaction",
532+
elements=[
533+
Textfield(
534+
uid="my_input",
535+
label="My input",
536+
placeholder="Input text",
537+
),
538+
]
539+
)
540+
pi.build(output_dir=OUTPUT_DIR, template=TEMPLATE)
541+
542+
543+
if __name__ == '__main__':
544+
# Run to generate Property Inspector
545+
main()
546+
```
547+
548+
Then in the plugin's `Action` you can use code something like this to get the value from the `My input` field
549+
and then change the value if needed:
550+
551+
```python
552+
def on_key_down(self, obj: events_received_objs.KeyDown):
553+
my_input_value = obj.payload.settings["my_input"]
554+
print(my_input_value)
555+
556+
stngs = obj.payload.settings.copy()
557+
stngs["my_input"] = "12345"
558+
self.set_settings(
559+
context=obj.context,
560+
payload=stngs,
561+
)
562+
```
563+
564+
After executing `self.set_settings` the value of the `My input` field will change to `12345`.
565+
208566
## Examples
209567

210568
[LoremFlickr](https://github.com/gri-gus/loremflickr-streamdeck-plugin) - Plugin for installing images on a button from

0 commit comments

Comments
 (0)