Skip to content

Commit b9fc231

Browse files
committed
port layout refactor.
1 parent 7d46023 commit b9fc231

File tree

2 files changed

+94
-124
lines changed

2 files changed

+94
-124
lines changed

NodeGraphQt/qgraphics/node_base.py

Lines changed: 71 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,17 @@ def _tooltip_disable(self, state):
231231
tooltip += '<br/>{}<br/>'.format(self.type_)
232232
self.setToolTip(tooltip)
233233

234-
def _set_base_size(self):
234+
def _set_base_size(self, add_w=0.0, add_h=0.0):
235235
"""
236236
setup initial base size.
237+
238+
Args:
239+
add_w (float): additional width.
240+
add_h (float): additional height.
237241
"""
238242
self._width = NODE_WIDTH
239243
self._height = NODE_HEIGHT
240-
width, height = self.calc_size()
244+
width, height = self.calc_size(add_w, add_h)
241245
if width > self._width:
242246
self._width = width
243247
if height > self._height:
@@ -284,151 +288,146 @@ def reset_pipes(self):
284288
for pipe in port.connected_pipes:
285289
pipe.reset()
286290

287-
def calc_size(self):
291+
def calc_size(self, add_w=0.0, add_h=0.0):
288292
"""
289293
calculate minimum node size.
294+
295+
Args:
296+
add_w (float): additional width.
297+
add_h (float): additional height.
290298
"""
291-
width = 0.0
299+
width = self._text_item.boundingRect().width()
300+
height = self._text_item.boundingRect().height()
301+
292302
if self._widgets:
293303
width = max([
294304
w.boundingRect().width() for w in self._widgets.values()
295305
])
296306

297-
lbl_width = self._text_item.boundingRect().width()
298-
if lbl_width > width:
299-
width = lbl_width
300-
301307
port_height = 0.0
302308
if self._input_items:
303309
input_widths = []
304310
for port, text in self._input_items.items():
305-
input_width = port.boundingRect().width() * 2
311+
input_width = port.boundingRect().width()
306312
if text.isVisible():
307313
input_width += text.boundingRect().width()
308314
input_widths.append(input_width)
309315
width += max(input_widths)
310-
port = list(self._input_items.keys())[0]
311-
port_height = port.boundingRect().height() * 2
316+
port_height = port.boundingRect().height()
317+
312318
if self._output_items:
313319
output_widths = []
314320
for port, text in self._output_items.items():
315-
output_width = port.boundingRect().width() * 2
321+
output_width = port.boundingRect().width()
316322
if text.isVisible():
317323
output_width += text.boundingRect().width()
318324
output_widths.append(output_width)
319325
width += max(output_widths)
320-
port = list(self._output_items.keys())[0]
321-
port_height = port.boundingRect().height() * 2
322-
323-
if not (self._input_items and self._output_items):
324-
width += self._icon_item.boundingRect().width() * 3
326+
port_height = port.boundingRect().height()
325327

326328
in_count = len([p for p in self.inputs if p.isVisible()])
327329
out_count = len([p for p in self.outputs if p.isVisible()])
328-
height = port_height * (max([in_count, out_count]) + 2)
330+
height += port_height * max([in_count, out_count])
329331
if self._widgets:
330-
wid_height = sum(
331-
[w.boundingRect().height() for w in self._widgets.values()])
332+
wid_height = 0.0
333+
for w in self._widgets.values():
334+
wid_height += w.boundingRect().height()
335+
wid_height += wid_height / len(self._widgets.values())
332336
if wid_height > height:
333-
height = wid_height + (wid_height / len(self._widgets))
337+
height = wid_height
334338

335-
height += 10
339+
width += add_w
340+
height += add_h
336341

337342
return width, height
338343

339-
def arrange_icon(self):
344+
def arrange_icon(self, h_offset=0.0, v_offset=0.0):
340345
"""
341346
Arrange node icon to the default top left of the node.
347+
348+
Args:
349+
v_offset (float): vertical offset.
350+
h_offset (float): horizontal offset.
342351
"""
343-
self._icon_item.setPos(2.0, 2.0)
352+
x = 2.0 + h_offset
353+
y = 2.0 + v_offset
354+
self._icon_item.setPos(x, y)
344355

345-
def arrange_label(self):
356+
def arrange_label(self, h_offset=0.0, v_offset=0.0):
346357
"""
347358
Arrange node label to the default top center of the node.
359+
360+
Args:
361+
v_offset (float): vertical offset.
362+
h_offset (float): horizontal offset.
348363
"""
349364
text_rect = self._text_item.boundingRect()
350365
text_x = (self._width / 2) - (text_rect.width() / 2)
351-
self._text_item.setPos(text_x, 1.0)
366+
text_x += h_offset
367+
text_y = 1.0 + v_offset
368+
self._text_item.setPos(text_x, text_y)
352369

353-
def arrange_widgets(self):
370+
def arrange_widgets(self, v_offset=0.0):
354371
"""
355372
Arrange node widgets to the default center of the node.
373+
374+
Args:
375+
v_offset (float): vertical offset.
356376
"""
357377
if not self._widgets:
358378
return
359379
wid_heights = sum(
360380
[w.boundingRect().height() for w in self._widgets.values()])
361381
pos_y = self._height / 2
362382
pos_y -= wid_heights / 2
363-
for name, widget in self._widgets.items():
383+
pos_y += v_offset
384+
for widget in self._widgets.values():
364385
rect = widget.boundingRect()
365386
pos_x = (self._width / 2) - (rect.width() / 2)
366387
widget.setPos(pos_x, pos_y)
367388
pos_y += rect.height()
368389

369-
def arrange_ports(self, padding_x=0.0, padding_y=0.0):
390+
def arrange_ports(self, v_offset=0.0):
370391
"""
371392
Arrange input, output ports in the node layout.
372393
373394
Args:
374-
padding_x (float): horizontal padding.
375-
padding_y: (float): vertical padding.
395+
v_offset (float): port vertical offset.
376396
"""
377-
width = self._width - padding_x
378-
height = self._height - padding_y
397+
width = self._width
379398

380399
# adjust input position
381400
inputs = [p for p in self.inputs if p.isVisible()]
382401
if inputs:
383402
port_width = inputs[0].boundingRect().width()
384403
port_height = inputs[0].boundingRect().height()
385-
chunk = (height / len(inputs))
386404
port_x = (port_width / 2) * -1
387-
port_y = (chunk / 2) - (port_height / 2)
405+
port_y = v_offset
388406
for port in inputs:
389-
port.setPos(port_x + padding_x, port_y + (padding_y / 2))
390-
port_y += chunk
407+
port.setPos(port_x, port_y)
408+
port_y += port_height
391409
# adjust input text position
392410
for port, text in self._input_items.items():
393-
if not port.isVisible():
394-
continue
395-
txt_height = text.boundingRect().height() - 8.0
396-
txt_x = port.x() + port.boundingRect().width()
397-
txt_y = port.y() - (txt_height / 2)
398-
text.setPos(txt_x + 3.0, txt_y)
411+
if port.isVisible():
412+
text.setPos(port.boundingRect().width() / 2, port.y() - 1.5)
413+
399414
# adjust output position
400415
outputs = [p for p in self.outputs if p.isVisible()]
401416
if outputs:
402417
port_width = outputs[0].boundingRect().width()
403418
port_height = outputs[0].boundingRect().height()
404-
chunk = height / len(outputs)
405419
port_x = width - (port_width / 2)
406-
port_y = (chunk / 2) - (port_height / 2)
420+
port_y = v_offset
407421
for port in outputs:
408-
port.setPos(port_x, port_y + (padding_y / 2))
409-
port_y += chunk
422+
port.setPos(port_x, port_y)
423+
port_y += port_height
410424
# adjust output text position
411425
for port, text in self._output_items.items():
412426
if not port.isVisible():
413427
continue
414428
txt_width = text.boundingRect().width()
415-
txt_height = text.boundingRect().height() - 8.0
416-
txt_x = width - txt_width - (port.boundingRect().width() / 2)
417-
txt_y = port.y() - (txt_height / 2)
418-
text.setPos(txt_x - 1.0, txt_y)
419-
420-
def offset_icon(self, x=0.0, y=0.0):
421-
"""
422-
offset the icon in the node layout.
423-
424-
Args:
425-
x (float): horizontal x offset
426-
y (float): vertical y offset
427-
"""
428-
if self._icon_item:
429-
icon_x = self._icon_item.pos().x() + x
430-
icon_y = self._icon_item.pos().y() + y
431-
self._icon_item.setPos(icon_x, icon_y)
429+
txt_x = port.x() - txt_width
430+
text.setPos(txt_x, port.y() - 1.5)
432431

433432
def offset_label(self, x=0.0, y=0.0):
434433
"""
@@ -442,38 +441,6 @@ def offset_label(self, x=0.0, y=0.0):
442441
icon_y = self._text_item.pos().y() + y
443442
self._text_item.setPos(icon_x, icon_y)
444443

445-
def offset_widgets(self, x=0.0, y=0.0):
446-
"""
447-
offset the node widgets in the node layout.
448-
449-
Args:
450-
x (float): horizontal x offset
451-
y (float): vertical y offset
452-
"""
453-
for name, widget in self._widgets.items():
454-
pos_x = widget.pos().x()
455-
pos_y = widget.pos().y()
456-
widget.setPos(pos_x + x, pos_y + y)
457-
458-
def offset_ports(self, x=0.0, y=0.0):
459-
"""
460-
offset the ports in the node layout.
461-
462-
Args:
463-
x (float): horizontal x offset
464-
y (float): vertical y offset
465-
"""
466-
for port, text in self._input_items.items():
467-
port_x, port_y = port.pos().x(), port.pos().y()
468-
text_x, text_y = text.pos().x(), text.pos().y()
469-
port.setPos(port_x + x, port_y + y)
470-
text.setPos(text_x + x, text_y + y)
471-
for port, text in self._output_items.items():
472-
port_x, port_y = port.pos().x(), port.pos().y()
473-
text_x, text_y = text.pos().x(), text.pos().y()
474-
port.setPos(port_x + x, port_y + y)
475-
text.setPos(text_x + x, text_y + y)
476-
477444
def post_init(self, viewer=None, pos=None):
478445
"""
479446
Called after node has been added into the scene.
@@ -483,8 +450,10 @@ def post_init(self, viewer=None, pos=None):
483450
viewer (NodeGraphQt.widgets.viewer.NodeViewer): not used
484451
pos (tuple): cursor position.
485452
"""
453+
height = self._text_item.boundingRect().height()
454+
486455
# setup initial base size.
487-
self._set_base_size()
456+
self._set_base_size(add_w=0.0, add_h=height)
488457
# set text color when node is initialized.
489458
self._set_text_color(self.text_color)
490459
# set the tooltip
@@ -493,21 +462,13 @@ def post_init(self, viewer=None, pos=None):
493462
# --- setup node layout ---
494463

495464
# arrange label text
496-
self.arrange_label()
497-
txt_y = self._text_item.boundingRect().height() / 10
498-
self.offset_label(0.0, txt_y)
499-
465+
self.arrange_label(h_offset=0.0, v_offset=0.0)
500466
# arrange icon
501-
self.arrange_icon()
502-
self.offset_icon(5.0, 2.0)
503-
504-
# arrange node widgets
505-
self.arrange_widgets()
506-
self.offset_widgets(0.0, 10.0)
507-
467+
self.arrange_icon(h_offset=0.0, v_offset=0.0)
508468
# arrange input and output ports.
509-
self.arrange_ports(padding_y=35.0)
510-
self.offset_ports(0.0, 15.0)
469+
self.arrange_ports(v_offset=height + (height / 2))
470+
# arrange node widgets
471+
self.arrange_widgets(v_offset=height / 2)
511472

512473
# set initial node position.
513474
if pos:

NodeGraphQt/qgraphics/port.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ def __init__(self, parent=None):
2222
self.setFlag(self.ItemSendsScenePositionChanges, True)
2323
self.setZValue(Z_VAL_PORT)
2424
self._pipes = []
25-
self._width = 10.0
26-
self._height = 10.0
25+
self._width = 18.5
26+
self._height = 18.5
2727
self._hovered = False
2828
self._name = 'port'
2929
self._display_name = True
@@ -53,6 +53,13 @@ def paint(self, painter, option, widget):
5353
widget (QtWidgets.QWidget): not used.
5454
"""
5555
painter.save()
56+
57+
rect_w = self._width / 1.5
58+
rect_h = self._height / 1.5
59+
rect_x = self._width - (rect_w * 1.25)
60+
rect_y = self._height - (rect_h * 1.25)
61+
port_rect = QtCore.QRectF(rect_x, rect_y, rect_w, rect_h)
62+
5663
if self._hovered:
5764
color = QtGui.QColor(*PORT_HOVER_COLOR)
5865
border_color = QtGui.QColor(*PORT_HOVER_BORDER_COLOR)
@@ -64,29 +71,31 @@ def paint(self, painter, option, widget):
6471
border_color = QtGui.QColor(*self.border_color)
6572

6673
painter.setBrush(color)
67-
pen = QtGui.QPen(border_color, 1.5)
74+
pen = QtGui.QPen(border_color, 1.8)
6875
painter.setPen(pen)
69-
painter.drawEllipse(self.boundingRect())
76+
painter.drawEllipse(port_rect)
7077

7178
if self.connected_pipes and not self._hovered:
7279
painter.setBrush(border_color)
73-
w = self._width / 2.5
74-
h = self._height / 2.5
75-
rect = QtCore.QRectF(self.boundingRect().center().x() - w / 2,
76-
self.boundingRect().center().y() - h / 2,
80+
w = port_rect.width() / 2.5
81+
h = port_rect.height() / 2.5
82+
rect = QtCore.QRectF(port_rect.center().x() - w / 2,
83+
port_rect.center().y() - h / 2,
7784
w, h)
7885
painter.drawEllipse(rect)
7986
elif self._hovered:
8087
if self.multi_connection:
88+
pen = QtGui.QPen(border_color, 1.4)
89+
painter.setPen(pen)
8190
painter.setBrush(color)
82-
w = self._width / 1.8
83-
h = self._height / 1.8
91+
w = port_rect.width() / 1.8
92+
h = port_rect.height() / 1.8
8493
else:
8594
painter.setBrush(border_color)
86-
w = self._width / 3.5
87-
h = self._height / 3.5
88-
rect = QtCore.QRectF(self.boundingRect().center().x() - w / 2,
89-
self.boundingRect().center().y() - h / 2,
95+
w = port_rect.width() / 3.5
96+
h = port_rect.height() / 3.5
97+
rect = QtCore.QRectF(port_rect.center().x() - w / 2,
98+
port_rect.center().y() - h / 2,
9099
w, h)
91100
painter.drawEllipse(rect)
92101
painter.restore()

0 commit comments

Comments
 (0)