It comes close, yes, but on EyeOS we have more than 20 SearchFields and they
increase as you open more apps. So copy-paste this code will not solve the
problem, that's why I created a widget.
I don't want a composit, I need a widget with the same API and functionality
as the TextField, plus a clickable image (the original idea was to use a IMG
element as button because I just need the click event, nothing else)
configurable by a new property.
Maybe a better example is the Sprite class I talked before, I don't want to
add widgets to the image, I want to change a little bit its behaviour. I
just want a class who has Image API and Image behaviour, but just with two
more properties and overwrite a few methods to use the new properties. So
the most correct way to do it than I can see is OO inheritance.
I know there are so many ways to do the same on programming, I just want to
highlight the way getContentElement is used on TextField and Image.
---
Seldaiendil
2011/10/5 thron7 <[email protected]>
> **
> I think you are mixing OO inheritance with composition. You want to create
> a composit, but still retain the API as if it were a child class (which
> certainly is not what OO inheritance is about).
>
> You might want to look at the implementation of the search field in the
> Demobrowser. In demobrowser.DemoBrowser, you find code starting with
>
> // search
> var searchComposlite = new qx.ui.container.Composite();
> searchComposlite.setLayout(new qx.ui.layout.HBox(3));
> searchComposlite.setAppearance("textfield");
> leftComposite.add(searchComposlite);
>
> var searchIcon = new
> qx.ui.basic.Image("icon/16/actions/edit-find.png");
> searchComposlite.add(searchIcon);
>
> this._searchTextField = new qx.ui.form.TextField();
> this._searchTextField.setLiveUpdate(true);
> this._searchTextField.setAppearance("widget");
> this._searchTextField.setPlaceholder("Filter...");
>
> ...
>
> That comes probably close to what you want to achieve.
>
> T.
>
>
>
> On 10/05/2011 01:15 PM, Seldaiendil D. Flourite wrote:
>
> Hi Tron, thanks for the response,
>
> Yes, I did it this way because I found no other way to do it. But you
> think it's ok to have to wrap (this is create a *getValue* method to call
> the *TextField* *getValue* method) all *TextField* methods? There are so
> many, why I have to create so many dummy methods instead of focus on the
> development I have to do?
>
> Isn't it against *Object Oriented* that I cannot inherit from *TextField*and
> modify it's structure? I found it is again its fur to use
> *getContentElement*() and expect it to be the DOM INPUT, I found it's
> overload the *getContentElement* with two responsabilities: Return the
> content element and return the INPUT element, than in the current code are
> the same element, but someday it can change.
>
> I mean, I don't see right, for example, to add a listener '*change*' to
> the element returned by *getContentElement*() why if someday someones
> changes the content element? why not add the '*change*' listener directly
> where we want to add it, to the INPUT element.
>
> And as I understand, *Object Oriented Programming* is a elegant way to
> reuse code, I don't see here to reuse code nor elegant code.
> *
> *
> Here is how my *SearchField* class looks like:
>
> - My code with spaces: ~*145* lines
> - Fake inheritace from TextField: ~*170* lines
>
> -------------------------------------------------------------
>
>
> qx.Class.define("eyeos.ui.form.SearchField",
> {
> extend : qx.ui.core.Widget,
>
> construct : function(value, icon)
> {
> this.base(arguments);
> this._timer = new qx.event.Timer(0);
> this._timer.addListener('interval', this.__fireExecuteEvent, this);
>
> this._setLayout(new qx.ui.layout.HBox);
>
> // Create childs if they doesn't exist
> this.getChildControl('input');
> this.getChildControl('button');
> },
>
>
> events :
> {
> /**
> * The event is fired when the user press enter key inside the field
> */
> 'execute': "qx.event.type.Data",
>
>
> /**
> * The event is fired on every keystroke modifying the value of the field.
> */
> 'change': "qx.event.type.Data",
>
> /**
> * The event is fired when the user clicks the remove button and clears
> the textfield
> */
> 'clear': "qx.event.type.Data"
> },
>
>
> properties :
> {
> appearance: {
> refine: true,
> init: "searchfield"
> },
> icon: {
> check: "String",
> apply: "_applyIcon",
> nullable: true,
> themeable: true,
> event: "changeIcon"
> },
> showButton: {
> check: "Boolean",
> themeable: true,
> init: true
> },
> delay: {
> check: "Number",
> apply: "_applyDelay",
> nullable: false,
> init: 0
> }
> },
>
>
> members :
> {
> _timer: null,
>
>
> _updateClearButton: function() {
> // If button can be showed and input is empty
> if (this.getShowButton() && !!this.getChildControl('input').getValue()) {
> this.getChildControl('button').show();
> } else {
> this.getChildControl('button').exclude();
> }
> },
> _clearField: function() {
> this.getChildControl('input').setValue("")
> this._updateClearButton();
> this.fireDataEvent('clear');
> this.__fireExecuteEvent();
> },
>
>
> __fireExecuteEvent: function() {
> this._timer.stop();
> var value = this.getChildControl('input').getValue();
> this.fireDataEvent('change', value);
> this.fireDataEvent('execute', value);
> },
>
> __inputKeydown: function(e) {
> if (e.getKeyIdentifier() === 'Enter') {
> this.__fireExecuteEvent();
> }
> },
>
> __inputChange: function(e) {
> this._updateClearButton();
> this.fireDataEvent('change', e.getData(), e.getOldData());
> this.__scheduleDelayedEvent();
> },
>
> __scheduleDelayedEvent: function() {
> if (this.getDelay() === 0)
> return;
> this._timer.restart();
> },
> // properties
> _applyIcon: function(value) {
> this.getChildControl('button').setIcon(value);
> },
> _applyDelay: function(value) {
> this._timer.setInterval(value);
> },
>
> // overridden
> _createChildControlImpl: function(id, hash)
> {
> var control;
>
> switch(id) {
> case "input":
> control = new qx.ui.form.TextField;
> control.addListener('keydown', this.__inputKeydown, this);
> control.addListener('input', this.__inputChange, this);
> this._add(control, { flex: 1 });
> break;
> case "button":
> control = new qx.ui.toolbar.Button;
> control.addListener('execute', this._clearField, this);
> control.exclude();
> this._add(control);
> }
>
> return control || this.base(arguments, id);
> },
>
>
> /**
> * Fake inheritance
> */
> // Implement and include same Interfaces and Mixins as TextField to full
> compatibility
> implement: [ qx.ui.form.IStringForm, qx.ui.form.IForm ],
> include: [ qx.ui.form.MForm ]
> // Propagate TextField events
> __propagateDataEvent: function(event) {
> this.fireDataEvent(event.getName(), event.getData(), event.getOldData());
> },
> __propagateTextFieldEvents: function() {
> var input = this.getChildControl('input');
> input.addListener('changeInvalidMessage', this.__propagateDataEvent,
> this);
> input.addListener('changeReadOnly', this.__propagateDataEvent, this);
> input.addListener('changeRequired', this.__propagateDataEvent, this);
> input.addListener('changeValid', this.__propagateDataEvent, this);
> input.addListener('changeValue', this.__propagateDataEvent, this);
> }
> // TextField wrappers
> clearTextSelection: function() {
> return this.getChildControl('input').clearTextSelection();
> },
> getFilter: function() {
> return this.getChildControl('input').getFilter();
> },
> getFocusElement: function() {
> return this.getChildControl('input').getFocusElement();
> },
> getInvalidMessage: function() {
> return this.getChildControl('input').getInvalidMessage();
> },
> getLiveUpdate: function() {
> return this.getChildControl('input').getLiveUpdate();
> },
> getMaxLength: function() {
> return this.getChildControl('input').getMaxLength();
> },
> getPlaceholder: function() {
> return this.getChildControl('input').getPlaceholder();
> },
> clearTextSelection: function() {
> return this.getChildControl('input').clearTextSelection();
> },
> getReadOnly: function() {
> return this.getChildControl('input').getReadOnly();
> },
> getRequired: function() {
> return this.getChildControl('input').getRequired();
> },
> getRequiredInvalidMessage: function() {
> return this.getChildControl('input').getRequiredInvalidMessage();
> },
> getTextAlign: function() {
> return this.getChildControl('input').getTextAlign();
> },
> getTextSelection: function() {
> return this.getChildControl('input').getTextSelection();
> },
> getTextSelectionEnd: function() {
> return this.getChildControl('input').getTextSelectionEnd();
> },
> getTextSelectionLength: function() {
> return this.getChildControl('input').getTextSelectionLength();
> },
> getTextSelectionStart: function() {
> return this.getChildControl('input').getTextSelectionStart();
> },
> getValid: function() {
> return this.getChildControl('input').getValid();
> },
> getValue: function() {
> return this.getChildControl('input').getValue();
> },
> isLiveUpdate: function() {
> return this.getChildControl('input').isLiveUpdate();
> },
> isReadOnly: function() {
> return this.getChildControl('input').isReadOnly();
> },
> isRequired: function() {
> return this.getChildControl('input').isRequired();
> },
> isValid: function() {
> return this.getChildControl('input').isValid();
> },
> resetFilter: function() {
> return this.getChildControl('input').resetFilter();
> },
> resetInvalidMessage: function() {
> return this.getChildControl('input').resetInvalidMessage();
> },
> resetLiveUpdate: function() {
> return this.getChildControl('input').resetLiveUpdate();
> },
> resetMaxLength: function() {
> return this.getChildControl('input').resetMaxLength();
> },
> resetPlaceholder: function() {
> return this.getChildControl('input').resetPlaceholder();
> },
> resetReadOnly: function() {
> return this.getChildControl('input').resetReadOnly();
> },
> resetRequired: function() {
> return this.getChildControl('input').resetRequired();
> },
> resetRequiredInvalidMessage: function() {
> return this.getChildControl('input').resetRequiredInvalidMessage();
> },
> resetTextAlign: function() {
> return this.getChildControl('input').resetTextAlign();
> },
> resetValid: function() {
> return this.getChildControl('input').resetValid();
> },
> resetValue: function() {
> return this.getChildControl('input').resetValue();
> },
> selectAllText: function() {
> return this.getChildControl('input').selectAllText();
> },
> setFilter: function(value) {
> return this.getChildControl('input').setFilter(value);
> },
> setInvalidMessage: function(value) {
> return this.getChildControl('input').setInvalidMessage(value);
> },
> setLiveUpdate: function(value) {
> return this.getChildControl('input').setLiveUpdate(value);
> },
> setMaxLength: function(value) {
> return this.getChildControl('input').setMaxLength(value);
> },
> setPlaceholder: function(value) {
> return this.getChildControl('input').setPlaceholder(value);
> },
> setReadOnly: function(value) {
> return this.getChildControl('input').setReadOnly(value);
> },
> setRequired: function(value) {
> return this.getChildControl('input').setRequired(value);
> },
> setRequiredInvalidMessage: function(value) {
> return this.getChildControl('input').setRequiredInvalidMessage(value);
> },
> setTextAlign: function(value) {
> return this.getChildControl('input').setTextAlign(value);
> },
> setTextSelection: function(value) {
> return this.getChildControl('input').setTextSelection(value);
> },
> setValid: function(value) {
> return this.getChildControl('input').setValid(value);
> },
> setValue: function(value) {
> return this.getChildControl('input').setValue(value);
> },
> toggleLiveUpdate: function() {
> return this.getChildControl('input').toggleLiveUpdate();
> },
> toggleReadOnly: function() {
> return this.getChildControl('input').toggleReadOnly();
> },
> toggleRequired: function() {
> return this.getChildControl('input').toggleRequired();
> },
> toggleValid: function() {
> return this.getChildControl('input').toggleValid();
> }
> }
> });
>
>
> ------------------------------------------------------------------------------
> All the data continuously generated in your IT infrastructure contains a
> definitive record of customers, application performance, security
> threats, fraudulent activity and more. Splunk takes this data and makes
> sense of it. Business sense. IT sense. Common
> sense.http://p.sf.net/sfu/splunk-d2dcopy1
>
>
> _______________________________________________
> qooxdoo-devel mailing
> [email protected]https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>
>
>
> ------------------------------------------------------------------------------
> All the data continuously generated in your IT infrastructure contains a
> definitive record of customers, application performance, security
> threats, fraudulent activity and more. Splunk takes this data and makes
> sense of it. Business sense. IT sense. Common sense.
> http://p.sf.net/sfu/splunk-d2dcopy1
> _______________________________________________
> qooxdoo-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>
>
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________
qooxdoo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel