]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/applet/appletwindow.cpp
don't call wxYield() from EnsureVisible(), this is too dangerous - and unnecessary...
[wxWidgets.git] / contrib / src / applet / appletwindow.cpp
CommitLineData
d9b91de7
KB
1/****************************************************************************
2*
67fc151d 3* wxWindows HTML Applet Package
d9b91de7
KB
4*
5* Copyright (C) 1991-2001 SciTech Software, Inc.
6* All rights reserved.
7*
716cd410
KB
8* ========================================================================
9*
10* The contents of this file are subject to the wxWindows License
11* Version 3.0 (the "License"); you may not use this file except in
12* compliance with the License. You may obtain a copy of the License at
13* http://www.wxwindows.org/licence3.txt
14*
15* Software distributed under the License is distributed on an
16* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17* implied. See the License for the specific language governing
18* rights and limitations under the License.
19*
20* ========================================================================
d9b91de7 21*
67fc151d
KB
22* Language: ANSI C++
23* Environment: Any
d9b91de7
KB
24*
25* Description: Main wxHtmlAppletWindow class implementation
26*
27****************************************************************************/
28
29// For compilers that support precompilation
30#include "wx/wxprec.h"
38caaa61 31#include "wx/html/forcelnk.h"
d9b91de7
KB
32
33// Include private headers
34#include "wx/applet/applet.h"
38caaa61
KB
35#include "wx/applet/window.h"
36#include "wx/applet/loadpage.h"
d9b91de7 37
38caaa61
KB
38// Preprocessor Stuff
39#include "wx/applet/prepinclude.h"
40#include "wx/applet/prepecho.h"
41#include "wx/applet/prepifelse.h"
42
43
44/*---------------------------- Global variables ---------------------------*/
45
46wxHashTable wxHtmlAppletWindow::m_Cookies;
47
d9b91de7
KB
48/*------------------------- Implementation --------------------------------*/
49
50// Empty event handler. We include this event handler simply so that
51// sub-classes of wxApplet can reference wxApplet in the event tables
52// that they create as necessary.
53BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow)
38caaa61
KB
54 EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage)
55 EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded)
d9b91de7
KB
56END_EVENT_TABLE()
57
58// Implement the class functions for wxHtmlAppletWindow
59IMPLEMENT_CLASS(wxHtmlAppletWindow, wxHtmlWindow);
60
61// Define the wxAppletList implementation
62#include "wx/listimpl.cpp"
63WX_DEFINE_LIST(wxAppletList);
64
65/****************************************************************************
66REMARKS:
67Constructor for the applet window class.
68****************************************************************************/
69wxHtmlAppletWindow::wxHtmlAppletWindow(
67fc151d
KB
70 wxWindow *parent,
71 wxWindowID id,
38caaa61
KB
72 wxToolBarBase *navBar,
73 int navBackId,
74 int navForwardId,
67fc151d
KB
75 const wxPoint& pos,
76 const wxSize& size,
77 long style,
78 const wxString& name)
79 : wxHtmlWindow(parent,id,pos,size,style,name)
d9b91de7 80{
716cd410
KB
81 // Init our locks
82 UnLock();
83
84 // setup client navbars
38caaa61
KB
85 if (navBar) {
86 m_NavBar = navBar;
87 m_NavBackId = navBackId;
88 m_NavForwardId = navForwardId;
89 }
90 else {
91 m_NavBar = NULL;
92 }
93
716cd410 94 // Add HTML preprocessors
38caaa61
KB
95 // deleting preprocessors is done by the code within the window
96
97 incPreprocessor = new wxIncludePrep(); // #include preprocessor
98 wxEchoPrep * echoPreprocessor = new wxEchoPrep(); // #echo preprocessor
99 wxIfElsePrep * ifPreprocessor = new wxIfElsePrep();
100
101 this->AddProcessor(incPreprocessor);
102 this->AddProcessor(echoPreprocessor);
103 this->AddProcessor(ifPreprocessor);
d9b91de7
KB
104}
105
106/****************************************************************************
107REMARKS:
108Destructor for the applet window class.
109****************************************************************************/
110wxHtmlAppletWindow::~wxHtmlAppletWindow()
111{
112}
113
114/****************************************************************************
115PARAMETERS:
67fc151d
KB
116className - Name of the applet class to create an object for
117size - Initial size of the applet to be created
d9b91de7
KB
118
119RETURNS:
120Pointer to the wxApplet created, or NULL if unable to create the applet.
121
122REMARKS:
123This function is used to create new wxApplet objects dynamically based on the
124class name as a string. This allows instances of wxApplet classes to be
125created dynamically based on string values embedded in the custom tags of an
126HTML page.
127****************************************************************************/
128wxApplet *wxHtmlAppletWindow::CreateApplet(
38caaa61
KB
129 const wxString& classId,
130 const wxString& iName,
131 const wxHtmlTag& params,
67fc151d 132 const wxSize& size)
d9b91de7 133{
67fc151d 134 // Dynamically create the class instance at runtime
38caaa61 135 wxClassInfo *info = wxClassInfo::FindClass(classId.c_str());
d9b91de7
KB
136 if (!info)
137 return NULL;
67fc151d
KB
138 wxObject *obj = info->CreateObject();
139 if (!obj)
140 return NULL;
d9b91de7 141 wxApplet *applet = wxDynamicCast(obj,wxApplet);
67fc151d
KB
142 if (!applet)
143 return NULL;
38caaa61 144 if (!applet->Create(this,params,size)) {
67fc151d
KB
145 delete applet;
146 return NULL;
147 }
38caaa61 148 m_AppletList.Append(iName,applet);
67fc151d 149 return applet;
d9b91de7
KB
150}
151
152/****************************************************************************
153PARAMETERS:
67fc151d 154appletName - Name of the applet class to find
d9b91de7
KB
155
156RETURNS:
157Pointer to the wxApplet found, or NULL if not found.
158
159REMARKS:
160Find an instance of an applet based on it's name
161****************************************************************************/
162wxApplet *wxHtmlAppletWindow::FindApplet(
67fc151d 163 const wxString& appletName)
d9b91de7 164{
67fc151d
KB
165 wxAppletList::Node *node = m_AppletList.Find(appletName);
166 if (!node)
167 return NULL;
168 return node->GetData();
38caaa61 169}
d9b91de7
KB
170
171/****************************************************************************
172PARAMETERS:
67fc151d 173applet - Pointer to the applet object to remove from the list
d9b91de7
KB
174
175RETURNS:
176True if the applet was found and removed, false if not. The applet itself
177is *not* destroyed!
178
179REMARKS:
180Remove an applet from the manager. Called during applet destruction
181****************************************************************************/
182bool wxHtmlAppletWindow::RemoveApplet(
67fc151d 183 const wxApplet *applet)
d9b91de7 184{
67fc151d
KB
185 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
186 if (node->GetData() == applet) {
187 m_AppletList.DeleteNode(node);
188 return true;
189 }
190 }
191 return false;
38caaa61 192}
d9b91de7
KB
193
194/****************************************************************************
195PARAMETERS:
67fc151d 196URL - New URL for the page to load
d9b91de7
KB
197
198RETURNS:
199True if page loaded successfully, false if not
200
201REMARKS:
202Remove an applet from the manager. Called during applet destruction
203****************************************************************************/
204bool wxHtmlAppletWindow::LoadPage(
38caaa61 205 const wxString& link)
d9b91de7 206{
38caaa61
KB
207 wxString href(link);
208
209 // TODO: This needs to be made platform inde if possible.
210 if (link.GetChar(0) == '?'){
211 wxString cmd = link.BeforeFirst('=');
212 wxString cmdValue = link.AfterFirst('=');
213
214 if(!(cmd.CmpNoCase("?EXTERNAL"))){
215#ifdef __WINDOWS__
216 ShellExecute(this ? (HWND)this->GetHWND() : NULL,NULL,cmdValue.c_str(),NULL,"",SW_SHOWNORMAL);
217#else
218 #error Platform not implemented yet!
219#endif
220 return true;
221 }
222 if (!(cmd.CmpNoCase("?EXECUTE"))){
223 wxMessageBox(cmdValue);
224 return true;
225 }
226 if (!(cmd.CmpNoCase("?VIRTUAL"))){
227 VirtualData& temp = *((VirtualData*)FindCookie(cmdValue));
228 if (&temp) {
229 href = temp.GetHref();
230 }
231 else {
232#ifdef CHECKED
233 wxMessageBox("VIRTUAL LINK ERROR: " + cmdValue + " does not exist.");
234#endif
235 return true;
236 }
237 }
238 }
239
716cd410
KB
240 // Make a copy of the current path the translate for <!-- include files from what will be the new path
241 // we cannot just grab this value from the base class since it is not correct until after LoadPage is
242 // called. And we need the incPreprocessor to know the right path before LoadPage.
243 wxFileSystem fs;
244 fs.ChangePathTo(m_FS->GetPath(), true);
245 fs.ChangePathTo(link);
246 incPreprocessor->ChangeDirectory(fs.GetPath());
38caaa61
KB
247
248 // Inform all the applets that the new page is being loaded
67fc151d 249 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
38caaa61
KB
250 (node->GetData())->OnLinkClicked(wxHtmlLinkInfo(href));
251 bool stat = wxHtmlWindow::LoadPage(href);
252
716cd410
KB
253
254
38caaa61
KB
255 // Enable/Dis the navbar tools
256 if (m_NavBar) {
257 m_NavBar->EnableTool(m_NavForwardId,HistoryCanForward());
258 m_NavBar->EnableTool(m_NavBackId,HistoryCanBack());
259 }
260 return stat;
d9b91de7
KB
261}
262
263/****************************************************************************
264PARAMETERS:
67fc151d 265URL - String URL that we are navigating to
d9b91de7
KB
266
267REMARKS:
268Called when the user navigates to a new URL from the current page. We simply
269call the LoadPage function above to load the new page and display it.
270****************************************************************************/
271void wxHtmlAppletWindow::OnLinkClicked(
67fc151d 272 const wxHtmlLinkInfo& link)
d9b91de7 273{
38caaa61 274 LoadPage(link.GetHref());
d9b91de7
KB
275}
276
277/****************************************************************************
278REMARKS:
279Called when the user navigates forward within the HTML history stack.
280We call all the applets in turn allowing them to handle the navigation
281command prior to being destructed when the current page is destroyed.
282****************************************************************************/
283bool wxHtmlAppletWindow::HistoryForward()
284{
38caaa61 285 if (!HistoryCanForward())
67fc151d 286 return false;
38caaa61 287
67fc151d
KB
288 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
289 (node->GetData())->OnHistoryForward();
38caaa61 290
67fc151d 291 return wxHtmlWindow::HistoryForward();
d9b91de7
KB
292}
293
294/****************************************************************************
295REMARKS:
296Called when the user navigates backwards within the HTML history stack.
297We call all the applets in turn allowing them to handle the navigation
298command prior to being destructed when the current page is destroyed.
299****************************************************************************/
300bool wxHtmlAppletWindow::HistoryBack()
301{
38caaa61 302 if (!HistoryCanBack())
67fc151d 303 return false;
38caaa61 304
67fc151d
KB
305 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
306 (node->GetData())->OnHistoryBack();
38caaa61 307
67fc151d 308 return wxHtmlWindow::HistoryBack();
d9b91de7
KB
309}
310
311/****************************************************************************
312PARAMETERS:
67fc151d 313msg - wxEvent message to be sent to all wxApplets
d9b91de7
KB
314
315REMARKS:
316This function is called by the wxApplet's when they need to send a message
317to all other applets on the current page. This is the primary form of
318communication between applets on the page if they need to inform each
319other of internal information.
320
321Note that the event handling terminates as soon as the first wxApplet
322handles the event. If the event should be handled by all wxApplet's,
323the event handlers for the applets should not reset the wxEvent::Skip()
324value (ie: by default it is true).
325****************************************************************************/
326void wxHtmlAppletWindow::SendMessage(
67fc151d 327 wxEvent& msg)
38caaa61 328{
67fc151d
KB
329 // Preset the skip flag
330 msg.Skip();
38caaa61 331
67fc151d
KB
332 // Process all applets in turn and send them the message
333 for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
334 (node->GetData())->OnMessage(msg);
38caaa61
KB
335 if (!msg.GetSkipped()){
336 wxMessageBox("BREAK");
67fc151d 337 break;
38caaa61 338 }
67fc151d 339 }
d9b91de7
KB
340}
341
342/****************************************************************************
343PARAMETERS:
38caaa61
KB
344name - Uniq wxString used as hash key
345cookie - wxObject data returned when name is found.
d9b91de7
KB
346
347RETURNS:
67fc151d 348True if new cookie was added, false if cookie with same name already exists.
d9b91de7
KB
349
350REMARKS:
351This function is called by the wxApplet's when they need register a cookie
352of data in the applet window's cookie table. Cookies are arbitrary data
353objects that are references by unique name's by the wxApplet. These
354values can be used to store and retrieve data that needs to remain
355persisent across invocations of the wxApplet. Ie: The first time an
356applet is created it would use the cookie to store data to maintain
357it's present state so that if you navigated back to the same page
358is would be able to re-load the prior state as though the applet
359was never actually destructed.
360
361Note: If a cookie with the same name already exists, this function returns
67fc151d
KB
362 false. Hence if you wish to replace a cookie you should first call
363 UnRegisterCookie to ensure the cookie is deleted and then call this
364 function.
d9b91de7
KB
365****************************************************************************/
366bool wxHtmlAppletWindow::RegisterCookie(
67fc151d
KB
367 const wxString& name,
368 wxObject *cookie)
d9b91de7 369{
67fc151d
KB
370 // Fail if the named cookie already exists!
371 if (m_Cookies.Get(name))
372 return false;
38caaa61 373 m_Cookies.Put(name,cookie);
67fc151d 374 return true;
d9b91de7
KB
375}
376
377/****************************************************************************
378PARAMETERS:
38caaa61 379name - wxString uniq haskey used to remove item from hash
d9b91de7
KB
380
381RETURNS:
382True if found and deleted, false if not found in table.
383
384REMARKS:
385This function is called by the wxApplet's when they need de-register a
386cookie of data in the applet window's cookie table. The data in the
387cookie itself is also deleted before it is removed from the table.
388****************************************************************************/
389bool wxHtmlAppletWindow::UnRegisterCookie(
67fc151d 390 const wxString& name)
d9b91de7 391{
67fc151d
KB
392 wxObject *data = m_Cookies.Delete(name);
393 if (data) {
394 delete data;
395 return true;
396 }
397 return false;
d9b91de7
KB
398}
399
400/****************************************************************************
401PARAMETERS:
67fc151d 402msg - wxEvent message to be sent to all wxApplets
d9b91de7
KB
403
404RETURNS:
405Pointer to the cookie data if found, NULL if not found.
406
407REMARKS:
408This function is called by the wxApplet's when they need to find a cookie
409of data given it's public name. If the cookie is not found, NULL is
410returned.
411****************************************************************************/
412wxObject *wxHtmlAppletWindow::FindCookie(
67fc151d 413 const wxString& name)
d9b91de7 414{
67fc151d 415 return m_Cookies.Get(name);
d9b91de7
KB
416}
417
38caaa61
KB
418/****************************************************************************
419PARAMETERS:
420event - Event to handle
421
422REMARKS:
423This function handles delayed LoadPage events posted from applets that
424need to change the page for the current window to a new window.
425****************************************************************************/
426void wxHtmlAppletWindow::OnLoadPage(
427 wxLoadPageEvent &event)
428{
716cd410
KB
429 // Test the mutex lock. We have to do this here because wxHTML constantly
430 // calls wxYield which processes the message queue. This in turns means
431 // that we may end up processing a new 'loadPage' event while the new
432 // page is still loading! We need to avoid this so we use a simple
433 // lock to avoid loading a page while presently loading another page.
434 if (TryLock()) {
435 if (event.GetHtmlWindow() == this){
436 if (LoadPage(event.GetHRef())){
437 // wxPageLoadedEvent evt;
438 // NOTE: This is reserved for later use as we might need to send
439 // page loaded events to applets.
440 }
38caaa61 441 }
716cd410 442 UnLock();
38caaa61
KB
443 }
444}
445
446/****************************************************************************
447PARAMETERS:
448event - Event to handle
449
450REMARKS:
451This function handles delayed LoadPage events posted from applets that
452need to change the page for the current window to a new window.
453****************************************************************************/
454void wxHtmlAppletWindow::OnPageLoaded(
455 wxPageLoadedEvent &)
456{
457 Enable(true);
458}
459
716cd410
KB
460/****************************************************************************
461PARAMETERS:
462none
463
464REMARKS:
465This function tries to lock the mutex. If it can't, returns
466immediately with false.
467***************************************************************************/
468bool wxHtmlAppletWindow::TryLock()
469{
470 if (!m_mutexLock) {
471 m_mutexLock = true;
472 return true;
473 }
474 return false;
475}
476
38caaa61
KB
477/****************************************************************************
478PARAMETERS:
479name - name of the last applet that changed the data in this object
480group - name of the group the allplet belongs to.
481href - webpage to go to.
482
483REMARKS:
484VirtualData is used to store information on the virtual links.
485****************************************************************************/
486VirtualData::VirtualData(
487 wxString& name,
488 wxString& group,
489 wxString& href )
490{
491 m_name = name;
492 m_group = group;
493 m_href = href;
494}
495
d9b91de7
KB
496#include "wx/html/m_templ.h"
497
498/****************************************************************************
499REMARKS:
500Implementation for the <embed> HTML tag handler. This handler takes care
501of automatically constructing the wxApplet objects of the appropriate
502class based on the <embed> tag information.
503****************************************************************************/
38caaa61 504TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET")
d9b91de7
KB
505
506TAG_HANDLER_PROC(tag)
507{
38caaa61
KB
508 wxWindow *wnd;
509 wxHtmlAppletWindow *appletWindow;
510 wxApplet *applet;
511 wxString classId;
512 wxString name;
513 int width, height;
514
515 wnd = m_WParser->GetWindow();
516
517 if ((appletWindow = wxDynamicCast(wnd,wxHtmlAppletWindow)) != NULL){
518 tag.ScanParam("WIDTH", "%i", &width);
519 tag.ScanParam("HEIGHT", "%i", &height);
520 if (tag.HasParam("CLASSID")){
521 classId = tag.GetParam("CLASSID");
522 if ( classId.IsNull() || classId.Len() == 0 ){
523 wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR);
524 return false;
67fc151d 525 }
38caaa61
KB
526 if (tag.HasParam("NAME"))
527 name = tag.GetParam("NAME");
528
529 // If the name is NULL or len is zero then we assume that the html guy
530 // didn't include the name param which is optional.
531 if ( name.IsNull() || name.Len() == 0 )
532 name = classId;
533
534 // We got all the params and can now create the applet
535 if ((applet = appletWindow->CreateApplet(classId, name, tag , wxSize(width, height))) != NULL){
536 applet->Show(true);
537 m_WParser->OpenContainer()->InsertCell(new wxHtmlWidgetCell(applet,0));
538 }
539 else
540 wxMessageBox("wxApplet error: Could not create:" + classId + "," + name);
541 }
542 else{
543 wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR);
544 return false;
67fc151d 545 }
38caaa61
KB
546 //Add more param parsing here. If or when spec changes.
547 //For now we'll ignore any other params those HTML guys
548 //might put in our tag.
67fc151d 549 }
38caaa61
KB
550
551 return false;
d9b91de7
KB
552}
553
38caaa61
KB
554TAG_HANDLER_END(wxApplet)
555
556TAGS_MODULE_BEGIN(wxApplet)
557 TAGS_MODULE_ADD(wxApplet)
558TAGS_MODULE_END(wxApplet)
d9b91de7 559
38caaa61
KB
560// This is our little forcelink hack.
561FORCE_LINK(loadpage)
d9b91de7 562