org.jbpm.designer.public.js.Plugins.renameShapes.js Maven / Gradle / Ivy
/**
* Copyright (c) 2008
* Willi Tscheschner
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
**/
if (!ORYX.Plugins)
ORYX.Plugins = new Object();
ORYX.Plugins.RenameShapes = Clazz.extend({
facade: undefined,
construct: function(facade){
this.facade = facade;
this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DBLCLICK, this.actOnDBLClick.bind(this));
this.facade.registerOnEvent(ORYX.CONFIG.EVENT_CLICK, this.actOnClick.bind(this));
this.facade.offer({
keyCodes: [{
keyCode: 113, // F2-Key
keyAction: ORYX.CONFIG.KEY_ACTION_DOWN
}
],
functionality: this.renamePerF2.bind(this)
});
//document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.actOnClick.bind(this), true );
},
/**
* This method handles the "F2" key down event. The selected shape are looked
* up and the editing of title/name of it gets started.
*/
renamePerF2 : function renamePerF2() {
var selectedShapes = this.facade.getSelection();
this.actOnDBLClick(undefined, selectedShapes.first());
},
getEditableProperties: function getEditableProperties(shape) {
// Get all properties which where at least one ref to view is set
var props = shape.getStencil().properties().findAll(function(item){
return (item.refToView()
&& item.refToView().length > 0
&& item.directlyEditable());
});
// from these, get all properties where write access are and the type is String or Text
return props.findAll(function(item){ return !item.readonly() && (item.type() == ORYX.CONFIG.TYPE_STRING || item.type() == ORYX.CONFIG.TYPE_TEXT)});
},
getPropertyForLabel: function getPropertyForLabel(properties, shape, label) {
return properties.find(function(item){ return item.refToView().any(function(toView){ return label.id == shape.id + toView })});
},
actOnClick: function actOnClick(evt, shape){
this.hide();
this.destroy();
},
actOnDBLClick: function actOnDBLClick(evt, shape){
if( !(shape instanceof ORYX.Core.Shape) ){ return; }
if((shape instanceof ORYX.Core.Node || shape instanceof ORYX.Core.Edge) && shape.properties["oryx-isselectable"] == "false") {
return;
}
// Saves and Destroys the old input, if there is one
this.hide();
this.destroy();
var props = this.getEditableProperties(shape);
// Get all ref ids
var allRefToViews = props.collect(function(prop){ return prop.refToView() }).flatten().compact();
// Get all labels from the shape with the ref ids
var labels = shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView) }); })
// If there are no referenced labels --> return
if( labels.length == 0 ){ return }
// Define the nearest label
var nearestLabel = labels.length == 1 ? labels[0] : null;
if( !nearestLabel ){
nearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode })
if( !nearestLabel ){
var evtCoord = this.facade.eventCoordinates(evt);
var trans = this.facade.getCanvas().rootNode.lastChild.getScreenCTM();
evtCoord.x *= trans.a;
evtCoord.y *= trans.d;
if (!shape instanceof ORYX.Core.Node) {
var diff = labels.collect(function(label){
var center = this.getCenterPosition( label.node );
var len = Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));
return {diff: len, label: label}
}.bind(this));
diff.sort(function(a, b){ return a.diff > b.diff })
nearestLabel = diff[0].label;
} else {
var diff = labels.collect(function(label){
var center = this.getDifferenceCenterForNode( label.node );
var len = Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2));
return {diff: len, label: label}
}.bind(this));
diff.sort(function(a, b){ return a.diff > b.diff })
nearestLabel = diff[0].label;
}
}
}
// Get the particular property for the label
var prop = this.getPropertyForLabel(props, shape, nearestLabel);
this.showTextField(shape, prop, nearestLabel);
},
showTextField: function showTextField(shape, prop, label) {
// Set all particular config values
var htmlCont = this.facade.getCanvas().getHTMLContainer().id;
// Get the center position from the nearest label
var width;
if(!(shape instanceof ORYX.Core.Node)) {
var bounds = label.node.getBoundingClientRect();
width = Math.max(150, bounds.width);
} else {
width = shape.bounds.width();
}
if (!shape instanceof ORYX.Core.Node) {
var center = this.getCenterPosition( label.node );
center.x -= (width/2);
} else {
var center = shape.absoluteBounds().center();
center.x -= (width/2);
}
var propId = prop.prefix() + "-" + prop.id();
// Set the config values for the TextField/Area
this.comboId = Ext.id();
var config = {
id : this.comboId,
renderTo : htmlCont,
value : shape.properties[propId],
//x : (center.x < 10) ? 10 : center.x,
//y : center.y,
//width : Math.max(100, width),
//style : 'position:absolute',
//allowBlank : prop.optional(),
maxLength : prop.length(),
emptyText : prop.title(),
//cls : 'x_form_text_set_absolute',
listeners : {
specialkey: this._specialKeyPressed.bind(this),
blur : function() {
//this.destroy();
}.bind(this),
change : function(field, newValue, oldValue) {
if(this.shownComboBox) {
var currentEl = shape;
var oldValue = currentEl.properties[propId];
var newValue = this.shownComboBox.getRawValue();
var facade = this.facade;
if (oldValue != newValue) {
// Implement the specific command for property change
var commandClass = ORYX.Core.Command.extend({
construct: function(){
this.el = currentEl;
this.propId = propId;
this.oldValue = oldValue;
this.newValue = newValue;
this.facade = facade;
},
execute: function(){
this.el.setProperty(this.propId, this.newValue);
//this.el.update();
this.facade.setSelection([this.el]);
this.facade.getCanvas().update();
this.facade.updateSelection();
this.facade.raiseEvent({
type: ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,
elements: this.el,
key: this.propId,
value: this.newValue
});
},
rollback: function(){
this.el.setProperty(this.propId, this.oldValue);
//this.el.update();
this.facade.setSelection([this.el]);
this.facade.getCanvas().update();
this.facade.updateSelection();
this.facade.raiseEvent({
type: ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED,
elements: this.el,
key: this.propId,
value: this.oldValue
});
}
})
// Instanciated the class
var command = new commandClass();
// Execute the command
this.facade.executeCommands([command]);
}
}
}.bind(this)
},
// combo-box specific configs
hideTrigger: true,
typeAhead: true,
queryMode: 'local',
minChars: 1,
labelStyle:'display:none',
store: ORYX.Dictionary.Dictionaryitems,
displayField: 'name',
valueField: 'name',
mode: 'local',
triggerAction: 'all',
forceSelection: false,
//toFrontOnShow: true,
caseSensitive: false,
autoSelect:false
};
this.shownComboBox = new Ext.form.ComboBox(config);
this.shownComboBox.setPosition((center.x < 10) ? 10 : center.x, center.y - 16);
this.shownComboBox.setSize(Math.max(100, width), 40);
if (('webkitSpeech' in document.createElement('input'))) {
var attribs = {'x-webkit-speech':'true'};
Ext.get(this.comboId).set(attribs);
}
this.shownComboBox.show();
this.shownComboBox.focus('', 40);
// Diable the keydown in the editor (that when hitting the delete button, the shapes not get deleted)
this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
},
_specialKeyPressed: function _specialKeyPressed(field, e) {
// Enter or Ctrl+Enter pressed
var keyCode = e.getKey();
if (keyCode == 13 && (e.shiftKey || !field.initialConfig.grow)) {
field.fireEvent("change", null, field.getValue());
this.destroy();
//field.fireEvent("blur");
} else if (keyCode == e.ESC) {
this.destroy();
//field.fireEvent("blur");
}
},
getCenterPosition: function(svgNode){
var center = {x: 0, y:0 };
// transformation to the coordinate origin of the canvas
var trans = svgNode.getTransformToElement(this.facade.getCanvas().rootNode.lastChild);
var scale = this.facade.getCanvas().rootNode.lastChild.getScreenCTM();
var transLocal = svgNode.getTransformToElement(svgNode.parentNode);
var bounds = undefined;
center.x = trans.e - transLocal.e;
center.y = trans.f - transLocal.f;
try {
bounds = svgNode.getBBox();
} catch (e) {}
// Firefox often fails to calculate the correct bounding box
// in this case we fall back to the upper left corner of the shape
if (bounds === null || typeof bounds === "undefined" || bounds.width == 0 || bounds.height == 0) {
bounds = {
x: Number(svgNode.getAttribute('x')),
y: Number(svgNode.getAttribute('y')),
width: 0,
height: 0
};
}
center.x += bounds.x;
center.y += bounds.y;
center.x += bounds.width/2;
center.y += bounds.height/2;
center.x *= scale.a;
center.y *= scale.d;
return center;
},
getDifferenceCenterForNode: function getDifferenceCenterForNode(svgNode){
//for shapes that do not have multiple lables on the x-line, only the vertical difference matters
var center = this.getCenterPosition(svgNode);
center.x = 0;
center.y = center.y + 10;
return center;
},
hide: function(e){
if (this.shownComboBox) {
this.shownComboBox.fireEvent("change");
this.shownComboBox.fireEvent("blur");
}
},
destroy: function(e){
if( this.shownComboBox ){
this.shownComboBox.hide();
delete this.shownComboBox;
this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN);
}
}
});
© 2015 - 2025 Weber Informatics LLC | Privacy Policy