@@ -172,58 +172,48 @@ def main(
172172 f"User chose theme '{ chosen_theme } ' but no file found. Keeping old theme."
173173 )
174174
175- # Check if any nodes have predefined positions from the YAML
176- has_predefined_positions = any (
177- node .pos_x is not None
175+ # Determine which nodes have predefined positions
176+ predefined = {
177+ name : node
178+ for name , node in nodes .items ()
179+ if node .pos_x is not None
178180 and node .pos_y is not None
179181 and str (node .pos_x ).strip () != ""
180182 and str (node .pos_y ).strip () != ""
181- for node in nodes .values ()
182- )
183+ }
184+
185+ has_any_fixed = bool (predefined )
186+ all_fixed = len (predefined ) == len (nodes )
183187
184- if has_predefined_positions :
188+ fixed_positions = {}
189+ if has_any_fixed :
185190 logger .debug ("Using predefined positions from YAML file with scaling..." )
186191
187- # Scale factor to ensure adequate spacing between nodes
188192 x_scale = (styles .get ("padding_x" , 150 ) / 100 ) * 1.5
189193 y_scale = (styles .get ("padding_y" , 150 ) / 100 ) * 1.5
190194
191- # Convert string positions to float and apply scaling
192- for node in nodes .values ():
195+ for name , node in predefined .items ():
193196 try :
194- if (
195- node .pos_x is not None
196- and node .pos_y is not None
197- and str (node .pos_x ).strip () != ""
198- and str (node .pos_y ).strip () != ""
199- ):
200- node .pos_x = int (node .pos_x ) * x_scale
201- node .pos_y = int (node .pos_y ) * y_scale
197+ node .pos_x = int (node .pos_x ) * x_scale
198+ node .pos_y = int (node .pos_y ) * y_scale
199+ fixed_positions [name ] = (node .pos_x , node .pos_y )
202200 except (ValueError , TypeError ):
203201 logger .debug (
204202 f"Could not convert position for node { node .name } , will use layout position"
205203 )
206204 node .pos_x = None
207205 node .pos_y = None
208206
209- # When fixed positions are available, we still assign graph levels for connectivity purposes
210- # but instruct it to skip warnings and not override positions
211- logger .debug (
212- "Using predefined positions - graph levels will only be used for connectivity"
213- )
214207 graph_manager = GraphLevelManager ()
215208 graph_manager .assign_graphlevels (
216- diagram , verbose = False , skip_warnings = True , respect_fixed_positions = True
209+ diagram , verbose = False , skip_warnings = True , respect_fixed_positions = False
217210 )
218211 else :
219- # No fixed positions, proceed with normal graph level assignment
220212 logger .debug ("No predefined positions found - assigning graph levels normally" )
221213 graph_manager = GraphLevelManager ()
222214 graph_manager .assign_graphlevels (diagram , verbose = False )
223215
224- # Only apply layout manager if we don't have predefined positions
225- if not has_predefined_positions :
226- # Choose layout based on layout argument
216+ if not all_fixed :
227217 if layout == "vertical" :
228218 layout_manager = VerticalLayout ()
229219 else :
@@ -232,24 +222,34 @@ def main(
232222 logger .debug (f"Applying { layout } layout..." )
233223 layout_manager .apply (diagram , verbose = log_level == LogLevel .DEBUG )
234224
225+ # Restore positions for nodes that had predefined coordinates
226+ for name , (x , y ) in fixed_positions .items ():
227+ node = nodes .get (name )
228+ if node :
229+ node .pos_x = x
230+ node .pos_y = y
231+
235232 # Calculate the diagram size based on the positions of the nodes
236- min_x = min (node .pos_x for node in nodes .values ())
237- min_y = min (node .pos_y for node in nodes .values ())
238- max_x = max (node .pos_x for node in nodes .values ())
239- max_y = max (node .pos_y for node in nodes .values ())
233+ positioned_nodes = [
234+ n for n in nodes .values () if n .pos_x is not None and n .pos_y is not None
235+ ]
236+ min_x = min (node .pos_x for node in positioned_nodes )
237+ min_y = min (node .pos_y for node in positioned_nodes )
238+ max_x = max (node .pos_x for node in positioned_nodes )
239+ max_y = max (node .pos_y for node in positioned_nodes )
240240
241241 # Determine the necessary adjustments
242242 adjust_x = - min_x + 100 # Adjust so the minimum x is at least 100
243243 adjust_y = - min_y + 100 # Adjust so the minimum y is at least 100
244244
245245 # Apply adjustments to each node's position
246- for node in nodes . values () :
246+ for node in positioned_nodes :
247247 node .pos_x += adjust_x
248248 node .pos_y += adjust_y
249249
250250 # Recalculate diagram size if necessary, after adjustment
251- max_x = max (node .pos_x for node in nodes . values () )
252- max_y = max (node .pos_y for node in nodes . values () )
251+ max_x = max (node .pos_x for node in positioned_nodes )
252+ max_y = max (node .pos_y for node in positioned_nodes )
253253
254254 max_size_x = max_x + 100 # Adding a margin to the right side
255255 max_size_y = max_y + 100 # Adding a margin to the bottom
0 commit comments