Commit 47e75c78 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Improved user interface when using nested states

parent 9414451d
......@@ -624,8 +624,7 @@ class Symbol(QObject, QGraphicsPathItem, object):
def is_composite(self):
''' Return True if nested scene has something in it '''
try:
return self.allow_nesting and any(item.isVisible()
for item in self._nested_scene.items())
return any(self._nested_scene.visible_symb)
except AttributeError:
return False
......@@ -979,6 +978,10 @@ class Symbol(QObject, QGraphicsPathItem, object):
else:
self.mode = 'Move'
def double_click(self):
''' Handle double click on symbol - redefined at symbol level '''
pass
def mouse_move(self, event):
''' Handle resizing of items - moving is handled in subclass '''
self.updateConnectionPoints()
......
......@@ -292,6 +292,8 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
self.search_pattern = None
# Selection rectangle when user clicks on the scene and moves mouse
self.select_rect = None
# Keep a list of composite states: {'stateName': SDL_Scene}
self._composite_states = {}
@property
......@@ -345,8 +347,16 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
@property
def composite_states(self):
''' Return states that contain a composite part '''
return (it for it in self.states if it.is_composite())
# Update the list first
for each in self.states:
if each.is_composite() and \
each.nested_scene not in self._composite_states.viewvalues():
self._composite_states[str(each).lower()] = each.nested_scene
return self._composite_states
@composite_states.setter
def composite_states(self, value):
self._composite_states = value
@property
def all_nested_scenes(self):
......@@ -375,6 +385,18 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
subscene.messages_window = self.messages_window
recursive_render(item.nested_scene.content, subscene)
item.nested_scene = subscene
for each in dest_scene.states:
# Update the list of composite states at scene level
if each.is_composite():
dest_scene.composite_states[str(each).lower()] =\
each.nested_scene
for each in dest_scene.states:
# Make sure all composite states are initially up to date
# (Needed for the symbol shape)
if str(each).lower() in dest_scene.composite_states.viewkeys()\
and not each.nested_scene:
each.nested_scene = dest_scene.composite_states[
str(each).lower()]
recursive_render(process, self)
......@@ -640,9 +662,14 @@ class SDL_Scene(QtGui.QGraphicsScene, object):
pr_data.append(repr(item))
for item in self.floating_labels:
pr_data.append(item.parse_gr())
composite = set(self.composite_states.keys())
for item in self.states:
if item.is_composite():
pr_data.appendleft(item.parse_composite_state())
try:
composite.remove(str(item).lower())
pr_data.appendleft(item.parse_composite_state())
except KeyError:
pass
pr_data.append(item.parse_gr())
pr_data.appendleft('PROCESS {};'.format(self.process_name))
......@@ -1235,15 +1262,11 @@ class SDL_View(QtGui.QGraphicsView, object):
item = self.scene().symbol_near(self.mapToScene(evt.pos()))
try:
if item.allow_nesting:
item.double_click()
if not isinstance(item.nested_scene, SDL_Scene):
subscene = SDL_Scene(
context=item.__class__.__name__.lower())
subscene.messages_window = self.messages_window
# if item.nested_scene:
# Removed - cannot happen, scenes are created by SDL_Scene.render_process
# for top_level in Renderer.render(
# item.nested_scene.content, subscene):
# G_SYMBOLS.add(top_level)
item.nested_scene = subscene
self.go_down(item.nested_scene)
else:
......@@ -1310,14 +1333,14 @@ class SDL_View(QtGui.QGraphicsView, object):
# Translate scenes to avoid negative coordinates
for each in scene.all_nested_scenes:
each.translate_to_origin()
# XXX don't translate current scene to avoid a jump of scrollbars
#center = self.viewport().rect().center()
#delta_x, delta_y = scene.translate_to_origin()
#center.setX(center.x() + delta_x)
#center.setY(center.y() + delta_y)
#self.centerOn(center)
delta_x, delta_y = scene.translate_to_origin()
pr_raw = scene.get_pr_string()
# Move items back to original place to avoid scrollbar jumps
for item in scene.floating_symb:
item.moveBy(-delta_x, -delta_y)
pr_data = str('\n'.join(pr_raw))
try:
pr_file.write(pr_data)
......
......@@ -879,16 +879,17 @@ class State(VerticalSymbol):
@property
def nested_scene(self):
''' Redefined - nested scene per state must be unique '''
if not self._nested_scene:
# Check that the nested scene is not already rendered
try:
for each in self.scene().composite_states:
if str(each).lower().strip() == str(self).lower().strip():
return each._nested_scene
except AttributeError:
pass
return self._nested_scene
def double_click(self):
''' Catch a double click - Set nested scene '''
for each, value in self.scene().composite_states.viewitems():
if str(self).lower() == str(each):
self.nested_scene = value
break
else:
self.nested_scene = None
@nested_scene.setter
def nested_scene(self, value):
''' Set the value of the nested scene '''
......@@ -917,16 +918,10 @@ class State(VerticalSymbol):
''' Compute the polygon to fit in width, height '''
path = QPainterPath()
path.addRoundedRect(0, 0, width, height, height / 4, height)
if self.is_composite():
path.addRoundedRect(5,5, width-10, height-10, height/4, height)
textattr = Qt.TextBrowserInteraction
else:
textattr = Qt.TextEditorInteraction
try:
# Set text of state to readonly when it is composite
self.text.setTextInteractionFlags(textattr)
except AttributeError:
pass
if self.nested_scene and self.is_composite():
# Distinguish composite states with dash line
self.setPen(QPen(Qt.DashLine))
self.setPath(path)
super(State, self).set_shape(width, height)
......@@ -945,7 +940,6 @@ class State(VerticalSymbol):
def parse_composite_state(self):
''' Return PR string corresponding to the nested part of the state '''
# TODO: add CIF comment for merging at parsing
entry_points, exit_points = [], []
result = ['STATE {};'.format(str(self)),
'SUBSTRUCTURE']
......
......@@ -3,29 +3,29 @@ STATE ON;
SUBSTRUCTURE
in (via_toto);
out (ret0);
/* CIF TEXT (-642, 222), (334, 95) */
/* CIF TEXT (242, 251), (334, 95) */
dcl myresult T_UInt8 := 4;
-- Use a variable with the same name as a variable
-- in the outer scope, to check that code generators
-- use the proper one
dcl result T_UInt32 := 9;
/* CIF ENDTEXT */
/* CIF PROCEDURE (-326, 114), (70, 35) */
PROCEDURE exit
/* CIF COMMENT (-236, 90), (157, 93) */
COMMENT 'Special exit
/* CIF PROCEDURE (554, 54), (73, 35) */
PROCEDURE entry
/* CIF COMMENT (643, 31), (190, 83) */
COMMENT 'Special Entry
procedure - called
automatically when
leaving the nested
automatically upon
entrance to the nested
state';
/* CIF START (163, 119), (70, 35) */
/* CIF START (191, 78), (70, 35) */
START;
/* CIF PROCEDURECALL (68, 169), (259, 35) */
CALL writeln('LEAVING the nested state');
/* CIF RETURN (180, 219), (35, 35) */
/* CIF PROCEDURECALL (100, 128), (251, 35) */
CALL writeln('ENTERING NESTED STATE');
/* CIF RETURN (208, 178), (35, 35) */
RETURN ;
ENDPROCEDURE;
/* CIF PROCEDURE (-645, 493), (102, 35) */
/* CIF PROCEDURE (239, 522), (102, 35) */
PROCEDURE inner_proc;
/* CIF TEXT (31, 41), (364, 93) */
fpar in toto T_UInt8;
......@@ -46,86 +46,86 @@ leaving:
/* CIF RETURN (496, 347), (35, 35) */
RETURN ;
ENDPROCEDURE;
/* CIF PROCEDURE (-330, 25), (73, 35) */
PROCEDURE entry
/* CIF COMMENT (-241, 2), (190, 83) */
COMMENT 'Special Entry
/* CIF PROCEDURE (558, 143), (70, 35) */
PROCEDURE exit
/* CIF COMMENT (648, 119), (157, 93) */
COMMENT 'Special exit
procedure - called
automatically upon
entrance to the nested
automatically when
leaving the nested
state';
/* CIF START (191, 78), (70, 35) */
/* CIF START (163, 119), (70, 35) */
START;
/* CIF PROCEDURECALL (100, 128), (251, 35) */
CALL writeln('ENTERING NESTED STATE');
/* CIF RETURN (208, 178), (35, 35) */
/* CIF PROCEDURECALL (68, 169), (259, 35) */
CALL writeln('LEAVING the nested state');
/* CIF RETURN (180, 219), (35, 35) */
RETURN ;
ENDPROCEDURE;
/* CIF START (304, -22), (89, 35) */
/* CIF START (1188, 7), (89, 35) */
START via_toto ;
/* CIF PROCEDURECALL (213, 28), (271, 35) */
/* CIF PROCEDURECALL (1097, 57), (271, 35) */
CALL writeln('start via toto, returning ret0');
/* CIF RETURN (331, 78), (35, 35) */
/* CIF RETURN (1215, 107), (35, 35) */
RETURN ret0;
/* CIF START (54, -21), (70, 35) */
/* CIF START (938, 8), (70, 35) */
START;
/* CIF PROCEDURECALL (-10, 29), (199, 35) */
/* CIF PROCEDURECALL (873, 58), (199, 35) */
CALL writeln('start without via');
/* CIF LABEL (33, 79), (111, 35) */
/* CIF LABEL (917, 108), (111, 35) */
inside_label:
/* CIF PROCEDURECALL (20, 129), (137, 35) */
/* CIF PROCEDURECALL (904, 158), (137, 35) */
CALL pow(3,3, result);
/* CIF DECISION (52, 179), (74, 50) */
/* CIF DECISION (936, 208), (74, 50) */
DECISION result;
/* CIF ANSWER (-23, 249), (92, 23) */
/* CIF ANSWER (861, 278), (92, 23) */
(myresult):
/* CIF ANSWER (101, 249), (70, 23) */
/* CIF ANSWER (985, 278), (70, 23) */
ELSE:
/* CIF TASK (78, 287), (115, 35) */
/* CIF TASK (962, 316), (115, 35) */
TASK myresult := 5;
ENDDECISION;
/* CIF PROCEDURECALL (-47, 337), (272, 35) */
/* CIF PROCEDURECALL (837, 366), (272, 35) */
CALL writeln('going to internal hello state');
/* CIF LABEL (45, 387), (88, 35) */
/* CIF LABEL (929, 416), (88, 35) */
nslabel:
/* CIF NEXTSTATE (54, 437), (70, 35) */
/* CIF NEXTSTATE (938, 466), (70, 35) */
NEXTSTATE hello;
/* CIF LABEL (-752, 295), (90, 35) */
CONNECTION to_label:
/* CIF JOIN (-725, 345), (35, 35) */
JOIN another_floating;
/* CIF End Label */
ENDCONNECTION;
/* CIF LABEL (-372, 443), (141, 35) */
/* CIF LABEL (512, 472), (141, 35) */
CONNECTION another_floating:
/* CIF TASK (-359, 493), (115, 35) */
/* CIF TASK (525, 522), (115, 35) */
TASK myresult := 1;
/* CIF PROCEDURECALL (-383, 543), (164, 35) */
/* CIF PROCEDURECALL (500, 572), (164, 35) */
CALL inner_proc(myresult);
/* CIF RETURN (-319, 593), (35, 35) */
/* CIF RETURN (565, 622), (35, 35) */
RETURN ;
/* CIF End Label */
ENDCONNECTION;
/* CIF STATE (-884, -29), (70, 35) */
/* CIF LABEL (132, 324), (90, 35) */
CONNECTION to_label:
/* CIF JOIN (159, 374), (35, 35) */
JOIN another_floating;
/* CIF End Label */
ENDCONNECTION;
/* CIF STATE (0, 0), (70, 35) */
STATE hello;
/* CIF INPUT (-884, 32), (70, 35) */
/* CIF INPUT (0, 61), (70, 35) */
INPUT run;
/* CIF PROCEDURECALL (-1047, 82), (395, 35) */
/* CIF PROCEDURECALL (-162, 111), (395, 35) */
CALL writeln('Bye substate, leaving with no return value', result);
/* CIF TASK (-912, 132), (125, 53) */
/* CIF TASK (-27, 161), (125, 53) */
TASK myresult := 88,
result := 33;
/* CIF JOIN (-867, 200), (35, 35) */
/* CIF JOIN (17, 229), (35, 35) */
JOIN to_label;
ENDSTATE;
ENDSUBSTRUCTURE;
/* CIF TEXT (-486, -40), (298, 56) */
/* CIF TEXT (506, 0), (298, 56) */
-- This system tests nested states
dcl result T_uint32 :=0;
/* CIF ENDTEXT */
/* CIF PROCEDURE (-992, 214), (66, 35) */
/* CIF PROCEDURE (0, 254), (66, 35) */
PROCEDURE toto;
/* CIF TEXT (371, 134), (298, 140) */
-- Declare your variables
......@@ -150,66 +150,66 @@ ELSE:
RETURN ;
ENDDECISION;
ENDPROCEDURE;
/* CIF START (-857, 59), (68, 37) */
/* CIF START (135, 99), (68, 37) */
START;
/* CIF PROCEDURECALL (-935, 111), (225, 35) */
/* CIF PROCEDURECALL (56, 151), (225, 35) */
CALL writeln('[STARTUP] Going OFF');
/* CIF NEXTSTATE (-858, 161), (70, 35) */
/* CIF NEXTSTATE (134, 201), (70, 35) */
NEXTSTATE OFF;
/* CIF STATE (-443, 238), (73, 35) */
STATE Safe;
/* CIF INPUT (-487, 293), (70, 35) */
INPUT *;
/* CIF PROCEDURECALL (-517, 343), (130, 35) */
CALL pow(2,2, result);
/* CIF PROCEDURECALL (-583, 393), (262, 35) */
CALL writeln('Result of pow(2,2) = ', result);
/* CIF NEXTSTATE (-487, 443), (70, 35) */
NEXTSTATE -;
/* CIF INPUT (-313, 293), (88, 35) */
INPUT any_one;
/* CIF NEXTSTATE (-304, 343), (70, 35) */
NEXTSTATE on;
ENDSTATE;
/* CIF STATE (-141, 32), (65, 35) */
/* CIF STATE (851, 72), (65, 35) */
STATE ON;
/* CIF INPUT (51, 87), (88, 35) */
/* CIF INPUT (1043, 127), (88, 35) */
INPUT any_one;
/* CIF NEXTSTATE (38, 137), (113, 35) */
/* CIF NEXTSTATE (1030, 177), (113, 35) */
NEXTSTATE -;
/* CIF INPUT (161, 87), (78, 35) */
/* CIF INPUT (1153, 127), (78, 35) */
INPUT go_off;
/* CIF NEXTSTATE (169, 137), (62, 35) */
/* CIF NEXTSTATE (1161, 177), (62, 35) */
NEXTSTATE OFF;
/* CIF CONNECT (-108, 87), (0, 35) */
/* CIF CONNECT (884, 127), (0, 35) */
CONNECT ret0;
/* CIF PROCEDURECALL (-244, 137), (272, 35) */
/* CIF PROCEDURECALL (748, 177), (272, 35) */
CALL writeln('Received ret0, going to Safe');
/* CIF NEXTSTATE (-141, 187), (67, 35) */
/* CIF NEXTSTATE (851, 227), (67, 35) */
NEXTSTATE Safe;
/* CIF CONNECT (-424, 87), (0, 35) */
/* CIF CONNECT (568, 127), (0, 35) */
CONNECT ;
/* CIF PROCEDURECALL (-594, 137), (340, 35) */
/* CIF PROCEDURECALL (398, 177), (340, 35) */
CALL writeln('Exit from nested state (no return value)');
/* CIF NEXTSTATE (-459, 187), (70, 35) */
/* CIF NEXTSTATE (533, 227), (70, 35) */
NEXTSTATE off;
ENDSTATE;
/* CIF STATE (-858, 161), (70, 35) */
/* CIF STATE (549, 278), (73, 35) */
STATE Safe;
/* CIF INPUT (505, 333), (70, 35) */
INPUT *;
/* CIF PROCEDURECALL (475, 383), (130, 35) */
CALL pow(2,2, result);
/* CIF PROCEDURECALL (409, 433), (262, 35) */
CALL writeln('Result of pow(2,2) = ', result);
/* CIF NEXTSTATE (505, 483), (70, 35) */
NEXTSTATE -;
/* CIF INPUT (679, 333), (88, 35) */
INPUT any_one;
/* CIF NEXTSTATE (688, 383), (70, 35) */
NEXTSTATE on;
ENDSTATE;
/* CIF STATE (134, 201), (70, 35) */
STATE OFF;
/* CIF INPUT (-858, 216), (70, 35) */
/* CIF INPUT (134, 256), (70, 35) */
INPUT run;
/* CIF PROCEDURECALL (-931, 266), (217, 35) */
/* CIF PROCEDURECALL (60, 306), (217, 35) */
CALL writeln('Going ON VIA TOTO');
/* CIF NEXTSTATE (-890, 317), (132, 35) */
/* CIF NEXTSTATE (102, 357), (132, 35) */
NEXTSTATE ON via via_toto
/* CIF COMMENT (-738, 317), (219, 35) */
/* CIF COMMENT (254, 357), (219, 35) */
COMMENT 'Enter substate via entry point';
ENDSTATE;
ENDPROCESS challenge;
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment