// For compilers that support precompilation
#include "wx/wxprec.h"
+#include "wx/utils.h"
+#include "wx/process.h"
+#include "wx/spawnbrowser.h"
+#include "wx/html/forcelnk.h"
+
+// crt
+#ifdef __WXMSW__
+#include <process.h> // spawnl()
+#endif
// Include private headers
#include "wx/applet/applet.h"
+#include "wx/applet/window.h"
+#include "wx/applet/loadpage.h"
+#include "wx/applet/plugin.h"
+
+// Preprocessor Stuff
+#include "wx/applet/prepinclude.h"
+#include "wx/applet/prepecho.h"
+#include "wx/applet/prepifelse.h"
+
+/*---------------------------- Global variables ---------------------------*/
+wxHashTable wxHtmlAppletWindow::m_Cookies;
+
/*------------------------- Implementation --------------------------------*/
// Empty event handler. We include this event handler simply so that
// sub-classes of wxApplet can reference wxApplet in the event tables
// that they create as necessary.
BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow)
+ EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage)
+ EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded)
END_EVENT_TABLE()
// Implement the class functions for wxHtmlAppletWindow
wxHtmlAppletWindow::wxHtmlAppletWindow(
wxWindow *parent,
wxWindowID id,
+ wxToolBarBase *navBar,
+ int navBackId,
+ int navForwardId,
const wxPoint& pos,
const wxSize& size,
long style,
- const wxString& name)
+ const wxString& name,
+ const wxString& docroot )
: wxHtmlWindow(parent,id,pos,size,style,name)
{
- // Ensure all cookie data is destroyed when window is killed
- m_Cookies.DeleteContents(true);
+ // Init our locks
+ UnLock();
+
+ // setup client navbars
+ if (navBar) {
+ m_NavBar = navBar;
+ m_NavBackId = navBackId;
+ m_NavForwardId = navForwardId;
+ }
+ else {
+ m_NavBar = NULL;
+ }
+
+ // Set up docroot
+ m_DocRoot = docroot;
+
+ // Set the key_type for applets
+ m_AppletList = wxAppletList(wxKEY_STRING);
+
+ // Add HTML preprocessors
+ // deleting preprocessors is done by the code within the window
+
+ incPreprocessor = new wxIncludePrep(); // #include preprocessor
+ incPreprocessor->ChangeDirectory(m_DocRoot);
+
+ wxEchoPrep * echoPreprocessor = new wxEchoPrep(); // #echo preprocessor
+ wxIfElsePrep * ifPreprocessor = new wxIfElsePrep();
+
+ this->AddProcessor(incPreprocessor);
+ this->AddProcessor(echoPreprocessor);
+ this->AddProcessor(ifPreprocessor);
}
/****************************************************************************
HTML page.
****************************************************************************/
wxApplet *wxHtmlAppletWindow::CreateApplet(
- const wxString& className,
+ const wxString& classId,
+ const wxString& iName,
+ const wxHtmlTag& params,
const wxSize& size)
{
- // We presently only allow one applet per page of the same class!
- if (m_AppletList.Find(className))
- return NULL;
-
// Dynamically create the class instance at runtime
- wxClassInfo *info = wxClassInfo::FindClass(className.c_str());
+ wxClassInfo *info = wxClassInfo::FindClass(classId.c_str());
if (!info)
return NULL;
wxObject *obj = info->CreateObject();
wxApplet *applet = wxDynamicCast(obj,wxApplet);
if (!applet)
return NULL;
- if (!applet->Create(this,size)) {
+ if (!applet->Create(this,params,size)) {
delete applet;
return NULL;
}
- m_AppletList.Append(className,applet);
+ else {
+ // do some fixups on the size if its screwed up
+ wxSize nsize = applet->GetBestSize();
+ if (nsize.x < size.x) nsize.x = size.x;
+ if (nsize.y < size.y) nsize.y = size.y;
+ applet->SetSize(nsize);
+ }
+
+ m_AppletList.Append(iName,(wxObject*)applet);
return applet;
}
+/****************************************************************************
+PARAMETERS:
+classId - Name of the Plugin class to create an object for
+
+RETURNS:
+Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
+
+REMARKS:
+This function is used to create new wxPlugIn objects dynamically based on the
+class name as a string. This allows instances of wxPlugIn classes to be
+created dynamically based on string values embedded in the custom tags of an
+HTML page.
+****************************************************************************/
+bool wxHtmlAppletWindow::CreatePlugIn(
+ const wxString& classId )
+{
+ // Dynamically create the class instance at runtime
+ wxClassInfo *info = wxClassInfo::FindClass(classId.c_str());
+ if (!info)
+ return false;
+ wxObject *obj = info->CreateObject();
+ if (!obj)
+ return false;
+ wxPlugIn *plugIn = wxDynamicCast(obj,wxPlugIn);
+ if (!plugIn)
+ return false;
+ if (!plugIn->Create(this)) {
+ delete plugIn;
+ return false;
+ }
+ return true;
+}
+
/****************************************************************************
PARAMETERS:
appletName - Name of the applet class to find
if (!node)
return NULL;
return node->GetData();
-}
+}
/****************************************************************************
PARAMETERS:
}
}
return false;
-}
+}
/****************************************************************************
PARAMETERS:
REMARKS:
Remove an applet from the manager. Called during applet destruction
****************************************************************************/
+#include "scitech"
bool wxHtmlAppletWindow::LoadPage(
- const wxString& hRef)
+ const wxString& link)
{
+ wxString href(link);
+
+ // TODO: technically we allow no relative paths
+
+ // Check to see if it is a real url, if not it is a file
+ if (link.Mid(0, 5).CmpNoCase("http:") != 0) {
+
+ // Check for abs path. If it is not then tack on the path
+ // supplied at creation.
+ // TODO: Abs paths are only used in testing (remove this)
+ if (link.GetChar(1) != ':')
+ href = m_DocRoot + href;
+ }
+
+ if (link.GetChar(0) == '?'){
+ wxString cmd = link.BeforeFirst('=');
+ wxString cmdValue = link.AfterFirst('=');
+
+ // Launches the default Internet browser for the system.
+ if(!(cmd.CmpNoCase("?EXTERNAL"))){
+ return wxSpawnBrowser(this, cmdValue.c_str());
+ }
+
+ // Launches an external program on the system.
+ if (!(cmd.CmpNoCase("?EXECUTE"))){
+ int code = spawnl( P_NOWAIT, cmdValue , NULL );
+ return (!code);
+ }
+
+ // Looks for a href in a variable stored as a cookie. The href can be
+ // changed on the fly.
+ if (!(cmd.CmpNoCase("?VIRTUAL"))){
+ VirtualData& temp = *((VirtualData*)FindCookie(cmdValue));
+ if (&temp) {
+ href = temp.GetHref();
+ }
+ else {
+#ifdef CHECKED
+ wxLogError(_T("VIRTUAL LINK ERROR: '%s' does not exist."), cmdValue.c_str());
+#endif
+ return true;
+ }
+ }
+
+ // This launches a qlet - It is like an applet but is more generic in that it
+ // can be of any wxWin type so it then has the freedom to do more stuff.
+ if (!(cmd.CmpNoCase("?WXAPPLET"))){
+ if (!cmdValue.IsNull()){
+ if (!CreatePlugIn(cmdValue)){
+#ifdef CHECKED
+ wxLogError(_T("Launch Applet ERROR: '%s' does not exist."), cmdValue.c_str());
+#endif
+ }
+ }
+ return true;
+ }
+ }
+
+ // Inform all the applets that the new page is being loaded
for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
- (node->GetData())->OnLinkClicked(hRef);
- return wxHtmlWindow::LoadPage(hRef);
+ (node->GetData())->OnLinkClicked(wxHtmlLinkInfo(href));
+ Show(false);
+ bool stat = wxHtmlWindow::LoadPage(href);
+ Show(true);
+
+ // Enable/Dis the navbar tools
+ if (m_NavBar) {
+ m_NavBar->EnableTool(m_NavForwardId,HistoryCanForward());
+ m_NavBar->EnableTool(m_NavBackId,HistoryCanBack());
+ }
+ return stat;
}
/****************************************************************************
void wxHtmlAppletWindow::OnLinkClicked(
const wxHtmlLinkInfo& link)
{
- for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
- (node->GetData())->OnLinkClicked(link);
- wxHtmlWindow::LoadPage(link.GetHref());
+ LoadPage(link.GetHref());
}
/****************************************************************************
****************************************************************************/
bool wxHtmlAppletWindow::HistoryForward()
{
- if (!HistoryCanForward())
+ if (!HistoryCanForward())
return false;
+
for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
(node->GetData())->OnHistoryForward();
+
return wxHtmlWindow::HistoryForward();
}
****************************************************************************/
bool wxHtmlAppletWindow::HistoryBack()
{
- if (!HistoryCanBack())
+ if (!HistoryCanBack())
return false;
+
for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
(node->GetData())->OnHistoryBack();
+
return wxHtmlWindow::HistoryBack();
}
****************************************************************************/
void wxHtmlAppletWindow::SendMessage(
wxEvent& msg)
-{
+{
// Preset the skip flag
msg.Skip();
-
+
// Process all applets in turn and send them the message
for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
(node->GetData())->OnMessage(msg);
- if (!msg.GetSkipped())
+ if (!msg.GetSkipped()){
+ wxMessageBox("BREAK");
break;
+ }
}
}
/****************************************************************************
PARAMETERS:
-msg - wxEvent message to be sent to all wxApplets
+name - Uniq wxString used as hash key
+cookie - wxObject data returned when name is found.
RETURNS:
True if new cookie was added, false if cookie with same name already exists.
// Fail if the named cookie already exists!
if (m_Cookies.Get(name))
return false;
- m_Cookies.Put(name,cookie);
+ m_Cookies.Put(name,cookie);
return true;
}
/****************************************************************************
PARAMETERS:
-msg - wxEvent message to be sent to all wxApplets
+name - wxString uniq haskey used to remove item from hash
RETURNS:
True if found and deleted, false if not found in table.
return m_Cookies.Get(name);
}
+/****************************************************************************
+PARAMETERS:
+event - Event to handle
+
+REMARKS:
+This function handles delayed LoadPage events posted from applets that
+need to change the page for the current window to a new window.
+****************************************************************************/
+void wxHtmlAppletWindow::OnLoadPage(
+ wxLoadPageEvent &event)
+{
+ // Test the mutex lock.
+ if (!(IsLocked())){
+ Lock();
+ if (event.GetHtmlWindow() == this){
+ if (LoadPage(event.GetHRef())){
+ // wxPageLoadedEvent evt;
+ // NOTE: This is reserved for later use as we might need to send
+ // page loaded events to applets.
+ }
+ }
+ UnLock();
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+event - Event to handle
+
+REMARKS:
+This function handles delayed LoadPage events posted from applets that
+need to change the page for the current window to a new window.
+****************************************************************************/
+void wxHtmlAppletWindow::OnPageLoaded(
+ wxPageLoadedEvent &)
+{
+ Enable(true);
+}
+
+/****************************************************************************
+PARAMETERS:
+none
+
+REMARKS:
+This function tries to lock the mutex. If it can't, returns
+immediately with false.
+***************************************************************************/
+bool wxHtmlAppletWindow::TryLock()
+{
+ if (!m_mutexLock) {
+ m_mutexLock = true;
+ return true;
+ }
+ return false;
+}
+
+/****************************************************************************
+PARAMETERS:
+name - name of the last applet that changed the data in this object
+group - name of the group the allplet belongs to.
+href - webpage to go to.
+
+REMARKS:
+VirtualData is used to store information on the virtual links.
+****************************************************************************/
+VirtualData::VirtualData(
+ wxString& name,
+ wxString& group,
+ wxString& href )
+{
+ m_name = name;
+ m_group = group;
+ m_href = href;
+}
+
+/****************************************************************************
+PARAMETERS:
+REMARKS:
+****************************************************************************/
+void AppletProcess::OnTerminate(
+ int,
+ int )
+{
+ // we're not needed any more
+ delete this;
+}
+
#include "wx/html/m_templ.h"
/****************************************************************************
of automatically constructing the wxApplet objects of the appropriate
class based on the <embed> tag information.
****************************************************************************/
-TAG_HANDLER_BEGIN(Embed, "EMBED")
+TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET")
TAG_HANDLER_PROC(tag)
{
- wxWindow *wnd;
- wxHtmlAppletWindow *appletWindow;
- wxApplet *applet;
- int width, height;
- int floatPercent = 0;
-
- wnd = m_WParser->GetWindow();
- if ((appletWindow = wxDynamicCast(wnd,wxHtmlAppletWindow)) != NULL) {
- tag.ScanParam("WIDTH", "%i", &width);
- tag.ScanParam("HEIGHT", "%i", &height);
- if (tag.HasParam("FLOAT"))
- tag.ScanParam("FLOAT", "%i", &floatPercent);
- if (tag.HasParam("APPLET")) {
- if ((applet = appletWindow->CreateApplet(tag.GetParam("APPLET"), wxSize(width, height))) != NULL) {
- applet->Show(true);
- m_WParser->OpenContainer()->InsertCell(new wxHtmlWidgetCell(applet,floatPercent));
- }
+ wxWindow *wnd;
+ wxHtmlAppletWindow *appletWindow;
+ wxApplet *applet;
+ wxString classId;
+ wxString name;
+ int width, height;
+
+ wnd = m_WParser->GetWindow();
+
+ if ((appletWindow = wxDynamicCast(wnd,wxHtmlAppletWindow)) != NULL){
+ wxSize size = wxDefaultSize;
+ int al;
+ if (tag.HasParam("WIDTH")) {
+ tag.GetParamAsInt("WIDTH", &width);
+ size.SetWidth(width);
+ }
+
+ if (tag.HasParam("HEIGHT")) {
+ tag.GetParamAsInt("HEIGHT", &height);
+ size.SetHeight(height);
+ }
+
+ al = wxHTML_ALIGN_BOTTOM;
+ if (tag.HasParam(wxT("ALIGN"))) {
+ wxString alstr = tag.GetParam(wxT("ALIGN"));
+ alstr.MakeUpper(); // for the case alignment was in ".."
+ if (alstr == wxT("TEXTTOP") || alstr == wxT("TOP"))
+ al = wxHTML_ALIGN_TOP;
+ else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
+ al = wxHTML_ALIGN_CENTER;
}
- else if (tag.HasParam("TEXT")) {
- // TODO: Somehow get the text returned from this class displayed on the page!
+
+ if (tag.HasParam("CLASSID")){
+ classId = tag.GetParam("CLASSID");
+ if ( classId.IsNull() || classId.Len() == 0 ){
+ wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR);
+ return false;
+ }
+ if (tag.HasParam("NAME"))
+ name = tag.GetParam("NAME");
+
+ // If the name is NULL or len is zero then we assume that the html guy
+ // didn't include the name param which is optional.
+ if ( name.IsNull() || name.Len() == 0 )
+ name = classId;
+
+ // We got all the params and can now create the applet
+ if ((applet = appletWindow->CreateApplet(classId, name, tag , size)) != NULL){
+ applet->Show(true);
+ m_WParser->OpenContainer()->InsertCell(new wxHtmlAppletCell(applet,al));
+ }
+ else
+ wxMessageBox("wxApplet error: Could not create:" + classId + "," + name);
+ }
+ else{
+ wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR);
+ return false;
}
+ //Add more param parsing here. If or when spec changes.
+ //For now we'll ignore any other params those HTML guys
+ //might put in our tag.
}
- return false;
+
+ return false;
}
-TAG_HANDLER_END(Embed)
+TAG_HANDLER_END(wxApplet)
+
+TAGS_MODULE_BEGIN(wxApplet)
+ TAGS_MODULE_ADD(wxApplet)
+TAGS_MODULE_END(wxApplet)
+
+/*********************************************************************************
+wxHtmlAppletCell
+*********************************************************************************/
+wxHtmlAppletCell::wxHtmlAppletCell(wxWindow *wnd, int align) : wxHtmlCell()
+{
+ int sx, sy;
+ m_Wnd = wnd;
+ m_Wnd->GetSize(&sx, &sy);
+ m_Width = sx, m_Height = sy;
+
+ switch (align) {
+ case wxHTML_ALIGN_TOP :
+ m_Descent = m_Height;
+ break;
+ case wxHTML_ALIGN_CENTER :
+ m_Descent = m_Height / 2;
+ break;
+ case wxHTML_ALIGN_BOTTOM :
+ default :
+ m_Descent = 0;
+ break;
+ }
+
+ SetCanLiveOnPagebreak(FALSE);
+}
+
+
+void wxHtmlAppletCell::Draw(wxDC& WXUNUSED(dc), int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(view_y1), int WXUNUSED(view_y2))
+{
+ int absx = 0, absy = 0, stx, sty;
+ wxHtmlCell *c = this;
+
+ while (c)
+ {
+ absx += c->GetPosX();
+ absy += c->GetPosY();
+ c = c->GetParent();
+ }
+
+ ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
+ m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty);
+}
+
+
+
+void wxHtmlAppletCell::DrawInvisible(wxDC& WXUNUSED(dc), int WXUNUSED(x), int WXUNUSED(y))
+{
+ int absx = 0, absy = 0, stx, sty;
+ wxHtmlCell *c = this;
+
+ while (c)
+ {
+ absx += c->GetPosX();
+ absy += c->GetPosY();
+ c = c->GetParent();
+ }
+
+ ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
+ m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty);
+}
+
+
+
+void wxHtmlAppletCell::Layout(int w)
+{
+ int sx, sy;
+ m_Wnd->GetSize(&sx, &sy);
+ m_Width = sx, m_Height = sy;
+
+ wxHtmlCell::Layout(w);
+}
+
+
+
-TAGS_MODULE_BEGIN(Embed)
- TAGS_MODULE_ADD(Embed)
-TAGS_MODULE_END(Embed)
+// This is our little forcelink hack.
+FORCE_LINK(loadpage)