diff --git a/webshell/public/nsIBrowserWindow.h b/webshell/public/nsIBrowserWindow.h new file mode 100644 index 00000000000..cf7a5fbcd77 --- /dev/null +++ b/webshell/public/nsIBrowserWindow.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#ifndef nsIBrowserWindow_h___ +#define nsIBrowserWindow_h___ + +#include "nsweb.h" +#include "nsISupports.h" + +class nsIFactory; + +#define NS_IBROWSER_WINDOW_IID \ + { 0xa6cf905c, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} + +#define NS_BROWSER_WINDOW_CID \ + { 0xa6cf905d, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} + +// Chrome mask +#define NS_CHROME_TOOL_BAR_ON 0x1 +#define NS_CHROME_STATUS_BAR_ON 0x2 + +/** + * API to a "browser window". A browser window contains a toolbar, a web shell + * and a status bar. The toolbar and status bar are optional and are + * controlled by the chrome API. + */ +class nsIBrowserWindow : public nsISupports { +public: + NS_IMETHOD Init(PRUint32 aChromeMask) = 0; + + NS_IMETHOD Show() = 0; + + NS_IMETHOD Hide() = 0; + + NS_IMETHOD ChangeChrome(PRUint32 aNewChromeMask) = 0; + + NS_IMETHOD GetChrome(PRUint32& aChromeMaskResult) = 0; + + // XXX minimize, maximize + // XXX event control: enable/disable window close box, stick to glass, modal +}; + +extern "C" NS_WEB nsresult +NS_NewBrowserWindowFactory(nsIFactory** aFactory); + +#endif /* nsIBrowserWindow_h___ */ diff --git a/webshell/public/nsIThrobber.h b/webshell/public/nsIThrobber.h new file mode 100644 index 00000000000..bdd1305e201 --- /dev/null +++ b/webshell/public/nsIThrobber.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#ifndef nsIThrobber_h___ +#define nsIThrobber_h___ + +#include "nsweb.h" +#include "nsISupports.h" + +class nsIFactory; +class nsIWidget; +class nsString; +struct nsRect; + +#define NS_ITHROBBER_IID \ + { 0xa6cf905e, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} + +#define NS_THROBBER_CID \ + { 0xa6cf905f, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} + +class nsIThrobber : public nsISupports { +public: + NS_IMETHOD Init(nsIWidget* aParent, const nsRect& aBounds) = 0; + NS_IMETHOD MoveTo(PRInt32 aX, PRInt32 aY) = 0; + NS_IMETHOD Show() = 0; + NS_IMETHOD Hide() = 0; + NS_IMETHOD Start() = 0; + NS_IMETHOD Stop() = 0; +}; + +extern "C" NS_WEB nsresult +NS_NewThrobberFactory(nsIFactory** aFactory); + +#endif /* nsIThrobber_h___ */ diff --git a/webshell/src/nsBrowserWindow.cpp b/webshell/src/nsBrowserWindow.cpp new file mode 100644 index 00000000000..4670a0dbff7 --- /dev/null +++ b/webshell/src/nsBrowserWindow.cpp @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsIBrowserWindow.h" +#include "nsIWebShell.h" +#include "nsIWidget.h" +#include "nsITextWidget.h" +#include "nsIButton.h" +#include "nsIImageGroup.h" +#include "nsITimer.h" +#include "nsVoidArray.h" +#include "nsIFactory.h" +#include "nsCRT.h" + +static NS_DEFINE_IID(kBrowserWindowCID, NS_BROWSER_WINDOW_CID); + +static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_IID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +class nsBrowserWindow : public nsIBrowserWindow { +public: + nsBrowserWindow(); + virtual ~nsBrowserWindow(); + + void* operator new(size_t sz) { + void* rv = new char[sz]; + nsCRT::zero(rv, sz); + return rv; + } + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIBrowserWindow + NS_IMETHOD Init(PRUint32 aChromeMask); + NS_IMETHOD Show(); + NS_IMETHOD Hide(); + NS_IMETHOD ChangeChrome(PRUint32 aNewChromeMask); + NS_IMETHOD GetChrome(PRUint32& aChromeMaskResult); + + // nsBrowserWindow + void StartThrobber(); + void StopThrobber(); + void LoadThrobberImages(); + void DestroyThrobberImages(); + +protected: + PRUint32 mChromeMask; + + // Web shell + nsIWebShell* mWebShell; + + // "Toolbar" + nsITextWidget* mLocation; + nsIButton* mBack; + nsIButton* mForward; + + // Status bar + +}; + +// Note: operator new zeros our memory +nsBrowserWindow::nsBrowserWindow() +{ +} + +nsBrowserWindow::~nsBrowserWindow() +{ +} + +NS_IMPL_ISUPPORTS(nsBrowserWindow, kIBrowserWindowIID) + +NS_IMETHODIMP +nsBrowserWindow::Init(PRUint32 aChromeMask) +{ + mChromeMask = aChromeMask; + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserWindow::Show() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserWindow::Hide() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserWindow::ChangeChrome(PRUint32 aChromeMask) +{ + mChromeMask = aChromeMask; + return NS_OK; +} + +NS_IMETHODIMP +nsBrowserWindow::GetChrome(PRUint32& aChromeMaskResult) +{ + aChromeMaskResult = mChromeMask; + return NS_OK; +} + +//---------------------------------------- + +// Toolbar support + +void +nsBrowserWindow::StartThrobber() +{ +} + +void +nsBrowserWindow::StopThrobber() +{ +} + +void +nsBrowserWindow::LoadThrobberImages() +{ +} + +void +nsBrowserWindow::DestroyThrobberImages() +{ +} + +//---------------------------------------------------------------------- + +// Factory code for creating nsBrowserWindow's + +class nsBrowserWindowFactory : public nsIFactory +{ +public: + nsBrowserWindowFactory(); + ~nsBrowserWindowFactory(); + + // nsISupports methods + NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + +private: + nsrefcnt mRefCnt; +}; + +nsBrowserWindowFactory::nsBrowserWindowFactory() +{ + mRefCnt = 0; +} + +nsBrowserWindowFactory::~nsBrowserWindowFactory() +{ + NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); +} + +nsresult +nsBrowserWindowFactory::QueryInterface(const nsIID &aIID, void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + // Always NULL result, in case of failure + *aResult = NULL; + + if (aIID.Equals(kISupportsIID)) { + *aResult = (void *)(nsISupports*)this; + } else if (aIID.Equals(kIFactoryIID)) { + *aResult = (void *)(nsIFactory*)this; + } + + if (*aResult == NULL) { + return NS_NOINTERFACE; + } + + AddRef(); // Increase reference count for caller + return NS_OK; +} + +nsrefcnt +nsBrowserWindowFactory::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +nsBrowserWindowFactory::Release() +{ + if (--mRefCnt == 0) { + delete this; + return 0; // Don't access mRefCnt after deleting! + } + return mRefCnt; +} + +nsresult +nsBrowserWindowFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + nsresult rv; + nsBrowserWindow *inst; + + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + *aResult = NULL; + if (nsnull != aOuter) { + rv = NS_ERROR_NO_AGGREGATION; + goto done; + } + + inst = new nsBrowserWindow(); + if (inst == NULL) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto done; + } + + NS_ADDREF(inst); + rv = inst->QueryInterface(aIID, aResult); + NS_RELEASE(inst); + +done: + return rv; +} + +nsresult +nsBrowserWindowFactory::LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +extern "C" NS_WEB nsresult +NS_NewBrowserWindowFactory(nsIFactory** aFactory) +{ + nsresult rv = NS_OK; + nsIFactory* inst = new nsBrowserWindowFactory(); + if (nsnull == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } + else { + NS_ADDREF(inst); + } + *aFactory = inst; + return rv; +} diff --git a/webshell/src/nsDLLFactory.cpp b/webshell/src/nsDLLFactory.cpp new file mode 100644 index 00000000000..4f94bd0db28 --- /dev/null +++ b/webshell/src/nsDLLFactory.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsIFactory.h" +#include "nsIBrowserWindow.h" +#include "nsIWebShell.h" +#include "nsIDocumentLoader.h" +#include "nsIThrobber.h" + +static NS_DEFINE_IID(kBrowserWindowCID, NS_BROWSER_WINDOW_CID); +static NS_DEFINE_IID(kDocumentLoaderCID, NS_DOCUMENTLOADER_CID); +static NS_DEFINE_IID(kThrobberCID, NS_THROBBER_CID); +static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); + +extern "C" NS_WEB nsresult +NSGetFactory(const nsCID& aClass, nsIFactory** aFactory) +{ + nsresult rv = NS_OK; + + if (nsnull == aFactory) { + return NS_ERROR_NULL_POINTER; + } + + if (aClass.Equals(kWebShellCID)) { + rv = NS_NewWebShellFactory(aFactory); + } + else if (aClass.Equals(kDocumentLoaderCID)) { + rv = NS_NewDocumentLoaderFactory(aFactory); + } + else if (aClass.Equals(kBrowserWindowCID)) { + rv = NS_NewBrowserWindowFactory(aFactory); + } + else if (aClass.Equals(kThrobberCID)) { + rv = NS_NewThrobberFactory(aFactory); + } + + return rv; +} diff --git a/webshell/src/nsThrobber.cpp b/webshell/src/nsThrobber.cpp new file mode 100644 index 00000000000..73706fbdd15 --- /dev/null +++ b/webshell/src/nsThrobber.cpp @@ -0,0 +1,534 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ +#include "nsIThrobber.h" +#include "nsIFactory.h" +#include "nsIWidget.h" +#include "nsVoidArray.h" +#include "nsITimer.h" +#include "nsIImageGroup.h" +#include "nsIImageObserver.h" +#include "nsIImageRequest.h" +#include "nsFont.h" +#include "nsIRenderingContext.h" +#include "nsIFontMetrics.h" +#include "nsRepository.h" +#include "nsWidgetsCID.h" +#include "nsCRT.h" +#include "prprf.h" + +static NS_DEFINE_IID(kChildCID, NS_CHILD_CID); +static NS_DEFINE_IID(kThrobberCID, NS_THROBBER_CID); + +static NS_DEFINE_IID(kIChildWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); +static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIThrobberIID, NS_ITHROBBER_IID); + +#define THROB_NUM 14 +#define THROBBER_AT "resource:/res/throbber/anims%02d.gif" + +static nsVoidArray gThrobbers; + +class nsThrobber : public nsIThrobber { +public: + nsThrobber(); + + void* operator new(size_t sz) { + void* rv = new char[sz]; + nsCRT::zero(rv, sz); + return rv; + } + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIThrobber + NS_IMETHOD Init(nsIWidget* aParent, const nsRect& aBounds); + NS_IMETHOD MoveTo(PRInt32 aX, PRInt32 aY); + NS_IMETHOD Show(); + NS_IMETHOD Hide(); + NS_IMETHOD Start(); + NS_IMETHOD Stop(); + + void Tick(); + + virtual ~nsThrobber(); + + nsresult LoadThrobberImages(); + + void DestroyThrobberImages(); + + PRInt32 mWidth; + PRInt32 mHeight; + nsIWidget* mWidget; + nsVoidArray* mImages; + PRInt32 mIndex; + nsIImageGroup* mImageGroup; + nsITimer* mTimer; + PRBool mRunning; +}; + +class ThrobObserver : public nsIImageRequestObserver { +public: + ThrobObserver(); + ~ThrobObserver(); + + NS_DECL_ISUPPORTS + + virtual void Notify(nsIImageRequest *aImageRequest, + nsIImage *aImage, + nsImageNotification aNotificationType, + PRInt32 aParam1, PRInt32 aParam2, + void *aParam3); + + virtual void NotifyError(nsIImageRequest *aImageRequest, + nsImageError aErrorType); +}; + +//---------------------------------------------------------------------- + +static nsThrobber* +FindThrobberFor(nsIWidget* aWidget) +{ + PRInt32 i, n = gThrobbers.Count(); + for (i = 0; i < n; i++) { + nsThrobber* th = (nsThrobber*) gThrobbers.ElementAt(i); + if (nsnull != th) { + if (th->mWidget == aWidget) { + return th; + } + } + } + return nsnull; +} + +static void +AddThrobber(nsThrobber* aThrobber) +{ + gThrobbers.AppendElement(aThrobber); +} + +static void +RemoveThrobber(nsThrobber* aThrobber) +{ + gThrobbers.RemoveElement(aThrobber); +} + +static nsEventStatus PR_CALLBACK +HandleThrobberEvent(nsGUIEvent *aEvent) +{ + nsThrobber* throbber = FindThrobberFor(aEvent->widget); + if (nsnull == throbber) { + return nsEventStatus_eIgnore; + } + + switch (aEvent->message) + { + case NS_PAINT: + { + nsPaintEvent *pe = (nsPaintEvent *)aEvent; + nsIRenderingContext *cx = pe->renderingContext; + nsRect bounds; + nsIImageRequest *imgreq; + nsIImage *img; + + pe->widget->GetBounds(bounds); + + cx->SetClipRect(*pe->rect, nsClipCombine_kReplace); + + cx->SetColor(NS_RGB(255, 255, 255)); + cx->DrawLine(0, bounds.height - 1, 0, 0); + cx->DrawLine(0, 0, bounds.width, 0); + + cx->SetColor(NS_RGB(128, 128, 128)); + cx->DrawLine(bounds.width - 1, 1, bounds.width - 1, bounds.height - 1); + cx->DrawLine(bounds.width - 1, bounds.height - 1, 0, bounds.height - 1); + + imgreq = (nsIImageRequest *) + throbber->mImages->ElementAt(throbber->mIndex); + + if ((nsnull == imgreq) || (nsnull == (img = imgreq->GetImage()))) + { + char str[10]; + nsFont tfont = nsFont("monospace", 0, 0, 0, 0, 10); + nsIFontMetrics *met; + nscoord w, h; + + cx->SetColor(NS_RGB(0, 0, 0)); + cx->FillRect(1, 1, bounds.width - 2, bounds.height - 2); + + PR_snprintf(str, sizeof(str), "%02d", throbber->mIndex); + + cx->SetColor(NS_RGB(255, 255, 255)); + cx->SetFont(tfont); + met = cx->GetFontMetrics(); + w = met->GetWidth(str[0]) + met->GetWidth(str[1]); + h = met->GetHeight(); + cx->DrawString(str, 2, (bounds.width - w) >> 1, (bounds.height - h) >> 1, 0); + } + else + { + cx->DrawImage(img, 1, 1); + NS_RELEASE(img); + } + + break; + } + + case NS_MOUSE_LEFT_BUTTON_UP: + // XXX wire up to API + //gTheViewer->GoTo(nsString("http://www.mozilla.org")); + break; + + case NS_MOUSE_ENTER: + aEvent->widget->SetCursor(eCursor_hyperlink); + break; + + case NS_MOUSE_EXIT: + aEvent->widget->SetCursor(eCursor_standard); + break; + } + + return nsEventStatus_eIgnore; +} + +//---------------------------------------------------------------------- + +// Note: operator new zeros our memory +nsThrobber::nsThrobber() +{ + AddThrobber(this); +} + +nsThrobber::~nsThrobber() +{ + RemoveThrobber(this); +} + +NS_IMPL_ISUPPORTS(nsThrobber, kIThrobberIID); + +NS_IMETHODIMP +nsThrobber::Init(nsIWidget* aParent, const nsRect& aBounds) +{ + mWidth = aBounds.width; + mHeight = aBounds.height; + + // Create widget + nsresult rv = NSRepository::CreateInstance(kChildCID, nsnull, + kIChildWidgetIID, + (void**)&mWidget); + if (NS_OK != rv) { + return rv; + } + + mWidget->Create(aParent, aBounds, HandleThrobberEvent, NULL); + + return LoadThrobberImages(); +} + +NS_IMETHODIMP +nsThrobber::MoveTo(PRInt32 aX, PRInt32 aY) +{ + NS_PRECONDITION(nsnull != mWidget, "no widget"); + mWidget->Resize(aX, aY, mWidth, mHeight, PR_TRUE); + return NS_OK; +} + +NS_IMETHODIMP +nsThrobber::Show() +{ + mWidget->Show(PR_TRUE); + return NS_OK; +} + +NS_IMETHODIMP +nsThrobber::Hide() +{ + mWidget->Show(PR_FALSE); + return NS_OK; +} + +NS_IMETHODIMP +nsThrobber::Start() +{ + mRunning = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP +nsThrobber::Stop() +{ + mRunning = PR_FALSE; + mIndex = 0; + nsRect trect;/* XXX why */ + mWidget->GetBounds(trect);/* XXX why */ + mWidget->Invalidate(PR_FALSE); + return NS_OK; +} + +//---------------------------------------- + +ThrobObserver::ThrobObserver() +{ + NS_INIT_REFCNT(); +} + +ThrobObserver::~ThrobObserver() +{ +} + +NS_IMPL_ISUPPORTS(ThrobObserver, kIImageObserverIID) + +void +ThrobObserver::Notify(nsIImageRequest *aImageRequest, + nsIImage *aImage, + nsImageNotification aNotificationType, + PRInt32 aParam1, PRInt32 aParam2, + void *aParam3) +{ +} + +void +ThrobObserver::NotifyError(nsIImageRequest *aImageRequest, + nsImageError aErrorType) +{ +} + +static void throb_timer_callback(nsITimer *aTimer, void *aClosure) +{ + nsThrobber* throbber = (nsThrobber*)aClosure; + throbber->Tick(); +} + +void +nsThrobber::Tick() +{ + if (mRunning) + { + nsRect trect; + mIndex++; + if (mIndex >= THROB_NUM) + mIndex = 0; + mWidget->GetBounds(trect); + mWidget->Invalidate(PR_TRUE); + } + + NS_RELEASE(mTimer); + + nsresult rv = NS_NewTimer(&mTimer); + if (NS_OK == rv) { + mTimer->Init(throb_timer_callback, this, 33); + } +} + +nsresult +nsThrobber::LoadThrobberImages() +{ + nsresult rv; + char url[2000]; + + mImages = new nsVoidArray(THROB_NUM); + if (nsnull == mImages) { + return NS_ERROR_OUT_OF_MEMORY; + } + rv = NS_NewImageGroup(&mImageGroup); + if (NS_OK != rv) { + return rv; + } + + nsIRenderingContext *drawCtx = mWidget->GetRenderingContext(); + mImageGroup->Init(drawCtx); + NS_RELEASE(drawCtx); + + rv = NS_NewTimer(&mTimer); + if (NS_OK != rv) { + return rv; + } + mTimer->Init(throb_timer_callback, this, 33); + + for (PRInt32 cnt = 0; cnt < THROB_NUM; cnt++) { + PR_snprintf(url, sizeof(url), THROBBER_AT, cnt); + ThrobObserver* observer = new ThrobObserver(); + nscolor bgcolor = NS_RGB(0, 0, 0); + mImages->InsertElementAt(mImageGroup->GetImage(url, + observer, + &bgcolor, + mWidth - 2, + mHeight - 2, 0), + cnt); + } + + return rv; +} + +void +nsThrobber::DestroyThrobberImages() +{ + if (nsnull != mImageGroup) + { + if (nsnull != mTimer) + { + mTimer->Cancel(); //XXX this should not be necessary. MMP + NS_RELEASE(mTimer); + } + + mImageGroup->Interrupt(); + for (PRInt32 cnt = 0; cnt < THROB_NUM; cnt++) + { + nsIImageRequest *imgreq; + imgreq = (nsIImageRequest *)mImages->ElementAt(cnt); + if (nsnull != imgreq) + { + NS_RELEASE(imgreq); + mImages->ReplaceElementAt(nsnull, cnt); + } + } + delete mImages; + } +} + +//---------------------------------------------------------------------- + +// Factory code for creating nsThrobber's + +class nsThrobberFactory : public nsIFactory +{ +public: + nsThrobberFactory(); + ~nsThrobberFactory(); + + // nsISupports methods + NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + +private: + nsrefcnt mRefCnt; +}; + +nsThrobberFactory::nsThrobberFactory() +{ + mRefCnt = 0; +} + +nsThrobberFactory::~nsThrobberFactory() +{ + NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); +} + +nsresult +nsThrobberFactory::QueryInterface(const nsIID &aIID, void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + // Always NULL result, in case of failure + *aResult = NULL; + + if (aIID.Equals(kISupportsIID)) { + *aResult = (void *)(nsISupports*)this; + } else if (aIID.Equals(kIFactoryIID)) { + *aResult = (void *)(nsIFactory*)this; + } + + if (*aResult == NULL) { + return NS_NOINTERFACE; + } + + AddRef(); // Increase reference count for caller + return NS_OK; +} + +nsrefcnt +nsThrobberFactory::AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt +nsThrobberFactory::Release() +{ + if (--mRefCnt == 0) { + delete this; + return 0; // Don't access mRefCnt after deleting! + } + return mRefCnt; +} + +nsresult +nsThrobberFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + nsresult rv; + nsThrobber *inst; + + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + *aResult = NULL; + if (nsnull != aOuter) { + rv = NS_ERROR_NO_AGGREGATION; + goto done; + } + + inst = new nsThrobber(); + if (inst == NULL) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto done; + } + + NS_ADDREF(inst); + rv = inst->QueryInterface(aIID, aResult); + NS_RELEASE(inst); + +done: + return rv; +} + +nsresult +nsThrobberFactory::LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +extern "C" NS_WEB nsresult +NS_NewThrobberFactory(nsIFactory** aFactory) +{ + nsresult rv = NS_OK; + nsIFactory* inst = new nsThrobberFactory(); + if (nsnull == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } + else { + NS_ADDREF(inst); + } + *aFactory = inst; + return rv; +}