elismasilva commited on
Commit
089beca
·
verified ·
1 Parent(s): d50fcf7

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. README.md +69 -45
  2. app.py +70 -45
  3. space.py +69 -45
  4. src/README.md +69 -45
  5. src/demo/app.py +70 -45
  6. src/demo/space.py +69 -45
README.md CHANGED
@@ -55,10 +55,10 @@ from gradio_propertysheet import PropertySheet
55
  from gradio_htmlinjector import HTMLInjector
56
 
57
 
58
- # --- 1. Dataclass Definitions (unchanged) ---
59
  @dataclass
60
  class EffectBase:
61
- """Classe base com configurações de efeito comuns."""
62
  strength: float = field(
63
  default=0.5,
64
  metadata={
@@ -67,14 +67,14 @@ class EffectBase:
67
  "minimum": 0.0,
68
  "maximum": 1.0,
69
  "step": 0.01,
70
- # Esta regra depende do 'is_active' da classe filha
71
  "interactive_if": {"field": "is_active", "value": True}
72
  }
73
  )
74
 
75
  @dataclass
76
  class EffectSettings(EffectBase):
77
- """Classe filha que adiciona o controle de ativação."""
78
  is_active: bool = field(
79
  default=True,
80
  metadata={"label": "Enable Effect"}
@@ -82,7 +82,7 @@ class EffectSettings(EffectBase):
82
 
83
  @dataclass
84
  class EffectsConfig:
85
- """Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome."""
86
  blur_effect: EffectSettings = field(
87
  default_factory=EffectSettings,
88
  metadata={"label": "Blur Effect"}
@@ -95,6 +95,7 @@ class EffectsConfig:
95
  default_factory=EffectSettings,
96
  metadata={"label": "Vignette Effect"}
97
  )
 
98
  @dataclass
99
  class APISettings:
100
  api_key: str = field(
@@ -109,7 +110,7 @@ class APISettings:
109
  default="https://api.example.com",
110
  metadata={
111
  "label": "API Endpoint",
112
- "component": "string", # string normal
113
  "help": "The URL of the API server."
114
  }
115
  )
@@ -124,7 +125,6 @@ class QuantizationSettings:
124
  "help": "Quantization mechanism to save VRAM and increase speed."
125
  }
126
  )
127
- # Option 1: Literal values
128
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
129
  default="FP8",
130
  metadata={
@@ -134,7 +134,6 @@ class QuantizationSettings:
134
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
135
  }
136
  )
137
- # Option 2: neq operand
138
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
139
  default="FP8",
140
  metadata={
@@ -144,6 +143,7 @@ class QuantizationSettings:
144
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
145
  }
146
  )
 
147
  @dataclass
148
  class ModelSettings:
149
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -152,7 +152,7 @@ class ModelSettings:
152
  "component": "dropdown",
153
  "label": "Base Model",
154
  "help": "Select the base diffusion model.",
155
- "visible": True #change here to test visibility
156
  }
157
  )
158
  custom_model_path: str = field(
@@ -244,6 +244,30 @@ class SamplingSettings:
244
  }
245
  )
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  @dataclass
248
  class RenderConfig:
249
  api_settings: APISettings = field(
@@ -273,6 +297,12 @@ class RenderConfig:
273
  default_factory=SamplingSettings,
274
  metadata={"label": "Sampling Settings"}
275
  )
 
 
 
 
 
 
276
  quantization: QuantizationSettings = field(
277
  default_factory=QuantizationSettings,
278
  metadata={"label": "Quantization Settings"}
@@ -347,9 +377,11 @@ class DPM_Settings:
347
  }
348
  )
349
 
350
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
351
  initial_render_config = RenderConfig()
352
  initial_env_config = EnvironmentConfig()
 
 
353
  sampler_settings_map_py = {
354
  "Euler": EulerSettings(),
355
  "DPM++ 2M Karras": DPM_Settings(),
@@ -362,8 +394,7 @@ model_settings_map_py = {
362
  "Pony": None,
363
  }
364
 
365
-
366
- # --- 3. CSS & JS Injection function (unchanged) ---
367
  def inject_assets():
368
  """
369
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -406,14 +437,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
406
  gr.Markdown(
407
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
408
  )
409
- initial_effects_config = EffectsConfig()
410
  effects_state = gr.State(value=initial_effects_config)
411
  render_state = gr.State(value=initial_render_config)
412
  env_state = gr.State(value=initial_env_config)
413
  sidebar_visible = gr.State(False)
414
  with gr.Row():
415
  with gr.Column(scale=3):
416
- generate = gr.Button("Show Settings", variant="primary")
417
  with gr.Row():
418
  output_render_json = gr.JSON(label="Live Render State")
419
  output_env_json = gr.JSON(label="Live Environment State")
@@ -472,11 +502,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
472
  if updated_config is None:
473
  return current_state, asdict(current_state), current_state
474
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
475
 
476
- generate.click(
477
  fn=change_visibility,
478
  inputs=[sidebar_visible, render_state, env_state, effects_state],
479
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
480
  )
481
 
482
  render_sheet.change(
@@ -489,41 +524,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
489
  inputs=[environment_sheet, env_state],
490
  outputs=[environment_sheet, output_env_json, env_state],
491
  )
492
-
493
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
494
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
495
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
496
- if updated_config is None:
497
- return current_state, asdict(current_state), current_state
498
- return updated_config, asdict(updated_config), current_state
499
-
500
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
501
- if updated_config is None:
502
- return current_state, asdict(current_state), current_state
503
- return updated_config, asdict(updated_config), current_state
504
-
505
- render_sheet.undo(fn=render_undo,
506
- inputs=[render_sheet, render_state],
507
- outputs=[render_sheet, output_render_json, render_state]
508
- )
509
- environment_sheet.undo(fn=environment_undo,
510
- inputs=[environment_sheet, env_state],
511
- outputs=[environment_sheet, output_env_json, env_state],
512
- )
513
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
514
- if updated_config is None:
515
- return current_state, asdict(current_state), current_state
516
- return updated_config, asdict(updated_config), updated_config
517
-
518
  effects_sheet.change(
519
  fn=handle_effects_change,
520
  inputs=[effects_sheet, effects_state],
521
  outputs=[effects_sheet, output_effects_json, effects_state]
522
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  effects_sheet.undo(
524
- fn=handle_effects_change,
525
  inputs=[effects_sheet, effects_state],
526
- outputs=[effects_sheet, output_effects_json, effects_state]
527
  )
528
 
529
  demo.load(
@@ -697,7 +722,6 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
697
 
698
  if __name__ == "__main__":
699
  demo.launch()
700
-
701
  ```
702
 
703
  ## `PropertySheet`
 
55
  from gradio_htmlinjector import HTMLInjector
56
 
57
 
58
+ # --- 1. Dataclass Definitions ---
59
  @dataclass
60
  class EffectBase:
61
+ """Base class with common effect settings."""
62
  strength: float = field(
63
  default=0.5,
64
  metadata={
 
67
  "minimum": 0.0,
68
  "maximum": 1.0,
69
  "step": 0.01,
70
+ # This rule depends on the 'is_active' field from the child class
71
  "interactive_if": {"field": "is_active", "value": True}
72
  }
73
  )
74
 
75
  @dataclass
76
  class EffectSettings(EffectBase):
77
+ """Child class that adds the activation control."""
78
  is_active: bool = field(
79
  default=True,
80
  metadata={"label": "Enable Effect"}
 
82
 
83
  @dataclass
84
  class EffectsConfig:
85
+ """Main dataclass containing multiple effects with same-named control fields."""
86
  blur_effect: EffectSettings = field(
87
  default_factory=EffectSettings,
88
  metadata={"label": "Blur Effect"}
 
95
  default_factory=EffectSettings,
96
  metadata={"label": "Vignette Effect"}
97
  )
98
+
99
  @dataclass
100
  class APISettings:
101
  api_key: str = field(
 
110
  default="https://api.example.com",
111
  metadata={
112
  "label": "API Endpoint",
113
+ "component": "string", # Normal string
114
  "help": "The URL of the API server."
115
  }
116
  )
 
125
  "help": "Quantization mechanism to save VRAM and increase speed."
126
  }
127
  )
 
128
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
129
  default="FP8",
130
  metadata={
 
134
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
135
  }
136
  )
 
137
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
138
  default="FP8",
139
  metadata={
 
143
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
144
  }
145
  )
146
+
147
  @dataclass
148
  class ModelSettings:
149
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
152
  "component": "dropdown",
153
  "label": "Base Model",
154
  "help": "Select the base diffusion model.",
155
+ "visible": True
156
  }
157
  )
158
  custom_model_path: str = field(
 
244
  }
245
  )
246
 
247
+
248
+ @dataclass
249
+ class AdvancedSamplingSettings:
250
+ override_sampler: bool = field(
251
+ default=False,
252
+ metadata={
253
+ "label": "Override Sampler Settings",
254
+ "help": "Enable this to activate special sampler-specific options below."
255
+ }
256
+ )
257
+ custom_noise: float = field(
258
+ default=1.0,
259
+ metadata={
260
+ "component": "slider",
261
+ "label": "Custom Noise Multiplier",
262
+ "minimum": 0.5,
263
+ "maximum": 1.5,
264
+ "step": 0.01,
265
+ "interactive_if": {"field": "override_sampler", "value": True},
266
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
267
+ }
268
+ )
269
+
270
+
271
  @dataclass
272
  class RenderConfig:
273
  api_settings: APISettings = field(
 
297
  default_factory=SamplingSettings,
298
  metadata={"label": "Sampling Settings"}
299
  )
300
+
301
+ advanced_sampling: AdvancedSamplingSettings = field(
302
+ default_factory=AdvancedSamplingSettings,
303
+ metadata={"label": "Advanced Sampling"}
304
+ )
305
+
306
  quantization: QuantizationSettings = field(
307
  default_factory=QuantizationSettings,
308
  metadata={"label": "Quantization Settings"}
 
377
  }
378
  )
379
 
380
+ # --- 2. Data Mappings and Initial Instances ---
381
  initial_render_config = RenderConfig()
382
  initial_env_config = EnvironmentConfig()
383
+ initial_effects_config = EffectsConfig()
384
+
385
  sampler_settings_map_py = {
386
  "Euler": EulerSettings(),
387
  "DPM++ 2M Karras": DPM_Settings(),
 
394
  "Pony": None,
395
  }
396
 
397
+ # --- 3. CSS & JS Injection function ---
 
398
  def inject_assets():
399
  """
400
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
437
  gr.Markdown(
438
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
439
  )
 
440
  effects_state = gr.State(value=initial_effects_config)
441
  render_state = gr.State(value=initial_render_config)
442
  env_state = gr.State(value=initial_env_config)
443
  sidebar_visible = gr.State(False)
444
  with gr.Row():
445
  with gr.Column(scale=3):
446
+ generate_btn = gr.Button("Show Settings", variant="primary")
447
  with gr.Row():
448
  output_render_json = gr.JSON(label="Live Render State")
449
  output_env_json = gr.JSON(label="Live Environment State")
 
502
  if updated_config is None:
503
  return current_state, asdict(current_state), current_state
504
  return updated_config, asdict(updated_config), current_state
505
+
506
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
507
+ if updated_config is None:
508
+ return current_state, asdict(current_state), current_state
509
+ return updated_config, asdict(updated_config), updated_config
510
 
511
+ generate_btn.click(
512
  fn=change_visibility,
513
  inputs=[sidebar_visible, render_state, env_state, effects_state],
514
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
515
  )
516
 
517
  render_sheet.change(
 
524
  inputs=[environment_sheet, env_state],
525
  outputs=[environment_sheet, output_env_json, env_state],
526
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  effects_sheet.change(
528
  fn=handle_effects_change,
529
  inputs=[effects_sheet, effects_state],
530
  outputs=[effects_sheet, output_effects_json, effects_state]
531
  )
532
+
533
+ def on_undo(updated_config, current_state):
534
+ if updated_config is None:
535
+ return current_state, asdict(current_state)
536
+ return updated_config, asdict(updated_config)
537
+
538
+ render_sheet.undo(
539
+ fn=on_undo,
540
+ inputs=[render_sheet, render_state],
541
+ outputs=[render_state, output_render_json]
542
+ )
543
+ environment_sheet.undo(
544
+ fn=on_undo,
545
+ inputs=[environment_sheet, env_state],
546
+ outputs=[env_state, output_env_json],
547
+ )
548
  effects_sheet.undo(
549
+ fn=on_undo,
550
  inputs=[effects_sheet, effects_state],
551
+ outputs=[effects_state, output_effects_json]
552
  )
553
 
554
  demo.load(
 
722
 
723
  if __name__ == "__main__":
724
  demo.launch()
 
725
  ```
726
 
727
  ## `PropertySheet`
app.py CHANGED
@@ -7,10 +7,10 @@ from gradio_propertysheet import PropertySheet
7
  from gradio_htmlinjector import HTMLInjector
8
 
9
 
10
- # --- 1. Dataclass Definitions (unchanged) ---
11
  @dataclass
12
  class EffectBase:
13
- """Classe base com configurações de efeito comuns."""
14
  strength: float = field(
15
  default=0.5,
16
  metadata={
@@ -19,14 +19,14 @@ class EffectBase:
19
  "minimum": 0.0,
20
  "maximum": 1.0,
21
  "step": 0.01,
22
- # Esta regra depende do 'is_active' da classe filha
23
  "interactive_if": {"field": "is_active", "value": True}
24
  }
25
  )
26
 
27
  @dataclass
28
  class EffectSettings(EffectBase):
29
- """Classe filha que adiciona o controle de ativação."""
30
  is_active: bool = field(
31
  default=True,
32
  metadata={"label": "Enable Effect"}
@@ -34,7 +34,7 @@ class EffectSettings(EffectBase):
34
 
35
  @dataclass
36
  class EffectsConfig:
37
- """Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome."""
38
  blur_effect: EffectSettings = field(
39
  default_factory=EffectSettings,
40
  metadata={"label": "Blur Effect"}
@@ -47,6 +47,7 @@ class EffectsConfig:
47
  default_factory=EffectSettings,
48
  metadata={"label": "Vignette Effect"}
49
  )
 
50
  @dataclass
51
  class APISettings:
52
  api_key: str = field(
@@ -61,7 +62,7 @@ class APISettings:
61
  default="https://api.example.com",
62
  metadata={
63
  "label": "API Endpoint",
64
- "component": "string", # string normal
65
  "help": "The URL of the API server."
66
  }
67
  )
@@ -76,7 +77,6 @@ class QuantizationSettings:
76
  "help": "Quantization mechanism to save VRAM and increase speed."
77
  }
78
  )
79
- # Option 1: Literal values
80
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
81
  default="FP8",
82
  metadata={
@@ -86,7 +86,6 @@ class QuantizationSettings:
86
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
87
  }
88
  )
89
- # Option 2: neq operand
90
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
91
  default="FP8",
92
  metadata={
@@ -96,6 +95,7 @@ class QuantizationSettings:
96
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
97
  }
98
  )
 
99
  @dataclass
100
  class ModelSettings:
101
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -104,7 +104,7 @@ class ModelSettings:
104
  "component": "dropdown",
105
  "label": "Base Model",
106
  "help": "Select the base diffusion model.",
107
- "visible": True #change here to test visibility
108
  }
109
  )
110
  custom_model_path: str = field(
@@ -196,6 +196,30 @@ class SamplingSettings:
196
  }
197
  )
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  @dataclass
200
  class RenderConfig:
201
  api_settings: APISettings = field(
@@ -225,6 +249,12 @@ class RenderConfig:
225
  default_factory=SamplingSettings,
226
  metadata={"label": "Sampling Settings"}
227
  )
 
 
 
 
 
 
228
  quantization: QuantizationSettings = field(
229
  default_factory=QuantizationSettings,
230
  metadata={"label": "Quantization Settings"}
@@ -299,9 +329,11 @@ class DPM_Settings:
299
  }
300
  )
301
 
302
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
303
  initial_render_config = RenderConfig()
304
  initial_env_config = EnvironmentConfig()
 
 
305
  sampler_settings_map_py = {
306
  "Euler": EulerSettings(),
307
  "DPM++ 2M Karras": DPM_Settings(),
@@ -314,8 +346,7 @@ model_settings_map_py = {
314
  "Pony": None,
315
  }
316
 
317
-
318
- # --- 3. CSS & JS Injection function (unchanged) ---
319
  def inject_assets():
320
  """
321
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -358,14 +389,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
358
  gr.Markdown(
359
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
360
  )
361
- initial_effects_config = EffectsConfig()
362
  effects_state = gr.State(value=initial_effects_config)
363
  render_state = gr.State(value=initial_render_config)
364
  env_state = gr.State(value=initial_env_config)
365
  sidebar_visible = gr.State(False)
366
  with gr.Row():
367
  with gr.Column(scale=3):
368
- generate = gr.Button("Show Settings", variant="primary")
369
  with gr.Row():
370
  output_render_json = gr.JSON(label="Live Render State")
371
  output_env_json = gr.JSON(label="Live Environment State")
@@ -424,11 +454,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
424
  if updated_config is None:
425
  return current_state, asdict(current_state), current_state
426
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
427
 
428
- generate.click(
429
  fn=change_visibility,
430
  inputs=[sidebar_visible, render_state, env_state, effects_state],
431
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
432
  )
433
 
434
  render_sheet.change(
@@ -441,41 +476,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
441
  inputs=[environment_sheet, env_state],
442
  outputs=[environment_sheet, output_env_json, env_state],
443
  )
444
-
445
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
446
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
447
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
448
- if updated_config is None:
449
- return current_state, asdict(current_state), current_state
450
- return updated_config, asdict(updated_config), current_state
451
-
452
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
453
- if updated_config is None:
454
- return current_state, asdict(current_state), current_state
455
- return updated_config, asdict(updated_config), current_state
456
-
457
- render_sheet.undo(fn=render_undo,
458
- inputs=[render_sheet, render_state],
459
- outputs=[render_sheet, output_render_json, render_state]
460
- )
461
- environment_sheet.undo(fn=environment_undo,
462
- inputs=[environment_sheet, env_state],
463
- outputs=[environment_sheet, output_env_json, env_state],
464
- )
465
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
466
- if updated_config is None:
467
- return current_state, asdict(current_state), current_state
468
- return updated_config, asdict(updated_config), updated_config
469
-
470
  effects_sheet.change(
471
  fn=handle_effects_change,
472
  inputs=[effects_sheet, effects_state],
473
  outputs=[effects_sheet, output_effects_json, effects_state]
474
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  effects_sheet.undo(
476
- fn=handle_effects_change,
477
  inputs=[effects_sheet, effects_state],
478
- outputs=[effects_sheet, output_effects_json, effects_state]
479
  )
480
 
481
  demo.load(
@@ -648,4 +673,4 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
648
  )
649
 
650
  if __name__ == "__main__":
651
- demo.launch()
 
7
  from gradio_htmlinjector import HTMLInjector
8
 
9
 
10
+ # --- 1. Dataclass Definitions ---
11
  @dataclass
12
  class EffectBase:
13
+ """Base class with common effect settings."""
14
  strength: float = field(
15
  default=0.5,
16
  metadata={
 
19
  "minimum": 0.0,
20
  "maximum": 1.0,
21
  "step": 0.01,
22
+ # This rule depends on the 'is_active' field from the child class
23
  "interactive_if": {"field": "is_active", "value": True}
24
  }
25
  )
26
 
27
  @dataclass
28
  class EffectSettings(EffectBase):
29
+ """Child class that adds the activation control."""
30
  is_active: bool = field(
31
  default=True,
32
  metadata={"label": "Enable Effect"}
 
34
 
35
  @dataclass
36
  class EffectsConfig:
37
+ """Main dataclass containing multiple effects with same-named control fields."""
38
  blur_effect: EffectSettings = field(
39
  default_factory=EffectSettings,
40
  metadata={"label": "Blur Effect"}
 
47
  default_factory=EffectSettings,
48
  metadata={"label": "Vignette Effect"}
49
  )
50
+
51
  @dataclass
52
  class APISettings:
53
  api_key: str = field(
 
62
  default="https://api.example.com",
63
  metadata={
64
  "label": "API Endpoint",
65
+ "component": "string", # Normal string
66
  "help": "The URL of the API server."
67
  }
68
  )
 
77
  "help": "Quantization mechanism to save VRAM and increase speed."
78
  }
79
  )
 
80
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
81
  default="FP8",
82
  metadata={
 
86
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
87
  }
88
  )
 
89
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
90
  default="FP8",
91
  metadata={
 
95
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
96
  }
97
  )
98
+
99
  @dataclass
100
  class ModelSettings:
101
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
104
  "component": "dropdown",
105
  "label": "Base Model",
106
  "help": "Select the base diffusion model.",
107
+ "visible": True
108
  }
109
  )
110
  custom_model_path: str = field(
 
196
  }
197
  )
198
 
199
+
200
+ @dataclass
201
+ class AdvancedSamplingSettings:
202
+ override_sampler: bool = field(
203
+ default=False,
204
+ metadata={
205
+ "label": "Override Sampler Settings",
206
+ "help": "Enable this to activate special sampler-specific options below."
207
+ }
208
+ )
209
+ custom_noise: float = field(
210
+ default=1.0,
211
+ metadata={
212
+ "component": "slider",
213
+ "label": "Custom Noise Multiplier",
214
+ "minimum": 0.5,
215
+ "maximum": 1.5,
216
+ "step": 0.01,
217
+ "interactive_if": {"field": "override_sampler", "value": True},
218
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
219
+ }
220
+ )
221
+
222
+
223
  @dataclass
224
  class RenderConfig:
225
  api_settings: APISettings = field(
 
249
  default_factory=SamplingSettings,
250
  metadata={"label": "Sampling Settings"}
251
  )
252
+
253
+ advanced_sampling: AdvancedSamplingSettings = field(
254
+ default_factory=AdvancedSamplingSettings,
255
+ metadata={"label": "Advanced Sampling"}
256
+ )
257
+
258
  quantization: QuantizationSettings = field(
259
  default_factory=QuantizationSettings,
260
  metadata={"label": "Quantization Settings"}
 
329
  }
330
  )
331
 
332
+ # --- 2. Data Mappings and Initial Instances ---
333
  initial_render_config = RenderConfig()
334
  initial_env_config = EnvironmentConfig()
335
+ initial_effects_config = EffectsConfig()
336
+
337
  sampler_settings_map_py = {
338
  "Euler": EulerSettings(),
339
  "DPM++ 2M Karras": DPM_Settings(),
 
346
  "Pony": None,
347
  }
348
 
349
+ # --- 3. CSS & JS Injection function ---
 
350
  def inject_assets():
351
  """
352
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
389
  gr.Markdown(
390
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
391
  )
 
392
  effects_state = gr.State(value=initial_effects_config)
393
  render_state = gr.State(value=initial_render_config)
394
  env_state = gr.State(value=initial_env_config)
395
  sidebar_visible = gr.State(False)
396
  with gr.Row():
397
  with gr.Column(scale=3):
398
+ generate_btn = gr.Button("Show Settings", variant="primary")
399
  with gr.Row():
400
  output_render_json = gr.JSON(label="Live Render State")
401
  output_env_json = gr.JSON(label="Live Environment State")
 
454
  if updated_config is None:
455
  return current_state, asdict(current_state), current_state
456
  return updated_config, asdict(updated_config), current_state
457
+
458
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
459
+ if updated_config is None:
460
+ return current_state, asdict(current_state), current_state
461
+ return updated_config, asdict(updated_config), updated_config
462
 
463
+ generate_btn.click(
464
  fn=change_visibility,
465
  inputs=[sidebar_visible, render_state, env_state, effects_state],
466
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
467
  )
468
 
469
  render_sheet.change(
 
476
  inputs=[environment_sheet, env_state],
477
  outputs=[environment_sheet, output_env_json, env_state],
478
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  effects_sheet.change(
480
  fn=handle_effects_change,
481
  inputs=[effects_sheet, effects_state],
482
  outputs=[effects_sheet, output_effects_json, effects_state]
483
  )
484
+
485
+ def on_undo(updated_config, current_state):
486
+ if updated_config is None:
487
+ return current_state, asdict(current_state)
488
+ return updated_config, asdict(updated_config)
489
+
490
+ render_sheet.undo(
491
+ fn=on_undo,
492
+ inputs=[render_sheet, render_state],
493
+ outputs=[render_state, output_render_json]
494
+ )
495
+ environment_sheet.undo(
496
+ fn=on_undo,
497
+ inputs=[environment_sheet, env_state],
498
+ outputs=[env_state, output_env_json],
499
+ )
500
  effects_sheet.undo(
501
+ fn=on_undo,
502
  inputs=[effects_sheet, effects_state],
503
+ outputs=[effects_state, output_effects_json]
504
  )
505
 
506
  demo.load(
 
673
  )
674
 
675
  if __name__ == "__main__":
676
+ demo.launch()
space.py CHANGED
@@ -47,10 +47,10 @@ from gradio_propertysheet import PropertySheet
47
  from gradio_htmlinjector import HTMLInjector
48
 
49
 
50
- # --- 1. Dataclass Definitions (unchanged) ---
51
  @dataclass
52
  class EffectBase:
53
- \"\"\"Classe base com configurações de efeito comuns.\"\"\"
54
  strength: float = field(
55
  default=0.5,
56
  metadata={
@@ -59,14 +59,14 @@ class EffectBase:
59
  "minimum": 0.0,
60
  "maximum": 1.0,
61
  "step": 0.01,
62
- # Esta regra depende do 'is_active' da classe filha
63
  "interactive_if": {"field": "is_active", "value": True}
64
  }
65
  )
66
 
67
  @dataclass
68
  class EffectSettings(EffectBase):
69
- \"\"\"Classe filha que adiciona o controle de ativação.\"\"\"
70
  is_active: bool = field(
71
  default=True,
72
  metadata={"label": "Enable Effect"}
@@ -74,7 +74,7 @@ class EffectSettings(EffectBase):
74
 
75
  @dataclass
76
  class EffectsConfig:
77
- \"\"\"Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome.\"\"\"
78
  blur_effect: EffectSettings = field(
79
  default_factory=EffectSettings,
80
  metadata={"label": "Blur Effect"}
@@ -87,6 +87,7 @@ class EffectsConfig:
87
  default_factory=EffectSettings,
88
  metadata={"label": "Vignette Effect"}
89
  )
 
90
  @dataclass
91
  class APISettings:
92
  api_key: str = field(
@@ -101,7 +102,7 @@ class APISettings:
101
  default="https://api.example.com",
102
  metadata={
103
  "label": "API Endpoint",
104
- "component": "string", # string normal
105
  "help": "The URL of the API server."
106
  }
107
  )
@@ -116,7 +117,6 @@ class QuantizationSettings:
116
  "help": "Quantization mechanism to save VRAM and increase speed."
117
  }
118
  )
119
- # Option 1: Literal values
120
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
121
  default="FP8",
122
  metadata={
@@ -126,7 +126,6 @@ class QuantizationSettings:
126
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
127
  }
128
  )
129
- # Option 2: neq operand
130
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
131
  default="FP8",
132
  metadata={
@@ -136,6 +135,7 @@ class QuantizationSettings:
136
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
137
  }
138
  )
 
139
  @dataclass
140
  class ModelSettings:
141
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -144,7 +144,7 @@ class ModelSettings:
144
  "component": "dropdown",
145
  "label": "Base Model",
146
  "help": "Select the base diffusion model.",
147
- "visible": True #change here to test visibility
148
  }
149
  )
150
  custom_model_path: str = field(
@@ -236,6 +236,30 @@ class SamplingSettings:
236
  }
237
  )
238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  @dataclass
240
  class RenderConfig:
241
  api_settings: APISettings = field(
@@ -265,6 +289,12 @@ class RenderConfig:
265
  default_factory=SamplingSettings,
266
  metadata={"label": "Sampling Settings"}
267
  )
 
 
 
 
 
 
268
  quantization: QuantizationSettings = field(
269
  default_factory=QuantizationSettings,
270
  metadata={"label": "Quantization Settings"}
@@ -339,9 +369,11 @@ class DPM_Settings:
339
  }
340
  )
341
 
342
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
343
  initial_render_config = RenderConfig()
344
  initial_env_config = EnvironmentConfig()
 
 
345
  sampler_settings_map_py = {
346
  "Euler": EulerSettings(),
347
  "DPM++ 2M Karras": DPM_Settings(),
@@ -354,8 +386,7 @@ model_settings_map_py = {
354
  "Pony": None,
355
  }
356
 
357
-
358
- # --- 3. CSS & JS Injection function (unchanged) ---
359
  def inject_assets():
360
  \"\"\"
361
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -398,14 +429,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
398
  gr.Markdown(
399
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
400
  )
401
- initial_effects_config = EffectsConfig()
402
  effects_state = gr.State(value=initial_effects_config)
403
  render_state = gr.State(value=initial_render_config)
404
  env_state = gr.State(value=initial_env_config)
405
  sidebar_visible = gr.State(False)
406
  with gr.Row():
407
  with gr.Column(scale=3):
408
- generate = gr.Button("Show Settings", variant="primary")
409
  with gr.Row():
410
  output_render_json = gr.JSON(label="Live Render State")
411
  output_env_json = gr.JSON(label="Live Environment State")
@@ -464,11 +494,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
464
  if updated_config is None:
465
  return current_state, asdict(current_state), current_state
466
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
467
 
468
- generate.click(
469
  fn=change_visibility,
470
  inputs=[sidebar_visible, render_state, env_state, effects_state],
471
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
472
  )
473
 
474
  render_sheet.change(
@@ -481,41 +516,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
481
  inputs=[environment_sheet, env_state],
482
  outputs=[environment_sheet, output_env_json, env_state],
483
  )
484
-
485
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
486
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
487
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
488
- if updated_config is None:
489
- return current_state, asdict(current_state), current_state
490
- return updated_config, asdict(updated_config), current_state
491
-
492
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
493
- if updated_config is None:
494
- return current_state, asdict(current_state), current_state
495
- return updated_config, asdict(updated_config), current_state
496
-
497
- render_sheet.undo(fn=render_undo,
498
- inputs=[render_sheet, render_state],
499
- outputs=[render_sheet, output_render_json, render_state]
500
- )
501
- environment_sheet.undo(fn=environment_undo,
502
- inputs=[environment_sheet, env_state],
503
- outputs=[environment_sheet, output_env_json, env_state],
504
- )
505
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
506
- if updated_config is None:
507
- return current_state, asdict(current_state), current_state
508
- return updated_config, asdict(updated_config), updated_config
509
-
510
  effects_sheet.change(
511
  fn=handle_effects_change,
512
  inputs=[effects_sheet, effects_state],
513
  outputs=[effects_sheet, output_effects_json, effects_state]
514
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  effects_sheet.undo(
516
- fn=handle_effects_change,
517
  inputs=[effects_sheet, effects_state],
518
- outputs=[effects_sheet, output_effects_json, effects_state]
519
  )
520
 
521
  demo.load(
@@ -689,7 +714,6 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
689
 
690
  if __name__ == "__main__":
691
  demo.launch()
692
-
693
  ```
694
  """, elem_classes=["md-custom"], header_links=True)
695
 
 
47
  from gradio_htmlinjector import HTMLInjector
48
 
49
 
50
+ # --- 1. Dataclass Definitions ---
51
  @dataclass
52
  class EffectBase:
53
+ \"\"\"Base class with common effect settings.\"\"\"
54
  strength: float = field(
55
  default=0.5,
56
  metadata={
 
59
  "minimum": 0.0,
60
  "maximum": 1.0,
61
  "step": 0.01,
62
+ # This rule depends on the 'is_active' field from the child class
63
  "interactive_if": {"field": "is_active", "value": True}
64
  }
65
  )
66
 
67
  @dataclass
68
  class EffectSettings(EffectBase):
69
+ \"\"\"Child class that adds the activation control.\"\"\"
70
  is_active: bool = field(
71
  default=True,
72
  metadata={"label": "Enable Effect"}
 
74
 
75
  @dataclass
76
  class EffectsConfig:
77
+ \"\"\"Main dataclass containing multiple effects with same-named control fields.\"\"\"
78
  blur_effect: EffectSettings = field(
79
  default_factory=EffectSettings,
80
  metadata={"label": "Blur Effect"}
 
87
  default_factory=EffectSettings,
88
  metadata={"label": "Vignette Effect"}
89
  )
90
+
91
  @dataclass
92
  class APISettings:
93
  api_key: str = field(
 
102
  default="https://api.example.com",
103
  metadata={
104
  "label": "API Endpoint",
105
+ "component": "string", # Normal string
106
  "help": "The URL of the API server."
107
  }
108
  )
 
117
  "help": "Quantization mechanism to save VRAM and increase speed."
118
  }
119
  )
 
120
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
121
  default="FP8",
122
  metadata={
 
126
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
127
  }
128
  )
 
129
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
130
  default="FP8",
131
  metadata={
 
135
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
136
  }
137
  )
138
+
139
  @dataclass
140
  class ModelSettings:
141
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
144
  "component": "dropdown",
145
  "label": "Base Model",
146
  "help": "Select the base diffusion model.",
147
+ "visible": True
148
  }
149
  )
150
  custom_model_path: str = field(
 
236
  }
237
  )
238
 
239
+
240
+ @dataclass
241
+ class AdvancedSamplingSettings:
242
+ override_sampler: bool = field(
243
+ default=False,
244
+ metadata={
245
+ "label": "Override Sampler Settings",
246
+ "help": "Enable this to activate special sampler-specific options below."
247
+ }
248
+ )
249
+ custom_noise: float = field(
250
+ default=1.0,
251
+ metadata={
252
+ "component": "slider",
253
+ "label": "Custom Noise Multiplier",
254
+ "minimum": 0.5,
255
+ "maximum": 1.5,
256
+ "step": 0.01,
257
+ "interactive_if": {"field": "override_sampler", "value": True},
258
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
259
+ }
260
+ )
261
+
262
+
263
  @dataclass
264
  class RenderConfig:
265
  api_settings: APISettings = field(
 
289
  default_factory=SamplingSettings,
290
  metadata={"label": "Sampling Settings"}
291
  )
292
+
293
+ advanced_sampling: AdvancedSamplingSettings = field(
294
+ default_factory=AdvancedSamplingSettings,
295
+ metadata={"label": "Advanced Sampling"}
296
+ )
297
+
298
  quantization: QuantizationSettings = field(
299
  default_factory=QuantizationSettings,
300
  metadata={"label": "Quantization Settings"}
 
369
  }
370
  )
371
 
372
+ # --- 2. Data Mappings and Initial Instances ---
373
  initial_render_config = RenderConfig()
374
  initial_env_config = EnvironmentConfig()
375
+ initial_effects_config = EffectsConfig()
376
+
377
  sampler_settings_map_py = {
378
  "Euler": EulerSettings(),
379
  "DPM++ 2M Karras": DPM_Settings(),
 
386
  "Pony": None,
387
  }
388
 
389
+ # --- 3. CSS & JS Injection function ---
 
390
  def inject_assets():
391
  \"\"\"
392
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
429
  gr.Markdown(
430
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
431
  )
 
432
  effects_state = gr.State(value=initial_effects_config)
433
  render_state = gr.State(value=initial_render_config)
434
  env_state = gr.State(value=initial_env_config)
435
  sidebar_visible = gr.State(False)
436
  with gr.Row():
437
  with gr.Column(scale=3):
438
+ generate_btn = gr.Button("Show Settings", variant="primary")
439
  with gr.Row():
440
  output_render_json = gr.JSON(label="Live Render State")
441
  output_env_json = gr.JSON(label="Live Environment State")
 
494
  if updated_config is None:
495
  return current_state, asdict(current_state), current_state
496
  return updated_config, asdict(updated_config), current_state
497
+
498
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
499
+ if updated_config is None:
500
+ return current_state, asdict(current_state), current_state
501
+ return updated_config, asdict(updated_config), updated_config
502
 
503
+ generate_btn.click(
504
  fn=change_visibility,
505
  inputs=[sidebar_visible, render_state, env_state, effects_state],
506
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
507
  )
508
 
509
  render_sheet.change(
 
516
  inputs=[environment_sheet, env_state],
517
  outputs=[environment_sheet, output_env_json, env_state],
518
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  effects_sheet.change(
520
  fn=handle_effects_change,
521
  inputs=[effects_sheet, effects_state],
522
  outputs=[effects_sheet, output_effects_json, effects_state]
523
  )
524
+
525
+ def on_undo(updated_config, current_state):
526
+ if updated_config is None:
527
+ return current_state, asdict(current_state)
528
+ return updated_config, asdict(updated_config)
529
+
530
+ render_sheet.undo(
531
+ fn=on_undo,
532
+ inputs=[render_sheet, render_state],
533
+ outputs=[render_state, output_render_json]
534
+ )
535
+ environment_sheet.undo(
536
+ fn=on_undo,
537
+ inputs=[environment_sheet, env_state],
538
+ outputs=[env_state, output_env_json],
539
+ )
540
  effects_sheet.undo(
541
+ fn=on_undo,
542
  inputs=[effects_sheet, effects_state],
543
+ outputs=[effects_state, output_effects_json]
544
  )
545
 
546
  demo.load(
 
714
 
715
  if __name__ == "__main__":
716
  demo.launch()
 
717
  ```
718
  """, elem_classes=["md-custom"], header_links=True)
719
 
src/README.md CHANGED
@@ -55,10 +55,10 @@ from gradio_propertysheet import PropertySheet
55
  from gradio_htmlinjector import HTMLInjector
56
 
57
 
58
- # --- 1. Dataclass Definitions (unchanged) ---
59
  @dataclass
60
  class EffectBase:
61
- """Classe base com configurações de efeito comuns."""
62
  strength: float = field(
63
  default=0.5,
64
  metadata={
@@ -67,14 +67,14 @@ class EffectBase:
67
  "minimum": 0.0,
68
  "maximum": 1.0,
69
  "step": 0.01,
70
- # Esta regra depende do 'is_active' da classe filha
71
  "interactive_if": {"field": "is_active", "value": True}
72
  }
73
  )
74
 
75
  @dataclass
76
  class EffectSettings(EffectBase):
77
- """Classe filha que adiciona o controle de ativação."""
78
  is_active: bool = field(
79
  default=True,
80
  metadata={"label": "Enable Effect"}
@@ -82,7 +82,7 @@ class EffectSettings(EffectBase):
82
 
83
  @dataclass
84
  class EffectsConfig:
85
- """Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome."""
86
  blur_effect: EffectSettings = field(
87
  default_factory=EffectSettings,
88
  metadata={"label": "Blur Effect"}
@@ -95,6 +95,7 @@ class EffectsConfig:
95
  default_factory=EffectSettings,
96
  metadata={"label": "Vignette Effect"}
97
  )
 
98
  @dataclass
99
  class APISettings:
100
  api_key: str = field(
@@ -109,7 +110,7 @@ class APISettings:
109
  default="https://api.example.com",
110
  metadata={
111
  "label": "API Endpoint",
112
- "component": "string", # string normal
113
  "help": "The URL of the API server."
114
  }
115
  )
@@ -124,7 +125,6 @@ class QuantizationSettings:
124
  "help": "Quantization mechanism to save VRAM and increase speed."
125
  }
126
  )
127
- # Option 1: Literal values
128
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
129
  default="FP8",
130
  metadata={
@@ -134,7 +134,6 @@ class QuantizationSettings:
134
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
135
  }
136
  )
137
- # Option 2: neq operand
138
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
139
  default="FP8",
140
  metadata={
@@ -144,6 +143,7 @@ class QuantizationSettings:
144
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
145
  }
146
  )
 
147
  @dataclass
148
  class ModelSettings:
149
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -152,7 +152,7 @@ class ModelSettings:
152
  "component": "dropdown",
153
  "label": "Base Model",
154
  "help": "Select the base diffusion model.",
155
- "visible": True #change here to test visibility
156
  }
157
  )
158
  custom_model_path: str = field(
@@ -244,6 +244,30 @@ class SamplingSettings:
244
  }
245
  )
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  @dataclass
248
  class RenderConfig:
249
  api_settings: APISettings = field(
@@ -273,6 +297,12 @@ class RenderConfig:
273
  default_factory=SamplingSettings,
274
  metadata={"label": "Sampling Settings"}
275
  )
 
 
 
 
 
 
276
  quantization: QuantizationSettings = field(
277
  default_factory=QuantizationSettings,
278
  metadata={"label": "Quantization Settings"}
@@ -347,9 +377,11 @@ class DPM_Settings:
347
  }
348
  )
349
 
350
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
351
  initial_render_config = RenderConfig()
352
  initial_env_config = EnvironmentConfig()
 
 
353
  sampler_settings_map_py = {
354
  "Euler": EulerSettings(),
355
  "DPM++ 2M Karras": DPM_Settings(),
@@ -362,8 +394,7 @@ model_settings_map_py = {
362
  "Pony": None,
363
  }
364
 
365
-
366
- # --- 3. CSS & JS Injection function (unchanged) ---
367
  def inject_assets():
368
  """
369
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -406,14 +437,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
406
  gr.Markdown(
407
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
408
  )
409
- initial_effects_config = EffectsConfig()
410
  effects_state = gr.State(value=initial_effects_config)
411
  render_state = gr.State(value=initial_render_config)
412
  env_state = gr.State(value=initial_env_config)
413
  sidebar_visible = gr.State(False)
414
  with gr.Row():
415
  with gr.Column(scale=3):
416
- generate = gr.Button("Show Settings", variant="primary")
417
  with gr.Row():
418
  output_render_json = gr.JSON(label="Live Render State")
419
  output_env_json = gr.JSON(label="Live Environment State")
@@ -472,11 +502,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
472
  if updated_config is None:
473
  return current_state, asdict(current_state), current_state
474
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
475
 
476
- generate.click(
477
  fn=change_visibility,
478
  inputs=[sidebar_visible, render_state, env_state, effects_state],
479
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
480
  )
481
 
482
  render_sheet.change(
@@ -489,41 +524,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
489
  inputs=[environment_sheet, env_state],
490
  outputs=[environment_sheet, output_env_json, env_state],
491
  )
492
-
493
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
494
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
495
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
496
- if updated_config is None:
497
- return current_state, asdict(current_state), current_state
498
- return updated_config, asdict(updated_config), current_state
499
-
500
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
501
- if updated_config is None:
502
- return current_state, asdict(current_state), current_state
503
- return updated_config, asdict(updated_config), current_state
504
-
505
- render_sheet.undo(fn=render_undo,
506
- inputs=[render_sheet, render_state],
507
- outputs=[render_sheet, output_render_json, render_state]
508
- )
509
- environment_sheet.undo(fn=environment_undo,
510
- inputs=[environment_sheet, env_state],
511
- outputs=[environment_sheet, output_env_json, env_state],
512
- )
513
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
514
- if updated_config is None:
515
- return current_state, asdict(current_state), current_state
516
- return updated_config, asdict(updated_config), updated_config
517
-
518
  effects_sheet.change(
519
  fn=handle_effects_change,
520
  inputs=[effects_sheet, effects_state],
521
  outputs=[effects_sheet, output_effects_json, effects_state]
522
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  effects_sheet.undo(
524
- fn=handle_effects_change,
525
  inputs=[effects_sheet, effects_state],
526
- outputs=[effects_sheet, output_effects_json, effects_state]
527
  )
528
 
529
  demo.load(
@@ -697,7 +722,6 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
697
 
698
  if __name__ == "__main__":
699
  demo.launch()
700
-
701
  ```
702
 
703
  ## `PropertySheet`
 
55
  from gradio_htmlinjector import HTMLInjector
56
 
57
 
58
+ # --- 1. Dataclass Definitions ---
59
  @dataclass
60
  class EffectBase:
61
+ """Base class with common effect settings."""
62
  strength: float = field(
63
  default=0.5,
64
  metadata={
 
67
  "minimum": 0.0,
68
  "maximum": 1.0,
69
  "step": 0.01,
70
+ # This rule depends on the 'is_active' field from the child class
71
  "interactive_if": {"field": "is_active", "value": True}
72
  }
73
  )
74
 
75
  @dataclass
76
  class EffectSettings(EffectBase):
77
+ """Child class that adds the activation control."""
78
  is_active: bool = field(
79
  default=True,
80
  metadata={"label": "Enable Effect"}
 
82
 
83
  @dataclass
84
  class EffectsConfig:
85
+ """Main dataclass containing multiple effects with same-named control fields."""
86
  blur_effect: EffectSettings = field(
87
  default_factory=EffectSettings,
88
  metadata={"label": "Blur Effect"}
 
95
  default_factory=EffectSettings,
96
  metadata={"label": "Vignette Effect"}
97
  )
98
+
99
  @dataclass
100
  class APISettings:
101
  api_key: str = field(
 
110
  default="https://api.example.com",
111
  metadata={
112
  "label": "API Endpoint",
113
+ "component": "string", # Normal string
114
  "help": "The URL of the API server."
115
  }
116
  )
 
125
  "help": "Quantization mechanism to save VRAM and increase speed."
126
  }
127
  )
 
128
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
129
  default="FP8",
130
  metadata={
 
134
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
135
  }
136
  )
 
137
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
138
  default="FP8",
139
  metadata={
 
143
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
144
  }
145
  )
146
+
147
  @dataclass
148
  class ModelSettings:
149
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
152
  "component": "dropdown",
153
  "label": "Base Model",
154
  "help": "Select the base diffusion model.",
155
+ "visible": True
156
  }
157
  )
158
  custom_model_path: str = field(
 
244
  }
245
  )
246
 
247
+
248
+ @dataclass
249
+ class AdvancedSamplingSettings:
250
+ override_sampler: bool = field(
251
+ default=False,
252
+ metadata={
253
+ "label": "Override Sampler Settings",
254
+ "help": "Enable this to activate special sampler-specific options below."
255
+ }
256
+ )
257
+ custom_noise: float = field(
258
+ default=1.0,
259
+ metadata={
260
+ "component": "slider",
261
+ "label": "Custom Noise Multiplier",
262
+ "minimum": 0.5,
263
+ "maximum": 1.5,
264
+ "step": 0.01,
265
+ "interactive_if": {"field": "override_sampler", "value": True},
266
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
267
+ }
268
+ )
269
+
270
+
271
  @dataclass
272
  class RenderConfig:
273
  api_settings: APISettings = field(
 
297
  default_factory=SamplingSettings,
298
  metadata={"label": "Sampling Settings"}
299
  )
300
+
301
+ advanced_sampling: AdvancedSamplingSettings = field(
302
+ default_factory=AdvancedSamplingSettings,
303
+ metadata={"label": "Advanced Sampling"}
304
+ )
305
+
306
  quantization: QuantizationSettings = field(
307
  default_factory=QuantizationSettings,
308
  metadata={"label": "Quantization Settings"}
 
377
  }
378
  )
379
 
380
+ # --- 2. Data Mappings and Initial Instances ---
381
  initial_render_config = RenderConfig()
382
  initial_env_config = EnvironmentConfig()
383
+ initial_effects_config = EffectsConfig()
384
+
385
  sampler_settings_map_py = {
386
  "Euler": EulerSettings(),
387
  "DPM++ 2M Karras": DPM_Settings(),
 
394
  "Pony": None,
395
  }
396
 
397
+ # --- 3. CSS & JS Injection function ---
 
398
  def inject_assets():
399
  """
400
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
437
  gr.Markdown(
438
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
439
  )
 
440
  effects_state = gr.State(value=initial_effects_config)
441
  render_state = gr.State(value=initial_render_config)
442
  env_state = gr.State(value=initial_env_config)
443
  sidebar_visible = gr.State(False)
444
  with gr.Row():
445
  with gr.Column(scale=3):
446
+ generate_btn = gr.Button("Show Settings", variant="primary")
447
  with gr.Row():
448
  output_render_json = gr.JSON(label="Live Render State")
449
  output_env_json = gr.JSON(label="Live Environment State")
 
502
  if updated_config is None:
503
  return current_state, asdict(current_state), current_state
504
  return updated_config, asdict(updated_config), current_state
505
+
506
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
507
+ if updated_config is None:
508
+ return current_state, asdict(current_state), current_state
509
+ return updated_config, asdict(updated_config), updated_config
510
 
511
+ generate_btn.click(
512
  fn=change_visibility,
513
  inputs=[sidebar_visible, render_state, env_state, effects_state],
514
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
515
  )
516
 
517
  render_sheet.change(
 
524
  inputs=[environment_sheet, env_state],
525
  outputs=[environment_sheet, output_env_json, env_state],
526
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  effects_sheet.change(
528
  fn=handle_effects_change,
529
  inputs=[effects_sheet, effects_state],
530
  outputs=[effects_sheet, output_effects_json, effects_state]
531
  )
532
+
533
+ def on_undo(updated_config, current_state):
534
+ if updated_config is None:
535
+ return current_state, asdict(current_state)
536
+ return updated_config, asdict(updated_config)
537
+
538
+ render_sheet.undo(
539
+ fn=on_undo,
540
+ inputs=[render_sheet, render_state],
541
+ outputs=[render_state, output_render_json]
542
+ )
543
+ environment_sheet.undo(
544
+ fn=on_undo,
545
+ inputs=[environment_sheet, env_state],
546
+ outputs=[env_state, output_env_json],
547
+ )
548
  effects_sheet.undo(
549
+ fn=on_undo,
550
  inputs=[effects_sheet, effects_state],
551
+ outputs=[effects_state, output_effects_json]
552
  )
553
 
554
  demo.load(
 
722
 
723
  if __name__ == "__main__":
724
  demo.launch()
 
725
  ```
726
 
727
  ## `PropertySheet`
src/demo/app.py CHANGED
@@ -7,10 +7,10 @@ from gradio_propertysheet import PropertySheet
7
  from gradio_htmlinjector import HTMLInjector
8
 
9
 
10
- # --- 1. Dataclass Definitions (unchanged) ---
11
  @dataclass
12
  class EffectBase:
13
- """Classe base com configurações de efeito comuns."""
14
  strength: float = field(
15
  default=0.5,
16
  metadata={
@@ -19,14 +19,14 @@ class EffectBase:
19
  "minimum": 0.0,
20
  "maximum": 1.0,
21
  "step": 0.01,
22
- # Esta regra depende do 'is_active' da classe filha
23
  "interactive_if": {"field": "is_active", "value": True}
24
  }
25
  )
26
 
27
  @dataclass
28
  class EffectSettings(EffectBase):
29
- """Classe filha que adiciona o controle de ativação."""
30
  is_active: bool = field(
31
  default=True,
32
  metadata={"label": "Enable Effect"}
@@ -34,7 +34,7 @@ class EffectSettings(EffectBase):
34
 
35
  @dataclass
36
  class EffectsConfig:
37
- """Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome."""
38
  blur_effect: EffectSettings = field(
39
  default_factory=EffectSettings,
40
  metadata={"label": "Blur Effect"}
@@ -47,6 +47,7 @@ class EffectsConfig:
47
  default_factory=EffectSettings,
48
  metadata={"label": "Vignette Effect"}
49
  )
 
50
  @dataclass
51
  class APISettings:
52
  api_key: str = field(
@@ -61,7 +62,7 @@ class APISettings:
61
  default="https://api.example.com",
62
  metadata={
63
  "label": "API Endpoint",
64
- "component": "string", # string normal
65
  "help": "The URL of the API server."
66
  }
67
  )
@@ -76,7 +77,6 @@ class QuantizationSettings:
76
  "help": "Quantization mechanism to save VRAM and increase speed."
77
  }
78
  )
79
- # Option 1: Literal values
80
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
81
  default="FP8",
82
  metadata={
@@ -86,7 +86,6 @@ class QuantizationSettings:
86
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
87
  }
88
  )
89
- # Option 2: neq operand
90
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
91
  default="FP8",
92
  metadata={
@@ -96,6 +95,7 @@ class QuantizationSettings:
96
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
97
  }
98
  )
 
99
  @dataclass
100
  class ModelSettings:
101
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -104,7 +104,7 @@ class ModelSettings:
104
  "component": "dropdown",
105
  "label": "Base Model",
106
  "help": "Select the base diffusion model.",
107
- "visible": True #change here to test visibility
108
  }
109
  )
110
  custom_model_path: str = field(
@@ -196,6 +196,30 @@ class SamplingSettings:
196
  }
197
  )
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  @dataclass
200
  class RenderConfig:
201
  api_settings: APISettings = field(
@@ -225,6 +249,12 @@ class RenderConfig:
225
  default_factory=SamplingSettings,
226
  metadata={"label": "Sampling Settings"}
227
  )
 
 
 
 
 
 
228
  quantization: QuantizationSettings = field(
229
  default_factory=QuantizationSettings,
230
  metadata={"label": "Quantization Settings"}
@@ -299,9 +329,11 @@ class DPM_Settings:
299
  }
300
  )
301
 
302
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
303
  initial_render_config = RenderConfig()
304
  initial_env_config = EnvironmentConfig()
 
 
305
  sampler_settings_map_py = {
306
  "Euler": EulerSettings(),
307
  "DPM++ 2M Karras": DPM_Settings(),
@@ -314,8 +346,7 @@ model_settings_map_py = {
314
  "Pony": None,
315
  }
316
 
317
-
318
- # --- 3. CSS & JS Injection function (unchanged) ---
319
  def inject_assets():
320
  """
321
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -358,14 +389,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
358
  gr.Markdown(
359
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
360
  )
361
- initial_effects_config = EffectsConfig()
362
  effects_state = gr.State(value=initial_effects_config)
363
  render_state = gr.State(value=initial_render_config)
364
  env_state = gr.State(value=initial_env_config)
365
  sidebar_visible = gr.State(False)
366
  with gr.Row():
367
  with gr.Column(scale=3):
368
- generate = gr.Button("Show Settings", variant="primary")
369
  with gr.Row():
370
  output_render_json = gr.JSON(label="Live Render State")
371
  output_env_json = gr.JSON(label="Live Environment State")
@@ -424,11 +454,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
424
  if updated_config is None:
425
  return current_state, asdict(current_state), current_state
426
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
427
 
428
- generate.click(
429
  fn=change_visibility,
430
  inputs=[sidebar_visible, render_state, env_state, effects_state],
431
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
432
  )
433
 
434
  render_sheet.change(
@@ -441,41 +476,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
441
  inputs=[environment_sheet, env_state],
442
  outputs=[environment_sheet, output_env_json, env_state],
443
  )
444
-
445
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
446
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
447
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
448
- if updated_config is None:
449
- return current_state, asdict(current_state), current_state
450
- return updated_config, asdict(updated_config), current_state
451
-
452
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
453
- if updated_config is None:
454
- return current_state, asdict(current_state), current_state
455
- return updated_config, asdict(updated_config), current_state
456
-
457
- render_sheet.undo(fn=render_undo,
458
- inputs=[render_sheet, render_state],
459
- outputs=[render_sheet, output_render_json, render_state]
460
- )
461
- environment_sheet.undo(fn=environment_undo,
462
- inputs=[environment_sheet, env_state],
463
- outputs=[environment_sheet, output_env_json, env_state],
464
- )
465
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
466
- if updated_config is None:
467
- return current_state, asdict(current_state), current_state
468
- return updated_config, asdict(updated_config), updated_config
469
-
470
  effects_sheet.change(
471
  fn=handle_effects_change,
472
  inputs=[effects_sheet, effects_state],
473
  outputs=[effects_sheet, output_effects_json, effects_state]
474
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  effects_sheet.undo(
476
- fn=handle_effects_change,
477
  inputs=[effects_sheet, effects_state],
478
- outputs=[effects_sheet, output_effects_json, effects_state]
479
  )
480
 
481
  demo.load(
@@ -648,4 +673,4 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
648
  )
649
 
650
  if __name__ == "__main__":
651
- demo.launch()
 
7
  from gradio_htmlinjector import HTMLInjector
8
 
9
 
10
+ # --- 1. Dataclass Definitions ---
11
  @dataclass
12
  class EffectBase:
13
+ """Base class with common effect settings."""
14
  strength: float = field(
15
  default=0.5,
16
  metadata={
 
19
  "minimum": 0.0,
20
  "maximum": 1.0,
21
  "step": 0.01,
22
+ # This rule depends on the 'is_active' field from the child class
23
  "interactive_if": {"field": "is_active", "value": True}
24
  }
25
  )
26
 
27
  @dataclass
28
  class EffectSettings(EffectBase):
29
+ """Child class that adds the activation control."""
30
  is_active: bool = field(
31
  default=True,
32
  metadata={"label": "Enable Effect"}
 
34
 
35
  @dataclass
36
  class EffectsConfig:
37
+ """Main dataclass containing multiple effects with same-named control fields."""
38
  blur_effect: EffectSettings = field(
39
  default_factory=EffectSettings,
40
  metadata={"label": "Blur Effect"}
 
47
  default_factory=EffectSettings,
48
  metadata={"label": "Vignette Effect"}
49
  )
50
+
51
  @dataclass
52
  class APISettings:
53
  api_key: str = field(
 
62
  default="https://api.example.com",
63
  metadata={
64
  "label": "API Endpoint",
65
+ "component": "string", # Normal string
66
  "help": "The URL of the API server."
67
  }
68
  )
 
77
  "help": "Quantization mechanism to save VRAM and increase speed."
78
  }
79
  )
 
80
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
81
  default="FP8",
82
  metadata={
 
86
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
87
  }
88
  )
 
89
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
90
  default="FP8",
91
  metadata={
 
95
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
96
  }
97
  )
98
+
99
  @dataclass
100
  class ModelSettings:
101
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
104
  "component": "dropdown",
105
  "label": "Base Model",
106
  "help": "Select the base diffusion model.",
107
+ "visible": True
108
  }
109
  )
110
  custom_model_path: str = field(
 
196
  }
197
  )
198
 
199
+
200
+ @dataclass
201
+ class AdvancedSamplingSettings:
202
+ override_sampler: bool = field(
203
+ default=False,
204
+ metadata={
205
+ "label": "Override Sampler Settings",
206
+ "help": "Enable this to activate special sampler-specific options below."
207
+ }
208
+ )
209
+ custom_noise: float = field(
210
+ default=1.0,
211
+ metadata={
212
+ "component": "slider",
213
+ "label": "Custom Noise Multiplier",
214
+ "minimum": 0.5,
215
+ "maximum": 1.5,
216
+ "step": 0.01,
217
+ "interactive_if": {"field": "override_sampler", "value": True},
218
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
219
+ }
220
+ )
221
+
222
+
223
  @dataclass
224
  class RenderConfig:
225
  api_settings: APISettings = field(
 
249
  default_factory=SamplingSettings,
250
  metadata={"label": "Sampling Settings"}
251
  )
252
+
253
+ advanced_sampling: AdvancedSamplingSettings = field(
254
+ default_factory=AdvancedSamplingSettings,
255
+ metadata={"label": "Advanced Sampling"}
256
+ )
257
+
258
  quantization: QuantizationSettings = field(
259
  default_factory=QuantizationSettings,
260
  metadata={"label": "Quantization Settings"}
 
329
  }
330
  )
331
 
332
+ # --- 2. Data Mappings and Initial Instances ---
333
  initial_render_config = RenderConfig()
334
  initial_env_config = EnvironmentConfig()
335
+ initial_effects_config = EffectsConfig()
336
+
337
  sampler_settings_map_py = {
338
  "Euler": EulerSettings(),
339
  "DPM++ 2M Karras": DPM_Settings(),
 
346
  "Pony": None,
347
  }
348
 
349
+ # --- 3. CSS & JS Injection function ---
 
350
  def inject_assets():
351
  """
352
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
389
  gr.Markdown(
390
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
391
  )
 
392
  effects_state = gr.State(value=initial_effects_config)
393
  render_state = gr.State(value=initial_render_config)
394
  env_state = gr.State(value=initial_env_config)
395
  sidebar_visible = gr.State(False)
396
  with gr.Row():
397
  with gr.Column(scale=3):
398
+ generate_btn = gr.Button("Show Settings", variant="primary")
399
  with gr.Row():
400
  output_render_json = gr.JSON(label="Live Render State")
401
  output_env_json = gr.JSON(label="Live Environment State")
 
454
  if updated_config is None:
455
  return current_state, asdict(current_state), current_state
456
  return updated_config, asdict(updated_config), current_state
457
+
458
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
459
+ if updated_config is None:
460
+ return current_state, asdict(current_state), current_state
461
+ return updated_config, asdict(updated_config), updated_config
462
 
463
+ generate_btn.click(
464
  fn=change_visibility,
465
  inputs=[sidebar_visible, render_state, env_state, effects_state],
466
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
467
  )
468
 
469
  render_sheet.change(
 
476
  inputs=[environment_sheet, env_state],
477
  outputs=[environment_sheet, output_env_json, env_state],
478
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  effects_sheet.change(
480
  fn=handle_effects_change,
481
  inputs=[effects_sheet, effects_state],
482
  outputs=[effects_sheet, output_effects_json, effects_state]
483
  )
484
+
485
+ def on_undo(updated_config, current_state):
486
+ if updated_config is None:
487
+ return current_state, asdict(current_state)
488
+ return updated_config, asdict(updated_config)
489
+
490
+ render_sheet.undo(
491
+ fn=on_undo,
492
+ inputs=[render_sheet, render_state],
493
+ outputs=[render_state, output_render_json]
494
+ )
495
+ environment_sheet.undo(
496
+ fn=on_undo,
497
+ inputs=[environment_sheet, env_state],
498
+ outputs=[env_state, output_env_json],
499
+ )
500
  effects_sheet.undo(
501
+ fn=on_undo,
502
  inputs=[effects_sheet, effects_state],
503
+ outputs=[effects_state, output_effects_json]
504
  )
505
 
506
  demo.load(
 
673
  )
674
 
675
  if __name__ == "__main__":
676
+ demo.launch()
src/demo/space.py CHANGED
@@ -47,10 +47,10 @@ from gradio_propertysheet import PropertySheet
47
  from gradio_htmlinjector import HTMLInjector
48
 
49
 
50
- # --- 1. Dataclass Definitions (unchanged) ---
51
  @dataclass
52
  class EffectBase:
53
- \"\"\"Classe base com configurações de efeito comuns.\"\"\"
54
  strength: float = field(
55
  default=0.5,
56
  metadata={
@@ -59,14 +59,14 @@ class EffectBase:
59
  "minimum": 0.0,
60
  "maximum": 1.0,
61
  "step": 0.01,
62
- # Esta regra depende do 'is_active' da classe filha
63
  "interactive_if": {"field": "is_active", "value": True}
64
  }
65
  )
66
 
67
  @dataclass
68
  class EffectSettings(EffectBase):
69
- \"\"\"Classe filha que adiciona o controle de ativação.\"\"\"
70
  is_active: bool = field(
71
  default=True,
72
  metadata={"label": "Enable Effect"}
@@ -74,7 +74,7 @@ class EffectSettings(EffectBase):
74
 
75
  @dataclass
76
  class EffectsConfig:
77
- \"\"\"Dataclass principal que contém múltiplos efeitos com campos de controle de mesmo nome.\"\"\"
78
  blur_effect: EffectSettings = field(
79
  default_factory=EffectSettings,
80
  metadata={"label": "Blur Effect"}
@@ -87,6 +87,7 @@ class EffectsConfig:
87
  default_factory=EffectSettings,
88
  metadata={"label": "Vignette Effect"}
89
  )
 
90
  @dataclass
91
  class APISettings:
92
  api_key: str = field(
@@ -101,7 +102,7 @@ class APISettings:
101
  default="https://api.example.com",
102
  metadata={
103
  "label": "API Endpoint",
104
- "component": "string", # string normal
105
  "help": "The URL of the API server."
106
  }
107
  )
@@ -116,7 +117,6 @@ class QuantizationSettings:
116
  "help": "Quantization mechanism to save VRAM and increase speed."
117
  }
118
  )
119
- # Option 1: Literal values
120
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
121
  default="FP8",
122
  metadata={
@@ -126,7 +126,6 @@ class QuantizationSettings:
126
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
127
  }
128
  )
129
- # Option 2: neq operand
130
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
131
  default="FP8",
132
  metadata={
@@ -136,6 +135,7 @@ class QuantizationSettings:
136
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
137
  }
138
  )
 
139
  @dataclass
140
  class ModelSettings:
141
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
@@ -144,7 +144,7 @@ class ModelSettings:
144
  "component": "dropdown",
145
  "label": "Base Model",
146
  "help": "Select the base diffusion model.",
147
- "visible": True #change here to test visibility
148
  }
149
  )
150
  custom_model_path: str = field(
@@ -236,6 +236,30 @@ class SamplingSettings:
236
  }
237
  )
238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  @dataclass
240
  class RenderConfig:
241
  api_settings: APISettings = field(
@@ -265,6 +289,12 @@ class RenderConfig:
265
  default_factory=SamplingSettings,
266
  metadata={"label": "Sampling Settings"}
267
  )
 
 
 
 
 
 
268
  quantization: QuantizationSettings = field(
269
  default_factory=QuantizationSettings,
270
  metadata={"label": "Quantization Settings"}
@@ -339,9 +369,11 @@ class DPM_Settings:
339
  }
340
  )
341
 
342
- # --- 2. Data Mappings and Initial Instances (unchanged) ---
343
  initial_render_config = RenderConfig()
344
  initial_env_config = EnvironmentConfig()
 
 
345
  sampler_settings_map_py = {
346
  "Euler": EulerSettings(),
347
  "DPM++ 2M Karras": DPM_Settings(),
@@ -354,8 +386,7 @@ model_settings_map_py = {
354
  "Pony": None,
355
  }
356
 
357
-
358
- # --- 3. CSS & JS Injection function (unchanged) ---
359
  def inject_assets():
360
  \"\"\"
361
  This function prepares the payload of CSS, JS, and Body HTML for injection.
@@ -398,14 +429,13 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
398
  gr.Markdown(
399
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
400
  )
401
- initial_effects_config = EffectsConfig()
402
  effects_state = gr.State(value=initial_effects_config)
403
  render_state = gr.State(value=initial_render_config)
404
  env_state = gr.State(value=initial_env_config)
405
  sidebar_visible = gr.State(False)
406
  with gr.Row():
407
  with gr.Column(scale=3):
408
- generate = gr.Button("Show Settings", variant="primary")
409
  with gr.Row():
410
  output_render_json = gr.JSON(label="Live Render State")
411
  output_env_json = gr.JSON(label="Live Environment State")
@@ -464,11 +494,16 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
464
  if updated_config is None:
465
  return current_state, asdict(current_state), current_state
466
  return updated_config, asdict(updated_config), current_state
 
 
 
 
 
467
 
468
- generate.click(
469
  fn=change_visibility,
470
  inputs=[sidebar_visible, render_state, env_state, effects_state],
471
- outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate],
472
  )
473
 
474
  render_sheet.change(
@@ -481,41 +516,31 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
481
  inputs=[environment_sheet, env_state],
482
  outputs=[environment_sheet, output_env_json, env_state],
483
  )
484
-
485
- #In version 0.0.7, I moved the undo function to a new `undo` event. This was necessary to avoid conflict with the `change` event where it was previously implemented.
486
- # Now you need to implement the undo event for the undo button to work. You can simply receive the component as input and set it as output.
487
- def render_undo(updated_config: RenderConfig, current_state: RenderConfig):
488
- if updated_config is None:
489
- return current_state, asdict(current_state), current_state
490
- return updated_config, asdict(updated_config), current_state
491
-
492
- def environment_undo(updated_config: EnvironmentConfig, current_state: EnvironmentConfig):
493
- if updated_config is None:
494
- return current_state, asdict(current_state), current_state
495
- return updated_config, asdict(updated_config), current_state
496
-
497
- render_sheet.undo(fn=render_undo,
498
- inputs=[render_sheet, render_state],
499
- outputs=[render_sheet, output_render_json, render_state]
500
- )
501
- environment_sheet.undo(fn=environment_undo,
502
- inputs=[environment_sheet, env_state],
503
- outputs=[environment_sheet, output_env_json, env_state],
504
- )
505
- def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
506
- if updated_config is None:
507
- return current_state, asdict(current_state), current_state
508
- return updated_config, asdict(updated_config), updated_config
509
-
510
  effects_sheet.change(
511
  fn=handle_effects_change,
512
  inputs=[effects_sheet, effects_state],
513
  outputs=[effects_sheet, output_effects_json, effects_state]
514
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  effects_sheet.undo(
516
- fn=handle_effects_change,
517
  inputs=[effects_sheet, effects_state],
518
- outputs=[effects_sheet, output_effects_json, effects_state]
519
  )
520
 
521
  demo.load(
@@ -689,7 +714,6 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="PropertySheet Demos") as demo:
689
 
690
  if __name__ == "__main__":
691
  demo.launch()
692
-
693
  ```
694
  """, elem_classes=["md-custom"], header_links=True)
695
 
 
47
  from gradio_htmlinjector import HTMLInjector
48
 
49
 
50
+ # --- 1. Dataclass Definitions ---
51
  @dataclass
52
  class EffectBase:
53
+ \"\"\"Base class with common effect settings.\"\"\"
54
  strength: float = field(
55
  default=0.5,
56
  metadata={
 
59
  "minimum": 0.0,
60
  "maximum": 1.0,
61
  "step": 0.01,
62
+ # This rule depends on the 'is_active' field from the child class
63
  "interactive_if": {"field": "is_active", "value": True}
64
  }
65
  )
66
 
67
  @dataclass
68
  class EffectSettings(EffectBase):
69
+ \"\"\"Child class that adds the activation control.\"\"\"
70
  is_active: bool = field(
71
  default=True,
72
  metadata={"label": "Enable Effect"}
 
74
 
75
  @dataclass
76
  class EffectsConfig:
77
+ \"\"\"Main dataclass containing multiple effects with same-named control fields.\"\"\"
78
  blur_effect: EffectSettings = field(
79
  default_factory=EffectSettings,
80
  metadata={"label": "Blur Effect"}
 
87
  default_factory=EffectSettings,
88
  metadata={"label": "Vignette Effect"}
89
  )
90
+
91
  @dataclass
92
  class APISettings:
93
  api_key: str = field(
 
102
  default="https://api.example.com",
103
  metadata={
104
  "label": "API Endpoint",
105
+ "component": "string", # Normal string
106
  "help": "The URL of the API server."
107
  }
108
  )
 
117
  "help": "Quantization mechanism to save VRAM and increase speed."
118
  }
119
  )
 
120
  quantize_mode_list: Literal["FP8", "INT8", "IN4"] = field(
121
  default="FP8",
122
  metadata={
 
126
  "help": "This becomes interactive if Quantization Method is 'Quanto' OR 'Layerwise'."
127
  }
128
  )
 
129
  quantize_mode_neq: Literal["FP8", "INT8", "IN4"] = field(
130
  default="FP8",
131
  metadata={
 
135
  "help": "This becomes interactive if Quantization Method is NOT 'None'."
136
  }
137
  )
138
+
139
  @dataclass
140
  class ModelSettings:
141
  model_type: Literal["SD 1.5", "SDXL", "Pony", "Custom"] = field(
 
144
  "component": "dropdown",
145
  "label": "Base Model",
146
  "help": "Select the base diffusion model.",
147
+ "visible": True
148
  }
149
  )
150
  custom_model_path: str = field(
 
236
  }
237
  )
238
 
239
+
240
+ @dataclass
241
+ class AdvancedSamplingSettings:
242
+ override_sampler: bool = field(
243
+ default=False,
244
+ metadata={
245
+ "label": "Override Sampler Settings",
246
+ "help": "Enable this to activate special sampler-specific options below."
247
+ }
248
+ )
249
+ custom_noise: float = field(
250
+ default=1.0,
251
+ metadata={
252
+ "component": "slider",
253
+ "label": "Custom Noise Multiplier",
254
+ "minimum": 0.5,
255
+ "maximum": 1.5,
256
+ "step": 0.01,
257
+ "interactive_if": {"field": "override_sampler", "value": True},
258
+ "help": "A custom setting that is only active when 'Override Sampler Settings' is checked."
259
+ }
260
+ )
261
+
262
+
263
  @dataclass
264
  class RenderConfig:
265
  api_settings: APISettings = field(
 
289
  default_factory=SamplingSettings,
290
  metadata={"label": "Sampling Settings"}
291
  )
292
+
293
+ advanced_sampling: AdvancedSamplingSettings = field(
294
+ default_factory=AdvancedSamplingSettings,
295
+ metadata={"label": "Advanced Sampling"}
296
+ )
297
+
298
  quantization: QuantizationSettings = field(
299
  default_factory=QuantizationSettings,
300
  metadata={"label": "Quantization Settings"}
 
369
  }
370
  )
371
 
372
+ # --- 2. Data Mappings and Initial Instances ---
373
  initial_render_config = RenderConfig()
374
  initial_env_config = EnvironmentConfig()
375
+ initial_effects_config = EffectsConfig()
376
+
377
  sampler_settings_map_py = {
378
  "Euler": EulerSettings(),
379
  "DPM++ 2M Karras": DPM_Settings(),
 
386
  "Pony": None,
387
  }
388
 
389
+ # --- 3. CSS & JS Injection function ---
 
390
  def inject_assets():
391
  \"\"\"
392
  This function prepares the payload of CSS, JS, and Body HTML for injection.
 
429
  gr.Markdown(
430
  "An example of using the `PropertySheet` component as a traditional sidebar for settings."
431
  )
 
432
  effects_state = gr.State(value=initial_effects_config)
433
  render_state = gr.State(value=initial_render_config)
434
  env_state = gr.State(value=initial_env_config)
435
  sidebar_visible = gr.State(False)
436
  with gr.Row():
437
  with gr.Column(scale=3):
438
+ generate_btn = gr.Button("Show Settings", variant="primary")
439
  with gr.Row():
440
  output_render_json = gr.JSON(label="Live Render State")
441
  output_env_json = gr.JSON(label="Live Environment State")
 
494
  if updated_config is None:
495
  return current_state, asdict(current_state), current_state
496
  return updated_config, asdict(updated_config), current_state
497
+
498
+ def handle_effects_change(updated_config: EffectsConfig, current_state: EffectsConfig):
499
+ if updated_config is None:
500
+ return current_state, asdict(current_state), current_state
501
+ return updated_config, asdict(updated_config), updated_config
502
 
503
+ generate_btn.click(
504
  fn=change_visibility,
505
  inputs=[sidebar_visible, render_state, env_state, effects_state],
506
+ outputs=[sidebar_visible, render_sheet, environment_sheet, effects_sheet, generate_btn],
507
  )
508
 
509
  render_sheet.change(
 
516
  inputs=[environment_sheet, env_state],
517
  outputs=[environment_sheet, output_env_json, env_state],
518
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  effects_sheet.change(
520
  fn=handle_effects_change,
521
  inputs=[effects_sheet, effects_state],
522
  outputs=[effects_sheet, output_effects_json, effects_state]
523
  )
524
+
525
+ def on_undo(updated_config, current_state):
526
+ if updated_config is None:
527
+ return current_state, asdict(current_state)
528
+ return updated_config, asdict(updated_config)
529
+
530
+ render_sheet.undo(
531
+ fn=on_undo,
532
+ inputs=[render_sheet, render_state],
533
+ outputs=[render_state, output_render_json]
534
+ )
535
+ environment_sheet.undo(
536
+ fn=on_undo,
537
+ inputs=[environment_sheet, env_state],
538
+ outputs=[env_state, output_env_json],
539
+ )
540
  effects_sheet.undo(
541
+ fn=on_undo,
542
  inputs=[effects_sheet, effects_state],
543
+ outputs=[effects_state, output_effects_json]
544
  )
545
 
546
  demo.load(
 
714
 
715
  if __name__ == "__main__":
716
  demo.launch()
 
717
  ```
718
  """, elem_classes=["md-custom"], header_links=True)
719