XRC: add GetBitmapBundle function
The function creates wxBitmapBundle from <bitmaps> xrc tag. Co-authored-by: VZ <vz-github@zeitlins.org>
This commit is contained in:
@@ -340,8 +340,9 @@ or translations are done.
|
|||||||
|
|
||||||
@subsection overview_xrcformat_type_bitmap Bitmap
|
@subsection overview_xrcformat_type_bitmap Bitmap
|
||||||
|
|
||||||
Bitmap properties contain specification of a single bitmap or icon. In the most
|
Bitmap properties contain specification of a single bitmap, icon, a set of bitmaps
|
||||||
basic form, their text value is simply a relative URL of the bitmap to use.
|
or SVG file. In the most basic form, their text value is simply a relative URL of
|
||||||
|
the bitmap to use.
|
||||||
For example:
|
For example:
|
||||||
@code
|
@code
|
||||||
<object class="tool" name="wxID_NEW">
|
<object class="tool" name="wxID_NEW">
|
||||||
@@ -363,6 +364,31 @@ percent-encoded, e.g. here is the correct way to specify a bitmap with the path
|
|||||||
Bitmap file paths can include environment variables that are expanded if
|
Bitmap file paths can include environment variables that are expanded if
|
||||||
wxXRC_USE_ENVVARS was passed to the wxXmlResource constructor.
|
wxXRC_USE_ENVVARS was passed to the wxXmlResource constructor.
|
||||||
|
|
||||||
|
It is possible to specify the multi-resolution bitmap by a set of bitmaps or
|
||||||
|
an SVG file, which are mutually exclusive. The set of bitmaps should contain
|
||||||
|
one or more relative URLs of a bitmap, separated by @c ';'.
|
||||||
|
For example, to specify two bitmaps, to be used in standard and 200% DPI
|
||||||
|
scaling respectively, you could write:
|
||||||
|
@code
|
||||||
|
<bitmap>new.png;new_2x.png</bitmap>
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Here the first bitmap is special, as its size determines the logical size of
|
||||||
|
the bitmap. In other words, this bitmap is the one used when DPI scaling
|
||||||
|
is not in effect. Any subsequent bitmaps can come in any order and will be used
|
||||||
|
when the DPI scaling factor is equal, or at least close, to the ratio of their
|
||||||
|
size to the size of the first bitmap. Using @c _2x naming convention here is common,
|
||||||
|
but @e not required, the names of the bitmaps can be arbitrary, e.g.
|
||||||
|
@code
|
||||||
|
<bitmap>new_32x32.png;new_64x64.png</bitmap>
|
||||||
|
@endcode
|
||||||
|
would work just as well.
|
||||||
|
When using SVG file you must also specify @c default_size attribute
|
||||||
|
(even if the size is specified in SVG file, it may be different from the size needed here):
|
||||||
|
@code
|
||||||
|
<bitmap default_size="32,32">new.svg</bitmap>
|
||||||
|
@endcode
|
||||||
|
|
||||||
Alternatively, it is possible to specify the bitmap using wxArtProvider IDs.
|
Alternatively, it is possible to specify the bitmap using wxArtProvider IDs.
|
||||||
In this case, the property element has no textual value (filename) and instead
|
In this case, the property element has no textual value (filename) and instead
|
||||||
has the @c stock_id XML attribute that contains stock art ID as accepted by
|
has the @c stock_id XML attribute that contains stock art ID as accepted by
|
||||||
|
|||||||
@@ -583,6 +583,11 @@ public:
|
|||||||
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
wxSize size = wxDefaultSize) wxOVERRIDE;
|
wxSize size = wxDefaultSize) wxOVERRIDE;
|
||||||
|
|
||||||
|
// Gets a bitmap bundle.
|
||||||
|
wxBitmapBundle GetBitmapBundle(const wxString& param = wxT("bitmap"),
|
||||||
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
|
wxSize size = wxDefaultSize) wxOVERRIDE;
|
||||||
|
|
||||||
// Gets an icon.
|
// Gets an icon.
|
||||||
wxIcon GetIcon(const wxString& param = wxT("icon"),
|
wxIcon GetIcon(const wxString& param = wxT("icon"),
|
||||||
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ public:
|
|||||||
virtual wxBitmap GetBitmap(const wxXmlNode* node,
|
virtual wxBitmap GetBitmap(const wxXmlNode* node,
|
||||||
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
wxSize size = wxDefaultSize) = 0;
|
wxSize size = wxDefaultSize) = 0;
|
||||||
|
virtual wxBitmapBundle GetBitmapBundle(const wxString& param = wxT("bitmap"),
|
||||||
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
|
wxSize size = wxDefaultSize) = 0;
|
||||||
virtual wxIcon GetIcon(const wxString& param = wxT("icon"),
|
virtual wxIcon GetIcon(const wxString& param = wxT("icon"),
|
||||||
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
wxSize size = wxDefaultSize) = 0;
|
wxSize size = wxDefaultSize) = 0;
|
||||||
@@ -332,6 +335,12 @@ protected:
|
|||||||
{
|
{
|
||||||
return GetImpl()->GetBitmap(node, defaultArtClient, size);
|
return GetImpl()->GetBitmap(node, defaultArtClient, size);
|
||||||
}
|
}
|
||||||
|
wxBitmapBundle GetBitmapBundle(const wxString& param = wxT("bitmap"),
|
||||||
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
|
wxSize size = wxDefaultSize)
|
||||||
|
{
|
||||||
|
return GetImpl()->GetBitmapBundle(param, defaultArtClient, size);
|
||||||
|
}
|
||||||
wxIcon GetIcon(const wxString& param = wxT("icon"),
|
wxIcon GetIcon(const wxString& param = wxT("icon"),
|
||||||
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
const wxArtClient& defaultArtClient = wxASCII_STR(wxART_OTHER),
|
||||||
wxSize size = wxDefaultSize)
|
wxSize size = wxDefaultSize)
|
||||||
|
|||||||
@@ -467,7 +467,8 @@ t_bitmap = t_url?,
|
|||||||
(
|
(
|
||||||
attribute stock_id { t_identifier},
|
attribute stock_id { t_identifier},
|
||||||
attribute stock_client { t_identifier}?
|
attribute stock_client { t_identifier}?
|
||||||
)?
|
)?,
|
||||||
|
attribute default_size { t_size}?
|
||||||
|
|
||||||
t_font = (
|
t_font = (
|
||||||
[xrc:p="o"] element size {_, t_float }* &
|
[xrc:p="o"] element size {_, t_float }* &
|
||||||
|
|||||||
@@ -1852,6 +1852,52 @@ bool GetStockArtAttrs(const wxXmlNode *paramNode,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load a bitmap from a file system element.
|
||||||
|
wxBitmap LoadBitmapFromFS(wxXmlResourceHandlerImpl* impl,
|
||||||
|
const wxString& path,
|
||||||
|
wxSize size,
|
||||||
|
const wxString& nodeName)
|
||||||
|
{
|
||||||
|
if (path.empty()) return wxNullBitmap;
|
||||||
|
#if wxUSE_FILESYSTEM
|
||||||
|
wxFSFile *fsfile = impl->GetCurFileSystem().OpenFile(path, wxFS_READ | wxFS_SEEKABLE);
|
||||||
|
if (fsfile == NULL)
|
||||||
|
{
|
||||||
|
impl->ReportParamError
|
||||||
|
(
|
||||||
|
nodeName,
|
||||||
|
wxString::Format("cannot open bitmap resource \"%s\"", path)
|
||||||
|
);
|
||||||
|
return wxNullBitmap;
|
||||||
|
}
|
||||||
|
wxImage img(*(fsfile->GetStream()));
|
||||||
|
delete fsfile;
|
||||||
|
#else
|
||||||
|
wxImage img(name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!img.IsOk())
|
||||||
|
{
|
||||||
|
impl->ReportParamError
|
||||||
|
(
|
||||||
|
nodeName,
|
||||||
|
wxString::Format("cannot create bitmap from \"%s\"", path)
|
||||||
|
);
|
||||||
|
return wxNullBitmap;
|
||||||
|
}
|
||||||
|
if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y);
|
||||||
|
return wxBitmap(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
// forward declaration
|
||||||
|
template <typename T>
|
||||||
|
T
|
||||||
|
ParseStringInPixels(wxXmlResourceHandlerImpl* impl,
|
||||||
|
const wxString& param,
|
||||||
|
const wxString& str,
|
||||||
|
const T& defaultValue,
|
||||||
|
wxWindow *windowToUse = NULL);
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
wxBitmap wxXmlResourceHandlerImpl::GetBitmap(const wxString& param,
|
wxBitmap wxXmlResourceHandlerImpl::GetBitmap(const wxString& param,
|
||||||
@@ -1892,36 +1938,126 @@ wxBitmap wxXmlResourceHandlerImpl::GetBitmap(const wxXmlNode* node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ...or load the bitmap from file: */
|
/* ...or load the bitmap from file: */
|
||||||
wxString name = GetFilePath(node);
|
return LoadBitmapFromFS(this, GetFilePath(node), size, node->GetName());
|
||||||
if (name.empty()) return wxNullBitmap;
|
}
|
||||||
#if wxUSE_FILESYSTEM
|
|
||||||
wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
|
|
||||||
if (fsfile == NULL)
|
|
||||||
{
|
|
||||||
ReportParamError
|
|
||||||
(
|
|
||||||
node->GetName(),
|
|
||||||
wxString::Format("cannot open bitmap resource \"%s\"", name)
|
|
||||||
);
|
|
||||||
return wxNullBitmap;
|
|
||||||
}
|
|
||||||
wxImage img(*(fsfile->GetStream()));
|
|
||||||
delete fsfile;
|
|
||||||
#else
|
|
||||||
wxImage img(name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!img.IsOk())
|
|
||||||
|
wxBitmapBundle wxXmlResourceHandlerImpl::GetBitmapBundle(const wxString& param,
|
||||||
|
const wxArtClient& defaultArtClient,
|
||||||
|
wxSize size)
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !param.empty(), "bitmap parameter name can't be empty" );
|
||||||
|
|
||||||
|
const wxXmlNode* const node = GetParamNode(param);
|
||||||
|
|
||||||
|
if ( !node )
|
||||||
{
|
{
|
||||||
ReportParamError
|
// this is not an error as bitmap parameter could be optional
|
||||||
(
|
|
||||||
node->GetName(),
|
|
||||||
wxString::Format("cannot create bitmap from \"%s\"", name)
|
|
||||||
);
|
|
||||||
return wxNullBitmap;
|
return wxNullBitmap;
|
||||||
}
|
}
|
||||||
if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y);
|
|
||||||
return wxBitmap(img);
|
/* If the bitmap is specified as stock item, query wxArtProvider for it: */
|
||||||
|
wxString art_id, art_client;
|
||||||
|
if ( GetStockArtAttrs(node, defaultArtClient,
|
||||||
|
art_id, art_client) )
|
||||||
|
{
|
||||||
|
wxBitmapBundle stockArt(wxArtProvider::GetBitmapBundle(art_id, art_client, size));
|
||||||
|
if ( stockArt.IsOk() )
|
||||||
|
return stockArt;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxBitmapBundle bitmapBundle;
|
||||||
|
wxString paramValue = GetParamValue(node);
|
||||||
|
if ( paramValue.EndsWith(".svg") )
|
||||||
|
{
|
||||||
|
if ( paramValue.Contains(";") )
|
||||||
|
{
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
param,
|
||||||
|
"may contain either one SVG file or a list of files separated by ';'"
|
||||||
|
);
|
||||||
|
return bitmapBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it is a bundle from svg file
|
||||||
|
wxString svgDefaultSizeAttr = node->GetAttribute("default_size", "");
|
||||||
|
if ( svgDefaultSizeAttr.empty() )
|
||||||
|
{
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
param,
|
||||||
|
"'default_size' attribute required with svg file"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef wxHAS_SVG
|
||||||
|
wxSize svgDefaultSize = ParseStringInPixels(this, param, svgDefaultSizeAttr, wxDefaultSize);
|
||||||
|
#if wxUSE_FILESYSTEM
|
||||||
|
wxFSFile* fsfile = GetCurFileSystem().OpenFile(paramValue, wxFS_READ | wxFS_SEEKABLE);
|
||||||
|
if (fsfile == NULL)
|
||||||
|
{
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
param,
|
||||||
|
wxString::Format("cannot open SVG resource \"%s\"", paramValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxInputStream* s = fsfile->GetStream();
|
||||||
|
const size_t len = static_cast<size_t>(s->GetLength());
|
||||||
|
wxCharBuffer buf(len);
|
||||||
|
char* const ptr = buf.data();
|
||||||
|
|
||||||
|
if (s->ReadAll(ptr, len))
|
||||||
|
{
|
||||||
|
bitmapBundle = wxBitmapBundle::FromSVG(ptr, svgDefaultSize);
|
||||||
|
}
|
||||||
|
delete fsfile;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bitmapBundle = wxBitmapBundle::FromSVGFile(paramValue, svgDefaultSize);
|
||||||
|
#endif
|
||||||
|
#else // !wxHAS_SVG
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
param,
|
||||||
|
"SVG bitmaps are not supported in this build of the library"
|
||||||
|
);
|
||||||
|
#endif // wxHAS_SVG/!wxHAS_SVG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( paramValue.Contains(".svg;") )
|
||||||
|
{
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
param,
|
||||||
|
"may contain either one SVG file or a list of files separated by ';'"
|
||||||
|
);
|
||||||
|
return bitmapBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it is a bundle from bitmaps
|
||||||
|
wxVector<wxBitmap> bitmaps;
|
||||||
|
wxArrayString paths = wxSplit(paramValue, ';', '\0');
|
||||||
|
for ( wxArrayString::const_iterator i = paths.begin(); i != paths.end(); ++i )
|
||||||
|
{
|
||||||
|
wxBitmap bmpNext = LoadBitmapFromFS(this, *i, size, param);
|
||||||
|
if ( !bmpNext.IsOk() )
|
||||||
|
{
|
||||||
|
// error in loading wxBitmap, return invalid wxBitmapBundle
|
||||||
|
return bitmapBundle;
|
||||||
|
}
|
||||||
|
bitmaps.push_back(bmpNext);
|
||||||
|
}
|
||||||
|
bitmapBundle = wxBitmapBundle::FromBitmaps(bitmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmapBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2182,17 +2318,17 @@ void XRCConvertFromDLU(wxWindow* w, T& value)
|
|||||||
value = w->ConvertDialogToPixels(value);
|
value = w->ConvertDialogToPixels(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for parsing values (of type T, for which XRCConvertFromAbsValue() and
|
// Helper for parsing strings which contain values (of type T, for which
|
||||||
// XRCConvertFromDLU() functions must be defined) which can be expressed either
|
// XRCConvertFromAbsValue() and XRCConvertFromDLU() functions must be defined)
|
||||||
// in pixels or dialog units.
|
// which can be expressed either in pixels or dialog units.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T
|
T
|
||||||
ParseValueInPixels(wxXmlResourceHandlerImpl* impl,
|
ParseStringInPixels(wxXmlResourceHandlerImpl* impl,
|
||||||
const wxString& param,
|
const wxString& param,
|
||||||
|
const wxString& s,
|
||||||
const T& defaultValue,
|
const T& defaultValue,
|
||||||
wxWindow *windowToUse = NULL)
|
wxWindow *windowToUse)
|
||||||
{
|
{
|
||||||
const wxString s = impl->GetParamValue(param);
|
|
||||||
if ( s.empty() )
|
if ( s.empty() )
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
|
||||||
@@ -2235,6 +2371,17 @@ ParseValueInPixels(wxXmlResourceHandlerImpl* impl,
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper for parsing values which uses ParseStringInPixels() above.
|
||||||
|
template <typename T>
|
||||||
|
T
|
||||||
|
ParseValueInPixels(wxXmlResourceHandlerImpl* impl,
|
||||||
|
const wxString& param,
|
||||||
|
const T& defaultValue,
|
||||||
|
wxWindow *windowToUse = NULL)
|
||||||
|
{
|
||||||
|
return ParseStringInPixels(impl, param, impl->GetParamValue(param), defaultValue, windowToUse);
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
wxSize wxXmlResourceHandlerImpl::GetSize(const wxString& param,
|
wxSize wxXmlResourceHandlerImpl::GetSize(const wxString& param,
|
||||||
|
|||||||
Reference in New Issue
Block a user