This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C1294XL: Graphics Lib (CanvasStruct, CanvasOutlineOn, CanvasTextSet, CanvasImageSet) questions

Part Number: EK-TM4C1294XL

Dear support,

I'm trying to work with these data structures inside the grlib_demo program.

I'm currently changing the function "OnButtonPress", just for testing purposes.

It seems to me that, while "CanvasImageSet" can be called and updated just with "WidgetPaint", the same doesn't happen to CanvasOutlineOn/Off and CanvasTextSet, is that so?

void
OnButtonPress(tWidget *psWidget)
{
    uint32_t ui32Idx;

    //
    // Find the index of this push button.
    //
    for(ui32Idx = 0; ui32Idx < NUM_PUSH_BUTTONS; ui32Idx++)
    {
        if(psWidget == (tWidget *)(g_psPushButtons + ui32Idx))
        {
            break;
        }
    }

    //
    // Return if the push button could not be found.
    //
    if(ui32Idx == NUM_PUSH_BUTTONS)
    {
        return;
    }

    //
    // Toggle the state of this push button indicator.
    //
    g_ui32ButtonState ^= 1 << ui32Idx;

    //
    // Change text from "auto" to "etc"
    //
    CanvasTextSet(g_psPushButtonIndicators + 7, "etc");
    WidgetPaint((tWidget *)(g_psPushButtonIndicators + 7));

    //
    // Set the matching indicator based on the selected state of the check box.
    //
    CanvasImageSet(g_psPushButtonIndicators + ui32Idx,
                   (g_ui32ButtonState & (1 << ui32Idx)) ? g_pui8LightOn :
                   g_pui8LightOff);
    WidgetPaint((tWidget *)(g_psPushButtonIndicators + ui32Idx));

}



The update is realized when I remove the panel using WidgetRemove, and add it once again with WidgetAdd. Am I doing something wrong, or is it supposed to work in that way?

It is clear to me that a possible workaround for this would be creating images and using "CanvasImageSet", but I'd like to know if there's an easier and possibly more efficient way to do it.

Thanks in advance!

Best regards,
Gustavo Wegher

  • Hello Gustavo,

    I am not certain about OutlineOn/Off because I don't see how you are using them but I don't believe you are using CanvasTextSet properly.

    CanvasTextSet(g_psPushButtonIndicators + 7, "etc");

    You are passing in "etc" into the function, but the API is looking for a pointer to the text to draw. So I suspect the information for your TextSet is not being registered properly given you are not providing a pointer at all.

    Try assigning 'etc' to an array and pass the array in that way, and then see if that works with WidgetPaint.

    Here is an example of that from grlib_demo:

        //
        // Set the title of this panel.
        //
        CanvasTextSet(&g_sTitle, g_pcPanei32Names[g_ui32Panel]);
        WidgetPaint((tWidget *)&g_sTitle);

    That said, it's not really clear to me why the WidgetRemove would work instead. Maybe it has to do with how the messages are processed. Usually the idea of WidgetPaint is to queue an update. So perhaps the context of 'etc' is lost in that situation because its not actually a pointer to a memory location, but when using WidgetRemove the 'etc' still remains accessible and therefore shows up. That's my leading theory anyways.

    In any case, let me know if that adjustment works out.

    Lastly, here is the source code in canvas.h of the GrLib which may help you understand how the API works with the pointer and such:

    //*****************************************************************************
    //
    //! Changes the text drawn on a canvas widget.
    //!
    //! \param psWidget is a pointer to the canvas widget to be modified.
    //! \param pcTxt is a pointer to the text to draw onto the canvas.
    //!
    //! This function changes the text that is drawn onto the canvas.  The display
    //! is not updated until the next paint request.
    //!
    //! \return None.
    //
    //*****************************************************************************
    #define CanvasTextSet(psWidget, pcTxt)                                        \
            do                                                                    \
            {                                                                     \
                tCanvasWidget *pW = psWidget;                                     \
                const char *pcT = pcTxt;                                          \
                pW->pcText = pcT;                                                 \
            }                                                                     \
            while(0)

    Best Regards,

    Ralph Jacobi

  • Hey Ralph,

    thanks for the quick answer.

    Yeah, you are right about the pointer. Actually I tested it with and without and got the same result, then I thought it wouldn't be a problem.

    I've corrected the code to work with a pointer, but still got a problem. I'm sending 2 short videos to clarify (3s and 10s).
    In the first case, the char is printed onto the old char (220103_FirstTest).



    Then I thought it could be a problem of initial declaration - g_sTitle is declared with no initial text (maybe because it is a Canvas instead of a CanvasStruct?). 
    I've tried then the following code, initializing the CanvasStruct with "":


    char *g_pcTest[] =
    {
         "test1",
         "test2",
         "test3"
    };
    
    int8_t g_pcTestIdx = 0;


    [...]

    void
    OnButtonPress(tWidget *psWidget)
    {
        uint32_t ui32Idx;
    
        //
        // Find the index of this push button.
        //
        for(ui32Idx = 0; ui32Idx < NUM_PUSH_BUTTONS; ui32Idx++)
        {
            if(psWidget == (tWidget *)(g_psPushButtons + ui32Idx))
            {
                break;
            }
        }
    
        //
        // Return if the push button could not be found.
        //
        if(ui32Idx == NUM_PUSH_BUTTONS)
        {
            return;
        }
    
        //
        // Toggle the state of this push button indicator.
        //
        g_ui32ButtonState ^= 1 << ui32Idx;
    
        //
        // Set the matching indicator based on the selected state of the check box.
        //
        CanvasImageSet(g_psPushButtonIndicators + ui32Idx,
                       (g_ui32ButtonState & (1 << ui32Idx)) ? g_pui8LightOn :
                       g_pui8LightOff);
        WidgetPaint((tWidget *)(g_psPushButtonIndicators + ui32Idx));
    
        //
        // Change the text dynamically
        //
        CanvasTextSet(g_psPushButtonIndicators + 7, g_pcTest[g_pcTestIdx]);
        WidgetPaint((tWidget *)(g_psPushButtonIndicators + 7));
    
        g_pcTestIdx++;
    
        if (g_pcTestIdx > 2) {
            g_pcTestIdx = 0;
        }
    
    }


    In the second video it is also possible to verify that clicking in Previous and Next button (OnPrevious and OnNext functions) makes the text update correctly, and that's why I thought it was related to WidgetRemove and WidgetAdd.

    OutlineOn/Off were behaving in the same way. Maybe I'm missing something? I will also perform more tests tomorrow.

    Best regards,
    Gustavo Wegher

  • Hello Gustavo,

    Can you please upload the video directly to E2E: 

    I am unable to download such content from Google Drive.

    Best Regards,

    Ralph Jacobi

  • Hey Ralph,

    of course. Here it is:

     



    Best regards,
    Gustavo Wegher

  • Hello Gustavo,

    Can you post the Canvas and Widget configuration for review?

    I am looking through our TivaWare examples and I see the usage of the APIs seems to match yours and has the desired behavior so I suspect perhaps the way you have configured either the Canvas or the Widget is causing the issue.

    For example from grlib_demo:

    //*****************************************************************************
    //
    // Handles notifications from the slider controls.
    //
    //*****************************************************************************
    void
    OnSliderChange(tWidget *psWidget, int32_t i32Value)
    {
        static char pcCanvasText[5];
        static char pcSliderText[5];
    
        //
        // Is this the widget whose value we mirror in the canvas widget and the
        // locked slider?
        //
        if(psWidget == (tWidget *)&g_psSliders[SLIDER_CANVAS_VAL_INDEX])
        {
            //
            // Yes - update the canvas to show the slider value.
            //
            usprintf(pcCanvasText, "%3d%%", i32Value);
            CanvasTextSet(&g_sSliderValueCanvas, pcCanvasText);
            WidgetPaint((tWidget *)&g_sSliderValueCanvas);
    
            //
            // Also update the value of the locked slider to reflect this one.
            //
            SliderValueSet(&g_psSliders[SLIDER_LOCKED_INDEX], i32Value);
            WidgetPaint((tWidget *)&g_psSliders[SLIDER_LOCKED_INDEX]);
        }
    
        if(psWidget == (tWidget *)&g_psSliders[SLIDER_TEXT_VAL_INDEX])
        {
            //
            // Yes - update the canvas to show the slider value.
            //
            usprintf(pcSliderText, "%3d%%", i32Value);
            SliderTextSet(&g_psSliders[SLIDER_TEXT_VAL_INDEX], pcSliderText);
            WidgetPaint((tWidget *)&g_psSliders[SLIDER_TEXT_VAL_INDEX]);
        }
    }

    Best Regards,

    Ralph Jacobi

  • Hey Ralph,

    As you pointed out, I decided to compare the sixth and eighth panel (Slider). When I add the style CANVAS_STYLE_TEXT_OPAQUE and set the right Background Color, the application works fine. Nevertheless, the elements of char should have the same size, otherwise some modified characters may appear again. Here's the modifications in the CanvasWidget:

    //*****************************************************************************
    //
    // The sixth panel, which contains a selection of push buttons.
    //
    //*****************************************************************************
    tCanvasWidget g_psPushButtonIndicators[] =
    {
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 1, 0,
                     &g_sKentec320x240x16_SSD2119, 40, 85, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 2, 0,
                     &g_sKentec320x240x16_SSD2119, 90, 85, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 3, 0,
                     &g_sKentec320x240x16_SSD2119, 145, 85, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 4, 0,
                     &g_sKentec320x240x16_SSD2119, 40, 165, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 5, 0,
                     &g_sKentec320x240x16_SSD2119, 90, 165, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 6, 0,
                     &g_sKentec320x240x16_SSD2119, 145, 165, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pui8LightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 7, 0,
                     &g_sKentec320x240x16_SSD2119, 190, 35, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, &g_sFontCm20, "Non-auto",
                     0, 0),
                     
        // ------------------------------------
        // Canvas modified for testing purposes
        //-------------------------------------
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 8, 0,
                     &g_sKentec320x240x16_SSD2119, 190, 55, 110, 24,
                     CANVAS_STYLE_TEXT | CANVAS_STYLE_TEXT_OPAQUE | CANVAS_STYLE_OUTLINE, ClrBlack, ClrWhite, ClrSilver, &g_sFontCm20, "",
                     0, 0),
                     
                     
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 9, 0,
                     &g_sKentec320x240x16_SSD2119, 190, 115, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, &g_sFontCm20, "Auto",
                     0, 0),
        CanvasStruct(g_psPanels + 5, 0, 0,
                     &g_sKentec320x240x16_SSD2119, 190, 135, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, &g_sFontCm20, "repeat",
                     0, 0),
    };


    About the CanvasOutlineOn/Off: The CanvasOutlineOn seems to be updated with the WidgetPaint, but the CanvasOutlineOff was updated only when I changed my panel (similar to the second video sent).

    //*****************************************************************************
    //
    // Handles press notifications for the push button widgets.
    //
    //*****************************************************************************
    void
    OnButtonPress(tWidget *psWidget)
    {
        uint32_t ui32Idx;
    
        //
        // Find the index of this push button.
        //
        for(ui32Idx = 0; ui32Idx < NUM_PUSH_BUTTONS; ui32Idx++)
        {
            if(psWidget == (tWidget *)(g_psPushButtons + ui32Idx))
            {
                break;
            }
        }
    
        //
        // Return if the push button could not be found.
        //
        if(ui32Idx == NUM_PUSH_BUTTONS)
        {
            return;
        }
    
        //
        // Toggle the state of this push button indicator.
        //
        g_ui32ButtonState ^= 1 << ui32Idx;
    
        //
        // Set the matching indicator based on the selected state of the check box.
        //
        CanvasImageSet(g_psPushButtonIndicators + ui32Idx,
                       (g_ui32ButtonState & (1 << ui32Idx)) ? g_pui8LightOn :
                       g_pui8LightOff);
        WidgetPaint((tWidget *)(g_psPushButtonIndicators + ui32Idx));
    
        //
        // Change the text dynamically
        //
        CanvasTextSet(g_psPushButtonIndicators + 7, g_pcTest[g_pcTestIdx]);
    
        //
        // Trigger Outline On and Off
        //
        if (g_pcTestIdx == 1) {
            CanvasOutlineOn(g_psPushButtonIndicators + 7);
        }
        else {
            CanvasOutlineOff(g_psPushButtonIndicators + 7);
        }
    
    
        WidgetPaint((tWidget *)(g_psPushButtonIndicators + 7));
    
        g_pcTestIdx++;
    
        if (g_pcTestIdx > 2) {
            g_pcTestIdx = 0;
        }
    
    }


    A workaround was possible using the CanvasOutlineColorSet, Off being equal to the background color and On to the desired Outline color.

    That said, I think my issues have been resolved. Thanks for all the help provided.

    Best regards,
    Gustavo Wegher