]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/applet/appletwindow.cpp
fix for (re)positioning the main window when the style changes
[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 *
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