Skip to content

Commit

Permalink
Merge pull request #275 from jchanvfx/dynamic_layout_switching
Browse files Browse the repository at this point in the history
Dynamic layout switching.
  • Loading branch information
jchanvfx authored Oct 9, 2022
2 parents 72bb974 + 04038d3 commit 80d9af9
Show file tree
Hide file tree
Showing 20 changed files with 841 additions and 840 deletions.
5 changes: 5 additions & 0 deletions NodeGraphQt/base/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ def redo(self):
self.model.nodes[self.node.id] = self.node
self.viewer.add_node(self.node.view, self.pos)

# node width & height is calculated when its added to the scene
# so we have to update the node model here.
self.node.model.width = self.node.view.width
self.node.model.height = self.node.view.height


class NodeRemovedCmd(QtWidgets.QUndoCommand):
"""
Expand Down
105 changes: 92 additions & 13 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
from NodeGraphQt.base.node import NodeObject
from NodeGraphQt.base.port import Port
from NodeGraphQt.constants import (
NODE_LAYOUT_DIRECTION, NODE_LAYOUT_HORIZONTAL, NODE_LAYOUT_VERTICAL,
URI_SCHEME,
URN_SCHEME,
LayoutDirectionEnum,
PipeLayoutEnum,
URI_SCHEME, URN_SCHEME,
PortTypeEnum,
ViewerEnum
)
Expand Down Expand Up @@ -125,6 +126,15 @@ def __init__(self, parent=None, **kwargs):
self.setObjectName('NodeGraph')
self._model = (
kwargs.get('model') or NodeGraphModel())

layout_direction = kwargs.get('layout_direction')
if layout_direction:
if layout_direction not in [e.value for e in LayoutDirectionEnum]:
layout_direction = LayoutDirectionEnum.HORIZONTAL.value
self._model.layout_direction = layout_direction
else:
layout_direction = self._model.layout_direction

self._node_factory = (
kwargs.get('node_factory') or NodeFactory())

Expand All @@ -138,6 +148,7 @@ def __init__(self, parent=None, **kwargs):

self._viewer = (
kwargs.get('viewer') or NodeViewer(undo_stack=self._undo_stack))
self._viewer.set_layout_direction(layout_direction)

self._build_context_menu()
self._register_builtin_nodes()
Expand Down Expand Up @@ -786,6 +797,52 @@ def set_pipe_style(self, style=PipeLayoutEnum.CURVED.value):
style = style if 0 <= style <= pipe_max else PipeLayoutEnum.CURVED.value
self._viewer.set_pipe_layout(style)

def layout_direction(self):
"""
Return the current node graph layout direction.
`Implemented in` ``v0.3.0``
See Also:
:meth:`NodeGraph.set_layout_direction`
Returns:
int: layout direction.
"""
return self.model.layout_direction

def set_layout_direction(self, direction):
"""
Sets the node graph layout direction to horizontal or vertical.
This function will also override the layout direction on all
nodes in the current node graph.
`Implemented in` ``v0.3.0``
See Also:
:meth:`NodeGraph.layout_direction`,
:meth:`NodeObject.set_layout_direction`
Note:
Node Graph Layout Types:
* :attr:`NodeGraphQt.constants.LayoutDirectionEnum.HORIZONTAL`
* :attr:`NodeGraphQt.constants.LayoutDirectionEnum.VERTICAL`
Warnings:
This function does not register to the undo stack.
Args:
direction (int): layout direction.
"""
direction_types = [e.value for e in LayoutDirectionEnum]
if direction not in direction_types:
direction = LayoutDirectionEnum.HORIZONTAL.value
self._model.layout_direction = direction
for node in self.all_nodes():
node.set_layout_direction(direction)
self._viewer.set_layout_direction(direction)

def fit_to_selection(self):
"""
Sets the zoom level to fit selected nodes.
Expand Down Expand Up @@ -853,7 +910,7 @@ def register_node(self, node, alias=None):
Register the node to the :meth:`NodeGraph.node_factory`
Args:
node (_NodeGraphQt.NodeObject): node object.
node (NodeGraphQt.NodeObject): node object.
alias (str): custom alias name for the node type.
"""
self._node_factory.register_node(node, alias)
Expand Down Expand Up @@ -922,6 +979,9 @@ def format_color(clr):
if pos:
node.model.pos = [float(pos[0]), float(pos[1])]

# initial node direction layout.
node.model.layout_direction = self.layout_direction()

node.update()

if push_undo:
Expand Down Expand Up @@ -964,6 +1024,11 @@ def add_node(self, node, pos=None, selected=True, push_undo=True):
node.NODE_NAME = self.get_unique_name(node.NODE_NAME)
node.model._graph_model = self.model
node.model.name = node.NODE_NAME

# initial node direction layout.
node.model.layout_direction = self.layout_direction()

# update method must be called before it's been added to the viewer.
node.update()

if push_undo:
Expand Down Expand Up @@ -1672,7 +1737,9 @@ def auto_layout_nodes(self, nodes=None, down_stream=True, start_nodes=None):
else:
rank_map[rank] = [node]

if NODE_LAYOUT_DIRECTION is NODE_LAYOUT_HORIZONTAL:
node_layout_direction = self._viewer.get_layout_direction()

if node_layout_direction is LayoutDirectionEnum.HORIZONTAL.value:
current_x = 0
node_height = 120
for rank in sorted(range(len(rank_map)), reverse=not down_stream):
Expand All @@ -1687,7 +1754,7 @@ def auto_layout_nodes(self, nodes=None, down_stream=True, start_nodes=None):
current_y += dy * 0.5 + 10

current_x += max_width * 0.5 + 100
elif NODE_LAYOUT_DIRECTION is NODE_LAYOUT_VERTICAL:
elif node_layout_direction is LayoutDirectionEnum.VERTICAL.value:
current_y = 0
node_width = 250
for rank in sorted(range(len(rank_map)), reverse=not down_stream):
Expand Down Expand Up @@ -1861,7 +1928,11 @@ def expand_group_node(self, node):

# build new sub graph.
node_factory = copy.deepcopy(self.node_factory)
sub_graph = SubGraph(self, node=node, node_factory=node_factory)
layout_direction = self.layout_direction()
sub_graph = SubGraph(self,
node=node,
node_factory=node_factory,
layout_direction=layout_direction)

# populate the sub graph.
session = node.get_sub_graph_session()
Expand Down Expand Up @@ -1913,14 +1984,17 @@ class SubGraph(NodeGraph):
-
"""

def __init__(self, parent=None, node=None, node_factory=None):
def __init__(self, parent=None, node=None, node_factory=None, **kwargs):
"""
Args:
parent (object): object parent.
node (GroupNode): group node related to this sub graph.
node_factory (NodeFactory): override node factory.
**kwargs (dict): additional kwargs.
"""
super(SubGraph, self).__init__(parent, node_factory=node_factory)
super(SubGraph, self).__init__(
parent, node_factory=node_factory, **kwargs
)

# sub graph attributes.
self._node = node
Expand Down Expand Up @@ -1953,6 +2027,8 @@ def _build_port_nodes(self):
Returns:
tuple(dict, dict): input nodes, output nodes.
"""
node_layout_direction = self._viewer.get_layout_direction()

# build the parent input port nodes.
input_nodes = {n.name(): n for n in
self.get_nodes_by_type(PortInputNode.type_)}
Expand All @@ -1965,9 +2041,9 @@ def _build_port_nodes(self):
input_nodes[port.name()] = input_node
self.add_node(input_node, selected=False, push_undo=False)
x, y = input_node.pos()
if NODE_LAYOUT_DIRECTION is NODE_LAYOUT_HORIZONTAL:
if node_layout_direction is LayoutDirectionEnum.HORIZONTAL.value:
x -= 100
elif NODE_LAYOUT_DIRECTION is NODE_LAYOUT_VERTICAL:
elif node_layout_direction is LayoutDirectionEnum.VERTICAL.value:
y -= 100
input_node.set_property('pos', [x, y], push_undo=False)

Expand All @@ -1983,9 +2059,9 @@ def _build_port_nodes(self):
output_nodes[port.name()] = output_node
self.add_node(output_node, selected=False, push_undo=False)
x, y = output_node.pos()
if NODE_LAYOUT_DIRECTION is NODE_LAYOUT_HORIZONTAL:
if node_layout_direction is LayoutDirectionEnum.HORIZONTAL.value:
x += 100
elif NODE_LAYOUT_DIRECTION is NODE_LAYOUT_VERTICAL:
elif node_layout_direction is LayoutDirectionEnum.VERTICAL.value:
y += 100
output_node.set_property('pos', [x, y], push_undo=False)

Expand Down Expand Up @@ -2282,7 +2358,10 @@ def expand_group_node(self, node):

# build new sub graph.
node_factory = copy.deepcopy(self.node_factory)
sub_graph = SubGraph(self, node=node, node_factory=node_factory)
sub_graph = SubGraph(self,
node=node,
node_factory=node_factory,
layout_direction=self.layout_direction())

# populate the sub graph.
serialized_session = node.get_sub_graph_session()
Expand Down
42 changes: 30 additions & 12 deletions NodeGraphQt/base/graph_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ def build_context_menu(graph):
graph (NodeGraphQt.NodeGraph): node graph controller.
"""
from Qt import QtGui, QtCore
graph_menu = graph.get_context_menu('graph')
context_menu = graph.get_context_menu('graph')

# "File" menu.
# --------------------------------------------------------------------------
file_menu = graph_menu.add_menu('&File')
file_menu = context_menu.add_menu('&File')

file_menu.add_command('Open...', _open_session, QtGui.QKeySequence.Open)
file_menu.add_command('Import...', _import_session)
Expand All @@ -22,7 +22,7 @@ def build_context_menu(graph):

# "Edit" menu.
# --------------------------------------------------------------------------
edit_menu = graph_menu.add_menu('&Edit')
edit_menu = context_menu.add_menu('&Edit')

edit_menu.add_separator()
edit_menu.add_command('Clear Undo History', _clear_undo)
Expand All @@ -49,20 +49,24 @@ def build_context_menu(graph):
edit_menu.add_command('Zoom Out', _zoom_out, '-')
edit_menu.add_command('Reset Zoom', _reset_zoom, 'H')

edit_menu.add_separator()
context_menu.add_separator()

# "Grid Mode" submenu.
# "Node" menu.
# --------------------------------------------------------------------------
bg_menu = edit_menu.add_menu('&Grid Mode')
bg_menu.add_command('None', _bg_grid_none)
bg_menu.add_command('Lines', _bg_grid_lines)
bg_menu.add_command('Dots', _bg_grid_dots)
graph_menu = context_menu.add_menu('&Graph')

edit_menu.add_separator()
bg_menu = graph_menu.add_menu('&Background')
bg_menu.add_command('None', _bg_grid_none, 'Alt+1')
bg_menu.add_command('Lines', _bg_grid_lines, 'Alt+2')
bg_menu.add_command('Dots', _bg_grid_dots, 'Alt+3')

layout_menu = graph_menu.add_menu('&Layout')
layout_menu.add_command('Horizontal', _layout_h_mode, 'Shift+1')
layout_menu.add_command('Vertical', _layout_v_mode, 'Shift+2')

# "Node" menu.
# --------------------------------------------------------------------------
node_menu = graph_menu.add_menu('&Nodes')
node_menu = context_menu.add_menu('&Nodes')
node_menu.add_command('Node Search', _toggle_node_search, 'Tab')
node_menu.add_separator()
node_menu.add_command(
Expand All @@ -76,7 +80,7 @@ def build_context_menu(graph):

# "Pipe" menu.
# --------------------------------------------------------------------------
pipe_menu = graph_menu.add_menu('&Pipes')
pipe_menu = context_menu.add_menu('&Pipes')
pipe_menu.add_command('Curved', _curved_pipe)
pipe_menu.add_command('Straight', _straight_pipe)
pipe_menu.add_command('Angle', _angle_pipe)
Expand Down Expand Up @@ -109,6 +113,20 @@ def _reset_zoom(graph):
graph.reset_zoom()


def _layout_h_mode(graph):
"""
Set node graph layout direction to horizontal.
"""
graph.set_layout_direction(0)


def _layout_v_mode(graph):
"""
Set node graph layout direction to vertical.
"""
graph.set_layout_direction(1)


def _open_session(graph):
"""
Prompts a file open dialog to load a session.
Expand Down
5 changes: 5 additions & 0 deletions NodeGraphQt/base/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from collections import defaultdict

from NodeGraphQt.constants import (
LayoutDirectionEnum,
NODE_PROP,
NODE_PROP_QLABEL,
NODE_PROP_QLINEEDIT,
Expand Down Expand Up @@ -73,6 +74,7 @@ def __init__(self):
self.width = 100.0
self.height = 80.0
self.pos = [0.0, 0.0]
self.layout_direction = LayoutDirectionEnum.HORIZONTAL.value

# BaseNode attrs.
self.inputs = {}
Expand Down Expand Up @@ -107,6 +109,7 @@ def __init__(self):
'width': NODE_PROP,
'height': NODE_PROP,
'pos': NODE_PROP,
'layout_direction': NODE_PROP,
'inputs': NODE_PROP,
'outputs': NODE_PROP,
}
Expand Down Expand Up @@ -230,6 +233,7 @@ def to_dict(self):
'width': 0.0,
'height: 0.0,
'pos': (0.0, 0.0),
'layout_direction': 0,
'custom': {},
'inputs': {
<port_name>: {<node_id>: [<port_name>, <port_name>]}
Expand Down Expand Up @@ -317,6 +321,7 @@ def __init__(self):
self.session = ''
self.acyclic = True
self.pipe_collision = False
self.layout_direction = LayoutDirectionEnum.HORIZONTAL.value

def common_properties(self):
"""
Expand Down
Loading

0 comments on commit 80d9af9

Please sign in to comment.