Skip to content

Commit

Permalink
Fix #15: Correctly handle duplicate state class definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
pschillinger committed Nov 30, 2018
1 parent deb1d14 commit e4b90f3
Show file tree
Hide file tree
Showing 17 changed files with 120 additions and 51 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "FlexBE App",
"version": "2.0.10",
"version": "2.0.11",
"main": "src/main.js",
"window": {
"icon": "src/img/icon-128.png",
Expand Down
2 changes: 1 addition & 1 deletion package.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<package>
<name>flexbe_app</name>
<version>2.0.10</version>
<version>2.0.11</version>
<description>
flexbe_app provides a user interface (editor + runtime control) for the FlexBE behavior engine.
</description>
Expand Down
8 changes: 4 additions & 4 deletions src/_helper/command_lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ CommandLib = new (function() {
text: "Lists all available commands."
},
{
desc: "findStateUsage [state_class]",
match: /^findStateUsage[( ]["']?([a-zA-Z0-9_]+)["']?\)?$/,
desc: "findStateUsage [state_type]",
match: /^findStateUsage[( ]["']?([a-zA-Z0-9_]+\.[a-zA-Z0-9_]+)["']?\)?$/,
impl: function(args) {
Scripts.findStateUsage(args[1]);
UI.Tools.notifyRosCommand('findStateUsage');
},
text: "Searches in all behaviors for instantiations of the given class.",
completions: [function() { return WS.Statelib.getClassList(); }]
text: "Searches in all behaviors for instantiations of the given type.",
completions: [function() { return WS.Statelib.getTypeList(); }]
},
{
desc: "statemachine [new_name]",
Expand Down
2 changes: 1 addition & 1 deletion src/_helper/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Tools = new (function() {
new_state = new BehaviorState(s.getBehaviorName(), WS.Behaviorlib.getByName(s.getBehaviorName()), s.getDefaultKeys().clone());
new_state.setStateName(s.getStateName());
} else if (s instanceof State) {
var state_def = WS.Statelib.getFromLib(s.getStateClass());
var state_def = WS.Statelib.getFromLib(s.getStateType());
new_state = new State(s.getStateName(), state_def);
}

Expand Down
4 changes: 4 additions & 0 deletions src/_model/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ State = function(state_name, state_def) {
state_pkg = _state_pkg;
}

this.getStateType = function() {
return that.getStatePackage() + "." + that.getStateClass();
}

this.getParameters = function() {
return parameters;
}
Expand Down
2 changes: 1 addition & 1 deletion src/_test/statelib.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ StatelibTest = new (function() {

this.testWaitStateAvailable = function(report, done) {
// flexbe_states/WaitState is found and properly imported
var result = WS.Statelib.getClassList().contains("WaitState");
var result = WS.Statelib.getTypeList().contains("flexbe_states.WaitState");
report.assertTrue.test_statelib = result;
done();
}
Expand Down
1 change: 1 addition & 0 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ document.addEventListener('DOMContentLoaded', function() {

document.getElementById('select_default_package').addEventListener('change', UI.Settings.defaultPackageChanged);
document.getElementById('select_code_indentation').addEventListener('change', UI.Settings.codeIndentationChanged);
document.getElementById('cb_explicit_states').addEventListener('change', UI.Settings.explicitStatesClicked);
document.getElementById('input_editor_command').addEventListener('change', UI.Settings.editorCommandChanged);

document.getElementById('select_transition_mode').addEventListener('change', UI.Settings.transitionEndpointsChanged);
Expand Down
15 changes: 12 additions & 3 deletions src/io/io_codegenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ IO.CodeGenerator = new (function() {
if (states[i] instanceof Statemachine) continue;

var import_reference = imported_states.findElement(function(element) {
return element.getStateClass() == states[i].getStateClass();
return element.getStateClass() == states[i].getStateClass()
&& element.getStatePackage() == states[i].getStatePackage();
});
if (import_reference == undefined) {
imported_states.push(states[i]);
Expand All @@ -38,7 +39,12 @@ IO.CodeGenerator = new (function() {
// generate import lines
var import_list = [];
for (var i=0; i<imported_states.length; ++i) {
import_list.push("from " + imported_states[i].getStateImport() + " import " + imported_states[i].getStateClass());
if (!UI.Settings.isExplicitStates() && WS.Statelib.isClassUnique(imported_states[i].getStateClass())) {
import_list.push("from " + imported_states[i].getStateImport() + " import " + imported_states[i].getStateClass());
} else {
import_list.push("from " + imported_states[i].getStateImport() + " import " + imported_states[i].getStateClass()
+ " as " + imported_states[i].getStatePackage() + "__" + imported_states[i].getStateClass());
}
}
// put together
code += "from flexbe_core import Behavior, Autonomy, OperatableStateMachine, ConcurrencyContainer, PriorityContainer, Logger\n";
Expand Down Expand Up @@ -302,7 +308,10 @@ IO.CodeGenerator = new (function() {
code += ws+ws+ws+ws+ws+ws+ws+ws+ws+ws+"self.use_behavior(" + s.getStateClass() + ", '" + s.getStatePath().substr(1) + "'" + defkeys_str + "),\n";

} else {
code += ws+ws+ws+ws+ws+ws+ws+ws+ws+ws+ s.getStateClass() + "(";
var class_key = (!UI.Settings.isExplicitStates() && WS.Statelib.isClassUnique(s.getStateClass()))?
s.getStateClass() :
s.getStatePackage() + "__" + s.getStateClass();
code += ws+ws+ws+ws+ws+ws+ws+ws+ws+ws+ class_key + "(";
var param_strings = [];
for (var j=0; j<s.getParameters().length; ++j) {
if (s.getParameters()[j].startsWith("?")) continue;
Expand Down
13 changes: 11 additions & 2 deletions src/io/io_codeparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ IO.CodeParser = new (function() {
// [1] - content of the block
var doc_block_pattern = /'''\n\r?([^']*)\n\r?\s*'''/i;
// Finds all import lines
// [1] - from ..., [3] - import ... (comma separated list)
var import_line_pattern = /^\s*from ((\w|\.)+) import (.+)\s*$/igm;
// [1] - from ..., [3] - import ... (comma separated list), [4] - optional import alias
var import_line_pattern = /^\s*from ((\w|\.)+) import (\w+)(?: as (\w+))?\s*$/igm;
// [1] - date of behavior creation
var behavior_date_pattern = /Created on\s*(.+)/i;
// [1] - author of the behavior
Expand Down Expand Up @@ -180,6 +180,13 @@ IO.CodeParser = new (function() {

var parseTopSection = function(code) {
// parse documentation
var state_type_imports = {};
code.replace(import_line_pattern, function(l, import_path, _, import_class, import_alias) {
if (import_path == "flexbe_core") return l;
var import_package = import_path.split(".")[0];
state_type_imports[import_alias || import_class] = import_package;
});

var comment_result = code.match(doc_block_pattern);
var behavior_date = "";
var behavior_author = "";
Expand All @@ -201,6 +208,7 @@ IO.CodeParser = new (function() {
return {
behavior_date: behavior_date,
behavior_author: behavior_author,
state_type_imports: state_type_imports,
additional_imports: additional_imports
}
}
Expand Down Expand Up @@ -626,6 +634,7 @@ IO.CodeParser = new (function() {
author: top_result.behavior_author,
creation_date: top_result.behavior_date,
behavior_comments: init_result.comments,
state_types: top_result.state_type_imports,

manual_code: {
manual_import: manual_import,
Expand Down
16 changes: 14 additions & 2 deletions src/io/io_modelgenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,21 @@ IO.ModelGenerator = new (function() {
}
s = new BehaviorState(s_def.state_name, state_def, s_def.parameter_values);
} else {
var state_def = WS.Statelib.getFromLib(s_def.state_class);
var state_def = undefined;
if (s_def.state_class.includes("__")) {
var type_split = s_def.state_class.split("__");
var state_key = type_split[0] + "." + type_split[1];
var state_def = WS.Statelib.getFromLib(state_key);
if (state_def == undefined) {
s_def.state_class = type_split[1];
}
}
if (state_def == undefined) {
var state_key = s_def.state_class;
var state_def = WS.Statelib.getClassFromLib(state_key);
}
if (state_def == undefined) {
T.logError("Unable to find state definition for: " + s_def.state_class);
T.logError("Unable to find state definition for: " + state_key);
T.logInfo("Please check your workspace settings.");
continue;
}
Expand Down
42 changes: 22 additions & 20 deletions src/ui/panels/ui_panels_addstate.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ UI.Panels.AddState = new (function() {
return element.toLowerCase().indexOf(filter_exp) > 0;
});

displayStateClasses(begin_list);
displayStateClasses(contain_list);
displayStateTypes(begin_list);
displayStateTypes(contain_list);

if (begin_list.length + contain_list.length == 1) {
var selected_element;
Expand All @@ -98,36 +98,38 @@ UI.Panels.AddState = new (function() {
}
};

var displayStateClasses = function(class_list) {
var displayStateTypes = function(type_list) {
var panel_class_select = document.getElementById('panel_class_select');

class_list.sort();
type_list.sort((el1, el2) => {
return el1.split(".")[1].localeCompare(el2.split(".")[1]);
});

for (var i=0; i<class_list.length; ++i) {
state_def = WS.Statelib.getFromLib(class_list[i]);
for (var i=0; i<type_list.length; ++i) {
state_def = WS.Statelib.getFromLib(type_list[i]);

class_div = document.createElement("div");
class_div.setAttribute("id", "class_select_" + state_def.getStateClass());
class_div.setAttribute("class", "panel_class_select_class");
class_div.setAttribute("value", state_def.getStateClass());
class_div.innerHTML =
state_div = document.createElement("div");
state_div.setAttribute("id", "class_select_" + state_def.getStatePackage() + "_" + state_def.getStateClass());
state_div.setAttribute("class", "panel_class_select_class");
state_div.setAttribute("value", type_list[i]);
state_div.innerHTML =
'<b>' + state_def.getStateClass() + '</b><br>'
+ '<i>' + state_def.getShortDesc() + '</i>';

class_div.addEventListener('click', function() {
state_div.addEventListener('click', function() {
document.getElementById('add_state_class').value = this.getAttribute("value");
});
addHoverDetails(class_div, state_def);
addHoverDetails(state_div, state_def);

panel_class_select.appendChild(class_div);
panel_class_select.appendChild(state_div);
}
};


this.show = function() {
panel_class_select.innerHTML = "";
statelib = WS.Statelib.getClassList();
displayStateClasses(statelib);
statelib = WS.Statelib.getTypeList();
displayStateTypes(statelib);
UI.Panels.setActivePanel(UI.Panels.ADD_STATE_PANEL);
UI.Settings.createStatePackageSelect(document.getElementById("input_package_filter"), true);
}
Expand All @@ -141,14 +143,14 @@ UI.Panels.AddState = new (function() {

this.addStateConfirmClicked = function() {
var state_name = document.getElementById("add_state_name").value;
var state_class = document.getElementById("add_state_class").value;
if (state_name == "" || state_class == "") return;
var state_type = document.getElementById("add_state_class").value;
if (state_name == "" || state_type == "") return;
if (UI.Statemachine.getDisplayedSM().getStateByName(state_name) != undefined) {
T.logWarn("State name already in use!");
return;
}

var state_def = WS.Statelib.getFromLib(state_class);
var state_def = WS.Statelib.getFromLib(state_type);
var new_state = new State(state_name, state_def);
var sm = UI.Statemachine.getDisplayedSM();
sm.addState(new_state);
Expand Down Expand Up @@ -176,7 +178,7 @@ UI.Panels.AddState = new (function() {
},
function() {
var container = (container_path == "")? Behavior.getStatemachine() : Behavior.getStatemachine().getStateByPath(container_path);
var redo_state = new State(state_name, WS.Statelib.getFromLib(state_class));
var redo_state = new State(state_name, WS.Statelib.getFromLib(state_type));
container.addState(redo_state);
UI.Statemachine.refreshView();
}
Expand Down
16 changes: 8 additions & 8 deletions src/ui/panels/ui_panels_stateproperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ UI.Panels.StateProperties = new (function() {
document.getElementById("input_prop_state_name").value = state.getStateName();
document.getElementById("label_prop_state_class").innerText = state.getStateClass();
document.getElementById("label_prop_state_package").innerText = state.getStatePackage();
document.getElementById("label_prop_state_desc").innerText = WS.Statelib.getFromLib(state.getStateClass()).getStateDesc();
document.getElementById("label_prop_state_desc").innerText = WS.Statelib.getFromLib(state.getStateType()).getStateDesc();

var highlight_apply_button = function() {
if (apply_pulse != undefined) return;
Expand Down Expand Up @@ -154,9 +154,9 @@ UI.Panels.StateProperties = new (function() {
tr.appendChild(td_input);
document.getElementById("panel_prop_parameters_content").appendChild(tr);

addHoverDocumentation(tr, "param", params[i], state.getStateClass());
addHoverDocumentation(tr, "param", params[i], state.getStateType());

addAutocomplete(input_field, state.getStateClass());
addAutocomplete(input_field, state.getStateType());

input_field.addEventListener('blur', function() {
this.style.backgroundColor = Checking.isValidExpressionSyntax(this.value, false)? "initial" : "#fca";
Expand Down Expand Up @@ -185,7 +185,7 @@ UI.Panels.StateProperties = new (function() {
+"<option value='-1' " + ((autonomy_list_complete[i] == -1)? "selected='selected'" : "") + " style='color: gray; font-style: italic;'>Inherit</option>"
+"</select></td>";
document.getElementById("panel_prop_autonomy_content").appendChild(tr);
addHoverDocumentation(tr, "outcome", outcome_list_complete[i], state.getStateClass());
addHoverDocumentation(tr, "outcome", outcome_list_complete[i], state.getStateType());
}
} else {
document.getElementById("panel_prop_autonomy").style.display = "none";
Expand Down Expand Up @@ -214,9 +214,9 @@ UI.Panels.StateProperties = new (function() {
tr.appendChild(td_input);
document.getElementById("panel_prop_input_keys_content").appendChild(tr);

addHoverDocumentation(tr, "input", input_keys[i], state.getStateClass());
addHoverDocumentation(tr, "input", input_keys[i], state.getStateType());

addAutocomplete(input_field, state.getStateClass(), "input", state);
addAutocomplete(input_field, state.getStateType(), "input", state);
}
} else {
document.getElementById("panel_prop_input_keys").style.display = "none";
Expand Down Expand Up @@ -246,9 +246,9 @@ UI.Panels.StateProperties = new (function() {
tr.appendChild(td_input);
document.getElementById("panel_prop_output_keys_content").appendChild(tr);

addHoverDocumentation(tr, "output", output_keys[i], state.getStateClass());
addHoverDocumentation(tr, "output", output_keys[i], state.getStateType());

addAutocomplete(input_field, state.getStateClass(), "output", state);
addAutocomplete(input_field, state.getStateType(), "output", state);
}
} else {
document.getElementById("panel_prop_output_keys").style.display = "none";
Expand Down
8 changes: 4 additions & 4 deletions src/ui/ui_runtimecontrol.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,16 @@ UI.RuntimeControl = new (function() {
return;
}

var state_class = state.getStateClass();
var state_type = state.getStateType();
var doc = "";

if (state instanceof Statemachine) {
doc += "<b>Statemachine</b><br />";
} else if (state instanceof BehaviorState) {
doc += "<b>Behavior</b><br />";
} else if (WS.Statelib.getFromLib(state_class) != undefined) {
doc += "<b>" + state_class + "</b><br />";
doc += WS.Statelib.getFromLib(state_class).getStateDesc() + "<br />";
} else if (WS.Statelib.getFromLib(state_type) != undefined) {
doc += "<b>" + state_type + "</b><br />";
doc += WS.Statelib.getFromLib(state_type).getStateDesc() + "<br />";
var pkeys = state.getParameters();
var pvals = state.getParameterValues();
if (pkeys.length > 0) {
Expand Down
14 changes: 14 additions & 0 deletions src/ui/ui_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ UI.Settings = new (function() {

var default_package;
var code_indentation;
var explicit_states;
var editor_command;

var transition_mode;
Expand All @@ -41,6 +42,7 @@ UI.Settings = new (function() {
'collapse_hint': collapse_hint,
'default_package': default_package,
'code_indentation': code_indentation,
'explicit_states': explicit_states,
'editor_command': editor_command,
'transition_mode': transition_mode,
'gridsize': gridsize,
Expand Down Expand Up @@ -68,6 +70,7 @@ UI.Settings = new (function() {
'collapse_hint': false,
'default_package': 'flexbe_behaviors',
'code_indentation': 0,
'explicit_states': false,
'editor_command': 'gedit --new-window $FILE +$LINE',
'transition_mode': 1,
'gridsize': 50,
Expand Down Expand Up @@ -99,6 +102,8 @@ UI.Settings = new (function() {
that.createBehaviorPackageSelect(document.getElementById("select_default_package"));
code_indentation = items.code_indentation;
document.getElementById("select_code_indentation").selectedIndex = items.code_indentation;
explicit_states = items.explicit_states;
document.getElementById("cb_explicit_states").checked = items.explicit_states;
editor_command = items.editor_command;
document.getElementById("input_editor_command").value = items.editor_command;

Expand Down Expand Up @@ -423,6 +428,11 @@ UI.Settings = new (function() {
storeSettings();
}

this.explicitStatesClicked = function(evt) {
explicit_states = evt.target.checked;
storeSettings();
}

this.editorCommandChanged = function() {
var el = document.getElementById('input_editor_command');
editor_command = el.value;
Expand All @@ -438,6 +448,10 @@ UI.Settings = new (function() {
return chars[code_indentation];
}

this.isExplicitStates = function() {
return explicit_states;
}

this.getEditorCommand = function(file_path, line_number) {
if (line_number == undefined) line_number = 0;
return editor_command.replace("$LINE", line_number).replace("$FILE", file_path);
Expand Down
Loading

0 comments on commit e4b90f3

Please sign in to comment.