]> git.saurik.com Git - wxWidgets.git/blame_incremental - contrib/src/applet/appletwindow.cpp
pass correct key code in TREE_KEY_DOWN event
[wxWidgets.git] / contrib / src / applet / appletwindow.cpp
... / ...
CommitLineData
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
56wxHashTable 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.
63BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow)
64 EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage)
65 EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded)
66END_EVENT_TABLE()
67
68// Implement the class functions for wxHtmlAppletWindow
69IMPLEMENT_CLASS(wxHtmlAppletWindow, wxHtmlWindow);
70
71// Define the wxAppletList implementation
72#include "wx/listimpl.cpp"
73WX_DEFINE_LIST(wxAppletList);
74
75/****************************************************************************
76REMARKS:
77Constructor for the applet window class.
78****************************************************************************/
79wxHtmlAppletWindow::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/****************************************************************************
126REMARKS:
127Destructor for the applet window class.
128****************************************************************************/
129wxHtmlAppletWindow::~wxHtmlAppletWindow()
130{
131}
132
133/****************************************************************************
134PARAMETERS:
135className - Name of the applet class to create an object for
136size - Initial size of the applet to be created
137
138RETURNS:
139Pointer to the wxApplet created, or NULL if unable to create the applet.
140
141REMARKS:
142This function is used to create new wxApplet objects dynamically based on the
143class name as a string. This allows instances of wxApplet classes to be
144created dynamically based on string values embedded in the custom tags of an
145HTML page.
146****************************************************************************/
147wxApplet *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/****************************************************************************
180PARAMETERS:
181classId - Name of the Plugin class to create an object for
182
183RETURNS:
184Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
185
186REMARKS:
187This function is used to create new wxPlugIn objects dynamically based on the
188class name as a string. This allows instances of wxPlugIn classes to be
189created dynamically based on string values embedded in the custom tags of an
190HTML page.
191****************************************************************************/
192bool 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/****************************************************************************
213PARAMETERS:
214appletName - Name of the applet class to find
215
216RETURNS:
217Pointer to the wxApplet found, or NULL if not found.
218
219REMARKS:
220Find an instance of an applet based on it's name
221****************************************************************************/
222wxApplet *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/****************************************************************************
232PARAMETERS:
233applet - Pointer to the applet object to remove from the list
234
235RETURNS:
236True if the applet was found and removed, false if not. The applet itself
237is *not* destroyed!
238
239REMARKS:
240Remove an applet from the manager. Called during applet destruction
241****************************************************************************/
242bool 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/****************************************************************************
255PARAMETERS:
256URL - New URL for the page to load
257
258RETURNS:
259True if page loaded successfully, false if not
260
261REMARKS:
262Remove an applet from the manager. Called during applet destruction
263****************************************************************************/
264#include "scitech"
265bool 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/****************************************************************************
342PARAMETERS:
343URL - String URL that we are navigating to
344
345REMARKS:
346Called when the user navigates to a new URL from the current page. We simply
347call the LoadPage function above to load the new page and display it.
348****************************************************************************/
349void wxHtmlAppletWindow::OnLinkClicked(
350 const wxHtmlLinkInfo& link)
351{
352 LoadPage(link.GetHref());
353}
354
355/****************************************************************************
356REMARKS:
357Called when the user navigates forward within the HTML history stack.
358We call all the applets in turn allowing them to handle the navigation
359command prior to being destructed when the current page is destroyed.
360****************************************************************************/
361bool 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/****************************************************************************
373REMARKS:
374Called when the user navigates backwards within the HTML history stack.
375We call all the applets in turn allowing them to handle the navigation
376command prior to being destructed when the current page is destroyed.
377****************************************************************************/
378bool 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/****************************************************************************
390PARAMETERS:
391msg - wxEvent message to be sent to all wxApplets
392
393REMARKS:
394This function is called by the wxApplet's when they need to send a message
395to all other applets on the current page. This is the primary form of
396communication between applets on the page if they need to inform each
397other of internal information.
398
399Note that the event handling terminates as soon as the first wxApplet
400handles the event. If the event should be handled by all wxApplet's,
401the event handlers for the applets should not reset the wxEvent::Skip()
402value (ie: by default it is true).
403****************************************************************************/
404void 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/****************************************************************************
421PARAMETERS:
422name - Uniq wxString used as hash key
423cookie - wxObject data returned when name is found.
424
425RETURNS:
426True if new cookie was added, false if cookie with same name already exists.
427
428REMARKS:
429This function is called by the wxApplet's when they need register a cookie
430of data in the applet window's cookie table. Cookies are arbitrary data
431objects that are references by unique name's by the wxApplet. These
432values can be used to store and retrieve data that needs to remain
433persisent across invocations of the wxApplet. Ie: The first time an
434applet is created it would use the cookie to store data to maintain
435it's present state so that if you navigated back to the same page
436is would be able to re-load the prior state as though the applet
437was never actually destructed.
438
439Note: 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****************************************************************************/
444bool 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/****************************************************************************
456PARAMETERS:
457name - wxString uniq haskey used to remove item from hash
458
459RETURNS:
460True if found and deleted, false if not found in table.
461
462REMARKS:
463This function is called by the wxApplet's when they need de-register a
464cookie of data in the applet window's cookie table. The data in the
465cookie itself is also deleted before it is removed from the table.
466****************************************************************************/
467bool 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/****************************************************************************
479PARAMETERS:
480msg - wxEvent message to be sent to all wxApplets
481
482RETURNS:
483Pointer to the cookie data if found, NULL if not found.
484
485REMARKS:
486This function is called by the wxApplet's when they need to find a cookie
487of data given it's public name. If the cookie is not found, NULL is
488returned.
489****************************************************************************/
490wxObject *wxHtmlAppletWindow::FindCookie(
491 const wxString& name)
492{
493 return m_Cookies.Get(name);
494}
495
496/****************************************************************************
497PARAMETERS:
498event - Event to handle
499
500REMARKS:
501This function handles delayed LoadPage events posted from applets that
502need to change the page for the current window to a new window.
503****************************************************************************/
504void 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/****************************************************************************
522PARAMETERS:
523event - Event to handle
524
525REMARKS:
526This function handles delayed LoadPage events posted from applets that
527need to change the page for the current window to a new window.
528****************************************************************************/
529void wxHtmlAppletWindow::OnPageLoaded(
530 wxPageLoadedEvent &)
531{
532 Enable(true);
533}
534
535/****************************************************************************
536PARAMETERS:
537none
538
539REMARKS:
540This function tries to lock the mutex. If it can't, returns
541immediately with false.
542***************************************************************************/
543bool wxHtmlAppletWindow::TryLock()
544{
545 if (!m_mutexLock) {
546 m_mutexLock = true;
547 return true;
548 }
549 return false;
550}
551
552/****************************************************************************
553PARAMETERS:
554name - name of the last applet that changed the data in this object
555group - name of the group the allplet belongs to.
556href - webpage to go to.
557
558REMARKS:
559VirtualData is used to store information on the virtual links.
560****************************************************************************/
561VirtualData::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/****************************************************************************
572PARAMETERS:
573REMARKS:
574****************************************************************************/
575void 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/****************************************************************************
586REMARKS:
587Implementation for the <embed> HTML tag handler. This handler takes care
588of automatically constructing the wxApplet objects of the appropriate
589class based on the <embed> tag information.
590****************************************************************************/
591TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET")
592
593TAG_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
661TAG_HANDLER_END(wxApplet)
662
663TAGS_MODULE_BEGIN(wxApplet)
664 TAGS_MODULE_ADD(wxApplet)
665TAGS_MODULE_END(wxApplet)
666
667/*********************************************************************************
668wxHtmlAppletCell
669*********************************************************************************/
670wxHtmlAppletCell::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
694void 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
712void 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
730void 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.
743FORCE_LINK(loadpage)
744