Back to index

lightning-sunbird  0.9+nobinonly
UDownloadDisplay.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Conrad Carlen <ccarlen@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "UDownloadDisplay.h"
00040 #include "ApplIDs.h"
00041 #include "CIconServicesIcon.h"
00042 
00043 // Gecko
00044 #include "nsString.h"
00045 #include "nsILocalFileMac.h"
00046 
00047 // Std
00048 #include <algorithm>
00049 using namespace std;
00050 
00051 // PowerPlant
00052 #include <LStaticText.h>
00053 #include <LProgressBar.h>
00054 
00055 //*****************************************************************************
00056 // CMultiDownloadProgress
00057 //*****************************************************************************
00058 #pragma mark [CMultiDownloadProgress]
00059 
00060 bool CMultiDownloadProgress::sRegisteredViewClasses = false;
00061 
00062 CMultiDownloadProgress::CMultiDownloadProgress() :
00063     mWindow(nil)
00064 {
00065     if (!sRegisteredViewClasses) {
00066         RegisterClass_(CMultiDownloadProgressWindow);
00067         RegisterClass_(CDownloadProgressView);
00068         RegisterClass_(CIconServicesIcon);
00069         sRegisteredViewClasses = true;
00070     }
00071 }
00072 
00073 CMultiDownloadProgress::~CMultiDownloadProgress()
00074 {
00075 }
00076     
00077 void CMultiDownloadProgress::AddDownloadItem(CDownload *aDownloadItem)
00078 {
00079     if (!mWindow) {
00080         mWindow = static_cast<CMultiDownloadProgressWindow*>
00081             (LWindow::CreateWindow(wind_DownloadProgress, this));
00082         ThrowIfNil_(mWindow);
00083         
00084         // Add this as a listener to the window so we can know when it's destroyed.
00085         mWindow->AddListener(this);
00086     }
00087     
00088     // Create the view...
00089     LView::SetDefaultView(mWindow);
00090     LCommander::SetDefaultCommander(mWindow);
00091     LAttachable::SetDefaultAttachable(nil);
00092 
00093     CDownloadProgressView *itemView = static_cast<CDownloadProgressView*>
00094         (UReanimator::ReadObjects(ResType_PPob, view_DownloadProgressItem));
00095     ThrowIfNil_(itemView);
00096     
00097     // and add it to the window.
00098     mWindow->AddDownloadView(itemView);
00099     itemView->SetDownload(aDownloadItem);
00100 }
00101 
00102 // This happens in response to the window being closed. Check for active
00103 // downloads and confirm stopping them if there are any. Returning false
00104 // will prevent the window from being closed.
00105 Boolean CMultiDownloadProgress::AllowSubRemoval(LCommander* inSub)
00106 {
00107     return (!mWindow || (inSub == mWindow && mWindow->ConfirmClose()));
00108 }
00109 
00110 // This happens in response to the app being quit. Check for active
00111 // downloads and confirm stopping them if there are any. Returning
00112 // false will prevent the app from quitting.
00113 Boolean CMultiDownloadProgress::AttemptQuitSelf(SInt32 inSaveOption)
00114 {
00115     return (!mWindow || mWindow->ConfirmClose());
00116 }
00117 
00118 void CMultiDownloadProgress::ListenToMessage(MessageT inMessage,
00119                                              void* ioParam)
00120 {
00121     if (inMessage == msg_BroadcasterDied &&
00122         (CMultiDownloadProgressWindow*)((LBroadcaster*)ioParam) == mWindow)
00123         mWindow = nil;
00124 }
00125 
00126 
00127 //*****************************************************************************
00128 // CMultiDownloadProgressWindow
00129 //*****************************************************************************
00130 #pragma mark -
00131 #pragma mark [CMultiDownloadProgressWindow]
00132 
00133 CMultiDownloadProgressWindow::CMultiDownloadProgressWindow() :
00134     mDownloadViewCount(0)
00135 {
00136     StartBroadcasting();
00137 }
00138 
00139 CMultiDownloadProgressWindow::CMultiDownloadProgressWindow(LStream* inStream) :
00140     LWindow(inStream),
00141     mDownloadViewCount(0)
00142 {
00143     StartBroadcasting();
00144 }
00145                             
00146 CMultiDownloadProgressWindow::~CMultiDownloadProgressWindow()
00147 {
00148 }
00149 
00150 void CMultiDownloadProgressWindow::AddDownloadView(CDownloadProgressView *aView)
00151 {
00152     const SInt16 kSeparatorHeight = 3;
00153     
00154     SDimension16 currSize;
00155     GetFrameSize(currSize);
00156     
00157     SDimension16 viewSize;
00158     aView->GetFrameSize(viewSize);
00159     ResizeWindowTo(currSize.width,  (viewSize.height * (mDownloadViewCount + 1)) - kSeparatorHeight);
00160     
00161     aView->PlaceInSuperFrameAt(0, viewSize.height * mDownloadViewCount++, false);
00162     aView->FinishCreate();
00163 }
00164 
00165 void CMultiDownloadProgressWindow::RemoveDownloadView(CDownloadProgressView *aView)
00166 {
00167     // We can't remove the last view, leaving an empty window frame
00168     if (mDownloadViewCount <= 1)
00169         return;
00170         
00171     SDimension16 removedPaneSize;
00172     aView->GetFrameSize(removedPaneSize);
00173     SPoint32 removedPaneLoc;
00174     aView->GetFrameLocation(removedPaneLoc);
00175     
00176     delete aView;
00177     RemoveSubPane(aView);
00178     mDownloadViewCount--;
00179 
00180     TArrayIterator<LPane*>  iterator(GetSubPanes());
00181     LPane   *subPane;
00182     while (iterator.Next(subPane)) {
00183         SPoint32 subPaneLoc;
00184         subPane->GetFrameLocation(subPaneLoc);
00185         if (subPaneLoc.v >= removedPaneLoc.v + removedPaneSize.height) {
00186             subPane->MoveBy(0, -removedPaneSize.height, true);
00187         }
00188     }
00189     ResizeWindowBy(0, -removedPaneSize.height);
00190 }
00191 
00192 Boolean CMultiDownloadProgressWindow::ConfirmClose()
00193 {
00194     Boolean canClose = true;
00195     SInt32 numActiveDownloads = 0;
00196 
00197     TArrayIterator<LPane*>  iterator(GetSubPanes());
00198     LPane   *subPane;
00199     while (iterator.Next(subPane)) {
00200         CDownloadProgressView *downloadView = dynamic_cast<CDownloadProgressView*>(subPane);
00201         if (downloadView && downloadView->IsActive())
00202             numActiveDownloads++;    
00203     }
00204     
00205     if (numActiveDownloads != 0) {
00206         short itemHit;
00207         AlertStdAlertParamRec pb;
00208 
00209         pb.movable = false;
00210         pb.helpButton = false;
00211         pb.filterProc = nil;
00212         pb.defaultText = (StringPtr) kAlertDefaultOKText;
00213         pb.cancelText = (StringPtr) kAlertDefaultCancelText;
00214         pb.otherText = nil;
00215         pb.defaultButton = kStdOkItemIndex;
00216         pb.cancelButton = kStdCancelItemIndex;
00217         pb.position = kWindowAlertPositionParentWindowScreen;
00218 
00219         LStr255 msgString(STRx_StdAlertStrings, str_ConfirmCloseDownloads);
00220         LStr255 explainString(STRx_StdAlertStrings, str_ConfirmCloseDownloadsExp);
00221         ::StandardAlert(kAlertStopAlert, msgString, explainString, &pb, &itemHit);
00222         if (itemHit != kAlertStdAlertOKButton)
00223             canClose = false;
00224     }
00225     return canClose;    
00226 }
00227 
00228 
00229 //*****************************************************************************
00230 // CDownloadProgressView
00231 //*****************************************************************************
00232 #pragma mark -
00233 #pragma mark [CDownloadProgressView]
00234 
00235 enum {
00236     paneID_ProgressBar      = 'Prog',
00237     paneID_CancelButton     = 'Cncl',
00238     paneID_OpenButton       = 'Open',
00239     paneID_RevealButton     = 'Rvel',
00240     paneID_CloseButton      = 'Clos',
00241     paneID_StatusText       = 'Stat',
00242     paneID_StatusLabel      = 'StLa',
00243     paneID_TimeRemText      = 'Time',
00244     paneID_TimeRemLabel     = 'TiLa',
00245     paneID_SrcURIText       = 'SURI',
00246     paneID_SrcURILabel      = 'SULa',
00247     paneID_DestFileText     = 'Dest',
00248     paneID_DestFileLabel    = 'DFLa'
00249 };
00250 
00251 CDownloadProgressView::CDownloadProgressView() :
00252     mDownloadActive(false)
00253 {
00254 }
00255 
00256 CDownloadProgressView::CDownloadProgressView(LStream* inStream) :
00257     LView(inStream),
00258     mDownloadActive(false)
00259 {
00260 }
00261                             
00262 CDownloadProgressView::~CDownloadProgressView()
00263 {
00264     if (mDownloadActive)
00265         CancelDownload();
00266         
00267     mDownload = nsnull;
00268 }
00269 
00270 void CDownloadProgressView::FinishCreateSelf()
00271 {
00272     mProgressBar = dynamic_cast<LProgressBar*>(FindPaneByID(paneID_ProgressBar));
00273     mCancelButton = dynamic_cast<LControl*>(FindPaneByID(paneID_CancelButton));
00274     mOpenButton = dynamic_cast<LControl*>(FindPaneByID(paneID_OpenButton));
00275     mRevealButton = dynamic_cast<LControl*>(FindPaneByID(paneID_RevealButton));
00276     mCloseButton = dynamic_cast<LControl*>(FindPaneByID(paneID_CloseButton));
00277     mStatusText = dynamic_cast<LStaticText*>(FindPaneByID(paneID_StatusText));
00278     mTimeRemainingText = dynamic_cast<LStaticText*>(FindPaneByID(paneID_TimeRemText));
00279     mSrcURIText = dynamic_cast<LStaticText*>(FindPaneByID(paneID_SrcURIText));
00280     mDestFileText = dynamic_cast<LStaticText*>(FindPaneByID(paneID_DestFileText));
00281 
00282     // The control value is set in terms of percent
00283     if (mProgressBar)
00284         mProgressBar->SetMaxValue(100);
00285         
00286     ControlFontStyleRec styleRec;
00287     
00288     if (CreateStyleRecFromThemeFont(kThemeSmallSystemFont, styleRec) == noErr) {
00289         if (mStatusText)
00290             mStatusText->SetFontStyle(styleRec);
00291         if (mTimeRemainingText)
00292             mTimeRemainingText->SetFontStyle(styleRec);
00293         if (mSrcURIText)
00294             mSrcURIText->SetFontStyle(styleRec);
00295         if (mDestFileText)
00296             mDestFileText->SetFontStyle(styleRec);    
00297     }
00298     if (CreateStyleRecFromThemeFont(kThemeSmallEmphasizedSystemFont, styleRec) == noErr) {
00299         
00300         ResIDT labelIDs [] = { paneID_StatusLabel,
00301                                paneID_TimeRemLabel,
00302                                paneID_SrcURILabel,
00303                                paneID_DestFileLabel };
00304                                  
00305         for (size_t i = 0; i < sizeof(labelIDs) / sizeof(labelIDs[0]); i++) {
00306             LStaticText *staticText = dynamic_cast<LStaticText*>(FindPaneByID(labelIDs[i]));
00307             if (staticText)
00308                 staticText->SetFontStyle(styleRec);
00309         }
00310     }
00311    
00312     UReanimator::LinkListenerToControls(this, this, view_DownloadProgressItem);
00313     StartListening();
00314 }
00315 
00316 
00317 Boolean CDownloadProgressView::ObeyCommand(CommandT inCommand,
00318                                            void *ioParam)
00319 {
00320 #pragma unused(ioParam)
00321 
00322     Boolean cmdHandled = false;
00323     nsCOMPtr<nsILocalFile> targetFile;
00324     
00325     switch (inCommand)
00326     {            
00327         case paneID_CancelButton:
00328         {
00329             CancelDownload();
00330             cmdHandled = true;
00331         }
00332         break;
00333         
00334         case paneID_OpenButton:
00335         {
00336             mDownload->GetTarget(getter_AddRefs(targetFile));
00337             if (targetFile)
00338                 targetFile->Launch();
00339         }
00340         break;
00341         
00342         case paneID_RevealButton:
00343         {
00344             mDownload->GetTarget(getter_AddRefs(targetFile));
00345             if (targetFile)
00346                 targetFile->Reveal();
00347         }
00348         break;
00349         
00350         case paneID_CloseButton:
00351         {
00352             LView *view = this, *superView;
00353             while ((superView = view->GetSuperView()) != nil)
00354                 view = superView;
00355             CMultiDownloadProgressWindow *multiWindow = dynamic_cast<CMultiDownloadProgressWindow*>(view);
00356             if (multiWindow)
00357                 multiWindow->RemoveDownloadView(this);
00358         }
00359         break;
00360 
00361     }
00362 
00363     return cmdHandled;
00364 }
00365 
00366 void CDownloadProgressView::ListenToMessage(MessageT inMessage,
00367                                             void* ioParam)
00368 {
00369     switch (inMessage) {
00370     
00371         case CDownload::msg_OnDLStart:
00372         {
00373             mDownloadActive = true;
00374             if (mCancelButton)
00375                 mCancelButton->Enable();
00376         }
00377         break;
00378 
00379         case CDownload::msg_OnDLComplete:
00380         {
00381             mDownloadActive = false;
00382             if (mCancelButton)
00383                 mCancelButton->Disable();
00384             if (mCloseButton)
00385                 mCloseButton->Enable();
00386 
00387             CDownload *download = reinterpret_cast<CDownload*>(ioParam);                    
00388             nsresult downloadStatus;
00389             download->GetStatus(downloadStatus);
00390             
00391             // When saving documents as plain text, we might not get any
00392             // progress change notifications in which to set the progress bar.
00393             // Now that the download is done, put the bar in a reasonable state.
00394             if (mProgressBar) {
00395                 mProgressBar->SetIndeterminateFlag(false, false);
00396                 if (NS_SUCCEEDED(downloadStatus))
00397                     mProgressBar->SetValue(mProgressBar->GetMaxValue());
00398                 else
00399                     mProgressBar->SetValue(0);
00400             }
00401             
00402             if (NS_SUCCEEDED(downloadStatus)) {
00403                 if (mOpenButton)
00404                     mOpenButton->Enable();
00405             }
00406             if (mRevealButton)
00407                 mRevealButton->Enable();
00408             if (mTimeRemainingText)
00409                 mTimeRemainingText->SetText(LStr255("\p"));
00410         }
00411         break;
00412 
00413         case CDownload::msg_OnDLProgressChange:
00414         {
00415             CDownload::MsgOnDLProgressChangeInfo *info =
00416                 static_cast<CDownload::MsgOnDLProgressChangeInfo*>(ioParam);
00417                             
00418             if (mProgressBar) {
00419                 PRInt32 percentComplete;
00420                 info->mBroadcaster->GetPercentComplete(&percentComplete);
00421                 if (percentComplete != -1 && mProgressBar->IsIndeterminate())
00422                     mProgressBar->SetIndeterminateFlag(false, false);
00423                 else if (percentComplete == -1 && !mProgressBar->IsIndeterminate())
00424                     mProgressBar->SetIndeterminateFlag(true, true);
00425                 
00426                 if (!mProgressBar->IsIndeterminate()) {
00427                     PRInt32 controlVal = min(100, max(0, percentComplete));
00428                     mProgressBar->SetValue(controlVal);
00429                 }
00430             }
00431             
00432             // Set the progress bar as often as we're called. Smooth movement is nice.
00433             // Limit the frequency at which the textual status is updated though.
00434             if (info->mCurProgress == info->mMaxProgress ||
00435                 ::TickCount() - mLastStatusUpdateTicks >= kStatusUpdateIntervalTicks) {
00436                 UpdateStatus(info);
00437                 mLastStatusUpdateTicks = ::TickCount();
00438             }
00439         }
00440         break;
00441                   
00442         default:
00443           ProcessCommand(inMessage, ioParam);
00444           break;
00445     }
00446 }
00447 
00448 void CDownloadProgressView::SetDownload(CDownload *aDownload)
00449 {
00450     mDownload = aDownload;
00451     if (!mDownload)
00452         return;
00453     
00454     mDownloadActive = true;
00455     mLastStatusUpdateTicks = ::TickCount();    
00456     aDownload->AddListener(this);
00457     
00458     nsresult rv;
00459     nsCAutoString tempStr;
00460     
00461     if (mSrcURIText) {
00462         nsCOMPtr<nsIURI> srcURI;
00463         aDownload->GetSource(getter_AddRefs(srcURI));
00464         if (srcURI) {
00465             rv = srcURI->GetSpec(tempStr);
00466             if (NS_SUCCEEDED(rv))
00467                 mSrcURIText->SetText(const_cast<Ptr>(PromiseFlatCString(tempStr).get()), tempStr.Length());    
00468         }
00469     }
00470     
00471     if (mDestFileText) {
00472         nsCOMPtr<nsILocalFile> destFile;
00473         aDownload->GetTarget(getter_AddRefs(destFile));
00474         if (destFile) {
00475             rv = destFile->GetNativePath(tempStr);
00476             if (NS_SUCCEEDED(rv))
00477                 mDestFileText->SetText(const_cast<Ptr>(PromiseFlatCString(tempStr).get()), tempStr.Length());    
00478         }
00479     }
00480     
00481     // At this point, make sure our window is showing.
00482     LWindow::FetchWindowObject(GetMacWindow())->Show();
00483 }
00484 
00485 void CDownloadProgressView::CancelDownload()
00486 {
00487     CDownload *download = dynamic_cast<CDownload*>(mDownload.get());
00488     download->Cancel();
00489 }
00490 
00491 Boolean CDownloadProgressView::IsActive()
00492 {
00493     return mDownloadActive;
00494 }
00495 
00496 void CDownloadProgressView::UpdateStatus(CDownload::MsgOnDLProgressChangeInfo *info)
00497 {    
00498     PRInt64 startTime;
00499     mDownload->GetStartTime(&startTime);
00500     PRInt32 elapsedSecs = (PR_Now() - startTime) / PR_USEC_PER_SEC;
00501     float bytesPerSec = info->mCurProgress / elapsedSecs;
00502 
00503     UInt8 startPos;
00504     LStr255 valueStr;
00505     
00506     if (mStatusText) {
00507         // "@1 of @2 (at @3/sec)"
00508         LStr255 formatStr(STRx_DownloadStatus, str_ProgressFormat);
00509         
00510         // Insert each item into the string individually in order to
00511         // allow certain elements to be omitted from the format.
00512         if ((startPos = formatStr.Find("\p@1")) != 0)
00513             formatStr.Replace(startPos, 2, FormatBytes(info->mCurProgress, valueStr));
00514         if ((startPos = formatStr.Find("\p@2")) != 0)
00515             formatStr.Replace(startPos, 2, FormatBytes(info->mMaxProgress, valueStr));
00516         if ((startPos = formatStr.Find("\p@3")) != 0)
00517             formatStr.Replace(startPos, 2, FormatBytes(bytesPerSec, valueStr));
00518             
00519         mStatusText->SetText(formatStr);
00520     }
00521     
00522     if (mTimeRemainingText) {
00523         PRInt32 secsRemaining = (PRInt32)(float(info->mMaxProgress - info->mCurProgress) / bytesPerSec + 0.5);
00524         mTimeRemainingText->SetText(FormatFuzzyTime(secsRemaining, valueStr));
00525     }
00526 }
00527 
00528 LStr255& CDownloadProgressView::FormatBytes(float inBytes, LStr255& ioString)
00529 {
00530     const float kOneThousand24 = 1024.0;
00531     char buf[256];
00532     
00533     if (inBytes < 0) {
00534         return (ioString = "???");
00535     }
00536     if (inBytes < kOneThousand24) {
00537         sprintf(buf, "%.1f Bytes", inBytes);
00538         return (ioString = buf);
00539     }
00540     inBytes /= kOneThousand24;
00541     if (inBytes < 1024) {
00542         sprintf(buf, "%.1f KB", inBytes);
00543         return (ioString = buf);
00544     }
00545     inBytes /= kOneThousand24;
00546     if (inBytes < 1024) {
00547         sprintf(buf, "%.1f MB", inBytes);
00548         return (ioString = buf);
00549     }
00550     inBytes /= kOneThousand24;
00551     sprintf(buf, "%.2f GB", inBytes);
00552     return (ioString = buf);
00553 }
00554 
00555 LStr255& CDownloadProgressView::FormatFuzzyTime(PRInt32 inSecs, LStr255& ioString)
00556 {
00557     char valueBuf[32];
00558 
00559     if (inSecs < 90) {
00560         if (inSecs < 7)
00561             ioString.Assign(STRx_DownloadStatus, str_About5Seconds);
00562         else if (inSecs < 13)
00563             ioString.Assign(STRx_DownloadStatus, str_About10Seconds);
00564         else if (inSecs < 60)
00565             ioString.Assign(STRx_DownloadStatus, str_LessThan1Minute);
00566         else
00567             ioString.Assign(STRx_DownloadStatus, str_About1Minute);
00568         return ioString;
00569     }
00570     inSecs = (inSecs + 30) / 60; // Round up so we don't say "About 1 minutes"
00571     if (inSecs < 60) {
00572         sprintf(valueBuf, "%d", inSecs);
00573         ioString.Assign(STRx_DownloadStatus, str_AboutNMinutes);
00574         ioString.Replace(ioString.Find("\p@1"), 2, LStr255(valueBuf));
00575         return ioString;
00576     }
00577     inSecs /= 60;
00578     if (inSecs == 1)
00579         ioString.Assign(STRx_DownloadStatus, str_About1Hour);
00580     else {
00581         sprintf(valueBuf, "%d", inSecs);
00582         ioString.Assign(STRx_DownloadStatus, str_AboutNHours);
00583         ioString.Replace(ioString.Find("\p@1"), 2, LStr255(valueBuf));
00584     }
00585     return ioString;
00586 }
00587 
00588 OSErr CDownloadProgressView::CreateStyleRecFromThemeFont(ThemeFontID inThemeID,
00589                                                          ControlFontStyleRec& outStyle)
00590 {
00591     Str255  themeFontName;
00592     SInt16  themeFontSize;
00593     Style   themeStyle;
00594     SInt16  themeFontNum;
00595 
00596     OSErr err = ::GetThemeFont(kThemeSmallSystemFont,
00597                                smSystemScript,
00598                                themeFontName,
00599                                &themeFontSize,
00600                                &themeStyle);
00601     if (err != noErr)
00602         return err;
00603             
00604     outStyle.flags   = kControlUseFontMask +
00605                       kControlUseFaceMask +
00606                       kControlUseSizeMask;
00607     
00608     ::GetFNum(themeFontName, &themeFontNum);
00609     outStyle.font    = themeFontNum;
00610     outStyle.size    = themeFontSize;
00611     outStyle.style   = themeStyle;
00612 
00613     return noErr;
00614 }
00615