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.
<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
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. :)
In the file:
\src\plugins\contrib\wxSmith\wxwidgets\defitems\wxsimage.h
I see it has some code snippet:
/*! \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)
(http://i683.photobucket.com/albums/vv194/ollydbg_cb/2018-10-23%2022%2047%2050_zpshfherl3u.png)
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)
(http://i683.photobucket.com/albums/vv194/ollydbg_cb/2018-10-23%2022%2052%2002_zpsqem11tvv.png)
3, select the "Image1" in the wxImagePanel control, see image below:
(http://i683.photobucket.com/albums/vv194/ollydbg_cb/2018-10-23%2022%2053%2034_zpsnlqie83r.png)
4, then I build the project, I see such warning:
-------------- 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:
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?
Image1 = new wxImage(Image1_XPM);
If you look at the wxs file, you will see some code snippet:
<object class="wxImage" variable="Image1" member="yes">
<image>
<Item>static const char *xpm_data[] = {</Item>
<Item>"225 225 48 1",</Item>
<Item>", c #FFD6D6",</Item>
<Item>"x c #FF2E2E",</Item>
<Item>"$ c #FF9B9B",</Item>
<Item>"O c #FFD0D0",</Item>
<Item>"& c #FF9595",</Item>
<Item>"9 c #FF5A5A",</Item>
<Item>"_ c #FFFFFF",</Item>
<Item>"* c #FF8F8F",</Item>
<Item>"< c #FF8C8C",</Item>
<Item>"l c #FFC1C1",</Item>
<Item>". c #FFF6F6",</Item>
<Item>"X c #FFF0F0",</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.
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"
//(*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".
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.
(http://i683.photobucket.com/albums/vv194/ollydbg_cb/2018-10-24%2008%2001%2023_zpsjgad3ztf.png)
So, the genereated image code in either XPM file or in cpp file are a direct copy of the <image> in the wxs file.
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.
[Edit:]
But I don't see Image1 is used in some place
Where should 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:
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 :) )
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:
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:
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:
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. ;)
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:
.../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?
OK, I have added the code generation part, so now the full patch comes, any comments?
.../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?
I'm not following the topic, but please check that old wxs files still work and produce correct code!
Today, I found one issue about my changes in rev11510.
I have a wxImagePanel control in wxSmith which is created by C::B 17.12.
The Image field is "<none>".
When I load this wxs file, the latest C::B will complain that there is not file named "<none>", and a MessageBox will shown.
I think I need to handle this special case for the migration.
EDIT:
+ wxBitmap ImagePanel2_bmp = wxBitmap(wxImage(("")));
+ ImagePanel2->SetBitmap(ImagePanel2_bmp);
+ wxBitmap ImagePanel1_bmp = wxBitmap(wxImage(("<none>")));
+ ImagePanel1->SetBitmap(ImagePanel1_bmp);
So, it should not create the above two code snippet if the Image field is empty or "<none>"