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