cancel
Showing results for 
Search instead for 
Did you mean: 

How to create a custom widget class by combining two(or more) existing widget classes?

AL
Associate II

I tried to create a TextBox widget which derived from Box widget and TextArea widget. Because of its multiple inheritances, I also made minor changes to library files by adding keyword "virtual" to solve ambiguity error("base class"touchgfx::Drawable" is ambiguous). Project compiled but it still didn't work.

I would like to know how to create a custom widget class if it's possible. Thank you.

1 ACCEPTED SOLUTION

Accepted Solutions
Martin KJELDSEN
Chief III

Multiple inheritance of widgets is not the right way to go about creating custom widgets and you definitely should not have to modify core files.

One option, like @Community member​ suggests is to create a Custom Container through the designer interface that has a Box and a textarea on top. That container is reusable through your application.

Another option is to write your own c++ class, inherit from, e.g. Box and then use the draw() method to draw text. If you're interested in this i can show you an example. This class won't be usable through the designer.

A third option is to write templates that you can use to add the same functionality to a number of drawables (This is what we've done with Draggable, ClickListener, FadeAnimator, MoveAnimator that you can find in touchgfx/mixins/. These mixins are applicable through the designer for any drawable.

Let me know what you think

/Martin

View solution in original post

6 REPLIES 6
cameronf
Senior

I don't know why what you're trying to do wouldn't work, though I would be hesitant to change library files, even just to switch to virtual inheritance from Drawable (also don't know if Box and TextArea sharing their Drawable members would break anything, even if it didn't, you're limited to making changes to the Drawable for both of them (rect size, etc)).

It may be easier to make a custom container that just has a Box and a TextArea in it and then you can configure them both separately.

If you provide source code for your widget and detail about what's not working someone might be able to help you with making it work as a custom widget though.

Martin KJELDSEN
Chief III

Multiple inheritance of widgets is not the right way to go about creating custom widgets and you definitely should not have to modify core files.

One option, like @Community member​ suggests is to create a Custom Container through the designer interface that has a Box and a textarea on top. That container is reusable through your application.

Another option is to write your own c++ class, inherit from, e.g. Box and then use the draw() method to draw text. If you're interested in this i can show you an example. This class won't be usable through the designer.

A third option is to write templates that you can use to add the same functionality to a number of drawables (This is what we've done with Draggable, ClickListener, FadeAnimator, MoveAnimator that you can find in touchgfx/mixins/. These mixins are applicable through the designer for any drawable.

Let me know what you think

/Martin

Thank you for answering my question. I think I broke something when I did virtual inheritance. In TextArea.hpp file, I made a small change like this, class TextArea : virtual public Widget. After this change, textarea widget is no longer working, no texts display on screen, and when I called resizeToCurrentText() function, application generated exception thrown error(Access violation executing location 0x006E0069).

Those unexpected behaviors occur when I used virtual inheritance for TextArea widget class. My custom widget code didn't cause these behaviors, because I removed it from project.

I think I should use custom container instead as you suggested.

Thank you for answering my question. I think I will go with first option - using custom container, it's definitely the easiest solution to implement.

When I tried to use virtual inheritance, I did something like this (class TextArea : virtual public Widget ) in TextArea.hpp. After this simple change, textarea widget stopped working, no texts display on screen, and got exception thrown error when resizeToCurrentText() function is called. No sure why these kinda behaviors occur.

And If you don't mind, can you show me the example how to use draw()method to draw text in Second Option. It also sounds interesting to me.

It's a bit late now, but i'll show you an example tomorrow how to create a Button with both a label and a text using the draw() method.

#ifndef __BUTTON_WITH_IMAGE_AND_LABEL__
#define __BUTTON_WITH_IMAGE_AND_LABEL__
 
class ButtonWithImageAndLabel : public ButtonWithLabel
{
public:
    ButtonWithImageAndLabel() :
        offset(0)
    {}
 
    virtual ~ButtonWithImageAndLabel() {}
 
    void setOffset(uint16_t _offset)
    {
        offset = _offset;
    }
 
    virtual void draw(const Rect& area) const
    {
        Button::draw(area);
 
        const Font* fontToDraw = typedText.getFont();
        if ((fontToDraw != 0) && typedText.hasValidId())
        {
            uint8_t height = textHeightIncludingSpacing;
 
            Rect labelRect;
            labelRect = Rect(0, offset, this->getWidth(), height);
            Rect dirty = labelRect & area;
 
            if (!dirty.isEmpty())
            {
                dirty.x -= labelRect.x;
                dirty.y -= labelRect.y;
                translateRectToAbsolute(labelRect);
                LCD::StringVisuals visuals(fontToDraw, pressed ? colorPressed : color, alpha, typedText.getAlignment(), 0, rotation, typedText.getTextDirection(), 0);
                HAL::lcd().drawString(labelRect, dirty, visuals, typedText.getText());
            }
        }
    }
 
private:
    uint16_t offset;
};
 
#endif /* __BUTTON_WITH_IMAGE_AND_LABEL__ */