RetroZilla/embedding/browser/powerplant/source/CIconServicesIcon.cpp
2015-10-20 23:03:22 -04:00

249 lines
7.4 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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/MPL/
*
* 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 the Mozilla browser.
*
* The Initial Developer of the Original Code is
* Netscape Communications, Inc.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Conrad Carlen <ccarlen@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CIconServicesIcon.h"
#include "UResourceMgr.h"
#include "UMemoryMgr.h"
#include <Processes.h>
//*****************************************************************************
// CIconServicesIcon
//*****************************************************************************
OSType CIconServicesIcon::mgAppCreator;
FSSpec CIconServicesIcon::mgIconFileSpec;
CIconServicesIcon::CIconServicesIcon(const SPaneInfo& inPaneInfo,
MessageT inValueMessage,
OSType inIconType,
SInt16 inIconResID) :
LControl(inPaneInfo, inValueMessage),
mIconType(inIconType), mIconResID(inIconResID),
mAlignmentType(kAlignAbsoluteCenter), mIconRef(nil),
mbIsPressed(false)
{
Init();
}
CIconServicesIcon::CIconServicesIcon(LStream* inStream) :
LControl(inStream),
mAlignmentType(kAlignAbsoluteCenter), mIconRef(nil),
mbIsPressed(false)
{
*inStream >> mIconType;
*inStream >> mIconResID;
Init();
}
CIconServicesIcon::~CIconServicesIcon()
{
ReleaseIconRef();
}
void CIconServicesIcon::DrawSelf()
{
if (!mIconRef)
return;
Rect iconRect;
CalcLocalFrameRect(iconRect);
AdjustIconRect(iconRect);
IconTransformType transform;
if (mbIsPressed)
transform = kTransformSelected;
else if (mEnabled != triState_On)
transform = kTransformDisabled;
else
transform = kTransformNone;
// Because the icon may be translucent, clear out the
// region under it. The icon will draw differently
// depending on the background. This makes it consistent.
StRegion cleanRgn;
if (::IconRefToRgn(cleanRgn,
&iconRect,
mAlignmentType,
kIconServicesNormalUsageFlag,
mIconRef) == noErr)
::EraseRgn(cleanRgn);
::PlotIconRef(&iconRect,
mAlignmentType,
transform,
kIconServicesNormalUsageFlag,
mIconRef);
}
void CIconServicesIcon::EnableSelf()
{
Refresh();
}
void CIconServicesIcon::DisableSelf()
{
Refresh();
}
SInt16 CIconServicesIcon::FindHotSpot(Point inPoint) const
{
Boolean inHotSpot = PointInHotSpot(inPoint, 0);
return inHotSpot ? 1 : 0;
}
Boolean CIconServicesIcon::PointInHotSpot(Point inPoint,
SInt16 inHotSpot) const
{
if (!mIconRef)
return false;
Rect iconRect;
CalcLocalFrameRect(iconRect);
AdjustIconRect(iconRect);
return ::PtInIconRef(&inPoint, &iconRect, mAlignmentType, kIconServicesNormalUsageFlag, mIconRef);
}
void CIconServicesIcon::HotSpotAction(SInt16 /* inHotSpot */,
Boolean inCurrInside,
Boolean inPrevInside)
{
if (inCurrInside != inPrevInside)
{
mbIsPressed = inCurrInside;
Draw(nil);
}
}
void CIconServicesIcon::HotSpotResult(SInt16 /* inHotSpot */)
{
BroadcastValueMessage();
}
void CIconServicesIcon::Init()
{
static bool gInitialized;
if (!gInitialized)
{
OSErr err;
// Since this a part of mozilla, which requires System 8.6,
// we can be sure of having this. Just in case...
long response;
err = ::Gestalt(gestaltIconUtilitiesAttr, &response);
ThrowIfError_(err);
if (!(response & gestaltIconUtilitiesHasIconServices))
Throw_(-12345);
ProcessSerialNumber psn;
err = ::GetCurrentProcess(&psn);
ThrowIfError_(err);
ProcessInfoRec info;
info.processInfoLength = sizeof(info);
info.processName = nil;
info.processAppSpec = nil;
err = ::GetProcessInformation(&psn, &info);
ThrowIfError_(err);
mgAppCreator = info.processSignature;
// RegisterIconRefFromResource() needs to be given an FSSpec of
// the file containing the 'icns' resource of the icon being
// registered. The following will track down the file no matter
// how our application is packaged.
StResLoad resLoadState(false);
StResource resHandle('icns', mIconResID); // throws if N/A
SInt16 resRefNum = ::HomeResFile(resHandle);
if (resRefNum != -1)
{
FCBPBRec pb;
pb.ioNamePtr = mgIconFileSpec.name;
pb.ioVRefNum = 0;
pb.ioRefNum = resRefNum;
pb.ioFCBIndx = 0;
err = PBGetFCBInfoSync(&pb);
if (err == noErr)
{
mgIconFileSpec.vRefNum = pb.ioFCBVRefNum;
mgIconFileSpec.parID = pb.ioFCBParID;
}
}
gInitialized = true;
}
GetIconRef();
}
void CIconServicesIcon::AdjustIconRect(Rect& ioRect) const
{
SDimension16 frameSize;
GetFrameSize(frameSize);
SInt16 iconSize = (frameSize.width <= 16 && frameSize.height <= 16) ? 16 : 32;
ioRect.top += ((ioRect.bottom - ioRect.top) - iconSize) / 2;
ioRect.left += ((ioRect.right - ioRect.left) - iconSize) / 2;
ioRect.right = ioRect.left + iconSize;
ioRect.bottom = ioRect.top + iconSize;
}
void CIconServicesIcon::GetIconRef()
{
// We would like to first see if the icon is already registered
// But, for some reason, the following call always returns noErr and the wrong icon.
// err = ::GetIconRef(mgIconFileSpec.vRefNum, mgAppCreator, mIconType, &iconRef);
// if (err != noErr)
::RegisterIconRefFromResource(mgAppCreator, mIconType, &mgIconFileSpec, mIconResID, &mIconRef);
}
void CIconServicesIcon::ReleaseIconRef()
{
if (mIconRef)
{
::ReleaseIconRef(mIconRef);
mIconRef = nil;
}
}