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