]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/applet/appletwindow.cpp
1 /****************************************************************************
3 * wxWindows HTML Applet Package
5 * Copyright (C) 1991-2001 SciTech Software, Inc.
8 * ======================================================================
9 * |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
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. |
19 * |If you received this code in error or you would like to report |
20 * |improper use, please immediately contact SciTech Software, Inc. at |
23 * |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
24 * ======================================================================
29 * Description: Main wxHtmlAppletWindow class implementation
31 ****************************************************************************/
33 // For compilers that support precompilation
34 #include "wx/wxprec.h"
36 #include "wx/process.h"
37 #include "wx/spawnbrowser.h"
38 #include "wx/html/forcelnk.h"
42 #include <process.h> // spawnl()
45 // Include private headers
46 #include "wx/applet/applet.h"
47 #include "wx/applet/window.h"
48 #include "wx/applet/loadpage.h"
49 #include "wx/applet/plugin.h"
52 #include "wx/applet/prepinclude.h"
53 #include "wx/applet/prepecho.h"
54 #include "wx/applet/prepifelse.h"
56 /*---------------------------- Global variables ---------------------------*/
58 wxHashTable
wxHtmlAppletWindow::m_Cookies
;
60 /*------------------------- Implementation --------------------------------*/
62 // Empty event handler. We include this event handler simply so that
63 // sub-classes of wxApplet can reference wxApplet in the event tables
64 // that they create as necessary.
65 BEGIN_EVENT_TABLE(wxHtmlAppletWindow
, wxHtmlWindow
)
66 EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage
)
67 EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded
)
70 // Implement the class functions for wxHtmlAppletWindow
71 IMPLEMENT_CLASS(wxHtmlAppletWindow
, wxHtmlWindow
);
73 // Define the wxAppletList implementation
74 #include "wx/listimpl.cpp"
75 WX_DEFINE_LIST(wxAppletList
);
77 /****************************************************************************
79 Constructor for the applet window class.
80 ****************************************************************************/
81 wxHtmlAppletWindow::wxHtmlAppletWindow(
84 wxToolBarBase
*navBar
,
91 const wxString
& docroot
)
92 : wxHtmlWindow(parent
,id
,pos
,size
,style
,name
)
97 // setup client navbars
100 m_NavBackId
= navBackId
;
101 m_NavForwardId
= navForwardId
;
110 // Set the key_type for applets
111 m_AppletList
= wxAppletList(wxKEY_STRING
);
113 // Add HTML preprocessors
114 // deleting preprocessors is done by the code within the window
116 incPreprocessor
= new wxIncludePrep(); // #include preprocessor
117 incPreprocessor
->ChangeDirectory(m_DocRoot
);
119 wxEchoPrep
* echoPreprocessor
= new wxEchoPrep(); // #echo preprocessor
120 wxIfElsePrep
* ifPreprocessor
= new wxIfElsePrep();
122 this->AddProcessor(incPreprocessor
);
123 this->AddProcessor(echoPreprocessor
);
124 this->AddProcessor(ifPreprocessor
);
127 /****************************************************************************
129 Destructor for the applet window class.
130 ****************************************************************************/
131 wxHtmlAppletWindow::~wxHtmlAppletWindow()
135 /****************************************************************************
137 className - Name of the applet class to create an object for
138 size - Initial size of the applet to be created
141 Pointer to the wxApplet created, or NULL if unable to create the applet.
144 This function is used to create new wxApplet objects dynamically based on the
145 class name as a string. This allows instances of wxApplet classes to be
146 created dynamically based on string values embedded in the custom tags of an
148 ****************************************************************************/
149 wxApplet
*wxHtmlAppletWindow::CreateApplet(
150 const wxString
& classId
,
151 const wxString
& iName
,
152 const wxHtmlTag
& params
,
155 // Dynamically create the class instance at runtime
156 wxClassInfo
*info
= wxClassInfo::FindClass(classId
.c_str());
159 wxObject
*obj
= info
->CreateObject();
162 wxApplet
*applet
= wxDynamicCast(obj
,wxApplet
);
165 if (!applet
->Create(this,params
,size
)) {
170 // do some fixups on the size if its screwed up
171 wxSize nsize
= applet
->GetBestSize();
172 if (nsize
.x
< size
.x
) nsize
.x
= size
.x
;
173 if (nsize
.y
< size
.y
) nsize
.y
= size
.y
;
174 applet
->SetSize(nsize
);
177 m_AppletList
.Append(iName
,(wxObject
*)applet
);
181 /****************************************************************************
183 classId - Name of the Plugin class to create an object for
186 Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
189 This function is used to create new wxPlugIn objects dynamically based on the
190 class name as a string. This allows instances of wxPlugIn classes to be
191 created dynamically based on string values embedded in the custom tags of an
193 ****************************************************************************/
194 bool wxHtmlAppletWindow::CreatePlugIn(
195 const wxString
& classId
)
197 // Dynamically create the class instance at runtime
198 wxClassInfo
*info
= wxClassInfo::FindClass(classId
.c_str());
201 wxObject
*obj
= info
->CreateObject();
204 wxPlugIn
*plugIn
= wxDynamicCast(obj
,wxPlugIn
);
207 if (!plugIn
->Create(this)) {
214 /****************************************************************************
216 appletName - Name of the applet class to find
219 Pointer to the wxApplet found, or NULL if not found.
222 Find an instance of an applet based on it's name
223 ****************************************************************************/
224 wxApplet
*wxHtmlAppletWindow::FindApplet(
225 const wxString
& appletName
)
227 wxAppletList::Node
*node
= m_AppletList
.Find(appletName
);
230 return node
->GetData();
233 /****************************************************************************
235 applet - Pointer to the applet object to remove from the list
238 True if the applet was found and removed, false if not. The applet itself
242 Remove an applet from the manager. Called during applet destruction
243 ****************************************************************************/
244 bool wxHtmlAppletWindow::RemoveApplet(
245 const wxApplet
*applet
)
247 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext()) {
248 if (node
->GetData() == applet
) {
249 m_AppletList
.DeleteNode(node
);
256 /****************************************************************************
258 URL - New URL for the page to load
261 True if page loaded successfully, false if not
264 Remove an applet from the manager. Called during applet destruction
265 ****************************************************************************/
267 bool wxHtmlAppletWindow::LoadPage(
268 const wxString
& link
)
272 // TODO: technically we allow no relative paths
274 // Check to see if it is a real url, if not it is a file
275 if (link
.Mid(0, 5).CmpNoCase("http:") != 0) {
277 // Check for abs path. If it is not then tack on the path
278 // supplied at creation.
279 // TODO: Abs paths are only used in testing (remove this)
280 if (link
.GetChar(1) != ':')
281 href
= m_DocRoot
+ href
;
284 if (link
.GetChar(0) == '?'){
285 wxString cmd
= link
.BeforeFirst('=');
286 wxString cmdValue
= link
.AfterFirst('=');
288 // Launches the default Internet browser for the system.
289 if(!(cmd
.CmpNoCase("?EXTERNAL"))){
290 return wxSpawnBrowser(this, cmdValue
.c_str());
293 // Launches an external program on the system.
294 if (!(cmd
.CmpNoCase("?EXECUTE"))){
295 int code
= spawnl( P_NOWAIT
, cmdValue
, NULL
);
299 // Looks for a href in a variable stored as a cookie. The href can be
300 // changed on the fly.
301 if (!(cmd
.CmpNoCase("?VIRTUAL"))){
302 VirtualData
& temp
= *((VirtualData
*)FindCookie(cmdValue
));
304 href
= temp
.GetHref();
308 wxLogError(_T("VIRTUAL LINK ERROR: '%s' does not exist."), cmdValue
.c_str());
314 // This launches a qlet - It is like an applet but is more generic in that it
315 // can be of any wxWin type so it then has the freedom to do more stuff.
316 if (!(cmd
.CmpNoCase("?WXAPPLET"))){
317 if (!cmdValue
.IsNull()){
318 if (!CreatePlugIn(cmdValue
)){
320 wxLogError(_T("Launch Applet ERROR: '%s' does not exist."), cmdValue
.c_str());
328 // Inform all the applets that the new page is being loaded
329 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
330 (node
->GetData())->OnLinkClicked(wxHtmlLinkInfo(href
));
332 bool stat
= wxHtmlWindow::LoadPage(href
);
335 // Enable/Dis the navbar tools
337 m_NavBar
->EnableTool(m_NavForwardId
,HistoryCanForward());
338 m_NavBar
->EnableTool(m_NavBackId
,HistoryCanBack());
343 /****************************************************************************
345 URL - String URL that we are navigating to
348 Called when the user navigates to a new URL from the current page. We simply
349 call the LoadPage function above to load the new page and display it.
350 ****************************************************************************/
351 void wxHtmlAppletWindow::OnLinkClicked(
352 const wxHtmlLinkInfo
& link
)
354 LoadPage(link
.GetHref());
357 /****************************************************************************
359 Called when the user navigates forward within the HTML history stack.
360 We call all the applets in turn allowing them to handle the navigation
361 command prior to being destructed when the current page is destroyed.
362 ****************************************************************************/
363 bool wxHtmlAppletWindow::HistoryForward()
365 if (!HistoryCanForward())
368 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
369 (node
->GetData())->OnHistoryForward();
371 return wxHtmlWindow::HistoryForward();
374 /****************************************************************************
376 Called when the user navigates backwards within the HTML history stack.
377 We call all the applets in turn allowing them to handle the navigation
378 command prior to being destructed when the current page is destroyed.
379 ****************************************************************************/
380 bool wxHtmlAppletWindow::HistoryBack()
382 if (!HistoryCanBack())
385 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
386 (node
->GetData())->OnHistoryBack();
388 return wxHtmlWindow::HistoryBack();
391 /****************************************************************************
393 msg - wxEvent message to be sent to all wxApplets
396 This function is called by the wxApplet's when they need to send a message
397 to all other applets on the current page. This is the primary form of
398 communication between applets on the page if they need to inform each
399 other of internal information.
401 Note that the event handling terminates as soon as the first wxApplet
402 handles the event. If the event should be handled by all wxApplet's,
403 the event handlers for the applets should not reset the wxEvent::Skip()
404 value (ie: by default it is true).
405 ****************************************************************************/
406 void wxHtmlAppletWindow::SendMessage(
409 // Preset the skip flag
412 // Process all applets in turn and send them the message
413 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext()) {
414 (node
->GetData())->OnMessage(msg
);
415 if (!msg
.GetSkipped()){
416 wxMessageBox("BREAK");
422 /****************************************************************************
424 name - Uniq wxString used as hash key
425 cookie - wxObject data returned when name is found.
428 True if new cookie was added, false if cookie with same name already exists.
431 This function is called by the wxApplet's when they need register a cookie
432 of data in the applet window's cookie table. Cookies are arbitrary data
433 objects that are references by unique name's by the wxApplet. These
434 values can be used to store and retrieve data that needs to remain
435 persisent across invocations of the wxApplet. Ie: The first time an
436 applet is created it would use the cookie to store data to maintain
437 it's present state so that if you navigated back to the same page
438 is would be able to re-load the prior state as though the applet
439 was never actually destructed.
441 Note: If a cookie with the same name already exists, this function returns
442 false. Hence if you wish to replace a cookie you should first call
443 UnRegisterCookie to ensure the cookie is deleted and then call this
445 ****************************************************************************/
446 bool wxHtmlAppletWindow::RegisterCookie(
447 const wxString
& name
,
450 // Fail if the named cookie already exists!
451 if (m_Cookies
.Get(name
))
453 m_Cookies
.Put(name
,cookie
);
457 /****************************************************************************
459 name - wxString uniq haskey used to remove item from hash
462 True if found and deleted, false if not found in table.
465 This function is called by the wxApplet's when they need de-register a
466 cookie of data in the applet window's cookie table. The data in the
467 cookie itself is also deleted before it is removed from the table.
468 ****************************************************************************/
469 bool wxHtmlAppletWindow::UnRegisterCookie(
470 const wxString
& name
)
472 wxObject
*data
= m_Cookies
.Delete(name
);
480 /****************************************************************************
482 msg - wxEvent message to be sent to all wxApplets
485 Pointer to the cookie data if found, NULL if not found.
488 This function is called by the wxApplet's when they need to find a cookie
489 of data given it's public name. If the cookie is not found, NULL is
491 ****************************************************************************/
492 wxObject
*wxHtmlAppletWindow::FindCookie(
493 const wxString
& name
)
495 return m_Cookies
.Get(name
);
498 /****************************************************************************
500 event - Event to handle
503 This function handles delayed LoadPage events posted from applets that
504 need to change the page for the current window to a new window.
505 ****************************************************************************/
506 void wxHtmlAppletWindow::OnLoadPage(
507 wxLoadPageEvent
&event
)
509 // Test the mutex lock.
512 if (event
.GetHtmlWindow() == this){
513 if (LoadPage(event
.GetHRef())){
514 // wxPageLoadedEvent evt;
515 // NOTE: This is reserved for later use as we might need to send
516 // page loaded events to applets.
523 /****************************************************************************
525 event - Event to handle
528 This function handles delayed LoadPage events posted from applets that
529 need to change the page for the current window to a new window.
530 ****************************************************************************/
531 void wxHtmlAppletWindow::OnPageLoaded(
537 /****************************************************************************
542 This function tries to lock the mutex. If it can't, returns
543 immediately with false.
544 ***************************************************************************/
545 bool wxHtmlAppletWindow::TryLock()
554 /****************************************************************************
556 name - name of the last applet that changed the data in this object
557 group - name of the group the allplet belongs to.
558 href - webpage to go to.
561 VirtualData is used to store information on the virtual links.
562 ****************************************************************************/
563 VirtualData::VirtualData(
573 /****************************************************************************
576 ****************************************************************************/
577 void AppletProcess::OnTerminate(
581 // we're not needed any more
585 #include "wx/html/m_templ.h"
587 /****************************************************************************
589 Implementation for the <embed> HTML tag handler. This handler takes care
590 of automatically constructing the wxApplet objects of the appropriate
591 class based on the <embed> tag information.
592 ****************************************************************************/
593 TAG_HANDLER_BEGIN(wxApplet
, "WXAPPLET")
595 TAG_HANDLER_PROC(tag
)
598 wxHtmlAppletWindow
*appletWindow
;
604 wnd
= m_WParser
->GetWindow();
606 if ((appletWindow
= wxDynamicCast(wnd
,wxHtmlAppletWindow
)) != NULL
){
607 wxSize size
= wxDefaultSize
;
609 if (tag
.HasParam("WIDTH")) {
610 tag
.GetParamAsInt("WIDTH", &width
);
611 size
.SetWidth(width
);
614 if (tag
.HasParam("HEIGHT")) {
615 tag
.GetParamAsInt("HEIGHT", &height
);
616 size
.SetHeight(height
);
619 al
= wxHTML_ALIGN_BOTTOM
;
620 if (tag
.HasParam(wxT("ALIGN"))) {
621 wxString alstr
= tag
.GetParam(wxT("ALIGN"));
622 alstr
.MakeUpper(); // for the case alignment was in ".."
623 if (alstr
== wxT("TEXTTOP") || alstr
== wxT("TOP"))
624 al
= wxHTML_ALIGN_TOP
;
625 else if ((alstr
== wxT("CENTER")) || (alstr
== wxT("ABSCENTER")))
626 al
= wxHTML_ALIGN_CENTER
;
629 if (tag
.HasParam("CLASSID")){
630 classId
= tag
.GetParam("CLASSID");
631 if ( classId
.IsNull() || classId
.Len() == 0 ){
632 wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR
);
635 if (tag
.HasParam("NAME"))
636 name
= tag
.GetParam("NAME");
638 // If the name is NULL or len is zero then we assume that the html guy
639 // didn't include the name param which is optional.
640 if ( name
.IsNull() || name
.Len() == 0 )
643 // We got all the params and can now create the applet
644 if ((applet
= appletWindow
->CreateApplet(classId
, name
, tag
, size
)) != NULL
){
646 m_WParser
->OpenContainer()->InsertCell(new wxHtmlAppletCell(applet
,al
));
649 wxMessageBox("wxApplet error: Could not create:" + classId
+ "," + name
);
652 wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR
);
655 //Add more param parsing here. If or when spec changes.
656 //For now we'll ignore any other params those HTML guys
657 //might put in our tag.
663 TAG_HANDLER_END(wxApplet
)
665 TAGS_MODULE_BEGIN(wxApplet
)
666 TAGS_MODULE_ADD(wxApplet
)
667 TAGS_MODULE_END(wxApplet
)
669 /*********************************************************************************
671 *********************************************************************************/
672 wxHtmlAppletCell::wxHtmlAppletCell(wxWindow
*wnd
, int align
) : wxHtmlCell()
676 m_Wnd
->GetSize(&sx
, &sy
);
677 m_Width
= sx
, m_Height
= sy
;
680 case wxHTML_ALIGN_TOP
:
681 m_Descent
= m_Height
;
683 case wxHTML_ALIGN_CENTER
:
684 m_Descent
= m_Height
/ 2;
686 case wxHTML_ALIGN_BOTTOM
:
692 SetCanLiveOnPagebreak(FALSE
);
696 void wxHtmlAppletCell::Draw(wxDC
& WXUNUSED(dc
), int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(view_y1
), int WXUNUSED(view_y2
))
698 int absx
= 0, absy
= 0, stx
, sty
;
699 wxHtmlCell
*c
= this;
703 absx
+= c
->GetPosX();
704 absy
+= c
->GetPosY();
708 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
);
709 m_Wnd
->Move(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
);
714 void wxHtmlAppletCell::DrawInvisible(wxDC
& WXUNUSED(dc
), int WXUNUSED(x
), int WXUNUSED(y
))
716 int absx
= 0, absy
= 0, stx
, sty
;
717 wxHtmlCell
*c
= this;
721 absx
+= c
->GetPosX();
722 absy
+= c
->GetPosY();
726 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
);
727 m_Wnd
->Move(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
);
732 void wxHtmlAppletCell::Layout(int w
)
735 m_Wnd
->GetSize(&sx
, &sy
);
736 m_Width
= sx
, m_Height
= sy
;
738 wxHtmlCell::Layout(w
);
744 // This is our little forcelink hack.