gecko-dev/widget/src/nsImageButton.cpp
1999-01-28 05:06:06 +00:00

976 lines
29 KiB
C++

/* -*- 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 "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsImageButton.h"
#include "nsWidgetsCID.h"
#include "nspr.h"
#include "nsIButton.h"
#include "nsIFontMetrics.h"
#include "nsIDeviceContext.h"
#include "nsWidgetsCID.h"
#include "nsIAppShell.h"
#include "nsIWidget.h"
#include "nsITextWidget.h"
#include "nsIButton.h"
#include "nsIImageGroup.h"
#include "nsITimer.h"
#include "nsIThrobber.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kCImageButtonCID, NS_IMAGEBUTTON_CID);
static NS_DEFINE_IID(kCIImageButtonIID, NS_IIMAGEBUTTON_IID);
//static NS_DEFINE_IID(kCButtonCID, NS_BUTTON_CID);
//static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID);
static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID);
#define DEFAULT_WIDTH 50
#define DEFAULT_HEIGHT 50
NS_IMPL_ADDREF(nsImageButton)
NS_IMPL_RELEASE(nsImageButton)
//typedef enum {eAlignJustText, eAlignJustImage, eAlignBoth} eWhichAlignment;
const PRInt32 kAlignJustText = 0;
const PRInt32 kAlignJustImage = 1;
const PRInt32 kAlignBoth = 2;
//---------------------------------------------------------------
static nsEventStatus PR_CALLBACK
HandleImageButtonEvent(nsGUIEvent *aEvent)
{
nsEventStatus result = nsEventStatus_eIgnore;
nsIImageButton * button;
if (NS_OK == aEvent->widget->QueryInterface(kCIImageButtonIID,(void**)&button)) {
result = button->HandleEvent(aEvent);
NS_RELEASE(button);
}
return result;
}
//------------------------------------------------------------
nsImageButton::nsImageButton() : ChildWindow(), nsIImageButton(),
mFont("Sans",
NS_FONT_STYLE_NORMAL,
NS_FONT_VARIANT_NORMAL,
NS_FONT_WEIGHT_NORMAL,
0,
13)
{
NS_INIT_REFCNT();
mUpImageRequest = nsnull;
mPressedImageRequest = nsnull;
mDisabledImageRequest = nsnull;
mRollOverImageRequest = nsnull;
mState = eButtonState_up;
// From Canvas
mBackgroundColor = NS_RGB(192,192,192);
mForegroundColor = NS_RGB(0,0,0);
mHighlightColor = NS_RGB(255,255,255);
mShadowColor = NS_RGB(128,128,128);
mShowButtonBorder = PR_FALSE;
// XXX: We should probably auto-generate unique names here
mLabel = "Default Label";
mImageGroup = nsnull;
mImageRequest = nsnull;
mImageWidth = 32;
mImageHeight = 32;
mShowBorder = PR_TRUE;
mTextVAlignment = eButtonVerticalAligment_Bottom;
mTextHAlignment = eButtonHorizontalAligment_Middle;
mImageVAlignment = eButtonVerticalAligment_Top;
mImageHAlignment = eButtonHorizontalAligment_Middle;
mShowImage = PR_TRUE;
mShowText = PR_TRUE;
mAlwaysShowBorder = PR_FALSE;
mBorderWidth = 1;
mBorderOffset = 2;
mTextGap = 2;
mCommand = 0;
mLabel.SetLength(0);
mLabel.Append("Default");
mNumListeners = 0;
}
//------------------------------------------------------------
nsImageButton::~nsImageButton()
{
// XXX will be switching to a nsDeque
PRInt32 i;
for (i=0;i<mNumListeners;i++) {
NS_RELEASE(mListeners[i]);
}
}
//------------------------------------------------------------
NS_METHOD nsImageButton::Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData)
{
return ChildWindow::Create(aParent, aRect,
nsnull != aHandleEventFunction ? aHandleEventFunction:HandleImageButtonEvent,
aContext, aAppShell, aToolkit, aInitData);
}
//------------------------------------------------------------
nsresult nsImageButton::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kClassIID, kCImageButtonCID);
if (aIID.Equals(kCIImageButtonIID)) {
*aInstancePtr = (void*) (nsIImageButton *)this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kIImageObserverIID)) {
*aInstancePtr = (void*)(nsIImageRequestObserver*)this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kClassIID)) {
*aInstancePtr = (void*) (nsImageButton *)this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) (this);
AddRef();
return NS_OK;
}
return (nsWindow::QueryInterface(aIID, aInstancePtr));
}
//------------------------------------------------------------
nsresult nsImageButton::SetBounds(const nsRect &aBounds)
{
nsWindow::Invalidate(PR_FALSE);
return nsWindow::Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height, PR_FALSE);
}
//------------------------------------------------------------
nsIImageRequest * nsImageButton::GetImageForPainting()
{
nsIImageRequest * img;
if ((mState & eButtonState_pressed) && (mPressedImageRequest != nsnull))
img = mPressedImageRequest;
else if ((mState & eButtonState_rollover) && (mRollOverImageRequest != nsnull))
img = mRollOverImageRequest;
else if ((mState & eButtonState_disabled) && (mDisabledImageRequest != nsnull))
img = mDisabledImageRequest;
else if (mUpImageRequest != nsnull)
img = mUpImageRequest;
return img;
}
//------------------------------------------------------------
nsEventStatus nsImageButton::OnPaint(nsIRenderingContext& aRenderingContext,
const nsRect & aDirtyRect)
{
PushState(aRenderingContext);
nsRect bounds;
nsString label;
GetLabel(label);
GetBounds(bounds);
bounds.x = 0;
bounds.y = 0;
nsRect imgRect;
nsRect txtRect;
PRInt32 which;
PRInt32 width;
PRInt32 height;
nsIImageRequest * img = GetImageForPainting();
PerformAlignment(bounds, img, imgRect, label, txtRect, which, width, height);
PaintBackground(aRenderingContext, aDirtyRect, bounds, img, imgRect);
PaintForeground(aRenderingContext, aDirtyRect, bounds, label, txtRect);
if (mShowBorder || mAlwaysShowBorder) {
PaintBorder(aRenderingContext, aDirtyRect, bounds);
}
PopState(aRenderingContext);
return nsEventStatus_eConsumeNoDefault;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::PaintBackground(nsIRenderingContext& aRenderingContext,
const nsRect & aDirtyRect,
const nsRect & aEntireRect,
nsIImageRequest * anImage,
const nsRect & aRect)
{
aRenderingContext.SetColor(GetBackgroundColor());
aRenderingContext.FillRect(aEntireRect);
if (!mShowImage || anImage == nsnull) {
return nsEventStatus_eIgnore;
}
nsIImage * img = anImage->GetImage();
if (nsnull != img) {
aRenderingContext.DrawImage(img, aRect.x, aRect.y);
}
NS_IF_RELEASE(img);
return nsEventStatus_eIgnore;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::PaintForeground(nsIRenderingContext& aRenderingContext,
const nsRect & aDirtyRect,
const nsRect & aEntireRect,
const nsString & aLabel,
const nsRect & aRect)
{
if (!mShowText) {
return nsEventStatus_eConsumeNoDefault;
}
//if (mShowText == eShowText_none)
// return nsEventStatus_eConsumeNoDefault;
// XXX: We really need to query system-wide colors via gfx system manager here?
// On windows, the calls are:
//
// GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_GRAYTEXT), GetSysColor(COLOR_GRAYTEXT)
// Draw text based on justifications
if ((mState & eButtonState_rollover))
aRenderingContext.SetColor(NS_RGB(0,0,255));
else if (mState & eButtonState_disabled)
aRenderingContext.SetColor(NS_RGB(255, 255, 255));
else
aRenderingContext.SetColor(GetForegroundColor());
if (mState & eButtonState_disabled) {
aRenderingContext.DrawString(aLabel, aLabel.Length(), aRect.x+1, aRect.y+1);
aRenderingContext.SetColor(NS_RGB(128, 128, 128));
}
aRenderingContext.DrawString(aLabel, aLabel.Length(), aRect.x, aRect.y);
return nsEventStatus_eConsumeNoDefault;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::OnMouseMove(nsGUIEvent *aEvent)
{
return nsEventStatus_eIgnore;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::OnMouseEnter(nsGUIEvent *aEvent)
{
SetCursor(eCursor_standard);
mState |= eButtonState_rollover;
Invalidate(PR_FALSE);
return nsEventStatus_eIgnore;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::OnMouseExit(nsGUIEvent *aEvent)
{
mState &= ~eButtonState_rollover;
mState &= ~eButtonState_pressed;
Invalidate(PR_FALSE);
return nsEventStatus_eIgnore;//(nsWindow::OnMouseExit(aEvent));
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::OnLeftButtonDown(nsGUIEvent *aEvent)
{
mState |= eButtonState_pressed;
Invalidate(PR_FALSE);
return nsEventStatus_eIgnore;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::OnLeftButtonUp(nsGUIEvent *aEvent)
{
mState &= ~eButtonState_pressed;
Invalidate(PR_FALSE);
return nsEventStatus_eIgnore;
}
//-----------------------------------------------------------------------------
nsresult nsImageButton::CreateImageGroup()
{
nsresult res = NS_OK;
if (mImageGroup != nsnull)
return NS_OK;
res = NS_NewImageGroup(&mImageGroup);
if (NS_OK == res)
{
nsIDeviceContext * deviceCtx = GetDeviceContext();
mImageGroup->Init(deviceCtx, nsnull);
NS_RELEASE(deviceCtx);
}
return res;
}
//-----------------------------------------------------------------------------
nsIImageRequest * nsImageButton::RequestImage(nsString aUrl)
{
if (aUrl.Length() == 0) {
return nsnull;
}
char * url = aUrl.ToNewCString();
nsIImageRequest * request ;
nscolor bgcolor = GetBackgroundColor();
nsRect rect;
GetBounds(rect);
request = mImageGroup->GetImage(url,
(nsIImageRequestObserver *)this,
&bgcolor,
mImageWidth,
mImageHeight,
0);//nsImageLoadFlags_kSticky);
//request->GetNaturalDimensions(&mImageWidth, &mImageHeight);
delete url;
return request;
}
//-----------------------------------------------------------------------------
nsresult nsImageButton::PushState(nsIRenderingContext& aRenderingContext)
{
aRenderingContext.PushState();
aRenderingContext.SetFont(mFont);
return NS_OK;
}
//-----------------------------------------------------------------------------
PRBool nsImageButton::PopState(nsIRenderingContext& aRenderingContext)
{
PRBool clipState;
aRenderingContext.PopState(clipState);
return clipState;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::GetLabel(nsString & aString)
{
aString = mLabel;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::SetLabel(const nsString& aString)
{
mLabel = aString;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::GetRollOverDesc(nsString & aString)
{
aString = mRollOverDesc;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::SetRollOverDesc(const nsString& aString)
{
mRollOverDesc = aString;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::GetCommand(PRInt32 & aCommand)
{
aCommand = mCommand;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::SetCommand(PRInt32 aCommand)
{
mCommand = aCommand;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::GetHighlightColor(nscolor &aColor)
{
aColor = mHighlightColor;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::SetHighlightColor(const nscolor &aColor)
{
mHighlightColor = aColor;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::GetShadowColor(nscolor &aColor)
{
aColor = mShadowColor;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_METHOD nsImageButton::SetShadowColor(const nscolor &aColor)
{
mShadowColor = aColor;
return NS_OK;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::PaintBorder(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aEntireRect)
{
nsRect rect(aEntireRect);
if ((mState == eButtonState_up || (mState & eButtonState_disabled)) && !mAlwaysShowBorder) {
return nsEventStatus_eConsumeNoDefault;
}
rect.x = 0;
rect.y = 0;
rect.width--;
rect.height--;
if (mShowButtonBorder) {
aRenderingContext.SetColor(NS_RGB(0,0,0));
aRenderingContext.DrawRect(0,0, rect.width, rect.height);
rect.x++;
rect.y++;
rect.width -= 2;
rect.height -= 2;
}
if (mState & eButtonState_pressed) {
aRenderingContext.SetColor(mHighlightColor);
} else {
aRenderingContext.SetColor(mShadowColor);
}
aRenderingContext.DrawLine(rect.x, rect.height, rect.width, rect.height);
aRenderingContext.DrawLine(rect.width, rect.y, rect.width, rect.height);
if (mState & eButtonState_pressed) {
aRenderingContext.SetColor(mShadowColor);
} else {
aRenderingContext.SetColor(mHighlightColor);
}
aRenderingContext.DrawLine(rect.x,rect.y, rect.width,rect.y);
aRenderingContext.DrawLine(rect.x,rect.y, rect.x, rect.height);
return nsEventStatus_eConsumeNoDefault;
}
//-----------------------------------------------------------------------------
nsEventStatus nsImageButton::HandleEvent(nsGUIEvent *aEvent)
{
if (aEvent->message == NS_PAINT || aEvent->message == NS_SIZE)
{
switch(aEvent->message)
{
case NS_PAINT:
{
nsEventStatus es ;
nsRect rect;
nsDrawingSurface ds = nsnull;
nsIRenderingContext * ctx = ((nsPaintEvent*)aEvent)->renderingContext;
/*nsRect widgetRect;
GetBounds(widgetRect);
widgetRect.x = 0;
widgetRect.y = 0;
ctx->SetClipRect(widgetRect, nsClipCombine_kReplace);
*/
rect.x = ((nsPaintEvent *)aEvent)->rect->x;
rect.y = ((nsPaintEvent *)aEvent)->rect->y;
rect.width = ((nsPaintEvent *)aEvent)->rect->width;
rect.height = ((nsPaintEvent *)aEvent)->rect->height;
aEvent->widget->GetBounds(rect);
rect.x = 0;
rect.y = 0;
ctx->CreateDrawingSurface(&rect, 0, ds);
if (ds == nsnull) {
return nsEventStatus_eConsumeNoDefault;
}
ctx->SelectOffScreenDrawingSurface(ds);
es = OnPaint((*((nsPaintEvent*)aEvent)->renderingContext),(*((nsPaintEvent*)aEvent)->rect));
ctx->CopyOffScreenBits(ds, 0, 0, rect, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
ctx->DestroyDrawingSurface(ds);
return es;
}
break;
/*case NS_SIZE: {
nscoord x = ((nsSizeEvent*)aEvent)->windowSize->x;
nscoord y = ((nsSizeEvent*)aEvent)->windowSize->y;
nscoord w = ((nsSizeEvent*)aEvent)->windowSize->width;
nscoord h = ((nsSizeEvent*)aEvent)->windowSize->height;
OnResize(x,y,w,h);
}
break;*/
}
//PRInt32 i = 0;
//for (i=0;i<mNumListeners;i++) {
// mListeners->NotifyImageButtonEvent(aEvent);
//}
return nsEventStatus_eIgnore;
}
if (aEvent->message == NS_DESTROY)
return nsEventStatus_eIgnore;
/*
* XXX: Make this a HandleInputEvent...
*/
switch(aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
OnLeftButtonDown(aEvent);
break;
case NS_MOUSE_LEFT_BUTTON_UP:
OnLeftButtonUp(aEvent);
break;
case NS_MOUSE_RIGHT_BUTTON_DOWN:
OnLeftButtonDown(aEvent);
break;
case NS_MOUSE_RIGHT_BUTTON_UP:
OnLeftButtonUp(aEvent);
break;
case NS_MOUSE_MOVE:
OnMouseMove(aEvent);
break;
case NS_MOUSE_ENTER:
OnMouseEnter(aEvent);
break;
case NS_MOUSE_EXIT:
OnMouseExit(aEvent);
break;
case NS_KEY_UP:
//OnKeyUp(aEvent);
break;
case NS_KEY_DOWN:
//OnKeyDown(aEvent);
break;
} // switch
PRInt32 i = 0;
for (i=0;i<mNumListeners;i++) {
mListeners[i]->NotifyImageButtonEvent(this, aEvent);
}
return nsEventStatus_eIgnore;
}
//----------------------------------------------------------------
void nsImageButton::Notify(nsIImageRequest *aImageRequest,
nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,
void *aParam3)
{
if (aNotificationType == nsImageNotification_kImageComplete) {
PRUint32 w,h;
aImageRequest->GetNaturalDimensions(&w, &h);
if (w > 0 && h > 0) {
aImageRequest->GetNaturalDimensions(&mImageWidth, &mImageHeight);
}
Invalidate(PR_FALSE);
}
return ;
}
//----------------------------------------------------------------
void nsImageButton::NotifyError(nsIImageRequest *aImageRequest,
nsImageError aErrorType)
{
return ;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetImageDimensions(const PRInt32 & aWidth, const PRInt32 & aHeight)
{
mImageWidth = aWidth;
mImageHeight = aHeight;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetImageURLs(const nsString& aUpURL,
const nsString& aPressedURL,
const nsString& aDisabledURL,
const nsString& aRollOverURL)
{
CreateImageGroup();
mUpImageRequest = RequestImage(aUpURL);
mPressedImageRequest = RequestImage(aPressedURL);
mDisabledImageRequest = RequestImage(aDisabledURL);
mRollOverImageRequest = RequestImage(aRollOverURL);
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetShowBorder(PRBool aState)
{
mShowBorder = aState;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetAlwaysShowBorder(PRBool aState)
{
mAlwaysShowBorder = aState;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SwapHighlightShadowColors()
{
nscolor highColor;
nscolor shadeColor;
GetHighlightColor(highColor);
GetShadowColor(shadeColor);
SetHighlightColor(shadeColor);
SetShadowColor(highColor);
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetShowButtonBorder(PRBool aState)
{
mShowButtonBorder = aState;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetBorderWidth(PRInt32 aWidth)
{
mBorderWidth = aWidth;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetBorderOffset(PRInt32 aOffset)
{
mBorderOffset = aOffset;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetShowText(PRBool aState)
{
mShowText = aState;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetShowImage(PRBool aState)
{
mShowImage = aState;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetImageVerticalAlignment(nsButtonVerticalAligment aAlign)
{
mImageVAlignment = aAlign;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetImageHorizontalAlignment(nsButtonHorizontalAligment aAlign)
{
mImageHAlignment = aAlign;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetTextVerticalAlignment(nsButtonVerticalAligment aAlign)
{
mTextVAlignment = aAlign;
return NS_OK;
}
//----------------------------------------------------------------
NS_METHOD nsImageButton::SetTextHorizontalAlignment(nsButtonHorizontalAligment aAlign)
{
mTextHAlignment = aAlign;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsImageButton::AddListener(nsIImageButtonListener * aListener)
{
// XXX will be switching to a nsDeque
mListeners[mNumListeners++] = aListener;
NS_ADDREF(aListener);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsImageButton::RemoveListener(nsIImageButtonListener * aListener)
{
// XXX will be switching to a nsDeque
PRInt32 i;
for (i=0;i<mNumListeners;i++) {
if (aListener == mListeners[i]) {
// XXX remove it from list here
NS_RELEASE(aListener);
break;
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsImageButton::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
{
if (mPreferredWidth != 0 || mPreferredHeight != 0) {
aWidth = mPreferredWidth;
aHeight = mPreferredHeight;
} else {
nsRect imgRect;
nsRect txtRect;
nsRect rect;
PRInt32 which;
GetBounds(rect);
PerformAlignment(rect, mUpImageRequest, imgRect, mLabel, txtRect, which, aWidth, aHeight);
aWidth += (mBorderWidth*2)+(mBorderOffset*2);
aHeight += (mBorderWidth*2)+(mBorderOffset*2);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsImageButton::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
{
mPreferredWidth = aWidth;
mPreferredHeight = aHeight;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsImageButton::Enable(PRBool aState)
{
nsresult status = nsWindow::Enable(aState);
if (aState) {
mState &= ~eButtonState_disabled;
} else {
mState |= eButtonState_disabled;
}
return status;
}
//-------------------------------------------------------------------------
void nsImageButton::PerformAlignment(const nsRect & aRect,
const nsIImageRequest * anImage, nsRect & aImgRect,
const nsString & aText, nsRect & aTxtRect,
PRInt32 &aWhichAlignment, PRInt32 &aMaxWidth, PRInt32 &aMaxHeight)
{
nscoord string_height = 0;
nscoord string_width = 0;
aImgRect.SetRect(0, 0, 0, 0);
aTxtRect.SetRect(0, 0, 0, 0);
aMaxWidth = 0;
aMaxHeight = 0;
PRInt32 offset = mBorderWidth + mBorderOffset;
// set up initial text size
if (mShowText) {
nsIRenderingContext *cx;
if (NS_OK != mContext->CreateRenderingContext(this, cx)) {
return;
}
nsIFontMetrics* metrics;
if (NS_OK != mContext->GetMetricsFor(mFont, metrics)) {
NS_RELEASE(cx);
return;
}
cx->SetFont(metrics);
metrics->GetHeight(string_height);
cx->GetWidth(aText, string_width);
NS_RELEASE(metrics);
NS_RELEASE(cx);
aTxtRect.SetRect(offset,offset, string_width, string_height); // Align left
if (!mShowImage || anImage == nsnull) {
aWhichAlignment = kAlignJustText;
// Align horizontally
if (mTextHAlignment == eButtonHorizontalAligment_Right) {
aTxtRect.x = aRect.width - aTxtRect.width - offset;
} if (mTextHAlignment == eButtonHorizontalAligment_Middle) {
aTxtRect.x = (aRect.width - aTxtRect.width) / 2;
}
// Align vertically
if (mTextVAlignment == eButtonVerticalAligment_Bottom) {
aTxtRect.y = aRect.height - aTxtRect.height - offset;
} if (mTextVAlignment == eButtonVerticalAligment_Center) {
aTxtRect.y = (aRect.height - aTxtRect.height) / 2;
}
aMaxWidth = string_width;
aMaxHeight = string_height;
}
}
// Set up initial image size
if (mShowImage && anImage != nsnull) {
aImgRect.SetRect(offset, offset, mImageWidth, mImageHeight); // Align left
if (!mShowText || aText.Length() == 0) {
aWhichAlignment = kAlignJustImage;
// Align horizontally
if (mImageHAlignment == eButtonHorizontalAligment_Right) {
aImgRect.x = aRect.width - aImgRect.width - offset;
} if (mImageHAlignment == eButtonHorizontalAligment_Middle) {
aImgRect.x = (aRect.width - aImgRect.width) / 2;
}
// Align vertically
if (mImageVAlignment == eButtonVerticalAligment_Bottom) {
aImgRect.y = aRect.height - aImgRect.height - offset;
} if (mImageVAlignment == eButtonVerticalAligment_Center) {
aImgRect.y = (aRect.height - aImgRect.height) / 2;
}
aMaxWidth = mImageWidth;
aMaxHeight = mImageHeight;
}
}
aWhichAlignment = kAlignBoth;
// Now align and layout both text and image
// Text align is relative to the image, so it forces the image to an alignment
if (mTextHAlignment == eButtonHorizontalAligment_Right) {
aImgRect.x = offset;
aTxtRect.x = aImgRect.x + aImgRect.width + mTextGap;
aMaxWidth = aTxtRect.x + aTxtRect.width - offset;
} else if (mTextHAlignment == eButtonHorizontalAligment_Middle) {
aImgRect.x = (aRect.width - aImgRect.width) / 2;
aTxtRect.x = (aRect.width - aTxtRect.width) / 2;
aMaxWidth = (aTxtRect.width > aImgRect.width? aTxtRect.width : aImgRect.width);
} else { // Text is on the Left
aTxtRect.x = offset;
aImgRect.x = aTxtRect.x + aTxtRect.width + mTextGap;
aMaxWidth = aImgRect.x + aImgRect.width - offset;
}
// vertical
if (mTextVAlignment == eButtonVerticalAligment_Bottom) {
aImgRect.y = offset;
aTxtRect.y = aImgRect.y + aImgRect.height;// + mTextGap;
aMaxHeight = aTxtRect.y + aTxtRect.height;
} else if (mTextVAlignment == eButtonVerticalAligment_Center) {
aImgRect.y = (aRect.height - aImgRect.height) / 2;
aTxtRect.y = (aRect.height - aTxtRect.height) / 2;
aMaxHeight = (aTxtRect.height > aImgRect.height? aTxtRect.height : aImgRect.height);
} else { // Text is on the Left
aTxtRect.y = offset;
aImgRect.y = aTxtRect.y + aTxtRect.height;// + mTextGap;
aMaxHeight = aImgRect.y + aImgRect.height - offset;
}
}