Author Topic: Image field in wxImagePanel wxSmith tools  (Read 744 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Image field in wxImagePanel wxSmith tools
« on: October 23, 2018, 05:34:54 am »
Hi, does any one know what is the Image field used for? (See image shot below)
It looks like this field does not affect the generated code.

This is the xml in the wxs file.
Code: [Select]
<object class="wxImagePanel" name="ID_IMAGEPANEL3" variable="ImagePanel3" member="yes">
<image>Lenna111.png</image>
<pos>120,8</pos>
</object>

This is the generated code in cpp file
Code: [Select]
    ImagePanel3 = new wxImagePanel(AuiNotebook1, ID_IMAGEPANEL3, wxPoint(120,8), wxDefaultSize, wxRAISED_BORDER|wxTAB_TRAVERSAL, _T("ID_IMAGEPANEL3"));
    ImagePanel3->SetStretch(false);

What I want is that I can set the Image, and the wxSmith should show the image in its GUI preview window.  :)

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #1 on: October 23, 2018, 05:47:53 am »
OK, problem solved.
By looking at the source code:
https://github.com/obfuscated/codeblocks_sf/blob/master/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp

I see that an wxImage is needed, so I simply add an wxImage, and now I can select the wxImage variable name in the "Image" field of the wxImagePanel.  ;)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #2 on: October 23, 2018, 12:01:28 pm »
OK, I just found another issue.
When I use the "wxImage tool" inside wxSmith, I see all the image data(XPM char format in text mode) was saved in the wxs file. This make my wxs file a lot larger if I would like to use a big image.

Is there any way I can directly save the file like the "wxStaticBitmap" does? This control only save the path of the image file.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #3 on: October 23, 2018, 05:09:15 pm »
In the file:
\src\plugins\contrib\wxSmith\wxwidgets\defitems\wxsimage.h

I see it has some code snippet:
Code: [Select]
/*! \brief Class for the wxsImage tool.
 *    \note For reasons unknown, GCC emits a warning that the image is declared but not used when "Use Include File" is set.
 */
class wxsImage : public wxsTool
{
    public:

        wxsImage(wxsItemResData* Data);
        wxBitmap  GetPreview(void);
        void            DoBuild(void);


So, it report the GCC will report a warning. I also see this build warning of the generated code.
But what I see is that the generated code has some issues:

1, I first add a wxImage tool by click the wxImage toolbar button in the wxSmith Tools panel. (see below image)


2, then I add an image by select an png file in the wxImage's property list, also I have select the image from disk (see image below)


3, select the "Image1" in the wxImagePanel control, see image below:


4, then I build the project, I see such warning:

Code: [Select]

-------------- Build: Debug in test-wxImagePanel (compiler: GNU GCC Compiler)---------------

g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DWXUSINGDLL -DwxUSE_UNICODE -Winvalid-pch -include wx_pch.h -DWX_PRECOMP -Wall -g -DTEST -IE:\wxWidgets-3.1.1-rc\include -IE:\wxWidgets-3.1.1-rc\lib\gcc_dll\mswu -c E:\code\test-wxImagePanel\test_wxImagePanelApp.cpp -o obj\Debug\test_wxImagePanelApp.o
In file included from E:\code\test-wxImagePanel\test_wxImagePanelMain.h:14:0,
                 from E:\code\test-wxImagePanel\test_wxImagePanelApp.cpp:14:
E:/code/test-wxImagePanel/wximages/test_wxImagePanelMain_Image1_XPM.xpm:1:20: warning: 'Image1_XPM' defined but not used [-Wunused-variable]
 static const char *Image1_XPM[] = {
                    ^~~~~~~~~~
g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DWXUSINGDLL -DwxUSE_UNICODE -Winvalid-pch -include wx_pch.h -DWX_PRECOMP -Wall -g -DTEST -IE:\wxWidgets-3.1.1-rc\include -IE:\wxWidgets-3.1.1-rc\lib\gcc_dll\mswu -c E:\code\test-wxImagePanel\test_wxImagePanelMain.cpp -o obj\Debug\test_wxImagePanelMain.o
g++.exe -LE:\wxWidgets-3.1.1-rc\lib\gcc_dll -o bin\Debug\test-wxImagePanel.exe  obj\Debug\test_wxImagePanelApp.o obj\Debug\test_wxImagePanelMain.o obj\Debug\wximagepanel.o obj\Debug\resource.res -mthreads  -lwxmsw31u -mwindows
Output file is bin\Debug\test-wxImagePanel.exe with size 1.28 MB
Process terminated with status 0 (0 minute(s), 2 second(s))
0 error(s), 1 warning(s) (0 minute(s), 2 second(s))

I see the variable is used in such generated code:
Code: [Select]
test_wxImagePanelFrame::test_wxImagePanelFrame(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(test_wxImagePanelFrame)
...
    Image1 = new wxImage(Image1_XPM);
    Image1_BMP = new wxBitmap(Image1_XPM);

    // Set the bitmap for ImagePanel1.
    ImagePanel1->SetBitmap(*Image1_BMP);
...
    //*)
}

But as you can see, "Image1_XPM" is used here. But I don't see Image1 is used in some place. Question: does GCC deduced that Image1_XPM is not used?
Code: [Select]
Image1 = new wxImage(Image1_XPM);
If you look at the wxs file, you will see some code snippet:

Code: [Select]
<object class="wxImage" variable="Image1" member="yes">
<image>
<Item>static const char *xpm_data[] = {</Item>
<Item>&quot;225 225 48 1&quot;,</Item>
<Item>&quot;, c #FFD6D6&quot;,</Item>
<Item>&quot;x c #FF2E2E&quot;,</Item>
<Item>&quot;$ c #FF9B9B&quot;,</Item>
<Item>&quot;O c #FFD0D0&quot;,</Item>
<Item>&quot;&amp; c #FF9595&quot;,</Item>
<Item>&quot;9 c #FF5A5A&quot;,</Item>
<Item>&quot;_ c #FFFFFF&quot;,</Item>
<Item>&quot;* c #FF8F8F&quot;,</Item>
<Item>&quot;&lt; c #FF8C8C&quot;,</Item>
<Item>&quot;l c #FFC1C1&quot;,</Item>
<Item>&quot;. c #FFF6F6&quot;,</Item>
<Item>&quot;X c #FFF0F0&quot;,</Item>
......
......
Look, the whole image data was saved in the wxs file(the wxs file has thousands of lines), which make the wxs file hard to read and maintain.
My question is: can we simply save the file path like <image>red-car.png</image> here? From reading the source code(mainly the \src\plugins\contrib\wxSmith\wxwidgets\defitems\wxsimage.h and \src\plugins\contrib\wxSmith\wxwidgets\defitems\wxsimage.cpp, I don't see that "wxImage tool" support such data persistence.





If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Online BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 2064
Re: Image field in wxImagePanel wxSmith tools
« Reply #4 on: October 23, 2018, 10:34:49 pm »
generally: cool, i did not know this worked xD

What does "use include file" mean? Embed the image in the source code? Why is then the image stored in the wxs file? Is a header with the image code generated?
Is the basic idea that wxSmith needs the source image somewhere to restore the generated code if the user messes with it and saves the source image in the wxs-file?

[Edit:]
Quote
But I don't see Image1 is used in some place
Where should
Code: [Select]
Image1 be used? Isn't it only a name for the image tool?
« Last Edit: October 23, 2018, 10:36:23 pm by BlueHazzard »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #5 on: October 24, 2018, 02:16:36 am »
What does "use include file" mean? Embed the image in the source code? Why is then the image stored in the wxs file? Is a header with the image code generated?
When the checkbox "use include file" is on, this means the big data array "static const char *Image1_XPM[]" is defined in a file "./wximages/test_wxImagePanelMain_Image1_XPM.xpm", this xpm file is included by the file "test_wxImagePanelMain.h"
Code: [Select]
//(*Headers(test_wxImagePanelFrame)
#include "./wximages/test_wxImagePanelMain_Image1_XPM.xpm"
#include "wx/wxImagePanel.h"
#include <wx/bitmap.h>
#include <wx/frame.h>
#include <wx/image.h>
#include <wx/menu.h>
#include <wx/statusbr.h>
//*)

If the checkbox "use include file" is off, then the "static const char *Image1_XPM[]" is directly inserted in the "test_wxImagePanelMain.cpp".

Quote
Why is then the image stored in the wxs file? Is a header with the image code generated?
Whether the checkbox "use include file" is on or off, the wxs file always hold the whole XPM data array, which make the wxs file big. See the screen shot image below of the wxs file.

So, the genereated image code in either XPM file or in cpp file are a direct copy of the <image> in the wxs file.



Quote
Is the basic idea that wxSmith needs the source image somewhere to restore the generated code if the user messes with it and saves the source image in the wxs-file?
The "wxImage tool" in wxSmith currently can only store the image code inside wxs. Which from my point is not necessary, why not directly store the path of the original image file. For example, we can store "<image>red-car.png</image>".

If you use the "wxStaticBitmap" control in the wxSmith, you will see it store the image file path.


Quote
[Edit:]
Quote
But I don't see Image1 is used in some place
Where should
Code: [Select]
Image1 be used? Isn't it only a name for the image tool?
Yes, I see that the name "Image1" is only a name. In the source code, I don't see any one use this file. If you look at the generated code in the mainframe's constructor:
Code: [Select]
    Image1 = new wxImage(Image1_XPM);
    Image1_BMP = new wxBitmap(Image1_XPM);

    // Set the bitmap for ImagePanel1.
    ImagePanel1->SetBitmap(*Image1_BMP);
You see, instead of using Image1, we actually use Image1_BMP, which is a wxBitmap type, and for wxImagePanel, we only call the function "SetBitmap(*Image1_BMP)".


I now know why the GCC warning comes:
Because the #include "./wximages/test_wxImagePanelMain_Image1_XPM.xpm" is included in "test_wxImagePanelMain.h". And the later on is included in both test_wxImagePanelMain.cpp and test_wxImagePanelApp.cpp. While the xpm image code is only used in the test_wxImagePanelMain.cpp. So building the test_wxImagePanelApp.cpp, GCC will give warnings that this "static const char *Image1_XPM[]" is not used.


EDIT
I add my project in attachment, you can have a look. The file wximagepanel.cpp/h is added to the project otherwise you have link error.
The wximagepanel.cpp/h files are modified versions of myself, I can't remember their original version(maybe from C::B source  :) )
« Last Edit: October 24, 2018, 02:22:58 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Online BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 2064
Re: Image field in wxImagePanel wxSmith tools
« Reply #6 on: October 24, 2018, 10:56:53 pm »
I see.... I would also vote to use a path instead of the content, but i still wonder why the autor did it in the first place... I is a lot work to embed it, so i think he had some problem he wanted to circumvent...

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #7 on: October 26, 2018, 02:57:55 am »
I see.... I would also vote to use a path instead of the content, but i still wonder why the autor did it in the first place... I is a lot work to embed it, so i think he had some problem he wanted to circumvent...
I don't know who is the original author of this wxImagePanel support in wxSmith.

I just looked at this code:
Code: [Select]
wxObject* wxsStaticBitmap::OnBuildPreview(wxWindow* Parent,long Flags)
{
    // Cryogen 24/3/10 Bug #15354. Since we're no longer using the Background class we don't need to differentiate between cases where
    // the user has assigned a bitmap and those where he hasn't and we're using the fake background. Just return the preview.
    wxStaticBitmap* Preview = new wxStaticBitmap(Parent,GetId(),Bitmap.GetPreview(Size(Parent)),Pos(Parent),Size(Parent),Style());
    return SetupWindow(Preview,Flags);
}
For the wxStaticBitmap, this code create the wxBitmap:
Code: [Select]
wxBitmap wxsBitmapIconData::GetPreview(const wxSize& Size,const wxString& DefaultClient)
{
    if ( Id.empty() )
    {
        if ( FileName.empty() )
        {
            return wxNullBitmap;
        }

        wxImage Img(FileName);
        if ( !Img.Ok() ) return wxNullBitmap;
        if ( Size != wxDefaultSize )
        {
            Img.Rescale(Size.GetWidth(),Size.GetHeight());
        }
        return wxBitmap(Img);
    }

    wxString TempClient = Client.empty() ? DefaultClient : Client;
    return wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(Id),wxART_MAKE_CLIENT_ID_FROM_STR(TempClient),Size);
}
So, it support both the ID and the filename to construct the wxBitmap.

While, for wxImagePanel, it use such code:
Code: [Select]
wxObject* wxsImagePanel::OnBuildPreview(wxWindow* Parent, long Flags) {
wxImagePanel    *ap;
wxsImage        *image;
wxBitmap        bmp;

// make a panel

    ap = new wxImagePanel(Parent, GetId(), Pos(Parent), Size(Parent), Style());
    if (ap == NULL) return NULL;

// get the wxsImage pointer

    image = (wxsImage *) wxsImageListEditorDlg::FindTool(this, mImage);

// and make the preview image

    if (image != NULL) {
        bmp = ((wxsImage *) image)->GetPreview();
        ap->SetBitmap(bmp);
    };

// and stretch it?

    ap->SetStretch(mStretch);

// set all decorations

    SetupWindow(ap, Flags);

// add the children

    AddChildrenPreview(ap, Flags);

// done

    return ap;
}

The "mImage" is the Id name, in my test case, it is "Image1", you can see it just lookup the name in the wxImage tool dict, and if can't find any one, it just failed to create the wxBitmap.

So, my idea is that we can use the "mImage" to support both the Id name in the wxImage tool dict and the file path. So, if lookup failed, I can interpret this string as a file path, so if someone write "aaa.png" in the mImage field, I will try the similar way as function " wxsBitmapIconData::GetPreview" did, and construct the wxBitmap.  ;)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #8 on: October 26, 2018, 03:14:41 am »
The "mImage" is the Id name, in my test case, it is "Image1", you can see it just lookup the name in the wxImage tool dict, and if can't find any one, it just failed to create the wxBitmap.

So, my idea is that we can use the "mImage" to support both the Id name in the wxImage tool dict and the file path. So, if lookup failed, I can interpret this string as a file path, so if someone write "aaa.png" in the mImage field, I will try the similar way as function " wxsBitmapIconData::GetPreview" did, and construct the wxBitmap.  ;)
OK, this works, see the below patch:
Code: [Select]
.../contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp   | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp b/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
index f9b8430f..d52365e1 100644
--- a/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
+++ b/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
@@ -166,6 +166,15 @@ wxBitmap        bmp;
     if (image != NULL) {
         bmp = ((wxsImage *) image)->GetPreview();
         ap->SetBitmap(bmp);
+    }
+    else{ // in case we can't find the name in ImageList, we try to interpret it as a filepath
+          // see discussion http://forums.codeblocks.org/index.php/topic,22888.0.html
+        wxImage Img(mImage);
+        if (Img.Ok())
+        {
+            bmp = wxBitmap(Img);
+            ap->SetBitmap(bmp);
+        }
     };
 
 // and stretch it?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #9 on: October 26, 2018, 05:54:49 am »
The reason I would like this feature is that I want to put some wxTextCtrl on an image, so that I can tweak their values, see below two screen shot images:

First image, under wxsmith designer:


Second image, the test application:
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #10 on: October 27, 2018, 01:16:14 pm »
OK, I have added the code generation part, so now the full patch comes, any comments?
Code: [Select]
.../wximagepanel/wxsimagepanel.cpp                  | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp b/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
index f9b8430f..8d6ec110 100644
--- a/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
+++ b/src/plugins/contrib/wxSmithContribItems/wximagepanel/wxsimagepanel.cpp
@@ -134,7 +134,17 @@ wxString    tt;
         tt.Printf(_T("%s->SetBitmap(*%s);\n"), vname.c_str(), iname.c_str());
 #endif
         AddEventCode(tt);
-    };
+    }
+    else
+    {
+        // if we can't find the image in wxsImage, we fallback to interpret it as a file path
+        // some code need to be like below:
+        // wxBitmap bmp = wxBitmap(wxImage(_T("circuit.png")));
+        // ImagePanel1->SetBitmap(bmp);
+        wxString bmpFilename = vname + "_bmp";
+        Codef(_T("wxBitmap %s = wxBitmap(wxImage((\"%s\")));\n"), bmpFilename.wx_str(), mImage.wx_str());
+        Codef(_T("%ASetBitmap(%s);\n"), bmpFilename.wx_str());
+    }
 
 // do the rest of it
 
@@ -166,6 +176,15 @@ wxBitmap        bmp;
     if (image != NULL) {
         bmp = ((wxsImage *) image)->GetPreview();
         ap->SetBitmap(bmp);
+    }
+    else{ // in case we can't find the name in ImageList, we try to interpret it as a filepath
+          // see discussion http://forums.codeblocks.org/index.php/topic,22888.0.html
+        wxImage Img(mImage);
+        if (Img.Ok())
+        {
+            bmp = wxBitmap(Img);
+            ap->SetBitmap(bmp);
+        }
     };
 
 // and stretch it?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Online BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 2064
Re: Image field in wxImagePanel wxSmith tools
« Reply #11 on: October 27, 2018, 11:18:56 pm »
With your patches: if i put a filename in the "Image" property then this will get used? And the path will also be saved in the xrc resource?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #12 on: October 28, 2018, 08:54:35 am »
With your patches: if i put a filename in the "Image" property then this will get used? And the path will also be saved in the xrc resource?
Without the patch, the "Image" property of the wxImagePanel is only depend on the wxImage tool, so if I put a string in the property, it will look up the string as the image ID in the wxImage tool, and if it can't find one, it just doesn't show the image in the wxImagePanel's preview.

While, with this patch, the above lookup mechinism still exists, but if it failed, we can try to interpret the property's string as a filename, so the "Image" property support both the "Image ID in wxImage tool" and "the filename of the image".

About the wxsmith's wxImage control: my patch doesn't touch this control, so it still store the raw XPM text string in .wxs file.

Hope you understand my explanation.  :)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5109
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Image field in wxImagePanel wxSmith tools
« Reply #13 on: November 04, 2018, 03:22:13 am »
I will commit this changes next week if there is no objections.  :)
Thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11200
    • Travis build status
Re: Image field in wxImagePanel wxSmith tools
« Reply #14 on: November 04, 2018, 03:31:33 am »
I'm not following the topic, but please check that old wxs files still work and produce correct code!
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]