Back to index

lightning-sunbird  0.9+nobinonly
CIconServicesIcon.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Conrad Carlen <ccarlen@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039  
00040 #include "CIconServicesIcon.h"
00041 
00042 #include "UResourceMgr.h"
00043 #include "UMemoryMgr.h"
00044 
00045 #include <Processes.h>
00046 
00047 //*****************************************************************************
00048 // CIconServicesIcon
00049 //*****************************************************************************   
00050 
00051 OSType CIconServicesIcon::mgAppCreator;
00052 FSSpec CIconServicesIcon::mgIconFileSpec;
00053 
00054 CIconServicesIcon::CIconServicesIcon(const SPaneInfo&   inPaneInfo,
00055                                         MessageT               inValueMessage,
00056                                      OSType             inIconType,
00057                                      SInt16             inIconResID) :
00058     LControl(inPaneInfo, inValueMessage),
00059     mIconType(inIconType), mIconResID(inIconResID),
00060     mAlignmentType(kAlignAbsoluteCenter), mIconRef(nil),
00061     mbIsPressed(false)
00062 {
00063     Init();
00064 }
00065 
00066 
00067 CIconServicesIcon::CIconServicesIcon(LStream*    inStream) :
00068     LControl(inStream),
00069     mAlignmentType(kAlignAbsoluteCenter), mIconRef(nil),
00070     mbIsPressed(false)
00071 {
00072     *inStream >> mIconType;
00073     *inStream >> mIconResID;
00074     
00075     Init();
00076 }
00077 
00078 
00079 CIconServicesIcon::~CIconServicesIcon()
00080 {
00081     ReleaseIconRef();
00082 }
00083 
00084 void CIconServicesIcon::DrawSelf()
00085 {
00086   if (!mIconRef)
00087     return;
00088     
00089        Rect   iconRect;
00090        CalcLocalFrameRect(iconRect);
00091     AdjustIconRect(iconRect);
00092        
00093        IconTransformType transform;
00094        if (mbIsPressed)
00095            transform = kTransformSelected;
00096        else if (mEnabled != triState_On)
00097            transform = kTransformDisabled;
00098        else
00099            transform = kTransformNone;
00100        
00101        // Because the icon may be translucent, clear out the
00102        // region under it. The icon will draw differently
00103        // depending on the background. This makes it consistent.
00104        StRegion cleanRgn;
00105        if (::IconRefToRgn(cleanRgn,
00106                           &iconRect,
00107                           mAlignmentType,
00108                           kIconServicesNormalUsageFlag,
00109                        mIconRef) == noErr)
00110         ::EraseRgn(cleanRgn);
00111     
00112     ::PlotIconRef(&iconRect,
00113                   mAlignmentType,
00114                   transform,
00115                   kIconServicesNormalUsageFlag,
00116                   mIconRef);
00117 }
00118 
00119 void CIconServicesIcon::EnableSelf()
00120 {
00121     Refresh();
00122 }
00123 
00124 void CIconServicesIcon::DisableSelf()
00125 {
00126     Refresh();
00127 }
00128 
00129 SInt16 CIconServicesIcon::FindHotSpot(Point      inPoint) const
00130 {
00131          Boolean inHotSpot = PointInHotSpot(inPoint, 0);
00132          return inHotSpot ? 1 : 0;
00133 }
00134 
00135 Boolean CIconServicesIcon::PointInHotSpot(Point         inPoint,
00136                                                                   SInt16     inHotSpot) const
00137 {
00138   if (!mIconRef)
00139     return false;
00140     
00141        Rect   iconRect;
00142        CalcLocalFrameRect(iconRect);
00143     AdjustIconRect(iconRect);
00144 
00145     return ::PtInIconRef(&inPoint, &iconRect, mAlignmentType, kIconServicesNormalUsageFlag, mIconRef);
00146 }
00147 
00148 void CIconServicesIcon::HotSpotAction(SInt16            /* inHotSpot */,
00149                                          Boolean        inCurrInside,
00150                                          Boolean        inPrevInside)
00151 {
00152        if (inCurrInside != inPrevInside)
00153        {
00154            mbIsPressed = inCurrInside;
00155            Draw(nil);       
00156     }
00157 }
00158 
00159 void CIconServicesIcon::HotSpotResult(SInt16     /* inHotSpot */)
00160 {
00161        BroadcastValueMessage();
00162 }
00163 
00164 void CIconServicesIcon::Init()
00165 {
00166     static bool gInitialized;
00167     
00168     if (!gInitialized)
00169     {
00170         OSErr err;
00171         
00172         // Since this a part of mozilla, which requires System 8.6,
00173         // we can be sure of having this. Just in case...
00174         long response;
00175         err = ::Gestalt(gestaltIconUtilitiesAttr, &response);
00176         ThrowIfError_(err);
00177         if (!(response & gestaltIconUtilitiesHasIconServices))
00178             Throw_(-12345);
00179         
00180         ProcessSerialNumber psn;
00181         err = ::GetCurrentProcess(&psn);
00182         ThrowIfError_(err);
00183         
00184         ProcessInfoRec info;
00185         info.processInfoLength = sizeof(info);
00186         info.processName = nil;
00187         info.processAppSpec = nil;
00188         err = ::GetProcessInformation(&psn, &info);
00189         ThrowIfError_(err);
00190         mgAppCreator = info.processSignature;
00191         
00192         // RegisterIconRefFromResource() needs to be given an FSSpec of
00193         // the file containing the 'icns' resource of the icon being
00194         // registered. The following will track down the file no matter
00195         // how our application is packaged.
00196         
00197         StResLoad resLoadState(false);
00198         StResource resHandle('icns', mIconResID); // throws if N/A
00199         SInt16 resRefNum = ::HomeResFile(resHandle);
00200         if (resRefNum != -1)
00201         {
00202           FCBPBRec pb;
00203       
00204           pb.ioNamePtr = mgIconFileSpec.name;
00205           pb.ioVRefNum = 0;
00206           pb.ioRefNum = resRefNum;
00207           pb.ioFCBIndx = 0;
00208           err = PBGetFCBInfoSync(&pb);
00209           if (err == noErr)
00210           {
00211               mgIconFileSpec.vRefNum = pb.ioFCBVRefNum;
00212               mgIconFileSpec.parID = pb.ioFCBParID;
00213           }
00214         }
00215         gInitialized = true;
00216     }
00217     GetIconRef();
00218 }
00219 
00220 void CIconServicesIcon::AdjustIconRect(Rect& ioRect) const
00221 {
00222     SDimension16 frameSize;
00223     GetFrameSize(frameSize);
00224     SInt16 iconSize = (frameSize.width <= 16 && frameSize.height <= 16) ? 16 : 32;
00225     
00226        ioRect.top += ((ioRect.bottom - ioRect.top) - iconSize) / 2;
00227        ioRect.left += ((ioRect.right - ioRect.left) - iconSize) / 2;
00228     ioRect.right = ioRect.left + iconSize;
00229     ioRect.bottom = ioRect.top + iconSize;
00230 }
00231        
00232 void CIconServicesIcon::GetIconRef()
00233 {
00234     // We would like to first see if the icon is already registered
00235     // But, for some reason, the following call always returns noErr and the wrong icon.
00236     // err = ::GetIconRef(mgIconFileSpec.vRefNum, mgAppCreator, mIconType, &iconRef);    
00237     // if (err != noErr)
00238     ::RegisterIconRefFromResource(mgAppCreator, mIconType, &mgIconFileSpec, mIconResID, &mIconRef);
00239 }
00240 
00241 void CIconServicesIcon::ReleaseIconRef()
00242 {
00243     if (mIconRef)
00244     {
00245         ::ReleaseIconRef(mIconRef);
00246         mIconRef = nil;
00247     }
00248 }