3

I have the following code

qx.Class.define("myproject.EditorArea",
{
  extend : qx.ui.container.Composite,

  events : {
  },

   statics :
   {
   },

  members :
  {
    __htmlArea : null,
    __txtArea : null,

    setWidth : function( value )
    {
      this.__htmlArea.setWidth( value );
      this.__txtArea.setWidth( value );
      return( value );
    },
    setHeight : function( value )
    {
      this.__htmlArea.setHeight( value -19 );
      this.__txtArea.setHeight( value -19 );
      return( value );
    }

},

   /**
    * Constructor
   * @param sHtml {String} the initial html value for this widget.
    */
   construct : function( sHtml )
  {
   this.base(arguments);

    this.setLayout( new qx.ui.layout.VBox(1));

    var container = new qx.ui.container.Composite(new qx.ui.layout.HBox( 1, "right" )).set( {height:18} );
    this.__htmlArea = new qx.ui.embed.Html( sHtml );
    this.add(this.__htmlArea);
    this.__txtArea = new qx.ui.form.TextArea("");
  }
});

When calling the setWidth() from the class EditorArea the framework always calls the super function.

In other words

var editor = new myproject.EditorArea( somehtml );
editor.setWidth( 460 );

calls qx.ui.container.Composite.setWidth() instead of myproject.EditorArea.setWidth().

The overridden function is never reached. How can one override those setter functions?

Raymond
  • 61
  • 4
  • Let me pop like Clippy and say: It seems you are trying to make your own widget. qooxdoo has a recommended and well documented way of doing this and I think you would be better off if you follow that. Since this is not your question I am not going in more details. Here are some links. If you need help ask here. http://manual.qooxdoo.org/5.0.1/pages/desktop/ui_develop.html http://news.qooxdoo.org/tutorial-part-4-2-custom-widgets-4 https://github.com/qooxdoo/qooxdoo/blob/release_5_0_1/framework/source/class/qx/ui/basic/Atom.js#L207 – voger Jun 15 '16 at 14:46
  • Also I think data binding would be more proper for your case. Again since the question is not about data binding I am not going in more detail but here is a link to get you started. Again If you need help ask http://manual.qooxdoo.org/5.0.1/pages/data_binding/single_value_binding.html – voger Jun 15 '16 at 14:49

5 Answers5

4

The getter and setter functions are programatically generated during qx.Class.define(). Typically, you don't want to try to mess with them. If you want your own, you'd be better off creating setMyWidth() and setMyHeight() functions, i.e., functions of some not-automatically-generated name.

If you really, really want the function names to be setWidth/setHeight, you might try creating those functions in the defer section of the class defintion. The defer element of the map passed to qx.Class.define is at the same level as construct, events, statics, members (see the docs), and code in its function is run after the class is fully defined. You may be able to override / completely overwrite the automatically-generated getter and setter by adding your custom function there. You're in uncharted territory here, though, and I don't advise it.

Derrell

Derrell Lipman
  • 526
  • 2
  • 3
3

As Derrell already said, overriding automatic generated setters and getters for qooxdoo properties is possible with tricks but not recommendable.

But there might be a solution for you, by overriding the property applyer _applyDimension for width and height which is defined in qx.ui.core.LayoutItem.

The applyer is called on every property change. Please read the correspondig documentation at http://demo.qooxdoo.org/current/apiviewer/#qx.core.Property

Your override would be as follows:

_applyDimension : function(newValue, oldValue, propertyName) {
  if(propertyName == "width") {
    this.__htmlArea.setWidth( newValue );
    this.__txtArea.setWidth( newValue );
  }
  if(propertyName == "height") {
    this.__htmlArea.setWidth( newValue-19 );
    this.__txtArea.setWidth( newValue-19 );
  }

  this.base(arguments, newValue, oldValue, propertyName);
}

It is essential to call the super class method by calling this.base(arguments,...) here to not break upstream functionality on the inheritance path, or of course, you want to do so explicitly.

This way is safe and documented.

level420
  • 829
  • 5
  • 8
3

The reason that your setHeight and setWidth are not called is because you are never calling them in your example; please take a look at this version of your example and you can see that the setWidth/setHeight in the derived classes is called if you call them (you will need to click the "Log" button to see the debug output that proves this)

qx.Class.define("myproject.EditorArea", {
  extend: qx.ui.container.Composite,

  members: {
    __htmlArea: null,
    __txtArea: null,

    setWidth: function(value) {
      this.debug("in setWidth");
      this.__htmlArea.setWidth(value);
      this.__txtArea.setWidth(value);
      return (value);
    },
    setHeight: function(value) {
      this.debug("in setHeight");
      this.__htmlArea.setHeight(value - 19);
      this.__txtArea.setHeight(value - 19);
      return (value);
    }

  },

  construct: function(sHtml) {
    this.base(arguments);

    this.setLayout(new qx.ui.layout.VBox(1));
    this.__htmlArea = new qx.ui.embed.Html(sHtml);
    this.add(this.__htmlArea);
    this.__txtArea = new qx.ui.form.TextArea("");
  }
});

var test = new myproject.EditorArea();
test.set({ width: 200, height: 300 }); // outputs "in setWidth" and "in setHeight" 
test.set({ width: 250, height: 350 }); // outputs "in setWidth" and "in setHeight"

(However, note while this works in the playground, the debug compiler will prevent you from overriding property accessors - I have opened an issue to discuss this here https://github.com/qooxdoo/qooxdoo/issues/9053)

The bigger picture of what you are trying to achieve is to embed widgets within another widget and control the layout - but the approach you are taking will not work because you are not calling the super class setWidth and setHeight, this means you will prevent the widget from ever having anything other than zero width and height. Regardless of how big your htmlarea and text area are, they will never be visible because their container is zero width/height.

The correct way to change how layout works is to either choose a different Layout (ie qx.ui.layout.* class) or potentially to write your own, although IMHO that is rarely needed given the flexibility of the existing layout classes.

::EDIT:: Although I noted above that the debug compiler does not allow property accessors to be overridden, this has changed as of 22 June 2016. Qooxdoo has been upgraded to support overriding property accessor methods defined in super classes; this is in the master branch, and will be part of Qooxdoo 6.0 stable release

johnspackman
  • 980
  • 4
  • 10
2

This is not qooxdoo way because:

  1. To solve the task you usually use binding + listener + layout manager.
  2. In this case property setter works fast, because layout manager schedules update in its queue, but what if it runs slow? The property is designed to be fast and let a developer easy to read. Setter/getter call must not take to much time.
1

Also, just to add to the discussion, when we set a property sometimes we don't just want to do something else at the same time, as in the case of this question. We might also want to transform the value before we set it, validate it or simply check if it is in the proper format. Alongside _apply qooxdo provides other keys in property deffinitions. For example

properties : {
  myProp : {
        apply : "_applyMyProp",
        transform: "_transformMyProp",
        check: "_checkMyProp",  
        validate: "_validateMyProp"}
},

members :
{
  _applyMyProp : function(value, old, name) {
    // do something with the value 
  },

  _transformMyProp: function(value){
    // transform the value before being checked and validated and set
  },

  _checkMyProp: function(value){
    // check the value when on debug mode
  },

  _validateMyProp: function(value){
   // validate the value before set even when not in debug mode
  },
}

Here are more details http://manual.qooxdoo.org/5.0.1/pages/core/defining_properties.html

voger
  • 666
  • 6
  • 22