]>
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 * ========================================================================
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
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.
20 * ========================================================================
25 * Description: Main wxHtmlAppletWindow class implementation
27 ****************************************************************************/
29 // Include private headers
30 #include "wx/applet/applet.h"
31 #include "wx/applet/window.h"
32 #include "wx/applet/loadpage.h"
33 #include "wx/applet/plugin.h"
36 #include "wx/applet/prepinclude.h"
37 #include "wx/applet/prepecho.h"
38 #include "wx/applet/prepifelse.h"
42 // Kind of pointless to use precompiled headers when this is the only
43 // file in this lib that would need them.
45 #include "wx/spawnbrowser.h"
46 #include "wx/html/forcelnk.h"
48 #include "wx/msgdlg.h"
49 #include "wx/tbarbase.h"
53 #include <process.h> // spawnl()
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 // Implement the dynamic class so it can be constructed dynamically
74 IMPLEMENT_DYNAMIC_CLASS(VirtualData
, wxObject
)
76 // Define the wxAppletList implementation
77 #include "wx/listimpl.cpp"
78 WX_DEFINE_LIST(wxAppletList
)
80 /****************************************************************************
82 Constructor for the applet window class.
83 ****************************************************************************/
84 wxHtmlAppletWindow::wxHtmlAppletWindow(
87 wxToolBarBase
*navBar
,
94 : wxHtmlWindow(parent
,id
,pos
,size
,style
,name
), m_AppletList(wxKEY_STRING
)
99 // setup client navbars
101 m_NavBarEnabled
= true;
103 m_NavBackId
= navBackId
;
104 m_NavForwardId
= navForwardId
;
107 m_NavBarEnabled
= false;
111 m_NavBackId
= navBackId
;
112 m_NavForwardId
= navForwardId
;
114 // Add HTML preprocessors
115 // deleting preprocessors is done by the code within the window
116 incPreprocessor
= new wxIncludePrep(); // #include preprocessor
117 incPreprocessor
->ChangeDirectory(m_FS
); // give it access to our filesys object
118 this->AddProcessor(incPreprocessor
);
119 this->AddProcessor(new wxEchoPrep());
120 this->AddProcessor(new wxIfElsePrep());
123 /****************************************************************************
125 Destructor for the applet window class.
126 ****************************************************************************/
127 wxHtmlAppletWindow::~wxHtmlAppletWindow()
131 /****************************************************************************
133 dc - wxDC object to draw on
136 ****************************************************************************/
137 void wxHtmlAppletWindow::OnDraw(
140 wxHtmlWindow::OnDraw(dc
);
143 /****************************************************************************
145 className - Name of the applet class to create an object for
146 size - Initial size of the applet to be created
149 Pointer to the wxApplet created, or NULL if unable to create the applet.
152 This function is used to create new wxApplet objects dynamically based on the
153 class name as a string. This allows instances of wxApplet classes to be
154 created dynamically based on string values embedded in the custom tags of an
156 ****************************************************************************/
157 wxApplet
*wxHtmlAppletWindow::CreateApplet(
158 const wxString
& classId
,
159 const wxString
& iName
,
160 const wxHtmlTag
& params
,
163 // Dynamically create the class instance at runtime
164 wxObject
*obj
= wxCreateDynamicObject(classId
.c_str());
165 wxApplet
*applet
= wxDynamicCast(obj
,wxApplet
);
168 if (!applet
->Create(this,params
,size
)) {
173 // do some fixups on the size if its screwed up
174 wxSize nsize
= applet
->GetBestSize();
175 if (nsize
.x
< size
.x
) nsize
.x
= size
.x
;
176 if (nsize
.y
< size
.y
) nsize
.y
= size
.y
;
177 applet
->SetSize(nsize
);
180 m_AppletList
.Append(iName
,(wxObject
*)applet
);
184 /****************************************************************************
186 classId - Name of the Plugin class to create an object for
189 Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
192 This function is used to create new wxPlugIn objects dynamically based on the
193 class name as a string. This allows instances of wxPlugIn classes to be
194 created dynamically based on string values embedded in the custom tags of an
196 ****************************************************************************/
197 bool wxHtmlAppletWindow::CreatePlugIn(
198 const wxString
& classId
,
199 const wxString
& cmdLine
)
201 // Dynamically create the class instance at runtime, execute it
202 // and then destroy it.
203 wxObject
*obj
= wxCreateDynamicObject(classId
.c_str());
204 wxPlugIn
*plugIn
= wxDynamicCast(obj
,wxPlugIn
);
207 if (!plugIn
->Create(this)) {
211 plugIn
->Run(cmdLine
);
216 /****************************************************************************
218 appletName - Name of the applet class to find
221 Pointer to the wxApplet found, or NULL if not found.
224 Find an instance of an applet based on it's name
225 ****************************************************************************/
226 wxApplet
*wxHtmlAppletWindow::FindApplet(
227 const wxString
& appletName
)
229 wxAppletList::Node
*node
= m_AppletList
.Find(appletName
);
232 return node
->GetData();
235 /****************************************************************************
237 applet - Pointer to the applet object to remove from the list
240 True if the applet was found and removed, false if not. The applet itself
244 Remove an applet from the manager. Called during applet destruction
245 ****************************************************************************/
246 bool wxHtmlAppletWindow::RemoveApplet(
247 const wxApplet
*applet
)
249 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext()) {
250 if (node
->GetData() == applet
) {
251 m_AppletList
.DeleteNode(node
);
258 /****************************************************************************
260 URL - New URL for the page to load
263 True if page loaded successfully, false if not
266 Remove an applet from the manager. Called during applet destruction
267 ****************************************************************************/
268 bool wxHtmlAppletWindow::LoadPage(
269 const wxString
& link
)
273 if (link
.GetChar(0) == '?'){
274 wxString cmd
= link
.BeforeFirst('=');
275 wxString cmdValue
= link
.AfterFirst('=');
277 // Launches the default Internet browser for the system.
278 if(!(cmd
.CmpNoCase("?EXTERNAL"))) {
279 return wxSpawnBrowser(this, cmdValue
.c_str());
282 // Launches an external program on the system.
283 if (!(cmd
.CmpNoCase("?EXECUTE"))) {
284 int waitflag
= P_NOWAIT
;
287 wxString filename
, path
, ext
;
289 // Parse the params sent to the execute command. For now the only
290 // parm is "wait". wait will cause spawn wait, default is nowait.
291 // Since we only need one param for now I am not going to make this
292 // any smater then it needs to be. If we need more params later i'll
294 int i
= cmdValue
.Find('(');
296 wxString param
= cmdValue
.AfterFirst('(');
297 cmdValue
.Truncate(i
);
298 if (!param
.CmpNoCase("wait)"))
302 currentdir
= wxGetCwd();
303 //we don't want to change the path of the virtual file system so we have to use these
304 //functions rather than the filesystem
305 wxSplitPath(cmdValue
, &path
, &filename
, &ext
);
306 if (path
.CmpNoCase("") != 0) wxSetWorkingDirectory(path
);
308 ret
= !spawnl( waitflag
, cmdValue
, NULL
);
309 //HACK should use wxExecute
310 //ret = wxExecute(filename, bool sync = FALSE, wxProcess *callback = NULL)
311 wxSetWorkingDirectory(currentdir
);
316 // Looks for a href in a variable stored as a cookie. The href can be
317 // changed on the fly.
318 if (!(cmd
.CmpNoCase("?VIRTUAL"))){
319 wxObject
*obj
= FindCookie(cmdValue
);
320 VirtualData
*virtData
= wxDynamicCast(obj
,VirtualData
);
322 // recurse and loadpage, just in case the link is like another
324 return LoadPage(virtData
->GetHref());
328 wxLogError(_T("VIRTUAL LINK ERROR: '%s' does not exist."), cmdValue
.c_str());
334 // This launches a qlet - It is like an applet but is more generic in that it
335 // can be of any wxWin type so it then has the freedom to do more stuff.
336 if (!(cmd
.CmpNoCase("?WXPLUGIN"))){
337 if (!cmdValue
.IsNull()) {
338 // TODO: We are going to need to add code to parse the command line
339 // parameters string in here in the future...
340 wxString cmdLine
= link
.AfterFirst('(');
341 cmdLine
= cmdLine
.BeforeLast(')');
342 if (!CreatePlugIn(cmdValue
,cmdLine
)) {
344 wxLogError(_T("Launch PlugIn ERROR: '%s' does not exist."), cmdValue
.c_str());
351 // This used in a link or href will take you back in the history.
352 if (!(cmd
.CmpNoCase("?BACK"))){
357 // This used in a link or href will take you forward in the history
358 if (!(cmd
.CmpNoCase("?FORWARD"))){
364 // Inform all the applets that the new page is being loaded
365 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
366 (node
->GetData())->OnLinkClicked(wxHtmlLinkInfo(href
));
370 bool stat
= wxHtmlWindow::LoadPage(href
);
373 // Enable/Dis the navbar tools
374 if (m_NavBarEnabled
) {
375 m_NavBar
->EnableTool(m_NavForwardId
,HistoryCanForward());
376 m_NavBar
->EnableTool(m_NavBackId
,HistoryCanBack());
381 /****************************************************************************
383 URL - String URL that we are navigating to
386 Called when the user navigates to a new URL from the current page. We simply
387 call the LoadPage function above to load the new page and display it.
388 ****************************************************************************/
389 void wxHtmlAppletWindow::OnLinkClicked(
390 const wxHtmlLinkInfo
& link
)
392 LoadPage(link
.GetHref());
395 /****************************************************************************
397 Called when the user navigates forward within the HTML history stack.
398 We call all the applets in turn allowing them to handle the navigation
399 command prior to being destructed when the current page is destroyed.
400 ****************************************************************************/
401 bool wxHtmlAppletWindow::HistoryForward()
403 if (!HistoryCanForward())
406 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
407 (node
->GetData())->OnHistoryForward();
409 return wxHtmlWindow::HistoryForward();
412 /****************************************************************************
414 Called when the user navigates backwards within the HTML history stack.
415 We call all the applets in turn allowing them to handle the navigation
416 command prior to being destructed when the current page is destroyed.
417 ****************************************************************************/
418 bool wxHtmlAppletWindow::HistoryBack()
420 if (!HistoryCanBack())
423 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext())
424 (node
->GetData())->OnHistoryBack();
426 return wxHtmlWindow::HistoryBack();
429 /****************************************************************************
431 This function is used to disable the navigation bars. If you want to
432 toggle to the navbars off you must call this function.
433 ****************************************************************************/
434 void wxHtmlAppletWindow::DisableNavBar()
436 m_NavBarEnabled
= false;
439 /****************************************************************************
441 This function is used to enable the nav bars. If you toggle the nav bars on
442 you must call this function.
443 ****************************************************************************/
444 void wxHtmlAppletWindow::EnableNavBar()
446 m_NavBarEnabled
= true;
449 /****************************************************************************
451 This function is used to set the nav bar to a new nav bar if you deleted the
452 one that you were useing. Usally this happens when you toggle a nav bar
454 ****************************************************************************/
455 void wxHtmlAppletWindow::SetNavBar(wxToolBarBase
*navBar
)
460 /****************************************************************************
462 msg - wxEvent message to be sent to all wxApplets
465 This function is called by the wxApplet's when they need to send a message
466 to all other applets on the current page. This is the primary form of
467 communication between applets on the page if they need to inform each
468 other of internal information.
470 ****************************************************************************/
471 void wxHtmlAppletWindow::SendAppletMessage(
474 // TODO: make a named target for messages, only send a message to the correct
477 // Process all applets in turn and send them the message
478 for (wxAppletList::Node
*node
= m_AppletList
.GetFirst(); node
; node
= node
->GetNext()) {
479 (node
->GetData())->OnMessage(msg
);
483 /****************************************************************************
485 name - Uniq wxString used as hash key
486 cookie - wxObject data returned when name is found.
489 True if new cookie was added, false if cookie with same name already exists.
492 This function is called by the wxApplet's when they need register a cookie
493 of data in the applet window's cookie table. Cookies are arbitrary data
494 objects that are references by unique name's by the wxApplet. These
495 values can be used to store and retrieve data that needs to remain
496 persisent across invocations of the wxApplet. Ie: The first time an
497 applet is created it would use the cookie to store data to maintain
498 it's present state so that if you navigated back to the same page
499 is would be able to re-load the prior state as though the applet
500 was never actually destructed.
502 Note: If a cookie with the same name already exists, this function returns
503 false. Hence if you wish to replace a cookie you should first call
504 UnRegisterCookie to ensure the cookie is deleted and then call this
506 ****************************************************************************/
507 bool wxHtmlAppletWindow::RegisterCookie(
508 const wxString
& name
,
511 // Fail if the named cookie already exists!
512 if (m_Cookies
.Get(name
))
514 m_Cookies
.Put(name
,cookie
);
518 /****************************************************************************
520 name - wxString uniq haskey used to remove item from hash
523 True if found and deleted, false if not found in table.
526 This function is called by the wxApplet's when they need de-register a
527 cookie of data in the applet window's cookie table. The data in the
528 cookie itself is also deleted before it is removed from the table.
529 ****************************************************************************/
530 bool wxHtmlAppletWindow::UnRegisterCookie(
531 const wxString
& name
)
533 wxObject
*data
= m_Cookies
.Delete(name
);
541 /****************************************************************************
543 msg - wxEvent message to be sent to all wxApplets
546 Pointer to the cookie data if found, NULL if not found.
549 This function is called by the wxApplet's when they need to find a cookie
550 of data given it's public name. If the cookie is not found, NULL is
552 ****************************************************************************/
553 wxObject
*wxHtmlAppletWindow::FindCookie(
554 const wxString
& name
)
556 return m_Cookies
.Get(name
);
559 /****************************************************************************
561 event - Event to handle
564 This function handles delayed LoadPage events posted from applets that
565 need to change the page for the current window to a new window.
566 ****************************************************************************/
567 void wxHtmlAppletWindow::OnLoadPage(
568 wxLoadPageEvent
&event
)
570 // Test the mutex lock.
573 if (event
.GetHtmlWindow() == this) {
574 if (LoadPage(event
.GetHRef())) {
575 // wxPageLoadedEvent evt;
576 // NOTE: This is reserved for later use as we might need to send
577 // page loaded events to applets.
584 /****************************************************************************
586 event - Event to handle
589 This function handles delayed LoadPage events posted from applets that
590 need to change the page for the current window to a new window.
591 ****************************************************************************/
592 void wxHtmlAppletWindow::OnPageLoaded(
598 /****************************************************************************
603 This function tries to lock the mutex. If it can't, returns
604 immediately with false.
605 ***************************************************************************/
606 bool wxHtmlAppletWindow::TryLock()
615 /****************************************************************************
617 name - name of the last applet that changed the data in this object
618 group - name of the group the allplet belongs to.
619 href - webpage to go to.
622 VirtualData is used to store information on the virtual links.
623 ****************************************************************************/
624 VirtualData::VirtualData(
636 /****************************************************************************
639 VirtualData is used to store information on the virtual links.
640 ****************************************************************************/
641 VirtualData::VirtualData()
648 #include "wx/html/m_templ.h"
650 /****************************************************************************
652 Implementation for the <embed> HTML tag handler. This handler takes care
653 of automatically constructing the wxApplet objects of the appropriate
654 class based on the <embed> tag information.
655 ****************************************************************************/
656 TAG_HANDLER_BEGIN(wxApplet
, "WXAPPLET")
658 TAG_HANDLER_PROC(tag
)
661 wxHtmlAppletWindow
*appletWindow
;
667 // Get access to our wxHtmlAppletWindow class
668 wnd
= m_WParser
->GetWindow();
669 if ((appletWindow
= wxDynamicCast(wnd
,wxHtmlAppletWindow
)) == NULL
)
672 // Parse the applet dimensions from the tag
673 wxSize size
= wxDefaultSize
;
675 if (tag
.HasParam("WIDTH")) {
676 tag
.GetParamAsInt("WIDTH", &width
);
677 size
.SetWidth(width
);
679 if (tag
.HasParam("HEIGHT")) {
680 tag
.GetParamAsInt("HEIGHT", &height
);
681 size
.SetHeight(height
);
684 // Parse the applet alignment from the tag
685 al
= wxHTML_ALIGN_BOTTOM
;
686 if (tag
.HasParam(wxT("ALIGN"))) {
687 wxString alstr
= tag
.GetParam(wxT("ALIGN"));
688 alstr
.MakeUpper(); // for the case alignment was in ".."
689 if (alstr
== wxT("TEXTTOP") || alstr
== wxT("TOP"))
690 al
= wxHTML_ALIGN_TOP
;
691 else if ((alstr
== wxT("CENTER")) || (alstr
== wxT("ABSCENTER")))
692 al
= wxHTML_ALIGN_CENTER
;
695 // Create the applet based on it's class
696 if (tag
.HasParam("CLASSID")) {
697 classId
= tag
.GetParam("CLASSID");
698 if (classId
.IsNull() || classId
.Len() == 0) {
699 wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR
);
702 if (tag
.HasParam("NAME"))
703 name
= tag
.GetParam("NAME");
705 // If the name is NULL or len is zero then we assume that the html guy
706 // didn't include the name param which is optional.
707 if (name
.IsNull() || name
.Len() == 0)
710 // We got all the params and can now create the applet
711 if ((applet
= appletWindow
->CreateApplet(classId
, name
, tag
, size
)) != NULL
) {
713 m_WParser
->OpenContainer()->InsertCell(new wxHtmlAppletCell(applet
,al
));
716 wxMessageBox("wxApplet error: Could not create:" + classId
+ "," + name
);
719 wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR
);
723 // Add more param parsing here. If or when spec changes.
724 // For now we'll ignore any other params those HTML guys
725 // might put in our tag.
729 TAG_HANDLER_END(wxApplet
)
731 TAGS_MODULE_BEGIN(wxApplet
)
732 TAGS_MODULE_ADD(wxApplet
)
733 TAGS_MODULE_END(wxApplet
)
735 /****************************************************************************
737 Constructor for the HTML cell class to store our wxApplet windows in
738 the HTML page to be rendered by wxHTML.
739 ****************************************************************************/
740 wxHtmlAppletCell::wxHtmlAppletCell(
747 m_Wnd
->GetSize(&sx
, &sy
);
748 m_Width
= sx
, m_Height
= sy
;
750 case wxHTML_ALIGN_TOP
:
751 m_Descent
= m_Height
;
753 case wxHTML_ALIGN_CENTER
:
754 m_Descent
= m_Height
/ 2;
756 case wxHTML_ALIGN_BOTTOM
:
761 SetCanLiveOnPagebreak(FALSE
);
764 /****************************************************************************
766 Implementation for the HTML cell class to store our wxApplet windows in
767 the HTML page to be rendered by wxHTML.
768 ****************************************************************************/
769 wxHtmlAppletCell::~wxHtmlAppletCell()
774 /****************************************************************************
776 Code to draw the html applet cell
777 ****************************************************************************/
778 void wxHtmlAppletCell::Draw(
782 int WXUNUSED(view_y1
),
783 int WXUNUSED(view_y2
))
785 int absx
= 0, absy
= 0, stx
, sty
;
786 wxHtmlCell
*c
= this;
789 absx
+= c
->GetPosX();
790 absy
+= c
->GetPosY();
793 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
);
794 m_Wnd
->Move(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
);
797 /****************************************************************************
799 Code to draw the html applet cell invisibly
800 ****************************************************************************/
801 void wxHtmlAppletCell::DrawInvisible(
806 int absx
= 0, absy
= 0, stx
, sty
;
807 wxHtmlCell
*c
= this;
810 absx
+= c
->GetPosX();
811 absy
+= c
->GetPosY();
814 ((wxScrolledWindow
*)(m_Wnd
->GetParent()))->GetViewStart(&stx
, &sty
);
815 m_Wnd
->Move(absx
- wxHTML_SCROLL_STEP
* stx
, absy
- wxHTML_SCROLL_STEP
* sty
);
818 /****************************************************************************
820 Code to layout the html applet cell.
821 ****************************************************************************/
822 void wxHtmlAppletCell::Layout(
826 m_Wnd
->GetSize(&sx
, &sy
);
827 m_Width
= sx
, m_Height
= sy
;
828 wxHtmlCell::Layout(w
);
831 // This is our little forcelink hack.