11from __future__ import annotations
22
3+ import dataclasses
34import logging
4- from typing import TYPE_CHECKING , Any
5+ from typing import TYPE_CHECKING , Any , Literal
56from collections .abc import Callable
67
78import euklid
89from openglider .glider .parametric .shape import ParametricShape
910from openglider .glider .project import GliderProject
10- from openglider .gui .qt import QtWidgets
11+ from openglider .gui .qt import QtWidgets , QtCore
1112from openglider .gui .views_2d import Canvas , DraggableLine , Line2D
1213from openglider .gui .views_2d .canvas import LayoutGraphics
1314from openglider .gui .widgets import NumberInput
1415from openglider .gui .wizzards .base import GliderSelectionWizard
1516from openglider .plots .sketches .shapeplot import ShapePlot , ShapePlotConfig
1617from openglider .utils .colors import Color
18+ from openglider .utils .dataclass import dataclass
1719
1820if TYPE_CHECKING :
1921 from openglider .gui .app .main_window import MainWindow
@@ -201,10 +203,30 @@ def on_node_release(self, curve: DraggableLine, event: Any) -> None:
201203 pass
202204
203205
204- class ShapeSettings (QtWidgets .QWidget ):
206+ @dataclass
207+ class ShapeSettings :
208+ area : float
209+ aspect_ratio : float
210+ sweep : float
211+ cell_count : int
212+ scale : Literal ["Area" ] | Literal ["Span" ] | None
213+ zrot : bool = False
214+
215+ class ShapeSettingsWidget (QtWidgets .QWidget ):
216+ changed = QtCore .Signal ()
205217 def __init__ (self , shape : ParametricShape ):
206218 super ().__init__ ()
207219 layout = QtWidgets .QVBoxLayout ()
220+
221+ self .settings = ShapeSettings (
222+ area = shape .area ,
223+ aspect_ratio = shape .aspect_ratio ,
224+ sweep = shape .get_sweep (),
225+ cell_count = shape .cell_num ,
226+ scale = None ,
227+ zrot = False
228+ )
229+
208230 self .setLayout (layout )
209231
210232 self .setSizePolicy (QtWidgets .QSizePolicy .Policy .Fixed , QtWidgets .QSizePolicy .Policy .Fixed )
@@ -220,11 +242,38 @@ def __init__(self, shape: ParametricShape):
220242 self .input_scale .insertItem (1 , "Scale Area" )
221243 self .input_scale .insertItem (2 , "Scale Span" )
222244
245+ self .zrot = False
246+ self .input_zrot = QtWidgets .QCheckBox ()
247+ self .input_zrot .setChecked (False )
248+ layout .addWidget (self .input_zrot )
249+
250+ self .input_zrot .clicked .connect (self ._update )
251+ self .input_area .on_changed .append (self ._update )
252+ self .input_aspect_ratio .on_changed .append (self ._update )
253+ self .input_sweep .on_changed .append (self ._update )
254+ self .input_cell_count .on_changed .append (self ._update )
255+
223256 layout .addWidget (self .input_area )
224257 layout .addWidget (self .input_aspect_ratio )
225258 layout .addWidget (self .input_sweep )
226259 layout .addWidget (self .input_cell_count )
227260 layout .addWidget (self .input_scale )
261+
262+ def _update (self , value : Any = None ) -> None :
263+ self .settings .area = self .input_area .value
264+ self .settings .aspect_ratio = self .input_aspect_ratio .value
265+ self .settings .sweep = self .input_sweep .value
266+ self .settings .cell_count = int (self .input_cell_count .value )
267+ if self .normalize_area :
268+ self .settings .scale = "Area"
269+ elif self .normalize_span :
270+ self .settings .scale = "Span"
271+ else :
272+ self .settings .scale = None
273+
274+ self .settings .zrot = self .input_zrot .isChecked ()
275+
276+ self .changed .emit ()
228277
229278 @property
230279 def normalize_area (self ) -> bool :
@@ -234,6 +283,11 @@ def normalize_area(self) -> bool:
234283 def normalize_span (self ) -> bool :
235284 return self .input_scale .currentIndex () == 2
236285
286+ def update_zrot (self , value : bool = False ) -> None :
287+ self .zrot = not self .zrot
288+ self .input_zrot .setChecked (self .zrot )
289+ self .changed .emit ()
290+
237291 def update_shape (self , shape : ParametricShape ) -> None :
238292 self .input_area .set_value (shape .area , propagate = True )
239293 self .input_aspect_ratio .set_value (shape .aspect_ratio , propagate = True )
@@ -253,19 +307,17 @@ def __init__(self, app: MainWindow, project: GliderProject):
253307
254308 self .main_widget .setSizes ([300 , 700 ])
255309
256- self .shape_settings = ShapeSettings (self .project .glider .shape )
257- self .right_widget_layout .insertWidget (0 , self .shape_settings )
310+ self .shape_settings_widget = ShapeSettingsWidget (self .project .glider .shape )
311+ self .settings = self .shape_settings_widget .settings
312+
313+ self .right_widget_layout .insertWidget (0 , self .shape_settings_widget )
258314 #self.right_widget.layout().insertWidget(0, self.canvas_controls)
259315 self ._selection_changed ()
260316
261- self .shape_input .on_change .append (self .shape_settings .update_shape )
317+ self .shape_input .on_change .append (self .shape_settings_widget .update_shape )
262318 self .shape_input .on_change .append (self ._selection_changed )
263319
264- self .shape_settings .input_area .on_changed .append (self .apply_settings )
265- self .shape_settings .input_aspect_ratio .on_changed .append (self .apply_settings )
266- self .shape_settings .input_cell_count .on_changed .append (self .apply_settings )
267- self .shape_settings .input_sweep .on_changed .append (self .set_sweep )
268- self .shape_settings .input_scale .currentIndexChanged .connect (self ._selection_changed )
320+ self .shape_settings_widget .changed .connect (self .apply_settings )
269321
270322 @property
271323 def shape (self ) -> ParametricShape :
@@ -275,22 +327,29 @@ def set_sweep(self, value: float) -> None:
275327 self .shape .set_sweep (value )
276328 self ._update ()
277329
278- def apply_settings (self , value : float ) -> None :
330+ def apply_settings (self ) -> None :
331+ settings = self .shape_settings_widget .settings
332+ self .shape_input .config .apply_zrot = settings .zrot
333+
279334 shape : ParametricShape = self .shape
335+ shape .set_area (settings .area )
336+ shape .set_aspect_ratio (settings .aspect_ratio )
337+ shape .cell_num = settings .cell_count
338+
339+ if self .settings .sweep != settings .sweep :
340+ self .shape .set_sweep (settings .sweep )
280341
281- shape .set_area (self .shape_settings .input_area .value )
282- shape .set_aspect_ratio (self .shape_settings .input_aspect_ratio .value )
283- shape .cell_num = int (self .shape_settings .input_cell_count .value )
342+ self .settings = dataclasses .replace (settings )
284343 self ._update ()
285344
286345 def _update (self ) -> None :
287346 self .shape_input .front .set_controlpoints (self .shape .front_curve .controlpoints .nodes )
288347 self .shape_input .back .set_controlpoints (self .shape .back_curve .controlpoints .nodes )
289- self .shape_settings .update_shape (self .shape )
348+ self .shape_settings_widget .update_shape (self .shape )
290349 self .shape_input .redraw ()
291350
292351 def selection_changed (self , selected : list [tuple [GliderProject , Color ]]) -> None :
293- self .shape_input .draw_shapes (selected , normalize_area = self .shape_settings .normalize_area , normalize_span = self .shape_settings .normalize_span )
352+ self .shape_input .draw_shapes (selected , normalize_area = self .shape_settings_widget .normalize_area , normalize_span = self .shape_settings_widget .normalize_span )
294353 self .distribution_input .draw_shapes (selected )
295354
296355 def apply (self , update : bool = True ) -> None :
0 commit comments