Using Text Templates

From WxWiki
Jump to navigation Jump to search

Example for combining wxHashMap, wxVariant to make text templates, esp. embedding wxImage in wxHTML.

  
#include <wx/variant.h>
#include <wx/hashmap.h>
#include <wx/fs_mem.h>
#include <wx/html/htmlwin.h>

WX_DECLARE_STRING_HASH_MAP( wxVariant , ReplaceMap );

//! Expand the given template with the replaceMap
void ExpandTemplate( wxString& templ , ReplaceMap replaceMap ) 
{
	for( ReplaceMap::iterator it = replaceMap.begin() ; it != replaceMap.end() ; ++it )
	{
		wxString  pattern = it->first;
		wxVariant value   = it->second;

		// every wxVariant has a string representation
		// so no need to distinguish between wxString, long, .., :^)
		templ.Replace( pattern , value.MakeString() , true /* ReplaceAll */); 
	}
}

//! Scale originalSize to targetSize and keep ration
wxSize ScaleSizeKeepRatio( wxSize originalSize , wxSize targetSize )
{
	float scaleX = ((float)targetSize.GetWidth()) / ((float)originalSize.GetWidth());
	float scaleY = ((float)targetSize.GetHeight()) / ((float)originalSize.GetHeight());
	float scale  = wxMin( scaleX , scaleY );

	return wxSize( originalSize.GetWidth() * scale , originalSize.GetHeight() * scale );
}

void MyAppFrame::HtmlTest()
{
	// build the Template, with placeholder-pattern
	// REMARK: could loaded from Text file too.
	wxString htmlTemplate;

	htmlTemplate << wxString(wxT("<html>");
	htmlTemplate << wxString(wxT("<body>"));
	htmlTemplate << wxString(wxT("<h1>@PAGETITLE@</h1>"));
	htmlTemplate << wxString(wxT(" <center>"));
	htmlTemplate << wxString(wxT(" <img width=\"@WIDTH@\" height=\"@HEIGHT@\" src=\"@IMAGE@\" >"));
	htmlTemplate << wxString(wxT(" </center>"));
	htmlTemplate << wxString(wxT(" <h2>Details</h2>"));
	htmlTemplate << wxString(wxT(" @IMAGETITLE@ "));
	htmlTemplate << wxString(wxT("</body></html>"));

	// a image , e.g. generated from your code
	wxImage image(700,700);

	// check for existing logo.png im memoryfilesystem
	wxFileSystem myfs; // contents static member of current Filesystem
	if ( NULL != myfs.OpenFile(wxT("memory:logo.png")) )
		 wxMemoryFSHandler::RemoveFile(wxT("logo.png") );

	// for accessing the (not loaded) image from the wxHTML 
	// we must add this to the MemoryFileSystem
	wxMemoryFSHandler::AddFile(wxT("logo.png"), image , wxBITMAP_TYPE_PNG);

	// max size for the image
	int maxWidth  = 600;
	int maxHeight = 400;

	// calculate the desired imageSize 
	wxSize imageSize = ScaleSizeKeepRatio( wxSize(image.GetWidth(), image.GetHeight()),
					       wxSize(maxWidth , maxHeight) );

	// our replacement table
	// it is a (String) Hashmap of wxVariant, the key is the variablename (@PATTERN@)
	// the value is a wxVariant (a long,wxString,bool ...)
	ReplaceMap replaceMap;

	replaceMap[wxT("@WIDTH@")]      = (long)imageSize.GetWidth();
	replaceMap[wxT("@HEIGHT@")]     = (long)imageSize.GetHeight();
	replaceMap[wxT("@IMAGE@")]      = wxT("memory:logo.png");
	replaceMap[wxT("@IMAGETITLE@")] = wxT("memory:logo.png");
	replaceMap[wxT("@PAGETITLE@")]  = wxT("Image-Test");

	// now expand the template
	ExpandTemplate( htmlTemplate , replaceMap );

	// code taken from the html sample
	// show the expanded template in a HtmlDialog
	wxDialog dlg(this, -1, _("About")));

	wxBoxSizer *topsizer;
	wxHtmlWindow *html;
	topsizer = new wxBoxSizer(wxVERTICAL);

	html = new wxHtmlWindow(&dlg, -1, wxDefaultPosition,
				wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
	html->SetBorders(0);
	html->SetPage(htmlTemplate);
	html->SetSize(html->GetInternalRepresentation()->GetWidth(), 
	html->GetInternalRepresentation()->GetHeight());

	topsizer->Add(html, 1, wxALL, 10);
	topsizer->Add(new wxStaticLine(&dlg, -1), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
	topsizer->Add(new wxButton(&dlg, wxID_OK, _("Ok")), 
				   0, wxALL | wxALIGN_RIGHT, 15);

	dlg.SetAutoLayout(true);
	dlg.SetSizer(topsizer);
	topsizer->Fit(&dlg);
	dlg.Centre();
	dlg.ShowModal();
}

by Sternhaus