def state_machine_change_after(self, model, prop_name, info):
        """Called on any change within th state machine

        This method is called, when any state, transition, data flow, etc. within the state machine changes. This
        then typically requires a redraw of the graphical editor, to display these changes immediately.

        :param rafcon.gui.models.state_machine.StateMachineModel model: The state machine model
        :param str prop_name: The property that was changed
        :param dict info: Information about the change
        """

        if 'method_name' in info and info['method_name'] == 'root_state_change':
            method_name, model, result, arguments, instance = self._extract_info_data(info['kwargs'])

            if self.model.ongoing_complex_actions:
                return

            # The method causing the change raised an exception, thus nothing was changed
            if (isinstance(result, string_types) and "CRASH" in result) or isinstance(result, Exception):
                return

            # avoid to remove views of elements of states which parent state is destroyed recursively
            if 'remove' in method_name:
                # for remove the model is always a state and in case of remove_state it is the container_state
                # that performs the operation therefore if is_about_to_be_destroyed_recursively is False
                # the child state can be removed and for True ignored because its parent will create a notification
                if model.is_about_to_be_destroyed_recursively:
                    return

            # only react to the notification if the model is a model, which has to be drawn
            # if it is a model inside a library state, this is eventually not the case
            if isinstance(model, AbstractStateModel):
                library_root_state = model.state.get_next_upper_library_root_state()
                if library_root_state:
                    parent_library_root_state_m = self.model.get_state_model_by_path(library_root_state.get_path())
                    if not parent_library_root_state_m.parent.show_content():
                        return

            if method_name == 'state_execution_status':
                state_v = self.canvas.get_view_for_model(model)
                if state_v:  # Children of LibraryStates are not modeled, yet
                    self.canvas.request_update(state_v, matrix=False)
            elif method_name == 'add_state':
                new_state = arguments[1]
                new_state_m = model.states[new_state.state_id]
                self.add_state_view_with_meta_data_for_model(new_state_m, model)
                if not self.perform_drag_and_drop:
                    self.canvas.wait_for_update()
            elif method_name == 'remove_state':
                state_v = self.canvas.get_view_for_core_element(result)
                if state_v:
                    parent_v = self.canvas.get_parent(state_v)
                    state_v.remove()
                    if parent_v:
                        self.canvas.request_update(parent_v)
                    self.canvas.wait_for_update()

            # ----------------------------------
            #           TRANSITIONS
            # ----------------------------------
            elif method_name == 'add_transition':
                transitions_models = model.transitions
                transition_id = result
                for transition_m in transitions_models:
                    if transition_m.transition.transition_id == transition_id:
                        self.add_transition_view_for_model(transition_m, model)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'remove_transition':
                transition_v = self.canvas.get_view_for_core_element(result)
                if transition_v:
                    state_m = model
                    state_v = self.canvas.get_view_for_model(state_m)
                    transition_v.remove()
                    self.canvas.request_update(state_v, matrix=False)
                    self.canvas.wait_for_update()
            elif method_name == 'transition_change':
                transition_m = model
                transition_v = self.canvas.get_view_for_model(transition_m)
                self._reconnect_transition(transition_v, transition_m, transition_m.parent)
                self.canvas.wait_for_update()

            # ----------------------------------
            #           DATA FLOW
            # ----------------------------------
            elif method_name == 'add_data_flow':
                data_flow_models = model.data_flows
                data_flow_id = result
                for data_flow_m in data_flow_models:
                    if data_flow_m.data_flow.data_flow_id == data_flow_id:
                        self.add_data_flow_view_for_model(data_flow_m, model)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'remove_data_flow':
                data_flow_v = self.canvas.get_view_for_core_element(result)
                if data_flow_v:
                    state_m = model
                    state_v = self.canvas.get_view_for_model(state_m)
                    self.canvas.request_update(state_v, matrix=False)
                    data_flow_v.remove()
                    self.canvas.wait_for_update()
            elif method_name == 'data_flow_change':
                data_flow_m = model
                data_flow_v = self.canvas.get_view_for_model(data_flow_m)
                self._reconnect_data_flow(data_flow_v, data_flow_m, data_flow_m.parent)
                self.canvas.wait_for_update()

            # ----------------------------------
            #           OUTCOMES
            # ----------------------------------
            elif method_name == 'add_outcome':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                for outcome_m in state_m.outcomes:
                    if outcome_m.outcome.outcome_id == result:
                        state_v.add_outcome(outcome_m)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'remove_outcome':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                if state_v is None:
                    logger.debug("no state_v found for method_name '{}'".format(method_name))
                else:
                    outcome_v = self.canvas.get_view_for_core_element(result)
                    if outcome_v:
                        state_v.remove_outcome(outcome_v)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()

            # ----------------------------------
            #           DATA PORTS
            # ----------------------------------
            elif method_name == 'add_input_data_port':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                for input_data_port_m in state_m.input_data_ports:
                    if input_data_port_m.data_port.data_port_id == result:
                        state_v.add_input_port(input_data_port_m)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'add_output_data_port':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                for output_data_port_m in state_m.output_data_ports:
                    if output_data_port_m.data_port.data_port_id == result:
                        state_v.add_output_port(output_data_port_m)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'remove_input_data_port':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                if state_v is None:
                    logger.debug("no state_v found for method_name '{}'".format(method_name))
                else:
                    input_port_v = self.canvas.get_view_for_core_element(result)
                    if input_port_v:
                        state_v.remove_input_port(input_port_v)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
            elif method_name == 'remove_output_data_port':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                if state_v is None:
                    logger.debug("no state_v found for method_name '{}'".format(method_name))
                else:
                    output_port_v = self.canvas.get_view_for_core_element(result)
                    if output_port_v:
                        state_v.remove_output_port(output_port_v)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
            elif method_name in ['data_type', 'change_data_type']:
                pass
            elif method_name == 'default_value':
                pass

            # ----------------------------------
            #         SCOPED VARIABLES
            # ----------------------------------
            elif method_name == 'add_scoped_variable':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                for scoped_variable_m in state_m.scoped_variables:
                    if scoped_variable_m.scoped_variable.data_port_id == result:
                        state_v.add_scoped_variable(scoped_variable_m)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()
                        break
            elif method_name == 'remove_scoped_variable':
                state_m = model
                state_v = self.canvas.get_view_for_model(state_m)
                if state_v is None:
                    logger.debug("no state_v found for method_name '{}'".format(method_name))
                else:
                    scoped_variable_v = self.canvas.get_view_for_core_element(result)
                    if scoped_variable_v:
                        state_v.remove_scoped_variable(scoped_variable_v)
                        self.canvas.request_update(state_v, matrix=False)
                        self.canvas.wait_for_update()

            # ----------------------------------
            #        STATE MISCELLANEOUS
            # ----------------------------------
            elif method_name == 'name':
                # The name of a state was changed
                if not isinstance(model, AbstractStateModel):
                    parent_model = model.parent
                # The name of a port (input, output, scoped var, outcome) was changed
                else:
                    parent_model = model
                state_v = self.canvas.get_view_for_model(parent_model)
                if parent_model is model:
                    state_v.name_view.name = arguments[1]
                    self.canvas.request_update(state_v.name_view, matrix=False)
                else:
                    self.canvas.request_update(state_v, matrix=False)
                self.canvas.wait_for_update()
            elif method_name == 'parent':
                pass
            elif method_name == 'description':
                pass
            elif method_name == 'script_text':
                pass
            # TODO handle the following method calls -> for now those are explicit (in the past implicit) ignored
            # TODO -> correct the complex actions which are used in some test (by test calls or by adapting the model)
            elif method_name in ['input_data_ports', 'output_data_ports', 'outcomes',
                                 'change_root_state_type', 'change_state_type',
                                 'group_states', 'ungroup_state', 'substitute_state']:
                pass
            else:
                known_ignore_list = ['set_input_runtime_value', 'set_use_input_runtime_value',  # from library State
                                     'set_output_runtime_value', 'set_use_output_runtime_value',
                                     'input_data_port_runtime_values', 'use_runtime_value_input_data_ports',
                                     'output_data_port_runtime_values', 'use_runtime_value_output_data_ports',
                                     'semantic_data', 'add_semantic_data', 'remove_semantic_data',
                                     'remove_income']
                if method_name not in known_ignore_list:
                    logger.warning("Method {0} not caught in GraphicalViewer, details: {1}".format(method_name, info))

            if method_name in ['add_state', 'add_transition', 'add_data_flow', 'add_outcome', 'add_input_data_port',
                               'add_output_data_port', 'add_scoped_variable', 'data_flow_change', 'transition_change']:
                try:
                    self._meta_data_changed(None, model, 'append_to_last_change', True)
                except Exception as e:
                    logger.exception('Error while trying to emit meta data signal {0} {1}'.format(e, model))