]> git.saurik.com Git - wxWidgets.git/blame_incremental - contrib/src/applet/appletwindow.cpp
Fixed compile errors, warnings and other DSMs, and improved comments.
[wxWidgets.git] / contrib / src / applet / appletwindow.cpp
... / ...
CommitLineData
1/****************************************************************************
2*
3* wxWindows HTML Applet Package
4*
5* Copyright (C) 1991-2001 SciTech Software, Inc.
6* All rights reserved.
7*
8* ======================================================================
9* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
10* | |
11* |This copyrighted computer code is a proprietary trade secret of |
12* |SciTech Software, Inc., located at 505 Wall Street, Chico, CA 95928 |
13* |USA (www.scitechsoft.com). ANY UNAUTHORIZED POSSESSION, USE, |
14* |VIEWING, COPYING, MODIFICATION OR DISSEMINATION OF THIS CODE IS |
15* |STRICTLY PROHIBITED BY LAW. Unless you have current, express |
16* |written authorization from SciTech to possess or use this code, you |
17* |may be subject to civil and/or criminal penalties. |
18* | |
19* |If you received this code in error or you would like to report |
20* |improper use, please immediately contact SciTech Software, Inc. at |
21* |530-894-8400. |
22* | |
23* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
24* ======================================================================
25*
26* Language: ANSI C++
27* Environment: Any
28*
29* Description: Main wxHtmlAppletWindow class implementation
30*
31****************************************************************************/
32
33// For compilers that support precompilation
34#include "wx/wxprec.h"
35#include "wx/utils.h"
36#include "wx/process.h"
37#include "wx/spawnbrowser.h"
38#include "wx/html/forcelnk.h"
39
40// crt
41#ifdef __WXMSW__
42#include <process.h> // spawnl()
43#endif
44
45// Include private headers
46#include "wx/applet/applet.h"
47#include "wx/applet/window.h"
48#include "wx/applet/loadpage.h"
49#include "wx/applet/plugin.h"
50
51// Preprocessor Stuff
52#include "wx/applet/prepinclude.h"
53#include "wx/applet/prepecho.h"
54#include "wx/applet/prepifelse.h"
55
56/*---------------------------- Global variables ---------------------------*/
57
58wxHashTable wxHtmlAppletWindow::m_Cookies;
59
60/*------------------------- Implementation --------------------------------*/
61
62// Empty event handler. We include this event handler simply so that
63// sub-classes of wxApplet can reference wxApplet in the event tables
64// that they create as necessary.
65BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow)
66 EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage)
67 EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded)
68END_EVENT_TABLE()
69
70// Implement the class functions for wxHtmlAppletWindow
71IMPLEMENT_CLASS(wxHtmlAppletWindow, wxHtmlWindow);
72
73// Define the wxAppletList implementation
74#include "wx/listimpl.cpp"
75WX_DEFINE_LIST(wxAppletList);
76
77/****************************************************************************
78REMARKS:
79Constructor for the applet window class.
80****************************************************************************/
81wxHtmlAppletWindow::wxHtmlAppletWindow(
82 wxWindow *parent,
83 wxWindowID id,
84 wxToolBarBase *navBar,
85 int navBackId,
86 int navForwardId,
87 const wxPoint& pos,
88 const wxSize& size,
89 long style,
90 const wxString& name,
91 const wxString& docroot )
92 : wxHtmlWindow(parent,id,pos,size,style,name)
93{
94 // Init our locks
95 UnLock();
96
97 // setup client navbars
98 if (navBar) {
99 m_NavBar = navBar;
100 m_NavBackId = navBackId;
101 m_NavForwardId = navForwardId;
102 }
103 else {
104 m_NavBar = NULL;
105 }
106
107 // Set up docroot
108 m_DocRoot = docroot;
109
110 // Set the key_type for applets
111 m_AppletList = wxAppletList(wxKEY_STRING);
112
113 // Add HTML preprocessors
114 // deleting preprocessors is done by the code within the window
115
116 incPreprocessor = new wxIncludePrep(); // #include preprocessor
117 incPreprocessor->ChangeDirectory(m_DocRoot);
118
119 wxEchoPrep * echoPreprocessor = new wxEchoPrep(); // #echo preprocessor
120 wxIfElsePrep * ifPreprocessor = new wxIfElsePrep();
121
122 this->AddProcessor(incPreprocessor);
123 this->AddProcessor(echoPreprocessor);
124 this->AddProcessor(ifPreprocessor);
125}
126
127/****************************************************************************
128REMARKS:
129Destructor for the applet window class.
130****************************************************************************/
131wxHtmlAppletWindow::~wxHtmlAppletWindow()
132{
133}
134
135/****************************************************************************
136PARAMETERS:
137className - Name of the applet class to create an object for
138size - Initial size of the applet to be created
139
140RETURNS:
141Pointer to the wxApplet created, or NULL if unable to create the applet.
142
143REMARKS:
144This function is used to create new wxApplet objects dynamically based on the
145class name as a string. This allows instances of wxApplet classes to be
146created dynamically based on string values embedded in the custom tags of an
147HTML page.
148****************************************************************************/
149wxApplet *wxHtmlAppletWindow::CreateApplet(
150 const wxString& classId,
151 const wxString& iName,
152 const wxHtmlTag& params,
153 const wxSize& size)
154{
155 // Dynamically create the class instance at runtime
156 wxClassInfo *info = wxClassInfo::FindClass(classId.c_str());
157 if (!info)
158 return NULL;
159 wxObject *obj = info->CreateObject();
160 if (!obj)
161 return NULL;
162 wxApplet *applet = wxDynamicCast(obj,wxApplet);
163 if (!applet)
164 return NULL;
165 if (!applet->Create(this,params,size)) {
166 delete applet;
167 return NULL;
168 }
169 else {
170 // do some fixups on the size if its screwed up
171 wxSize nsize = applet->GetBestSize();
172 if (nsize.x < size.x) nsize.x = size.x;
173 if (nsize.y < size.y) nsize.y = size.y;
174 applet->SetSize(nsize);
175 }
176
177 m_AppletList.Append(iName,(wxObject*)applet);
178 return applet;
179}
180
181/****************************************************************************
182PARAMETERS:
183classId - Name of the Plugin class to create an object for
184
185RETURNS:
186Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
187
188REMARKS:
189This function is used to create new wxPlugIn objects dynamically based on the
190class name as a string. This allows instances of wxPlugIn classes to be
191created dynamically based on string values embedded in the custom tags of an
192HTML page.
193****************************************************************************/
194bool wxHtmlAppletWindow::CreatePlugIn(
195 const wxString& classId )
196{
197 // Dynamically create the class instance at runtime
198 wxClassInfo *info = wxClassInfo::FindClass(classId.c_str());
199 if (!info)
200 return false;
201 wxObject *obj = info->CreateObject();
202 if (!obj)
203 return false;
204 wxPlugIn *plugIn = wxDynamicCast(obj,wxPlugIn);
205 if (!plugIn)
206 return false;
207 if (!plugIn->Create(this)) {
208 delete plugIn;
209 return false;
210 }
211 return true;
212}
213
214/****************************************************************************
215PARAMETERS:
216appletName - Name of the applet class to find
217
218RETURNS:
219Pointer to the wxApplet found, or NULL if not found.
220
221REMARKS:
222Find an instance of an applet based on it's name
223****************************************************************************/
224wxApplet *wxHtmlAppletWindow::FindApplet(
225 const wxString& appletName)
226{
227 wxAppletList::Node *node = m_AppletList.Find(appletName);
228 if (!node)
229 return NULL;
230 return node->GetData();
231}
232
233/****************************************************************************
234PARAMETERS:
235applet - Pointer to the applet object to remove from the list
236
237RETURNS:
238True if the applet was found and removed, false if not. The applet itself
239is *not* destroyed!
240
241REMARKS:
242Remove an applet from the manager. Called during applet destruction
243****************************************************************************/
244bool wxHtmlAppletWindow::RemoveApplet(
245 const wxApplet *applet)
246{
247 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
248 if (node->GetData() == applet) {
249 m_AppletList.DeleteNode(node);
250 return true;
251 }
252 }
253 return false;
254}
255
256/****************************************************************************
257PARAMETERS:
258URL - New URL for the page to load
259
260RETURNS:
261True if page loaded successfully, false if not
262
263REMARKS:
264Remove an applet from the manager. Called during applet destruction
265****************************************************************************/
266#include "scitech"
267bool wxHtmlAppletWindow::LoadPage(
268 const wxString& link)
269{
270 wxString href(link);
271
272 // TODO: technically we allow no relative paths
273
274 // Check to see if it is a real url, if not it is a file
275 if (link.Mid(0, 5).CmpNoCase("http:") != 0) {
276
277 // Check for abs path. If it is not then tack on the path
278 // supplied at creation.
279 // TODO: Abs paths are only used in testing (remove this)
280 if (link.GetChar(1) != ':')
281 href = m_DocRoot + href;
282 }
283
284 if (link.GetChar(0) == '?'){
285 wxString cmd = link.BeforeFirst('=');
286 wxString cmdValue = link.AfterFirst('=');
287
288 // Launches the default Internet browser for the system.
289 if(!(cmd.CmpNoCase("?EXTERNAL"))){
290 return wxSpawnBrowser(this, cmdValue.c_str());
291 }
292
293 // Launches an external program on the system.
294 if (!(cmd.CmpNoCase("?EXECUTE"))){
295 int code = spawnl( P_NOWAIT, cmdValue , NULL );
296 return (!code);
297 }
298
299 // Looks for a href in a variable stored as a cookie. The href can be
300 // changed on the fly.
301 if (!(cmd.CmpNoCase("?VIRTUAL"))){
302 VirtualData& temp = *((VirtualData*)FindCookie(cmdValue));
303 if (&temp) {
304 href = temp.GetHref();
305 }
306 else {
307#ifdef CHECKED
308 wxLogError(_T("VIRTUAL LINK ERROR: '%s' does not exist."), cmdValue.c_str());
309#endif
310 return true;
311 }
312 }
313
314 // This launches a qlet - It is like an applet but is more generic in that it
315 // can be of any wxWin type so it then has the freedom to do more stuff.
316 if (!(cmd.CmpNoCase("?WXAPPLET"))){
317 if (!cmdValue.IsNull()){
318 if (!CreatePlugIn(cmdValue)){
319#ifdef CHECKED
320 wxLogError(_T("Launch Applet ERROR: '%s' does not exist."), cmdValue.c_str());
321#endif
322 }
323 }
324 return true;
325 }
326 }
327
328 // Inform all the applets that the new page is being loaded
329 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
330 (node->GetData())->OnLinkClicked(wxHtmlLinkInfo(href));
331 Show(false);
332 bool stat = wxHtmlWindow::LoadPage(href);
333 Show(true);
334
335 // Enable/Dis the navbar tools
336 if (m_NavBar) {
337 m_NavBar->EnableTool(m_NavForwardId,HistoryCanForward());
338 m_NavBar->EnableTool(m_NavBackId,HistoryCanBack());
339 }
340 return stat;
341}
342
343/****************************************************************************
344PARAMETERS:
345URL - String URL that we are navigating to
346
347REMARKS:
348Called when the user navigates to a new URL from the current page. We simply
349call the LoadPage function above to load the new page and display it.
350****************************************************************************/
351void wxHtmlAppletWindow::OnLinkClicked(
352 const wxHtmlLinkInfo& link)
353{
354 LoadPage(link.GetHref());
355}
356
357/****************************************************************************
358REMARKS:
359Called when the user navigates forward within the HTML history stack.
360We call all the applets in turn allowing them to handle the navigation
361command prior to being destructed when the current page is destroyed.
362****************************************************************************/
363bool wxHtmlAppletWindow::HistoryForward()
364{
365 if (!HistoryCanForward())
366 return false;
367
368 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
369 (node->GetData())->OnHistoryForward();
370
371 return wxHtmlWindow::HistoryForward();
372}
373
374/****************************************************************************
375REMARKS:
376Called when the user navigates backwards within the HTML history stack.
377We call all the applets in turn allowing them to handle the navigation
378command prior to being destructed when the current page is destroyed.
379****************************************************************************/
380bool wxHtmlAppletWindow::HistoryBack()
381{
382 if (!HistoryCanBack())
383 return false;
384
385 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
386 (node->GetData())->OnHistoryBack();
387
388 return wxHtmlWindow::HistoryBack();
389}
390
391/****************************************************************************
392PARAMETERS:
393msg - wxEvent message to be sent to all wxApplets
394
395REMARKS:
396This function is called by the wxApplet's when they need to send a message
397to all other applets on the current page. This is the primary form of
398communication between applets on the page if they need to inform each
399other of internal information.
400
401Note that the event handling terminates as soon as the first wxApplet
402handles the event. If the event should be handled by all wxApplet's,
403the event handlers for the applets should not reset the wxEvent::Skip()
404value (ie: by default it is true).
405****************************************************************************/
406void wxHtmlAppletWindow::SendMessage(
407 wxEvent& msg)
408{
409 // Preset the skip flag
410 msg.Skip();
411
412 // Process all applets in turn and send them the message
413 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
414 (node->GetData())->OnMessage(msg);
415 if (!msg.GetSkipped()){
416 wxMessageBox("BREAK");
417 break;
418 }
419 }
420}
421
422/****************************************************************************
423PARAMETERS:
424name - Uniq wxString used as hash key
425cookie - wxObject data returned when name is found.
426
427RETURNS:
428True if new cookie was added, false if cookie with same name already exists.
429
430REMARKS:
431This function is called by the wxApplet's when they need register a cookie
432of data in the applet window's cookie table. Cookies are arbitrary data
433objects that are references by unique name's by the wxApplet. These
434values can be used to store and retrieve data that needs to remain
435persisent across invocations of the wxApplet. Ie: The first time an
436applet is created it would use the cookie to store data to maintain
437it's present state so that if you navigated back to the same page
438is would be able to re-load the prior state as though the applet
439was never actually destructed.
440
441Note: If a cookie with the same name already exists, this function returns
442 false. Hence if you wish to replace a cookie you should first call
443 UnRegisterCookie to ensure the cookie is deleted and then call this
444 function.
445****************************************************************************/
446bool wxHtmlAppletWindow::RegisterCookie(
447 const wxString& name,
448 wxObject *cookie)
449{
450 // Fail if the named cookie already exists!
451 if (m_Cookies.Get(name))
452 return false;
453 m_Cookies.Put(name,cookie);
454 return true;
455}
456
457/****************************************************************************
458PARAMETERS:
459name - wxString uniq haskey used to remove item from hash
460
461RETURNS:
462True if found and deleted, false if not found in table.
463
464REMARKS:
465This function is called by the wxApplet's when they need de-register a
466cookie of data in the applet window's cookie table. The data in the
467cookie itself is also deleted before it is removed from the table.
468****************************************************************************/
469bool wxHtmlAppletWindow::UnRegisterCookie(
470 const wxString& name)
471{
472 wxObject *data = m_Cookies.Delete(name);
473 if (data) {
474 delete data;
475 return true;
476 }
477 return false;
478}
479
480/****************************************************************************
481PARAMETERS:
482msg - wxEvent message to be sent to all wxApplets
483
484RETURNS:
485Pointer to the cookie data if found, NULL if not found.
486
487REMARKS:
488This function is called by the wxApplet's when they need to find a cookie
489of data given it's public name. If the cookie is not found, NULL is
490returned.
491****************************************************************************/
492wxObject *wxHtmlAppletWindow::FindCookie(
493 const wxString& name)
494{
495 return m_Cookies.Get(name);
496}
497
498/****************************************************************************
499PARAMETERS:
500event - Event to handle
501
502REMARKS:
503This function handles delayed LoadPage events posted from applets that
504need to change the page for the current window to a new window.
505****************************************************************************/
506void wxHtmlAppletWindow::OnLoadPage(
507 wxLoadPageEvent &event)
508{
509 // Test the mutex lock.
510 if (!(IsLocked())){
511 Lock();
512 if (event.GetHtmlWindow() == this){
513 if (LoadPage(event.GetHRef())){
514 // wxPageLoadedEvent evt;
515 // NOTE: This is reserved for later use as we might need to send
516 // page loaded events to applets.
517 }
518 }
519 UnLock();
520 }
521}
522
523/****************************************************************************
524PARAMETERS:
525event - Event to handle
526
527REMARKS:
528This function handles delayed LoadPage events posted from applets that
529need to change the page for the current window to a new window.
530****************************************************************************/
531void wxHtmlAppletWindow::OnPageLoaded(
532 wxPageLoadedEvent &)
533{
534 Enable(true);
535}
536
537/****************************************************************************
538PARAMETERS:
539none
540
541REMARKS:
542This function tries to lock the mutex. If it can't, returns
543immediately with false.
544***************************************************************************/
545bool wxHtmlAppletWindow::TryLock()
546{
547 if (!m_mutexLock) {
548 m_mutexLock = true;
549 return true;
550 }
551 return false;
552}
553
554/****************************************************************************
555PARAMETERS:
556name - name of the last applet that changed the data in this object
557group - name of the group the allplet belongs to.
558href - webpage to go to.
559
560REMARKS:
561VirtualData is used to store information on the virtual links.
562****************************************************************************/
563VirtualData::VirtualData(
564 wxString& name,
565 wxString& group,
566 wxString& href )
567{
568 m_name = name;
569 m_group = group;
570 m_href = href;
571}
572
573/****************************************************************************
574PARAMETERS:
575REMARKS:
576****************************************************************************/
577void AppletProcess::OnTerminate(
578 int,
579 int )
580{
581 // we're not needed any more
582 delete this;
583}
584
585#include "wx/html/m_templ.h"
586
587/****************************************************************************
588REMARKS:
589Implementation for the <embed> HTML tag handler. This handler takes care
590of automatically constructing the wxApplet objects of the appropriate
591class based on the <embed> tag information.
592****************************************************************************/
593TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET")
594
595TAG_HANDLER_PROC(tag)
596{
597 wxWindow *wnd;
598 wxHtmlAppletWindow *appletWindow;
599 wxApplet *applet;
600 wxString classId;
601 wxString name;
602 int width, height;
603
604 wnd = m_WParser->GetWindow();
605
606 if ((appletWindow = wxDynamicCast(wnd,wxHtmlAppletWindow)) != NULL){
607 wxSize size = wxDefaultSize;
608 int al;
609 if (tag.HasParam("WIDTH")) {
610 tag.GetParamAsInt("WIDTH", &width);
611 size.SetWidth(width);
612 }
613
614 if (tag.HasParam("HEIGHT")) {
615 tag.GetParamAsInt("HEIGHT", &height);
616 size.SetHeight(height);
617 }
618
619 al = wxHTML_ALIGN_BOTTOM;
620 if (tag.HasParam(wxT("ALIGN"))) {
621 wxString alstr = tag.GetParam(wxT("ALIGN"));
622 alstr.MakeUpper(); // for the case alignment was in ".."
623 if (alstr == wxT("TEXTTOP") || alstr == wxT("TOP"))
624 al = wxHTML_ALIGN_TOP;
625 else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
626 al = wxHTML_ALIGN_CENTER;
627 }
628
629 if (tag.HasParam("CLASSID")){
630 classId = tag.GetParam("CLASSID");
631 if ( classId.IsNull() || classId.Len() == 0 ){
632 wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR);
633 return false;
634 }
635 if (tag.HasParam("NAME"))
636 name = tag.GetParam("NAME");
637
638 // If the name is NULL or len is zero then we assume that the html guy
639 // didn't include the name param which is optional.
640 if ( name.IsNull() || name.Len() == 0 )
641 name = classId;
642
643 // We got all the params and can now create the applet
644 if ((applet = appletWindow->CreateApplet(classId, name, tag , size)) != NULL){
645 applet->Show(true);
646 m_WParser->OpenContainer()->InsertCell(new wxHtmlAppletCell(applet,al));
647 }
648 else
649 wxMessageBox("wxApplet error: Could not create:" + classId + "," + name);
650 }
651 else{
652 wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR);
653 return false;
654 }
655 //Add more param parsing here. If or when spec changes.
656 //For now we'll ignore any other params those HTML guys
657 //might put in our tag.
658 }
659
660 return false;
661}
662
663TAG_HANDLER_END(wxApplet)
664
665TAGS_MODULE_BEGIN(wxApplet)
666 TAGS_MODULE_ADD(wxApplet)
667TAGS_MODULE_END(wxApplet)
668
669/*********************************************************************************
670wxHtmlAppletCell
671*********************************************************************************/
672wxHtmlAppletCell::wxHtmlAppletCell(wxWindow *wnd, int align) : wxHtmlCell()
673{
674 int sx, sy;
675 m_Wnd = wnd;
676 m_Wnd->GetSize(&sx, &sy);
677 m_Width = sx, m_Height = sy;
678
679 switch (align) {
680 case wxHTML_ALIGN_TOP :
681 m_Descent = m_Height;
682 break;
683 case wxHTML_ALIGN_CENTER :
684 m_Descent = m_Height / 2;
685 break;
686 case wxHTML_ALIGN_BOTTOM :
687 default :
688 m_Descent = 0;
689 break;
690 }
691
692 SetCanLiveOnPagebreak(FALSE);
693}
694
695
696void wxHtmlAppletCell::Draw(wxDC& WXUNUSED(dc), int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(view_y1), int WXUNUSED(view_y2))
697{
698 int absx = 0, absy = 0, stx, sty;
699 wxHtmlCell *c = this;
700
701 while (c)
702 {
703 absx += c->GetPosX();
704 absy += c->GetPosY();
705 c = c->GetParent();
706 }
707
708 ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
709 m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty);
710}
711
712
713
714void wxHtmlAppletCell::DrawInvisible(wxDC& WXUNUSED(dc), int WXUNUSED(x), int WXUNUSED(y))
715{
716 int absx = 0, absy = 0, stx, sty;
717 wxHtmlCell *c = this;
718
719 while (c)
720 {
721 absx += c->GetPosX();
722 absy += c->GetPosY();
723 c = c->GetParent();
724 }
725
726 ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
727 m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty);
728}
729
730
731
732void wxHtmlAppletCell::Layout(int w)
733{
734 int sx, sy;
735 m_Wnd->GetSize(&sx, &sy);
736 m_Width = sx, m_Height = sy;
737
738 wxHtmlCell::Layout(w);
739}
740
741
742
743
744// This is our little forcelink hack.
745FORCE_LINK(loadpage)
746