]>
Commit | Line | Data |
---|---|---|
1 | /**************************************************************************** | |
2 | * | |
3 | * wxWindows HTML Applet Package | |
4 | * | |
5 | * Copyright (C) 1991-2001 SciTech Software, Inc. | |
6 | * All rights reserved. | |
7 | * | |
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 | * ======================================================================== | |
21 | * | |
22 | * Language: ANSI C++ | |
23 | * Environment: Any | |
24 | * | |
25 | * Description: Main wxHtmlAppletWindow class implementation | |
26 | * | |
27 | ****************************************************************************/ | |
28 | ||
29 | // For compilers that support precompilation | |
30 | #include "wx/wxprec.h" | |
31 | #include "wx/html/forcelnk.h" | |
32 | ||
33 | // Include private headers | |
34 | #include "wx/applet/applet.h" | |
35 | #include "wx/applet/window.h" | |
36 | #include "wx/applet/loadpage.h" | |
37 | ||
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 | ||
46 | wxHashTable wxHtmlAppletWindow::m_Cookies; | |
47 | ||
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. | |
53 | BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow) | |
54 | EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage) | |
55 | EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded) | |
56 | END_EVENT_TABLE() | |
57 | ||
58 | // Implement the class functions for wxHtmlAppletWindow | |
59 | IMPLEMENT_CLASS(wxHtmlAppletWindow, wxHtmlWindow); | |
60 | ||
61 | // Define the wxAppletList implementation | |
62 | #include "wx/listimpl.cpp" | |
63 | WX_DEFINE_LIST(wxAppletList); | |
64 | ||
65 | /**************************************************************************** | |
66 | REMARKS: | |
67 | Constructor for the applet window class. | |
68 | ****************************************************************************/ | |
69 | wxHtmlAppletWindow::wxHtmlAppletWindow( | |
70 | wxWindow *parent, | |
71 | wxWindowID id, | |
72 | wxToolBarBase *navBar, | |
73 | int navBackId, | |
74 | int navForwardId, | |
75 | const wxPoint& pos, | |
76 | const wxSize& size, | |
77 | long style, | |
78 | const wxString& name) | |
79 | : wxHtmlWindow(parent,id,pos,size,style,name) | |
80 | { | |
81 | // Init our locks | |
82 | UnLock(); | |
83 | ||
84 | // setup client navbars | |
85 | if (navBar) { | |
86 | m_NavBar = navBar; | |
87 | m_NavBackId = navBackId; | |
88 | m_NavForwardId = navForwardId; | |
89 | } | |
90 | else { | |
91 | m_NavBar = NULL; | |
92 | } | |
93 | ||
94 | // Add HTML preprocessors | |
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); | |
104 | } | |
105 | ||
106 | /**************************************************************************** | |
107 | REMARKS: | |
108 | Destructor for the applet window class. | |
109 | ****************************************************************************/ | |
110 | wxHtmlAppletWindow::~wxHtmlAppletWindow() | |
111 | { | |
112 | } | |
113 | ||
114 | /**************************************************************************** | |
115 | PARAMETERS: | |
116 | className - Name of the applet class to create an object for | |
117 | size - Initial size of the applet to be created | |
118 | ||
119 | RETURNS: | |
120 | Pointer to the wxApplet created, or NULL if unable to create the applet. | |
121 | ||
122 | REMARKS: | |
123 | This function is used to create new wxApplet objects dynamically based on the | |
124 | class name as a string. This allows instances of wxApplet classes to be | |
125 | created dynamically based on string values embedded in the custom tags of an | |
126 | HTML page. | |
127 | ****************************************************************************/ | |
128 | wxApplet *wxHtmlAppletWindow::CreateApplet( | |
129 | const wxString& classId, | |
130 | const wxString& iName, | |
131 | const wxHtmlTag& params, | |
132 | const wxSize& size) | |
133 | { | |
134 | // Dynamically create the class instance at runtime | |
135 | wxClassInfo *info = wxClassInfo::FindClass(classId.c_str()); | |
136 | if (!info) | |
137 | return NULL; | |
138 | wxObject *obj = info->CreateObject(); | |
139 | if (!obj) | |
140 | return NULL; | |
141 | wxApplet *applet = wxDynamicCast(obj,wxApplet); | |
142 | if (!applet) | |
143 | return NULL; | |
144 | if (!applet->Create(this,params,size)) { | |
145 | delete applet; | |
146 | return NULL; | |
147 | } | |
148 | m_AppletList.Append(iName,applet); | |
149 | return applet; | |
150 | } | |
151 | ||
152 | /**************************************************************************** | |
153 | PARAMETERS: | |
154 | appletName - Name of the applet class to find | |
155 | ||
156 | RETURNS: | |
157 | Pointer to the wxApplet found, or NULL if not found. | |
158 | ||
159 | REMARKS: | |
160 | Find an instance of an applet based on it's name | |
161 | ****************************************************************************/ | |
162 | wxApplet *wxHtmlAppletWindow::FindApplet( | |
163 | const wxString& appletName) | |
164 | { | |
165 | wxAppletList::Node *node = m_AppletList.Find(appletName); | |
166 | if (!node) | |
167 | return NULL; | |
168 | return node->GetData(); | |
169 | } | |
170 | ||
171 | /**************************************************************************** | |
172 | PARAMETERS: | |
173 | applet - Pointer to the applet object to remove from the list | |
174 | ||
175 | RETURNS: | |
176 | True if the applet was found and removed, false if not. The applet itself | |
177 | is *not* destroyed! | |
178 | ||
179 | REMARKS: | |
180 | Remove an applet from the manager. Called during applet destruction | |
181 | ****************************************************************************/ | |
182 | bool wxHtmlAppletWindow::RemoveApplet( | |
183 | const wxApplet *applet) | |
184 | { | |
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; | |
192 | } | |
193 | ||
194 | /**************************************************************************** | |
195 | PARAMETERS: | |
196 | URL - New URL for the page to load | |
197 | ||
198 | RETURNS: | |
199 | True if page loaded successfully, false if not | |
200 | ||
201 | REMARKS: | |
202 | Remove an applet from the manager. Called during applet destruction | |
203 | ****************************************************************************/ | |
204 | bool wxHtmlAppletWindow::LoadPage( | |
205 | const wxString& link) | |
206 | { | |
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 | ||
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()); | |
247 | ||
248 | // Inform all the applets that the new page is being loaded | |
249 | for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) | |
250 | (node->GetData())->OnLinkClicked(wxHtmlLinkInfo(href)); | |
251 | bool stat = wxHtmlWindow::LoadPage(href); | |
252 | ||
253 | ||
254 | ||
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; | |
261 | } | |
262 | ||
263 | /**************************************************************************** | |
264 | PARAMETERS: | |
265 | URL - String URL that we are navigating to | |
266 | ||
267 | REMARKS: | |
268 | Called when the user navigates to a new URL from the current page. We simply | |
269 | call the LoadPage function above to load the new page and display it. | |
270 | ****************************************************************************/ | |
271 | void wxHtmlAppletWindow::OnLinkClicked( | |
272 | const wxHtmlLinkInfo& link) | |
273 | { | |
274 | LoadPage(link.GetHref()); | |
275 | } | |
276 | ||
277 | /**************************************************************************** | |
278 | REMARKS: | |
279 | Called when the user navigates forward within the HTML history stack. | |
280 | We call all the applets in turn allowing them to handle the navigation | |
281 | command prior to being destructed when the current page is destroyed. | |
282 | ****************************************************************************/ | |
283 | bool wxHtmlAppletWindow::HistoryForward() | |
284 | { | |
285 | if (!HistoryCanForward()) | |
286 | return false; | |
287 | ||
288 | for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) | |
289 | (node->GetData())->OnHistoryForward(); | |
290 | ||
291 | return wxHtmlWindow::HistoryForward(); | |
292 | } | |
293 | ||
294 | /**************************************************************************** | |
295 | REMARKS: | |
296 | Called when the user navigates backwards within the HTML history stack. | |
297 | We call all the applets in turn allowing them to handle the navigation | |
298 | command prior to being destructed when the current page is destroyed. | |
299 | ****************************************************************************/ | |
300 | bool wxHtmlAppletWindow::HistoryBack() | |
301 | { | |
302 | if (!HistoryCanBack()) | |
303 | return false; | |
304 | ||
305 | for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) | |
306 | (node->GetData())->OnHistoryBack(); | |
307 | ||
308 | return wxHtmlWindow::HistoryBack(); | |
309 | } | |
310 | ||
311 | /**************************************************************************** | |
312 | PARAMETERS: | |
313 | msg - wxEvent message to be sent to all wxApplets | |
314 | ||
315 | REMARKS: | |
316 | This function is called by the wxApplet's when they need to send a message | |
317 | to all other applets on the current page. This is the primary form of | |
318 | communication between applets on the page if they need to inform each | |
319 | other of internal information. | |
320 | ||
321 | Note that the event handling terminates as soon as the first wxApplet | |
322 | handles the event. If the event should be handled by all wxApplet's, | |
323 | the event handlers for the applets should not reset the wxEvent::Skip() | |
324 | value (ie: by default it is true). | |
325 | ****************************************************************************/ | |
326 | void wxHtmlAppletWindow::SendMessage( | |
327 | wxEvent& msg) | |
328 | { | |
329 | // Preset the skip flag | |
330 | msg.Skip(); | |
331 | ||
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); | |
335 | if (!msg.GetSkipped()){ | |
336 | wxMessageBox("BREAK"); | |
337 | break; | |
338 | } | |
339 | } | |
340 | } | |
341 | ||
342 | /**************************************************************************** | |
343 | PARAMETERS: | |
344 | name - Uniq wxString used as hash key | |
345 | cookie - wxObject data returned when name is found. | |
346 | ||
347 | RETURNS: | |
348 | True if new cookie was added, false if cookie with same name already exists. | |
349 | ||
350 | REMARKS: | |
351 | This function is called by the wxApplet's when they need register a cookie | |
352 | of data in the applet window's cookie table. Cookies are arbitrary data | |
353 | objects that are references by unique name's by the wxApplet. These | |
354 | values can be used to store and retrieve data that needs to remain | |
355 | persisent across invocations of the wxApplet. Ie: The first time an | |
356 | applet is created it would use the cookie to store data to maintain | |
357 | it's present state so that if you navigated back to the same page | |
358 | is would be able to re-load the prior state as though the applet | |
359 | was never actually destructed. | |
360 | ||
361 | Note: If a cookie with the same name already exists, this function returns | |
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. | |
365 | ****************************************************************************/ | |
366 | bool wxHtmlAppletWindow::RegisterCookie( | |
367 | const wxString& name, | |
368 | wxObject *cookie) | |
369 | { | |
370 | // Fail if the named cookie already exists! | |
371 | if (m_Cookies.Get(name)) | |
372 | return false; | |
373 | m_Cookies.Put(name,cookie); | |
374 | return true; | |
375 | } | |
376 | ||
377 | /**************************************************************************** | |
378 | PARAMETERS: | |
379 | name - wxString uniq haskey used to remove item from hash | |
380 | ||
381 | RETURNS: | |
382 | True if found and deleted, false if not found in table. | |
383 | ||
384 | REMARKS: | |
385 | This function is called by the wxApplet's when they need de-register a | |
386 | cookie of data in the applet window's cookie table. The data in the | |
387 | cookie itself is also deleted before it is removed from the table. | |
388 | ****************************************************************************/ | |
389 | bool wxHtmlAppletWindow::UnRegisterCookie( | |
390 | const wxString& name) | |
391 | { | |
392 | wxObject *data = m_Cookies.Delete(name); | |
393 | if (data) { | |
394 | delete data; | |
395 | return true; | |
396 | } | |
397 | return false; | |
398 | } | |
399 | ||
400 | /**************************************************************************** | |
401 | PARAMETERS: | |
402 | msg - wxEvent message to be sent to all wxApplets | |
403 | ||
404 | RETURNS: | |
405 | Pointer to the cookie data if found, NULL if not found. | |
406 | ||
407 | REMARKS: | |
408 | This function is called by the wxApplet's when they need to find a cookie | |
409 | of data given it's public name. If the cookie is not found, NULL is | |
410 | returned. | |
411 | ****************************************************************************/ | |
412 | wxObject *wxHtmlAppletWindow::FindCookie( | |
413 | const wxString& name) | |
414 | { | |
415 | return m_Cookies.Get(name); | |
416 | } | |
417 | ||
418 | /**************************************************************************** | |
419 | PARAMETERS: | |
420 | event - Event to handle | |
421 | ||
422 | REMARKS: | |
423 | This function handles delayed LoadPage events posted from applets that | |
424 | need to change the page for the current window to a new window. | |
425 | ****************************************************************************/ | |
426 | void wxHtmlAppletWindow::OnLoadPage( | |
427 | wxLoadPageEvent &event) | |
428 | { | |
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 | } | |
441 | } | |
442 | UnLock(); | |
443 | } | |
444 | } | |
445 | ||
446 | /**************************************************************************** | |
447 | PARAMETERS: | |
448 | event - Event to handle | |
449 | ||
450 | REMARKS: | |
451 | This function handles delayed LoadPage events posted from applets that | |
452 | need to change the page for the current window to a new window. | |
453 | ****************************************************************************/ | |
454 | void wxHtmlAppletWindow::OnPageLoaded( | |
455 | wxPageLoadedEvent &) | |
456 | { | |
457 | Enable(true); | |
458 | } | |
459 | ||
460 | /**************************************************************************** | |
461 | PARAMETERS: | |
462 | none | |
463 | ||
464 | REMARKS: | |
465 | This function tries to lock the mutex. If it can't, returns | |
466 | immediately with false. | |
467 | ***************************************************************************/ | |
468 | bool wxHtmlAppletWindow::TryLock() | |
469 | { | |
470 | if (!m_mutexLock) { | |
471 | m_mutexLock = true; | |
472 | return true; | |
473 | } | |
474 | return false; | |
475 | } | |
476 | ||
477 | /**************************************************************************** | |
478 | PARAMETERS: | |
479 | name - name of the last applet that changed the data in this object | |
480 | group - name of the group the allplet belongs to. | |
481 | href - webpage to go to. | |
482 | ||
483 | REMARKS: | |
484 | VirtualData is used to store information on the virtual links. | |
485 | ****************************************************************************/ | |
486 | VirtualData::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 | ||
496 | #include "wx/html/m_templ.h" | |
497 | ||
498 | /**************************************************************************** | |
499 | REMARKS: | |
500 | Implementation for the <embed> HTML tag handler. This handler takes care | |
501 | of automatically constructing the wxApplet objects of the appropriate | |
502 | class based on the <embed> tag information. | |
503 | ****************************************************************************/ | |
504 | TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET") | |
505 | ||
506 | TAG_HANDLER_PROC(tag) | |
507 | { | |
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; | |
525 | } | |
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; | |
545 | } | |
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. | |
549 | } | |
550 | ||
551 | return false; | |
552 | } | |
553 | ||
554 | TAG_HANDLER_END(wxApplet) | |
555 | ||
556 | TAGS_MODULE_BEGIN(wxApplet) | |
557 | TAGS_MODULE_ADD(wxApplet) | |
558 | TAGS_MODULE_END(wxApplet) | |
559 | ||
560 | // This is our little forcelink hack. | |
561 | FORCE_LINK(loadpage) | |
562 |